source: abnfparser/bap/main.c @ 2746

Last change on this file since 2746 was 2746, checked in by julian.reschke@…, 4 years ago

bap: update usage message

File size: 20.4 KB
Line 
1/*
2 * Bill's ABNF Parser
3 * Copyright 2002-2006 William C. Fenner <fenner@research.att.com>
4 *  All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the author nor the names of contributors
15 *    may be used to endorse or promote products derived from this software
16 *    without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY WILLIAM C. FENNER ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
20 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WILLIAM C. FENNER OR HIS
22 * BROTHER B1FF BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
26 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
28 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29 * DAMAGE.
30 */
31
32#include "config.h"
33#include <stdio.h>
34#include <stdlib.h>
35#include <search.h>
36#include <unistd.h>
37#include <ctype.h>
38#include <string.h>
39#include "common.h"
40
41static const char rcsid[] =
42  "$Id: main.c,v 1.3 2008-05-30 12:33:45 jre Exp $";
43static const char versionstring[] = PACKAGE_VERSION;
44
45static void printobjasxml(object *, int);
46static void printobj_r(object *, int, int);
47static void printobjasxml_r(object *, int, int);
48static void canonify(struct rule *);
49static void canonify_r(struct object **);
50static void parse_from(char *filename);
51static void predefine(fn_list *ifile);
52static int summary(void);
53
54#define MAXRULE         1000    /* XXX */
55
56#define local_printf(format, args...)                           \
57  if (!olenlimit) {                                             \
58    printf( format, ## args );                                  \
59  } else {                                                      \
60    int prevcount = charcount;  \
61    charcount += sprintf((charbuf+charcount), format, ## args); \
62    if (charcount > olenlimit) {                                \
63      char x[1000];  \
64      sprintf(x, format, ## args ); \
65      if (*x == '<') { /* prose rule? */  \
66        charcut = charbuf + prevcount - 1; /* wrap all of it */ \
67        charcount = olenlimit + strlen(x) + 1;  \
68      } \
69      else { \
70        charcut = charbuf+olenlimit;                            \
71        while (*charcut != ' ' && charcut >= charbuf) {         \
72                charcut--;                                              \
73                charcount++;                                            \
74        }                                                               \
75      } \
76      if (charcut != charbuf) {                                 \
77        *charcut++ = 0;                                         \
78        printf("%s\n", charbuf);                                \
79        if (*charbuf == ';') {                                  \
80          memmove(charbuf+2, charcut, charcount - olenlimit);   \
81          *(charbuf+1) = ' ';                                   \
82          charcount -= (olenlimit-1);                           \
83        } else {                                                \
84          memmove(charbuf+1, charcut, charcount - olenlimit);   \
85          *charbuf = ' ';                                       \
86          charcount -= olenlimit;                               \
87        }                                                       \
88      }                                                         \
89    }                                                           \
90    /* flush the line when EOL present */ \
91    charcut = strchr(charbuf, '\n');                            \
92    if (charcut) {                                              \
93      printf("%s", charbuf);                                    \
94      charcount = 0;                                            \
95    }                                                           \
96  }
97   
98
99char *charbuf = NULL;
100char *charcut = NULL;
101int charcount = 0;
102
103struct rule *rules = NULL;
104char *input_file; /* of current input file */
105
106char *top_rule_name = "ABNF";
107
108int cflag = 0;          /* include line number comments */
109int c2flag = 0;         /* include comments for printable constants */
110int tflag = 0;          /* print type info */
111int permissive = 1;     /* Be permissive (e.g. accept '|') */
112int qflag = 0;          /* quiet */
113int canon = 1;          /* canonify */
114int asxml = 0;    /* output XML */
115int olenlimit = 0;   /* 0 for unlimited, might be any other value */
116
117int yyparse(void);
118
119void
120usage(void)
121{
122  fprintf(stderr, "Bill's ABNF Parser version %s\n", versionstring);
123  fprintf(stderr, "usage: bap [-cknqtx][-i rules][-l num][-S name][file]\n");
124  fprintf(stderr, " parse ABNF grammar from file or stdin\n");
125  fprintf(stderr, " Input options:\n");
126  fprintf(stderr, "  -c       include rule definition line # in comment\n");
127  fprintf(stderr, "  -i file  read predefined rules from \"file\"\n");
128  fprintf(stderr, "  -S name  name rule as production start\n");
129  fprintf(stderr, " Output options:\n");
130  fprintf(stderr, "  -k       add comments for printable characters specified as %%x\n");
131  fprintf(stderr, "  -l num   limit the length of each line to \"num\" characters\n");
132  fprintf(stderr, "  -n       don't \"canonify\" result\n");
133  fprintf(stderr, "  -q       don't print parsed grammar\n");
134  fprintf(stderr, "  -t       include type info in result\n");
135  fprintf(stderr, "  -x       output XML\n");
136  exit(1);
137}
138
139int
140main(int argc, char **argv)
141{
142  int ch;
143  int rc = 0;
144  struct rule *r;
145  fn_list *pre_input = NULL;
146 
147#ifdef YYDEBUG
148  extern int yydebug;
149
150  yydebug = 0;
151#endif
152  hcreate(MAXRULE);
153
154  while ((ch = getopt(argc, argv, "cdi:kntqS:xl:")) != -1) {
155    switch (ch) {
156    case 'c':
157      cflag++;
158      break;
159
160    case 'd':
161#ifdef YYDEBUG
162      yydebug = 1;
163#else
164      fprintf(stderr, "Rebuild with -DYYDEBUG to use -d.\n");
165#endif
166      break;
167
168    case 'k':
169      c2flag++;
170      break;
171
172    case 'n':
173      canon = 0;
174      break;
175
176    case 'i': {
177      fn_list *ifile = calloc(sizeof(fn_list), 1);
178      ifile->filename = optarg;
179      ifile->next = pre_input;
180      pre_input = ifile;
181      break;
182    }
183     
184    case 't':
185      tflag++;
186      break;
187
188    case 'p':
189      permissive = 0;
190      break;
191
192    case 'q':
193      qflag++;
194      break;
195
196    case 'S':
197      top_rule_name = optarg;
198      break;
199     
200    case 'x':
201      asxml = 1;
202      break;
203
204    case 'l':
205      olenlimit = atoi(optarg);
206      break;
207
208    default:
209      usage();
210    }
211  }
212  argc -= optind;
213  argv += optind;
214
215  if (argc > 1)
216    usage();
217
218  if (olenlimit) {
219    charbuf = (char *) calloc (8192, sizeof(char));
220  }
221  predefine(pre_input);   
222 
223  /* Parse the grammar, perhaps spouting errors. */
224  parse_from((argc > 0)? argv[0] : NULL);
225
226  /* If we're not quiet, then output the grammar again. */
227  if (!qflag) {
228    if (canon)
229      canonify(rules);
230    if (!asxml) {
231      for (r = rules; r; r = r->next) {
232        if (r->predefined) {
233          /* do not output */
234        }
235        else if (r->rule) {
236          local_printf("%s = ", r->name);
237          printobj(r->rule, tflag);
238          if (cflag)
239            local_printf(" ; line %d", r->line);
240          local_printf("\n");
241        } else {
242          local_printf("; %s UNDEFINED\n", r->name);
243        }
244        if (r->next == rules)
245          break;
246      }
247      for (r = rules; r; r = r->next) {
248        if (r->used == 0
249            && r->predefined == 0
250            && r->rule
251            && strcmp(r->name, top_rule_name))
252          local_printf("; %s defined but not used\n", r->name);
253        if (r->next == rules)
254          break;
255      }
256    }
257    else {
258      local_printf("<abnf xmlns='tag:greenbytes.de,2008:abnf'>\n");
259      for (r = rules; r; r = r->next) {
260        if (r->predefined) {
261          /* do not output */
262        }
263        else if (r->rule) {
264          local_printf("  <rule name='%s'", r->name);
265          if (cflag)
266            local_printf(" line='%d'", r->line);
267          local_printf(">");
268          printobjasxml(r->rule, 2);
269          local_printf("\n  </rule>\n");
270        } else {
271          local_printf("  <undefined name='%s'/>\n", r->name);
272        }
273        if (r->next == rules)
274          break;
275      }
276      local_printf("</abnf>\n");
277    }
278  }
279 
280  rc = summary();
281  hdestroy();
282  exit(rc);
283}
284
285void
286canonify(struct rule *rules)
287{
288  struct rule *r;
289
290  for (r = rules; r; r = r->next) {
291    if (r->rule)
292      canonify_r(&r->rule);
293    if (r->next == rules)
294      break;
295  }
296}
297
298/* XXX may need to modify in the future? */
299void
300canonify_r(struct object **op)
301{
302  struct object *o = *op;
303  while (o) {
304    switch (o->type) {
305    case T_ALTERNATION:
306      canonify_r(&o->u.alternation.left);
307      canonify_r(&o->u.alternation.right);
308      break;
309    case T_RULE:
310      /* nothing to do */
311      break;
312    case T_GROUP:
313      canonify_r(&o->u.e.e.group);
314      break;
315    case T_TERMSTR:
316      while (o->next && o->next->type == T_TERMSTR &&
317             o->u.e.repetition.lo == 1 && o->u.e.repetition.hi == 1 &&
318             o->next->u.e.repetition.lo == 1 && o->next->u.e.repetition.hi == 1 &&
319             ((o->u.e.e.termstr.flags & F_CASESENSITIVE) ==
320              (o->next->u.e.e.termstr.flags & F_CASESENSITIVE))) {
321        int len = strlen(o->u.e.e.termstr.str) + strlen(o->next->u.e.e.termstr.str);
322        char *p = malloc(len + 1);
323        strcpy(p, o->u.e.e.termstr.str);
324        strcat(p, o->next->u.e.e.termstr.str);
325        free(o->u.e.e.termstr.str);
326        o->u.e.e.termstr.str = p;
327        /* XXX leak o->next */
328        o->next = o->next->next;
329      }
330      if (o->u.e.e.termstr.flags & F_CASESENSITIVE) {
331        int anybad = 0;
332        char *p;
333        for (p = o->u.e.e.termstr.str; *p; p++) {
334          if (isalpha(*p) || *p == '"' || !isprint(*p)) {
335            anybad = 1;
336            break;
337          }
338        }
339        if (anybad == 0)
340          o->u.e.e.termstr.flags &= ~F_CASESENSITIVE;
341      }
342    case T_TERMRANGE:
343    case T_PROSE:
344    default:
345      /* nothing to do */
346      break;
347    }
348    o = o->next;
349  }
350}
351
352void
353printrep(struct range *rep)
354{
355  if (rep->lo == 1 && rep->hi == 1)
356    return;
357  if (rep->lo > 0)
358    local_printf("%d", rep->lo);
359  if (rep->lo == rep->hi) {
360    if (rep->lo == 0)
361      local_printf("0");
362    return;
363  }
364  local_printf("*");
365  if (rep->hi != -1)
366    local_printf("%d", rep->hi);
367}
368
369void
370printobj(object *o, int tflag)
371{
372  /* T_GROUP means don't put grouping characters
373   * around the top level. */
374  printobj_r(o, T_GROUP, tflag);
375}
376
377void
378printobjasxml(object *o, int indent)
379{
380  /* T_GROUP means don't put grouping characters
381   * around the top level. */
382  printobjasxml_r(o, T_GROUP, indent);
383}
384
385/*
386 * No paren needed around a group that's:
387 * - not concatenation (no next)
388 * - not an ALTERNATION
389 * - got a repeat count of 1
390 */
391#define NOPAREN(o)      ((o->next == NULL) && (o->type != T_ALTERNATION) && (o->u.e.repetition.lo == 1 && o->u.e.repetition.hi == 1))
392
393/*
394 * No brackets needed around a group that
395 * contains a single element that has a
396 * possible repetition of 0.
397 */
398#define NOBRACKET(o)    ((o->next == NULL) && (o->u.e.repetition.lo == 0))
399
400static void
401printobj_r(object *o, int parenttype, int tflag)
402{
403  int iterating = 0;
404
405  /* Put parenthesis around concatenations */
406  if (parenttype != T_GROUP && o->next) {
407    iterating = 1;
408    local_printf("( ");
409  }
410  while (o) {
411    switch (o->type) {
412    case T_ALTERNATION:
413      if (tflag)
414        local_printf("{ALTERNATION}");
415      if (o->next)
416        local_printf("( ");
417      printobj_r(o->u.alternation.left, o->type, tflag);
418      local_printf(" / ");
419      printobj_r(o->u.alternation.right, o->type, tflag);
420      if (o->next)
421        local_printf(" )");
422      break;
423    case T_RULE: /* identation to delimit the code change */
424      if (tflag)
425        local_printf("{RULE}");
426      if (o->u.e.islist) {
427        if (o->u.e.repetition.lo == 0) {
428          local_printf("[ ( \",\" / ");
429          if (o->u.e.e.rule.rule) {
430            local_printf("%s", o->u.e.e.rule.rule->name);
431            o->u.e.e.rule.rule->used = 1;
432          } else {
433            local_printf("%s", o->u.e.e.rule.name);
434          }
435          local_printf(" ) *( OWS \",\" [ OWS ");
436          local_printf("%s", (o->u.e.e.rule.rule) ?
437                 o->u.e.e.rule.rule->name :
438                 o->u.e.e.rule.name);
439          local_printf(" ] ) ]");
440        } else if (o->u.e.repetition.lo == 1) {
441          local_printf(" *( \",\" OWS ) ");
442          if (o->u.e.e.rule.rule) {
443            local_printf("%s", o->u.e.e.rule.rule->name);
444            o->u.e.e.rule.rule->used = 1;
445          } else {
446            local_printf("%s", o->u.e.e.rule.name);
447          }
448          local_printf(" *( OWS \",\" [ OWS ");
449          local_printf("%s", (o->u.e.e.rule.rule) ?
450                 o->u.e.e.rule.rule->name :
451                 o->u.e.e.rule.name);
452          local_printf(" ] )");
453        }
454        else {
455          local_printf("TODO: something is wrong");
456        }
457      } else {
458        printrep(&o->u.e.repetition);
459        if (o->u.e.e.rule.rule) {
460          local_printf("%s", o->u.e.e.rule.rule->name);
461          o->u.e.e.rule.rule->used = 1;
462        }
463        else {
464          local_printf("%s", o->u.e.e.rule.name);
465        }
466      }
467      break;
468    case T_GROUP:
469      if (tflag)
470        local_printf("{GROUP}");
471      if (o->u.e.islist) {
472        if (o->u.e.repetition.lo == 0) {
473          local_printf("[ ( \",\" / ( ");
474          printobj_r(o->u.e.e.group, o->type, tflag);
475          local_printf(" ) ) *( OWS \",\" [ OWS ( ");
476          printobj_r(o->u.e.e.group, o->type, tflag);
477          local_printf(" ) ] ) ]");
478        }
479        else if (o->u.e.repetition.lo == 1) {
480          local_printf("*( \",\" OWS ) ( ");
481          printobj_r(o->u.e.e.group, o->type, tflag);
482          local_printf(" ) *( OWS \",\" [ OWS ( ");
483          printobj_r(o->u.e.e.group, o->type, tflag);
484          local_printf(" ) ] )");
485        }
486        else {
487          local_printf("TODO: something is wrong");
488        }
489      } else {
490        if (o->u.e.repetition.lo == 0 &&
491            o->u.e.repetition.hi == 1) {
492          if (!NOBRACKET(o->u.e.e.group))
493            local_printf("[ ");
494        } else {
495          printrep(&o->u.e.repetition);
496          if (!NOPAREN(o->u.e.e.group))
497            local_printf("( ");
498        }
499        printobj_r(o->u.e.e.group, o->type, tflag);
500        if (o->u.e.repetition.lo == 0 &&
501            o->u.e.repetition.hi == 1) {
502          if (!NOBRACKET(o->u.e.e.group))
503            local_printf(" ]");
504        } else {
505          if (!NOPAREN(o->u.e.e.group))
506            local_printf(" )");
507        }
508      }
509      break;
510    case T_TERMSTR:
511      if (tflag)
512        local_printf("{TERMSTR}");
513      printrep(&o->u.e.repetition);
514      if (o->u.e.e.termstr.flags & F_CASESENSITIVE) {
515        unsigned char *p = (unsigned char*)o->u.e.e.termstr.str;
516        char sep;
517        int allprintable = 1;
518        local_printf("%%");
519        sep = 'x';
520        while (*p) {
521          if (!isgraph(*p)) allprintable = 0;
522          local_printf("%c%02X", sep, *p++);
523          sep = '.';
524        }
525        if (c2flag && allprintable)
526          local_printf(" ; %s\n", o->u.e.e.termstr.str);
527      } else {
528        local_printf("%c%s%c", '"', o->u.e.e.termstr.str, '"');
529      }
530      break;
531    case T_TERMRANGE:
532      if (tflag)
533        local_printf("{TERMRANGE}");
534      printrep(&o->u.e.repetition);
535      local_printf("%%x%02X-%02X",
536             o->u.e.e.termrange.lo,
537             o->u.e.e.termrange.hi);
538      /* XXX isprint does not handle non-ASCII */
539      if (c2flag &&
540          isprint(o->u.e.e.termrange.lo) &&
541          isprint(o->u.e.e.termrange.hi)) {
542        local_printf(" ; '%c'-'%c'\n",
543               o->u.e.e.termrange.lo,
544               o->u.e.e.termrange.hi);
545      }
546      break;
547    case T_PROSE:
548      if (tflag)
549        local_printf("{PROSE}");
550      printrep(&o->u.e.repetition);
551      local_printf("<%s>", o->u.e.e.proseval);
552      break;
553    default:
554      local_printf("{UNKNOWN OBJECT TYPE %d}", o->type);
555      break;
556    }
557    if (o->next)
558      local_printf(" ");
559    o = o->next;
560  }
561  if (iterating)
562    local_printf(" )");
563}
564
565static void
566escaped(char *c) {
567  while (*c) {
568    if (*c == '&') {
569      local_printf("&amp;");
570    }
571    else if (*c == '<') {
572      local_printf("&lt;");
573    }
574    else {
575      local_printf("%c", *c);
576    }
577    c += 1;
578  }
579}
580
581static void
582printobjasxml_r(object *o, int parenttype, int indent)
583{
584  while (o) {
585    switch (o->type) {
586    case T_ALTERNATION:
587      local_printf("<alternation>\n");
588      local_printf("<alternative>");
589      printobjasxml_r(o->u.alternation.left, o->type, indent + 2);
590      local_printf("</alternative>\n");
591      local_printf("<alternative>");
592      printobjasxml_r(o->u.alternation.right, o->type, indent + 2);
593      local_printf("</alternative>\n");
594      local_printf("</alternation>\n");
595      break;
596    case T_RULE:
597      if (o->u.e.islist) {
598        local_printf("<list min='%d' max='%d'>\n", o->u.e.repetition.lo, o->u.e.repetition.hi);
599        if (o->u.e.e.rule.rule) {
600          local_printf("<rule ref='%s'/>", o->u.e.e.rule.rule->name);
601          o->u.e.e.rule.rule->used = 1;
602        }
603        else {
604          local_printf("<rule ref='%s'/>", o->u.e.e.rule.name);
605        }
606        local_printf("</list>\n");
607      }
608      else {
609        if (o->u.e.e.rule.rule) {
610          local_printf("<rule min='%d' max='%d' ref='%s'/>", o->u.e.repetition.lo, o->u.e.repetition.hi, o->u.e.e.rule.rule->name);
611          o->u.e.e.rule.rule->used = 1;
612        }
613        else {
614          local_printf("<rule min='%d' max='%d' ref='%s'/>", o->u.e.repetition.lo, o->u.e.repetition.hi, o->u.e.e.rule.name);
615        }
616      }
617      break;
618    case T_GROUP:
619      if (o->u.e.islist) {
620        local_printf("<list min='%d' max='%d'>\n", o->u.e.repetition.lo, o->u.e.repetition.hi);
621        printobjasxml_r(o->u.e.e.group, o->type, indent + 2);
622        local_printf("</list>");
623      }
624      else {
625        local_printf("<group min='%d' max='%d'>\n", o->u.e.repetition.lo, o->u.e.repetition.hi);
626        printobjasxml_r(o->u.e.e.group, o->type, indent + 2);
627        local_printf("</group>");
628      }
629      break;
630    case T_TERMSTR:
631      local_printf("<term min='%d' max='%d'>", o->u.e.repetition.lo, o->u.e.repetition.hi);
632      if (o->u.e.e.termstr.flags & F_CASESENSITIVE) {
633        unsigned char *p = (unsigned char*)o->u.e.e.termstr.str;
634        char sep;
635        int allprintable = 1;
636        local_printf("%%");
637        sep = 'x';
638        while (*p) {
639          if (!isgraph(*p)) allprintable = 0;
640          local_printf("%c%02X", sep, *p++);
641          sep = '.';
642        }
643      } else {
644        local_printf("\"");
645        escaped(o->u.e.e.termstr.str);
646        local_printf("\"");
647      }
648      local_printf("</term>");
649      break;
650    case T_TERMRANGE:
651      local_printf("<termrange min='%d' max='%d'>", o->u.e.repetition.lo, o->u.e.repetition.hi);
652      local_printf("%%x%02X-%02X",
653             o->u.e.e.termrange.lo,
654             o->u.e.e.termrange.hi);
655      /* XXX isprint does not handle non-ASCII */
656      if (c2flag &&
657          isprint(o->u.e.e.termrange.lo) &&
658          isprint(o->u.e.e.termrange.hi)) {
659        local_printf(" ; '%c'-'%c'\n",
660               o->u.e.e.termrange.lo,
661               o->u.e.e.termrange.hi);
662      }
663      local_printf("</termrange>");
664      break;
665    case T_PROSE:
666      local_printf("<prose min='%d' max='%d'>", o->u.e.repetition.lo, o->u.e.repetition.hi);
667      escaped(o->u.e.e.proseval);
668      local_printf("</prose>");
669      break;
670    default:
671      local_printf("{UNKNOWN OBJECT TYPE %d}", o->type);
672      break;
673    }
674    if (o->next)
675      local_printf(" ");
676    o = o->next;
677  }
678}
679
680struct rule *
681findrule(char *name)
682{
683  char *lowername;
684  char *p, *q;
685  ENTRY *e;
686  ENTRY search;
687  struct rule *r;
688
689  lowername = malloc(strlen(name) + 1);
690  for (p = name, q = lowername; *p; p++, q++)
691    if (isupper(*p))
692      *q = tolower(*p);
693    else
694      *q = *p;
695  *q = '\0';
696  search.key = lowername;
697  search.data = NULL;
698  e = hsearch(search, FIND);
699  if (e == NULL) {
700    r = calloc(1, sizeof(struct rule));
701    r->name = name;
702    r->lowername = lowername;
703    search.data = r;
704    e = hsearch(search, ENTER);
705    if (e == NULL) {
706      fprintf(stderr, "hash table full -- increase MAXRULE\n");
707      exit(1);
708    }
709    if (rules) {
710      r->next = rules;
711      r->prev = rules->prev;
712      rules->prev->next = r;
713      rules->prev = r;
714    } else {
715      rules = r->next = r->prev = r;
716    }
717    return r;
718  } else {
719    free(lowername);
720    return (struct rule *)e->data;
721  }
722}
723
724void
725parse_from(char *filename) {
726  extern FILE *yyin;
727  FILE *fin = NULL;
728 
729  if (filename != NULL) {
730    fin = fopen (filename, "rt");
731    if (!fin) {
732      fprintf(stderr, "input file not found: %s\n", filename);
733      exit(1);
734    }
735   
736    input_file = filename;
737    yyin = fin;
738  }
739  else {
740    yyin = stdin;
741    input_file = "stdin";
742  }
743 
744  scanreset();
745  yyparse();
746 
747  if (fin) fclose(fin); 
748}
749
750void
751predefine(fn_list *ifile) {
752  struct rule *r;
753  for (;ifile; ifile = ifile->next) {
754    parse_from(ifile->filename);
755  }
756 
757  for (r = rules; r; r = r->next) {
758    /* struct without rule definitions are created when names are used
759       they are != null when the rule was actually defined */
760    if (r->rule)
761      r->predefined = 1;
762    else
763      r->used = 1;
764
765    if (r->next == rules)
766      break;
767  }
768}
769
770int
771summary(void) {
772  extern int yyerrors;
773  if (yyerrors > 0) {
774    fflush(stdout);
775    fprintf(stderr, "parsing failed: %d errors encountered\n", yyerrors);
776  }
777  return yyerrors;
778}
779
Note: See TracBrowser for help on using the repository browser.