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