include: add macros to properly declare assembly functions/data
[hvf.git] / build / byacc / reader.c
blob06512437bcd6a66fdb7cb1f13b4a70cb8cdb9637
1 /* $Id: reader.c,v 1.33 2011/09/06 22:56:53 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 '}'
15 static void start_rule(bucket *bp, int s_lineno);
17 static char *cache;
18 static int cinc, cache_size;
20 int ntags;
21 static int tagmax;
22 static char **tag_table;
24 static char saw_eof;
25 char unionized;
26 char *cptr, *line;
27 static int linesize;
29 static bucket *goal;
30 static Value_t prec;
31 static int gensym;
32 static char last_was_action;
34 static int maxitems;
35 static bucket **pitem;
37 static int maxrules;
38 static bucket **plhs;
40 static size_t name_pool_size;
41 static char *name_pool;
43 char line_format[] = "#line %d \"%s\"\n";
45 param *lex_param;
46 param *parse_param;
48 static void
49 cachec(int c)
51 assert(cinc >= 0);
52 if (cinc >= cache_size)
54 cache_size += 256;
55 cache = REALLOC(cache, cache_size);
56 NO_SPACE(cache);
58 cache[cinc] = (char)c;
59 ++cinc;
62 static void
63 get_line(void)
65 FILE *f = input_file;
66 int c;
67 int i;
69 if (saw_eof || (c = getc(f)) == EOF)
71 if (line)
73 FREE(line);
74 line = 0;
76 cptr = 0;
77 saw_eof = 1;
78 return;
81 if (line == 0 || linesize != (LINESIZE + 1))
83 if (line)
84 FREE(line);
85 linesize = LINESIZE + 1;
86 line = MALLOC(linesize);
87 NO_SPACE(line);
90 i = 0;
91 ++lineno;
92 for (;;)
94 line[i] = (char)c;
95 if (c == '\n')
97 cptr = line;
98 return;
100 if (++i >= linesize)
102 linesize += LINESIZE;
103 line = REALLOC(line, linesize);
104 NO_SPACE(line);
106 c = getc(f);
107 if (c == EOF)
109 line[i] = '\n';
110 saw_eof = 1;
111 cptr = line;
112 return;
117 static char *
118 dup_line(void)
120 char *p, *s, *t;
122 if (line == 0)
123 return (0);
124 s = line;
125 while (*s != '\n')
126 ++s;
127 p = MALLOC(s - line + 1);
128 NO_SPACE(p);
130 s = line;
131 t = p;
132 while ((*t++ = *s++) != '\n')
133 continue;
134 return (p);
137 static void
138 skip_comment(void)
140 char *s;
142 int st_lineno = lineno;
143 char *st_line = dup_line();
144 char *st_cptr = st_line + (cptr - line);
146 s = cptr + 2;
147 for (;;)
149 if (*s == '*' && s[1] == '/')
151 cptr = s + 2;
152 FREE(st_line);
153 return;
155 if (*s == '\n')
157 get_line();
158 if (line == 0)
159 unterminated_comment(st_lineno, st_line, st_cptr);
160 s = cptr;
162 else
163 ++s;
167 static int
168 nextc(void)
170 char *s;
172 if (line == 0)
174 get_line();
175 if (line == 0)
176 return (EOF);
179 s = cptr;
180 for (;;)
182 switch (*s)
184 case '\n':
185 get_line();
186 if (line == 0)
187 return (EOF);
188 s = cptr;
189 break;
191 case ' ':
192 case '\t':
193 case '\f':
194 case '\r':
195 case '\v':
196 case ',':
197 case ';':
198 ++s;
199 break;
201 case '\\':
202 cptr = s;
203 return ('%');
205 case '/':
206 if (s[1] == '*')
208 cptr = s;
209 skip_comment();
210 s = cptr;
211 break;
213 else if (s[1] == '/')
215 get_line();
216 if (line == 0)
217 return (EOF);
218 s = cptr;
219 break;
221 /* FALLTHRU */
223 default:
224 cptr = s;
225 return (*s);
231 * Compare keyword to cached token, treating '_' and '-' the same. Some
232 * grammars rely upon this misfeature.
234 static int
235 matchec(const char *name)
237 const char *p = cache;
238 const char *q = name;
239 int code = 0; /* assume mismatch */
241 while (*p != '\0' && *q != '\0')
243 char a = *p++;
244 char b = *q++;
245 if (a == '_')
246 a = '-';
247 if (b == '_')
248 b = '-';
249 if (a != b)
250 break;
251 if (*p == '\0' && *q == '\0')
253 code = 1;
254 break;
257 return code;
260 static int
261 keyword(void)
263 int c;
264 char *t_cptr = cptr;
266 c = *++cptr;
267 if (isalpha(c))
269 cinc = 0;
270 for (;;)
272 if (isalpha(c))
274 if (isupper(c))
275 c = tolower(c);
276 cachec(c);
278 else if (isdigit(c)
279 || c == '-'
280 || c == '_'
281 || c == '.'
282 || c == '$')
284 cachec(c);
286 else
288 break;
290 c = *++cptr;
292 cachec(NUL);
294 if (matchec("token") || matchec("term"))
295 return (TOKEN);
296 if (matchec("type"))
297 return (TYPE);
298 if (matchec("left"))
299 return (LEFT);
300 if (matchec("right"))
301 return (RIGHT);
302 if (matchec("nonassoc") || matchec("binary"))
303 return (NONASSOC);
304 if (matchec("start"))
305 return (START);
306 if (matchec("union"))
307 return (UNION);
308 if (matchec("ident"))
309 return (IDENT);
310 if (matchec("expect"))
311 return (EXPECT);
312 if (matchec("expect-rr"))
313 return (EXPECT_RR);
314 if (matchec("pure-parser"))
315 return (PURE_PARSER);
316 if (matchec("parse-param"))
317 return (PARSE_PARAM);
318 if (matchec("lex-param"))
319 return (LEX_PARAM);
320 if (matchec("yacc"))
321 return (POSIX_YACC);
323 else
325 ++cptr;
326 if (c == L_CURL)
327 return (TEXT);
328 if (c == '%' || c == '\\')
329 return (MARK);
330 if (c == '<')
331 return (LEFT);
332 if (c == '>')
333 return (RIGHT);
334 if (c == '0')
335 return (TOKEN);
336 if (c == '2')
337 return (NONASSOC);
339 syntax_error(lineno, line, t_cptr);
340 /*NOTREACHED */
343 static void
344 copy_ident(void)
346 int c;
347 FILE *f = output_file;
349 c = nextc();
350 if (c == EOF)
351 unexpected_EOF();
352 if (c != '"')
353 syntax_error(lineno, line, cptr);
354 ++outline;
355 fprintf(f, "#ident \"");
356 for (;;)
358 c = *++cptr;
359 if (c == '\n')
361 fprintf(f, "\"\n");
362 return;
364 putc(c, f);
365 if (c == '"')
367 putc('\n', f);
368 ++cptr;
369 return;
374 static void
375 copy_text(void)
377 int c;
378 int quote;
379 FILE *f = text_file;
380 int need_newline = 0;
381 int t_lineno = lineno;
382 char *t_line = dup_line();
383 char *t_cptr = t_line + (cptr - line - 2);
385 if (*cptr == '\n')
387 get_line();
388 if (line == 0)
389 unterminated_text(t_lineno, t_line, t_cptr);
391 if (!lflag)
392 fprintf(f, line_format, lineno, input_file_name);
394 loop:
395 c = *cptr++;
396 switch (c)
398 case '\n':
399 next_line:
400 putc('\n', f);
401 need_newline = 0;
402 get_line();
403 if (line)
404 goto loop;
405 unterminated_text(t_lineno, t_line, t_cptr);
407 case '\'':
408 case '"':
410 int s_lineno = lineno;
411 char *s_line = dup_line();
412 char *s_cptr = s_line + (cptr - line - 1);
414 quote = c;
415 putc(c, f);
416 for (;;)
418 c = *cptr++;
419 putc(c, f);
420 if (c == quote)
422 need_newline = 1;
423 FREE(s_line);
424 goto loop;
426 if (c == '\n')
427 unterminated_string(s_lineno, s_line, s_cptr);
428 if (c == '\\')
430 c = *cptr++;
431 putc(c, f);
432 if (c == '\n')
434 get_line();
435 if (line == 0)
436 unterminated_string(s_lineno, s_line, s_cptr);
442 case '/':
443 putc(c, f);
444 need_newline = 1;
445 c = *cptr;
446 if (c == '/')
448 putc('*', f);
449 while ((c = *++cptr) != '\n')
451 if (c == '*' && cptr[1] == '/')
452 fprintf(f, "* ");
453 else
454 putc(c, f);
456 fprintf(f, "*/");
457 goto next_line;
459 if (c == '*')
461 int c_lineno = lineno;
462 char *c_line = dup_line();
463 char *c_cptr = c_line + (cptr - line - 1);
465 putc('*', f);
466 ++cptr;
467 for (;;)
469 c = *cptr++;
470 putc(c, f);
471 if (c == '*' && *cptr == '/')
473 putc('/', f);
474 ++cptr;
475 FREE(c_line);
476 goto loop;
478 if (c == '\n')
480 get_line();
481 if (line == 0)
482 unterminated_comment(c_lineno, c_line, c_cptr);
486 need_newline = 1;
487 goto loop;
489 case '%':
490 case '\\':
491 if (*cptr == R_CURL)
493 if (need_newline)
494 putc('\n', f);
495 ++cptr;
496 FREE(t_line);
497 return;
499 /* FALLTHRU */
501 default:
502 putc(c, f);
503 need_newline = 1;
504 goto loop;
508 static void
509 puts_both(const char *s)
511 fputs(s, text_file);
512 if (dflag)
513 fputs(s, union_file);
516 static void
517 putc_both(int c)
519 putc(c, text_file);
520 if (dflag)
521 putc(c, union_file);
524 static void
525 copy_union(void)
527 int c;
528 int quote;
529 int depth;
530 int u_lineno = lineno;
531 char *u_line = dup_line();
532 char *u_cptr = u_line + (cptr - line - 6);
534 if (unionized)
535 over_unionized(cptr - 6);
536 unionized = 1;
538 if (!lflag)
539 fprintf(text_file, line_format, lineno, input_file_name);
541 puts_both("#ifdef YYSTYPE\n");
542 puts_both("#undef YYSTYPE_IS_DECLARED\n");
543 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
544 puts_both("#endif\n");
545 puts_both("#ifndef YYSTYPE_IS_DECLARED\n");
546 puts_both("#define YYSTYPE_IS_DECLARED 1\n");
547 puts_both("typedef union");
549 depth = 0;
550 loop:
551 c = *cptr++;
552 putc_both(c);
553 switch (c)
555 case '\n':
556 next_line:
557 get_line();
558 if (line == 0)
559 unterminated_union(u_lineno, u_line, u_cptr);
560 goto loop;
562 case L_CURL:
563 ++depth;
564 goto loop;
566 case R_CURL:
567 if (--depth == 0)
569 puts_both(" YYSTYPE;\n");
570 puts_both("#endif /* !YYSTYPE_IS_DECLARED */\n");
571 FREE(u_line);
572 return;
574 goto loop;
576 case '\'':
577 case '"':
579 int s_lineno = lineno;
580 char *s_line = dup_line();
581 char *s_cptr = s_line + (cptr - line - 1);
583 quote = c;
584 for (;;)
586 c = *cptr++;
587 putc_both(c);
588 if (c == quote)
590 FREE(s_line);
591 goto loop;
593 if (c == '\n')
594 unterminated_string(s_lineno, s_line, s_cptr);
595 if (c == '\\')
597 c = *cptr++;
598 putc_both(c);
599 if (c == '\n')
601 get_line();
602 if (line == 0)
603 unterminated_string(s_lineno, s_line, s_cptr);
609 case '/':
610 c = *cptr;
611 if (c == '/')
613 putc_both('*');
614 while ((c = *++cptr) != '\n')
616 if (c == '*' && cptr[1] == '/')
618 puts_both("* ");
620 else
622 putc_both(c);
625 puts_both("*/\n");
626 goto next_line;
628 if (c == '*')
630 int c_lineno = lineno;
631 char *c_line = dup_line();
632 char *c_cptr = c_line + (cptr - line - 1);
634 putc_both('*');
635 ++cptr;
636 for (;;)
638 c = *cptr++;
639 putc_both(c);
640 if (c == '*' && *cptr == '/')
642 putc_both('/');
643 ++cptr;
644 FREE(c_line);
645 goto loop;
647 if (c == '\n')
649 get_line();
650 if (line == 0)
651 unterminated_comment(c_lineno, c_line, c_cptr);
655 goto loop;
657 default:
658 goto loop;
663 * Keep a linked list of parameters
665 static void
666 copy_param(int k)
668 char *buf;
669 int c;
670 param *head, *p;
671 int i;
672 int name, type2;
674 c = nextc();
675 if (c == EOF)
676 unexpected_EOF();
677 if (c != '{')
678 goto out;
679 cptr++;
681 c = nextc();
682 if (c == EOF)
683 unexpected_EOF();
684 if (c == '}')
685 goto out;
687 buf = MALLOC(linesize);
688 NO_SPACE(buf);
690 for (i = 0; (c = *cptr++) != '}'; i++)
692 if (c == '\0')
693 missing_brace();
694 if (c == EOF)
695 unexpected_EOF();
696 buf[i] = (char)c;
699 if (i == 0)
700 goto out;
702 buf[i--] = '\0';
703 while (i >= 0 && isspace(UCH(buf[i])))
704 buf[i--] = '\0';
706 if (buf[i] == ']')
708 int level = 1;
709 while (i >= 0 && level > 0 && buf[i] != '[')
711 if (buf[i] == ']')
712 ++level;
713 else if (buf[i] == '[')
714 --level;
715 i--;
717 if (i <= 0)
718 unexpected_EOF();
719 type2 = i--;
721 else
723 type2 = i + 1;
726 while (i >= 0 && (isalnum(UCH(buf[i])) ||
727 UCH(buf[i]) == '_'))
728 i--;
730 if (!isspace(UCH(buf[i])) && buf[i] != '*')
731 goto out;
733 name = i + 1;
735 p = MALLOC(sizeof(*p));
736 NO_SPACE(p);
738 p->type2 = strdup(buf + type2);
739 NO_SPACE(p->type2);
741 buf[type2] = '\0';
743 p->name = strdup(buf + name);
744 NO_SPACE(p->name);
746 buf[name] = '\0';
747 p->type = buf;
749 if (k == LEX_PARAM)
750 head = lex_param;
751 else
752 head = parse_param;
754 if (head != NULL)
756 while (head->next)
757 head = head->next;
758 head->next = p;
760 else
762 if (k == LEX_PARAM)
763 lex_param = p;
764 else
765 parse_param = p;
767 p->next = NULL;
768 return;
770 out:
771 syntax_error(lineno, line, cptr);
774 static int
775 hexval(int c)
777 if (c >= '0' && c <= '9')
778 return (c - '0');
779 if (c >= 'A' && c <= 'F')
780 return (c - 'A' + 10);
781 if (c >= 'a' && c <= 'f')
782 return (c - 'a' + 10);
783 return (-1);
786 static bucket *
787 get_literal(void)
789 int c, quote;
790 int i;
791 int n;
792 char *s;
793 bucket *bp;
794 int s_lineno = lineno;
795 char *s_line = dup_line();
796 char *s_cptr = s_line + (cptr - line);
798 quote = *cptr++;
799 cinc = 0;
800 for (;;)
802 c = *cptr++;
803 if (c == quote)
804 break;
805 if (c == '\n')
806 unterminated_string(s_lineno, s_line, s_cptr);
807 if (c == '\\')
809 char *c_cptr = cptr - 1;
811 c = *cptr++;
812 switch (c)
814 case '\n':
815 get_line();
816 if (line == 0)
817 unterminated_string(s_lineno, s_line, s_cptr);
818 continue;
820 case '0':
821 case '1':
822 case '2':
823 case '3':
824 case '4':
825 case '5':
826 case '6':
827 case '7':
828 n = c - '0';
829 c = *cptr;
830 if (IS_OCTAL(c))
832 n = (n << 3) + (c - '0');
833 c = *++cptr;
834 if (IS_OCTAL(c))
836 n = (n << 3) + (c - '0');
837 ++cptr;
840 if (n > MAXCHAR)
841 illegal_character(c_cptr);
842 c = n;
843 break;
845 case 'x':
846 c = *cptr++;
847 n = hexval(c);
848 if (n < 0 || n >= 16)
849 illegal_character(c_cptr);
850 for (;;)
852 c = *cptr;
853 i = hexval(c);
854 if (i < 0 || i >= 16)
855 break;
856 ++cptr;
857 n = (n << 4) + i;
858 if (n > MAXCHAR)
859 illegal_character(c_cptr);
861 c = n;
862 break;
864 case 'a':
865 c = 7;
866 break;
867 case 'b':
868 c = '\b';
869 break;
870 case 'f':
871 c = '\f';
872 break;
873 case 'n':
874 c = '\n';
875 break;
876 case 'r':
877 c = '\r';
878 break;
879 case 't':
880 c = '\t';
881 break;
882 case 'v':
883 c = '\v';
884 break;
887 cachec(c);
889 FREE(s_line);
891 n = cinc;
892 s = MALLOC(n);
893 NO_SPACE(s);
895 for (i = 0; i < n; ++i)
896 s[i] = cache[i];
898 cinc = 0;
899 if (n == 1)
900 cachec('\'');
901 else
902 cachec('"');
904 for (i = 0; i < n; ++i)
906 c = UCH(s[i]);
907 if (c == '\\' || c == cache[0])
909 cachec('\\');
910 cachec(c);
912 else if (isprint(c))
913 cachec(c);
914 else
916 cachec('\\');
917 switch (c)
919 case 7:
920 cachec('a');
921 break;
922 case '\b':
923 cachec('b');
924 break;
925 case '\f':
926 cachec('f');
927 break;
928 case '\n':
929 cachec('n');
930 break;
931 case '\r':
932 cachec('r');
933 break;
934 case '\t':
935 cachec('t');
936 break;
937 case '\v':
938 cachec('v');
939 break;
940 default:
941 cachec(((c >> 6) & 7) + '0');
942 cachec(((c >> 3) & 7) + '0');
943 cachec((c & 7) + '0');
944 break;
949 if (n == 1)
950 cachec('\'');
951 else
952 cachec('"');
954 cachec(NUL);
955 bp = lookup(cache);
956 bp->class = TERM;
957 if (n == 1 && bp->value == UNDEFINED)
958 bp->value = UCH(*s);
959 FREE(s);
961 return (bp);
964 static int
965 is_reserved(char *name)
967 char *s;
969 if (strcmp(name, ".") == 0 ||
970 strcmp(name, "$accept") == 0 ||
971 strcmp(name, "$end") == 0)
972 return (1);
974 if (name[0] == '$' && name[1] == '$' && isdigit(UCH(name[2])))
976 s = name + 3;
977 while (isdigit(UCH(*s)))
978 ++s;
979 if (*s == NUL)
980 return (1);
983 return (0);
986 static bucket *
987 get_name(void)
989 int c;
991 cinc = 0;
992 for (c = *cptr; IS_IDENT(c); c = *++cptr)
993 cachec(c);
994 cachec(NUL);
996 if (is_reserved(cache))
997 used_reserved(cache);
999 return (lookup(cache));
1002 static Value_t
1003 get_number(void)
1005 int c;
1006 Value_t n;
1008 n = 0;
1009 for (c = *cptr; isdigit(c); c = *++cptr)
1010 n = (Value_t) (10 * n + (c - '0'));
1012 return (n);
1015 static char *
1016 get_tag(void)
1018 int c;
1019 int i;
1020 char *s;
1021 int t_lineno = lineno;
1022 char *t_line = dup_line();
1023 char *t_cptr = t_line + (cptr - line);
1025 ++cptr;
1026 c = nextc();
1027 if (c == EOF)
1028 unexpected_EOF();
1029 if (!isalpha(c) && c != '_' && c != '$')
1030 illegal_tag(t_lineno, t_line, t_cptr);
1032 cinc = 0;
1035 cachec(c);
1036 c = *++cptr;
1038 while (IS_IDENT(c));
1039 cachec(NUL);
1041 c = nextc();
1042 if (c == EOF)
1043 unexpected_EOF();
1044 if (c != '>')
1045 illegal_tag(t_lineno, t_line, t_cptr);
1046 ++cptr;
1048 for (i = 0; i < ntags; ++i)
1050 if (strcmp(cache, tag_table[i]) == 0)
1052 FREE(t_line);
1053 return (tag_table[i]);
1057 if (ntags >= tagmax)
1059 tagmax += 16;
1060 tag_table = (char **)
1061 (tag_table
1062 ? REALLOC(tag_table, (unsigned)tagmax * sizeof(char *))
1063 : MALLOC((unsigned)tagmax * sizeof(char *)));
1064 NO_SPACE(tag_table);
1067 s = MALLOC(cinc);
1068 NO_SPACE(s);
1070 strcpy(s, cache);
1071 tag_table[ntags] = s;
1072 ++ntags;
1073 FREE(t_line);
1074 return (s);
1077 static void
1078 declare_tokens(int assoc)
1080 int c;
1081 bucket *bp;
1082 Value_t value;
1083 char *tag = 0;
1085 if (assoc != TOKEN)
1086 ++prec;
1088 c = nextc();
1089 if (c == EOF)
1090 unexpected_EOF();
1091 if (c == '<')
1093 tag = get_tag();
1094 c = nextc();
1095 if (c == EOF)
1096 unexpected_EOF();
1099 for (;;)
1101 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1102 bp = get_name();
1103 else if (c == '\'' || c == '"')
1104 bp = get_literal();
1105 else
1106 return;
1108 if (bp == goal)
1109 tokenized_start(bp->name);
1110 bp->class = TERM;
1112 if (tag)
1114 if (bp->tag && tag != bp->tag)
1115 retyped_warning(bp->name);
1116 bp->tag = tag;
1119 if (assoc != TOKEN)
1121 if (bp->prec && prec != bp->prec)
1122 reprec_warning(bp->name);
1123 bp->assoc = (Assoc_t) assoc;
1124 bp->prec = prec;
1127 c = nextc();
1128 if (c == EOF)
1129 unexpected_EOF();
1131 if (isdigit(c))
1133 value = get_number();
1134 if (bp->value != UNDEFINED && value != bp->value)
1135 revalued_warning(bp->name);
1136 bp->value = value;
1137 c = nextc();
1138 if (c == EOF)
1139 unexpected_EOF();
1145 * %expect requires special handling
1146 * as it really isn't part of the yacc
1147 * grammar only a flag for yacc proper.
1149 static void
1150 declare_expect(int assoc)
1152 int c;
1154 if (assoc != EXPECT && assoc != EXPECT_RR)
1155 ++prec;
1158 * Stay away from nextc - doesn't
1159 * detect EOL and will read to EOF.
1161 c = *++cptr;
1162 if (c == EOF)
1163 unexpected_EOF();
1165 for (;;)
1167 if (isdigit(c))
1169 if (assoc == EXPECT)
1170 SRexpect = get_number();
1171 else
1172 RRexpect = get_number();
1173 break;
1176 * Looking for number before EOL.
1177 * Spaces, tabs, and numbers are ok,
1178 * words, punc., etc. are syntax errors.
1180 else if (c == '\n' || isalpha(c) || !isspace(c))
1182 syntax_error(lineno, line, cptr);
1184 else
1186 c = *++cptr;
1187 if (c == EOF)
1188 unexpected_EOF();
1193 static void
1194 declare_types(void)
1196 int c;
1197 bucket *bp;
1198 char *tag;
1200 c = nextc();
1201 if (c == EOF)
1202 unexpected_EOF();
1203 if (c != '<')
1204 syntax_error(lineno, line, cptr);
1205 tag = get_tag();
1207 for (;;)
1209 c = nextc();
1210 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1211 bp = get_name();
1212 else if (c == '\'' || c == '"')
1213 bp = get_literal();
1214 else
1215 return;
1217 if (bp->tag && tag != bp->tag)
1218 retyped_warning(bp->name);
1219 bp->tag = tag;
1223 static void
1224 declare_start(void)
1226 int c;
1227 bucket *bp;
1229 c = nextc();
1230 if (c == EOF)
1231 unexpected_EOF();
1232 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
1233 syntax_error(lineno, line, cptr);
1234 bp = get_name();
1235 if (bp->class == TERM)
1236 terminal_start(bp->name);
1237 if (goal && goal != bp)
1238 restarted_warning();
1239 goal = bp;
1242 static void
1243 read_declarations(void)
1245 int c, k;
1247 cache_size = 256;
1248 cache = MALLOC(cache_size);
1249 NO_SPACE(cache);
1251 for (;;)
1253 c = nextc();
1254 if (c == EOF)
1255 unexpected_EOF();
1256 if (c != '%')
1257 syntax_error(lineno, line, cptr);
1258 switch (k = keyword())
1260 case MARK:
1261 return;
1263 case IDENT:
1264 copy_ident();
1265 break;
1267 case TEXT:
1268 copy_text();
1269 break;
1271 case UNION:
1272 copy_union();
1273 break;
1275 case TOKEN:
1276 case LEFT:
1277 case RIGHT:
1278 case NONASSOC:
1279 declare_tokens(k);
1280 break;
1282 case EXPECT:
1283 case EXPECT_RR:
1284 declare_expect(k);
1285 break;
1287 case TYPE:
1288 declare_types();
1289 break;
1291 case START:
1292 declare_start();
1293 break;
1295 case PURE_PARSER:
1296 pure_parser = 1;
1297 break;
1299 case PARSE_PARAM:
1300 case LEX_PARAM:
1301 copy_param(k);
1302 break;
1304 case POSIX_YACC:
1305 /* noop for bison compatibility. byacc is already designed to be posix
1306 * yacc compatible. */
1307 break;
1312 static void
1313 initialize_grammar(void)
1315 nitems = 4;
1316 maxitems = 300;
1318 pitem = (bucket **)MALLOC((unsigned)maxitems * sizeof(bucket *));
1319 NO_SPACE(pitem);
1321 pitem[0] = 0;
1322 pitem[1] = 0;
1323 pitem[2] = 0;
1324 pitem[3] = 0;
1326 nrules = 3;
1327 maxrules = 100;
1329 plhs = (bucket **)MALLOC((unsigned)maxrules * sizeof(bucket *));
1330 NO_SPACE(plhs);
1332 plhs[0] = 0;
1333 plhs[1] = 0;
1334 plhs[2] = 0;
1336 rprec = (short *)MALLOC((unsigned)maxrules * sizeof(short));
1337 NO_SPACE(rprec);
1339 rprec[0] = 0;
1340 rprec[1] = 0;
1341 rprec[2] = 0;
1343 rassoc = (char *)MALLOC((unsigned)maxrules * sizeof(char));
1344 NO_SPACE(rassoc);
1346 rassoc[0] = TOKEN;
1347 rassoc[1] = TOKEN;
1348 rassoc[2] = TOKEN;
1351 static void
1352 expand_items(void)
1354 maxitems += 300;
1355 pitem = (bucket **)REALLOC(pitem, (unsigned)maxitems * sizeof(bucket *));
1356 NO_SPACE(pitem);
1359 static void
1360 expand_rules(void)
1362 maxrules += 100;
1364 plhs = (bucket **)REALLOC(plhs, (unsigned)maxrules * sizeof(bucket *));
1365 NO_SPACE(plhs);
1367 rprec = (short *)REALLOC(rprec, (unsigned)maxrules * sizeof(short));
1368 NO_SPACE(rprec);
1370 rassoc = (char *)REALLOC(rassoc, (unsigned)maxrules * sizeof(char));
1371 NO_SPACE(rassoc);
1374 static void
1375 advance_to_start(void)
1377 int c;
1378 bucket *bp;
1379 char *s_cptr;
1380 int s_lineno;
1382 for (;;)
1384 c = nextc();
1385 if (c != '%')
1386 break;
1387 s_cptr = cptr;
1388 switch (keyword())
1390 case MARK:
1391 no_grammar();
1393 case TEXT:
1394 copy_text();
1395 break;
1397 case START:
1398 declare_start();
1399 break;
1401 default:
1402 syntax_error(lineno, line, s_cptr);
1406 c = nextc();
1407 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
1408 syntax_error(lineno, line, cptr);
1409 bp = get_name();
1410 if (goal == 0)
1412 if (bp->class == TERM)
1413 terminal_start(bp->name);
1414 goal = bp;
1417 s_lineno = lineno;
1418 c = nextc();
1419 if (c == EOF)
1420 unexpected_EOF();
1421 if (c != ':')
1422 syntax_error(lineno, line, cptr);
1423 start_rule(bp, s_lineno);
1424 ++cptr;
1427 static void
1428 start_rule(bucket *bp, int s_lineno)
1430 if (bp->class == TERM)
1431 terminal_lhs(s_lineno);
1432 bp->class = NONTERM;
1433 if (nrules >= maxrules)
1434 expand_rules();
1435 plhs[nrules] = bp;
1436 rprec[nrules] = UNDEFINED;
1437 rassoc[nrules] = TOKEN;
1440 static void
1441 end_rule(void)
1443 int i;
1445 if (!last_was_action && plhs[nrules]->tag)
1447 if (pitem[nitems - 1])
1449 for (i = nitems - 1; (i > 0) && pitem[i]; --i)
1450 continue;
1451 if (pitem[i + 1] == 0 || pitem[i + 1]->tag != plhs[nrules]->tag)
1452 default_action_warning();
1454 else
1456 default_action_warning();
1460 last_was_action = 0;
1461 if (nitems >= maxitems)
1462 expand_items();
1463 pitem[nitems] = 0;
1464 ++nitems;
1465 ++nrules;
1468 static void
1469 insert_empty_rule(void)
1471 bucket *bp, **bpp;
1473 assert(cache);
1474 sprintf(cache, "$$%d", ++gensym);
1475 bp = make_bucket(cache);
1476 last_symbol->next = bp;
1477 last_symbol = bp;
1478 bp->tag = plhs[nrules]->tag;
1479 bp->class = NONTERM;
1481 if ((nitems += 2) > maxitems)
1482 expand_items();
1483 bpp = pitem + nitems - 1;
1484 *bpp-- = bp;
1485 while ((bpp[0] = bpp[-1]) != 0)
1486 --bpp;
1488 if (++nrules >= maxrules)
1489 expand_rules();
1490 plhs[nrules] = plhs[nrules - 1];
1491 plhs[nrules - 1] = bp;
1492 rprec[nrules] = rprec[nrules - 1];
1493 rprec[nrules - 1] = 0;
1494 rassoc[nrules] = rassoc[nrules - 1];
1495 rassoc[nrules - 1] = TOKEN;
1498 static void
1499 add_symbol(void)
1501 int c;
1502 bucket *bp;
1503 int s_lineno = lineno;
1505 c = *cptr;
1506 if (c == '\'' || c == '"')
1507 bp = get_literal();
1508 else
1509 bp = get_name();
1511 c = nextc();
1512 if (c == ':')
1514 end_rule();
1515 start_rule(bp, s_lineno);
1516 ++cptr;
1517 return;
1520 if (last_was_action)
1521 insert_empty_rule();
1522 last_was_action = 0;
1524 if (++nitems > maxitems)
1525 expand_items();
1526 pitem[nitems - 1] = bp;
1529 static char *
1530 after_blanks(char *s)
1532 while (*s != '\0' && isspace(UCH(*s)))
1533 ++s;
1534 return s;
1537 static void
1538 copy_action(void)
1540 int c;
1541 int i, n;
1542 int depth;
1543 int quote;
1544 char *tag;
1545 FILE *f = action_file;
1546 int a_lineno = lineno;
1547 char *a_line = dup_line();
1548 char *a_cptr = a_line + (cptr - line);
1550 if (last_was_action)
1551 insert_empty_rule();
1552 last_was_action = 1;
1554 fprintf(f, "case %d:\n", nrules - 2);
1555 if (!lflag)
1556 fprintf(f, line_format, lineno, input_file_name);
1557 if (*cptr == '=')
1558 ++cptr;
1560 /* avoid putting curly-braces in first column, to ease editing */
1561 if (*after_blanks(cptr) == L_CURL)
1563 putc('\t', f);
1564 cptr = after_blanks(cptr);
1567 n = 0;
1568 for (i = nitems - 1; pitem[i]; --i)
1569 ++n;
1571 depth = 0;
1572 loop:
1573 c = *cptr;
1574 if (c == '$')
1576 if (cptr[1] == '<')
1578 int d_lineno = lineno;
1579 char *d_line = dup_line();
1580 char *d_cptr = d_line + (cptr - line);
1582 ++cptr;
1583 tag = get_tag();
1584 c = *cptr;
1585 if (c == '$')
1587 fprintf(f, "yyval.%s", tag);
1588 ++cptr;
1589 FREE(d_line);
1590 goto loop;
1592 else if (isdigit(c))
1594 i = get_number();
1595 if (i > n)
1596 dollar_warning(d_lineno, i);
1597 fprintf(f, "yystack.l_mark[%d].%s", i - n, tag);
1598 FREE(d_line);
1599 goto loop;
1601 else if (c == '-' && isdigit(UCH(cptr[1])))
1603 ++cptr;
1604 i = -get_number() - n;
1605 fprintf(f, "yystack.l_mark[%d].%s", i, tag);
1606 FREE(d_line);
1607 goto loop;
1609 else
1610 dollar_error(d_lineno, d_line, d_cptr);
1612 else if (cptr[1] == '$')
1614 if (ntags)
1616 tag = plhs[nrules]->tag;
1617 if (tag == 0)
1618 untyped_lhs();
1619 fprintf(f, "yyval.%s", tag);
1621 else
1622 fprintf(f, "yyval");
1623 cptr += 2;
1624 goto loop;
1626 else if (isdigit(UCH(cptr[1])))
1628 ++cptr;
1629 i = get_number();
1630 if (ntags)
1632 if (i <= 0 || i > n)
1633 unknown_rhs(i);
1634 tag = pitem[nitems + i - n - 1]->tag;
1635 if (tag == 0)
1636 untyped_rhs(i, pitem[nitems + i - n - 1]->name);
1637 fprintf(f, "yystack.l_mark[%d].%s", i - n, tag);
1639 else
1641 if (i > n)
1642 dollar_warning(lineno, i);
1643 fprintf(f, "yystack.l_mark[%d]", i - n);
1645 goto loop;
1647 else if (cptr[1] == '-')
1649 cptr += 2;
1650 i = get_number();
1651 if (ntags)
1652 unknown_rhs(-i);
1653 fprintf(f, "yystack.l_mark[%d]", -i - n);
1654 goto loop;
1657 if (isalpha(c) || c == '_' || c == '$')
1661 putc(c, f);
1662 c = *++cptr;
1664 while (isalnum(c) || c == '_' || c == '$');
1665 goto loop;
1667 putc(c, f);
1668 ++cptr;
1669 switch (c)
1671 case '\n':
1672 next_line:
1673 get_line();
1674 if (line)
1675 goto loop;
1676 unterminated_action(a_lineno, a_line, a_cptr);
1678 case ';':
1679 if (depth > 0)
1680 goto loop;
1681 fprintf(f, "\nbreak;\n");
1682 free(a_line);
1683 return;
1685 case L_CURL:
1686 ++depth;
1687 goto loop;
1689 case R_CURL:
1690 if (--depth > 0)
1691 goto loop;
1692 fprintf(f, "\nbreak;\n");
1693 free(a_line);
1694 return;
1696 case '\'':
1697 case '"':
1699 int s_lineno = lineno;
1700 char *s_line = dup_line();
1701 char *s_cptr = s_line + (cptr - line - 1);
1703 quote = c;
1704 for (;;)
1706 c = *cptr++;
1707 putc(c, f);
1708 if (c == quote)
1710 FREE(s_line);
1711 goto loop;
1713 if (c == '\n')
1714 unterminated_string(s_lineno, s_line, s_cptr);
1715 if (c == '\\')
1717 c = *cptr++;
1718 putc(c, f);
1719 if (c == '\n')
1721 get_line();
1722 if (line == 0)
1723 unterminated_string(s_lineno, s_line, s_cptr);
1729 case '/':
1730 c = *cptr;
1731 if (c == '/')
1733 putc('*', f);
1734 while ((c = *++cptr) != '\n')
1736 if (c == '*' && cptr[1] == '/')
1737 fprintf(f, "* ");
1738 else
1739 putc(c, f);
1741 fprintf(f, "*/\n");
1742 goto next_line;
1744 if (c == '*')
1746 int c_lineno = lineno;
1747 char *c_line = dup_line();
1748 char *c_cptr = c_line + (cptr - line - 1);
1750 putc('*', f);
1751 ++cptr;
1752 for (;;)
1754 c = *cptr++;
1755 putc(c, f);
1756 if (c == '*' && *cptr == '/')
1758 putc('/', f);
1759 ++cptr;
1760 FREE(c_line);
1761 goto loop;
1763 if (c == '\n')
1765 get_line();
1766 if (line == 0)
1767 unterminated_comment(c_lineno, c_line, c_cptr);
1771 goto loop;
1773 default:
1774 goto loop;
1778 static int
1779 mark_symbol(void)
1781 int c;
1782 bucket *bp;
1784 c = cptr[1];
1785 if (c == '%' || c == '\\')
1787 cptr += 2;
1788 return (1);
1791 if (c == '=')
1792 cptr += 2;
1793 else if ((c == 'p' || c == 'P') &&
1794 ((c = cptr[2]) == 'r' || c == 'R') &&
1795 ((c = cptr[3]) == 'e' || c == 'E') &&
1796 ((c = cptr[4]) == 'c' || c == 'C') &&
1797 ((c = cptr[5], !IS_IDENT(c))))
1798 cptr += 5;
1799 else
1800 syntax_error(lineno, line, cptr);
1802 c = nextc();
1803 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1804 bp = get_name();
1805 else if (c == '\'' || c == '"')
1806 bp = get_literal();
1807 else
1809 syntax_error(lineno, line, cptr);
1810 /*NOTREACHED */
1813 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
1814 prec_redeclared();
1816 rprec[nrules] = bp->prec;
1817 rassoc[nrules] = bp->assoc;
1818 return (0);
1821 static void
1822 read_grammar(void)
1824 int c;
1826 initialize_grammar();
1827 advance_to_start();
1829 for (;;)
1831 c = nextc();
1832 if (c == EOF)
1833 break;
1834 if (isalpha(c)
1835 || c == '_'
1836 || c == '.'
1837 || c == '$'
1838 || c == '\''
1839 || c == '"')
1840 add_symbol();
1841 else if (c == L_CURL || c == '=')
1842 copy_action();
1843 else if (c == '|')
1845 end_rule();
1846 start_rule(plhs[nrules - 1], 0);
1847 ++cptr;
1849 else if (c == '%')
1851 if (mark_symbol())
1852 break;
1854 else
1855 syntax_error(lineno, line, cptr);
1857 end_rule();
1860 static void
1861 free_tags(void)
1863 int i;
1865 if (tag_table == 0)
1866 return;
1868 for (i = 0; i < ntags; ++i)
1870 assert(tag_table[i]);
1871 FREE(tag_table[i]);
1873 FREE(tag_table);
1876 static void
1877 pack_names(void)
1879 bucket *bp;
1880 char *p, *s, *t;
1882 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
1883 for (bp = first_symbol; bp; bp = bp->next)
1884 name_pool_size += strlen(bp->name) + 1;
1886 name_pool = MALLOC(name_pool_size);
1887 NO_SPACE(name_pool);
1889 strcpy(name_pool, "$accept");
1890 strcpy(name_pool + 8, "$end");
1891 t = name_pool + 13;
1892 for (bp = first_symbol; bp; bp = bp->next)
1894 p = t;
1895 s = bp->name;
1896 while ((*t++ = *s++) != 0)
1897 continue;
1898 FREE(bp->name);
1899 bp->name = p;
1903 static void
1904 check_symbols(void)
1906 bucket *bp;
1908 if (goal->class == UNKNOWN)
1909 undefined_goal(goal->name);
1911 for (bp = first_symbol; bp; bp = bp->next)
1913 if (bp->class == UNKNOWN)
1915 undefined_symbol_warning(bp->name);
1916 bp->class = TERM;
1921 static void
1922 protect_string(char *src, char **des)
1924 unsigned len;
1925 char *s;
1926 char *d;
1928 *des = src;
1929 if (src)
1931 len = 1;
1932 s = src;
1933 while (*s)
1935 if ('\\' == *s || '"' == *s)
1936 len++;
1937 s++;
1938 len++;
1941 *des = d = (char *)MALLOC(len);
1942 NO_SPACE(d);
1944 s = src;
1945 while (*s)
1947 if ('\\' == *s || '"' == *s)
1948 *d++ = '\\';
1949 *d++ = *s++;
1951 *d = '\0';
1955 static void
1956 pack_symbols(void)
1958 bucket *bp;
1959 bucket **v;
1960 Value_t i, j, k, n;
1962 nsyms = 2;
1963 ntokens = 1;
1964 for (bp = first_symbol; bp; bp = bp->next)
1966 ++nsyms;
1967 if (bp->class == TERM)
1968 ++ntokens;
1970 start_symbol = (Value_t) ntokens;
1971 nvars = nsyms - ntokens;
1973 symbol_name = (char **)MALLOC((unsigned)nsyms * sizeof(char *));
1974 NO_SPACE(symbol_name);
1976 symbol_value = (short *)MALLOC((unsigned)nsyms * sizeof(short));
1977 NO_SPACE(symbol_value);
1979 symbol_prec = (short *)MALLOC((unsigned)nsyms * sizeof(short));
1980 NO_SPACE(symbol_prec);
1982 symbol_assoc = MALLOC(nsyms);
1983 NO_SPACE(symbol_assoc);
1985 v = (bucket **)MALLOC((unsigned)nsyms * sizeof(bucket *));
1986 NO_SPACE(v);
1988 v[0] = 0;
1989 v[start_symbol] = 0;
1991 i = 1;
1992 j = (Value_t) (start_symbol + 1);
1993 for (bp = first_symbol; bp; bp = bp->next)
1995 if (bp->class == TERM)
1996 v[i++] = bp;
1997 else
1998 v[j++] = bp;
2000 assert(i == ntokens && j == nsyms);
2002 for (i = 1; i < ntokens; ++i)
2003 v[i]->index = i;
2005 goal->index = (Index_t) (start_symbol + 1);
2006 k = (Value_t) (start_symbol + 2);
2007 while (++i < nsyms)
2008 if (v[i] != goal)
2010 v[i]->index = k;
2011 ++k;
2014 goal->value = 0;
2015 k = 1;
2016 for (i = (Value_t) (start_symbol + 1); i < nsyms; ++i)
2018 if (v[i] != goal)
2020 v[i]->value = k;
2021 ++k;
2025 k = 0;
2026 for (i = 1; i < ntokens; ++i)
2028 n = v[i]->value;
2029 if (n > 256)
2031 for (j = k++; j > 0 && symbol_value[j - 1] > n; --j)
2032 symbol_value[j] = symbol_value[j - 1];
2033 symbol_value[j] = n;
2037 assert(v[1] != 0);
2039 if (v[1]->value == UNDEFINED)
2040 v[1]->value = 256;
2042 j = 0;
2043 n = 257;
2044 for (i = 2; i < ntokens; ++i)
2046 if (v[i]->value == UNDEFINED)
2048 while (j < k && n == symbol_value[j])
2050 while (++j < k && n == symbol_value[j])
2051 continue;
2052 ++n;
2054 v[i]->value = n;
2055 ++n;
2059 symbol_name[0] = name_pool + 8;
2060 symbol_value[0] = 0;
2061 symbol_prec[0] = 0;
2062 symbol_assoc[0] = TOKEN;
2063 for (i = 1; i < ntokens; ++i)
2065 symbol_name[i] = v[i]->name;
2066 symbol_value[i] = v[i]->value;
2067 symbol_prec[i] = v[i]->prec;
2068 symbol_assoc[i] = v[i]->assoc;
2070 symbol_name[start_symbol] = name_pool;
2071 symbol_value[start_symbol] = -1;
2072 symbol_prec[start_symbol] = 0;
2073 symbol_assoc[start_symbol] = TOKEN;
2074 for (++i; i < nsyms; ++i)
2076 k = v[i]->index;
2077 symbol_name[k] = v[i]->name;
2078 symbol_value[k] = v[i]->value;
2079 symbol_prec[k] = v[i]->prec;
2080 symbol_assoc[k] = v[i]->assoc;
2083 if (gflag)
2085 symbol_pname = (char **)MALLOC((unsigned)nsyms * sizeof(char *));
2086 NO_SPACE(symbol_pname);
2088 for (i = 0; i < nsyms; ++i)
2089 protect_string(symbol_name[i], &(symbol_pname[i]));
2092 FREE(v);
2095 static void
2096 pack_grammar(void)
2098 int i;
2099 Value_t j;
2100 Assoc_t assoc;
2101 Value_t prec2;
2103 ritem = (short *)MALLOC((unsigned)nitems * sizeof(short));
2104 NO_SPACE(ritem);
2106 rlhs = (short *)MALLOC((unsigned)nrules * sizeof(short));
2107 NO_SPACE(rlhs);
2109 rrhs = (short *)MALLOC((unsigned)(nrules + 1) * sizeof(short));
2110 NO_SPACE(rrhs);
2112 rprec = (short *)REALLOC(rprec, (unsigned)nrules * sizeof(short));
2113 NO_SPACE(rprec);
2115 rassoc = REALLOC(rassoc, nrules);
2116 NO_SPACE(rassoc);
2118 ritem[0] = -1;
2119 ritem[1] = goal->index;
2120 ritem[2] = 0;
2121 ritem[3] = -2;
2122 rlhs[0] = 0;
2123 rlhs[1] = 0;
2124 rlhs[2] = start_symbol;
2125 rrhs[0] = 0;
2126 rrhs[1] = 0;
2127 rrhs[2] = 1;
2129 j = 4;
2130 for (i = 3; i < nrules; ++i)
2132 rlhs[i] = plhs[i]->index;
2133 rrhs[i] = j;
2134 assoc = TOKEN;
2135 prec2 = 0;
2136 while (pitem[j])
2138 ritem[j] = pitem[j]->index;
2139 if (pitem[j]->class == TERM)
2141 prec2 = pitem[j]->prec;
2142 assoc = pitem[j]->assoc;
2144 ++j;
2146 ritem[j] = (Value_t) - i;
2147 ++j;
2148 if (rprec[i] == UNDEFINED)
2150 rprec[i] = prec2;
2151 rassoc[i] = assoc;
2154 rrhs[i] = j;
2156 FREE(plhs);
2157 FREE(pitem);
2160 static void
2161 print_grammar(void)
2163 int i, k;
2164 size_t j, spacing = 0;
2165 FILE *f = verbose_file;
2167 if (!vflag)
2168 return;
2170 k = 1;
2171 for (i = 2; i < nrules; ++i)
2173 if (rlhs[i] != rlhs[i - 1])
2175 if (i != 2)
2176 fprintf(f, "\n");
2177 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
2178 spacing = strlen(symbol_name[rlhs[i]]) + 1;
2180 else
2182 fprintf(f, "%4d ", i - 2);
2183 j = spacing;
2184 while (j-- != 0)
2185 putc(' ', f);
2186 putc('|', f);
2189 while (ritem[k] >= 0)
2191 fprintf(f, " %s", symbol_name[ritem[k]]);
2192 ++k;
2194 ++k;
2195 putc('\n', f);
2199 void
2200 reader(void)
2202 write_section(code_file, banner);
2203 create_symbol_table();
2204 read_declarations();
2205 read_grammar();
2206 free_symbol_table();
2207 free_tags();
2208 pack_names();
2209 check_symbols();
2210 pack_symbols();
2211 pack_grammar();
2212 free_symbols();
2213 print_grammar();
2216 #ifdef NO_LEAKS
2217 static param *
2218 free_declarations(param * list)
2220 while (list != 0)
2222 param *next = list->next;
2223 free(list->type);
2224 free(list->name);
2225 free(list->type2);
2226 free(list);
2227 list = next;
2229 return list;
2232 void
2233 reader_leaks(void)
2235 lex_param = free_declarations(lex_param);
2236 parse_param = free_declarations(parse_param);
2238 DO_FREE(line);
2239 DO_FREE(rrhs);
2240 DO_FREE(rlhs);
2241 DO_FREE(rprec);
2242 DO_FREE(ritem);
2243 DO_FREE(rassoc);
2244 DO_FREE(cache);
2245 DO_FREE(name_pool);
2246 DO_FREE(symbol_name);
2247 DO_FREE(symbol_prec);
2248 DO_FREE(symbol_assoc);
2249 DO_FREE(symbol_value);
2251 #endif