summaryrefslogtreecommitdiff
path: root/support/dktools/dkdbt.ctr
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /support/dktools/dkdbt.ctr
Initial commit
Diffstat (limited to 'support/dktools/dkdbt.ctr')
-rw-r--r--support/dktools/dkdbt.ctr2023
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;
+}
+
+