%{ /* -*- flex-mode -*- */ /* FreeS/WAN config file parser (parser.l) * Copyright (C) 2001 Mathieu Lafon - Arkoon Network Security * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. See . * * 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. * * RCSID $Id: parser.l,v 1.6 2004/01/21 01:35:29 mcr Exp $ */ #include #include #include #include #include #include "keywords.h" #include "parser.h" #include "parser.tab.h" #include "parserlast.h" #define MAX_INCLUDE_DEPTH 10 #define YY_NO_UNPUT extern void yyerror(const char *); extern int yylex (void); extern int yydebug; extern int verbose; static struct { int stack_ptr; YY_BUFFER_STATE stack[MAX_INCLUDE_DEPTH]; FILE *file[MAX_INCLUDE_DEPTH]; unsigned int line[MAX_INCLUDE_DEPTH]; char *filename[MAX_INCLUDE_DEPTH]; } ic_private; char *parser_cur_filename(void) { return ic_private.filename[ic_private.stack_ptr]; } int parser_cur_lineno(void) { return ic_private.line[ic_private.stack_ptr]; } void parser_y_error(char *b, int size, const char *s) { extern char *yytext; snprintf(b, size, "%s:%d: %s [%s]", ic_private.filename[ic_private.stack_ptr], ic_private.line[ic_private.stack_ptr], s, yytext); } void parser_y_init (const char *f) { memset(&ic_private, 0, sizeof(ic_private)); ic_private.line[0] = 1; ic_private.filename[0] = strdup(f); } void parser_y_fini (void) { unsigned int i; for (i=0; i= MAX_INCLUDE_DEPTH) { yyerror("max inclusion depth reached"); return 1; } if(verbose) { fprintf(stderr, "including file %s from line %s:%d\n" , filename , ic_private.filename[ic_private.stack_ptr] , ic_private.line[ic_private.stack_ptr]); } /** * TODO: handle wildcards -- see glob() */ f = fopen(filename, "r"); if (!f) { yyerror("can't open include filename"); return 1; } p = ++ic_private.stack_ptr; ic_private.file[p] = f; ic_private.stack[p] = YY_CURRENT_BUFFER; ic_private.line[p] = 1; ic_private.filename[p] = strdup(filename); yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); return 0; } %} %x USERDEF BOOLEAN %% <> { if (ic_private.filename[ic_private.stack_ptr]) { free(ic_private.filename[ic_private.stack_ptr]); ic_private.filename[ic_private.stack_ptr] = NULL; } if (ic_private.file[ic_private.stack_ptr]) { int stackp = ic_private.stack_ptr; fclose(ic_private.file[stackp]); if(verbose) { fprintf(stderr, "end of file %s, resuming %s line %d\n" , ic_private.filename[stackp] , (stackp > 0 ? ic_private.filename[stackp-1] : "") , (stackp > 0 ? ic_private.line[stackp-1] : -1)); } ic_private.file[stackp] = NULL; yy_delete_buffer (YY_CURRENT_BUFFER); yy_switch_to_buffer(ic_private.stack[stackp]); } if (--ic_private.stack_ptr < 0) { yyterminate(); } } ^\n { /* eat totally blank lines */ ic_private.line[ic_private.stack_ptr]++; } ^#.*\n { /* eat comment lines */ ic_private.line[ic_private.stack_ptr]++; } ^[\t ]+#.*\n { /* eat comment lines inside of stanzas */ ic_private.line[ic_private.stack_ptr]++; } ^[\t ]+ return FIRST_SPACES; [\t ]+ /* ignore spaces in line */ ; [0-9]+ { /* process a number */ yylval.num = atof(yytext); return INTEGER; } %forever { /* a number, really 0 */ yylval.num = 0; return INTEGER; } [0-9]+\.[0-9]* { /* process a number */ yylval.dblnum = atof(yytext); return NUMBER; } y | yes | true | on { /* process a boolean */ yylval.num = 1; return BOOL; } n | no | false | off { /* process a boolean */ yylval.num = 0; return BOOL; } = return EQUAL; \n { ic_private.line[ic_private.stack_ptr]++; BEGIN INITIAL; return EOL; } \n { ic_private.line[ic_private.stack_ptr]++; return EOL; } = return EQUAL; version return VERSION; config return CONFIG; setup return SETUP; conn { BEGIN USERDEF; return CONN; } include return INCLUDE; %default return DEFAULT; [^\"= \t\n]+ { int tok; if(yydebug) { fprintf(stderr, "STR/KEY: %s\n", yytext); } tok = parser_find_keyword(yytext, &yylval); switch(tok) { case BOOLWORD: BEGIN BOOLEAN; break; default: } return tok; } %default { BEGIN INITIAL; return DEFAULT; } [^\"= \t\n]+ { yylval.s = strdup(yytext); BEGIN INITIAL; return STRING; } \"[^\"\n]*\" { char *s = yytext + 1; int len = strlen(s); assert(len>0); /* remove trailing " */ s[len-1]='\0'; if(yydebug) { fprintf(stderr, "STRING: \"%s\"\n", s);} yylval.s = strdup(s); return STRING; } #.* /* eat comment lines */ ; . yyerror(yytext); %% int yywrap(void) { return 1; } /* * Local Variables: * c-basic-offset:4 * c-style: pluto * End: */