%top{
/*
* Scanner for C declarations.
- * Copyright © 2011, 2021, 2023 Nick Bowler
+ * Copyright © 2011, 2021, 2023-2024 Nick Bowler
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <config.h>
#include "parse.h"
+
+/* Disable various generated code we don't use */
+#define YY_INPUT(a, b, c) do {} while (0)
+#define YY_NO_INPUT 1
+#define YY_NO_UNPUT 1
}
%option nodefault noyywrap bison-locations reentrant never-interactive
#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
-
-#define dup_token() do { \
- yylval->strval = malloc(yyleng+1); \
- if (!yylval->strval) { \
- cdecl__errmsg(CDECL__ENOMEM); \
- return T_LEX_ERROR; \
- } \
- memcpy(yylval->strval, yytext, yyleng); \
- yylval->strval[yyleng] = 0; \
-} while(0)
+#include "intconv.h"
static char *to_octal(char *dst, unsigned val)
{
%}
IDENT [_[:alpha:]][-_[:alnum:]]*
-INTEGER 0x[[:xdigit:]]+|0[0-7]+|[[:digit:]]+
%%
%{
+ int intconv_base;
char *c;
-
- if (yyextra > 0) {
- yyextra = -yyextra;
- return T_ENGLISH;
- }
%}
"..."|[][;*(),] {
+ unsigned char *match;
static const unsigned char tab[2][8] = {
"*[](),.;",
{
- T_ASTERISK & 0xff,
- T_LBRACKET & 0xff,
- T_RBRACKET & 0xff,
- T_LPAREN & 0xff,
- T_RPAREN & 0xff,
- T_COMMA & 0xff,
- T_ELLIPSIS & 0xff,
- T_SEMICOLON & 0xff
+ PACK_TOKEN(T_ASTERISK),
+ PACK_TOKEN(T_LBRACKET),
+ PACK_TOKEN(T_RBRACKET),
+ PACK_TOKEN(T_LPAREN),
+ PACK_TOKEN(T_RPAREN),
+ PACK_TOKEN(T_COMMA),
+ PACK_TOKEN(T_ELLIPSIS),
+ PACK_TOKEN(T_SEMICOLON)
}
};
- unsigned char *match;
- int x;
-
match = memchr(&tab, yytext[0], sizeof tab[0]);
- x = match[sizeof tab[0]];
-
- if (T_VOID >= 256)
- x += 256;
- return x;
+ 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 ret = cdecl__to_keyword(yytext, yyleng, yyextra);
- if (ret == T_IDENT) {
+ int len = yyleng, tok;
+ unsigned x;
+
+ x = cdecl__to_keyword(yytext, len, yyextra);
+ yylval->spectype = UNPACK_SPEC(x & 0xff);
+ if ((tok = (x >> 8)) == PACK_TOKEN(T_IDENT)) {
/*
* Our IDENT pattern includes hyphens so we can match
* "variable-length" as a keyword. In all other cases a
* downsides.
*/
#if 1
- if ((c = strchr(yytext, '-')))
+ if ((c = memchr(yytext, '-', len)))
goto invalid_char;
#else
yyless(strcspn(yytext, "-"));
#endif
- dup_token();
+ if (!(yylval->item = cdecl__alloc_item(len+1)))
+ return T_LEX_ERROR;
+ memcpy(yylval->item->s, yytext, len+1);
}
- return ret;
+ return UNPACK_TOKEN(tok);
}
[[:space:]]+