1 /* $NetBSD: output.c,v 1.14 2006/05/24 18:01:43 christos Exp $ */
4 * Copyright (c) 1989 The Regents of the University of California.
7 * This code is derived from software contributed to Berkeley by
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 #include <sys/cdefs.h>
36 #if defined(__RCSID) && !defined(lint)
38 static char sccsid
[] = "@(#)output.c 5.7 (Berkeley) 5/24/93";
40 __RCSID("$NetBSD: output.c,v 1.14 2006/05/24 18:01:43 christos Exp $");
52 static short *state_count
;
62 static void output_prefix(void);
63 static void output_rule_data(void);
64 static void output_yydefred(void);
65 static void output_actions(void);
66 static void token_actions(void);
67 static void goto_actions(void);
68 static int default_goto(int);
69 static void save_column(int, int);
70 static void sort_actions(void);
71 static void pack_table(void);
72 static int matching_vector(int);
73 static int pack_vector(int);
74 static void output_base(void);
75 static void output_table(void);
76 static void output_check(void);
77 static int is_C_identifier(char *);
78 static void output_defines(void);
79 static void output_stored_text(void);
80 static void output_debug(void);
81 static void output_stype(void);
82 static void output_trailing_text(void);
83 static void output_semantic_actions(void);
84 static void free_itemsets(void);
85 static void free_shifts(void);
86 static void free_reductions(void);
88 static const char line_format
[] = "#line %d \"%s\"\n";
105 if (rflag
) write_section(tables
);
106 write_section(header
);
107 output_trailing_text();
109 output_semantic_actions();
110 write_section(trailer
);
116 if (symbol_prefix
== NULL
)
117 symbol_prefix
= "yy";
121 fprintf(code_file
, "#define yyparse %sparse\n", symbol_prefix
);
123 fprintf(code_file
, "#define yylex %slex\n", symbol_prefix
);
125 fprintf(code_file
, "#define yyerror %serror\n", symbol_prefix
);
127 fprintf(code_file
, "#define yychar %schar\n", symbol_prefix
);
129 fprintf(code_file
, "#define yyval %sval\n", symbol_prefix
);
131 fprintf(code_file
, "#define yylval %slval\n", symbol_prefix
);
133 fprintf(code_file
, "#define yydebug %sdebug\n", symbol_prefix
);
135 fprintf(code_file
, "#define yynerrs %snerrs\n", symbol_prefix
);
137 fprintf(code_file
, "#define yyerrflag %serrflag\n", symbol_prefix
);
139 fprintf(code_file
, "#define yyss %sss\n", symbol_prefix
);
141 fprintf(code_file
, "#define yysslim %ssslim\n", symbol_prefix
);
143 fprintf(code_file
, "#define yyssp %sssp\n", symbol_prefix
);
145 fprintf(code_file
, "#define yyvs %svs\n", symbol_prefix
);
147 fprintf(code_file
, "#define yyvsp %svsp\n", symbol_prefix
);
149 fprintf(code_file
, "#define yystacksize %sstacksize\n", symbol_prefix
);
151 fprintf(code_file
, "#define yylhs %slhs\n", symbol_prefix
);
153 fprintf(code_file
, "#define yylen %slen\n", symbol_prefix
);
155 fprintf(code_file
, "#define yydefred %sdefred\n", symbol_prefix
);
157 fprintf(code_file
, "#define yydgoto %sdgoto\n", symbol_prefix
);
159 fprintf(code_file
, "#define yysindex %ssindex\n", symbol_prefix
);
161 fprintf(code_file
, "#define yyrindex %srindex\n", symbol_prefix
);
163 fprintf(code_file
, "#define yygindex %sgindex\n", symbol_prefix
);
165 fprintf(code_file
, "#define yytable %stable\n", symbol_prefix
);
167 fprintf(code_file
, "#define yycheck %scheck\n", symbol_prefix
);
169 fprintf(code_file
, "#define yyname %sname\n", symbol_prefix
);
171 fprintf(code_file
, "#define yyrule %srule\n", symbol_prefix
);
174 fprintf(code_file
, "#define YYPREFIX \"%s\"\n", symbol_prefix
);
178 output_rule_data(void)
184 fprintf(output_file
, "const short %slhs[] = {%42d,", symbol_prefix
,
185 symbol_value
[start_symbol
]);
188 for (i
= 3; i
< nrules
; i
++)
192 if (!rflag
) ++outline
;
193 putc('\n', output_file
);
199 fprintf(output_file
, "%5d,", symbol_value
[rlhs
[i
]]);
201 if (!rflag
) outline
+= 2;
202 fprintf(output_file
, "\n};\n");
204 fprintf(output_file
, "const short %slen[] = {%42d,", symbol_prefix
, 2);
207 for (i
= 3; i
< nrules
; i
++)
211 if (!rflag
) ++outline
;
212 putc('\n', output_file
);
218 fprintf(output_file
, "%5d,", rrhs
[i
+ 1] - rrhs
[i
] - 1);
220 if (!rflag
) outline
+= 2;
221 fprintf(output_file
, "\n};\n");
225 output_yydefred(void)
229 fprintf(output_file
, "const short %sdefred[] = {%39d,", symbol_prefix
,
230 (defred
[0] ? defred
[0] - 2 : 0));
233 for (i
= 1; i
< nstates
; i
++)
239 if (!rflag
) ++outline
;
240 putc('\n', output_file
);
244 fprintf(output_file
, "%5d,", (defred
[i
] ? defred
[i
] - 2 : 0));
247 if (!rflag
) outline
+= 2;
248 fprintf(output_file
, "\n};\n");
254 nvectors
= 2*nstates
+ nvars
;
256 froms
= NEW2(nvectors
, short *);
257 tos
= NEW2(nvectors
, short *);
258 tally
= NEW2(nvectors
, short);
259 width
= NEW2(nvectors
, short);
265 FREE(accessing_symbol
);
268 FREE(goto_map
+ ntokens
);
283 int shiftcount
, reducecount
;
285 short *actionrow
, *r
, *s
;
288 actionrow
= NEW2(2*ntokens
, short);
289 for (i
= 0; i
< nstates
; ++i
)
293 for (j
= 0; j
< 2*ntokens
; ++j
)
298 for (p
= parser
[i
]; p
; p
= p
->next
)
300 if (p
->suppressed
== 0)
302 if (p
->action_code
== SHIFT
)
305 actionrow
[p
->symbol
] = p
->number
;
307 else if (p
->action_code
== REDUCE
&& p
->number
!= defred
[i
])
310 actionrow
[p
->symbol
+ ntokens
] = p
->number
;
315 tally
[i
] = shiftcount
;
316 tally
[nstates
+i
] = reducecount
;
318 width
[nstates
+i
] = 0;
321 froms
[i
] = r
= NEW2(shiftcount
, short);
322 tos
[i
] = s
= NEW2(shiftcount
, short);
325 for (j
= 0; j
< ntokens
; ++j
)
329 if (min
> symbol_value
[j
])
330 min
= symbol_value
[j
];
331 if (max
< symbol_value
[j
])
332 max
= symbol_value
[j
];
333 *r
++ = symbol_value
[j
];
337 width
[i
] = max
- min
+ 1;
341 froms
[nstates
+i
] = r
= NEW2(reducecount
, short);
342 tos
[nstates
+i
] = s
= NEW2(reducecount
, short);
345 for (j
= 0; j
< ntokens
; ++j
)
347 if (actionrow
[ntokens
+j
])
349 if (min
> symbol_value
[j
])
350 min
= symbol_value
[j
];
351 if (max
< symbol_value
[j
])
352 max
= symbol_value
[j
];
353 *r
++ = symbol_value
[j
];
354 *s
++ = actionrow
[ntokens
+j
] - 2;
357 width
[nstates
+i
] = max
- min
+ 1;
369 state_count
= NEW2(nstates
, short);
371 k
= default_goto(start_symbol
+ 1);
372 fprintf(output_file
, "const short %sdgoto[] = {%40d,", symbol_prefix
, k
);
373 save_column(start_symbol
+ 1, k
);
376 for (i
= start_symbol
+ 2; i
< nsyms
; i
++)
380 if (!rflag
) ++outline
;
381 putc('\n', output_file
);
388 fprintf(output_file
, "%5d,", k
);
392 if (!rflag
) outline
+= 2;
393 fprintf(output_file
, "\n};\n");
398 default_goto(int symbol
)
406 m
= goto_map
[symbol
];
407 n
= goto_map
[symbol
+ 1];
409 if (m
== n
) return (0);
411 for (i
= 0; i
< nstates
; i
++)
414 for (i
= m
; i
< n
; i
++)
415 state_count
[to_state
[i
]]++;
419 for (i
= 0; i
< nstates
; i
++)
421 if (state_count
[i
] > max
)
423 max
= state_count
[i
];
428 return (default_state
);
433 save_column(int symbol
, int default_state
)
444 m
= goto_map
[symbol
];
445 n
= goto_map
[symbol
+ 1];
448 for (i
= m
; i
< n
; i
++)
450 if (to_state
[i
] != default_state
)
453 if (count
== 0) return;
455 symno
= symbol_value
[symbol
] + 2*nstates
;
457 froms
[symno
] = sp1
= sp
= NEW2(count
, short);
458 tos
[symno
] = sp2
= NEW2(count
, short);
460 for (i
= m
; i
< n
; i
++)
462 if (to_state
[i
] != default_state
)
464 *sp1
++ = from_state
[i
];
465 *sp2
++ = to_state
[i
];
469 tally
[symno
] = count
;
470 width
[symno
] = sp1
[-1] - sp
[0] + 1;
482 order
= NEW2(nvectors
, short);
485 for (i
= 0; i
< nvectors
; i
++)
493 while (j
>= 0 && (width
[order
[j
]] < w
))
496 while (j
>= 0 && (width
[order
[j
]] == w
) && (tally
[order
[j
]] < t
))
499 for (k
= nentries
- 1; k
> j
; k
--)
500 order
[k
+ 1] = order
[k
];
516 base
= NEW2(nvectors
, short);
517 pos
= NEW2(nentries
, short);
520 table
= NEW2(maxtable
, short);
521 check
= NEW2(maxtable
, short);
526 for (i
= 0; i
< maxtable
; i
++)
529 for (i
= 0; i
< nentries
; i
++)
531 state
= matching_vector(i
);
534 place
= pack_vector(i
);
539 base
[order
[i
]] = place
;
542 for (i
= 0; i
< nvectors
; i
++)
556 /* The function matching_vector determines if the vector specified by */
557 /* the input parameter matches a previously considered vector. The */
558 /* test at the start of the function checks if the vector represents */
559 /* a row of shifts over terminal symbols or a row of reductions, or a */
560 /* column of shifts over a nonterminal symbol. Berkeley Yacc does not */
561 /* check if a column of shifts over a nonterminal symbols matches a */
562 /* previously considered vector. Because of the nature of LR parsing */
563 /* tables, no two columns can match. Therefore, the only possible */
564 /* match would be between a row and a column. Such matches are */
565 /* unlikely. Therefore, to save time, no attempt is made to see if a */
566 /* column matches a previously considered vector. */
568 /* Matching_vector is poorly designed. The test could easily be made */
569 /* faster. Also, it depends on the vectors being in a specific */
573 matching_vector(int vector
)
590 for (prev
= vector
- 1; prev
>= 0; prev
--)
593 if (width
[j
] != w
|| tally
[j
] != t
)
597 for (k
= 0; match
&& k
< t
; k
++)
599 if (tos
[j
][k
] != tos
[i
][k
] || froms
[j
][k
] != froms
[i
][k
])
613 pack_vector(int vector
)
630 j
= lowzero
- from
[0];
631 for (k
= 1; k
< t
; ++k
)
632 if (lowzero
- from
[k
] > j
)
633 j
= lowzero
- from
[k
];
639 for (k
= 0; ok
&& k
< t
; k
++)
645 fatal("maximum table size exceeded");
648 do { newmax
+= 200; } while (newmax
<= loc
);
649 table
= (short *) REALLOC(table
, newmax
*sizeof(short));
650 if (table
== 0) no_space();
651 check
= (short *) REALLOC(check
, newmax
*sizeof(short));
652 if (check
== 0) no_space();
653 for (l
= maxtable
; l
< newmax
; ++l
)
661 if (check
[loc
] != -1)
664 for (k
= 0; ok
&& k
< vector
; k
++)
671 for (k
= 0; k
< t
; k
++)
675 check
[loc
] = from
[k
];
676 if (loc
> high
) high
= loc
;
679 while (check
[lowzero
] != -1)
693 fprintf(output_file
, "const short %ssindex[] = {%39d,", symbol_prefix
,
697 for (i
= 1; i
< nstates
; i
++)
701 if (!rflag
) ++outline
;
702 putc('\n', output_file
);
708 fprintf(output_file
, "%5d,", base
[i
]);
711 if (!rflag
) outline
+= 2;
712 fprintf(output_file
, "\n};\nconst short %srindex[] = {%39d,", symbol_prefix
,
716 for (i
= nstates
+ 1; i
< 2*nstates
; i
++)
720 if (!rflag
) ++outline
;
721 putc('\n', output_file
);
727 fprintf(output_file
, "%5d,", base
[i
]);
730 if (!rflag
) outline
+= 2;
731 fprintf(output_file
, "\n};\nconst short %sgindex[] = {%39d,", symbol_prefix
,
735 for (i
= 2*nstates
+ 1; i
< nvectors
- 1; i
++)
739 if (!rflag
) ++outline
;
740 putc('\n', output_file
);
746 fprintf(output_file
, "%5d,", base
[i
]);
749 if (!rflag
) outline
+= 2;
750 fprintf(output_file
, "\n};\n");
762 fprintf(code_file
, "#define YYTABLESIZE %d\n", high
);
763 fprintf(output_file
, "const short %stable[] = {%40d,", symbol_prefix
,
767 for (i
= 1; i
<= high
; i
++)
771 if (!rflag
) ++outline
;
772 putc('\n', output_file
);
778 fprintf(output_file
, "%5d,", table
[i
]);
781 if (!rflag
) outline
+= 2;
782 fprintf(output_file
, "\n};\n");
793 fprintf(output_file
, "const short %scheck[] = {%40d,", symbol_prefix
,
797 for (i
= 1; i
<= high
; i
++)
801 if (!rflag
) ++outline
;
802 putc('\n', output_file
);
808 fprintf(output_file
, "%5d,", check
[i
]);
811 if (!rflag
) outline
+= 2;
812 fprintf(output_file
, "\n};\n");
818 is_C_identifier(char *name
)
828 if (!isalpha(c
) && c
!= '_' && c
!= '$')
830 while ((c
= *++s
) != '"')
832 if (!isalnum(c
) && c
!= '_' && c
!= '$')
838 if (!isalpha(c
) && c
!= '_' && c
!= '$')
840 while ((c
= *++s
) != '\0')
842 if (!isalnum(c
) && c
!= '_' && c
!= '$')
855 for (i
= 2; i
< ntokens
; ++i
)
858 if (is_C_identifier(s
))
860 fprintf(code_file
, "#define ");
861 if (dflag
) fprintf(defines_file
, "#define ");
865 while ((c
= *++s
) != '"')
868 if (dflag
) putc(c
, defines_file
);
876 if (dflag
) putc(c
, defines_file
);
878 while ((c
= *++s
) != '\0');
881 fprintf(code_file
, " %d\n", symbol_value
[i
]);
882 if (dflag
) fprintf(defines_file
, " %d\n", symbol_value
[i
]);
887 fprintf(code_file
, "#define YYERRCODE %d\n", symbol_value
[1]);
889 if (dflag
&& unionized
)
892 union_file
= fopen(union_file_name
, "r");
893 if (union_file
== NULL
) open_error(union_file_name
);
894 while ((c
= getc(union_file
)) != EOF
)
895 putc(c
, defines_file
);
896 fprintf(defines_file
, " YYSTYPE;\nextern YYSTYPE %slval;\n",
903 output_stored_text(void)
909 text_file
= fopen(text_file_name
, "r");
910 if (text_file
== NULL
)
911 open_error(text_file_name
);
913 if ((c
= getc(in
)) == EOF
)
919 while ((c
= getc(in
)) != EOF
)
926 fprintf(out
, line_format
, ++outline
+ 1, code_file_name
);
934 const char **symnam
, *s
;
937 fprintf(code_file
, "#define YYFINAL %d\n", final_state
);
939 fprintf(code_file
, "#ifndef YYDEBUG\n#define YYDEBUG %d\n#endif\n",
942 fprintf(output_file
, "#ifndef YYDEBUG\n#define YYDEBUG %d\n#endif\n",
946 for (i
= 2; i
< ntokens
; ++i
)
947 if (symbol_value
[i
] > max
)
948 max
= symbol_value
[i
];
950 fprintf(code_file
, "#define YYMAXTOKEN %d\n", max
);
952 symnam
= (const char **) MALLOC((max
+1)*sizeof(char *));
953 if (symnam
== 0) no_space();
955 /* Note that it is not necessary to initialize the element */
957 for (i
= 0; i
< max
; ++i
)
959 for (i
= ntokens
- 1; i
>= 2; --i
)
960 symnam
[symbol_value
[i
]] = symbol_name
[i
];
961 symnam
[0] = "end-of-file";
963 if (!rflag
) ++outline
;
964 fprintf(output_file
, "#if YYDEBUG\nconst char * const %sname[] = {",
967 for (i
= 0; i
<= max
; ++i
)
969 if ((s
= symnam
[i
]) != NULL
)
987 if (!rflag
) ++outline
;
988 putc('\n', output_file
);
991 fprintf(output_file
, "\"\\\"");
997 fprintf(output_file
, "\\\\");
999 fprintf(output_file
, "\\\\");
1001 putc(*s
, output_file
);
1004 putc(*s
, output_file
);
1006 fprintf(output_file
, "\\\"\",");
1008 else if (s
[0] == '\'')
1015 if (!rflag
) ++outline
;
1016 putc('\n', output_file
);
1019 fprintf(output_file
, "\"'\\\"'\",");
1024 while (*++s
!= '\'')
1037 if (!rflag
) ++outline
;
1038 putc('\n', output_file
);
1041 fprintf(output_file
, "\"'");
1043 while (*++s
!= '\'')
1047 fprintf(output_file
, "\\\\");
1049 fprintf(output_file
, "\\\\");
1051 putc(*s
, output_file
);
1054 putc(*s
, output_file
);
1056 fprintf(output_file
, "'\",");
1065 if (!rflag
) ++outline
;
1066 putc('\n', output_file
);
1069 putc('"', output_file
);
1070 do { putc(*s
, output_file
); } while (*++s
);
1071 fprintf(output_file
, "\",");
1079 if (!rflag
) ++outline
;
1080 putc('\n', output_file
);
1083 fprintf(output_file
, "0,");
1086 if (!rflag
) outline
+= 2;
1087 fprintf(output_file
, "\n};\n");
1090 if (!rflag
) ++outline
;
1091 fprintf(output_file
, "const char * const %srule[] = {\n", symbol_prefix
);
1092 for (i
= 2; i
< nrules
; ++i
)
1094 fprintf(output_file
, "\"%s :", symbol_name
[rlhs
[i
]]);
1095 for (j
= rrhs
[i
]; ritem
[j
] > 0; ++j
)
1097 s
= symbol_name
[ritem
[j
]];
1100 fprintf(output_file
, " \\\"");
1106 fprintf(output_file
, "\\\\\\\\");
1108 fprintf(output_file
, "\\\\%c", s
[1]);
1112 putc(*s
, output_file
);
1114 fprintf(output_file
, "\\\"");
1116 else if (s
[0] == '\'')
1119 fprintf(output_file
, " '\\\"'");
1120 else if (s
[1] == '\\')
1123 fprintf(output_file
, " '\\\\\\\\");
1125 fprintf(output_file
, " '\\\\%c", s
[2]);
1127 while (*++s
!= '\'')
1128 putc(*s
, output_file
);
1129 putc('\'', output_file
);
1132 fprintf(output_file
, " '%c'", s
[1]);
1135 fprintf(output_file
, " %s", s
);
1137 if (!rflag
) ++outline
;
1138 fprintf(output_file
, "\",\n");
1141 if (!rflag
) outline
+= 2;
1142 fprintf(output_file
, "};\n#endif\n");
1149 if (!unionized
&& ntags
== 0)
1152 fprintf(code_file
, "#ifndef YYSTYPE\ntypedef int YYSTYPE;\n#endif\n");
1158 output_trailing_text(void)
1172 if ((c
= getc(in
)) == EOF
)
1177 fprintf(out
, line_format
, lineno
, input_file_name
);
1189 fprintf(out
, line_format
, lineno
, input_file_name
);
1191 do { putc(c
, out
); } while ((c
= *++cptr
) != '\n');
1197 while ((c
= getc(in
)) != EOF
)
1211 fprintf(out
, line_format
, ++outline
+ 1, code_file_name
);
1216 output_semantic_actions(void)
1221 fclose(action_file
);
1222 action_file
= fopen(action_file_name
, "r");
1223 if (action_file
== NULL
)
1224 open_error(action_file_name
);
1226 if ((c
= getc(action_file
)) == EOF
)
1234 while ((c
= getc(action_file
)) != EOF
)
1249 fprintf(out
, line_format
, ++outline
+ 1, code_file_name
);
1259 for (cp
= first_state
; cp
; cp
= next
)
1273 for (sp
= first_shift
; sp
; sp
= next
)
1282 free_reductions(void)
1284 reductions
*rp
, *next
;
1286 FREE(reduction_table
);
1287 for (rp
= first_reduction
; rp
; rp
= next
)