1 : %{
2 : /*
3 : +----------------------------------------------------------------------+
4 : | Zend Engine |
5 : +----------------------------------------------------------------------+
6 : | Copyright (c) 1998-2009 Zend Technologies Ltd. (http://www.zend.com) |
7 : +----------------------------------------------------------------------+
8 : | This source file is subject to version 2.00 of the Zend license, |
9 : | that is bundled with this package in the file LICENSE, and is |
10 : | available through the world-wide-web at the following url: |
11 : | http://www.zend.com/license/2_00.txt. |
12 : | If you did not receive a copy of the Zend license and are unable to |
13 : | obtain it through the world-wide-web, please send a note to |
14 : | license@zend.com so we can mail you a copy immediately. |
15 : +----------------------------------------------------------------------+
16 : | Authors: Zeev Suraski <zeev@zend.com> |
17 : | Jani Taskinen <jani@php.net> |
18 : +----------------------------------------------------------------------+
19 : */
20 :
21 : /* $Id: zend_ini_parser.y 277841 2009-03-26 20:02:53Z felipe $ */
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 : #define YYERROR_VERBOSE
33 : #define YYSTYPE zval
34 :
35 : #ifdef ZTS
36 : #define YYPARSE_PARAM tsrm_ls
37 : #define YYLEX_PARAM tsrm_ls
38 : int ini_parse(void *arg);
39 : #else
40 : int ini_parse(void);
41 : #endif
42 :
43 : #define ZEND_INI_PARSER_CB (CG(ini_parser_param))->ini_parser_cb
44 : #define ZEND_INI_PARSER_ARG (CG(ini_parser_param))->arg
45 :
46 : /* {{{ zend_ini_do_op()
47 : */
48 : static void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
49 156 : {
50 : int i_result;
51 : int i_op1, i_op2;
52 : char str_result[MAX_LENGTH_OF_LONG];
53 :
54 156 : i_op1 = atoi(Z_STRVAL_P(op1));
55 156 : free(Z_STRVAL_P(op1));
56 156 : if (op2) {
57 92 : i_op2 = atoi(Z_STRVAL_P(op2));
58 92 : free(Z_STRVAL_P(op2));
59 : } else {
60 64 : i_op2 = 0;
61 : }
62 :
63 156 : switch (type) {
64 : case '|':
65 28 : i_result = i_op1 | i_op2;
66 28 : break;
67 : case '&':
68 64 : i_result = i_op1 & i_op2;
69 64 : break;
70 : case '~':
71 64 : i_result = ~i_op1;
72 64 : break;
73 : case '!':
74 0 : i_result = !i_op1;
75 0 : break;
76 : default:
77 0 : i_result = 0;
78 : break;
79 : }
80 :
81 156 : Z_STRLEN_P(result) = zend_sprintf(str_result, "%d", i_result);
82 156 : Z_STRVAL_P(result) = (char *) malloc(Z_STRLEN_P(result)+1);
83 156 : memcpy(Z_STRVAL_P(result), str_result, Z_STRLEN_P(result));
84 156 : Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
85 156 : Z_TYPE_P(result) = IS_STRING;
86 156 : }
87 : /* }}} */
88 :
89 : /* {{{ zend_ini_init_string()
90 : */
91 : static void zend_ini_init_string(zval *result)
92 152654 : {
93 152654 : Z_STRVAL_P(result) = malloc(1);
94 152654 : Z_STRVAL_P(result)[0] = 0;
95 152654 : Z_STRLEN_P(result) = 0;
96 152654 : Z_TYPE_P(result) = IS_STRING;
97 152654 : }
98 : /* }}} */
99 :
100 : /* {{{ zend_ini_add_string()
101 : */
102 : static void zend_ini_add_string(zval *result, zval *op1, zval *op2)
103 18074 : {
104 18074 : int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
105 :
106 18074 : Z_STRVAL_P(result) = (char *) realloc(Z_STRVAL_P(op1), length+1);
107 18074 : memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
108 18074 : Z_STRVAL_P(result)[length] = 0;
109 18074 : Z_STRLEN_P(result) = length;
110 18074 : Z_TYPE_P(result) = IS_STRING;
111 18074 : }
112 : /* }}} */
113 :
114 : /* {{{ zend_ini_get_constant()
115 : */
116 : static void zend_ini_get_constant(zval *result, zval *name TSRMLS_DC)
117 34792 : {
118 : zval z_constant;
119 : UChar *u_name;
120 :
121 : /* in Unicode mode all constants are registered as Unicode */
122 34792 : u_name = malloc(UBYTES(Z_STRLEN_P(name) + 1));
123 34792 : u_charsToUChars(Z_STRVAL_P(name), u_name, Z_STRLEN_P(name) + 1);
124 :
125 : /* If name contains ':' it is not a constant. Bug #26893. */
126 35023 : if (!u_memchr(u_name, ':', Z_STRLEN_P(name))
127 : && zend_u_get_constant_ex(IS_UNICODE, ZSTR(u_name), Z_STRLEN_P(name), &z_constant, NULL, 0 TSRMLS_CC)) {
128 : /* z_constant is emalloc()'d */
129 231 : convert_to_string(&z_constant);
130 231 : Z_STRVAL_P(result) = zend_strndup(Z_STRVAL(z_constant), Z_STRLEN(z_constant));
131 231 : Z_STRLEN_P(result) = Z_STRLEN(z_constant);
132 231 : Z_TYPE_P(result) = Z_TYPE(z_constant);
133 231 : zval_dtor(&z_constant);
134 231 : free(Z_STRVAL_P(name));
135 : } else {
136 34561 : *result = *name;
137 : }
138 34792 : free(u_name);
139 34792 : }
140 : /* }}} */
141 :
142 : /* {{{ zend_ini_get_var()
143 : */
144 : static void zend_ini_get_var(zval *result, zval *name TSRMLS_DC)
145 26 : {
146 : zval curval;
147 : char *envvar;
148 :
149 : /* Fetch configuration option value */
150 26 : if (zend_get_configuration_directive(Z_STRVAL_P(name), Z_STRLEN_P(name)+1, &curval) == SUCCESS) {
151 0 : Z_STRVAL_P(result) = zend_strndup(Z_STRVAL(curval), Z_STRLEN(curval));
152 0 : Z_STRLEN_P(result) = Z_STRLEN(curval);
153 : /* ..or if not found, try ENV */
154 52 : } else if ((envvar = zend_getenv(Z_STRVAL_P(name), Z_STRLEN_P(name) TSRMLS_CC)) != NULL ||
155 : (envvar = getenv(Z_STRVAL_P(name))) != NULL) {
156 26 : Z_STRVAL_P(result) = strdup(envvar);
157 26 : Z_STRLEN_P(result) = strlen(envvar);
158 : } else {
159 0 : zend_ini_init_string(result);
160 : }
161 26 : }
162 : /* }}} */
163 :
164 : /* {{{ ini_error()
165 : */
166 : static void ini_error(char *msg)
167 4 : {
168 : char *error_buf;
169 : int error_buf_len;
170 : char *currently_parsed_filename;
171 : TSRMLS_FETCH();
172 :
173 4 : currently_parsed_filename = zend_ini_scanner_get_filename(TSRMLS_C);
174 4 : if (currently_parsed_filename) {
175 4 : error_buf_len = 128 + strlen(msg) + strlen(currently_parsed_filename); /* should be more than enough */
176 4 : error_buf = (char *) emalloc(error_buf_len);
177 :
178 4 : sprintf(error_buf, "%s in %s on line %d\n", msg, currently_parsed_filename, zend_ini_scanner_get_lineno(TSRMLS_C));
179 : } else {
180 0 : error_buf = estrdup("Invalid configuration directive\n");
181 : }
182 :
183 4 : if (CG(ini_parser_unbuffered_errors)) {
184 : #ifdef PHP_WIN32
185 : MessageBox(NULL, error_buf, "PHP Error", MB_OK|MB_TOPMOST|0x00200000L);
186 : #else
187 0 : fprintf(stderr, "PHP: %s", error_buf);
188 : #endif
189 : } else {
190 4 : zend_error(E_WARNING, "%s", error_buf);
191 : }
192 4 : efree(error_buf);
193 4 : }
194 : /* }}} */
195 :
196 : /* {{{ zend_parse_ini_file()
197 : */
198 : 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 TSRMLS_DC)
199 16988 : {
200 : int retval;
201 : zend_ini_parser_param ini_parser_param;
202 :
203 16988 : ini_parser_param.ini_parser_cb = ini_parser_cb;
204 16988 : ini_parser_param.arg = arg;
205 16988 : CG(ini_parser_param) = &ini_parser_param;
206 :
207 16988 : if (zend_ini_open_file_for_scanning(fh, scanner_mode TSRMLS_CC) == FAILURE) {
208 24 : return FAILURE;
209 : }
210 :
211 16964 : CG(ini_parser_unbuffered_errors) = unbuffered_errors;
212 16964 : retval = ini_parse(TSRMLS_C);
213 16964 : zend_file_handle_dtor(fh TSRMLS_CC);
214 :
215 16964 : shutdown_ini_scanner(TSRMLS_C);
216 :
217 16964 : if (retval == 0) {
218 16962 : return SUCCESS;
219 : } else {
220 2 : return FAILURE;
221 : }
222 : }
223 : /* }}} */
224 :
225 : /* {{{ zend_parse_ini_string()
226 : */
227 : 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 TSRMLS_DC)
228 17011 : {
229 : int retval;
230 : zend_ini_parser_param ini_parser_param;
231 :
232 17011 : ini_parser_param.ini_parser_cb = ini_parser_cb;
233 17011 : ini_parser_param.arg = arg;
234 17011 : CG(ini_parser_param) = &ini_parser_param;
235 :
236 17011 : if (zend_ini_prepare_string_for_scanning(str, scanner_mode TSRMLS_CC) == FAILURE) {
237 0 : return FAILURE;
238 : }
239 :
240 17011 : CG(ini_parser_unbuffered_errors) = unbuffered_errors;
241 17011 : retval = ini_parse(TSRMLS_C);
242 :
243 17011 : shutdown_ini_scanner(TSRMLS_C);
244 :
245 17011 : if (retval == 0) {
246 17009 : return SUCCESS;
247 : } else {
248 2 : return FAILURE;
249 : }
250 : }
251 : /* }}} */
252 :
253 : %}
254 :
255 : %expect 0
256 : %pure_parser
257 :
258 : %token TC_SECTION
259 : %token TC_RAW
260 : %token TC_CONSTANT
261 : %token TC_NUMBER
262 : %token TC_STRING
263 : %token TC_WHITESPACE
264 : %token TC_LABEL
265 : %token TC_OFFSET
266 : %token TC_DOLLAR_CURLY
267 : %token TC_VARNAME
268 : %token TC_QUOTED_STRING
269 : %token BOOL_TRUE
270 : %token BOOL_FALSE
271 : %token END_OF_LINE
272 : %token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?' '@' '{' '}'
273 : %left '|' '&'
274 : %right '~' '!'
275 :
276 : %%
277 :
278 : statement_list:
279 : statement_list statement
280 : | /* empty */
281 : ;
282 :
283 : statement:
284 : TC_SECTION section_string_or_value ']' {
285 : #if DEBUG_CFG_PARSER
286 : printf("SECTION: [%s]\n", Z_STRVAL($2));
287 : #endif
288 19304 : ZEND_INI_PARSER_CB(&$2, NULL, NULL, ZEND_INI_PARSER_SECTION, ZEND_INI_PARSER_ARG TSRMLS_CC);
289 19304 : free(Z_STRVAL($2));
290 : }
291 19304 : | TC_LABEL '=' string_or_value {
292 : #if DEBUG_CFG_PARSER
293 : printf("NORMAL: '%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3));
294 : #endif
295 721930 : ZEND_INI_PARSER_CB(&$1, &$3, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
296 721930 : free(Z_STRVAL($1));
297 721930 : free(Z_STRVAL($3));
298 : }
299 721930 : | TC_OFFSET option_offset ']' '=' string_or_value {
300 : #if DEBUG_CFG_PARSER
301 : printf("OFFSET: '%s'[%s] = '%s'\n", Z_STRVAL($1), Z_STRVAL($2), Z_STRVAL($5));
302 : #endif
303 21 : ZEND_INI_PARSER_CB(&$1, &$5, &$2, ZEND_INI_PARSER_POP_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
304 21 : free(Z_STRVAL($1));
305 21 : free(Z_STRVAL($2));
306 21 : free(Z_STRVAL($5));
307 : }
308 21 : | TC_LABEL { ZEND_INI_PARSER_CB(&$1, NULL, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); free(Z_STRVAL($1)); }
309 8 : | END_OF_LINE
310 : ;
311 :
312 : section_string_or_value:
313 19304 : var_string_list { $$ = $1; }
314 19304 : | /* empty */ { zend_ini_init_string(&$$); }
315 0 : ;
316 :
317 : string_or_value:
318 552942 : expr { $$ = $1; }
319 552942 : | BOOL_TRUE { $$ = $1; }
320 99 : | BOOL_FALSE { $$ = $1; }
321 33768 : | END_OF_LINE { zend_ini_init_string(&$$); }
322 135142 : ;
323 :
324 : option_offset:
325 14 : var_string_list { $$ = $1; }
326 14 : | /* empty */ { zend_ini_init_string(&$$); }
327 7 : ;
328 :
329 : encapsed_list:
330 13 : encapsed_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
331 13 : | encapsed_list TC_QUOTED_STRING { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
332 17500 : | /* empty */ { zend_ini_init_string(&$$); }
333 17505 : ;
334 :
335 : var_string_list:
336 6 : cfg_var_ref { $$ = $1; }
337 6 : | constant_string { $$ = $1; }
338 554847 : | '"' encapsed_list '"' { $$ = $2; }
339 17499 : | var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
340 7 : | var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
341 548 : | var_string_list '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); free(Z_STRVAL($3)); }
342 6 : ;
343 :
344 : expr:
345 553034 : var_string_list { $$ = $1; }
346 553034 : | expr '|' expr { zend_ini_do_op('|', &$$, &$1, &$3); }
347 28 : | expr '&' expr { zend_ini_do_op('&', &$$, &$1, &$3); }
348 64 : | '~' expr { zend_ini_do_op('~', &$$, &$2, NULL); }
349 64 : | '!' expr { zend_ini_do_op('!', &$$, &$2, NULL); }
350 0 : | '(' expr ')' { $$ = $2; }
351 0 : ;
352 :
353 : cfg_var_ref:
354 26 : TC_DOLLAR_CURLY TC_VARNAME '}' { zend_ini_get_var(&$$, &$2 TSRMLS_CC); free(Z_STRVAL($2)); }
355 26 : ;
356 :
357 : constant_string:
358 34792 : TC_CONSTANT { zend_ini_get_constant(&$$, &$1 TSRMLS_CC); }
359 34792 : | TC_RAW { $$ = $1; /*printf("TC_RAW: '%s'\n", Z_STRVAL($1));*/ }
360 79792 : | TC_NUMBER { $$ = $1; /*printf("TC_NUMBER: '%s'\n", Z_STRVAL($1));*/ }
361 355658 : | TC_STRING { $$ = $1; /*printf("TC_STRING: '%s'\n", Z_STRVAL($1));*/ }
362 84863 : | TC_WHITESPACE { $$ = $1; /*printf("TC_WHITESPACE: '%s'\n", Z_STRVAL($1));*/ }
363 : ;
364 :
365 : /*
366 : * Local variables:
367 : * tab-width: 4
368 : * c-basic-offset: 4
369 : * indent-tabs-mode: t
370 : * End:
371 : */
|