]> git.draconx.ca Git - cdecl99.git/blobdiff - src/scan.l
libcdecl: Implement portable alternative to strtoumax.
[cdecl99.git] / src / scan.l
index fbe80b2fddae12cc5076a9a0e108497d0b28d7ff..48314d4e00df2203cdba59f2aac0ca5c67009307 100644 (file)
 #include "cdecl-internal.h"
 #include "cdecl.h"
 #include "errmsg.h"
-
-#if HAVE_STRTOUMAX
-/* Best case, implementation provides strtoumax. */
-#  define STRTOUMAX strtoumax
-#elif HAVE_STRTOULL
-/* Fall back to strtoull, with possibly reduced range. */
-#define STRTOUMAX strtoull
-#elif HAVE___STRTOULL
-/* HP-UX 11 has __strtoull in <inttypes.h> */
-#define STRTOUMAX __strtoull
-#else
-/* Fall back to strtoul, with possibly reduced range. */
-#define STRTOUMAX strtoul
-#endif
+#include "intconv.h"
 
 static char *to_octal(char *dst, unsigned val)
 {
@@ -111,11 +98,11 @@ static void to_readable_ch(char *dst, char c)
 %}
 
 IDENT [_[:alpha:]][-_[:alnum:]]*
-INTEGER 0[Xx][[:xdigit:]]*|[[:digit:]]+
 
 %%
 
 %{
+       int intconv_base;
        char *c;
 %}
 
@@ -139,22 +126,29 @@ INTEGER 0[Xx][[:xdigit:]]*|[[:digit:]]+
        return UNPACK_TOKEN(match[sizeof tab[0]]);
 }
 
-{INTEGER} {
-       char *end;
-
-       errno = 0;
-       yylval->uintval = STRTOUMAX(yytext, &end, 0);
-       if (errno == ERANGE) {
-               cdecl__errmsg(CDECL__ERANGE);
-               return T_LEX_ERROR;
-       }
-       if (*end) {
-               cdecl__errmsg(CDECL__EBADINT);
-               return T_LEX_ERROR;
+0[0-7]* { intconv_base = INTCONV_OCTAL; goto int_parse; }
+[1-9][0-9]* { intconv_base = INTCONV_DECIMAL; goto int_parse; }
+0[Xx][[:xdigit:]]+ {
+       unsigned char d;
+       uintmax_t v;
+
+       yytext += 2;
+       intconv_base = INTCONV_HEXADECIMAL;
+int_parse:
+       for (v = 0; (d = *yytext++);) {
+               if (!intconv_shift(&v, intconv_base, intconv_digit(d))) {
+                       cdecl__errmsg(CDECL__ERANGE);
+                       return T_LEX_ERROR;
+               }
        }
 
+       yylval->uintval = v;
        return T_UINT;
 }
+0[Xx]|[0-9]+ {
+       cdecl__errmsg(CDECL__EBADINT);
+       return T_LEX_ERROR;
+}
 
 {IDENT} {
        int len = yyleng, tok;
@@ -180,7 +174,7 @@ INTEGER 0[Xx][[:xdigit:]]*|[[:digit:]]+
                yyless(strcspn(yytext, "-"));
 #endif
                if (!(yylval->item = cdecl__alloc_item(len+1)))
-                       return T_LEX_ERROR; \
+                       return T_LEX_ERROR;
                memcpy(yylval->item->s, yytext, len+1);
        }
        return UNPACK_TOKEN(tok);