Module Name: src
Committed By: rillig
Date: Mon Nov 23 20:05:31 UTC 2020
Modified Files:
src/usr.bin/make: cond.c
Log Message:
make(1): indent cond.c with tabs instead of spaces
To generate a diff of this commit:
cvs rdiff -u -r1.214 -r1.215 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.214 src/usr.bin/make/cond.c:1.215
--- src/usr.bin/make/cond.c:1.214 Fri Nov 13 09:01:59 2020
+++ src/usr.bin/make/cond.c Mon Nov 23 20:05:31 2020
@@ -1,4 +1,4 @@
-/* $NetBSD: cond.c,v 1.214 2020/11/13 09:01:59 rillig Exp $ */
+/* $NetBSD: cond.c,v 1.215 2020/11/23 20:05:31 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.214 2020/11/13 09:01:59 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.215 2020/11/23 20:05:31 rillig Exp $");
/*
* The parsing of conditional expressions is based on this grammar:
@@ -135,20 +135,22 @@ MAKE_RCSID("$NetBSD: cond.c,v 1.214 2020
* CondParser_Term) return either TOK_FALSE, TOK_TRUE, or TOK_ERROR on error.
*/
typedef enum Token {
- TOK_FALSE = 0, TOK_TRUE = 1, TOK_AND, TOK_OR, TOK_NOT,
- TOK_LPAREN, TOK_RPAREN, TOK_EOF, TOK_NONE, TOK_ERROR
+ TOK_FALSE = 0, TOK_TRUE = 1, TOK_AND, TOK_OR, TOK_NOT,
+ TOK_LPAREN, TOK_RPAREN, TOK_EOF, TOK_NONE, TOK_ERROR
} Token;
typedef struct CondParser {
- const struct If *if_info; /* Info for current statement */
- const char *p; /* The remaining condition to parse */
- Token curr; /* Single push-back token used in parsing */
-
- /* Whether an error message has already been printed for this condition.
- * The first available error message is usually the most specific one,
- * therefore it makes sense to suppress the standard "Malformed
- * conditional" message. */
- Boolean printedError;
+ const struct If *if_info; /* Info for current statement */
+ const char *p; /* The remaining condition to parse */
+ Token curr; /* Single push-back token used in parsing */
+
+ /*
+ * Whether an error message has already been printed for this
+ * condition. The first available error message is usually the most
+ * specific one, therefore it makes sense to suppress the standard
+ * "Malformed conditional" message.
+ */
+ Boolean printedError;
} CondParser;
static Token CondParser_Expr(CondParser *par, Boolean);
@@ -171,29 +173,29 @@ static Boolean lhsStrict;
static int
is_token(const char *str, const char *tok, size_t len)
{
- return strncmp(str, tok, len) == 0 && !ch_isalpha(str[len]);
+ return strncmp(str, tok, len) == 0 && !ch_isalpha(str[len]);
}
static Token
ToToken(Boolean cond)
{
- return cond ? TOK_TRUE : TOK_FALSE;
+ return cond ? TOK_TRUE : TOK_FALSE;
}
/* Push back the most recent token read. We only need one level of this. */
static void
CondParser_PushBack(CondParser *par, Token t)
{
- assert(par->curr == TOK_NONE);
- assert(t != TOK_NONE);
+ assert(par->curr == TOK_NONE);
+ assert(t != TOK_NONE);
- par->curr = t;
+ par->curr = t;
}
static void
CondParser_SkipWhitespace(CondParser *par)
{
- cpp_skip_whitespace(&par->p);
+ cpp_skip_whitespace(&par->p);
}
/* Parse the argument of a built-in function.
@@ -210,116 +212,121 @@ CondParser_SkipWhitespace(CondParser *pa
* Return the length of the argument, or 0 on error. */
static size_t
ParseFuncArg(const char **pp, Boolean doEval, const char *func,
- char **out_arg) {
- const char *p = *pp;
- Buffer argBuf;
- int paren_depth;
- size_t argLen;
-
- if (func != NULL)
- p++; /* Skip opening '(' - verified by caller */
-
- if (*p == '\0') {
- *out_arg = NULL; /* Missing closing parenthesis: */
- return 0; /* .if defined( */
- }
-
- cpp_skip_hspace(&p);
-
- Buf_InitSize(&argBuf, 16);
-
- paren_depth = 0;
- for (;;) {
- char ch = *p;
- if (ch == '\0' || ch == ' ' || ch == '\t')
- break;
- if ((ch == '&' || ch == '|') && paren_depth == 0)
- break;
- if (*p == '$') {
- /*
- * Parse the variable spec and install it as part of the argument
- * if it's valid. We tell Var_Parse to complain on an undefined
- * variable, so we don't need to do it. Nor do we return an error,
- * though perhaps we should...
- */
- void *nestedVal_freeIt;
- VarEvalFlags eflags = doEval ? VARE_WANTRES | VARE_UNDEFERR
- : VARE_NONE;
- const char *nestedVal;
- (void)Var_Parse(&p, VAR_CMDLINE, eflags, &nestedVal,
- &nestedVal_freeIt);
- /* TODO: handle errors */
- Buf_AddStr(&argBuf, nestedVal);
- free(nestedVal_freeIt);
- continue;
- }
- if (ch == '(')
- paren_depth++;
- else if (ch == ')' && --paren_depth < 0)
- break;
- Buf_AddByte(&argBuf, *p);
- p++;
- }
-
- *out_arg = Buf_GetAll(&argBuf, &argLen);
- Buf_Destroy(&argBuf, FALSE);
-
- cpp_skip_hspace(&p);
-
- if (func != NULL && *p++ != ')') {
- Parse_Error(PARSE_WARNING, "Missing closing parenthesis for %s()",
- func);
- /* The PARSE_FATAL is done as a follow-up by CondEvalExpression. */
- return 0;
- }
+ char **out_arg)
+{
+ const char *p = *pp;
+ Buffer argBuf;
+ int paren_depth;
+ size_t argLen;
+
+ if (func != NULL)
+ p++; /* Skip opening '(' - verified by caller */
+
+ if (*p == '\0') {
+ *out_arg = NULL; /* Missing closing parenthesis: */
+ return 0; /* .if defined( */
+ }
+
+ cpp_skip_hspace(&p);
+
+ Buf_InitSize(&argBuf, 16);
+
+ paren_depth = 0;
+ for (;;) {
+ char ch = *p;
+ if (ch == '\0' || ch == ' ' || ch == '\t')
+ break;
+ if ((ch == '&' || ch == '|') && paren_depth == 0)
+ break;
+ if (*p == '$') {
+ /*
+ * Parse the variable expression and install it as
+ * part of the argument if it's valid. We tell
+ * Var_Parse to complain on an undefined variable,
+ * (XXX: but Var_Parse ignores that request)
+ * so we don't need to do it. Nor do we return an
+ * error, though perhaps we should.
+ */
+ void *nestedVal_freeIt;
+ VarEvalFlags eflags = doEval
+ ? VARE_WANTRES | VARE_UNDEFERR
+ : VARE_NONE;
+ const char *nestedVal;
+ (void)Var_Parse(&p, VAR_CMDLINE, eflags,
+ &nestedVal, &nestedVal_freeIt);
+ /* TODO: handle errors */
+ Buf_AddStr(&argBuf, nestedVal);
+ free(nestedVal_freeIt);
+ continue;
+ }
+ if (ch == '(')
+ paren_depth++;
+ else if (ch == ')' && --paren_depth < 0)
+ break;
+ Buf_AddByte(&argBuf, *p);
+ p++;
+ }
- *pp = p;
- return argLen;
+ *out_arg = Buf_GetAll(&argBuf, &argLen);
+ Buf_Destroy(&argBuf, FALSE);
+
+ cpp_skip_hspace(&p);
+
+ if (func != NULL && *p++ != ')') {
+ Parse_Error(PARSE_WARNING,
+ "Missing closing parenthesis for %s()",
+ func);
+ /* The PARSE_FATAL follows in CondEvalExpression. */
+ return 0;
+ }
+
+ *pp = p;
+ return argLen;
}
/* Test whether the given variable is defined. */
static Boolean
FuncDefined(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
{
- void *freeIt;
- Boolean result = Var_Value(arg, VAR_CMDLINE, &freeIt) != NULL;
- bmake_free(freeIt);
- return result;
+ void *freeIt;
+ Boolean result = Var_Value(arg, VAR_CMDLINE, &freeIt) != NULL;
+ bmake_free(freeIt);
+ return result;
}
/* See if the given target is being made. */
static Boolean
FuncMake(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
{
- StringListNode *ln;
+ StringListNode *ln;
- for (ln = opts.create->first; ln != NULL; ln = ln->next)
- if (Str_Match(ln->datum, arg))
- return TRUE;
- return FALSE;
+ for (ln = opts.create->first; ln != NULL; ln = ln->next)
+ if (Str_Match(ln->datum, arg))
+ return TRUE;
+ return FALSE;
}
/* See if the given file exists. */
static Boolean
FuncExists(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
{
- Boolean result;
- char *path;
+ Boolean result;
+ char *path;
- path = Dir_FindFile(arg, dirSearchPath);
- DEBUG2(COND, "exists(%s) result is \"%s\"\n",
- arg, path != NULL ? path : "");
- result = path != NULL;
- free(path);
- return result;
+ path = Dir_FindFile(arg, dirSearchPath);
+ DEBUG2(COND, "exists(%s) result is \"%s\"\n",
+ arg, path != NULL ? path : "");
+ result = path != NULL;
+ free(path);
+ return result;
}
/* See if the given node exists and is an actual target. */
static Boolean
FuncTarget(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
{
- GNode *gn = Targ_FindNode(arg);
- return gn != NULL && GNode_IsTarget(gn);
+ GNode *gn = Targ_FindNode(arg);
+ return gn != NULL && GNode_IsTarget(gn);
}
/* See if the given node exists and is an actual target with commands
@@ -327,8 +334,8 @@ FuncTarget(size_t argLen MAKE_ATTR_UNUSE
static Boolean
FuncCommands(size_t argLen MAKE_ATTR_UNUSED, const char *arg)
{
- GNode *gn = Targ_FindNode(arg);
- return gn != NULL && GNode_IsTarget(gn) && !Lst_IsEmpty(gn->commands);
+ GNode *gn = Targ_FindNode(arg);
+ return gn != NULL && GNode_IsTarget(gn) && !Lst_IsEmpty(gn->commands);
}
/*
@@ -343,36 +350,36 @@ FuncCommands(size_t argLen MAKE_ATTR_UNU
static Boolean
TryParseNumber(const char *str, double *out_value)
{
- char *end;
- unsigned long ul_val;
- double dbl_val;
-
- errno = 0;
- if (str[0] == '\0') { /* XXX: why is an empty string a number? */
- *out_value = 0.0;
- return TRUE;
- }
+ char *end;
+ unsigned long ul_val;
+ double dbl_val;
+
+ errno = 0;
+ if (str[0] == '\0') { /* XXX: why is an empty string a number? */
+ *out_value = 0.0;
+ return TRUE;
+ }
- ul_val = strtoul(str, &end, str[1] == 'x' ? 16 : 10);
- if (*end == '\0' && errno != ERANGE) {
- *out_value = str[0] == '-' ? -(double)-ul_val : (double)ul_val;
- return TRUE;
- }
+ ul_val = strtoul(str, &end, str[1] == 'x' ? 16 : 10);
+ if (*end == '\0' && errno != ERANGE) {
+ *out_value = str[0] == '-' ? -(double)-ul_val : (double)ul_val;
+ return TRUE;
+ }
- if (*end != '\0' && *end != '.' && *end != 'e' && *end != 'E')
- return FALSE; /* skip the expensive strtod call */
- dbl_val = strtod(str, &end);
- if (*end != '\0')
- return FALSE;
+ if (*end != '\0' && *end != '.' && *end != 'e' && *end != 'E')
+ return FALSE; /* skip the expensive strtod call */
+ dbl_val = strtod(str, &end);
+ if (*end != '\0')
+ return FALSE;
- *out_value = dbl_val;
- return TRUE;
+ *out_value = dbl_val;
+ return TRUE;
}
static Boolean
is_separator(char ch)
{
- return ch == '\0' || ch_isspace(ch) || strchr("!=><)", ch) != NULL;
+ return ch == '\0' || ch_isspace(ch) || strchr("!=><)", ch) != NULL;
}
/*-
@@ -389,120 +396,131 @@ static const char *
CondParser_String(CondParser *par, Boolean doEval, Boolean strictLHS,
Boolean *out_quoted, void **out_freeIt)
{
- Buffer buf;
- const char *str;
- Boolean atStart;
- const char *nested_p;
- Boolean quoted;
- const char *start;
- VarEvalFlags eflags;
- VarParseResult parseResult;
-
- Buf_Init(&buf);
- str = NULL;
- *out_freeIt = NULL;
- *out_quoted = quoted = par->p[0] == '"';
- start = par->p;
- if (quoted)
- par->p++;
- while (par->p[0] != '\0' && str == NULL) {
- switch (par->p[0]) {
- case '\\':
- par->p++;
- if (par->p[0] != '\0') {
- Buf_AddByte(&buf, par->p[0]);
+ Buffer buf;
+ const char *str;
+ Boolean atStart;
+ const char *nested_p;
+ Boolean quoted;
+ const char *start;
+ VarEvalFlags eflags;
+ VarParseResult parseResult;
+
+ Buf_Init(&buf);
+ str = NULL;
+ *out_freeIt = NULL;
+ *out_quoted = quoted = par->p[0] == '"';
+ start = par->p;
+ if (quoted)
par->p++;
- }
- continue;
- case '"':
- if (quoted) {
- par->p++; /* skip the closing quote */
- goto got_str;
- }
- Buf_AddByte(&buf, par->p[0]); /* likely? */
- par->p++;
- continue;
- case ')': /* see is_separator */
- case '!':
- case '=':
- case '>':
- case '<':
- case ' ':
- case '\t':
- if (!quoted)
- goto got_str;
- Buf_AddByte(&buf, par->p[0]);
- par->p++;
- continue;
- case '$':
- /* if we are in quotes, an undefined variable is ok */
- eflags = doEval && !quoted ? VARE_WANTRES | VARE_UNDEFERR :
- doEval ? VARE_WANTRES :
- VARE_NONE;
-
- nested_p = par->p;
- atStart = nested_p == start;
- parseResult = Var_Parse(&nested_p, VAR_CMDLINE, eflags, &str,
- out_freeIt);
- /* TODO: handle errors */
- if (str == var_Error) {
- if (parseResult & VPR_ANY_MSG)
- par->printedError = TRUE;
- if (*out_freeIt != NULL) {
- /* XXX: Can there be any situation in which a returned
- * var_Error requires freeIt? */
- free(*out_freeIt);
- *out_freeIt = NULL;
+ while (par->p[0] != '\0' && str == NULL) {
+ switch (par->p[0]) {
+ case '\\':
+ par->p++;
+ if (par->p[0] != '\0') {
+ Buf_AddByte(&buf, par->p[0]);
+ par->p++;
+ }
+ continue;
+ case '"':
+ if (quoted) {
+ par->p++; /* skip the closing quote */
+ goto got_str;
+ }
+ Buf_AddByte(&buf, par->p[0]); /* likely? */
+ par->p++;
+ continue;
+ case ')': /* see is_separator */
+ case '!':
+ case '=':
+ case '>':
+ case '<':
+ case ' ':
+ case '\t':
+ if (!quoted)
+ goto got_str;
+ Buf_AddByte(&buf, par->p[0]);
+ par->p++;
+ continue;
+ case '$':
+ /* if we are in quotes, an undefined variable is ok */
+ eflags =
+ doEval && !quoted ? VARE_WANTRES | VARE_UNDEFERR :
+ doEval ? VARE_WANTRES :
+ VARE_NONE;
+
+ nested_p = par->p;
+ atStart = nested_p == start;
+ parseResult = Var_Parse(&nested_p, VAR_CMDLINE, eflags,
+ &str,
+ out_freeIt);
+ /* TODO: handle errors */
+ if (str == var_Error) {
+ if (parseResult & VPR_ANY_MSG)
+ par->printedError = TRUE;
+ if (*out_freeIt != NULL) {
+ /*
+ * XXX: Can there be any situation
+ * in which a returned var_Error
+ * requires freeIt?
+ */
+ free(*out_freeIt);
+ *out_freeIt = NULL;
+ }
+ /*
+ * Even if !doEval, we still report syntax
+ * errors, which is what getting var_Error
+ * back with !doEval means.
+ */
+ str = NULL;
+ goto cleanup;
+ }
+ par->p = nested_p;
+
+ /*
+ * If the '$' started the string literal (which means
+ * no quotes), and the variable expression is followed
+ * by a space, looks like a comparison operator or is
+ * the end of the expression, we are done.
+ */
+ if (atStart && is_separator(par->p[0]))
+ goto cleanup;
+
+ Buf_AddStr(&buf, str);
+ if (*out_freeIt) {
+ free(*out_freeIt);
+ *out_freeIt = NULL;
+ }
+ str = NULL; /* not finished yet */
+ continue;
+ default:
+ if (strictLHS && !quoted && *start != '$' &&
+ !ch_isdigit(*start)) {
+ /*
+ * The left-hand side must be quoted,
+ * a variable reference or a number.
+ */
+ str = NULL;
+ goto cleanup;
+ }
+ Buf_AddByte(&buf, par->p[0]);
+ par->p++;
+ continue;
}
- /*
- * Even if !doEval, we still report syntax errors, which
- * is what getting var_Error back with !doEval means.
- */
- str = NULL;
- goto cleanup;
- }
- par->p = nested_p;
-
- /*
- * If the '$' started the string literal (which means no quotes),
- * and the variable expression is followed by a space, looks like
- * a comparison operator or is the end of the expression, we are
- * done.
- */
- if (atStart && is_separator(par->p[0]))
- goto cleanup;
-
- Buf_AddStr(&buf, str);
- if (*out_freeIt) {
- free(*out_freeIt);
- *out_freeIt = NULL;
- }
- str = NULL; /* not finished yet */
- continue;
- default:
- if (strictLHS && !quoted && *start != '$' && !ch_isdigit(*start)) {
- /* lhs must be quoted, a variable reference or number */
- str = NULL;
- goto cleanup;
- }
- Buf_AddByte(&buf, par->p[0]);
- par->p++;
- continue;
}
- }
got_str:
- *out_freeIt = Buf_GetAll(&buf, NULL);
- str = *out_freeIt;
+ *out_freeIt = Buf_GetAll(&buf, NULL);
+ str = *out_freeIt;
cleanup:
- Buf_Destroy(&buf, FALSE);
- return str;
+ Buf_Destroy(&buf, FALSE);
+ return str;
}
struct If {
- const char *form; /* Form of if */
- size_t formlen; /* Length of form */
- Boolean doNot; /* TRUE if default function should be negated */
- Boolean (*defProc)(size_t, const char *); /* Default function to apply */
+ 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. */
@@ -514,13 +532,15 @@ static const struct If ifs[] = {
{ "", 0, FALSE, FuncDefined },
{ NULL, 0, FALSE, NULL }
};
-enum { PLAIN_IF_INDEX = 4 };
+enum {
+ PLAIN_IF_INDEX = 4
+};
static Boolean
If_Eval(const struct If *if_info, const char *arg, size_t arglen)
{
- Boolean res = if_info->defProc(arglen, arg);
- return if_info->doNot ? !res : res;
+ Boolean res = if_info->defProc(arglen, arg);
+ return if_info->doNot ? !res : res;
}
/* Evaluate a "comparison without operator", such as in ".if ${VAR}" or
@@ -528,68 +548,69 @@ If_Eval(const struct If *if_info, const
static Boolean
EvalNotEmpty(CondParser *par, const char *value, Boolean quoted)
{
- double num;
+ double num;
- /* For .ifxxx "...", check for non-empty string. */
- if (quoted)
- return value[0] != '\0';
-
- /* For .ifxxx <number>, compare against zero */
- if (TryParseNumber(value, &num))
- return num != 0.0;
-
- /* For .if ${...}, check for non-empty string. This is different from
- * 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')
- return value[0] != '\0';
+ /* For .ifxxx "...", check for non-empty string. */
+ if (quoted)
+ return value[0] != '\0';
+
+ /* For .ifxxx <number>, compare against zero */
+ if (TryParseNumber(value, &num))
+ return num != 0.0;
+
+ /* For .if ${...}, check for non-empty string. This is different from
+ * 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')
+ return value[0] != '\0';
- /* For the other variants of .ifxxx ${...}, use its default function. */
- return If_Eval(par->if_info, value, strlen(value));
+ /* For the other variants of .ifxxx ${...}, use its default function. */
+ return If_Eval(par->if_info, value, strlen(value));
}
/* Evaluate a numerical comparison, such as in ".if ${VAR} >= 9". */
static Token
EvalCompareNum(double lhs, const char *op, double rhs)
{
- DEBUG3(COND, "lhs = %f, rhs = %f, op = %.2s\n", lhs, rhs, op);
+ DEBUG3(COND, "lhs = %f, rhs = %f, op = %.2s\n", lhs, rhs, op);
- switch (op[0]) {
- case '!':
- if (op[1] != '=') {
- Parse_Error(PARSE_WARNING, "Unknown operator");
- /* The PARSE_FATAL is done as a follow-up by CondEvalExpression. */
- return TOK_ERROR;
- }
- return ToToken(lhs != rhs);
- case '=':
- if (op[1] != '=') {
- Parse_Error(PARSE_WARNING, "Unknown operator");
- /* The PARSE_FATAL is done as a follow-up by CondEvalExpression. */
- return TOK_ERROR;
- }
- return ToToken(lhs == rhs);
- case '<':
- return ToToken(op[1] == '=' ? lhs <= rhs : lhs < rhs);
- case '>':
- return ToToken(op[1] == '=' ? lhs >= rhs : lhs > rhs);
- }
- return TOK_ERROR;
+ switch (op[0]) {
+ case '!':
+ if (op[1] != '=') {
+ Parse_Error(PARSE_WARNING, "Unknown operator");
+ /* The PARSE_FATAL follows in CondEvalExpression. */
+ return TOK_ERROR;
+ }
+ return ToToken(lhs != rhs);
+ case '=':
+ if (op[1] != '=') {
+ Parse_Error(PARSE_WARNING, "Unknown operator");
+ /* The PARSE_FATAL follows in CondEvalExpression. */
+ return TOK_ERROR;
+ }
+ return ToToken(lhs == rhs);
+ case '<':
+ return ToToken(op[1] == '=' ? lhs <= rhs : lhs < rhs);
+ case '>':
+ return ToToken(op[1] == '=' ? lhs >= rhs : lhs > rhs);
+ }
+ return TOK_ERROR;
}
static Token
EvalCompareStr(const char *lhs, const char *op, const char *rhs)
{
- if (!((op[0] == '!' || op[0] == '=') && op[1] == '=')) {
- Parse_Error(PARSE_WARNING,
- "String comparison operator must be either == or !=");
- /* The PARSE_FATAL is done as a follow-up by CondEvalExpression. */
- return TOK_ERROR;
- }
+ if (!((op[0] == '!' || op[0] == '=') && op[1] == '=')) {
+ Parse_Error(PARSE_WARNING,
+ "String comparison operator "
+ "must be either == or !=");
+ /* The PARSE_FATAL follows in CondEvalExpression. */
+ return TOK_ERROR;
+ }
- DEBUG3(COND, "lhs = \"%s\", rhs = \"%s\", op = %.2s\n", lhs, rhs, op);
- return ToToken((*op == '=') == (strcmp(lhs, rhs) == 0));
+ DEBUG3(COND, "lhs = \"%s\", rhs = \"%s\", op = %.2s\n", lhs, rhs, op);
+ return ToToken((*op == '=') == (strcmp(lhs, rhs) == 0));
}
/* Evaluate a comparison, such as "${VAR} == 12345". */
@@ -597,13 +618,13 @@ static Token
EvalCompare(const char *lhs, Boolean lhsQuoted, const char *op,
const char *rhs, Boolean rhsQuoted)
{
- double left, right;
+ double left, right;
- if (!rhsQuoted && !lhsQuoted)
- if (TryParseNumber(lhs, &left) && TryParseNumber(rhs, &right))
- return EvalCompareNum(left, op, right);
+ if (!rhsQuoted && !lhsQuoted)
+ if (TryParseNumber(lhs, &left) && TryParseNumber(rhs, &right))
+ return EvalCompareNum(left, op, right);
- return EvalCompareStr(lhs, op, rhs);
+ return EvalCompareStr(lhs, op, rhs);
}
/* Parse a comparison condition such as:
@@ -616,62 +637,64 @@ EvalCompare(const char *lhs, Boolean lhs
static Token
CondParser_Comparison(CondParser *par, Boolean doEval)
{
- Token t = TOK_ERROR;
- const char *lhs, *op, *rhs;
- void *lhs_freeIt, *rhs_freeIt;
- Boolean lhsQuoted, rhsQuoted;
-
- /*
- * Parse the variable spec and skip over it, saving its
- * value in lhs.
- */
- lhs = CondParser_String(par, doEval, lhsStrict, &lhsQuoted, &lhs_freeIt);
- if (lhs == NULL)
- goto done_lhs;
-
- CondParser_SkipWhitespace(par);
-
- op = par->p;
- switch (par->p[0]) {
- case '!':
- case '=':
- case '<':
- case '>':
- if (par->p[1] == '=')
- par->p += 2;
- else
- par->p++;
- break;
- default:
- /* Unknown operator, compare against an empty string or 0. */
- t = ToToken(doEval && EvalNotEmpty(par, lhs, lhsQuoted));
- goto done_lhs;
- }
-
- CondParser_SkipWhitespace(par);
-
- if (par->p[0] == '\0') {
- Parse_Error(PARSE_WARNING, "Missing right-hand-side of operator");
- /* The PARSE_FATAL is done as a follow-up by CondEvalExpression. */
- goto done_lhs;
- }
-
- rhs = CondParser_String(par, doEval, FALSE, &rhsQuoted, &rhs_freeIt);
- if (rhs == NULL)
- goto done_rhs;
-
- if (!doEval) {
- t = TOK_FALSE;
- goto done_rhs;
- }
+ Token t = TOK_ERROR;
+ const char *lhs, *op, *rhs;
+ void *lhs_freeIt, *rhs_freeIt;
+ Boolean lhsQuoted, rhsQuoted;
+
+ /*
+ * Parse the variable spec and skip over it, saving its
+ * value in lhs.
+ */
+ lhs = CondParser_String(par, doEval, lhsStrict, &lhsQuoted,
+ &lhs_freeIt);
+ if (lhs == NULL)
+ goto done_lhs;
+
+ CondParser_SkipWhitespace(par);
+
+ op = par->p;
+ switch (par->p[0]) {
+ case '!':
+ case '=':
+ case '<':
+ case '>':
+ if (par->p[1] == '=')
+ par->p += 2;
+ else
+ par->p++;
+ break;
+ default:
+ /* Unknown operator, compare against an empty string or 0. */
+ t = ToToken(doEval && EvalNotEmpty(par, lhs, lhsQuoted));
+ goto done_lhs;
+ }
+
+ CondParser_SkipWhitespace(par);
+
+ if (par->p[0] == '\0') {
+ Parse_Error(PARSE_WARNING,
+ "Missing right-hand-side of operator");
+ /* The PARSE_FATAL follows in CondEvalExpression. */
+ goto done_lhs;
+ }
+
+ rhs = CondParser_String(par, doEval, FALSE, &rhsQuoted, &rhs_freeIt);
+ if (rhs == NULL)
+ goto done_rhs;
+
+ if (!doEval) {
+ t = TOK_FALSE;
+ goto done_rhs;
+ }
- t = EvalCompare(lhs, lhsQuoted, op, rhs, rhsQuoted);
+ t = EvalCompare(lhs, lhsQuoted, op, rhs, rhsQuoted);
done_rhs:
- free(rhs_freeIt);
+ free(rhs_freeIt);
done_lhs:
- free(lhs_freeIt);
- return t;
+ free(lhs_freeIt);
+ return t;
}
/* The argument to empty() is a variable name, optionally followed by
@@ -680,89 +703,93 @@ static size_t
ParseEmptyArg(const char **pp, Boolean doEval,
const char *func MAKE_ATTR_UNUSED, char **out_arg)
{
- void *val_freeIt;
- const char *val;
- size_t magic_res;
-
- /* We do all the work here and return the result as the length */
- *out_arg = NULL;
-
- (*pp)--; /* Make (*pp)[1] point to the '('. */
- (void)Var_Parse(pp, VAR_CMDLINE, doEval ? VARE_WANTRES : VARE_NONE,
- &val, &val_freeIt);
- /* TODO: handle errors */
- /* If successful, *pp points beyond the closing ')' now. */
-
- if (val == var_Error) {
- free(val_freeIt);
- return (size_t)-1;
- }
+ void *val_freeIt;
+ const char *val;
+ size_t magic_res;
+
+ /* We do all the work here and return the result as the length */
+ *out_arg = NULL;
+
+ (*pp)--; /* Make (*pp)[1] point to the '('. */
+ (void)Var_Parse(pp, VAR_CMDLINE, doEval ? VARE_WANTRES : VARE_NONE,
+ &val, &val_freeIt);
+ /* TODO: handle errors */
+ /* If successful, *pp points beyond the closing ')' now. */
+
+ if (val == var_Error) {
+ free(val_freeIt);
+ return (size_t)-1;
+ }
- /* A variable is empty when it just contains spaces... 4/15/92, christos */
- cpp_skip_whitespace(&val);
+ /*
+ * A variable is empty when it just contains spaces...
+ * 4/15/92, christos
+ */
+ cpp_skip_whitespace(&val);
- /*
- * For consistency with the other functions we can't generate the
- * true/false here.
- */
- magic_res = *val != '\0' ? 2 : 1;
- free(val_freeIt);
- return magic_res;
+ /*
+ * For consistency with the other functions we can't generate the
+ * true/false here.
+ */
+ magic_res = *val != '\0' ? 2 : 1;
+ free(val_freeIt);
+ return magic_res;
}
static Boolean
FuncEmpty(size_t arglen, const char *arg MAKE_ATTR_UNUSED)
{
- /* Magic values ahead, see ParseEmptyArg. */
- return arglen == 1;
+ /* Magic values ahead, see ParseEmptyArg. */
+ return arglen == 1;
}
static Boolean
CondParser_Func(CondParser *par, Boolean doEval, Token *out_token)
{
- static const struct fn_def {
- const char *fn_name;
- size_t fn_name_len;
- size_t (*fn_parse)(const char **, Boolean, const char *, char **);
- Boolean (*fn_eval)(size_t, const char *);
- } fns[] = {
- { "defined", 7, ParseFuncArg, FuncDefined },
- { "make", 4, ParseFuncArg, FuncMake },
- { "exists", 6, ParseFuncArg, FuncExists },
- { "empty", 5, ParseEmptyArg, FuncEmpty },
- { "target", 6, ParseFuncArg, FuncTarget },
- { "commands", 8, ParseFuncArg, FuncCommands }
- };
- const struct fn_def *fn;
- char *arg = NULL;
- size_t arglen;
- const char *cp = par->p;
- const struct fn_def *fns_end = fns + sizeof fns / sizeof fns[0];
-
- for (fn = fns; fn != fns_end; fn++) {
- if (!is_token(cp, fn->fn_name, fn->fn_name_len))
- continue;
-
- cp += fn->fn_name_len;
- cpp_skip_whitespace(&cp);
- if (*cp != '(')
- break;
-
- arglen = fn->fn_parse(&cp, doEval, fn->fn_name, &arg);
- if (arglen == 0 || arglen == (size_t)-1) {
- par->p = cp;
- *out_token = arglen == 0 ? TOK_FALSE : TOK_ERROR;
- return TRUE;
- }
+ static const struct fn_def {
+ const char *fn_name;
+ size_t fn_name_len;
+ size_t (*fn_parse)(const char **, Boolean, const char *,
+ char **);
+ Boolean (*fn_eval)(size_t, const char *);
+ } fns[] = {
+ { "defined", 7, ParseFuncArg, FuncDefined },
+ { "make", 4, ParseFuncArg, FuncMake },
+ { "exists", 6, ParseFuncArg, FuncExists },
+ { "empty", 5, ParseEmptyArg, FuncEmpty },
+ { "target", 6, ParseFuncArg, FuncTarget },
+ { "commands", 8, ParseFuncArg, FuncCommands }
+ };
+ const struct fn_def *fn;
+ char *arg = NULL;
+ size_t arglen;
+ const char *cp = par->p;
+ const struct fn_def *fns_end = fns + sizeof fns / sizeof fns[0];
+
+ for (fn = fns; fn != fns_end; fn++) {
+ if (!is_token(cp, fn->fn_name, fn->fn_name_len))
+ continue;
+
+ cp += fn->fn_name_len;
+ cpp_skip_whitespace(&cp);
+ if (*cp != '(')
+ break;
+
+ arglen = fn->fn_parse(&cp, doEval, fn->fn_name, &arg);
+ if (arglen == 0 || arglen == (size_t)-1) {
+ par->p = cp;
+ *out_token = arglen == 0 ? TOK_FALSE : TOK_ERROR;
+ return TRUE;
+ }
- /* Evaluate the argument using the required function. */
- *out_token = ToToken(!doEval || fn->fn_eval(arglen, arg));
- free(arg);
- par->p = cp;
- return TRUE;
- }
+ /* Evaluate the argument using the required function. */
+ *out_token = ToToken(!doEval || fn->fn_eval(arglen, arg));
+ free(arg);
+ par->p = cp;
+ return TRUE;
+ }
- return FALSE;
+ return FALSE;
}
/* Parse a function call, a number, a variable expression or a string
@@ -770,109 +797,109 @@ CondParser_Func(CondParser *par, Boolean
static Token
CondParser_LeafToken(CondParser *par, Boolean doEval)
{
- Token t;
- char *arg = NULL;
- size_t arglen;
- const char *cp = par->p;
- const char *cp1;
+ Token t;
+ char *arg = NULL;
+ size_t arglen;
+ const char *cp = par->p;
+ const char *cp1;
+
+ if (CondParser_Func(par, doEval, &t))
+ return t;
+
+ /* Push anything numeric through the compare expression */
+ cp = par->p;
+ if (ch_isdigit(cp[0]) || cp[0] == '-' || cp[0] == '+')
+ return CondParser_Comparison(par, doEval);
- if (CondParser_Func(par, doEval, &t))
- return t;
+ /*
+ * Most likely we have a naked token to apply the default function to.
+ * However ".if a == b" gets here when the "a" is unquoted and doesn't
+ * start with a '$'. This surprises people.
+ * If what follows the function argument is a '=' or '!' then the
+ * syntax would be invalid if we did "defined(a)" - so instead treat
+ * as an expression.
+ */
+ arglen = ParseFuncArg(&cp, doEval, NULL, &arg);
+ cp1 = cp;
+ cpp_skip_whitespace(&cp1);
+ if (*cp1 == '=' || *cp1 == '!')
+ return CondParser_Comparison(par, doEval);
+ par->p = cp;
- /* Push anything numeric through the compare expression */
- cp = par->p;
- if (ch_isdigit(cp[0]) || cp[0] == '-' || cp[0] == '+')
- return CondParser_Comparison(par, doEval);
-
- /*
- * Most likely we have a naked token to apply the default function to.
- * However ".if a == b" gets here when the "a" is unquoted and doesn't
- * start with a '$'. This surprises people.
- * If what follows the function argument is a '=' or '!' then the syntax
- * would be invalid if we did "defined(a)" - so instead treat as an
- * expression.
- */
- arglen = ParseFuncArg(&cp, doEval, NULL, &arg);
- cp1 = cp;
- cpp_skip_whitespace(&cp1);
- if (*cp1 == '=' || *cp1 == '!')
- return CondParser_Comparison(par, doEval);
- par->p = cp;
-
- /*
- * Evaluate the argument using the default function.
- * This path always treats .if as .ifdef. To get here, the character
- * 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));
- free(arg);
- return t;
+ /*
+ * Evaluate the argument using the default function.
+ * This path always treats .if as .ifdef. To get here, the character
+ * 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));
+ free(arg);
+ return t;
}
/* Return the next token or comparison result from the parser. */
static Token
CondParser_Token(CondParser *par, Boolean doEval)
{
- Token t;
+ Token t;
- t = par->curr;
- if (t != TOK_NONE) {
- par->curr = TOK_NONE;
- return t;
- }
+ t = par->curr;
+ if (t != TOK_NONE) {
+ par->curr = TOK_NONE;
+ return t;
+ }
+
+ cpp_skip_hspace(&par->p);
+
+ switch (par->p[0]) {
- cpp_skip_hspace(&par->p);
+ case '(':
+ par->p++;
+ return TOK_LPAREN;
+
+ case ')':
+ par->p++;
+ return TOK_RPAREN;
+
+ case '|':
+ par->p++;
+ if (par->p[0] == '|')
+ par->p++;
+ else if (opts.lint) {
+ Parse_Error(PARSE_FATAL, "Unknown operator '|'");
+ par->printedError = TRUE;
+ return TOK_ERROR;
+ }
+ return TOK_OR;
- switch (par->p[0]) {
+ case '&':
+ par->p++;
+ if (par->p[0] == '&')
+ par->p++;
+ else if (opts.lint) {
+ Parse_Error(PARSE_FATAL, "Unknown operator '&'");
+ par->printedError = TRUE;
+ return TOK_ERROR;
+ }
+ return TOK_AND;
- case '(':
- par->p++;
- return TOK_LPAREN;
-
- case ')':
- par->p++;
- return TOK_RPAREN;
-
- case '|':
- par->p++;
- if (par->p[0] == '|')
- par->p++;
- else if (opts.lint) {
- Parse_Error(PARSE_FATAL, "Unknown operator '|'");
- par->printedError = TRUE;
- return TOK_ERROR;
- }
- return TOK_OR;
-
- case '&':
- par->p++;
- if (par->p[0] == '&')
- par->p++;
- else if (opts.lint) {
- Parse_Error(PARSE_FATAL, "Unknown operator '&'");
- par->printedError = TRUE;
- return TOK_ERROR;
- }
- return TOK_AND;
-
- case '!':
- par->p++;
- return TOK_NOT;
-
- case '#': /* XXX: see unit-tests/cond-token-plain.mk */
- case '\n': /* XXX: why should this end the condition? */
- /* Probably obsolete now, from 1993-03-21. */
- case '\0':
- return TOK_EOF;
-
- case '"':
- case '$':
- return CondParser_Comparison(par, doEval);
-
- default:
- return CondParser_LeafToken(par, doEval);
- }
+ case '!':
+ par->p++;
+ return TOK_NOT;
+
+ case '#': /* XXX: see unit-tests/cond-token-plain.mk */
+ case '\n': /* XXX: why should this end the condition? */
+ /* Probably obsolete now, from 1993-03-21. */
+ case '\0':
+ return TOK_EOF;
+
+ case '"':
+ case '$':
+ return CondParser_Comparison(par, doEval);
+
+ default:
+ return CondParser_LeafToken(par, doEval);
+ }
}
/* Parse a single term in the expression. This consists of a terminal symbol
@@ -887,35 +914,35 @@ CondParser_Token(CondParser *par, Boolea
static Token
CondParser_Term(CondParser *par, Boolean doEval)
{
- Token t;
+ Token t;
- t = CondParser_Token(par, doEval);
+ t = CondParser_Token(par, doEval);
- if (t == TOK_EOF) {
- /*
- * If we reached the end of the expression, the expression
- * is malformed...
- */
- t = TOK_ERROR;
- } else if (t == TOK_LPAREN) {
- /*
- * T -> ( E )
- */
- t = CondParser_Expr(par, doEval);
- if (t != TOK_ERROR) {
- if (CondParser_Token(par, doEval) != TOK_RPAREN) {
+ if (t == TOK_EOF) {
+ /*
+ * If we reached the end of the expression, the expression
+ * is malformed...
+ */
t = TOK_ERROR;
- }
- }
- } else if (t == TOK_NOT) {
- t = CondParser_Term(par, doEval);
- if (t == TOK_TRUE) {
- t = TOK_FALSE;
- } else if (t == TOK_FALSE) {
- t = TOK_TRUE;
+ } else if (t == TOK_LPAREN) {
+ /*
+ * T -> ( E )
+ */
+ t = CondParser_Expr(par, doEval);
+ if (t != TOK_ERROR) {
+ if (CondParser_Token(par, doEval) != TOK_RPAREN) {
+ t = TOK_ERROR;
+ }
+ }
+ } else if (t == TOK_NOT) {
+ t = CondParser_Term(par, doEval);
+ if (t == TOK_TRUE) {
+ t = TOK_FALSE;
+ } else if (t == TOK_FALSE) {
+ t = TOK_TRUE;
+ }
}
- }
- return t;
+ return t;
}
/* Parse a conjunctive factor (nice name, wot?)
@@ -928,34 +955,34 @@ CondParser_Term(CondParser *par, Boolean
static Token
CondParser_Factor(CondParser *par, Boolean doEval)
{
- Token l, o;
+ Token l, o;
- l = CondParser_Term(par, doEval);
- if (l != TOK_ERROR) {
- o = CondParser_Token(par, doEval);
-
- if (o == TOK_AND) {
- /*
- * F -> T && F
- *
- * If T is TOK_FALSE, the whole thing will be TOK_FALSE, but we
- * have to parse the r.h.s. anyway (to throw it away).
- * If T is TOK_TRUE, the result is the r.h.s., be it a TOK_ERROR
- * or not.
- */
- if (l == TOK_TRUE) {
- l = CondParser_Factor(par, doEval);
- } else {
- (void)CondParser_Factor(par, FALSE);
- }
- } else {
- /*
- * F -> T
- */
- CondParser_PushBack(par, o);
+ l = CondParser_Term(par, doEval);
+ if (l != TOK_ERROR) {
+ o = CondParser_Token(par, doEval);
+
+ if (o == TOK_AND) {
+ /*
+ * F -> T && F
+ *
+ * If T is TOK_FALSE, the whole thing will be
+ * TOK_FALSE, but we have to parse the r.h.s. anyway
+ * (to throw it away). If T is TOK_TRUE, the result
+ * is the r.h.s., be it a TOK_ERROR or not.
+ */
+ if (l == TOK_TRUE) {
+ l = CondParser_Factor(par, doEval);
+ } else {
+ (void)CondParser_Factor(par, FALSE);
+ }
+ } else {
+ /*
+ * F -> T
+ */
+ CondParser_PushBack(par, o);
+ }
}
- }
- return l;
+ return l;
}
/* Main expression production.
@@ -968,52 +995,54 @@ CondParser_Factor(CondParser *par, Boole
static Token
CondParser_Expr(CondParser *par, Boolean doEval)
{
- Token l, o;
+ Token l, o;
- l = CondParser_Factor(par, doEval);
- if (l != TOK_ERROR) {
- o = CondParser_Token(par, doEval);
-
- if (o == TOK_OR) {
- /*
- * E -> F || E
- *
- * A similar thing occurs for ||, except that here we make sure
- * the l.h.s. is TOK_FALSE before we bother to evaluate the r.h.s.
- * Once again, if l is TOK_FALSE, the result is the r.h.s. and once
- * again if l is TOK_TRUE, we parse the r.h.s. to throw it away.
- */
- if (l == TOK_FALSE) {
- l = CondParser_Expr(par, doEval);
- } else {
- (void)CondParser_Expr(par, FALSE);
- }
- } else {
- /*
- * E -> F
- */
- CondParser_PushBack(par, o);
+ l = CondParser_Factor(par, doEval);
+ if (l != TOK_ERROR) {
+ o = CondParser_Token(par, doEval);
+
+ if (o == TOK_OR) {
+ /*
+ * E -> F || E
+ *
+ * A similar thing occurs for ||, except that here
+ * we make sure the l.h.s. is TOK_FALSE before we
+ * bother to evaluate the r.h.s. Once again, if l
+ * is TOK_FALSE, the result is the r.h.s. and once
+ * again if l is TOK_TRUE, we parse the r.h.s. to
+ * throw it away.
+ */
+ if (l == TOK_FALSE) {
+ l = CondParser_Expr(par, doEval);
+ } else {
+ (void)CondParser_Expr(par, FALSE);
+ }
+ } else {
+ /*
+ * E -> F
+ */
+ CondParser_PushBack(par, o);
+ }
}
- }
- return l;
+ return l;
}
static CondEvalResult
CondParser_Eval(CondParser *par, Boolean *value)
{
- Token res;
+ Token res;
- DEBUG1(COND, "CondParser_Eval: %s\n", par->p);
+ DEBUG1(COND, "CondParser_Eval: %s\n", par->p);
- res = CondParser_Expr(par, TRUE);
- if (res != TOK_FALSE && res != TOK_TRUE)
- return COND_INVALID;
+ res = CondParser_Expr(par, TRUE);
+ if (res != TOK_FALSE && res != TOK_TRUE)
+ return COND_INVALID;
- if (CondParser_Token(par, TRUE /* XXX: Why TRUE? */) != TOK_EOF)
- return COND_INVALID;
+ if (CondParser_Token(par, TRUE /* XXX: Why TRUE? */) != TOK_EOF)
+ return COND_INVALID;
- *value = res == TOK_TRUE;
- return COND_PARSE;
+ *value = res == TOK_TRUE;
+ return COND_PARSE;
}
/* Evaluate the condition, including any side effects from the variable
@@ -1028,26 +1057,26 @@ CondParser_Eval(CondParser *par, Boolean
*/
static CondEvalResult
CondEvalExpression(const struct If *info, const char *cond, Boolean *value,
- Boolean eprint, Boolean strictLHS)
+ Boolean eprint, Boolean strictLHS)
{
- CondParser par;
- CondEvalResult rval;
+ CondParser par;
+ CondEvalResult rval;
- lhsStrict = strictLHS;
+ lhsStrict = strictLHS;
- cpp_skip_hspace(&cond);
+ cpp_skip_hspace(&cond);
- par.if_info = info != NULL ? info : ifs + PLAIN_IF_INDEX;
- par.p = cond;
- par.curr = TOK_NONE;
- par.printedError = FALSE;
+ par.if_info = info != NULL ? info : ifs + PLAIN_IF_INDEX;
+ par.p = cond;
+ par.curr = TOK_NONE;
+ par.printedError = FALSE;
- rval = CondParser_Eval(&par, value);
+ rval = CondParser_Eval(&par, value);
- if (rval == COND_INVALID && eprint && !par.printedError)
- Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", cond);
+ if (rval == COND_INVALID && eprint && !par.printedError)
+ Parse_Error(PARSE_FATAL, "Malformed conditional (%s)", cond);
- return rval;
+ return rval;
}
/* Evaluate a condition in a :? modifier, such as
@@ -1090,192 +1119,208 @@ Cond_EvalCondition(const char *cond, Boo
CondEvalResult
Cond_EvalLine(const char *const line)
{
- typedef enum IfState {
+ typedef enum IfState {
- /* None of the previous <cond> evaluated to TRUE. */
- IFS_INITIAL = 0,
+ /* 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;
-
- static enum IfState *cond_states = NULL;
- static unsigned int cond_states_cap = 128;
-
- const struct If *ifp;
- Boolean isElif;
- Boolean value;
- IfState state;
- const char *p = line;
-
- if (cond_states == NULL) {
- cond_states = bmake_malloc(cond_states_cap * sizeof *cond_states);
- cond_states[0] = IFS_ACTIVE;
- }
-
- p++; /* skip the leading '.' */
- cpp_skip_hspace(&p);
-
- /* Parse the name of the directive, such as 'if', 'elif', 'endif'. */
- 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. */
- return COND_INVALID;
- }
+ /* 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;
- /* It is an '.endif'. */
- /* TODO: check for extraneous <cond> */
+ static enum IfState *cond_states = NULL;
+ static unsigned int cond_states_cap = 128;
- if (cond_depth == cond_min_depth) {
- Parse_Error(PARSE_FATAL, "if-less endif");
- return COND_PARSE;
- }
+ const struct If *ifp;
+ Boolean isElif;
+ Boolean value;
+ IfState state;
+ const char *p = line;
- /* Return state for previous conditional */
- cond_depth--;
- return cond_states[cond_depth] & IFS_ACTIVE
- ? COND_PARSE : COND_SKIP;
+ if (cond_states == NULL) {
+ cond_states = bmake_malloc(
+ cond_states_cap * sizeof *cond_states);
+ cond_states[0] = IFS_ACTIVE;
+ }
+
+ p++; /* skip the leading '.' */
+ cpp_skip_hspace(&p);
+
+ /* Parse the name of the directive, such as 'if', 'elif', 'endif'. */
+ 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.
+ */
+ return COND_INVALID;
+ }
+
+ /* It is an '.endif'. */
+ /* TODO: check for extraneous <cond> */
+
+ if (cond_depth == cond_min_depth) {
+ Parse_Error(PARSE_FATAL, "if-less endif");
+ return COND_PARSE;
+ }
+
+ /* Return state for previous conditional */
+ cond_depth--;
+ return cond_states[cond_depth] & IFS_ACTIVE
+ ? COND_PARSE : COND_SKIP;
+ }
+
+ /* Quite likely this is 'else' or 'elif' */
+ p += 2;
+ if (is_token(p, "se", 2)) { /* It is an 'else'. */
+
+ if (opts.lint && p[2] != '\0')
+ Parse_Error(PARSE_FATAL,
+ "The .else directive "
+ "does not take arguments.");
+
+ if (cond_depth == cond_min_depth) {
+ Parse_Error(PARSE_FATAL, "if-less else");
+ return COND_PARSE;
+ }
+
+ state = cond_states[cond_depth];
+ if (state == IFS_INITIAL) {
+ state = IFS_ACTIVE | IFS_SEEN_ELSE;
+ } else {
+ if (state & IFS_SEEN_ELSE)
+ Parse_Error(PARSE_WARNING,
+ "extra else");
+ state = IFS_WAS_ACTIVE | IFS_SEEN_ELSE;
+ }
+ cond_states[cond_depth] = state;
+
+ return state & IFS_ACTIVE ? COND_PARSE : COND_SKIP;
+ }
+ /* Assume for now it is an elif */
+ isElif = TRUE;
+ } else
+ isElif = FALSE;
+
+ if (p[0] != 'i' || p[1] != 'f') {
+ /*
+ * Unknown directive. It might still be a transformation rule
+ * like '.elisp.scm', therefore no error message here.
+ */
+ return COND_INVALID; /* Not an ifxxx or elifxxx line */
}
- /* Quite likely this is 'else' or 'elif' */
+ /*
+ * Figure out what sort of conditional it is -- what its default
+ * function is, etc. -- by looking in the table of valid "ifs"
+ */
p += 2;
- if (is_token(p, "se", 2)) { /* It is an 'else'. */
+ 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;
+ }
+ }
+
+ /* Now we know what sort of 'if' it is... */
- if (opts.lint && p[2] != '\0')
- Parse_Error(PARSE_FATAL,
- "The .else directive does not take arguments.");
-
- if (cond_depth == cond_min_depth) {
- Parse_Error(PARSE_FATAL, "if-less else");
- return COND_PARSE;
- }
-
- state = cond_states[cond_depth];
- if (state == IFS_INITIAL) {
- state = IFS_ACTIVE | IFS_SEEN_ELSE;
- } else {
- if (state & IFS_SEEN_ELSE)
- Parse_Error(PARSE_WARNING, "extra else");
- state = IFS_WAS_ACTIVE | IFS_SEEN_ELSE;
- }
- cond_states[cond_depth] = state;
-
- return state & IFS_ACTIVE ? COND_PARSE : COND_SKIP;
- }
- /* Assume for now it is an elif */
- isElif = TRUE;
- } else
- isElif = FALSE;
-
- if (p[0] != 'i' || p[1] != 'f') {
- /* Unknown directive. It might still be a transformation rule like
- * '.elisp.scm', therefore no error message here. */
- return COND_INVALID; /* Not an ifxxx or elifxxx line */
- }
-
- /*
- * Figure out what sort of conditional it is -- what its default
- * function is, etc. -- by looking in the table of valid "ifs"
- */
- 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;
- }
- }
-
- /* Now we know what sort of 'if' it is... */
-
- if (isElif) {
- if (cond_depth == cond_min_depth) {
- Parse_Error(PARSE_FATAL, "if-less elif");
- return COND_PARSE;
- }
- state = cond_states[cond_depth];
- if (state & IFS_SEEN_ELSE) {
- Parse_Error(PARSE_WARNING, "extra elif");
- cond_states[cond_depth] = IFS_WAS_ACTIVE | IFS_SEEN_ELSE;
- return COND_SKIP;
- }
- if (state != IFS_INITIAL) {
- cond_states[cond_depth] = IFS_WAS_ACTIVE;
- return COND_SKIP;
- }
- } else {
- /* Normal .if */
- if (cond_depth + 1 >= cond_states_cap) {
- /*
- * This is rare, but not impossible.
- * In meta mode, dirdeps.mk (only runs at level 0)
- * can need more than the default.
- */
- cond_states_cap += 32;
- cond_states = bmake_realloc(cond_states,
- cond_states_cap * sizeof *cond_states);
- }
- state = cond_states[cond_depth];
- cond_depth++;
- if (!(state & IFS_ACTIVE)) {
- /* If we aren't parsing the data, treat as always false */
- cond_states[cond_depth] = IFS_WAS_ACTIVE;
- return COND_SKIP;
- }
- }
-
- /* And evaluate the conditional expression */
- if (CondEvalExpression(ifp, p, &value, 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. */
- cond_states[cond_depth] = IFS_WAS_ACTIVE;
- return COND_SKIP;
- }
-
- if (!value) {
- cond_states[cond_depth] = IFS_INITIAL;
- return COND_SKIP;
- }
- cond_states[cond_depth] = IFS_ACTIVE;
- return COND_PARSE;
+ if (isElif) {
+ if (cond_depth == cond_min_depth) {
+ Parse_Error(PARSE_FATAL, "if-less elif");
+ return COND_PARSE;
+ }
+ state = cond_states[cond_depth];
+ if (state & IFS_SEEN_ELSE) {
+ Parse_Error(PARSE_WARNING, "extra elif");
+ cond_states[cond_depth] =
+ IFS_WAS_ACTIVE | IFS_SEEN_ELSE;
+ return COND_SKIP;
+ }
+ if (state != IFS_INITIAL) {
+ cond_states[cond_depth] = IFS_WAS_ACTIVE;
+ return COND_SKIP;
+ }
+ } else {
+ /* Normal .if */
+ if (cond_depth + 1 >= cond_states_cap) {
+ /*
+ * This is rare, but not impossible.
+ * In meta mode, dirdeps.mk (only runs at level 0)
+ * can need more than the default.
+ */
+ cond_states_cap += 32;
+ cond_states = bmake_realloc(cond_states,
+ cond_states_cap *
+ sizeof *cond_states);
+ }
+ state = cond_states[cond_depth];
+ cond_depth++;
+ if (!(state & IFS_ACTIVE)) {
+ /*
+ * If we aren't parsing the data,
+ * treat as always false.
+ */
+ cond_states[cond_depth] = IFS_WAS_ACTIVE;
+ return COND_SKIP;
+ }
+ }
+
+ /* And evaluate the conditional expression */
+ if (CondEvalExpression(ifp, p, &value, 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. */
+ cond_states[cond_depth] = IFS_WAS_ACTIVE;
+ return COND_SKIP;
+ }
+
+ if (!value) {
+ cond_states[cond_depth] = IFS_INITIAL;
+ return COND_SKIP;
+ }
+ cond_states[cond_depth] = IFS_ACTIVE;
+ return COND_PARSE;
}
void
Cond_restore_depth(unsigned int saved_depth)
{
- unsigned int open_conds = cond_depth - cond_min_depth;
+ unsigned int open_conds = cond_depth - cond_min_depth;
- if (open_conds != 0 || saved_depth > cond_depth) {
- Parse_Error(PARSE_FATAL, "%u open conditional%s", open_conds,
- open_conds == 1 ? "" : "s");
- cond_depth = cond_min_depth;
- }
+ if (open_conds != 0 || saved_depth > cond_depth) {
+ Parse_Error(PARSE_FATAL, "%u open conditional%s",
+ open_conds, open_conds == 1 ? "" : "s");
+ cond_depth = cond_min_depth;
+ }
- cond_min_depth = saved_depth;
+ cond_min_depth = saved_depth;
}
unsigned int
Cond_save_depth(void)
{
- unsigned int depth = cond_min_depth;
+ unsigned int depth = cond_min_depth;
- cond_min_depth = cond_depth;
- return depth;
+ cond_min_depth = cond_depth;
+ return depth;
}