summaryrefslogtreecommitdiff
path: root/function.c
diff options
context:
space:
mode:
authorPaul Smith <psmith@gnu.org>2006-02-10 05:29:00 +0000
committerPaul Smith <psmith@gnu.org>2006-02-10 05:29:00 +0000
commit5a7a42cfce638f52f702b4d317c45c7186b8c0b4 (patch)
treef212e35eac087bedeb88d64d96fb5a4c8c25d08c /function.c
parentd0c4e92f1145110793ffb04596019a864c88d2fc (diff)
downloadgunmake-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.c106
1 files changed, 106 insertions, 0 deletions
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