From: Nicholas Clark Date: Thu, 14 Dec 2000 18:38:57 +0000 (+0000) Subject: strtoq, strtou(q|ll|l) testing (was [PATCH] faster and 64 bit preserving arithmetic) X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=d0e6d399d7d5c2c9072a29da40b2cf4e9246353f;p=p5sagit%2Fp5-mst-13.2.git strtoq, strtou(q|ll|l) testing (was [PATCH] faster and 64 bit preserving arithmetic) Message-ID: <20001214183857.B97909@plum.flirble.org> p4raw-id: //depot/perl@8120 --- diff --git a/Configure b/Configure index 18e64b6..95a6283 100755 --- 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$$ <try.c <<'EOCP' +#include +#include +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 <&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 <try.c <<'EOCP' +#include +#include +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 <&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' diff --git a/Porting/Glossary b/Porting/Glossary index c4ce3de..5c7b393 100644 --- a/Porting/Glossary +++ b/Porting/Glossary @@ -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 diff --git a/Porting/config.sh b/Porting/config.sh index 2f760ae..b160d19 100644 --- a/Porting/config.sh +++ b/Porting/config.sh @@ -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' diff --git a/Porting/config_H b/Porting/config_H index 10130c2..ec65e11 100644 --- a/Porting/config_H +++ b/Porting/config_H @@ -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 */ @@ -585,12 +585,6 @@ */ #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. @@ -961,12 +955,6 @@ */ #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. @@ -2111,6 +2099,12 @@ */ /*#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. @@ -3191,6 +3185,18 @@ #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. diff --git a/config_h.SH b/config_h.SH index bc1fc3f..8ab759d 100644 --- a/config_h.SH +++ b/config_h.SH @@ -605,12 +605,6 @@ sed <$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 <$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 <$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". diff --git a/configure.com b/configure.com index 5b8ccbc..13b0d17 100644 --- a/configure.com +++ b/configure.com @@ -3596,6 +3596,24 @@ $ tmp = "strtoll" $ GOSUB inlibc $ d_strtoll = tmp $! +$! Check for strtoq +$! +$ OS +$ WS "#if defined(__DECC) || defined(__DECCXX)" +$ WS "#include " +$ WS "#endif" +$ WS "#include " +$ 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 + "'" diff --git a/epoc/config.sh b/epoc/config.sh index 2ea89c1..c2921b7 100644 --- a/epoc/config.sh +++ b/epoc/config.sh @@ -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 --- 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 --- 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 diff --git a/uconfig.h b/uconfig.h index 8d25c1c..91fe0bc 100644 --- a/uconfig.h +++ b/uconfig.h @@ -581,12 +581,6 @@ */ /*#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. @@ -957,12 +951,6 @@ */ #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. @@ -2107,6 +2095,12 @@ */ /*#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. @@ -3187,6 +3181,18 @@ /*#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. diff --git a/vos/config.alpha.def b/vos/config.alpha.def index 92ac457..7a20937 100644 --- a/vos/config.alpha.def +++ b/vos/config.alpha.def @@ -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' diff --git a/vos/config.alpha.h b/vos/config.alpha.h index 6344668..4ba1f29 100644 --- a/vos/config.alpha.h +++ b/vos/config.alpha.h @@ -2136,6 +2136,12 @@ */ /*#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. diff --git a/vos/config.ga.def b/vos/config.ga.def index f694977..46cbc20 100644 --- a/vos/config.ga.def +++ b/vos/config.ga.def @@ -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' diff --git a/vos/config.ga.h b/vos/config.ga.h index 834764a..b01b905 100644 --- a/vos/config.ga.h +++ b/vos/config.ga.h @@ -601,6 +601,12 @@ */ #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. diff --git a/win32/config.bc b/win32/config.bc index e171ab8..8427200 100644 --- a/win32/config.bc +++ b/win32/config.bc @@ -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' diff --git a/win32/config.gc b/win32/config.gc index aa2d188..f43007f 100644 --- a/win32/config.gc +++ b/win32/config.gc @@ -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' diff --git a/win32/config.vc b/win32/config.vc index 9346ae0..2cbd63c 100644 --- a/win32/config.vc +++ b/win32/config.vc @@ -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'