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/dkdbt.ctr |
Initial commit
Diffstat (limited to 'support/dktools/dkdbt.ctr')
-rw-r--r-- | support/dktools/dkdbt.ctr | 2023 |
1 files changed, 2023 insertions, 0 deletions
diff --git a/support/dktools/dkdbt.ctr b/support/dktools/dkdbt.ctr new file mode 100644 index 0000000000..f249fecb38 --- /dev/null +++ b/support/dktools/dkdbt.ctr @@ -0,0 +1,2023 @@ +%% options + +copyright owner = Dirk Krause +copyright year = 2011-xxxx +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" +#if 0 +#include "dkt-version.h" +#endif +#include "dk4vers.h" +#include "dk3ma.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 <db.h> +/** Use Berkeley DB. +*/ +#define DK3_USE_DB 1 +#endif + +#if DK3_HAVE_NDBM_H +#include <ndbm.h> +/** Use NDBM. +*/ +#define DK3_USE_NDBM 1 +#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("dktools") }; + + + +/** 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_DK +}; + + + +/** 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 macro=dkT + +dkdbt - Dirk Krause's database tool +=================================== + +Usage +----- + +dkdbt copy [-a] <source-db-name> <destination-db-name> +dkdbt make [-c <char>] [-a] [-i <encoding>] <destination-db-name> [<file(s)>] +dkdbt text [-o <encoding>] <source-db-name> [<file>] +dkdbt split-sql-lines [<inputfile> [<outputfile>]] + +dkdbt help +dkdbt version +dkdbt license +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 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-2016, Dirk Krause +All rights reserved. + +Redistribution and use in source and binary forms, +with or without modification, are permitted provided +that the following conditions are met: + +* Redistributions of source code must retain the above + copyright notice, this list of conditions and the + following disclaimer. +* Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. +* Neither the name of the 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=\"%!ds\"", il + p1 = dk3str_start(il, NULL); + if(p1) { + if(j->comm) { + if(*p1 == j->comm) { + comm = 1; + back = 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 = \"%!ds\"", 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 \"%!ds\"", 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_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 = 1; /* Flag: No errors found. */ + int res = 0; /* Operation result. */ + int ec = 0; /* Error code. */ + + dkdbt_job_init(&dkdbtj, app, msg, xargc, xargv); +#if VERSION_BEFORE_20150821 + ok = 1; ec = 0; +#endif + 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)) { +#if VERSION_BEFORE_20150821 + ok = 0; +#endif + } + } 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 = 1; /* Flag: No errors. */ + int have_files = 0; /* Flag: Files found. */ + + $? "+ dkdbt_split_sql_lines" +#if VERSION_BEFORE_20150821 + ok = 1; have_files = 0; +#endif + 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; +} + + |