diff options
author | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-09-02 13:46:59 +0900 |
commit | e0c6872cf40896c7be36b11dcc744620f10adf1d (patch) | |
tree | 60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dk-cat.c |
Initial commit
Diffstat (limited to 'support/dktools/dk-cat.c')
-rw-r--r-- | support/dktools/dk-cat.c | 2433 |
1 files changed, 2433 insertions, 0 deletions
diff --git a/support/dktools/dk-cat.c b/support/dktools/dk-cat.c new file mode 100644 index 0000000000..63b35118ff --- /dev/null +++ b/support/dktools/dk-cat.c @@ -0,0 +1,2433 @@ +/* + 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 <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_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_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 + +#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 [<options>] [<files>]"), +dkT(""), +dkT("Options:"), +dkT("-c <bool> Enable CR/NL -n Write line numbers"), +dkT("-i <encoding> Expected input encoding -w Normalize text lines"), +dkT("-o <encoding> 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=<int> 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; +} + |