strtoq, strtou(q|ll|l) testing (was [PATCH] faster and 64 bit preserving arithmetic)
Nicholas Clark [Thu, 14 Dec 2000 18:38:57 +0000 (18:38 +0000)]
Message-ID: <20001214183857.B97909@plum.flirble.org>

p4raw-id: //depot/perl@8120

17 files changed:
Configure
Porting/Glossary
Porting/config.sh
Porting/config_H
config_h.SH
configure.com
epoc/config.sh
perl.h
sv.c
uconfig.h
vos/config.alpha.def
vos/config.alpha.h
vos/config.ga.def
vos/config.ga.h
win32/config.bc
win32/config.gc
win32/config.vc

index 18e64b6..95a6283 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -20,7 +20,7 @@
 
 # $Id: Head.U,v 3.0.1.9 1997/02/28 15:02:09 ram Exp $
 #
-# Generated on Wed Dec 13 17:45:13 EET 2000 [metaconfig 3.0 PL70]
+# Generated on Fri Dec 15 04:41:40 EET 2000 [metaconfig 3.0 PL70]
 # (with additional metaconfig patches by perlbug@perl.org)
 
 cat >c1$$ <<EOF
@@ -562,6 +562,7 @@ d_strtod=''
 d_strtol=''
 d_strtold=''
 d_strtoll=''
+d_strtoq=''
 d_strtoul=''
 d_strtoull=''
 d_strtouq=''
@@ -11927,10 +11928,83 @@ EOM
        ;;
 esac
 
+: see if strtoq exists
+set strtoq d_strtoq
+eval $inlibc
+
 : see if strtoul exists
 set strtoul d_strtoul
 eval $inlibc
 
+case "$d_strtoul" in
+"$define")
+       $cat <<EOM
+Checking whether your strtoul() works okay...
+EOM
+       $cat >try.c <<'EOCP'
+#include <errno.h>
+#include <stdio.h>
+extern unsigned long int strtoul(char *s, char **, int); 
+static int bad = 0;
+void check(char *s, unsigned long eul, int een) {
+       unsigned long gul;
+       errno = 0;
+       gul = strtoul(s, 0, 10);
+       if (!((gul == eul) && (errno == een)))
+               bad++;
+}
+int main() {
+       check(" 1", 1L, 0);
+       check(" 0", 0L, 0);
+EOCP
+       case "$longsize" in
+       8)
+           $cat >>try.c <<'EOCP'
+       check("18446744073709551615", 18446744073709551615ULL, 0);
+       check("18446744073709551616", 18446744073709551615ULL, ERANGE);
+       check("-1", 18446744073709551615ULL, 0);
+       check("-18446744073709551614", 2, 0);
+       check("-18446744073709551615", 1, 0);
+               check("-18446744073709551616", 18446744073709551615ULL, ERANGE);
+       check("-18446744073709551617", 18446744073709551615ULL, ERANGE);
+EOCP
+               ;;
+       4)
+                   $cat >>try.c <<'EOCP'
+       check("4294967295", 4294967295UL, 0);
+       check("4294967296", 4294967295UL, ERANGE);
+       check("-1", 4294967295UL, 0);
+       check("-4294967294", 2, 0);
+       check("-4294967295", 1, 0);
+               check("-4294967296", 4294967295UL, ERANGE);
+       check("-4294967297", 4294967295UL, ERANGE);
+EOCP
+               ;;
+       *)
+: Should we write these tests to be more portable by sprintf-ing
+: ~0 and then manipulating that char string as input for strtol?
+               ;;
+       esac
+       $cat >>try.c <<'EOCP'
+       if (!bad)
+               printf("ok\n");
+       return 0;
+}
+EOCP
+       set try
+       if eval $compile; then
+               case "`./try`" in
+               ok) echo "Your strtoul() seems to be working okay." ;;
+               *) cat <<EOM >&4
+Your strtoul() doesn't seem to be working okay.
+EOM
+                  d_strtoul="$undef"
+                  ;;
+               esac
+       fi
+       ;;
+esac
+
 : see if strtoull exists
 set strtoull d_strtoull
 eval $inlibc
