Module Name: src Committed By: rillig Date: Fri Nov 13 07:52:04 UTC 2020
Modified Files: src/usr.bin/make: cond.c Log Message: make(1): use bitset for IfState Previously, the individual IfStates contained redundant information, which was apparent in the documentation. This led to expressions like (state > ELSE_ACTIVE) that are hard to read since the reader has to look up the order of the enum. To avoid this, the state of an '.if' block is now encoded using a bitset, encoding the properties of each state directly. This replaces the previous (state > ELSE_ACTIVE) with !(state & IFS_ACTIVE), which is easier to understand. No change in behavior. To generate a diff of this commit: cvs rdiff -u -r1.212 -r1.213 src/usr.bin/make/cond.c 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/make/cond.c diff -u src/usr.bin/make/cond.c:1.212 src/usr.bin/make/cond.c:1.213 --- src/usr.bin/make/cond.c:1.212 Fri Nov 13 07:35:27 2020 +++ src/usr.bin/make/cond.c Fri Nov 13 07:52:03 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: cond.c,v 1.212 2020/11/13 07:35:27 rillig Exp $ */ +/* $NetBSD: cond.c,v 1.213 2020/11/13 07:52:03 rillig Exp $ */ /* * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. @@ -94,7 +94,7 @@ #include "dir.h" /* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */ -MAKE_RCSID("$NetBSD: cond.c,v 1.212 2020/11/13 07:35:27 rillig Exp $"); +MAKE_RCSID("$NetBSD: cond.c,v 1.213 2020/11/13 07:52:03 rillig Exp $"); /* * The parsing of conditional expressions is based on this grammar: @@ -1092,26 +1092,18 @@ Cond_EvalLine(const char *const line) { typedef enum IfState { - /* The previous <cond> evaluated to TRUE. The lines following this - * condition are interpreted. */ - IF_ACTIVE, - - /* The previous '.else' evaluated to TRUE. The lines following this - * condition are interpreted. The only difference to IF_ACTIVE is - * that no other '.else' may follow. */ - ELSE_ACTIVE, - - /* All of the previous <cond> evaluated to FALSE. Still searching - * for an '.elif' or an 'else' that evaluates to TRUE. */ - SEARCH_FOR_ELIF, - - /* One of the previous <cond> evaluated to TRUE. There was no '.else' - * yet. */ - SKIP_TO_ELSE, - - /* One of the previous <cond> evaluated to TRUE, and '.else' was - * already seen. No other '.else' may follow. */ - SKIP_TO_ENDIF + /* None of the previous <cond> evaluated to TRUE. */ + IFS_INITIAL = 0, + + /* The previous <cond> evaluated to TRUE. + * The lines following this condition are interpreted. */ + IFS_ACTIVE = 1 << 0, + + /* The previous directive was an '.else'. */ + IFS_SEEN_ELSE = 1 << 1, + + /* One of the previous <cond> evaluated to TRUE. */ + IFS_WAS_ACTIVE = 1 << 2 } IfState; @@ -1126,7 +1118,7 @@ Cond_EvalLine(const char *const line) if (cond_states == NULL) { cond_states = bmake_malloc(cond_states_cap * sizeof *cond_states); - cond_states[0] = IF_ACTIVE; + cond_states[0] = IFS_ACTIVE; } p++; /* skip the leading '.' */ @@ -1136,8 +1128,8 @@ Cond_EvalLine(const char *const line) if (p[0] == 'e') { if (p[1] != 'l') { if (!is_token(p + 1, "ndif", 4)) { - /* Unknown directive. It might still be a transformation - * rule like '.elisp.scm', therefore no error message here. */ + /* Unknown directive. It might still be a transformation + * rule like '.elisp.scm', therefore no error message here. */ return COND_INVALID; } @@ -1151,7 +1143,7 @@ Cond_EvalLine(const char *const line) /* Return state for previous conditional */ cond_depth--; - return cond_states[cond_depth] <= ELSE_ACTIVE + return cond_states[cond_depth] & IFS_ACTIVE ? COND_PARSE : COND_SKIP; } @@ -1167,15 +1159,16 @@ Cond_EvalLine(const char *const line) } state = cond_states[cond_depth]; - if (state == SEARCH_FOR_ELIF) { - state = ELSE_ACTIVE; + if (state == IFS_INITIAL) { + state = IFS_ACTIVE | IFS_SEEN_ELSE; } else { - if (state == ELSE_ACTIVE || state == SKIP_TO_ENDIF) + if (state & IFS_SEEN_ELSE) Parse_Error(PARSE_WARNING, "extra else"); - state = SKIP_TO_ENDIF; + state = IFS_WAS_ACTIVE | IFS_SEEN_ELSE; } cond_states[cond_depth] = state; - return state <= ELSE_ACTIVE ? COND_PARSE : COND_SKIP; + + return state & IFS_ACTIVE ? COND_PARSE : COND_SKIP; } /* Assume for now it is an elif */ isElif = TRUE; @@ -1215,14 +1208,13 @@ Cond_EvalLine(const char *const line) return COND_PARSE; } state = cond_states[cond_depth]; - if (state == SKIP_TO_ENDIF || state == ELSE_ACTIVE) { + if (state & IFS_SEEN_ELSE) { Parse_Error(PARSE_WARNING, "extra elif"); - cond_states[cond_depth] = SKIP_TO_ENDIF; + cond_states[cond_depth] = IFS_WAS_ACTIVE | IFS_SEEN_ELSE; return COND_SKIP; } - if (state != SEARCH_FOR_ELIF) { - /* Either just finished the 'true' block, or already SKIP_TO_ELSE */ - cond_states[cond_depth] = SKIP_TO_ELSE; + if (state != IFS_INITIAL) { + cond_states[cond_depth] = IFS_WAS_ACTIVE; return COND_SKIP; } } else { @@ -1239,9 +1231,9 @@ Cond_EvalLine(const char *const line) } state = cond_states[cond_depth]; cond_depth++; - if (state > ELSE_ACTIVE) { + if (!(state & IFS_ACTIVE)) { /* If we aren't parsing the data, treat as always false */ - cond_states[cond_depth] = SKIP_TO_ELSE; + cond_states[cond_depth] = IFS_WAS_ACTIVE; return COND_SKIP; } } @@ -1250,15 +1242,16 @@ Cond_EvalLine(const char *const line) if (CondEvalExpression(ifp, p, &value, TRUE, TRUE) == COND_INVALID) { /* Syntax error in conditional, error message already output. */ /* Skip everything to matching .endif */ - cond_states[cond_depth] = SKIP_TO_ELSE; + /* XXX: An extra '.else' is not detected in this case. */ + cond_states[cond_depth] = IFS_WAS_ACTIVE; return COND_SKIP; } if (!value) { - cond_states[cond_depth] = SEARCH_FOR_ELIF; + cond_states[cond_depth] = IFS_INITIAL; return COND_SKIP; } - cond_states[cond_depth] = IF_ACTIVE; + cond_states[cond_depth] = IFS_ACTIVE; return COND_PARSE; }