%{ /* Nessus Attack Scripting Language version 2 * * Copyright (C) 2002 - 2003 Michel Arboi and Renaud Deraison * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, * as published by the Free Software Foundation * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * In addition, as a special exception, Renaud Deraison and Michel Arboi * give permission to link the code of this program with any * version of the OpenSSL library which is distributed under a * license identical to that listed in the included COPYING.OpenSSL * file, and distribute linked combinations including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. If you modify * this file, you may extend this exception to your version of the * file, but you are not obligated to do so. If you do not wish to * do so, delete this exception statement from your version. * */ #define YYPARSE_PARAM parm #define YYLEX_PARAM parm #define LNB (((naslctxt*)parm)->line_nb) #include "includes.h" #include "nasl_tree.h" #include "nasl_global_ctxt.h" static void naslerror(const char *); #define YYERROR_VERBOSE %} %union { int num; char *str; tree_cell *node; } %pure_parser %expect 1 %token IF %token ELSE %token EQ %token NEQ %token SUPEQ %token INFEQ %token OR %token AND %token MATCH %token NOMATCH %token REP %token FOR %token REPEAT %token UNTIL %token FOREACH %token WHILE %token BREAK %token FUNCTION %token RETURN %token INCLUDE %token LOCAL %token GLOBAL %token PLUS_PLUS %token MINUS_MINUS %token L_SHIFT %token R_SHIFT %token R_USHIFT %token EXPO %token PLUS_EQ %token MINUS_EQ %token MULT_EQ %token DIV_EQ %token MODULO_EQ %token L_SHIFT_EQ %token R_SHIFT_EQ %token R_USHIFT_EQ %token RE_MATCH %token RE_NOMATCH %token IDENT %token STRING1 %token STRING2 %token INTEGER %type arg_list_1 arg_list arg %type arg_decl_1 arg_decl %type func_call func_decl %type instr instr_list instr_decl instr_decl_list simple_instr %type if_block block loop for_loop while_loop foreach_loop repeat_loop %type aff rep ret expr aff_func array_index array_elem lvalue var %type ipaddr post_pre_incr %type inc loc glob %type identifier string /* Priority of all operators */ %right '=' PLUS_EQ MINUS_EQ MULT_EQ DIV_EQ MODULO_EQ L_SHIFT_EQ R_SHIFT_EQ R_USHIFT_EQ %left OR %left AND %nonassoc '<' '>' EQ NEQ SUPEQ INFEQ MATCH NOMATCH RE_MATCH RE_NOMATCH %left '|' %left '^' %left '&' %nonassoc R_SHIFT R_USHIFT L_SHIFT %left '+' '-' %left '*' '/' '%' %nonassoc NOT %nonassoc UMINUS BIT_NOT %right EXPO %nonassoc PLUS_PLUS MINUS_MINUS %start tiptop %% tiptop: instr_decl_list { ((naslctxt*)parm)->tree = $1; } ; instr_decl_list: instr_decl { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_INSTR_L; $$->link[0] = $1; } | instr_decl instr_decl_list { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_INSTR_L; $$->link[0] = $1; $$->link[1] = $2; }; instr_decl: instr | func_decl; /* Function declaration */ func_decl: FUNCTION identifier '(' arg_decl ')' block { $$ = alloc_tree_cell(LNB, $2); $$->type = NODE_FUN_DEF; $$->link[0] = $4; $$->link[1] = $6; }; arg_decl: { $$ = NULL; } | arg_decl_1 { $$ = $1; }; arg_decl_1: identifier { $$ = alloc_tree_cell(LNB, $1); $$->type = NODE_DECL; } | identifier ',' arg_decl_1 { $$ = alloc_tree_cell(LNB, $1); $$->type = NODE_DECL; $$->link[0] = $3; }; /* Block */ block: '{' instr_list '}' { $$ = $2; } | '{' '}' { $$ = NULL; }; instr_list: instr | instr instr_list { if ($1 == NULL) $$ = $2; else { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_INSTR_L; $$->link[0] = $1; $$->link[1] = $2; } } ; /* Instructions */ instr: simple_instr ';' { $$ = $1; } | block | if_block | loop ; /* "simple" instruction */ simple_instr : aff | post_pre_incr | rep | func_call | ret | inc | loc | glob | BREAK { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_BREAK; } | /* nop */ { $$ = NULL; }; /* return */ ret: RETURN expr { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_RETURN; $$->link[0] = $2; } | RETURN { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_RETURN; } ; /* If block */ if_block: IF '(' expr ')' instr { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_IF_ELSE; $$->link[0] = $3; $$->link[1] = $5; } | IF '(' expr ')' instr ELSE instr { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_IF_ELSE; $$->link[0] = $3; $$->link[1] = $5; $$->link[2] = $7; }; /* Loops */ loop : for_loop | while_loop | repeat_loop | foreach_loop ; for_loop : FOR '(' aff_func ';' expr ';' aff_func ')' instr { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_FOR; $$->link[0] = $3; $$->link[1] = $5; $$->link[2] = $7; $$->link[3] = $9; } ; while_loop : WHILE '(' expr ')' instr { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_WHILE; $$->link[0] = $3; $$->link[1] = $5; } ; repeat_loop : REPEAT instr UNTIL expr ';' { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_REPEAT_UNTIL; $$->link[0] = $2; $$->link[1] = $4; } ; foreach_loop : FOREACH identifier '(' expr ')' instr { $$ = alloc_tree_cell(LNB, $2); $$->type = NODE_FOREACH; $$->link[0] = $4; $$->link[1] = $6; } ; /* affectation or function call */ aff_func: aff | post_pre_incr | func_call | /*nop */ { $$ = NULL; }; /* repetition */ rep: func_call REP expr { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_REPEATED; $$->link[0] = $1; $$->link[1] = $3; } ; string : STRING1 | STRING2 ; /* include */ inc: INCLUDE '(' string ')' { naslctxt subctx; int x; x = init_nasl_ctx(&subctx, $3); $$ = NULL; if (x >= 0) { if (! naslparse(&subctx)) { $$ = subctx.tree; } else nasl_perror(NULL, "%s: Parse error at or near line %d\n", $3, subctx.line_nb); efree(&subctx.buffer); fclose(subctx.fp); subctx.fp = NULL; } efree(& $3); } ; /* Function call */ func_call: identifier '(' arg_list ')' { $$ = alloc_tree_cell(LNB, $1); $$->type = NODE_FUN_CALL; $$->link[0] = $3; }; arg_list : arg_list_1 | { $$ = NULL; }; arg_list_1: arg | arg ',' arg_list_1 { $1->link[1] = $3; $$ = $1; } ; arg : expr { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_ARG; $$->link[0] = $1; } | identifier ':' expr { $$ = alloc_tree_cell(LNB, $1); $$->type = NODE_ARG; $$->link[0] = $3; } ; /* Affectation */ aff: lvalue '=' expr { $$ = alloc_expr_cell(LNB, NODE_AFF, $1, $3); } | lvalue PLUS_EQ expr { $$ = alloc_expr_cell(LNB, NODE_PLUS_EQ, $1, $3); } | lvalue MINUS_EQ expr { $$ = alloc_expr_cell(LNB, NODE_MINUS_EQ, $1, $3); } | lvalue MULT_EQ expr { $$ = alloc_expr_cell(LNB, NODE_MULT_EQ, $1, $3); } | lvalue DIV_EQ expr { $$ = alloc_expr_cell(LNB, NODE_DIV_EQ, $1, $3); } | lvalue MODULO_EQ expr { $$ = alloc_expr_cell(LNB, NODE_MODULO_EQ, $1, $3); } | lvalue R_SHIFT_EQ expr { $$ = alloc_expr_cell(LNB, NODE_R_SHIFT_EQ, $1, $3); } | lvalue R_USHIFT_EQ expr { $$ = alloc_expr_cell(LNB, NODE_R_USHIFT_EQ, $1, $3); } | lvalue L_SHIFT_EQ expr { $$ = alloc_expr_cell(LNB, NODE_L_SHIFT_EQ, $1, $3); } ; lvalue: identifier { $$ = alloc_tree_cell(LNB, $1); $$->type = NODE_VAR; } | array_elem ; identifier: IDENT | REP { $$ = strdup("x"); } ; /* => For "x" */ array_elem: identifier '[' array_index ']' { $$ = alloc_tree_cell(LNB, $1); $$->type = NODE_ARRAY_EL; $$->link[0] = $3; } ; array_index: expr ; post_pre_incr: PLUS_PLUS lvalue { $$ = alloc_expr_cell(LNB, EXPR_INCR, NULL, $2); } | MINUS_MINUS lvalue {$$ = alloc_expr_cell(LNB, EXPR_DECR, NULL, $2); } | lvalue PLUS_PLUS { $$= alloc_expr_cell(LNB, EXPR_INCR, $1, NULL); } | lvalue MINUS_MINUS { $$= alloc_expr_cell(LNB, EXPR_DECR, $1, NULL); } ; /* expression. We accepte affectations inside parenthesis */ expr: '(' expr ')' { $$ = $2; } | expr AND expr { $$ = alloc_expr_cell(LNB, EXPR_AND, $1, $3); } | '!' expr %prec NOT { $$ = alloc_expr_cell(LNB, EXPR_NOT, $2, NULL); } | expr OR expr { $$ = alloc_expr_cell(LNB, EXPR_OR, $1, $3); } | expr '+' expr { $$ = alloc_expr_cell(LNB, EXPR_PLUS, $1, $3); } | expr '-' expr { $$ = alloc_expr_cell(LNB, EXPR_MINUS, $1, $3); } | '-' expr %prec UMINUS { $$ = alloc_expr_cell(LNB, EXPR_U_MINUS, $2, NULL);} | '~' expr %prec BIT_NOT { $$ = alloc_expr_cell(LNB, EXPR_BIT_NOT, $2, NULL);} | expr '*' expr { $$ = alloc_expr_cell(LNB, EXPR_MULT, $1, $3); } | expr EXPO expr { $$ = alloc_expr_cell(LNB, EXPR_EXPO, $1, $3); } | expr '/' expr { $$ = alloc_expr_cell(LNB, EXPR_DIV, $1, $3); } | expr '%' expr { $$ = alloc_expr_cell(LNB, EXPR_MODULO, $1, $3); } | expr '&' expr { $$ = alloc_expr_cell(LNB, EXPR_BIT_AND, $1, $3); } | expr '^' expr { $$ = alloc_expr_cell(LNB, EXPR_BIT_XOR, $1, $3); } | expr '|' expr { $$ = alloc_expr_cell(LNB, EXPR_BIT_OR, $1, $3); } | expr R_SHIFT expr { $$ = alloc_expr_cell(LNB, EXPR_R_SHIFT, $1, $3); } | expr R_USHIFT expr { $$ = alloc_expr_cell(LNB, EXPR_R_USHIFT, $1, $3); } | expr L_SHIFT expr { $$ = alloc_expr_cell(LNB, EXPR_L_SHIFT, $1, $3); } | post_pre_incr | expr MATCH expr { $$ = alloc_expr_cell(LNB, COMP_MATCH, $1, $3); } | expr NOMATCH expr { $$ = alloc_expr_cell(LNB, COMP_NOMATCH, $1, $3); } | expr RE_MATCH string { $$ = alloc_RE_cell(LNB, COMP_RE_MATCH, $1, $3); } | expr RE_NOMATCH string { $$ = alloc_RE_cell(LNB, COMP_RE_NOMATCH, $1, $3); } | expr '<' expr { $$ = alloc_expr_cell(LNB, COMP_LT, $1, $3); } | expr '>' expr { $$ = alloc_expr_cell(LNB, COMP_GT, $1, $3); } | expr EQ expr { $$ = alloc_expr_cell(LNB, COMP_EQ, $1, $3); } | expr NEQ expr { $$ = alloc_expr_cell(LNB, COMP_NE, $1, $3); } | expr SUPEQ expr { $$ = alloc_expr_cell(LNB, COMP_GE, $1, $3); } | expr INFEQ expr { $$ = alloc_expr_cell(LNB, COMP_LE, $1, $3); } | INTEGER { $$ = alloc_tree_cell(LNB, NULL); $$->x.i_val = $1; $$->type = CONST_INT; } | STRING2 { $$ = alloc_tree_cell(LNB, NULL); $$->x.str_val = $1; $$->type = CONST_STR; $$->size = strlen($1); } | STRING1 { $$ = alloc_tree_cell(LNB, NULL); $$->x.str_val = $1; $$->type = CONST_DATA; $$->size = strlen($1); } | var | aff | ipaddr; var: identifier { $$ = alloc_tree_cell(LNB, $1); $$->type = NODE_VAR; } | array_elem | func_call; ipaddr: INTEGER '.' INTEGER '.' INTEGER '.' INTEGER { char *s = emalloc(44); snprintf(s, 44, "%d.%d.%d.%d", $1, $3, $5, $7); $$ = alloc_tree_cell(LNB, s); $$->type = CONST_STR; $$->size = strlen(s); }; /* Local variable declaration */ loc: LOCAL arg_decl { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_LOCAL; $$->link[0] = $2; }; /* Global variable declaration */ glob: GLOBAL arg_decl { $$ = alloc_tree_cell(LNB, NULL); $$->type = NODE_GLOBAL; $$->link[0] = $2; }; %% #include #include static void naslerror(const char *s) { fputs(s, stderr); } int init_nasl_ctx(naslctxt* pc, const char* name) { #ifdef MULTIPLE_INCLUDE_DIRS static const char* inc_dirs[] = { ".", "/tmp" }; /* TBD */ #endif pc->line_nb = 1; pc->tree = NULL; pc->buffer = emalloc(80); pc->maxlen = 80; #ifdef MULTIPLE_INCLUDE_DIRS if (name[0] == '/') /* absolute path */ #endif { /* Shouldn't we reject the file? */ if ((pc->fp = fopen(name, "r")) == NULL) { perror(name); return -1; } return 0; } #ifdef MULTIPLE_INCLUDE_DIRS else { char full_name[MAXPATHLEN]; int i; for (i = 0; i < sizeof(inc_dirs) / sizeof(*inc_dirs); i ++) { snprintf(full_name, sizeof(full_name), "%s/%s", inc_dirs[i], name); if ((pc->fp = fopen(full_name, "r")) != NULL) return 0; perror(full_name); } return -1; } #endif } void nasl_clean_ctx(naslctxt* c) { #if 0 nasl_dump_tree(c->tree); #endif deref_cell(c->tree); efree(&c->buffer); if (c->fp) { fclose(c->fp); c->fp = NULL; } } #if 0 int main(int argc,char **argv) { naslctxt ctx; ctx.line_nb = 1; ctx.tree = NULL; if (argc != 2) { nasl_perror(NULL, "Usage : nasl \n"); return 1; } if ((ctx.fp = fopen(argv[1], "r")) == NULL) { perror(argv[1]); return 1; } return naslparse((void*) &ctx); } #endif enum lex_state { ST_START = 0, ST_SPACE, ST_IDENT, ST_ZERO, ST_ZEROX, ST_OCT, ST_DEC, ST_HEX, ST_COMMENT, ST_SUP, ST_INF, ST_SUP_EXCL, ST_STRING1, ST_STRING1_ESC, ST_STRING2, ST_PLUS, ST_MINUS, ST_MULT, ST_DIV, ST_MODULO, ST_R_SHIFT, ST_R_USHIFT, ST_L_SHIFT, ST_NOT, ST_EQ, ST_AND, ST_OR }; static int mylex(lvalp, parm) YYSTYPE *lvalp; void *parm; { char *p; naslctxt *ctx = parm; FILE *fp = ctx->fp; int c, st = ST_START, len, maxlen, r; int x, i; p = ctx->buffer; len = 0; while ((c = getc(fp)) != EOF) { if (c == '\n') ctx->line_nb ++; switch(st) { case ST_START: if (c == '#') st = ST_COMMENT; else if (isalpha(c) || c == '_') { st = ST_IDENT; *p++ = c; len ++; } else if (isspace(c)) st = ST_SPACE; else if (c == '0') st = ST_ZERO; else if (isdigit(c)) { st = ST_DEC; *p++ = c; len ++; } else if (c == '\'') st = ST_STRING1; else if (c == '"') st = ST_STRING2; else if (c == '+') st = ST_PLUS; else if (c == '-') st = ST_MINUS; else if (c == '*') st = ST_MULT; else if (c == '/') st = ST_DIV; else if (c == '%') st = ST_MODULO; else if (c == '>') st = ST_SUP; else if (c == '<') st = ST_INF; else if (c == '=') st = ST_EQ; else if (c == '|') st = ST_OR; else if (c == '!') st = ST_NOT; else if (c == '&') st = ST_AND; else { return c; } break; case ST_STRING2: if (c == '"') goto exit_loop; *p++ = c; len ++; break; case ST_STRING1: if (c == '\'') goto exit_loop; else if (c == '\\') { c = getc(fp); switch (c) { case EOF: nasl_perror(NULL, "Unfinished string\n"); goto exit_loop; /* parse error? */ case '\n': /* escaped end of line */ ctx->line_nb ++; break; case '\\': *p++ ='\\'; len ++; break; case 'n': *p++ = '\n'; len++; break; case 'f': *p++ = '\f'; len ++; break; case 't': *p++ = '\t'; len ++; break; case 'r': *p++ = '\r'; len++; break; case 'v': *p++ = '\v'; len ++; break; case '"': *p ++ = '"'; len ++; break; #if 0 /* Not yet, as we do not return the length of the string */ case '0': *p++ = '\0'; len++; break; #endif case '\'': *p++ = '\''; len++; break; case 'x': x = 0; for (i = 0; i < 2; i ++) { c = getc(fp); if (c == EOF) { nasl_perror(NULL, "Unfinished \\x escape sequence (EOF)\n"); goto exit_loop; } if (c == '\n') ctx->line_nb ++; c = tolower(c); if (c >= '0' && c <= '9') x = x * 16 + (c - '0'); else if (c >= 'a' && c <= 'f') x = x * 16 + 10 + (c - 'a'); else { nasl_perror(NULL, "Unfinished \\x escape sequence\n"); ungetc(c, fp); if (c == '\n') ctx->line_nb --; break; } } *p++ = x; len ++; break; default: nasl_perror(NULL, "Unknown escape sequence \\%c\n", c); *p++ = c; len ++; break; } } else { *p++ = c; len ++; } break; case ST_IDENT: if (isalnum(c) || c == '_') { st = ST_IDENT; *p++ = c; len ++; } else { ungetc(c, fp); if (c == '\n') ctx->line_nb --; goto exit_loop; } break; case ST_ZERO: if (c == 'x' || c == 'X') st = ST_ZEROX; else if (isdigit(c)) { if (c <= '7') st = ST_OCT; else st = ST_DEC; *p ++ = c; len ++; } else { ungetc(c, fp); if (c == '\n') ctx->line_nb --; goto exit_loop; } break; case ST_ZEROX: if (isxdigit(c)) { st = ST_HEX; *p++ = c; len ++; } else { /* This should be a parse error */ ungetc(c, fp); if (c == '\n') ctx->line_nb --; goto exit_loop; } break; case ST_OCT: if (c >= '0') if (c <= '7') { *p++ = c; len ++; break; } else if (c <= '9') { *p++ = c; len ++; st = ST_DEC; break; } ungetc(c, fp); if (c == '\n') ctx->line_nb --; goto exit_loop; case ST_DEC: if (isdigit(c)) { *p++ = c; len ++; } else { ungetc(c, fp); if (c == '\n') ctx->line_nb --; goto exit_loop; } break; case ST_HEX: if (isxdigit(c)) { *p++ = c; len ++; } else { ungetc(c, fp); if (c == '\n') ctx->line_nb --; goto exit_loop; } break; case ST_SPACE: if (! isspace(c)) { ungetc(c, fp); if (c == '\n') ctx->line_nb --; st = ST_START; } break; case ST_COMMENT: if (c == '\n') st = ST_START; break; case ST_SUP_EXCL: if (c == '<') return NOMATCH; else { ungetc(c, fp); if (c == '\n') ctx->line_nb --; if (! isprint(c)) c = '.'; fprintf(stderr, "lexer error: invalid token >!%c parsed as >!< %c\n", c, c); return NOMATCH; } break; case ST_SUP: if (c == '=') return SUPEQ; else if (c == '<') return MATCH; else if (c == '>') st = ST_R_SHIFT; else if (c == '!') st = ST_SUP_EXCL; else { ungetc(c, fp); if (c == '\n') ctx->line_nb --; return '>'; } break; case ST_INF: if (c == '=') return INFEQ; else if (c == '<') st = ST_L_SHIFT; else { ungetc(c, fp); if (c == '\n') ctx->line_nb --; return '<'; } break; case ST_R_SHIFT: if (c == '=') return R_SHIFT_EQ; else if (c == '>') st = ST_R_USHIFT; else { ungetc(c, fp); if (c == '\n') ctx->line_nb --; return R_SHIFT; } /*NOTREACHED*/ break; case ST_R_USHIFT: if (c == '=') return R_USHIFT_EQ; else { ungetc(c, fp); if (c == '\n') ctx->line_nb --; return R_USHIFT; } /*NOTREACHED*/ break; case ST_L_SHIFT: if (c == '=') return L_SHIFT_EQ; else { ungetc(c, fp); if (c == '\n') ctx->line_nb --; return L_SHIFT; } /*NOTREACHED*/ break; case ST_AND: if (c == '&') return AND; ungetc(c, fp); if (c == '\n') ctx->line_nb --; return '&'; case ST_OR: if (c == '|') return OR; ungetc(c, fp); if (c == '\n') ctx->line_nb --; return '|'; case ST_NOT: if (c == '=') return NEQ; else if (c == '~') return RE_NOMATCH; ungetc(c, fp); if (c == '\n') ctx->line_nb --; return '!'; case ST_EQ: if (c == '=') return EQ; else if (c == '~') return RE_MATCH; ungetc(c, fp); if (c == '\n') ctx->line_nb --; return '='; case ST_PLUS: if (c == '+') return PLUS_PLUS; else if (c == '=') return PLUS_EQ; ungetc(c, fp); if (c == '\n') ctx->line_nb --; return '+'; case ST_MINUS: if (c == '-') return MINUS_MINUS; else if (c == '=') return MINUS_EQ; ungetc(c, fp); if (c == '\n') ctx->line_nb --; return '-'; case ST_MULT: if (c == '=') return MULT_EQ; else if (c == '*') return EXPO; ungetc(c, fp); if (c == '\n') ctx->line_nb --; return '*'; case ST_DIV: if (c == '=') return DIV_EQ; ungetc(c, fp); if (c == '\n') ctx->line_nb --; return '/'; case ST_MODULO: if (c == '=') return MODULO_EQ; ungetc(c, fp); if (c == '\n') ctx->line_nb --; return '%'; } if (len >= ctx->maxlen) { int offs = p - ctx->buffer; char *buf2; ctx->maxlen += 80; buf2 = erealloc(ctx->buffer, ctx->maxlen + 1); if (buf2 == NULL) { perror("realloc"); abort(); } p = buf2 + offs; ctx->buffer = buf2; } } exit_loop: ctx->buffer[len] = '\0'; switch (st) { case ST_START: case ST_COMMENT: case ST_SPACE: return 0; case ST_STRING2: r = STRING2; lvalp->str = estrdup(ctx->buffer); return r; case ST_STRING1: r = STRING1; lvalp->str = estrdup(ctx->buffer); return r; case ST_IDENT: if (strcmp(ctx->buffer, "if") == 0) r = IF; else if (strcmp(ctx->buffer, "else") == 0) r = ELSE; else if (strcmp(ctx->buffer, "for") == 0) r = FOR; else if (strcmp(ctx->buffer, "while") == 0) r = WHILE; else if (strcmp(ctx->buffer, "repeat") == 0) r = REPEAT; else if (strcmp(ctx->buffer, "until") == 0) r = UNTIL; else if (strcmp(ctx->buffer, "foreach") == 0) r = FOREACH; else if (strcmp(ctx->buffer, "function") == 0) r = FUNCTION; else if (strcmp(ctx->buffer, "return") == 0) r = RETURN; else if (strcmp(ctx->buffer, "x") == 0) r = REP; else if (strcmp(ctx->buffer, "include") == 0) r = INCLUDE; else if (strcmp(ctx->buffer, "break") == 0) r = BREAK; else if (strcmp(ctx->buffer, "local_var") == 0) r = LOCAL; else if (strcmp(ctx->buffer, "global_var") == 0) r = GLOBAL; else { r = IDENT; lvalp->str = estrdup(ctx->buffer); return r; } return r; case ST_DEC: /* -123 is parsed as "-" and "123" so that we can write "4-2" without * inserting a white space after the minus operator * Note that strtoul would also work on negative integers */ lvalp->num = x = strtoul(ctx->buffer, NULL, 10); #if NASL_DEBUG > 1 && defined(ULONG_MAX) && defined(ERANGE) if (x == ULONG_MAX && errno == ERANGE) nasl_perror(NULL, "Integer overflow while converting %s at or near line %d\n", ctx->buffer, ctx->line_nb); #endif return INTEGER; case ST_OCT: lvalp->num = x = strtoul(ctx->buffer, NULL, 8); #if NASL_DEBUG > 1 && defined(ULONG_MAX) && defined(ERANGE) if (x == ULONG_MAX && errno == ERANGE) nasl_perror(NULL, "Integer overflow while converting %s at or near line %d\n", ctx->buffer, ctx->line_nb); #endif return INTEGER; case ST_HEX: lvalp->num = x = strtoul(ctx->buffer, NULL, 16); #if NASL_DEBUG > 1 && defined(ULONG_MAX) if (x == ULONG_MAX) nasl_perror(NULL, "Possible integer overflow while converting %s at or near line %d\n", ctx->buffer, ctx->line_nb); #endif return INTEGER; case ST_ZEROX: nasl_perror(NULL, "Invalid token 0x parsed as 0 at line %d\n", ctx->line_nb); case ST_ZERO: lvalp->num = 0; return INTEGER; default: abort(); } } int nasllex(lvalp, parm) YYSTYPE *lvalp; void *parm; { naslctxt *ctx = parm; int x = mylex(lvalp, parm); #if 0 if (isprint(x)) fprintf(stderr, "Line %d\t: '%c'\n", ctx->line_nb, x); else fprintf(stderr, "Line %d\t: %d\n", ctx->line_nb, x); #endif return x; }