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