]> git.ipfire.org Git - thirdparty/make.git/commitdiff
Convert word, wordlist, and intcmp functions to use long long
authorPaul Smith <psmith@gnu.org>
Sun, 28 Nov 2021 14:50:10 +0000 (09:50 -0500)
committerPaul Smith <psmith@gnu.org>
Sun, 28 Nov 2021 19:27:10 +0000 (14:27 -0500)
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.

bootstrap.conf
src/config.ami.template
src/config.h-vms.template
src/config.h.W32.template
src/function.c
src/makeint.h
tests/run_make_tests.pl
tests/scripts/functions/intcmp
tests/scripts/functions/word

index 69058aa0728196bfa427b1d0374b2c46a7e93a9c..13ded359567aaebaf47cfb8e333b8035abb102d3 100644 (file)
@@ -51,5 +51,5 @@ getloadavg
 host-cpu-c-abi
 mempcpy
 strerror
-strtol
+strtoll
 make-glob"
index 0d44fc6469c64e53613dea8f280aec89ec350c07..52d8f51f1c6d49a65d6606bd8aec57177ef237aa 100644 (file)
@@ -261,6 +261,9 @@ this program.  If not, see <http://www.gnu.org/licenses/>.  */
 /* Define if you have the strsignal function.  */
 /* #undef HAVE_STRSIGNAL */
 
+/* Define if you have the strtoll function.  */
+/* #undef HAVE_STRTOLL */
+
 /* Define if you have the wait3 function.  */
 /* #undef HAVE_WAIT3 */
 
index 62daac2d1a369aecd2564d4c126649579ac28f2b..f3f6d30ff00d5b5165b76ace29cab9beb7f04fd3 100644 (file)
@@ -301,6 +301,9 @@ this program.  If not, see <http://www.gnu.org/licenses/>.  */
 /* Define to 1 if you have the strsignal function.  */
 /* #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.  */
 /* #undef HAVE_WAIT3 */
 
index bd3b47630478ace68853a5bb74d8fe2d6f69cee5..3a92b205177c927b2758f0014995d3306e3d1961 100644 (file)
@@ -293,6 +293,9 @@ this program.  If not, see <http://www.gnu.org/licenses/>.  */
 /* Define to 1 if you have the 'strsignal' function. */
 /* #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'. */
 /* SV 57152: MinGW64 version of dirent doesn't support d_type. */
 #ifndef __MINGW64__
index 63fd238c149eb2258853c9979775bf3af661ccb6..75aa1ca675baa0f854e645dfd2863a593c2acf7d 100644 (file)
@@ -765,17 +765,17 @@ strip_whitespace (const char **begpp, const char **endpp)
   return (char *)*begpp;
 }
 
