1 /* $OpenBSD: output.c,v 1.26 2016/09/21 16:26:30 otto Exp $ */
2 /* $NetBSD: output.c,v 1.4 1996/03/19 03:21:41 jtc Exp $ */
5 * Copyright (c) 1989 The Regents of the University of California.
8 * This code is derived from software contributed to Berkeley by
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44 static short *state_count
;
54 void output_prefix(void);
55 void output_rule_data(void);
56 void output_yydefred(void);
57 void output_actions(void);
58 void token_actions(void);
59 void goto_actions(void);
60 int default_goto(int);
61 void save_column(int, int);
62 void sort_actions(void);
63 void pack_table(void);
64 int matching_vector(int);
66 void output_base(void);
67 void output_table(void);
68 void output_check(void);
69 int is_C_identifier(char *);
70 void output_defines(void);
71 void output_stored_text(void);
72 void output_debug(void);
73 void output_stype(void);
74 void output_trailing_text(void);
75 void output_semantic_actions(void);
76 void free_itemsets(void);
77 void free_shifts(void);
78 void free_reductions(void);
96 write_section(tables
);
97 write_section(header
);
98 output_trailing_text();
100 output_semantic_actions();
101 write_section(trailer
);
108 if (symbol_prefix
== NULL
)
109 symbol_prefix
= "yy";
112 fprintf(code_file
, "#define yyparse %sparse\n", symbol_prefix
);
114 fprintf(code_file
, "#define yylex %slex\n", symbol_prefix
);
116 fprintf(code_file
, "#define yyerror %serror\n", symbol_prefix
);
118 fprintf(code_file
, "#define yychar %schar\n", symbol_prefix
);
120 fprintf(code_file
, "#define yyval %sval\n", symbol_prefix
);
122 fprintf(code_file
, "#define yylval %slval\n", symbol_prefix
);
124 fprintf(code_file
, "#define yydebug %sdebug\n", symbol_prefix
);
126 fprintf(code_file
, "#define yynerrs %snerrs\n", symbol_prefix
);
128 fprintf(code_file
, "#define yyerrflag %serrflag\n", symbol_prefix
);
130 fprintf(code_file
, "#define yyss %sss\n", symbol_prefix
);
132 fprintf(code_file
, "#define yysslim %ssslim\n", symbol_prefix
);
134 fprintf(code_file
, "#define yyssp %sssp\n", symbol_prefix
);
136 fprintf(code_file
, "#define yyvs %svs\n", symbol_prefix
);
138 fprintf(code_file
, "#define yyvsp %svsp\n", symbol_prefix
);
140 fprintf(code_file
, "#define yystacksize %sstacksize\n", symbol_prefix
);
142 fprintf(code_file
, "#define yylhs %slhs\n", symbol_prefix
);
144 fprintf(code_file
, "#define yylen %slen\n", symbol_prefix
);
146 fprintf(code_file
, "#define yydefred %sdefred\n", symbol_prefix
);
148 fprintf(code_file
, "#define yydgoto %sdgoto\n", symbol_prefix
);
150 fprintf(code_file
, "#define yysindex %ssindex\n", symbol_prefix
);
152 fprintf(code_file
, "#define yyrindex %srindex\n", symbol_prefix
);
154 fprintf(code_file
, "#define yygindex %sgindex\n", symbol_prefix
);
156 fprintf(code_file
, "#define yytable %stable\n", symbol_prefix
);
158 fprintf(code_file
, "#define yycheck %scheck\n", symbol_prefix
);
160 fprintf(code_file
, "#define yyname %sname\n", symbol_prefix
);
162 fprintf(code_file
, "#define yyrule %srule\n", symbol_prefix
);
165 fprintf(code_file
, "#define YYPREFIX \"%s\"\n", symbol_prefix
);
170 output_rule_data(void)
176 "const short %slhs[] =\n"
177 "\t{%42d,", symbol_prefix
, symbol_value
[start_symbol
]);
180 for (i
= 3; i
< nrules
; i
++) {
184 putc('\n', output_file
);
188 fprintf(output_file
, "%5d,", symbol_value
[rlhs
[i
]]);
192 fprintf(output_file
, "\n};\n");
195 "const short %slen[] =\n"
196 "\t{%42d,", symbol_prefix
, 2);
199 for (i
= 3; i
< nrules
; i
++) {
203 putc('\n', output_file
);
207 fprintf(output_file
, "%5d,", rrhs
[i
+ 1] - rrhs
[i
] - 1);
211 fprintf(output_file
, "\n};\n");
216 output_yydefred(void)
221 "const short %sdefred[] =\n"
223 symbol_prefix
, (defred
[0] ? defred
[0] - 2 : 0));
226 for (i
= 1; i
< nstates
; i
++) {
232 putc('\n', output_file
);
235 fprintf(output_file
, "%5d,", (defred
[i
] ? defred
[i
] - 2 : 0));
240 fprintf(output_file
, "\n};\n");
247 nvectors
= 2 * nstates
+ nvars
;
249 froms
= NEW2(nvectors
, short *);
250 tos
= NEW2(nvectors
, short *);
251 tally
= NEW2(nvectors
, short);
252 width
= NEW2(nvectors
, short);
258 free(accessing_symbol
);
261 free(goto_map
+ ntokens
);
277 int shiftcount
, reducecount
;
279 short *actionrow
, *r
, *s
;
282 actionrow
= NEW2(2*ntokens
, short);
283 for (i
= 0; i
< nstates
; ++i
) {
285 for (j
= 0; j
< 2 * ntokens
; ++j
)
289 for (p
= parser
[i
]; p
; p
= p
->next
) {
290 if (p
->suppressed
== 0) {
291 if (p
->action_code
== SHIFT
) {
293 actionrow
[p
->symbol
] = p
->number
;
294 } else if (p
->action_code
== REDUCE
&&
295 p
->number
!= defred
[i
]) {
297 actionrow
[p
->symbol
+ ntokens
] = p
->number
;
302 tally
[i
] = shiftcount
;
303 tally
[nstates
+i
] = reducecount
;
305 width
[nstates
+i
] = 0;
306 if (shiftcount
> 0) {
307 froms
[i
] = r
= NEW2(shiftcount
, short);
308 tos
[i
] = s
= NEW2(shiftcount
, short);
311 for (j
= 0; j
< ntokens
; ++j
) {
313 if (min
> symbol_value
[j
])
314 min
= symbol_value
[j
];
315 if (max
< symbol_value
[j
])
316 max
= symbol_value
[j
];
317 *r
++ = symbol_value
[j
];
321 width
[i
] = max
- min
+ 1;
323 if (reducecount
> 0) {
324 froms
[nstates
+i
] = r
= NEW2(reducecount
, short);
325 tos
[nstates
+i
] = s
= NEW2(reducecount
, short);
328 for (j
= 0; j
< ntokens
; ++j
) {
329 if (actionrow
[ntokens
+j
]) {
330 if (min
> symbol_value
[j
])
331 min
= symbol_value
[j
];
332 if (max
< symbol_value
[j
])
333 max
= symbol_value
[j
];
334 *r
++ = symbol_value
[j
];
335 *s
++ = actionrow
[ntokens
+j
] - 2;
338 width
[nstates
+i
] = max
- min
+ 1;
350 state_count
= NEW2(nstates
, short);
352 k
= default_goto(start_symbol
+ 1);
353 fprintf(output_file
, "const short %sdgoto[] =\n"
354 "\t{%40d,", symbol_prefix
, k
);
355 save_column(start_symbol
+ 1, k
);
358 for (i
= start_symbol
+ 2; i
< nsyms
; i
++) {
362 putc('\n', output_file
);
368 fprintf(output_file
, "%5d,", k
);
374 fprintf(output_file
, "\n};\n");
379 default_goto(int symbol
)
387 m
= goto_map
[symbol
];
388 n
= goto_map
[symbol
+ 1];
393 memset(state_count
, 0, nstates
* sizeof(short));
395 for (i
= m
; i
< n
; i
++)
396 state_count
[to_state
[i
]]++;
400 for (i
= 0; i
< nstates
; i
++) {
401 if (state_count
[i
] > max
) {
402 max
= state_count
[i
];
407 return (default_state
);
413 save_column(int symbol
, int default_state
)
424 m
= goto_map
[symbol
];
425 n
= goto_map
[symbol
+ 1];
428 for (i
= m
; i
< n
; i
++) {
429 if (to_state
[i
] != default_state
)
435 symno
= symbol_value
[symbol
] + 2*nstates
;
437 froms
[symno
] = sp1
= sp
= NEW2(count
, short);
438 tos
[symno
] = sp2
= NEW2(count
, short);
440 for (i
= m
; i
< n
; i
++) {
441 if (to_state
[i
] != default_state
) {
442 *sp1
++ = from_state
[i
];
443 *sp2
++ = to_state
[i
];
447 tally
[symno
] = count
;
448 width
[symno
] = sp1
[-1] - sp
[0] + 1;
460 order
= NEW2(nvectors
, short);
463 for (i
= 0; i
< nvectors
; i
++) {
469 while (j
>= 0 && (width
[order
[j
]] < w
))
472 while (j
>= 0 && (width
[order
[j
]] == w
) &&
473 (tally
[order
[j
]] < t
))
476 for (k
= nentries
- 1; k
> j
; k
--)
477 order
[k
+ 1] = order
[k
];
493 base
= NEW2(nvectors
, short);
494 pos
= NEW2(nentries
, short);
497 table
= NEW2(maxtable
, short);
498 check
= NEW2(maxtable
, short);
503 for (i
= 0; i
< maxtable
; i
++)
506 for (i
= 0; i
< nentries
; i
++) {
507 state
= matching_vector(i
);
510 place
= pack_vector(i
);
515 base
[order
[i
]] = place
;
518 for (i
= 0; i
< nvectors
; i
++) {
529 /* The function matching_vector determines if the vector specified by */
530 /* the input parameter matches a previously considered vector. The */
531 /* test at the start of the function checks if the vector represents */
532 /* a row of shifts over terminal symbols or a row of reductions, or a */
533 /* column of shifts over a nonterminal symbol. Berkeley Yacc does not */
534 /* check if a column of shifts over a nonterminal symbols matches a */
535 /* previously considered vector. Because of the nature of LR parsing */
536 /* tables, no two columns can match. Therefore, the only possible */
537 /* match would be between a row and a column. Such matches are */
538 /* unlikely. Therefore, to save time, no attempt is made to see if a */
539 /* column matches a previously considered vector. */
541 /* Matching_vector is poorly designed. The test could easily be made */
542 /* faster. Also, it depends on the vectors being in a specific */
546 matching_vector(int vector
)
548 int i
, j
, k
, t
, w
, match
, prev
;
557 for (prev
= vector
- 1; prev
>= 0; prev
--) {
559 if (width
[j
] != w
|| tally
[j
] != t
)
563 for (k
= 0; match
&& k
< t
; k
++) {
564 if (tos
[j
][k
] != tos
[i
][k
] ||
565 froms
[j
][k
] != froms
[i
][k
])
579 pack_vector(int vector
)
593 j
= lowzero
- from
[0];
594 for (k
= 1; k
< t
; ++k
)
595 if (lowzero
- from
[k
] > j
)
596 j
= lowzero
- from
[k
];
601 for (k
= 0; ok
&& k
< t
; k
++) {
603 if (loc
>= maxtable
) {
605 fatal("maximum table size exceeded");
610 } while (newmax
<= loc
);
611 table
= realloc(table
, newmax
* sizeof(short));
614 check
= realloc(check
, newmax
* sizeof(short));
617 for (l
= maxtable
; l
< newmax
; ++l
) {
624 if (check
[loc
] != -1)
627 for (k
= 0; ok
&& k
< vector
; k
++) {
632 for (k
= 0; k
< t
; k
++) {
635 check
[loc
] = from
[k
];
640 while (lowzero
< maxtable
&& check
[lowzero
] != -1)
655 fprintf(output_file
, "const short %ssindex[] =\n"
656 "\t{%39d,", symbol_prefix
, base
[0]);
659 for (i
= 1; i
< nstates
; i
++) {
663 putc('\n', output_file
);
667 fprintf(output_file
, "%5d,", base
[i
]);
672 fprintf(output_file
, "};\n"
673 "const short %srindex[] =\n"
674 "\t{%39d,", symbol_prefix
, base
[nstates
]);
677 for (i
= nstates
+ 1; i
< 2*nstates
; i
++) {
681 putc('\n', output_file
);
685 fprintf(output_file
, "%5d,", base
[i
]);
690 fprintf(output_file
, "};\n"
691 "const short %sgindex[] =\n"
692 "\t{%39d,", symbol_prefix
, base
[2*nstates
]);
695 for (i
= 2*nstates
+ 1; i
< nvectors
- 1; i
++) {
699 putc('\n', output_file
);
703 fprintf(output_file
, "%5d,", base
[i
]);
708 fprintf(output_file
, "\n};\n");
719 fprintf(code_file
, "#define YYTABLESIZE %d\n", high
);
720 fprintf(output_file
, "const short %stable[] =\n"
721 "\t{%40d,", symbol_prefix
, table
[0]);
724 for (i
= 1; i
<= high
; i
++) {
728 putc('\n', output_file
);
732 fprintf(output_file
, "%5d,", table
[i
]);
737 fprintf(output_file
, "\n};\n");
747 fprintf(output_file
, "const short %scheck[] =\n"
748 "\t{%40d,", symbol_prefix
, check
[0]);
751 for (i
= 1; i
<= high
; i
++) {
755 putc('\n', output_file
);
759 fprintf(output_file
, "%5d,", check
[i
]);
764 fprintf(output_file
, "\n};\n");
770 is_C_identifier(char *name
)
776 c
= (unsigned char)*s
;
778 c
= (unsigned char)*++s
;
779 if (!isalpha(c
) && c
!= '_' && c
!= '$')
781 while ((c
= (unsigned char)*++s
) != '"') {
782 if (!isalnum(c
) && c
!= '_' && c
!= '$')
788 if (!isalpha(c
) && c
!= '_' && c
!= '$')
790 while ((c
= (unsigned char)*++s
)) {
791 if (!isalnum(c
) && c
!= '_' && c
!= '$')
804 for (i
= 2; i
< ntokens
; ++i
) {
806 if (is_C_identifier(s
)) {
807 fprintf(code_file
, "#define ");
809 fprintf(defines_file
, "#define ");
810 c
= (unsigned char)*s
;
812 while ((c
= (unsigned char)*++s
) != '"') {
815 putc(c
, defines_file
);
821 putc(c
, defines_file
);
822 } while ((c
= (unsigned char)*++s
));
825 fprintf(code_file
, " %d\n", symbol_value
[i
]);
827 fprintf(defines_file
, " %d\n", symbol_value
[i
]);
832 fprintf(code_file
, "#define YYERRCODE %d\n", symbol_value
[1]);
834 if (dflag
&& unionized
) {
836 union_file
= fopen(union_file_name
, "r");
837 if (union_file
== NULL
)
838 open_error(union_file_name
);
839 while ((c
= getc(union_file
)) != EOF
)
840 putc(c
, defines_file
);
841 fprintf(defines_file
, " YYSTYPE;\n");
842 fprintf(defines_file
, "#endif /* YYSTYPE_DEFINED */\n");
843 fprintf(defines_file
, "extern YYSTYPE %slval;\n",
850 output_stored_text(void)
856 text_file
= fopen(text_file_name
, "r");
857 if (text_file
== NULL
)
858 open_error(text_file_name
);
860 if ((c
= getc(in
)) == EOF
)
866 while ((c
= getc(in
)) != EOF
) {
872 fprintf(out
, line_format
, ++outline
+ 1, code_file_name
);
883 fprintf(code_file
, "#define YYFINAL %d\n", final_state
);
885 fprintf(code_file
, "#ifndef YYDEBUG\n#define YYDEBUG %d\n#endif\n",
888 fprintf(output_file
, "#ifndef YYDEBUG\n#define YYDEBUG %d\n#endif\n",
892 for (i
= 2; i
< ntokens
; ++i
)
893 if (symbol_value
[i
] > max
)
894 max
= symbol_value
[i
];
896 fprintf(code_file
, "#define YYMAXTOKEN %d\n", max
);
898 symnam
= calloc(max
+1, sizeof(char *));
902 for (i
= ntokens
- 1; i
>= 2; --i
)
903 symnam
[symbol_value
[i
]] = symbol_name
[i
];
904 symnam
[0] = "end-of-file";
910 "const char * const %sname[] =\n"
911 "\t{", symbol_prefix
);
913 for (i
= 0; i
<= max
; ++i
) {
914 if ((s
= symnam
[i
]) != '\0') {
917 while (*++s
!= '"') {
929 putc('\n', output_file
);
932 fprintf(output_file
, "\"\\\"");
934 while (*++s
!= '"') {
936 fprintf(output_file
, "\\\\");
938 fprintf(output_file
, "\\\\");
940 putc(*s
, output_file
);
942 putc(*s
, output_file
);
944 fprintf(output_file
, "\\\"\",");
945 } else if (s
[0] == '\'') {
951 putc('\n', output_file
);
954 fprintf(output_file
, "\"'\\\"'\",");
957 while (*++s
!= '\'') {
969 putc('\n', output_file
);
972 fprintf(output_file
, "\"'");
974 while (*++s
!= '\'') {
976 fprintf(output_file
, "\\\\");
978 fprintf(output_file
, "\\\\");
980 putc(*s
, output_file
);
982 putc(*s
, output_file
);
984 fprintf(output_file
, "'\",");
992 putc('\n', output_file
);
995 putc('"', output_file
);
997 putc(*s
, output_file
);
999 fprintf(output_file
, "\",");
1006 putc('\n', output_file
);
1009 fprintf(output_file
, "0,");
1014 fprintf(output_file
, "\n};\n");
1019 fprintf(output_file
,
1020 "const char * const %srule[] =\n"
1021 "\t{", symbol_prefix
);
1022 for (i
= 2; i
< nrules
; ++i
) {
1023 fprintf(output_file
, "\"%s :", symbol_name
[rlhs
[i
]]);
1024 for (j
= rrhs
[i
]; ritem
[j
] > 0; ++j
) {
1025 s
= symbol_name
[ritem
[j
]];
1027 fprintf(output_file
, " \\\"");
1028 while (*++s
!= '"') {
1031 fprintf(output_file
, "\\\\\\\\");
1033 fprintf(output_file
, "\\\\%c", s
[1]);
1036 putc(*s
, output_file
);
1038 fprintf(output_file
, "\\\"");
1039 } else if (s
[0] == '\'') {
1041 fprintf(output_file
, " '\\\"'");
1042 else if (s
[1] == '\\') {
1044 fprintf(output_file
, " '\\\\\\\\");
1046 fprintf(output_file
, " '\\\\%c", s
[2]);
1048 while (*++s
!= '\'')
1049 putc(*s
, output_file
);
1050 putc('\'', output_file
);
1052 fprintf(output_file
, " '%c'", s
[1]);
1054 fprintf(output_file
, " %s", s
);
1058 fprintf(output_file
, "\",\n");
1063 fprintf(output_file
, "};\n#endif\n");
1070 if (!unionized
&& ntags
== 0) {
1072 fprintf(code_file
, "#ifndef YYSTYPE\ntypedef int YYSTYPE;\n#endif\n");
1078 output_trailing_text(void)
1088 c
= (unsigned char)*cptr
;
1091 if ((c
= getc(in
)) == EOF
)
1095 fprintf(out
, line_format
, lineno
, input_file_name
);
1104 fprintf(out
, line_format
, lineno
, input_file_name
);
1108 } while ((c
= (unsigned char)*++cptr
) != '\n');
1114 while ((c
= getc(in
)) != EOF
) {
1126 fprintf(out
, line_format
, ++outline
+ 1, code_file_name
);
1131 output_semantic_actions(void)
1136 fclose(action_file
);
1137 action_file
= fopen(action_file_name
, "r");
1138 if (action_file
== NULL
)
1139 open_error(action_file_name
);
1141 if ((c
= getc(action_file
)) == EOF
)
1149 while ((c
= getc(action_file
)) != EOF
) {
1162 fprintf(out
, line_format
, ++outline
+ 1, code_file_name
);
1172 for (cp
= first_state
; cp
; cp
= next
) {
1185 for (sp
= first_shift
; sp
; sp
= next
) {
1194 free_reductions(void)
1196 reductions
*rp
, *next
;
1198 free(reduction_table
);
1199 for (rp
= first_reduction
; rp
; rp
= next
) {