/* Copyright (c) 2007-2010, 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 opyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Dirk Krause nor the names of other 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. */ /** @file text2htm.c The text2htm program. */ /* text2htm [ []] -e encoding input encoding -f full HTML output -g template -b keep line breaks -s style style sheet (referenced as ) -t title title -h -v -c -u -C -r */ #include #include #if DK_HAVE_STDLIB_H #include #endif #if DK_HAVE_UNISTD_H #include #endif #if DK_HAVE_PROCESS_H #include #endif #include #include #include #include #include #include #include /** Text2html job. */ typedef struct { int success; /**< Flag: Success (1) or failure (0). */ int cmd; /**< Command to execute. */ int enc; /**< Input encoding. */ size_t sz_ib; /**< Size of input buffer. */ dk_udword u; /**< Current 32-bit character to process. */ unsigned long ln; /**< Current line number. */ char c; /**< Current character to process. */ unsigned char full; /**< Flag: Generate full HTML output. */ unsigned char tmpl; /**< Flag: create template code. */ unsigned char kplb; /**< Flag: Keep line breaks. */ unsigned char enca; /**< Flag: Choose encoding automatically. */ char *i1; /**< Input file name from command line. */ char *o1; /**< Output file name from command line. */ char *i2; /**< Input file name after pattern expansion. */ char *o2; /**< Output file name after pattern expansion. */ char *style; /**< Stylesheet to use. */ char *title; /**< HTML page title. */ char *ib; /**< Input buffer. */ FILE *fi; /**< Input file. */ FILE *fo; /**< Output file. */ dk_app_t *a; /**< Applicaton. */ char **msg; /**< Messages. */ } T2H; /** Encoding: ISO-LATIN-8859-1. */ #define ENCODING_ISO_LATIN_8859_1 0 /** Encoding: UTF-8. */ #define ENCODING_UTF_8 1 #include "dktools-version.h" #line 129 "text2htm.ctr" /** String finder data. */ dk_key_value_t kv[] = { { (char *)"/m/00", (char *)"Current configuration:" }, { (char *)"/m/01", (char *)"Too many file names specified!" }, { (char *)"/m/02", (char *)"" }, { (char *)"/m/03", (char *)"Current configuration:" }, { (char *)"/m/04", (char *)"Input encoding:" }, { (char *)"/m/05", (char *)"HTML page title " }, { (char *)"/m/06", (char *)"Style URL " }, { (char *)"/m/07", (char *)"Write full HTML file:" }, { (char *)"/m/08", (char *)"Write full HTML file, add templates:" }, { (char *)"/m/09", (char *)"Keep line breaks:" }, { (char *)"/m/10", (char *)"yes" }, { (char *)"/m/11", (char *)"no" }, { (char *)"/m/12", (char *)"<<< Not specified. >>>" }, { (char *)"/m/13", (char *)"Inspect the LANG environment variable" }, { (char *)"/m/14", (char *)"ISO-LATIN-8859-1" }, { (char *)"/m/15", (char *)"UTF-8" }, { (char *)"/m/16", (char *)"Failed to expand input file name pattern!" }, { (char *)"/m/17", (char *)"Input file name pattern must match exactly one name!" }, { (char *)"/m/18", (char *)"Failed to expand output file name pattern!" }, { (char *)"/m/19", (char *)"Output file name pattern must match exactly one name!" }, { (char *)"/m/20", (char *)"Error while decoding input!" }, { (char *)"/m/21", (char *)"Conversion aborted, output may be incomplete!" }, }; /** Number of elements in the \a kv array. */ static size_t szkv = sizeof(kv)/sizeof(dk_key_value_t); /** Default input file name. */ static char str_stdin[] = { "" }; /** Default output file name. */ static char str_stdout[] = { "" }; /** Line break tag. */ static char tag_br[] = { "
" }; /** String: None. */ static char str_none[] = { "<<>>" }; /** Spaces are used when showing the configuration. */ static char str_sp8[] = { " " }; /** Option -e. */ static char str_minus_e[] = { "-e " }; /** Option -t. */ static char str_minus_t[] = { "-t " }; /** Option -s. */ static char str_minus_s[] = { "-s " }; /** Option -f. */ static char str_minus_f[] = { "-f" }; /** Option -g. */ static char str_minus_g[] = { "-g" }; /** Option -b. */ static char str_minus_b[] = { "-b" }; /** Encodings. */ static char *str_enc[] = { "automatic", "latin-1", "utf-8" }; /** Full page header. */ static char *a_header[] = { "", "", "", "", NULL }; /** Template for title. */ static char *a_template_title[] = { "", "__TEXT__", NULL }; /** Template for style sheet URL. */ static char *a_template_style[] = { "", "", NULL }; /** Template for lots of header elements. */ static char *a_template_all[] = { "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", NULL }; /** Style tag. */ static char *a_tag_style[] = { "" }; /** Full page body start. */ static char *a_middle[] = { "", "", "

", NULL }; /** Full page footer. */ static char *a_footer[] = { "

