mirror of
https://github.com/mirror/make.git
synced 2026-08-31 03:38:03 +08:00
- New code capability: a read-only string cache. Start of solution for
Savannah bug #15182, but not much uses it yet. Coming shortly. - Added short-circuiting $(and ..) and $(or ...) functions.
This commit is contained in:
106
function.c
106
function.c
@@ -1230,6 +1230,110 @@ func_if (char *o, char **argv, const char *funcname UNUSED)
|
||||
return o;
|
||||
}
|
||||
|
||||
/*
|
||||
$(or condition1[,condition2[,condition3[...]]])
|
||||
|
||||
A CONDITION is false iff it evaluates to an empty string. White
|
||||
space before and after CONDITION are stripped before evaluation.
|
||||
|
||||
CONDITION1 is evaluated. If it's true, then this is the result of
|
||||
expansion. If it's false, CONDITION2 is evaluated, and so on. If none of
|
||||
the conditions are true, the expansion is the empty string.
|
||||
|
||||
Once a CONDITION is true no further conditions are evaluated
|
||||
(short-circuiting).
|
||||
*/
|
||||
|
||||
static char *
|
||||
func_or (char *o, char **argv, const char *funcname UNUSED)
|
||||
{
|
||||
for ( ; *argv ; ++argv)
|
||||
{
|
||||
const char *begp = *argv;
|
||||
const char *endp = begp + strlen (*argv) - 1;
|
||||
char *expansion;
|
||||
int result = 0;
|
||||
|
||||
/* Find the result of the condition: if it's false keep going. */
|
||||
|
||||
strip_whitespace (&begp, &endp);
|
||||
|
||||
if (begp > endp)
|
||||
continue;
|
||||
|
||||
expansion = expand_argument (begp, endp+1);
|
||||
result = strlen (expansion);
|
||||
|
||||
/* If the result is false keep going. */
|
||||
if (!result)
|
||||
{
|
||||
free (expansion);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* It's true! Keep this result and return. */
|
||||
o = variable_buffer_output (o, expansion, result);
|
||||
free (expansion);
|
||||
break;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
/*
|
||||
$(and condition1[,condition2[,condition3[...]]])
|
||||
|
||||
A CONDITION is false iff it evaluates to an empty string. White
|
||||
space before and after CONDITION are stripped before evaluation.
|
||||
|
||||
CONDITION1 is evaluated. If it's false, then this is the result of
|
||||
expansion. If it's true, CONDITION2 is evaluated, and so on. If all of
|
||||
the conditions are true, the expansion is the result of the last condition.
|
||||
|
||||
Once a CONDITION is false no further conditions are evaluated
|
||||
(short-circuiting).
|
||||
*/
|
||||
|
||||
static char *
|
||||
func_and (char *o, char **argv, const char *funcname UNUSED)
|
||||
{
|
||||
char *expansion;
|
||||
int result;
|
||||
|
||||
while (1)
|
||||
{
|
||||
const char *begp = *argv;
|
||||
const char *endp = begp + strlen (*argv) - 1;
|
||||
|
||||
/* An empty condition is always false. */
|
||||
strip_whitespace (&begp, &endp);
|
||||
if (begp > endp)
|
||||
return o;
|
||||
|
||||
expansion = expand_argument (begp, endp+1);
|
||||
result = strlen (expansion);
|
||||
|
||||
/* If the result is false, stop here: we're done. */
|
||||
if (!result)
|
||||
break;
|
||||
|
||||
/* Otherwise the result is true. If this is the last one, keep this
|
||||
result and quit. Otherwise go on to the next one! */
|
||||
|
||||
if (*(++argv))
|
||||
free (expansion);
|
||||
else
|
||||
{
|
||||
o = variable_buffer_output (o, expansion, result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free (expansion);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
static char *
|
||||
func_wildcard (char *o, char **argv, const char *funcname UNUSED)
|
||||
{
|
||||
@@ -1977,6 +2081,8 @@ static struct function_table_entry function_table_init[] =
|
||||
{ STRING_SIZE_TUPLE("error"), 0, 1, 1, func_error},
|
||||
{ STRING_SIZE_TUPLE("warning"), 0, 1, 1, func_error},
|
||||
{ STRING_SIZE_TUPLE("if"), 2, 3, 0, func_if},
|
||||
{ STRING_SIZE_TUPLE("or"), 1, 0, 0, func_or},
|
||||
{ STRING_SIZE_TUPLE("and"), 1, 0, 0, func_and},
|
||||
{ STRING_SIZE_TUPLE("value"), 0, 1, 1, func_value},
|
||||
{ STRING_SIZE_TUPLE("eval"), 0, 1, 1, func_eval},
|
||||
#ifdef EXPERIMENTAL
|
||||
|
||||
Reference in New Issue
Block a user