version 1.232, 2020/12/27 10:53:23 |
version 1.233, 2020/12/30 10:03:16 |
|
|
* SUCH DAMAGE. |
* SUCH DAMAGE. |
*/ |
*/ |
|
|
/* Handling of conditionals in a makefile. |
/* |
|
* Handling of conditionals in a makefile. |
* |
* |
* Interface: |
* Interface: |
* Cond_EvalLine Evaluate the conditional directive, such as |
* Cond_EvalLine Evaluate the conditional directive, such as |
Line 198 CondParser_SkipWhitespace(CondParser *pa |
|
Line 199 CondParser_SkipWhitespace(CondParser *pa |
|
cpp_skip_whitespace(&par->p); |
cpp_skip_whitespace(&par->p); |
} |
} |
|
|
/* Parse the argument of a built-in function. |
/* |
|
* Parse the argument of a built-in function. |
* |
* |
* Arguments: |
* Arguments: |
* *pp initially points at the '(', |
* *pp initially points at the '(', |
Line 209 CondParser_SkipWhitespace(CondParser *pa |
|
Line 211 CondParser_SkipWhitespace(CondParser *pa |
|
* func says whether the argument belongs to an actual function, or |
* func says whether the argument belongs to an actual function, or |
* whether the parsed argument is passed to the default function. |
* whether the parsed argument is passed to the default function. |
* |
* |
* Return the length of the argument, or 0 on error. */ |
* Return the length of the argument, or 0 on error. |
|
*/ |
static size_t |
static size_t |
ParseFuncArg(const char **pp, Boolean doEval, const char *func, |
ParseFuncArg(const char **pp, Boolean doEval, const char *func, |
char **out_arg) |
char **out_arg) |
Line 327 FuncTarget(size_t argLen MAKE_ATTR_UNUSE |
|
Line 330 FuncTarget(size_t argLen MAKE_ATTR_UNUSE |
|
return gn != NULL && GNode_IsTarget(gn); |
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 exists and is an actual target with commands |
|
* associated with it. |
|
*/ |
static Boolean |
static Boolean |
FuncCommands(size_t argLen MAKE_ATTR_UNUSED, const char *arg) |
FuncCommands(size_t argLen MAKE_ATTR_UNUSED, const char *arg) |
{ |
{ |
Line 532 If_Eval(const struct If *if_info, const |
|
Line 537 If_Eval(const struct If *if_info, const |
|
return if_info->doNot ? !res : res; |
return if_info->doNot ? !res : res; |
} |
} |
|
|
/* Evaluate a "comparison without operator", such as in ".if ${VAR}" or |
/* |
* ".if 0". */ |
* Evaluate a "comparison without operator", such as in ".if ${VAR}" or |
|
* ".if 0". |
|
*/ |
static Boolean |
static Boolean |
EvalNotEmpty(CondParser *par, const char *value, Boolean quoted) |
EvalNotEmpty(CondParser *par, const char *value, Boolean quoted) |
{ |
{ |
Line 616 EvalCompare(const char *lhs, Boolean lhs |
|
Line 623 EvalCompare(const char *lhs, Boolean lhs |
|
return EvalCompareStr(lhs, op, rhs); |
return EvalCompareStr(lhs, op, rhs); |
} |
} |
|
|
/* Parse a comparison condition such as: |
/* |
|
* Parse a comparison condition such as: |
* |
* |
* 0 |
* 0 |
* ${VAR:Mpattern} |
* ${VAR:Mpattern} |
|
|
return t; |
return t; |
} |
} |
|
|
/* The argument to empty() is a variable name, optionally followed by |
/* |
* variable modifiers. */ |
* The argument to empty() is a variable name, optionally followed by |
|
* variable modifiers. |
|
*/ |
static size_t |
static size_t |
ParseEmptyArg(const char **pp, Boolean doEval, |
ParseEmptyArg(const char **pp, Boolean doEval, |
const char *func MAKE_ATTR_UNUSED, char **out_arg) |
const char *func MAKE_ATTR_UNUSED, char **out_arg) |
Line 779 CondParser_Func(CondParser *par, Boolean |
|
Line 789 CondParser_Func(CondParser *par, Boolean |
|
return FALSE; |
return FALSE; |
} |
} |
|
|
/* Parse a function call, a number, a variable expression or a string |
/* |
* literal. */ |
* Parse a function call, a number, a variable expression or a string |
|
* literal. |
|
*/ |
static Token |
static Token |
CondParser_LeafToken(CondParser *par, Boolean doEval) |
CondParser_LeafToken(CondParser *par, Boolean doEval) |
{ |
{ |
Line 889 CondParser_Token(CondParser *par, Boolea |
|
Line 901 CondParser_Token(CondParser *par, Boolea |
|
} |
} |
} |
} |
|
|
/* Parse a single term in the expression. This consists of a terminal symbol |
/* |
|
* Parse a single term in the expression. This consists of a terminal symbol |
* or TOK_NOT and a term (not including the binary operators): |
* or TOK_NOT and a term (not including the binary operators): |
* |
* |
* T -> defined(variable) | make(target) | exists(file) | symbol |
* T -> defined(variable) | make(target) | exists(file) | symbol |
Line 932 CondParser_Term(CondParser *par, Boolean |
|
Line 945 CondParser_Term(CondParser *par, Boolean |
|
return t; |
return t; |
} |
} |
|
|
/* Parse a conjunctive factor (nice name, wot?) |
/* |
|
* Parse a conjunctive factor (nice name, wot?) |
* |
* |
* F -> T && F | T |
* F -> T && F | T |
* |
* |
Line 972 CondParser_Factor(CondParser *par, Boole |
|
Line 986 CondParser_Factor(CondParser *par, Boole |
|
return l; |
return l; |
} |
} |
|
|
/* Main expression production. |
/* |
|
* Main expression production. |
* |
* |
* E -> F || E | F |
* E -> F || E | F |
* |
* |
Line 1032 CondParser_Eval(CondParser *par, Boolean |
|
Line 1047 CondParser_Eval(CondParser *par, Boolean |
|
return COND_PARSE; |
return COND_PARSE; |
} |
} |
|
|
/* Evaluate the condition, including any side effects from the variable |
/* |
|
* Evaluate the condition, including any side effects from the variable |
* expressions in the condition. The condition consists of &&, ||, !, |
* expressions in the condition. The condition consists of &&, ||, !, |
* function(arg), comparisons and parenthetical groupings thereof. |
* function(arg), comparisons and parenthetical groupings thereof. |
* |
* |
Line 1066 CondEvalExpression(const struct If *info |
|
Line 1082 CondEvalExpression(const struct If *info |
|
return rval; |
return rval; |
} |
} |
|
|
/* Evaluate a condition in a :? modifier, such as |
/* |
* ${"${VAR}" == value:?yes:no}. */ |
* Evaluate a condition in a :? modifier, such as |
|
* ${"${VAR}" == value:?yes:no}. |
|
*/ |
CondEvalResult |
CondEvalResult |
Cond_EvalCondition(const char *cond, Boolean *out_value) |
Cond_EvalCondition(const char *cond, Boolean *out_value) |
{ |
{ |
Line 1081 IsEndif(const char *p) |
|
Line 1099 IsEndif(const char *p) |
|
p[3] == 'i' && p[4] == 'f' && !ch_isalpha(p[5]); |
p[3] == 'i' && p[4] == 'f' && !ch_isalpha(p[5]); |
} |
} |
|
|
/* Evaluate the conditional directive in the line, which is one of: |
/* |
|
* Evaluate the conditional directive in the line, which is one of: |
* |
* |
* .if <cond> |
* .if <cond> |
* .ifmake <cond> |
* .ifmake <cond> |