1 /* servscan.l -- Scanner for dictd server configuration file
2  * Created: Fri Feb 28 08:23:03 1997 by faith@cs.unc.edu
3  * Copyright 1997, 1999, 2000, 2002 Rickard E. Faith (faith@acm.org)
4  * Copyright 2002-2008 Aleksey Cheusov (vle@gmx.net)
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation; either version 1, or (at your option) any
9  * later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with this program; if not, write to the Free Software Foundation, Inc.,
18  * 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 %option stack debug
22 %{
23 #include "dictd.h"
24 #include "servparse.h"
25 extern int  yylex( void );
26 extern int  yydebug;
27 extern void yyerror( const char *message );
28 static void include_file( void );
29 static void include_complete( void );
30 YY_BUFFER_STATE orig_buffer = NULL;
31 src_Type orig_source = NULL;
32 #define RETURN(val) do {                  \
33    yylval.token.src = src_get( yyleng );  \
34    return val;                            \
35 } while (0)
36 
37 /*
38   \n    --> new line character
39   \\    --> backslash
40   \<NL> --> no symbol
41   \"    --> double quote symbol
42 */
escape_string(char * s,int len)43 static int escape_string (char *s, int len)
44 {
45    int ret = 0;
46    int i   = 0;
47 
48    for (i=0; i < len; ++i){
49       if (s [i] != '\\'){
50 	 s [ret++] = s [i];
51       }else if (s [i+1] == '\\'){
52 	 s [ret++] = '\\';
53 
54 	 ++i;
55       }else if (s [i+1] == 'n'){
56 	 s [ret++] = '\n';
57 
58 	 ++i;
59       }else if (s [i+1] == '"'){
60 	 s [ret++] = '"';
61 
62 	 ++i;
63       }else if (s [i+1] != '\n'){
64 	 s [ret++] = s [++i];
65       }else{
66 	 ++i;
67       }
68    }
69 
70    return ret;
71 }
72 
73 %}
74 %s OTHER
75 integer                     [[:digit:]]+
76 comment                     #.*
77 word                        ([[:alnum:]_/:.*-][[:alnum:]_/:.*%-]*)
78 string                      \"(([^\"\n])|\"\"|\\\n|\\\")*\"
79 NL                          \n
80 WS                          [[:blank:]]+
81 %%
82 <INITIAL>{
83    .*{NL}                   src_line(yytext,yyleng); yyless(0); BEGIN(OTHER);
84    .*                       src_line(yytext,yyleng); yyless(0); BEGIN(OTHER);
85 }
86 include{WS}({word}|{string})   include_file();
87 access                      RETURN(TOKEN_ACCESS);
88 allow                       RETURN(TOKEN_ALLOW);
89 deny                        RETURN(TOKEN_DENY);
90 group                       RETURN(TOKEN_GROUP);
91 database                    RETURN(TOKEN_DATABASE);
92 database_exit               RETURN(TOKEN_DATABASE_EXIT);
93 data                        RETURN(TOKEN_DATA);
94 index                       RETURN(TOKEN_INDEX);
95 index_suffix                RETURN(TOKEN_INDEX_SUFFIX);
96 index_word                  RETURN(TOKEN_INDEX_WORD);
97 filter                      RETURN(TOKEN_FILTER);
98 prefilter                   RETURN(TOKEN_PREFILTER);
99 postfilter                  RETURN(TOKEN_POSTFILTER);
100 name                        RETURN(TOKEN_NAME);
101 user                        RETURN(TOKEN_USER);
102 authonly                    RETURN(TOKEN_AUTHONLY);
103 
104 site                        RETURN(TOKEN_SITE);
105 site_no_banner              RETURN(TOKEN_SITE_NO_BANNER);
106 site_no_uptime              RETURN(TOKEN_SITE_NO_UPTIME);
107 site_no_dblist              RETURN(TOKEN_SITE_NO_DBLIST);
108 
109 invisible                   RETURN(TOKEN_INVISIBLE);
110 database_virtual            RETURN(TOKEN_DATABASE_VIRTUAL);
111 info                        RETURN(TOKEN_INFO);
112 database_list               RETURN(TOKEN_DATABASE_LIST);
113 database_plugin             RETURN(TOKEN_DATABASE_PLUGIN);
114 plugin                      RETURN(TOKEN_PLUGIN);
115 disable_strategy            RETURN(TOKEN_DISABLE_STRAT);
116 default_strategy            RETURN(TOKEN_DEFAULT_STRAT);
117 
118 dbname_nomime               RETURN(TOKEN_NOMIME_DBNAME);
119 dbname_mime                 RETURN(TOKEN_MIME_DBNAME);
120 database_mime               RETURN(TOKEN_DATABASE_MIME);
121 
122 global                      RETURN(TOKEN_GLOBAL);
123 port                        RETURN(TOKEN_PORT);
124 delay                       RETURN(TOKEN_DELAY);
125 depth                       RETURN(TOKEN_DEPTH);
126 timestamp                   RETURN(TOKEN_TIMESTAMP);
127 log_option                  RETURN(TOKEN_LOG_OPTION);
128 debug_option                RETURN(TOKEN_DEBUG_OPTION);
129 locale                      RETURN(TOKEN_LOCALE);
130 add_strategy                RETURN(TOKEN_ADD_STRAT);
131 listen_to                   RETURN(TOKEN_LISTEN_TO);
132 address_family              RETURN(TOKEN_ADDRESS_FAMILY);
133 syslog                      RETURN(TOKEN_SYSLOG);
134 syslog_facility             RETURN(TOKEN_SYSLOG_FACILITY);
135 log_file                    RETURN(TOKEN_LOG_FILE);
136 pid_file                    RETURN(TOKEN_PID_FILE);
137 fast_start                  RETURN(TOKEN_FAST_START);
138 without_mmap                RETURN(TOKEN_WITHOUT_MMAP);
139 
140 limit                       RETURN(TOKEN_LIMIT_CHILDS);
141 limit_childs                RETURN(TOKEN_LIMIT_CHILDS);
142 limit_matches               RETURN(TOKEN_LIMIT_MATCHES);
143 limit_definitions           RETURN(TOKEN_LIMIT_DEFS);
144 limit_time                  RETURN(TOKEN_LIMIT_TIME);
145 limit_queries               RETURN(TOKEN_LIMIT_QUERIES);
146 
147 {integer}                   { yylval.token.integer = atoi(yytext);
148                               RETURN(TOKEN_NUMBER);
149                             }
150 {word}                      { yylval.token.string = str_findn(yytext, yyleng);
151                               RETURN(TOKEN_STRING);
152                             }
153 {string}                    {
154 				yylval.token.string =
155 				   str_findn (
156 				      yytext+1,
157 				      escape_string (yytext+1, yyleng-2));
158 				RETURN(TOKEN_STRING);
159                             }
160 {NL}                        BEGIN(INITIAL);
161 {WS}                        src_advance( yyleng );
162 {comment}                   src_advance( yyleng );
163 .                           RETURN(yytext[0]);
164 <<EOF>>                     { if (orig_buffer) include_complete();
165                               else RETURN(0);
166                             }
167 %%
168 int yywrap( void )
169 {
170    return 1;
171 }
172 
173 void yyerror( const char *message )
174 {
175    src_parse_error( stderr, yylval.token.src, message );
176    err_fatal( __func__, "parse error\n" );
177    exit( 1 );
178 }
179 
180 static void include_file( void ) {
181    const char *file;
182    int i;
183    for ( i = 8; yytext[i] == ' ' || yytext[i] == '\t'; ++i )
184       ;  /* advance past include{WS} to filename */
185    if ( yytext[i] == '"' )  /* process {string} */
186       file = str_findn(yytext+i+1, yyleng-i-2);
187    else                     /* process {word} */
188       file = str_findn(yytext+i, yyleng-i);
189    orig_source = src_get( yyleng );
190    if ( orig_buffer ) {
191       src_print_error( stderr, orig_source, NULL );
192       err_fatal( __func__, "Nested includes are not permitted\n" );
193       exit( 1 );
194    }
195    orig_buffer = YY_CURRENT_BUFFER;
196    yyin = fopen( file, "r" );
197    if ( ! yyin ) {
198       src_print_error( stderr, orig_source, NULL );
199       err_fatal( __func__, "Cannot open \"%s\" for read\n", file );
200       exit( 1 );
201    }
202    src_new_file( file );
203    src_new_line ( 0 );
204    yy_switch_to_buffer(
205       yy_create_buffer( yyin, YY_BUF_SIZE ) );
206    BEGIN(INITIAL);
207 }
208 
209 static void include_complete( void ) {
210    const char *orig_line;
211    yy_delete_buffer( YY_CURRENT_BUFFER );
212    yy_switch_to_buffer( orig_buffer );
213    orig_buffer = NULL;
214    BEGIN(OTHER);
215    src_new_file( src_filename( orig_source ) );
216    orig_line = src_source_line( orig_source );
217    src_line( orig_line, strlen( orig_line ) );
218    src_new_line( src_linenumber( orig_source ) );
219    src_advance( src_offset( orig_source ) + src_length( orig_source ) );
220    orig_source = NULL;
221 }
222