summaryrefslogtreecommitdiff
path: root/support/dktools/dk-t2l.ctr
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk-t2l.ctr
Initial commit
Diffstat (limited to 'support/dktools/dk-t2l.ctr')
-rw-r--r--support/dktools/dk-t2l.ctr1955
1 files changed, 1955 insertions, 0 deletions
diff --git a/support/dktools/dk-t2l.ctr b/support/dktools/dk-t2l.ctr
new file mode 100644
index 0000000000..8a1bcbeb9b
--- /dev/null
+++ b/support/dktools/dk-t2l.ctr
@@ -0,0 +1,1955 @@
+%% options
+
+copyright owner = Dirk Krause
+copyright year = 2015-xxxx
+license = bsd
+
+
+%% module
+
+/** @file dk-th2.c The dk-t2l program.
+ See dk_t2l_help_text for details.
+*/
+
+#include "dk4conf.h"
+
+#include <stdio.h>
+
+#if DK4_HAVE_STDLIB_H
+#ifndef STDLIB_H_INCLUDED
+#include <stdlib.h>
+#define STDLIB_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_UNISTD_H
+#ifndef UNISTD_H_INCLUDED
+#include <unistd.h>
+#define UNISTD_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_SYS_TYPES_H
+#ifndef SYS_TYPES_H_INCLUDED
+#include <sys/types.h>
+#define SYS_TYPES_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_SIGNAL_H
+#ifndef SIGNAL_H_INCLUDED
+#include <signal.h>
+#define SIGNAL_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_PROCESS_H
+#ifndef PROCESS_H_INCLUDED
+#include <process.h>
+#define PROCESS_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_IO_H
+#ifndef IO_H_INCLUDED
+#include <io.h>
+#define IO_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_FCNTL_H
+#ifndef FCNTL_H_INCLUDED
+#include <fcntl.h>
+#define FCNTL_H_INCLUDED 1
+#endif
+#endif
+
+#if DK4_HAVE_ERRNO_H
+#ifndef ERRNO_H_INCLUDED
+#include <errno.h>
+#define ERRNO_H_INCLUDED 1
+#endif
+#endif
+
+#include "dk4types.h"
+#include "dk4const.h"
+#include "dk4mem.h"
+#include "dk4enc.h"
+#include "dk4app.h"
+#include "dk4aopt.h"
+#include "dk4fopda.h"
+#include "dk4fput.h"
+#include "dk4vers.h"
+#include "dk4tsp32.h"
+#include "dk4uc2l.h"
+#include "dk4maidhdu.h"
+#include "dk4maidddu.h"
+#include "dk4maodh.h"
+#include "dk4maodd.h"
+#include "dk4mpl.h"
+#include "dk4strd.h"
+#include "dk4pathd.h"
+
+#if DK4_CHAR_SIZE > 1
+#if DK4_CHAR_SIZE == 2
+#include "dk4utf16.h"
+#endif
+#else
+#include "dk4ansi.h"
+#include "dk4utf8.h"
+#endif
+
+
+
+$!trace-include
+
+
+
+/** Default help text, shown if no help text file is found.
+*/
+static const dkChar * const dk_t2l_help_text[] = {
+$!text macro=dkT,preprocessor
+
+dk-t2l - Text to LaTeX converter
+
+dk-t2l [<options>] [<file(s)>]
+
+Options:
+-i <encoding> --input-encoding=<encoding> Expected input encoding.
+-e --echo Process command line arguments.
+-n --numeric Numeric values on command line.
+-h --hex Hexadecimal values on cmd line.
+-r --recommendations Write recommendations for
+ packages and font encodings
+ to use.
+-l --line-feed Write \\ sequence for newline.
+-t --tabulator Write LaTeX sequence for
+ tabulators
+ --verbose Show error message on SIGPIPE.
+
+--help Show this short help text.
+--manual *** SHOW FULL MANUAL. ***
+--version Show version information.
+--license Show license information.
+
+http://dktools.sourceforge.net
+
+$!end
+};
+
+
+
+/** License text.
+*/
+static const dkChar * const dk_t2l_license_text[] = {
+$!text macro=dkT,preprocessor
+
+This software uses code from the following projects, either directly or as
+a library:
+
+dktools Dirk Krause's tools and libraries.
+ See http://dktools.sourceforge.net/ for more information.
+#if DK4_HAVE_ZLIB_H
+
+zlib Data compression library.
+ See http://www.zlib.net/ for more information.
+#endif
+#if DK4_HAVE_BZLIB_H
+
+bzip2 Data compression program and library.
+ See http://www.bzip.org/ for more information.
+#endif
+
+All the licenses below apply to the program.
+Licenses for used libraries are shown as found on my Scientific Linux 6.x
+computer in the /usr/share/doc directory on 2015-04-01. Check the project
+homepages of the used libraries for additional information and/or updated
+license terms.
+
+
+DK tools and libraries license
+==============================
+Copyright (c) 2015-2016, Dirk Krause
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+* Neither the name of the Dirk Krause nor the names of contributors may be
+ used to endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.
+
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#if DK4_HAVE_ZLIB_H
+
+
+Zlib license
+============
+(C) 1995-2004 Jean-loup Gailly and Mark Adler
+
+This software is provided 'as-is', without any express or implied
+warranty. In no event will the authors be held liable for any damages
+arising from the use of this software.
+
+Permission is granted to anyone to use this software for any purpose,
+including commercial applications, and to alter it and redistribute it
+freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+Jean-loup Gailly Mark Adler
+jloup@gzip.org madler@alumni.caltech.edu
+#endif
+#if DK4_HAVE_BZLIB_H
+
+
+Bzip2 and libbzip2 library license
+==================================
+This program, "bzip2", the associated library "libbzip2", and all
+documentation, are copyright (C) 1996-2007 Julian R Seward. All
+rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+2. The origin of this software must not be misrepresented; you must
+ not claim that you wrote the original software. If you use this
+ software in a product, an acknowledgment in the product
+ documentation would be appreciated but is not required.
+
+3. Altered source versions must be plainly marked as such, and must
+ not be misrepresented as being the original software.
+
+4. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior written
+ permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Julian Seward, jseward@bzip.org
+bzip2/libbzip2 version 1.0.5 of 10 December 2007
+#endif
+
+$!end
+};
+
+
+
+/** Constant 8 bit character texts, not localized.
+*/
+static const char * const dk_t2l_kw8[] = {
+$!string-table
+#
+# 0 1 Open and close math mode.
+#
+\\(
+\\)
+#
+# 2
+#
+\\\\
+$!end
+};
+
+
+
+/** Constant text keywords used by the program, not localized.
+*/
+static const dkChar * const dk_t2l_kwnl[] = {
+$!string-table macro=dkT
+#
+# 0 Program group name
+#
+dktools
+#
+# 1 Help text file name
+#
+dk-t2l.txt
+#
+# 2 String table file name
+#
+dk-t2l.str
+#
+# 3 File opening mode, read binary
+#
+rb
+#
+# 4 Pseudo file name for standard input
+#
+stdin
+#
+# 5 Path separator for Windows
+#
+\\
+#
+# 6 Long option for verbose mode
+#
+verbose
+$!end
+};
+
+
+
+/** Constant keywords used by the program, replaced by localized texts.
+*/
+static const dkChar * const dk_t2l_kw_def[] = {
+$!string-table macro=dkT
+#
+# 0 Error: Failed to set up signal handlers!
+#
+Failed to set up signal handlers!
+#
+# 1 Error: Failed to restore signal handlers!
+#
+Failed to restore signal handlers!
+#
+# 2 3 Error: Illegal input encoding name: "..."!
+#
+Illegal input encoding name: "
+"!
+#
+# 4 5 Temporarily unused.
+#
+Not a hexadecimal number: "
+"!
+#
+# 6 7 8 Error: No data found for character 0x...!
+#
+No data found for character 0x
+!
+No data found for character!
+#
+# 9 Error: Overflow in line number count!
+#
+Overflow in line number count!
+#
+# 10 Error: Failed to setup character by character processing!
+#
+Failed to setup character by character processing!
+#
+# 11 Error: Probably incorrect output due to problems ...
+#
+Probably incorrect output due to problems with the data files!
+#
+# 12 .. 15 Error: Aborted by SIGINT signal!
+#
+Aborted by SIGINT signal!
+Aborted by SIGTERM signal!
+Received SIGPIPE signal!
+Write attempt to standard output failed.
+#
+# 16 ... 21 Error messages.
+#
+Decoding failed!\n\tByte:
+Encoding failed!\n\tByte:
+Processing failed!\n\tByte:
+,\n\tCharacter:
+,\n\tPosition in line:
+.
+#
+# 22 ... 27 Error messages.
+#
+Decoding failed!
+Encoding failed!
+Processing failed!
+Further decoding failures!
+Further encoding failures!
+Further processing failures!
+#
+# 28 29 Error: Out of range!
+#
+Out of range: "
+"!
+#
+# 30 31 Error: Not a decimal number!
+#
+Not a decimal number: "
+"!
+$!end
+};
+
+
+
+/** Options for the program.
+*/
+static const dk4_option_specification_t dk_t2l_options[] = {
+
+ /* Expected input encoding.
+ */
+ { dkT('i'), dkT("input-encoding"), DK4_OPT_ARG_STRING },
+
+ /* Process command line arguments.
+ */
+ { dkT('e'), dkT("echo"), DK4_OPT_ARG_NONE },
+
+ /* Command line arguments are decimal character numbers.
+ */
+ { dkT('n'), dkT("numeric"), DK4_OPT_ARG_NONE },
+
+ /* Command line arguments are hexadecimal character numbers.
+ */
+ { dkT('x'), dkT("hex"), DK4_OPT_ARG_NONE },
+
+ /* Write recommendations about font encodings and packages.
+ */
+ { dkT('r'), dkT("recommendations"), DK4_OPT_ARG_NONE },
+
+ /* Convert tabulators.
+ */
+ { dkT('t'), dkT("tabulator"), DK4_OPT_ARG_NONE },
+
+ /* Convert line feeds.
+ */
+ { dkT('l'), dkT("line-feed"), DK4_OPT_ARG_NONE },
+
+ /* Verbose output.
+ */
+ { dkT('\0'), dkT("verbose"), DK4_OPT_ARG_NONE }
+};
+
+
+
+/** Pointer to localized or not localized texts.
+*/
+static const dkChar * const *dk_t2l_msg = dk_t2l_kw_def;
+
+
+
+/** Application structure.
+*/
+static dk4_app_t *app = NULL;
+
+
+
+/** Conversion data structure.
+*/
+static dk4_uc2l_t *uc2l = NULL;
+
+
+
+/** Current line number.
+*/
+static dk4_um_t dk_t2l_lineno = (dk4_um_t)1UL;
+
+
+
+/** Number of elements in the dk_t2l_options array.
+*/
+static const size_t dk_t2l_sz_options =
+sizeof(dk_t2l_options)/sizeof(dk4_option_specification_t);
+
+
+
+/** Number of elements in dk_t2l_msg array.
+*/
+static size_t dk_t2l_sz_msg =
+sizeof(dk_t2l_kw_def)/sizeof(DK4_PCDKCHAR) - 1;
+
+
+/** Program exit status.
+*/
+static int exval = EXIT_FAILURE;
+
+
+
+/** Flag: Error occured while writing to stdout.
+*/
+static int output_error = 0;
+
+
+
+/** Flag: Verbose output (report SIGPIPE).
+*/
+static int verbose = 0;
+
+
+
+/** Flag: Echo command line arguments instead of processing files.
+*/
+static int dk_t2l_echo = 0;
+
+
+
+/** Command line arguments are numeric:
+ 0 = text,
+ 1 = decimal,
+ 2 = hexadecimal.
+*/
+static int dk_t2l_numeric = 0;
+
+
+
+/** Input encoding expected when processing stdin.
+*/
+static int dk_t2l_i_std = DK4_FILE_ENCODING_ASCII;
+
+
+
+/** Input encoding expected when processing files.
+*/
+static int dk_t2l_i_file = DK4_FILE_ENCODING_ASCII;
+
+
+
+/** Number of decoding errors in current file.
+*/
+static int dk_t2l_dec_err = 0;
+
+
+
+/** Number of encoding errors in current file.
+*/
+static int dk_t2l_enc_err = 0;
+
+
+
+/** Number of processing errors in current file.
+*/
+static int dk_t2l_pro_err = 0;
+
+
+
+/** Flag: Previous character was carriage return.
+*/
+static int dk_t2l_last_cr = 0;
+
+
+
+/** Flag: Previous character was newline.
+*/
+static int dk_t2l_last_nl = 0;
+
+
+
+/** Flag: Have text in line, newline needed.
+*/
+static int dk_t2l_lhtx = 0;
+
+
+
+/** Flag: In math mode.
+*/
+static int dk_t2l_in_mm = 0;
+
+
+
+/** Flag: Find LaTeX sequence also for tabulators.
+*/
+static int dk_t2l_tabs = 0;
+
+
+
+/** Flag: Write sequence for line feeds.
+*/
+static int dk_t2l_linef = 0;
+
+
+
+#ifdef SIGPIPE
+/** Indicator: SIGPIPE signal received.
+*/
+static
+DK4_VOLATILE
+dk4_sig_atomic_t sig_had_pipe = 0;
+#endif
+
+/** Indicator: SIGINT signal received.
+*/
+static
+DK4_VOLATILE
+dk4_sig_atomic_t sig_had_int = 0;
+
+/** Indicator: SIGTERM signal received.
+*/
+static
+DK4_VOLATILE
+dk4_sig_atomic_t sig_had_term = 0;
+
+
+
+/** Pass a volatile pointer to an atomic integer.
+ This function is necessary as some compilers mis-optimize
+ direct access to volatile variables (at least if you believe
+ one of the coding standards).
+ @param ptr Address of atomic integer variable.
+ @return The unmodified pointer.
+*/
+static
+DK4_VOLATILE
+dk4_sig_atomic_t *
+sig_pass_pointer(DK4_VOLATILE dk4_sig_atomic_t *ptr)
+{
+ return ptr;
+}
+
+
+
+#ifdef SIGPIPE
+/** Handler for SIGPIPE signal.
+ @param signo Signal number (always SIGPIPE, ignored).
+*/
+static
+void
+sig_handler_pipe(int signo)
+{
+ *sig_pass_pointer(&sig_had_pipe) = 1;
+}
+#endif
+
+/** Handler for SIGINT signal.
+ @param signo Signal number (always SIGINT, ignored).
+*/
+static
+void
+sig_handler_int(int signo)
+{
+ *sig_pass_pointer(&sig_had_int) = 1;
+}
+
+/** Handler for SIGTERM signal.
+ @param signo Signal number (always SIGTERM, ignored).
+*/
+static
+void
+sig_handler_term(int signo)
+{
+ *sig_pass_pointer(&sig_had_term) = 1;
+}
+
+/** Read value from volatile atomic type.
+ This function is necessary as some compilers mis-optimize
+ direct access to volatile variables (at least if you believe
+ one of the coding standards).
+ @param ap Pointer to volatile atomic variable.
+ @return Contents of the variable.
+*/
+static
+dk4_sig_atomic_t
+sig_read_atomic(DK4_VOLATILE dk4_sig_atomic_t *ap)
+{
+ return (*ap);
+}
+
+/** Check whether we can continue or if a signal was received.
+ @param check_pipe Flag: Check for occured SIGPIPE signal too.
+ @return 1 if the program can continue, 0 if a signal was received.
+*/
+static
+int
+sig_can_continue(int check_pipe)
+{
+ int back = 1;
+#ifdef SIGPIPE
+ if (0 != check_pipe) {
+ if (0 != sig_read_atomic(&sig_had_pipe)) { back = 0; }
+ }
+#endif
+ if (0 != sig_read_atomic(&sig_had_int )) { back = 0; }
+ if (0 != sig_read_atomic(&sig_had_term)) { back = 0; }
+ return back;
+}
+
+
+
+/** Check whether we can continue.
+ @return 1 for yes, 0 for no.
+*/
+static
+int
+dk_t2l_can_continue(void)
+{
+ int back = 1;
+ if (0 == sig_can_continue(1)) {
+ back = 0;
+ }
+ return back;
+}
+
+
+
+/** Process command line options.
+ @return 1 on success, 0 on error.
+*/
+static
+int
+dk_t2l_process_options(void)
+{
+ const dkChar *oaptr;
+ int encval = 0;
+ int bomval = 0;
+ int back = 1;
+
+ if (0 != dk4app_opt_is_set_long(app, dk_t2l_kwnl[6], NULL)) {
+ verbose = 1;
+ }
+ if (0 != dk4app_opt_is_set_short(app, dkT('t'), NULL)) {
+ dk_t2l_tabs = 1;
+ }
+ if (0 != dk4app_opt_is_set_short(app, dkT('l'), NULL)) {
+ dk_t2l_linef = 1;
+ }
+ if (0 != dk4app_opt_is_set_short(app, dkT('i'), NULL)) {
+ oaptr = dk4app_opt_get_string_ptr_short(app, dkT('i'), NULL);
+ if (NULL != oaptr) {
+ if (0 != dk4enc_find(&encval, &bomval, oaptr, NULL)) {
+ dk_t2l_i_std = dk_t2l_i_file = encval;
+ } else {
+ /* ERROR: Illegal encoding */
+ dk4app_log_3(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 2, 3, oaptr);
+ back = 0;
+ }
+ } else { $? "! bug"
+ /* ERROR: Failed to obtain option argument, bug! */
+ }
+ }
+ if (0 != dk4app_opt_is_set_short(app, dkT('e'), NULL)) {
+ dk_t2l_echo = 1;
+ }
+ if (0 != dk4app_opt_is_set_short(app, dkT('n'), NULL)) {
+ dk_t2l_echo = 1;
+ dk_t2l_numeric = 1;
+ }
+ if (0 != dk4app_opt_is_set_short(app, dkT('x'), NULL)) {
+ dk_t2l_echo = 1;
+ dk_t2l_numeric = 2;
+ }
+ uc2l = dk4uc2l_open_from_app(app);
+ if (NULL == uc2l) {
+ back = 0;
+ }
+ return back;
+}
+
+
+
+/** Start output page.
+*/
+static
+void
+dk_t2l_output_start_page(void)
+{
+ /* Hook */
+}
+
+
+
+/** Finish output page.
+*/
+static
+void
+dk_t2l_output_finish_page(void)
+{
+ /* Hook */
+}
+
+
+
+/** Start processing of one file.
+*/
+static
+void
+dk_t2l_output_start_file(void)
+{
+ /* No errors in this file yet.
+ */
+ dk_t2l_dec_err = 0;
+ dk_t2l_enc_err = 0;
+ dk_t2l_pro_err = 0;
+ dk_t2l_last_cr = 0;
+ dk_t2l_last_nl = 0;
+ dk_t2l_lhtx = 0;
+ dk_t2l_lineno = (dk4_um_t)1UL;
+ dk4app_set_log_source_line(app, dk_t2l_lineno);
+}
+
+
+
+/** Finish processing of one file.
+*/
+static
+void
+dk_t2l_output_finish_file(void)
+{
+
+}
+
+
+
+static
+void
+dk_t2l_begin_math_mode(void)
+{
+ if (0 == dk_t2l_in_mm) {
+ dk_t2l_in_mm = 1;
+ if (EOF == fputs(dk_t2l_kw8[0], stdout)) {
+ output_error = 1;
+ }
+ }
+}
+
+
+
+static
+void
+dk_t2l_end_math_mode(void)
+{
+ if (0 != dk_t2l_in_mm) {
+ dk_t2l_in_mm = 0;
+ if (EOF == fputs(dk_t2l_kw8[1], stdout)) {
+ output_error = 1;
+ }
+ }
+}
+
+
+
+/** Handler function after processing CR/NL sequences.
+ Here we do the real output.
+ @param c Character to process.
+ @param pos Current position in file or data stream, may be NULL.
+ @param erp Error report, may be NULL.
+ @return Result code:
+ - DK4_TSP_RES_OK if the character was processed successfully,
+ - DK4_TSP_RES_ERROR if there was an error but we can continue,
+ - DK4_TSP_RES_FATAL if there was a fatal error so we
+ should abort processing.
+*/
+static
+int
+dk_t2l_c32_after_cr_nl_check(
+ dk4_c32_t c,
+ dk4_text_stream_position_t *pos,
+ dk4_er_t *erp
+)
+{
+ dkChar buf[16*sizeof(dk4_um_t)];
+ const char *lseq;
+ size_t szbuf;
+ int back = DK4_TSP_RES_OK;
+
+ if (dkC32(0x0A) == c) {
+ /*
+ Newline, finish line and write newline to output.
+ */
+ dk_t2l_end_math_mode();
+ if (0 != dk_t2l_linef) {
+ if (EOF == fputs(dk_t2l_kw8[2], stdout)) { output_error = 1; }
+ }
+ if (EOF == fputc('\n', stdout)) { output_error = 1; }
+ } else {
+ if (0 == dk_t2l_lhtx) {
+ /*
+ Start new line.
+ */
+ }
+ /*
+ Write character to output.
+ */
+ if ((dkC32(0x09) == c) && (0 == dk_t2l_tabs)) {
+ dk_t2l_end_math_mode();
+ if (EOF == fputc(' ', stdout)) { output_error = 1; }
+ } else {
+ lseq = dk4uc2l_find(uc2l, c, 0, app);
+ if (NULL != lseq) {
+ dk_t2l_end_math_mode();
+ if (EOF == fputs(lseq, stdout)) { output_error = 1; }
+ } else {
+ lseq = dk4uc2l_find(uc2l, c, 1, app);
+ if (NULL != lseq) {
+ dk_t2l_begin_math_mode();
+ if (EOF == fputs(lseq, stdout)) { output_error = 1; }
+ } else {
+ /* ERROR, no encoding found */
+ szbuf = DK4_SIZEOF(buf,dkChar);
+ if (0 != dk4ma_write_hex_unsigned(buf, szbuf, (dk4_um_t)c, 8, NULL)) {
+ dk4app_log_3(app,dk_t2l_msg,dk_t2l_sz_msg,DK4_LL_ERROR,6,7,buf);
+ } else {
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 8);
+ }
+ exval = EXIT_FAILURE;
+ }
+ }
+ }
+ }
+ return back;
+}
+
+
+
+/** Handler function for single characters.
+ @param obj Object to modify while processing the character.
+ @param c Character to process.
+ @param pos Current position in file or data stream.
+ @param erp Error report, may be NULL.
+ @return Result code:
+ - DK4_TSP_RES_OK if the character was processed successfully,
+ - DK4_TSP_RES_ERROR if there was an error but we can continue,
+ - DK4_TSP_RES_FATAL if there was a fatal error so we
+ should abort processing.
+*/
+static
+int
+dk_t2l_c32_handler(
+ void *obj,
+ dk4_c32_t c,
+ dk4_text_stream_position_t *pos,
+ dk4_er_t *erp
+)
+{
+ int back = DK4_TSP_RES_OK;
+ if (dkC32(0x0A) == c) {
+ /*
+ For a newline clear CR and TXT flag, set NL flag.
+ */
+ back = dk_t2l_c32_after_cr_nl_check(c, pos, erp);
+ dk_t2l_lineno++;
+ if ((dk4_um_t)0UL == dk_t2l_lineno) {
+ /* ERROR: Overflow in line number counting */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 9);
+ exval = EXIT_FAILURE;
+ }
+ dk4app_set_log_source_line(app, dk_t2l_lineno);
+ dk_t2l_last_cr = 0;
+ dk_t2l_last_nl = 1;
+ dk_t2l_lhtx = 0;
+ } else {
+ if (dkC32(0x0D) == c) {
+ /*
+ For a cr if CR flag is set, pass the cr and set TXT flag, clear nl flag.
+ Otherwise simply set CR flag.
+ */
+ if (0 != dk_t2l_last_cr) {
+ back = dk_t2l_c32_after_cr_nl_check(dkC32(0x0D), pos, erp);
+ dk_t2l_lhtx = 1;
+ dk_t2l_last_nl = 0;
+ } else {
+ dk_t2l_last_cr = 1;
+ }
+ } else {
+ /*
+ For any other character:
+ If the CR flag is set, pass cr and current character.
+ Otherwise pass the current character.
+ Reset NL and CR flag, set TXT flag.
+ */
+ if (0 != dk_t2l_last_cr) {
+ back = dk_t2l_c32_after_cr_nl_check(dkC32(0x0D), pos, erp);
+ switch (dk_t2l_c32_after_cr_nl_check(c, pos, erp)) {
+ case DK4_TSP_RES_FATAL: {
+ back = DK4_TSP_RES_FATAL;
+ } break;
+ case DK4_TSP_RES_ERROR: {
+ if (DK4_TSP_RES_OK == back) {
+ back = DK4_TSP_RES_ERROR;
+ }
+ } break;
+ }
+ } else {
+ back = dk_t2l_c32_after_cr_nl_check(c, pos, erp);
+ }
+ dk_t2l_lhtx = 1;
+ dk_t2l_last_nl = 0;
+ dk_t2l_last_cr = 0;
+ }
+ }
+ return back;
+}
+
+
+
+/** Report an error with position in source line.
+ @param i1 Index of first message part in array.
+ @param i2 Index of alternative first message part.
+ @param bno Byte processed.
+ @param lno Current line number.
+ @param cno Current character number.
+ @param cil Current character number in line.
+*/
+static
+void
+dk_t2l_report_with_position(
+ size_t i1,
+ size_t i2,
+ dk4_um_t bno,
+ dk4_um_t lno,
+ dk4_um_t cno,
+ dk4_um_t cil
+)
+{
+ dkChar b1[8*(1+sizeof(dk4_um_t))];
+ dkChar b2[8*(1+sizeof(dk4_um_t))];
+ dkChar b3[8*(1+sizeof(dk4_um_t))];
+ dk4_um_t oldlogline = (dk4_um_t)0UL;
+ int allbuffersok = 0;
+
+ oldlogline = dk4app_get_log_source_line(app);
+ dk4app_set_log_source_line(app, lno);
+ if (0 != dk4ma_write_decimal_unsigned(b3,DK4_SIZEOF(b3,dkChar),cil,0,NULL)) {
+ if (0 != dk4ma_write_decimal_unsigned(b2,DK4_SIZEOF(b2,dkChar),cno,0,NULL)) {
+ if (0 != dk4ma_write_decimal_unsigned(b1,DK4_SIZEOF(b1,dkChar),bno,0,NULL)) {
+ allbuffersok = 1;
+ }
+ }
+ }
+ if (0 != allbuffersok) {
+ dk4app_log_7(
+ app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, i1, 19, 20, 21, b1, b2, b3
+ );
+ } else {
+ dk4app_log_1(
+ app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, i2
+ );
+ }
+ dk4app_set_log_source_line(app, oldlogline);
+}
+
+
+
+static
+void
+dk_t2l_report_errors(dk4_er_t *er_en, dk4_er_t *er_pr)
+{
+ if (NULL != er_en) {
+ switch (er_en->ec) {
+ case DK4_E_DECODING_FAILED: {
+ switch (dk_t2l_dec_err) {
+ case 0: case 1: {
+ dk_t2l_report_with_position(
+ 16, 22,
+ er_en->dt.fpos.byteno,
+ er_en->dt.fpos.lineno,
+ er_en->dt.fpos.charno,
+ er_en->dt.fpos.charinline
+ );
+ } break;
+ case 2: {
+ dk4app_log_1(
+ app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 25
+ );
+ } break;
+ }
+ if (3 > dk_t2l_dec_err) { dk_t2l_dec_err++; }
+ } break;
+ case DK4_E_ENCODING_FAILED: {
+ switch (dk_t2l_enc_err) {
+ case 0: case 1: {
+ dk_t2l_report_with_position(
+ 17, 23,
+ er_en->dt.fpos.byteno,
+ er_en->dt.fpos.lineno,
+ er_en->dt.fpos.charno,
+ er_en->dt.fpos.charinline
+ );
+ } break;
+ case 2: {
+ dk4app_log_1(
+ app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 26
+ );
+ } break;
+ }
+ if (3 > dk_t2l_enc_err) { dk_t2l_enc_err++; }
+ } break;
+ }
+ }
+ if (NULL != er_pr) {
+ if (DK4_E_NONE != er_pr->ec) {
+ switch (dk_t2l_pro_err) {
+ case 0: case 1: {
+ dk_t2l_report_with_position(
+ 18, 24,
+ er_pr->dt.fpos.byteno,
+ er_pr->dt.fpos.lineno,
+ er_pr->dt.fpos.charno,
+ er_pr->dt.fpos.charinline
+ );
+ } break;
+ case 2: {
+ dk4app_log_1(
+ app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 27
+ );
+ } break;
+ }
+ if (3 > dk_t2l_pro_err) { dk_t2l_pro_err++; }
+ }
+ }
+}
+
+
+
+static
+void
+dk_t2l_echo_hex(const dkChar *txt, int argno)
+{
+ const dkChar *endptr = NULL;
+ dk4_um_t um = (dk4_um_t)0UL;
+ int res = 0;
+ if (dkT('0') == txt[0]) {
+ if ((dkT('x') == txt[1]) || (dkT('X') == txt[1])) {
+ txt++; txt++;
+ }
+ }
+ res = dk4ma_input_dk_hex_dk4_um_t(
+ &um, txt, &endptr, 1, NULL
+ );
+ if (0 != res) {
+ if ((dk4_um_t)0xFFFFFFFFUL >= um) {
+ (void)dk_t2l_c32_after_cr_nl_check((dk4_c32_t)um, NULL, NULL);
+ } else {
+ dk4app_log_3(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 28, 29, txt);
+ }
+ } else {
+ /* ERROR: Not a hexadecimal number */
+ dk4app_log_3(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 4, 5, txt);
+ }
+}
+
+
+
+static
+void
+dk_t2l_echo_numeric(const dkChar *txt, int argno)
+{
+ const dkChar *endptr = NULL;
+ dk4_um_t um = (dk4_um_t)0UL;
+ int res = 0;
+ int ishex = 0;
+
+ if (dkT('0') == txt[0]) {
+ if ((dkT('x') == txt[1]) || (dkT('X') == txt[1])) {
+ ishex = 1;
+ }
+ }
+ if (0 == ishex) {
+ res = dk4ma_input_dk_dec_dk4_um_t(
+ &um, txt, &endptr, 1, NULL
+ );
+ if (0 != res) {
+ if ((dk4_um_t)0xFFFFFFFFUL >= um) {
+ (void)dk_t2l_c32_after_cr_nl_check((dk4_c32_t)um, NULL, NULL);
+ } else {
+ dk4app_log_3(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 28, 29, txt);
+ }
+ } else {
+ /* ERROR: Not a decimal number */
+ dk4app_log_3(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 30, 31, txt);
+ }
+ } else {
+ dk_t2l_echo_hex(&(txt[2]), argno);
+ }
+}
+
+
+#if DK4_CHAR_SIZE > 1
+#if DK4_CHAR_SIZE > 2
+
+/** Process one text word from command line, UNICODE character.
+ @param txt Text word.
+ @param argno Number of current word.
+*/
+static
+void
+dk_t2l_echo_c32(const dkChar *txt, int argno)
+{
+ int isfirst = 1;
+ while (dkC32(0) != *txt) {
+ if ((1 == isfirst) && (0 != argno)) {
+ if (EOF == fputc(' ', stdout)) { output_error = 1; }
+ }
+ isfirst = 0;
+ (void)dk_t2l_c32_after_cr_nl_check(*(txt++), NULL, NULL);
+ }
+}
+
+#else
+
+/** Process one text word from command line, UTF-16 encoded.
+ @param txt Text word.
+ @param argno Number of current word.
+*/
+static
+void
+dk_t2l_echo_utf16(const dkChar *txt, int argno)
+{
+ dk4_utf16_decoder_t dec;
+ int cc = 1;
+ int isfirst = 1;
+ dk4utf16_init(&dec);
+ while (1 == cc) {
+ if (dkC16(0) != *txt) {
+ switch (dk4utf16_add(&dec, *(txt++))) {
+ case DK4_EDSTM_ERROR : {
+ cc = -1;
+ /* !!!!! ERROR: Decoding */
+ exval = EXIT_FAILURE;
+ } break;
+ case DK4_EDSTM_FINISHED : {
+ if ((1 == isfirst) && (0 != argno)) {
+ if (EOF == fputc(' ', stdout)) { output_error = 1; }
+ }
+ isfirst = 0;
+ (void)dk_t2l_c32_after_cr_nl_check(dk4utf16_get(&dec), NULL, NULL);
+ } break;
+ }
+ } else {
+ cc = 0;
+ }
+ }
+ if (0 == cc) {
+ if (0 == dk4utf16_is_empty(&dec)) {
+ /* !!!!! ERROR: Decoding */
+ exval = EXIT_FAILURE;
+ }
+ }
+ /* !!!!! TODO: Implementation */
+}
+
+#endif
+#else
+
+/** Process one text word from command line, ASCII encoded.
+ @param txt Text word.
+ @param argno Number of current word.
+*/
+static
+void
+dk_t2l_echo_ascii(const dkChar *txt, int argno)
+{
+ dk4_c32_t c32;
+ int isfirst = 1;
+ while ('\0' != *txt) {
+ if ((1 == isfirst) && (0 != argno)) {
+ if (EOF == fputc(' ', stdout)) { output_error = 1; }
+ }
+ isfirst = 0;
+ c32 = dkC32(0xFF) & ((dk4_c32_t)((unsigned char)(*(txt++))));
+ (void)dk_t2l_c32_after_cr_nl_check(c32, NULL, NULL);
+ }
+}
+
+/** Process one text word from command line, UTF-8 encoded.
+ @param txt Text word.
+ @param argno Number of current word.
+*/
+static
+void
+dk_t2l_echo_utf8(const dkChar *txt, int argno)
+{
+ dk4_utf8_decoder_t dec;
+ int cc = 1;
+ int isfirst = 1;
+
+ dk4utf8_init(&dec);
+ while (1 == cc) {
+ if ('\0' != *txt) {
+ switch (dk4utf8_add(&dec, *(txt++))) {
+ case DK4_EDSTM_ERROR : {
+ cc = -1;
+ exval = EXIT_FAILURE;
+ /* !!!!! ERROR: Decoding */
+ } break;
+ case DK4_EDSTM_FINISHED : {
+ if ((1 == isfirst) && (0 != argno)) {
+ if (EOF == fputc(' ', stdout)) { output_error = 1; }
+ }
+ isfirst = 0;
+ (void)dk_t2l_c32_after_cr_nl_check(dk4utf8_get(&dec), NULL, NULL);
+ } break;
+ }
+ } else {
+ cc = 0;
+ }
+ }
+ if (0 == cc) {
+ if (0 == dk4utf8_is_empty(&dec)) {
+ exval = EXIT_FAILURE;
+ /* !!!!! ERROR: Decoding */
+ }
+ }
+}
+
+/** Process one text word from command line, ANSI encoded.
+ @param txt Text word.
+ @param argno Number of current word.
+*/
+static
+void
+dk_t2l_echo_ansi(const dkChar *txt, int argno)
+{
+ dk4_c32_t c32;
+ int isfirst = 1;
+ char c;
+ while ('\0' != *txt) {
+ c = *(txt++);
+ if (0 != dk4ansi_decode(&c32, (unsigned char)c)) {
+ if ((1 == isfirst) && (0 != argno)) {
+ if (EOF == fputc(' ', stdout)) { output_error = 1; }
+ }
+ isfirst = 0;
+ (void)dk_t2l_c32_after_cr_nl_check(c32, NULL, NULL);
+ } else {
+ /* !!!!! ERROR: Decoding */
+ exval = EXIT_FAILURE;
+ }
+ }
+}
+
+#endif
+
+
+
+/** Process one text word from command line.
+ @param txt Text word.
+ @param argno Number of current word.
+*/
+static
+void
+dk_t2l_echo_text(const dkChar *txt, int argno)
+{
+#if DK4_CHAR_SIZE > 1
+#if DK4_CHAR_SIZE > 2
+ dk_t2l_echo_c32(txt, argno);
+#else
+ dk_t2l_echo_utf16(txt, argno);
+#endif
+#else
+ switch (dk4app_get_encoding(app)) {
+ case DK4_ENCODING_UTF8 : {
+ dk_t2l_echo_utf8(txt, argno);
+ } break;
+ case DK4_ENCODING_ANSI : {
+ dk_t2l_echo_ansi(txt, argno);
+ } break;
+ default : {
+ dk_t2l_echo_ascii(txt, argno);
+ } break;
+ }
+#endif
+ dk_t2l_end_math_mode();
+}
+
+
+
+/** Process command line arguments.
+*/
+static
+void
+dk_t2l_process_cmdline(void)
+{
+ const dkChar *xargv;
+ int argc;
+ int i;
+ /* !!!!! TODO: Implementation */
+ dk_t2l_output_start_file();
+ argc = dk4app_get_argc(app);
+ if (0 < argc) {
+ switch (dk_t2l_numeric) {
+ case 2: {
+ for (i = 0; i < argc; i++) {
+ xargv = dk4app_get_argv(app, i);
+ if (NULL != xargv) {
+ dk_t2l_echo_hex(xargv, i);
+ }
+ }
+ dk_t2l_end_math_mode();
+ } break;
+ case 1: {
+ for (i = 0; i < argc; i++) {
+ xargv = dk4app_get_argv(app, i);
+ if (NULL != xargv) {
+ dk_t2l_echo_numeric(xargv, i);
+ }
+ }
+ dk_t2l_end_math_mode();
+ } break;
+ default: {
+ for (i = 0; i < argc; i++) {
+ xargv = dk4app_get_argv(app, i);
+ if (NULL != xargv) {
+ dk_t2l_echo_text(xargv, i);
+ }
+ }
+ } break;
+ }
+ if (EOF == fputc('\n', stdout)) { output_error = 1; }
+ } else {
+ /* !!!!! ERROR: No command line arguments specified */
+ }
+ dk_t2l_output_finish_file();
+}
+
+
+
+/** Process an opened file with file name.
+ @param fipo Opened file.
+ @param fn File name.
+ @param ienc_def Expected input encoding.
+*/
+static
+void
+dk_t2l_process_named_file(FILE *fipo, const dkChar *fn, int ienc_def)
+{
+ dk4_tsp32_t tsp32;
+ dk4_er_t er;
+ dk4_er_t er_en;
+ dk4_er_t er_pr;
+ const dkChar *oldsourcefile;
+ dk4_um_t oldsourceline;
+ int c;
+ int cc;
+ int res;
+ unsigned char ub;
+
+ dk_t2l_in_mm = 0;
+ oldsourcefile = dk4app_get_log_source_file(app);
+ oldsourceline = dk4app_get_log_source_line(app);
+ dk4app_set_log_source_file(app, fn);
+ dk4app_set_log_source_line(app, (dk4_um_t)0UL);
+ dk_t2l_output_start_file();
+ dk4error_init(&er);
+ res = dk4tsp32_setup_char(
+ &tsp32, NULL, dk_t2l_c32_handler, ienc_def, &er
+ );
+ if (0 != res) {
+ cc = 1;
+ while (1 == cc) {
+ if (0 != dk_t2l_can_continue()) {
+ c = fgetc(fipo);
+ if (EOF != c) {
+ ub = (unsigned char)c;
+ res = dk4tsp32_add_one_byte(&tsp32, ub);
+ switch (res) {
+ case DK4_TSP_RES_ERROR: {
+ exval = EXIT_FAILURE;
+ dk4tsp32_get_errors(&er_en, &er_pr, &tsp32);
+ dk_t2l_report_errors(&er_en, &er_pr);
+ } break;
+ case DK4_TSP_RES_FATAL: {
+ cc = -1;
+ exval = EXIT_FAILURE;
+ dk4tsp32_get_errors(&er_en, &er_pr, &tsp32);
+ dk_t2l_report_errors(&er_en, &er_pr);
+ } break;
+ default: {
+ } break;
+ }
+ } else {
+ cc = 0;
+ }
+ if (0 != feof(fipo)) { if (1 == cc) { cc = 0; } }
+ } else {
+ cc = -1;
+ }
+ }
+ if (0 == cc) {
+ res = dk4tsp32_finish(&tsp32);
+ switch (res) {
+ case DK4_TSP_RES_ERROR: case DK4_TSP_RES_FATAL: {
+ exval = EXIT_FAILURE;
+ dk4tsp32_get_errors(&er_en, &er_pr, &tsp32);
+ dk_t2l_report_errors(&er_en, &er_pr);
+ } break;
+ }
+ }
+ if (0 != dk_t2l_can_continue()) {
+ /* TODO: Finish current line */
+ if (0 != dk_t2l_in_mm) {
+ dk_t2l_end_math_mode();
+ if (EOF == fputc('\n', stdout)) { output_error = 1; }
+ } else {
+ if (0 == dk_t2l_last_nl) {
+ if (EOF == fputc('\n', stdout)) { output_error = 1; }
+ }
+ }
+ }
+ } else {
+ /* ERROR: Setup failed, should not happen, bug */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 10);
+ exval = EXIT_FAILURE;
+ }
+ dk_t2l_output_finish_file();
+ dk4app_set_log_source_file(app, oldsourcefile);
+ dk4app_set_log_source_line(app, oldsourceline);
+}
+
+
+
+/** Process standard input.
+*/
+static
+void
+dk_t2l_process_stdin(void)
+{
+#if DK4_ON_WINDOWS
+ int oldmode;
+
+ oldmode = _setmode(_fileno(stdin), _O_BINARY);
+#endif
+ dk_t2l_process_named_file(stdin, dk_t2l_kwnl[4], dk_t2l_i_std);
+#if DK4_ON_WINDOWS
+ _setmode(_fileno(stdin), oldmode);
+#endif
+}
+
+
+
+/** Process one real file name.
+ @param infname File name to process.
+*/
+static
+void
+dk_t2l_process_one_file_name(const dkChar *infname)
+{
+ FILE *fipo = NULL;
+ int tests = DK4_FOPEN_SC_IS_REGULAR;
+ fipo = dk4fopen_app(infname, dk_t2l_kwnl[3], tests, app);
+ if (NULL != fipo) {
+ dk_t2l_process_named_file(fipo, infname, dk_t2l_i_file);
+ fclose(fipo);
+ } else {
+ exval = EXIT_FAILURE;
+ }
+}
+
+
+
+#if DK4_ON_WINDOWS
+
+/** Expand file name pattern and process the files.
+ @pattern File name pattern to expand.
+ @return 1 if files were found, 0 otherwise.
+*/
+static
+int
+dk_t2l_expand_and_process(const dkChar *pattern)
+{
+ dkChar buf[DK4_MAX_PATH];
+ dk4_dir_t *fne;
+ const dkChar *shf;
+ const dkChar *pth;
+ int cc;
+ int back = 0;
+ fne = dk4app_fne_open(pattern, app);
+ if (NULL != fne) {
+ cc = 1;
+ while (1 == cc) {
+ if (0 != dk_t2l_can_continue()) {
+ shf = dk4dir_next_file(fne);
+ if (NULL != shf) {
+ back = 1;
+ pth = dk4dir_get_path(fne);
+ if (NULL != pth) {
+ if (0 != dk4str_cpy_s(buf, DK4_SIZEOF(buf,dkChar), pth, NULL)) {
+ if(0!=dk4str_cat_s(buf,DK4_SIZEOF(buf,dkChar),dk_t2l_kwnl[5],NULL))
+ {
+ if(0 != dk4str_cat_s(buf, DK4_SIZEOF(buf,dkChar), shf, NULL)) {
+ dk_t2l_process_one_file_name(buf);
+ } else {
+ /* ERROR: Path too long */
+ dk4app_log_base3(app, DK4_LL_ERROR, 98, 99, pth);
+ exval = EXIT_FAILURE;
+ }
+ }
+ else
+ {
+ /* ERROR: Path too long */
+ dk4app_log_base3(app, DK4_LL_ERROR, 98, 99, pth);
+ exval = EXIT_FAILURE;
+ }
+ } else {
+ /* ERROR: Path too long */
+ dk4app_log_base3(app, DK4_LL_ERROR, 98, 99, pth);
+ exval = EXIT_FAILURE;
+ }
+ } else {
+ dk_t2l_process_one_file_name(shf);
+ }
+ } else {
+ cc = 0;
+ }
+ } else {
+ cc = -1;
+ }
+ }
+ dk4dir_close(fne);
+ } else {
+ exval = EXIT_FAILURE;
+ }
+ return back;
+}
+
+#endif
+
+
+
+/** Process one file name, check whether expansion is necessary.
+ @param infname Input file name to process, may be NULL.
+*/
+static
+void
+dk_t2l_process_filename(const dkChar *infname)
+{
+ if (NULL != infname) {
+#if DK4_ON_WINDOWS
+ if (0 != dk4path_must_expand(infname)) {
+ if (0 == dk_t2l_expand_and_process(infname)) {
+ exval = EXIT_FAILURE;
+ /* ERROR: No such file */
+ dk4app_log_base3(app, DK4_LL_ERROR, 100, 107, infname);
+ }
+ } else {
+#endif
+ dk_t2l_process_one_file_name(infname);
+#if DK4_ON_WINDOWS
+ }
+#endif
+ }
+}
+
+
+
+/** Run after installing the signal handlers.
+*/
+static
+void
+dk_t2l_normal_run(void)
+{
+ int argc;
+ int i;
+ if (0 != dk_t2l_process_options()) {
+ exval = EXIT_SUCCESS;
+ dk_t2l_output_start_page();
+ if (0 != dk_t2l_echo) {
+ dk_t2l_process_cmdline();
+ } else {
+ argc = dk4app_get_argc(app);
+ if (0 < argc) {
+ for (i = 0; ((0 != dk_t2l_can_continue()) && (i < argc)); i++) {
+ dk_t2l_process_filename(dk4app_get_argv(app, i));
+ }
+ } else {
+ dk_t2l_process_stdin();
+ }
+ }
+ dk_t2l_output_finish_page();
+ if (0 != dk4app_opt_is_set_short(app, dkT('r'), NULL)) {
+ dk4uc2l_recommendations(uc2l, stdout);
+ }
+ if (0 != dk4uc2l_retrieve_errors(uc2l)) { $? "! ERROR"
+ /* ERROR: Probably incorrect output due to problems */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 11);
+ exval = EXIT_FAILURE;
+ }
+ }
+ if (NULL != uc2l) {
+ dk4uc2l_close(uc2l);
+ uc2l = NULL;
+ }
+}
+
+
+
+#if DK4_HAVE_SIGACTION
+/** Set signal handlers and run.
+*/
+static
+void
+dk_t2l_run_with_signal_handlers(void)
+{
+#ifdef SIGPIPE
+ struct sigaction opipe;
+#endif
+ struct sigaction oint;
+#ifdef SIGPIPE
+ struct sigaction npipe;
+#endif
+ struct sigaction nint;
+ struct sigaction oterm;
+ struct sigaction nterm;
+ int success = 0;
+
+#ifdef SIGPIPE
+ /* Set up signal handling for SIGPIPE.
+ */
+ DK4_MEMRES(&npipe, sizeof(npipe));
+ npipe.sa_handler = sig_handler_pipe;
+ npipe.sa_flags = 0;
+ if (0 != sigemptyset(&npipe.sa_mask)) {
+ /* ERROR: Failed to set up masked signal set for SIGPIPE */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 0);
+ goto finished;
+ }
+ if (0 != sigaddset(&npipe.sa_mask, SIGPIPE)) {
+ /* ERROR: Failed to set up masked signal set for SIGPIPE */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 0);
+ goto finished;
+ }
+ if (0 != sigaction(SIGPIPE, &npipe, &opipe)) {
+ /* ERROR: Failed to set up signal handler for SIGPIPE */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 0);
+ goto finished;
+ }
+#endif
+
+ /* Set up signal handling for SIGINT.
+ */
+ DK4_MEMRES(&nint, sizeof(nint));
+ nint.sa_handler = sig_handler_int;
+ nint.sa_flags = 0;
+ if (0 != sigemptyset(&nint.sa_mask)) {
+ /* ERROR: Failed to set up masked signal set for SIGINT */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 0);
+ goto restore_old_pipe;
+ }
+ if (0 != sigaddset(&nint.sa_mask, SIGINT)) {
+ /* ERROR: Failed to set up masked signal set for SIGINT */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 0);
+ goto restore_old_pipe;
+ }
+ if (0 != sigaction(SIGINT, &nint, &oint)) {
+ /* ERROR: Failed to set up signal handler for SIGINT */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 0);
+ goto restore_old_pipe;
+ }
+
+ /* Set up signal handling for SIGTERM
+ */
+ DK4_MEMRES(&nterm, sizeof(nterm));
+ nterm.sa_handler = sig_handler_term;
+ nterm.sa_flags = 0;
+ if (0 != sigemptyset(&nterm.sa_mask)) {
+ /* ERROR: Failed to set up masked signal set for SIGTERM */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 0);
+ goto restore_old_int;
+ }
+ if (0 != sigaddset(&nterm.sa_mask, SIGTERM)) {
+ /* ERROR: Failed to set up masked signal set for SIGTERM */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 0);
+ goto restore_old_int;
+ }
+ if (0 != sigaction(SIGTERM, &nterm, &oterm)) {
+ /* ERROR: Failed to set up signal handler for SIGTERM */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 0);
+ goto restore_old_int;
+ }
+
+ success = 1;
+ dk_t2l_normal_run();
+
+ /* Restore signal handling for SIGTERM.
+ */
+ if (0 != sigaction(SIGTERM, &oterm, NULL)) {
+ /* ERROR: Failed to restore old SIGTERM settings */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 1);
+ success = 0;
+ }
+
+ /* Restore signal handling for SIGINT.
+ */
+ restore_old_int:
+ if (0 != sigaction(SIGINT, &oint, NULL)) {
+ /* ERROR: Failed to restore old SIGPIPE settings */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 1);
+ success = 0;
+ }
+
+#ifdef SIGPIPE
+ /* Restore signal handling for SIGPIPE.
+ */
+ restore_old_pipe:
+ if (0 != sigaction(SIGPIPE, &opipe, NULL)) {
+ /* ERROR: Failed to restore old SIGPIPE settings */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 1);
+ success = 0;
+ }
+#endif
+
+ /* Set exit status code if error occured.
+ */
+ finished:
+ if (0 == success) { exval = EXIT_FAILURE; }
+}
+#else
+#if DK4_HAVE_SIGSET
+/** Set signal handlers and run.
+*/
+static
+void
+dk_t2l_run_with_signal_handlers(void)
+{
+#ifdef SIGPIPE
+ dk4_sig_handler_t *oldpipe = NULL;
+#endif
+ dk4_sig_handler_t *oldint = NULL;
+ dk4_sig_handler_t *oldterm = NULL;
+
+#ifdef SIGPIPE
+ oldpipe = sigset(SIGPIPE, sig_handler_pipe);
+#endif
+ oldint = sigset(SIGINT, sig_handler_int);
+ oldterm = sigset(SIGTERM, sig_handler_term);
+ dk_t2l_normal_run();
+ sigset(SIGTERM, oldterm);
+ sigset(SIGINT, oldint);
+#ifdef SIGPIPE
+ sigset(SIGPIPE, oldpipe);
+#endif
+}
+#else
+#if DK4_HAVE_SIGNAL
+/** Set signal handlers and run.
+*/
+static
+void
+dk_t2l_run_with_signal_handlers(void)
+{
+#ifdef SIGPIPE
+ dk4_sig_handler_t *oldpipe = NULL;
+#endif
+ dk4_sig_handler_t *oldint = NULL;
+ dk4_sig_handler_t *oldterm = NULL;
+
+#ifdef SIGPIPE
+ oldpipe = signal(SIGPIPE, sig_handler_pipe);
+#endif
+ oldint = signal(SIGINT, sig_handler_int);
+ oldterm = signal(SIGTERM, sig_handler_term);
+ dk_t2l_normal_run();
+ signal(SIGTERM, oldterm);
+ signal(SIGINT, oldint);
+#ifdef SIGPIPE
+ signal(SIGPIPE, oldpipe);
+#endif
+}
+#else
+/** Set signal handlers and run.
+*/
+static
+void
+dk_t2l_run_with_signal_handlers(void)
+{
+ dk_t2l_normal_run();
+}
+#endif
+#endif
+#endif
+
+
+
+/** Main function.
+ @param argc Number of command line arguments.
+ @param argv Command line arguments array.
+ @return 0 on success, all other values indicate errors.
+*/
+#if DK4_CHAR_SIZE > 1
+int wmain(int argc, wchar_t *argv[])
+#else
+int main(int argc, char *argv[])
+#endif
+{
+ int shp;
+ $!trace-init dk-t2l.deb
+ $? "+ main"
+ dk4fput_initialize_stderr();
+ app = dk4app_open_cmd(
+ argc, argv, dk_t2l_options, dk_t2l_sz_options,
+ dk_t2l_kwnl[0], DKT_VERSION_DK,
+ dk_t2l_kwnl[1], dk_t2l_help_text, dk_t2l_license_text
+ );
+ if (NULL != app) {
+ dk_t2l_i_std = dk4app_get_stdin_encoding(app);
+ dk_t2l_i_file = dk4app_get_file_in_encoding(app);
+ dk_t2l_sz_msg = dk4app_string_table_size(dk_t2l_kw_def);
+ dk_t2l_msg = dk4app_string_table(app, dk_t2l_kwnl[2], dk_t2l_kw_def);
+ if (0 != dk4app_can_run_normally(app)) {
+ dk_t2l_run_with_signal_handlers();
+ } else {
+ dk4fput_initialize_stdout();
+ if (0 != dk4app_help_version_license(app)) {
+ exval = EXIT_SUCCESS;
+ }
+ fflush(stdout);
+ fflush(stderr);
+ dk4fput_cleanup_stdout();
+ }
+ if (0 != sig_read_atomic(&sig_had_int )) {
+ exval = EXIT_FAILURE;
+ /* ERROR: Interrupted by SIGINT */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 12);
+ }
+ if (0 != sig_read_atomic(&sig_had_term)) {
+ exval = EXIT_FAILURE;
+ /* ERROR: Interrupted by SIGTERM */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 13);
+ }
+#ifdef SIGPIPE
+ if (0 != sig_read_atomic(&sig_had_pipe)) {
+ exval = EXIT_FAILURE;
+ shp = 1;
+ /* ERROR: Interrupted by SIGPIPE */
+ if (0 != verbose) {
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 14);
+ }
+ } else {
+ shp = 0;
+ }
+#else
+ shp = 0;
+#endif
+ if ((0 == shp) && (0 != output_error)) {
+ exval = EXIT_FAILURE;
+ /* ERROR: Output to stdout failed */
+ dk4app_log_1(app, dk_t2l_msg, dk_t2l_sz_msg, DK4_LL_ERROR, 15);
+ }
+ dk4app_close(app);
+ }
+ fflush(stdout);
+ if (0 != sig_read_atomic(&sig_had_int )) { exval = EXIT_FAILURE; }
+ if (0 != sig_read_atomic(&sig_had_term)) { exval = EXIT_FAILURE; }
+#ifdef SIGPIPE
+ if (0 != sig_read_atomic(&sig_had_pipe)) { exval = EXIT_FAILURE; }
+#endif
+ if (0 != output_error) { exval = EXIT_FAILURE; }
+ fflush(stderr);
+ dk4fput_cleanup_stderr();
+ $? "- main %d", exval
+ $!trace-end
+ exit(exval); return exval;
+}
+
+