", "", "", NULL }; /** Title tag. */ static char *a_title[] = { "", "" }; /** Long options. */ static char *long_options[] = { /* 0 */ "h$elp", /* 1 */ "v$ersion", /* 2 */ "conf$igure", /* 3 */ "unconf$igure", /* 4 */ "res$et", /* 5 */ "sh$ow-configuration", /* 6 */ "sil$ently", /* 7 */ "e$ncoding", /* 8 */ "title", /* 9 */ "style", /* 10 */ "full", /* 11 */ "template", /* 12 */ "keep-line-breaks", NULL }; /** String table name. */ static char table_name[] = { "text2htm" }; /** Program group name. */ static char group_name[] = { "dktools" }; /** System configuration directory. */ static char sysconf_dir[] = { DK_SYSCONFDIR }; /** Preference key: Input encoding */ static char pk_encoding[] = { "/input/encoding" }; /** Preference key: Style sheet URL. */ static char pk_style[] = { "/html/stylesheet" }; /** Preference key: Title for HTML file. */ static char pk_title[] = { "/html/title" }; /** Preference key: Create full HTML file. */ static char pk_full[] = { "/html/page/full" }; /** Prefrence key: Template for full HTML file. */ static char pk_tmpl[] = { "/html/page/template" }; /** Preference key: Keep line breaks. */ static char pk_keep[] = { "/html/keep-linebreaks" }; /** Preference value: On. */ static char str_on[] = { "on" }; /** Preference value: Off. */ static char str_off[] = { "off" }; /** Language settings. */ static char *val_enc[] = { /* used to restore settings */ /* 0 */ "a$utomatic", /* 1 */ "l$atin-1", /* 2 */ "u$tf-8", NULL }; /** Language suffix to indicate UTF-8 encoding. */ static char str_utf8[] = { ".UTF-8" }; /** Translation table for ASCII characters. */ static char *translation_table[] = { /* 0 00 */ NULL, /* 1 01 */ NULL, /* 2 02 */ NULL, /* 3 03 */ NULL, /* 4 04 */ NULL, /* 5 05 */ NULL, /* 6 06 */ NULL, /* 7 07 */ NULL, /* 8 08 */ NULL, /* 9 09 */ "\t", /* 10 0a */ NULL, /* 11 0b */ NULL, /* 12 0c */ NULL, /* 13 0d */ NULL, /* 14 0e */ NULL, /* 15 0f */ NULL, /* 16 10 */ NULL, /* 17 11 */ NULL, /* 18 12 */ NULL, /* 19 13 */ NULL, /* 20 14 */ NULL, /* 21 15 */ NULL, /* 22 16 */ NULL, /* 23 17 */ NULL, /* 24 18 */ NULL, /* 25 19 */ NULL, /* 26 1a */ NULL, /* 27 1b */ NULL, /* 28 1c */ NULL, /* 29 1d */ NULL, /* 30 1e */ NULL, /* 31 1f */ NULL, /* 32 20 */ " ", /* 33 21 */ "!", /* 34 22 */ "\"", /* 35 23 */ "#", /* 36 24 */ "$", /* 37 25 */ "%", /* 38 26 */ "&", /* 39 27 */ "'", /* 40 28 */ "(", /* 41 29 */ ")", /* 42 2a */ "*", /* 43 2b */ "+", /* 44 2c */ ",", /* 45 2d */ "-", /* 46 2e */ ".", /* 47 2f */ "/", /* 48 30 */ "0", /* 49 31 */ "1", /* 50 32 */ "2", /* 51 33 */ "3", /* 52 34 */ "4", /* 53 35 */ "5", /* 54 36 */ "6", /* 55 37 */ "7", /* 56 38 */ "8", /* 57 39 */ "9", /* 58 3a */ ":", /* 59 3b */ ";", /* 60 3c */ "<", /* 61 3d */ "=", /* 62 3e */ ">", /* 63 3f */ "?", /* 64 40 */ "@", /* 65 41 */ "A", /* 66 42 */ "B", /* 67 43 */ "C", /* 68 44 */ "D", /* 69 45 */ "E", /* 70 46 */ "F", /* 71 47 */ "G", /* 72 48 */ "H", /* 73 49 */ "I", /* 74 4a */ "J", /* 75 4b */ "K", /* 76 4c */ "L", /* 77 4d */ "M", /* 78 4e */ "N", /* 79 4f */ "O", /* 80 50 */ "P", /* 81 51 */ "Q", /* 82 52 */ "R", /* 83 53 */ "S", /* 84 54 */ "T", /* 85 55 */ "U", /* 86 56 */ "V", /* 87 57 */ "W", /* 88 58 */ "X", /* 89 59 */ "Y", /* 90 5a */ "Z", /* 91 5b */ "[", /* 92 5c */ "\\", /* 93 5d */ "]", /* 94 5e */ "^", /* 95 5f */ "_", /* 96 60 */ "`", /* 97 61 */ "a", /* 98 62 */ "b", /* 99 63 */ "c", /* 100 64 */ "d", /* 101 65 */ "e", /* 102 66 */ "f", /* 103 67 */ "g", /* 104 68 */ "h", /* 105 69 */ "i", /* 106 6a */ "j", /* 107 6b */ "k", /* 108 6c */ "l", /* 109 6d */ "m", /* 110 6e */ "n", /* 111 6f */ "o", /* 112 70 */ "p", /* 113 71 */ "q", /* 114 72 */ "r", /* 115 73 */ "s", /* 116 74 */ "t", /* 117 75 */ "u", /* 118 76 */ "v", /* 119 77 */ "w", /* 120 78 */ "x", /* 121 79 */ "y", /* 122 7a */ "z", /* 123 7b */ "{", /* 124 7c */ "|", /* 125 7d */ "}", /* 126 7e */ "~", /* 127 7f */ NULL, /* 128 80 */ NULL, /* 129 81 */ NULL, /* 130 82 */ NULL, /* 131 83 */ NULL, /* 132 84 */ NULL, /* 133 85 */ NULL, /* 134 86 */ NULL, /* 135 87 */ NULL, /* 136 88 */ NULL, /* 137 89 */ NULL, /* 138 8a */ NULL, /* 139 8b */ NULL, /* 140 8c */ NULL, /* 141 8d */ NULL, /* 142 8e */ NULL, /* 143 8f */ NULL, /* 144 90 */ NULL, /* 145 91 */ NULL, /* 146 92 */ NULL, /* 147 93 */ NULL, /* 148 94 */ NULL, /* 149 95 */ NULL, /* 150 96 */ NULL, /* 151 97 */ NULL, /* 152 98 */ NULL, /* 153 99 */ NULL, /* 154 9a */ NULL, /* 155 9b */ NULL, /* 156 9c */ NULL, /* 157 9d */ NULL, /* 158 9e */ NULL, /* 159 9f */ NULL, /* 160 a0 */ " ", /* 161 a1 */ "¡", /* 162 a2 */ "¢", /* 163 a3 */ "£", /* 164 a4 */ "¤", /* 165 a5 */ "¥", /* 166 a6 */ "¦", /* 167 a7 */ "§", /* 168 a8 */ "¨", /* 169 a9 */ "©", /* 170 aa */ "ª", /* 171 ab */ "«", /* 172 ac */ "¬", /* 173 ad */ "­", /* 174 ae */ "®", /* 175 af */ "¯", /* 176 b0 */ "°", /* 177 b1 */ "±", /* 178 b2 */ "²", /* 179 b3 */ "³", /* 180 b4 */ "´", /* 181 b5 */ "µ", /* 182 b6 */ "¶", /* 183 b7 */ "·", /* 184 b8 */ "¸", /* 185 b9 */ "¹", /* 186 ba */ "º", /* 187 bb */ "»", /* 188 bc */ "¼", /* 189 bd */ "½", /* 190 be */ "¾", /* 191 bf */ "¿", /* 192 c0 */ "À", /* 193 c1 */ "Á", /* 194 c2 */ "Â", /* 195 c3 */ "Ã", /* 196 c4 */ "Ä", /* 197 c5 */ "Å", /* 198 c6 */ "Æ", /* 199 c7 */ "Ç", /* 200 c8 */ "È", /* 201 c9 */ "É", /* 202 ca */ "Ê", /* 203 cb */ "Ë", /* 204 cc */ "/Igrave;", /* 205 cd */ "Í", /* 206 ce */ "Î", /* 207 cf */ "Ï", /* 208 d0 */ "Ð", /* 209 d1 */ "Ñ", /* 210 d2 */ "Ò", /* 211 d3 */ "Ó", /* 212 d4 */ "Ô", /* 213 d5 */ "Õ", /* 214 d6 */ "Ö", /* 215 d7 */ "×", /* 216 d8 */ "Ø", /* 217 d9 */ "Ù", /* 218 da */ "Ú", /* 219 db */ "Û", /* 220 dc */ "Ü", /* 221 dd */ "Ý", /* 222 de */ "Þ", /* 223 df */ "ß", /* 224 e0 */ "à", /* 225 e1 */ "á", /* 226 e2 */ "â", /* 227 e3 */ "ã", /* 228 e4 */ "ä", /* 229 e5 */ "å", /* 230 e6 */ "æ", /* 231 e7 */ "ç", /* 232 e8 */ "è", /* 233 e9 */ "é", /* 234 ea */ "ê", /* 235 eb */ "ë", /* 236 ec */ "ì", /* 237 ed */ "í", /* 238 ee */ "î", /* 239 ef */ "ï", /* 240 f0 */ "ð", /* 241 f1 */ "ñ", /* 242 f2 */ "ò", /* 243 f3 */ "ó", /* 244 f4 */ "ô", /* 245 f5 */ "õ", /* 246 f6 */ "ö", /* 247 f7 */ "÷", /* 248 f8 */ "ø", /* 249 f9 */ "ù", /* 250 fa */ "ú", /* 251 fb */ "û", /* 252 fc */ "ü", /* 253 fd */ "ý", /* 254 fe */ "þ", /* 255 ff */ "ÿ" }; /** Version number text. */ static char *version_text[] = { "", "text2htm (part of the dktools collection, version " VERSNUMB ")", "Copyright (C) 2007-2010 - Dipl.-Ing. Dirk Krause", "http://dktools.sourceforge.net", "", NULL }; /** License conditions. */ static char *license_text[] = { "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 Dirk Krause nor the names of other 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.", NULL }; /** Default help text, printed if help text file is not found. */ static char *help_text[] = { "", "Overview", "--------", "The program converts text (plain text or UTF-8 encoded text) to HTML.", "", "Usage", "-----", "text2htm [] [ []]", "", "Options", "-------", "-e encoding", " Input encoding", " automatic: Inspect the LANG environment variable", " latin-1: ISO-LATIN-8859-1", " utf-8: UTF-8", "-t title", " Title for HTML page", "-s style", " URL of CSS style sheet to use", "-f", " Write full HTML file (use -f- to disable)", "-g", " Write full HTML file and template code (use -g- to disable)", "-b", " Convert line breaks to
tag (use -b- to disable)", NULL }; /** Command: Show help text. */ #define CMD_HELP 1 /** Command: Show version information. */ #define CMD_VERSION 2 /** Command: Configure application. */ #define CMD_CONFIGURE 4 /** Command: Unconfigure application. */ #define CMD_UNCONFIGURE 8 /** Command: Show configuration. */ #define CMD_SHOW_CONFIGURATION 16 /** Command: Abort due to error. */ #define CMD_ABORT_ERROR 32 /** Boolean value TRUE. */ #define UC1 ((unsigned char)0x01) /** Boolean value FALSE. */ #define UC0 ((unsigned char)0x00) /** Function prototype. */ #define T2H_VOID(a) static void a DK_P1(T2H *,t) /** Check whether or not the program must run silently. @param argc Number of command line arguments. @param argv Command line arguments array. @param rs Pointer to result variable (run silently). @param rf Pointer to result variable (run as filter). */ static void silence_check DK_P4(int,argc, char **,argv, int *,rs, int *,rf) { int i; char *ptr, **lfdptr; int myrf = 1, myrs = 0; lfdptr = argv; lfdptr++; i = 1; while(i < argc) { ptr = *lfdptr; if(*ptr == '-') { ptr++; if(*ptr == '-') { ptr++; switch(dkstr_array_abbr(long_options, ptr, '$', 0)) { case 6: myrs = 1; break; } } else { switch(*ptr) { case 'e': case 's': case 't': { ptr++; if(!(*ptr)) { lfdptr++; i++; } } break; } } } else { myrf = 0; } lfdptr++; i++; } if(rs) { *rs = myrs; } if(rf) { *rf = myrf; } } /** Initialize text2htm job. @param t Text2htm job to initialize. */ T2H_VOID(t2h_init) { if(t) { t->success = t->cmd = 0; t->i1 = t->o1 = t->i2 = t->o2 = NULL; t->fi = t->fo = NULL; t->a = NULL; t->style = t->title = NULL; t->full = t->tmpl = t->kplb = UC0; t->enca = UC1; t->enc = 0; t->msg = NULL; t->ib = NULL; t->sz_ib = 0; t->ln = 0UL; } } /** Show error message. @param t Text2htm job. @param n Index of message text in t->msg. */ static void error_1 DK_P2(T2H *,t, size_t,n) { char *messages[2]; messages[0] = (t->msg)[n]; dkapp_log_msg(t->a, DK_LOG_LEVEL_ERROR, messages, 1); } /** Set style. @param t Text2htm job. @param s Style URL. */ static void set_style DK_P2(T2H *,t, char *,s) { char *p; if(t->style) { p = t->style; dk_delete(p); t->style = NULL; } if(strcmp(s, str_none)) { t->style = dkstr_dup(s); if(!(t->style)) { t->cmd = CMD_ABORT_ERROR; error_1(t, 0); } } } /** Set title for HTML document. @param t Text2htm job. @param s Title string. */ static void set_title DK_P2(T2H *,t, char *,s) { char *p; if(t->title) { p = t->title; dk_delete(p); t->title = NULL; } if(strcmp(s, str_none)) { t->title = dkstr_dup(s); if(!(t->title)) { t->cmd = CMD_ABORT_ERROR; error_1(t, 0); } } } /** Get boolean value from string. @param t Text2htm job. @param s String containing the boolean value. @param d Default value. @return Boolen value obtained from \a s. */ static unsigned char get_bool DK_P3(T2H *,t, char *,s, unsigned char,d) { unsigned char back; back = d; switch(*s) { case '+': back = UC1; break; case '-': back = UC0; break; default: { if(dkstr_is_bool(s)) { if(dkstr_is_on(s)) { back = UC1; } else { back = UC0; } } } } return back; } /** Get encoding from string. @param t Text2htm job. @param s String containing the encoding. */ static void encoding_from_string DK_P2(T2H *,t, char *,s) { char *ptr; t->enca = UC0; t->enc = ENCODING_ISO_LATIN_8859_1; switch(dkstr_array_abbr(val_enc, s, '$', 0)) { case 1: { t->enc = ENCODING_ISO_LATIN_8859_1; } break; case 2: { t->enc = ENCODING_UTF_8; } break; default: { ptr = getenv("LANG"); if(ptr) { ptr = strchr(ptr, '.'); if(ptr) { if(dkstr_casecmp(ptr, str_utf8) == 0) { t->enc = ENCODING_UTF_8; } else { t->enc = ENCODING_ISO_LATIN_8859_1; } t->enca = UC1; } } } break; } } /** Initialize from preferences. @param t Text2htm job. */ T2H_VOID(init_from_preferences) { char buffer[1024], *ptr; if(dkapp_get_pref(t->a, pk_encoding, buffer, sizeof(buffer), 0)) { ptr = dkstr_start(buffer, NULL); if(ptr) { dkstr_chomp(ptr, NULL); encoding_from_string(t, ptr); } } if(dkapp_get_pref(t->a, pk_style, buffer, sizeof(buffer), 0)) { ptr = dkstr_start(buffer, NULL); if(ptr) { dkstr_chomp(ptr, NULL); set_style(t, ptr); } } if(dkapp_get_pref(t->a, pk_title, buffer, sizeof(buffer), 0)) { ptr = dkstr_start(buffer, NULL); if(ptr) { dkstr_chomp(ptr, NULL); set_title(t, ptr); } } if(dkapp_get_pref(t->a, pk_full, buffer, sizeof(buffer), 0)) { ptr = dkstr_start(buffer, NULL); if(ptr) { dkstr_chomp(ptr, NULL); t->full = get_bool(t, ptr, UC0); } } if(dkapp_get_pref(t->a, pk_tmpl, buffer, sizeof(buffer), 0)) { ptr = dkstr_start(buffer, NULL); if(ptr) { dkstr_chomp(ptr, NULL); t->tmpl = get_bool(t, ptr, UC0); } } if(dkapp_get_pref(t->a, pk_keep, buffer, sizeof(buffer), 0)) { ptr = dkstr_start(buffer, NULL); if(ptr) { dkstr_chomp(ptr, NULL); t->kplb = get_bool(t, ptr, UC0); } } } /** Reset configuration (-r option). @param t Text2htm job. */ T2H_VOID(reset_configuration) { char *p; t->enc = ENCODING_ISO_LATIN_8859_1; t->full = t->tmpl = t->kplb = t->enca = UC0; if(t->style) { p = t->style; dk_delete(p); t->style = NULL; } if(t->title) { p = t->title; dk_delete(p); t->title = NULL; } } /** Process command line arguments. @param t Text2htm job. */ T2H_VOID(check_arguments) { int i, xargc; char **lfdptr, **xargv, *ptr, *arg, *oarg, *p; xargc = dkapp_get_argc(t->a); xargv = dkapp_get_argv(t->a); i = 1; lfdptr = xargv; lfdptr++; while(i < xargc) { ptr = *lfdptr; if(*ptr == '-') { /* option */ ptr++; if(*ptr == '-') { /* long option */ ptr++; oarg = NULL; arg = strchr(ptr, '='); if(arg) { oarg = arg; *(arg++) = '\0'; } switch(dkstr_array_abbr(long_options, ptr, '$', 0)) { case 0: { t->cmd = CMD_HELP; } break; case 1: { t->cmd = CMD_VERSION; } break; case 2: { t->cmd = CMD_CONFIGURE; } break; case 3: { t->cmd = CMD_UNCONFIGURE; } break; case 4: { reset_configuration(t); } break; case 5: { t->cmd = CMD_SHOW_CONFIGURATION; } break; case 6: {} break; case 7: { if(arg) { encoding_from_string(t, arg); } else { t->enca = UC1; t->enc = 0; } } break; case 8: { if(arg) { set_title(t, arg); } else { if(t->title) { p = t->title; t->title = NULL; dk_delete(p); } } } break; case 9: { if(arg) { set_style(t, arg); } else { if(t->style) { p = t->style; t->style = NULL; dk_delete(p); } } } break; case 10: { /* full */ if(arg) { t->full = get_bool(t, arg, UC1); } else { t->full = UC1; } } break; case 11: { /* template */ if(arg) { t->tmpl = get_bool(t, arg, UC1); } else { t->tmpl = UC1; } } break; case 12: { /* keep line-breaks */ if(arg) { t->kplb = get_bool(t, arg, UC1); } else { t->kplb = UC1; } } break; } if(oarg) { *oarg = '='; } } else { /* normal options */ switch(*ptr) { case 'h': { t->cmd = CMD_HELP; } break; case 'v': { t->cmd = CMD_VERSION; } break; case 'c': { t->cmd = CMD_CONFIGURE; } break; case 'C': { t->cmd = CMD_SHOW_CONFIGURATION; } break; case 'u': { t->cmd = CMD_UNCONFIGURE; } break; case 'r': { reset_configuration(t); } break; case 'e': { /* encoding */ ptr++; if(!(*ptr)) { ptr = NULL; i++; lfdptr++; if(i < xargc) { ptr = *lfdptr; } } if(ptr) { encoding_from_string(t, ptr); } } break; case 'f': { /* full file */ ptr++; if(*ptr) { t->full = get_bool(t, ptr, UC1); } else { t->full = UC1; } } break; case 'g': { /* template */ ptr++; if(*ptr) { t->tmpl = get_bool(t, ptr, UC1); } else { t->tmpl = UC1; } } break; case 'b': { /* keep line breaks */ ptr++; if(*ptr) { t->kplb = get_bool(t, ptr, UC1); } else { t->kplb = UC1; } } break; case 's': { /* stylesheet */ ptr++; if(!(*ptr)) { ptr = NULL; i++; lfdptr++; if(i < xargc) { ptr = *lfdptr; } } if(ptr) { set_style(t, ptr); } } break; case 't': { /* title */ ptr++; if(!(*ptr)) { ptr = NULL; i++; lfdptr++; if(i < xargc) { ptr = *lfdptr; } } if(ptr) { set_title(t, ptr); } } break; } } } else { /* file name */ if(t->i1) { if(t->o1) { t->cmd = CMD_ABORT_ERROR; error_1(t, 1); } else { t->o1 = ptr; } } else { t->i1 = ptr; } } lfdptr++; i++; } } /** Process one character. @param t Text2htm job. */ T2H_VOID(process_one_character) { int done = 0; char buffer[16], *p; if(t->u < 256UL) { p = translation_table[((size_t)(t->u)) & 255]; if(p) { (void)fputs(p, t->fo); done = 1; } switch(t->c) { case '\n': { if(t->kplb) { (void)fputs(tag_br, t->fo); } (void)fputc('\n', t->fo); done = 1; t->ln += 1UL; dkapp_set_source_lineno(t->a, t->ln); } break; } } if(!done) { if(t->u > 0x000000FFUL) { if(t->u > 0x0000FFFFUL) { if(t->u > 0x00FFFFFFUL) { sprintf(buffer, "&#x%08lu;", t->u); } else { sprintf(buffer, "&#x%06lu;", t->u); } } else { sprintf(buffer, "&#x%04lu;", t->u); } } else { sprintf(buffer, "&#x%02lu;", t->u); } (void)fputs(buffer, t->fo); } } /** Process UTF-8 encoded input. @param t Text2htm job. */ T2H_VOID(run_utf) { dk_ubyte cb[16], *p1, *p2; dk_udword uw; size_t u_cb, u_ib, i, j, k; unsigned char error_aborted; char *ptr; int cc; cc = 1; u_cb = 0; error_aborted = UC0; while((cc) && (!error_aborted)) { u_ib = fread(t->ib, 1, t->sz_ib, t->fi); if(u_ib > 0) { ptr = t->ib; for(i = 0; ((i < u_ib) && (!error_aborted)); i++) { cb[u_cb++] = (dk_ubyte)(*(ptr++)); if(u_cb > 12) { while((u_cb > 8) && (!error_aborted)) { j = 0; if(dkenc_utf82uc(&uw, cb, u_cb, &j)) { t->u = uw; t->c = ' '; if(t->u < 256UL) { t->c = (char)(t->u); } process_one_character(t); if(j >= u_cb) { u_cb = 0; } else { p1 = cb; p2 = &(cb[j]); for(k = j; k < u_cb; k++) { *(p1++) = *(p2++); } u_cb = u_cb - j; } } else { error_aborted = UC1; } } } } } else { cc = 0; } } /* flush conversion buffer */ if((u_cb) && (!error_aborted)) { while((u_cb > 0) && (!error_aborted)) { j = 0; if(dkenc_utf82uc(&uw, cb, u_cb, &j)) { t->u = uw; t->c = ' '; if(t->u < 256UL) { t->c = (char)(t->u); } process_one_character(t); if(j >= u_cb) { u_cb = 0; } else { p1 = cb; p2 = &(cb[j]); for(k = j; k < u_cb; k++) { *(p1++) = *(p2++); } u_cb = u_cb - j; } } else { error_aborted = UC1; } } } if(error_aborted) { error_1(t, 20); error_1(t, 21); } } /** Process ISO-LATIN-1 encoded input. @param t Text2htm job. */ T2H_VOID(run_iso) { size_t u_ib, i; char *ptr; int cc; cc = 1; while(cc) { u_ib = fread(t->ib, 1, t->sz_ib, t->fi); if(u_ib > 0) { ptr = t->ib; for(i = 0; i < u_ib; i++) { t->c = *(ptr++); t->u = ((dk_udword)(t->c)) & 0xFFUL; process_one_character(t); } } else { cc = 0; } } } /** Write array of strings to output. @param t Text2htm job. @param a Array to output. */ static void put_text_array DK_P2(T2H *,t, char **,a) { char **ptr; ptr = a; while(*ptr) { (void)fputs(*(ptr++), t->fo); (void)fputc('\n', t->fo); } } /** Transfer one string (UTF-8 or ISO-LATIN-1 encoded) to output. @param t Text2htm job. @param s String to convert and output. */ static void put_one_text DK_P2(T2H *,t, char *,s) { size_t u8l, u8u; dk_ubyte *u8p; dk_udword uw; int cc; switch(t->enc) { case ENCODING_UTF_8: { u8l = strlen(s); u8p = (dk_ubyte *)s; cc = 1; while(cc) { u8u = 0; if(dkenc_utf82uc(&uw, u8p, u8l, &u8u)) { /* print character */ t->u = uw; t->c = ' '; if(t->u < 256UL) { t->c = (char)((t->u) & 255UL); } process_one_character(t); /* go on */ if(u8u < u8l) { u8p = &(u8p[u8u]); u8l = u8l - u8u; } else { cc = 0; } } else { cc = 0; t->success = 0; error_1(t, 20); error_1(t, 21); } } } break; default: { (void)fputs(s, t->fo); } break; } } /** All files are opened, run the conversion. @param t Text2htm job. */ T2H_VOID(run_for_files) { t->success = 1; t->ln = 1UL; dkapp_set_source_filename(t->a, t->i2); dkapp_set_source_lineno(t->a, t->ln); /* write HTML code before text */ if((t->full) || (t->tmpl)) { put_text_array(t, a_header); if(t->style) { (void)fputs(a_tag_style[0], t->fo); (void)fputs(t->style, t->fo); (void)fputs(a_tag_style[1], t->fo); (void)fputc('\n', t->fo); } if(t->tmpl) { if(!(t->title)) { put_text_array(t, a_template_title); } if(!(t->style)) { put_text_array(t, a_template_style); } put_text_array(t, a_template_all); } if(t->title) { (void)fputs(a_title[0], t->fo); put_one_text(t, t->title); (void)fputs(a_title[1], t->fo); (void)fputc('\n', t->fo); } put_text_array(t, a_middle); } /* convert text */ switch(t->enc) { case ENCODING_UTF_8: { run_utf(t); } break; default: { run_iso(t); } break; } /* write HTML code after text */ if((t->full) || (t->tmpl)) { put_text_array(t, a_footer); } dkapp_set_source_filename(t->a, NULL); dkapp_set_source_lineno(t->a, 0UL); } /** Run with output file name known. @param t Text2htm job. */ T2H_VOID(run_with_output_name) { t->fo = dkapp_fopen(t->a, t->o2, "w"); if(t->fo) { run_for_files(t); fclose(t->fo); t->fo = NULL; } else { dkapp_err_fopenw(t->a, t->o2); } } /** Run for specified input file. @param t Text2htm job. */ T2H_VOID(run_with_input_name) { dk_fne_t *fneo = NULL; t->fi = dkapp_fopen(t->a, t->i2, "r"); if(t->fi) { if(t->o1) { if(dksf_must_expand_filename(t->o1)) { fneo = dkfne_open(t->o1, 1, 0); if(fneo) { t->o2 = dkfne_get_one(fneo); if(t->o2) { run_with_output_name(t); t->o2 = NULL; } else { error_1(t, 19); } dkfne_close(fneo); fneo = NULL; } else { error_1(t, 18); } } else { t->o2 = t->o1; run_with_output_name(t); t->o2 = NULL; } } else { t->o2 = str_stdout; t->fo = stdout; run_for_files(t); t->o2 = NULL; t->fo = NULL; } fclose(t->fi); t->fi = NULL; } else { dkapp_err_fopenr(t->a, t->i2); } } /** Do conversion. @param t Text2htm job. */ T2H_VOID(run_normally) { dk_fne_t *fnei = NULL; t->i2 = t->o2 = NULL; t->fi = t->fo = NULL; if(t->i1) { if(dksf_must_expand_filename(t->i1)) { fnei = dkfne_open(t->i1, 1, 0); if(fnei) { t->i2 = dkfne_get_one(fnei); if(t->i2) { run_with_input_name(t); t->i2 = NULL; } else { error_1(t, 17); } dkfne_close(fnei); fnei = NULL; } else { error_1(t, 16); } } else { t->i2 = t->i1; run_with_input_name(t); t->i2 = NULL; } } else { t->i2 = str_stdin; t->o2 = str_stdout; t->fi = stdin; t->fo = stdout; run_for_files(t); t->i2 = t->o2 = NULL; t->fi = t->fo = NULL; } } /** Show message. @param t Text2htm job. @param n Index of message text in t->msg array. */ static void msg DK_P2(T2H *,t, size_t, n) { (void)fputs((t->msg)[n], stdout); } /** Find maximum length of multiple strings. @param t Text2htm job. @param s One string to analyze. @param m Maximum found in previously analyzed strings. @return Maximum of length of \a s and \a m. */ static size_t max_strlen DK_P3(T2H *,t, char *,s, size_t,m) { size_t back = 0; back = dkapp_prlen(t->a, s); if(m > back) { back = m; } return back; } /** Put text into available room. @param t Text2htm job. @param s Text to show. @param m Available space for text. */ static void put_formatted DK_P3(T2H *,t, char *,s, size_t,m) { size_t sz; sz = dkapp_prlen(t->a, s); if(sz < m) { while(sz++ < m) { (void)fputc(' ', stdout); } } dkapp_stdout(t->a, s); } /** Show current configuration on screen. @param t Text2htm job. */ T2H_VOID(show_configuration) { size_t sz, sz_max, i; sz_max = 0; for(sz = 4; sz < 10; sz++) { sz_max = max_strlen(t, (t->msg)[sz], sz_max); } msg(t, 0); (void)fputc('\n', stdout); sz = strlen((t->msg)[0]); for(i = 0; i < sz; i++) { (void)fputc('-', stdout); } (void)fputc('\n', stdout); dkapp_stdout(t->a, str_minus_e); if(t->enca) { dkapp_stdout(t->a, str_enc[0]); } else { switch(t->enc) { case ENCODING_UTF_8: { dkapp_stdout(t->a, str_enc[2]); } break; default: { dkapp_stdout(t->a, str_enc[1]); } break; } } (void)fputc('\n', stdout); dkapp_stdout(t->a, str_sp8); put_formatted(t, (t->msg)[4], sz_max); (void)fputc(' ', stdout); if(t->enca) { dkapp_stdout(t->a, (t->msg)[13]); } else { switch(t->enc) { case ENCODING_UTF_8: { dkapp_stdout(t->a, (t->msg)[15]); } break; default: { dkapp_stdout(t->a, (t->msg)[14]); } break; } } (void)fputc('\n', stdout); dkapp_stdout(t->a, str_minus_t); if(t->title) { dkapp_stdout(t->a, t->title); } else { dkapp_stdout(t->a, str_none); } (void)fputc('\n', stdout); dkapp_stdout(t->a, str_sp8); put_formatted(t, (t->msg)[5], sz_max); (void)fputc('\n', stdout); dkapp_stdout(t->a, str_minus_s); if(t->style) { dkapp_stdout(t->a, t->style); } else { dkapp_stdout(t->a, str_none); } (void)fputc('\n', stdout); dkapp_stdout(t->a, str_sp8); put_formatted(t, (t->msg)[6], sz_max); (void)fputc('\n', stdout); dkapp_stdout(t->a, str_minus_f); (void)fputc((t->full ? ' ' : '-'), stdout); (void)fputc('\n', stdout); dkapp_stdout(t->a, str_sp8); put_formatted(t, (t->msg)[7], sz_max); (void)fputc(' ', stdout); dkapp_stdout(t->a, (t->msg)[t->full ? 10 : 11]); (void)fputc('\n', stdout); dkapp_stdout(t->a, str_minus_g); (void)fputc((t->tmpl ? ' ' : '-'), stdout); (void)fputc('\n', stdout); dkapp_stdout(t->a, str_sp8); put_formatted(t, (t->msg)[8], sz_max); (void)fputc(' ', stdout); dkapp_stdout(t->a, (t->msg)[t->tmpl ? 10 : 11]); (void)fputc('\n', stdout); dkapp_stdout(t->a, str_minus_b); (void)fputc((t->kplb ? ' ' : '-'), stdout); (void)fputc('\n', stdout); dkapp_stdout(t->a, str_sp8); put_formatted(t, (t->msg)[9], sz_max); (void)fputc(' ', stdout); dkapp_stdout(t->a, (t->msg)[t->kplb ? 10 : 11]); (void)fputc('\n', stdout); } /** Save current configuration to preferences. @param t Text2htm job. */ T2H_VOID(save_configuration) { dkapp_set_pref(t->a, pk_style, ((t->style) ? t->style : str_none)); dkapp_set_pref(t->a, pk_title, ((t->title) ? t->title : str_none)); dkapp_set_pref(t->a, pk_full, ((t->full) ? str_on : str_off)); dkapp_set_pref(t->a, pk_tmpl, ((t->tmpl) ? str_on : str_off)); dkapp_set_pref(t->a, pk_keep, ((t->kplb) ? str_on : str_off)); } /** Show help text. @param t Text2htm job. */ T2H_VOID(show_help) { dkapp_help(t->a, "text2htm.txt", help_text); } /** Show version number. @param t Text2htm job. */ T2H_VOID(show_version) { char **ptr; ptr = version_text; while(*ptr) { (void)fputs(*(ptr++), stdout); (void)fputc('\n', stdout); } ptr = license_text; while(*ptr) { (void)fputs(*(ptr++), stdout); (void)fputc('\n', stdout); } } /** Run for applications options (help/version/configure/unconfigure/showconf). @param t Text2htm job. */ T2H_VOID(run_special) { if((t->cmd) & (CMD_HELP | CMD_VERSION)) { show_version(t); if((t->cmd) & CMD_HELP) { (void)fputc('\n', stdout); show_help(t); } } else { if((t->cmd) & CMD_UNCONFIGURE) { dkapp_unconfigure(t->a); } else { if((t->cmd) & CMD_CONFIGURE) { save_configuration(t); } show_configuration(t); } } } /** Run normally or print help/version. @param t Text2htm job. */ T2H_VOID(run) { init_from_preferences(t); if(!((t->cmd) & CMD_ABORT_ERROR)) { check_arguments(t); if(!((t->cmd) & CMD_ABORT_ERROR)) { if(t->cmd) { run_special(t); } else { run_normally(t); } } } } /** Input buffer. */ static char ibuffer[4096]; /** The main function of the text2htm program. @param argc Number of command line arguments. @param argv Command line arguments array. @return 0 on success, any other value indicates an error. */ #if DK_HAVE_PROTOTYPES int main(int argc, char *argv[]) #else int main(argc, argv) int argc; char *argv[]; #endif { int exval = 0; int rs = 0, rf = 0; T2H t2h; #line 1872 "text2htm.ctr" t2h_init(&t2h); silence_check(argc, argv, &rs, &rf); t2h.a = dkapp_open_ext1(argc, argv, group_name, sysconf_dir, rs, rf); t2h.ib = ibuffer; t2h.sz_ib = sizeof(ibuffer); if(t2h.a) { t2h.msg = dkapp_find_key_value(t2h.a, kv, szkv, table_name); if(t2h.msg) { run(&t2h); dk_delete(t2h.msg); t2h.msg = NULL; if(t2h.style) { dk_delete(t2h.style); t2h.style = NULL; } if(t2h.title) { dk_delete(t2h.title); t2h.title = NULL; } } else { error_1(&t2h, 0); } dkapp_close(t2h.a); t2h.a = NULL; } else { if(!rs) { fprintf(stderr, "text2htm: ERROR: Not enough memory (RAM/swap)!\n"); (void)fflush(stderr); } } exval = (exval ? 0 : 1); #line 1898 "text2htm.ctr" exit(exval); return exval; } /* vim: set ai sw=2 foldmethod=marker foldopen=all : */