/* $Id: output.c,v 1.74 2014/10/05 23:21:09 tom Exp $ */ #include "defs.h" #define StaticOrR (rflag ? "" : "static ") #define CountLine(fp) (!rflag || ((fp) == code_file)) #if defined(YYBTYACC) #define PER_STATE 3 #else #define PER_STATE 2 #endif static int nvectors; static int nentries; static Value_t **froms; static Value_t **tos; #if defined(YYBTYACC) static Value_t *conflicts = NULL; static Value_t nconflicts = 0; #endif static Value_t *tally; static Value_t *width; static Value_t *state_count; static Value_t *order; static Value_t *base; static Value_t *pos; static int maxtable; static Value_t *table; static Value_t *check; static int lowzero; static long high; static void putc_code(FILE * fp, int c) { if ((c == '\n') && (fp == code_file)) ++outline; putc(c, fp); } static void putl_code(FILE * fp, const char *s) { if (fp == code_file) ++outline; fputs(s, fp); } static void puts_code(FILE * fp, const char *s) { fputs(s, fp); } static void puts_param_types(FILE * fp, param * list, int more) { param *p; if (list != 0) { for (p = list; p; p = p->next) { size_t len_type = strlen(p->type); fprintf(fp, "%s%s%s%s%s", p->type, (((len_type != 0) && (p->type[len_type - 1] == '*')) ? "" : " "), p->name, p->type2, ((more || p->next) ? ", " : "")); } } else { if (!more) fprintf(fp, "void"); } } static void puts_param_names(FILE * fp, param * list, int more) { param *p; for (p = list; p; p = p->next) { fprintf(fp, "%s%s", p->name, ((more || p->next) ? ", " : "")); } } static void write_code_lineno(FILE * fp) { if (!lflag && (fp == code_file)) { ++outline; fprintf(fp, line_format, outline + 1, code_file_name); } } static void write_input_lineno(void) { if (!lflag) { ++outline; fprintf(code_file, line_format, lineno, input_file_name); } } static void define_prefixed(FILE * fp, const char *name) { int bump_line = CountLine(fp); if (bump_line) ++outline; fprintf(fp, "\n"); if (bump_line) ++outline; fprintf(fp, "#ifndef %s\n", name); if (bump_line) ++outline; fprintf(fp, "#define %-10s %s%s\n", name, symbol_prefix, name + 2); if (bump_line) ++outline; fprintf(fp, "#endif /* %s */\n", name); } static void output_prefix(FILE * fp) { if (symbol_prefix == NULL) { symbol_prefix = "yy"; } else { define_prefixed(fp, "yyparse"); define_prefixed(fp, "yylex"); define_prefixed(fp, "yyerror"); define_prefixed(fp, "yychar"); define_prefixed(fp, "yyval"); define_prefixed(fp, "yylval"); define_prefixed(fp, "yydebug"); define_prefixed(fp, "yynerrs"); define_prefixed(fp, "yyerrflag"); define_prefixed(fp, "yylhs"); define_prefixed(fp, "yylen"); define_prefixed(fp, "yydefred"); #if defined(YYBTYACC) define_prefixed(fp, "yystos"); #endif define_prefixed(fp, "yydgoto"); define_prefixed(fp, "yysindex"); define_prefixed(fp, "yyrindex"); define_prefixed(fp, "yygindex"); define_prefixed(fp, "yytable"); define_prefixed(fp, "yycheck"); define_prefixed(fp, "yyname"); define_prefixed(fp, "yyrule"); #if defined(YYBTYACC) if (locations) { define_prefixed(fp, "yyloc"); define_prefixed(fp, "yylloc"); } putc_code(fp, '\n'); putl_code(fp, "#if YYBTYACC\n"); define_prefixed(fp, "yycindex"); define_prefixed(fp, "yyctable"); putc_code(fp, '\n'); putl_code(fp, "#endif /* YYBTYACC */\n"); putc_code(fp, '\n'); #endif } if (CountLine(fp)) ++outline; fprintf(fp, "#define YYPREFIX \"%s\"\n", symbol_prefix); } static void output_newline(void) { if (!rflag) ++outline; putc('\n', output_file); } static void output_line(const char *value) { fputs(value, output_file); output_newline(); } static void output_int(int value) { fprintf(output_file, "%5d,", value); } static void start_int_table(const char *name, int value) { int need = 34 - (int)(strlen(symbol_prefix) + strlen(name)); if (need < 6) need = 6; fprintf(output_file, "%sconst YYINT %s%s[] = {%*d,", StaticOrR, symbol_prefix, name, need, value); } static void start_str_table(const char *name) { fprintf(output_file, "%sconst char *const %s%s[] = {", StaticOrR, symbol_prefix, name); output_newline(); } static void end_table(void) { output_newline(); output_line("};"); } static void output_YYINT_typedef(FILE * fp) { /* generate the type used to index the various parser tables */ if (CountLine(fp)) ++outline; fprintf(fp, "typedef %s YYINT;\n", CONCAT1("", YYINT)); } static void output_rule_data(void) { int i; int j; output_YYINT_typedef(output_file); start_int_table("lhs", symbol_value[start_symbol]); j = 10; for (i = 3; i < nrules; i++) { if (j >= 10) { output_newline(); j = 1; } else ++j; output_int(symbol_value[rlhs[i]]); } end_table(); start_int_table("len", 2); j = 10; for (i = 3; i < nrules; i++) { if (j >= 10) { output_newline(); j = 1; } else j++; output_int(rrhs[i + 1] - rrhs[i] - 1); } end_table(); } static void output_yydefred(void) { int i, j; start_int_table("defred", (defred[0] ? defred[0] - 2 : 0)); j = 10; for (i = 1; i < nstates; i++) { if (j < 10) ++j; else { output_newline(); j = 1; } output_int((defred[i] ? defred[i] - 2 : 0)); } end_table(); } #if defined(YYBTYACC) static void output_accessing_symbols(void) { int i, j; int *translate; if (nstates != 0) { translate = TMALLOC(int, nstates); NO_SPACE(translate); for (i = 0; i < nstates; ++i) { int gsymb = accessing_symbol[i]; translate[i] = symbol_pval[gsymb]; } /* yystos[] may be unused, depending on compile-time defines */ start_int_table("stos", translate[0]); j = 10; for (i = 1; i < nstates; ++i) { if (j < 10) ++j; else { output_newline(); j = 1; } output_int(translate[i]); } end_table(); FREE(translate); } } static Value_t find_conflict_base(int cbase) { int i, j; for (i = 0; i < cbase; i++) { for (j = 0; j + cbase < nconflicts; j++) { if (conflicts[i + j] != conflicts[cbase + j]) break; } if (j + cbase >= nconflicts) break; } return (Value_t) i; } #endif static void token_actions(void) { int i, j; Value_t shiftcount, reducecount; #if defined(YYBTYACC) Value_t conflictcount = 0; Value_t csym = -1; Value_t cbase = 0; #endif int max, min; Value_t *actionrow, *r, *s; action *p; actionrow = NEW2(PER_STATE * ntokens, Value_t); for (i = 0; i < nstates; ++i) { if (parser[i]) { for (j = 0; j < PER_STATE * ntokens; ++j) actionrow[j] = 0; shiftcount = 0; reducecount = 0; #if defined(YYBTYACC) if (backtrack) { conflictcount = 0; csym = -1; cbase = nconflicts; } #endif for (p = parser[i]; p; p = p->next) { #if defined(YYBTYACC) if (backtrack) { if (csym != -1 && csym != p->symbol) { conflictcount++; conflicts[nconflicts++] = -1; j = find_conflict_base(cbase); actionrow[csym + 2 * ntokens] = (Value_t) (j + 1); if (j == cbase) { cbase = nconflicts; } else { if (conflicts[cbase] == -1) cbase++; nconflicts = cbase; } csym = -1; } } #endif if (p->suppressed == 0) { if (p->action_code == SHIFT) { ++shiftcount; actionrow[p->symbol] = p->number; } else if (p->action_code == REDUCE && p->number != defred[i]) { ++reducecount; actionrow[p->symbol + ntokens] = p->number; } } #if defined(YYBTYACC) else if (backtrack && p->suppressed == 1) { csym = p->symbol; if (p->action_code == SHIFT) { conflicts[nconflicts++] = p->number; } else if (p->action_code == REDUCE && p->number != defred[i]) { if (cbase == nconflicts) { if (cbase) cbase--; else conflicts[nconflicts++] = -1; } conflicts[nconflicts++] = (Value_t) (p->number - 2); } } #endif } #if defined(YYBTYACC) if (backtrack && csym != -1) { conflictcount++; conflicts[nconflicts++] = -1; j = find_conflict_base(cbase); actionrow[csym + 2 * ntokens] = (Value_t) (j + 1); if (j == cbase) { cbase = nconflicts; } else { if (conflicts[cbase] == -1) cbase++; nconflicts = cbase; } } #endif tally[i] = shiftcount; tally[nstates + i] = reducecount; #if defined(YYBTYACC) if (backtrack) tally[2 * nstates + i] = conflictcount; #endif width[i] = 0; width[nstates + i] = 0; #if defined(YYBTYACC) if (backtrack) width[2 * nstates + i] = 0; #endif if (shiftcount > 0) { froms[i] = r = NEW2(shiftcount, Value_t); tos[i] = s = NEW2(shiftcount, Value_t); min = MAXYYINT; max = 0; for (j = 0; j < ntokens; ++j) { if (actionrow[j]) { if (min > symbol_value[j]) min = symbol_value[j]; if (max < symbol_value[j]) max = symbol_value[j]; *r++ = symbol_value[j]; *s++ = actionrow[j]; } } width[i] = (Value_t) (max - min + 1); } if (reducecount > 0) { froms[nstates + i] = r = NEW2(reducecount, Value_t); tos[nstates + i] = s = NEW2(reducecount, Value_t); min = MAXYYINT; max = 0; for (j = 0; j < ntokens; ++j) { if (actionrow[ntokens + j]) { if (min > symbol_value[j]) min = symbol_value[j]; if (max < symbol_value[j]) max = symbol_value[j]; *r++ = symbol_value[j]; *s++ = (Value_t) (actionrow[ntokens + j] - 2); } } width[nstates + i] = (Value_t) (max - min + 1); } #if defined(YYBTYACC) if (backtrack && conflictcount > 0) { froms[2 * nstates + i] = r = NEW2(conflictcount, Value_t); tos[2 * nstates + i] = s = NEW2(conflictcount, Value_t); min = MAXYYINT; max = 0; for (j = 0; j < ntokens; ++j) { if (actionrow[2 * ntokens + j]) { if (min > symbol_value[j]) min = symbol_value[j]; if (max < symbol_value[j]) max = symbol_value[j]; *r++ = symbol_value[j]; *s++ = (Value_t) (actionrow[2 * ntokens + j] - 1); } } width[2 * nstates + i] = (Value_t) (max - min + 1); } #endif } } FREE(actionrow); } static int default_goto(int symbol) { int i; int m; int n; int default_state; int max; m = goto_map[symbol]; n = goto_map[symbol + 1]; if (m == n) return (0); for (i = 0; i < nstates; i++) state_count[i] = 0; for (i = m; i < n; i++) state_count[to_state[i]]++; max = 0; default_state = 0; for (i = 0; i < nstates; i++) { if (state_count[i] > max) { max = state_count[i]; default_state = i; } } return (default_state); } static void save_column(int symbol, int default_state) { int i; int m; int n; Value_t *sp; Value_t *sp1; Value_t *sp2; Value_t count; int symno; m = goto_map[symbol]; n = goto_map[symbol + 1]; count = 0; for (i = m; i < n; i++) { if (to_state[i] != default_state) ++count; } if (count == 0) return; symno = symbol_value[symbol] + PER_STATE * nstates; froms[symno] = sp1 = sp = NEW2(count, Value_t); tos[symno] = sp2 = NEW2(count, Value_t); for (i = m; i < n; i++) { if (to_state[i] != default_state) { *sp1++ = from_state[i]; *sp2++ = to_state[i]; } } tally[symno] = count; width[symno] = (Value_t) (sp1[-1] - sp[0] + 1); } static void goto_actions(void) { int i, j, k; state_count = NEW2(nstates, Value_t); k = default_goto(start_symbol + 1); start_int_table("dgoto", k); save_column(start_symbol + 1, k); j = 10; for (i = start_symbol + 2; i < nsyms; i++) { if (j >= 10) { output_newline(); j = 1; } else ++j; k = default_goto(i); output_int(k); save_column(i, k); } end_table(); FREE(state_count); } static void sort_actions(void) { Value_t i; int j; int k; int t; int w; order = NEW2(nvectors, Value_t); nentries = 0; for (i = 0; i < nvectors; i++) { if (tally[i] > 0) { t = tally[i]; w = width[i]; j = nentries - 1; while (j >= 0 && (width[order[j]] < w)) j--; while (j >= 0 && (width[order[j]] == w) && (tally[order[j]] < t)) j--; for (k = nentries - 1; k > j; k--) order[k + 1] = order[k]; order[j + 1] = i; nentries++; } } } /* The function matching_vector determines if the vector specified by */ /* the input parameter matches a previously considered vector. The */ /* test at the start of the function checks if the vector represents */ /* a row of shifts over terminal symbols or a row of reductions, or a */ /* column of shifts over a nonterminal symbol. Berkeley Yacc does not */ /* check if a column of shifts over a nonterminal symbols matches a */ /* previously considered vector. Because of the nature of LR parsing */ /* tables, no two columns can match. Therefore, the only possible */ /* match would be between a row and a column. Such matches are */ /* unlikely. Therefore, to save time, no attempt is made to see if a */ /* column matches a previously considered vector. */ /* */ /* Matching_vector is poorly designed. The test could easily be made */ /* faster. Also, it depends on the vectors being in a specific */ /* order. */ #if defined(YYBTYACC) /* */ /* Not really any point in checking for matching conflicts -- it is */ /* extremely unlikely to occur, and conflicts are (hopefully) rare. */ #endif static int matching_vector(int vector) { int i; int j; int k; int t; int w; int match; int prev; i = order[vector]; if (i >= 2 * nstates) return (-1); t = tally[i]; w = width[i]; for (prev = vector - 1; prev >= 0; prev--) { j = order[prev]; if (width[j] != w || tally[j] != t) return (-1); match = 1; for (k = 0; match && k < t; k++) { if (tos[j][k] != tos[i][k] || froms[j][k] != froms[i][k]) match = 0; } if (match) return (j); } return (-1); } static int pack_vector(int vector) { int i, j, k, l; int t; int loc; int ok; Value_t *from; Value_t *to; int newmax; i = order[vector]; t = tally[i]; assert(t); from = froms[i]; to = tos[i]; j = lowzero - from[0]; for (k = 1; k < t; ++k) if (lowzero - from[k] > j) j = lowzero - from[k]; for (;; ++j) { if (j == 0) continue; ok = 1; for (k = 0; ok && k < t; k++) { loc = j + from[k]; if (loc >= maxtable - 1) { if (loc >= MAXTABLE - 1) fatal("maximum table size exceeded"); newmax = maxtable; do { newmax += 200; } while (newmax <= loc); table = TREALLOC(Value_t, table, newmax); NO_SPACE(table); check = TREALLOC(Value_t, check, newmax); NO_SPACE(check); for (l = maxtable; l < newmax; ++l) { table[l] = 0; check[l] = -1; } maxtable = newmax; } if (check[loc] != -1) ok = 0; } for (k = 0; ok && k < vector; k++) { if (pos[k] == j) ok = 0; } if (ok) { for (k = 0; k < t; k++) { loc = j + from[k]; table[loc] = to[k]; check[loc] = from[k]; if (loc > high) high = loc; } while (check[lowzero] != -1) ++lowzero; return (j); } } } static void pack_table(void) { int i; Value_t place; int state; base = NEW2(nvectors, Value_t); pos = NEW2(nentries, Value_t); maxtable = 1000; table = NEW2(maxtable, Value_t); check = NEW2(maxtable, Value_t); lowzero = 0; high = 0; for (i = 0; i < maxtable; i++) check[i] = -1; for (i = 0; i < nentries; i++) { state = matching_vector(i); if (state < 0) place = (Value_t) pack_vector(i); else place = base[state]; pos[i] = place; base[order[i]] = place; } for (i = 0; i < nvectors; i++) { if (froms[i]) FREE(froms[i]); if (tos[i]) FREE(tos[i]); } DO_FREE(froms); DO_FREE(tos); DO_FREE(tally); DO_FREE(width); DO_FREE(pos); } static void output_base(void) { int i, j; start_int_table("sindex", base[0]); j = 10; for (i = 1; i < nstates; i++) { if (j >= 10) { output_newline(); j = 1; } else ++j; output_int(base[i]); } end_table(); start_int_table("rindex", base[nstates]); j = 10; for (i = nstates + 1; i < 2 * nstates; i++) { if (j >= 10) { output_newline(); j = 1; } else ++j; output_int(base[i]); } end_table(); #if defined(YYBTYACC) output_line("#if YYBTYACC"); start_int_table("cindex", base[2 * nstates]); j = 10; for (i = 2 * nstates + 1; i < 3 * nstates; i++) { if (j >= 10) { output_newline(); j = 1; } else ++j; output_int(base[i]); } end_table(); output_line("#endif"); #endif start_int_table("gindex", base[PER_STATE * nstates]); j = 10; for (i = PER_STATE * nstates + 1; i < nvectors - 1; i++) { if (j >= 10) { output_newline(); j = 1; } else ++j; output_int(base[i]); } end_table(); FREE(base); } static void output_table(void) { int i; int j; if (high >= MAXYYINT) { fprintf(stderr, "YYTABLESIZE: %ld\n", high); fprintf(stderr, "Table is longer than %d elements.\n", MAXYYINT); done(1); } ++outline; fprintf(code_file, "#define YYTABLESIZE %ld\n", high); start_int_table("table", table[0]); j = 10; for (i = 1; i <= high; i++) { if (j >= 10) { output_newline(); j = 1; } else ++j; output_int(table[i]); } end_table(); FREE(table); } static void output_check(void) { int i; int j; start_int_table("check", check[0]); j = 10; for (i = 1; i <= high; i++) { if (j >= 10) { output_newline(); j = 1; } else ++j; output_int(check[i]); } end_table(); FREE(check); } #if defined(YYBTYACC) static void output_ctable(void) { int i; int j; int limit = (conflicts != 0) ? nconflicts : 0; if (limit < high) limit = (int)high; output_line("#if YYBTYACC"); start_int_table("ctable", conflicts ? conflicts[0] : -1); j = 10; for (i = 1; i < limit; i++) { if (j >= 10) { output_newline(); j = 1; } else ++j; output_int((conflicts != 0 && i < nconflicts) ? conflicts[i] : -1); } if (conflicts) FREE(conflicts); end_table(); output_line("#endif"); } #endif static void output_actions(void) { nvectors = PER_STATE * nstates + nvars; froms = NEW2(nvectors, Value_t *); tos = NEW2(nvectors, Value_t *); tally = NEW2(nvectors, Value_t); width = NEW2(nvectors, Value_t); #if defined(YYBTYACC) if (backtrack && (SRtotal + RRtotal) != 0) conflicts = NEW2(4 * (SRtotal + RRtotal), Value_t); #endif token_actions(); FREE(lookaheads); FREE(LA); FREE(LAruleno); FREE(accessing_symbol); goto_actions(); FREE(goto_base); FREE(from_state); FREE(to_state); sort_actions(); pack_table(); output_base(); output_table(); output_check(); #if defined(YYBTYACC) output_ctable(); #endif } static int is_C_identifier(char *name) { char *s; int c; s = name; c = *s; if (c == '"') { c = *++s; if (!isalpha(c) && c != '_' && c != '$') return (0); while ((c = *++s) != '"') { if (!isalnum(c) && c != '_' && c != '$') return (0); } return (1); } if (!isalpha(c) && c != '_' && c != '$') return (0); while ((c = *++s) != 0) { if (!isalnum(c) && c != '_' && c != '$') return (0); } return (1); } #if USE_HEADER_GUARDS static void start_defines_file(void) { fprintf(defines_file, "#ifndef _%s_defines_h_\n", symbol_prefix); fprintf(defines_file, "#define _%s_defines_h_\n\n", symbol_prefix); } static void end_defines_file(void) { fprintf(defines_file, "\n#endif /* _%s_defines_h_ */\n", symbol_prefix); } #else #define start_defines_file() /* nothing */ #define end_defines_file() /* nothing */ #endif static void output_defines(FILE * fp) { int c, i; char *s; for (i = 2; i < ntokens; ++i) { s = symbol_name[i]; if (is_C_identifier(s) && (!sflag || *s != '"')) { fprintf(fp, "#define "); c = *s; if (c == '"') { while ((c = *++s) != '"') { putc(c, fp); } } else { do { putc(c, fp); } while ((c = *++s) != 0); } if (fp == code_file) ++outline; fprintf(fp, " %d\n", symbol_value[i]); } } if (fp == code_file) ++outline; if (fp != defines_file || iflag) fprintf(fp, "#define YYERRCODE %d\n", symbol_value[1]); if (fp == defines_file || (iflag && !dflag)) { if (unionized) { if (union_file != 0) { rewind(union_file); while ((c = getc(union_file)) != EOF) putc_code(fp, c); } fprintf(fp, "extern YYSTYPE %slval;\n", symbol_prefix); } } } static void output_stored_text(FILE * fp) { int c; FILE *in; rewind(text_file); if (text_file == NULL) open_error("text_file"); in = text_file; if ((c = getc(in)) == EOF) return; putc_code(fp, c); while ((c = getc(in)) != EOF) { putc_code(fp, c); } write_code_lineno(fp); } static void output_debug(void) { int i, j, k, max, maxtok; const char **symnam; const char *s; ++outline; fprintf(code_file, "#define YYFINAL %d\n", final_state); putl_code(code_file, "#ifndef YYDEBUG\n"); ++outline; fprintf(code_file, "#define YYDEBUG %d\n", tflag); putl_code(code_file, "#endif\n"); if (rflag) { fprintf(output_file, "#ifndef YYDEBUG\n"); fprintf(output_file, "#define YYDEBUG %d\n", tflag); fprintf(output_file, "#endif\n"); } maxtok = 0; for (i = 0; i < ntokens; ++i) if (symbol_value[i] > maxtok) maxtok = symbol_value[i]; /* symbol_value[$accept] = -1 */ /* symbol_value[] = 0 */ /* remaining non-terminals start at 1 */ max = maxtok; for (i = ntokens; i < nsyms; ++i) if (((maxtok + 1) + (symbol_value[i] + 1)) > max) max = (maxtok + 1) + (symbol_value[i] + 1); ++outline; fprintf(code_file, "#define YYMAXTOKEN %d\n", maxtok); ++outline; fprintf(code_file, "#define YYUNDFTOKEN %d\n", max + 1); ++outline; fprintf(code_file, "#define YYTRANSLATE(a) ((a) > YYMAXTOKEN ? " "YYUNDFTOKEN : (a))\n"); symnam = TMALLOC(const char *, max + 2); NO_SPACE(symnam); /* Note that it is not necessary to initialize the element */ /* symnam[max]. */ #if defined(YYBTYACC) for (i = 0; i < max; ++i) symnam[i] = 0; for (i = nsyms - 1; i >= 0; --i) symnam[symbol_pval[i]] = symbol_name[i]; symnam[max + 1] = "illegal-symbol"; #else for (i = 0; i <= max; ++i) symnam[i] = 0; for (i = ntokens - 1; i >= 2; --i) symnam[symbol_value[i]] = symbol_name[i]; symnam[0] = "end-of-file"; symnam[max + 1] = "illegal-symbol"; #endif /* * bison's yytname[] array is roughly the same as byacc's yyname[] array. * The difference is that byacc does not predefine "$undefined". * * If the grammar declares "%token-table", define symbol "yytname" so * an application such as ntpd can build. */ if (token_table) { output_line("#undef yytname"); output_line("#define yytname yyname"); } else { output_line("#if YYDEBUG"); } start_str_table("name"); j = 80; for (i = 0; i <= max + 1; ++i) { if ((s = symnam[i]) != 0) { if (s[0] == '"') { k = 7; while (*++s != '"') { ++k; if (*s == '\\') { k += 2; if (*++s == '\\') ++k; } } j += k; if (j > 80) { output_newline(); j = k; } fprintf(output_file, "\"\\\""); s = symnam[i]; while (*++s != '"') { if (*s == '\\') { fprintf(output_file, "\\\\"); if (*++s == '\\') fprintf(output_file, "\\\\"); else putc(*s, output_file); } else putc(*s, output_file); } fprintf(output_file, "\\\"\","); } else if (s[0] == '\'') { if (s[1] == '"') { j += 7; if (j > 80) { output_newline(); j = 7; } fprintf(output_file, "\"'\\\"'\","); } else { k = 5; while (*++s != '\'') { ++k; if (*s == '\\') { k += 2; if (*++s == '\\') ++k; } } j += k; if (j > 80) { output_newline(); j = k; } fprintf(output_file, "\"'"); s = symnam[i]; while (*++s != '\'') { if (*s == '\\') { fprintf(output_file, "\\\\"); if (*++s == '\\') fprintf(output_file, "\\\\"); else putc(*s, output_file); } else putc(*s, output_file); } fprintf(output_file, "'\","); } } else { k = (int)strlen(s) + 3; j += k; if (j > 80) { output_newline(); j = k; } putc('"', output_file); do { putc(*s, output_file); } while (*++s); fprintf(output_file, "\","); } } else { j += 2; if (j > 80) { output_newline(); j = 2; } fprintf(output_file, "0,"); } } end_table(); FREE(symnam); if (token_table) output_line("#if YYDEBUG"); start_str_table("rule"); for (i = 2; i < nrules; ++i) { fprintf(output_file, "\"%s :", symbol_name[rlhs[i]]); for (j = rrhs[i]; ritem[j] > 0; ++j) { s = symbol_name[ritem[j]]; if (s[0] == '"') { fprintf(output_file, " \\\""); while (*++s != '"') { if (*s == '\\') { if (s[1] == '\\') fprintf(output_file, "\\\\\\\\"); else fprintf(output_file, "\\\\%c", s[1]); ++s; } else putc(*s, output_file); } fprintf(output_file, "\\\""); } else if (s[0] == '\'') { if (s[1] == '"') fprintf(output_file, " '\\\"'"); else if (s[1] == '\\') { if (s[2] == '\\') fprintf(output_file, " '\\\\\\\\"); else fprintf(output_file, " '\\\\%c", s[2]); s += 2; while (*++s != '\'') putc(*s, output_file); putc('\'', output_file); } else fprintf(output_file, " '%c'", s[1]); } else fprintf(output_file, " %s", s); } fprintf(output_file, "\","); output_newline(); } end_table(); output_line("#endif"); } #if defined(YYBTYACC) static void output_backtracking_parser(FILE * fp) { putl_code(fp, "#undef YYBTYACC\n"); #if defined(YYBTYACC) if (backtrack) { putl_code(fp, "#define YYBTYACC 1\n"); putl_code(fp, "#define YYDEBUGSTR (yytrial ? YYPREFIX \"debug(trial)\" : YYPREFIX \"debug\")\n"); } else #endif { putl_code(fp, "#define YYBTYACC 0\n"); putl_code(fp, "#define YYDEBUGSTR YYPREFIX \"debug\"\n"); } } #endif static void output_pure_parser(FILE * fp) { putc_code(fp, '\n'); if (fp == code_file) ++outline; fprintf(fp, "#define YYPURE %d\n", pure_parser); putc_code(fp, '\n'); } static void output_stype(FILE * fp) { if (!unionized && ntags == 0) { putc_code(fp, '\n'); putl_code(fp, "#if " "! defined(YYSTYPE) && " "! defined(YYSTYPE_IS_DECLARED)\n"); putl_code(fp, "/* Default: YYSTYPE is the semantic value type. */\n"); putl_code(fp, "typedef int YYSTYPE;\n"); putl_code(fp, "# define YYSTYPE_IS_DECLARED 1\n"); putl_code(fp, "#endif\n"); } } #if defined(YYBTYACC) static void output_ltype(FILE * fp) { putc_code(fp, '\n'); putl_code(fp, "#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED\n"); putl_code(fp, "/* Default: YYLTYPE is the text position type. */\n"); putl_code(fp, "typedef struct YYLTYPE\n"); putl_code(fp, "{\n"); putl_code(fp, " int first_line;\n"); putl_code(fp, " int first_column;\n"); putl_code(fp, " int last_line;\n"); putl_code(fp, " int last_column;\n"); putl_code(fp, "} YYLTYPE;\n"); putl_code(fp, "#define YYLTYPE_IS_DECLARED 1\n"); putl_code(fp, "#endif\n"); } #endif static void output_trailing_text(void) { int c, last; FILE *in; if (line == 0) return; in = input_file; c = *cptr; if (c == '\n') { ++lineno; if ((c = getc(in)) == EOF) return; write_input_lineno(); putc_code(code_file, c); last = c; } else { write_input_lineno(); do { putc_code(code_file, c); } while ((c = *++cptr) != '\n'); putc_code(code_file, c); last = '\n'; } while ((c = getc(in)) != EOF) { putc_code(code_file, c); last = c; } if (last != '\n') { putc_code(code_file, '\n'); } write_code_lineno(code_file); } static void output_semantic_actions(void) { int c, last; rewind(action_file); if ((c = getc(action_file)) == EOF) return; last = c; putc_code(code_file, c); while ((c = getc(action_file)) != EOF) { putc_code(code_file, c); last = c; } if (last != '\n') { putc_code(code_file, '\n'); } write_code_lineno(code_file); } static void output_parse_decl(FILE * fp) { putc_code(fp, '\n'); putl_code(fp, "/* compatibility with bison */\n"); putl_code(fp, "#ifdef YYPARSE_PARAM\n"); putl_code(fp, "/* compatibility with FreeBSD */\n"); putl_code(fp, "# ifdef YYPARSE_PARAM_TYPE\n"); putl_code(fp, "# define YYPARSE_DECL() yyparse(YYPARSE_PARAM_TYPE YYPARSE_PARAM)\n"); putl_code(fp, "# else\n"); putl_code(fp, "# define YYPARSE_DECL() yyparse(void *YYPARSE_PARAM)\n"); putl_code(fp, "# endif\n"); putl_code(fp, "#else\n"); puts_code(fp, "# define YYPARSE_DECL() yyparse("); puts_param_types(fp, parse_param, 0); putl_code(fp, ")\n"); putl_code(fp, "#endif\n"); } static void output_lex_decl(FILE * fp) { putc_code(fp, '\n'); putl_code(fp, "/* Parameters sent to lex. */\n"); putl_code(fp, "#ifdef YYLEX_PARAM\n"); if (pure_parser) { putl_code(fp, "# ifdef YYLEX_PARAM_TYPE\n"); #if defined(YYBTYACC) if (locations) { putl_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval," " YYLTYPE *yylloc," " YYLEX_PARAM_TYPE YYLEX_PARAM)\n"); } else #endif { putl_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval," " YYLEX_PARAM_TYPE YYLEX_PARAM)\n"); } putl_code(fp, "# else\n"); #if defined(YYBTYACC) if (locations) { putl_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval," " YYLTYPE *yylloc," " void * YYLEX_PARAM)\n"); } else #endif { putl_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval," " void * YYLEX_PARAM)\n"); } putl_code(fp, "# endif\n"); #if defined(YYBTYACC) if (locations) putl_code(fp, "# define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM)\n"); else #endif putl_code(fp, "# define YYLEX yylex(&yylval, YYLEX_PARAM)\n"); } else { putl_code(fp, "# define YYLEX_DECL() yylex(void *YYLEX_PARAM)\n"); putl_code(fp, "# define YYLEX yylex(YYLEX_PARAM)\n"); } putl_code(fp, "#else\n"); if (pure_parser && lex_param) { #if defined(YYBTYACC) if (locations) puts_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval, YYLTYPE *yylloc, "); else #endif puts_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval, "); puts_param_types(fp, lex_param, 0); putl_code(fp, ")\n"); #if defined(YYBTYACC) if (locations) puts_code(fp, "# define YYLEX yylex(&yylval, &yylloc, "); else #endif puts_code(fp, "# define YYLEX yylex(&yylval, "); puts_param_names(fp, lex_param, 0); putl_code(fp, ")\n"); } else if (pure_parser) { #if defined(YYBTYACC) if (locations) { putl_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval, YYLTYPE *yylloc)\n"); putl_code(fp, "# define YYLEX yylex(&yylval, &yylloc)\n"); } else #endif { putl_code(fp, "# define YYLEX_DECL() yylex(YYSTYPE *yylval)\n"); putl_code(fp, "# define YYLEX yylex(&yylval)\n"); } } else if (lex_param) { puts_code(fp, "# define YYLEX_DECL() yylex("); puts_param_types(fp, lex_param, 0); putl_code(fp, ")\n"); puts_code(fp, "# define YYLEX yylex("); puts_param_names(fp, lex_param, 0); putl_code(fp, ")\n"); } else { putl_code(fp, "# define YYLEX_DECL() yylex(void)\n"); putl_code(fp, "# define YYLEX yylex()\n"); } putl_code(fp, "#endif\n"); } static void output_error_decl(FILE * fp) { putc_code(fp, '\n'); putl_code(fp, "/* Parameters sent to yyerror. */\n"); putl_code(fp, "#ifndef YYERROR_DECL\n"); puts_code(fp, "#define YYERROR_DECL() yyerror("); #if defined(YYBTYACC) if (locations) puts_code(fp, "YYLTYPE loc, "); #endif puts_param_types(fp, parse_param, 1); putl_code(fp, "const char *s)\n"); putl_code(fp, "#endif\n"); putl_code(fp, "#ifndef YYERROR_CALL\n"); puts_code(fp, "#define YYERROR_CALL(msg) yyerror("); #if defined(YYBTYACC) if (locations) puts_code(fp, "yylloc, "); #endif puts_param_names(fp, parse_param, 1); putl_code(fp, "msg)\n"); putl_code(fp, "#endif\n"); } #if defined(YYBTYACC) static void output_yydestruct_decl(FILE * fp) { putc_code(fp, '\n'); putl_code(fp, "#ifndef YYDESTRUCT_DECL\n"); puts_code(fp, "#define YYDESTRUCT_DECL() " "yydestruct(const char *msg, int psymb, YYSTYPE *val"); #if defined(YYBTYACC) if (locations) puts_code(fp, ", YYLTYPE *loc"); #endif if (parse_param) { puts_code(fp, ", "); puts_param_types(fp, parse_param, 0); } putl_code(fp, ")\n"); putl_code(fp, "#endif\n"); putl_code(fp, "#ifndef YYDESTRUCT_CALL\n"); puts_code(fp, "#define YYDESTRUCT_CALL(msg, psymb, val"); #if defined(YYBTYACC) if (locations) puts_code(fp, ", loc"); #endif puts_code(fp, ") yydestruct(msg, psymb, val"); #if defined(YYBTYACC) if (locations) puts_code(fp, ", loc"); #endif if (parse_param) { puts_code(fp, ", "); puts_param_names(fp, parse_param, 0); } putl_code(fp, ")\n"); putl_code(fp, "#endif\n"); } static void output_yydestruct_impl(void) { int i; char *s, *destructor_code; putc_code(code_file, '\n'); putl_code(code_file, "/* Release memory associated with symbol. */\n"); putl_code(code_file, "#if ! defined YYDESTRUCT_IS_DECLARED\n"); putl_code(code_file, "static void\n"); putl_code(code_file, "YYDESTRUCT_DECL()\n"); putl_code(code_file, "{\n"); putl_code(code_file, " switch (psymb)\n"); putl_code(code_file, " {\n"); for (i = 2; i < nsyms; ++i) { if ((destructor_code = symbol_destructor[i]) != NULL) { ++outline; fprintf(code_file, "\tcase %d:\n", symbol_pval[i]); /* comprehend the number of lines in the destructor code */ for (s = destructor_code; (s = strchr(s, '\n')) != NULL; s++) ++outline; puts_code(code_file, destructor_code); putc_code(code_file, '\n'); putl_code(code_file, "\tbreak;\n"); write_code_lineno(code_file); FREE(destructor_code); } } putl_code(code_file, " }\n"); putl_code(code_file, "}\n"); putl_code(code_file, "#define YYDESTRUCT_IS_DECLARED 1\n"); putl_code(code_file, "#endif\n"); DO_FREE(symbol_destructor); } #endif static void free_itemsets(void) { core *cp, *next; FREE(state_table); for (cp = first_state; cp; cp = next) { next = cp->next; FREE(cp); } } static void free_shifts(void) { shifts *sp, *next; FREE(shift_table); for (sp = first_shift; sp; sp = next) { next = sp->next; FREE(sp); } } static void free_reductions(void) { reductions *rp, *next; FREE(reduction_table); for (rp = first_reduction; rp; rp = next) { next = rp->next; FREE(rp); } } static void output_externs(FILE * fp, const char *const section[]) { int i; const char *s; for (i = 0; (s = section[i]) != 0; ++i) { /* prefix non-blank lines that don't start with C pre-processor directives with 'extern ' */ if (*s && (*s != '#')) fputs("extern\t", fp); if (fp == code_file) ++outline; fprintf(fp, "%s\n", s); } } void output(void) { FILE *fp; free_itemsets(); free_shifts(); free_reductions(); #if defined(YYBTYACC) output_backtracking_parser(output_file); if (rflag) output_backtracking_parser(code_file); #endif if (iflag) { write_code_lineno(code_file); ++outline; fprintf(code_file, "#include \"%s\"\n", externs_file_name); fp = externs_file; } else fp = code_file; output_prefix(fp); output_pure_parser(fp); output_stored_text(fp); output_stype(fp); #if defined(YYBTYACC) if (locations) output_ltype(fp); #endif output_parse_decl(fp); output_lex_decl(fp); output_error_decl(fp); #if defined(YYBTYACC) if (destructor) output_yydestruct_decl(fp); #endif if (iflag || !rflag) { write_section(fp, xdecls); } if (iflag) { output_externs(externs_file, global_vars); if (!pure_parser) output_externs(externs_file, impure_vars); } if (iflag) { if (dflag) { ++outline; fprintf(code_file, "#include \"%s\"\n", defines_file_name); } else output_defines(externs_file); } else { putc_code(code_file, '\n'); output_defines(code_file); } if (dflag) { start_defines_file(); output_defines(defines_file); end_defines_file(); } output_rule_data(); output_yydefred(); #if defined(YYBTYACC) output_accessing_symbols(); #endif output_actions(); free_parser(); output_debug(); if (rflag) { write_section(code_file, xdecls); output_YYINT_typedef(code_file); write_section(code_file, tables); } write_section(code_file, global_vars); if (!pure_parser) { write_section(code_file, impure_vars); } write_section(code_file, hdr_defs); if (!pure_parser) { write_section(code_file, hdr_vars); } output_trailing_text(); #if defined(YYBTYACC) if (destructor) output_yydestruct_impl(); #endif write_section(code_file, body_1); if (pure_parser) { write_section(code_file, body_vars); } write_section(code_file, body_2); output_semantic_actions(); write_section(code_file, trailer); } #ifdef NO_LEAKS void output_leaks(void) { DO_FREE(tally); DO_FREE(width); DO_FREE(order); } #endif