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