@@ -11956,10 +12030,15 @@ int check(char *s, long long eull, int een) {
                bad++;
 }
 int main() {
-       check(" 1",                                       1LL, 0);
-       check(" 0",                                       0LL, 0);
-       check("18446744073709551615", 18446744073709551615ULL, 0);
-       check("18446744073709551616", 18446744073709551615ULL, ERANGE);
+       check(" 1",                                        1LL, 0);
+       check(" 0",                                        0LL, 0);
+       check("18446744073709551615",  18446744073709551615ULL, 0);
+       check("18446744073709551616",  18446744073709551615ULL, ERANGE);
+       check("-1",                    18446744073709551615ULL, 0);
+       check("-18446744073709551614",                     2LL, 0);
+       check("-18446744073709551615",                     1LL, 0);
+               check("-18446744073709551616", 18446744073709551615ULL, ERANGE);
+       check("-18446744073709551617", 18446744073709551615ULL, ERANGE);
        if (!bad)
                printf("ok\n");
 }
@@ -11982,6 +12061,52 @@ esac
 set strtouq d_strtouq
 eval $inlibc
 
+case "$d_strtouq" in
+"$define")
+       $cat <<EOM
+Checking whether your strtouq() works okay...
+EOM
+       $cat >try.c <<'EOCP'
+#include <errno.h>
+#include <stdio.h>
+extern unsigned long long int strtouq(char *s, char **, int); 
+static int bad = 0;
+void check(char *s, unsigned long long eull, int een) {
+       unsigned long long gull;
+       errno = 0;
+       gull = strtouq(s, 0, 10);
+       if (!((gull == eull) && (errno == een)))
+               bad++;
+}
+int main() {
+       check(" 1",                                        1LL, 0);
+       check(" 0",                                        0LL, 0);
+       check("18446744073709551615",  18446744073709551615ULL, 0);
+       check("18446744073709551616",  18446744073709551615ULL, ERANGE);
+       check("-1",                    18446744073709551615ULL, 0);
+       check("-18446744073709551614",                     2LL, 0);
+       check("-18446744073709551615",                     1LL, 0);
+               check("-18446744073709551616", 18446744073709551615ULL, ERANGE);
+       check("-18446744073709551617", 18446744073709551615ULL, ERANGE);
+       if (!bad)
+               printf("ok\n");
+       return 0;
+}
+EOCP
+       set try
+       if eval $compile; then
+               case "`./try`" in
+               ok) echo "Your strtouq() seems to be working okay." ;;
+               *) cat <<EOM >&4
+Your strtouq() doesn't seem to be working okay.
+EOM
+                  d_strtouq="$undef"
+                  ;;
+               esac
+       fi
+       ;;
+esac
+
 : see if strxfrm exists
 set strxfrm d_strxfrm
 eval $inlibc
@@ -15883,6 +16008,7 @@ d_strtod='$d_strtod'
 d_strtol='$d_strtol'
 d_strtold='$d_strtold'
 d_strtoll='$d_strtoll'
+d_strtoq='$d_strtoq'
 d_strtoul='$d_strtoul'
 d_strtoull='$d_strtoull'
 d_strtouq='$d_strtouq'
index c4ce3de..5c7b393 100644 (file)
@@ -1564,6 +1564,10 @@ d_strtoll (d_strtoll.U):
        This variable conditionally defines the HAS_STRTOLL symbol, which
        indicates to the C program that the strtoll() routine is available.
 
+d_strtoq (d_strtoq.U):
+       This variable conditionally defines the HAS_STRTOQ symbol, which
+       indicates to the C program that the strtoq() routine is available.
+
 d_strtoul (d_strtoul.U):
        This variable conditionally defines the HAS_STRTOUL symbol, which
        indicates to the C program that the strtoul() routine is available
index 2f760ae..b160d19 100644 (file)
@@ -8,7 +8,7 @@
 
 # Package name      : perl5
 # Source directory  : /m/fs/work/work/permanent/perl/pp4/perl
