%{ /* $NetBSD: testlang_conf.l,v 1.7 2013/11/21 11:06:04 blymn Exp $ */ /*- * Copyright 2009 Brett Lymn * * All rights reserved. * * This code has been donated to The NetBSD Foundation by the Author. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. The name of the author may not be used to endorse or promote products * derived from this software withough specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * */ #include #include #include #include #include #include #include #include "returns.h" #include "testlang_parse.h" #define MAX_INCLUDES 32 /* limit for the number of nested includes */ int yylex(void); extern size_t line; extern char *include_path; /* from director.c */ extern char *cur_file; /* from director.c */ static int include_stack[MAX_INCLUDES]; static char *include_files[MAX_INCLUDES]; static int include_ptr = 0; static char * dequote(const char *s, size_t *len) { const unsigned char *p; char *buf, *q; *len = 0; p = (const unsigned char *)s; while (*p) { if (*p == '\\' && *(p+1)) { if (isdigit(*(p+1)) && *(p+2) && isdigit(*(p+2)) && *(p+3) && isdigit(*(p+3))) p += 3; else ++p; } ++(*len); ++p; } buf = malloc(*len + 1); if (buf == NULL) return NULL; p = (const unsigned char *)s; q = buf; while (*p) { if (*p == '\\' && *(p+1)) { ++p; if (isdigit(*p)) { if (*(p+1) && isdigit(*(p+1)) && *(p+2) && isdigit(*(p+2))) { *q++ = ((*p - '0') * 8 + (*(p+1) - '0')) * 8 + (*(p+2) - '0'); p += 3; } else { *q++ = *p++; } } else { switch (*p) { case 'e': /* escape */ *q++ = '\e'; p++; break; case 'n': /* newline */ *q++ = '\n'; p++; break; case 'r': /* carriage return */ *q++ = '\r'; p++; break; case 't': /* tab */ *q++ = '\t'; p++; break; case '\\': /* backslash */ *q++ = '\\'; p++; break; default: *q++ = *p++; } } } else *q++ = *p++; } *q++ = '\0'; return buf; } %} HEX 0[xX][0-9a-zA-Z]+ STRING [0-9a-z!#-&(-^ \t%._\\]+ numeric [-0-9]+ PCHAR (\\.|[^ \t\n]) ASSIGN [aA][sS][sS][iI][gG][nN] CALL2 [cC][aA][lL][lL]2 CALL3 [cC][aA][lL][lL]3 CALL4 [cC][aA][lL][lL]4 CALL [cC][aA][lL][lL] CHECK [cC][hH][eE][cC][kK] DELAY [dD][eE][lL][aA][yY] INPUT [iI][nN][pP][uU][tT] NOINPUT [nN][oO][iI][nN][pP][uU][tT] OK_RET [oO][kK] ERR_RET [eE][rR][rR] COMPARE [cC][oO][mM][pP][aA][rR][eE] COMPAREND [cC][oO][mM][pP][aA][rR][eE][Nn][Dd] FILENAME [A-Za-z0-9.][A-Za-z0-9./_-]+ VARNAME [A-Za-z][A-Za-z0-9_-]+ NULL_RET NULL NON_NULL NON_NULL BYTE BYTE OR \| LHB \( RHB \) %x incl %option noinput nounput %% include BEGIN(incl); [ \t]* /* eat the whitespace */ [^ \t\n]+ { /* got the include file name */ char inc_file[MAXPATHLEN]; if (include_ptr > MAX_INCLUDES) { fprintf(stderr, "Maximum number of nested includes exceeded " "at line %zu of file %s\n", line, cur_file); exit(2); } if (yytext[0] != '/') { if (strlcpy(inc_file, include_path, sizeof(inc_file)) >= sizeof(inc_file)) err(2, "CHECK_PATH too long"); if ((include_path[strlen(include_path) - 1] != '/') && ((strlcat(inc_file, "/", sizeof(inc_file)) >= sizeof(inc_file)))) err(2, "Could not append / to include file path"); } else { inc_file[0] = '\0'; } if (strlcat(inc_file, yytext, sizeof(inc_file)) >= sizeof(inc_file)) err(2, "Path to include file path overflowed"); yyin = fopen(inc_file, "r" ); if (!yyin) err(1, "Error opening %s", inc_file); yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE)); include_stack[include_ptr] = line; include_files[include_ptr++] = cur_file; cur_file = strdup(inc_file); if (cur_file == NULL) err(2, "Cannot allocate new include file string"); line = 0; BEGIN(INITIAL); } <> { yypop_buffer_state(); if ( !YY_CURRENT_BUFFER ) { yyterminate(); } if (--include_ptr < 0) err(2, "Include stack underflow"); free(cur_file); cur_file = include_files[include_ptr]; line = include_stack[include_ptr]; } {ASSIGN} { return ASSIGN; } {CALL2} { return CALL2; } {CALL3} { return CALL3; } {CALL4} { return CALL4; } {CALL} { return CALL; } {CHECK} { return CHECK; } {DELAY} { return DELAY; } {INPUT} { return INPUT; } {NOINPUT} { return NOINPUT; } {COMPARE} { return COMPARE; } {COMPAREND} { return COMPAREND; } {NON_NULL} { return NON_NULL; } {NULL_RET} { return NULL_RET; } {OK_RET} { return OK_RET; } {ERR_RET} { return ERR_RET; } {OR} { return OR; } {LHB} { return LHB; } {RHB} { return RHB; } {HEX} { /* Hex value, convert to decimal and return numeric */ unsigned long val; if (sscanf(yytext, "%lx", &val) != 1) err(1, "Bad hex conversion"); asprintf(&yylval.string, "%ld", val); return numeric; } {numeric} { if ((yylval.string = strdup(yytext)) == NULL) err(1, "Cannot allocate numeric string"); return numeric; } {VARNAME} { if ((yylval.string = strdup(yytext)) == NULL) err(1, "Cannot allocate string for varname"); return VARNAME; } {FILENAME} { size_t len; if ((yylval.string = dequote(yytext, &len)) == NULL) err(1, "Cannot allocate filename string"); return FILENAME; } /* path */ \/{PCHAR}+ { size_t len; if ((yylval.string = dequote(yytext, &len)) == NULL) err(1, "Cannot allocate string"); return PATH; } \'{STRING}\' { char *p; size_t len; if ((yylval.retval = malloc(sizeof(returns_t))) == NULL) err(1, "Cannot allocate return struct"); p = yytext; p++; /* skip the leading ' */ if ((yylval.retval->return_value = dequote(p, &len)) == NULL) err(1, "Cannot allocate string"); yylval.retval->return_type = ret_byte; /* trim trailing ' */ yylval.retval->return_len = len - 1; return BYTE; } \`{STRING}\` { char *p, *str; size_t len, chlen; size_t i; chtype *rv; if ((yylval.retval = malloc(sizeof(returns_t))) == NULL) err(1, "Cannot allocate return struct"); p = yytext; p++; /* skip the leading ' */ if ((str = dequote(p, &len)) == NULL) err(1, "Cannot allocate string"); len--; /* trim trailing ` */ if ((len % 2) != 0) len--; chlen = ((len / 2) + 1) * sizeof(chtype); if ((yylval.retval->return_value = malloc(chlen)) == NULL) err(1, "Cannot allocate chtype array"); rv = yylval.retval->return_value; for (i = 0; i < len; i += 2) *rv++ = (str[i] << 8) | str[i+1]; *rv = __NORMAL | '\0'; /* terminates chtype array */ yylval.retval->return_type = ret_byte; yylval.retval->return_len = chlen; return BYTE; } \"{STRING}\" { char *p; size_t len; p = yytext; p++; /* skip the leading " */ if ((yylval.string = dequote(p, &len)) == NULL) err(1, "Cannot allocate string"); /* remove trailing " */ yylval.string[len - 1] = '\0'; return STRING; } \${VARNAME} { char *p; p = yytext; p++; /* skip $ before var name */ if ((yylval.string = strdup(p)) == NULL) err(1, "Cannot allocate string for varname"); return VARIABLE; } /* comments, white-outs */ [ \t\r] | #.* ; ^#.*\n | #.*\n | \\\n | ^\n { line++; } /* eol on a line with data. need to process, return eol */ \n { line++; return EOL; } . { } %% int yywrap(void) { return 1; }