testlang_conf.l revision 1.11 1 1.1 blymn %{
2 1.11 rillig /* $NetBSD: testlang_conf.l,v 1.11 2021/02/07 12:05:36 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.1 blymn ASSIGN [aA][sS][sS][iI][gG][nN]
142 1.1 blymn CALL2 [cC][aA][lL][lL]2
143 1.1 blymn CALL3 [cC][aA][lL][lL]3
144 1.1 blymn CALL4 [cC][aA][lL][lL]4
145 1.1 blymn CALL [cC][aA][lL][lL]
146 1.1 blymn CHECK [cC][hH][eE][cC][kK]
147 1.1 blymn DELAY [dD][eE][lL][aA][yY]
148 1.1 blymn INPUT [iI][nN][pP][uU][tT]
149 1.1 blymn NOINPUT [nN][oO][iI][nN][pP][uU][tT]
150 1.1 blymn OK_RET [oO][kK]
151 1.1 blymn ERR_RET [eE][rR][rR]
152 1.1 blymn COMPARE [cC][oO][mM][pP][aA][rR][eE]
153 1.1 blymn COMPAREND [cC][oO][mM][pP][aA][rR][eE][Nn][Dd]
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.8 blymn CCHAR [cC][cC][hH][aA][rR]
159 1.9 blymn WCHAR [wW][cC][hH][aA][rR]
160 1.1 blymn BYTE BYTE
161 1.1 blymn OR \|
162 1.1 blymn LHB \(
163 1.1 blymn RHB \)
164 1.8 blymn LHSB \[
165 1.8 blymn RHSB \]
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.10 rillig {LHB} return LHB;
252 1.10 rillig {RHB} return RHB;
253 1.10 rillig {LHSB} return LHSB;
254 1.10 rillig {RHSB} return RHSB;
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