testlang_conf.l revision 1.16 1 1.1 blymn %{
2 1.16 rillig /* $NetBSD: testlang_conf.l,v 1.16 2021/02/07 20:40:05 rillig Exp $ */
3 1.1 blymn
4 1.1 blymn /*-
5 1.1 blymn * Copyright 2009 Brett Lymn <blymn (at) NetBSD.org>
6 1.1 blymn *
7 1.1 blymn * All rights reserved.
8 1.1 blymn *
9 1.1 blymn * This code has been donated to The NetBSD Foundation by the Author.
10 1.1 blymn *
11 1.1 blymn * Redistribution and use in source and binary forms, with or without
12 1.1 blymn * modification, are permitted provided that the following conditions
13 1.1 blymn * are met:
14 1.1 blymn * 1. Redistributions of source code must retain the above copyright
15 1.1 blymn * notice, this list of conditions and the following disclaimer.
16 1.1 blymn * 2. The name of the author may not be used to endorse or promote products
17 1.1 blymn * derived from this software withough specific prior written permission
18 1.1 blymn *
19 1.1 blymn * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 1.1 blymn * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 1.1 blymn * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 1.1 blymn * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 1.1 blymn * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 1.1 blymn * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 1.1 blymn * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 1.1 blymn * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 1.1 blymn * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 1.1 blymn * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 1.1 blymn *
30 1.1 blymn *
31 1.1 blymn */
32 1.1 blymn
33 1.1 blymn #include <curses.h>
34 1.3 christos #include <ctype.h>
35 1.1 blymn #include <stdio.h>
36 1.1 blymn #include <stdlib.h>
37 1.1 blymn #include <string.h>
38 1.1 blymn #include <sys/param.h>
39 1.1 blymn #include <err.h>
40 1.1 blymn #include "returns.h"
41 1.1 blymn #include "testlang_parse.h"
42 1.1 blymn
43 1.1 blymn #define MAX_INCLUDES 32 /* limit for the number of nested includes */
44 1.1 blymn
45 1.1 blymn int yylex(void);
46 1.1 blymn
47 1.1 blymn extern size_t line;
48 1.1 blymn extern char *include_path; /* from director.c */
49 1.1 blymn extern char *cur_file; /* from director.c */
50 1.1 blymn
51 1.1 blymn static int include_stack[MAX_INCLUDES];
52 1.1 blymn static char *include_files[MAX_INCLUDES];
53 1.1 blymn static int include_ptr = 0;
54 1.1 blymn
55 1.1 blymn static char *
56 1.1 blymn dequote(const char *s, size_t *len)
57 1.1 blymn {
58 1.4 christos const unsigned char *p;
59 1.4 christos char *buf, *q;
60 1.1 blymn
61 1.1 blymn *len = 0;
62 1.4 christos p = (const unsigned char *)s;
63 1.1 blymn while (*p) {
64 1.1 blymn if (*p == '\\' && *(p+1)) {
65 1.1 blymn if (isdigit(*(p+1)) && *(p+2) && isdigit(*(p+2)) &&
66 1.1 blymn *(p+3) && isdigit(*(p+3)))
67 1.1 blymn p += 3;
68 1.1 blymn else
69 1.1 blymn ++p;
70 1.1 blymn }
71 1.1 blymn ++(*len);
72 1.1 blymn ++p;
73 1.1 blymn }
74 1.1 blymn
75 1.1 blymn buf = malloc(*len + 1);
76 1.1 blymn if (buf == NULL)
77 1.1 blymn return NULL;
78 1.1 blymn
79 1.4 christos p = (const unsigned char *)s;
80 1.1 blymn q = buf;
81 1.1 blymn while (*p) {
82 1.1 blymn if (*p == '\\' && *(p+1)) {
83 1.1 blymn ++p;
84 1.1 blymn if (isdigit(*p)) {
85 1.1 blymn if (*(p+1) && isdigit(*(p+1)) && *(p+2) &&
86 1.1 blymn isdigit(*(p+2))) {
87 1.1 blymn *q++ = ((*p - '0') * 8 + (*(p+1) - '0')) * 8 + (*(p+2) - '0');
88 1.1 blymn p += 3;
89 1.1 blymn } else {
90 1.1 blymn *q++ = *p++;
91 1.1 blymn }
92 1.1 blymn } else {
93 1.1 blymn switch (*p) {
94 1.1 blymn case 'e':
95 1.1 blymn /* escape */
96 1.1 blymn *q++ = '\e';
97 1.1 blymn p++;
98 1.1 blymn break;
99 1.1 blymn
100 1.1 blymn case 'n':
101 1.1 blymn /* newline */
102 1.1 blymn *q++ = '\n';
103 1.1 blymn p++;
104 1.1 blymn break;
105 1.1 blymn
106 1.7 blymn case 'r':
107 1.7 blymn /* carriage return */
108 1.7 blymn *q++ = '\r';
109 1.7 blymn p++;
110 1.7 blymn break;
111 1.7 blymn
112 1.1 blymn case 't':
113 1.1 blymn /* tab */
114 1.1 blymn *q++ = '\t';
115 1.1 blymn p++;
116 1.1 blymn break;
117 1.1 blymn
118 1.1 blymn case '\\':
119 1.1 blymn /* backslash */
120 1.1 blymn *q++ = '\\';
121 1.1 blymn p++;
122 1.1 blymn break;
123 1.1 blymn
124 1.1 blymn default:
125 1.1 blymn *q++ = *p++;
126 1.1 blymn }
127 1.1 blymn }
128 1.1 blymn } else
129 1.1 blymn *q++ = *p++;
130 1.1 blymn }
131 1.1 blymn *q++ = '\0';
132 1.1 blymn
133 1.1 blymn return buf;
134 1.1 blymn }
135 1.1 blymn %}
136 1.1 blymn
137 1.1 blymn HEX 0[xX][0-9a-zA-Z]+
138 1.1 blymn STRING [0-9a-z!#-&(-^ \t%._\\]+
139 1.1 blymn numeric [-0-9]+
140 1.15 rillig PCHAR (\\.|[!-~])
141 1.13 rillig ASSIGN assign
142 1.13 rillig CALL2 call2
143 1.13 rillig CALL3 call3
144 1.13 rillig CALL4 call4
145 1.13 rillig CALL call
146 1.13 rillig CHECK check
147 1.13 rillig DELAY delay
148 1.13 rillig INPUT input
149 1.13 rillig NOINPUT noinput
150 1.13 rillig OK_RET OK
151 1.13 rillig ERR_RET ERR
152 1.13 rillig COMPARE compare
153 1.13 rillig COMPAREND comparend
154 1.1 blymn FILENAME [A-Za-z0-9.][A-Za-z0-9./_-]+
155 1.1 blymn VARNAME [A-Za-z][A-Za-z0-9_-]+
156 1.1 blymn NULL_RET NULL
157 1.1 blymn NON_NULL NON_NULL
158 1.13 rillig CCHAR cchar
159 1.13 rillig WCHAR wchar
160 1.1 blymn BYTE BYTE
161 1.1 blymn OR \|
162 1.12 rillig LPAREN \(
163 1.12 rillig RPAREN \)
164 1.12 rillig LBRACK \[
165 1.12 rillig RBRACK \]
166 1.8 blymn MULTIPLIER \*
167 1.16 rillig COMMA ,
168 1.1 blymn
169 1.1 blymn %x incl
170 1.5 joerg %option noinput nounput
171 1.1 blymn
172 1.1 blymn %%
173 1.1 blymn
174 1.1 blymn include BEGIN(incl);
175 1.1 blymn
176 1.10 rillig <incl>[ \t]* /* eat the whitespace */
177 1.10 rillig <incl>[^ \t\n]+ { /* got the include file name */
178 1.1 blymn char inc_file[MAXPATHLEN];
179 1.1 blymn
180 1.1 blymn if (include_ptr > MAX_INCLUDES) {
181 1.1 blymn fprintf(stderr,
182 1.1 blymn "Maximum number of nested includes exceeded "
183 1.4 christos "at line %zu of file %s\n", line, cur_file);
184 1.1 blymn exit(2);
185 1.1 blymn }
186 1.1 blymn
187 1.1 blymn if (yytext[0] != '/') {
188 1.1 blymn if (strlcpy(inc_file, include_path, sizeof(inc_file))
189 1.1 blymn >= sizeof(inc_file))
190 1.1 blymn err(2, "CHECK_PATH too long");
191 1.1 blymn if ((include_path[strlen(include_path) - 1] != '/') &&
192 1.1 blymn ((strlcat(inc_file, "/", sizeof(inc_file))
193 1.1 blymn >= sizeof(inc_file))))
194 1.1 blymn err(2, "Could not append / to include file path");
195 1.1 blymn } else {
196 1.1 blymn inc_file[0] = '\0';
197 1.1 blymn }
198 1.1 blymn
199 1.1 blymn if (strlcat(inc_file, yytext, sizeof(inc_file))
200 1.1 blymn >= sizeof(inc_file))
201 1.1 blymn err(2, "Path to include file path overflowed");
202 1.1 blymn
203 1.1 blymn yyin = fopen(inc_file, "r" );
204 1.1 blymn
205 1.4 christos if (!yyin)
206 1.4 christos err(1, "Error opening %s", inc_file);
207 1.1 blymn
208 1.1 blymn yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
209 1.1 blymn
210 1.1 blymn include_stack[include_ptr] = line;
211 1.1 blymn include_files[include_ptr++] = cur_file;
212 1.6 joerg cur_file = strdup(inc_file);
213 1.1 blymn if (cur_file == NULL)
214 1.1 blymn err(2, "Cannot allocate new include file string");
215 1.1 blymn line = 0;
216 1.1 blymn BEGIN(INITIAL);
217 1.1 blymn }
218 1.1 blymn
219 1.1 blymn <<EOF>> {
220 1.1 blymn yypop_buffer_state();
221 1.1 blymn
222 1.10 rillig if (!YY_CURRENT_BUFFER)
223 1.1 blymn yyterminate();
224 1.1 blymn
225 1.1 blymn if (--include_ptr < 0)
226 1.1 blymn err(2, "Include stack underflow");
227 1.1 blymn
228 1.1 blymn free(cur_file);
229 1.1 blymn cur_file = include_files[include_ptr];
230 1.1 blymn line = include_stack[include_ptr];
231 1.1 blymn }
232 1.1 blymn
233 1.10 rillig {ASSIGN} return ASSIGN;
234 1.10 rillig {CALL2} return CALL2;
235 1.10 rillig {CALL3} return CALL3;
236 1.10 rillig {CALL4} return CALL4;
237 1.10 rillig {CALL} return CALL;
238 1.10 rillig {CHECK} return CHECK;
239 1.10 rillig {DELAY} return DELAY;
240 1.10 rillig {INPUT} return INPUT;
241 1.10 rillig {NOINPUT} return NOINPUT;
242 1.10 rillig {COMPARE} return COMPARE;
243 1.10 rillig {COMPAREND} return COMPAREND;
244 1.10 rillig {NON_NULL} return NON_NULL;
245 1.10 rillig {NULL_RET} return NULL_RET;
246 1.10 rillig {OK_RET} return OK_RET;
247 1.10 rillig {ERR_RET} return ERR_RET;
248 1.10 rillig {MULTIPLIER} return MULTIPLIER;
249 1.16 rillig {COMMA} return COMMA;
250 1.10 rillig {CCHAR} return CCHAR;
251 1.10 rillig {WCHAR} return WCHAR;
252 1.10 rillig {OR} return OR;
253 1.12 rillig {LPAREN} return LPAREN;
254 1.12 rillig {RPAREN} return RPAREN;
255 1.12 rillig {LBRACK} return LBRACK;
256 1.12 rillig {RBRACK} return RBRACK;
257 1.8 blymn
258 1.1 blymn {HEX} {
259 1.1 blymn /* Hex value, convert to decimal and return numeric */
260 1.1 blymn unsigned long val;
261 1.1 blymn
262 1.1 blymn if (sscanf(yytext, "%lx", &val) != 1)
263 1.1 blymn err(1, "Bad hex conversion");
264 1.1 blymn
265 1.1 blymn asprintf(&yylval.string, "%ld", val);
266 1.1 blymn return numeric;
267 1.1 blymn }
268 1.1 blymn
269 1.10 rillig {numeric} {
270 1.1 blymn if ((yylval.string = strdup(yytext)) == NULL)
271 1.1 blymn err(1, "Cannot allocate numeric string");
272 1.1 blymn return numeric;
273 1.10 rillig }
274 1.1 blymn
275 1.1 blymn {VARNAME} {
276 1.1 blymn if ((yylval.string = strdup(yytext)) == NULL)
277 1.1 blymn err(1, "Cannot allocate string for varname");
278 1.1 blymn return VARNAME;
279 1.1 blymn }
280 1.1 blymn
281 1.1 blymn {FILENAME} {
282 1.1 blymn size_t len;
283 1.1 blymn
284 1.1 blymn if ((yylval.string = dequote(yytext, &len)) == NULL)
285 1.1 blymn err(1, "Cannot allocate filename string");
286 1.1 blymn return FILENAME;
287 1.1 blymn }
288 1.1 blymn
289 1.1 blymn /* path */
290 1.1 blymn \/{PCHAR}+ {
291 1.1 blymn size_t len;
292 1.1 blymn if ((yylval.string = dequote(yytext, &len)) == NULL)
293 1.1 blymn err(1, "Cannot allocate string");
294 1.1 blymn return PATH;
295 1.1 blymn }
296 1.1 blymn
297 1.1 blymn \'{STRING}\' {
298 1.1 blymn char *p;
299 1.1 blymn size_t len;
300 1.1 blymn
301 1.8 blymn if ((yylval.retval = malloc(sizeof(ct_data_t))) == NULL)
302 1.1 blymn err(1, "Cannot allocate return struct");
303 1.1 blymn p = yytext;
304 1.1 blymn p++; /* skip the leading ' */
305 1.8 blymn if ((yylval.retval->data_value = dequote(p, &len))
306 1.1 blymn == NULL)
307 1.1 blymn err(1, "Cannot allocate string");
308 1.1 blymn
309 1.8 blymn yylval.retval->data_type = data_byte;
310 1.1 blymn /* trim trailing ' */
311 1.8 blymn yylval.retval->data_len = len - 1;
312 1.1 blymn return BYTE;
313 1.1 blymn }
314 1.1 blymn
315 1.1 blymn \`{STRING}\` {
316 1.1 blymn char *p, *str;
317 1.1 blymn size_t len, chlen;
318 1.4 christos size_t i;
319 1.1 blymn chtype *rv;
320 1.1 blymn
321 1.8 blymn if ((yylval.retval = malloc(sizeof(ct_data_t))) == NULL)
322 1.1 blymn err(1, "Cannot allocate return struct");
323 1.1 blymn p = yytext;
324 1.9 blymn p++; /* skip the leading ` */
325 1.1 blymn if ((str = dequote(p, &len)) == NULL)
326 1.1 blymn err(1, "Cannot allocate string");
327 1.1 blymn len--; /* trim trailing ` */
328 1.1 blymn if ((len % 2) != 0)
329 1.1 blymn len--;
330 1.1 blymn
331 1.1 blymn chlen = ((len / 2) + 1) * sizeof(chtype);
332 1.8 blymn if ((yylval.retval->data_value = malloc(chlen))
333 1.1 blymn == NULL)
334 1.1 blymn err(1, "Cannot allocate chtype array");
335 1.1 blymn
336 1.8 blymn rv = yylval.retval->data_value;
337 1.1 blymn for (i = 0; i < len; i += 2)
338 1.1 blymn *rv++ = (str[i] << 8) | str[i+1];
339 1.1 blymn *rv = __NORMAL | '\0'; /* terminates chtype array */
340 1.8 blymn yylval.retval->data_type = data_byte;
341 1.8 blymn yylval.retval->data_len = chlen;
342 1.1 blymn return BYTE;
343 1.1 blymn }
344 1.1 blymn
345 1.1 blymn \"{STRING}\" {
346 1.1 blymn char *p;
347 1.1 blymn size_t len;
348 1.1 blymn
349 1.1 blymn p = yytext;
350 1.1 blymn p++; /* skip the leading " */
351 1.1 blymn if ((yylval.string = dequote(p, &len)) == NULL)
352 1.1 blymn err(1, "Cannot allocate string");
353 1.1 blymn
354 1.1 blymn /* remove trailing " */
355 1.1 blymn yylval.string[len - 1] = '\0';
356 1.1 blymn return STRING;
357 1.1 blymn }
358 1.1 blymn
359 1.1 blymn \${VARNAME} {
360 1.1 blymn char *p;
361 1.1 blymn
362 1.1 blymn p = yytext;
363 1.1 blymn p++; /* skip $ before var name */
364 1.1 blymn if ((yylval.string = strdup(p)) == NULL)
365 1.1 blymn err(1, "Cannot allocate string for varname");
366 1.1 blymn return VARIABLE;
367 1.1 blymn }
368 1.10 rillig
369 1.11 rillig /* whitespace, comments */
370 1.1 blymn [ \t\r] |
371 1.1 blymn #.* ;
372 1.11 rillig
373 1.11 rillig ^[ \t\r]*#.*\n |
374 1.1 blymn \\\n |
375 1.10 rillig ^\n line++;
376 1.1 blymn
377 1.1 blymn /* eol on a line with data. need to process, return eol */
378 1.11 rillig #.*\n |
379 1.1 blymn \n {
380 1.1 blymn line++;
381 1.1 blymn return EOL;
382 1.1 blymn }
383 1.1 blymn
384 1.1 blymn . {
385 1.14 rillig if (isprint((unsigned char)yytext[0]))
386 1.14 rillig errx(1, "%s:%zu: Invalid character '%c'",
387 1.14 rillig cur_file, line + 1, yytext[0]);
388 1.14 rillig else
389 1.14 rillig errx(1, "%s:%zu: Invalid character '0x%02x'",
390 1.14 rillig cur_file, line + 1, yytext[0]);
391 1.1 blymn }
392 1.1 blymn
393 1.1 blymn %%
394 1.1 blymn
395 1.1 blymn int
396 1.1 blymn yywrap(void)
397 1.1 blymn {
398 1.1 blymn return 1;
399 1.1 blymn }
400