/* the "incl" state is used for picking up the name of an include file */ %x incl %{ #include #include #include #include "conffile_internal.h" #include "conffile.tab.h" #include "util.h" #define YY_NO_UNPUT #define YY_INPUT(buf,result,max_size) \ do{ \ (result)= fread((buf),1,(max_size),yyin); \ if (ferror(yyin)) \ fatal_perror("Error reading configuration file (%s)", \ config_file); \ }while(0) #define MAX_INCLUDE_DEPTH 10 struct include_stack_item { YY_BUFFER_STATE bst; uint32_t lineno; cstring_t file; }; struct include_stack_item include_stack[MAX_INCLUDE_DEPTH]; int include_stack_ptr=0; uint32_t config_lineno=0; cstring_t config_file="xxx"; static struct p_node *leafnode(uint32_t type) { struct p_node *r; r=safe_malloc(sizeof(*r),"leafnode"); r->type=type; r->loc.file=config_file; r->loc.line=config_lineno; r->l=NULL; r->r=NULL; return r; } static struct p_node *keynode(atom_t key) { struct p_node *r; r=leafnode(T_KEY); r->data.key=intern(key); return r; } static struct p_node *stringnode(string_t string) { struct p_node *r; r=leafnode(T_STRING); string++; string[strlen(string)-1]=0; r->data.string=safe_strdup(string,"stringnode"); return r; } static struct p_node *numnode(string_t number) { struct p_node *r; r=leafnode(T_NUMBER); r->data.number=atoi(number); return r; } %} %% include BEGIN(incl); [ \t]* /* eat the whitespace */ [^ \t\n]+ { /* got the include filename */ if (include_stack_ptr >= MAX_INCLUDE_DEPTH) { fatal("Configuration file includes nested too deeply"); } include_stack[include_stack_ptr].bst=YY_CURRENT_BUFFER; include_stack[include_stack_ptr].lineno=config_lineno; include_stack[include_stack_ptr].file=config_file; include_stack_ptr++; yyin=fopen(yytext,"r"); if (!yyin) { fatal("Can't open included file %s",yytext); } config_lineno=1; config_file=safe_strdup(yytext,"conffile.fl/include"); yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); BEGIN(INITIAL); } \n { /* include with no filename */ Message(M_FATAL,"config file %s line %d: %s\n",config_file, config_lineno,"``include'' requires a filename"); BEGIN(INITIAL); ++config_lineno; ++yynerrs; } <> { if (--include_stack_ptr < 0) { yyterminate(); } else { fclose(yyin); yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer(include_stack[include_stack_ptr].bst); config_lineno=include_stack[include_stack_ptr].lineno; config_file=include_stack[include_stack_ptr].file; } } \"[^\"]*\" yylval=stringnode(yytext); return TOK_STRING; [[:alpha:]_][[:alnum:]\-_]* yylval=keynode(yytext); return TOK_KEY; [[:digit:]]+ yylval=numnode(yytext); return TOK_NUMBER; /* Eat comments */ \#.*\n config_lineno++; /* Count lines */ \n config_lineno++; /* Eat whitespace */ [[:blank:]\j] /* Return all unclaimed single characters to the parser */ . return *yytext;