From 253c8abb67a72cdfcdb2be4b92e2dba8689e6554 Mon Sep 17 00:00:00 2001 From: Daniel Jacobowitz Date: Thu, 21 Sep 2006 13:50:51 +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 1ff1fa6b476..6b84a4b14d7 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +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. diff --git a/gdb/ada-lex.l b/gdb/ada-lex.l index b25264cadad..7ece1090c96 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 c9d55041fb9..f7dfbacabd9 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 6c4afb7daac..cf5ef19b9d9 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.30.2