testlang_conf.l revision 1.13 1 1.1 blymn %{
2 1.13 rillig /* $NetBSD: testlang_conf.l,v 1.13 2021/02/07 19:49:32 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.1 blymn PCHAR (\\.|[^ \t\n])
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.1 blymn
168 1.1 blymn %x incl
169 1.5 joerg %option noinput nounput
170 1.1 blymn
171 1.1 blymn %%
172 1.1 blymn
173 1.1 blymn include BEGIN(incl);
174 1.1 blymn
175 1.10 rillig <incl>[ \t]* /* eat the whitespace */
176 1.10 rillig <incl>[^ \t\n]+ { /* got the include file name */
177 1.1 blymn char inc_file[MAXPATHLEN];
178 1.1 blymn
179 1.1 blymn if (include_ptr > MAX_INCLUDES) {
180 1.1 blymn fprintf(stderr,
181 1.1 blymn "Maximum number of nested includes exceeded "
182 1.4 christos "at line %zu of file %s\n", line, cur_file);
183 1.1 blymn exit(2);
184 1.1 blymn }
185 1.1 blymn
186 1.1 blymn if (yytext[0] != '/') {
187 1.1 blymn if (strlcpy(inc_file, include_path, sizeof(inc_file))
188 1.1 blymn >= sizeof(inc_file))
189 1.1 blymn err(2, "CHECK_PATH too long");
190 1.1 blymn if ((include_path[strlen(include_path) - 1] != '/') &&
191 1.1 blymn ((strlcat(inc_file, "/", sizeof(inc_file))
192 1.1 blymn >= sizeof(inc_file))))
193 1.1 blymn err(2, "Could not append / to include file path");
194 1.1 blymn } else {
195 1.1 blymn inc_file[0] = '\0';
196 1.1 blymn }
197 1.1 blymn
198 1.1 blymn if (strlcat(inc_file, yytext, sizeof(inc_file))
199 1.1 blymn >= sizeof(inc_file))
200 1.1 blymn err(2, "Path to include file path overflowed");
201 1.1 blymn
202 1.1 blymn yyin = fopen(inc_file, "r" );
203 1.1 blymn
204 1.4 christos if (!yyin)
205 1.4 christos err(1, "Error opening %s", inc_file);
206 1.1 blymn
207 1.1 blymn yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
208 1.1 blymn
209 1.1 blymn include_stack[include_ptr] = line;
210 1.1 blymn include_files[include_ptr++] = cur_file;
211 1.6 joerg cur_file = strdup(inc_file);
212 1.1 blymn if (cur_file == NULL)
213 1.1 blymn err(2, "Cannot allocate new include file string");
214 1.1 blymn line = 0;
215 1.1 blymn BEGIN(INITIAL);
216 1.1 blymn }
217 1.1 blymn
218 1.1 blymn <<EOF>> {
219 1.1 blymn yypop_buffer_state();
220 1.1 blymn
221 1.10 rillig if (!YY_CURRENT_BUFFER)
222 1.1 blymn yyterminate();
223 1.1 blymn
224 1.1 blymn if (--include_ptr < 0)
225 1.1 blymn err(2, "Include stack underflow");
226 1.1 blymn
227 1.1 blymn free(cur_file);
228 1.1 blymn cur_file = include_files[include_ptr];
229 1.1 blymn line = include_stack[include_ptr];
230 1.1 blymn }
231 1.1 blymn
232 1.10 rillig {ASSIGN} return ASSIGN;
233 1.10 rillig {CALL2} return CALL2;
234 1.10 rillig {CALL3} return CALL3;
235 1.10 rillig {CALL4} return CALL4;
236 1.10 rillig {CALL} return CALL;
237 1.10 rillig {CHECK} return CHECK;
238 1.10 rillig {DELAY} return DELAY;
239 1.10 rillig {INPUT} return INPUT;
240 1.10 rillig {NOINPUT} return NOINPUT;
241 1.10 rillig {COMPARE} return COMPARE;
242 1.10 rillig {COMPAREND} return COMPAREND;
243 1.10 rillig {NON_NULL} return NON_NULL;
244 1.10 rillig {NULL_RET} return NULL_RET;
245 1.10 rillig {OK_RET} return OK_RET;
246 1.10 rillig {ERR_RET} return ERR_RET;
247 1.10 rillig {MULTIPLIER} return MULTIPLIER;
248 1.10 rillig {CCHAR} return CCHAR;
249 1.10 rillig {WCHAR} return WCHAR;
250 1.10 rillig {OR} return OR;
251 1.12 rillig {LPAREN} return LPAREN;
252 1.12 rillig {RPAREN} return RPAREN;
253 1.12 rillig {LBRACK} return LBRACK;
254 1.12 rillig {RBRACK} return RBRACK;
255 1.8 blymn
256 1.1 blymn {HEX} {
257 1.1 blymn /* Hex value, convert to decimal and return numeric */
258 1.1 blymn unsigned long val;
259 1.1 blymn
260 1.1 blymn if (sscanf(yytext, "%lx", &val) != 1)
261 1.1 blymn err(1, "Bad hex conversion");
262 1.1 blymn
263 1.1 blymn asprintf(&yylval.string, "%ld", val);
264 1.1 blymn return numeric;
265 1.1 blymn }
266 1.1 blymn
267 1.10 rillig {numeric} {
268 1.1 blymn if ((yylval.string = strdup(yytext)) == NULL)
269 1.1 blymn err(1, "Cannot allocate numeric string");
270 1.1 blymn return numeric;
271 1.10 rillig }
272 1.1 blymn
273 1.1 blymn {VARNAME} {
274 1.1 blymn if ((yylval.string = strdup(yytext)) == NULL)
275 1.1 blymn err(1, "Cannot allocate string for varname");
276 1.1 blymn return VARNAME;
277 1.1 blymn }
278 1.1 blymn
279 1.1 blymn {FILENAME} {
280 1.1 blymn size_t len;
281 1.1 blymn
282 1.1 blymn if ((yylval.string = dequote(yytext, &len)) == NULL)
283 1.1 blymn err(1, "Cannot allocate filename string");
284 1.1 blymn return FILENAME;
285 1.1 blymn }
286 1.1 blymn
287 1.1 blymn /* path */
288 1.1 blymn \/{PCHAR}+ {
289 1.1 blymn size_t len;
290 1.1 blymn if ((yylval.string = dequote(yytext, &len)) == NULL)
291 1.1 blymn err(1, "Cannot allocate string");
292 1.1 blymn return PATH;
293 1.1 blymn }
294 1.1 blymn
295 1.1 blymn \'{STRING}\' {
296 1.1 blymn char *p;
297 1.1 blymn size_t len;
298 1.1 blymn
299 1.8 blymn if ((yylval.retval = malloc(sizeof(ct_data_t))) == NULL)
300 1.1 blymn err(1, "Cannot allocate return struct");
301 1.1 blymn p = yytext;
302 1.1 blymn p++; /* skip the leading ' */
303 1.8 blymn if ((yylval.retval->data_value = dequote(p, &len))
304 1.1 blymn == NULL)
305 1.1 blymn err(1, "Cannot allocate string");
306 1.1 blymn
307 1.8 blymn yylval.retval->data_type = data_byte;
308 1.1 blymn /* trim trailing ' */
309 1.8 blymn yylval.retval->data_len = len - 1;
310 1.1 blymn return BYTE;
311 1.1 blymn }
312 1.1 blymn
313 1.1 blymn \`{STRING}\` {
314 1.1 blymn char *p, *str;
315 1.1 blymn size_t len, chlen;
316 1.4 christos size_t i;
317 1.1 blymn chtype *rv;
318 1.1 blymn
319 1.8 blymn if ((yylval.retval = malloc(sizeof(ct_data_t))) == NULL)
320 1.1 blymn err(1, "Cannot allocate return struct");
321 1.1 blymn p = yytext;
322 1.9 blymn p++; /* skip the leading ` */
323 1.1 blymn if ((str = dequote(p, &len)) == NULL)
324 1.1 blymn err(1, "Cannot allocate string");
325 1.1 blymn len--; /* trim trailing ` */
326 1.1 blymn if ((len % 2) != 0)
327 1.1 blymn len--;
328 1.1 blymn
329 1.1 blymn chlen = ((len / 2) + 1) * sizeof(chtype);
330 1.8 blymn if ((yylval.retval->data_value = malloc(chlen))
331 1.1 blymn == NULL)
332 1.1 blymn err(1, "Cannot allocate chtype array");
333 1.1 blymn
334 1.8 blymn rv = yylval.retval->data_value;
335 1.1 blymn for (i = 0; i < len; i += 2)
336 1.1 blymn *rv++ = (str[i] << 8) | str[i+1];
337 1.1 blymn *rv = __NORMAL | '\0'; /* terminates chtype array */
338 1.8 blymn yylval.retval->data_type = data_byte;
339 1.8 blymn yylval.retval->data_len = chlen;
340 1.1 blymn return BYTE;
341 1.1 blymn }
342 1.1 blymn
343 1.1 blymn \"{STRING}\" {
344 1.1 blymn char *p;
345 1.1 blymn size_t len;
346 1.1 blymn
347 1.1 blymn p = yytext;
348 1.1 blymn p++; /* skip the leading " */
349 1.1 blymn if ((yylval.string = dequote(p, &len)) == NULL)
350 1.1 blymn err(1, "Cannot allocate string");
351 1.1 blymn
352 1.1 blymn /* remove trailing " */
353 1.1 blymn yylval.string[len - 1] = '\0';
354 1.1 blymn return STRING;
355 1.1 blymn }
356 1.1 blymn
357 1.1 blymn \${VARNAME} {
358 1.1 blymn char *p;
359 1.1 blymn
360 1.1 blymn p = yytext;
361 1.1 blymn p++; /* skip $ before var name */
362 1.1 blymn if ((yylval.string = strdup(p)) == NULL)
363 1.1 blymn err(1, "Cannot allocate string for varname");
364 1.1 blymn return VARIABLE;
365 1.1 blymn }
366 1.10 rillig
367 1.11 rillig /* whitespace, comments */
368 1.1 blymn [ \t\r] |
369 1.1 blymn #.* ;
370 1.11 rillig
371 1.11 rillig ^[ \t\r]*#.*\n |
372 1.1 blymn \\\n |
373 1.10 rillig ^\n line++;
374 1.1 blymn
375 1.1 blymn /* eol on a line with data. need to process, return eol */
376 1.11 rillig #.*\n |
377 1.1 blymn \n {
378 1.1 blymn line++;
379 1.1 blymn return EOL;
380 1.1 blymn }
381 1.1 blymn
382 1.1 blymn . {
383 1.10 rillig /* FIXME: report syntax error */
384 1.1 blymn }
385 1.1 blymn
386 1.1 blymn %%
387 1.1 blymn
388 1.1 blymn int
389 1.1 blymn yywrap(void)
390 1.1 blymn {
391 1.1 blymn return 1;
392 1.1 blymn }
393