user-defined function and they will not impact global variable assignments.
Implementation provided by Jouke Witteveen <j.witteveen@gmail.com>
+* New feature: The $(intcmp ...) function
+ This function allows conditional evaluation controlled by a numerical
+ comparison.
+
* If the MAKEFLAGS variable is modified in a makefile, it will be re-parsed
immediately rather than after all makefiles have been read. Note that
although all options are parsed immediately, some special effects won't
@section Functions for Conditionals
@findex if
@cindex conditional expansion
-There are three functions that provide conditional expansion. A key
+There are four functions that provide conditional expansion. A key
aspect of these functions is that not all of the arguments are
expanded initially. Only those arguments which need to be expanded,
will be expanded.
the empty string. If all arguments expand to a non-empty string then
the result of the expansion is the expansion of the last argument.
+@item $(intcmp @var{lhs},@var{rhs}[,@var{lt-part}[,@var{eq-part}[,@var{gt-part}]]])
+@findex intcmp
+The @code{intcmp} function provides support for numerical comparison of
+integers. This function has no counterpart among the GNU @code{make} makefile
+conditionals.
+
+The left-hand side, @var{lhs}, and right-hand side, @var{rhs}, are expanded
+and parsed as integral numbers in base 10. Expansion of the remaining
+arguments is controlled by how the numerical left-hand side compares to the
+numerical right-hand side.
+
+If there are no further arguments, then the function expands to empty if the
+left-hand side and right-hand side do not compare equal, or to their numerical
+value if they do compare equal.
+
+Else if the left-hand side is strictly less than the right-hand side, the
+@code{intcmp} function evaluates to the expansion of the third argument,
+@var{lt-part}. If both sides compare equal, then the @code{intcmp} function
+evaluates to the expansion of the fourth argument, @var{eq-part}. If the
+left-hand side is strictly greater than the right-hand side, then the
+@code{intcmp} function evaluates to the expansion of the fifth argument,
+@var{gt-part}.
+
+If @var{gt-part} is missing, it defaults to @var{eq-part}. If @var{eq-part}
+is missing, it defaults to the empty string. Thus both @samp{$(intcmp
+9,7,hello)} and @samp{$(intcmp 9,7,hello,world,)} evaluate to the empty
+string, while @samp{$(intcmp 9,7,hello,world)} (notice the absence of a comma
+after @code{world}) evaluates to @samp{world}.
+
@end table
@node Let Function, Foreach Function, Conditional Functions, Functions
of the last @var{condition}.@*
@xref{Conditional Functions, ,Functions for Conditionals}.
+@item $(intcmp @var{lhs},@var{rhs}[,@var{lt-part}[,@var{eq-part}[,@var{gt-part}]]])
+Compare @var{lhs} and @var{rhs} numerically; substitute the expansion of
+@var{lt-part}, @var{eq-part}, or @var{gt-part} depending on whether the
+left-hand side is less-than, equal-to, or greater-than the right-hand
+side, respectively.@*
+@xref{Conditional Functions, ,Functions for Conditionals}.
+
@item $(call @var{var},@var{param},@dots{})
Evaluate the variable @var{var} replacing any references to @code{$(1)},
@code{$(2)} with the first, second, etc.@: @var{param} values.@*
return o;
}
+/*
+ $(intcmp lhs,rhs[,lt-part[,eq-part[,gt-part]]])
+
+ LHS and RHS must be integer values (leading/trailing whitespace is ignored).
+ If none of LT-PART, EQ-PART, or GT-PART are given then the function expands
+ to empty if LHS and RHS are not equal, or the numeric value if they are equal.
+ LT-PART is evaluated when LHS is strictly less than RHS, EQ-PART is evaluated
+ when LHS is equal to RHS, and GT-part is evaluated when LHS is strictly
+ greater than RHS.
+ If GT-PART is not provided, it defaults to EQ-PART. When neither EQ-PART
+ nor GT-PART are provided, the function expands to empty if LHS is not
+ strictly less than RHS.
+*/
+
+static char *
+func_intcmp (char *o, char **argv, const char *funcname UNUSED)
+{
+ char *lhs_str = expand_argument (argv[0], NULL);
+ char *rhs_str = expand_argument (argv[1], NULL);
+ long lhs, rhs;
+
+ lhs = parse_numeric (lhs_str,
+ _("non-numeric first argument to 'intcmp' function"));
+ rhs = parse_numeric (rhs_str,
+ _("non-numeric second argument to 'intcmp' function"));
+ free (lhs_str);
+ free (rhs_str);
+
+ argv += 2;
+
+ if (*argv == NULL)
+ {
+ if (lhs == rhs)
+ {
+ char buf[INTSTR_LENGTH+1];
+ sprintf (buf, "%ld", lhs);
+ o = variable_buffer_output(o, buf, strlen (buf));
+ }
+ return o;
+ }
+
+ if (lhs >= rhs)
+ {
+ ++argv;
+ if (lhs > rhs && *argv && *(argv + 1))
+ ++argv;
+ }
+
+ if (*argv)
+ {
+ char *expansion = expand_argument (*argv, NULL);
+
+ o = variable_buffer_output (o, expansion, strlen (expansion));
+
+ free (expansion);
+ }
+
+ return o;
+}
+
/*
$(if condition,true-part[,false-part])
FT_ENTRY ("info", 0, 1, 1, func_error),
FT_ENTRY ("error", 0, 1, 1, func_error),
FT_ENTRY ("warning", 0, 1, 1, func_error),
+ FT_ENTRY ("intcmp", 2, 5, 0, func_intcmp),
FT_ENTRY ("if", 2, 3, 0, func_if),
FT_ENTRY ("or", 1, 0, 0, func_or),
FT_ENTRY ("and", 1, 0, 0, func_and),
--- /dev/null
+# -*-perl-*-
+$description = "Test the intcmp function.\n";
+
+$details = "Try various uses of intcmp and ensure they all give the correct
+results.\n";
+
+run_make_test('# Negative
+n = -10
+# Zero
+z = 0
+# Positive
+p = 1000000000
+.RECIPEPREFIX = >
+all:
+> @echo 0_1 $(intcmp $n,$n)
+> @echo 0_2 $(intcmp $n,$z)
+> @echo 0_3 $(intcmp $z,$n)
+> @echo 1_1 $(intcmp $n,$n,$(shell echo lt))
+> @echo 1_2 $(intcmp $n,$z,$(shell echo lt))
+> @echo 1_3 $(intcmp $z,$n,$(shell echo lt))
+> @echo 2_1 $(intcmp $n,$p,lt,ge)
+> @echo 2_2 $(intcmp $z,$z,lt,ge)
+> @echo 2_3 $(intcmp $p,$n,lt,ge)
+> @echo 3_0 $(intcmp $p,$n,lt,eq,)
+> @echo 3_1 $(intcmp $z,$p,lt,eq,gt)
+> @echo 3_2 $(intcmp $p,$z,lt,eq,gt)
+> @echo 3_3 $(intcmp $p,$p,lt,eq,gt)
+', '', "0_1 -10\n0_2\n0_3\n1_1\n1_2 lt\n1_3\n2_1 lt\n2_2 ge\n2_3 ge\n3_0\n3_1 lt\n3_2 gt\n3_3 eq\n");
+
+# Test error conditions
+
+run_make_test('
+intcmp-e1: ; @echo $(intcmp 12a,1,foo)
+intcmp-e2: ; @echo $(intcmp 0,,foo)
+intcmp-e3: ; @echo $(intcmp -1,9999999999999999999,foo)
+intcmp-e4: ; @echo $(intcmp -1)
+intcmp-e5: ; @echo $(intcmp ,55)',
+ 'intcmp-e1',
+ "#MAKEFILE#:2: *** non-numeric first argument to 'intcmp' function: '12a'. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'intcmp-e2',
+ "#MAKEFILE#:3: *** non-numeric second argument to 'intcmp' function: ''. Stop.",
+ 512);
+
+run_make_test(undef,
+ 'intcmp-e3',
+ "#MAKEFILE#:4: *** Numerical result out of range: '9999999999999999999'. Stop.",
+ 512);
+
+
+# This tells the test driver that the perl test script executed properly.
+1;