/* * File: boxes.c * Date created: March 18, 1999 (Thursday, 15:09h) * Author: Thomas Jensen * tsjensen@stud.informatik.uni-erlangen.de * Version: $Id: boxes.c,v 1.20 1999/06/23 19:17:27 tsjensen Exp tsjensen $ * Language: ANSI C * Platforms: sunos5/sparc, for now * World Wide Web: http://home.pages.de/~jensen/boxes/ * Purpose: Filter to draw boxes around input text (and remove it). * Intended for use with vim(1). * * Remarks: - This version is leaking a small bit of memory. The sizes * of the leaks do not depend on the number of lines * processed, so the leaks don't matter as long as this * program is executed as a single process. * - The decision to number box shapes in clockwise order was * a major design mistake. Treatment of box parts of the * same alignment (N-S and E-W) is usually combined in one * function, which must now deal with the numbering being * reversed all the time. This is nasty, but changing the * shape order would pretty much mean a total rewrite of * the code, so we'll have to live with it. :-( * - All shapes defined in a box design must be used in any * box of that design at least once. In other words, there * must not be a shape which is defined in the config file * but cannot be found in an actual box of that design. * This sort of limits how small your boxes can get. * However, in practice it is not a problem, because boxes * which must be small usually consist of small shapes * which can be packed pretty tightly anyway. And again, * changing this would pretty much mean a total rewrite. * * Revision History: * * $Log: boxes.c,v $ * Revision 1.20 1999/06/23 19:17:27 tsjensen * Removed snprintf() and vsnprintf() prototypes (why were they in anyway?) * along with stdarg.h include * Exported input global data and empty_side() function * Declared non-exported functions static * Moved horiz_precalc(), vert_precalc(), horiz_assemble(), vert_assemble(), * horiz_generate(), vert_generate(), generate_box() and output_box() to a * new file generate.c * Moved best_match(), hmm(), detect_horiz(), detect_design(), remove_box() * and output_input() to a new file remove.c * * Revision 1.19 1999/06/23 12:31:26 tsjensen * Improvements on design detection (could still be better though) * Moved iscorner(), on_side(), isempty(), shapecmp(), both_on_side(), * shape_distance(), empty_side(), highest(), and widest() as well as * some data structures and macros related to shapes to new file shape.c * * Revision 1.18 1999/06/22 12:03:33 tsjensen * DEBUGging is now activated in boxes.h * Moved MAX_TABSTOP, LINE_MAX macros and struct opt_t to boxes.h * Moved BMAX, strrstr(), btrim(), yyerror(), expand_tabs_into(), * regerror(), empty_line() to a new file tools.c, added #include tools.h * Some cleanup in main() * Declared style_sort() helper function static * Renamed strrstr() to my_strnrstr() (now defined in tools.c) * Default design is now defined by DEF_DESIGN macro * Changed select_design(), because default design value now set in process_commandline() * Bugfix: segfaulted if shape was bigger than input when detecting design * Bugfix: Padding was not removed when box was removed * Bugfix: Forgot null byte when removing west box side * * Revision 1.17 1999/06/20 14:20:29 tsjensen * Added code for padding handling (-p) * Added BMAX macro (returns maximum of two values) * * Revision 1.16 1999/06/17 19:07:06 tsjensen * Moved line_t to boxes.h * empty_line() now also considers \r and \n whitespace * Added empty_side() function * Added handling of empty box sides in output_box() * * Revision 1.15 1999/06/15 12:07:39 tsjensen * Removed a stray debug message * Move apply_substitutions() regexp handling function up in file * Use apply_substitutions() in read_input() routine also * Moved "extern int yyparse()" prototype to start of file * * Revision 1.14 1999/06/14 12:08:49 tsjensen * Bugfix: best_match() box side detection used numw instead of nume * Added apply_substitutions() routine for central regexp handling * Added regexp reversion code for box removal * Unified use of current_re[pv]rule * Added a few comments and debugging code * * Revision 1.13 1999/06/13 15:28:31 tsjensen * Some error message clean-up * Regular expression substitutions on input text only if *drawing* a box, * not if the box is to be removed (requires other substitutions, todo). * Added code for box design auto-detection when removing a box. * * Revision 1.12 1999/06/04 18:13:26 tsjensen * Don't adjust indentation after removing a box unless something was * removed on the west side * East Padding made dynamic, i.e. dependant on the east side size * * Revision 1.11 1999/06/03 19:24:14 tsjensen * A few fixes related to box removal (as expected) * * Revision 1.10 1999/06/03 18:54:05 tsjensen * Lots of fixes * Added remove box functionality (-r), which remains to be tested * * Revision 1.9 1999/04/09 13:33:24 tsjensen * Removed code related to OFFSET blocks (obsolete) * * Revision 1.8 1999/04/04 16:09:01 tsjensen * Added code for specification of indentation handling of input * Added regular expression substitutions * Some minor fixes * * Revision 1.7 1999/04/02 18:42:44 tsjensen * Added infile/outfile parameter code (pasted from tal, more or less) * Added code to remove trailing spaces from output lines * * Revision 1.6 1999/04/01 17:26:18 tsjensen * Some bug fixes * Added size option (-s) * Added Alignment Option (-a) * It seems actually usable for drawing boxes :-) * * Revision 1.4 1999/03/30 13:30:19 tsjensen * Added minimum width/height for a design. Fixed screwed tiny boxes. * Bugfix: Did not handle zero input. * * Revision 1.3 1999/03/30 09:36:23 tsjensen * ... still programming ... * (removed setlocale() call and locale.h include) * * Revision 1.1 1999/03/18 15:09:17 tsjensen * Initial revision * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include #include #include #include #include #include "shape.h" #include "boxes.h" #include "tools.h" #include "regexp.h" #include "generate.h" #include "remove.h" extern char *optarg; /* for getopt() */ extern int optind, opterr, optopt; /* for getopt() */ static const char rcsid_boxes_c[] = "$Id: boxes.c,v 1.20 1999/06/23 19:17:27 tsjensen Exp tsjensen $"; /* _\|/_ (o o) +----oOO-{_}-OOo------------------------------------------------------------+ | G l o b a l V a r i a b l e s | +--------------------------------------------------------------------------*/ extern int yyparse(); extern FILE *yyin; /* lex input file */ char *yyfilename = NULL; /* file name of config file used */ design_t *designs = NULL; /* available box designs */ int design_idx = 0; /* anz_designs-1 */ int anz_designs = 0; /* no of designs after parsing */ opt_t opt; /* command line options */ input_t input = INPUT_INITIALIZER; /* input lines */ /* _\|/_ (o o) +----oOO-{_}-OOo------------------------------------------------------------+ | F u n c t i o n s | +--------------------------------------------------------------------------*/ static void usage (FILE *st) /* * Print usage information on stream st. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { fprintf (st, "Usage: %s [options] [infile [outfile]]\n", PROJECT); fprintf (st, " -a fmt alignment/positioning of text inside box [default: hlvt]\n"); fprintf (st, " -d name select box design\n"); fprintf (st, " -f file use only file as configuration file\n"); fprintf (st, " -h print usage information\n"); fprintf (st, " -i mode indentation mode\n"); fprintf (st, " -l list available box designs w/ samples\n"); fprintf (st, " -p fmt padding [default: design-dependent]\n"); fprintf (st, " -r remove box from input\n"); fprintf (st, " -s wxh specify box size (width w and/or height h)\n"); fprintf (st, " -t uint set tab stop distance [default: %d]\n", DEF_TABSTOP); fprintf (st, " -v print version information\n"); } static int process_commandline (int argc, char *argv[]) /* * Process command line options. * * argc, argv command line as passed to main() * * RETURNS: == 0 success, continue * == 42 success, but terminate anyway (e.g. help/version) * != 0/42 error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { int oc; /* option character */ FILE *f; /* potential input file */ int idummy; char *pdummy; char c; int errfl = 0; /* true on error */ int outfile_existed = 0; /* true if we overwrite a file */ size_t optlen; /* * Set default values */ memset (&opt, 0, sizeof(opt)); opt.tabstop = DEF_TABSTOP; yyin = stdin; for (idummy=0; idummy\n"); printf (" Web page: http://home.pages.de/~jensen/%s/\n", PROJECT); usage (stdout); return 42; case 'i': /* * Indentation mode */ optlen = strlen (optarg); if (optlen <= 3 && !strncasecmp ("box", optarg, optlen)) opt.indentmode = 'b'; else if (optlen <= 4 && !strncasecmp ("text", optarg, optlen)) opt.indentmode = 't'; else if (optlen <= 4 && !strncasecmp ("none", optarg, optlen)) opt.indentmode = 'n'; else { fprintf (stderr, "%s: invalid indentation mode\n", PROJECT); return 1; } break; case 'l': /* * List available box styles */ opt.l = 1; break; case 'p': /* * Padding. format is ([ahvtrbl]n)+ */ errfl = 0; pdummy = optarg; while (*pdummy) { if (pdummy[1] == '\0') { errfl = 1; break; } c = *pdummy; errno = 0; idummy = (int) strtol (pdummy+1, &pdummy, 10); if (errno || idummy < 0) { errfl = 1; break; } switch (c) { case 'a': case 'A': opt.padding[BTOP] = idummy; opt.padding[BBOT] = idummy; opt.padding[BLEF] = idummy; opt.padding[BRIG] = idummy; break; case 'h': case 'H': opt.padding[BLEF] = idummy; opt.padding[BRIG] = idummy; break; case 'v': case 'V': opt.padding[BTOP] = idummy; opt.padding[BBOT] = idummy; break; case 't': case 'T': opt.padding[BTOP] = idummy; break; case 'l': case 'L': opt.padding[BLEF] = idummy; break; case 'b': case 'B': opt.padding[BBOT] = idummy; break; case 'r': case 'R': opt.padding[BRIG] = idummy; break; default: errfl = 1; break; } if (errfl) break; } if (errfl) { fprintf (stderr, "%s: invalid padding specification - " "%s\n", PROJECT, optarg); return 1; } break; case 'r': /* * Remove box from input */ opt.r = 1; break; case 's': /* * Specify desired box target size */ pdummy = strchr (optarg, 'x'); if (!pdummy) pdummy = strchr (optarg, 'X'); errno = 0; opt.reqwidth = strtol (optarg, NULL, 10); idummy = errno; if (idummy) { fprintf (stderr, "%s: invalid box size specification: %s\n", PROJECT, strerror(idummy)); return 1; } if (pdummy) { errno = 0; opt.reqheight = strtol (pdummy+1, NULL, 10); idummy = errno; if (idummy) { fprintf (stderr, "%s: invalid box size specification: %s\n", PROJECT, strerror(idummy)); return 1; } } if ((opt.reqwidth == 0 && opt.reqheight == 0) || opt.reqwidth < 0 || opt.reqheight < 0) { fprintf (stderr, "%s: invalid box size specification -- %s\n", PROJECT, optarg); return 1; } break; case 't': /* * Tab stop distance */ idummy = (int) strtol (optarg, NULL, 10); if (idummy < 1 || idummy > MAX_TABSTOP) { fprintf (stderr, "%s: invalid tab stop distance -- %d\n", PROJECT, idummy); return 1; } opt.tabstop = idummy; break; case 'v': /* * Print version number */ printf ("%s version %s\n", PROJECT, VERSION); return 42; case ':': case '?': /* * Missing argument or illegal option - do nothing else */ return 1; case EOF: /* * End of list, do nothing more */ break; default: /* This case must never be */ fprintf (stderr, "%s: Uh-oh! This should have been " "unreachable code. %%-)\n", PROJECT); return 1; } } while (oc != EOF); /* * If no config file has been specified, try getting it from other * locations. (1) contents of BOXES environment variable (2) file * ~/.boxes. If neither file exists, complain and die. */ if (yyin == stdin) { char *s = getenv ("BOXES"); if (s) { f = fopen (s, "r"); if (f == NULL) { fprintf (stderr, "%s: Couldn\'t open config file \'%s\' " "for input (taken from environment).\n", PROJECT, s); return 1; } yyfilename = (char *) strdup (s); yyin = f; } else { char buf[PATH_MAX]; /* to build file name */ s = getenv ("HOME"); if (s) { strncpy (buf, s, PATH_MAX); buf[PATH_MAX-1-7] = '\0'; /* ensure space for "/.boxes" */ strcat (buf, "/.boxes"); f = fopen (buf, "r"); if (f) { yyfilename = (char *) strdup (buf); yyin = f; } else { fprintf (stderr, "%s: Could not find config file.\n", PROJECT); return 1; } } else { fprintf (stderr, "%s: Environment variable HOME must point to " "the user\'s home directory.\n", PROJECT); return 1; } } } /* * Input and Output Files * * After any command line options, an input file and an output file may * be specified (in that order). "-" may be substituted for standard * input or output. A third file name would be invalid. * The alogrithm is as follows: * * If no files are given, use stdin and stdout. * Else If infile is "-", use stdin for input * Else open specified file (die if it doesn't work) * If no output file is given, use stdout for output * Else If outfile is "-", use stdout for output * Else open specified file for writing (die if it doesn't work) * If a third file is given, die. */ if (argv[optind] == NULL) { /* neither infile nor outfile given */ opt.infile = stdin; opt.outfile = stdout; } else { if (strcmp (argv[optind], "-") == 0) { opt.infile = stdin; /* use stdin for input */ } else { opt.infile = fopen (argv[optind], "r"); if (opt.infile == NULL) { fprintf (stderr, "%s: Can\'t open input file -- %s\n", PROJECT, argv[optind]); return 9; /* can't read infile */ } } if (argv[optind+1] == NULL) { opt.outfile = stdout; /* no outfile given */ } else { if (strcmp (argv[optind+1], "-") == 0) { opt.outfile = stdout; /* use stdout for output */ } else { outfile_existed = !access (argv[optind+1], F_OK); opt.outfile = fopen (argv[optind+1], "w"); if (opt.outfile == NULL) { perror (PROJECT); if (opt.infile != stdin) fclose (opt.infile); return 10; } } if (argv[optind+2]) { /* illegal third file */ fprintf (stderr, "%s: illegal parameter -- %s\n", PROJECT, argv[optind+2]); usage (stderr); if (opt.infile != stdin) fclose (opt.infile); if (opt.outfile != stdout) { fclose (opt.outfile); if (!outfile_existed) unlink (argv[optind+1]); } return 1; } } } #ifdef DEBUG fprintf (stderr, "Command line option settings (excerpt):\n"); fprintf (stderr, "- Padding: l%d o%d r%d u%d\n", opt.padding[BLEF], opt.padding[BTOP], opt.padding[BRIG], opt.padding[BBOT]); fprintf (stderr, "- Requested box size: %ldx%ld\n", opt.reqwidth, opt.reqheight); fprintf (stderr, "- Tabstop distance: %d\n", opt.tabstop); fprintf (stderr, "- Alignment: horiz %c, vert %c\n", opt.halign?opt.halign:'?', opt.valign?opt.valign:'?'); fprintf (stderr, "- Indentmode: \'%c\'\n", opt.indentmode? opt.indentmode: '?'); fprintf (stderr, "- Line justification: \'%c\'\n", opt.justify? opt.justify: '?'); #endif return 0; } static int style_sort (const void *p1, const void *p2) { return strcasecmp ((const char *) ((*((design_t **) p1))->name), (const char *) ((*((design_t **) p2))->name)); } static int list_styles() /* * Generate sorted listing of available box styles. * Uses design name from BOX spec and sample picture plus author. * * RETURNS: != 0 on error (out of memory) * == 0 on success * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { int i; design_t **list; /* temp list for sorting */ list = (design_t **) calloc (design_idx+1, sizeof(design_t *)); if (list == NULL) { perror (PROJECT); return 1; } for (i=0; i<=design_idx; ++i) list[i] = &(designs[i]); qsort (list, design_idx+1, sizeof(design_t *), style_sort); fprintf (opt.outfile, "Available Styles:\n"); fprintf (opt.outfile, "-----------------\n\n"); for (i=0; i<=design_idx; ++i) fprintf (opt.outfile, "%s (%s):\n\n%s\n\n", list[i]->name, list[i]->author? list[i]->author: "unknown artist", list[i]->sample); BFREE (list); return 0; } static int apply_substitutions (const int mode) /* * Apply regular expression substitutions to input text. * * mode == 0 use replacement rules (box is being *drawn*) * == 1 use reversion rules (box is being *removed*) * * Attn: This modifies the actual input array! * * RETURNS: == 0 success * != 0 error * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { size_t anz_rules; reprule_t *rules; size_t j, k; char buf[LINE_MAX*2]; size_t buf_len; /* length of string in buf */ if (opt.design == NULL) return 1; if (mode == 0) { anz_rules = opt.design->anz_reprules; rules = opt.design->reprules; } else if (mode == 1) { anz_rules = opt.design->anz_revrules; rules = opt.design->revrules; } else { fprintf (stderr, "%s: internal error\n", PROJECT); return 2; } /* * Compile regular expressions */ errno = 0; opt.design->current_rule = rules; for (j=0; jcurrent_rule)) { rules[j].prog = regcomp (rules[j].search); } opt.design->current_rule = NULL; if (errno) return 3; /* * Apply regular expression substitutions to input lines */ for (k=0; kcurrent_rule = rules; for (j=0; jcurrent_rule)) { #ifdef REGEXP_DEBUG fprintf (stderr, "myregsub (0x%p, \"%s\", %d, \"%s\", buf, %d, \'%c\') == ", rules[j].prog, input.lines[k].text, input.lines[k].len, rules[j].repstr, LINE_MAX*2, rules[j].mode); #endif errno = 0; buf_len = myregsub (rules[j].prog, input.lines[k].text, input.lines[k].len, rules[j].repstr, buf, LINE_MAX*2, rules[j].mode); #ifdef REGEXP_DEBUG fprintf (stderr, "%d\n", buf_len); #endif if (errno) return 1; BFREE (input.lines[k].text); input.lines[k].text = (char *) strdup (buf); if (input.lines[k].text == NULL) { perror (PROJECT); return 1; } input.lines[k].len = buf_len; if (input.lines[k].len > input.maxline) input.maxline = input.lines[k].len; #ifdef REGEXP_DEBUG fprintf (stderr, "input.lines[%d] == {%d, \"%s\"}\n", k, input.lines[k].len, input.lines[k].text); #endif } opt.design->current_rule = NULL; } return 0; } static int read_all_input() /* * Read entire input from stdin and store it in 'input' array. * * Tabs are expanded. * Might allocate slightly more memory than it needs. Trade-off for speed. * * RETURNS: != 0 on error (out of memory) * == 0 on success * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ { char buf[LINE_MAX+2]; /* input buffer */ size_t input_size = 0; /* number of elements allocated */ line_t *tmp = NULL; char *temp = NULL; /* string resulting from tab exp. */ size_t newlen; /* line length after tab expansion */ size_t i; input.anz_lines = 0; input.indent = LINE_MAX; input.maxline = 0; /* * Start reading */ while (fgets (buf, LINE_MAX+1, opt.infile)) { if (input_size % 100 == 0) { input_size += 100; tmp = (line_t *) realloc (input.lines, input_size*sizeof(line_t)); if (tmp == NULL) { perror (PROJECT); BFREE (input.lines); return 1; } input.lines = tmp; } input.lines[input.anz_lines].len = strlen (buf); if (opt.r) { input.lines[input.anz_lines].len -= 1; if (buf[input.lines[input.anz_lines].len] == '\n') buf[input.lines[input.anz_lines].len] = '\0'; } else { btrim (buf, &(input.lines[input.anz_lines].len)); } if (input.lines[input.anz_lines].len > 0) { newlen = expand_tabs_into (buf, input.lines[input.anz_lines].len, opt.tabstop, &temp); if (newlen == 0) { perror (PROJECT); BFREE (input.lines); return 1; } input.lines[input.anz_lines].text = temp; input.lines[input.anz_lines].len = newlen; temp = NULL; } else { input.lines[input.anz_lines].text = (char *) strdup (buf); } /* * Update length of longest line */ if (input.lines[input.anz_lines].len > input.maxline) input.maxline = input.lines[input.anz_lines].len; /* * Update current estimate for text indentation */ if (input.lines[input.anz_lines].len > 0) { size_t ispc; ispc = strspn (input.lines[input.anz_lines].text, " "); if (ispc < input.indent) input.indent = ispc; } /* * next please */ ++input.anz_lines; } if (ferror (stdin)) { perror (PROJECT); BFREE (input.lines); return 1; } /* * Exit if there was no input at all */ if (input.lines == NULL || input.lines[0].text == NULL) { return 0; } /* * Apply regular expression substitutions */ if (opt.r == 0) { if (apply_substitutions(0) != 0) return 1; } /* * Remove indentation, unless we want to preserve it (when removing * a box or if the user wants to retain it inside the box) */ if (input.indent < LINE_MAX) { if (opt.design->indentmode != 't' && opt.r == 0) { for (i=0; i= input.indent) { memmove (input.lines[i].text, input.lines[i].text+input.indent, input.lines[i].len-input.indent+1); input.lines[i].len -= input.indent; } } input.maxline -= input.indent; } } else { input.indent = 0; /* seems like blank lines only */ } #if 0 /* * Debugging Code: Display contents of input structure */ for (i=0; iindentmode = DEF_INDENTMODE; /* * If the following parser is one created by lex, the application must * be careful to ensure that LC_CTYPE and LC_COLLATE are set to the * POSIX locale. [pasted from man page --TJ] */ #ifdef DEBUG fprintf (stderr, "Parsing Config File ...\n"); #endif rc = yyparse(); if (rc) exit (EXIT_FAILURE); --design_idx; tmp = (design_t *) realloc (designs, (design_idx+1)*sizeof(design_t)); if (tmp) { designs = tmp; /* yyparse() allocates space */ } /* for one design too much */ else { perror (PROJECT); exit (EXIT_FAILURE); } anz_designs = design_idx + 1; #ifdef DEBUG fprintf (stderr, "Selecting Design ...\n"); #endif tmp = select_design (designs, (char *) opt.design); if (tmp == NULL) exit (EXIT_FAILURE); BFREE (opt.design); opt.design = tmp; /* * If "-l" option was given, list styles and exit. */ if (opt.l) { rc = list_styles(); exit (rc); } /* * Adjust box size and indentmode to command line specification */ if (opt.reqheight > (long) opt.design->minheight) opt.design->minheight = opt.reqheight; if (opt.reqwidth > (long) opt.design->minwidth) opt.design->minwidth = opt.reqwidth; if (opt.indentmode) opt.design->indentmode = opt.indentmode; /* * Read input lines */ #ifdef DEBUG fprintf (stderr, "Reading all input ...\n"); #endif rc = read_all_input(); if (rc) exit (EXIT_FAILURE); if (input.anz_lines == 0) exit (EXIT_SUCCESS); /* * Adjust box size to fit requested padding value * Command line-specified box size takes precedence over padding. */ for (i=0; i -1) opt.design->padding[i] = opt.padding[i]; } pad = opt.design->padding[BTOP] + opt.design->padding[BBOT]; if (pad > 0) { pad += input.anz_lines; pad += opt.design->shape[NW].height + opt.design->shape[SW].height; if (pad > opt.design->minheight) { if (opt.reqheight) { for (i=0; i<(int)(pad-opt.design->minheight); ++i) { if (opt.design->padding[i%2?BBOT:BTOP]) opt.design->padding[i%2?BBOT:BTOP] -= 1; else if (opt.design->padding[i%2?BTOP:BBOT]) opt.design->padding[i%2?BTOP:BBOT] -= 1; else break; } } else { opt.design->minheight = pad; } } } pad = opt.design->padding[BLEF] + opt.design->padding[BRIG]; if (pad > 0) { pad += input.maxline; pad += opt.design->shape[NW].width + opt.design->shape[NE].width; if (pad > opt.design->minwidth) { if (opt.reqwidth) { for (i=0; i<(int)(pad-opt.design->minwidth); ++i) { if (opt.design->padding[i%2?BRIG:BLEF]) opt.design->padding[i%2?BRIG:BLEF] -= 1; else if (opt.design->padding[i%2?BLEF:BRIG]) opt.design->padding[i%2?BLEF:BRIG] -= 1; else break; } } else { opt.design->minwidth = pad; } } } if (opt.r) { /* * Remove box */ #ifdef DEBUG fprintf (stderr, "Removing Box ...\n"); #endif rc = remove_box(); if (rc) exit (EXIT_FAILURE); rc = apply_substitutions (1); if (rc) exit (EXIT_FAILURE); output_input(); } else { /* * Generate box */ #ifdef DEBUG fprintf (stderr, "Generating Box ...\n"); #endif rc = generate_box (thebox); if (rc) exit (EXIT_FAILURE); output_box (thebox); } return EXIT_SUCCESS; } /*EOF*/ /* vim: set sw=4: */