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--;

Reply via email to