mirror of
https://github.com/mirror/make.git
synced 2025-03-27 20:40:35 +08:00
Convert word, wordlist, and intcmp functions to use long long
Modify make functions that parse integer values to use long long values instead of long: on Windows long is the same as int (4 bytes) and we don't want behavior to differ between different platforms. * bootstrap.conf: Change strtol module to strtoll module. * src/function.c (parse_numeric): Use strtoll() and return long long. (func_word): Use long long. (func_wordlist): Use long long. Verify second argument is >= 0. (func_intcmp): Use long long. * src/config.ami.template: Don't define HAVE_STRTOLL. * src/config-vms.template: Define HAVE_STRTOLL. * src/config.W32.template: Define HAVE_STRTOLL. * tests/run_make_tests.pl: Set $ERR_out_of_range to the proper string. * tests/scripts/functions/word: Rework to use the new style and avoid TAB characters. Verify trailing whitespace is ignored. Add a test for a negative second argument to wordlist. Add tests for max signed integer values. Use $ERR_out_of_range for the error string. * tests/scripts/functions/intcmp: Add tests for min and max signed integer values. Use $ERR_out_of_range for the error string.
This commit is contained in:
parent
71eb0a8038
commit
116767901f
@ -51,5 +51,5 @@ getloadavg
|
|||||||
host-cpu-c-abi
|
host-cpu-c-abi
|
||||||
mempcpy
|
mempcpy
|
||||||
strerror
|
strerror
|
||||||
strtol
|
strtoll
|
||||||
make-glob"
|
make-glob"
|
||||||
|
@ -261,6 +261,9 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||||||
/* Define if you have the strsignal function. */
|
/* Define if you have the strsignal function. */
|
||||||
/* #undef HAVE_STRSIGNAL */
|
/* #undef HAVE_STRSIGNAL */
|
||||||
|
|
||||||
|
/* Define if you have the strtoll function. */
|
||||||
|
/* #undef HAVE_STRTOLL */
|
||||||
|
|
||||||
/* Define if you have the wait3 function. */
|
/* Define if you have the wait3 function. */
|
||||||
/* #undef HAVE_WAIT3 */
|
/* #undef HAVE_WAIT3 */
|
||||||
|
|
||||||
|
@ -301,6 +301,9 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||||||
/* Define to 1 if you have the strsignal function. */
|
/* Define to 1 if you have the strsignal function. */
|
||||||
/* #undef HAVE_STRSIGNAL */
|
/* #undef HAVE_STRSIGNAL */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strtoll' function. */
|
||||||
|
#define HAVE_STRTOLL 1
|
||||||
|
|
||||||
/* Define to 1 if you have the wait3 function. */
|
/* Define to 1 if you have the wait3 function. */
|
||||||
/* #undef HAVE_WAIT3 */
|
/* #undef HAVE_WAIT3 */
|
||||||
|
|
||||||
|
@ -293,6 +293,9 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||||||
/* Define to 1 if you have the 'strsignal' function. */
|
/* Define to 1 if you have the 'strsignal' function. */
|
||||||
/* #undef HAVE_STRSIGNAL */
|
/* #undef HAVE_STRSIGNAL */
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `strtoll' function. */
|
||||||
|
#define HAVE_STRTOLL 1
|
||||||
|
|
||||||
/* Define to 1 if `d_type' is a member of `struct dirent'. */
|
/* Define to 1 if `d_type' is a member of `struct dirent'. */
|
||||||
/* SV 57152: MinGW64 version of dirent doesn't support d_type. */
|
/* SV 57152: MinGW64 version of dirent doesn't support d_type. */
|
||||||
#ifndef __MINGW64__
|
#ifndef __MINGW64__
|
||||||
|
@ -765,17 +765,17 @@ strip_whitespace (const char **begpp, const char **endpp)
|
|||||||
return (char *)*begpp;
|
return (char *)*begpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long
|
static long long
|
||||||
parse_numeric (const char *s, const char *msg)
|
parse_numeric (const char *s, const char *msg)
|
||||||
{
|
{
|
||||||
const char *beg = s;
|
const char *beg = s;
|
||||||
const char *end = s + strlen (s) - 1;
|
const char *end = s + strlen (s) - 1;
|
||||||
char *endp;
|
char *endp;
|
||||||
long num;
|
long long num;
|
||||||
strip_whitespace (&beg, &end);
|
strip_whitespace (&beg, &end);
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
num = strtol (beg, &endp, 10);
|
num = strtoll (beg, &endp, 10);
|
||||||
if (errno == ERANGE)
|
if (errno == ERANGE)
|
||||||
OSS (fatal, *expanding_var, "%s: '%s'", strerror (errno), s);
|
OSS (fatal, *expanding_var, "%s: '%s'", strerror (errno), s);
|
||||||
else if (endp == beg || endp <= end)
|
else if (endp == beg || endp <= end)
|
||||||
@ -790,11 +790,11 @@ func_word (char *o, char **argv, const char *funcname UNUSED)
|
|||||||
{
|
{
|
||||||
const char *end_p;
|
const char *end_p;
|
||||||
const char *p;
|
const char *p;
|
||||||
long i;
|
long long i;
|
||||||
|
|
||||||
i = parse_numeric (argv[0],
|
i = parse_numeric (argv[0],
|
||||||
_("non-numeric first argument to 'word' function"));
|
_("non-numeric first argument to 'word' function"));
|
||||||
if (i <= 0)
|
if (i < 1)
|
||||||
O (fatal, *expanding_var,
|
O (fatal, *expanding_var,
|
||||||
_("first argument to 'word' function must be greater than 0"));
|
_("first argument to 'word' function must be greater than 0"));
|
||||||
|
|
||||||
@ -812,7 +812,7 @@ func_word (char *o, char **argv, const char *funcname UNUSED)
|
|||||||
static char *
|
static char *
|
||||||
func_wordlist (char *o, char **argv, const char *funcname UNUSED)
|
func_wordlist (char *o, char **argv, const char *funcname UNUSED)
|
||||||
{
|
{
|
||||||
long start, stop, count;
|
long long start, stop, count;
|
||||||
|
|
||||||
start = parse_numeric (argv[0],
|
start = parse_numeric (argv[0],
|
||||||
_("non-numeric first argument to 'wordlist' function"));
|
_("non-numeric first argument to 'wordlist' function"));
|
||||||
@ -821,7 +821,11 @@ func_wordlist (char *o, char **argv, const char *funcname UNUSED)
|
|||||||
|
|
||||||
if (start < 1)
|
if (start < 1)
|
||||||
ON (fatal, *expanding_var,
|
ON (fatal, *expanding_var,
|
||||||
"invalid first argument to 'wordlist' function: '%ld'", start);
|
"invalid first argument to 'wordlist' function: '%lld'", start);
|
||||||
|
|
||||||
|
if (stop < 0)
|
||||||
|
ON (fatal, *expanding_var,
|
||||||
|
"invalid second argument to 'wordlist' function: '%lld'", stop);
|
||||||
|
|
||||||
count = stop - start + 1;
|
count = stop - start + 1;
|
||||||
|
|
||||||
@ -1288,7 +1292,7 @@ func_intcmp (char *o, char **argv, const char *funcname UNUSED)
|
|||||||
{
|
{
|
||||||
char *lhs_str = expand_argument (argv[0], NULL);
|
char *lhs_str = expand_argument (argv[0], NULL);
|
||||||
char *rhs_str = expand_argument (argv[1], NULL);
|
char *rhs_str = expand_argument (argv[1], NULL);
|
||||||
long lhs, rhs;
|
long long lhs, rhs;
|
||||||
|
|
||||||
lhs = parse_numeric (lhs_str,
|
lhs = parse_numeric (lhs_str,
|
||||||
_("non-numeric first argument to 'intcmp' function"));
|
_("non-numeric first argument to 'intcmp' function"));
|
||||||
@ -1304,7 +1308,7 @@ func_intcmp (char *o, char **argv, const char *funcname UNUSED)
|
|||||||
if (lhs == rhs)
|
if (lhs == rhs)
|
||||||
{
|
{
|
||||||
char buf[INTSTR_LENGTH+1];
|
char buf[INTSTR_LENGTH+1];
|
||||||
sprintf (buf, "%ld", lhs);
|
sprintf (buf, "%lld", lhs);
|
||||||
o = variable_buffer_output(o, buf, strlen (buf));
|
o = variable_buffer_output(o, buf, strlen (buf));
|
||||||
}
|
}
|
||||||
return o;
|
return o;
|
||||||
|
@ -482,8 +482,9 @@ extern struct rlimit stack_limit;
|
|||||||
#define CSTRLEN(_s) (sizeof (_s)-1)
|
#define CSTRLEN(_s) (sizeof (_s)-1)
|
||||||
#define STRING_SIZE_TUPLE(_s) (_s), CSTRLEN(_s)
|
#define STRING_SIZE_TUPLE(_s) (_s), CSTRLEN(_s)
|
||||||
|
|
||||||
/* The number of bytes needed to represent the largest integer as a string. */
|
/* The number of bytes needed to represent the largest integer as a string.
|
||||||
#define INTSTR_LENGTH CSTRLEN ("18446744073709551616")
|
Large enough for both the largest signed and unsigned long long. */
|
||||||
|
#define INTSTR_LENGTH CSTRLEN ("18446744073709551615")
|
||||||
|
|
||||||
#define DEFAULT_TTYNAME "true"
|
#define DEFAULT_TTYNAME "true"
|
||||||
#ifdef HAVE_TTYNAME
|
#ifdef HAVE_TTYNAME
|
||||||
|
@ -108,6 +108,7 @@ $ERR_read_only_file = undef;
|
|||||||
$ERR_unreadable_file = undef;
|
$ERR_unreadable_file = undef;
|
||||||
$ERR_nonexe_file = undef;
|
$ERR_nonexe_file = undef;
|
||||||
$ERR_exe_dir = undef;
|
$ERR_exe_dir = undef;
|
||||||
|
$ERR_out_of_range = undef;
|
||||||
|
|
||||||
{
|
{
|
||||||
use locale;
|
use locale;
|
||||||
@ -118,6 +119,12 @@ $ERR_exe_dir = undef;
|
|||||||
# Windows has POSIX locale, but only LC_ALL not LC_MESSAGES
|
# Windows has POSIX locale, but only LC_ALL not LC_MESSAGES
|
||||||
$loc = POSIX::setlocale(&POSIX::LC_ALL);
|
$loc = POSIX::setlocale(&POSIX::LC_ALL);
|
||||||
POSIX::setlocale(&POSIX::LC_ALL, 'C');
|
POSIX::setlocale(&POSIX::LC_ALL, 'C');
|
||||||
|
|
||||||
|
# See set_defaults() as this doesn't work right on Windows :(
|
||||||
|
$! = &POSIX::ERANGE;
|
||||||
|
$ERR_out_of_range = "$!";
|
||||||
|
} else {
|
||||||
|
$ERR_out_of_range = 'Numerical result out of range';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (open(my $F, '<', 'file.none')) {
|
if (open(my $F, '<', 'file.none')) {
|
||||||
@ -457,6 +464,10 @@ sub set_defaults
|
|||||||
$scriptsuffix = '.com';
|
$scriptsuffix = '.com';
|
||||||
} else {
|
} else {
|
||||||
$scriptsuffix = '.bat';
|
$scriptsuffix = '.bat';
|
||||||
|
|
||||||
|
# Frustratingly, Perl reports the wrong strerror string for ERANGE.
|
||||||
|
# It's weird because Python gets it right. Not sure what's going on.
|
||||||
|
$ERR_out_of_range = 'Result too large';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,8 @@ n = -10
|
|||||||
z = 0
|
z = 0
|
||||||
# Positive
|
# Positive
|
||||||
p = 1000000000
|
p = 1000000000
|
||||||
|
min = -9223372036854775808
|
||||||
|
max = 9223372036854775807
|
||||||
.RECIPEPREFIX = >
|
.RECIPEPREFIX = >
|
||||||
all:
|
all:
|
||||||
> @echo 0_1 $(intcmp $n,$n)
|
> @echo 0_1 $(intcmp $n,$n)
|
||||||
@ -25,7 +27,11 @@ all:
|
|||||||
> @echo 3_1 $(intcmp $z,$p,lt,eq,gt)
|
> @echo 3_1 $(intcmp $z,$p,lt,eq,gt)
|
||||||
> @echo 3_2 $(intcmp $p,$z,lt,eq,gt)
|
> @echo 3_2 $(intcmp $p,$z,lt,eq,gt)
|
||||||
> @echo 3_3 $(intcmp $p,$p,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");
|
> @echo 4_0 $(intcmp $(min),$(max),lt,eq,gt)
|
||||||
|
> @echo 4_1 $(intcmp $(max),$(min),lt,eq,gt)
|
||||||
|
> @echo 4_2 $(intcmp $(min),$(min),lt,eq,gt)
|
||||||
|
> @echo 4_3 $(intcmp $(max),$(max),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\n4_0 lt\n4_1 gt\n4_2 eq\n4_3 eq\n");
|
||||||
|
|
||||||
# Test error conditions
|
# Test error conditions
|
||||||
|
|
||||||
@ -46,7 +52,7 @@ run_make_test(undef,
|
|||||||
|
|
||||||
run_make_test(undef,
|
run_make_test(undef,
|
||||||
'intcmp-e3',
|
'intcmp-e3',
|
||||||
"#MAKEFILE#:4: *** Numerical result out of range: '9999999999999999999'. Stop.",
|
"#MAKEFILE#:4: *** $ERR_out_of_range: '9999999999999999999'. Stop.",
|
||||||
512);
|
512);
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,43 +6,42 @@ $details = "\
|
|||||||
Produce a variable with a large number of words in it,
|
Produce a variable with a large number of words in it,
|
||||||
determine the number of words, and then read each one back.\n";
|
determine the number of words, and then read each one back.\n";
|
||||||
|
|
||||||
open(MAKEFILE,"> $makefile");
|
run_make_test('
|
||||||
print MAKEFILE <<'EOF';
|
|
||||||
string := word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl
|
string := word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl
|
||||||
string2 := $(string) $(string) $(string) $(string) $(string) $(string) $(string)
|
string2 := $(string) $(string) $(string) $(string) $(string) $(string) $(string)
|
||||||
string3 := $(string2) $(string2) $(string2) $(string2) $(string2) $(string2) $(string2)
|
string3 := $(string2) $(string2) $(string2) $(string2) $(string2) $(string2) $(string2)
|
||||||
string4 := $(string3) $(string3) $(string3) $(string3) $(string3) $(string3) $(string3)
|
string4 := $(string3) $(string3) $(string3) $(string3) $(string3) $(string3) $(string3)
|
||||||
|
.RECIPEPREFIX = >
|
||||||
all:
|
all:
|
||||||
@echo $(words $(string))
|
> @echo $(words $(string))
|
||||||
@echo $(words $(string4))
|
> @echo $(words $(string4))
|
||||||
@echo $(word 1, $(string))
|
> @echo $(word 1, $(string))
|
||||||
@echo $(word 100, $(string))
|
> @echo $(word 100, $(string))
|
||||||
@echo $(word 1, $(string))
|
> @echo $(word 1 , $(string))
|
||||||
@echo $(word 1000, $(string3))
|
> @echo $(word 1000, $(string3))
|
||||||
@echo $(wordlist 3, 4, $(string))
|
> @echo $(word 9223372036854775807, $(string2))
|
||||||
@echo $(wordlist 4, 3, $(string))
|
> @echo $(wordlist 3, 4, $(string))
|
||||||
@echo $(wordlist 1, 6, $(string))
|
> @echo $(wordlist 4, 3, $(string))
|
||||||
@echo $(wordlist 5, 7, $(string))
|
> @echo $(wordlist 1 , 6 , $(string))
|
||||||
@echo $(wordlist 100, 110, $(string))
|
> @echo $(wordlist 5,7, $(string))
|
||||||
@echo $(wordlist 7, 10, $(string2))
|
> @echo $(wordlist 100, 110, $(string))
|
||||||
EOF
|
> @echo $(wordlist 7, 10, $(string2))
|
||||||
close(MAKEFILE);
|
> @echo $(wordlist 9223372036854775807, 0, $(string2))
|
||||||
|
', '', "6\n"
|
||||||
&run_make_with_options($makefile, "", &get_logfile);
|
."2058\n"
|
||||||
$answer = "6\n"
|
."word.pl\n"
|
||||||
."2058\n"
|
."\n"
|
||||||
."word.pl\n"
|
."word.pl\n"
|
||||||
."\n"
|
."\n"
|
||||||
."word.pl\n"
|
."\n"
|
||||||
."\n"
|
."FORCE.pl word.pl\n"
|
||||||
."FORCE.pl word.pl\n"
|
."\n"
|
||||||
."\n"
|
."word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl\n"
|
||||||
."word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl\n"
|
."generic_test.perl MAKEFILES_variable.pl\n"
|
||||||
."generic_test.perl MAKEFILES_variable.pl\n"
|
."\n"
|
||||||
."\n"
|
."word.pl general_test2.pl FORCE.pl word.pl\n"
|
||||||
."word.pl general_test2.pl FORCE.pl word.pl\n";
|
."\n"
|
||||||
&compare_output($answer, &get_logfile(1));
|
);
|
||||||
|
|
||||||
|
|
||||||
# Test error conditions
|
# Test error conditions
|
||||||
|
|
||||||
@ -72,7 +71,7 @@ run_make_test(undef,
|
|||||||
|
|
||||||
run_make_test(undef,
|
run_make_test(undef,
|
||||||
'word-e4',
|
'word-e4',
|
||||||
"#MAKEFILE#:6: *** Numerical result out of range: '9999999999999999999'. Stop.",
|
"#MAKEFILE#:6: *** $ERR_out_of_range: '9999999999999999999'. Stop.",
|
||||||
512);
|
512);
|
||||||
|
|
||||||
run_make_test(undef,
|
run_make_test(undef,
|
||||||
@ -133,6 +132,11 @@ run_make_test(undef,
|
|||||||
"#MAKEFILE#:4: *** invalid first argument to 'wordlist' function: '0'. Stop.",
|
"#MAKEFILE#:4: *** invalid first argument to 'wordlist' function: '0'. Stop.",
|
||||||
512);
|
512);
|
||||||
|
|
||||||
|
run_make_test(undef,
|
||||||
|
'wordlist-e s=1 e=-1',
|
||||||
|
"#MAKEFILE#:4: *** invalid second argument to 'wordlist' function: '-1'. Stop.",
|
||||||
|
512);
|
||||||
|
|
||||||
|
|
||||||
# TEST #8 -- test $(firstword )
|
# TEST #8 -- test $(firstword )
|
||||||
#
|
#
|
||||||
@ -145,8 +149,7 @@ b := $(firstword $(list))
|
|||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
||||||
all:
|
all: ; @test "$a" = "$b" && echo $a
|
||||||
@test "$a" = "$b" && echo $a
|
|
||||||
',
|
',
|
||||||
'',
|
'',
|
||||||
'foo');
|
'foo');
|
||||||
@ -163,8 +166,7 @@ b := $(lastword $(list))
|
|||||||
|
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
|
|
||||||
all:
|
all: ; @test "$a" = "$b" && echo $a
|
||||||
@test "$a" = "$b" && echo $a
|
|
||||||
',
|
',
|
||||||
'',
|
'',
|
||||||
'baz');
|
'baz');
|
||||||
|
Loading…
Reference in New Issue
Block a user