diff options
author | Paul Smith <psmith@gnu.org> | 2006-02-10 05:29:00 +0000 |
---|---|---|
committer | Paul Smith <psmith@gnu.org> | 2006-02-10 05:29:00 +0000 |
commit | 5a7a42cfce638f52f702b4d317c45c7186b8c0b4 (patch) | |
tree | f212e35eac087bedeb88d64d96fb5a4c8c25d08c /function.c | |
parent | d0c4e92f1145110793ffb04596019a864c88d2fc (diff) | |
download | gunmake-5a7a42cfce638f52f702b4d317c45c7186b8c0b4.tar.gz |
- 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.
Diffstat (limited to 'function.c')
-rw-r--r-- | function.c | 106 |
1 files changed, 106 insertions, 0 deletions
@@ -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 |