Mercurial > hg > xemacs-beta
diff src/data.c @ 169:15872534500d r20-3b11
Import from CVS: tag r20-3b11
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:46:53 +0200 |
parents | 28f395d8dc7a |
children | 929b76928fce |
line wrap: on
line diff
--- a/src/data.c Mon Aug 13 09:45:48 2007 +0200 +++ b/src/data.c Mon Aug 13 09:46:53 2007 +0200 @@ -1244,18 +1244,54 @@ return build_string (buffer); } -DEFUN ("string-to-number", Fstring_to_number, 1, 1, 0, /* +static int +digit_to_number (int character, int base) +{ + int digit; + + if (character >= '0' && character <= '9') + digit = character - '0'; + else if (character >= 'a' && character <= 'z') + digit = character - 'a' + 10; + else if (character >= 'A' && character <= 'Z') + digit = character - 'A' + 10; + else + return -1; + + if (digit >= base) + return -1; + else + return digit; +} + +DEFUN ("string-to-number", Fstring_to_number, 1, 2, 0, /* Convert STRING to a number by parsing it as a decimal number. This parses both integers and floating point numbers. It ignores leading spaces and tabs. + +If BASE, interpret STRING as a number in that base. If BASE isn't +present, base 10 is used. BASE must be between 2 and 16 (inclusive). +Floating point numbers always use base 10. */ - (string)) + (string, base)) { - Lisp_Object value; char *p; + int b; + CHECK_STRING (string); + if (NILP (base)) + b = 10; + else + { + CHECK_INT (base); + b = XINT (base); + if (b < 2 || b > 16) + Fsignal (Qargs_out_of_range, Fcons (base, Qnil)); + } + p = (char *) XSTRING_DATA (string); + /* Skip any whitespace at the front of the number. Some versions of atoi do this anyway, so we might as well make Emacs lisp consistent. */ while (*p == ' ' || *p == '\t') @@ -1266,13 +1302,39 @@ return make_float (atof (p)); #endif /* LISP_FLOAT_TYPE */ - if (sizeof (int) == sizeof (EMACS_INT)) - XSETINT (value, atoi (p)); - else if (sizeof (long) == sizeof (EMACS_INT)) - XSETINT (value, atol (p)); + if (XINT(base) == 10) + { + /* Use the system-provided functions for base 10. */ + Lisp_Object value; + if (sizeof (int) == sizeof (EMACS_INT)) + XSETINT (value, atoi (p)); + else if (sizeof (long) == sizeof (EMACS_INT)) + XSETINT (value, atol (p)); + else + abort (); + return value; + } else - abort (); - return value; + { + int digit, negative = 1; + EMACS_INT v = 0; + + if (*p == '-') + { + negative = -1; + p++; + } + else if (*p == '+') + p++; + while (1) + { + digit = digit_to_number (*p++, b); + if (digit < 0) + break; + v = v * b + digit; + } + return make_int (negative * v); + } } enum arithop