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