aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jacobowitz <drow@false.org>2006-09-21 13:50:51 +0000
committerDaniel Jacobowitz <drow@false.org>2006-09-21 13:50:51 +0000
commit253c8abb67a72cdfcdb2be4b92e2dba8689e6554 (patch)
tree7d79e3725009992103877706f6e2317a558a663c
parentc96fc75e9e90e0781789095b842495bbcdbb037a (diff)
downloadgdb-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/ChangeLog9
-rw-r--r--gdb/ada-lex.l62
-rw-r--r--gdb/defs.h2
-rw-r--r--gdb/utils.c99
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
diff --git a/gdb/defs.h b/gdb/defs.h
index c9d5504..f7dfbac 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 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;
+}