make(1): extract CondParser_StringExpr from CondParser_String

This commit is contained in:
rillig 2021-01-21 14:24:25 +00:00
parent 94db50b820
commit 91b99e6865
1 changed files with 71 additions and 54 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: cond.c,v 1.247 2021/01/21 14:08:09 rillig Exp $ */
/* $NetBSD: cond.c,v 1.248 2021/01/21 14:24:25 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.247 2021/01/21 14:08:09 rillig Exp $");
MAKE_RCSID("$NetBSD: cond.c,v 1.248 2021/01/21 14:24:25 rillig Exp $");
/*
* The parsing of conditional expressions is based on this grammar:
@ -398,6 +398,73 @@ is_separator(char ch)
return ch == '\0' || ch_isspace(ch) || strchr("!=><)", ch) != NULL;
}
/*
* In a quoted or unquoted string literal or a number, parse a variable
* expression.
*
* Example: .if x${CENTER}y == "${PREFIX}${SUFFIX}" || 0x${HEX}
*/
static Boolean
CondParser_StringExpr(CondParser *par, const char *start,
Boolean const doEval, Boolean const quoted,
Buffer *buf, FStr *const inout_str)
{
VarEvalFlags eflags;
const char *nested_p;
Boolean atStart;
VarParseResult parseResult;
/* 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, inout_str);
/* TODO: handle errors */
if (inout_str->str == var_Error) {
if (parseResult == VPR_ERR) {
/*
* FIXME: Even if an error occurs,
* there is no guarantee that it is
* reported.
*
* See cond-token-plain.mk $$$$$$$$.
*/
par->printedError = TRUE;
}
/*
* XXX: Can there be any situation in which
* a returned var_Error requires freeIt?
*/
FStr_Done(inout_str);
/*
* Even if !doEval, we still report syntax
* errors, which is what getting var_Error
* back with !doEval means.
*/
*inout_str = FStr_InitRefer(NULL);
return FALSE;
}
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]))
return FALSE;
Buf_AddStr(buf, inout_str->str);
FStr_Done(inout_str);
*inout_str = FStr_InitRefer(NULL); /* not finished yet */
return TRUE;
}
/*
* Parse a string from a variable reference or an optionally quoted
* string. This is called for the lhs and rhs of string comparisons.
@ -413,12 +480,8 @@ CondParser_String(CondParser *par, Boolean doEval, Boolean strictLHS,
{
Buffer buf;
FStr str;
Boolean atStart;
const char *nested_p;
Boolean quoted;
const char *start;
VarEvalFlags eflags;
VarParseResult parseResult;
Buf_Init(&buf);
str = FStr_InitRefer(NULL);
@ -455,55 +518,9 @@ CondParser_String(CondParser *par, Boolean doEval, Boolean strictLHS,
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);
/* TODO: handle errors */
if (str.str == var_Error) {
if (parseResult == VPR_ERR) {
/*
* FIXME: Even if an error occurs,
* there is no guarantee that it is
* reported.
*
* See cond-token-plain.mk $$$$$$$$.
*/
par->printedError = TRUE;
}
/*
* XXX: Can there be any situation in which
* a returned var_Error requires freeIt?
*/
FStr_Done(&str);
/*
* Even if !doEval, we still report syntax
* errors, which is what getting var_Error
* back with !doEval means.
*/
str = FStr_InitRefer(NULL);
if (!CondParser_StringExpr(par,
start, doEval, quoted, &buf, &str))
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.str);
FStr_Done(&str);
str = FStr_InitRefer(NULL); /* not finished yet */
continue;
default:
if (strictLHS && !quoted && *start != '$' &&