%{ /* 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.5 2006/03/28 22:32:33 as Exp $ */ #include #include #include #include "y.tab.h" #define MAX_INCLUDE_DEPTH 20 #define YY_NO_UNPUT extern void yyerror(const char *); extern int yylex (void); 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]; } __parser_y_private; void _parser_y_error(char *b, int size, const char *s); void _parser_y_init (const char *f); void _parser_y_fini (void); int _parser_y_include (const char *filename); void _parser_y_error(char *b, int size, const char *s) { extern char *yytext; // was: char yytext[]; snprintf(b, size, "%s:%d: %s [%s]", __parser_y_private.filename[__parser_y_private.stack_ptr], __parser_y_private.line[__parser_y_private.stack_ptr], s, yytext); } void _parser_y_init (const char *f) { memset(&__parser_y_private, 0, sizeof(__parser_y_private)); __parser_y_private.line[0] = 1; __parser_y_private.filename[0] = strdup(f); } void _parser_y_fini (void) { unsigned int i; for (i = 0; i < MAX_INCLUDE_DEPTH; i++) { if (__parser_y_private.filename[i]) free(__parser_y_private.filename[i]); if (__parser_y_private.file[i]) fclose(__parser_y_private.file[i]); } memset(&__parser_y_private, 0, sizeof(__parser_y_private)); } int _parser_y_include (const char *filename) { glob_t files; int i, ret; ret = glob(filename, GLOB_ERR, NULL, &files); if (ret) { const char *err; switch (ret) { case GLOB_NOSPACE: err = "include files ran out of memory"; break; case GLOB_ABORTED: err = "include files aborted due to read error"; break; case GLOB_NOMATCH: err = "include files found no matches"; break; default: err = "unknown include files error"; } yyerror(err); return 1; } for (i = 0; i < files.gl_pathc; i++) { FILE *f; unsigned int p = __parser_y_private.stack_ptr + 1; if (p >= MAX_INCLUDE_DEPTH) { yyerror("max inclusion depth reached"); return 1; } f = fopen(files.gl_pathv[i], "r"); if (!f) { yyerror("can't open include filename"); continue; } __parser_y_private.stack_ptr++; __parser_y_private.file[p] = f; __parser_y_private.stack[p] = YY_CURRENT_BUFFER; __parser_y_private.line[p] = 1; __parser_y_private.filename[p] = strdup(files.gl_pathv[i]); yy_switch_to_buffer(yy_create_buffer(f, YY_BUF_SIZE)); } globfree(&files); return 0; } %} %% <> { if (__parser_y_private.filename[__parser_y_private.stack_ptr]) { free(__parser_y_private.filename[__parser_y_private.stack_ptr]); __parser_y_private.filename[__parser_y_private.stack_ptr] = NULL; } if (__parser_y_private.file[__parser_y_private.stack_ptr]) { fclose(__parser_y_private.file[__parser_y_private.stack_ptr]); __parser_y_private.file[__parser_y_private.stack_ptr] = NULL; yy_delete_buffer (YY_CURRENT_BUFFER); yy_switch_to_buffer (__parser_y_private.stack[__parser_y_private.stack_ptr]); } if (--__parser_y_private.stack_ptr < 0) { yyterminate(); } } ^[\t ]+ return FIRST_SPACES; [\t ]+ /* ignore spaces in line */ ; = return EQUAL; \n|#.*\n { __parser_y_private.line[__parser_y_private.stack_ptr]++; return EOL; } config return CONFIG; setup return SETUP; conn return CONN; ca return CA; include return INCLUDE; version return FILE_VERSION; [^\"= \t\n]+ { yylval.s = strdup(yytext); return STRING; } \"[^\"\n]*\" { yylval.s = strdup(yytext+1); if (yylval.s) yylval.s[strlen(yylval.s)-1]='\0'; return STRING; } . yyerror(yytext); %% int yywrap(void) { return 1; }