source: trunk/third/enscript/states/main.c @ 17620

Revision 17620, 8.9 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17619, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * The main for states.
3 * Copyright (c) 1997-1998 Markku Rossi.
4 *
5 * Author: Markku Rossi <mtr@iki.fi>
6 */
7
8/*
9 * This file is part of GNU enscript.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
14 * any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; see the file COPYING.  If not, write to
23 * the Free Software Foundation, 59 Temple Place - Suite 330,
24 * Boston, MA 02111-1307, USA.
25 */
26
27#include "defs.h"
28#include "getopt.h"
29
30/*
31 * Types and definitions.
32 */
33
34#define STDIN_NAME "(stdin)"
35
36
37/*
38 * Global variables.
39 */
40
41char *program;
42
43/* Namespaces. */
44StringHashPtr ns_prims = NULL;
45StringHashPtr ns_vars = NULL;
46StringHashPtr ns_subs = NULL;
47StringHashPtr ns_states = NULL;
48
49/*
50 * Global expressions which are evaluated after config file has been
51 * parsed.
52 */
53List *global_stmts = NULL;
54
55/* Statements from the start{} block. */
56List *start_stmts = NULL;
57
58/* Start and name rules. */
59List *startrules = NULL;
60List *namerules = NULL;
61
62Node *nvoid = NULL;
63
64FILE *ifp = NULL;
65char *inbuf = NULL;
66unsigned int data_in_buffer;
67unsigned int bufpos;
68int eof_seen;
69char *current_fname;
70unsigned int current_linenum;
71
72struct re_registers *current_match = NULL;
73char *current_match_buf = NULL;
74
75/* Options. */
76
77/*
78 * -D VAR=VAL, --define=VAR=VAL
79 *
80 * Define variable VAR to have value VAL.
81 */
82
83VariableDef *vardefs = NULL;
84VariableDef *vardefs_tail = NULL;
85
86/*
87 * -f NAME, --file=NAME
88 *
89 * Read state definitions from file NAME.  The default is "states.st" in
90 * the current working directory.
91 */
92
93char *defs_file = "states.st";
94unsigned int linenum = 1;
95
96/*
97 * -o FILE, --output=FILE
98 *
99 * Save output to file FILE, the default is stdout.
100 */
101
102FILE *ofp = NULL;
103
104/*
105 * -s NAME, --state=NAME
106 *
107 * Start from state NAME.  As a default, start date is resolved during
108 * the program startup by using start, namerules and startrules rules.
109 */
110char *start_state_arg = NULL;
111char *start_state;
112
113/*
114 * -W LEVEL, --warning=LEVEL
115 *
116 * Set the warning level to LEVEL.
117 */
118WarningLevel warning_level = WARN_LIGHT;
119
120
121/*
122 * Static variables.
123 */
124
125static struct option long_options[] =
126{
127  {"define",            required_argument,      0, 'D'},
128  {"file",              required_argument,      0, 'f'},
129  {"help",              no_argument,            0, 'h'},
130  {"output",            required_argument,      0, 'o'},
131  {"state",             required_argument,      0, 's'},
132  {"version",           no_argument,            0, 'V'},
133  {"warning",           required_argument,      0, 'W'},
134
135  {NULL, 0, 0, 0},
136};
137
138/* Version string. */
139char version[256];
140
141
142/*
143 * Prototypes for static functions.
144 */
145
146static void usage ___P ((void));
147
148
149/*
150 * Global functions.
151 */
152
153int
154main (argc, argv)
155     int argc;
156     char *argv[];
157{
158  int c;
159  VariableDef *vardef;
160
161  /* Set defaults for options. */
162  ofp = stdout;
163
164  /* Get program's name. */
165  program = strrchr (argv[0], '/');
166  if (program == NULL)
167    program = argv[0];
168  else
169    program++;
170
171  /* Make getopt_long() to use our modified program name. */
172  argv[0] = program;
173
174  /* Format version string. */
175  sprintf (version, _("states for GNU %s %s"), PACKAGE, VERSION);
176
177  /* Internationalization. */
178#if HAVE_SETLOCALE
179#if HAVE_LC_MESSAGES
180  setlocale (LC_MESSAGES, "");
181#endif
182#endif
183#if ENABLE_NLS
184  bindtextdomain (PACKAGE, LOCALEDIR);
185  textdomain (PACKAGE);
186#endif
187
188  /* Init namespaces. */
189  ns_prims = strhash_init ();
190  ns_vars = strhash_init ();
191  ns_subs = strhash_init ();
192  ns_states = strhash_init ();
193
194  global_stmts = list ();
195  start_stmts = list ();
196  startrules = list ();
197  namerules = list ();
198
199  nvoid = node_alloc (nVOID);
200  inbuf = (char *) xmalloc (INBUFSIZE);
201
202  init_primitives ();
203
204  re_set_syntax (RE_SYNTAX_GNU_AWK);
205
206  /* Enter some system variables. */
207  enter_system_variable ("program", program);
208  enter_system_variable ("version", version);
209
210  /* Parse arguments. */
211  while (1)
212    {
213      int option_index = 0;
214
215      c = getopt_long (argc, argv, "D:f:ho:s:VW:", long_options,
216                       &option_index);
217      if (c == -1)
218        break;
219
220      switch (c)
221        {
222        case 'D':               /* define variable */
223          vardef = (VariableDef *) xcalloc (1, sizeof (*vardef));
224          vardef->sym = (char *) xmalloc (strlen (optarg) + 1);
225          strcpy (vardef->sym, optarg);
226
227          vardef->val = strchr (vardef->sym, '=');
228          if (vardef->val == NULL)
229            {
230              fprintf (stderr, _("%s: malformed variable definition \"%s\"\n"),
231                       program, vardef->sym);
232              exit (1);
233            }
234          *vardef->val = '\0';
235          vardef->val++;
236
237          if (vardefs)
238            vardefs_tail->next = vardef;
239          else
240            vardefs = vardef;
241          vardefs_tail = vardef;
242          break;
243
244        case 'f':               /* definitions file */
245          defs_file = optarg;
246          break;
247
248        case 'h':               /* help */
249          usage ();
250          exit (0);
251          break;
252
253        case 'o':               /* output file */
254          ofp = fopen (optarg, "w");
255          if (ofp == NULL)
256            {
257              fprintf (stderr,
258                       _("%s: couldn't create output file \"%s\": %s\n"),
259                       program, optarg, strerror (errno));
260              exit (1);
261            }
262          break;
263
264        case 's':               /* start state */
265          start_state_arg = optarg;
266          break;
267
268        case 'V':               /* version */
269          printf ("%s\n", version);
270          exit (0);
271          break;
272
273        case 'W':               /* warning level */
274          if (strcmp (optarg, "light") == 0)
275            warning_level = WARN_LIGHT;
276          else if (strcmp (optarg, "all") == 0)
277            warning_level = WARN_ALL;
278          else
279            {
280              fprintf (stderr,
281                       _("%s: unknown warning level `%s'\n"),
282                       program, optarg);
283              exit (1);
284            }
285          break;
286
287        case '?':               /* Errors found during getopt_long(). */
288          fprintf (stderr, _("Try `%s --help' for more information.\n"),
289                   program);
290          exit (1);
291          break;
292
293        default:
294          printf ("Hey! main() didn't handle option \"%c\" (%d)", c, c);
295          if (optarg)
296            printf (" with arg %s", optarg);
297          printf ("\n");
298          abort ();
299          break;
300        }
301    }
302
303  /* Pass all remaining arguments to States through `argv' array. */
304  {
305    Node *v, *n;
306    int i;
307
308    v = node_alloc (nARRAY);
309    v->u.array.allocated = argc - optind + 1;
310    v->u.array.len = argc - optind;
311    v->u.array.array = (Node **) xcalloc (v->u.array.allocated,
312                                          sizeof (Node *));
313    for (i = optind; i < argc; i++)
314      {
315        char *data;
316
317        n = node_alloc (nSTRING);
318        if (strcmp (argv[i], "-") == 0)
319          data = STDIN_NAME;
320        else
321          data = argv[i];
322
323        n->u.str.len = strlen (data);
324        n->u.str.data = xstrdup (data);
325        v->u.array.array[i - optind] = n;
326      }
327
328    if (!strhash_put (ns_vars, "argv", 4, v, (void **) &n))
329      {
330        fprintf (stderr, _("%s: out of memory\n"), program);
331        exit (1);
332      }
333    node_free (n);
334  }
335
336  /* Parse config file. */
337
338  yyin = fopen (defs_file, "r");
339  if (yyin == NULL)
340    {
341      fprintf (stderr, _("%s: couldn't open definition file `%s': %s\n"),
342               program, defs_file, strerror (errno));
343      exit (1);
344    }
345
346  yyparse ();
347  fclose (yyin);
348
349  /* Evaluate all top-level statements. */
350  {
351    Node *n;
352    int return_seen = 0;
353
354    n = eval_statement_list (global_stmts, NULL, &return_seen);
355    node_free (n);
356  }
357
358  /* Define variables given at the command line. */
359  for (vardef = vardefs; vardef; vardef = vardef->next)
360    {
361      Node *val;
362      Node *old_val;
363
364      val = node_alloc (nSTRING);
365      val->u.str.len = strlen (vardef->val);
366      val->u.str.data = xstrdup (vardef->val);
367
368      if (!strhash_put (ns_vars, vardef->sym, strlen (vardef->sym),
369                        val, (void **) &old_val))
370        {
371          fprintf (stderr, _("%s: out of memory\n"), program);
372          exit (1);
373        }
374      node_free (old_val);
375    }
376
377  /* Process files. */
378  if (optind == argc)
379    {
380      ifp = stdin;
381      process_file (STDIN_NAME);
382    }
383  else
384    for (; optind < argc; optind++)
385      {
386        if (strcmp (argv[optind], "-") == 0)
387          {
388            ifp = stdin;
389            process_file (STDIN_NAME);
390          }
391        else
392          {
393            ifp = fopen (argv[optind], "r");
394            if (ifp == NULL)
395              {
396                fprintf (stderr, _("%s: couldn't open input file `%s': %s\n"),
397                         program, argv[optind], strerror (errno));
398                exit (1);
399              }
400            process_file (argv[optind]);
401            fclose (ifp);
402          }
403      }
404
405  /* Close output file. */
406  if (ofp != stdout)
407    fclose (ofp);
408
409  return 0;
410}
411
412
413/*
414 * Static functions.
415 */
416
417static void
418usage ()
419{
420  printf (_("\
421Usage: %s [OPTION]... [FILE]...\n\
422Mandatory arguments to long options are mandatory for short options too.\n"),
423          program);
424  printf (_("\
425  -D, --define=VAR=VAL       define variable VAR to have value VAR\n\
426  -f, --file=NAME            read state definitions from file NAME\n\
427  -h, --help                 print this help and exit\n\
428  -o, --output=NAME          save output to file NAME\n\
429  -s, --state=NAME           start from state NAME\n\
430  -V, --version              print version number\n\
431  -W, --warning=LEVEL        set the warning level to LEVEL\n"));
432}
Note: See TracBrowser for help on using the repository browser.