periodic: Remove obsolete daily/status-named and weekly/clean-kvmdb
[dragonfly.git] / contrib / byacc / reader.c
blobebf40d2a6d147f42da0f6f4d069bcee75c0853da
1 /* $Id: reader.c,v 1.73 2017/07/09 19:15:35 tom Exp $ */
3 #include "defs.h"
5 /* The line size must be a positive integer. One hundred was chosen */
6 /* because few lines in Yacc input grammars exceed 100 characters. */
7 /* Note that if a line exceeds LINESIZE characters, the line buffer */
8 /* will be expanded to accomodate it. */
10 #define LINESIZE 100
12 #define L_CURL '{'
13 #define R_CURL '}'
14 #define L_PAREN '('
15 #define R_PAREN ')'
16 #define L_BRAC '['
17 #define R_BRAC ']'
19 /* the maximum number of arguments (inherited attributes) to a non-terminal */
20 /* this is a hard limit, but seems more than adequate */
21 #define MAXARGS 20
23 static void start_rule(bucket *bp, int s_lineno);
24 #if defined(YYBTYACC)
25 static void copy_initial_action(void);
26 static void copy_destructor(void);
27 static char *process_destructor_XX(char *code, char *tag);
28 #endif
30 #define CACHE_SIZE 256
31 static char *cache;
32 static int cinc, cache_size;
34 int ntags;
35 static int tagmax, havetags;
36 static char **tag_table;
38 static char saw_eof;
39 char unionized;
40 char *cptr, *line;
41 static int linesize;
43 static bucket *goal;
44 static Value_t prec;
45 static int gensym;
46 static char last_was_action;
47 #if defined(YYBTYACC)
48 static int trialaction;
49 #endif
51 static int maxitems;
52 static bucket **pitem;
54 static int maxrules;
55 static bucket **plhs;
57 static size_t name_pool_size;
58 static char *name_pool;
60 char line_format[] = "#line %d \"%s\"\n";
62 param *lex_param;
63 param *parse_param;
65 #if defined(YYBTYACC)
66 int destructor = 0; /* =1 if at least one %destructor */
68 static bucket *default_destructor[3] =
69 {0, 0, 0};
71 #define UNTYPED_DEFAULT 0
72 #define TYPED_DEFAULT 1
73 #define TYPE_SPECIFIED 2
75 static bucket *
76 lookup_type_destructor(char *tag)
78 const char fmt[] = "%.*s destructor";
79 char name[1024] = "\0";
80 bucket *bp, **bpp = &default_destructor[TYPE_SPECIFIED];
82 while ((bp = *bpp) != NULL)
84 if (bp->tag == tag)
85 return (bp);
86 bpp = &bp->link;
89 sprintf(name, fmt, (int)(sizeof(name) - sizeof(fmt)), tag);
90 *bpp = bp = make_bucket(name);
91 bp->tag = tag;
93 return (bp);
95 #endif /* defined(YYBTYACC) */
97 static void
98 cachec(int c)
100 assert(cinc >= 0);
101 if (cinc >= cache_size)
103 cache_size += CACHE_SIZE;
104 cache = TREALLOC(char, cache, cache_size);
105 NO_SPACE(cache);
107 cache[cinc] = (char)c;
108 ++cinc;
111 typedef enum
113 ldSPC1,
114 ldSPC2,
115 ldNAME,
116 ldSPC3,
117 ldNUM,
118 ldSPC4,
119 ldFILE,
120 ldOK,
121 ldERR
123 LINE_DIR;
126 * Expect this pattern:
127 * /^[[:space:]]*#[[:space:]]*
128 * line[[:space:]]+
129 * [[:digit:]]+
130 * ([[:space:]]*|[[:space:]]+"[^"]+")/
132 static int
133 line_directive(void)
135 #define UNLESS(what) if (what) { ld = ldERR; break; }
136 int n;
137 int line_1st = -1;
138 int name_1st = -1;
139 int name_end = -1;
140 LINE_DIR ld = ldSPC1;
141 for (n = 0; (ld <= ldOK) && (line[n] != '\0'); ++n)
143 int ch = UCH(line[n]);
144 switch (ld)
146 case ldSPC1:
147 if (isspace(UCH(ch)))
149 break;
151 else
152 UNLESS(ch != '#');
153 ld = ldSPC2;
154 break;
155 case ldSPC2:
156 if (isspace(UCH(ch)))
158 break;
160 /* FALLTHRU */
161 case ldNAME:
162 UNLESS(strncmp(line + n, "line", 4));
163 n += 4;
164 if (line[n] == '\0')
166 ld = ldOK;
167 break;
169 else
170 UNLESS(!isspace(UCH(line[n])));
171 ld = ldSPC3;
172 break;
173 case ldSPC3:
174 if (isspace(UCH(ch)))
176 break;
178 else
179 UNLESS(!isdigit(UCH(ch)));
180 line_1st = n;
181 ld = ldNUM;
182 /* FALLTHRU */
183 case ldNUM:
184 if (isdigit(UCH(ch)))
186 break;
188 else
189 UNLESS(!isspace(UCH(ch)));
190 ld = ldSPC4;
191 break;
192 case ldSPC4:
193 if (isspace(UCH(ch)))
195 break;
197 else
198 UNLESS(ch != '"');
199 UNLESS(line[n + 1] == '"');
200 ld = ldFILE;
201 name_1st = n;
202 break;
203 case ldFILE:
204 if (ch != '"')
206 break;
208 ld = ldOK;
209 name_end = n;
210 /* FALLTHRU */
211 case ldERR:
212 case ldOK:
213 break;
217 if (ld == ldOK)
219 size_t need = (size_t) (name_end - name_1st);
220 if ((long)need > (long)input_file_name_len)
222 input_file_name_len = ((need + 1) * 3) / 2;
223 input_file_name = TREALLOC(char, input_file_name, input_file_name_len);
224 NO_SPACE(input_file_name);
226 if ((long)need > 0)
228 memcpy(input_file_name, line + name_1st + 1, need - 1);
229 input_file_name[need - 1] = '\0';
231 else
233 input_file_name[0] = '\0';
237 if (ld >= ldNUM && ld < ldERR)
239 if (line_1st >= 0)
241 lineno = (int)strtol(line + line_1st, NULL, 10) - 1;
243 else
245 lineno = 0;
249 return (ld == ldOK);
250 #undef UNLESS
253 static void
254 get_line(void)
256 FILE *f = input_file;
257 int c;
258 int i;
262 if (saw_eof || (c = getc(f)) == EOF)
264 if (line)
266 FREE(line);
267 line = 0;
269 cptr = 0;
270 saw_eof = 1;
271 return;
274 if (line == NULL || linesize != (LINESIZE + 1))
276 if (line)
277 FREE(line);
278 linesize = LINESIZE + 1;
279 line = TMALLOC(char, linesize);
280 NO_SPACE(line);
283 i = 0;
284 ++lineno;
285 for (;;)
287 line[i++] = (char)c;
288 if (c == '\n')
289 break;
290 if ((i + 3) >= linesize)
292 linesize += LINESIZE;
293 line = TREALLOC(char, line, linesize);
294 NO_SPACE(line);
296 c = getc(f);
297 if (c == EOF)
299 line[i++] = '\n';
300 saw_eof = 1;
301 break;
304 line[i] = '\0';
306 while (line_directive());
307 cptr = line;
308 return;
311 static char *
312 dup_line(void)
314 char *p, *s, *t;
316 if (line == NULL)
317 return (NULL);
318 s = line;
319 while (*s != '\n')
320 ++s;
321 p = TMALLOC(char, s - line + 1);
322 NO_SPACE(p);
324 s = line;
325 t = p;
326 while ((*t++ = *s++) != '\n')
327 continue;
328 return (p);
331 static void
332 skip_comment(void)
334 char *s;
335 struct ainfo a;
336 a.a_lineno = lineno;
337 a.a_line = dup_line();
338 a.a_cptr = a.a_line + (cptr - line);
340 s = cptr + 2;
341 for (;;)
343 if (*s == '*' && s[1] == '/')
345 cptr = s + 2;
346 FREE(a.a_line);
347 return;
349 if (*s == '\n')
351 get_line();
352 if (line == NULL)
353 unterminated_comment(&a);
354 s = cptr;
356 else
357 ++s;
361 static int
362 next_inline(void)
364 char *s;
366 if (line == NULL)
368 get_line();
369 if (line == NULL)
370 return (EOF);
373 s = cptr;
374 for (;;)
376 switch (*s)
378 case '/':
379 if (s[1] == '*')
381 cptr = s;
382 skip_comment();
383 s = cptr;
384 break;
386 else if (s[1] == '/')
388 get_line();
389 if (line == NULL)
390 return (EOF);
391 s = cptr;
392 break;
394 /* FALLTHRU */
396 default:
397 cptr = s;
398 return (*s);
403 static int
404 nextc(void)
406 int ch;
407 int finish = 0;
411 switch (ch = next_inline())
413 case '\n':
414 get_line();
415 break;
416 case ' ':
417 case '\t':
418 case '\f':
419 case '\r':
420 case '\v':
421 case ',':
422 case ';':
423 ++cptr;
424 break;
425 case '\\':
426 ch = '%';
427 /* FALLTHRU */
428 default:
429 finish = 1;
430 break;
433 while (!finish);
435 return ch;
437 /* *INDENT-OFF* */
438 static struct keyword
440 char name[14];
441 int token;
443 keywords[] = {
444 { "binary", NONASSOC },
445 { "debug", XXXDEBUG },
446 #if defined(YYBTYACC)
447 { "destructor", DESTRUCTOR },
448 #endif
449 { "error-verbose",ERROR_VERBOSE },
450 { "expect", EXPECT },
451 { "expect-rr", EXPECT_RR },
452 { "ident", IDENT },
453 #if defined(YYBTYACC)
454 { "initial-action", INITIAL_ACTION },
455 #endif
456 { "left", LEFT },
457 { "lex-param", LEX_PARAM },
458 #if defined(YYBTYACC)
459 { "locations", LOCATIONS },
460 #endif
461 { "nonassoc", NONASSOC },
462 { "parse-param", PARSE_PARAM },
463 { "pure-parser", PURE_PARSER },
464 { "right", RIGHT },
465 { "start", START },
466 { "term", TOKEN },
467 { "token", TOKEN },
468 { "token-table", TOKEN_TABLE },
469 { "type", TYPE },
470 { "union", UNION },
471 { "yacc", POSIX_YACC },
473 /* *INDENT-ON* */
475 static int
476 compare_keys(const void *a, const void *b)
478 const struct keyword *p = (const struct keyword *)a;
479 const struct keyword *q = (const struct keyword *)b;
480 return strcmp(p->name, q->name);
483 static int
484 keyword(void)
486 int c;
487 char *t_cptr = cptr;
488 struct keyword *key;
490 c = *++cptr;
491 if (isalpha(UCH(c)))
493 cinc = 0;
494 for (;;)
496 if (isalpha(UCH(c)))
498 if (isupper(UCH(c)))
499 c = tolower(c);
500 cachec(c);
502 else if (isdigit(UCH(c))
503 || c == '-'
504 || c == '.'
505 || c == '$')
507 cachec(c);
509 else if (c == '_')
511 /* treat keywords spelled with '_' as if it were '-' */
512 cachec('-');
514 else
516 break;
518 c = *++cptr;
520 cachec(NUL);
522 if ((key = bsearch(cache, keywords,
523 sizeof(keywords) / sizeof(*key),
524 sizeof(*key), compare_keys)))
525 return key->token;
527 else
529 ++cptr;
530 if (c == L_CURL)
531 return (TEXT);
532 if (c == '%' || c == '\\')
533 return (MARK);
534 if (c == '<')
535 return (LEFT);
536 if (c == '>')
537 return (RIGHT);
538 if (c == '0')
539 return (TOKEN);
540 if (c == '2')
541 return (NONASSOC);
543 syntax_error(lineno, line, t_cptr);
544 /*NOTREACHED */
547 static void
548 copy_ident(void)
550 int c;
551 FILE *f = output_file;
553 c = nextc();
554 if (c == EOF)
555 unexpected_EOF();
556 if (c != '"')
557 syntax_error(lineno, line, cptr);
558 ++outline;
559 fprintf(f, "#ident \"");
560 for (;;)
562 c = *++cptr;
563 if (c == '\n')
565 fprintf(f, "\"\n");
566 return;
568 putc(c, f);
569 if (c == '"')
571 putc('\n', f);
572 ++cptr;
573 return;
578 static char *
579 copy_string(int quote)
581 struct mstring *temp = msnew();
582 int c;
583 struct ainfo a;
584 a.a_lineno = lineno;
585 a.a_line = dup_line();
586 a.a_cptr = a.a_line + (cptr - line - 1);
588 for (;;)
590 c = *cptr++;
591 mputc(temp, c);
592 if (c == quote)
594 FREE(a.a_line);
595 return msdone(temp);
597 if (c == '\n')
598 unterminated_string(&a);
599 if (c == '\\')
601 c = *cptr++;
602 mputc(temp, c);
603 if (c == '\n')
605 get_line();
606 if (line == NULL)
607 unterminated_string(&a);
613 static char *
614 copy_comment(void)
616 struct mstring *temp = msnew();
617 int c;
619 c = *cptr;
620 if (c == '/')
622 mputc(temp, '*');
623 while ((c = *++cptr) != '\n')
625 mputc(temp, c);
626 if (c == '*' && cptr[1] == '/')
627 mputc(temp, ' ');
629 mputc(temp, '*');
630 mputc(temp, '/');
632 else if (c == '*')
634 struct ainfo a;
635 a.a_lineno = lineno;
636 a.a_line = dup_line();
637 a.a_cptr = a.a_line + (cptr - line - 1);
639 mputc(temp, c);
640 ++cptr;
641 for (;;)
643 c = *cptr++;
644 mputc(temp, c);
645 if (c == '*' && *cptr == '/')
647 mputc(temp, '/');
648 ++cptr;
649 FREE(a.a_line);
650 return msdone(temp);
652 if (c == '\n')
654 get_line();
655 if (line == NULL)
656 unterminated_comment(&a);
660 return msdone(temp);
663 static void
664 copy_text(void)
666 int c;
667 FILE *f = text_file;
668 int need_newline = 0;
669 struct ainfo a;
670 a.a_lineno = lineno;
671 a.a_line = dup_line();
672 a.a_cptr = a.a_line + (cptr - line - 2);
674 if (*cptr == '\n')
676 get_line();
677 if (line == NULL)
678 unterminated_text(&a);
680 if (!lflag)
681 fprintf(f, line_format, lineno, input_file_name);
683 loop:
684 c = *cptr++;
685 switch (c)
687 case '\n':
688 putc('\n', f);
689 need_newline = 0;
690 get_line();
691 if (line)
692 goto loop;
693 unterminated_text(&a);
695 case '\'':
696 case '"':
697 putc(c, f);
699 char *s = copy_string(c);
700 fputs(s, f);
701 free(s);
703 need_newline = 1;
704 goto loop;
706 case '/':
707 putc(c, f);
709 char *s = copy_comment();
710 fputs(s, f);
711 free(s);
713 need_newline = 1;
714 goto loop;
716 case '%':
717 case '\\':
718 if (*cptr == R_CURL)
720 if (need_newline)
721 putc('\n', f);
722 ++cptr;
723 FREE(a.a_line);
724 return;
726 /* FALLTHRU */
728 default:
729 putc(c, f);
730 need_newline = 1;
731 goto loop;
735 static void
736 puts_both(const char *s)
738 fputs(s, text_file);
739 if (dflag)
740 fputs(s, union_file);
743 static void
744 putc_both(int c)
746 putc(c, text_file);
747 if (dflag)
748 putc(c, union_file);
751 static void
752 copy_union(void)
754 int c;
755 int depth;
756 struct ainfo a;
757 a.a_lineno = lineno;
758 a.a_line = dup_line();
759 a.a_cptr = a.a_line + (cptr - line - 6);
761 if (unionized)
762 over_unionized(cptr - 6);
763 unionized = 1;
765 puts_both("#ifdef YYSTYPE\n");
766 puts_both("#undef YYSTYPE_IS_DECLARED\n");
767 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
768 puts_both("#endif\n");
769 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
770 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
772 if (!lflag)
773 fprintf(text_file, line_format, lineno, input_file_name);
774 puts_both("typedef union");
776 depth = 0;
777 loop:
778 c = *cptr++;
779 putc_both(c);
780 switch (c)
782 case '\n':
783 get_line();
784 if (line == NULL)
785 unterminated_union(&a);
786 goto loop;
788 case L_CURL:
789 ++depth;
790 goto loop;
792 case R_CURL:
793 if (--depth == 0)
795 puts_both(" YYSTYPE;\n");
796 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
797 FREE(a.a_line);
798 return;
800 goto loop;
802 case '\'':
803 case '"':
805 char *s = copy_string(c);
806 puts_both(s);
807 free(s);
809 goto loop;
811 case '/':
813 char *s = copy_comment();
814 puts_both(s);
815 free(s);
817 goto loop;
819 default:
820 goto loop;
824 static char *
825 after_blanks(char *s)
827 while (*s != '\0' && isspace(UCH(*s)))
828 ++s;
829 return s;
833 * Trim leading/trailing blanks, and collapse multiple embedded blanks to a
834 * single space. Return index to last character in the buffer.
836 static int
837 trim_blanks(char *buffer)
839 if (*buffer != '\0')
841 char *d = buffer;
842 char *s = after_blanks(d);
844 while ((*d++ = *s++) != '\0')
849 --d;
850 while ((--d != buffer) && isspace(UCH(*d)))
851 *d = '\0';
853 for (s = d = buffer; (*d++ = *s++) != '\0';)
855 if (isspace(UCH(*s)))
857 *s = ' ';
858 while (isspace(UCH(*s)))
860 *s++ = ' ';
862 --s;
867 return (int)strlen(buffer) - 1;
871 * Scan forward in the current line-buffer looking for a right-curly bracket.
873 * Parameters begin with a left-curly bracket, and continue until there are no
874 * more interesting characters after the last right-curly bracket on the
875 * current line. Bison documents parameters as separated like this:
876 * {type param1} {type2 param2}
877 * but also accepts commas (although some versions of bison mishandle this)
878 * {type param1, type2 param2}
880 static int
881 more_curly(void)
883 char *save = cptr;
884 int result = 0;
885 int finish = 0;
888 switch (next_inline())
890 case 0:
891 case '\n':
892 finish = 1;
893 break;
894 case R_CURL:
895 finish = 1;
896 result = 1;
897 break;
899 ++cptr;
901 while (!finish);
902 cptr = save;
903 return result;
906 static void
907 save_param(int k, char *buffer, int name, int type2)
909 param *head, *p;
911 p = TMALLOC(param, 1);
912 NO_SPACE(p);
914 p->type2 = strdup(buffer + type2);
915 NO_SPACE(p->type2);
916 buffer[type2] = '\0';
917 (void)trim_blanks(p->type2);
919 p->name = strdup(buffer + name);
920 NO_SPACE(p->name);
921 buffer[name] = '\0';
922 (void)trim_blanks(p->name);
924 p->type = strdup(buffer);
925 NO_SPACE(p->type);
926 (void)trim_blanks(p->type);
928 if (k == LEX_PARAM)
929 head = lex_param;
930 else
931 head = parse_param;
933 if (head != NULL)
935 while (head->next)
936 head = head->next;
937 head->next = p;
939 else
941 if (k == LEX_PARAM)
942 lex_param = p;
943 else
944 parse_param = p;
946 p->next = NULL;
950 * Keep a linked list of parameters. This may be multi-line, if the trailing
951 * right-curly bracket is absent.
953 static void
954 copy_param(int k)
956 int c;
957 int name, type2;
958 int curly = 0;
959 char *buf = 0;
960 int i = -1;
961 size_t buf_size = 0;
962 int st_lineno = lineno;
963 char *comma;
967 int state = curly;
968 c = next_inline();
969 switch (c)
971 case EOF:
972 unexpected_EOF();
973 break;
974 case L_CURL:
975 if (curly == 1)
977 goto oops;
979 curly = 1;
980 st_lineno = lineno;
981 break;
982 case R_CURL:
983 if (curly != 1)
985 goto oops;
987 curly = 2;
988 break;
989 case '\n':
990 if (curly == 0)
992 goto oops;
994 break;
995 case '%':
996 if ((curly == 1) && (cptr == line))
998 lineno = st_lineno;
999 missing_brace();
1001 /* FALLTHRU */
1002 case '"':
1003 case '\'':
1004 goto oops;
1005 default:
1006 if (curly == 0 && !isspace(UCH(c)))
1008 goto oops;
1010 break;
1012 if (buf == 0)
1014 buf_size = (size_t) linesize;
1015 buf = TMALLOC(char, buf_size);
1017 else if (c == '\n')
1019 get_line();
1020 if (line == NULL)
1021 unexpected_EOF();
1022 --cptr;
1023 buf_size += (size_t) linesize;
1024 buf = TREALLOC(char, buf, buf_size);
1026 NO_SPACE(buf);
1027 if (curly)
1029 if ((state == 2) && (c == L_CURL))
1031 buf[++i] = ',';
1033 else if ((state == 2) && isspace(UCH(c)))
1037 else if ((c != L_CURL) && (c != R_CURL))
1039 buf[++i] = (char)c;
1042 cptr++;
1044 while (curly < 2 || more_curly());
1046 if (i == 0)
1048 if (curly == 1)
1050 lineno = st_lineno;
1051 missing_brace();
1053 goto oops;
1056 buf[++i] = '\0';
1057 (void)trim_blanks(buf);
1059 comma = buf - 1;
1062 char *parms = (comma + 1);
1063 comma = strchr(parms, ',');
1064 if (comma != 0)
1065 *comma = '\0';
1067 (void)trim_blanks(parms);
1068 i = (int)strlen(parms) - 1;
1069 if (i < 0)
1071 goto oops;
1074 if (parms[i] == ']')
1076 int level = 1;
1077 while (i >= 0 && level > 0 && parms[i] != '[')
1079 if (parms[i] == ']')
1080 ++level;
1081 else if (parms[i] == '[')
1082 --level;
1083 i--;
1085 if (i <= 0)
1086 unexpected_EOF();
1087 type2 = i--;
1089 else
1091 type2 = i + 1;
1094 while (i > 0 && (isalnum(UCH(parms[i])) || UCH(parms[i]) == '_'))
1095 i--;
1097 if (!isspace(UCH(parms[i])) && parms[i] != '*')
1098 goto oops;
1100 name = i + 1;
1102 save_param(k, parms, name, type2);
1104 while (comma != 0);
1105 FREE(buf);
1106 return;
1108 oops:
1109 FREE(buf);
1110 syntax_error(lineno, line, cptr);
1113 static int
1114 hexval(int c)
1116 if (c >= '0' && c <= '9')
1117 return (c - '0');
1118 if (c >= 'A' && c <= 'F')
1119 return (c - 'A' + 10);
1120 if (c >= 'a' && c <= 'f')
1121 return (c - 'a' + 10);
1122 return (-1);
1125 static bucket *
1126 get_literal(void)
1128 int c, quote;
1129 int i;
1130 int n;
1131 char *s;
1132 bucket *bp;
1133 struct ainfo a;
1134 a.a_lineno = lineno;
1135 a.a_line = dup_line();
1136 a.a_cptr = a.a_line + (cptr - line);
1138 quote = *cptr++;
1139 cinc = 0;
1140 for (;;)
1142 c = *cptr++;
1143 if (c == quote)
1144 break;
1145 if (c == '\n')
1146 unterminated_string(&a);
1147 if (c == '\\')
1149 char *c_cptr = cptr - 1;
1151 c = *cptr++;
1152 switch (c)
1154 case '\n':
1155 get_line();
1156 if (line == NULL)
1157 unterminated_string(&a);
1158 continue;
1160 case '0':
1161 case '1':
1162 case '2':
1163 case '3':
1164 case '4':
1165 case '5':
1166 case '6':
1167 case '7':
1168 n = c - '0';
1169 c = *cptr;
1170 if (IS_OCTAL(c))
1172 n = (n << 3) + (c - '0');
1173 c = *++cptr;
1174 if (IS_OCTAL(c))
1176 n = (n << 3) + (c - '0');
1177 ++cptr;
1180 if (n > MAXCHAR)
1181 illegal_character(c_cptr);
1182 c = n;
1183 break;
1185 case 'x':
1186 c = *cptr++;
1187 n = hexval(c);
1188 if (n < 0 || n >= 16)
1189 illegal_character(c_cptr);
1190 for (;;)
1192 c = *cptr;
1193 i = hexval(c);
1194 if (i < 0 || i >= 16)
1195 break;
1196 ++cptr;
1197 n = (n << 4) + i;
1198 if (n > MAXCHAR)
1199 illegal_character(c_cptr);
1201 c = n;
1202 break;
1204 case 'a':
1205 c = 7;
1206 break;
1207 case 'b':
1208 c = '\b';
1209 break;
1210 case 'f':
1211 c = '\f';
1212 break;
1213 case 'n':
1214 c = '\n';
1215 break;
1216 case 'r':
1217 c = '\r';
1218 break;
1219 case 't':
1220 c = '\t';
1221 break;
1222 case 'v':
1223 c = '\v';
1224 break;
1227 cachec(c);
1229 FREE(a.a_line);
1231 n = cinc;
1232 s = TMALLOC(char, n);
1233 NO_SPACE(s);
1235 for (i = 0; i < n; ++i)
1236 s[i] = cache[i];
1238 cinc = 0;
1239 if (n == 1)
1240 cachec('\'');
1241 else
1242 cachec('"');
1244 for (i = 0; i < n; ++i)
1246 c = UCH(s[i]);
1247 if (c == '\\' || c == cache[0])
1249 cachec('\\');
1250 cachec(c);
1252 else if (isprint(UCH(c)))
1253 cachec(c);
1254 else
1256 cachec('\\');
1257 switch (c)
1259 case 7:
1260 cachec('a');
1261 break;
1262 case '\b':
1263 cachec('b');
1264 break;
1265 case '\f':
1266 cachec('f');
1267 break;
1268 case '\n':
1269 cachec('n');
1270 break;
1271 case '\r':
1272 cachec('r');
1273 break;
1274 case '\t':
1275 cachec('t');
1276 break;
1277 case '\v':
1278 cachec('v');
1279 break;
1280 default:
1281 cachec(((c >> 6) & 7) + '0');
1282 cachec(((c >> 3) & 7) + '0');
1283 cachec((c & 7) + '0');
1284 break;
1289 if (n == 1)
1290 cachec('\'');
1291 else
1292 cachec('"');
1294 cachec(NUL);
1295 bp = lookup(cache);
1296 bp->class = TERM;
1297 if (n == 1 && bp->value == UNDEFINED)
1298 bp->value = UCH(*s);
1299 FREE(s);
1301 return (bp);
1304 static int
1305 is_reserved(char *name)
1307 char *s;
1309 if (strcmp(name, ".") == 0 ||
1310 strcmp(name, "$accept") == 0 ||
1311 strcmp(name, "$end") == 0)
1312 return (1);
1314 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
1316 s = name + 3;
1317 while (isdigit(UCH(*s)))
1318 ++s;
1319 if (*s == NUL)
1320 return (1);
1323 return (0);
1326 static bucket *
1327 get_name(void)
1329 int c;
1331 cinc = 0;
1332 for (c = *cptr; IS_IDENT(c); c = *++cptr)
1333 cachec(c);
1334 cachec(NUL);
1336 if (is_reserved(cache))
1337 used_reserved(cache);
1339 return (lookup(cache));
1342 static Value_t
1343 get_number(void)
1345 int c;
1346 long n;
1347 char *base = cptr;
1349 n = 0;
1350 for (c = *cptr; isdigit(UCH(c)); c = *++cptr)
1352 n = (10 * n + (c - '0'));
1353 if (n > MAXYYINT)
1355 syntax_error(lineno, line, base);
1356 n = 0;
1357 break;
1361 return (Value_t)(n);
1364 static char *
1365 cache_tag(char *tag, size_t len)
1367 int i;
1368 char *s;
1370 for (i = 0; i < ntags; ++i)
1372 if (strncmp(tag, tag_table[i], len) == 0 &&
1373 tag_table[i][len] == NUL)
1374 return (tag_table[i]);
1377 if (ntags >= tagmax)
1379 tagmax += 16;
1380 tag_table =
1381 (tag_table
1382 ? TREALLOC(char *, tag_table, tagmax)
1383 : TMALLOC(char *, tagmax));
1384 NO_SPACE(tag_table);
1387 s = TMALLOC(char, len + 1);
1388 NO_SPACE(s);
1390 strncpy(s, tag, len);
1391 s[len] = 0;
1392 tag_table[ntags++] = s;
1393 return s;
1396 static char *
1397 get_tag(void)
1399 int c;
1400 int t_lineno = lineno;
1401 char *t_line = dup_line();
1402 char *t_cptr = t_line + (cptr - line);
1404 ++cptr;
1405 c = nextc();
1406 if (c == EOF)
1407 unexpected_EOF();
1408 if (!IS_NAME1(c))
1409 illegal_tag(t_lineno, t_line, t_cptr);
1411 cinc = 0;
1414 cachec(c);
1415 c = *++cptr;
1417 while (IS_IDENT(c));
1418 cachec(NUL);
1420 c = nextc();
1421 if (c == EOF)
1422 unexpected_EOF();
1423 if (c != '>')
1424 illegal_tag(t_lineno, t_line, t_cptr);
1425 ++cptr;
1427 FREE(t_line);
1428 havetags = 1;
1429 return cache_tag(cache, (size_t) cinc);
1432 #if defined(YYBTYACC)
1433 static char *
1434 scan_id(void)
1436 char *b = cptr;
1438 while (IS_NAME2(UCH(*cptr)))
1439 cptr++;
1440 return cache_tag(b, (size_t) (cptr - b));
1442 #endif
1444 static void
1445 declare_tokens(int assoc)
1447 int c;
1448 bucket *bp;
1449 Value_t value;
1450 char *tag = 0;
1452 if (assoc != TOKEN)
1453 ++prec;
1455 c = nextc();
1456 if (c == EOF)
1457 unexpected_EOF();
1458 if (c == '<')
1460 tag = get_tag();
1461 c = nextc();
1462 if (c == EOF)
1463 unexpected_EOF();
1466 for (;;)
1468 if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
1469 bp = get_name();
1470 else if (c == '\'' || c == '"')
1471 bp = get_literal();
1472 else
1473 return;
1475 if (bp == goal)
1476 tokenized_start(bp->name);
1477 bp->class = TERM;
1479 if (tag)
1481 if (bp->tag && tag != bp->tag)
1482 retyped_warning(bp->name);
1483 bp->tag = tag;
1486 if (assoc != TOKEN)
1488 if (bp->prec && prec != bp->prec)
1489 reprec_warning(bp->name);
1490 bp->assoc = (Assoc_t)assoc;
1491 bp->prec = prec;
1494 c = nextc();
1495 if (c == EOF)
1496 unexpected_EOF();
1498 if (isdigit(UCH(c)))
1500 value = get_number();
1501 if (bp->value != UNDEFINED && value != bp->value)
1502 revalued_warning(bp->name);
1503 bp->value = value;
1504 c = nextc();
1505 if (c == EOF)
1506 unexpected_EOF();
1512 * %expect requires special handling
1513 * as it really isn't part of the yacc
1514 * grammar only a flag for yacc proper.
1516 static void
1517 declare_expect(int assoc)
1519 int c;
1521 if (assoc != EXPECT && assoc != EXPECT_RR)
1522 ++prec;
1525 * Stay away from nextc - doesn't
1526 * detect EOL and will read to EOF.
1528 c = *++cptr;
1529 if (c == EOF)
1530 unexpected_EOF();
1532 for (;;)
1534 if (isdigit(UCH(c)))
1536 if (assoc == EXPECT)
1537 SRexpect = get_number();
1538 else
1539 RRexpect = get_number();
1540 break;
1543 * Looking for number before EOL.
1544 * Spaces, tabs, and numbers are ok,
1545 * words, punc., etc. are syntax errors.
1547 else if (c == '\n' || isalpha(UCH(c)) || !isspace(UCH(c)))
1549 syntax_error(lineno, line, cptr);
1551 else
1553 c = *++cptr;
1554 if (c == EOF)
1555 unexpected_EOF();
1560 #if defined(YYBTYACC)
1561 static void
1562 declare_argtypes(bucket *bp)
1564 char *tags[MAXARGS];
1565 int args = 0, c;
1567 if (bp->args >= 0)
1568 retyped_warning(bp->name);
1569 cptr++; /* skip open paren */
1570 for (;;)
1572 c = nextc();
1573 if (c == EOF)
1574 unexpected_EOF();
1575 if (c != '<')
1576 syntax_error(lineno, line, cptr);
1577 tags[args++] = get_tag();
1578 c = nextc();
1579 if (c == R_PAREN)
1580 break;
1581 if (c == EOF)
1582 unexpected_EOF();
1584 cptr++; /* skip close paren */
1585 bp->args = args;
1586 bp->argnames = TMALLOC(char *, args);
1587 NO_SPACE(bp->argnames);
1588 bp->argtags = CALLOC(sizeof(char *), args + 1);
1589 NO_SPACE(bp->argtags);
1590 while (--args >= 0)
1592 bp->argtags[args] = tags[args];
1593 bp->argnames[args] = NULL;
1596 #endif
1598 static void
1599 declare_types(void)
1601 int c;
1602 bucket *bp = NULL;
1603 char *tag = NULL;
1605 c = nextc();
1606 if (c == EOF)
1607 unexpected_EOF();
1608 if (c == '<')
1609 tag = get_tag();
1611 for (;;)
1613 c = nextc();
1614 if (c == EOF)
1615 unexpected_EOF();
1616 if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
1618 bp = get_name();
1619 #if defined(YYBTYACC)
1620 if (nextc() == L_PAREN)
1621 declare_argtypes(bp);
1622 else
1623 bp->args = 0;
1624 #endif
1626 else if (c == '\'' || c == '"')
1628 bp = get_literal();
1629 #if defined(YYBTYACC)
1630 bp->args = 0;
1631 #endif
1633 else
1634 return;
1636 if (tag)
1638 if (bp->tag && tag != bp->tag)
1639 retyped_warning(bp->name);
1640 bp->tag = tag;
1645 static void
1646 declare_start(void)
1648 int c;
1649 bucket *bp;
1651 c = nextc();
1652 if (c == EOF)
1653 unexpected_EOF();
1654 if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '$')
1655 syntax_error(lineno, line, cptr);
1656 bp = get_name();
1657 if (bp->class == TERM)
1658 terminal_start(bp->name);
1659 if (goal && goal != bp)
1660 restarted_warning();
1661 goal = bp;
1664 static void
1665 read_declarations(void)
1667 int c, k;
1669 cache_size = CACHE_SIZE;
1670 cache = TMALLOC(char, cache_size);
1671 NO_SPACE(cache);
1673 for (;;)
1675 c = nextc();
1676 if (c == EOF)
1677 unexpected_EOF();
1678 if (c != '%')
1679 syntax_error(lineno, line, cptr);
1680 switch (k = keyword())
1682 case MARK:
1683 return;
1685 case IDENT:
1686 copy_ident();
1687 break;
1689 case TEXT:
1690 copy_text();
1691 break;
1693 case UNION:
1694 copy_union();
1695 break;
1697 case TOKEN:
1698 case LEFT:
1699 case RIGHT:
1700 case NONASSOC:
1701 declare_tokens(k);
1702 break;
1704 case EXPECT:
1705 case EXPECT_RR:
1706 declare_expect(k);
1707 break;
1709 case TYPE:
1710 declare_types();
1711 break;
1713 case START:
1714 declare_start();
1715 break;
1717 case PURE_PARSER:
1718 pure_parser = 1;
1719 break;
1721 case PARSE_PARAM:
1722 case LEX_PARAM:
1723 copy_param(k);
1724 break;
1726 case TOKEN_TABLE:
1727 token_table = 1;
1728 break;
1730 case ERROR_VERBOSE:
1731 error_verbose = 1;
1732 break;
1734 #if defined(YYBTYACC)
1735 case LOCATIONS:
1736 locations = 1;
1737 break;
1739 case DESTRUCTOR:
1740 destructor = 1;
1741 copy_destructor();
1742 break;
1743 case INITIAL_ACTION:
1744 copy_initial_action();
1745 break;
1746 #endif
1748 case XXXDEBUG:
1749 /* XXX: FIXME */
1750 break;
1752 case POSIX_YACC:
1753 /* noop for bison compatibility. byacc is already designed to be posix
1754 * yacc compatible. */
1755 break;
1760 static void
1761 initialize_grammar(void)
1763 nitems = 4;
1764 maxitems = 300;
1766 pitem = TMALLOC(bucket *, maxitems);
1767 NO_SPACE(pitem);
1769 pitem[0] = 0;
1770 pitem[1] = 0;
1771 pitem[2] = 0;
1772 pitem[3] = 0;
1774 nrules = 3;
1775 maxrules = 100;
1777 plhs = TMALLOC(bucket *, maxrules);
1778 NO_SPACE(plhs);
1780 plhs[0] = 0;
1781 plhs[1] = 0;
1782 plhs[2] = 0;
1784 rprec = TMALLOC(Value_t, maxrules);
1785 NO_SPACE(rprec);
1787 rprec[0] = 0;
1788 rprec[1] = 0;
1789 rprec[2] = 0;
1791 rassoc = TMALLOC(Assoc_t, maxrules);
1792 NO_SPACE(rassoc);
1794 rassoc[0] = TOKEN;
1795 rassoc[1] = TOKEN;
1796 rassoc[2] = TOKEN;
1799 static void
1800 expand_items(void)
1802 maxitems += 300;
1803 pitem = TREALLOC(bucket *, pitem, maxitems);
1804 NO_SPACE(pitem);
1807 static void
1808 expand_rules(void)
1810 maxrules += 100;
1812 plhs = TREALLOC(bucket *, plhs, maxrules);
1813 NO_SPACE(plhs);
1815 rprec = TREALLOC(Value_t, rprec, maxrules);
1816 NO_SPACE(rprec);
1818 rassoc = TREALLOC(Assoc_t, rassoc, maxrules);
1819 NO_SPACE(rassoc);
1822 /* set immediately prior to where copy_args() could be called, and incremented by
1823 the various routines that will rescan the argument list as appropriate */
1824 static int rescan_lineno;
1825 #if defined(YYBTYACC)
1827 static char *
1828 copy_args(int *alen)
1830 struct mstring *s = msnew();
1831 int depth = 0, len = 1;
1832 char c, quote = 0;
1833 struct ainfo a;
1835 a.a_lineno = lineno;
1836 a.a_line = dup_line();
1837 a.a_cptr = a.a_line + (cptr - line - 1);
1839 while ((c = *cptr++) != R_PAREN || depth || quote)
1841 if (c == ',' && !quote && !depth)
1843 len++;
1844 mputc(s, 0);
1845 continue;
1847 mputc(s, c);
1848 if (c == '\n')
1850 get_line();
1851 if (!line)
1853 if (quote)
1854 unterminated_string(&a);
1855 else
1856 unterminated_arglist(&a);
1859 else if (quote)
1861 if (c == quote)
1862 quote = 0;
1863 else if (c == '\\')
1865 if (*cptr != '\n')
1866 mputc(s, *cptr++);
1869 else
1871 if (c == L_PAREN)
1872 depth++;
1873 else if (c == R_PAREN)
1874 depth--;
1875 else if (c == '\"' || c == '\'')
1876 quote = c;
1879 if (alen)
1880 *alen = len;
1881 FREE(a.a_line);
1882 return msdone(s);
1885 static char *
1886 parse_id(char *p, char **save)
1888 char *b;
1890 while (isspace(UCH(*p)))
1891 if (*p++ == '\n')
1892 rescan_lineno++;
1893 if (!isalpha(UCH(*p)) && *p != '_')
1894 return NULL;
1895 b = p;
1896 while (IS_NAME2(UCH(*p)))
1897 p++;
1898 if (save)
1900 *save = cache_tag(b, (size_t) (p - b));
1902 return p;
1905 static char *
1906 parse_int(char *p, int *save)
1908 int neg = 0, val = 0;
1910 while (isspace(UCH(*p)))
1911 if (*p++ == '\n')
1912 rescan_lineno++;
1913 if (*p == '-')
1915 neg = 1;
1916 p++;
1918 if (!isdigit(UCH(*p)))
1919 return NULL;
1920 while (isdigit(UCH(*p)))
1921 val = val * 10 + *p++ - '0';
1922 if (neg)
1923 val = -val;
1924 if (save)
1925 *save = val;
1926 return p;
1929 static void
1930 parse_arginfo(bucket *a, char *args, int argslen)
1932 char *p = args, *tmp;
1933 int i, redec = 0;
1935 if (a->args >= 0)
1937 if (a->args != argslen)
1938 arg_number_disagree_warning(rescan_lineno, a->name);
1939 redec = 1;
1941 else
1943 if ((a->args = argslen) == 0)
1944 return;
1945 a->argnames = TMALLOC(char *, argslen);
1946 NO_SPACE(a->argnames);
1947 a->argtags = TMALLOC(char *, argslen);
1948 NO_SPACE(a->argtags);
1950 if (!args)
1951 return;
1952 for (i = 0; i < argslen; i++)
1954 while (isspace(UCH(*p)))
1955 if (*p++ == '\n')
1956 rescan_lineno++;
1957 if (*p++ != '$')
1958 bad_formals();
1959 while (isspace(UCH(*p)))
1960 if (*p++ == '\n')
1961 rescan_lineno++;
1962 if (*p == '<')
1964 havetags = 1;
1965 if (!(p = parse_id(p + 1, &tmp)))
1966 bad_formals();
1967 while (isspace(UCH(*p)))
1968 if (*p++ == '\n')
1969 rescan_lineno++;
1970 if (*p++ != '>')
1971 bad_formals();
1972 if (redec)
1974 if (a->argtags[i] != tmp)
1975 arg_type_disagree_warning(rescan_lineno, i + 1, a->name);
1977 else
1978 a->argtags[i] = tmp;
1980 else if (!redec)
1981 a->argtags[i] = NULL;
1982 if (!(p = parse_id(p, &a->argnames[i])))
1983 bad_formals();
1984 while (isspace(UCH(*p)))
1985 if (*p++ == '\n')
1986 rescan_lineno++;
1987 if (*p++)
1988 bad_formals();
1990 free(args);
1993 static char *
1994 compile_arg(char **theptr, char *yyvaltag)
1996 char *p = *theptr;
1997 struct mstring *c = msnew();
1998 int i, j, n;
1999 Value_t *offsets = NULL, maxoffset;
2000 bucket **rhs;
2002 maxoffset = 0;
2003 n = 0;
2004 for (i = nitems - 1; pitem[i]; --i)
2006 n++;
2007 if (pitem[i]->class != ARGUMENT)
2008 maxoffset++;
2010 if (maxoffset > 0)
2012 offsets = TMALLOC(Value_t, maxoffset + 1);
2013 NO_SPACE(offsets);
2015 for (j = 0, i++; i < nitems; i++)
2016 if (pitem[i]->class != ARGUMENT)
2017 offsets[++j] = (Value_t)(i - nitems + 1);
2019 rhs = pitem + nitems - 1;
2021 if (yyvaltag)
2022 msprintf(c, "yyval.%s = ", yyvaltag);
2023 else
2024 msprintf(c, "yyval = ");
2025 while (*p)
2027 if (*p == '$')
2029 char *tag = NULL;
2030 if (*++p == '<')
2031 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
2032 illegal_tag(rescan_lineno, NULL, NULL);
2033 if (isdigit(UCH(*p)) || *p == '-')
2035 int val;
2036 if (!(p = parse_int(p, &val)))
2037 dollar_error(rescan_lineno, NULL, NULL);
2038 if (val <= 0)
2039 i = val - n;
2040 else if (val > maxoffset)
2042 dollar_warning(rescan_lineno, val);
2043 i = val - maxoffset;
2045 else if (maxoffset > 0)
2047 i = offsets[val];
2048 if (!tag && !(tag = rhs[i]->tag) && havetags)
2049 untyped_rhs(val, rhs[i]->name);
2051 msprintf(c, "yystack.l_mark[%d]", i);
2052 if (tag)
2053 msprintf(c, ".%s", tag);
2054 else if (havetags)
2055 unknown_rhs(val);
2057 else if (isalpha(UCH(*p)) || *p == '_')
2059 char *arg;
2060 if (!(p = parse_id(p, &arg)))
2061 dollar_error(rescan_lineno, NULL, NULL);
2062 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2063 if (arg == plhs[nrules]->argnames[i])
2064 break;
2065 if (i < 0)
2066 unknown_arg_warning(rescan_lineno, "$", arg, NULL, NULL);
2067 else if (!tag)
2068 tag = plhs[nrules]->argtags[i];
2069 msprintf(c, "yystack.l_mark[%d]",
2070 i - plhs[nrules]->args + 1 - n);
2071 if (tag)
2072 msprintf(c, ".%s", tag);
2073 else if (havetags)
2074 untyped_arg_warning(rescan_lineno, "$", arg);
2076 else
2077 dollar_error(rescan_lineno, NULL, NULL);
2079 else if (*p == '@')
2081 at_error(rescan_lineno, NULL, NULL);
2083 else
2085 if (*p == '\n')
2086 rescan_lineno++;
2087 mputc(c, *p++);
2090 *theptr = p;
2091 if (maxoffset > 0)
2092 FREE(offsets);
2093 return msdone(c);
2096 static int
2097 can_elide_arg(char **theptr, char *yyvaltag)
2099 char *p = *theptr;
2100 int rv = 0;
2101 int i, j, n = 0;
2102 Value_t *offsets = NULL, maxoffset = 0;
2103 bucket **rhs;
2104 char *tag = 0;
2106 if (*p++ != '$')
2107 return 0;
2108 if (*p == '<')
2110 if (!(p = parse_id(++p, &tag)) || *p++ != '>')
2111 return 0;
2113 for (i = nitems - 1; pitem[i]; --i)
2115 n++;
2116 if (pitem[i]->class != ARGUMENT)
2117 maxoffset++;
2119 if (maxoffset > 0)
2121 offsets = TMALLOC(Value_t, maxoffset + 1);
2122 NO_SPACE(offsets);
2124 for (j = 0, i++; i < nitems; i++)
2125 if (pitem[i]->class != ARGUMENT)
2126 offsets[++j] = (Value_t)(i - nitems + 1);
2128 rhs = pitem + nitems - 1;
2130 if (isdigit(UCH(*p)) || *p == '-')
2132 int val;
2133 if (!(p = parse_int(p, &val)))
2134 rv = 0;
2135 else
2137 if (val <= 0)
2138 rv = 1 - val + n;
2139 else if (val > maxoffset)
2140 rv = 0;
2141 else
2143 i = offsets[val];
2144 rv = 1 - i;
2145 if (!tag)
2146 tag = rhs[i]->tag;
2150 else if (isalpha(UCH(*p)) || *p == '_')
2152 char *arg;
2153 if (!(p = parse_id(p, &arg)))
2154 return 0;
2155 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2156 if (arg == plhs[nrules]->argnames[i])
2157 break;
2158 if (i >= 0)
2160 if (!tag)
2161 tag = plhs[nrules]->argtags[i];
2162 rv = plhs[nrules]->args + n - i;
2165 if (tag && yyvaltag)
2167 if (strcmp(tag, yyvaltag))
2168 rv = 0;
2170 else if (tag || yyvaltag)
2171 rv = 0;
2172 if (maxoffset > 0)
2173 FREE(offsets);
2174 if (*p || rv <= 0)
2175 return 0;
2176 *theptr = p + 1;
2177 return rv;
2180 #define ARG_CACHE_SIZE 1024
2181 static struct arg_cache
2183 struct arg_cache *next;
2184 char *code;
2185 int rule;
2187 *arg_cache[ARG_CACHE_SIZE];
2189 static int
2190 lookup_arg_cache(char *code)
2192 struct arg_cache *entry;
2194 entry = arg_cache[strnshash(code) % ARG_CACHE_SIZE];
2195 while (entry)
2197 if (!strnscmp(entry->code, code))
2198 return entry->rule;
2199 entry = entry->next;
2201 return -1;
2204 static void
2205 insert_arg_cache(char *code, int rule)
2207 struct arg_cache *entry = NEW(struct arg_cache);
2208 int i;
2210 NO_SPACE(entry);
2211 i = strnshash(code) % ARG_CACHE_SIZE;
2212 entry->code = code;
2213 entry->rule = rule;
2214 entry->next = arg_cache[i];
2215 arg_cache[i] = entry;
2218 static void
2219 clean_arg_cache(void)
2221 struct arg_cache *e, *t;
2222 int i;
2224 for (i = 0; i < ARG_CACHE_SIZE; i++)
2226 for (e = arg_cache[i]; (t = e); e = e->next, FREE(t))
2227 free(e->code);
2228 arg_cache[i] = NULL;
2231 #endif /* defined(YYBTYACC) */
2233 static void
2234 advance_to_start(void)
2236 int c;
2237 bucket *bp;
2238 char *s_cptr;
2239 int s_lineno;
2240 #if defined(YYBTYACC)
2241 char *args = NULL;
2242 int argslen = 0;
2243 #endif
2245 for (;;)
2247 c = nextc();
2248 if (c != '%')
2249 break;
2250 s_cptr = cptr;
2251 switch (keyword())
2253 case MARK:
2254 no_grammar();
2256 case TEXT:
2257 copy_text();
2258 break;
2260 case START:
2261 declare_start();
2262 break;
2264 default:
2265 syntax_error(lineno, line, s_cptr);
2269 c = nextc();
2270 if (!isalpha(UCH(c)) && c != '_' && c != '.' && c != '_')
2271 syntax_error(lineno, line, cptr);
2272 bp = get_name();
2273 if (goal == 0)
2275 if (bp->class == TERM)
2276 terminal_start(bp->name);
2277 goal = bp;
2280 s_lineno = lineno;
2281 c = nextc();
2282 if (c == EOF)
2283 unexpected_EOF();
2284 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2285 #if defined(YYBTYACC)
2286 if (c == L_PAREN)
2288 ++cptr;
2289 args = copy_args(&argslen);
2290 NO_SPACE(args);
2291 c = nextc();
2293 #endif
2294 if (c != ':')
2295 syntax_error(lineno, line, cptr);
2296 start_rule(bp, s_lineno);
2297 #if defined(YYBTYACC)
2298 parse_arginfo(bp, args, argslen);
2299 #endif
2300 ++cptr;
2303 static void
2304 start_rule(bucket *bp, int s_lineno)
2306 if (bp->class == TERM)
2307 terminal_lhs(s_lineno);
2308 bp->class = NONTERM;
2309 if (!bp->index)
2310 bp->index = nrules;
2311 if (nrules >= maxrules)
2312 expand_rules();
2313 plhs[nrules] = bp;
2314 rprec[nrules] = UNDEFINED;
2315 rassoc[nrules] = TOKEN;
2318 static void
2319 end_rule(void)
2321 int i;
2323 if (!last_was_action && plhs[nrules]->tag)
2325 if (pitem[nitems - 1])
2327 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
2328 continue;
2329 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
2330 default_action_warning(plhs[nrules]->name);
2332 else
2333 default_action_warning(plhs[nrules]->name);
2336 last_was_action = 0;
2337 if (nitems >= maxitems)
2338 expand_items();
2339 pitem[nitems] = 0;
2340 ++nitems;
2341 ++nrules;
2344 static void
2345 insert_empty_rule(void)
2347 bucket *bp, **bpp;
2349 assert(cache);
2350 assert(cache_size >= CACHE_SIZE);
2351 sprintf(cache, "$$%d", ++gensym);
2352 bp = make_bucket(cache);
2353 last_symbol->next = bp;
2354 last_symbol = bp;
2355 bp->tag = plhs[nrules]->tag;
2356 bp->class = ACTION;
2357 #if defined(YYBTYACC)
2358 bp->args = 0;
2359 #endif
2361 nitems = (Value_t)(nitems + 2);
2362 if (nitems > maxitems)
2363 expand_items();
2364 bpp = pitem + nitems - 1;
2365 *bpp-- = bp;
2366 while ((bpp[0] = bpp[-1]) != 0)
2367 --bpp;
2369 if (++nrules >= maxrules)
2370 expand_rules();
2371 plhs[nrules] = plhs[nrules - 1];
2372 plhs[nrules - 1] = bp;
2373 rprec[nrules] = rprec[nrules - 1];
2374 rprec[nrules - 1] = 0;
2375 rassoc[nrules] = rassoc[nrules - 1];
2376 rassoc[nrules - 1] = TOKEN;
2379 #if defined(YYBTYACC)
2380 static char *
2381 insert_arg_rule(char *arg, char *tag)
2383 int line_number = rescan_lineno;
2384 char *code = compile_arg(&arg, tag);
2385 int rule = lookup_arg_cache(code);
2386 FILE *f = action_file;
2388 if (rule < 0)
2390 rule = nrules;
2391 insert_arg_cache(code, rule);
2392 trialaction = 1; /* arg rules always run in trial mode */
2393 fprintf(f, "case %d:\n", rule - 2);
2394 if (!lflag)
2395 fprintf(f, line_format, line_number, input_file_name);
2396 fprintf(f, "%s;\n", code);
2397 fprintf(f, "break;\n");
2398 insert_empty_rule();
2399 plhs[rule]->tag = cache_tag(tag, strlen(tag));
2400 plhs[rule]->class = ARGUMENT;
2402 else
2404 if (++nitems > maxitems)
2405 expand_items();
2406 pitem[nitems - 1] = plhs[rule];
2407 free(code);
2409 return arg + 1;
2411 #endif
2413 static void
2414 add_symbol(void)
2416 int c;
2417 bucket *bp;
2418 int s_lineno = lineno;
2419 #if defined(YYBTYACC)
2420 char *args = NULL;
2421 int argslen = 0;
2422 #endif
2424 c = *cptr;
2425 if (c == '\'' || c == '"')
2426 bp = get_literal();
2427 else
2428 bp = get_name();
2430 c = nextc();
2431 rescan_lineno = lineno; /* line# for possible inherited args rescan */
2432 #if defined(YYBTYACC)
2433 if (c == L_PAREN)
2435 ++cptr;
2436 args = copy_args(&argslen);
2437 NO_SPACE(args);
2438 c = nextc();
2440 #endif
2441 if (c == ':')
2443 end_rule();
2444 start_rule(bp, s_lineno);
2445 #if defined(YYBTYACC)
2446 parse_arginfo(bp, args, argslen);
2447 #endif
2448 ++cptr;
2449 return;
2452 if (last_was_action)
2453 insert_empty_rule();
2454 last_was_action = 0;
2456 #if defined(YYBTYACC)
2457 if (bp->args < 0)
2458 bp->args = argslen;
2459 if (argslen == 0 && bp->args > 0 && pitem[nitems - 1] == NULL)
2461 int i;
2462 if (plhs[nrules]->args != bp->args)
2463 wrong_number_args_warning("default ", bp->name);
2464 for (i = bp->args - 1; i >= 0; i--)
2465 if (plhs[nrules]->argtags[i] != bp->argtags[i])
2466 wrong_type_for_arg_warning(i + 1, bp->name);
2468 else if (bp->args != argslen)
2469 wrong_number_args_warning("", bp->name);
2470 if (args != 0)
2472 char *ap = args;
2473 int i = 0;
2474 int elide_cnt = can_elide_arg(&ap, bp->argtags[0]);
2476 if (elide_cnt > argslen)
2477 elide_cnt = 0;
2478 if (elide_cnt)
2480 for (i = 1; i < elide_cnt; i++)
2481 if (can_elide_arg(&ap, bp->argtags[i]) != elide_cnt - i)
2483 elide_cnt = 0;
2484 break;
2487 if (elide_cnt)
2489 assert(i == elide_cnt);
2491 else
2493 ap = args;
2494 i = 0;
2496 for (; i < argslen; i++)
2497 ap = insert_arg_rule(ap, bp->argtags[i]);
2498 free(args);
2500 #endif /* defined(YYBTYACC) */
2502 if (++nitems > maxitems)
2503 expand_items();
2504 pitem[nitems - 1] = bp;
2507 static void
2508 copy_action(void)
2510 int c;
2511 int i, j, n;
2512 int depth;
2513 #if defined(YYBTYACC)
2514 int haveyyval = 0;
2515 #endif
2516 char *tag;
2517 FILE *f = action_file;
2518 struct ainfo a;
2519 Value_t *offsets = NULL, maxoffset;
2520 bucket **rhs;
2522 a.a_lineno = lineno;
2523 a.a_line = dup_line();
2524 a.a_cptr = a.a_line + (cptr - line);
2526 if (last_was_action)
2527 insert_empty_rule();
2528 last_was_action = 1;
2529 #if defined(YYBTYACC)
2530 trialaction = (*cptr == L_BRAC);
2531 #endif
2533 fprintf(f, "case %d:\n", nrules - 2);
2534 #if defined(YYBTYACC)
2535 if (backtrack)
2537 if (!trialaction)
2538 fprintf(f, " if (!yytrial)\n");
2540 #endif
2541 if (!lflag)
2542 fprintf(f, line_format, lineno, input_file_name);
2543 if (*cptr == '=')
2544 ++cptr;
2546 /* avoid putting curly-braces in first column, to ease editing */
2547 if (*after_blanks(cptr) == L_CURL)
2549 putc('\t', f);
2550 cptr = after_blanks(cptr);
2553 maxoffset = 0;
2554 n = 0;
2555 for (i = nitems - 1; pitem[i]; --i)
2557 ++n;
2558 if (pitem[i]->class != ARGUMENT)
2559 maxoffset++;
2561 if (maxoffset > 0)
2563 offsets = TMALLOC(Value_t, maxoffset + 1);
2564 NO_SPACE(offsets);
2566 for (j = 0, i++; i < nitems; i++)
2568 if (pitem[i]->class != ARGUMENT)
2570 offsets[++j] = (Value_t)(i - nitems + 1);
2574 rhs = pitem + nitems - 1;
2576 depth = 0;
2577 loop:
2578 c = *cptr;
2579 if (c == '$')
2581 if (cptr[1] == '<')
2583 int d_lineno = lineno;
2584 char *d_line = dup_line();
2585 char *d_cptr = d_line + (cptr - line);
2587 ++cptr;
2588 tag = get_tag();
2589 c = *cptr;
2590 if (c == '$')
2592 fprintf(f, "yyval.%s", tag);
2593 ++cptr;
2594 FREE(d_line);
2595 goto loop;
2597 else if (isdigit(UCH(c)))
2599 i = get_number();
2600 if (i == 0)
2601 fprintf(f, "yystack.l_mark[%d].%s", -n, tag);
2602 else if (i > maxoffset)
2604 dollar_warning(d_lineno, i);
2605 fprintf(f, "yystack.l_mark[%d].%s", i - maxoffset, tag);
2607 else if (offsets)
2608 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2609 FREE(d_line);
2610 goto loop;
2612 else if (c == '-' && isdigit(UCH(cptr[1])))
2614 ++cptr;
2615 i = -get_number() - n;
2616 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
2617 FREE(d_line);
2618 goto loop;
2620 #if defined(YYBTYACC)
2621 else if (isalpha(UCH(c)) || c == '_')
2623 char *arg = scan_id();
2624 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2625 if (arg == plhs[nrules]->argnames[i])
2626 break;
2627 if (i < 0)
2628 unknown_arg_warning(d_lineno, "$", arg, d_line, d_cptr);
2629 fprintf(f, "yystack.l_mark[%d].%s",
2630 i - plhs[nrules]->args + 1 - n, tag);
2631 FREE(d_line);
2632 goto loop;
2634 #endif
2635 else
2636 dollar_error(d_lineno, d_line, d_cptr);
2638 else if (cptr[1] == '$')
2640 if (havetags)
2642 tag = plhs[nrules]->tag;
2643 if (tag == 0)
2644 untyped_lhs();
2645 fprintf(f, "yyval.%s", tag);
2647 else
2648 fprintf(f, "yyval");
2649 cptr += 2;
2650 #if defined(YYBTYACC)
2651 haveyyval = 1;
2652 #endif
2653 goto loop;
2655 else if (isdigit(UCH(cptr[1])))
2657 ++cptr;
2658 i = get_number();
2659 if (havetags && offsets)
2661 if (i <= 0 || i > maxoffset)
2662 unknown_rhs(i);
2663 tag = rhs[offsets[i]]->tag;
2664 if (tag == 0)
2665 untyped_rhs(i, rhs[offsets[i]]->name);
2666 fprintf(f, "yystack.l_mark[%d].%s", offsets[i], tag);
2668 else
2670 if (i == 0)
2671 fprintf(f, "yystack.l_mark[%d]", -n);
2672 else if (i > maxoffset)
2674 dollar_warning(lineno, i);
2675 fprintf(f, "yystack.l_mark[%d]", i - maxoffset);
2677 else if (offsets)
2678 fprintf(f, "yystack.l_mark[%d]", offsets[i]);
2680 goto loop;
2682 else if (cptr[1] == '-')
2684 cptr += 2;
2685 i = get_number();
2686 if (havetags)
2687 unknown_rhs(-i);
2688 fprintf(f, "yystack.l_mark[%d]", -i - n);
2689 goto loop;
2691 #if defined(YYBTYACC)
2692 else if (isalpha(UCH(cptr[1])) || cptr[1] == '_')
2694 char *arg;
2695 ++cptr;
2696 arg = scan_id();
2697 for (i = plhs[nrules]->args - 1; i >= 0; i--)
2698 if (arg == plhs[nrules]->argnames[i])
2699 break;
2700 if (i < 0)
2701 unknown_arg_warning(lineno, "$", arg, line, cptr);
2702 tag = (i < 0 ? NULL : plhs[nrules]->argtags[i]);
2703 fprintf(f, "yystack.l_mark[%d]", i - plhs[nrules]->args + 1 - n);
2704 if (tag)
2705 fprintf(f, ".%s", tag);
2706 else if (havetags)
2707 untyped_arg_warning(lineno, "$", arg);
2708 goto loop;
2710 #endif
2712 #if defined(YYBTYACC)
2713 if (c == '@')
2715 if (!locations)
2717 int l_lineno = lineno;
2718 char *l_line = dup_line();
2719 char *l_cptr = l_line + (cptr - line);
2720 syntax_error(l_lineno, l_line, l_cptr);
2722 if (cptr[1] == '$')
2724 fprintf(f, "yyloc");
2725 cptr += 2;
2726 goto loop;
2728 else if (isdigit(UCH(cptr[1])))
2730 ++cptr;
2731 i = get_number();
2732 if (i == 0)
2733 fprintf(f, "yystack.p_mark[%d]", -n);
2734 else if (i > maxoffset)
2736 at_warning(lineno, i);
2737 fprintf(f, "yystack.p_mark[%d]", i - maxoffset);
2739 else if (offsets)
2740 fprintf(f, "yystack.p_mark[%d]", offsets[i]);
2741 goto loop;
2743 else if (cptr[1] == '-')
2745 cptr += 2;
2746 i = get_number();
2747 fprintf(f, "yystack.p_mark[%d]", -i - n);
2748 goto loop;
2751 #endif
2752 if (IS_NAME1(c))
2756 putc(c, f);
2757 c = *++cptr;
2759 while (IS_NAME2(c));
2760 goto loop;
2762 ++cptr;
2763 #if defined(YYBTYACC)
2764 if (backtrack)
2766 if (trialaction && c == L_BRAC && depth == 0)
2768 ++depth;
2769 putc(L_CURL, f);
2770 goto loop;
2772 if (trialaction && c == R_BRAC && depth == 1)
2774 --depth;
2775 putc(R_CURL, f);
2776 c = nextc();
2777 if (c == L_BRAC && !haveyyval)
2779 goto loop;
2781 if (c == L_CURL && !haveyyval)
2783 fprintf(f, " if (!yytrial)\n");
2784 if (!lflag)
2785 fprintf(f, line_format, lineno, input_file_name);
2786 trialaction = 0;
2787 goto loop;
2789 fprintf(f, "\nbreak;\n");
2790 FREE(a.a_line);
2791 if (maxoffset > 0)
2792 FREE(offsets);
2793 return;
2796 #endif
2797 putc(c, f);
2798 switch (c)
2800 case '\n':
2801 get_line();
2802 if (line)
2803 goto loop;
2804 unterminated_action(&a);
2806 case ';':
2807 if (depth > 0)
2808 goto loop;
2809 fprintf(f, "\nbreak;\n");
2810 free(a.a_line);
2811 if (maxoffset > 0)
2812 FREE(offsets);
2813 return;
2815 #if defined(YYBTYACC)
2816 case L_BRAC:
2817 if (backtrack)
2818 ++depth;
2819 goto loop;
2821 case R_BRAC:
2822 if (backtrack)
2823 --depth;
2824 goto loop;
2825 #endif
2827 case L_CURL:
2828 ++depth;
2829 goto loop;
2831 case R_CURL:
2832 if (--depth > 0)
2833 goto loop;
2834 #if defined(YYBTYACC)
2835 if (backtrack)
2837 c = nextc();
2838 if (c == L_BRAC && !haveyyval)
2840 trialaction = 1;
2841 goto loop;
2843 if (c == L_CURL && !haveyyval)
2845 fprintf(f, " if (!yytrial)\n");
2846 if (!lflag)
2847 fprintf(f, line_format, lineno, input_file_name);
2848 goto loop;
2851 #endif
2852 fprintf(f, "\nbreak;\n");
2853 free(a.a_line);
2854 if (maxoffset > 0)
2855 FREE(offsets);
2856 return;
2858 case '\'':
2859 case '"':
2861 char *s = copy_string(c);
2862 fputs(s, f);
2863 free(s);
2865 goto loop;
2867 case '/':
2869 char *s = copy_comment();
2870 fputs(s, f);
2871 free(s);
2873 goto loop;
2875 default:
2876 goto loop;
2880 #if defined(YYBTYACC)
2881 static char *
2882 get_code(struct ainfo *a, const char *loc)
2884 int c;
2885 int depth;
2886 char *tag;
2887 struct mstring *code_mstr = msnew();
2889 if (!lflag)
2890 msprintf(code_mstr, line_format, lineno, input_file_name);
2892 cptr = after_blanks(cptr);
2893 if (*cptr == L_CURL)
2894 /* avoid putting curly-braces in first column, to ease editing */
2895 mputc(code_mstr, '\t');
2896 else
2897 syntax_error(lineno, line, cptr);
2899 a->a_lineno = lineno;
2900 a->a_line = dup_line();
2901 a->a_cptr = a->a_line + (cptr - line);
2903 depth = 0;
2904 loop:
2905 c = *cptr;
2906 if (c == '$')
2908 if (cptr[1] == '<')
2910 int d_lineno = lineno;
2911 char *d_line = dup_line();
2912 char *d_cptr = d_line + (cptr - line);
2914 ++cptr;
2915 tag = get_tag();
2916 c = *cptr;
2917 if (c == '$')
2919 msprintf(code_mstr, "(*val).%s", tag);
2920 ++cptr;
2921 FREE(d_line);
2922 goto loop;
2924 else
2925 dollar_error(d_lineno, d_line, d_cptr);
2927 else if (cptr[1] == '$')
2929 /* process '$$' later; replacement is context dependent */
2930 msprintf(code_mstr, "$$");
2931 cptr += 2;
2932 goto loop;
2935 if (c == '@' && cptr[1] == '$')
2937 if (!locations)
2939 int l_lineno = lineno;
2940 char *l_line = dup_line();
2941 char *l_cptr = l_line + (cptr - line);
2942 syntax_error(l_lineno, l_line, l_cptr);
2944 msprintf(code_mstr, "%s", loc);
2945 cptr += 2;
2946 goto loop;
2948 if (IS_NAME1(c))
2952 mputc(code_mstr, c);
2953 c = *++cptr;
2955 while (IS_NAME2(c));
2956 goto loop;
2958 ++cptr;
2959 mputc(code_mstr, c);
2960 switch (c)
2962 case '\n':
2963 get_line();
2964 if (line)
2965 goto loop;
2966 unterminated_action(a);
2968 case L_CURL:
2969 ++depth;
2970 goto loop;
2972 case R_CURL:
2973 if (--depth > 0)
2974 goto loop;
2975 goto out;
2977 case '\'':
2978 case '"':
2980 char *s = copy_string(c);
2981 msprintf(code_mstr, "%s", s);
2982 free(s);
2984 goto loop;
2986 case '/':
2988 char *s = copy_comment();
2989 msprintf(code_mstr, "%s", s);
2990 free(s);
2992 goto loop;
2994 default:
2995 goto loop;
2997 out:
2998 return msdone(code_mstr);
3001 static void
3002 copy_initial_action(void)
3004 struct ainfo a;
3006 initial_action = get_code(&a, "yyloc");
3007 free(a.a_line);
3010 static void
3011 copy_destructor(void)
3013 char *code_text;
3014 int c;
3015 struct ainfo a;
3016 bucket *bp;
3018 code_text = get_code(&a, "(*loc)");
3020 for (;;)
3022 c = nextc();
3023 if (c == EOF)
3024 unexpected_EOF();
3025 if (c == '<')
3027 if (cptr[1] == '>')
3028 { /* "no semantic type" default destructor */
3029 cptr += 2;
3030 if ((bp = default_destructor[UNTYPED_DEFAULT]) == NULL)
3032 static char untyped_default[] = "<>";
3033 bp = make_bucket("untyped default");
3034 bp->tag = untyped_default;
3035 default_destructor[UNTYPED_DEFAULT] = bp;
3037 if (bp->destructor != NULL)
3038 destructor_redeclared_warning(&a);
3039 else
3040 /* replace "$$" with "(*val)" in destructor code */
3041 bp->destructor = process_destructor_XX(code_text, NULL);
3043 else if (cptr[1] == '*' && cptr[2] == '>')
3044 { /* "no per-symbol or per-type" default destructor */
3045 cptr += 3;
3046 if ((bp = default_destructor[TYPED_DEFAULT]) == NULL)
3048 static char typed_default[] = "<*>";
3049 bp = make_bucket("typed default");
3050 bp->tag = typed_default;
3051 default_destructor[TYPED_DEFAULT] = bp;
3053 if (bp->destructor != NULL)
3054 destructor_redeclared_warning(&a);
3055 else
3057 /* postpone re-processing destructor $$s until end of grammar spec */
3058 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
3059 NO_SPACE(bp->destructor);
3060 strcpy(bp->destructor, code_text);
3063 else
3064 { /* "semantic type" default destructor */
3065 char *tag = get_tag();
3066 bp = lookup_type_destructor(tag);
3067 if (bp->destructor != NULL)
3068 destructor_redeclared_warning(&a);
3069 else
3070 /* replace "$$" with "(*val).tag" in destructor code */
3071 bp->destructor = process_destructor_XX(code_text, tag);
3074 else if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
3075 { /* "symbol" destructor */
3076 bp = get_name();
3077 if (bp->destructor != NULL)
3078 destructor_redeclared_warning(&a);
3079 else
3081 /* postpone re-processing destructor $$s until end of grammar spec */
3082 bp->destructor = TMALLOC(char, strlen(code_text) + 1);
3083 NO_SPACE(bp->destructor);
3084 strcpy(bp->destructor, code_text);
3087 else
3088 break;
3090 free(a.a_line);
3091 free(code_text);
3094 static char *
3095 process_destructor_XX(char *code, char *tag)
3097 int c;
3098 int quote;
3099 int depth;
3100 struct mstring *new_code = msnew();
3101 char *codeptr = code;
3103 depth = 0;
3104 loop: /* step thru code */
3105 c = *codeptr;
3106 if (c == '$' && codeptr[1] == '$')
3108 codeptr += 2;
3109 if (tag == NULL)
3110 msprintf(new_code, "(*val)");
3111 else
3112 msprintf(new_code, "(*val).%s", tag);
3113 goto loop;
3115 if (IS_NAME1(c))
3119 mputc(new_code, c);
3120 c = *++codeptr;
3122 while (IS_NAME2(c));
3123 goto loop;
3125 ++codeptr;
3126 mputc(new_code, c);
3127 switch (c)
3129 case L_CURL:
3130 ++depth;
3131 goto loop;
3133 case R_CURL:
3134 if (--depth > 0)
3135 goto loop;
3136 return msdone(new_code);
3138 case '\'':
3139 case '"':
3140 quote = c;
3141 for (;;)
3143 c = *codeptr++;
3144 mputc(new_code, c);
3145 if (c == quote)
3146 goto loop;
3147 if (c == '\\')
3149 c = *codeptr++;
3150 mputc(new_code, c);
3154 case '/':
3155 c = *codeptr;
3156 if (c == '*')
3158 mputc(new_code, c);
3159 ++codeptr;
3160 for (;;)
3162 c = *codeptr++;
3163 mputc(new_code, c);
3164 if (c == '*' && *codeptr == '/')
3166 mputc(new_code, '/');
3167 ++codeptr;
3168 goto loop;
3172 goto loop;
3174 default:
3175 goto loop;
3178 #endif /* defined(YYBTYACC) */
3180 static int
3181 mark_symbol(void)
3183 int c;
3184 bucket *bp = NULL;
3186 c = cptr[1];
3187 if (c == '%' || c == '\\')
3189 cptr += 2;
3190 return (1);
3193 if (c == '=')
3194 cptr += 2;
3195 else if ((c == 'p' || c == 'P') &&
3196 ((c = cptr[2]) == 'r' || c == 'R') &&
3197 ((c = cptr[3]) == 'e' || c == 'E') &&
3198 ((c = cptr[4]) == 'c' || c == 'C') &&
3199 ((c = cptr[5], !IS_IDENT(c))))
3200 cptr += 5;
3201 else
3202 syntax_error(lineno, line, cptr);
3204 c = nextc();
3205 if (isalpha(UCH(c)) || c == '_' || c == '.' || c == '$')
3206 bp = get_name();
3207 else if (c == '\'' || c == '"')
3208 bp = get_literal();
3209 else
3211 syntax_error(lineno, line, cptr);
3212 /*NOTREACHED */
3215 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
3216 prec_redeclared();
3218 rprec[nrules] = bp->prec;
3219 rassoc[nrules] = bp->assoc;
3220 return (0);
3223 static void
3224 read_grammar(void)
3226 int c;
3228 initialize_grammar();
3229 advance_to_start();
3231 for (;;)
3233 c = nextc();
3234 if (c == EOF)
3235 break;
3236 if (isalpha(UCH(c))
3237 || c == '_'
3238 || c == '.'
3239 || c == '$'
3240 || c == '\''
3241 || c == '"')
3242 add_symbol();
3243 #if defined(YYBTYACC)
3244 else if (c == L_CURL || c == '=' || (backtrack && c == L_BRAC))
3245 #else
3246 else if (c == L_CURL || c == '=')
3247 #endif
3248 copy_action();
3249 else if (c == '|')
3251 end_rule();
3252 start_rule(plhs[nrules - 1], 0);
3253 ++cptr;
3255 else if (c == '%')
3257 if (mark_symbol())
3258 break;
3260 else
3261 syntax_error(lineno, line, cptr);
3263 end_rule();
3264 #if defined(YYBTYACC)
3265 if (goal->args > 0)
3266 start_requires_args(goal->name);
3267 #endif
3270 static void
3271 free_tags(void)
3273 int i;
3275 if (tag_table == 0)
3276 return;
3278 for (i = 0; i < ntags; ++i)
3280 assert(tag_table[i]);
3281 FREE(tag_table[i]);
3283 FREE(tag_table);
3286 static void
3287 pack_names(void)
3289 bucket *bp;
3290 char *p, *s, *t;
3292 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
3293 for (bp = first_symbol; bp; bp = bp->next)
3294 name_pool_size += strlen(bp->name) + 1;
3296 name_pool = TMALLOC(char, name_pool_size);
3297 NO_SPACE(name_pool);
3299 strcpy(name_pool, "$accept");
3300 strcpy(name_pool + 8, "$end");
3301 t = name_pool + 13;
3302 for (bp = first_symbol; bp; bp = bp->next)
3304 p = t;
3305 s = bp->name;
3306 while ((*t++ = *s++) != 0)
3307 continue;
3308 FREE(bp->name);
3309 bp->name = p;
3313 static void
3314 check_symbols(void)
3316 bucket *bp;
3318 if (goal->class == UNKNOWN)
3319 undefined_goal(goal->name);
3321 for (bp = first_symbol; bp; bp = bp->next)
3323 if (bp->class == UNKNOWN)
3325 undefined_symbol_warning(bp->name);
3326 bp->class = TERM;
3331 static void
3332 protect_string(char *src, char **des)
3334 unsigned len;
3335 char *s;
3336 char *d;
3338 *des = src;
3339 if (src)
3341 len = 1;
3342 s = src;
3343 while (*s)
3345 if ('\\' == *s || '"' == *s)
3346 len++;
3347 s++;
3348 len++;
3351 *des = d = TMALLOC(char, len);
3352 NO_SPACE(d);
3354 s = src;
3355 while (*s)
3357 if ('\\' == *s || '"' == *s)
3358 *d++ = '\\';
3359 *d++ = *s++;
3361 *d = '\0';
3365 static void
3366 pack_symbols(void)
3368 bucket *bp;
3369 bucket **v;
3370 Value_t i, j, k, n;
3371 #if defined(YYBTYACC)
3372 Value_t max_tok_pval;
3373 #endif
3375 nsyms = 2;
3376 ntokens = 1;
3377 for (bp = first_symbol; bp; bp = bp->next)
3379 ++nsyms;
3380 if (bp->class == TERM)
3381 ++ntokens;
3383 start_symbol = (Value_t)ntokens;
3384 nvars = (Value_t)(nsyms - ntokens);
3386 symbol_name = TMALLOC(char *, nsyms);
3387 NO_SPACE(symbol_name);
3389 symbol_value = TMALLOC(Value_t, nsyms);
3390 NO_SPACE(symbol_value);
3392 symbol_prec = TMALLOC(Value_t, nsyms);
3393 NO_SPACE(symbol_prec);
3395 symbol_assoc = TMALLOC(char, nsyms);
3396 NO_SPACE(symbol_assoc);
3398 #if defined(YYBTYACC)
3399 symbol_pval = TMALLOC(Value_t, nsyms);
3400 NO_SPACE(symbol_pval);
3402 if (destructor)
3404 symbol_destructor = CALLOC(sizeof(char *), nsyms);
3405 NO_SPACE(symbol_destructor);
3407 symbol_type_tag = CALLOC(sizeof(char *), nsyms);
3408 NO_SPACE(symbol_type_tag);
3410 #endif
3412 v = TMALLOC(bucket *, nsyms);
3413 NO_SPACE(v);
3415 v[0] = 0;
3416 v[start_symbol] = 0;
3418 i = 1;
3419 j = (Value_t)(start_symbol + 1);
3420 for (bp = first_symbol; bp; bp = bp->next)
3422 if (bp->class == TERM)
3423 v[i++] = bp;
3424 else
3425 v[j++] = bp;
3427 assert(i == ntokens && j == nsyms);
3429 for (i = 1; i < ntokens; ++i)
3430 v[i]->index = i;
3432 goal->index = (Index_t)(start_symbol + 1);
3433 k = (Value_t)(start_symbol + 2);
3434 while (++i < nsyms)
3435 if (v[i] != goal)
3437 v[i]->index = k;
3438 ++k;
3441 goal->value = 0;
3442 k = 1;
3443 for (i = (Value_t)(start_symbol + 1); i < nsyms; ++i)
3445 if (v[i] != goal)
3447 v[i]->value = k;
3448 ++k;
3452 k = 0;
3453 for (i = 1; i < ntokens; ++i)
3455 n = v[i]->value;
3456 if (n > 256)
3458 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
3459 symbol_value[j] = symbol_value[j - 1];
3460 symbol_value[j] = n;
3464 assert(v[1] != 0);
3466 if (v[1]->value == UNDEFINED)
3467 v[1]->value = 256;
3469 j = 0;
3470 n = 257;
3471 for (i = 2; i < ntokens; ++i)
3473 if (v[i]->value == UNDEFINED)
3475 while (j < k && n == symbol_value[j])
3477 while (++j < k && n == symbol_value[j])
3478 continue;
3479 ++n;
3481 v[i]->value = n;
3482 ++n;
3486 symbol_name[0] = name_pool + 8;
3487 symbol_value[0] = 0;
3488 symbol_prec[0] = 0;
3489 symbol_assoc[0] = TOKEN;
3490 #if defined(YYBTYACC)
3491 symbol_pval[0] = 0;
3492 max_tok_pval = 0;
3493 #endif
3494 for (i = 1; i < ntokens; ++i)
3496 symbol_name[i] = v[i]->name;
3497 symbol_value[i] = v[i]->value;
3498 symbol_prec[i] = v[i]->prec;
3499 symbol_assoc[i] = v[i]->assoc;
3500 #if defined(YYBTYACC)
3501 symbol_pval[i] = v[i]->value;
3502 if (symbol_pval[i] > max_tok_pval)
3503 max_tok_pval = symbol_pval[i];
3504 if (destructor)
3506 symbol_destructor[i] = v[i]->destructor;
3507 symbol_type_tag[i] = v[i]->tag;
3509 #endif
3511 symbol_name[start_symbol] = name_pool;
3512 symbol_value[start_symbol] = -1;
3513 symbol_prec[start_symbol] = 0;
3514 symbol_assoc[start_symbol] = TOKEN;
3515 #if defined(YYBTYACC)
3516 symbol_pval[start_symbol] = (Value_t)(max_tok_pval + 1);
3517 #endif
3518 for (++i; i < nsyms; ++i)
3520 k = v[i]->index;
3521 symbol_name[k] = v[i]->name;
3522 symbol_value[k] = v[i]->value;
3523 symbol_prec[k] = v[i]->prec;
3524 symbol_assoc[k] = v[i]->assoc;
3525 #if defined(YYBTYACC)
3526 symbol_pval[k] = (Value_t)((max_tok_pval + 1) + v[i]->value + 1);
3527 if (destructor)
3529 symbol_destructor[k] = v[i]->destructor;
3530 symbol_type_tag[k] = v[i]->tag;
3532 #endif
3535 if (gflag)
3537 symbol_pname = TMALLOC(char *, nsyms);
3538 NO_SPACE(symbol_pname);
3540 for (i = 0; i < nsyms; ++i)
3541 protect_string(symbol_name[i], &(symbol_pname[i]));
3544 FREE(v);
3547 static void
3548 pack_grammar(void)
3550 int i;
3551 Value_t j;
3552 Assoc_t assoc;
3553 Value_t prec2;
3555 ritem = TMALLOC(Value_t, nitems);
3556 NO_SPACE(ritem);
3558 rlhs = TMALLOC(Value_t, nrules);
3559 NO_SPACE(rlhs);
3561 rrhs = TMALLOC(Value_t, nrules + 1);
3562 NO_SPACE(rrhs);
3564 rprec = TREALLOC(Value_t, rprec, nrules);
3565 NO_SPACE(rprec);
3567 rassoc = TREALLOC(Assoc_t, rassoc, nrules);
3568 NO_SPACE(rassoc);
3570 ritem[0] = -1;
3571 ritem[1] = goal->index;
3572 ritem[2] = 0;
3573 ritem[3] = -2;
3574 rlhs[0] = 0;
3575 rlhs[1] = 0;
3576 rlhs[2] = start_symbol;
3577 rrhs[0] = 0;
3578 rrhs[1] = 0;
3579 rrhs[2] = 1;
3581 j = 4;
3582 for (i = 3; i < nrules; ++i)
3584 #if defined(YYBTYACC)
3585 if (plhs[i]->args > 0)
3587 if (plhs[i]->argnames)
3589 FREE(plhs[i]->argnames);
3590 plhs[i]->argnames = NULL;
3592 if (plhs[i]->argtags)
3594 FREE(plhs[i]->argtags);
3595 plhs[i]->argtags = NULL;
3598 #endif /* defined(YYBTYACC) */
3599 rlhs[i] = plhs[i]->index;
3600 rrhs[i] = j;
3601 assoc = TOKEN;
3602 prec2 = 0;
3603 while (pitem[j])
3605 ritem[j] = pitem[j]->index;
3606 if (pitem[j]->class == TERM)
3608 prec2 = pitem[j]->prec;
3609 assoc = pitem[j]->assoc;
3611 ++j;
3613 ritem[j] = (Value_t)-i;
3614 ++j;
3615 if (rprec[i] == UNDEFINED)
3617 rprec[i] = prec2;
3618 rassoc[i] = assoc;
3621 rrhs[i] = j;
3623 FREE(plhs);
3624 FREE(pitem);
3625 #if defined(YYBTYACC)
3626 clean_arg_cache();
3627 #endif
3630 static void
3631 print_grammar(void)
3633 int i, k;
3634 size_t j, spacing = 0;
3635 FILE *f = verbose_file;
3637 if (!vflag)
3638 return;
3640 k = 1;
3641 for (i = 2; i < nrules; ++i)
3643 if (rlhs[i] != rlhs[i - 1])
3645 if (i != 2)
3646 fprintf(f, "\n");
3647 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
3648 spacing = strlen(symbol_name[rlhs[i]]) + 1;
3650 else
3652 fprintf(f, "%4d ", i - 2);
3653 j = spacing;
3654 while (j-- != 0)
3655 putc(' ', f);
3656 putc('|', f);
3659 while (ritem[k] >= 0)
3661 fprintf(f, " %s", symbol_name[ritem[k]]);
3662 ++k;
3664 ++k;
3665 putc('\n', f);
3669 #if defined(YYBTYACC)
3670 static void
3671 finalize_destructors(void)
3673 int i;
3674 bucket *bp;
3675 char *tag;
3677 for (i = 2; i < nsyms; ++i)
3679 tag = symbol_type_tag[i];
3680 if (symbol_destructor[i] == NULL)
3682 if (tag == NULL)
3683 { /* use <> destructor, if there is one */
3684 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3686 symbol_destructor[i] = TMALLOC(char,
3687 strlen(bp->destructor) + 1);
3688 NO_SPACE(symbol_destructor[i]);
3689 strcpy(symbol_destructor[i], bp->destructor);
3692 else
3693 { /* use type destructor for this tag, if there is one */
3694 bp = lookup_type_destructor(tag);
3695 if (bp->destructor != NULL)
3697 symbol_destructor[i] = TMALLOC(char,
3698 strlen(bp->destructor) + 1);
3699 NO_SPACE(symbol_destructor[i]);
3700 strcpy(symbol_destructor[i], bp->destructor);
3702 else
3703 { /* use <*> destructor, if there is one */
3704 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3705 /* replace "$$" with "(*val).tag" in destructor code */
3706 symbol_destructor[i]
3707 = process_destructor_XX(bp->destructor, tag);
3711 else
3712 { /* replace "$$" with "(*val)[.tag]" in destructor code */
3713 symbol_destructor[i]
3714 = process_destructor_XX(symbol_destructor[i], tag);
3717 /* 'symbol_type_tag[]' elements are freed by 'free_tags()' */
3718 DO_FREE(symbol_type_tag); /* no longer needed */
3719 if ((bp = default_destructor[UNTYPED_DEFAULT]) != NULL)
3721 FREE(bp->name);
3722 /* 'bp->tag' is a static value, don't free */
3723 FREE(bp->destructor);
3724 FREE(bp);
3726 if ((bp = default_destructor[TYPED_DEFAULT]) != NULL)
3728 FREE(bp->name);
3729 /* 'bp->tag' is a static value, don't free */
3730 FREE(bp->destructor);
3731 FREE(bp);
3733 if ((bp = default_destructor[TYPE_SPECIFIED]) != NULL)
3735 bucket *p;
3736 for (; bp; bp = p)
3738 p = bp->link;
3739 FREE(bp->name);
3740 /* 'bp->tag' freed by 'free_tags()' */
3741 FREE(bp->destructor);
3742 FREE(bp);
3746 #endif /* defined(YYBTYACC) */
3748 void
3749 reader(void)
3751 write_section(code_file, banner);
3752 create_symbol_table();
3753 read_declarations();
3754 read_grammar();
3755 free_symbol_table();
3756 pack_names();
3757 check_symbols();
3758 pack_symbols();
3759 pack_grammar();
3760 free_symbols();
3761 print_grammar();
3762 #if defined(YYBTYACC)
3763 if (destructor)
3764 finalize_destructors();
3765 #endif
3766 free_tags();
3769 #ifdef NO_LEAKS
3770 static param *
3771 free_declarations(param *list)
3773 while (list != 0)
3775 param *next = list->next;
3776 free(list->type);
3777 free(list->name);
3778 free(list->type2);
3779 free(list);
3780 list = next;
3782 return list;
3785 void
3786 reader_leaks(void)
3788 lex_param = free_declarations(lex_param);
3789 parse_param = free_declarations(parse_param);
3791 DO_FREE(line);
3792 DO_FREE(rrhs);
3793 DO_FREE(rlhs);
3794 DO_FREE(rprec);
3795 DO_FREE(ritem);
3796 DO_FREE(rassoc);
3797 DO_FREE(cache);
3798 DO_FREE(name_pool);
3799 DO_FREE(symbol_name);
3800 DO_FREE(symbol_prec);
3801 DO_FREE(symbol_assoc);
3802 DO_FREE(symbol_value);
3803 #if defined(YYBTYACC)
3804 DO_FREE(symbol_pval);
3805 DO_FREE(symbol_destructor);
3806 DO_FREE(symbol_type_tag);
3807 #endif
3809 #endif