mirror of
https://github.com/mirror/make.git
synced 2025-02-11 04:10:46 +08:00
Introduce $(intcmp ...) for numerical comparison
Numbers can come from $(words ...), automatic variables such as $(MAKELEVEL), from environment variables, or from shell output such as through $(shell expr ...). The $(intcmp ...) function allows conditional evaluation controlled by numerical variables. * NEWS: Announce this feature. * doc/make.texi (Functions for Conditionals): Document 'intcmp'. * src/function.c (func_intcmp): Create the 'intcmp' built-in function. * tests/scripts/functions/intcmp: Test the 'intcmp' built-in function.
This commit is contained in:
parent
d9291d09b8
commit
71eb0a8038
4
NEWS
4
NEWS
@ -50,6 +50,10 @@ https://sv.gnu.org/bugs/index.php?group=make&report_id=111&fix_release_id=109&se
|
|||||||
user-defined function and they will not impact global variable assignments.
|
user-defined function and they will not impact global variable assignments.
|
||||||
Implementation provided by Jouke Witteveen <j.witteveen@gmail.com>
|
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
|
* 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
|
immediately rather than after all makefiles have been read. Note that
|
||||||
although all options are parsed immediately, some special effects won't
|
although all options are parsed immediately, some special effects won't
|
||||||
|
@ -7820,7 +7820,7 @@ the file names to refer to an existing file or directory. Use the
|
|||||||
@section Functions for Conditionals
|
@section Functions for Conditionals
|
||||||
@findex if
|
@findex if
|
||||||
@cindex conditional expansion
|
@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
|
aspect of these functions is that not all of the arguments are
|
||||||
expanded initially. Only those arguments which need to be expanded,
|
expanded initially. Only those arguments which need to be expanded,
|
||||||
will be expanded.
|
will be expanded.
|
||||||
@ -7867,6 +7867,35 @@ empty string the processing stops and the result of the expansion is
|
|||||||
the empty string. If all arguments expand to a non-empty string then
|
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.
|
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
|
@end table
|
||||||
|
|
||||||
@node Let Function, Foreach Function, Conditional Functions, Functions
|
@node Let Function, Foreach Function, Conditional Functions, Functions
|
||||||
@ -12707,6 +12736,13 @@ all expansions result in a non-empty string, substitute the expansion
|
|||||||
of the last @var{condition}.@*
|
of the last @var{condition}.@*
|
||||||
@xref{Conditional Functions, ,Functions for Conditionals}.
|
@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{})
|
@item $(call @var{var},@var{param},@dots{})
|
||||||
Evaluate the variable @var{var} replacing any references to @code{$(1)},
|
Evaluate the variable @var{var} replacing any references to @code{$(1)},
|
||||||
@code{$(2)} with the first, second, etc.@: @var{param} values.@*
|
@code{$(2)} with the first, second, etc.@: @var{param} values.@*
|
||||||
|
@ -1269,6 +1269,66 @@ func_sort (char *o, char **argv, const char *funcname UNUSED)
|
|||||||
return o;
|
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])
|
$(if condition,true-part[,false-part])
|
||||||
|
|
||||||
@ -2435,6 +2495,7 @@ static struct function_table_entry function_table_init[] =
|
|||||||
FT_ENTRY ("info", 0, 1, 1, func_error),
|
FT_ENTRY ("info", 0, 1, 1, func_error),
|
||||||
FT_ENTRY ("error", 0, 1, 1, func_error),
|
FT_ENTRY ("error", 0, 1, 1, func_error),
|
||||||
FT_ENTRY ("warning", 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 ("if", 2, 3, 0, func_if),
|
||||||
FT_ENTRY ("or", 1, 0, 0, func_or),
|
FT_ENTRY ("or", 1, 0, 0, func_or),
|
||||||
FT_ENTRY ("and", 1, 0, 0, func_and),
|
FT_ENTRY ("and", 1, 0, 0, func_and),
|
||||||
|
54
tests/scripts/functions/intcmp
Normal file
54
tests/scripts/functions/intcmp
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# -*-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;
|
Loading…
Reference in New Issue
Block a user