X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Fcmpt.c;h=4bd582c85dff8342106f552e2af008d0c4d8949d;hp=08a92aefadab9b75f4c69809e98c46bad5d9f3fc;hb=4d7c5e087b2bc82c9f503dff003916d1047903ce;hpb=f25d593c16d10ae1ef6d519eb0268fead356b014 diff --git a/src/cmpt.c b/src/cmpt.c index 08a92aef..4bd582c8 100644 --- a/src/cmpt.c +++ b/src/cmpt.c @@ -1,11 +1,11 @@ /* Replacements for routines missing on some systems. - Copyright (C) 1996-2005 Free Software Foundation, Inc. + Copyright (C) 1996-2006 Free Software Foundation, Inc. This file is part of GNU Wget. GNU Wget is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or +the Free Software Foundation; either version 3 of the License, or (at your option) any later version. GNU Wget is distributed in the hope that it will be useful, @@ -14,8 +14,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with Wget; if not, write to the Free Software Foundation, Inc., -51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +along with Wget. If not, see . In addition, as a special exception, the Free Software Foundation gives permission to link the code of its release of Wget with the @@ -111,10 +110,28 @@ strncasecmp (const char *s1, const char *s2, size_t n) return c1 - c2; } #endif /* not HAVE_STRNCASECMP */ + +#ifndef HAVE_MEMRCHR +/* memrchr is a GNU extension. It is like the memchr function, except + that it searches backwards from the end of the n bytes pointed to + by s instead of forwards from the front. */ + +void * +memrchr (const void *s, int c, size_t n) +{ + const char *b = s; + const char *e = b + n; + while (e > b) + if (*--e == c) + return (void *) e; + return NULL; +} +#endif /* strptime is required by POSIX, but it is missing from Windows, which means we must keep a fallback implementation. It is - reportedly missing or broken on many older systems as well. */ + reportedly missing or broken on many older Unix systems as well, so + it's good to have around. */ #ifndef HAVE_STRPTIME /* From GNU libc 2.1.3. */ @@ -1046,9 +1063,10 @@ const unsigned short int __mon_yday[2][13] = and given a prefix, but many systems out there are still (as of this writing in 2005) broken and we must cater to them. - Additionally, according to some conventional, many historical - implementations of fnmatch are buggy and unreliable. If yours is - such, undefine SYSTEM_FNMATCH in sysdep.h and tell us about it. */ + Additionally, according to some conventional wisdom, many + historical implementations of fnmatch are buggy and unreliable. If + yours is such, undefine SYSTEM_FNMATCH in sysdep.h and tell us + about it. */ #ifndef SYSTEM_FNMATCH @@ -1296,23 +1314,22 @@ char_value (char c, int base) return value; } -#define LL strtoll_return /* long long or __int64 */ +#define STRTOLL_MAX TYPE_MAXIMUM (strtoll_type) +/* This definition assumes two's complement arithmetic */ +#define STRTOLL_MIN (-STRTOLL_MAX - 1) -/* These constants assume 64-bit strtoll_return. */ +/* Like a%b, but always returns a positive number when A is negative. + (C doesn't guarantee the sign of the result.) */ +#define MOD(a, b) ((strtoll_type) -1 % 2 == 1 ? (a) % (b) : - ((a) % (b))) -/* 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-like replacement for systems that have an integral type + larger than long but don't supply strtoll. This implementation + makes no assumptions about the size of strtoll_type. */ -/* 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_type strtoll (const char *nptr, char **endptr, int base) { - strtoll_return result = 0; + strtoll_type result = 0; bool negative; if (base != 0 && (base < 2 || base > 36)) @@ -1336,7 +1353,7 @@ strtoll (const char *nptr, char **endptr, int base) else negative = false; - /* If base is 0, determine the real base based on the beginning on + /* 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') @@ -1347,6 +1364,13 @@ strtoll (const char *nptr, char **endptr, int base) { base = 16; nptr += 2; + /* "0x" must be followed by at least one hex char. If not, + return 0 and place ENDPTR on 'x'. */ + if (!ISXDIGIT (*nptr)) + { + --nptr; + goto out; + } } else if (base == 0) base = 8; @@ -1357,37 +1381,48 @@ strtoll (const char *nptr, char **endptr, int base) if (!negative) { /* Parse positive number, checking for overflow. */ - int val; - for (; (val = char_value (*nptr, base)) != -1; ++nptr) + int digit; + /* Overflow watermark. If RESULT exceeds it, overflow occurs on + this digit. If result==WATERMARK, current digit may not + exceed the last digit of maximum value. */ + const strtoll_type WATERMARK = STRTOLL_MAX / base; + for (; (digit = char_value (*nptr, base)) != -1; ++nptr) { - strtoll_return newresult = base * result + val; - if (newresult < result) + if (result > WATERMARK + || (result == WATERMARK && digit > STRTOLL_MAX % base)) { - result = STRTOLL_OVERFLOW; + result = STRTOLL_MAX; errno = ERANGE; break; } - result = newresult; + result = base * result + digit; } } else { /* Parse negative number, checking for underflow. */ - int val; - for (; (val = char_value (*nptr, base)) != -1; ++nptr) + int digit; + const strtoll_type WATERMARK = STRTOLL_MIN / base; + for (; (digit = char_value (*nptr, base)) != -1; ++nptr) { - strtoll_return newresult = base * result - val; - if (newresult > result) + if (result < WATERMARK + || (result == WATERMARK && digit > MOD (STRTOLL_MIN, base))) { - result = STRTOLL_UNDERFLOW; + result = STRTOLL_MIN; errno = ERANGE; break; } - result = newresult; + result = base * result - digit; } } + out: if (endptr) *endptr = (char *) nptr; return result; } + +#undef STRTOLL_MAX +#undef STRTOLL_MIN +#undef ABS + #endif /* NEED_STRTOLL */