diff --git a/ChangeLog b/ChangeLog index 2a73c003..3f5f3c3d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2005-08-11 Hrvoje Niksic + + * configure.in: Check for strtoll and strtoimax. + 2005-07-08 Hrvoje Niksic * configure.in: Remove -Wno-implicit from default GCC warning diff --git a/configure.in b/configure.in index 94aefb48..2a6f4163 100644 --- a/configure.in +++ b/configure.in @@ -205,7 +205,7 @@ AC_FUNC_ALLOCA AC_FUNC_MMAP AC_FUNC_FSEEKO AC_CHECK_FUNCS(strptime timegm snprintf vsnprintf vasprintf drand48) -AC_CHECK_FUNCS(usleep ftello sigblock sigsetjmp) +AC_CHECK_FUNCS(strtoll strtoimax usleep ftello sigblock sigsetjmp) dnl We expect to have these functions on Unix-like systems configure dnl runs on. The defines are provided to get them in config.h.in so diff --git a/src/ChangeLog b/src/ChangeLog index 6575c255..7d782ced 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2005-08-11 Hrvoje Niksic + + * cmpt.c (strtoll): Define it if missing on the system and if Wget + needs it. + + * mswindows.c (str_to_int64): Move to cmpt.c and rename to strtoll. + 2005-08-10 Hrvoje Niksic * host.c (print_address): Always use inet_ntop when IPv6 is diff --git a/src/cmpt.c b/src/cmpt.c index de14657e..08a92aef 100644 --- a/src/cmpt.c +++ b/src/cmpt.c @@ -1266,3 +1266,128 @@ timegm (struct tm *t) return (time_t) secs; } #endif /* HAVE_TIMEGM */ + +#ifdef NEED_STRTOLL +/* strtoll is required by C99 and used by Wget only on systems with + LFS. Unfortunately, some systems have LFS, but no strtoll or + equivalent. These include HPUX 11.0 and Windows. + + We use #ifdef NEED_STRTOLL instead of #ifndef HAVE_STRTOLL because + of the systems which have a suitable replacement (e.g. _strtoi64 on + Windows), on which Wget's str_to_wgint is instructed to use that + instead. */ + +static inline int +char_value (char c, int base) +{ + int value; + if (c < '0') + return -1; + if ('0' <= c && c <= '9') + value = c - '0'; + else if ('a' <= c && c <= 'z') + value = c - 'a' + 10; + else if ('A' <= c && c <= 'Z') + value = c - 'A' + 10; + else + return -1; + if (value >= base) + return -1; + return value; +} + +#define LL strtoll_return /* long long or __int64 */ + +/* These constants assume 64-bit strtoll_return. */ + +/* A roundabout way of writing 2**63-1 = 9223372036854775807 */ +#define STRTOLL_OVERFLOW (((LL) 1 << 62) - 1 + ((LL) 1 << 62)) +/* A roundabout way of writing -2**63 = -9223372036854775808 */ +#define STRTOLL_UNDERFLOW (-STRTOLL_OVERFLOW - 1) + +/* A strtoll replacement for systems that have LFS but don't supply + strtoll. The headers typedef strtoll_return to long long or to + __int64. */ + +strtoll_return +strtoll (const char *nptr, char **endptr, int base) +{ + strtoll_return result = 0; + bool negative; + + if (base != 0 && (base < 2 || base > 36)) + { + errno = EINVAL; + return 0; + } + + while (*nptr == ' ' || *nptr == '\t') + ++nptr; + if (*nptr == '-') + { + negative = true; + ++nptr; + } + else if (*nptr == '+') + { + negative = false; + ++nptr; + } + else + negative = false; + + /* If base is 0, determine the real base based on the beginning on + the number; octal numbers begin with "0", hexadecimal with "0x", + and the others are considered octal. */ + if (*nptr == '0') + { + if ((base == 0 || base == 16) + && + (*(nptr + 1) == 'x' || *(nptr + 1) == 'X')) + { + base = 16; + nptr += 2; + } + else if (base == 0) + base = 8; + } + else if (base == 0) + base = 10; + + if (!negative) + { + /* Parse positive number, checking for overflow. */ + int val; + for (; (val = char_value (*nptr, base)) != -1; ++nptr) + { + strtoll_return newresult = base * result + val; + if (newresult < result) + { + result = STRTOLL_OVERFLOW; + errno = ERANGE; + break; + } + result = newresult; + } + } + else + { + /* Parse negative number, checking for underflow. */ + int val; + for (; (val = char_value (*nptr, base)) != -1; ++nptr) + { + strtoll_return newresult = base * result - val; + if (newresult > result) + { + result = STRTOLL_UNDERFLOW; + errno = ERANGE; + break; + } + result = newresult; + } + } + if (endptr) + *endptr = (char *) nptr; + return result; +} +#endif /* NEED_STRTOLL */ diff --git a/src/mswindows.c b/src/mswindows.c index e160e958..986f1ba4 100644 --- a/src/mswindows.c +++ b/src/mswindows.c @@ -72,116 +72,6 @@ xsleep (double seconds) #endif /* not HAVE_USLEEP */ } -#if !defined(HAVE_STRTOLL) && !defined(HAVE__STRTOI64) - -static inline int -char_value (char c, int base) -{ - int value; - if (c < '0') - return -1; - if ('0' <= c && c <= '9') - value = c - '0'; - else if ('a' <= c && c <= 'z') - value = c - 'a' + 10; - else if ('A' <= c && c <= 'Z') - value = c - 'A' + 10; - else - return -1; - if (value >= base) - return -1; - return value; -} - -/* A fairly simple strtoll replacement for MS VC versions that don't - supply _strtoi64. */ - -__int64 -str_to_int64 (const char *nptr, char **endptr, int base) -{ -#define INT64_OVERFLOW 9223372036854775807I64 -#define INT64_UNDERFLOW (-INT64_OVERFLOW - 1) - - __int64 result = 0; - bool negative; - - if (base != 0 && (base < 2 || base > 36)) - { - errno = EINVAL; - return 0; - } - - while (*nptr == ' ' || *nptr == '\t') - ++nptr; - if (*nptr == '-') - { - negative = true; - ++nptr; - } - else if (*nptr == '+') - { - negative = false; - ++nptr; - } - else - negative = false; - - /* If base is 0, determine the real base based on the beginning on - the number; octal numbers begin with "0", hexadecimal with "0x", - and the others are considered octal. */ - if (*nptr == '0') - { - if ((base == 0 || base == 16) - && - (*(nptr + 1) == 'x' || *(nptr + 1) == 'X')) - { - base = 16; - nptr += 2; - } - else if (base == 0) - base = 8; - } - else if (base == 0) - base = 10; - - if (!negative) - { - /* Parse positive number, checking for overflow. */ - int val; - for (; (val = char_value (*nptr, base)) != -1; ++nptr) - { - __int64 newresult = base * result + val; - if (newresult < result) - { - result = INT64_OVERFLOW; - errno = ERANGE; - break; - } - result = newresult; - } - } - else - { - /* Parse negative number, checking for underflow. */ - int val; - for (; (val = char_value (*nptr, base)) != -1; ++nptr) - { - __int64 newresult = base * result - val; - if (newresult > result) - { - result = INT64_UNDERFLOW; - errno = ERANGE; - break; - } - result = newresult; - } - } - if (endptr) - *endptr = (char *) nptr; - return result; -} -#endif - void windows_main (int *argc, char **argv, char **exec_name) { diff --git a/src/mswindows.h b/src/mswindows.h index f72372b7..0799b831 100644 --- a/src/mswindows.h +++ b/src/mswindows.h @@ -86,15 +86,16 @@ typedef __int64 wgint; #define SIZEOF_WGINT 8 #define WGINT_MAX LL (9223372036854775807) -/* str_to_wgint is a function with the semantics of strtol, but which - works on wgint. */ +/* str_to_wgint is a function with the semantics of strtol[l], but + which works on wgint. */ #if defined HAVE_STRTOLL # define str_to_wgint strtoll #elif defined HAVE__STRTOI64 # define str_to_wgint _strtoi64 #else -__int64 str_to_int64 (const char *, char **, int); -# define str_to_wgint str_to_int64 +# define str_to_wgint strtoll +# define NEED_STRTOLL +# define strtoll_return __int64 #endif /* Windows has no symlink, therefore no lstat. Without symlinks lstat diff --git a/src/wget.h b/src/wget.h index 8c76282c..c312471d 100644 --- a/src/wget.h +++ b/src/wget.h @@ -133,11 +133,24 @@ typedef off_t wgint; # define str_to_wgint strtol # define WGINT_MAX LONG_MAX # else -# define str_to_wgint strtoll # define WGINT_MAX LLONG_MAX +# ifdef HAVE_STRTOLL +# define str_to_wgint strtoll +# elif HAVE_STRTOIMAX +# define str_to_wgint strtoimax +# else +# define str_to_wgint strtoll +# define NEED_STRTOLL +# define strtoll_return long long +# endif # endif #endif +/* Declare our strtoll replacement. */ +#ifdef NEED_STRTOLL +strtoll_return strtoll (const char *, char **, int); +#endif + /* Now define a large integral type useful for storing sizes of *sums* of downloads, such as the value of the --quota option. This should be a type able to hold 2G+ values even on systems without large