X-Git-Url: https://git.draconx.ca/gitweb/cdecl99.git/blobdiff_plain/f64af1a757804cd18bd1731b4634e5752b9ca0ed..7df5e2a15f784ab786f56ca25d739c8b546ccde8:/src/scan.l?ds=inline
diff --git a/src/scan.l b/src/scan.l
index e59b0aa..0a4db93 100644
--- a/src/scan.l
+++ b/src/scan.l
@@ -1,7 +1,7 @@
%top{
/*
* Scanner for C declarations.
- * Copyright © 2011 Nick Bowler
+ * Copyright © 2011, 2021, 2023 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
@@ -17,25 +17,103 @@
* along with this program. If not, see .
*/
+#include
#include "parse.h"
}
-%option noyywrap bison-locations reentrant
+%option nodefault noyywrap bison-locations reentrant never-interactive
%option extra-type="_Bool"
%option prefix="cdecl__yy"
%{
-#define lex_error(msg) do { \
- cdecl__yyerror(yylloc, NULL, NULL, (msg)); \
- return T_LEX_ERROR; \
-} while(0)
+#include
+#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) \
- lex_error("failed to allocate memory"); \
+ if (!yylval->strval) { \
+ cdecl__errmsg(CDECL__ENOMEM); \
+ return T_LEX_ERROR; \
+ } \
strcpy(yylval->strval, yytext); \
} while(0)
+
+static char *to_octal(char *dst, unsigned val)
+{
+ unsigned i;
+
+ for (i = 0; i < 3; i++) {
+ *dst++ = '0' + ((val >> 6) & 7u);
+ val <<= 3;
+ }
+
+ return dst;
+}
+
+/*
+ * Convert a single character to a C-style character constant, including quote
+ * characters. At most 7 bytes are written to the buffer for the longest
+ * octal encoding, e.g., '\177'
+ */
+static void to_readable_ch(char *dst, char c)
+{
+ unsigned char uc = c;
+ unsigned i;
+ char esc;
+
+ /*
+ * The 7 standard C control characters are contiguous in ASCII,
+ * permitting a simple and compact lookup table; separating their
+ * handling from backslash and quote characters hopefully allows
+ * the compiler to recognize that.
+ */
+ switch (c) {
+ case '\a': i = 0; break;
+ case '\b': i = 1; break;
+ case '\t': i = 2; break;
+ case '\n': i = 3; break;
+ case '\v': i = 4; break;
+ case '\f': i = 5; break;
+ case '\r': i = 6; break;
+ default: i = 7; break;
+ }
+ esc = "abtnvfr"[i];
+
+ /* Otherwise printable characters that should still be escaped. */
+ switch (c) {
+ case '\\': case '\'': esc = c; break;
+ }
+
+ *dst++ = '\'';
+ if (esc) {
+ *dst++ = '\\';
+ *dst++ = esc;
+ } else if (isprint(uc)) {
+ *dst++ = c;
+ } else {
+ *dst++ = '\\';
+ dst = to_octal(dst, uc);
+ }
+ *dst++ = '\'';
+ *dst++ = 0;
+}
+
%}
%s ENGLISH
@@ -95,11 +173,15 @@ INTEGER 0x[[:xdigit:]]+|0[0-7]+|[[:digit:]]+
char *end;
errno = 0;
- yylval->uintval = strtoumax(yytext, &end, 0);
- if (errno == ERANGE)
- lex_error("integer constant out of range");
- if (*end)
- lex_error("invalid integer constant");
+ 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;
+ }
return T_UINT;
}
@@ -121,7 +203,9 @@ INTEGER 0x[[:xdigit:]]+|0[0-7]+|[[:digit:]]+
[[:space:]]+
. {
- char buf[] = "syntax error, unexpected #";
- *strchr(buf, '#') = *yytext;
- lex_error(buf);
+ char buf[8];
+
+ to_readable_ch(buf, yytext[0]);
+ cdecl__err(CDECL_ENOPARSE, _("syntax error, unexpected %s"), buf);
+ return T_LEX_ERROR;
}