aboutsummaryrefslogtreecommitdiff
path: root/contrib/bmake/cond.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bmake/cond.c')
-rw-r--r--contrib/bmake/cond.c89
1 files changed, 47 insertions, 42 deletions
diff --git a/contrib/bmake/cond.c b/contrib/bmake/cond.c
index f83163cbb50e..b3613bbadf5d 100644
--- a/contrib/bmake/cond.c
+++ b/contrib/bmake/cond.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cond.c,v 1.373 2025/04/22 19:28:50 rillig Exp $ */
+/* $NetBSD: cond.c,v 1.378 2025/07/06 07:56:16 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -77,9 +77,8 @@
* '.if <cond>', '.elifnmake <cond>', '.else', '.endif'.
*
* Cond_EvalCondition
- * Evaluate the conditional, which is either the argument
- * of one of the .if directives or the condition in a
- * ':?then:else' variable modifier.
+ * Evaluate a condition, either from one of the .if
+ * directives, or from a ':?then:else' modifier.
*
* Cond_EndFile At the end of reading a makefile, ensure that the
* conditional directives are well-balanced.
@@ -91,14 +90,14 @@
#include "dir.h"
/* "@(#)cond.c 8.2 (Berkeley) 1/2/94" */
-MAKE_RCSID("$NetBSD: cond.c,v 1.373 2025/04/22 19:28:50 rillig Exp $");
+MAKE_RCSID("$NetBSD: cond.c,v 1.378 2025/07/06 07:56:16 rillig Exp $");
/*
* Conditional expressions conform to this grammar:
* Or -> And ('||' And)*
* And -> Term ('&&' Term)*
* Term -> Function '(' Argument ')'
- * Term -> Leaf Operator Leaf
+ * Term -> Leaf ComparisonOp Leaf
* Term -> Leaf
* Term -> '(' Or ')'
* Term -> '!' Term
@@ -106,7 +105,7 @@ MAKE_RCSID("$NetBSD: cond.c,v 1.373 2025/04/22 19:28:50 rillig Exp $");
* Leaf -> Number
* Leaf -> VariableExpression
* Leaf -> BareWord
- * Operator -> '==' | '!=' | '>' | '<' | '>=' | '<='
+ * ComparisonOp -> '==' | '!=' | '>' | '<' | '>=' | '<='
*
* BareWord is an unquoted string literal, its evaluation depends on the kind
* of '.if' directive.
@@ -156,12 +155,12 @@ typedef struct CondParser {
* been an expression or a plain word.
*
* In conditional directives like '.if', the left-hand side must
- * either be an expression, a quoted string or a number.
+ * either be a defined expression, a quoted string or a number.
*/
bool leftUnquotedOK;
const char *p; /* The remaining condition to parse */
- Token curr; /* Single push-back token used in parsing */
+ Token curr; /* The push-back token, or TOK_NONE */
} CondParser;
static CondResult CondParser_Or(CondParser *, bool);
@@ -255,7 +254,7 @@ ParseFuncArg(const char **pp, bool doEval, const char *func)
len++;
Parse_Error(PARSE_FATAL,
- "Missing ')' after argument '%.*s' for '%.*s'",
+ "Missing \")\" after argument \"%.*s\" for \"%.*s\"",
(int)(argEnd - argStart), argStart, len, func);
free(res);
return NULL;
@@ -284,7 +283,8 @@ FuncMake(const char *targetPattern)
if (res.error != NULL && !warned) {
warned = true;
Parse_Error(PARSE_WARNING,
- "%s in pattern argument '%s' to function 'make'",
+ "%s in pattern argument \"%s\" "
+ "to function \"make\"",
res.error, targetPattern);
}
if (res.matched)
@@ -301,14 +301,16 @@ FuncExists(const char *file)
char *path;
path = Dir_FindFile(file, &dirSearchPath);
- DEBUG2(COND, "exists(%s) result is \"%s\"\n",
- file, path != NULL ? path : "");
result = path != NULL;
+ if (result)
+ DEBUG2(COND, "\"%s\" exists in \"%s\"\n", file, path);
+ else
+ DEBUG1(COND, "\"%s\" does not exist\n", file);
free(path);
return result;
}
-/* See if the given node exists and is an actual target. */
+/* See if the given node is an actual target. */
static bool
FuncTarget(const char *node)
{
@@ -316,10 +318,7 @@ FuncTarget(const char *node)
return gn != NULL && GNode_IsTarget(gn);
}
-/*
- * See if the given node exists and is an actual target with commands
- * associated with it.
- */
+/* See if the given node is an actual target with commands. */
static bool
FuncCommands(const char *node)
{
@@ -374,38 +373,37 @@ is_separator(char ch)
*
* Return whether to continue parsing the leaf.
*
- * Example: .if x${CENTER}y == "${PREFIX}${SUFFIX}" || 0x${HEX}
+ * Examples: .if x${CENTER}y == "${PREFIX}${SUFFIX}" || 0x${HEX}
*/
static bool
CondParser_StringExpr(CondParser *par, const char *start,
bool doEval, bool quoted,
- Buffer *buf, FStr *inout_str)
+ Buffer *buf, FStr *out_str)
{
VarEvalMode emode;
const char *p;
- bool atStart; /* true means an expression outside quotes */
+ bool outsideQuotes;
emode = doEval && quoted ? VARE_EVAL
: doEval ? VARE_EVAL_DEFINED_LOUD
: VARE_PARSE;
p = par->p;
- atStart = p == start;
- *inout_str = Var_Parse(&p, SCOPE_CMDLINE, emode);
- /* TODO: handle errors */
- if (inout_str->str == var_Error) {
- FStr_Done(inout_str);
- *inout_str = FStr_InitRefer(NULL);
+ outsideQuotes = p == start;
+ *out_str = Var_Parse(&p, SCOPE_CMDLINE, emode);
+ if (out_str->str == var_Error) {
+ FStr_Done(out_str);
+ *out_str = FStr_InitRefer(NULL);
return false;
}
par->p = p;
- if (atStart && is_separator(par->p[0]))
+ if (outsideQuotes && is_separator(par->p[0]))
return false;
- Buf_AddStr(buf, inout_str->str);
- FStr_Done(inout_str);
- *inout_str = FStr_InitRefer(NULL); /* not finished yet */
+ Buf_AddStr(buf, out_str->str);
+ FStr_Done(out_str);
+ *out_str = FStr_InitRefer(NULL); /* not finished yet */
return true;
}
@@ -414,7 +412,7 @@ CondParser_StringExpr(CondParser *par, const char *start,
* on the left-hand and right-hand sides of comparisons.
*
* Return the string without any enclosing quotes, or NULL on error.
- * Sets out_quoted if the leaf was a quoted string literal.
+ * Set out_quoted if the leaf was a quoted string literal.
*/
static FStr
CondParser_Leaf(CondParser *par, bool doEval, bool unquotedOK,
@@ -439,12 +437,14 @@ CondParser_Leaf(CondParser *par, bool doEval, bool unquotedOK,
if (par->p[0] != '\0') {
Buf_AddByte(&buf, par->p[0]);
par->p++;
- }
+ } else
+ Parse_Error(PARSE_FATAL,
+ "Unfinished backslash escape sequence");
continue;
case '"':
par->p++;
if (quoted)
- goto return_buf; /* skip the closing quote */
+ goto return_buf;
Buf_AddByte(&buf, '"');
continue;
case ')': /* see is_separator */
@@ -475,6 +475,9 @@ CondParser_Leaf(CondParser *par, bool doEval, bool unquotedOK,
continue;
}
}
+ if (quoted)
+ Parse_Error(PARSE_FATAL,
+ "Unfinished string literal \"%s\"", start);
return_buf:
str = FStr_InitOwn(buf.data);
buf.data = NULL;
@@ -528,8 +531,8 @@ EvalCompareStr(const char *lhs, ComparisonOp op, const char *rhs)
{
if (op != EQ && op != NE) {
Parse_Error(PARSE_FATAL,
- "Comparison with '%s' requires both operands "
- "'%s' and '%s' to be numeric",
+ "Comparison with \"%s\" requires both operands "
+ "\"%s\" and \"%s\" to be numeric",
opname[op], lhs, rhs);
return TOK_ERROR;
}
@@ -603,7 +606,7 @@ CondParser_Comparison(CondParser *par, bool doEval)
if (par->p[0] == '\0') {
Parse_Error(PARSE_FATAL,
- "Missing right-hand side of operator '%s'", opname[op]);
+ "Missing right-hand side of operator \"%s\"", opname[op]);
goto done_lhs;
}
@@ -768,7 +771,7 @@ CondParser_Token(CondParser *par, bool doEval)
if (par->p[0] == '|')
par->p++;
else {
- Parse_Error(PARSE_FATAL, "Unknown operator '|'");
+ Parse_Error(PARSE_FATAL, "Unknown operator \"|\"");
return TOK_ERROR;
}
return TOK_OR;
@@ -778,7 +781,7 @@ CondParser_Token(CondParser *par, bool doEval)
if (par->p[0] == '&')
par->p++;
else {
- Parse_Error(PARSE_FATAL, "Unknown operator '&'");
+ Parse_Error(PARSE_FATAL, "Unknown operator \"&\"");
return TOK_ERROR;
}
return TOK_AND;
@@ -825,7 +828,7 @@ CondParser_Skip(CondParser *par, Token t)
/*
* Term -> '(' Or ')'
* Term -> '!' Term
- * Term -> Leaf Operator Leaf
+ * Term -> Leaf ComparisonOp Leaf
* Term -> Leaf
*/
static CondResult
@@ -923,8 +926,10 @@ CondEvalExpression(const char *cond, bool plain,
if (par.curr != TOK_EOF)
rval = CR_ERROR;
- if (rval == CR_ERROR && eprint && parseErrors == parseErrorsBefore)
- Parse_Error(PARSE_FATAL, "Malformed conditional '%s'", cond);
+ if (parseErrors != parseErrorsBefore)
+ rval = CR_ERROR;
+ else if (rval == CR_ERROR && eprint)
+ Parse_Error(PARSE_FATAL, "Malformed conditional \"%s\"", cond);
return rval;
}