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