aboutsummaryrefslogtreecommitdiff
path: root/gdb/utils.c
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 /gdb/utils.c
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.
Diffstat (limited to 'gdb/utils.c')
-rw-r--r--gdb/utils.c99
1 files changed, 99 insertions, 0 deletions
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;
+}