Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/usr.bin/make make(1): remove struct If from evaluation of co...
details: https://anonhg.NetBSD.org/src/rev/6fc8ba25f49a
branches: trunk
changeset: 950193:6fc8ba25f49a
user: rillig <rillig%NetBSD.org@localhost>
date: Tue Jan 19 21:55:20 2021 +0000
description:
make(1): remove struct If from evaluation of conditionals
The variant of the .if directive can be stored in the CondParser
directly, instead of pointing to a struct If.
The type CondParser may have to be renamed since the condition is not
only parsed, it is evaluated as well.
No functional change.
diffstat:
usr.bin/make/cond.c | 115 ++++++++++++++++++++++++++-------------------------
1 files changed, 59 insertions(+), 56 deletions(-)
diffs (223 lines):
diff -r ed764d8b6b0f -r 6fc8ba25f49a usr.bin/make/cond.c
--- a/usr.bin/make/cond.c Tue Jan 19 20:51:46 2021 +0000
+++ b/usr.bin/make/cond.c Tue Jan 19 21:55:20 2021 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cond.c,v 1.242 2021/01/19 20:51:46 rillig Exp $ */
+/* $NetBSD: cond.c,v 1.243 2021/01/19 21:55:20 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -95,7 +95,7 @@
#include "dir.h"
/* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */
-MAKE_RCSID("$NetBSD: cond.c,v 1.242 2021/01/19 20:51:46 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.243 2021/01/19 21:55:20 rillig Exp $");
/*
* The parsing of conditional expressions is based on this grammar:
@@ -138,7 +138,18 @@
} CondResult;
typedef struct CondParser {
- const struct If *if_info; /* Info for current statement */
+
+ /*
+ * The plain '.if ${VAR}' evaluates to true if the value of the
+ * expression has length > 0. The other '.if' variants delegate
+ * to evalBare instead.
+ */
+ Boolean plain;
+
+ /* The function to apply on unquoted bare words. */
+ Boolean (*evalBare)(size_t, const char *);
+ Boolean negateEvalBare;
+
const char *p; /* The remaining condition to parse */
Token curr; /* Single push-back token used in parsing */
@@ -511,32 +522,11 @@
*out_str = str;
}
-struct If {
- const char *form; /* Form of if */
- size_t formlen; /* Length of form */
- Boolean doNot; /* TRUE if default function should be negated */
- /* The default function to apply on unquoted bare words. */
- Boolean (*defProc)(size_t, const char *);
-};
-
-/* The different forms of .if directives. */
-static const struct If ifs[] = {
- { "def", 3, FALSE, FuncDefined },
- { "ndef", 4, TRUE, FuncDefined },
- { "make", 4, FALSE, FuncMake },
- { "nmake", 5, TRUE, FuncMake },
- { "", 0, FALSE, FuncDefined },
- { NULL, 0, FALSE, NULL }
-};
-enum {
- PLAIN_IF_INDEX = 4
-};
-
static Boolean
-If_Eval(const struct If *if_info, const char *arg, size_t arglen)
+If_Eval(const CondParser *par, const char *arg, size_t arglen)
{
- Boolean res = if_info->defProc(arglen, arg);
- return if_info->doNot ? !res : res;
+ Boolean res = par->evalBare(arglen, arg);
+ return par->negateEvalBare ? !res : res;
}
/*
@@ -560,11 +550,10 @@
* the evaluation function from that .if variant, which would test
* whether a variable of the given name were defined. */
/* XXX: Whitespace should count as empty, just as in ParseEmptyArg. */
- if (par->if_info->form[0] == '\0')
+ if (par->plain)
return value[0] != '\0';
- /* For the other variants of .ifxxx ${...}, use its default function. */
- return If_Eval(par->if_info, value, strlen(value));
+ return If_Eval(par, value, strlen(value));
}
/* Evaluate a numerical comparison, such as in ".if ${VAR} >= 9". */
@@ -835,7 +824,7 @@
* after .if must have been taken literally, so the argument cannot
* be empty - even if it contained a variable expansion.
*/
- t = ToToken(!doEval || If_Eval(par->if_info, arg, arglen));
+ t = ToToken(!doEval || If_Eval(par, arg, arglen));
free(arg);
return t;
}
@@ -999,7 +988,7 @@
}
static CondEvalResult
-CondParser_Eval(CondParser *par, Boolean *value)
+CondParser_Eval(CondParser *par, Boolean *out_value)
{
CondResult res;
@@ -1012,7 +1001,7 @@
if (CondParser_Token(par, FALSE) != TOK_EOF)
return COND_INVALID;
- *value = res == CR_TRUE;
+ *out_value = res == CR_TRUE;
return COND_PARSE;
}
@@ -1028,7 +1017,8 @@
* (*value) is set to the boolean value of the condition
*/
static CondEvalResult
-CondEvalExpression(const struct If *info, const char *cond, Boolean *value,
+CondEvalExpression(const char *cond, Boolean *out_value, Boolean plain,
+ Boolean (*evalBare)(size_t, const char *), Boolean negate,
Boolean eprint, Boolean strictLHS)
{
CondParser par;
@@ -1038,12 +1028,14 @@
cpp_skip_hspace(&cond);
- par.if_info = info != NULL ? info : ifs + PLAIN_IF_INDEX;
+ par.plain = plain;
+ par.evalBare = evalBare;
+ par.negateEvalBare = negate;
par.p = cond;
par.curr = TOK_NONE;
par.printedError = FALSE;
- rval = CondParser_Eval(&par, value);
+ rval = CondParser_Eval(&par, out_value);
if (rval == COND_INVALID && eprint && !par.printedError)
Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", cond);
@@ -1058,7 +1050,8 @@
CondEvalResult
Cond_EvalCondition(const char *cond, Boolean *out_value)
{
- return CondEvalExpression(NULL, cond, out_value, FALSE, FALSE);
+ return CondEvalExpression(cond, out_value, TRUE,
+ FuncDefined, FALSE, FALSE, FALSE);
}
static Boolean
@@ -1121,7 +1114,9 @@
static enum IfState *cond_states = NULL;
static unsigned int cond_states_cap = 128;
- const struct If *ifp;
+ Boolean plain;
+ Boolean (*evalBare)(size_t, const char *);
+ Boolean negate;
Boolean isElif;
Boolean value;
IfState state;
@@ -1205,25 +1200,32 @@
}
/*
- * Figure out what sort of conditional it is -- what its default
- * function is, etc. -- by looking in the table of valid "ifs"
+ * Figure out what sort of conditional it is.
*/
p += 2;
- for (ifp = ifs;; ifp++) {
- if (ifp->form == NULL) {
- /*
- * TODO: Add error message about unknown directive,
- * since there is no other known directive that starts
- * with 'el' or 'if'.
- *
- * Example: .elifx 123
- */
- return COND_INVALID;
- }
- if (is_token(p, ifp->form, ifp->formlen)) {
- p += ifp->formlen;
- break;
- }
+ plain = FALSE;
+ evalBare = FuncDefined;
+ negate = FALSE;
+ if (*p == 'n') {
+ p++;
+ negate = TRUE;
+ }
+ if (is_token(p, "def", 3)) { /* .ifdef and .ifndef */
+ p += 3;
+ } else if (is_token(p, "make", 4)) { /* .ifmake and .ifnmake */
+ p += 4;
+ evalBare = FuncMake;
+ } else if (is_token(p, "", 0) && !negate) { /* plain .if */
+ plain = TRUE;
+ } else {
+ /*
+ * TODO: Add error message about unknown directive,
+ * since there is no other known directive that starts
+ * with 'el' or 'if'.
+ *
+ * Example: .elifx 123
+ */
+ return COND_INVALID;
}
/* Now we know what sort of 'if' it is... */
@@ -1270,7 +1272,8 @@
}
/* And evaluate the conditional expression */
- if (CondEvalExpression(ifp, p, &value, TRUE, TRUE) == COND_INVALID) {
+ if (CondEvalExpression(p, &value, plain, evalBare, negate,
+ TRUE, TRUE) == COND_INVALID) {
/* Syntax error in conditional, error message already output. */
/* Skip everything to matching .endif */
/* XXX: An extra '.else' is not detected in this case. */
Home |
Main Index |
Thread Index |
Old Index