- int ch; /* Current char being considered */
- unsigned f = 0; /* Flags about the current number */
- int r; /* Radix to switch over to */
- mpw rd; /* Radix as an @mp@ digit */
- mp rr; /* The @mp@ for the radix */
- unsigned nf = m ? m->f & MP_BURN : 0; /* New @mp@ flags */
-
- /* --- Stacks --- */
-
- mp *pow[DEPTH]; /* List of powers */
- unsigned pows; /* Next index to fill */
- struct { unsigned i; mp *m; } s[DEPTH]; /* Main stack */
- unsigned sp; /* Current stack pointer */
-
- /* --- Flags --- */
-
-#define f_neg 1u
-#define f_ok 2u
-#define f_start 4u
-
- /* --- Initialize the stacks --- */
-
- mp_build(&rr, &rd, &rd + 1);
- pow[0] = &rr;
- pows = 1;
-
- sp = 0;
-
- /* --- Initialize the destination number --- */
-
- if (m)
- MP_DROP(m);
-
- /* --- Read an initial character --- */
-
- ch = ops->get(p);
- if (radix >= 0) {
- while (isspace(ch))
- ch = ops->get(p);
- }
-
- /* --- Handle an initial sign --- */
-
- if (radix >= 0 && (ch == '-' || ch == '+')) {
- if (ch == '-')
- f |= f_neg;
- do ch = ops->get(p); while isspace(ch);
- }
-
- /* --- If the radix is zero, look for leading zeros --- */
-
- if (radix > 0) {
- assert(((void)"ascii radix must be <= 62", radix <= 62));
- rd = radix;
- r = -1;
- } else if (radix < 0) {
- rd = -radix;
- assert(((void)"binary radix must fit in a byte", rd <= UCHAR_MAX));
- r = -1;
- } else if (ch != '0') {
- rd = 10;
- r = 0;
- } else {
- ch = ops->get(p);
- switch (ch) {
- case 'x':
- rd = 16;
- goto prefix;
- case 'o':
- rd = 8;
- goto prefix;
- case 'b':
- rd = 2;
- goto prefix;
- prefix:
- ch = ops->get(p);
- break;
- default:
- rd = 8;
- f |= f_ok;
- }
- r = -1;
- }
-
- /* --- Use fast algorithm for binary radix --- *
- *
- * This is the restart point after having parsed a radix number from the
- * input. We check whether the radix is binary, and if so use a fast
- * algorithm which just stacks the bits up in the right order.
- */
+ int r = radix < 0 ? -radix : radix;
+ int d;
+
+ if (ch < 0) return (-1);
+ if (radix < 0) d = ch;
+ else if ('0' <= ch && ch <= '9') d = ch - '0';
+ else if ('a' <= ch && ch <= 'z') d = ch - 'a' + 10;
+ else if ('A' <= ch && ch <= 'Z') d = ch - 'A' + (radix > 36 ? 36 : 10);
+ else return (-1);
+ if (d >= r) return (-1);
+ return (d);
+}