Commit 2675512cde3a67c8ad8c4da347921f8013006983

Authored by Perry Werneck
1 parent 43a6be91

Incluindo gerador de fallbacks.

Showing 1 changed file with 662 additions and 0 deletions   Show diff stats
src/mkfb/mkfb.c 0 → 100644
@@ -0,0 +1,662 @@ @@ -0,0 +1,662 @@
  1 +/*
  2 + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270
  3 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a
  4 + * aplicativos mainframe. Registro no INPI sob o nome G3270. Registro no INPI sob o nome G3270.
  5 + *
  6 + * Copyright (C) <2008> <Banco do Brasil S.A.>
  7 + *
  8 + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob
  9 + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela
  10 + * Free Software Foundation.
  11 + *
  12 + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER
  13 + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO
  14 + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para
  15 + * obter mais detalhes.
  16 + *
  17 + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este
  18 + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin
  19 + * St, Fifth Floor, Boston, MA 02110-1301 USA
  20 + *
  21 + * Este programa está nomeado como mkfb.c e possui - linhas de código.
  22 + *
  23 + * Contatos:
  24 + *
  25 + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck)
  26 + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça)
  27 + *
  28 + */
  29 +
  30 +/*
  31 + * mkfb.c
  32 + * Utility to create RDB string definitions from a simple #ifdef'd .ad
  33 + * file
  34 + */
  35 +
  36 +#include "../include/config.h"
  37 +
  38 +
  39 +#if defined( WIN32 )
  40 + #include <windows.h>
  41 + #define tmpfile w32_tmpfile
  42 +#elif defined( __APPLE__ )
  43 + #define tmpfile osx_tmpfile
  44 +#endif // OS
  45 +
  46 +#include <sys/stat.h>
  47 +#include <fcntl.h>
  48 +
  49 +#include <stdio.h>
  50 +#include <string.h>
  51 +#include <ctype.h>
  52 +#include <stdlib.h>
  53 +#include <errno.h>
  54 +
  55 +#define BUFSZ 1024 /* input line buffer size */
  56 +#define ARRSZ 8192 /* output array size */
  57 +#define SSSZ 10 /* maximum nested ifdef */
  58 +
  59 +unsigned aix[ARRSZ]; /* fallback array indices */
  60 +unsigned xlno[ARRSZ]; /* fallback array line numbers */
  61 +unsigned n_fallbacks = 0; /* number of fallback entries */
  62 +
  63 +/* ifdef state stack */
  64 +#define MODE_COLOR 0x00000001
  65 +#define MODE_FT 0x00000002
  66 +#define MODE_TRACE 0x00000004
  67 +#define MODE_MENUS 0x00000008
  68 +#define MODE_ANSI 0x00000010
  69 +#define MODE_KEYPAD 0x00000020
  70 +#define MODE_APL 0x00000040
  71 +#define MODE_PRINTER 0x00000080
  72 +#define MODE_STANDALONE 0x00000100
  73 +#define MODE_SCRIPT 0x00000200
  74 +#define MODE_DBCS 0x00000400
  75 +#define MODE__WIN32 0x00000800
  76 +
  77 +#define MODEMASK 0x00000fff
  78 +
  79 +struct {
  80 + unsigned long ifdefs;
  81 + unsigned long ifndefs;
  82 + unsigned lno;
  83 +} ss[SSSZ];
  84 +int ssp = 0;
  85 +
  86 +struct {
  87 + const char *name;
  88 + unsigned long mask;
  89 +} parts[] = {
  90 + { "COLOR", MODE_COLOR },
  91 + { "X3270_FT", MODE_FT },
  92 + { "X3270_TRACE", MODE_TRACE },
  93 + { "X3270_MENUS", MODE_MENUS },
  94 + { "X3270_ANSI", MODE_ANSI },
  95 + { "X3270_KEYPAD", MODE_KEYPAD },
  96 + { "X3270_APL", MODE_APL },
  97 + { "X3270_PRINTER", MODE_PRINTER },
  98 + { "STANDALONE", MODE_STANDALONE },
  99 + { "X3270_SCRIPT", MODE_SCRIPT },
  100 + { "X3270_DBCS", MODE_DBCS },
  101 + { "_WIN32", MODE__WIN32 }
  102 +};
  103 +#define NPARTS (sizeof(parts)/sizeof(parts[0]))
  104 +
  105 +unsigned long is_defined =
  106 + MODE_COLOR |
  107 +#if defined(X3270_FT)
  108 + MODE_FT
  109 +#else
  110 + 0
  111 +#endif
  112 +|
  113 +#if defined(X3270_TRACE)
  114 + MODE_TRACE
  115 +#else
  116 + 0
  117 +#endif
  118 +|
  119 +#if defined(X3270_MENUS)
  120 + MODE_MENUS
  121 +#else
  122 + 0
  123 +#endif
  124 +|
  125 +#if defined(X3270_ANSI)
  126 + MODE_ANSI
  127 +#else
  128 + 0
  129 +#endif
  130 +|
  131 +#if defined(X3270_KEYPAD)
  132 + MODE_KEYPAD
  133 +#else
  134 + 0
  135 +#endif
  136 +|
  137 +#if defined(X3270_APL)
  138 + MODE_APL
  139 +#else
  140 + 0
  141 +#endif
  142 +|
  143 +#if defined(X3270_PRINTER)
  144 + MODE_PRINTER
  145 +#else
  146 + 0
  147 +#endif
  148 +|
  149 +#if defined(X3270_SCRIPT)
  150 + MODE_SCRIPT
  151 +#else
  152 + 0
  153 +#endif
  154 +|
  155 +#if defined(X3270_DBCS)
  156 + MODE_DBCS
  157 +#else
  158 + 0
  159 +#endif
  160 +|
  161 +#if defined(_WIN32)
  162 + MODE__WIN32
  163 +#else
  164 + 0
  165 +#endif
  166 + ;
  167 +unsigned long is_undefined;
  168 +
  169 +char *me;
  170 +
  171 +void emit(FILE *t, int ix, char c);
  172 +
  173 +void
  174 +usage(void)
  175 +{
  176 + fprintf(stderr, "usage: %s [infile [outfile]]\n", me);
  177 + exit(1);
  178 +}
  179 +
  180 +int
  181 +main(int argc, char *argv[])
  182 +{
  183 + char buf[BUFSZ];
  184 + int lno = 0;
  185 + int cc = 0;
  186 + int i;
  187 + int continued = 0;
  188 + const char *filename = "standard input";
  189 + FILE *u, *t, *tc = NULL, *tm = NULL, *o;
  190 + int cmode = 0;
  191 + unsigned long ifdefs;
  192 + unsigned long ifndefs;
  193 + int last_continue = 0;
  194 +
  195 + /* Parse arguments. */
  196 + if ((me = strrchr(argv[0], '/')) != (char *)NULL)
  197 + me++;
  198 + else
  199 + me = argv[0];
  200 + if (argc > 1 && !strcmp(argv[1], "-c")) {
  201 + cmode = 1;
  202 + is_defined |= MODE_STANDALONE;
  203 + argc--;
  204 + argv++;
  205 + }
  206 + switch (argc) {
  207 + case 1:
  208 + break;
  209 + case 2:
  210 + case 3:
  211 + if (strcmp(argv[1], "-")) {
  212 + if (freopen(argv[1], "r", stdin) == (FILE *)NULL) {
  213 + perror(argv[1]);
  214 + exit(1);
  215 + }
  216 + filename = argv[1];
  217 + }
  218 + break;
  219 + default:
  220 + usage();
  221 + }
  222 +
  223 + is_undefined = MODE_COLOR | (~is_defined & MODEMASK);
  224 +
  225 + /* Do #ifdef, comment and whitespace processing first. */
  226 + u = tmpfile();
  227 + if (u == NULL) {
  228 + perror("tmpfile");
  229 + exit(1);
  230 + }
  231 +
  232 + while (fgets(buf, BUFSZ, stdin) != (char *)NULL) {
  233 + char *s = buf;
  234 + int sl;
  235 + int i;
  236 +
  237 + lno++;
  238 +
  239 + /* Skip leading white space. */
  240 + while (isspace(*s))
  241 + s++;
  242 + if (cmode &&
  243 + (!strncmp(s, "x3270.", 6) || !strncmp(s, "x3270*", 6))) {
  244 + s += 6;
  245 + }
  246 +
  247 + /* Remove trailing white space. */
  248 + while ((sl = strlen(s)) && isspace(s[sl-1]))
  249 + s[sl-1] = '\0';
  250 +
  251 + /* Skip comments and empty lines. */
  252 + if ((!last_continue && *s == '!') || !*s)
  253 + continue;
  254 +
  255 + /* Check for simple if[n]defs. */
  256 + if (*s == '#') {
  257 + int ifnd = 1;
  258 +
  259 + if (!strncmp(s, "#ifdef ", 7) ||
  260 + !(ifnd = strncmp(s, "#ifndef ", 8))) {
  261 + char *tk;
  262 +
  263 + if (ssp >= SSSZ) {
  264 + fprintf(stderr,
  265 + "%s, line %d: Stack overflow\n",
  266 + filename, lno);
  267 + exit(1);
  268 + }
  269 + ss[ssp].ifdefs = 0L;
  270 + ss[ssp].ifndefs = 0L;
  271 + ss[ssp].lno = lno;
  272 +
  273 + tk = s + 7 + !ifnd;
  274 + for (i = 0; i < NPARTS; i++) {
  275 + if (!strcmp(tk, parts[i].name)) {
  276 + if (!ifnd)
  277 + ss[ssp++].ifndefs =
  278 + parts[i].mask;
  279 + else
  280 + ss[ssp++].ifdefs =
  281 + parts[i].mask;
  282 + break;
  283 + }
  284 + }
  285 + if (i >= NPARTS) {
  286 + fprintf(stderr,
  287 + "%s, line %d: Unknown condition\n",
  288 + filename, lno);
  289 + exit(1);
  290 + }
  291 + continue;
  292 + }
  293 +
  294 + else if (!strcmp(s, "#else")) {
  295 + unsigned long tmp;
  296 +
  297 + if (!ssp) {
  298 + fprintf(stderr,
  299 + "%s, line %d: Missing #if[n]def\n",
  300 + filename, lno);
  301 + exit(1);
  302 + }
  303 + tmp = ss[ssp-1].ifdefs;
  304 + ss[ssp-1].ifdefs = ss[ssp-1].ifndefs;
  305 + ss[ssp-1].ifndefs = tmp;
  306 + } else if (!strcmp(s, "#endif")) {
  307 + if (!ssp) {
  308 + fprintf(stderr,
  309 + "%s, line %d: Missing #if[n]def\n",
  310 + filename, lno);
  311 + exit(1);
  312 + }
  313 + ssp--;
  314 + } else {
  315 + fprintf(stderr,
  316 + "%s, line %d: Unrecognized # directive\n",
  317 + filename, lno);
  318 + exit(1);
  319 + }
  320 + continue;
  321 + }
  322 +
  323 + /* Figure out if there's anything to emit. */
  324 +
  325 + /* First, look for contradictions. */
  326 + ifdefs = 0;
  327 + ifndefs = 0;
  328 + for (i = 0; i < ssp; i++) {
  329 + ifdefs |= ss[i].ifdefs;
  330 + ifndefs |= ss[i].ifndefs;
  331 + }
  332 + if (ifdefs & ifndefs) {
  333 +#ifdef DEBUG_IFDEFS
  334 + fprintf(stderr, "contradiction, line %d\n", lno);
  335 +#endif
  336 + continue;
  337 + }
  338 +
  339 + /* Then, apply the actual values. */
  340 + if (ifdefs && (ifdefs & is_defined) != ifdefs) {
  341 +#ifdef DEBUG_IFDEFS
  342 + fprintf(stderr, "ifdef failed, line %d\n", lno);
  343 +#endif
  344 + continue;
  345 + }
  346 + if (ifndefs && (ifndefs & is_undefined) != ifndefs) {
  347 +#ifdef DEBUG_IFDEFS
  348 + fprintf(stderr, "ifndef failed, line %d\n", lno);
  349 +#endif
  350 + continue;
  351 + }
  352 +
  353 + /* Emit the text. */
  354 + fprintf(u, "%lx %lx %d\n%s\n", ifdefs, ifndefs, lno, s);
  355 + last_continue = strlen(s) > 0 && s[strlen(s) - 1] == '\\';
  356 + }
  357 + if (ssp) {
  358 + fprintf(stderr, "%d missing #endif(s) in %s\n", ssp, filename);
  359 + fprintf(stderr, "last #ifdef was at line %u\n", ss[ssp-1].lno);
  360 + exit(1);
  361 + }
  362 +
  363 + /* Re-scan, emitting code this time. */
  364 + rewind(u);
  365 + t = tmpfile();
  366 + if (t == NULL) {
  367 + perror("tmpfile");
  368 + exit(1);
  369 + }
  370 + if (!cmode) {
  371 + tc = tmpfile();
  372 + if (tc == NULL) {
  373 + perror("tmpfile");
  374 + exit(1);
  375 + }
  376 + tm = tmpfile();
  377 + if (tm == NULL) {
  378 + perror("tmpfile");
  379 + exit(1);
  380 + }
  381 + }
  382 +
  383 + /* Emit the initial boilerplate. */
  384 + fprintf(t, "/* This file was created automatically from %s by mkfb. */\n\n",
  385 + filename);
  386 + if (cmode) {
  387 + fprintf(t, "#include \"../../src/lib3270/private.h\"\n");
  388 + fprintf(t, "static unsigned char fsd[] = {\n");
  389 + } else {
  390 + fprintf(t, "unsigned char common_fallbacks[] = {\n");
  391 + fprintf(tc, "unsigned char color_fallbacks[] = {\n");
  392 + fprintf(tm, "unsigned char mono_fallbacks[] = {\n");
  393 + }
  394 +
  395 + /* Scan the file, emitting the fsd array and creating the indices. */
  396 + while (fscanf(u, "%lx %lx %d\n", &ifdefs, &ifndefs, &lno) == 3) {
  397 + char *s = buf;
  398 + char c;
  399 + int white;
  400 + FILE *t_this = t;
  401 + int ix = 0;
  402 +
  403 + if (fgets(buf, BUFSZ, u) == NULL)
  404 + break;
  405 + if (strlen(buf) > 0 && buf[strlen(buf)-1] == '\n')
  406 + buf[strlen(buf)-1] = '\0';
  407 +
  408 +#if 0
  409 + fprintf(stderr, "%lx %lx %d %s\n", ifdefs, ifndefs, lno, buf);
  410 +#endif
  411 +
  412 + /* Add array offsets. */
  413 + if (cmode) {
  414 + /* Ignore color. Accumulate offsets into an array. */
  415 + if (n_fallbacks >= ARRSZ) {
  416 + fprintf(stderr, "%s, line %d: Buffer overflow\n", filename, lno);
  417 + exit(1);
  418 + }
  419 + aix[n_fallbacks] = cc;
  420 + xlno[n_fallbacks++] = lno;
  421 + } else {
  422 + /* Use color to decide which file to write into. */
  423 + if (!(ifdefs & MODE_COLOR) && !(ifndefs & MODE_COLOR)) {
  424 + /* Both. */
  425 + t_this = t;
  426 + ix = 0;
  427 + } else if (ifdefs & MODE_COLOR) {
  428 + /* Just color. */
  429 + t_this = tc;
  430 + ix = 1;
  431 + } else {
  432 + /* Just mono. */
  433 + t_this = tm;
  434 + ix = 2;
  435 + }
  436 + }
  437 +
  438 + continued = 0;
  439 + white = 0;
  440 + while ((c = *s++) != '\0') {
  441 + if (c == ' ' || c == '\t')
  442 + white++;
  443 + else if (white) {
  444 + emit(t_this, ix, ' ');
  445 + cc++;
  446 + white = 0;
  447 + }
  448 + switch (c) {
  449 + case ' ':
  450 + case '\t':
  451 + break;
  452 + case '#':
  453 + if (!cmode) {
  454 + emit(t_this, ix, '\\');
  455 + emit(t_this, ix, '#');
  456 + cc += 2;
  457 + } else {
  458 + emit(t_this, ix, c);
  459 + cc++;
  460 + }
  461 + break;
  462 + case '\\':
  463 + if (*s == '\0') {
  464 + continued = 1;
  465 + break;
  466 + } else if (cmode) {
  467 + switch ((c = *s++)) {
  468 + case 't':
  469 + c = '\t';
  470 + break;
  471 + case 'n':
  472 + c = '\n';
  473 + break;
  474 + default:
  475 + break;
  476 + }
  477 + }
  478 + /* else fall through */
  479 + default:
  480 + emit(t_this, ix, c);
  481 + cc++;
  482 + break;
  483 + }
  484 + }
  485 + if (white) {
  486 + emit(t_this, ix, ' ');
  487 + cc++;
  488 + white = 0;
  489 + }
  490 + if (!continued) {
  491 + if (cmode)
  492 + emit(t_this, ix, 0);
  493 + else
  494 + emit(t_this, ix, '\n');
  495 + cc++;
  496 + }
  497 + }
  498 + fclose(u);
  499 + if (cmode)
  500 + fprintf(t, "};\n\n");
  501 + else {
  502 + emit(t, 0, 0);
  503 + fprintf(t, "};\n\n");
  504 + emit(tc, 0, 0);
  505 + fprintf(tc, "};\n\n");
  506 + emit(tm, 0, 0);
  507 + fprintf(tm, "};\n\n");
  508 + }
  509 +
  510 +
  511 + /* Open the output file. */
  512 + if (argc == 3) {
  513 + o = fopen(argv[2], "w");
  514 + if (o == NULL) {
  515 + perror(argv[2]);
  516 + exit(1);
  517 + }
  518 + } else
  519 + o = stdout;
  520 +
  521 + /* Copy tmp to output. */
  522 + rewind(t);
  523 + if (!cmode) {
  524 + rewind(tc);
  525 + rewind(tm);
  526 + }
  527 + while (fgets(buf, sizeof(buf), t) != NULL) {
  528 + fprintf(o, "%s", buf);
  529 + }
  530 + if (!cmode) {
  531 + while (fgets(buf, sizeof(buf), tc) != NULL) {
  532 + fprintf(o, "%s", buf);
  533 + }
  534 + while (fgets(buf, sizeof(buf), tm) != NULL) {
  535 + fprintf(o, "%s", buf);
  536 + }
  537 + }
  538 +
  539 + if (cmode) {
  540 + /* Emit the fallback array. */
  541 + fprintf(o, "String fallbacks[%u] = {\n", n_fallbacks + 1);
  542 + for (i = 0; i < n_fallbacks; i++) {
  543 + fprintf(o, "\t(String)&fsd[%u], /* line %u */\n",
  544 + aix[i],
  545 + xlno[i]);
  546 + }
  547 + fprintf(o, "\t(String)NULL\n};\n\n");
  548 +
  549 + /* Emit some test code. */
  550 + fprintf(o, "%s", "#if defined(DUMP) /*[*/\n\
  551 +#include <stdio.h>\n\
  552 +int\n\
  553 +main(int argc, char *argv[])\n\
  554 +{\n\
  555 + int i;\n\
  556 +\n\
  557 + for (i = 0; fallbacks[i] != NULL; i++)\n\
  558 + printf(\"%d: %s\\n\", i, fallbacks[i]);\n\
  559 + return 0;\n\
  560 +}\n");
  561 + fprintf(o, "#endif /*]*/\n\n");
  562 + }
  563 +
  564 + if (o != stdout)
  565 + fclose(o);
  566 + fclose(t);
  567 + if (!cmode) {
  568 + fclose(tc);
  569 + fclose(tm);
  570 + }
  571 +
  572 + return 0;
  573 +}
  574 +
  575 +static int n_out[3] = { 0, 0, 0 };
  576 +
  577 +void
  578 +emit(FILE *t, int ix, char c)
  579 +{
  580 + if (n_out[ix] >= 19) {
  581 + fprintf(t, "\n");
  582 + n_out[ix] = 0;
  583 + }
  584 + fprintf(t, "%3d,", (unsigned char)c);
  585 + n_out[ix]++;
  586 +}
  587 +
  588 +#if defined(_WIN32)
  589 +FILE * w32_tmpfile( void )
  590 +{
  591 + char *dir;
  592 + char *xtemplate;
  593 + DWORD retval;
  594 + size_t len;
  595 + int fd;
  596 + FILE *file = NULL;
  597 +
  598 + dir = (char *) malloc(PATH_MAX);
  599 + xtemplate = (char *) malloc(PATH_MAX);
  600 +
  601 + /* Find Windows temporary file directory.
  602 + We provide this as the directory argument to path_search
  603 + because Windows defines P_tmpdir to "\\" and will therefore
  604 + try to put all temporary files in the root (unless $TMPDIR
  605 + is set). */
  606 + retval = GetTempPath (PATH_MAX, dir);
  607 + if (retval == 0 || retval >= PATH_MAX - 1)
  608 + goto done;
  609 +
  610 + do
  611 + {
  612 + char *tempname = tempnam(dir,"XXXXXX");
  613 + if(!tempname)
  614 + goto done;
  615 +
  616 + fd = _open (tempname,_O_BINARY | _O_CREAT | _O_TEMPORARY | _O_EXCL | _O_RDWR,_S_IREAD | _S_IWRITE);
  617 + }
  618 + while (fd < 0 && errno == EEXIST);
  619 +
  620 + if (fd < 0)
  621 + goto done;
  622 +
  623 + file = _fdopen (fd, "w+b");
  624 + if (file == NULL)
  625 + {
  626 + int save_errno = errno;
  627 + _close (fd);
  628 + errno = save_errno;
  629 + }
  630 +
  631 + done:
  632 + free(xtemplate);
  633 + free(dir);
  634 + return file;
  635 +}
  636 +#elif defined( __APPLE__ )
  637 +FILE * osx_tmpfile( void )
  638 +{
  639 + int fd = -1;
  640 + FILE *file = NULL;
  641 +
  642 + do
  643 + {
  644 + char *tempname = tempnam(NULL,"XXXXXX");
  645 + if(!tempname)
  646 + return NULL;
  647 + fd = open (tempname,O_CREAT | O_EXCL | O_RDWR,S_IREAD | S_IWRITE);
  648 + } while (fd < 0 && errno == EEXIST);
  649 +
  650 +
  651 + file = fdopen (fd, "w+b");
  652 + if (file == NULL)
  653 + {
  654 + int save_errno = errno;
  655 + close (fd);
  656 + errno = save_errno;
  657 + }
  658 +
  659 + return file;
  660 +}
  661 +
  662 +#endif // _WIN32