-static long
+static long long
 parse_numeric (const char *s, const char *msg)
 {
   const char *beg = s;
   const char *end = s + strlen (s) - 1;
   char *endp;
-  long num;
+  long long num;
   strip_whitespace (&beg, &end);
 
   errno = 0;
-  num = strtol (beg, &endp, 10);
+  num = strtoll (beg, &endp, 10);
   if (errno == ERANGE)
     OSS (fatal, *expanding_var, "%s: '%s'", strerror (errno), s);
   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 *p;
-  long i;
+  long long i;
 
   i = parse_numeric (argv[0],
                      _("non-numeric first argument to 'word' function"));
-  if (i <= 0)
+  if (i < 1)
     O (fatal, *expanding_var,
        _("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 *
 func_wordlist (char *o, char **argv, const char *funcname UNUSED)
 {
-  long start, stop, count;
+  long long start, stop, count;
 
   start = parse_numeric (argv[0],
                          _("non-numeric first argument to 'wordlist' function"));
@@ -821,7 +821,11 @@ func_wordlist (char *o, char **argv, const char *funcname UNUSED)
 
   if (start < 1)
     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;
 
@@ -1288,7 +1292,7 @@ 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;
+  long long lhs, rhs;
 
   lhs = parse_numeric (lhs_str,
                        _("non-numeric first argument to 'intcmp' function"));
@@ -1304,7 +1308,7 @@ func_intcmp (char *o, char **argv, const char *funcname UNUSED)
       if (lhs == rhs)
         {
           char buf[INTSTR_LENGTH+1];
-          sprintf (buf, "%ld", lhs);
+          sprintf (buf, "%lld", lhs);
           o = variable_buffer_output(o, buf, strlen (buf));
         }
       return o;
index bf9dab7353a4e27316afea7a9ded8e8ddb38138c..9c80535ce5694a881af5420a0bf0abac18262b52 100644 (file)
@@ -482,8 +482,9 @@ extern struct rlimit stack_limit;
 #define CSTRLEN(_s)           (sizeof (_s)-1)
 #define STRING_SIZE_TUPLE(_s) (_s), CSTRLEN(_s)
 
-/* The number of bytes needed to represent the largest integer as a string.  */
-#define INTSTR_LENGTH         CSTRLEN ("18446744073709551616")
+/* The number of bytes needed to represent the largest integer as a string.
+   Large enough for both the largest signed and unsigned long long.  */
+#define INTSTR_LENGTH         CSTRLEN ("18446744073709551615")
 
 #define DEFAULT_TTYNAME "true"
 #ifdef HAVE_TTYNAME
index cc46af1fea800727112c2ed7731a0a76feecf676..ebf202a29c851bfea92ed1c252c2fb9a83e731e2 100644 (file)
@@ -108,6 +108,7 @@ $ERR_read_only_file = undef;
 $ERR_unreadable_file = undef;
 $ERR_nonexe_file = undef;
 $ERR_exe_dir = undef;
+$ERR_out_of_range = undef;
 
 {
   use locale;
@@ -118,6 +119,12 @@ $ERR_exe_dir = undef;
       # Windows has POSIX locale, but only LC_ALL not LC_MESSAGES
       $loc = POSIX::setlocale(&POSIX::LC_ALL);
       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')) {
@@ -457,6 +464,10 @@ sub set_defaults
     $scriptsuffix = '.com';
   } else {
     $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';
   }
 }
 
index 1abb205ffb314ceefcd4b30eafbfb4310e8f1964..eb58ae30b717537887d68e1d8dca06fedc86595c 100644 (file)
@@ -10,6 +10,8 @@ n = -10
 z = 0
 # Positive
 p = 1000000000
+min = -9223372036854775808
+max = 9223372036854775807
 .RECIPEPREFIX = >
 all:
 > @echo 0_1 $(intcmp $n,$n)
@@ -25,7 +27,11 @@ all:
 > @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");
+> @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
 
@@ -46,7 +52,7 @@ run_make_test(undef,
 
 run_make_test(undef,
               'intcmp-e3',
-              "#MAKEFILE#:4: *** Numerical result out of range: '9999999999999999999'.  Stop.",
+              "#MAKEFILE#:4: *** $ERR_out_of_range: '9999999999999999999'.  Stop.",
               512);
 
 
index 044bc947d32f3fb84fc5dfb4e6db864f89474b28..1c87c4a1a501e46bb4b6d134117d194e2697d73e 100644 (file)
@@ -6,43 +6,42 @@ $details = "\
 Produce a variable with a large number of words in it,
 determine the number of words, and then read each one back.\n";
 
-open(MAKEFILE,"> $makefile");
-print MAKEFILE <<'EOF';
+run_make_test('
 string  := word.pl general_test2.pl   FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl
 string2 := $(string) $(string) $(string) $(string) $(string) $(string) $(string)
 string3 := $(string2) $(string2) $(string2) $(string2) $(string2) $(string2) $(string2)
 string4 := $(string3) $(string3) $(string3) $(string3) $(string3) $(string3) $(string3)
+.RECIPEPREFIX = >
 all:
-       @echo $(words $(string))
-       @echo $(words $(string4))
-       @echo $(word 1, $(string))
-       @echo $(word 100, $(string))
-       @echo $(word 1, $(string))
-       @echo $(word 1000, $(string3))
-       @echo $(wordlist 3, 4, $(string))
-       @echo $(wordlist 4, 3, $(string))
-       @echo $(wordlist 1, 6, $(string))
-       @echo $(wordlist 5, 7, $(string))
-       @echo $(wordlist 100, 110, $(string))
-       @echo $(wordlist 7, 10, $(string2))
-EOF
-close(MAKEFILE);
-
-&run_make_with_options($makefile, "", &get_logfile);
-$answer = "6\n"
-         ."2058\n"
-         ."word.pl\n"
-         ."\n"
-         ."word.pl\n"
-         ."\n"
-        ."FORCE.pl word.pl\n"
-        ."\n"
-        ."word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl\n"
-        ."generic_test.perl MAKEFILES_variable.pl\n"
-        ."\n"
-        ."word.pl general_test2.pl FORCE.pl word.pl\n";
-&compare_output($answer, &get_logfile(1));
-
+> @echo $(words $(string))
+> @echo $(words $(string4))
+> @echo $(word 1, $(string))
+> @echo $(word 100, $(string))
+> @echo $(word 1  , $(string))
+> @echo $(word 1000, $(string3))
+> @echo $(word 9223372036854775807, $(string2))
+> @echo $(wordlist 3, 4, $(string))
+> @echo $(wordlist 4, 3, $(string))
+> @echo $(wordlist 1 , 6  , $(string))
+> @echo $(wordlist 5,7, $(string))
+> @echo $(wordlist 100, 110, $(string))
+> @echo $(wordlist 7, 10, $(string2))
+> @echo $(wordlist 9223372036854775807, 0, $(string2))
+', '', "6\n"
+      ."2058\n"
+      ."word.pl\n"
+      ."\n"
+      ."word.pl\n"
+      ."\n"
+      ."\n"
+      ."FORCE.pl word.pl\n"
+      ."\n"
+      ."word.pl general_test2.pl FORCE.pl word.pl generic_test.perl MAKEFILES_variable.pl\n"
+      ."generic_test.perl MAKEFILES_variable.pl\n"
+      ."\n"
+      ."word.pl general_test2.pl FORCE.pl word.pl\n"
+      ."\n"
+);
 
 # Test error conditions
 
@@ -72,7 +71,7 @@ run_make_test(undef,
 
 run_make_test(undef,
               'word-e4',
-              "#MAKEFILE#:6: *** Numerical result out of range: '9999999999999999999'.  Stop.",
+              "#MAKEFILE#:6: *** $ERR_out_of_range: '9999999999999999999'.  Stop.",
               512);
 
 run_make_test(undef,
@@ -133,6 +132,11 @@ run_make_test(undef,
               "#MAKEFILE#:4: *** invalid first argument to 'wordlist' function: '0'.  Stop.",
               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 )
 #
@@ -145,8 +149,7 @@ b := $(firstword $(list))
 
 .PHONY: all
 
-all:
-       @test "$a" = "$b" && echo $a
+all: ; @test "$a" = "$b" && echo $a
 ',
 '',
 'foo');
@@ -163,8 +166,7 @@ b := $(lastword $(list))
 
 .PHONY: all
 
-all:
-       @test "$a" = "$b" && echo $a
+all: ; @test "$a" = "$b" && echo $a
 ',
 '',
 'baz');