diff options
author | Daniel Jacobowitz <drow@false.org> | 2006-09-21 13:50:51 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2006-09-21 13:50:51 +0000 |
commit | 253c8abb67a72cdfcdb2be4b92e2dba8689e6554 (patch) | |
tree | 7d79e3725009992103877706f6e2317a558a663c | |
parent | c96fc75e9e90e0781789095b842495bbcdbb037a (diff) | |
download | gdb-253c8abb67a72cdfcdb2be4b92e2dba8689e6554.zip gdb-253c8abb67a72cdfcdb2be4b92e2dba8689e6554.tar.gz gdb-253c8abb67a72cdfcdb2be4b92e2dba8689e6554.tar.bz2 |
* ada-lex.l (HIGH_BYTE_POSN, is_digit_in_base, digit_to_int)
(strtoulst): Moved to ...
* utils.c (HIGH_BYTE_POSN, is_digit_in_base, digit_to_int)
(strtoulst): ... here. Enhanced to behave more similarly
to strtoul.
* defs.h (strtoulst): New prototype.
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/ada-lex.l | 62 | ||||
-rw-r--r-- | gdb/defs.h | 2 | ||||
-rw-r--r-- | gdb/utils.c | 99 |
4 files changed, 110 insertions, 62 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1ff1fa6..6b84a4b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,14 @@ 2006-09-21 Daniel Jacobowitz <dan@codesourcery.com> + * ada-lex.l (HIGH_BYTE_POSN, is_digit_in_base, digit_to_int) + (strtoulst): Moved to ... + * utils.c (HIGH_BYTE_POSN, is_digit_in_base, digit_to_int) + (strtoulst): ... here. Enhanced to behave more similarly + to strtoul. + * defs.h (strtoulst): New prototype. + +2006-09-21 Daniel Jacobowitz <dan@codesourcery.com> + * Makefile.in (memattr_h, memattr.o): Update. * memattr.h: Include "vec.h". (struct mem_region): Remove linked list pointer. diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l index b25264c..7ece109 100644 --- a/gdb/ada-lex.l +++ b/gdb/ada-lex.l @@ -296,68 +296,6 @@ canonicalizeNumeral (char *s1, const char *s2) s1[0] = '\000'; } -#define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT) - -/* True (non-zero) iff DIGIT is a valid digit in radix BASE, - where 2 <= BASE <= 16. */ - -static int -is_digit_in_base (unsigned char digit, int base) -{ - if (!isxdigit (digit)) - return 0; - if (base <= 10) - return (isdigit (digit) && digit < base + '0'); - else - return (isdigit (digit) || tolower (digit) < base - 10 + 'a'); -} - -static int -digit_to_int (unsigned char c) -{ - if (isdigit (c)) - return c - '0'; - else - return tolower (c) - 'a' + 10; -} - -/* As for strtoul, but for ULONGEST results. */ - -ULONGEST -strtoulst (const char *num, const char **trailer, int base) -{ - unsigned int high_part; - ULONGEST result; - int i; - unsigned char lim; - - if (base < 2 || base > 16) - { - errno = EINVAL; - return 0; - } - lim = base - 1 + '0'; - - result = high_part = 0; - for (i = 0; is_digit_in_base (num[i], base); i += 1) - { - result = result*base + digit_to_int (num[i]); - high_part = high_part*base + (unsigned int) (result >> HIGH_BYTE_POSN); - result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1; - if (high_part > 0xff) - { - errno = ERANGE; - result = high_part = 0; - break; - } - } - - if (trailer != NULL) - *trailer = &num[i]; - - return result + ((ULONGEST) high_part << HIGH_BYTE_POSN); -} - /* Interprets the prefix of NUM that consists of digits of the given BASE as an integer of that BASE, with the string EXP as an exponent. Puts value in yylval, and returns INT, if the string is valid. Causes @@ -415,6 +415,8 @@ extern char *xfullpath (const char *); extern unsigned long gnu_debuglink_crc32 (unsigned long crc, unsigned char *buf, size_t len); +ULONGEST strtoulst (const char *num, const char **trailer, int base); + /* From demangle.c */ extern void set_demangling_style (char *); diff --git a/gdb/utils.c b/gdb/utils.c index 6c4afb7..cf5ef19 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -3139,3 +3139,102 @@ dummy_obstack_deallocate (void *object, void *data) { return; } + +/* The bit offset of the highest byte in a ULONGEST, for overflow + checking. */ + +#define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT) + +/* True (non-zero) iff DIGIT is a valid digit in radix BASE, + where 2 <= BASE <= 36. */ + +static int +is_digit_in_base (unsigned char digit, int base) +{ + if (!isalnum (digit)) + return 0; + if (base <= 10) + return (isdigit (digit) && digit < base + '0'); + else + return (isdigit (digit) || tolower (digit) < base - 10 + 'a'); +} + +static int +digit_to_int (unsigned char c) +{ + if (isdigit (c)) + return c - '0'; + else + return tolower (c) - 'a' + 10; +} + +/* As for strtoul, but for ULONGEST results. */ + +ULONGEST +strtoulst (const char *num, const char **trailer, int base) +{ + unsigned int high_part; + ULONGEST result; + int minus = 0; + int i = 0; + + /* Skip leading whitespace. */ + while (isspace (num[i])) + i++; + + /* Handle prefixes. */ + if (num[i] == '+') + i++; + else if (num[i] == '-') + { + minus = 1; + i++; + } + + if (base == 0 || base == 16) + { + if (num[i] == '0' && (num[i + 1] == 'x' || num[i + 1] == 'X')) + { + i += 2; + if (base == 0) + base = 16; + } + } + + if (base == 0 && num[i] == '0') + base = 8; + + if (base == 0) + base = 10; + + if (base < 2 || base > 36) + { + errno = EINVAL; + return 0; + } + + result = high_part = 0; + for (; is_digit_in_base (num[i], base); i += 1) + { + result = result * base + digit_to_int (num[i]); + high_part = high_part * base + (unsigned int) (result >> HIGH_BYTE_POSN); + result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1; + if (high_part > 0xff) + { + errno = ERANGE; + result = ~ (ULONGEST) 0; + high_part = 0; + minus = 0; + break; + } + } + + if (trailer != NULL) + *trailer = &num[i]; + + result = result + ((ULONGEST) high_part << HIGH_BYTE_POSN); + if (minus) + return -result; + else + return result; +} |