Bug Summary

File:tools/unix/zacc.c
Warning:line 946, column 17
Value stored to 'l' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name zacc.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/kfp/aldor/aldor/aldor/tools/unix -fcoverage-compilation-dir=/home/kfp/aldor/aldor/aldor/tools/unix -resource-dir /usr/local/lib/clang/18 -D PACKAGE_NAME="aldor" -D PACKAGE_TARNAME="aldor" -D PACKAGE_VERSION="1.4.0" -D PACKAGE_STRING="aldor 1.4.0" -D PACKAGE_BUGREPORT="aldor@xinutec.org" -D PACKAGE_URL="" -D PACKAGE="aldor" -D VERSION="1.4.0" -D YYTEXT_POINTER=1 -D HAVE_STDIO_H=1 -D HAVE_STDLIB_H=1 -D HAVE_STRING_H=1 -D HAVE_INTTYPES_H=1 -D HAVE_STDINT_H=1 -D HAVE_STRINGS_H=1 -D HAVE_SYS_STAT_H=1 -D HAVE_SYS_TYPES_H=1 -D HAVE_UNISTD_H=1 -D STDC_HEADERS=1 -D HAVE_LIBREADLINE=1 -D HAVE_READLINE_READLINE_H=1 -D HAVE_READLINE_HISTORY=1 -D HAVE_READLINE_HISTORY_H=1 -D USE_GLOOP_SHELL=1 -D GENERATOR_COROUTINES=0 -D HAVE_DLFCN_H=1 -D LT_OBJDIR=".libs/" -I . -internal-isystem /usr/local/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-empty-body -Wno-enum-compare -Wno-missing-field-initializers -Wno-unused -Wno-unused-parameter -Wno-error=format -Wno-error=type-limits -Wno-error=strict-aliasing -Wno-sign-compare -Wno-error=shift-negative-value -Wno-error=clobbered -Wno-implicit-function-declaration -std=c99 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2026-01-15-223856-845667-1 -x c zacc.c
1/*
2 * 2-level grammar implementation.
3 *
4 * zacc [-y yaccfile] [-c cfile] [-v] [-p] infile
5 *
6 * This command accepts a grammar file and produces a yacc file as output.
7 * The grammar file looks like yacc, with the following differences:
8 *
9 * 1. Rules may be parameterized
10 * E.g. List(S): Nothing | List(S) S ;
11 *
12 * 2. Rules may be typed
13 * E.g. Node<pt>: '(' Node ')' | Node '+' Node ;
14 * List(S)<l>: Nothing | List(S) S ;
15 *
16 * 3. A default type for rules or tokens can be given:
17 * E.g. %default-token-type <tok>
18 * %default-rule-type <pt>
19 *
20 * A name which is used but does not have a rule is assumed to be a token.
21 *
22 * If a name is only used preceded by a back quote, then no type declaration
23 * is made for it.
24 * E.g. List(S,f): Nothing { $$ = 0; } | List(S,f) S { $$ = f($2,$1); } ;
25 * conslist: List(TK_Int, `cons);
26 *
27 * A rule typed as <void> is not given a type even in the presence of
28 * a "%default-rule-type".
29 *
30 * 4. A C source file may be included to obtain values for tokens:
31 * E.g. %include-enum "token.h" tokenTag
32 * produces %token statements for the entries in ``enum tokenTag''.
33 *
34 * The "-y" option gives a name to the generated yacc file and says to keep it.
35 * The "-c" option gives a name to the generated C file and says to keep it.
36 * The "-v" option causes the program to print debug messages.
37 * The "-p" option causes the token symbols to be prefaced with "YY_".
38 */
39
40# include <stdio.h>
41# include <stdlib.h>
42# include <string.h>
43# include <time.h>
44# include <unistd.h>
45# include "zacc.h"
46# include "zaccgram.h"
47# include "cenum.h"
48
49#define COMMENTARY
50
51/*
52 * Things imported.
53 */
54
55extern FILE *yyin;
56extern int yydebug;
57extern int yyparse();
58
59extern char *ctime();
60/*extern char *malloc();*/
61/*extern char *strcpy();*/
62
63/*
64 * Forward declarations for utilities.
65 */
66
67char * mustAlloc of((int))(int);
68char * strAlloc of((char *))(char *);
69FILE * mustOpen of((char *fname, char *mode))(char *fname, char *mode);
70char * timeNow of((void))(void);
71void fatalErr of((void))(void);
72char * fnameDir of((char *))(char *);
73
74
75/******************************************************************************
76 *
77 * :: Top-level global variables.
78 *
79 *****************************************************************************/
80
81#define DEFAULT_YACC_FILE"zacc.out" "zacc.out"
82#define DEFAULT_C_FILE"y.tab.c" "y.tab.c"
83
84static int verbose=0; /* -v flag given. */
85static char *prefix=""; /* -p flag prefix. */
86
87static char *yfile="zacc.out"; /* -y file name. */
88static int hadyfile=0;
89
90static char *cfile="y.tab.c"; /* -c file name. */
91static int hadcfile=0;
92
93static char *fnin; /* Name of input file. */
94static char *dirin; /* Directory part of input filename. */
95static FILE *fout; /* Output stream for yacc generation. */
96
97static int passno; /* Pass number. */
98static int errcount = 0; /* Number of syntax errors. */
99
100static char *dfltTokenType = 0; /* Default type for tokens. */
101static char *dfltRuleType = 0; /* Default type for rules. */
102static int hasPctType = 0; /* %type used? */
103
104static int isExtra(); /* Is this a XXX_START or XXX_LIMIT word? */
105static int isTerminal(); /* Is the given word a terminal (token)? */
106static void prWord(); /* Print the given word. */
107
108struct phrUse;
109struct phrDef;
110struct phrInfo;
111
112int yylex();
113void handleRule();
114void _2_endRule();
115void _2_startRule();
116void _2_endPhraseName();
117void _2_seeArg();
118void _2_seeType();
119void _2_seeName();
120void _2_endCommand();
121void _2_startCommand();
122void _2_seeIncludeEnum();
123void _2_wholeEpilog();
124void _2_endProlog();
125void _2_startProlog();
126void _2_endRule();
127void _2_startPhraseName();
128void _2_midRule();
129void _1_endRule();
130void _1_midRule();
131void _1_startRule();
132void _1_seeType();
133void _1_endPhraseName();
134void _1_seeArg();
135void _1_seeName();
136void _1_startPhraseName();
137void _1_seeIncludeEnum();
138void _1_endCommand();
139void _1_startCommand();
140void _1_wholeEpilog();
141void _1_endProlog();
142void _1_startProlog();
143struct phrUse *findUse(struct phrInfo *pinfo, struct phrDef *context, struct phrUse *);
144void _1_();
145void _1_();
146
147
148static int inLhs, inAction; /* context information */
149
150
151/******************************************************************************
152 *
153 * :: Top-level entry point and parser tie-ins.
154 *
155 *****************************************************************************/
156
157
158void
159zaccPass(char *fn, int n)
160{
161 yyin = mustOpen(fn, "r");
162 fnin = fn;
163 passno = n;
164 yyparse();
165 fclose(yyin);
166}
167
168
169void
170zacc(char *fn, char *yfn)
171{
172 dirin = fnameDir(fn);
173
174 fout = mustOpen(yfn, "w");
175
176#ifdef COMMENTARY
177 fprintf(fout, "/*\n * \"zacc\" output from \"%s\" on %s\n */\n\n",
178 fn, timeNow());
179#endif
180 zaccPass(fn, 1);
181 if (errcount > 0) exit(3);
182 zaccPass(fn, 2);
183
184 fclose(fout);
185}
186
187int
188main(int argc, char **argv)
189{
190 int options = 1;
191
192 while (options) {
193 if (argc > 1 && !strcmp(argv[1], "-v")) {
194 verbose = 1;
195 argc--, argv++;
196 continue;
197 }
198 if (argc > 1 && !strcmp(argv[1], "-p")) {
199 prefix = "_YY_";
200 argc--, argv++;
201 continue;
202 }
203 if (argc > 2 && !strcmp(argv[1], "-y")) {
204 yfile = argv[2];
205 hadyfile = 1;
206 argc -= 2, argv += 2;
207 continue;
208 }
209 if (argc > 2 && !strcmp(argv[1], "-c")) {
210 cfile = argv[2];
211 hadcfile = 1;
212 argc -= 2, argv += 2;
213 continue;
214 }
215 options = 0;
216 }
217
218 if (argc != 2) fatalErr();
219
220 if (hadyfile || hadcfile) {
221 zacc(argv[1], yfile);
222 }
223 if (hadcfile) {
224 char cmd[500];
225 int rc;
226
227 sprintf(cmd, "yacc %s", yfile);
228 if (verbose) printf("Exec: %s\n", cmd);
229 rc = system(cmd);
230 if (rc != 0) {
231 fprintf(stderrstderr, "Yacc failed on file \"%s\"\n", yfile);
232 return 3;
233 }
234 if (!hadyfile) unlink(yfile);
235
236 rc = rename("y.tab.c", cfile);
237 if (rc != 0) {
238 fprintf(stderrstderr,
239 "Rename failed from \"y.tab.c\" to \"%s\"\n",
240 cfile);
241 return 3;
242 }
243
244 }
245
246 return 0;
247}
248
249int lineNo;
250
251int
252yyerror(char *s)
253{
254 fprintf(stderrstderr, "\"%s\", line %d: %s\n", fnin, lineNo, s);
255 return errcount++;
256}
257
258void
259incLineCount()
260{
261 lineNo++;
262}
263
264int tokEcho; /* In "token", echo the string. */
265int tokEnlist; /* In "token", add a link to the token list. */
266
267struct tokList {
268 int tag;
269 char *str;
270 struct tokList *next;
271 int show; /* for rule emission */
272} *tokListHead, *tokListTail;
273
274void
275token(int tag, char *str)
276{
277 /*
278 * To finesse parser lookahead.
279 */
280 static char *prevTok = "";
281 static int prevEcho= 1;
282
283 yylval.str = strAlloc(str);
284
285 if (prevEcho && tokEcho)
286 prWord(fout, prevTok);
287
288 prevEcho = tokEcho;
289 prevTok = yylval.str;
290
291 if (tag == TK_PctId277 && !strcmp(str, "%type"))
292 hasPctType = 1;
293
294 if (tag == TK_NewLine283) incLineCount();
295
296 if (tokEnlist) {
297 struct tokList *t;
298 t = (struct tokList *) mustAlloc(sizeof(struct tokList));
299 t->tag = inAction ? TK_CTok281 : tag;
300 t->str = yylval.str;
301 t->show= 0;
302 t->next= 0;
303
304 if (!tokListHead)
305 tokListHead = tokListTail = t;
306 else {
307 tokListTail->next = t;
308 tokListTail = t;
309 }
310 }
311}
312
313
314/******************************************************************************
315 *
316 * :: Grammar actions
317 *
318 *****************************************************************************/
319
320void
321startProlog()
322{
323 inLhs = 0;
324 inAction = 0;
325
326 switch (passno) {
327 case 1: _1_startProlog(); break;
328 case 2: _2_startProlog(); break;
329 }
330}
331
332void
333endProlog()
334{
335 switch (passno) {
336 case 1: _1_endProlog(); break;
337 case 2: _2_endProlog(); break;
338 }
339}
340
341
342void
343wholeEpilog()
344{
345 switch (passno) {
346 case 1: _1_wholeEpilog(); break;
347 case 2: _2_wholeEpilog(); break;
348 }
349}
350
351
352void
353startCommand()
354{
355 switch (passno) {
356 case 1: _1_startCommand(); break;
357 case 2: _2_startCommand(); break;
358 }
359}
360
361void
362endCommand()
363{
364 switch (passno) {
365 case 1: _1_endCommand(); break;
366 case 2: _2_endCommand(); break;
367 }
368}
369
370
371void
372seeTokenType(char *str)
373{
374 dfltTokenType = str;
375}
376
377void
378seeIncludeEnum(char *fname, char *ename)
379{
380 char fbuf[500];
381 int i;
382
383 /* Convert "\"foo.h\"" -> "dirin/foo.h" */
384 if (*fname == '"') fname++;
385 for (i = 0; dirin[i]; i++) fbuf[i] = dirin[i];
386 fbuf[i++] = '/';
387 while (*fname && *fname != '"') fbuf[i++] = *fname++;
388 fbuf[i] = 0;
389
390 switch (passno) {
391 case 1: _1_seeIncludeEnum(fbuf, ename); break;
392 case 2: _2_seeIncludeEnum(fbuf, ename); break;
393 }
394}
395
396void
397seeRuleType(char *str)
398{
399 dfltRuleType = str;
400}
401
402void
403startPhraseName()
404{
405 switch (passno) {
406 case 1: _1_startPhraseName(); break;
407 case 2: _2_startPhraseName(); break;
408 }
409}
410
411void
412seeName(char *str)
413{
414 switch(passno) {
415 case 1: _1_seeName(str); break;
416 case 2: _2_seeName(str); break;
417 }
418}
419
420void
421seeArg(char *str)
422{
423 switch(passno) {
424 case 1: _1_seeArg(str); break;
425 case 2: _2_seeArg(str); break;
426 }
427}
428
429void
430endPhraseName()
431{
432 switch(passno) {
433 case 1: _1_endPhraseName(); break;
434 case 2: _2_endPhraseName(); break;
435 }
436}
437
438void
439seeType(char *str)
440{
441 switch(passno) {
442 case 1: _1_seeType(str); break;
443 case 2: _2_seeType(str); break;
444 }
445}
446
447
448void
449startRule()
450{
451 inLhs = 1;
452
453 switch(passno) {
454 case 1: _1_startRule(); break;
455 case 2: _2_startRule(); break;
456 }
457}
458
459void
460midRule()
461{
462 inLhs = 0;
463
464 switch(passno) {
465 case 1: _1_midRule(); break;
466 case 2: _2_midRule(); break;
467 }
468}
469
470void
471endRule()
472{
473 switch(passno) {
474 case 1: _1_endRule(); break;
475 case 2: _2_endRule(); break;
476 }
477}
478
479void
480startAction()
481{
482 inAction = 1;
483}
484
485void
486endAction()
487{
488 inAction = 0;
489}
490
491
492/******************************************************************************
493 *
494 * :: Structures for Pass 1.
495 *
496 *****************************************************************************/
497
498
499/*
500 * These structures maintain information on rules defined and used.
501 *
502 * E.g. z(a,b)<tok> : OPren x(b) y(q,r) a CPren ;
503 */
504
505static char * argName[] = { "&1","&2","&3","&4","&5","&6","&7","&8","&9" };
506# define MAXARGC(9) (9)
507
508struct phrInfo {
509 char *name;
510 int argc;
511 char *argv[MAXARGC(9)];
512};
513
514struct phrDef {
515 char *name; /* z */
516 int argc; /* 2 */
517 char *type; /* tok */
518 struct phrDef *next;
519};
520
521struct phrUse {
522 struct phrInfo info; /* x(&2) ; y(q) */
523 struct phrDef *context; /* ^{z,2,..} ; 0 */
524 struct phrUse *next;
525};
526
527struct phrDef *phrDefList = 0;
528struct phrUse *phrUseList = 0;
529
530struct phrUse *tokenSet, *genSet;
531
532#define UNQ(s)( ((s)[0] == '`') ? (s) + 1 : (s) ) ( ((s)[0] == '`') ? (s) + 1 : (s) )
533void
534fprintInfo(FILE *fout, struct phrInfo *pinfo)
535{
536 int i;
537
538 prWord(fout, UNQ(pinfo->name)( ((pinfo->name)[0] == '`') ? (pinfo->name) + 1 : (pinfo
->name) )
);
539
540 if (pinfo->argc == 0) return;
541
542 for (i = 0; i < pinfo->argc; i++) {
543 fprintf(fout, "_");
544 prWord(fout, UNQ(pinfo->argv[i])( ((pinfo->argv[i])[0] == '`') ? (pinfo->argv[i]) + 1 :
(pinfo->argv[i]) )
);
545 }
546 fprintf(fout, "_");
547}
548
549/* Does the arg use &1, etc? */
550int
551usesBV(struct phrInfo *pinfo)
552{
553 int i, j;
554 for (i = 0; i < pinfo->argc; i++)
555 for (j = 0; j < MAXARGC(9); j++)
556 if (pinfo->argv[i] == argName[j]) return 1;
557 return 0;
558}
559
560/* Rename bound variables to &1, etc. */
561char *
562renameBV(char *str, struct phrInfo *pinfo)
563{
564 int i;
565
566 for (i = 0; i < pinfo->argc; i++)
567 if (!strcmp(str, pinfo->argv[i]))
568 return argName[i];
569
570 return str;
571}
572
573int
574unnameBV(char *str)
575{
576 int i;
577 for (i = 0; i < MAXARGC(9); i++)
578 if (str == argName[i]) return i;
579 return -1;
580}
581
582struct phrUse *
583instance(struct phrUse *withFV, struct phrUse *withBV)
584{
585 struct phrUse *inst;
586 int i;
587
588 inst = (struct phrUse *) mustAlloc(sizeof(struct phrUse));
589 inst->context = 0;
590 inst->next = 0;
591
592 inst->info = withFV->info;
593
594 for (i = 0; i < withFV->info.argc; i++) {
595 int a = unnameBV(withFV->info.argv[i]);
596
597 if (a >= 0) inst->info.argv[i] = withBV->info.argv[a];
598 }
599
600 return inst;
601}
602
603struct phrDef *
604findDef(char *str, struct phrDef *l)
605{
606 for ( ; l; l = l->next) {
607 if (!strcmp(str, l->name)) return l;
608 }
609 return 0;
610}
611
612struct phrUse *
613findUse(struct phrInfo *pinfo, struct phrDef *context, struct phrUse *l)
614{
615 for ( ; l; l = l->next) {
616 int different = strcmp(pinfo->name, l->info.name);
617 int i;
618 for (i = 0; !different && i < pinfo->argc; i++)
619 different = strcmp(pinfo->argv[i], l->info.argv[i]);
620 if (!different)
621 different = l->context && (l->context != context);
622 if (!different)
623 return l;
624 }
625 return 0;
626}
627
628
629struct phrDef *
630addDef(char *name, int argc, char *type)
631{
632 struct phrDef *def;
633
634 def = findDef(name, phrDefList);
635
636 if (!def) {
637 def = (struct phrDef *) mustAlloc(sizeof(struct phrDef));
638 def->name = name;
639 def->argc = argc;
640 def->type = type;
641 def->next = phrDefList;
642 phrDefList = def;
643 }
644 else {
645 if (def->argc != argc)
646 fatalErr();
647 if (def->type && type && strcmp(def->type, type))
648 fatalErr();
649 if (type && !(def->type))
650 def->type = type;
651 }
652 return def;
653}
654
655struct phrDef *
656defListNReverse(struct phrDef *l)
657{
658 struct phrDef *r, *t;
659
660 r = 0;
661 while(l) {
662 t = l->next;
663 l->next = r;
664 r = l;
665 l = t;
666 }
667 return r;
668}
669
670int
671dontAddUse(char *str)
672{
673 int i;
674
675 if (*str == '`') return 1;
676 if (!strcmp(str, "error")) return 1;
677
678 for (i = 0; i < MAXARGC(9); i++)
679 if (str == argName[i]) return 1;
680 return 0;
681}
682
683struct phrUse *
684addUse(struct phrInfo *pinfo, struct phrDef *context)
685{
686 struct phrUse *use;
687
688 if (dontAddUse(pinfo->name))
689 return phrUseList;
690
691 use = findUse(pinfo, context, phrUseList);
692
693 if (!use) {
694 use = (struct phrUse *) mustAlloc(sizeof(struct phrUse));
695 use->info = *pinfo;
696 use->context = usesBV(pinfo) ? context : 0;
697 use->next = phrUseList;
698 phrUseList = use;
699 }
700 return phrUseList;
701}
702
703
704void
705showDefs(struct phrDef *l)
706{
707 for ( ; l; l = l->next) {
708 fprintf(stdoutstdout, "\t%s", l->name);
709 if (l->argc > 0)
710 fprintf(stdoutstdout, "[%d]", l->argc);
711 if (l->type)
712 fprintf(stdoutstdout,"<%s>", l->type);
713 fprintf(stdoutstdout,"\n");
714 }
715}
716
717void
718showUses(struct phrUse *l)
719{
720 for ( ; l; l = l->next) {
721 int i;
722 fprintf(stdoutstdout, "\t%s", l->info.name);
723 if (l->info.argc > 0) {
724 fprintf(stdoutstdout, "(");
725 for (i = 0; i < l->info.argc; i++)
726 fprintf(stdoutstdout, " %s", l->info.argv[i]);
727 fprintf(stdoutstdout, ")");
728
729 if (l->context)
730 fprintf(stdoutstdout, " in %s", l->context->name);
731 }
732 fprintf(stdoutstdout, "\n");
733 }
734}
735
736void
737phraseClosure()
738{
739 struct phrUse *withFV = 0, *undone = 0;
740 int n;
741
742 phrDefList = defListNReverse(phrDefList);
743
744 tokenSet = 0;
745 genSet = 0;
746
747 while (phrUseList) {
748 struct phrUse *t;
749
750 t = phrUseList; phrUseList = phrUseList->next;
751
752 if (t->context) {
753 t->next = withFV; withFV = t;
754 }
755 else if (!findDef(t->info.name, phrDefList)) {
756 if (t->info.argc != 0) fatalErr();
757 t->next = tokenSet; tokenSet = t;
758 }
759 else if(t->info.argc > 0) {
760 t->next = undone; undone = t;
761 }
762 }
763
764 if (verbose) {
765 printf("Starting to compute closure.\n");
766 printf("-- Defined rules and metarules:\n");
767 showDefs(phrDefList);
768 printf("-- Metarule uses:\n");
769 showUses(withFV);
770 }
771
772 for (n = 0; undone; n++) {
773 struct phrUse *u0, *u1, *l;
774
775 if (verbose) {
776 printf("Iteration %d.\n", n);
777/*
778 printf("-- Done forms:\n");
779 showUses(undone);
780 printf("-- So far generated rules:\n");
781 showUses(genSet);
782*/
783 }
784
785 u0 = undone;
786 undone = undone->next;
787
788 u0->next = genSet;
789 genSet = u0;
790
791 for (l = withFV; l; l = l->next) {
792 if (!strcmp(l->context->name, u0->info.name)) {
793 u1 = instance(l, u0);
794 if (!findUse(&(u1->info), 0, undone) &&
795 !findUse(&(u1->info), 0, genSet) )
796 {
797 u1->next = undone; undone = u1;
798 }
799 }
800 }
801 }
802
803 if (verbose) {
804 printf("-- Implicit tokens:\n");
805 showUses(tokenSet);
806 printf("-- Generated rules:\n");
807 showUses(genSet);
808 }
809}
810
811
812/*
813 * Code to gather information about parameterized phrases as they are parsed.
814 */
815
816static struct phrInfo phrInfo;
817static struct phrInfo lhsInfo;
818static char *lhsType;
819static struct phrDef *lhsDef;
820
821void
822_1_startProlog()
823{
824 tokEcho = 0;
825 tokEnlist = 0;
826}
827
828void
829_1_endProlog()
830{
831 if (hasPctType && (dfltTokenType || dfltRuleType))
832 fatalErr();
833}
834
835void
836_1_wholeEpilog()
837{
838 while (yylex() != 0)
839 ;
840
841 phraseClosure();
842}
843
844void
845_1_startCommand()
846{
847}
848
849void
850_1_endCommand()
851{
852}
853
854static EnumItem inclEnums = 0;
855
856void
857_1_seeIncludeEnum(char *fname, char *ename)
858{
859 EnumItem tt;
860
861 tt = skimEnums(fname, 1, &ename);
862 if (!tt) {
863 fprintf(stderrstderr, "Could not find enumeration %s in file %s.\n",
864 ename, fname);
865 exit(3);
866 }
867 inclEnums = skimNConcat(inclEnums, tt);
868}
869
870void
871_1_startPhraseName()
872{
873 phrInfo.name = 0;
874 phrInfo.argc = 0;
875}
876
877void
878_1_seeName(char *str)
879{
880 phrInfo.name = (!inLhs) ? renameBV(str, &lhsInfo) : str;
881}
882
883void
884_1_seeArg(char *str)
885{
886 if (phrInfo.argc == MAXARGC(9))
887 fatalErr();
888
889 str = (!inLhs) ? renameBV(str, &lhsInfo) : str;
890 phrInfo.argv[phrInfo.argc++] = str;
891
892 if (!inLhs) {
893 struct phrInfo argInfo;
894 argInfo.name = str;
895 argInfo.argc = 0;
896 addUse(&argInfo, lhsDef);
897 }
898}
899
900void
901_1_endPhraseName()
902{
903 if (inLhs)
904 lhsInfo = phrInfo;
905 else
906 addUse(&phrInfo, lhsDef);
907}
908
909void
910_1_seeType(char *str)
911{
912 if (passno != 1) return;
913
914 lhsType = str;
915}
916
917
918void
919_1_startRule()
920{
921 lhsType = 0;
922 lhsDef = 0;
923}
924
925void
926_1_midRule()
927{
928 lhsDef = addDef(lhsInfo.name, lhsInfo.argc, lhsType);
929}
930
931void
932_1_endRule()
933{
934}
935
936
937/******************************************************************************
938 *
939 * :: Functions for pass 2.
940 *
941 *****************************************************************************/
942
943static int
944isTerminal(char *w)
945{
946 struct phrUse *l = tokenSet;
Value stored to 'l' during its initialization is never read
947
948 for (l = tokenSet; l; l = l->next)
949 if (!strcmp(w, l->info.name)) return 1;
950
951 return 0;
952}
953
954char *extraSuffix[] = { "_START", "_LIMIT", 0 };
955
956static int
957isExtra(char *w)
958{
959 char *x;
960 int i, nx, nw;
961
962 nw = strlen(w);
963
964 for (i = 0; extraSuffix[i]; i++) {
965 x = extraSuffix[i];
966 nx = strlen(x);
967
968 if (nx > nw) continue;
969 if (!strcmp(w + (nw-nx), x)) return 1;
970
971 }
972 return 0;
973}
974
975static void
976prWord(FILE *fout, char *w)
977{
978 char *p;
979 p = isTerminal(w) ? prefix : "";
980 fprintf(fout, "%s%s", p, w);
981
982}
983
984void
985_2_startProlog()
986{ tokEcho = 1;
987 tokEnlist= 1;
988
989 tokListHead = 0;
990 tokListTail = 0;
991}
992
993void
994_2_endProlog()
995{
996 struct phrUse *ul;
997 struct phrDef *dl;
998 char *type;
999 int n = 0;
1000
1001 /*
1002 * Emit type declarations.
1003 */
1004
1005 if (dfltTokenType) {
1006#ifdef COMMENTARY
1007 fprintf(fout, "\n/*\n * Generated type declarations:\n */\n");
1008#endif
1009 for (ul = tokenSet; ul; ul = ul->next, n++) {
1010 fprintf(fout, "%%type <%s> ", dfltTokenType);
1011 prWord(fout, ul->info.name);
1012 fprintf(fout, "\n");
1013 }
1014 fprintf(fout, "\n");
1015 }
1016
1017 for (dl = phrDefList; dl; dl = dl->next) {
1018 if (dl->name[0] == '`')
1019 continue;
1020 if (dl->argc == 0) {
1021 type = 0;
1022 if (dl->type)
1023 type = dl->type;
1024 else if (dfltRuleType)
1025 type = dfltRuleType;
1026 if (type && strcmp(type, "void")) {
1027 n++;
1028 fprintf(fout, "%%type <%s> %s\n",
1029 type, dl->name);
1030 }
1031 }
1032 else for (ul = genSet; ul; ul = ul->next) {
1033 if (!strcmp(dl->name, ul->info.name)) {
1034 type = 0;
1035 if (dl->type)
1036 type = dl->type;
1037 else if (dfltRuleType)
1038 type = dfltRuleType;
1039 if (type && strcmp(type, "void")) {
1040 n++;
1041 fprintf(fout, "%%type <%s> ", type);
1042 fprintInfo(fout, &(ul->info));
1043 fprintf(fout, "\n");
1044 }
1045 }
1046 }
1047 }
1048 if (n > 0)
1049 fprintf(fout,"\n");
1050}
1051
1052void
1053_2_wholeEpilog()
1054{
1055 while (yylex() != 0) ;
1056
1057 token(TK_Other282, ""); /* Force echo of last token read */
1058}
1059
1060void
1061_2_seeIncludeEnum(char *fname, char *ename)
1062{
1063 EnumItem el, tl;
1064 el = skimEnums(fname, 1, &ename);
1065
1066#ifdef COMMENTARY
1067 fprintf(fout, "\n/*\n * Included token declarations:\n */\n");
1068#endif
1069 for (tl = el; tl; tl = tl->next) {
1070 if (isExtra(tl->id)) continue;
1071 fprintf(fout, "%%token %s%s %d\n", prefix, tl->id, tl->value);
1072 }
1073 fprintf(fout, "\n");
1074
1075 skimFree(el);
1076}
1077
1078void
1079_2_startCommand()
1080{
1081 tokEcho = 0;
1082}
1083
1084void
1085_2_endCommand()
1086{
1087 tokEcho = 1;
1088}
1089
1090void
1091_2_startPhraseName()
1092{
1093}
1094
1095void
1096_2_seeName(char *str)
1097{
1098}
1099
1100void
1101_2_seeArg(char *str)
1102{
1103}
1104
1105void
1106_2_endPhraseName()
1107{
1108}
1109
1110void
1111_2_seeType(char *str)
1112{
1113}
1114
1115void
1116_2_startRule()
1117{
1118 tokEcho = 0;
1119 tokListHead = tokListTail;
1120}
1121
1122void
1123_2_midRule()
1124{
1125}
1126
1127void
1128_2_endRule()
1129{
1130 tokEcho = 1;
1131 handleRule(tokListHead);
1132}
1133
1134
1135struct tokList *
1136nextMeaty(struct tokList *tl)
1137{
1138 while (tl && (tl->tag == TK_Space263 || tl->tag == TK_Comment262))
1139 tl = tl->next;
1140 return tl;
1141}
1142
1143void
1144emitRule(struct tokList *tl0, struct phrUse *use)
1145{
1146 struct tokList *tl;
1147 char *str;
1148
1149 for (tl = tl0; tl; tl = tl->next) {
1150 if (!tl->show) continue;
1151
1152 str = tl->str;
1153
1154 switch (tl->tag) {
1155 case TK_CTok281:
1156 case TK_Id258: {
1157 if (use) {
1158 int a = unnameBV(str);
1159 if (a >= 0) str = use->info.argv[a];
1160 }
1161 if (*str == '`') str++;
1162 prWord(fout, str);
1163 break;
1164 }
1165 case TK_OPren268:
1166 case TK_Comma266:
1167 case TK_CPren269:
1168 fprintf(fout, "_");
1169 break;
1170 default:
1171 fprintf(fout, "%s", str);
1172 }
1173 }
1174}
1175
1176
1177void
1178handleRule(struct tokList *tl0)
1179{
1180 struct tokList *tl;
1181 struct phrInfo info;
1182 struct phrUse *ul;
1183 int inAppl, inType; /* For removing words */
1184 int n;
1185
1186 /*
1187 * Preprocess:
1188 * 1. Remove type decl as well as spaces and comments within
1189 * metarule applications.
1190 * 2. Rename bound variables to standard names.
1191 */
1192
1193 inAppl = inType = 0;
1194 for (tl = tl0; tl; tl = tl->next) {
1195 if (tl->tag == TK_Id258) {
1196 struct tokList *tn = nextMeaty(tl->next);
1197 inAppl = inAppl || (tn && tn->tag == TK_OPren268);
1198 }
1199 else if (tl->tag == TK_OAngle272) {
1200 inType = 1;
1201 }
1202
1203 if (inAppl && (tl->tag == TK_Comment262 || tl->tag == TK_Space263))
1204 tl->show = 0;
1205 else if (inType)
1206 tl->show = 0;
1207 else
1208 tl->show = 1;
1209
1210 if (tl->tag == TK_CPren269) {
1211 inAppl = 0;
1212 }
1213 else if (tl->tag == TK_CAngle273) {
1214 inType = 0;
1215 }
1216 }
1217
1218 info.name = 0;
1219 info.argc = 0;
1220
1221 for (tl = tl0; tl; tl = tl->next) {
1222 if (!tl->show)
1223 continue;
1224 if (tl->tag == TK_Id258) {
1225 if (!info.name)
1226 info.name = tl->str;
1227 else
1228 info.argv[info.argc++] = tl->str;
1229 }
1230 else if (tl->tag == TK_Colon264)
1231 break;
1232 }
1233
1234 for (tl = tl0; tl; tl = tl->next) {
1235 if (tl->tag == TK_Id258 || tl->tag == TK_CTok281)
1236 tl->str = renameBV(tl->str, &info);
1237 }
1238
1239 /*
1240 * Emit rule instances.
1241 */
1242
1243 if (info.argc == 0) {
1244 emitRule(tl0, 0);
1245 }
1246 else for (n = 0, ul = genSet; ul; n++, ul = ul->next) {
1247 if (!strcmp(info.name, ul->info.name)) {
1248 if (n != 0) fprintf(fout, "\n");
1249 emitRule(tl0, ul);
1250 }
1251 }
1252}
1253
1254/*****************************************************************************
1255 *
1256 * :: Utilities
1257 *
1258 *****************************************************************************/
1259
1260char *
1261mustAlloc(int n)
1262{
1263 /*extern char *malloc();*/
1264 char *s;
1265 s = malloc(n);
1266 if (!s) fatalErr();
1267 return s;
1268}
1269
1270char *
1271strAlloc(char *str)
1272{
1273 return strcpy(mustAlloc(strlen(str) + 1), str);
1274}
1275
1276char *
1277fnameDir(char *fn)
1278{
1279 int i, n, slashPos;
1280 char *d;
1281
1282 n = strlen(fn);
1283 slashPos = -1;
1284 for (i = n-1; i >= 0 && slashPos == -1; i--)
1285 if (fn[i] == '/') slashPos = i;
1286
1287 if (slashPos == -1)
1288 d = strAlloc(".");
1289 else {
1290 d = mustAlloc(slashPos+1);
1291 strncpy(d, fn, slashPos);
1292 d[slashPos] = 0;
1293 }
1294 return d;
1295}
1296
1297FILE *
1298mustOpen(char *fname, char *mode)
1299{
1300 FILE *f;
1301 f = fopen(fname, mode);
1302 if (!f) fatalErr();
1303 return f;
1304}
1305
1306char *
1307timeNow()
1308{
1309 char *s;
1310 long t;
1311
1312 t = time(0);
1313 s = ctime(&t);
1314
1315 s[strlen(s)-1] = 0;
1316 return s;
1317}
1318
1319void
1320fatalErr()
1321{
1322#if 0
1323 va_list argp;
1324#endif
1325
1326 fprintf(stderrstderr, "zacc (fatal error): ");
1327#if 0
1328 va_start(argp, fmt)__builtin_va_start(argp, fmt);
1329 vfprintf(stderrstderr, fmt, argp);
1330 va_end(argp)__builtin_va_end(argp);
1331#endif
1332 fprintf(stderrstderr, "\n");
1333
1334 exit(3);
1335}