-# Configuration time: Tue Nov 21 20:44:07 EET 2000
+# Configuration time: Fri Dec 15 04:43:47 EET 2000
 # Configured by     : jhi
 # Target system     : osf1 alpha.hut.fi v4.0 878 alpha 
 
@@ -62,7 +62,7 @@ ccsymbols='__alpha=1 __LANGUAGE_C__=1 __osf__=1 __unix__=1 _LONGLONG=1 _SYSTYPE_
 ccversion='V5.6-082'
 cf_by='jhi'
 cf_email='yourname@yourhost.yourplace.com'
-cf_time='Tue Nov 21 20:44:07 EET 2000'
+cf_time='Fri Dec 15 04:43:47 EET 2000'
 charsize='1'
 chgrp=''
 chmod=''
@@ -355,7 +355,8 @@ d_strtod='define'
 d_strtol='define'
 d_strtold='undef'
 d_strtoll='undef'
-d_strtoul='define'
+d_strtoq='undef'
+d_strtoul='undef'
 d_strtoull='undef'
 d_strtouq='undef'
 d_strxfrm='define'
@@ -401,7 +402,7 @@ dlext='so'
 dlsrc='dl_dlopen.xs'
 doublesize='8'
 drand01='drand48()'
-dynamic_ext='B ByteLoader DB_File Data/Dumper Devel/DProf Devel/Peek Encode Fcntl File/Glob IO IPC/SysV NDBM_File ODBM_File Opcode POSIX SDBM_File Socket Storable Sys/Hostname Sys/Syslog Thread attrs re'
+dynamic_ext='B ByteLoader DB_File Data/Dumper Devel/DProf Devel/Peek Encode Fcntl File/Glob Filter/Util/Call IO IPC/SysV NDBM_File ODBM_File Opcode POSIX SDBM_File Socket Storable Sys/Hostname Sys/Syslog Thread attrs re'
 eagain='EAGAIN'
 ebcdic='undef'
 echo='echo'
@@ -410,7 +411,7 @@ emacs=''
 eunicefix=':'
 exe_ext=''
 expr='expr'
-extensions='B ByteLoader DB_File Data/Dumper Devel/DProf Devel/Peek Encode Fcntl File/Glob IO IPC/SysV NDBM_File ODBM_File Opcode POSIX SDBM_File Socket Storable Sys/Hostname Sys/Syslog Thread attrs re Errno'
+extensions='B ByteLoader DB_File Data/Dumper Devel/DProf Devel/Peek Encode Fcntl File/Glob Filter/Util/Call IO IPC/SysV NDBM_File ODBM_File Opcode POSIX SDBM_File Socket Storable Sys/Hostname Sys/Syslog Thread attrs re Errno'
 fflushNULL='define'
 fflushall='undef'
 find=''
@@ -549,7 +550,7 @@ intsize='4'
 ivdformat='"ld"'
 ivsize='8'
 ivtype='long'
-known_extensions='B ByteLoader DB_File Data/Dumper Devel/DProf Devel/Peek Encode Fcntl File/Glob GDBM_File IO IPC/SysV NDBM_File ODBM_File Opcode POSIX SDBM_File Socket Storable Sys/Hostname Sys/Syslog Thread attrs re'
+known_extensions='B ByteLoader DB_File Data/Dumper Devel/DProf Devel/Peek Encode Fcntl File/Glob Filter/Util/Call GDBM_File IO IPC/SysV NDBM_File ODBM_File Opcode POSIX SDBM_File Socket Storable Sys/Hostname Sys/Syslog Thread attrs re'
 ksh=''
 ld='ld'
 lddlflags='-shared -expect_unresolved "*" -msym -std -s'
index 10130c2..ec65e11 100644 (file)
@@ -17,7 +17,7 @@
 /*
  * Package name      : perl5
  * Source directory  : /m/fs/work/work/permanent/perl/pp4/perl
- * Configuration time: Tue Nov 21 20:44:07 EET 2000
+ * Configuration time: Fri Dec 15 04:43:47 EET 2000
  * Configured by     : jhi
  * Target system     : osf1 alpha.hut.fi v4.0 878 alpha 
  */
  */
 #define HAS_STRTOL     /**/
 
