This source file includes following definitions.
- zend_ini_do_op
- zend_ini_init_string
- zend_ini_add_string
- zend_ini_get_constant
- zend_ini_get_var
- ini_error
- zend_parse_ini_file
- zend_parse_ini_string
1 %{
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #define DEBUG_CFG_PARSER 0
24
25 #include "zend.h"
26 #include "zend_API.h"
27 #include "zend_ini.h"
28 #include "zend_constants.h"
29 #include "zend_ini_scanner.h"
30 #include "zend_extensions.h"
31
32 #ifdef ZEND_WIN32
33 #include "win32/syslog.h"
34 #endif
35
36 #define YYERROR_VERBOSE
37 #define YYSTYPE zval
38
39 int ini_parse(void);
40
41 #define ZEND_INI_PARSER_CB (CG(ini_parser_param))->ini_parser_cb
42 #define ZEND_INI_PARSER_ARG (CG(ini_parser_param))->arg
43
44 #ifdef _MSC_VER
45 #define YYMALLOC malloc
46 #define YYFREE free
47 #endif
48
49
50
51 static void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
52 {
53 int i_result;
54 int i_op1, i_op2;
55 int str_len;
56 char str_result[MAX_LENGTH_OF_LONG];
57
58 i_op1 = atoi(Z_STRVAL_P(op1));
59 zend_string_free(Z_STR_P(op1));
60 if (op2) {
61 i_op2 = atoi(Z_STRVAL_P(op2));
62 zend_string_free(Z_STR_P(op2));
63 } else {
64 i_op2 = 0;
65 }
66
67 switch (type) {
68 case '|':
69 i_result = i_op1 | i_op2;
70 break;
71 case '&':
72 i_result = i_op1 & i_op2;
73 break;
74 case '^':
75 i_result = i_op1 ^ i_op2;
76 break;
77 case '~':
78 i_result = ~i_op1;
79 break;
80 case '!':
81 i_result = !i_op1;
82 break;
83 default:
84 i_result = 0;
85 break;
86 }
87
88 str_len = zend_sprintf(str_result, "%d", i_result);
89 ZVAL_PSTRINGL(result, str_result, str_len);
90 }
91
92
93
94
95 static void zend_ini_init_string(zval *result)
96 {
97 ZVAL_EMPTY_PSTRING(result);
98 }
99
100
101
102
103 static void zend_ini_add_string(zval *result, zval *op1, zval *op2)
104 {
105 int length, op1_len;
106
107 if (Z_TYPE_P(op1) != IS_STRING) {
108 zend_string *str = zval_get_string(op1);
109
110 ZVAL_PSTRINGL(op1, ZSTR_VAL(str), ZSTR_LEN(str));
111 zend_string_release(str);
112 }
113 op1_len = (int)Z_STRLEN_P(op1);
114
115 if (Z_TYPE_P(op2) != IS_STRING) {
116 convert_to_string(op2);
117 }
118 length = op1_len + (int)Z_STRLEN_P(op2);
119
120 ZVAL_NEW_STR(result, zend_string_extend(Z_STR_P(op1), length, 1));
121 memcpy(Z_STRVAL_P(result) + op1_len, Z_STRVAL_P(op2), Z_STRLEN_P(op2) + 1);
122 }
123
124
125
126
127 static void zend_ini_get_constant(zval *result, zval *name)
128 {
129 zval *c, tmp;
130
131
132 if (!memchr(Z_STRVAL_P(name), ':', Z_STRLEN_P(name))
133 && (c = zend_get_constant(Z_STR_P(name))) != 0) {
134 if (Z_TYPE_P(c) != IS_STRING) {
135 ZVAL_COPY_VALUE(&tmp, c);
136 if (Z_OPT_CONSTANT(tmp)) {
137 zval_update_constant_ex(&tmp, 1, NULL);
138 }
139 zval_opt_copy_ctor(&tmp);
140 convert_to_string(&tmp);
141 c = &tmp;
142 }
143 ZVAL_PSTRINGL(result, Z_STRVAL_P(c), Z_STRLEN_P(c));
144 if (c == &tmp) {
145 zend_string_release(Z_STR(tmp));
146 }
147 zend_string_free(Z_STR_P(name));
148 } else {
149 *result = *name;
150 }
151 }
152
153
154
155
156 static void zend_ini_get_var(zval *result, zval *name)
157 {
158 zval *curval;
159 char *envvar;
160
161
162 if ((curval = zend_get_configuration_directive(Z_STR_P(name))) != NULL) {
163 ZVAL_PSTRINGL(result, Z_STRVAL_P(curval), Z_STRLEN_P(curval));
164
165 } else if ((envvar = zend_getenv(Z_STRVAL_P(name), Z_STRLEN_P(name))) != NULL ||
166 (envvar = getenv(Z_STRVAL_P(name))) != NULL) {
167 ZVAL_PSTRING(result, envvar);
168 } else {
169 zend_ini_init_string(result);
170 }
171 }
172
173
174
175
176 static ZEND_COLD void ini_error(const char *msg)
177 {
178 char *error_buf;
179 int error_buf_len;
180 char *currently_parsed_filename;
181
182 currently_parsed_filename = zend_ini_scanner_get_filename();
183 if (currently_parsed_filename) {
184 error_buf_len = 128 + (int)strlen(msg) + (int)strlen(currently_parsed_filename);
185 error_buf = (char *) emalloc(error_buf_len);
186
187 sprintf(error_buf, "%s in %s on line %d\n", msg, currently_parsed_filename, zend_ini_scanner_get_lineno());
188 } else {
189 error_buf = estrdup("Invalid configuration directive\n");
190 }
191
192 if (CG(ini_parser_unbuffered_errors)) {
193 #ifdef ZEND_WIN32
194 syslog(LOG_ALERT, "PHP: %s (%s)", error_buf, GetCommandLine());
195 #endif
196 fprintf(stderr, "PHP: %s", error_buf);
197 } else {
198 zend_error(E_WARNING, "%s", error_buf);
199 }
200 efree(error_buf);
201 }
202
203
204
205
206 ZEND_API int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, int scanner_mode, zend_ini_parser_cb_t ini_parser_cb, void *arg)
207 {
208 int retval;
209 zend_ini_parser_param ini_parser_param;
210
211 ini_parser_param.ini_parser_cb = ini_parser_cb;
212 ini_parser_param.arg = arg;
213 CG(ini_parser_param) = &ini_parser_param;
214
215 if (zend_ini_open_file_for_scanning(fh, scanner_mode) == FAILURE) {
216 return FAILURE;
217 }
218
219 CG(ini_parser_unbuffered_errors) = unbuffered_errors;
220 retval = ini_parse();
221 zend_file_handle_dtor(fh);
222
223 shutdown_ini_scanner();
224
225 if (retval == 0) {
226 return SUCCESS;
227 } else {
228 return FAILURE;
229 }
230 }
231
232
233
234
235 ZEND_API int zend_parse_ini_string(char *str, zend_bool unbuffered_errors, int scanner_mode, zend_ini_parser_cb_t ini_parser_cb, void *arg)
236 {
237 int retval;
238 zend_ini_parser_param ini_parser_param;
239
240 ini_parser_param.ini_parser_cb = ini_parser_cb;
241 ini_parser_param.arg = arg;
242 CG(ini_parser_param) = &ini_parser_param;
243
244 if (zend_ini_prepare_string_for_scanning(str, scanner_mode) == FAILURE) {
245 return FAILURE;
246 }
247
248 CG(ini_parser_unbuffered_errors) = unbuffered_errors;
249 retval = ini_parse();
250
251 shutdown_ini_scanner();
252
253 if (retval == 0) {
254 return SUCCESS;
255 } else {
256 return FAILURE;
257 }
258 }
259
260
261 %}
262
263 %expect 0
264 %pure_parser
265
266 %token TC_SECTION
267 %token TC_RAW
268 %token TC_CONSTANT
269 %token TC_NUMBER
270 %token TC_STRING
271 %token TC_WHITESPACE
272 %token TC_LABEL
273 %token TC_OFFSET
274 %token TC_DOLLAR_CURLY
275 %token TC_VARNAME
276 %token TC_QUOTED_STRING
277 %token BOOL_TRUE
278 %token BOOL_FALSE
279 %token NULL_NULL
280 %token END_OF_LINE
281 %token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?' '@' '{' '}'
282 %left '|' '&' '^'
283 %right '~' '!'
284
285 %%
286
287 statement_list:
288 statement_list statement
289 |
290 ;
291
292 statement:
293 TC_SECTION section_string_or_value ']' {
294 #if DEBUG_CFG_PARSER
295 printf("SECTION: [%s]\n", Z_STRVAL($2));
296 #endif
297 ZEND_INI_PARSER_CB(&$2, NULL, NULL, ZEND_INI_PARSER_SECTION, ZEND_INI_PARSER_ARG);
298 zend_string_release(Z_STR($2));
299 }
300 | TC_LABEL '=' string_or_value {
301 #if DEBUG_CFG_PARSER
302 printf("NORMAL: '%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3));
303 #endif
304 ZEND_INI_PARSER_CB(&$1, &$3, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG);
305 zend_string_release(Z_STR($1));
306 zval_ptr_dtor(&$3);
307 }
308 | TC_OFFSET option_offset ']' '=' string_or_value {
309 #if DEBUG_CFG_PARSER
310 printf("OFFSET: '%s'[%s] = '%s'\n", Z_STRVAL($1), Z_STRVAL($2), Z_STRVAL($5));
311 #endif
312 ZEND_INI_PARSER_CB(&$1, &$5, &$2, ZEND_INI_PARSER_POP_ENTRY, ZEND_INI_PARSER_ARG);
313 zend_string_release(Z_STR($1));
314 if (Z_TYPE($2) == IS_STRING) {
315 zend_string_release(Z_STR($2));
316 } else {
317 zval_dtor(&$2);
318 }
319 zval_ptr_dtor(&$5);
320 }
321 | TC_LABEL { ZEND_INI_PARSER_CB(&$1, NULL, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG); zend_string_release(Z_STR($1)); }
322 | END_OF_LINE
323 ;
324
325 section_string_or_value:
326 var_string_list_section { $$ = $1; }
327 | { zend_ini_init_string(&$$); }
328 ;
329
330 string_or_value:
331 expr { $$ = $1; }
332 | BOOL_TRUE { $$ = $1; }
333 | BOOL_FALSE { $$ = $1; }
334 | NULL_NULL { $$ = $1; }
335 | END_OF_LINE { zend_ini_init_string(&$$); }
336 ;
337
338 option_offset:
339 var_string_list { $$ = $1; }
340 | { zend_ini_init_string(&$$); }
341 ;
342
343 encapsed_list:
344 encapsed_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
345 | encapsed_list TC_QUOTED_STRING { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
346 | { zend_ini_init_string(&$$); }
347 ;
348
349 var_string_list_section:
350 cfg_var_ref { $$ = $1; }
351 | constant_literal { $$ = $1; }
352 | '"' encapsed_list '"' { $$ = $2; }
353 | var_string_list_section cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
354 | var_string_list_section constant_literal { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
355 | var_string_list_section '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); zend_string_free(Z_STR($3)); }
356 ;
357
358 var_string_list:
359 cfg_var_ref { $$ = $1; }
360 | constant_string { $$ = $1; }
361 | '"' encapsed_list '"' { $$ = $2; }
362 | var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
363 | var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
364 | var_string_list '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); zend_string_free(Z_STR($3)); }
365 ;
366
367 expr:
368 var_string_list { $$ = $1; }
369 | expr '|' expr { zend_ini_do_op('|', &$$, &$1, &$3); }
370 | expr '&' expr { zend_ini_do_op('&', &$$, &$1, &$3); }
371 | expr '^' expr { zend_ini_do_op('^', &$$, &$1, &$3); }
372 | '~' expr { zend_ini_do_op('~', &$$, &$2, NULL); }
373 | '!' expr { zend_ini_do_op('!', &$$, &$2, NULL); }
374 | '(' expr ')' { $$ = $2; }
375 ;
376
377 cfg_var_ref:
378 TC_DOLLAR_CURLY TC_VARNAME '}' { zend_ini_get_var(&$$, &$2); zend_string_free(Z_STR($2)); }
379 ;
380
381 constant_literal:
382 TC_CONSTANT { $$ = $1; }
383 | TC_RAW { $$ = $1; }
384 | TC_NUMBER { $$ = $1; }
385 | TC_STRING { $$ = $1; }
386 | TC_WHITESPACE { $$ = $1; }
387 ;
388
389 constant_string:
390 TC_CONSTANT { zend_ini_get_constant(&$$, &$1); }
391 | TC_RAW { $$ = $1; }
392 | TC_NUMBER { $$ = $1; }
393 | TC_STRING { $$ = $1; }
394 | TC_WHITESPACE { $$ = $1; }
395 ;
396
397
398
399
400
401
402
403