From 5a7a42cfce638f52f702b4d317c45c7186b8c0b4 Mon Sep 17 00:00:00 2001 From: Paul Smith Date: Fri, 10 Feb 2006 05:29:00 +0000 Subject: - 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. --- function.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) (limited to 'function.c') diff --git a/function.c b/function.c index 95872f0..62f67f0 100644 --- a/function.c +++ b/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 -- cgit v1.2.3