3 * Scanner for C declarations.
4 * Copyright © 2011, 2021, 2023 Nick Bowler
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
24 %option nodefault noyywrap bison-locations reentrant never-interactive
25 %option extra-type="_Bool"
26 %option prefix="cdecl__yy"
30 #include "cdecl-internal.h"
35 /* Best case, implementation provides strtoumax. */
36 # define STRTOUMAX strtoumax
38 /* Fall back to strtoull, with possibly reduced range. */
39 #define STRTOUMAX strtoull
41 /* HP-UX 11 has __strtoull in <inttypes.h> */
42 #define STRTOUMAX __strtoull
44 /* Fall back to strtoul, with possibly reduced range. */
45 #define STRTOUMAX strtoul
48 #define dup_token() do { \
49 yylval->strval = malloc(yyleng+1); \
50 if (!yylval->strval) { \
51 cdecl__errmsg(CDECL__ENOMEM); \
54 strcpy(yylval->strval, yytext); \
57 static char *to_octal(char *dst, unsigned val)
61 for (i = 0; i < 3; i++) {
62 *dst++ = '0' + ((val >> 6) & 7u);
70 * Convert a single character to a C-style character constant, including quote
71 * characters. At most 7 bytes are written to the buffer for the longest
72 * octal encoding, e.g., '\177'
74 static void to_readable_ch(char *dst, char c)
81 * The 7 standard C control characters are contiguous in ASCII,
82 * permitting a simple and compact lookup table; separating their
83 * handling from backslash and quote characters hopefully allows
84 * the compiler to recognize that.
87 case '\a': i = 0; break;
88 case '\b': i = 1; break;
89 case '\t': i = 2; break;
90 case '\n': i = 3; break;
91 case '\v': i = 4; break;
92 case '\f': i = 5; break;
93 case '\r': i = 6; break;
94 default: i = 7; break;
98 /* Otherwise printable characters that should still be escaped. */
100 case '\\': case '\'': esc = c; break;
107 } else if (isprint(uc)) {
111 dst = to_octal(dst, uc);
121 IDENT [_[:alpha:]][_[:alnum:]]*
122 INTEGER 0x[[:xdigit:]]+|0[0-7]+|[[:digit:]]+
134 "..." return T_ELLIPSIS;
135 ";" return T_SEMICOLON;
136 "*" return T_ASTERISK;
139 "[" return T_LBRACKET;
140 "]" return T_RBRACKET;
143 "typedef" return T_TYPEDEF;
144 "extern" return T_EXTERN;
145 "static" return T_STATIC;
146 "auto" return T_AUTO;
147 "register" return T_REGISTER;
149 "restrict" return T_RESTRICT;
150 "volatile" return T_VOLATILE;
151 "const" return T_CONST;
153 "inline" return T_INLINE;
155 "void" return T_VOID;
156 "char" return T_CHAR;
157 "short" return T_SHORT;
159 "long" return T_LONG;
160 "float" return T_FLOAT;
161 "double" return T_DOUBLE;
162 "signed" return T_SIGNED;
163 "unsigned" return T_UNSIGNED;
164 "_Bool" return T_BOOL;
165 "_Complex" return T_COMPLEX;
166 "_Imaginary" return T_IMAGINARY;
168 "struct" return T_STRUCT;
169 "union" return T_UNION;
170 "enum" return T_ENUM;
176 yylval->uintval = STRTOUMAX(yytext, &end, 0);
177 if (errno == ERANGE) {
178 cdecl__errmsg(CDECL__ERANGE);
182 cdecl__errmsg(CDECL__EBADINT);
190 "variable-length" return T_VLA;
191 "type" return T_TYPE;
192 "declare" return T_DECLARE;
193 "pointer" return T_POINTER;
194 "function" return T_FUNCTION;
195 "returning" return T_RETURNING;
196 "array" return T_ARRAY;
202 {IDENT} { dup_token(); return T_IDENT; }
208 to_readable_ch(buf, yytext[0]);
209 cdecl__err(CDECL_ENOPARSE, _("syntax error, unexpected %s"), buf);