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 45 int yylex(void); 46 47 extern size_t line; 48 extern char *include_path; /* from director.c */ 49 extern char *cur_file; /* from director.c */ 50 51 static int include_stack[MAX_INCLUDES]; 52 static char *include_files[MAX_INCLUDES]; 53 static int include_ptr = 0; 54 55 static char * 56 dequote(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 137 HEX 0[xX][0-9a-zA-Z]+ 138 STRING [0-9a-z!#-&(-^ \t%._\\]+ 139 numeric [-0-9]+ 140 PCHAR (\\.|[^ \t\n]) 141 ASSIGN [aA][sS][sS][iI][gG][nN] 142 CALL2 [cC][aA][lL][lL]2 143 CALL3 [cC][aA][lL][lL]3 144 CALL4 [cC][aA][lL][lL]4 145 CALL [cC][aA][lL][lL] 146 CHECK [cC][hH][eE][cC][kK] 147 DELAY [dD][eE][lL][aA][yY] 148 INPUT [iI][nN][pP][uU][tT] 149 NOINPUT [nN][oO][iI][nN][pP][uU][tT] 150 OK_RET [oO][kK] 151 ERR_RET [eE][rR][rR] 152 COMPARE [cC][oO][mM][pP][aA][rR][eE] 153 COMPAREND [cC][oO][mM][pP][aA][rR][eE][Nn][Dd] 154 FILENAME [A-Za-z0-9.][A-Za-z0-9./_-]+ 155 VARNAME [A-Za-z][A-Za-z0-9_-]+ 156 NULL_RET NULL 157 NON_NULL NON_NULL 158 BYTE BYTE 159 OR \| 160 LHB \( 161 RHB \) 162 163 %x incl 164 %option noinput nounput 165 166 %% 167 168 include 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 { 420 line++; } 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 433 int 434 yywrap(void) 435 { 436 return 1; 437 } 438