-/* HAS_STRTOUL:
- *     This symbol, if defined, indicates that the strtoul routine is
- *     available to provide conversion of strings to unsigned long.
- */
-#define HAS_STRTOUL    /**/
-
 /* HAS_STRXFRM:
  *     This symbol, if defined, indicates that the strxfrm() routine is
  *     available to transform strings.
  */
 #define SH_PATH "/bin/sh"  /**/
 
-/* STDCHAR:
- *     This symbol is defined to be the type of char used in stdio.h.
- *     It has the values "unsigned char" or "char".
- */
-#define STDCHAR unsigned char  /**/
-
 /* CROSSCOMPILE:
  *     This symbol, if defined, signifies that we our
  *     build process is a cross-compilation.
  */
 /*#define HAS_STRTOLL          / **/
 
+/* HAS_STRTOQ:
+ *     This symbol, if defined, indicates that the strtoq routine is
+ *     available to convert strings to long longs (quads).
+ */
+/*#define HAS_STRTOQ           / **/
+
 /* HAS_STRTOULL:
  *     This symbol, if defined, indicates that the strtoull routine is
  *     available to convert strings to unsigned long longs.
 #define HAS_SETPGRP            /**/
 #define USE_BSD_SETPGRP        /**/
 
+/* HAS_STRTOUL:
+ *     This symbol, if defined, indicates that the strtoul routine is
+ *     available to provide conversion of strings to unsigned long.
+ */
+/*#define HAS_STRTOUL  / **/
+
+/* STDCHAR:
+ *     This symbol is defined to be the type of char used in stdio.h.
+ *     It has the values "unsigned char" or "char".
+ */
+#define STDCHAR unsigned char  /**/
+
 /* HAS__FWALK:
  *     This symbol, if defined, indicates that the _fwalk system call is
  *     available to apply a function to all the file handles.
index bc1fc3f..8ab759d 100644 (file)
@@ -605,12 +605,6 @@ sed <<!GROK!THIS! >$CONFIG_H -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un
  */
 #$d_strtol HAS_STRTOL  /**/
 
-/* HAS_STRTOUL:
- *     This symbol, if defined, indicates that the strtoul routine is
- *     available to provide conversion of strings to unsigned long.
- */
-#$d_strtoul HAS_STRTOUL        /**/
-
 /* HAS_STRXFRM:
  *     This symbol, if defined, indicates that the strxfrm() routine is
  *     available to transform strings.
@@ -2125,6 +2119,12 @@ sed <<!GROK!THIS! >$CONFIG_H -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un
  */
 #$d_strtoll HAS_STRTOLL                /**/
 
+/* HAS_STRTOQ:
+ *     This symbol, if defined, indicates that the strtoq routine is
+ *     available to convert strings to long longs (quads).
+ */
+#$d_strtoq HAS_STRTOQ          /**/
+
 /* HAS_STRTOULL:
  *     This symbol, if defined, indicates that the strtoull routine is
  *     available to convert strings to unsigned long longs.
@@ -3205,6 +3205,12 @@ sed <<!GROK!THIS! >$CONFIG_H -e 's!^#undef\(.*/\)\*!/\*#define\1 \*!' -e 's!^#un
 #$d_setpgrp HAS_SETPGRP                /**/
 #$d_bsdsetpgrp USE_BSD_SETPGRP /**/
 
