%% options copyright owner = Dirk Krause copyright year = 2011-2014 license = bsd %% state machine # This state machine is used when splitting SQL lines. [options] name = dkdbt_sql_split write header = no [states] ST_N # Normal text. ST_N_BS # Normal text, backslash found. ST_CB # Normal text, closing bracket found. ST_CB_CO # Normal text, bracket and comma found. ST_SL # Normal text, slash found. ST_MINUS # Normal text, one minus found. ST_CO # Comment. ST_CO_AST # Comment, asterisk found. ST_LCO # Line comment. ST_Q # Single quote text. ST_Q_BS # Single quote text, backslash found. ST_DQ # Double quote text. ST_DQ_BS # Double quote text, backslash found. ST_BT # Backtick text. ST_BT_BS # Backtick text, backslash found. ST_ERROR # Any error occured. [inputs] I_ANY # Any text. I_BS # Backslash. I_SL # Slash. I_AST # Asterisk. I_Q # Single quote. I_DQ # Double quote. I_BT # Backtick. I_CL # Closing bracket. I_COMMA # Comma. I_MINUS # Minus sign. I_NL # Newline. [outputs] O_NORMAL # Normal output. O_NL # Append newline to current output. [rules] * * ST_ERROR O_NORMAL ST_N * ST_N O_NORMAL ST_N I_BS ST_N_BS O_NORMAL ST_N I_CL ST_CB O_NORMAL ST_N I_SL ST_SL O_NORMAL ST_N I_MINUS ST_MINUS O_NORMAL ST_N I_Q ST_Q O_NORMAL ST_N I_DQ ST_DQ O_NORMAL ST_N I_BT ST_BT O_NORMAL # If we have found a closing bracket we wait for # a comma. ST_CB * ST_N O_NORMAL ST_CB I_CL ST_CB O_NORMAL ST_CB I_COMMA ST_CB_CO O_NORMAL # After closing bracket and comma we want to have a newline. ST_CB_CO * ST_N O_NL ST_CB_CO I_NL ST_N O_NORMAL ST_CB_CO I_CL ST_CB O_NL # After a backslash we go back to normal work. ST_N_BS * ST_N O_NORMAL # A slash may be the start of a comment. ST_SL * ST_N O_NORMAL ST_SL I_SL ST_SL O_NORMAL ST_SL I_AST ST_CO O_NORMAL # A comment is continued until the end marker. ST_CO * ST_CO O_NORMAL ST_CO I_AST ST_CO_AST O_NORMAL # Once we have found an asterisk in a comment it might # be the start of the comment end marker. ST_CO_AST * ST_CO O_NORMAL ST_CO_AST I_AST ST_CO_AST O_NORMAL ST_CO_AST I_SL ST_N O_NORMAL # When a minus is found in normal state a second minus # will start a line comment. ST_MINUS * ST_N O_NORMAL ST_MINUS I_MINUS ST_LCO O_NORMAL # A line comment is finished at line end. ST_LCO * ST_LCO O_NORMAL ST_LCO I_NL ST_N O_NORMAL # A single quote text can be finished by another # single quote only. ST_Q * ST_Q O_NORMAL ST_Q I_BS ST_Q_BS O_NORMAL ST_Q I_Q ST_N O_NORMAL # A backslash in a single quote text escapes one character. ST_Q_BS * ST_Q O_NORMAL # A double quote text can be finished by another # double quote only. ST_DQ * ST_DQ O_NORMAL ST_DQ I_DQ ST_N O_NORMAL ST_DQ I_BS ST_DQ_BS O_NORMAL # A backslash in a double quote text escapes one character. ST_DQ_BS * ST_DQ O_NORMAL # A backtick text can be finished by another backtick only. ST_BT * ST_BT O_NORMAL ST_BT I_BT ST_N O_NORMAL ST_BT I_BS ST_BT_BS O_NORMAL # A backslash in a backtick text escapes one character. ST_BT_BS * ST_BT O_NORMAL %% module #include "dk3all.h" #include "dkt-version.h" $!trace-include #ifdef DK3_USE_DB #undef DK3_USE_DB #endif #ifdef DK3_USE_NDBM #undef DK3_USE_NDBM #endif #if DK3_HAVE_DB_H #include /** Use Berkeley DB. */ #define DK3_USE_DB 1 #endif #if DK3_HAVE_NDBM_H #if !DK3_HAVE_GDBM_H #include /** Use NDBM. */ #define DK3_USE_NDBM 1 #endif #endif /** Job structure. */ typedef struct { dk3_app_t *app; /**< Application structure. */ dkChar const * const *msg; /**< Localized messages. */ dk3_option_set_t *opt; /**< Options. */ dkChar const * const *xargv; /**< Command line arguments array. */ dk3_dbi_t *in; /**< Input database. */ dk3_dbi_t *out; /**< Output database. */ dk3_stream_t *os; /**< Output stream. */ size_t ls; /**< Line size. */ int xargc; /**< Number of command line arguments. */ int f_add; /**< Flag: Add to existing database. */ int enc_s; /**< Encoding for stdin. */ int enc_f; /**< Encoding for files. */ int ie; /**< Default system encoding. */ int oe; /**< Output encoding. */ char comm; /**< Character to start comment line. */ } DKDBT_JOB; /** Application group name. */ static dkChar const dkt_group_name[] = { dkT("dkt-3") }; /** File name for string table file. */ static dkChar const dkdbt_stt_file_name[] = { dkT("dkdbtool.str") }; /** File name for help file. */ static dkChar const dkdbt_help_file_name[] = { dkT("dkdbtool.txt") }; /** Version number string. */ static dkChar const dkdbt_version[] = { dkT("dkdbt ") DKT_VERSION }; /** Options for the copy operation. */ static dk3_option_t const dkdbt_copy_options[] = { { dkT('a'), dkT("append"), 0 } }; /** Number of elements in dkdbt_copy_options. */ static size_t const dkdbt_sz_copy_options = sizeof(dkdbt_copy_options)/sizeof(dk3_option_t); /** Options for the make operation. */ static dk3_option_t const dkdbt_make_options[] = { { dkT('a'), dkT("append"), 0 }, { dkT('c'), dkT("comment"), 1 }, { dkT('i'), dkT("input-encoding"), 1 }, { dkT('l'), dkT("line-size"), 1 } }; /** Number of elements in dkdbt_make_options. */ static size_t const dkdbt_sz_make_options = sizeof(dkdbt_make_options)/sizeof(dk3_option_t); /** Options for the reverse make operation. */ static dk3_option_t const dkdbt_text_options[] = { { dkT('o'), dkT("output-encoding"), 1 }, }; /** Number of elements in dkdbt_text_options. */ static size_t const dkdbt_sz_text_options = sizeof(dkdbt_text_options)/sizeof(dk3_option_t); /** Help text to show if help text file is not found. */ static dkChar const * const dkdbt_help_text[] = { $!text file=dkdbtool.txt,macro=dkT dkdbt - Dirk Krause's database tool =================================== Usage ----- dkdbt copy [-a] dkdbt make [-c ] [-a] [-i ] [] dkdbt text [-o ] [] dkdbt split-sql-lines [ []] dkdbt help dkdbt version dkdbt license-terms dkdbt features In a copy operation a new copy of the database is created, probably using another database type. By default the destination database is truncated when opening it so the destination database contains exactly the same records as the source database. The -a option switches to add mode, the records from the source database are added to the destination database. Records for existing keys are replaced, records for keys not yet existing are inserted. A make operation creates a database from text input. Each input line contains one record. The first text word in the line is the key, all remaining text beginning with the second text word is the value. The -c option can be used to specify a special character to start a comment. All lines started by the specified character are comment lines and thus ignored. The -i option can be used to specify the input encoding. The files specified on the command line after the destination database name are used as input files. If no files are specified, standard input is used. The text operation is a reverse make operation. It writes data from the database as a sequence of lines. The -o option can be used to specify the output encoding. The split-sql-lines operation can be used to split overlong lines in mysqldump output. The help operation shows this help text. The version operation shows the version number. The license-terms operation shows the license terms. The features operation lists the database types supported by the program. $!end }; /** Default message texts, used if no string table file is found. */ static dkChar const * const dkdbt_message_texts[] = { $!string-table file=dkdbtool.str,macro=dkT # # 0 # The following database types are supported: # # 1 # mem In-memory database from the dktools project. # # 2 # bdb Berkeley DB: An embedded database programmatic toolkit. # # 3 # NDBM The NDBM database. # # 4: Error message: Missing dkdbt command! # Missing dkdbt command!\nType "dkdbt help" for a list of commands. # # 5/6: Error message: Unknown command "..."! # Unknown command: " "!\nType "dkdbt help" for a list of commands. # # 7/8: Error message: Failed to expand file name pattern "..."! # Failed to expand file name pattern " "! # # 9: Error message: No input files found! # No input files found! # # 10: Error message: Wrong file type! # Wrong file type! # # 11: Error message: Error in SQL input! # Error in SQL input! # # 12: Error message: Error while traversing data! # Error while traversing data! # # 13: Error message: Key data is no text! # Key data is not text! # # 14: Error message: Value data is no text! # Value data is not text! # # 15: Error message: Failed to print key! # Failed to print key! # # 16: Error message: Failed to print space! # Failed to print space! # # 17: Error message: Failed to print value! # Failed to print value! # # 18: Error message: Failed to print newline! # Failed to print newline! # # 19: Error message: Missing destination database name! # Missing destination database name! # # 20: Error message: Errors occured while processing input! # Error(s) occured while processing input! # # 21: Error message: Input and output database file name required! # Input and output database file name required! # # 22: Error message: Missing input file name! # Missing input file name! # # 23: Error message: Missing output file name! # Missing output file name! # # 24: Error message: Error(s) occured while copying data! # Error(s) occured while copying data! $!end }; /** Commands for dkdbt. */ static dkChar const * const dkdbt_commands[] = { $!string-table macro=dkT # # 0, 1: Help # h$elp --help # # 2, 3: Version # v$ersion --version # # 4, 5: License # l$icense --license # # 6, 7: Features # f$eatures --features # # 8: Copy # c$opy # # 9: Make # m$ake # # 10: Reverse make (reconstruct text) # t$ext # # 11/12: Split lines in mysqldump output # s$plit-sql-lines split-sql # # 13/14: License terms # --license-terms -L $!end }; /** Licensing overview, list of all sources. */ static dkChar const * const dkdbt_overview_license[] = { dkT("This software uses code from the following projects either directly"), dkT("or as a library:"), dkT(""), dkT("dktools\t\tDirk Krause's tools and libraries."), dkT("\t\tSee http://dktools.sourceforge.net for more information."), #if DK3_USE_DB dkT(""), dkT("Berkeley DB\tBerkeley DB: An embedded database programmatic toolkit."), dkT("\t\tSee http://www.oracle.com for more information."), #endif #if DK3_USE_NDBM dkT(""), dkT("NDBM\t\tA library implementing the NDBM API."), dkT("\t\tLicense conditions depend on the NDBM library you use."), #endif dkT(""), NULL }; /** License terms for the dktools project itself. */ static dkChar const * const dkt_license[] = { $!text macro=dkT License for the dktools project =============================== Copyright (c) 2011-2013, Dirk Krause All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the copyright holder(s) 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. $!end }; #if DK3_USE_DB /** License conditions for the Berkeley DB. */ static dkChar const * const dkbtt_bdb_license[] = { $!text macro=dkT License for the Berkeley DB =========================== The license that applies to your copy of the Berkeley DB software may be found in the "LICENSE" file included in each Berkeley DB distribution. For a license to use the Berkeley DB software under conditions other than those described in the "LICENSE" file, or to purchase support for the Berkeley DB software, please send email to berkeleydb-info_us@oracle.com . Copyright (c) 1996,2009 Oracle. All rights reserved. /*- * $Id: LICENSE,v 12.9 2008/02/07 17:12:17 mark Exp $ */ The following is the license that applies to this copy of the Berkeley DB software. For a license to use the Berkeley DB software under conditions other than those described here, or to purchase support for this software, please contact Oracle at berkeleydb-info_us@oracle.com. =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= /* * Copyright (c) 1990,2008 Oracle. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Redistributions in any form must be accompanied by information on * how to obtain complete source code for the DB software and any * accompanying software that uses the DB software. The source code * must either be included in the distribution or be available for no * more than the cost of distribution plus a nominal fee, and must be * freely redistributable under reasonable conditions. For an * executable file, complete source code means the source code for all * modules it contains. It does not include source code for modules or * files that typically accompany the major components of the operating * system on which the executable file runs. * * THIS SOFTWARE IS PROVIDED BY ORACLE ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR * NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL ORACLE 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. */ /* * Copyright (c) 1990, 1993, 1994, 1995 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. */ /* * Copyright (c) 1995, 1996 * The President and Fellows of Harvard University. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY HARVARD AND ITS 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 HARVARD OR ITS 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. */ =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= /*** * ASM: a very small and fast Java bytecode manipulation framework * Copyright (c) 2000-2005 INRIA, France Telecom * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of its * 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. */ $!end }; #endif #if DK3_USE_NDBM /** License notice for NDBM libraries. */ static dkChar const * const dkdbt_ndbm_license[] = { $!text macro=dkT License for the NDBM software ============================= NDBM is an API implemented by different libraries from different vendors. The most common implementations are - NDBM software contained in the system distribution of commercial UNIX operating systems, and - the NDBM compatibility library of the GDBM software. Your use of the dktools software together with NDBM libraries must be in compliance to the license conditions of the NDBM library used. $!end }; #endif /** Keywords used by this module. */ static dkChar const * const dkdbt_kw[] = { /* 0 */ dkT("w"), /* 1 */ dkT(" "), /* 2 */ dkT("\n"), /* 3 */ dkT("DB: mem"), /* 4 */ dkT(" bdb"), /* 5 */ dkT(" ndbm"), }; /** Exit code. */ static int exval = 1; /** Initialize job structure. @param j Job structure to initialize. @param app Application structure. @param msg Localized message texts. @param xargc Number of command line arguments. @param xargv Command line arguments array. */ static void dkdbt_job_init( DKDBT_JOB *j, dk3_app_t *app, dkChar const * const *msg, int xargc, dkChar const * const *xargv ) { j->app = app; j->msg = msg; j->opt = NULL; j->xargc = xargc; j->xargv = xargv; j->ls = 1024; j->f_add = 0; j->enc_s = dk3app_get_input_stdin_encoding(j->app); j->enc_f = dk3app_get_input_file_encoding(j->app); j->comm = '\0'; j->in = NULL; j->out = NULL; } /** Clean up job structure. @param j Job structure to clean up. */ static void dkdbt_job_end(DKDBT_JOB *j) { if(j->opt) { dk3opt_close(j->opt); } j->opt = NULL; } /** Show help text, either from file or default text. @param app Application structure. */ static void dkdbt_show_help(dk3_app_t *app) { dk3app_help(app, dkdbt_help_file_name, dkdbt_help_text); } /** Show license terms. @param app Application structure. */ static void dkdbt_show_license(dk3_app_t *app) { dkChar const * const *sptr; dk3sf_initialize_stdout(); sptr = dkdbt_overview_license; while(*sptr) { dk3sf_fputs(*(sptr++), stdout); dk3sf_fputc(dkT('\n'), stdout); } sptr = dkt_license; while(*sptr) { dk3sf_fputs(*(sptr++), stdout); dk3sf_fputc(dkT('\n'), stdout); } #if DK3_USE_DB sptr = dkbtt_bdb_license; while(*sptr) { dk3sf_fputs(*(sptr++), stdout); dk3sf_fputc(dkT('\n'), stdout); } #endif #if DK3_USE_NDBM sptr = dkdbt_ndbm_license; while(*sptr) { dk3sf_fputs(*(sptr++), stdout); dk3sf_fputc(dkT('\n'), stdout); } #endif } /** Show features. @param app Application structure. @param msg Localized message texts. */ static void dkdbt_show_features(dk3_app_t *app, dkChar const * const *msg) { dk3sf_initialize_stdout(); dk3sf_fputs(msg[0], stdout); dk3sf_fputc(dkT('\n'), stdout); dk3sf_fputs(msg[1], stdout); dk3sf_fputc(dkT('\n'), stdout); #if DK3_USE_DB dk3sf_fputs(msg[2], stdout); dk3sf_fputc(dkT('\n'), stdout); #endif #if DK3_USE_NDBM dk3sf_fputs(msg[3], stdout); dk3sf_fputc(dkT('\n'), stdout); #endif } /** Show version number. @param app Application structure. */ static void dkdbt_show_version(dk3_app_t *app) { dk3sf_initialize_stdout(); dk3sf_fputs(dkdbt_version, stdout); dk3sf_fputc(dkT('\n'), stdout); dk3sf_fputs(dkdbt_kw[3], stdout); if(dk3dbi_type_supported(DK3_DB_TYPE_BDB)) { dk3sf_fputs(dkdbt_kw[4], stdout); } if(dk3dbi_type_supported(DK3_DB_TYPE_NDBM)) { dk3sf_fputs(dkdbt_kw[5], stdout); } dk3sf_fputs(dkdbt_kw[2], stdout); } /** Traversal function to copy all records to new database. @param obj Job structure. @param key Record key. @param val Record value. @return 1 on success, 0 on error (can continue), -1 on error (abort). */ static int dkdbt_copy_data(void *obj, dk3_datum_t *key, dk3_datum_t *val) { DKDBT_JOB *j; /* Copy job. */ int back; j = (DKDBT_JOB *)obj; back = dk3dbi_set(j->out, key, val); return back; } /** Copy function. @param app Application structure. @param msg Localized message texts. @param xargc Number of command line arguments. @param xargv Command line arguments array. */ static void dkdbt_copy( dk3_app_t *app, dkChar const * const *msg, int xargc, dkChar const * const *xargv ) { DKDBT_JOB dkdbtj; /* Copy job. */ dkChar const *inname; /* Input database name. */ dkChar const *outname; /* Output database name. */ int ec; /* Error code. */ int res; /* Operation result. */ dkdbt_job_init(&dkdbtj, app, msg, xargc, xargv); ec = 0; dkdbtj.opt = dk3opt_open_app( dkdbt_copy_options, dkdbt_sz_copy_options, dkT('\0'), NULL, (xargc - 1), &(xargv[1]), app ); if(dkdbtj.opt) { if(dk3opt_get_error_code(dkdbtj.opt) == 0) { if(dk3opt_is_set(dkdbtj.opt, dkT('a'))) { dkdbtj.f_add = 1; } if(dk3opt_get_num_args(dkdbtj.opt) >= 3) { inname = dk3opt_get_arg(dkdbtj.opt, 1); if(inname) { outname = dk3opt_get_arg(dkdbtj.opt, 2); if(outname) { dkdbtj.in = dk3dbi_open_app( inname, DK3_DB_TYPE_UNKNOWN, DK3_DB_ACCESS_READ, &ec, app ); if(dkdbtj.in) { if(dkdbtj.f_add) { dkdbtj.out = dk3dbi_open_app( outname, DK3_DB_TYPE_UNKNOWN, DK3_DB_ACCESS_WRITE, &ec, app ); } else { dkdbtj.out = dk3dbi_open_truncate_app( outname, DK3_DB_TYPE_UNKNOWN, DK3_DB_ACCESS_WRITE, &ec, app ); } if(dkdbtj.out) { res = dk3dbi_traverse( dkdbtj.in, (void *)(&dkdbtj), dkdbt_copy_data ); if(res) { exval = 0; } else { /* ERROR While copying */ dk3app_log_1(app, DK3_LL_ERROR, msg, 24); } dk3dbi_close(dkdbtj.out); } else { /* ERROR: Failed to open output database! */ } dk3dbi_close(dkdbtj.in); } else { /* ERROR: Failed to open input database! */ } } else { /* ERROR: Output file name missing! */ dk3app_log_1(app, DK3_LL_ERROR, msg, 23); } } else { /* ERROR: Missing input file name! */ dk3app_log_1(app, DK3_LL_ERROR, msg, 22); } if(dk3opt_get_num_args(dkdbtj.opt) > 3) { dk3app_log_i3( app, DK3_LL_WARNING, 164, 165, dk3opt_get_arg(dkdbtj.opt, 3) ); } } else { /* ERROR: File name missing! */ dk3app_log_1(app, DK3_LL_ERROR, msg, 22); } } else { /* ERROR: Error during option set creation! */ } } else { /* ERROR: Failed to create option set! */ } dkdbt_job_end(&dkdbtj); } /** Set input or output encoding from command line arguments. @param app Application structure. @param enc Variable to set. @param val Encoding name found on command line. @param de Default encoding. @return 1 on success, 0 on error. */ static int dkdbt_set_encoding( dk3_app_t *app, int *enc, dkChar const *val, int de ) { int back = 0; int i = -1; /* Index of string in array of encodings. */ if((app) && (enc)) { if(val) { i = dk3enc_get_text_encoding_app(val, app); if(i > -1) { *enc = i; back = 1; } else { *enc = de; } } else { *enc = de; back = 1; } } return back; } /** Handler function for one line. @param vj Job structure casted to void *. @param il Input line to process. @return 1=OK, 0=error, can continue, -1=error, abort processing. */ static int dkdbt_make_line_handler(void *vj, dkChar *il) { DKDBT_JOB *j; /* Make job. */ dkChar *ptr; /* Pointer to modify string. */ dkChar *p1; /* Key pointer. */ dkChar *p2; /* Value pointer. */ int back = 0; int comm = 0; /* Flag: Check lines for comments. */ $? "+ dkdbt_make_line_handler" j = (DKDBT_JOB *)vj; ptr = il; while(*ptr) { if(*ptr == dkT('\n')) *ptr = dkT('\0'); if(*ptr == dkT('\r')) *ptr = dkT('\0'); ptr++; } $? ". line=\"%s\"", il p1 = dk3str_start(il, NULL); if(p1) { if(j->comm) { if(*p1 == j->comm) { comm = 1; } } if(!(comm)) { p2 = dk3str_next(p1, NULL); if(p2) { dk3str_chomp(p2, NULL); back = dk3dbi_set_string(j->out, p1, p2); } else { dk3dbi_delete_string(j->out, p1); back = 1; } } } else { $? ". empty line" back = 1; } $? "- dkdbt_make_line_handler %d", back return back; } /** Run make operation. @param j Job structure. @param buffer Line buffer. @param szbuffer Size of @a buffer (number of characters). */ static void dkdbt_make_with_buffer(DKDBT_JOB *j, dkChar *buffer, size_t szbuffer) { dkChar bu[DK3_MAX_PATH]; /* Local file name copy. */ dk3_dir_t *fne; /* File name expander. */ dkChar const *outname; /* Output database name. */ dkChar const *fn; /* Current input file name. */ dkChar const *en; /* Entry name. */ dk3_um_t nf; /* Number of files available. */ int nargs; /* Number of command line arguments. */ int i; /* Index of current file to process. */ int ec; /* Error code. */ int res; /* Result for one file. */ $? "+ dkdbt_make_with_buffer" ec = 0; nargs = dk3opt_get_num_args(j->opt); if(nargs > 1) { $? ". nargs > 1" outname = dk3opt_get_arg(j->opt, 1); if(outname) { $? ". outname = \"%s\"", outname if(j->f_add) { $? ". add" j->out = dk3dbi_open_app( outname, DK3_DB_TYPE_UNKNOWN, DK3_DB_ACCESS_WRITE, &ec, j->app ); } else { $? ". new" j->out = dk3dbi_open_truncate_app( outname, DK3_DB_TYPE_UNKNOWN, DK3_DB_ACCESS_WRITE, &ec, j->app ); } if(j->out) { $? ". db opened" if(nargs > 2) { $? ". use files %d", nargs exval = 0; for(i = 2; i < nargs; i++) { $? ". yet another file" fn = dk3opt_get_arg(j->opt, i); if(fn) { $? ". input file \"%s\"", fn if(dk3str_len(fn) < DK3_SIZEOF(bu,dkChar)) { dk3str_cpy_not_overlapped(bu, fn); dk3str_correct_filename(bu); if(dk3sf_must_expand(bu)) { fne = dk3dir_fne_open_app(bu, j->app); if(fne) { nf = dk3dir_get_number_of_files(fne); if(nf > 0) { while(dk3dir_get_next_file(fne)) { en = dk3dir_get_fullname(fne); if(en) { res = dk3stream_process_filename_lines_app( (void *)j, dkdbt_make_line_handler, en, buffer, szbuffer, dk3app_get_encoding(j->app), j->enc_f, j->app ); if(res < 1) { exval = 1; /* ERROR: Error while processing input! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 20); } } else { /* BUG: Should not happen. */ } } } else { exval = 1; /* ERROR: No matching file name! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 215, 216, bu); } dk3dir_close(fne); } else { /* ERROR: File name expansion failed! */ exval = 1; } } else { res = dk3stream_process_filename_lines_app( (void *)j, dkdbt_make_line_handler, bu, buffer, szbuffer, dk3app_get_encoding(j->app), j->enc_f, j->app ); if(res < 1) { /* ERROR: Error while processing input! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 20); exval = 1; } } } else { /* ERROR: File name too large! */ dk3app_log_i3(j->app, DK3_LL_ERROR, 65, 66, fn); exval = 1; } } else { $? "! Missing input file name" /* BUG: Should not happen. */ exval = 1; } } } else { $? ". use standard input" res = dk3app_process_stdin_lines( j->app, (void *)j, dkdbt_make_line_handler, buffer, szbuffer, j->enc_s ); if(res) { exval = 0; } else { $? "! error while processing" /* ERROR: Error while processing input! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 20); } } dk3dbi_close(j->out); j->out = NULL; } else { $? "! failed to open db" /* ERROR: Failed to open database! */ } } else { $? "! missing destination db name" /* ERROR: Missing destination database name! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 19); } } else { $? "! missing destination db name" /* ERROR: Missing destination database name! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 19); } $? "- dkdbt_make_with_buffer" } /** Run make operation with automatic default size buffer. @param j Job structure. */ static void dkdbt_make_with_auto_buffer(DKDBT_JOB *j) { dkChar buffer[1024]; /* Buffer for input lines. */ dkdbt_make_with_buffer(j, buffer, DK3_SIZEOF(buffer,dkChar)); } /** Run make operation, allocate buffer of given size. @param j Job structure. */ static void dkdbt_make_with_allocated_buffer(DKDBT_JOB *j) { dkChar *bu; /* Buffer for input lines. */ bu = dk3_new_app(dkChar,j->ls,j->app); if(bu) { dkdbt_make_with_buffer(j, bu, j->ls); dk3_delete(bu); } else { /* ERROR: Memory! */ } } /** Make operation. @param app Application structure. @param msg Localized message texts. @param xargc Number of command line arguments. @param xargv Command line arguments array. */ static void dkdbt_make( dk3_app_t *app, dkChar const * const *msg, int xargc, dkChar const * const *xargv ) { DKDBT_JOB dkdbtj; /* Make job. */ dkChar const *arg; /* Option argument. */ #if VERSION_BEFORE_20140809 unsigned long ul; /* Line size as unsigned long. */ #endif size_t ls; /* Line size as size_t. */ int ok; /* Flag: No errors found. */ int res; /* Operation result. */ $? "+ dkdbt_make" ok = 1; dkdbt_job_init(&dkdbtj, app, msg, xargc, xargv); dkdbtj.opt = dk3opt_open_app( dkdbt_make_options, dkdbt_sz_make_options, dkT('\0'), NULL, (xargc - 1), &(xargv[1]), app ); if(dkdbtj.opt) { if(dk3opt_get_error_code(dkdbtj.opt) == 0) { if(dk3opt_is_set(dkdbtj.opt, dkT('a'))) { dkdbtj.f_add = 1; } if(dk3opt_is_set(dkdbtj.opt, dkT('c'))) { arg = dk3opt_get_short_arg(dkdbtj.opt, dkT('c')); if(arg) { dkdbtj.comm = (char)(*arg); } else { ok = 0; /* ERROR: Missing argument for -c! */ } } if(dk3opt_is_set(dkdbtj.opt, dkT('i'))) { arg = dk3opt_get_short_arg(dkdbtj.opt, dkT('i')); if(arg) { res = dkdbt_set_encoding( app, &(dkdbtj.enc_s), arg, dk3app_get_input_stdin_encoding(dkdbtj.app) ); if(res) { dkdbtj.enc_f = dkdbtj.enc_s; } else { ok = 0; } } else { ok = 0; /* ERROR: Missing argument for -i! */ } } if(dk3opt_is_set(dkdbtj.opt, dkT('l'))) { arg = dk3opt_get_short_arg(dkdbtj.opt, dkT('l')); if(arg) { #if VERSION_BEFORE_20140809 if(dk3sf_sscanf3(arg, dkT("%lu"), &ul) == 1) { ls = (size_t)ul; if((unsigned long)ls == ul) { dkdbtj.ls = ls; } else { ok = 0; /* ERROR: Too large! */ dk3app_log_i3(app, DK3_LL_ERROR, 135, 136, arg); } } else { ok = 0; /* ERROR: Not a number! */ dk3app_log_i3(app, DK3_LL_ERROR, 141, 142, arg); } #else dk3_um_t um = DK3_UM_0; #if VERSION_BEFORE_20140716 if (dk3ma_c8_string_to_um(&um, arg)) #else if (0 != dk3ma_um_from_c8_string(&um, arg, NULL)) #endif { if (DK3_UM_0 != um) { ls = dk3ma_um_to_sz(um, 0); if (0 != ls) { dkdbtj.ls = ls; } else { ok = 0; dk3app_log_i3(app, DK3_LL_ERROR, 135, 136, arg); } } else { /* Must not be 0 */ ok = 0; dk3app_log_i3(app, DK3_LL_ERROR, 135, 136, arg); } } else { ok = 0; dk3app_log_i3(app, DK3_LL_ERROR, 141, 142, arg); } #endif } else { ok = 0; /* ERROR: Missing argument for -l! */ } } if(ok) { if(dkdbtj.ls <= 1024) { dkdbt_make_with_auto_buffer(&dkdbtj); } else { dkdbt_make_with_allocated_buffer(&dkdbtj); } } } else { /* ERROR: Error while creating options set! */ } } else { /* ERROR: Failed to create options set! */ } dkdbt_job_end(&dkdbtj); $? "- dkdbt_make" } /** Check whether or not a datum contains printable text. @param dt Data buffer. @param sz Data buffer size in bytes. @return 1 on success (can print), 0 on error. */ static int dkdbt_can_print_text(void *dt, size_t sz) { int back = 0; size_t lgt; /* Data length. */ dkChar *tptr; /* Data buffer start address as dkChar pointer. */ if(dt) { if(sz) { if((sz % sizeof(dkChar)) == 0) { lgt = sz / sizeof(dkChar); if(lgt > 0) { tptr = (dkChar *)dt; if(tptr[lgt - 1] == dkT('\0')) { back = 1; } } } } } return back; } /** Traversal function to show data as text. @param obj Job structure. @param key Record key. @param val Record value. @return 1 on success, 0 on error (can continue), -1 on error (abort). */ static int dkdbt_show_data(void *obj, dk3_datum_t *key, dk3_datum_t *val) { DKDBT_JOB *j; /* Text job. */ int back = 0; $? "+ dkdbt_show_data" j = (DKDBT_JOB *)obj; if(dkdbt_can_print_text(key->dt, key->sz)) { if(dkdbt_can_print_text(val->dt, val->sz)) { if(dk3stream_strputs(j->os, (dkChar const *)(key->dt), j->ie)) { if(dk3stream_strputs(j->os, dkdbt_kw[1], j->ie)) { if(dk3stream_strputs(j->os, (dkChar const *)(val->dt), j->ie)) { if(dk3stream_strputs(j->os, dkdbt_kw[2], j->ie)) { back = 1; } else { $? "! failed to print newline" /* ERROR: Failed to print newline! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 18); } } else { $? "! failed to print value" /* ERROR: Failed to print value! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 17); } } else { $? "! failed to print space" /* ERROR: Failed to print space! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 16); } } else { $? "! failed to print key" /* ERROR: Failed to print key! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 15); } } else { $? "! illegal value data" /* ERROR: Illegal value data! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 14); } } else { $? "! illegal key data" /* ERROR: Illegal key data! */ dk3app_log_1(j->app, DK3_LL_ERROR, j->msg, 13); } $? "- dkdbt_show_data %d", back return back; } /** Reverse make operation (show database as text). @param job Job structure. @param fipo Output file, opened for text writing. @param isfile Flag: Writing to a file, not a terminal. */ static void dkdbt_make_reverse_file(DKDBT_JOB *job, FILE *fipo, int isfile) { int res; /* Operation result. */ job->os = dk3stream_open_file_app(fipo, DK3_STREAM_FLAG_WRITE, job->app); if(job->os) { job->oe = ((isfile) ? (job->enc_f) : (job->enc_s)); job->ie = dk3app_get_encoding(job->app); dk3stream_set_output_encoding(job->os, job->oe); if(job->oe != DK3_FILE_ENCODING_ASCII) { if(job->oe != DK3_FILE_ENCODING_UTF8) { dk3stream_write_byte_order_marker(job->os); } } res = dk3dbi_traverse(job->in, (void *)job, dkdbt_show_data); if(res) { $? ". res ok" exval = 0; } else { $? "! res" /* ERROR: Error while showing data! */ dk3app_log_1(job->app, DK3_LL_ERROR, job->msg, 12); } dk3stream_close(job->os); } else { /* ERROR: Failed to open stream */ } } /** Reverse make operation (show database as text). @param app Application structure. @param msg Localized message texts. @param xargc Number of command line arguments. @param xargv Command line arguments array. */ static void dkdbt_make_reverse( dk3_app_t *app, dkChar const * const *msg, int xargc, dkChar const * const *xargv ) { DKDBT_JOB dkdbtj; /* Text job. */ FILE *fipo; /* Output file. */ dkChar const *arg; /* Option argument. */ dkChar const *inname; /* Input database name. */ dkChar const *outname; /* Output file name. */ int ok; /* Flag: No errors found. */ int res; /* Operation result. */ int ec; /* Error code. */ dkdbt_job_init(&dkdbtj, app, msg, xargc, xargv); ok = 1; ec = 0; dkdbtj.opt = dk3opt_open_app( dkdbt_text_options, dkdbt_sz_text_options, dkT('\0'), NULL, (xargc - 1), &(xargv[1]), app ); if(dkdbtj.opt) { if(dk3opt_get_error_code(dkdbtj.opt) == 0) { if(dk3opt_is_set(dkdbtj.opt, dkT('o'))) { arg = dk3opt_get_short_arg(dkdbtj.opt, dkT('o')); if(arg) { res = dkdbt_set_encoding( app, &(dkdbtj.enc_s), arg, dk3app_get_input_stdin_encoding(dkdbtj.app) ); if(res) { dkdbtj.enc_f = dkdbtj.enc_s; } else { ok = 0; } } else { ok = 0; /* ERROR: Missing argument for -o! */ } } if(ok) { switch(dk3opt_get_num_args(dkdbtj.opt)) { case 2: case 3: { inname = dk3opt_get_arg(dkdbtj.opt, 1); if(inname) { dkdbtj.in = dk3dbi_open_app( inname, DK3_DB_TYPE_UNKNOWN, DK3_DB_ACCESS_READ, &ec, app ); if(dkdbtj.in) { if(dk3opt_get_num_args(dkdbtj.opt) >= 3) { outname = dk3opt_get_arg(dkdbtj.opt, 2); if(outname) { fipo = dk3sf_fopen_app(outname, dkdbt_kw[0], dkdbtj.app); if(fipo) { dkdbt_make_reverse_file(&dkdbtj, fipo, 1); if(!dk3sf_fclose_fn_app(fipo, outname, dkdbtj.app)) { ok = 0; } } else { /* ERROR: Failed to open file! */ } } else { /* BUG: Should not happen */ } if(dk3opt_get_num_args(dkdbtj.opt) > 3) { dk3app_log_i3( dkdbtj.app, DK3_LL_WARNING, 164, 165, dk3opt_get_arg(dkdbtj.opt, 3) ); } } else { dkdbt_make_reverse_file(&dkdbtj, stdout, 0); } dk3dbi_close(dkdbtj.in); } else { /* ERROR: Failed to open input database! */ } } else { /* BUG: Should not happen */ } } break; default: { /* ERROR: Wrong number of arguments! */ if(dk3opt_get_num_args(dkdbtj.opt) > 3) { dk3app_log_i3( app, DK3_LL_ERROR, 164, 165, dk3opt_get_arg(dkdbtj.opt, 3) ); } } break; } } } } dkdbt_job_end(&dkdbtj); } /** Split SQL input lines. @param app Application structure. @param msg Localized message texts. @param infile Input file, opened for text reading. @param outfile Output file, opened for text writing. @return 1 on success, 0 on error. */ static int dkdbt_split_for_files( dk3_app_t *app, dkChar const * const *msg, FILE *infile, FILE *outfile ) { int back = 0; int inputc; /* Current input character. */ int cc; /* Flag: Can continue. */ int inputt; /* Input character classification. */ int state; /* Current state. */ char c; /* Current input character. */ $? "+ dkdbt_split_for_files" dkdbt_sql_split_reset(&state); do { cc = 0; inputc = fgetc(infile); if(inputc != EOF) { cc = 1; c = (char)inputc; inputt = I_ANY; switch(c) { case '\\': inputt = I_BS; break; case '/': inputt = I_SL; break; case '*': inputt = I_AST; break; case '\'': inputt = I_Q; break; case '"': inputt = I_DQ; break; case '`': inputt = I_BT; break; case ')': inputt = I_CL; break; case ',': inputt = I_COMMA; break; case '-': inputt = I_MINUS; break; case '\n': inputt = I_NL; break; } switch(dkdbt_sql_split_step(&state, inputt)) { case O_NL: { fputc('\n', outfile); } break; } fputc(inputc, outfile); } } while(cc); if(state == ST_N) { back = 1; } else { /* ERROR: Error in SQL input! */ dk3app_log_1(app, DK3_LL_ERROR, msg, 11); } $? "- dkdbt_split_for_files" return back; } /** Issue error message for wrong file type. @param app Application structure for diagnostics. @param msg Array containing localized message texts. @param en File name. @param es Stat information for file. */ static void dkdbt_wrong_file_type( dk3_app_t *app, dkChar const * const *msg, dkChar const *en, dk3_stat_t const *es ) { dkChar const *oldsourcename; /* Previous source file name. */ unsigned long oldsourceline; /* Previous source file line. */ oldsourcename = dk3app_get_source_file(app); oldsourceline = dk3app_get_source_line(app); dk3app_set_source_file(app, en); dk3app_set_source_line(app, 0UL); dk3app_log_1(app, DK3_LL_ERROR, msg, 10); dk3app_set_source_file(app, oldsourcename); dk3app_set_source_line(app, oldsourceline); } /** Process one input file for splitting SQL lines. @param app Application structure. @param msg Localized message texts. @param fipo Input file, opened for text reading. @param xargc Number of command line arguments. @param xargv Command line arguments array. @return 1 on success, 0 on error. */ static int dkdbt_split_input_file( dk3_app_t *app, dkChar const * const *msg, FILE *fipo, int xargc, dkChar const * const *xargv ) { dkChar fnb[DK3_MAX_PATH]; /* Copy of file name. */ FILE *outf; /* Output file. */ dk3_dir_t *fne; /* File name expander. */ dk3_stat_t const *es; /* stat inf for current file. */ dkChar const *en; /* Full name current file. */ int back = 0; if(xargc > 3) { if(dk3str_len(xargv[3]) < DK3_SIZEOF(fnb,dkChar)) { dk3str_cpy_not_overlapped(fnb, xargv[3]); dk3str_correct_filename(fnb); if(dk3sf_must_expand(fnb)) { fne = dk3dir_fne_open_app(fnb, app); if(fne) { if(dk3dir_get_number_of_files(fne) == 1) { if(dk3dir_get_next_file(fne)) { en = dk3dir_get_fullname(fne); es = dk3dir_get_stat(fne); if((en) && (es)) { switch((es->ft) & (~(DK3_FT_SYMLINK))) { case DK3_FT_REGULAR: { outf = dk3sf_fopen_app(en, dk3app_not_localized(24), app); if(outf) { if(dkdbt_split_for_files(app, msg, fipo, outf)) { back = 1; } if(!dk3sf_fclose_fn_app(outf, en, app)) { back = 0; } } else { /* ERROR: Failed to open output file! */ } } break; default: { /* ERROR: Wrong file type! */ dkdbt_wrong_file_type(app, msg, en, es); } break; } } else { /* BUG: Should not happen! */ } } else { /* ERROR: No matching file name! */ dk3app_log_i3(app, DK3_LL_ERROR, 215, 216, fnb); } } else { if(dk3dir_get_number_of_files(fne)) { /* ERROR: Too many matching file names! */ dk3app_log_i3(app, DK3_LL_ERROR, 168, 169, fnb); } else { /* ERROR: No matching file name! */ dk3app_log_i3(app, DK3_LL_ERROR, 215, 216, fnb); } } dk3dir_close(fne); } else { /* ERROR: Failed to open file name expander! */ } } else { outf = dk3sf_fopen_app(fnb, dk3app_not_localized(24), app); if(outf) { if(dkdbt_split_for_files(app, msg, fipo, outf)) { back = 1; } if(!dk3sf_fclose_fn_app(outf, fnb, app)) { back = 0; } } else { /* ERROR: Failed to open output file! */ } } } else { /* ERROR: File name too long! */ dk3app_log_i3(app, DK3_LL_ERROR, 65, 66, xargv[3]); } } else { if(dkdbt_split_for_files(app, msg, fipo, stdout)) { back = 1; } } return back; } /** Split long lines in mysqldump output. @param app Application structure for diagnostics. @param msg Localized messages. @param xargc Number of command line arguments. @param xargv Command line arguments array. */ static void dkdbt_split_sql_lines( dk3_app_t *app, dkChar const * const *msg, int xargc, dkChar const * const *xargv ) { dkChar fnb[DK3_MAX_PATH]; /* Copy of file name. */ FILE *fipo; /* Input file. */ dk3_dir_t *fne; /* File name expander. */ dkChar const *en; /* File name current file. */ dk3_stat_t const *es; /* stat info current file. */ int ok; /* Flag: No errors. */ int have_files; /* Flag: Files found. */ $? "+ dkdbt_split_sql_lines" ok = 1; have_files = 0; if(xargc > 2) { if(dk3str_len(xargv[2]) < DK3_SIZEOF(fnb,DK3_SIZEOF(fnb,dkChar))) { dk3str_cpy_not_overlapped(fnb, xargv[2]); dk3str_correct_filename(fnb); if(dk3sf_must_expand(fnb)) { fne = dk3dir_fne_open_app(fnb, app); if(fne) { if(dk3dir_get_number_of_files(fne)) { ok = 1; while(dk3dir_get_next_file(fne)) { en = dk3dir_get_shortname(fne); es = dk3dir_get_stat(fne); if((en) && (es)) { switch((es->ft) & (~(DK3_FT_SYMLINK))) { case DK3_FT_REGULAR: { fipo = dk3sf_fopen_app( en, dk3app_not_localized(22), app ); if(fipo) { have_files = 1; if(!dkdbt_split_input_file(app, msg, fipo, xargc, xargv)) { ok = 0; } fclose(fipo); } else { /* ERROR: Failed to open file! */ ok = 0; } } break; default: { /* ERROR: Wrong file type! */ dkdbt_wrong_file_type(app, msg, en, es); ok = 0; } break; } } else { ok = 0; /* BUG: Should not happen! */ } } if((ok > 0) && (have_files > 0)) { exval = 0; } else { if(have_files == 0) { /* ERROR: No input files found! */ dk3app_log_1(app, DK3_LL_ERROR, msg, 9); } } } else { /* ERROR: No matching file name! */ dk3app_log_i3(app, DK3_LL_ERROR, 215, 216, fnb); } dk3dir_close(fne); } else { /* ERROR: Failed to expand file name! */ dk3app_log_3(app, DK3_LL_ERROR, msg, 7, 8, fnb); } } else { fipo = dk3sf_fopen_app(fnb, dk3app_not_localized(22), app); if(fipo) { if(dkdbt_split_input_file(app, msg, fipo, xargc, xargv)) { exval = 0; } fclose(fipo); } else { /* ERROR: Failed to open file! */ } } } else { /* ERROR: Input file name too long! */ dk3app_log_i3(app, DK3_LL_ERROR, 65, 66, xargv[2]); } } else { if(dkdbt_split_for_files(app, msg, stdin, stdout)) { exval = 0; } } $? "- dkdbt_split_sql_lines" } /** The main() function. @param argc Number of command line arguments. @param argv Command line arguments array. @return 0 on success, any other value indicates an error. */ DK3_MAIN { dk3_app_t *app = NULL; /* Application structure. */ dkChar const * const *msg = NULL; /* Localized message texts. */ dkChar const * const *xargv; /* Command line arguments array. */ int xargc; /* Number of command line arguments. */ $!trace-init dkdbtool.deb $? "+ main" app = dk3app_open_command( argc, (dkChar const * const *)argv, dkt_group_name ); if(app) { msg = dk3app_messages( app, dkdbt_stt_file_name, (dkChar const **)dkdbt_message_texts ); xargc = dk3app_get_argc(app); xargv = dk3app_get_argv(app); if(xargc > 1) { switch(dk3str_array_abbr(dkdbt_commands, xargv[1], dkT('$'), 0)) { case 0: case 1: { /* Help */ dkdbt_show_help(app); exval = 0; } break; case 2: case 3: { /* Version */ dkdbt_show_version(app); exval = 0; } break; case 4: case 5: case 13: case 14:{ /* License */ dkdbt_show_license(app); exval = 0; } break; case 6: case 7: { /* Features */ dkdbt_show_features(app, msg); exval = 0; } break; case 8: { /* Copy */ dkdbt_copy(app, msg, xargc, xargv); } break; case 9: { /* Make */ dkdbt_make(app, msg, xargc, xargv); } break; case 10: { /* Reverse make. */ dkdbt_make_reverse(app, msg, xargc, xargv); } break; case 11: case 12: { /* Split SQL lines. */ dkdbt_split_sql_lines(app, msg, xargc, xargv); } break; default: { /* Unknown command. */ /* ERROR: Unknown command! */ dk3app_log_3(app, DK3_LL_ERROR, dkdbt_message_texts, 5, 6, xargv[1]); dkdbt_show_help(app); } break; } } else { /* ERROR: Syntax */ dk3app_log_1(app, DK3_LL_ERROR, dkdbt_message_texts, 4); dkdbt_show_help(app); } dk3app_close(app); } else { /* ERROR: Memory */ fputs("Error: Not enough memory!\n", stderr); fflush(stderr); } $? "- main %d", exval $!trace-end fflush(stdout); exit(exval); return exval; }