X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/d0981bca9268f175a22f10b537c0099fb76921fd..HEAD:/src/scan.l diff --git a/src/scan.l b/src/scan.l index 767ba22..5d460ed 100644 --- a/src/scan.l +++ b/src/scan.l @@ -1,7 +1,7 @@ %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 @@ -18,7 +18,63 @@ */ #include +#include #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 + +/* + * The flex-generated scanner defines a huge pile of external functions of + * which we use almost none elsewhere. Explicitly declare any unneeded + * functions static, which allows better optimization (especially wrt. + * dead code elimination). + */ +#if !cdecl__yyIN_HEADER + +#if __GNUC__ +# define static __attribute__((__unused__)) static +#endif + +static struct yy_buffer_state *cdecl__yy_create_buffer(FILE *, int, void *); +static struct yy_buffer_state *cdecl__yy_scan_bytes(const char *, int, void *); +static struct yy_buffer_state *cdecl__yy_scan_buffer(char *, size_t, void *); +static void cdecl__yy_switch_to_buffer(struct yy_buffer_state *, void *); +static void cdecl__yy_flush_buffer(struct yy_buffer_state *, void *); +static void cdecl__yypush_buffer_state(struct yy_buffer_state *, void *); +static void cdecl__yypop_buffer_state(void *); +static void cdecl__yyrestart(FILE *, void *); +static int cdecl__yylex_init(void **); + +static int cdecl__yyget_extra(void *); +static YYLTYPE *cdecl__yyget_lloc(void *); +static YYSTYPE *cdecl__yyget_lval(void *); +static char *cdecl__yyget_text(void *); +static FILE *cdecl__yyget_out(void *); +static FILE *cdecl__yyget_in(void *); +static int cdecl__yyget_debug(void *); +static int cdecl__yyget_lineno(void *); +static int cdecl__yyget_column(void *); +static int cdecl__yyget_leng(void *); + +static void cdecl__yyset_extra(int, void *); +static void cdecl__yyset_lloc(YYLTYPE *, void *); +static void cdecl__yyset_lval(YYSTYPE *, void *); +static void cdecl__yyset_in(FILE *, void *); +static void cdecl__yyset_out(FILE *, void *); +static void cdecl__yyset_debug(int, void *); +static void cdecl__yyset_lineno(int, void *); +static void cdecl__yyset_column(int, void *); + +static void *cdecl__yyrealloc(void *, size_t, void *); +static void *cdecl__yyalloc(size_t, void *); +static void cdecl__yyfree(void *, void *); + +#undef static + +#endif } %option nodefault noyywrap bison-locations reentrant never-interactive @@ -30,30 +86,7 @@ #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 */ -#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) { @@ -118,17 +151,12 @@ static void to_readable_ch(char *dst, char c) %} IDENT [_[:alpha:]][-_[:alnum:]]* -INTEGER 0x[[:xdigit:]]+|0[0-7]+|[[:digit:]]+ %% %{ + int intconv_base; char *c; - - if (yyextra > 0) { - yyextra = -yyextra; - return T_ENGLISH; - } %} "..."|[][;*(),] { @@ -151,27 +179,35 @@ INTEGER 0x[[:xdigit:]]+|0[0-7]+|[[: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; + cdecl_uintmax 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} { - unsigned x = cdecl__to_keyword(yytext, yyleng, yyextra); - int tok; + 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)) { /* @@ -185,12 +221,14 @@ INTEGER 0x[[:xdigit:]]+|0[0-7]+|[[:digit:]]+ * 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 UNPACK_TOKEN(tok); } @@ -202,6 +240,6 @@ INTEGER 0x[[:xdigit:]]+|0[0-7]+|[[:digit:]]+ c = yytext; invalid_char: to_readable_ch(buf, *c); - cdecl__err(CDECL_ENOPARSE, _("syntax error, unexpected %s"), buf); + cdecl__err(_("syntax error, unexpected %s"), buf); return T_LEX_ERROR; }