* 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.
This commit is contained in:
parent
c96fc75e9e
commit
253c8abb67
4 changed files with 110 additions and 62 deletions
|
@ -1,3 +1,12 @@
|
|||
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.
|
||||
|
|
|
@ -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 *);
|
||||
|
|
99
gdb/utils.c
99
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue