testlang_conf.l revision 1.4 1 1.1 blymn %{
2 1.4 christos /* $NetBSD: testlang_conf.l,v 1.4 2011/06/11 18:03:18 christos 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.1 blymn case 't':
107 1.1 blymn /* tab */
108 1.1 blymn *q++ = '\t';
109 1.1 blymn p++;
110 1.1 blymn break;
111 1.1 blymn
112 1.1 blymn case '\\':
113 1.1 blymn /* backslash */
114 1.1 blymn *q++ = '\\';
115 1.1 blymn p++;
116 1.1 blymn break;
117 1.1 blymn
118 1.1 blymn default:
119 1.1 blymn *q++ = *p++;
120 1.1 blymn }
121 1.1 blymn }
122 1.1 blymn } else
123 1.1 blymn *q++ = *p++;
124 1.1 blymn }
125 1.1 blymn *q++ = '\0';
126 1.1 blymn
127 1.1 blymn return buf;
128 1.1 blymn }
129 1.1 blymn %}
130 1.1 blymn
131 1.1 blymn HEX 0[xX][0-9a-zA-Z]+
132 1.1 blymn STRING [0-9a-z!#-&(-^ \t%._\\]+
133 1.1 blymn numeric [-0-9]+
134 1.1 blymn PCHAR (\\.|[^ \t\n])
135 1.1 blymn ASSIGN [aA][sS][sS][iI][gG][nN]
136 1.1 blymn CALL2 [cC][aA][lL][lL]2
137 1.1 blymn CALL3 [cC][aA][lL][lL]3
138 1.1 blymn CALL4 [cC][aA][lL][lL]4
139 1.1 blymn CALL [cC][aA][lL][lL]
140 1.1 blymn CHECK [cC][hH][eE][cC][kK]
141 1.1 blymn DELAY [dD][eE][lL][aA][yY]
142 1.1 blymn INPUT [iI][nN][pP][uU][tT]
143 1.1 blymn NOINPUT [nN][oO][iI][nN][pP][uU][tT]
144 1.1 blymn OK_RET [oO][kK]
145 1.1 blymn ERR_RET [eE][rR][rR]
146 1.1 blymn COMPARE [cC][oO][mM][pP][aA][rR][eE]
147 1.1 blymn COMPAREND [cC][oO][mM][pP][aA][rR][eE][Nn][Dd]
148 1.1 blymn FILENAME [A-Za-z0-9.][A-Za-z0-9./_-]+
149 1.1 blymn VARNAME [A-Za-z][A-Za-z0-9_-]+
150 1.1 blymn NULL_RET NULL
151 1.1 blymn NON_NULL NON_NULL
152 1.1 blymn BYTE BYTE
153 1.1 blymn OR \|
154 1.1 blymn LHB \(
155 1.1 blymn RHB \)
156 1.1 blymn
157 1.1 blymn %x incl
158 1.4 christos %option nounput
159 1.1 blymn
160 1.1 blymn %%
161 1.1 blymn
162 1.1 blymn include BEGIN(incl);
163 1.1 blymn
164 1.1 blymn <incl>[ \t]* /* eat the whitespace */
165 1.1 blymn <incl>[^ \t\n]+ { /* got the include file name */
166 1.1 blymn char inc_file[MAXPATHLEN];
167 1.1 blymn
168 1.1 blymn if (include_ptr > MAX_INCLUDES) {
169 1.1 blymn fprintf(stderr,
170 1.1 blymn "Maximum number of nested includes exceeded "
171 1.4 christos "at line %zu of file %s\n", line, cur_file);
172 1.1 blymn exit(2);
173 1.1 blymn }
174 1.1 blymn
175 1.1 blymn if (yytext[0] != '/') {
176 1.1 blymn if (strlcpy(inc_file, include_path, sizeof(inc_file))
177 1.1 blymn >= sizeof(inc_file))
178 1.1 blymn err(2, "CHECK_PATH too long");
179 1.1 blymn if ((include_path[strlen(include_path) - 1] != '/') &&
180 1.1 blymn ((strlcat(inc_file, "/", sizeof(inc_file))
181 1.1 blymn >= sizeof(inc_file))))
182 1.1 blymn err(2, "Could not append / to include file path");
183 1.1 blymn } else {
184 1.1 blymn inc_file[0] = '\0';
185 1.1 blymn }
186 1.1 blymn
187 1.1 blymn if (strlcat(inc_file, yytext, sizeof(inc_file))
188 1.1 blymn >= sizeof(inc_file))
189 1.1 blymn err(2, "Path to include file path overflowed");
190 1.1 blymn
191 1.1 blymn yyin = fopen(inc_file, "r" );
192 1.1 blymn
193 1.4 christos if (!yyin)
194 1.4 christos err(1, "Error opening %s", inc_file);
195 1.1 blymn
196 1.1 blymn yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
197 1.1 blymn
198 1.1 blymn include_stack[include_ptr] = line;
199 1.1 blymn include_files[include_ptr++] = cur_file;
200 1.1 blymn cur_file = malloc(strlen(inc_file));
201 1.1 blymn if (cur_file == NULL)
202 1.1 blymn err(2, "Cannot allocate new include file string");
203 1.1 blymn
204 1.1 blymn strlcpy(cur_file, inc_file, sizeof(inc_file));
205 1.1 blymn line = 0;
206 1.1 blymn BEGIN(INITIAL);
207 1.1 blymn }
208 1.1 blymn
209 1.1 blymn <<EOF>> {
210 1.1 blymn yypop_buffer_state();
211 1.1 blymn
212 1.1 blymn if ( !YY_CURRENT_BUFFER )
213 1.1 blymn {
214 1.1 blymn yyterminate();
215 1.1 blymn }
216 1.1 blymn
217 1.1 blymn if (--include_ptr < 0)
218 1.1 blymn err(2, "Include stack underflow");
219 1.1 blymn
220 1.1 blymn free(cur_file);
221 1.1 blymn cur_file = include_files[include_ptr];
222 1.1 blymn line = include_stack[include_ptr];
223 1.1 blymn }
224 1.1 blymn
225 1.1 blymn {ASSIGN} {
226 1.1 blymn return ASSIGN;
227 1.1 blymn }
228 1.1 blymn
229 1.1 blymn {CALL2} {
230 1.1 blymn return CALL2;
231 1.1 blymn }
232 1.1 blymn
233 1.1 blymn {CALL3} {
234 1.1 blymn return CALL3;
235 1.1 blymn }
236 1.1 blymn
237 1.1 blymn {CALL4} {
238 1.1 blymn return CALL4;
239 1.1 blymn }
240 1.1 blymn
241 1.1 blymn {CALL} {
242 1.1 blymn return CALL;
243 1.1 blymn }
244 1.1 blymn
245 1.1 blymn {CHECK} {
246 1.1 blymn return CHECK;
247 1.1 blymn }
248 1.1 blymn
249 1.1 blymn {DELAY} {
250 1.1 blymn return DELAY;
251 1.1 blymn }
252 1.1 blymn
253 1.1 blymn {INPUT} {
254 1.1 blymn return INPUT;
255 1.1 blymn }
256 1.1 blymn
257 1.1 blymn {NOINPUT} {
258 1.1 blymn return NOINPUT;
259 1.1 blymn }
260 1.1 blymn
261 1.1 blymn {COMPARE} {
262 1.1 blymn return COMPARE;
263 1.1 blymn }
264 1.1 blymn
265 1.1 blymn {COMPAREND} {
266 1.1 blymn return COMPAREND;
267 1.1 blymn }
268 1.1 blymn
269 1.1 blymn {NON_NULL} {
270 1.1 blymn return NON_NULL;
271 1.1 blymn }
272 1.1 blymn
273 1.1 blymn {NULL_RET} {
274 1.1 blymn return NULL_RET;
275 1.1 blymn }
276 1.1 blymn
277 1.1 blymn {OK_RET} {
278 1.1 blymn return OK_RET;
279 1.1 blymn }
280 1.1 blymn
281 1.1 blymn {ERR_RET} {
282 1.1 blymn return ERR_RET;
283 1.1 blymn }
284 1.1 blymn
285 1.1 blymn {OR} {
286 1.1 blymn return OR;
287 1.1 blymn }
288 1.1 blymn
289 1.1 blymn {LHB} {
290 1.1 blymn return LHB;
291 1.1 blymn }
292 1.1 blymn
293 1.1 blymn {RHB} {
294 1.1 blymn return RHB;
295 1.1 blymn }
296 1.1 blymn
297 1.1 blymn {HEX} {
298 1.1 blymn /* Hex value, convert to decimal and return numeric */
299 1.1 blymn unsigned long val;
300 1.1 blymn
301 1.1 blymn if (sscanf(yytext, "%lx", &val) != 1)
302 1.1 blymn err(1, "Bad hex conversion");
303 1.1 blymn
304 1.1 blymn asprintf(&yylval.string, "%ld", val);
305 1.1 blymn return numeric;
306 1.1 blymn }
307 1.1 blymn
308 1.1 blymn
309 1.1 blymn {numeric} {
310 1.1 blymn if ((yylval.string = strdup(yytext)) == NULL)
311 1.1 blymn err(1, "Cannot allocate numeric string");
312 1.1 blymn return numeric;
313 1.1 blymn }
314 1.1 blymn
315 1.1 blymn {VARNAME} {
316 1.1 blymn if ((yylval.string = strdup(yytext)) == NULL)
317 1.1 blymn err(1, "Cannot allocate string for varname");
318 1.1 blymn return VARNAME;
319 1.1 blymn }
320 1.1 blymn
321 1.1 blymn {FILENAME} {
322 1.1 blymn size_t len;
323 1.1 blymn
324 1.1 blymn if ((yylval.string = dequote(yytext, &len)) == NULL)
325 1.1 blymn err(1, "Cannot allocate filename string");
326 1.1 blymn return FILENAME;
327 1.1 blymn }
328 1.1 blymn
329 1.1 blymn /* path */
330 1.1 blymn \/{PCHAR}+ {
331 1.1 blymn size_t len;
332 1.1 blymn if ((yylval.string = dequote(yytext, &len)) == NULL)
333 1.1 blymn err(1, "Cannot allocate string");
334 1.1 blymn return PATH;
335 1.1 blymn }
336 1.1 blymn
337 1.1 blymn \'{STRING}\' {
338 1.1 blymn char *p;
339 1.1 blymn size_t len;
340 1.1 blymn
341 1.1 blymn if ((yylval.retval = malloc(sizeof(returns_t))) == NULL)
342 1.1 blymn err(1, "Cannot allocate return struct");
343 1.1 blymn p = yytext;
344 1.1 blymn p++; /* skip the leading ' */
345 1.1 blymn if ((yylval.retval->return_value = dequote(p, &len))
346 1.1 blymn == NULL)
347 1.1 blymn err(1, "Cannot allocate string");
348 1.1 blymn
349 1.1 blymn yylval.retval->return_type = ret_byte;
350 1.1 blymn /* trim trailing ' */
351 1.1 blymn yylval.retval->return_len = len - 1;
352 1.1 blymn return BYTE;
353 1.1 blymn }
354 1.1 blymn
355 1.1 blymn \`{STRING}\` {
356 1.1 blymn char *p, *str;
357 1.1 blymn size_t len, chlen;
358 1.4 christos size_t i;
359 1.1 blymn chtype *rv;
360 1.1 blymn
361 1.1 blymn if ((yylval.retval = malloc(sizeof(returns_t))) == NULL)
362 1.1 blymn err(1, "Cannot allocate return struct");
363 1.1 blymn p = yytext;
364 1.1 blymn p++; /* skip the leading ' */
365 1.1 blymn if ((str = dequote(p, &len)) == NULL)
366 1.1 blymn err(1, "Cannot allocate string");
367 1.1 blymn len--; /* trim trailing ` */
368 1.1 blymn if ((len % 2) != 0)
369 1.1 blymn len--;
370 1.1 blymn
371 1.1 blymn chlen = ((len / 2) + 1) * sizeof(chtype);
372 1.1 blymn if ((yylval.retval->return_value = malloc(chlen))
373 1.1 blymn == NULL)
374 1.1 blymn err(1, "Cannot allocate chtype array");
375 1.1 blymn
376 1.1 blymn rv = yylval.retval->return_value;
377 1.1 blymn for (i = 0; i < len; i += 2)
378 1.1 blymn *rv++ = (str[i] << 8) | str[i+1];
379 1.1 blymn *rv = __NORMAL | '\0'; /* terminates chtype array */
380 1.1 blymn yylval.retval->return_type = ret_byte;
381 1.1 blymn yylval.retval->return_len = chlen;
382 1.1 blymn return BYTE;
383 1.1 blymn }
384 1.1 blymn
385 1.1 blymn \"{STRING}\" {
386 1.1 blymn char *p;
387 1.1 blymn size_t len;
388 1.1 blymn
389 1.1 blymn p = yytext;
390 1.1 blymn p++; /* skip the leading " */
391 1.1 blymn if ((yylval.string = dequote(p, &len)) == NULL)
392 1.1 blymn err(1, "Cannot allocate string");
393 1.1 blymn
394 1.1 blymn /* remove trailing " */
395 1.1 blymn yylval.string[len - 1] = '\0';
396 1.1 blymn return STRING;
397 1.1 blymn }
398 1.1 blymn
399 1.1 blymn \${VARNAME} {
400 1.1 blymn char *p;
401 1.1 blymn
402 1.1 blymn p = yytext;
403 1.1 blymn p++; /* skip $ before var name */
404 1.1 blymn if ((yylval.string = strdup(p)) == NULL)
405 1.1 blymn err(1, "Cannot allocate string for varname");
406 1.1 blymn return VARIABLE;
407 1.1 blymn }
408 1.1 blymn
409 1.1 blymn /* comments, white-outs */
410 1.1 blymn [ \t\r] |
411 1.1 blymn #.* ;
412 1.1 blymn ^#.*\n |
413 1.1 blymn #.*\n |
414 1.1 blymn \\\n |
415 1.1 blymn ^\n {
416 1.1 blymn line++; }
417 1.1 blymn
418 1.1 blymn /* eol on a line with data. need to process, return eol */
419 1.1 blymn \n {
420 1.1 blymn line++;
421 1.1 blymn return EOL;
422 1.1 blymn }
423 1.1 blymn
424 1.1 blymn . {
425 1.1 blymn }
426 1.1 blymn
427 1.1 blymn %%
428 1.1 blymn
429 1.1 blymn int
430 1.1 blymn yywrap(void)
431 1.1 blymn {
432 1.1 blymn return 1;
433 1.1 blymn }
434