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