Fix typo in OIDs corresponding to SHA256, SHA384, and SHA512 (#21707)
[mono-project.git] / mcs / jay / reader.c
blob96bcac4634efcbe83989d5cf9a29bc1b1193fe59
1 /*
2 * Copyright (c) 1989 The Regents of the University of California.
3 * All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Robert Paul Corbett.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
37 #ifndef lint
38 static char sccsid[] = "@(#)reader.c 5.7 (Berkeley) 1/20/91";
39 #endif /* not lint */
41 #include "defs.h"
43 /* this resolves "unresolved symbol _snprintf" on Windows */
44 #if defined (_MSC_VER)
45 #define snprintf _snprintf
46 #endif
48 /* The line size must be a positive integer. One hundred was chosen */
49 /* because few lines in Yacc input grammars exceed 100 characters. */
50 /* Note that if a line exceeds LINESIZE characters, the line buffer */
51 /* will be expanded to accomodate it. */
53 #define LINESIZE 100
55 static
56 char *cache;
57 static
58 int cinc, cache_size;
60 static
61 int ntags, tagmax;
62 static
63 char **tag_table;
65 static
66 char saw_eof;
67 char *cptr, *line;
68 static
69 int linesize;
71 static
72 bucket *goal;
73 static
74 int prec;
75 static
76 int gensym;
77 static
78 char last_was_action;
80 static
81 int maxitems;
82 static
83 bucket **pitem;
85 static
86 int maxrules;
87 static
88 bucket **plhs;
90 static
91 int maxmethods;
93 static
94 int name_pool_size;
95 static
96 char *name_pool;
98 const char *line_format = "\t\t\t\t\t// line %d \"%s\"\n";
99 const char *default_line_format = "\t\t\t\t\t// line %d\n";
101 static void
102 start_rule (bucket *bp, int s_lineno);
104 static void
105 cachec (int c)
107 assert(cinc >= 0);
108 if (cinc >= cache_size)
110 cache_size += 256;
111 cache = (char*)REALLOC(cache, cache_size);
112 if (cache == 0) no_space();
114 cache[cinc] = c;
115 ++cinc;
118 static void
119 get_line (void)
121 register FILE *f = input_file;
122 register int c;
123 register int i;
125 if (saw_eof || (c = getc(f)) == EOF)
127 if (line) { FREE(line); line = 0; }
128 cptr = 0;
129 saw_eof = 1;
130 return;
133 if (line == 0 || linesize != (LINESIZE + 1))
135 if (line) FREE(line);
136 linesize = LINESIZE + 1;
137 line = (char*)MALLOC(linesize);
138 if (line == 0) no_space();
141 i = 0;
142 ++lineno;
143 for (;;)
145 line[i] = c;
146 if (c == '\n') { cptr = line; return; }
147 if (++i >= linesize)
149 linesize += LINESIZE;
150 line = (char*)REALLOC(line, linesize);
151 if (line == 0) no_space();
153 c = getc(f);
154 if (c == EOF)
156 line[i] = '\n';
157 saw_eof = 1;
158 cptr = line;
159 return;
164 static char *
165 dup_line (void)
167 register char *p, *s, *t;
169 if (line == 0) return (0);
170 s = line;
171 while (*s != '\n') ++s;
172 p = (char*)MALLOC(s - line + 1);
173 if (p == 0) no_space();
175 s = line;
176 t = p;
177 while ((*t++ = *s++) != '\n') continue;
178 return (p);
181 static void
182 skip_comment (void)
184 register char *s;
186 int st_lineno = lineno;
187 char *st_line = dup_line();
188 char *st_cptr = st_line + (cptr - line);
190 s = cptr + 2;
191 for (;;)
193 if (*s == '*' && s[1] == '/')
195 cptr = s + 2;
196 FREE(st_line);
197 return;
199 if (*s == '\n')
201 get_line();
202 if (line == 0)
203 unterminated_comment(st_lineno, st_line, st_cptr);
204 s = cptr;
206 else
207 ++s;
211 static int
212 nextc (void)
214 register char *s;
216 if (line == 0)
218 get_line();
219 if (line == 0)
220 return (EOF);
223 s = cptr;
224 for (;;)
226 switch (*s)
228 case '\n':
229 get_line();
230 if (line == 0) return (EOF);
231 s = cptr;
232 break;
234 case ' ':
235 case '\t':
236 case '\f':
237 case '\r':
238 case '\v':
239 case ',':
240 case ';':
241 ++s;
242 break;
244 case '\\':
245 cptr = s;
246 return ('%');
248 case '/':
249 if (s[1] == '*')
251 cptr = s;
252 skip_comment();
253 s = cptr;
254 break;
256 else if (s[1] == '/')
258 get_line();
259 if (line == 0) return (EOF);
260 s = cptr;
261 break;
263 /* fall through */
265 default:
266 cptr = s;
267 return (*s);
272 static int
273 keyword (void)
275 register int c;
276 char *t_cptr = cptr;
278 c = *++cptr;
279 if (isalpha(c))
281 cinc = 0;
282 for (;;)
284 if (isalpha(c))
286 if (isupper(c)) c = tolower(c);
287 cachec(c);
289 else if (isdigit(c) || c == '_' || c == '.' || c == '$')
290 cachec(c);
291 else
292 break;
293 c = *++cptr;
295 cachec(NUL);
297 if (strcmp(cache, "token") == 0 || strcmp(cache, "term") == 0)
298 return (TOKEN);
299 if (strcmp(cache, "type") == 0)
300 return (TYPE);
301 if (strcmp(cache, "left") == 0)
302 return (LEFT);
303 if (strcmp(cache, "right") == 0)
304 return (RIGHT);
305 if (strcmp(cache, "nonassoc") == 0 || strcmp(cache, "binary") == 0)
306 return (NONASSOC);
307 if (strcmp(cache, "start") == 0)
308 return (START);
310 else
312 ++cptr;
313 if (c == '{')
314 return (TEXT);
315 if (c == '%' || c == '\\')
316 return (MARK);
317 if (c == '<')
318 return (LEFT);
319 if (c == '>')
320 return (RIGHT);
321 if (c == '0')
322 return (TOKEN);
323 if (c == '2')
324 return (NONASSOC);
326 syntax_error(lineno, line, t_cptr);
327 /*NOTREACHED*/
330 static void
331 copy_text (FILE *f)
333 register int c;
334 int quote;
335 int need_newline = 0;
336 int t_lineno = lineno;
337 char *t_line = dup_line();
338 char *t_cptr = t_line + (cptr - line - 2);
340 if (*cptr == '\n')
342 get_line();
343 if (line == 0)
344 unterminated_text(t_lineno, t_line, t_cptr);
346 fprintf(f, line_format, lineno, input_file_name);
348 loop:
349 c = *cptr++;
350 switch (c)
352 case '\n':
353 next_line:
354 putc('\n', f);
355 need_newline = 0;
356 get_line();
357 if (line) goto loop;
358 unterminated_text(t_lineno, t_line, t_cptr);
360 case '\'':
361 case '"':
363 int s_lineno = lineno;
364 char *s_line = dup_line();
365 char *s_cptr = s_line + (cptr - line - 1);
367 quote = c;
368 putc(c, f);
369 for (;;)
371 c = *cptr++;
372 putc(c, f);
373 if (c == quote)
375 need_newline = 1;
376 FREE(s_line);
377 goto loop;
379 if (c == '\n')
380 unterminated_string(s_lineno, s_line, s_cptr);
381 if (c == '\\')
383 c = *cptr++;
384 putc(c, f);
385 if (c == '\n')
387 get_line();
388 if (line == 0)
389 unterminated_string(s_lineno, s_line, s_cptr);
395 case '/':
396 putc(c, f);
397 need_newline = 1;
398 c = *cptr;
399 if (c == '/')
401 do putc(c, f); while ((c = *++cptr) != '\n');
402 goto next_line;
404 if (c == '*')
406 int c_lineno = lineno;
407 char *c_line = dup_line();
408 char *c_cptr = c_line + (cptr - line - 1);
410 putc('*', f);
411 ++cptr;
412 for (;;)
414 c = *cptr++;
415 putc(c, f);
416 if (c == '*' && *cptr == '/')
418 putc('/', f);
419 ++cptr;
420 FREE(c_line);
421 goto loop;
423 if (c == '\n')
425 get_line();
426 if (line == 0)
427 unterminated_comment(c_lineno, c_line, c_cptr);
431 need_newline = 1;
432 goto loop;
434 case '%':
435 case '\\':
436 if (*cptr == '}')
438 if (need_newline) putc('\n', f);
439 ++cptr;
440 FREE(t_line);
441 return;
443 /* fall through */
445 default:
446 putc(c, f);
447 need_newline = 1;
448 goto loop;
452 static int
453 hexval (int c)
455 if (c >= '0' && c <= '9')
456 return (c - '0');
457 if (c >= 'A' && c <= 'F')
458 return (c - 'A' + 10);
459 if (c >= 'a' && c <= 'f')
460 return (c - 'a' + 10);
461 return (-1);
464 static bucket *
465 get_literal (void)
467 register int c, quote;
468 register int i;
469 register int n;
470 register char *s;
471 register bucket *bp;
472 int s_lineno = lineno;
473 char *s_line = dup_line();
474 char *s_cptr = s_line + (cptr - line);
476 quote = *cptr++;
477 cinc = 0;
478 for (;;)
480 c = *cptr++;
481 if (c == quote) break;
482 if (c == '\n') unterminated_string(s_lineno, s_line, s_cptr);
483 if (c == '\\')
485 char *c_cptr = cptr - 1;
487 c = *cptr++;
488 switch (c)
490 case '\n':
491 get_line();
492 if (line == 0) unterminated_string(s_lineno, s_line, s_cptr);
493 continue;
495 case '0': case '1': case '2': case '3':
496 case '4': case '5': case '6': case '7':
497 n = c - '0';
498 c = *cptr;
499 if (IS_OCTAL(c))
501 n = (n << 3) + (c - '0');
502 c = *++cptr;
503 if (IS_OCTAL(c))
505 n = (n << 3) + (c - '0');
506 ++cptr;
509 if (n > MAXCHAR) illegal_character(c_cptr);
510 c = n;
511 break;
513 case 'x':
514 c = *cptr++;
515 n = hexval(c);
516 if (n < 0 || n >= 16)
517 illegal_character(c_cptr);
518 for (;;)
520 c = *cptr;
521 i = hexval(c);
522 if (i < 0 || i >= 16) break;
523 ++cptr;
524 n = (n << 4) + i;
525 if (n > MAXCHAR) illegal_character(c_cptr);
527 c = n;
528 break;
530 case 'a': c = 7; break;
531 case 'b': c = '\b'; break;
532 case 'f': c = '\f'; break;
533 case 'n': c = '\n'; break;
534 case 'r': c = '\r'; break;
535 case 't': c = '\t'; break;
536 case 'v': c = '\v'; break;
539 cachec(c);
541 FREE(s_line);
543 n = cinc;
544 s = (char*)MALLOC(n);
545 if (s == 0) no_space();
547 for (i = 0; i < n; ++i)
548 s[i] = cache[i];
550 cinc = 0;
551 if (n == 1)
552 cachec('\'');
553 else
554 cachec('"');
556 for (i = 0; i < n; ++i)
558 c = ((unsigned char *)s)[i];
559 if (c == '\\' || c == cache[0])
561 cachec('\\');
562 cachec(c);
564 else if (isprint(c))
565 cachec(c);
566 else
568 cachec('\\');
569 switch (c)
571 case 7: cachec('a'); break;
572 case '\b': cachec('b'); break;
573 case '\f': cachec('f'); break;
574 case '\n': cachec('n'); break;
575 case '\r': cachec('r'); break;
576 case '\t': cachec('t'); break;
577 case '\v': cachec('v'); break;
578 default:
579 cachec(((c >> 6) & 7) + '0');
580 cachec(((c >> 3) & 7) + '0');
581 cachec((c & 7) + '0');
582 break;
587 if (n == 1)
588 cachec('\'');
589 else
590 cachec('"');
592 cachec(NUL);
593 bp = lookup(cache);
594 bp->class = TERM;
595 if (n == 1 && bp->value == UNDEFINED)
596 bp->value = *(unsigned char *)s;
597 FREE(s);
599 return (bp);
602 static int
603 is_reserved (const char *name)
605 const char *s;
607 if (strcmp(name, ".") == 0 ||
608 strcmp(name, "$accept") == 0 ||
609 strcmp(name, "$end") == 0)
610 return (1);
612 if (name[0] == '$' && name[1] == '$' && isdigit(name[2]))
614 s = name + 3;
615 while (isdigit(*s)) ++s;
616 if (*s == NUL) return (1);
619 return (0);
622 static bucket *
623 get_name (void)
625 register int c;
627 cinc = 0;
628 for (c = *cptr; IS_IDENT(c); c = *++cptr)
629 cachec(c);
630 cachec(NUL);
632 if (is_reserved(cache)) used_reserved(cache);
634 return (lookup(cache));
637 static int
638 get_number (void)
640 register int c;
641 register int n;
643 n = 0;
644 for (c = *cptr; isdigit(c); c = *++cptr)
645 n = 10*n + (c - '0');
647 return (n);
650 static char *
651 get_tag (int emptyOk)
653 register int c;
654 register int i;
655 register char *s;
656 int t_lineno = lineno;
657 char *t_line = dup_line();
658 char *t_cptr = t_line + (cptr - line);
660 ++cptr;
661 c = nextc();
662 if (c == EOF) unexpected_EOF();
663 if (emptyOk && c == '>') {
664 ++cptr; return 0; // 0 indicates empty tag if emptyOk
666 if (!isalpha(c) && c != '_' && c != '$')
667 illegal_tag(t_lineno, t_line, t_cptr);
669 cinc = 0;
670 do { cachec(c); c = *++cptr; } while (IS_IDENT(c));
671 cachec(NUL);
673 c = nextc();
674 if (c == EOF) unexpected_EOF();
675 if (c != '>')
676 illegal_tag(t_lineno, t_line, t_cptr);
677 ++cptr;
679 for (i = 0; i < ntags; ++i)
681 if (strcmp(cache, tag_table[i]) == 0)
682 return (tag_table[i]);
685 if (ntags >= tagmax)
687 tagmax += 16;
688 tag_table = (char **)
689 (tag_table ? REALLOC(tag_table, tagmax*sizeof(char *))
690 : MALLOC(tagmax*sizeof(char *)));
691 if (tag_table == 0) no_space();
694 s = (char*)MALLOC(cinc);
695 if (s == 0) no_space();
696 strcpy(s, cache);
697 tag_table[ntags] = s;
698 ++ntags;
699 FREE(t_line);
700 return (s);
703 static void
704 declare_tokens (int assoc)
706 register int c;
707 register bucket *bp;
708 int value;
709 char *tag = 0;
711 if (assoc != TOKEN) ++prec;
713 c = nextc();
714 if (c == EOF) unexpected_EOF();
715 if (c == '<')
717 tag = get_tag(0);
718 c = nextc();
719 if (c == EOF) unexpected_EOF();
722 for (;;)
724 if (isalpha(c) || c == '_' || c == '.' || c == '$')
725 bp = get_name();
726 else if (c == '\'' || c == '"')
727 bp = get_literal();
728 else
729 return;
731 if (bp == goal) tokenized_start(bp->name);
732 bp->class = TERM;
734 if (tag)
736 if (bp->tag && tag != bp->tag)
737 retyped_warning(bp->name);
738 bp->tag = tag;
741 if (assoc != TOKEN)
743 if (bp->prec && prec != bp->prec)
744 reprec_warning(bp->name);
745 bp->assoc = assoc;
746 bp->prec = prec;
749 c = nextc();
750 if (c == EOF) unexpected_EOF();
751 value = UNDEFINED;
752 if (isdigit(c))
754 value = get_number();
755 if (bp->value != UNDEFINED && value != bp->value)
756 revalued_warning(bp->name);
757 bp->value = value;
758 c = nextc();
759 if (c == EOF) unexpected_EOF();
764 static void
765 declare_types (void)
767 register int c;
768 register bucket *bp;
769 char *tag;
771 c = nextc();
772 if (c == EOF) unexpected_EOF();
773 if (c != '<') syntax_error(lineno, line, cptr);
774 tag = get_tag(0);
776 for (;;)
778 c = nextc();
779 if (isalpha(c) || c == '_' || c == '.' || c == '$')
780 bp = get_name();
781 else if (c == '\'' || c == '"')
782 bp = get_literal();
783 else
784 return;
786 if (bp->tag && tag != bp->tag)
787 retyped_warning(bp->name);
788 bp->tag = tag;
792 static void
793 declare_start (void)
795 register int c;
796 register bucket *bp;
798 c = nextc();
799 if (c == EOF) unexpected_EOF();
800 if (!isalpha(c) && c != '_' && c != '.' && c != '$')
801 syntax_error(lineno, line, cptr);
802 bp = get_name();
803 if (bp->class == TERM)
804 terminal_start(bp->name);
805 if (goal && goal != bp)
806 restarted_warning();
807 goal = bp;
810 static void
811 read_declarations (void)
813 register int c, k;
815 cache_size = 256;
816 cache = (char*)MALLOC(cache_size);
817 if (cache == 0) no_space();
819 for (;;)
821 c = nextc();
822 if (c == EOF) unexpected_EOF();
823 if (c != '%') syntax_error(lineno, line, cptr);
824 switch (k = keyword())
826 case MARK:
827 return;
829 case TEXT:
830 copy_text(prolog_file);
831 break;
833 case TOKEN:
834 case LEFT:
835 case RIGHT:
836 case NONASSOC:
837 declare_tokens(k);
838 break;
840 case TYPE:
841 declare_types();
842 break;
844 case START:
845 declare_start();
846 break;
851 static void
852 initialize_grammar (void)
854 nitems = 4;
855 maxitems = 300;
856 pitem = (bucket **) MALLOC(maxitems*sizeof(bucket *));
857 if (pitem == 0) no_space();
858 pitem[0] = 0;
859 pitem[1] = 0;
860 pitem[2] = 0;
861 pitem[3] = 0;
863 nmethods = 0;
864 nrules = 3;
865 maxrules = 100;
866 plhs = (bucket **) MALLOC(maxrules*sizeof(bucket *));
867 if (plhs == 0) no_space();
868 plhs[0] = 0;
869 plhs[1] = 0;
870 plhs[2] = 0;
871 rprec = (short *) MALLOC(maxrules*sizeof(short));
872 if (rprec == 0) no_space();
873 rprec[0] = 0;
874 rprec[1] = 0;
875 rprec[2] = 0;
876 rassoc = (char *) MALLOC(maxrules*sizeof(char));
877 if (rassoc == 0) no_space();
878 rassoc[0] = TOKEN;
879 rassoc[1] = TOKEN;
880 rassoc[2] = TOKEN;
883 static void
884 expand_items (void)
886 maxitems += 300;
887 pitem = (bucket **) REALLOC(pitem, maxitems*sizeof(bucket *));
888 if (pitem == 0) no_space();
889 memset(pitem+maxitems-300, 0, 300*sizeof(bucket *));
892 static void
893 expand_rules (void)
895 maxrules += 100;
896 plhs = (bucket **) REALLOC(plhs, maxrules*sizeof(bucket *));
897 if (plhs == 0) no_space();
898 rprec = (short *) REALLOC(rprec, maxrules*sizeof(short));
899 if (rprec == 0) no_space();
900 rassoc = (char *) REALLOC(rassoc, maxrules*sizeof(char));
901 if (rassoc == 0) no_space();
904 static void
905 advance_to_start (void)
907 register int c;
908 register bucket *bp;
909 char *s_cptr;
910 int s_lineno;
912 for (;;)
914 c = nextc();
915 if (c != '%') break;
916 s_cptr = cptr;
917 switch (keyword())
919 case MARK:
920 no_grammar();
922 case TEXT:
923 copy_text(local_file);
924 break;
926 case START:
927 declare_start();
928 break;
930 default:
931 syntax_error(lineno, line, s_cptr);
935 c = nextc();
936 if (!isalpha(c) && c != '_' && c != '.' && c != '_')
937 syntax_error(lineno, line, cptr);
938 bp = get_name();
939 if (goal == 0)
941 if (bp->class == TERM)
942 terminal_start(bp->name);
943 goal = bp;
946 s_lineno = lineno;
947 c = nextc();
948 if (c == EOF) unexpected_EOF();
949 if (c != ':') syntax_error(lineno, line, cptr);
950 start_rule(bp, s_lineno);
951 ++cptr;
954 static void
955 start_rule (bucket *bp, int s_lineno)
957 if (bp->class == TERM)
958 terminal_lhs(s_lineno);
959 bp->class = NONTERM;
960 if (nrules >= maxrules)
961 expand_rules();
962 plhs[nrules] = bp;
963 rprec[nrules] = UNDEFINED;
964 rassoc[nrules] = TOKEN;
967 static void
968 end_rule (void)
970 register int i;
972 if (nitems >= maxitems) expand_items();
974 if (!last_was_action && plhs[nrules]->tag)
976 for (i = nitems - 1; pitem[i]; --i) continue;
977 if (pitem[i+1] == 0 || pitem[i+1]->tag != plhs[nrules]->tag)
978 default_action_warning(); /** if classes don't match exactly **/
979 } /** bug: could be superclass... **/
981 last_was_action = 0;
982 pitem[nitems] = 0;
983 ++nitems;
984 ++nrules;
987 static void
988 insert_empty_rule (void)
990 register bucket *bp, **bpp;
992 assert(cache);
993 sprintf(cache, "$$%d", ++gensym);
994 bp = make_bucket(cache);
995 last_symbol->next = bp;
996 last_symbol = bp;
997 bp->tag = plhs[nrules]->tag;
998 bp->class = NONTERM;
1000 if ((nitems += 2) > maxitems)
1001 expand_items();
1002 bpp = pitem + nitems - 1;
1003 *bpp-- = bp;
1004 while ((bpp[0] = bpp[-1])) --bpp;
1006 if (++nrules >= maxrules)
1007 expand_rules();
1008 plhs[nrules] = plhs[nrules-1];
1009 plhs[nrules-1] = bp;
1010 rprec[nrules] = rprec[nrules-1];
1011 rprec[nrules-1] = 0;
1012 rassoc[nrules] = rassoc[nrules-1];
1013 rassoc[nrules-1] = TOKEN;
1016 static void
1017 add_symbol (void)
1019 register int c;
1020 register bucket *bp;
1021 int s_lineno = lineno;
1023 c = *cptr;
1024 if (c == '\'' || c == '"')
1025 bp = get_literal();
1026 else
1027 bp = get_name();
1029 c = nextc();
1030 if (c == ':')
1032 end_rule();
1033 start_rule(bp, s_lineno);
1034 ++cptr;
1035 return;
1038 if (last_was_action)
1039 insert_empty_rule();
1040 last_was_action = 0;
1042 if (++nitems > maxitems)
1043 expand_items();
1044 pitem[nitems-1] = bp;
1047 static void
1048 copy_action (void)
1050 register int c;
1051 register int i, n;
1052 int depth;
1053 int quote;
1054 char *tag;
1055 FILE *f = action_file;
1056 int a_lineno = lineno;
1057 char *a_line = dup_line();
1058 char *a_cptr = a_line + (cptr - line);
1059 char buffer [10000];
1060 int len = 0;
1061 int comment_lines = 0;
1062 char *mbody;
1063 memset (buffer, 0, 10000);
1065 if (last_was_action)
1066 insert_empty_rule();
1067 last_was_action = 1;
1069 fprintf(f, "case %d:\n", nrules - 2);
1070 if (*cptr == '=') ++cptr;
1072 n = 0;
1074 for (i = nitems - 1; pitem[i]; --i) ++n;
1076 depth = 0;
1077 loop:
1078 c = *cptr;
1079 if (c == '$')
1081 if (cptr[1] == '<')
1083 int d_lineno = lineno;
1084 char *d_line = dup_line();
1085 char *d_cptr = d_line + (cptr - line);
1087 ++cptr;
1088 tag = get_tag(1);
1089 c = *cptr;
1090 if (c == '$')
1092 if (tag && strcmp(tag, "Object")) {
1093 len += sprintf(buffer + len, "((%s)yyVal)", tag);
1094 } else {
1095 strcat (buffer + len, "yyVal");
1096 len += 5;
1098 ++cptr;
1099 FREE(d_line);
1100 goto loop;
1102 else if (isdigit(c))
1104 i = get_number();
1105 if (i > n) dollar_warning(d_lineno, i);
1106 if (tag && strcmp(tag, "Object"))
1107 len += sprintf(buffer + len, "((%s)yyVals[%d+yyTop])", tag, i - n);
1108 else
1109 len += sprintf(buffer + len, "yyVals[%d+yyTop]", i - n);
1110 FREE(d_line);
1111 goto loop;
1113 else if (c == '-' && isdigit(cptr[1]))
1115 ++cptr;
1116 i = -get_number() - n;
1117 if (tag && strcmp(tag, "Object"))
1118 len += sprintf(buffer + len, "((%s)yyVals[%d+yyTop])", tag, i);
1119 else
1120 len += sprintf(buffer + len, "yyVals[%d+yyTop]", i);
1121 FREE(d_line);
1122 goto loop;
1124 else
1125 dollar_error(d_lineno, d_line, d_cptr);
1127 else if (cptr[1] == '$')
1129 if (ntags && plhs[nrules]->tag == 0)
1130 untyped_lhs();
1131 strcat (buffer, "yyVal");
1132 len += 5;
1133 cptr += 2;
1134 goto loop;
1136 else if (isdigit(cptr[1]))
1138 ++cptr;
1139 i = get_number();
1140 if (ntags)
1142 if (i <= 0 || i > n)
1143 unknown_rhs(i);
1144 tag = pitem[nitems + i - n - 1]->tag;
1145 if (tag == 0)
1146 untyped_rhs(i, pitem[nitems + i - n - 1]->name),
1147 len += sprintf(buffer + len, "yyVals[%d+yyTop]", i - n);
1148 else if (strcmp(tag, "Object"))
1149 len += sprintf(buffer + len, "((%s)yyVals[%d+yyTop])", tag, i - n);
1150 else
1151 len += sprintf(buffer + len, "yyVals[%d+yyTop]", i - n);
1153 else
1155 if (i > n)
1156 dollar_warning(lineno, i);
1158 len += sprintf(buffer + len,"yyVals[%d+yyTop]", i - n);
1160 goto loop;
1162 else if (cptr[1] == '-')
1164 cptr += 2;
1165 i = get_number();
1166 if (ntags)
1167 unknown_rhs(-i);
1168 len += sprintf(buffer + len, "yyVals[%d+yyTop]", -i - n);
1169 goto loop;
1172 if (isalpha(c) || c == '_' || c == '$')
1176 buffer[len++] = c;
1177 c = *++cptr;
1178 } while (isalnum(c) || c == '_' || c == '$');
1179 goto loop;
1181 buffer[len++] = c;
1182 ++cptr;
1183 switch (c)
1185 case '\n':
1186 next_line:
1187 get_line();
1188 if (line) goto loop;
1189 unterminated_action(a_lineno, a_line, a_cptr);
1191 case ';':
1192 if (depth > 0) goto loop;
1193 break;
1195 case '{':
1196 ++depth;
1197 goto loop;
1199 case '}':
1200 if (--depth > 0) goto loop;
1201 break;
1203 case '\'':
1204 case '"':
1206 int s_lineno = lineno;
1207 char *s_line = dup_line();
1208 char *s_cptr = s_line + (cptr - line - 1);
1210 quote = c;
1211 for (;;)
1213 c = *cptr++;
1214 buffer[len++] = c;
1215 if (c == quote)
1217 FREE(s_line);
1218 goto loop;
1220 if (c == '\n')
1221 unterminated_string(s_lineno, s_line, s_cptr);
1222 if (c == '\\')
1224 c = *cptr++;
1225 buffer[len++] = c;
1226 if (c == '\n')
1228 get_line();
1229 if (line == 0)
1230 unterminated_string(s_lineno, s_line, s_cptr);
1236 case '/':
1237 c = *cptr;
1238 if (c == '/')
1240 buffer[len++] = '*';
1241 while ((c = *++cptr) != '\n')
1243 if (c == '*' && cptr[1] == '/'){
1244 buffer[len++] = '*';
1245 buffer[len++] = ' ';
1246 } else {
1247 buffer[len++] = c;
1250 buffer[len++] = '*';
1251 buffer[len++] = '/';
1252 buffer[len++] = '\n';
1253 goto next_line;
1255 if (c == '*')
1257 int c_lineno = lineno;
1258 char *c_line = dup_line();
1259 char *c_cptr = c_line + (cptr - line - 1);
1261 buffer[len++] = '*';
1262 ++cptr;
1263 for (;;)
1265 c = *cptr++;
1266 buffer[len++] = c;
1267 if (c == '*' && *cptr == '/')
1269 buffer[len++] = '/';
1270 ++cptr;
1271 FREE(c_line);
1272 goto loop;
1274 if (c == '\n')
1276 ++comment_lines;
1277 get_line();
1278 if (line == 0)
1279 unterminated_comment(c_lineno, c_line, c_cptr);
1283 goto loop;
1285 default:
1286 goto loop;
1289 if (comment_lines > 0)
1290 comment_lines++;
1292 if ((lineno - (a_lineno + comment_lines)) > 2)
1294 char mname[28];
1295 char *line_define;
1297 // the maximum size of of an unsigned int in characters is 20, with 8 for 'case_()\0'
1298 sprintf(mname, "case_%d()", nrules - 2);
1300 putc(' ', f); putc(' ', f);
1301 fputs(mname, f);
1302 fprintf(f, ";");
1303 if (nmethods == 0)
1305 maxmethods = 100;
1306 methods = NEW2(maxmethods, char *);
1308 else if (nmethods == maxmethods)
1310 maxmethods += 500;
1311 methods = (char**)REALLOC (methods, maxmethods*sizeof(char *));
1314 line_define = NEW2(snprintf(NULL, 0, line_format, a_lineno, input_file_name)+1, char);
1315 sprintf(line_define, line_format, a_lineno, input_file_name);
1317 mbody = NEW2(5+strlen(line_define)+1+strlen(mname)+strlen(buffer)+1, char);
1318 strcpy(mbody, "void ");
1319 strcat(mbody, mname);
1320 strcat(mbody, "\n");
1321 strcat(mbody, line_define);
1322 strcat(mbody, buffer);
1323 methods[nmethods++] = mbody;
1325 FREE(line_define);
1327 else
1329 fprintf(f, line_format, lineno, input_file_name);
1330 putc(' ', f); putc(' ', f);
1331 fwrite(buffer, 1, len, f);
1334 fprintf(f, "\n break;\n");
1337 static int
1338 mark_symbol (void)
1340 register int c;
1341 register bucket *bp = NULL;
1343 c = cptr[1];
1344 if (c == '%' || c == '\\')
1346 cptr += 2;
1347 return (1);
1350 if (c == '=')
1351 cptr += 2;
1352 else if ((c == 'p' || c == 'P') &&
1353 ((c = cptr[2]) == 'r' || c == 'R') &&
1354 ((c = cptr[3]) == 'e' || c == 'E') &&
1355 ((c = cptr[4]) == 'c' || c == 'C') &&
1356 ((c = cptr[5], !IS_IDENT(c))))
1357 cptr += 5;
1358 else
1359 syntax_error(lineno, line, cptr);
1361 c = nextc();
1362 if (isalpha(c) || c == '_' || c == '.' || c == '$')
1363 bp = get_name();
1364 else if (c == '\'' || c == '"')
1365 bp = get_literal();
1366 else
1368 syntax_error(lineno, line, cptr);
1369 /*NOTREACHED*/
1372 if (rprec[nrules] != UNDEFINED && bp->prec != rprec[nrules])
1373 prec_redeclared();
1375 rprec[nrules] = bp->prec;
1376 rassoc[nrules] = bp->assoc;
1377 return (0);
1380 static void
1381 read_grammar (void)
1383 register int c;
1385 initialize_grammar();
1386 advance_to_start();
1388 for (;;)
1390 c = nextc();
1391 if (c == EOF) break;
1392 if (isalpha(c) || c == '_' || c == '.' || c == '$' || c == '\'' ||
1393 c == '"')
1394 add_symbol();
1395 else if (c == '{' || c == '=')
1396 copy_action();
1397 else if (c == '|')
1399 end_rule();
1400 start_rule(plhs[nrules-1], 0);
1401 ++cptr;
1403 else if (c == '%')
1405 if (mark_symbol()) break;
1407 else
1408 syntax_error(lineno, line, cptr);
1410 end_rule();
1413 static void
1414 free_tags (void)
1416 register int i;
1418 if (tag_table == 0) return;
1420 for (i = 0; i < ntags; ++i)
1422 assert(tag_table[i]);
1423 FREE(tag_table[i]);
1425 FREE(tag_table);
1428 static void
1429 pack_names (void)
1431 register bucket *bp;
1432 register char *p, *s, *t;
1434 name_pool_size = 13; /* 13 == sizeof("$end") + sizeof("$accept") */
1435 for (bp = first_symbol; bp; bp = bp->next)
1436 name_pool_size += strlen(bp->name) + 1;
1437 name_pool = (char*)MALLOC(name_pool_size);
1438 if (name_pool == 0) no_space();
1440 strcpy(name_pool, "$accept");
1441 strcpy(name_pool+8, "$end");
1442 t = name_pool + 13;
1443 for (bp = first_symbol; bp; bp = bp->next)
1445 p = t;
1446 s = bp->name;
1447 while ((*t++ = *s++)) continue;
1448 FREE(bp->name);
1449 bp->name = p;
1453 static void
1454 check_symbols (void)
1456 register bucket *bp;
1458 if (goal->class == UNKNOWN)
1459 undefined_goal(goal->name);
1461 for (bp = first_symbol; bp; bp = bp->next)
1463 if (bp->class == UNKNOWN)
1465 undefined_symbol_warning(bp->name);
1466 bp->class = TERM;
1471 static void
1472 pack_symbols (void)
1474 register bucket *bp;
1475 register bucket **v;
1476 register int i, j, k, n;
1478 nsyms = 2;
1479 ntokens = 1;
1480 for (bp = first_symbol; bp; bp = bp->next)
1482 ++nsyms;
1483 if (bp->class == TERM) ++ntokens;
1485 start_symbol = ntokens;
1486 nvars = nsyms - ntokens;
1488 symbol_name = (char **) MALLOC(nsyms*sizeof(char *));
1489 if (symbol_name == 0) no_space();
1490 symbol_value = (short *) MALLOC(nsyms*sizeof(short));
1491 if (symbol_value == 0) no_space();
1492 symbol_prec = (short *) MALLOC(nsyms*sizeof(short));
1493 if (symbol_prec == 0) no_space();
1494 symbol_assoc = (char*)MALLOC(nsyms);
1495 if (symbol_assoc == 0) no_space();
1497 v = (bucket **) MALLOC(nsyms*sizeof(bucket *));
1498 if (v == 0) no_space();
1500 v[0] = 0;
1501 v[start_symbol] = 0;
1503 i = 1;
1504 j = start_symbol + 1;
1505 for (bp = first_symbol; bp; bp = bp->next)
1507 if (bp->class == TERM)
1508 v[i++] = bp;
1509 else
1510 v[j++] = bp;
1512 assert(i == ntokens && j == nsyms);
1514 for (i = 1; i < ntokens; ++i)
1515 v[i]->index = i;
1517 goal->index = start_symbol + 1;
1518 k = start_symbol + 2;
1519 while (++i < nsyms)
1520 if (v[i] != goal)
1522 v[i]->index = k;
1523 ++k;
1526 goal->value = 0;
1527 k = 1;
1528 for (i = start_symbol + 1; i < nsyms; ++i)
1530 if (v[i] != goal)
1532 v[i]->value = k;
1533 ++k;
1537 k = 0;
1538 for (i = 1; i < ntokens; ++i)
1540 n = v[i]->value;
1541 if (n > 256)
1543 for (j = k++; j > 0 && symbol_value[j-1] > n; --j)
1544 symbol_value[j] = symbol_value[j-1];
1545 symbol_value[j] = n;
1549 if (v[1]->value == UNDEFINED)
1550 v[1]->value = 256;
1552 j = 0;
1553 n = 257;
1554 for (i = 2; i < ntokens; ++i)
1556 if (v[i]->value == UNDEFINED)
1558 while (j < k && n == symbol_value[j])
1560 while (++j < k && n == symbol_value[j]) continue;
1561 ++n;
1563 v[i]->value = n;
1564 ++n;
1568 symbol_name[0] = name_pool + 8;
1569 symbol_value[0] = 0;
1570 symbol_prec[0] = 0;
1571 symbol_assoc[0] = TOKEN;
1572 for (i = 1; i < ntokens; ++i)
1574 symbol_name[i] = v[i]->name;
1575 symbol_value[i] = v[i]->value;
1576 symbol_prec[i] = v[i]->prec;
1577 symbol_assoc[i] = v[i]->assoc;
1579 symbol_name[start_symbol] = name_pool;
1580 symbol_value[start_symbol] = -1;
1581 symbol_prec[start_symbol] = 0;
1582 symbol_assoc[start_symbol] = TOKEN;
1583 for (++i; i < nsyms; ++i)
1585 k = v[i]->index;
1586 symbol_name[k] = v[i]->name;
1587 symbol_value[k] = v[i]->value;
1588 symbol_prec[k] = v[i]->prec;
1589 symbol_assoc[k] = v[i]->assoc;
1592 FREE(v);
1595 static void
1596 pack_grammar (void)
1598 register int i, j;
1599 int assoc, prec;
1601 ritem = (short *) MALLOC(nitems*sizeof(short));
1602 if (ritem == 0) no_space();
1603 rlhs = (short *) MALLOC(nrules*sizeof(short));
1604 if (rlhs == 0) no_space();
1605 rrhs = (short *) MALLOC((nrules+1)*sizeof(short));
1606 if (rrhs == 0) no_space();
1607 rprec = (short *) REALLOC(rprec, nrules*sizeof(short));
1608 if (rprec == 0) no_space();
1609 rassoc = (char*)REALLOC(rassoc, nrules);
1610 if (rassoc == 0) no_space();
1612 ritem[0] = -1;
1613 ritem[1] = goal->index;
1614 ritem[2] = 0;
1615 ritem[3] = -2;
1616 rlhs[0] = 0;
1617 rlhs[1] = 0;
1618 rlhs[2] = start_symbol;
1619 rrhs[0] = 0;
1620 rrhs[1] = 0;
1621 rrhs[2] = 1;
1623 j = 4;
1624 for (i = 3; i < nrules; ++i)
1626 rlhs[i] = plhs[i]->index;
1627 rrhs[i] = j;
1628 assoc = TOKEN;
1629 prec = 0;
1630 while (pitem[j])
1632 ritem[j] = pitem[j]->index;
1633 if (pitem[j]->class == TERM)
1635 prec = pitem[j]->prec;
1636 assoc = pitem[j]->assoc;
1638 ++j;
1640 ritem[j] = -i;
1641 ++j;
1642 if (rprec[i] == UNDEFINED)
1644 rprec[i] = prec;
1645 rassoc[i] = assoc;
1648 rrhs[i] = j;
1650 FREE(plhs);
1651 FREE(pitem);
1654 static void
1655 print_grammar (void)
1657 register int i, j, k;
1658 int spacing;
1659 register FILE *f = verbose_file;
1661 if (!vflag) return;
1663 k = 1;
1664 for (i = 2; i < nrules; ++i)
1666 if (rlhs[i] != rlhs[i-1])
1668 if (i != 2) fprintf(f, "\n");
1669 fprintf(f, "%4d %s :", i - 2, symbol_name[rlhs[i]]);
1670 spacing = strlen(symbol_name[rlhs[i]]) + 1;
1672 else
1674 fprintf(f, "%4d ", i - 2);
1675 j = spacing;
1676 while (--j >= 0) putc(' ', f);
1677 putc('|', f);
1680 while (ritem[k] >= 0)
1682 fprintf(f, " %s", symbol_name[ritem[k]]);
1683 ++k;
1685 ++k;
1686 putc('\n', f);
1690 void
1691 reader (void)
1693 create_symbol_table();
1694 read_declarations();
1695 read_grammar();
1696 free_symbol_table();
1697 free_tags();
1698 pack_names();
1699 check_symbols();
1700 pack_symbols();
1701 pack_grammar();
1702 free_symbols();
1703 print_grammar();