From a2dc48148493c525d7d8d71b2e275a3343549286 Mon Sep 17 00:00:00 2001 From: drow Date: Thu, 21 Sep 2006 13:50:50 +0000 Subject: [PATCH] * 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. --- gdb/ChangeLog | 9 ++++++ gdb/ada-lex.l | 62 ------------------------------------- gdb/defs.h | 2 ++ gdb/utils.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 62 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1ff1fa6b47..6b84a4b14d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,14 @@ 2006-09-21 Daniel Jacobowitz + * 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 + * 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 b25264cada..7ece1090c9 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 diff --git a/gdb/defs.h b/gdb/defs.h index c9d55041fb..f7dfbacabd 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -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 6c4afb7daa..cf5ef19b9d 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; +} -- 2.11.0