+/* HAS_STRTOUL:
+ *     This symbol, if defined, indicates that the strtoul routine is
+ *     available to provide conversion of strings to unsigned long.
+ */
+#$d_strtoul HAS_STRTOUL        /**/
+
 /* STDCHAR:
  *     This symbol is defined to be the type of char used in stdio.h.
  *     It has the values "unsigned char" or "char".
index 5b8ccbc..13b0d17 100644 (file)
@@ -3596,6 +3596,24 @@ $ tmp = "strtoll"
 $ GOSUB inlibc
 $ d_strtoll = tmp
 $!
+$! Check for strtoq
+$!
+$ OS
+$ WS "#if defined(__DECC) || defined(__DECCXX)"
+$ WS "#include <stdlib.h>"
+$ WS "#endif"
+$ WS "#include <string.h>"
+$ WS "int main()"
+$ WS "{"
+$ WS "__int64 result;"
+$ WS "result = strtoq(""123123"", NULL, 10);"
+$ WS "exit(0);"
+$ WS "}"
+$ CS
+$ tmp = "strtoq"
+$ GOSUB inlibc
+$ d_strtoq = tmp
+$!
 $! Check for strtold
 $!
 $ OS
@@ -5004,6 +5022,7 @@ $ WC "d_strtod='define'"
 $ WC "d_strtol='define'"
 $ WC "d_strtold='" + d_strtold + "'"
 $ WC "d_strtoll='" + d_strtoll + "'"
+$ WC "d_strtoq='define'"
 $ WC "d_strtoul='define'"
 $ WC "d_strtoull='" + d_strtoull + "'"
 $ WC "d_strtouq='" + d_strtouq + "'"
index 2ea89c1..c2921b7 100644 (file)
@@ -341,7 +341,9 @@ d_strerrm='strerror(e)'
 d_strerror='define'
 d_strtod='define'
 d_strtol='define'
+d_strtoq='undef'
 d_strtoul='define'
+d_strtouq='undef'
 d_strtoull='undef'
 d_strxfrm='define'
 d_suidsafe='undef'
diff --git a/perl.h b/perl.h
index 42c5246..9c6883b 100644 (file)
--- a/perl.h
+++ b/perl.h
@@ -3240,6 +3240,9 @@ typedef struct am_table_short AMTS;
 #   if !defined(Strtol) && defined(HAS_STRTOLL)
 #       define Strtol  strtoll
 #   endif
+#    if !defined(Strtol) && defined(HAS_STRTOQ)
+#       define Strtol  strtoq
+#    endif
 /* is there atoq() anywhere? */
 #endif
 #if !defined(Strtol) && defined(HAS_STRTOL)
diff --git a/sv.c b/sv.c
index a018cea..ab95cb9 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -2450,9 +2450,28 @@ Perl_looks_like_number(pTHX_ SV *sv)
            s++;
         } while (isDIGIT(*s));
 
-       if (s - nbegin > TYPE_DIGITS(UV))       /* Cannot cache ato[ul]() */
+       /* Aaargh. long long really is irritating.
+          In the gospel according to ANSI 1989, it is an axiom that "long"
+          is the longest integer type, and that if you don't know how long
+          something is you can cast it to long, and nothing will be lost
+          (except possibly speed of execution if long is slower than the
+          type is was).
+          Now, one can't be sure if the old rules apply, or long long
+          (or some other newfangled thing) is actually longer than the
+          (formerly) longest thing.
+       */
+       /* This lot will work for 64 bit  *as long as* either
+          either long is 64 bit
+          or     we can find both strtol/strtoq and strtoul/strtouq
+          If not, we really should refuse to let the user use 64 bit IVs
+          By "64 bit" I really mean IVs that don't get preserved by NVs
+          It also should work for 128 bit IVs. Can any lend me a machine to
+          test this?
+       */
+       if (s - nbegin > TYPE_DIGITS(UV)) /* Cannot cache ato[ul]() */
            numtype |= IS_NUMBER_TO_INT_BY_ATOF | IS_NUMBER_LONGER_THAN_IV_MAX;
-       else if (s - nbegin < BIT_DIGITS(sizeof (IV)*8-1))
+       else if (s - nbegin < BIT_DIGITS(((sizeof (IV)>sizeof (long))
+                                         ? sizeof(long) : sizeof (IV))*8-1))
            numtype |= IS_NUMBER_TO_INT_BY_ATOL;
        else
            /* Can't be sure either way. (For 64 bit UV, 63 bit IV is 1 decimal
index 8d25c1c..91fe0bc 100644 (file)
--- a/uconfig.h
+++ b/uconfig.h
  */
 /*#define HAS_STRTOL   / **/
 
-/* HAS_STRTOUL:
- *     This symbol, if defined, indicates that the strtoul routine is
- *     available to provide conversion of strings to unsigned long.
- */
-/*#define HAS_STRTOUL  / **/
-
 /* HAS_STRXFRM:
  *     This symbol, if defined, indicates that the strxfrm() routine is
  *     available to transform strings.
  */
 #define SH_PATH ""  /**/
 
