/* WARNING: This file was generated by dkct. Changes you make here will be lost if dkct is run again! You should modify the original source and run dkct on it. Original source: dk-cat.ctr */ /* Copyright (C) 2015-2017, Dirk Krause 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 opyright 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 author 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. */ #line 10 "dk-cat.ctr" /** @file dk-cat.c The dk-cat program. The dk_cat_help_text array below shows details. */ #include "dk4conf.h" #include #if DK4_HAVE_STDLIB_H #ifndef STDLIB_H_INCLUDED #include #define STDLIB_H_INCLUDED 1 #endif #endif #if DK4_HAVE_UNISTD_H #ifndef UNISTD_H_INCLUDED #include #define UNISTD_H_INCLUDED 1 #endif #endif #if DK4_HAVE_PROCESS_H #ifndef PROCESS_H_INCLUDED #include #define PROCESS_H_INCLUDED 1 #endif #endif #if DK4_HAVE_IO_H #ifndef IO_H_INCLUDED #include #define IO_H_INCLUDED 1 #endif #endif #if DK4_HAVE_FCNTL_H #ifndef FCNTL_H_INCLUDED #include #define FCNTL_H_INCLUDED 1 #endif #endif #if DK4_HAVE_SYS_TYPES_H #ifndef SYS_TYPES_H_INCLUDED #include #define SYS_TYPES_H_INCLUDED 1 #endif #endif #if DK4_HAVE_SIGNAL_H #ifndef SIGNAL_H_INCLUDED #include #define SIGNAL_H_INCLUDED 1 #endif #endif #include "dk4types.h" #include "dk4const.h" #include "dk4vers.h" #include "dk4app.h" #include "dk4aopt.h" #include "dk4enc.h" #include "dk4mem.h" #include "dk4strm.h" #include "dk4strmf.h" #include "dk4strmo32.h" #include "dk4istty.h" #include "dk4fopda.h" #include "dk4tsp32.h" #include "dk4tspdk.h" #include "dk4mao8d.h" #include "dk4str8.h" #include "dk4strd.h" #include "dk4pathd.h" #include "dk4fput.h" #include "dk4maodd.h" #include "dk4mpl.h" #include "dk4isadm.h" #line 94 "dk-cat.ctr" #ifndef DK_CAT_INPUT_BUFFER_SIZE /** Input buffer size. */ #define DK_CAT_INPUT_BUFFER_SIZE 4096 #endif /** Default text, used if help text file is not found. */ static const dkChar * const dk_cat_help_text[] = { dkT(""), dkT("Show text files"), dkT(""), dkT("dk-cat [] []"), dkT(""), dkT("Options:"), dkT("-c Enable CR/NL -n Write line numbers"), dkT("-i Expected input encoding -w Normalize text lines"), dkT("-o Output encoding -p No unneccessary decoding/encoding"), dkT("--help Show this short help text. --manual *** SHOW FULL MANUAL. ***"), dkT("--version Show version information. --license Show license information."), dkT("--verbose Error message on SIGPIPE"), dkT("--line-number-width= Minimum line number width."), dkT(""), dkT("Encoding names: plain (ASCII text), ascii (synonym for plain), ansi, utf-8,"), dkT("utf-16, utf-16le (little-endian) utf-16be (big-endian),"), dkT("c32 (32 bit characters), c32le, c32be."), dkT(""), dkT("http://dktools.sourceforge.net"), dkT(""), NULL #line 130 "dk-cat.ctr" }; /** License conditions. */ static const dkChar * const dk_cat_license_text[] = { dkT(""), dkT("This software uses code from the following projects, either directly or as"), dkT("a library:"), dkT(""), dkT("dktools\t\tDirk Krause's tools and libraries."), dkT("\t\tSee http://dktools.sourceforge.net/ for more information."), #if DK4_HAVE_ZLIB_H dkT(""), dkT("zlib\t\tData compression library."), dkT("\t\tSee http://www.zlib.net/ for more information."), #endif #if DK4_HAVE_BZLIB_H dkT(""), dkT("bzip2\t\tData compression program and library."), dkT("\t\tSee http://www.bzip.org/ for more information."), #endif dkT(""), dkT("All the licenses below apply to the program."), dkT("Licenses for used libraries are shown as found on my Scientific Linux 6.x"), dkT("computer in the /usr/share/doc directory on 2015-04-01. Check the project"), dkT("homepages of the used libraries for additional information and/or updated"), dkT("license terms."), dkT(""), dkT(""), dkT("DK tools and libraries license"), dkT("=============================="), dkT("Copyright (c) 2015-2016, Dirk Krause"), dkT("All rights reserved."), dkT(""), dkT("Redistribution and use in source and binary forms, with or without"), dkT("modification, are permitted provided that the following conditions are met:"), dkT(""), dkT("* Redistributions of source code must retain the above copyright notice,"), dkT(" this list of conditions and the following disclaimer."), dkT("* Redistributions in binary form must reproduce the above copyright"), dkT(" notice, this list of conditions and the following disclaimer in the"), dkT(" documentation and/or other materials provided with the distribution."), dkT("* Neither the name of the Dirk Krause nor the names of contributors may be"), dkT(" used to endorse or promote products derived from this software without"), dkT(" specific prior written permission."), dkT(""), dkT("THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\""), dkT("AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE"), dkT("IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE"), dkT("ARE DISCLAIMED."), dkT(""), dkT("IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,"), dkT("INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,"), dkT("BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,"), dkT("DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY"), dkT("OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING"), dkT("NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,"), dkT("EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."), #if DK4_HAVE_ZLIB_H dkT(""), dkT(""), dkT("Zlib license"), dkT("============"), dkT("(C) 1995-2004 Jean-loup Gailly and Mark Adler"), dkT(""), dkT("This software is provided 'as-is', without any express or implied"), dkT("warranty. In no event will the authors be held liable for any damages"), dkT("arising from the use of this software."), dkT(""), dkT("Permission is granted to anyone to use this software for any purpose,"), dkT("including commercial applications, and to alter it and redistribute it"), dkT("freely, subject to the following restrictions:"), dkT(""), dkT("1. The origin of this software must not be misrepresented; you must not"), dkT(" claim that you wrote the original software. If you use this software"), dkT(" in a product, an acknowledgment in the product documentation would be"), dkT(" appreciated but is not required."), dkT("2. Altered source versions must be plainly marked as such, and must not be"), dkT(" misrepresented as being the original software."), dkT("3. This notice may not be removed or altered from any source distribution."), dkT(""), dkT("Jean-loup Gailly Mark Adler"), dkT("jloup@gzip.org madler@alumni.caltech.edu"), #endif #if DK4_HAVE_BZLIB_H dkT(""), dkT(""), dkT("Bzip2 and libbzip2 library license"), dkT("=================================="), dkT("This program, \"bzip2\", the associated library \"libbzip2\", and all"), dkT("documentation, are copyright (C) 1996-2007 Julian R Seward. All"), dkT("rights reserved."), dkT(""), dkT("Redistribution and use in source and binary forms, with or without"), dkT("modification, are permitted provided that the following conditions"), dkT("are met:"), dkT(""), dkT("1. Redistributions of source code must retain the above copyright"), dkT(" notice, this list of conditions and the following disclaimer."), dkT(""), dkT("2. The origin of this software must not be misrepresented; you must "), dkT(" not claim that you wrote the original software. If you use this "), dkT(" software in a product, an acknowledgment in the product "), dkT(" documentation would be appreciated but is not required."), dkT(""), dkT("3. Altered source versions must be plainly marked as such, and must"), dkT(" not be misrepresented as being the original software."), dkT(""), dkT("4. The name of the author may not be used to endorse or promote "), dkT(" products derived from this software without specific prior written "), dkT(" permission."), dkT(""), dkT("THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS"), dkT("OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED"), dkT("WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE"), dkT("ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY"), dkT("DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL"), dkT("DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE"), dkT("GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS"), dkT("INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,"), dkT("WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING"), dkT("NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS"), dkT("SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."), dkT(""), dkT("Julian Seward, jseward@bzip.org"), dkT("bzip2/libbzip2 version 1.0.5 of 10 December 2007"), #endif dkT(""), NULL #line 262 "dk-cat.ctr" }; /** Constant texts used by program, not localized. */ static const dkChar * const dk_cat_kwnl[] = { /* 0 */ dkT("dktools"), /* 1 */ dkT("dk-cat.txt"), /* 2 */ dkT("dk-cat.str"), /* 3 */ dkT("line-number-width"), /* 4 */ dkT("stdin"), /* 5 */ dkT("\\"), /* 6 */ dkT("verbose"), NULL #line 299 "dk-cat.ctr" }; /** Constant texts used by program, replaced by localized texts if available. */ static const dkChar * const dk_cat_kw_def[] = { /* 0 */ dkT("Decoding error!\n\tByte: "), /* 1 */ dkT("Another decoding error!"), /* 2 */ dkT("Further decoding errors!"), /* 3 */ dkT("Encoding error!\n\tByte: "), /* 4 */ dkT("Another encoding error!"), /* 5 */ dkT("Further encoding errors!"), /* 6 */ dkT("Processing error!\n\tByte: "), /* 7 */ dkT("Another processing error!"), /* 8 */ dkT("Further processing errors!"), /* 9 */ dkT(",\n\tCharacter: "), /* 10 */ dkT(",\n\tPosition in line: "), /* 11 */ dkT("Decoding error!"), /* 12 */ dkT("Encoding error!"), /* 13 */ dkT("Processing error!"), /* 14 */ dkT("."), /* 15 */ dkT("Illegal input encoding: \""), /* 16 */ dkT("\"!"), /* 17 */ dkT("Illegal output encoding: \""), /* 18 */ dkT("\"!"), /* 19 */ dkT("Line number width must be larger than 0!"), /* 20 */ dkT("Failed to write text to output!"), /* 21 */ dkT("Numeric conversion failed (should not happen, probably bug in program)!"), /* 22 */ dkT("Failed to set up signal handlers!"), /* 23 */ dkT("Failed to restore signal handlers!"), /* 24 */ dkT("Signal received: SIGPIPE!"), /* 25 */ dkT("Signal received: SIGINT!"), NULL #line 377 "dk-cat.ctr" }; /** Message texts, uses localized texts if possible. */ static const dkChar * const *msg = dk_cat_kw_def; /** Options used by program. */ static const dk4_option_specification_t dk_cat_options[] = { /* Flag: Line end consists of carriage return and newline. */ { dkT('c'), dkT("crnl"), DK4_OPT_ARG_BOOL }, /* Show line numbers. */ { dkT('n'), dkT("line-numbers"), DK4_OPT_ARG_NONE }, /* Number of digits for line numbers. */ { dkT('\0'), dkT("line-number-width"), DK4_OPT_ARG_SIZE }, /* Flag: Normalize text lines. */ { dkT('w'), dkT("normalize"), DK4_OPT_ARG_NONE }, /* Expected input encoding. */ { dkT('i'), dkT("input-encoding"), DK4_OPT_ARG_STRING }, /* Output encoding to produce. */ { dkT('o'), dkT("output-encoding"), DK4_OPT_ARG_STRING }, /* Pass-through UTF-8 data. */ { dkT('p'), dkT("pass-through"), DK4_OPT_ARG_NONE }, /* Verbose output. */ { dkT('\0'), dkT("verbose"), DK4_OPT_ARG_NONE } }; #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; 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; } /** Application structure. */ static dk4_app_t *app = NULL; /** Number of elements in the dk_cat_options array. */ static const size_t dk_cat_sz_options = sizeof(dk_cat_options)/sizeof(dk4_option_specification_t); /** Number of usable elements in the dk_cat_kw_def array and in msg. */ static size_t sz_msg = (sizeof(dk_cat_kw_def)/sizeof(DK4_PDKCHAR) - 1); /** Name of current input file processed. */ static const dkChar *input_file_name = NULL; /** Flag: Output already initialized. */ static int output_initialized = 0; #if DK4_ON_WINDOWS /** Original mode for stdout. */ static int old_output_mode = 0; #endif /** Flag: Use stream instead output to stdout. */ static int use_stream = 1; /** System output encoding. */ static int oenc_sys = DK4_FILE_ENCODING_ASCII; /** Default output encoding on the system. */ static int oenc_def = DK4_FILE_ENCODING_ASCII; /** Output encoding specified on command line. */ static int oenc = DK4_FILE_ENCODING_ASCII; /** System setting whether or not to write a BOM. */ static int obom_sys = 0; /** Flag: Write BOM. -1=auto, 0=no, 1=yes. */ static int obom = -1; /** Default CR/NL sequence setting. */ static int crnl_def = DK4_HAVE_LINE_END_CR_NL; /** CR/NL sequence setting from options if available. */ static int crnl = DK4_HAVE_LINE_END_CR_NL; /** Input encoding specified on the command line. */ static int ienc_def = DK4_FILE_ENCODING_ASCII; /** Flag: Show line numbers (from options). */ static int line_numbers = 0; /** Current line number. */ static dk4_um_t line_number = (dk4_um_t)1UL; /** Flag: Previous character was carriage return. */ static int previous_was_cr = 0; /** Flag: Previous character was not a whitespace. */ static int previous_was_text = 0; /** Flag: Previous character was a newline. */ static int previous_was_nl = 0; /** Flag: We already had text in this line. */ static int text_in_line = 0; /** Flag: We had any output for this file. */ static int there_was_text = 0; /** Flag: Line number was already printed for current line. */ static int line_number_printed = 0; /** Line number width. */ static size_t line_number_width = 5; /** Flag: Normalize lines. */ static int normalize_lines = 0; /** Exit status code. */ static int exval = EXIT_FAILURE; /** Flag: Already reported encoding errors for this file. */ static int had_encoding_error = 0; /** Flag: Already reported decoding errors for this file. */ static int had_decoding_error = 0; /** Flag: Already reported processing errors for this file. */ static int had_processing_error = 0; /** Flag: Had error while writing to stdout. */ static int had_write_error = 0; /** Flag: Verbose output (report SIGPIPE). */ static int verbose = 0; /** Output stream. */ static dk4_stream_t *output_stream = NULL; /* We can output to stdout using dk4fputc() if all the conditions below are true: - output encoding is system output encoding and - CR/NL setting is system CR/NL setting and - BOM settings is ``automatic'' or is system BOM setting. Otherwise we set stdout in binary mode (on Windows only) and use a dk4_stream_t to process 32 bit characters. */ /** Initialize settings from application. @return 1 on success, 0 on error. */ static int initialize_from_app(void) { dkChar buf[32]; int res = 0; /* Operation result */ int back = 1; #line 711 "dk-cat.ctr" /* String tables and defaults. */ #line 715 "dk-cat.ctr" oenc_sys = dk4app_get_stdout_encoding(app); oenc_def = oenc_sys; ienc_def = dk4app_get_stdin_encoding(app); #line 719 "dk-cat.ctr" if (0 < dk4app_get_argc(app)) { ienc_def = dk4app_get_file_in_encoding(app); #line 722 "dk-cat.ctr" } /* Set verbose flag if -v was used. */ if (0 != dk4app_opt_is_set_long(app, dk_cat_kwnl[6], NULL)) { verbose = 1; } /* Output encoding to produce (-o) */ #line 733 "dk-cat.ctr" if (0 != dk4app_opt_is_set_short(app, dkT('o'), NULL)) { #line 734 "dk-cat.ctr" res = dk4app_opt_get_string_short( buf, DK4_SIZEOF(buf,dkChar), app, dkT('o'), NULL ); if (0 != res) { #line 738 "dk-cat.ctr" res = dk4enc_find(&oenc_def, &obom, buf, NULL); if (0 == res) { #line 740 "dk-cat.ctr" /* ERROR: Illegal output encoding */ dk4app_log_3(app, msg, sz_msg, DK4_LL_ERROR, 17, 18, buf); back = 0; } } else { #line 745 "dk-cat.ctr" /* ERROR: BUG, No option argument */ back = 0; } } /* Expected input encoding (-i) */ #line 753 "dk-cat.ctr" if (0 != dk4app_opt_is_set_short(app, dkT('i'), NULL)) { #line 754 "dk-cat.ctr" res = dk4app_opt_get_string_short( buf, DK4_SIZEOF(buf,dkChar), app, dkT('i'), NULL ); if (0 != res) { #line 758 "dk-cat.ctr" res = dk4enc_find(&ienc_def, NULL, buf, NULL); if (0 == res) { #line 760 "dk-cat.ctr" /* ERROR: Illegal input encoding */ dk4app_log_3(app, msg, sz_msg, DK4_LL_ERROR, 15, 16, buf); back = 0; } } else { #line 765 "dk-cat.ctr" /* ERROR: BUG, No option argument */ back = 0; } } /* CR/NL (-c) */ #line 773 "dk-cat.ctr" if (0 != dk4app_opt_is_set_short(app, dkT('c'), NULL)) { #line 774 "dk-cat.ctr" if (0 == dk4app_opt_get_bool_short(&crnl, app, dkT('c'), NULL)) { /* ERROR: BUG, No option argument */ back = 0; #line 777 "dk-cat.ctr" } } /* Line numbers (-n) */ #line 783 "dk-cat.ctr" if (0 != dk4app_opt_is_set_short(app, dkT('n'), NULL)) { #line 784 "dk-cat.ctr" line_numbers = 1; } /* Line number width (--line-number-width) */ #line 790 "dk-cat.ctr" if (0 != dk4app_opt_is_set_long(app, dk_cat_kwnl[3], NULL)) { #line 791 "dk-cat.ctr" if (0 == dk4app_opt_get_size_long(&line_number_width, app, dk_cat_kwnl[3], NULL)) { /* ERROR: BUG, No option argument */ back = 0; #line 794 "dk-cat.ctr" } else { if (0 == line_number_width) { #line 796 "dk-cat.ctr" /* ERROR: Illegal line number width */ dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 19); back = 0; } } } /* Normalize text (-w) */ #line 806 "dk-cat.ctr" if (0 != dk4app_opt_is_set_short(app, dkT('w'), NULL)) { #line 807 "dk-cat.ctr" normalize_lines = 1; } #line 811 "dk-cat.ctr" switch (oenc_sys) { case DK4_FILE_ENCODING_ASCII : case DK4_FILE_ENCODING_ANSI : case DK4_FILE_ENCODING_UTF8 : { obom_sys = 0; } break; default : { if (0 == dk4istty(1, NULL)) { obom_sys = 1; } } break; } oenc = oenc_def; #line 828 "dk-cat.ctr" return back; } /** Check whether we can write to standard output directly. */ static void decide_for_output_type(void) { if (oenc_def == oenc_sys) { if (crnl == crnl_def) { if ((-1 == obom) || (obom_sys == obom)) { use_stream = 0; } } } } /** Initialize output structures before writing first output. */ static void initialize_output(void) { dk4_er_t er; #line 858 "dk-cat.ctr" if (0 == output_initialized) { output_initialized = 1; if (0 != use_stream) { dk4error_init(&er); #if DK4_ON_WINDOWS #line 864 "dk-cat.ctr" old_output_mode = _setmode(_fileno(stdout), _O_BINARY); #endif output_stream = dk4stream_open_for_file( stdout, DK4_STREAM_WRITE, 0, 4096, &er ); if (NULL != output_stream) { dk4stream_set_output_encoding(output_stream, oenc); switch (obom) { case 1: { if(0 == dk4stream_c32_putc(output_stream, dkC32(0xFEFF), NULL)) { /* ERROR: Failed to write BOM */ dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 20); exval = EXIT_FAILURE; } } break; case -1: { if (1 == obom_sys) { if(0 == dk4stream_c32_putc(output_stream,dkC32(0xFEFF),NULL)) { /* ERROR: Failed to write BOM */ dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 20); exval = EXIT_FAILURE; } } } break; } } else { /* ERROR: Failed to create stream */ dk4app_log_base1(app, DK4_LL_ERROR, 90); } } else { dk4fput_initialize_stdout(); } } #line 897 "dk-cat.ctr" } /** Close stream, or set mode for stdout back to original mode. */ static void cleanup_output(void) { dk4_er_t er; #line 909 "dk-cat.ctr" if (0 != output_initialized) { if (0 != use_stream) { if (NULL != output_stream) { /* Close output stream. */ dk4error_init(&er); if (0 == dk4stream_close(output_stream, &er)) { /* ERROR: Closing the stream failed */ dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 20); exval = EXIT_FAILURE; } } #if DK4_ON_WINDOWS /* Set stdout to original mode. */ #line 925 "dk-cat.ctr" _setmode(_fileno(stdout), old_output_mode); #endif } else { dk4fput_cleanup_stdout(); } } #line 931 "dk-cat.ctr" } /** 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 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))]; const dkChar *oldlogname = NULL; dk4_um_t oldlogline = (dk4_um_t)0UL; int allbuffersok = 0; oldlogname = dk4app_get_log_source_file(app); oldlogline = dk4app_get_log_source_line(app); dk4app_set_log_source_file(app, input_file_name); 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, msg, sz_msg, DK4_LL_ERROR, i1, 9, 10, 14, b1, b2, b3 ); } else { dk4app_log_1( app, msg, sz_msg, DK4_LL_ERROR, i2 ); } dk4app_set_log_source_file(app, oldlogname); dk4app_set_log_source_line(app, oldlogline); } /** Report an error occured while writing 32 bit character to output stream. @param erp Error information returned by dk4stream_c32_putc(). @param pos Position information. */ static void error_while_writing_c32(dk4_er_t *erp, dk4_text_stream_position_t *pos) { dk4_um_t bytes = (dk4_um_t)0UL; dk4_um_t lineno = (dk4_um_t)0UL; dk4_um_t chars = (dk4_um_t)0UL; dk4_um_t charil = (dk4_um_t)0UL; switch (erp->ec) { case DK4_E_ENCODING_FAILED : { if (NULL != pos) { bytes = pos->bytes; lineno = pos->lineno; chars = pos->chars; charil = pos->charil; } if ((dk4_um_t)0UL < bytes) { bytes = bytes - (dk4_um_t)1UL; } if ((dk4_um_t)0UL < chars) { chars = chars - (dk4_um_t)1UL; } if ((dk4_um_t)0UL < charil) { charil = charil - (dk4_um_t)1UL; } report_with_position(3, 12, bytes, lineno, chars, charil); } break; default: { dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 20); } break; } } /** Write one 32 bit character to output. If the character is a newline, convert to carriage return and newline sequence if required by crnl settings. @param obj Object to modify while processing the character (NULL here). @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 c32_real_output( void *obj, dk4_c32_t c, dk4_text_stream_position_t *pos, dk4_er_t *erp ) { dk4_er_t er; int back = DK4_TSP_RES_OK; dk4_sig_atomic_t shp; #line 1049 "dk-cat.ctr" initialize_output(); if (0 != use_stream) { if (NULL != output_stream) { dk4error_init(&er); #ifdef SIGPIPE shp = sig_read_atomic(&sig_had_pipe); #else shp = 0; #endif if (0 == shp) { if ((dkC32(0x0A) == c) && (0 != crnl)) { if (0 == dk4stream_c32_putc(output_stream, dkC32(0x0D), &er)) { /* ERROR: Failed to write output character */ error_while_writing_c32(&er, pos); back = DK4_TSP_RES_FATAL; } } if (0 == dk4stream_c32_putc(output_stream, c, &er)) { /* ERROR: Failed to write output character */ error_while_writing_c32(&er, pos); back = DK4_TSP_RES_FATAL; } } } else { /* ERROR: Failed to create output stream (already reported) */ back = DK4_TSP_RES_FATAL; } } else { } if (dkC32(0x0A) == c) { previous_was_nl = 1; } else { previous_was_nl = 0; } there_was_text = 1; #line 1085 "dk-cat.ctr" return back; } /** Check whether a character is the first character in a line, write line number if necessary and write the character. @param obj Object to modify while processing the character (NULL here). @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 c32_after_normalize( void *obj, dk4_c32_t c, dk4_text_stream_position_t *pos, dk4_er_t *erp ) { char buf[8*(1+sizeof(dk4_um_t))]; char *ptr = NULL; size_t i = 0; int res = 0; int back = DK4_TSP_RES_OK; #line 1118 "dk-cat.ctr" if (0 != line_numbers) { if (0 == line_number_printed) { line_number_printed = 1; res = dk4ma_write_c8_decimal_unsigned( buf, sizeof(buf), line_number, 0, NULL ); if (0 != res) { /* Spaces before line number. */ i = dk4str8_len(buf); while (i < line_number_width) { switch (c32_real_output(obj, dkC32(0x20), 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; } i++; } /* Line number */ ptr = buf; while ('\0' != *ptr) { res = c32_real_output( obj, (dk4_c32_t)((unsigned char)(*(ptr++))), pos, erp ); switch (res) { 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; } } /* Trailing space after line number */ switch (c32_real_output(obj, dkC32(0x20), 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 { /* ERROR: Failed to convert line number. */ dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 21); back = DK4_TSP_RES_FATAL; } } switch (c32_real_output(obj, 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 = c32_real_output(obj, c, pos, erp); } #line 1190 "dk-cat.ctr" return back; } /** Normalize the text if required and pass characters downwards. @param obj Object to modify while processing the character (NULL here). @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 c32_after_cr_nl( void *obj, dk4_c32_t c, dk4_text_stream_position_t *pos, dk4_er_t *erp ) { int back = DK4_TSP_RES_OK; #line 1218 "dk-cat.ctr" if (0 != normalize_lines) { if ((dkC32(0x09) == c) || (dkC32(0x20) == c) || (dkC32(0x0D) == c)) { previous_was_text = 0; } else { if (dkC32(0x0A) == c) { previous_was_text = 0; back = c32_after_normalize(obj, c, pos, erp); text_in_line = 0; } else { if ((0 == previous_was_text) && (0 != text_in_line)) { back = c32_after_normalize(obj, dkC32(0x20), pos, erp); } switch (c32_after_normalize(obj, 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; } previous_was_text = 1; text_in_line = 1; } } } else { back = c32_after_normalize(obj, c, pos, erp); } #line 1247 "dk-cat.ctr" 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 c32_handler( void *obj, dk4_c32_t c, dk4_text_stream_position_t *pos, dk4_er_t *erp ) { int back = DK4_TSP_RES_OK; #line 1274 "dk-cat.ctr" dk4app_set_log_source_line(app, line_number); if (dkC32(0x0D) == c) { #line 1276 "dk-cat.ctr" if (0 != previous_was_cr) { back = c32_after_cr_nl(obj, dkC32(0x0D), pos, erp); } previous_was_cr = 1; } else { if (dkC32(0x0A) == c) { #line 1282 "dk-cat.ctr" back = c32_after_cr_nl(obj, c, pos, erp); line_number++; dk4app_set_log_source_line(app, line_number); line_number_printed = 0; text_in_line = 0; } else { #line 1288 "dk-cat.ctr" if (0 != previous_was_cr) { back = c32_after_cr_nl(obj, dkC32(0x0D), pos, erp); } switch (c32_after_cr_nl(obj, 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; } } previous_was_cr = 0; } #line 1304 "dk-cat.ctr" return back; } /** Write one dkChar to output (for a newline write a carriage return, newline sequence if required). @param obj Object to modify while processing the character (NULL here). @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 dkc_real_output( void *obj, dkChar c, dk4_text_stream_position_t *pos, dk4_er_t *erp ) { dk4_er_t er; int back = DK4_TSP_RES_OK; dk4_sig_atomic_t shp; #line 1335 "dk-cat.ctr" initialize_output(); dk4error_init(&er); #ifdef SIGPIPE shp = sig_read_atomic(&sig_had_pipe); #else shp = 0; #endif if (0 == shp) { if (0 == dk4fputc(c, stdout, &er)) { /* ERROR while writing to standard output */ #if 0 dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 20); #endif had_write_error = 0; back = DK4_TSP_RES_FATAL; exval = EXIT_FAILURE; } } if (dkT('\n') == c) { previous_was_nl = 1; } else { previous_was_nl = 0; } there_was_text = 1; #line 1360 "dk-cat.ctr" return back; } /** Pass character downwards to dkc_real_output(). If the character is the first in the line, prepend line number if required. @param obj Object to modify while processing the character (NULL here). @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 dkc_after_normalize( void *obj, dkChar c, dk4_text_stream_position_t *pos, dk4_er_t *erp ) { char buf[8*(1+sizeof(dk4_um_t))]; char *ptr = NULL; size_t i = 0; int res = 0; int back = DK4_TSP_RES_OK; #line 1394 "dk-cat.ctr" if (0 != line_numbers) { if (0 == line_number_printed) { line_number_printed = 1; res = dk4ma_write_c8_decimal_unsigned( buf, sizeof(buf), line_number, 0, NULL ); if (0 != res) { /* Spaces before line number. */ i = dk4str8_len(buf); while (i < line_number_width) { switch (dkc_real_output(obj, dkT(' '), 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; } i++; } /* Line number */ ptr = buf; while ('\0' != *ptr) { res = dkc_real_output( obj, (dkChar)((unsigned char)(*(ptr++))), pos, erp ); switch (res) { 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; } } /* Trailing space after line number */ switch (dkc_real_output(obj, dkT(' '), 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 { /* ERROR: Failed to convert line number. */ dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 21); back = DK4_TSP_RES_FATAL; } } switch (dkc_real_output(obj, 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 = dkc_real_output(obj, c, pos, erp); } #line 1466 "dk-cat.ctr" return back; } /** Normalize text if required and pass characters downwards. @param obj Object to modify while processing the character (NULL here). @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 dkc_after_cr_nl( void *obj, dkChar c, dk4_text_stream_position_t *pos, dk4_er_t *erp ) { int back = DK4_TSP_RES_OK; #line 1494 "dk-cat.ctr" if (0 != normalize_lines) { if ((dkT('\t') == c) || (dkT(' ') == c) || (dkT('\r') == c)) { previous_was_text = 0; } else { if (dkT('\n') == c) { previous_was_text = 0; back = dkc_after_normalize(obj, c, pos, erp); text_in_line = 0; } else { if ((0 == previous_was_text) && (0 != text_in_line)) { back = dkc_after_normalize(obj, dkT(' '), pos, erp); } switch (dkc_after_normalize(obj, 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; } previous_was_text = 1; text_in_line = 1; } } } else { back = dkc_after_normalize(obj, c, pos, erp); } #line 1523 "dk-cat.ctr" return back; } /** Handler function for single characters. @param obj Object to modify while processing the character (NULL here). @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 dkc_handler( void *obj, dkChar c, dk4_text_stream_position_t *pos, dk4_er_t *erp ) { int back = DK4_TSP_RES_OK; #line 1551 "dk-cat.ctr" dk4app_set_log_source_line(app, line_number); if (dkT('\r') == c) { if (0 != previous_was_cr) { back = dkc_after_cr_nl(obj, dkT('\r'), pos, erp); } previous_was_cr = 1; } else { if (dkT('\n') == c) { back = dkc_after_cr_nl(obj, c, pos, erp); line_number++; dk4app_set_log_source_line(app, line_number); line_number_printed = 0; text_in_line = 0; } else { if (0 != previous_was_cr) { back = dkc_after_cr_nl(obj, dkT('\r'), pos, erp); } switch (dkc_after_cr_nl(obj, 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; } } previous_was_cr = 0; } #line 1582 "dk-cat.ctr" return back; } /** Initialize variables like line number and others for one file. */ static void initialize_for_one_file(void) { #line 1594 "dk-cat.ctr" line_number = (dk4_um_t)1UL; previous_was_cr = 0; previous_was_nl = 0; previous_was_text = 0; line_number_printed = 0; there_was_text = 0; had_encoding_error = 0; had_decoding_error = 0; had_processing_error = 0; text_in_line = 0; #line 1605 "dk-cat.ctr" } /** Report errors indicated by text processing. @param er_en Error report for decoding and encoding errors. @param er_pr Error report for processing errors. */ static void 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 (had_decoding_error) { case 0: case 1: { report_with_position( ((0 == had_decoding_error) ? 0 : 1), 11, er_en->dt.fpos.byteno, er_en->dt.fpos.lineno, er_en->dt.fpos.charno, er_en->dt.fpos.charinline ); } break; case 2: { } break; } if (3 > had_decoding_error) { had_decoding_error++; } } break; case DK4_E_ENCODING_FAILED: { switch (had_encoding_error) { case 0: case 1: { report_with_position( ((0 == had_encoding_error) ? 3 : 4), 12, er_en->dt.fpos.byteno, er_en->dt.fpos.lineno, er_en->dt.fpos.charno, er_en->dt.fpos.charinline ); } break; case 2: { } break; } if (3 > had_encoding_error) { had_encoding_error++; } } break; } } if (NULL != er_pr) { if (DK4_E_NONE != er_pr->ec) { switch (had_processing_error) { case 0: case 1: { report_with_position( ((0 == had_processing_error) ? 6 : 7), 13, er_en->dt.fpos.byteno, er_en->dt.fpos.lineno, er_en->dt.fpos.charno, er_en->dt.fpos.charinline ); } break; case 2: { } break; } if (3 > had_processing_error) { had_processing_error++; } } } } /** Process one input file. @param fipo File to process. */ static void process_one_file(FILE *fipo) { dk4_tsp32_t tsp32; dk4_tspdk_t tspdk; dk4_er_t er; dk4_er_t er_en; dk4_er_t er_pr; #if VERSION_1 size_t sz; #endif int res; int cc; int c; unsigned char ub; #line 1696 "dk-cat.ctr" cc = 1; initialize_for_one_file(); dk4error_init(&er); if (0 != use_stream) { #line 1700 "dk-cat.ctr" res = dk4tsp32_setup_char( &tsp32, NULL, c32_handler, ienc_def, &er ); if (0 != res) { #line 1704 "dk-cat.ctr" do { if (0 != sig_can_continue(0)) { c = fgetc(fipo); if (EOF != c) { ub = (unsigned char)c; switch (dk4tsp32_add_one_byte(&tsp32, ub)) { case DK4_TSP_RES_ERROR: { exval = EXIT_FAILURE; dk4tsp32_get_errors(&er_en, &er_pr, &tsp32); 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); report_errors(&er_en, &er_pr); } break; default: { } break; } } else { cc = 0; } if (0 != feof(fipo)) { if (1 == cc) { cc = 0; } } } else { cc = -1; } } while (1 == cc); if (0 == cc) { #line 1733 "dk-cat.ctr" res = dk4tsp32_finish(&tsp32); switch (res) { case DK4_TSP_RES_ERROR: { #line 1736 "dk-cat.ctr" exval = EXIT_FAILURE; dk4tsp32_get_errors(&er_en, &er_pr, &tsp32); report_errors(&er_en, &er_pr); } break; case DK4_TSP_RES_FATAL: { #line 1741 "dk-cat.ctr" exval = EXIT_FAILURE; dk4tsp32_get_errors(&er_en, &er_pr, &tsp32); report_errors(&er_en, &er_pr); } break; } } if (0 != sig_can_continue(0)) { if ((0 != there_was_text) && (0 == previous_was_nl)) { res = c32_real_output(NULL, dkC32(0x0A), NULL, NULL); switch (res) { case DK4_TSP_RES_ERROR: { #line 1752 "dk-cat.ctr" exval = EXIT_FAILURE; } break; case DK4_TSP_RES_FATAL: { #line 1755 "dk-cat.ctr" exval = EXIT_FAILURE; } break; } } } } else { #line 1761 "dk-cat.ctr" /* BUG, Should not happen */ exval = EXIT_FAILURE; } } else { #line 1765 "dk-cat.ctr" res = dk4tspdk_setup_char( &tspdk, NULL, dkc_handler, oenc_sys, ienc_def, &er ); if (0 != res) { if (0 != dk4app_opt_is_set_short(app, dkT('p'), NULL)) { #line 1771 "dk-cat.ctr" dk4tspdk_enable_utf8_pass_through(&tspdk, 1); } do { c = fgetc(fipo); if (EOF != c) { ub = (unsigned char)c; switch (dk4tspdk_add_one_byte(&tspdk, ub)) { case DK4_TSP_RES_FATAL: { cc = -1; exval = EXIT_FAILURE; dk4tspdk_get_errors(&er_en, &er_pr, &tspdk); report_errors(&er_en, &er_pr); } break; case DK4_TSP_RES_ERROR: { exval = EXIT_FAILURE; dk4tspdk_get_errors(&er_en, &er_pr, &tspdk); report_errors(&er_en, &er_pr); } break; default: { } break; } } else { cc = 0; } if (0 != feof(fipo)) { if (1 == cc) { cc = 0; } } } while (1 == cc); if (0 == cc) { res = dk4tspdk_finish(&tspdk); switch (res) { case DK4_TSP_RES_ERROR: { exval = EXIT_FAILURE; dk4tspdk_get_errors(&er_en, &er_pr, &tspdk); report_errors(&er_en, &er_pr); } break; case DK4_TSP_RES_FATAL: { exval = EXIT_FAILURE; dk4tspdk_get_errors(&er_en, &er_pr, &tspdk); report_errors(&er_en, &er_pr); } break; } } if ((0 != there_was_text) && (0 == previous_was_nl)) { res = dkc_real_output(NULL, dkT('\n'), NULL, NULL); switch (res) { case DK4_TSP_RES_ERROR: { exval = EXIT_FAILURE; } break; case DK4_TSP_RES_FATAL: { exval = EXIT_FAILURE; } break; } } } } #line 1826 "dk-cat.ctr" } /** Process one input file specified by name. @param filename Name of input file to process. */ static void process_one_file_name(const dkChar *filename) { dk4_er_t er; FILE *fipo = NULL; const dkChar *oldsourcefile; dk4_um_t oldsourceline; int tests = DK4_FOPEN_SC_USER; #line 1843 "dk-cat.ctr" dk4error_init(&er); oldsourcefile = dk4app_get_log_source_file(app); oldsourceline = dk4app_get_log_source_line(app); dk4app_set_log_source_file(app, filename); dk4app_set_log_source_line(app, (dk4_um_t)0UL); #if 0 /* File is opened for reading only. */ if (1 == dk4isadmin()) { tests = DK4_FOPEN_SC_PRIVILEGED; } #endif if (0 != sig_can_continue(1)) { fipo = dk4fopen_app(filename, dkT("rb"), tests, app); if (NULL != fipo) { input_file_name = filename; process_one_file(fipo); fclose(fipo); } else { /* ERROR: Failed to open file (already reported) */ exval = EXIT_FAILURE; } } dk4app_set_log_source_file(app, oldsourcefile); dk4app_set_log_source_line(app, oldsourceline); #line 1867 "dk-cat.ctr" } #if DK4_ON_WINDOWS static void expand_and_process(const dkChar *pattern) { dkChar buf[DK4_MAX_PATH]; dk4_dir_t *fne; const dkChar *shf; /* Short file name */ const dkChar *pth; /* Path */ int any_file_found = 0; /* Flag: Any file found */ int can_continue; fne = dk4app_fne_open(pattern, app); if (NULL != fne) { can_continue = 1; while ((0 != can_continue) && (NULL != (shf = dk4dir_next_file(fne)))) { any_file_found = 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_cat_kwnl[5],NULL)) { if(0 != dk4str_cat_s(buf, DK4_SIZEOF(buf,dkChar), shf, NULL)) { process_one_file_name(buf); } else { exval = EXIT_FAILURE; /* ERROR: Path too long */ dk4app_log_base3(app, DK4_LL_ERROR, 100, 105, pattern); } } else { exval = EXIT_FAILURE; /* ERROR: Path too long */ dk4app_log_base3(app, DK4_LL_ERROR, 100, 105, pattern); } } else { exval = EXIT_FAILURE; /* ERROR: Path too long! */ dk4app_log_base3(app, DK4_LL_ERROR, 100, 105, pattern); } } else { process_one_file_name(shf); } can_continue = sig_can_continue(1); } dk4dir_close(fne); if (0 == any_file_found) { /* ERROR: No such file */ dk4app_log_base3(app, DK4_LL_ERROR, 100, 107, pattern); exval = EXIT_FAILURE; } } else { /* ERROR: Failed to open file name expander (already reported) */ exval = EXIT_FAILURE; } } #endif /** Process all input files specified on command line or standard input if no file name is found. */ static void process_files(void) { int argc; int i; const dkChar *fn; #if DK4_ON_WINDOWS int oldmode; #endif #line 1948 "dk-cat.ctr" argc = dk4app_get_argc(app); if (0 < argc) { #line 1950 "dk-cat.ctr" for (i = 0; ((i < argc) && (0 != sig_can_continue(1))); i++) { fn = dk4app_get_argv(app, i); if (NULL != fn) { #if DK4_ON_WINDOWS if (0 != dk4path_must_expand(fn)) { expand_and_process(fn); } else { #endif process_one_file_name(fn); #if DK4_ON_WINDOWS } #endif } } } else { #line 1965 "dk-cat.ctr" #if DK4_ON_WINDOWS #line 1967 "dk-cat.ctr" oldmode = _setmode(_fileno(stdin), _O_BINARY); #endif input_file_name = dk_cat_kwnl[4]; process_one_file(stdin); #if DK4_ON_WINDOWS #line 1973 "dk-cat.ctr" _setmode(_fileno(stdin), oldmode); #endif } #line 1977 "dk-cat.ctr" } static void run_the_functions(void) { process_files(); fflush(stdout); cleanup_output(); } #if DK4_HAVE_SIGACTION /** Set signal handlers and run. */ static void run_with_signals(void) { #ifdef SIGPIPE struct sigaction opipe; #endif struct sigaction oint; struct sigaction oterm; #ifdef SIGPIPE struct sigaction npipe; #endif struct sigaction nint; 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, msg, sz_msg, DK4_LL_ERROR, 22); goto finished; } if (0 != sigaddset(&npipe.sa_mask, SIGPIPE)) { /* ERROR: Failed to set up masked signal set for SIGPIPE */ dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 22); goto finished; } if (0 != sigaction(SIGPIPE, &npipe, &opipe)) { /* ERROR: Failed to set up signal handler for SIGPIPE */ dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 22); 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, msg, sz_msg, DK4_LL_ERROR, 22); 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, msg, sz_msg, DK4_LL_ERROR, 22); goto restore_old_pipe; } if (0 != sigaction(SIGINT, &nint, &oint)) { /* ERROR: Failed to set up signal handler for SIGINT */ dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 22); 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, msg, sz_msg, DK4_LL_ERROR, 22); 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, msg, sz_msg, DK4_LL_ERROR, 22); goto restore_old_int; } if (0 != sigaction(SIGTERM, &nterm, &oterm)) { /* ERROR: Failed to set up signal handler for SIGTERM */ dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 22); goto restore_old_int; } success = 1; run_the_functions(); /* Restore signal handling for SIGTERM. */ if (0 != sigaction(SIGTERM, &oterm, NULL)) { /* ERROR: Failed to restore old SIGTERM settings */ dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 23); 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, msg, sz_msg, DK4_LL_ERROR, 23); 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, msg, sz_msg, DK4_LL_ERROR, 23); 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 run_with_signals(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); run_the_functions(); sigset(SIGTERM, oldterm); sigset(SIGINT, oldint); #ifdef SIGPIPE sigset(SIGPIPE, oldpipe); #endif } #else #if DK4_HAVE_SIGNAL /** Set signal handlers and run. */ static void run_with_signals(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); run_the_functions(); signal(SIGTERM, oldterm); signal(SIGINT, oldint); #ifdef SIGPIPE signal(SIGPIPE, oldpipe); #endif } #else /** Set signal handlers and run. */ static void run_with_signals(void) { run_the_functions(); } #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 { dk4_sig_atomic_t shp; #line 2191 "dk-cat.ctr" #line 2192 "dk-cat.ctr" app = dk4app_open_cmd( argc, argv, dk_cat_options, dk_cat_sz_options, dk_cat_kwnl[0], DKT_VERSION_DK, dk_cat_kwnl[1], dk_cat_help_text, dk_cat_license_text ); if (NULL != app) { sz_msg = dk4app_string_table_size(dk_cat_kw_def); msg = dk4app_string_table(app, dk_cat_kwnl[2], dk_cat_kw_def); if (0 != dk4app_can_run_normally(app)) { if (0 != initialize_from_app()) { decide_for_output_type(); exval = EXIT_SUCCESS; run_with_signals(); #ifdef SIGPIPE shp = sig_read_atomic(&sig_had_pipe); #else shp = 0; #endif if (0 != shp) { if (0 != verbose) { dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 24); } exval = EXIT_FAILURE; } else { if (0 != had_write_error) { dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 20); exval = EXIT_FAILURE; } } if (0 != sig_read_atomic(&sig_had_int)) { dk4app_log_1(app, msg, sz_msg, DK4_LL_ERROR, 25); } } } else { if (0 != dk4app_help_version_license(app)) { exval = EXIT_SUCCESS; } } dk4app_close(app); } #line 2233 "dk-cat.ctr" #line 2234 "dk-cat.ctr" exit(exval); return exval; }