--- btyacc-3.0.orig/Makefile +++ btyacc-3.0/Makefile @@ -2,15 +2,18 @@ # Makefile for BtYacc. # -VERSION = 3-0 +# Edited for Debian GNU/Linux. +DESTDIR = + +VERSION = 3.0 DEST = . HDRS = defs.h mstring.h -CFLAGS = -g -Wall -Wstrict-prototypes -Wmissing-prototypes +CFLAGS = -g -Wall -O2 -Wstrict-prototypes -Wmissing-prototypes -LDFLAGS = -static +LDFLAGS = #-static LIBS = @@ -51,7 +54,7 @@ index:; ctags -wx $(HDRS) $(SRCS) install: $(PROGRAM) - cp $(PROGRAM).exe /bin + install $(PROGRAM) $(DESTDIR)/usr/bin oldinstall: $(PROGRAM) @echo Installing $(PROGRAM) in $(DEST) @@ -79,11 +82,14 @@ mv btyacc.zip btyacc-$(VERSION).zip skeleton.c: btyaccpa.ske skel2c - awk -f skel2c btyaccpa.ske >skeleton.c + awk -f skel2c btyaccpa.ske > skeleton.c etags TAGS: etags *.c *.h +btyacc.1: btyacc.sgml + docbook-to-man btyacc.sgml > btyacc.1 + ### closure.o: defs.h error.o: defs.h --- btyacc-3.0.orig/btyacc-c.ske +++ btyacc-3.0/btyacc-c.ske @@ -0,0 +1,939 @@ +/* -*- C -*- + + The banner used here should be replaced with an #ident directive if + the target C compiler supports #ident directives. + + If the skeleton is changed, the banner should be changed so that + the altered version can easily be distinguished from the original. */ + +%% banner +/* -*- C -*- + + @(#)btyaccpar, based on byacc 1.8 (Berkeley) + +*/ +#define YYBTYACC 1 + +#include +#include +#include + +typedef int Yshort; + +%% tables + +#ifndef _YACC_EXTERN_ +# define _YACC_EXTERN_ "C" +#endif + +extern _YACC_EXTERN_ Yshort yylhs[]; +extern _YACC_EXTERN_ Yshort yylen[]; + +/* idx: current state; entry: non-zero if to reduce regardless of lookahead*/ +extern _YACC_EXTERN_ Yshort yydefred[]; + +extern _YACC_EXTERN_ Yshort yydgoto[]; + +/* idx: current state; entry: non-zero if shifting|reducing possible + in this state - in that case, yycheck[entry + lookahead] indicates + whether to perform the action for this lookahead. */ +extern _YACC_EXTERN_ Yshort yysindex[]; +extern _YACC_EXTERN_ Yshort yyrindex[]; + +/* yycindex idx: current state; entry: non-zero if shift/reduce + conflicts for this state - in that case, yycheck[entry + lookahead] + indicates whether there's a conflict for this lookahead */ +extern _YACC_EXTERN_ Yshort yycindex[]; +extern _YACC_EXTERN_ Yshort yycheck[]; + +extern _YACC_EXTERN_ Yshort yygindex[]; +extern _YACC_EXTERN_ Yshort yytable[]; +extern _YACC_EXTERN_ Yshort yyctable[]; + +#if YYDEBUG +/* idx: token code; entry: spelling of token */ +extern _YACC_EXTERN_ char *yyname[]; + +extern _YACC_EXTERN_ char *yyrule[]; +#endif + +%% header + +/* YYPOSN is user-defined text position type. */ +#ifndef YYPOSN +# define YYPOSN int +#endif + +#ifdef YYREDUCEPOSNFUNC +# define YYCALLREDUCEPOSN(e) \ + if(reduce_posn) { \ + YYREDUCEPOSNFUNC(yyps->pos, &(yyps->psp)[1-yym], &(yyps->vsp)[1-yym],\ + yym, yyps->psp - yyps->ps, yychar, yyposn, e); \ + reduce_posn = 0; \ + } + +# ifndef YYCALLREDUCEPOSNARG +# define YYCALLREDUCEPOSNARG (yyps->val) +# endif + + +# define YYPOSNARG(n) ((yyps->psp)[1-yym+(n)-1]) +# define YYPOSNOUT (yyps->pos) +#endif + +/* If delete function is not defined by the user, do not delete. */ +#ifndef YYDELETEVAL +# define YYDELETEVAL(v, t) +#endif + +/* If delete function is not defined by the user, do not delete. */ +#ifndef YYDELETEPOSN +# define YYDELETEPOSN(v, t) +#endif + +#define YYEMPTY (-1) +#define yyclearin (yychar=YYEMPTY) + +#define yyerrok (yyps->errflag=0) + +#ifndef YYSTACKGROWTH +# define YYSTACKGROWTH 32 +#endif + +#ifndef YYDEFSTACKSIZE +# define YYDEFSTACKSIZE 12 +#endif + +#ifdef YYDEBUG +int yydebug = 0; +#endif + +int yynerrs; + +/* These value/posn are taken from the lexer */ +YYSTYPE yylval; +YYPOSN yyposn; + +/* These value/posn of the root non-terminal are returned to the caller */ +YYSTYPE yyretlval; +YYPOSN yyretposn; + +#define YYABORT goto yyabort +#define YYACCEPT goto yyaccept +#define YYERROR goto yyerrlab +#define YYVALID do { if (yyps->save) goto yyvalid; } while(0) +#define YYVALID_NESTED do { if (yyps->save && \ + yyps->save->save==0) goto yyvalid; } while(0) + +struct YYParseState_s { + struct YYParseState_s *save; /* Previously saved parser state */ + int state; + int errflag; + Yshort *ssp; /* state stack pointer */ + YYSTYPE *vsp; /* value stack pointer */ + YYPOSN *psp; /* position stack pointer */ + YYSTYPE val; /* value as returned by actions */ + YYPOSN pos; /* position as returned by universal action */ + Yshort *ss; /* state stack base */ + YYSTYPE *vs; /* values stack base */ + YYPOSN *ps; /* position stack base */ + int lexeme; /* index of conflict lexeme in lexical queue */ + unsigned int stacksize; /* current maximum stack size */ + Yshort ctry; /* index in yyctable[] for this conflict */ +}; +typedef struct YYParseState_s YYParseState; + +/* Current parser state */ +static YYParseState *yyps = 0; + +/* yypath!=NULL: do the full parse, starting at *yypath parser state. */ +static YYParseState *yypath = 0; + +/* Base of the lexical value queue */ +static YYSTYPE *yylvals = 0; + +/* Current position at lexical value queue */ +static YYSTYPE *yylvp = 0; + +/* End position of lexical value queue */ +static YYSTYPE *yylve = 0; + +/* The last allocated position at the lexical value queue */ +static YYSTYPE *yylvlim = 0; + +/* Base of the lexical position queue */ +static YYPOSN *yylpsns = 0; + +/* Current position at lexical position queue */ +static YYPOSN *yylpp = 0; + +/* End position of lexical position queue */ +static YYPOSN *yylpe = 0; + +/* The last allocated position at the lexical position queue */ +static YYPOSN *yylplim = 0; + +/* Current position at lexical token queue */ +static Yshort *yylexp = 0; + +static Yshort *yylexemes = 0; + +/* For use in generated program */ +#define yytrial (yyps->save) +#define yyvsp (yyps->vsp) +#define yyval (yyps->val) +#define yydepth (yyps->ssp - yyps->ss) + + +/* Local prototypes. */ +int yyparse(void); + +static int yyLex1(); +static int yyExpand(); +static void yySCopy(YYSTYPE *to, YYSTYPE *from, int size); +static void yyPCopy(YYPOSN *to, YYPOSN *from, int size); +static void yyMoreStack(YYParseState *yyps); +static YYParseState *yyNewState(int size); +static void yyFreeState(YYParseState *p); + + +%% body + + +/* Parser function. Roughly looks like this: + int yyparse() { + yyloop: + if (reduce_possible) goto yyreduce; + read_token; + if (conflict) { + handle_conflict; + goto yyshift; or goto yyreduce; + } + if (shift_possible) { + yyshift: + do_shift; + goto yyloop; + } + if (reduce_possible) goto yyreduce; + + (error handling); + goto yyloop; + + yyreduce: + BIG_CHUNK_OF_RULE_ACTIONS; + goto yyloop; + + (more error handling); + }*/ +int yyparse() { + int yym, yyn, yystate, yychar, yynewerrflag; + YYParseState *yyerrctx = 0; + int reduce_posn; + +# if YYDEBUG + char *yys; + + if ((yys = getenv("YYDEBUG"))) { + yyn = *yys; + if (yyn >= '0' && yyn <= '9') + yydebug = yyn - '0'; + } + if (yydebug) { + fputs("btyacc[,]\n", + stderr); + } +# endif + + yyps = yyNewState(YYDEFSTACKSIZE); + yyps->save = 0; + yynerrs = 0; + yyps->errflag = 0; + yychar = (YYEMPTY); + + yyps->ssp = yyps->ss; + yyps->vsp = yyps->vs; + yyps->psp = yyps->ps; + *(yyps->ssp) = yystate = 0; + + + /* Main parsing loop */ + yyloop: + if ((yyn = yydefred[yystate])) { + goto yyreduce; + } + + /* Read one token */ + if (yychar < 0) { + yychar = yyLex1(); + if (yychar < 0) yychar = 0; +# if YYDEBUG + if (yydebug) { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + fprintf(stderr, "btyacc[%3d,%2d%s]: read token %d (%s)", + yystate, yydepth, (yytrial ? ",trial" : ""), yychar, yys); +# ifdef YYDBPR + fputc('<', stderr); + YYDBPR(yylval); + fputc('>', stderr); +# endif + fputc('\n', stderr); + } +# endif + } + + /* Do we have a conflict? */ + yyn = yycindex[yystate]; + if (yyn != 0 && (yyn += yychar) >= 0 + && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { + int ctry; + + if (yypath) { + YYParseState *save; +# if YYDEBUG + if (yydebug) { + fprintf(stderr, "btyacc[%3d,%2d%s]: CONFLICT: following successful " + "trial parse\n", yystate, yydepth, (yytrial ? ",trial" :"")); + } +# endif + /* Switch to the next conflict context */ + save = yypath; + yypath = save->save; + ctry = save->ctry; + if (save->state != yystate) + goto yyabort; + yyFreeState(save); + + } else { + + /* Unresolved conflict - start/continue trial parse */ + YYParseState *save; +# if YYDEBUG + if (yydebug) { + fprintf(stderr, "btyacc[%3d,%2d%s]: CONFLICT. ", + yystate, yydepth, (yytrial ? ",trial" : "")); + if(yyps->save) + fputs("ALREADY in conflict, continuing trial parse.\n", stderr); + else + fputs("starting trial parse.\n", stderr); + } +# endif + save = yyNewState(yyps->ssp - yyps->ss); + save->save = yyps->save; + save->state = yystate; + save->errflag = yyps->errflag; + save->ssp = save->ss + (yyps->ssp - yyps->ss); + save->vsp = save->vs + (yyps->vsp - yyps->vs); + save->psp = save->ps + (yyps->psp - yyps->ps); + memcpy(save->ss, yyps->ss, (yyps->ssp - yyps->ss + 1)*sizeof(Yshort)); + yySCopy(save->vs, yyps->vs, (yyps->ssp - yyps->ss + 1)); + yyPCopy(save->ps, yyps->ps, (yyps->ssp - yyps->ss + 1)); + ctry = yytable[yyn]; + if (yyctable[ctry] == -1) { +# if YYDEBUG + if (yydebug && yychar >= 0) + fputs("btyacc[trial]: backtracking 1 token\n", stderr); +# endif + ctry++; + } + save->ctry = ctry; + if (yyps->save == 0) { + /* If this is a first conflict in the stack, start saving lexemes */ + if (!yylexemes) { +# ifdef __cplusplus + yylexemes = new Yshort[YYSTACKGROWTH]; + yylvals = new YYSTYPE[YYSTACKGROWTH]; + yylvlim = yylvals + YYSTACKGROWTH; + yylpsns = new YYPOSN[YYSTACKGROWTH]; + yylplim = yylpsns + YYSTACKGROWTH; +# else + yylexemes = (Yshort*)malloc((YYSTACKGROWTH) * sizeof(Yshort)); + yylvals = (YYSTYPE*)malloc((YYSTACKGROWTH) * sizeof(YYSTYPE)); + yylvlim = yylvals + YYSTACKGROWTH; + yylpsns = (YYPOSN*)malloc((YYSTACKGROWTH) * sizeof(YYPOSN)); + yylplim = yylpsns + YYSTACKGROWTH; +# endif + } + if (yylvp == yylve) { + yylvp = yylve = yylvals; + yylpp = yylpe = yylpsns; + yylexp = yylexemes; + if (yychar >= 0) { + *yylve++ = yylval; + *yylpe++ = yyposn; + *yylexp = yychar; + yychar = YYEMPTY; + } + } + } + if (yychar >= 0) { + yylvp--, yylpp--, yylexp--; + yychar = YYEMPTY; + } + save->lexeme = yylvp - yylvals; + yyps->save = save; + } + + if (yytable[yyn] == ctry) { +# if YYDEBUG + if (yydebug) + fprintf(stderr, "btyacc[%3d,%2d%s]: shifting to state %d\n", + yystate, yydepth, (yytrial ? ",trial" : ""), yyctable[ctry]); +# endif + if (yychar < 0) { + yylvp++; yylpp++; yylexp++; + } + yychar = YYEMPTY; + if (yyps->errflag > 0) --yyps->errflag; + yystate = yyctable[ctry]; + goto yyshift; + } else { + yyn = yyctable[ctry]; + goto yyreduce; + } + } /* End of code dealing with conflicts */ + + + /* Is action a shift? */ + yyn = yysindex[yystate]; + if (yyn != 0 && (yyn += yychar) >= 0 + && yyn <= YYTABLESIZE && yycheck[yyn] == yychar) { +# if YYDEBUG + if (yydebug) + fprintf(stderr, "btyacc[%3d,%2d%s]: shifting to state %d\n", + yystate, yydepth, (yytrial ? ",trial" : ""), yytable[yyn]); +# endif + yychar = YYEMPTY; + if (yyps->errflag > 0) --yyps->errflag; + yystate = yytable[yyn]; + + yyshift: + if (yyps->ssp >= yyps->ss + yyps->stacksize - 1) { + yyMoreStack(yyps); + } + *++(yyps->ssp) = yystate; + *++(yyps->vsp) = yylval; + *++(yyps->psp) = yyposn; + goto yyloop; + } + if ((yyn = yyrindex[yystate]) && + (yyn += yychar) >= 0 && + yyn <= YYTABLESIZE && + yycheck[yyn] == yychar) { + yyn = yytable[yyn]; + goto yyreduce; + } + + /* According to the tables, neither shift nor reduce is OK here - error! */ + if (yyps->errflag) goto yyinrecovery; + yynewerrflag = 1; + goto yyerrhandler; +yyerrlab: + yynewerrflag = 0; +yyerrhandler: + while (yyps->save) { + int ctry; + YYParseState *save = yyps->save; +# if YYDEBUG + if (yydebug) + fprintf(stderr, "btyacc[%3d,%2d%s]: ERROR, " + "CONFLICT BACKTRACKING to state %d, %d tokens\n", + yystate, yydepth, (yytrial ? ",trial" : ""), + yyps->save->state, yylvp - yylvals - yyps->save->lexeme); +# endif + /* Memorize most forward-looking error state in case + it's really an error. */ + if(yyerrctx==0 || yyerrctx->lexemessp - yyps->ss); + yyerrctx->save = yyps->save; + yyerrctx->state = yystate; + yyerrctx->errflag = yyps->errflag; + yyerrctx->ssp = yyerrctx->ss + (yyps->ssp - yyps->ss); + yyerrctx->vsp = yyerrctx->vs + (yyps->vsp - yyps->vs); + yyerrctx->psp = yyerrctx->ps + (yyps->psp - yyps->ps); + memcpy (yyerrctx->ss, yyps->ss, + (yyps->ssp - yyps->ss + 1) * sizeof(Yshort)); + yySCopy(yyerrctx->vs, yyps->vs, (yyps->ssp - yyps->ss + 1)); + yyPCopy(yyerrctx->ps, yyps->ps, (yyps->ssp - yyps->ss + 1)); + yyerrctx->lexeme = yylvp - yylvals; + } + yylvp = yylvals + save->lexeme; + yylpp = yylpsns + save->lexeme; + yylexp = yylexemes + save->lexeme; + yychar = YYEMPTY; + yyps->ssp = yyps->ss + (save->ssp - save->ss); + yyps->vsp = yyps->vs + (save->vsp - save->vs); + yyps->psp = yyps->ps + (save->psp - save->ps); + memcpy (yyps->ss, save->ss, (yyps->ssp - yyps->ss + 1) * sizeof(Yshort)); + yySCopy(yyps->vs, save->vs, yyps->vsp - yyps->vs + 1); + yyPCopy(yyps->ps, save->ps, yyps->psp - yyps->ps + 1); + ctry = ++save->ctry; + yystate = save->state; + /* We tried shift, try reduce now */ + if ((yyn = yyctable[ctry]) >= 0) { + goto yyreduce; + } + yyps->save = save->save; + yyFreeState(save); + + /* Nothing left on the stack -- error */ + if (!yyps->save) { +# if YYDEBUG + if (yydebug) { + fputs("btyacc[trial]: trial parse FAILED, entering ERROR mode\n", + stderr); + } +# endif + /* Restore state as it was in the most forward-advanced error */ + yylvp = yylvals + yyerrctx->lexeme; + yylpp = yylpsns + yyerrctx->lexeme; + yylexp = yylexemes + yyerrctx->lexeme; + yychar = yylexp[-1]; + yylval = yylvp[-1]; + yyposn = yylpp[-1]; + yyps->ssp = yyps->ss + (yyerrctx->ssp - yyerrctx->ss); + yyps->vsp = yyps->vs + (yyerrctx->vsp - yyerrctx->vs); + yyps->psp = yyps->ps + (yyerrctx->psp - yyerrctx->ps); + memcpy (yyps->ss, yyerrctx->ss, + (yyps->ssp - yyps->ss + 1) * sizeof(Yshort)); + yySCopy(yyps->vs, yyerrctx->vs, yyps->vsp - yyps->vs + 1); + yyPCopy(yyps->ps, yyerrctx->ps, yyps->psp - yyps->ps + 1); + yystate = yyerrctx->state; + yyFreeState(yyerrctx); + yyerrctx = 0; + } + yynewerrflag = 1; + } + if (yynewerrflag) { +# ifdef YYERROR_DETAILED + yyerror_detailed("parse error", yychar, yylval, yyposn); +# else + yyerror("parse error"); +# endif + } + ++yynerrs; + yyinrecovery: + if (yyps->errflag < 3) { + yyps->errflag = 3; + for (;;) { + if ((yyn = yysindex[*(yyps->ssp)]) + && (yyn += YYERRCODE) >= 0 + && yyn <= YYTABLESIZE + && yycheck[yyn] == YYERRCODE) { +# if YYDEBUG + if (yydebug) + fprintf(stderr, "btyacc[%3d,%2d%s]: ERROR recovery shifts to " + "state %d\n", + *(yyps->ssp), yydepth, (yytrial ? ",trial" : ""), + yytable[yyn]); +# endif + /* Use label yyerrlab, so that compiler does not warn */ + if(yyps->errflag != yyps->errflag) goto yyerrlab; + yystate = yytable[yyn]; + goto yyshift; + } else { +# if YYDEBUG + if (yydebug) + fprintf(stderr, + "btyacc[%3d,%2d%s]: ERROR recovery discards this state\n", + *(yyps->ssp), yydepth, (yytrial ? ",trial" : "")); +# endif + if (yyps->ssp <= yyps->ss) { + goto yyabort; + } + if(!yytrial) { + YYDELETEVAL(yyps->vsp[0],1); + YYDELETEPOSN(yyps->psp[0],1); + } + --(yyps->ssp); + --(yyps->vsp); + --(yyps->psp); + } + } + } else { + if (yychar == 0) goto yyabort; +# if YYDEBUG + if (yydebug) { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + fprintf(stderr, "btyacc[%3d,%2d%s]: ERROR recovery discards token " + "%d (%s)\n", + yystate, yydepth, (yytrial ? ",trial" : ""), yychar, yys); + } +# endif + if(!yytrial) { + YYDELETEVAL(yylval,0); + YYDELETEPOSN(yyposn,0); + } + yychar = (YYEMPTY); + goto yyloop; + } + + /* Reduce the rule */ +yyreduce: + yym = yylen[yyn]; +# if YYDEBUG + if (yydebug) { + fprintf(stderr, "btyacc[%3d,%2d%s]: reducing by rule %d (%s)", + yystate, yydepth, (yytrial ? ",trial" : ""), yyn, yyrule[yyn]); +# ifdef YYDBPR + if (yym) { + int i; + fputc('<', stderr); + for (i=yym; i>0; i--) { + if (i!=yym) printf(", "); + YYDBPR((yyps->vsp)[1-i]); + } + fputc('>', stderr); + } +# endif + fputc('\n', stderr); + } +# endif + if (yyps->ssp + 1 - yym >= yyps->ss + yyps->stacksize) { + yyMoreStack(yyps); + } + +# ifdef _YACC_DEFAULT_ACTION_ + /* "$$ = NULL" default action */ + memset(&yyps->val, 0, sizeof(yyps->val)); +# else + /* RA: bison compatibility: default action is '$$ = $1;' */ + if (yym > 0) yyps->val = (yyps->vsp)[1 - yym]; +# endif + + /* Default reduced position is NULL -- no position at all. No + position will be assigned at trial time and if no position + handling is present */ + memset(&yyps->pos, 0, sizeof(yyps->pos)); + + reduce_posn = 1; + + switch (yyn) { + +%% trailer + + default: + break; + } + +# if YYDEBUG && defined(YYDBPR) + if (yydebug) { + fputs("btyacc[trial]: reduced, result is ", stderr); + YYDBPR(yyps->val); + fputc('\n', stderr); + } +# endif + + /* Perform user-defined position reduction */ +# ifdef YYREDUCEPOSNFUNC + if(!yytrial) { + YYCALLREDUCEPOSN(YYREDUCEPOSNFUNCARG); + } +# endif + + yyps->ssp -= yym; + yystate = *(yyps->ssp); + yyps->vsp -= yym; + yyps->psp -= yym; + + yym = yylhs[yyn]; + if (yystate == 0 && yym == 0) { +# if YYDEBUG + if (yydebug) { + fprintf(stderr, + "btyacc[ 0,%2d%s]: reduced, shifting to final state %d\n", + yydepth, (yytrial ? ",trial" : ""), YYFINAL); + } +# endif + yystate = YYFINAL; + *++(yyps->ssp) = YYFINAL; + *++(yyps->vsp) = yyps->val; + yyretlval = yyps->val; /* return value of root non-terminal to yylval */ + *++(yyps->psp) = yyps->pos; + yyretposn = yyps->pos; /* return value of root position to yyposn */ + if (yychar < 0) { + if ((yychar = yyLex1()) < 0) { + yychar = 0; + } +# if YYDEBUG + if (yydebug) { + yys = 0; + if (yychar <= YYMAXTOKEN) yys = yyname[yychar]; + if (!yys) yys = "illegal-symbol"; + fprintf(stderr, "btyacc[%3d,%2d%s]: read %d (%s)\n", + YYFINAL, yydepth, (yytrial ? ",trial" : ""), yychar, yys); + } +# endif + } + if (yychar == 0) goto yyaccept; + goto yyloop; + } + + if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 && + yyn <= YYTABLESIZE && yycheck[yyn] == yystate) { + yystate = yytable[yyn]; + } else { + yystate = yydgoto[yym]; + } +# if YYDEBUG + if (yydebug) + fprintf(stderr, "btyacc[%3d,%2d%s]: reduced, shifting to state %d\n", + *(yyps->ssp), yydepth, (yytrial ? ",trial" : ""), yystate); +# endif + if (yyps->ssp >= yyps->ss + yyps->stacksize - 1) { + yyMoreStack(yyps); + } + *++(yyps->ssp) = yystate; + *++(yyps->vsp) = yyps->val; + *++(yyps->psp) = yyps->pos; + goto yyloop; + + + /* Reduction declares that this path is valid. + Set yypath and do a full parse */ +yyvalid: + if (yypath) { + goto yyabort; + } + while (yyps->save) { + YYParseState *save = yyps->save; + yyps->save = save->save; + save->save = yypath; + yypath = save; + } +# if YYDEBUG + if (yydebug) + fprintf(stderr, "btyacc[%3d,%2d%s]: CONFLICT trial successful, " + "backtracking to state %d, %d tokens\n", + yystate, yydepth, (yytrial ? ",trial" : ""), + yypath->state, yylvp - yylvals - yypath->lexeme); +# endif + if(yyerrctx) { + yyFreeState(yyerrctx); yyerrctx = 0; + } + yychar = YYEMPTY; + yyps->ssp = yyps->ss + (yypath->ssp - yypath->ss); + yyps->vsp = yyps->vs + (yypath->vsp - yypath->vs); + yyps->psp = yyps->ps + (yypath->psp - yypath->ps); + memcpy (yyps->ss, yypath->ss, (yyps->ssp - yyps->ss + 1) * sizeof(Yshort)); + yySCopy(yyps->vs, yypath->vs, yyps->vsp - yyps->vs + 1); + yyPCopy(yyps->ps, yypath->ps, yyps->psp - yyps->ps + 1); + yylvp = yylvals + yypath->lexeme; + yylpp = yylpsns + yypath->lexeme; + yylexp = yylexemes + yypath->lexeme; + yystate = yypath->state; + goto yyloop; + + +yyabort: + { + YYSTYPE *pv; + YYPOSN *pp; + + if(yyerrctx) { + yyFreeState(yyerrctx); yyerrctx = 0; + } + + for(pv=yyps->vs; pvvsp; pv++) { + YYDELETEVAL(*pv,2); + } + + for(pp=yyps->ps; pppsp; pp++) { + YYDELETEPOSN(*pp,2); + } + + while (yyps) { + YYParseState *save = yyps; + yyps = save->save; + yyFreeState(save); + } + while (yypath) { + YYParseState *save = yypath; + yypath = save->save; + yyFreeState(save); + } + return (1); + } + +yyaccept: + if (yyps->save) goto yyvalid; + if(yyerrctx) { + yyFreeState(yyerrctx); yyerrctx = 0; + } + while (yyps) { + YYParseState *save = yyps; + yyps = save->save; + yyFreeState(save); + } + while (yypath) { + YYParseState *save = yypath; + yypath = save->save; + yyFreeState(save); + } + return (0); +} + + +/* Call yylex() unless the token has already been read. */ +static int yyLex1() { + if(yylvp < yylve) { + /* we're currently re-reading tokens */ + yylval = *yylvp++; + yyposn = *yylpp++; + return *yylexp++; + } else if(yyps->save) { + /* in trial mode; save scanner results for future parse attempts */ + if(yylvp == yylvlim) + yyExpand(); + *yylexp = yylex(); + *yylvp++ = yylval; + yylve++; + *yylpp++ = yyposn; + yylpe++; + return *yylexp++; + } else { /* normal operation, no conflict encountered */ + return yylex(); + } +} + +/* Enlarge lexical value queue */ +static int yyExpand() { + int p = yylvp - yylvals; + int s = yylvlim - yylvals; + s += YYSTACKGROWTH; + { + Yshort *tl = yylexemes; + YYSTYPE *tv = yylvals; + YYPOSN *tp = yylpsns; +# ifdef __cplusplus + yylvals = new YYSTYPE[s]; + yylpsns = new YYPOSN[s]; + yylexemes = new Yshort[s]; + memcpy(yylexemes, tl, (s-YYSTACKGROWTH)*sizeof(Yshort)); + yySCopy(yylvals, tv, s-YYSTACKGROWTH); + yyPCopy(yylpsns, tp, s-YYSTACKGROWTH); + delete[] tl; + delete[] tv; + delete[] tp; +# else + yylvals = (YYSTYPE*)malloc(s * sizeof(YYSTYPE)); + yylpsns = (YYPOSN*)malloc(s * sizeof(YYPOSN)); + yylexemes = (Yshort*)malloc(s * sizeof(Yshort)); + memcpy(yylexemes, tl, (s - YYSTACKGROWTH)*sizeof(Yshort)); + yySCopy(yylvals, tv, s - YYSTACKGROWTH); + yyPCopy(yylpsns, tp, s - YYSTACKGROWTH); + free(tl); + free(tv); + free(tp); +# endif + } + yylvp = yylve = yylvals + p; + yylvlim = yylvals + s; + yylpp = yylpe = yylpsns + p; + yylplim = yylpsns + s; + yylexp = yylexemes + p; + return 0; +} + +static void yySCopy(YYSTYPE *to, YYSTYPE *from, int size) { + int i; + for (i = size-1; i >= 0; i--) { + to[i] = from[i]; + } +} + +static void yyPCopy(YYPOSN *to, YYPOSN *from, int size) { + int i; + for (i = size-1; i >= 0; i--) { + to[i] = from[i]; + } +} + +static void yyMoreStack(YYParseState *yyps) { + int p = yyps->ssp - yyps->ss; + Yshort *tss = yyps->ss; + YYSTYPE *tvs = yyps->vs; + YYPOSN *tps = yyps->ps; + int newSize = yyps->stacksize + YYSTACKGROWTH; + +# ifdef __cplusplus + yyps->ss = new Yshort [newSize]; + yyps->vs = new YYSTYPE[newSize]; + yyps->ps = new YYPOSN [newSize]; + memcpy(yyps->ss, tss, yyps->stacksize * sizeof(Yshort)); + yySCopy(yyps->vs, tvs, yyps->stacksize); + yyPCopy(yyps->ps, tps, yyps->stacksize); + yyps->stacksize += YYSTACKGROWTH; + delete[] tss; + delete[] tvs; + delete[] tps; +# else + yyps->ss = (Yshort*) malloc(newSize * sizeof(Yshort)); + yyps->vs = (YYSTYPE*)malloc(newSize * sizeof(YYSTYPE)); + yyps->ps = (YYPOSN*) malloc(newSize * sizeof(YYPOSN)); + memcpy(yyps->ss, tss, yyps->stacksize * sizeof(Yshort)); + yySCopy(yyps->vs, tvs, yyps->stacksize); + yyPCopy(yyps->ps, tps, yyps->stacksize); + yyps->stacksize += YYSTACKGROWTH; + free(tss); + free(tvs); + free(tps); +# endif + yyps->ssp = yyps->ss + p; + yyps->vsp = yyps->vs + p; + yyps->psp = yyps->ps + p; +# if YYDEBUG + if (yydebug) + fprintf(stderr, "btyacc: stack size increased to %d\n", yyps->stacksize); +# endif +} + + +#ifdef __cplusplus + +static YYParseState *yyNewState(int size) { + YYParseState *p = new YYParseState; + p->stacksize = size+4; + p->ss = new Yshort [size + 4]; + p->vs = new YYSTYPE[size + 4]; + p->ps = new YYPOSN [size + 4]; + memset(&p->vs[0], 0, (size+4)*sizeof(YYSTYPE)); + memset(&p->ps[0], 0, (size+4)*sizeof(YYPOSN)); + return p; +} + +static void yyFreeState(YYParseState *p) { + delete[] p->ss; + delete[] p->vs; + delete[] p->ps; + delete p; +} + +#else /* not __cplusplus */ + +static YYParseState *yyNewState(int size) { + YYParseState *p = (YYParseState*)malloc(sizeof(YYParseState)); + + p->stacksize = size+4; + p->ss = (Yshort*) malloc((size + 4) * sizeof(Yshort)); + p->vs = (YYSTYPE*)malloc((size + 4) * sizeof(YYSTYPE)); + p->ps = (YYPOSN*) malloc((size + 4) * sizeof(YYPOSN)); + memset(&p->vs[0], 0, (size+4)*sizeof(YYSTYPE)); + memset(&p->ps[0], 0, (size+4)*sizeof(YYPOSN)); + return p; +} + +static void yyFreeState(YYParseState *p) { + free(p->ss); + free(p->vs); + free(p->ps); + free(p); +} + +#endif --- btyacc-3.0.orig/btyacc.1 +++ btyacc-3.0/btyacc.1 @@ -0,0 +1,455 @@ +.\" This -*- nroff -*- file has been generated from +.\" DocBook SGML with docbook-to-man on Debian GNU/Linux. +...\" +...\" transcript compatibility for postscript use. +...\" +...\" synopsis: .P! +...\" +.de P! +\\&. +.fl \" force out current output buffer +\\!%PB +\\!/showpage{}def +...\" the following is from Ken Flowers -- it prevents dictionary overflows +\\!/tempdict 200 dict def tempdict begin +.fl \" prolog +.sy cat \\$1\" bring in postscript file +...\" the following line matches the tempdict above +\\!end % tempdict % +\\!PE +\\!. +.sp \\$2u \" move below the image +.. +.de pF +.ie \\*(f1 .ds f1 \\n(.f +.el .ie \\*(f2 .ds f2 \\n(.f +.el .ie \\*(f3 .ds f3 \\n(.f +.el .ie \\*(f4 .ds f4 \\n(.f +.el .tm ? font overflow +.ft \\$1 +.. +.de fP +.ie !\\*(f4 \{\ +. ft \\*(f4 +. ds f4\" +' br \} +.el .ie !\\*(f3 \{\ +. ft \\*(f3 +. ds f3\" +' br \} +.el .ie !\\*(f2 \{\ +. ft \\*(f2 +. ds f2\" +' br \} +.el .ie !\\*(f1 \{\ +. ft \\*(f1 +. ds f1\" +' br \} +.el .tm ? font underflow +.. +.ds f1\" +.ds f2\" +.ds f3\" +.ds f4\" +'\" t +.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n +.TH "btyacc" "1" +.SH "NAME" +btyacc \(em an LALR(1) parser generator +with support for backtracking +.SH "SYNOPSIS" +.PP +\fBbtyacc\fP [-b \fIprefix\fP] [-d] [-D\fINAME\fP \&...] [-E] [-l] [-r] [-S \fIx.ske\fP] [-t] [-v] \fIfilename.y\fP +.SH "Description" +.PP +btyacc is a modified version of byacc (Berkeley YACC), which +in turn is a public domain version of the original AT&T YACC +parser generator. +.PP +btyacc reads the grammar specification in the file +\fIfilename.y\fP and generates an LR(1) +parser for it. The parser consists of a set of LALR(1) parsing +tables and a driver routine written in the C programming +language. btyacc normally writes the parse tables and the driver +routine to the file +\fIprefix\fP\fB.tab.c\fP, +where \fIprefix\fP defaults to `y'. +.PP +For a detailed description of the format of a grammar +specification, and an excellent tutorial on how to use YACC-like +tools, see the info manual for GNU +\fBbison\fP. +btyacc-specific extensions are explained below. +.PP +\fINote:\fP The parser skeleton supplied by +btyacc's upstream author only compiles as C++. Use the skeleton +\fB/usr/doc/btyacc/examples/btyacc-c.ske\fP to +generate a parser that compiles both as C and C++. +(Unfortunately, this alternative skeleton does not currently +check malloc() return values.) +.SH "Options" +.IP "-b \fIprefix\fP" 10 +Change the prefix prepended to the output file names +to the string denoted by \fIprefix\fP. +The default prefix is the character `y'. +.IP "-d" 10 +Create a header file called +\fIprefix\fP\fB.tab.h\fP along with +\fIprefix\fP\fB.tab.c\fP, +containing the symbol definitions and a declaration for +\fBYYSTYPE\fP and +\fByylval\fP. +.IP "-D\fINAME\fP" 10 +Define the btyacc preprocessor variable +\fINAME\fP, for use with +\fB%ifdef \fP\fINAME\fP directives in the grammar file. +.IP "-E" 10 +Print the preprocessed grammar to standard +output. +.IP "-l" 10 +Do not insert \fB#line\fP directives into +the generated parser code. +.IP "-r" 10 +Write the parser code and the associated tables to +different files. Whereas the tables can be found in +\fIprefix\fP\fB.tab.c\fP as before, the code now gets written to +\fIprefix\fP\fB.code.c\fP. + +.IP "-S \fIx.ske\fP" 10 +Select a different parser skeleton. The default +skeleton is hardwired into the program, but a copy can be +found in the file \fBbtyaccpa.ske\fP. + +.IP "-t" 10 +Cause debugging code to be compiled into the generated +parser. +.IP "-v" 10 +Write a human-readable description of the generated +parser to \fBy.output\fP. It includes +parser states, actions for a look-ahead token and +information about any conflicts. +.SH "BTYACC extensions" +.SS "Backtracking support" +.PP +Whenever a btyacc generated parser runs into a +shift-reduce or reduce-reduce error in the parse table, it +remembers the current parse point (stack and input stream +state), and goes into trial parse mode. It then continues +parsing, ignoring most rule actions. If it runs into an error +(either through the parse table or through an action calling +\fBYYERROR\fP), it backtracks to the most recent +conflict point and tries a different alternative. If it finds +a successful path (reaches the end of the input or an action +calls \fBYYVALID\fP), it backtracks to the point +where it first entered trial parse mode, and continues with a +full parse (executing all actions), following the path of the +successful trial. +.PP +Actions in btyacc come in two flavors: +\fB{}\fP actions, which are only executed when +not in trial mode, and \fB[]\fP actions, which +are executed regardless of mode. +.PP +Example: In YACC grammars for C, a +standard hack known as the "lexer feedback hack" is used to +find typedef names. The lexer uses semantic information to +decide if any given identifier is a typedef name or not and +returns a special token. With btyacc, you no longer need to do +this; the lexer should just always return an identifier. The +btyacc grammar then needs a rule of the form: +.PP +\fBtypename: ID [ if (!IsTypeName(LookupId($1))) +YYERROR; ]\fP +.PP +However, note that adding backtracking rules slows down +the parser. In practice, you should try to restrict the number +of conflicts in the grammar to what is absolutely necessary. +Consider using the "lexer feedback hack" if it is a clean +solution, and reserve backtracking for a few special +cases. +.PP +btyacc runs its trials using the rule "try shifting first, +then try reducing in the order that the conflicting rules +appear in the input file". This means you can implement +semantic disambiguation rules like, for example: (1) If it +looks like a declaration it is, otherwise (2) If it looks like +an expression it is, otherwise (3) it is a syntax error [Ellis +& Stroustrup, Annotated C++ Reference Manual, p93]. To +achieve this, put all the rules for declarations before the +rules for expressions in the grammar file. +.PP +Backtracking is only triggered when the parse hits a +shift/reduce or reduce/reduce conflict in the table. If you +have no conflicts in your grammar, there is no extra cost, +other than some extra code which will never be invoked. +.PP +Currently, the generated parser performs +\fIno\fP pruning of alternate parsing paths. To +avoid an exponential explosion of possible paths (and parsing +time), you need to manually tell the parser when it can throw +away saved paths using the \fBYYVALID\fP statement. In practice, this turns out to be fairly easy to +do. For example, a C++ parser can just contain +\fB[YYVALID;]\fP after every complete declaration +and statement rule, resulting in the backtracking state being +pruned after seeing a `;' or `}' - there will never be a +situation in which it is useful to backtrack past either of +these. +.SS "Improved token position handling" +.PP +Compilers often need to build ASTs (abstract syntax trees) +such that every node in a tree can relate to the parsed +program source it came from. The \fBYYPOSN\fP mechanism supported by btyacc helps you in automating the text +position computation and in assigning the computed text +positions to the AST nodes. +.PP +In standard YACCs every token and every non-terminal +has an \fBYYSTYPE\fP semantic value attached to +it. With btyacc, every token and every non-terminal also has +an \fBYYPOSN\fP text position attached to it. +\fBYYPOSN\fP is a user-defined type. +.PP +btyacc maintains a stack of text position values in the +same way that it maintains a stack of semantic values. To make +use of the text position feature, you need to +\fB#define\fP the following: + + +.IP "YYPOSN" 10 +Preprocessor symbol for the C/C++ type of +the text position attached to every token and +non-terminal. +.IP "yyposn" 10 +Global variable of type \fBYYPOSN\fP. +The lexer must assign the text position of the +returned token to yyposn, just like it assigns the +semantic value of the returned token to yylval. +.IP "YYREDUCEPOSNFUNC" 10 +Preprocessor symbol for a function that is called +immediately after the regular grammar rule reduction +has been performed, to reduce text positions located +on the stack. +.IP "" 10 +Typically, this function extracts text positions +from the right-hand side rule components and either +assigns them to the returned $$ structure/tree or, if +no $$ value is returned, puts them into the ret text +position where it will be picked up by other rules +later. Its prototype is: + + +.PP +.nf +.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n +.sp 1 +\fBvoid \fBReducePosn\fP\fR( +\fBYYPOSN& \fBret\fR\fR, +\fBYYPOSN* \fBterm_posns\fR\fR, +\fBYYSTYPE* \fBterm_vals\fR\fR, +\fBint \fBterm_no\fR\fR, +\fBint \fBstk_pos\fR\fR, +\fBint \fByychar\fR\fR, +\fBYYPOSN& \fByyposn\fR\fR, +\fBUserType \fBextra\fR\fR); +.fi + + +.RS +.IP "ret" 10 +Reference to the text position +returned by the rule. You must overwrite this +with the computed text position that the rule +yields, analogous to the $$ semantic +value. +.IP "term_posns" 10 +Array of the right-hand side rule +components' \fBYYPOSN\fP text +positions, analogous to $1, $2, ..., $N for +the semantic values. +.IP "term_vals" 10 +Array of the right-hand side rule +components' \fBYYSTYPE\fP values. +These are the $1, ..., $N +themselves. +.IP "term_no" 10 +Number of components in the right +hand side of the reduced rule, i.e. the size +of the term_posns and term_vals arrays. Also +equal to N in $1, ..., $N. +.IP "stk_pos" 10 +\fBYYSTYPE\fP/\fBYYPOSN\fP stack position before the +reduction. +.IP "yychar" 10 +Lookahead token that immediately +follows the reduced right hand side +components. +.IP "yyposn" 10 +\fBYYPOSN\fP of the +token that immediately follows the reduced +right hand side components. +.IP "extra" 10 +User-defined extra argument passed +to ReducePosn. +.RE + +.IP "YYREDUCEPOSNFUNCARG" 10 +Extra argument passed to the ReducePosn +function. This argument can be any variable defined in +\fBbtyaccpa.ske\fP. + +.SS "Token deallocation during error recovery" +.PP +For most YACC-like parser generators, the action of the +generated parser upon encountering a parse error is to throw +away semantic values and input tokens until a rule containing +the special non-terminal \fBerror\fP can be +matched. Discarding of tokens is simply performed by +overwriting variables and array entries of type +\fBYYSTYPE\fP with new values. +.PP +Unfortunately, this approach leads to a memory leak if +\fBYYSTYPE\fP is a pointer type. btyacc allows +you to supply functions for cleaning up the semantic and text +position values, by \fB#define\fPing the +following symbols in the preamble of your grammar file: +.PP + +.IP "YYDELETEVAL" 10 +Preprocessor symbol for a function to call +before the semantic value of a token or non-terminal +is discarded. +.IP "YYDELETEPOSN" 10 +Preprocessor symbol for a function to call +before the text position of a token or non-terminal is +discarded. +.PP +Both functions are called with two arguments. The first +argument of type \fBYYSTYPE\fP or +\fBYYPOSN\fP is the value that will be discarded. +The second argument is of type \fBint\fP and is +one of three values: + +.IP "0" 10 +discarding input +token +.IP "1" 10 +discarding state on +stack +.IP "2" 10 +cleaning up stack when +aborting + +.SS "Detailed syntax error reporting" +.PP +If you \fB#define\fP the preprocessor +variable \fBYYERROR_DETAILED\fP in your grammar +file, you must also define the following error processing +function: + + +.PP +.nf +.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n +.sp 1 +\fBvoid \fByyerror_detailed\fP\fR( +\fBchar* \fBtext\fR\fR, +\fBint \fBerrt\fR\fR, +\fBYYSTYPE& +\fBerrt_value\fR\fR, +\fBYYPOSN& \fBerrt_posn\fR\fR); +.fi + +.IP "text" 10 +error message +.IP "errt" 10 +code of the token that caused the +error +.IP "errt_value" 10 +value of the token that caused the +error +.IP "errt_posn" 10 +text position of token that caused +error +.SS "Preprocessor directives" +.PP +btyacc supports defining symbols and acting on them with +conditional directives inside grammar files, not unlike the C +preprocessor. +.IP "%define \fINAME\fP" 10 +Define the preprocessor symbol +\fINAME\fP. Equivalent to the +command line switch +\fB-D\fP\fINAME\fP. + +.IP "%ifdef \fINAME\fP" 10 +If preprocessor variable +\fINAME\fP is defined, process the +text from this \fB%ifdef\fP to the closing +\fB%endif\fP, otherwise skip +it. +.IP "%endif" 10 +Closing directive for +\fB%ifdef\fP. \fB%ifdef\fPs +cannot be nested. +.IP "%include \fIFILENAME\fP" 10 +Process contents of the file named +\fIFILENAME\fP. Only one nesting +level of \fB%include\fP is +allowed. +.IP "%ident \fISTRING\fP" 10 +Insert an `\fB#ident +\fP\fISTRING\fP' directive into +the output file. \fISTRING\fP must be a +string constant enclosed in "". +.SS "Inherited attributes" +.PP +Inherited attributes are undocumented. (See the +\fBREADME\fP and the btyacc source code for a +little information.) If you work out how they work, contact me +at ! +.SH "Bugs" +.PP +The worst-case complexity of parsing is exponential for any +grammar which allows backtracking to take place. In other words, +a btyacc-generated parser constitutes a denial-of-service bug if +used in applications where an attacker is able to supply +specially crafted data as input to the parser. (For all +"regular" input data, the potentially exponential complexity is +not normally an issue.) +.PP +bison's \fB%expect\fP directive is not +supported. +.PP +There is no \fB%else\fP and +\fB%ifndef\fP. \fB%ifdef\fPs and +\fB%include\fPs cannot be nested. +.SH "Authors" +.PP +Robert Corbett + / + was one of the +original authors of Berkeley byacc. Chris Dodd + had the brilliant +idea of adding backtracking capabilities, and is responsible for +the initial backtracking changes. Vadim Maslov + further improved the +code. +.PP +This documenation was written by Richard Atterer + for the Debian +GNU/Linux distribution, but is donated to the public domain and +may thus be used freely for any purpose. +.SH "Files" +.PP +.IP "" 10 +\fB/usr/doc/btyacc/examples/btyaccpa.ske\fP +.IP "" 10 +\fB/usr/doc/btyacc/examples/btyacc-c.ske\fP +.IP "" 10 +\fB/usr/doc/btyacc/README\fP +.SH "See also" +.PP +\fBbison\fP\fB(1)\fP (or `info bison'), +\fBbyacc\fP\fB(1)\fP, +\fByacc\fP\fB(1)\fP, +\fBantlr\fP\fB(1)\fP +...\" created by instant / docbook-to-man, Mon 13 May 2002, 13:36 --- btyacc-3.0.orig/btyacc.sgml +++ btyacc-3.0/btyacc.sgml @@ -0,0 +1,608 @@ + + + + + + +
+ atterer@debian.org +
+ + Richard + Atterer + + January 30, 2001 +
+ + btyacc + 1 + + + btyacc an LALR(1) parser generator + with support for backtracking + + + + btyacc + -b prefix + -d + -DNAME + -E + -l + -r + -S x.ske + -t + -v + filename.y + + + + Description + + btyacc is a modified version of byacc (Berkeley YACC), which + in turn is a public domain version of the original AT&T YACC + parser generator. + + btyacc reads the grammar specification in the file + filename.y and generates an LR(1) + parser for it. The parser consists of a set of LALR(1) parsing + tables and a driver routine written in the C programming + language. btyacc normally writes the parse tables and the driver + routine to the file + prefix.tab.c, + where prefix defaults to `y'. + + For a detailed description of the format of a grammar + specification, and an excellent tutorial on how to use YACC-like + tools, see the info manual for GNU + bison. + btyacc-specific extensions are explained below. + + Note: The parser skeleton supplied by + btyacc's upstream author only compiles as C++. Use the skeleton + /usr/doc/btyacc/examples/btyacc-c.ske to + generate a parser that compiles both as C and C++. + (Unfortunately, this alternative skeleton does not currently + check malloc() return values.) + + + + Options + + + + -b prefix + + Change the prefix prepended to the output file names + to the string denoted by prefix. + The default prefix is the character `y'. + + + + -d + + Create a header file called + prefix.tab.h + along with + prefix.tab.c, + containing the symbol definitions and a declaration for + YYSTYPE and + yylval. + + + + -DNAME + + Define the btyacc preprocessor variable + NAME, for use with + %ifdef NAME + directives in the grammar file. + + + + -E + + Print the preprocessed grammar to standard + output. + + + + -l + + Do not insert #line directives into + the generated parser code. + + + + -r + + Write the parser code and the associated tables to + different files. Whereas the tables can be found in + prefix.tab.c + as before, the code now gets written to + prefix.code.c. + + + + + -S x.ske + + Select a different parser skeleton. The default + skeleton is hardwired into the program, but a copy can be + found in the file btyaccpa.ske. + + + + + -t + + Cause debugging code to be compiled into the generated + parser. + + + + -v + + Write a human-readable description of the generated + parser to y.output. It includes + parser states, actions for a look-ahead token and + information about any conflicts. + + + + + + + BTYACC extensions + + + Backtracking support + + Whenever a btyacc generated parser runs into a + shift-reduce or reduce-reduce error in the parse table, it + remembers the current parse point (stack and input stream + state), and goes into trial parse mode. It then continues + parsing, ignoring most rule actions. If it runs into an error + (either through the parse table or through an action calling + YYERROR), it backtracks to the most recent + conflict point and tries a different alternative. If it finds + a successful path (reaches the end of the input or an action + calls YYVALID), it backtracks to the point + where it first entered trial parse mode, and continues with a + full parse (executing all actions), following the path of the + successful trial. + + Actions in btyacc come in two flavors: + {} actions, which are only executed when + not in trial mode, and [] actions, which + are executed regardless of mode. + + Example: In YACC grammars for C, a + standard hack known as the "lexer feedback hack" is used to + find typedef names. The lexer uses semantic information to + decide if any given identifier is a typedef name or not and + returns a special token. With btyacc, you no longer need to do + this; the lexer should just always return an identifier. The + btyacc grammar then needs a rule of the form: + + typename: ID [ if (!IsTypeName(LookupId($1))) + YYERROR; ] + + However, note that adding backtracking rules slows down + the parser. In practice, you should try to restrict the number + of conflicts in the grammar to what is absolutely necessary. + Consider using the "lexer feedback hack" if it is a clean + solution, and reserve backtracking for a few special + cases. + + btyacc runs its trials using the rule "try shifting first, + then try reducing in the order that the conflicting rules + appear in the input file". This means you can implement + semantic disambiguation rules like, for example: (1) If it + looks like a declaration it is, otherwise (2) If it looks like + an expression it is, otherwise (3) it is a syntax error [Ellis + & Stroustrup, Annotated C++ Reference Manual, p93]. To + achieve this, put all the rules for declarations before the + rules for expressions in the grammar file. + + Backtracking is only triggered when the parse hits a + shift/reduce or reduce/reduce conflict in the table. If you + have no conflicts in your grammar, there is no extra cost, + other than some extra code which will never be invoked. + + Currently, the generated parser performs + no pruning of alternate parsing paths. To + avoid an exponential explosion of possible paths (and parsing + time), you need to manually tell the parser when it can throw + away saved paths using the YYVALID + statement. In practice, this turns out to be fairly easy to + do. For example, a C++ parser can just contain + [YYVALID;] after every complete declaration + and statement rule, resulting in the backtracking state being + pruned after seeing a `;' or `}' - there will never be a + situation in which it is useful to backtrack past either of + these. + + + + Improved token position handling + + Compilers often need to build ASTs (abstract syntax trees) + such that every node in a tree can relate to the parsed + program source it came from. The YYPOSN + mechanism supported by btyacc helps you in automating the text + position computation and in assigning the computed text + positions to the AST nodes. + + In standard YACCs every token and every non-terminal + has an YYSTYPE semantic value attached to + it. With btyacc, every token and every non-terminal also has + an YYPOSN text position attached to it. + YYPOSN is a user-defined type. + + btyacc maintains a stack of text position values in the + same way that it maintains a stack of semantic values. To make + use of the text position feature, you need to + #define the following: + + + + YYPOSN + + Preprocessor symbol for the C/C++ type of + the text position attached to every token and + non-terminal. + + + + yyposn + + Global variable of type YYPOSN. + The lexer must assign the text position of the + returned token to yyposn, just like it assigns the + semantic value of the returned token to yylval. + + + + YYREDUCEPOSNFUNC + + + Preprocessor symbol for a function that is called + immediately after the regular grammar rule reduction + has been performed, to reduce text positions located + on the stack. + + Typically, this function extracts text positions + from the right-hand side rule components and either + assigns them to the returned $$ structure/tree or, if + no $$ value is returned, puts them into the ret text + position where it will be picked up by other rules + later. Its prototype is: + + + + void ReducePosn + YYPOSN& ret + YYPOSN* term_posns + YYSTYPE* term_vals + int term_no + int stk_pos + int yychar + YYPOSN& yyposn + UserType extra + + + + + + ret + Reference to the text position + returned by the rule. You must overwrite this + with the computed text position that the rule + yields, analogous to the $$ semantic + value. + + + term_posns + Array of the right-hand side rule + components' YYPOSN text + positions, analogous to $1, $2, ..., $N for + the semantic values. + + + term_vals + Array of the right-hand side rule + components' YYSTYPE values. + These are the $1, ..., $N + themselves. + + + term_no + Number of components in the right + hand side of the reduced rule, i.e. the size + of the term_posns and term_vals arrays. Also + equal to N in $1, ..., $N. + + + stk_pos + YYSTYPE/YYPOSN + stack position before the + reduction. + + + yychar + Lookahead token that immediately + follows the reduced right hand side + components. + + + yyposn + YYPOSN of the + token that immediately follows the reduced + right hand side components. + + + extra + User-defined extra argument passed + to ReducePosn. + + + + + + + + YYREDUCEPOSNFUNCARG + Extra argument passed to the ReducePosn + function. This argument can be any variable defined in + btyaccpa.ske. + + + + + + + + Token deallocation during error recovery + + For most YACC-like parser generators, the action of the + generated parser upon encountering a parse error is to throw + away semantic values and input tokens until a rule containing + the special non-terminal error can be + matched. Discarding of tokens is simply performed by + overwriting variables and array entries of type + YYSTYPE with new values. + + Unfortunately, this approach leads to a memory leak if + YYSTYPE is a pointer type. btyacc allows + you to supply functions for cleaning up the semantic and text + position values, by #defineing the + following symbols in the preamble of your grammar file: + + + + + YYDELETEVAL + Preprocessor symbol for a function to call + before the semantic value of a token or non-terminal + is discarded. + + + YYDELETEPOSN + Preprocessor symbol for a function to call + before the text position of a token or non-terminal is + discarded. + + + + + Both functions are called with two arguments. The first + argument of type YYSTYPE or + YYPOSN is the value that will be discarded. + The second argument is of type int and is + one of three values: + + + 0discarding input + token + + + 1discarding state on + stack + + + 2cleaning up stack when + aborting + + + + + + + + Detailed syntax error reporting + + If you #define the preprocessor + variable YYERROR_DETAILED in your grammar + file, you must also define the following error processing + function: + + + + void yyerror_detailed + char* text + int errt + YYSTYPE& + errt_value + YYPOSN& errt_posn + + + + + + + text + error message + + + errt + code of the token that caused the + error + + + errt_value + value of the token that caused the + error + + + errt_posn + text position of token that caused + error + + + + + + Preprocessor directives + + btyacc supports defining symbols and acting on them with + conditional directives inside grammar files, not unlike the C + preprocessor. + + + + %define NAME + Define the preprocessor symbol + NAME. Equivalent to the + command line switch + -DNAME. + + + + %ifdef NAME + If preprocessor variable + NAME is defined, process the + text from this %ifdef to the closing + %endif, otherwise skip + it. + + + %endif + Closing directive for + %ifdef. %ifdefs + cannot be nested. + + + %include FILENAME + Process contents of the file named + FILENAME. Only one nesting + level of %include is + allowed. + + + %ident STRING + Insert an `#ident + STRING' directive into + the output file. STRING must be a + string constant enclosed in "". + + + + + + Inherited attributes + + Inherited attributes are undocumented. (See the + README and the btyacc source code for a + little information.) If you work out how they work, contact me + at <atterer@debian.org>! + + + + + + Bugs + + The worst-case complexity of parsing is exponential for any + grammar which allows backtracking to take place. In other words, + a btyacc-generated parser constitutes a denial-of-service bug if + used in applications where an attacker is able to supply + specially crafted data as input to the parser. (For all + "regular" input data, the potentially exponential complexity is + not normally an issue.) + + bison's %expect directive is not + supported. + + There is no %else and + %ifndef. %ifdefs and + %includes cannot be nested. + + + + Authors + + Robert Corbett + <robert.corbett@eng.sun.com> / + <corbett@berkeley.edu> was one of the + original authors of Berkeley byacc. Chris Dodd + <chrisd@reservoir.com> had the brilliant + idea of adding backtracking capabilities, and is responsible for + the initial backtracking changes. Vadim Maslov + <vadik@siber.com> further improved the + code. + + This documenation was written by Richard Atterer + <atterer@debian.org> for the Debian + GNU/Linux distribution, but is donated to the public domain and + may thus be used freely for any purpose. + + + + Files + + + + /usr/doc/btyacc/examples/btyaccpa.ske + + + /usr/doc/btyacc/examples/btyacc-c.ske + + /usr/doc/btyacc/README + + + + + See also + + + bison + 1 (or `info bison'), + byacc + 1, + yacc + 1, + antlr + 1 + + + +
+ + --- btyacc-3.0.orig/btyaccpa.ske +++ btyacc-3.0/btyaccpa.ske @@ -64,14 +64,14 @@ #define YYPOSNOUT (yyps->pos) #endif -// If delete function is not defined by the user, do not deletions. +/* If delete function is not defined by the user, do not delete. */ #ifndef YYDELETEVAL -#define YYDELETEVAL(v) +# define YYDELETEVAL(v, t) #endif -// If delete function is not defined by the user, do not deletions. +/* If delete function is not defined by the user, do not delete. */ #ifndef YYDELETEPOSN -#define YYDELETEPOSN(v) +# define YYDELETEPOSN(v, t) #endif #define yyclearin (yychar=(-1)) @@ -552,14 +552,20 @@ YYMoreStack(yyps); } +# ifdef _YACC_DEFAULT_ACTION_ /* "$$ = NULL" default action */ memset(&yyps->val, 0, sizeof(yyps->val)); - - /* default reduced position is NULL -- no position at all. - no position will be assigned at trial time and if no position handling is present */ +# else + /* RA: bison compatibility: default action is '$$ = $1;' */ + if (yym > 0) yyps->val = (yyps->vsp)[1 - yym]; +# endif + + /* Default reduced position is NULL -- no position at all. No + position will be assigned at trial time and if no position + handling is present */ memset(&yyps->pos, 0, sizeof(yyps->pos)); - reduce_posn = TRUE; + reduce_posn = 1; switch (yyn) { --- btyacc-3.0.orig/debian/README.Debian +++ btyacc-3.0/debian/README.Debian @@ -0,0 +1,32 @@ +btyacc for Debian +----------------- + +A number of small bugfixes have been applied to this Debian version of +btyacc: + +- Using "$0" in a rule no longer causes btyacc to crash or + the generated parser to behave incorrectly. + +- The generated parser does no longer depend on TRUE being defined. + +- Generated files use the suffixes ".tab.h .tab.c .code.c" rather than + "_tab.h _tab.c _code.c" + +- The default definitions of YYDELETEVAL and YYDELETEPOSN (i.e. the + ones used if you don't #define your own) have been changed to take + two arguments. + +- The default rule action of btyacc was to zero out $$ using memset. + In order to get closer to bison compatibility, the default has been + changed to "$$=$1". You can still get the original behaviour with a + "#define _YACC_DEFAULT_ACTION_" in your grammar file. + +- Temporary files are created in a secure manner, using mkstemp() + rather than mktemp(). + +Furthermore, in /usr/doc/btyacc/examples/btyacc-c.ske a parser +skeleton is supplied which compiles not only as C++ like upstream's +btyaccpa.ske, but also as C. + + +Richard Atterer Tue, 3 Jul 2001 21:59:14 +0200 --- btyacc-3.0.orig/debian/changelog +++ btyacc-3.0/debian/changelog @@ -0,0 +1,46 @@ +btyacc (3.0-5build1) bionic; urgency=high + + * No change rebuild to pick up -fPIE compiler default + + -- Balint Reczey Tue, 03 Apr 2018 12:15:49 +0000 + +btyacc (3.0-5) unstable; urgency=low + + * Rebuild: finish /usr/doc transition (Closes: #359373) + * Update debhelper compat and standards version + + -- Richard Atterer Tue, 28 Mar 2006 11:22:34 +0200 + +btyacc (3.0-4) unstable; urgency=low + + * Remove dependency on btyacc.1 in Makefile, to prevent make from + trying to rebuild it, closes: #146895 + + -- Richard Atterer Tue, 14 May 2002 19:14:30 +0200 + +btyacc (3.0-3) unstable; urgency=low + + * Fix update-alternative handling, closes: #146192 + + -- Richard Atterer Mon, 13 May 2002 12:49:15 +0200 + +btyacc (3.0-2) unstable; urgency=low + + * Security bugfix: Switched to mkstemp() instead of mktemp(), + temporary files are unlink()ed immediately after creation + * Added parser skeleton /usr/doc/btyacc/examples/btyacc-c.ske.gz + which compiles both as C and C++ + * Applied some compatibility fixes by Mitchell Charity, made + "usage:" message more verbose, made "skel2c" build script work + with all awks, not just gawk + + -- Richard Atterer Tue, 3 Jul 2001 21:59:14 +0200 + +btyacc (3.0-1) unstable; urgency=low + + * Initial Release. Finishes the ITP process, closes: #83946 + * Applied 5 small bugfixes to the upstream source (see README.Debian) + * Wrote a man page + + -- Richard Atterer Wed, 31 Jan 2001 12:45:57 +0100 + --- btyacc-3.0.orig/debian/compat +++ btyacc-3.0/debian/compat @@ -0,0 +1 @@ +5 --- btyacc-3.0.orig/debian/control +++ btyacc-3.0/debian/control @@ -0,0 +1,25 @@ +Source: btyacc +Section: devel +Priority: extra +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Richard Atterer +Standards-Version: 3.6.2 +Build-Depends: debhelper (>= 5) + +Package: btyacc +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Description: Backtracking parser generator based on byacc + btyacc is a hacked version of the original Berkeley "byacc". The main + change to byacc is the addition of backtracking code, allowing you to + try both alternatives in case of shift-reduce or reduce-reduce + conflicts. As long as no backtracking takes place, speed is comparable + to bison. + . + Additional features: + - enhanced support for storing of text position information for tokens + - closes the potential *yacc/bison memory leak during error recovery + - preprocessor directives like %ifdef, %include + - C++ friendly + . + Related packages: bison, byacc, antlr --- btyacc-3.0.orig/debian/copyright +++ btyacc-3.0/debian/copyright @@ -0,0 +1,75 @@ +This package was debianized by Richard Atterer on +Sun, 28 Jan 2001 17:20:26 +0100. + +It was downloaded from http://www.siber.org/btyacc/ + +Upstream Authors: +- / + (Original author of Berkeley byacc - NB btyacc is based on an older + version of byacc) +- Chris Dodd (initial BT code) +- Vadim Maslov (further improvements, current + maintainer) + +Copyright: + +The original byacc code carries the following license: + + Berkeley Yacc is distributed with no warranty whatever. The code is + certain to contain errors. Neither the author nor any contributor + takes responsibility for any consequences of its use. + + Berkeley Yacc is in the public domain. The data structures and + algorithms used in Berkeley Yacc are all either taken from documents + available to the general public or are inventions of the author. + Anyone may freely distribute source or binary forms of Berkeley Yacc + whether unchanged or modified. Distributers may charge whatever fees + they can obtain for Berkeley Yacc. Programs generated by Berkeley + Yacc may be distributed freely. + +Initial changes by Chris Dodd: + + BTYACC was created by Chris Dodd using ideas from many places and + lots of code from the Berkeley Yacc distribution, which is a public + domain yacc clone put together by the good folks at Berkeley. This + code is distributed with NO WARRANTEE and is public domain. It is + certain to contain bugs, which you should report to: + chrisd@collins.com. + +Further license notice by Chris Dodd and Vadim Maslov: + + In English: BtYacc is freeware. BtYacc is distributed with no + warranty whatsoever. The author and any other contributors take no + responsibility for any and all consequences of its use. + + In Legalese: LIMITATION OF LIABILITY. NEITHER SIBER SYSTEMS NOR ANY + OF ITS LICENSORS NOR ANY BTYACC CONTRIBUTOR SHALL BE LIABLE FOR ANY + INDIRECT, INCIDENTAL, SPECIAL OR CONSEQUENTIAL DAMAGES, OR DAMAGES + FOR LOSS OF PROFITS, REVENUE, DATA OR DATA USE, CAUSED BY BTYACC AND + INCURRED BY CUSTOMER OR ANY THIRD PARTY, WHETHER IN AN ACTION IN + CONTRACT OR TORT, EVEN IF SIBER SYSTEMS HAS BEEN ADVISED OF THE + POSSIBILITY OF SUCH DAMAGES. + +Because of the unclear meaning of the term "Freeware", I (Richard +Atterer) contacted the contributors by mail and asked them to clarify +its meaning. Statement by Chris Dodd: + +> All of my changes to Berkeley Yacc in making btyacc are public +> domain, as is the original byacc. I did that originally as I was +> unable to maintain btyacc, and wanted to make it widely available to +> anyone who could. I beleive there's actaully a statement to this +> effect in the top of the readme file. + +Statement by Vadim Maslov: + +> BtYacc is free in the freest sense of a word. Modification, +> imporvement, commercial use -- all this is possible. +> +> It is free in the same sense as original Berkeley Yacc, so it is +> freer than GNU yacc -- you can use it in commercial systems, I +> myself use it in CobolTransformer that is licensed for a lot of +> money. +> +[snip] +> BtYacc, just like Byacc is hereby officially donated to public +> domain. And as I understand, Chris Dodd agrees with me. --- btyacc-3.0.orig/debian/postinst +++ btyacc-3.0/debian/postinst @@ -0,0 +1,16 @@ +#!/bin/sh + +set -e + +if test $1 != "upgrade"; then + update-alternatives \ + --install /usr/bin/yacc yacc /usr/bin/btyacc 80 \ + --slave /usr/share/man/man1/yacc.1.gz yaccman /usr/share/man/man1/btyacc.1.gz + +fi + +#DEBHELPER# + +exit 0 + + --- btyacc-3.0.orig/debian/prerm +++ btyacc-3.0/debian/prerm @@ -0,0 +1,11 @@ +#!/bin/sh + +set -e + +if test $1 != "upgrade"; then + update-alternatives --remove yacc /usr/bin/btyacc +fi + +#DEBHELPER# + +exit 0 --- btyacc-3.0.orig/debian/rules +++ btyacc-3.0/debian/rules @@ -0,0 +1,61 @@ +#!/usr/bin/make -f + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +build: build-stamp +build-stamp: + dh_testdir + $(MAKE) + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp + -$(MAKE) distclean + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs usr/bin + $(MAKE) install DESTDIR=`pwd`/debian/btyacc + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install +# dh_testversion + dh_testdir + dh_testroot +# dh_installdebconf + dh_installdocs README README.BYACC btyacc.sgml + dh_installexamples btyaccpa.ske btyacc-c.ske test/*.y +# dh_installmenu +# dh_installemacsen +# dh_installpam +# dh_installinit +# dh_installcron + dh_installman btyacc.1 +# dh_installinfo +# dh_undocumented + dh_installchangelogs +# dh_link + dh_strip + dh_compress + dh_fixperms +# dh_suidregister +# dh_makeshlibs + dh_installdeb +# dh_perl + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install --- btyacc-3.0.orig/debian/watch +++ btyacc-3.0/debian/watch @@ -0,0 +1,5 @@ +# Example watch control file for uscan +# Rename this file to "watch" and then you can run the "uscan" command +# to check for upstream updates and more. +# Site Directory Pattern Version Script +http://www.siber.org /btyacc/ btyacc-(.*)\.tar\.gz debian uupdate --- btyacc-3.0.orig/defs.h +++ btyacc-3.0/defs.h @@ -59,9 +59,9 @@ /* defines for constructing filenames */ -#define DEFINES_SUFFIX "_tab.h" -#define OUTPUT_SUFFIX "_tab.c" -#define CODE_SUFFIX "_code.c" +#define DEFINES_SUFFIX ".tab.h" +#define OUTPUT_SUFFIX ".tab.c" +#define CODE_SUFFIX ".code.c" #define VERBOSE_SUFFIX ".output" /* keyword codes */ @@ -391,7 +391,7 @@ /* main.c */ void done(int); -void onintr(void); +void onintr(int); void set_signals(void); void usage(void); void getargs(int, char **); --- btyacc-3.0.orig/main.c +++ btyacc-3.0/main.c @@ -1,7 +1,10 @@ #include "defs.h" #include #include +#include #include +#include +#include char dflag; char lflag; @@ -69,14 +72,11 @@ void done(int k) { - if (action_file) { fclose(action_file); unlink(action_file_name); } - if (text_file) { fclose(text_file); unlink(text_file_name); } - if (union_file) { fclose(union_file); unlink(union_file_name); } exit(k); } -void onintr() +void onintr(int ignored) { done(1); } @@ -99,11 +99,19 @@ } -void usage() -{ - fprintf(stderr, "usage: %s [-dlrtv] [-b file_prefix] [-S skeleton file] " - "filename\n", myname); - exit(1); +void usage() { + printf("usage: %s [OPTIONS] file\n", myname); + puts( + " -b prefix Change `y' into `prefix' in all output filenames\n" + " -d Generate header file `y.tab.h'\n" + " -DNAME Define btyacc preprocessor variable NAME\n" + " -E Print preprocessed grammar to stdout\n" + " -l Do not insert #line directives into generated code\n" + " -r Write tables to `y.tab.c', code to `y.code.c'\n" + " -S x.skel Select parser skeleton\n" + " -t Include debugging code in generated parser\n" + " -v Write description of parser to `y.output'"); + exit(1); } @@ -295,19 +303,6 @@ text_file_name[len + 5] = 't'; union_file_name[len + 5] = 'u'; - if(mktemp(action_file_name)==NULL) { - fprintf(stderr, "btyacc: Cannot create temporary file\n"); - exit(1); - } - if(mktemp(text_file_name)==NULL) { - fprintf(stderr, "btyacc: Cannot create temporary file\n"); - exit(1); - } - if(mktemp(union_file_name)==NULL) { - fprintf(stderr, "btyacc: Cannot create temporary file\n"); - exit(1); - } - len = strlen(file_prefix); output_file_name = MALLOC(len + 7); @@ -347,6 +342,23 @@ } +static FILE* my_mkstemp(char* template) { + /* Some old implementations of mkstemp() create files mode 0666. + We change the umask to avoid any problem. */ + mode_t old_mode; + int fd; + FILE* result; + + old_mode = umask(077); + fd = mkstemp(template); + umask(old_mode); + if (fd == -1) return 0; + result = fdopen(fd, "w+b"); // result == 0 on error + unlink(template); + return result; +} + + void open_files() { create_file_names(); @@ -358,11 +370,11 @@ open_error(input_file_name); } - action_file = fopen(action_file_name, "w"); + action_file = my_mkstemp(action_file_name); if (action_file == 0) open_error(action_file_name); - text_file = fopen(text_file_name, "w"); + text_file = my_mkstemp(text_file_name); if (text_file == 0) open_error(text_file_name); @@ -378,7 +390,7 @@ defines_file = fopen(defines_file_name, "w"); if (defines_file == 0) open_error(defines_file_name); - union_file = fopen(union_file_name, "w"); + union_file = my_mkstemp(union_file_name); if (union_file == 0) open_error(union_file_name); } --- btyacc-3.0.orig/mkpar.c +++ btyacc-3.0/mkpar.c @@ -176,11 +176,12 @@ for (i = 3; i < nrules; ++i) if (!rules_used[i]) ++nunused; - if (nunused) + if (nunused) { if (nunused == 1) fprintf(stderr, "%s: 1 rule never reduced\n", myname); else fprintf(stderr, "%s: %d rules never reduced\n", myname, nunused); + } } --- btyacc-3.0.orig/mstring.c +++ btyacc-3.0/mstring.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "mstring.h" /* parameters about string length. START is the starting size and --- btyacc-3.0.orig/output.c +++ btyacc-3.0/output.c @@ -849,9 +849,7 @@ if (dflag && unionized) { - fclose(union_file); - union_file = fopen(union_file_name, "r"); - if (union_file == NULL) open_error(union_file_name); + rewind(union_file); while ((c = getc(union_file)) != EOF) { putc(c, defines_file); } @@ -871,10 +869,7 @@ register int state; /* 0=middle of line, 1=start of line, 2=seen '#' */ state = 1; - fclose(text_file); - text_file = fopen(text_file_name, "r"); - if (text_file == NULL) - open_error(text_file_name); + rewind(text_file); in = text_file; if ((c = getc(in)) == EOF) return; @@ -1191,11 +1186,7 @@ register int state; /* 0=middle of line, 1=start of line, 2=seen '#' */ state = 1; - fclose(action_file); - action_file = fopen(action_file_name, "r"); - if (action_file == NULL) - open_error(action_file_name); - + rewind(action_file); if ((c = getc(action_file)) == EOF) return; --- btyacc-3.0.orig/reader.c +++ btyacc-3.0/reader.c @@ -631,15 +631,20 @@ return (lookup(cache)); } -int get_number() -{ - register int c; - register int n; +/* Return (possibly negative) integer stored a cptr. On exit, cptr + points to first character after integer. */ +int get_number() { + int n = 0; + char c, first = *cptr; + + if (first == '-') + ++cptr; + for (c = *cptr; isdigit(c); c = *++cptr) + n = 10 * n + (c - '0'); + if (first == '-') + n = -n; - n = 0; - for (c = *cptr; isdigit(c); c = *++cptr) - n = 10*n + (c - '0'); - return (n); + return n; } // @@ -1421,21 +1426,17 @@ ++cptr; FREE(d_line); goto loop; } - else if (isdigit(c)) { + else if (isdigit(c) || (c == '-' && isdigit(cptr[1]))) { i = get_number(); - if (i > maxoffset) { + if (i <= 0) { + fprintf(f, "yyvsp[%d].%s", i - n, tag); } + else if (i > maxoffset) { dollar_warning(d_lineno, i); fprintf(f, "yyvsp[%d].%s", i - maxoffset, tag); } else fprintf(f, "yyvsp[%d].%s", offsets[i], tag); FREE(d_line); goto loop; } - else if (c == '-' && isdigit(cptr[1])) { - ++cptr; - i = -get_number() - n; - fprintf(f, "yyvsp[%d].%s", i, tag); - FREE(d_line); - goto loop; } else if (isalpha(c) || c == '_') { char *arg = scan_id(); for (i=plhs[nrules]->args-1; i>=0; i--) --- btyacc-3.0.orig/skel2c +++ btyacc-3.0/skel2c @@ -20,7 +20,11 @@ next; } { if (havesection) { - gsub(/\\/, "\\\\"); + # Could use 'gsub(/\\/, "\\\\")' instead of the following + # two lines, but there's a bug in mawk and the original + # awk (not in gawk) which is triggered by that. + gsub(/\\/, "\\\1"); + gsub(/\1/, "\\"); gsub(/\t/, "\\t"); gsub(/\"/, "\\\""); printf " \"%s\",\n", $0;