1%{
2/*	$NetBSD: testlang_conf.l,v 1.5 2011/06/18 20:05:28 joerg Exp $ 	*/
3
4/*-
5 * Copyright 2009 Brett Lymn <blymn@NetBSD.org>
6 *
7 * All rights reserved.
8 *
9 * This code has been donated to The NetBSD Foundation by the Author.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. The name of the author may not be used to endorse or promote products
17 *    derived from this software withough specific prior written permission
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 *
31 */
32
33#include <curses.h>
34#include <ctype.h>
35#include <stdio.h>
36#include <stdlib.h>
37#include <string.h>
38#include <sys/param.h>
39#include <err.h>
40#include "returns.h"
41#include "testlang_parse.h"
42
43#define MAX_INCLUDES 32 /* limit for the number of nested includes */
44
45int yylex(void);
46
47extern size_t line;
48extern char *include_path; 	/* from director.c */
49extern char *cur_file;		/* from director.c */
50
51static int include_stack[MAX_INCLUDES];
52static char *include_files[MAX_INCLUDES];
53static int include_ptr = 0;
54
55static char *
56dequote(const char *s, size_t *len)
57{
58	const unsigned char *p;
59	char *buf, *q;
60
61	*len = 0;
62	p = (const unsigned char *)s;
63	while (*p) {
64		if (*p == '\\' && *(p+1)) {
65			if (isdigit(*(p+1)) && *(p+2) && isdigit(*(p+2)) &&
66			    *(p+3) && isdigit(*(p+3)))
67				p += 3;
68			else
69				++p;
70		}
71		++(*len);
72		++p;
73	}
74
75	buf = malloc(*len + 1);
76	if (buf == NULL)
77		return NULL;
78
79	p = (const unsigned char *)s;
80	q = buf;
81	while (*p) {
82		if (*p == '\\' && *(p+1)) {
83			++p;
84			if (isdigit(*p)) {
85				if (*(p+1) && isdigit(*(p+1)) && *(p+2) &&
86				    isdigit(*(p+2))) {
87					*q++ = ((*p - '0') * 8 + (*(p+1) - '0')) * 8 + (*(p+2) - '0');
88					p += 3;
89				} else {
90					*q++ = *p++;
91				}
92			} else {
93				switch (*p) {
94				case 'e':
95					/* escape */
96					*q++ = '\e';
97					p++;
98					break;
99
100				case 'n':
101					/* newline */
102					*q++ = '\n';
103					p++;
104					break;
105
106				case 't':
107					/* tab */
108					*q++ = '\t';
109					p++;
110					break;
111
112				case '\\':
113					/* backslash */
114					*q++ = '\\';
115					p++;
116					break;
117
118				default:
119					*q++ = *p++;
120				}
121			}
122		} else
123			*q++ = *p++;
124	}
125	*q++ = '\0';
126
127	return buf;
128}
129%}
130
131HEX		0[xX][0-9a-zA-Z]+
132STRING		[0-9a-z!#-&(-^ \t%._\\]+
133numeric		[-0-9]+
134PCHAR           (\\.|[^ \t\n])
135ASSIGN		[aA][sS][sS][iI][gG][nN]
136CALL2		[cC][aA][lL][lL]2
137CALL3		[cC][aA][lL][lL]3
138CALL4		[cC][aA][lL][lL]4
139CALL		[cC][aA][lL][lL]
140CHECK		[cC][hH][eE][cC][kK]
141DELAY		[dD][eE][lL][aA][yY]
142INPUT		[iI][nN][pP][uU][tT]
143NOINPUT		[nN][oO][iI][nN][pP][uU][tT]
144OK_RET		[oO][kK]
145ERR_RET		[eE][rR][rR]
146COMPARE		[cC][oO][mM][pP][aA][rR][eE]
147COMPAREND	[cC][oO][mM][pP][aA][rR][eE][Nn][Dd]
148FILENAME	[A-Za-z0-9.][A-Za-z0-9./_-]+
149VARNAME		[A-Za-z][A-Za-z0-9_-]+
150NULL_RET	NULL
151NON_NULL	NON_NULL
152BYTE		BYTE
153OR		\|
154LHB		\(
155RHB		\)
156
157%x incl
158%option noinput nounput
159
160%%
161
162include		BEGIN(incl);
163
164<incl>[ \t]*      /* eat the whitespace */
165<incl>[^ \t\n]+   { /* got the include file name */
166		char inc_file[MAXPATHLEN];
167
168		if (include_ptr > MAX_INCLUDES) {
169			fprintf(stderr,
170				"Maximum number of nested includes exceeded "
171				"at line %zu of file %s\n", line, cur_file);
172				exit(2);
173		}
174
175		if (yytext[0] != '/') {
176			if (strlcpy(inc_file, include_path, sizeof(inc_file))
177			    >= sizeof(inc_file))
178				err(2, "CHECK_PATH too long");
179			if ((include_path[strlen(include_path) - 1] != '/') &&
180			    ((strlcat(inc_file, "/", sizeof(inc_file))
181			    >= sizeof(inc_file))))
182				err(2, "Could not append / to include file path");
183		} else {
184			inc_file[0] = '\0';
185		}
186
187		if (strlcat(inc_file, yytext, sizeof(inc_file))
188		    >= sizeof(inc_file))
189			err(2, "Path to include file path overflowed");
190
191		yyin = fopen(inc_file, "r" );
192
193		if (!yyin)
194			err(1, "Error opening %s", inc_file);
195
196		yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
197
198		include_stack[include_ptr] = line;
199		include_files[include_ptr++] = cur_file;
200		cur_file = strdup(inc_file);
201		if (cur_file == NULL)
202			err(2, "Cannot allocate new include file string");
203		line = 0;
204		BEGIN(INITIAL);
205	}
206
207<<EOF>>	{
208		yypop_buffer_state();
209
210		if ( !YY_CURRENT_BUFFER )
211		{
212			yyterminate();
213		}
214
215		if (--include_ptr < 0)
216			err(2, "Include stack underflow");
217
218		free(cur_file);
219		cur_file = include_files[include_ptr];
220		line = include_stack[include_ptr];
221	}
222
223{ASSIGN}	{
224			return ASSIGN;
225		}
226
227{CALL2}		{
228			return CALL2;
229		}
230
231{CALL3}		{
232			return CALL3;
233		}
234
235{CALL4}		{
236			return CALL4;
237		}
238
239{CALL}		{
240			return CALL;
241		}
242
243{CHECK}		{
244			return CHECK;
245		}
246
247{DELAY}		{
248			return DELAY;
249		}
250
251{INPUT}		{
252			return INPUT;
253		}
254
255{NOINPUT}		{
256			return NOINPUT;
257		}
258
259{COMPARE}	{
260			return COMPARE;
261		}
262
263{COMPAREND}	{
264			return COMPAREND;
265		}
266
267{NON_NULL}	{
268			return NON_NULL;
269		}
270
271{NULL_RET}		{
272			return NULL_RET;
273		}
274
275{OK_RET}		{
276			return OK_RET;
277		}
278
279{ERR_RET}		{
280			return ERR_RET;
281		}
282
283{OR}		{
284			return OR;
285		}
286
287{LHB}		{
288			return LHB;
289		}
290
291{RHB}		{
292			return RHB;
293		}
294
295{HEX}		{
296			/* Hex value, convert to decimal and return numeric */
297			unsigned long val;
298
299			if (sscanf(yytext, "%lx", &val) != 1)
300				err(1, "Bad hex conversion");
301
302			asprintf(&yylval.string, "%ld", val);
303			return numeric;
304		}
305
306
307{numeric}		{
308			if ((yylval.string = strdup(yytext)) == NULL)
309				err(1, "Cannot allocate numeric string");
310			return numeric;
311}
312
313{VARNAME}	{
314			if ((yylval.string = strdup(yytext)) == NULL)
315				err(1, "Cannot allocate string for varname");
316			return VARNAME;
317		}
318
319{FILENAME}	{
320			size_t len;
321
322			if ((yylval.string = dequote(yytext, &len)) == NULL)
323				err(1, "Cannot allocate filename string");
324			return FILENAME;
325		}
326
327	/* path */
328\/{PCHAR}+	{
329			size_t len;
330			if ((yylval.string = dequote(yytext, &len)) == NULL)
331				err(1, "Cannot allocate string");
332			return PATH;
333		}
334
335\'{STRING}\' 	{
336			char *p;
337			size_t len;
338
339			if ((yylval.retval = malloc(sizeof(returns_t))) == NULL)
340				err(1, "Cannot allocate return struct");
341			p = yytext;
342			p++; /* skip the leading ' */
343			if ((yylval.retval->return_value = dequote(p, &len))
344			     == NULL)
345				err(1, "Cannot allocate string");
346
347			yylval.retval->return_type = ret_byte;
348			/* trim trailing ' */
349			yylval.retval->return_len = len - 1;
350			return BYTE;
351		}
352
353\`{STRING}\` 	{
354			char *p, *str;
355			size_t len, chlen;
356			size_t i;
357			chtype *rv;
358
359			if ((yylval.retval = malloc(sizeof(returns_t))) == NULL)
360				err(1, "Cannot allocate return struct");
361			p = yytext;
362			p++; /* skip the leading ' */
363			if ((str = dequote(p, &len)) == NULL)
364				err(1, "Cannot allocate string");
365			len--; /* trim trailing ` */
366			if ((len % 2) != 0)
367				len--;
368
369			chlen = ((len / 2) + 1) * sizeof(chtype);
370			if ((yylval.retval->return_value = malloc(chlen))
371			    == NULL)
372				err(1, "Cannot allocate chtype array");
373
374			rv = yylval.retval->return_value;
375			for (i = 0; i < len; i += 2)
376				*rv++ = (str[i] << 8) | str[i+1];
377			*rv = __NORMAL | '\0'; /* terminates chtype array */
378			yylval.retval->return_type = ret_byte;
379			yylval.retval->return_len = chlen;
380			return BYTE;
381		}
382
383\"{STRING}\" 	{
384			char *p;
385			size_t len;
386
387			p = yytext;
388			p++; /* skip the leading " */
389			if ((yylval.string = dequote(p, &len)) == NULL)
390				err(1, "Cannot allocate string");
391
392			/* remove trailing " */
393			yylval.string[len - 1] = '\0';
394			return STRING;
395		}
396
397\${VARNAME}	{
398			char *p;
399
400			p = yytext;
401			p++; /* skip $ before var name */
402			if ((yylval.string = strdup(p)) == NULL)
403				err(1, "Cannot allocate string for varname");
404			return VARIABLE;
405		}
406
407	/* comments, white-outs */
408[ \t\r]		|
409#.*		;
410^#.*\n		|
411#.*\n		|
412\\\n		|
413^\n		{
414line++; }
415
416	/* eol on a line with data. need to process, return eol */
417\n		{
418			line++;
419			return EOL;
420		}
421
422.		{
423		}
424
425%%
426
427int
428yywrap(void)
429{
430	return 1;
431}
432