/* servscan.l -- Scanner for dictd server configuration file
* Created: Fri Feb 28 08:23:03 1997 by faith@cs.unc.edu
* Revised: Fri Mar 29 12:42:57 2002 by faith@acm.org
* Copyright 1997, 1999, 2000, 2002 Rickard E. Faith (faith@acm.org)
*
* 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 1, or (at your option) any
* later version.
*
* 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.
*/
%option stack debug
%{
#include "dictd.h"
#include "servparse.h"
extern int yylex( void );
extern int yydebug;
extern void yyerror( const char *message );
static void include_file( void );
static void include_complete( void );
YY_BUFFER_STATE orig_buffer = NULL;
src_Type orig_source = NULL;
#define RETURN(val) do { \
yylval.token.src = src_get( yyleng ); \
return val; \
} while (0)
/*
\n --> new line character
\\ --> backslash
\<NL> --> no symbol
\" --> double quote symbol
*/
static int escape_string (char *s, int len)
{
int ret = 0;
int i = 0;
for (i=0; i < len; ++i){
if (s [i] != '\\'){
s [ret++] = s [i];
}else if (s [i+1] == '\\'){
s [ret++] = '\\';
++i;
}else if (s [i+1] == 'n'){
s [ret++] = '\n';
++i;
}else if (s [i+1] == '"'){
s [ret++] = '"';
++i;
}else if (s [i+1] != '\n'){
s [ret++] = s [++i];
}else{
++i;
}
}
return ret;
}
%}
%s OTHER
integer [[:digit:]]+
comment #.*
word ([[:alnum:]_/\-\.\*][[:alnum:]_/\-\.\*]*)
string \"(([^\"\n])|\"\"|\\\n|\\\")*\"
NL \n
WS [[:blank:]]+
%%
<INITIAL>{
.*{NL} src_line(yytext,yyleng); yyless(0); BEGIN(OTHER);
.* src_line(yytext,yyleng); yyless(0); BEGIN(OTHER);
}
include{WS}({word}|{string}) include_file();
access RETURN(TOKEN_ACCESS);
allow RETURN(TOKEN_ALLOW);
deny RETURN(TOKEN_DENY);
group RETURN(TOKEN_GROUP);
database RETURN(TOKEN_DATABASE);
database_exit RETURN(TOKEN_DATABASE_EXIT);
data RETURN(TOKEN_DATA);
index RETURN(TOKEN_INDEX);
index_suffix RETURN(TOKEN_INDEX_SUFFIX);
index_word RETURN(TOKEN_INDEX_WORD);
filter RETURN(TOKEN_FILTER);
prefilter RETURN(TOKEN_PREFILTER);
postfilter RETURN(TOKEN_POSTFILTER);
name RETURN(TOKEN_NAME);
user RETURN(TOKEN_USER);
authonly RETURN(TOKEN_AUTHONLY);
site RETURN(TOKEN_SITE);
site_no_banner RETURN(TOKEN_SITE_NO_BANNER);
site_no_uptime RETURN(TOKEN_SITE_NO_UPTIME);
site_no_dblist RETURN(TOKEN_SITE_NO_DBLIST);
invisible RETURN(TOKEN_INVISIBLE);
database_virtual RETURN(TOKEN_DATABASE_VIRTUAL);
info RETURN(TOKEN_INFO);
database_list RETURN(TOKEN_DATABASE_LIST);
database_plugin RETURN(TOKEN_DATABASE_PLUGIN);
plugin RETURN(TOKEN_PLUGIN);
disable_strategy RETURN(TOKEN_DISABLE_STRAT);
default_strategy RETURN(TOKEN_DEFAULT_STRAT);
dbname_nomime RETURN(TOKEN_NOMIME_DBNAME);
dbname_mime RETURN(TOKEN_MIME_DBNAME);
database_mime RETURN(TOKEN_DATABASE_MIME);
global RETURN(TOKEN_GLOBAL);
port RETURN(TOKEN_PORT);
delay RETURN(TOKEN_DELAY);
depth RETURN(TOKEN_DEPTH);
timestamp RETURN(TOKEN_TIMESTAMP);
log_option RETURN(TOKEN_LOG_OPTION);
debug_option RETURN(TOKEN_DEBUG_OPTION);
locale RETURN(TOKEN_LOCALE);
add_strategy RETURN(TOKEN_ADD_STRAT);
listen_to RETURN(TOKEN_LISTEN_TO);
syslog RETURN(TOKEN_SYSLOG);
syslog_facility RETURN(TOKEN_SYSLOG_FACILITY);
log_file RETURN(TOKEN_LOG_FILE);
pid_file RETURN(TOKEN_PID_FILE);
fast_start RETURN(TOKEN_FAST_START);
without_mmap RETURN(TOKEN_WITHOUT_MMAP);
limit RETURN(TOKEN_LIMIT_CHILDS);
limit_childs RETURN(TOKEN_LIMIT_CHILDS);
limit_matches RETURN(TOKEN_LIMIT_MATCHES);
limit_definitions RETURN(TOKEN_LIMIT_DEFS);
limit_time RETURN(TOKEN_LIMIT_TIME);
limit_queries RETURN(TOKEN_LIMIT_QUERIES);
{integer} { yylval.token.integer = atoi(yytext);
RETURN(TOKEN_NUMBER);
}
{word} { yylval.token.string = str_findn(yytext, yyleng);
RETURN(TOKEN_STRING);
}
{string} {
yylval.token.string =
str_findn (
yytext+1,
escape_string (yytext+1, yyleng-2));
RETURN(TOKEN_STRING);
}
{NL} BEGIN(INITIAL);
{WS} src_advance( yyleng );
{comment} src_advance( yyleng );
. RETURN(yytext[0]);
<<EOF>> { if (orig_buffer) include_complete();
else RETURN(0);
}
%%
int yywrap( void )
{
return 1;
}
void yyerror( const char *message )
{
src_parse_error( stderr, yylval.token.src, message );
err_fatal( __FUNCTION__, "parse error\n" );
exit( 1 );
}
static void include_file( void ) {
const char *file;
int i;
for ( i = 8; yytext[i] == ' ' || yytext[i] == '\t'; ++i )
; /* advance past include{WS} to filename */
if ( yytext[i] == '"' ) /* process {string} */
file = str_findn(yytext+i+1, yyleng-i-2);
else /* process {word} */
file = str_findn(yytext+i, yyleng-i);
orig_source = src_get( yyleng );
if ( orig_buffer ) {
src_print_error( stderr, orig_source, NULL );
err_fatal( __FUNCTION__, "Nested includes are not permitted\n" );
exit( 1 );
}
orig_buffer = YY_CURRENT_BUFFER;
yyin = fopen( file, "r" );
if ( ! yyin ) {
src_print_error( stderr, orig_source, NULL );
err_fatal( __FUNCTION__, "Cannot open \"%s\" for read\n", file );
exit( 1 );
}
src_new_file( file );
src_new_line ( 0 );
yy_switch_to_buffer(
yy_create_buffer( yyin, YY_BUF_SIZE ) );
BEGIN(INITIAL);
}
static void include_complete( void ) {
const char *orig_line;
yy_delete_buffer( YY_CURRENT_BUFFER );
yy_switch_to_buffer( orig_buffer );
orig_buffer = NULL;
BEGIN(OTHER);
src_new_file( src_filename( orig_source ) );
orig_line = src_source_line( orig_source );
src_line( orig_line, strlen( orig_line ) );
src_new_line( src_linenumber( orig_source ) );
src_advance( src_offset( orig_source ) + src_length( orig_source ) );
orig_source = NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1