-/* STDCHAR:
- *     This symbol is defined to be the type of char used in stdio.h.
- *     It has the values "unsigned char" or "char".
- */
-#define STDCHAR char   /**/
-
 /* CROSSCOMPILE:
  *     This symbol, if defined, signifies that we our
  *     build process is a cross-compilation.
  */
 /*#define HAS_STRTOLL          / **/
 
+/* HAS_STRTOQ:
+ *     This symbol, if defined, indicates that the strtoq routine is
+ *     available to convert strings to long longs (quads).
+ */
+# HAS_STRTOQ           /**/
+
 /* HAS_STRTOULL:
  *     This symbol, if defined, indicates that the strtoull routine is
  *     available to convert strings to unsigned long longs.
 /*#define HAS_SETPGRP          / **/
 /*#define USE_BSD_SETPGRP      / **/
 
+/* HAS_STRTOUL:
+ *     This symbol, if defined, indicates that the strtoul routine is
+ *     available to provide conversion of strings to unsigned long.
+ */
+/*#define HAS_STRTOUL  / **/
+
+/* STDCHAR:
+ *     This symbol is defined to be the type of char used in stdio.h.
+ *     It has the values "unsigned char" or "char".
+ */
+#define STDCHAR char   /**/
+
 /* HAS__FWALK:
  *     This symbol, if defined, indicates that the _fwalk system call is
  *     available to apply a function to all the file handles.
index 92ac457..7a20937 100644 (file)
@@ -254,6 +254,7 @@ $d_strtod='define'
 $d_strtol='define'
 $d_strtold='undef'
 $d_strtoll='undef'
+$d_strtoq='undef'
 $d_strtoul='define'
 $d_strtoull='undef'
 $d_strtouq='undef'
index 6344668..4ba1f29 100644 (file)
  */
 /*#define HAS_STRTOLL          /**/
 
+/* HAS_STRTOQ:
+ *     This symbol, if defined, indicates that the strtouq routine is
+ *     available to convert strings to long longs (quads).
+ */
+/*#define HAS_STRTOQ           /**/
+
 /* HAS_STRTOULL:
  *     This symbol, if defined, indicates that the strtoull routine is
  *     available to convert strings to unsigned long longs.
index f694977..46cbc20 100644 (file)
@@ -254,6 +254,7 @@ $d_strtod='define'
 $d_strtol='define'
 $d_strtold='undef'
 $d_strtoll='undef'
+$d_strtoq='undef'
 $d_strtoul='define'
 $d_strtoull='undef'
 $d_strtouq='undef'
index 834764a..b01b905 100644 (file)
  */
 #define HAS_STRTOL     /**/
 
+/* HAS_STRTOQ:
+ *     This symbol, if defined, indicates that the strtouq routine is
+ *     available to convert strings to long longs (quads).
+ */
+/*#define HAS_STRTOQ           /**/
+
 /* HAS_STRTOUL:
  *     This symbol, if defined, indicates that the strtoul routine is
  *     available to provide conversion of strings to unsigned long.
index e171ab8..8427200 100644 (file)
@@ -338,6 +338,7 @@ d_strtod='define'
 d_strtol='define'
 d_strtold='undef'
 d_strtoll='undef'
+d_strtoq='undef'
 d_strtoul='define'
 d_strtoull='undef'
 d_strtouq='undef'
index aa2d188..f43007f 100644 (file)
@@ -338,6 +338,7 @@ d_strtod='define'
 d_strtol='define'
 d_strtold='undef'
 d_strtoll='undef'
+d_strtoq='undef'
 d_strtoul='define'
 d_strtoull='undef'
 d_strtouq='undef'
index 9346ae0..2cbd63c 100644 (file)
@@ -338,6 +338,7 @@ d_strtod='define'
 d_strtol='define'
 d_strtold='undef'
 d_strtoll='undef'
+d_strtoq='undef'
 d_strtoul='define'
 d_strtoull='undef'
 d_strtouq='undef'