Module Name: src Committed By: christos Date: Sat Mar 7 22:35:16 UTC 2020
Modified Files: src/usr.bin/config: scan.l Log Message: PR/55057: Paul Goyette: Don't use % 6 arithmetic that hurts the brain for the ifdef state machine, use bits and shifts instead. Also don't forget to restore the state once an include file ends. To generate a diff of this commit: cvs rdiff -u -r1.27 -r1.28 src/usr.bin/config/scan.l Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/config/scan.l diff -u src/usr.bin/config/scan.l:1.27 src/usr.bin/config/scan.l:1.28 --- src/usr.bin/config/scan.l:1.27 Sat Mar 7 14:26:13 2020 +++ src/usr.bin/config/scan.l Sat Mar 7 17:35:16 2020 @@ -1,5 +1,5 @@ %{ -/* $NetBSD: scan.l,v 1.27 2020/03/07 19:26:13 christos Exp $ */ +/* $NetBSD: scan.l,v 1.28 2020/03/07 22:35:16 christos Exp $ */ /* * Copyright (c) 1992, 1993 @@ -42,7 +42,7 @@ */ #include <sys/cdefs.h> -__RCSID("$NetBSD: scan.l,v 1.27 2020/03/07 19:26:13 christos Exp $"); +__RCSID("$NetBSD: scan.l,v 1.28 2020/03/07 22:35:16 christos Exp $"); #include <sys/param.h> #include <errno.h> @@ -62,34 +62,23 @@ int yyline; const char *yyfile; const char *lastfile; char curinclpath[PATH_MAX]; -int ifdefstate = -1; -int st; -#define IDS_PARENT_DISABLED \ - ((ifdefstate > 6) && ((((ifdefstate/6)-1) & 1) == 1)) -#define IDS_MAX_DEPTH 362797056 /* 6^11 */ -/* States for ifdefstate: - - 0 -> matched ifdef - 1 -> unmatched ifdef - 2 -> matched elifdef - 3 -> unmatched elifdef - 4 -> matched else - 5 -> unmatched else - - Upon "ifdef", add one and multiply by 6. - Upon "endif", divide by 6, remove 1. - - ifdef -> MATCH => continue - MISMATCH => set to 1 - elifdef -> if (!1) -> MISMATCH - MATCH => set to 2 - MISMATCH => if (2 || 3) set to 3, else set to 1 - else -> if (1) -> MATCH - MATCH => set to 4 - MISMATCH => set to 5 +uint64_t ifdefstate; +int ifdefshift = -1; + +/* + * The state is represented by 3 bits. + */ +#define IDS_MATCH 1ll +#define IDS_ELIF 2ll +#define IDS_ELSE 4ll + +#define IDS_BITS 7 +#define IDS_SHIFT 3 - in each case, if parent & 1 == 1, MISMATCH -*/ +#define IDS_ISMATCH(st) (((st) & IDS_MATCH) != 0) +#define IDS_PARENT_DISABLED \ + (ifdefshift > 0 && !IDS_ISMATCH(ifdefstate >> IDS_SHIFT)) +#define IDS_MAX_DEPTH 21 /* 64 / 3 */ /* * Data for returning to previous files from include files. @@ -100,7 +89,8 @@ struct incl { struct where in_where; int in_ateof; /* token to insert at EOF */ int in_interesting; /* previous value for "interesting" */ - int in_ifdefstate; /* conditional level */ + uint64_t in_ifdefstate; /* conditional level */ + int in_ifdefshift; /* conditional level */ }; static struct incl *incl; static int endinclude(void); @@ -180,97 +170,88 @@ with return WITH; := return COLONEQ; <*>ifdef[ \t]+{WORD}{RESTOFLINE} { - ifdefstate = (ifdefstate + 1) * 6; - if (ifdefstate >= IDS_MAX_DEPTH) { + ifdefstate <<= IDS_SHIFT; + if (++ifdefshift >= IDS_MAX_DEPTH) { yyerror("too many levels of conditional"); } - if (!IDS_PARENT_DISABLED && getcurifdef()) { - BEGIN(INITIAL); - } else { - ifdefstate++; + if (IDS_PARENT_DISABLED || !getcurifdef()) { BEGIN(IGNORED); + } else { + ifdefstate |= IDS_MATCH; + BEGIN(INITIAL); } yyline++; } <*>ifndef[ \t]+{WORD}{RESTOFLINE} { - ifdefstate = (ifdefstate + 1) * 6; - if (ifdefstate >= IDS_MAX_DEPTH) { + ifdefstate <<= IDS_SHIFT; + if (++ifdefshift >= IDS_MAX_DEPTH) { yyerror("too many levels of conditional"); } - if (!IDS_PARENT_DISABLED && !getcurifdef()) { - BEGIN(INITIAL); - } else { - ifdefstate++; + if (IDS_PARENT_DISABLED || getcurifdef()) { BEGIN(IGNORED); + } else { + ifdefstate |= IDS_MATCH; + BEGIN(INITIAL); } yyline++; } <*>elifdef[ \t]+{WORD}{RESTOFLINE} { - st = ifdefstate % 6; - if (ifdefstate < 0 || st > 3) { + int st = ifdefstate & IDS_BITS; + if (ifdefshift == -1 || (st & IDS_ELSE) != 0) { yyerror("mismatched elifdef"); } - if (IDS_PARENT_DISABLED || - st != 1 || !getcurifdef()) { - if (st == 2 || st == 3) { - ifdefstate += 3 - st; - } else { - ifdefstate += 1 - st; - } + if (IDS_PARENT_DISABLED || IDS_ISMATCH(st) || !getcurifdef()) { BEGIN(IGNORED); } else { - ifdefstate++; + ifdefstate |= IDS_MATCH; BEGIN(INITIAL); } + ifdefstate |= IDS_ELIF; yyline++; } <*>elifndef[ \t]+{WORD}{RESTOFLINE} { - st = ifdefstate % 6; - if (ifdefstate < 0 || st > 3) { + int st = ifdefstate & IDS_BITS; + if (ifdefshift == -1 || (st & IDS_ELSE) != 0) { yyerror("mismatched elifndef"); } - if (IDS_PARENT_DISABLED || - st != 1 || getcurifdef()) { - if (st == 2 || st == 3) { - ifdefstate += 3 - st; - } else { - ifdefstate += 1 - st; - } + if (IDS_PARENT_DISABLED || IDS_ISMATCH(st) || getcurifdef()) { BEGIN(IGNORED); } else { - ifdefstate++; + ifdefstate |= IDS_MATCH; BEGIN(INITIAL); } + ifdefstate |= IDS_ELIF; yyline++; } <*>else{RESTOFLINE} { - st = ifdefstate % 6; - if (ifdefstate < 0 || st > 3) { + int st = ifdefstate & IDS_BITS; + if (ifdefshift == -1 || (st & IDS_ELSE) != 0) { yyerror("mismatched else"); } - if (!IDS_PARENT_DISABLED && (st == 1)) { - ifdefstate += 3; - BEGIN(INITIAL); - } else { - ifdefstate += 5 - st; + if (IDS_PARENT_DISABLED || IDS_ISMATCH(st)) { BEGIN(IGNORED); + } else { + ifdefstate |= IDS_MATCH; + BEGIN(INITIAL); } + ifdefstate |= IDS_ELSE; yyline++; } <*>endif{RESTOFLINE} { - if (ifdefstate < 0) { + if (ifdefshift == -1) { yyerror("mismatched endif"); } if (!IDS_PARENT_DISABLED) { BEGIN(INITIAL); } - ifdefstate = (ifdefstate/6) - 1; + ifdefshift--; + ifdefstate >>= IDS_SHIFT; yyline++; } @@ -369,7 +350,7 @@ package[ \t]+{FILENAME}{RESTOFLINE} { [ \t]+ { /* ignored (white space) */; } . { return yytext[0]; } <*><<EOF>> { - if (ifdefstate > (incl == NULL ? -1 : incl->in_ifdefstate)) { + if (ifdefshift > (incl == NULL ? -1 : incl->in_ifdefshift)) { yyerror("reached EOF while looking for endif"); } if (incl == NULL) @@ -530,6 +511,7 @@ include(const char *fname, int ateof, in in->in_ateof = ateof; in->in_interesting = interesting; in->in_ifdefstate = ifdefstate; + in->in_ifdefshift = ifdefshift; interesting = direct & interesting; if (interesting) logconfig_include(fp, fname); @@ -600,6 +582,8 @@ endinclude(void) yyline = in->in_where.w_srcline; ateof = in->in_ateof; interesting = in->in_interesting; + ifdefstate = in->in_ifdefstate; + ifdefshift = in->in_ifdefshift; free(in); includedepth--;