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 272368 2008-12-31 11:13:47Z sebastian $ */
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 114 : {
50 : int i_result;
51 : int i_op1, i_op2;
52 : char str_result[MAX_LENGTH_OF_LONG];
53 :
54 114 : i_op1 = atoi(Z_STRVAL_P(op1));
55 114 : free(Z_STRVAL_P(op1));
56 114 : if (op2) {
57 71 : i_op2 = atoi(Z_STRVAL_P(op2));
58 71 : free(Z_STRVAL_P(op2));
59 : } else {
60 43 : i_op2 = 0;
61 : }
62 :
63 114 : switch (type) {
64 : case '|':
65 28 : i_result = i_op1 | i_op2;
66 28 : break;
67 : case '&':
68 43 : i_result = i_op1 & i_op2;
69 43 : break;
70 : case '~':
71 43 : i_result = ~i_op1;
72 43 : break;
73 : case '!':
74 0 : i_result = !i_op1;
75 0 : break;
76 : default:
77 0 : i_result = 0;
78 : break;
79 : }
80 :
81 114 : Z_STRLEN_P(result) = zend_sprintf(str_result, "%d", i_result);
82 114 : Z_STRVAL_P(result) = (char *) malloc(Z_STRLEN_P(result)+1);
83 114 : memcpy(Z_STRVAL_P(result), str_result, Z_STRLEN_P(result));
84 114 : Z_STRVAL_P(result)[Z_STRLEN_P(result)] = 0;
85 114 : Z_TYPE_P(result) = IS_STRING;
86 114 : }
87 : /* }}} */
88 :
89 : /* {{{ zend_ini_init_string()
90 : */
91 : static void zend_ini_init_string(zval *result)
92 158313 : {
93 158313 : Z_STRVAL_P(result) = malloc(1);
94 158313 : Z_STRVAL_P(result)[0] = 0;
95 158313 : Z_STRLEN_P(result) = 0;
96 158313 : Z_TYPE_P(result) = IS_STRING;
97 158313 : }
98 : /* }}} */
99 :
100 : /* {{{ zend_ini_add_string()
101 : */
102 : static void zend_ini_add_string(zval *result, zval *op1, zval *op2)
103 18445 : {
104 18445 : int length = Z_STRLEN_P(op1) + Z_STRLEN_P(op2);
105 :
106 18445 : Z_STRVAL_P(result) = (char *) realloc(Z_STRVAL_P(op1), length+1);
107 18445 : memcpy(Z_STRVAL_P(result)+Z_STRLEN_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op2));
108 18445 : Z_STRVAL_P(result)[length] = 0;
109 18445 : Z_STRLEN_P(result) = length;
110 18445 : Z_TYPE_P(result) = IS_STRING;
111 18445 : }
112 : /* }}} */
113 :
114 : /* {{{ zend_ini_get_constant()
115 : */
116 : static void zend_ini_get_constant(zval *result, zval *name TSRMLS_DC)
117 35840 : {
118 : zval z_constant;
119 :
120 : /* If name contains ':' it is not a constant. Bug #26893. */
121 36007 : if (!memchr(Z_STRVAL_P(name), ':', Z_STRLEN_P(name))
122 : && zend_get_constant(Z_STRVAL_P(name), Z_STRLEN_P(name), &z_constant TSRMLS_CC)) {
123 : /* z_constant is emalloc()'d */
124 167 : convert_to_string(&z_constant);
125 167 : Z_STRVAL_P(result) = zend_strndup(Z_STRVAL(z_constant), Z_STRLEN(z_constant));
126 167 : Z_STRLEN_P(result) = Z_STRLEN(z_constant);
127 167 : Z_TYPE_P(result) = Z_TYPE(z_constant);
128 167 : zval_dtor(&z_constant);
129 167 : free(Z_STRVAL_P(name));
130 : } else {
131 35673 : *result = *name;
132 : }
133 35840 : }
134 : /* }}} */
135 :
136 : /* {{{ zend_ini_get_var()
137 : */
138 : static void zend_ini_get_var(zval *result, zval *name TSRMLS_DC)
139 26 : {
140 : zval curval;
141 : char *envvar;
142 :
143 : /* Fetch configuration option value */
144 26 : if (zend_get_configuration_directive(Z_STRVAL_P(name), Z_STRLEN_P(name)+1, &curval) == SUCCESS) {
145 0 : Z_STRVAL_P(result) = zend_strndup(Z_STRVAL(curval), Z_STRLEN(curval));
146 0 : Z_STRLEN_P(result) = Z_STRLEN(curval);
147 : /* ..or if not found, try ENV */
148 52 : } else if ((envvar = zend_getenv(Z_STRVAL_P(name), Z_STRLEN_P(name) TSRMLS_CC)) != NULL ||
149 : (envvar = getenv(Z_STRVAL_P(name))) != NULL) {
150 26 : Z_STRVAL_P(result) = strdup(envvar);
151 26 : Z_STRLEN_P(result) = strlen(envvar);
152 : } else {
153 0 : zend_ini_init_string(result);
154 : }
155 26 : }
156 : /* }}} */
157 :
158 : /* {{{ ini_error()
159 : */
160 : static void ini_error(char *msg)
161 4 : {
162 : char *error_buf;
163 : int error_buf_len;
164 : char *currently_parsed_filename;
165 : TSRMLS_FETCH();
166 :
167 4 : currently_parsed_filename = zend_ini_scanner_get_filename(TSRMLS_C);
168 4 : if (currently_parsed_filename) {
169 4 : error_buf_len = 128 + strlen(msg) + strlen(currently_parsed_filename); /* should be more than enough */
170 4 : error_buf = (char *) emalloc(error_buf_len);
171 :
172 4 : sprintf(error_buf, "%s in %s on line %d\n", msg, currently_parsed_filename, zend_ini_scanner_get_lineno(TSRMLS_C));
173 : } else {
174 0 : error_buf = estrdup("Invalid configuration directive\n");
175 : }
176 :
177 4 : if (CG(ini_parser_unbuffered_errors)) {
178 : #ifdef PHP_WIN32
179 : MessageBox(NULL, error_buf, "PHP Error", MB_OK|MB_TOPMOST|0x00200000L);
180 : #else
181 0 : fprintf(stderr, "PHP: %s", error_buf);
182 : #endif
183 : } else {
184 4 : zend_error(E_WARNING, "%s", error_buf);
185 : }
186 4 : efree(error_buf);
187 4 : }
188 : /* }}} */
189 :
190 : /* {{{ zend_parse_ini_file()
191 : */
192 : 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)
193 17609 : {
194 : int retval;
195 : zend_ini_parser_param ini_parser_param;
196 :
197 17609 : ini_parser_param.ini_parser_cb = ini_parser_cb;
198 17609 : ini_parser_param.arg = arg;
199 17609 : CG(ini_parser_param) = &ini_parser_param;
200 :
201 17609 : if (zend_ini_open_file_for_scanning(fh, scanner_mode TSRMLS_CC) == FAILURE) {
202 19 : return FAILURE;
203 : }
204 :
205 17590 : CG(ini_parser_unbuffered_errors) = unbuffered_errors;
206 17590 : retval = ini_parse(TSRMLS_C);
207 17590 : zend_file_handle_dtor(fh TSRMLS_CC);
208 :
209 17590 : shutdown_ini_scanner(TSRMLS_C);
210 :
211 17590 : if (retval == 0) {
212 17588 : return SUCCESS;
213 : } else {
214 2 : return FAILURE;
215 : }
216 : }
217 : /* }}} */
218 :
219 : /* {{{ zend_parse_ini_string()
220 : */
221 : 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)
222 17637 : {
223 : int retval;
224 : zend_ini_parser_param ini_parser_param;
225 :
226 17637 : ini_parser_param.ini_parser_cb = ini_parser_cb;
227 17637 : ini_parser_param.arg = arg;
228 17637 : CG(ini_parser_param) = &ini_parser_param;
229 :
230 17637 : if (zend_ini_prepare_string_for_scanning(str, scanner_mode TSRMLS_CC) == FAILURE) {
231 0 : return FAILURE;
232 : }
233 :
234 17637 : CG(ini_parser_unbuffered_errors) = unbuffered_errors;
235 17637 : retval = ini_parse(TSRMLS_C);
236 :
237 17637 : shutdown_ini_scanner(TSRMLS_C);
238 :
239 17637 : if (retval == 0) {
240 17635 : return SUCCESS;
241 : } else {
242 2 : return FAILURE;
243 : }
244 : }
245 : /* }}} */
246 :
247 : %}
248 :
249 : %expect 0
250 : %pure_parser
251 :
252 : %token TC_SECTION
253 : %token TC_RAW
254 : %token TC_CONSTANT
255 : %token TC_NUMBER
256 : %token TC_STRING
257 : %token TC_WHITESPACE
258 : %token TC_LABEL
259 : %token TC_OFFSET
260 : %token TC_DOLLAR_CURLY
261 : %token TC_VARNAME
262 : %token TC_QUOTED_STRING
263 : %token BOOL_TRUE
264 : %token BOOL_FALSE
265 : %token END_OF_LINE
266 : %token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?' '@' '{' '}'
267 : %left '|' '&'
268 : %right '~' '!'
269 :
270 : %%
271 :
272 : statement_list:
273 : statement_list statement
274 : | /* empty */
275 : ;
276 :
277 : statement:
278 : TC_SECTION section_string_or_value ']' {
279 : #if DEBUG_CFG_PARSER
280 : printf("SECTION: [%s]\n", Z_STRVAL($2));
281 : #endif
282 19304 : ZEND_INI_PARSER_CB(&$2, NULL, NULL, ZEND_INI_PARSER_SECTION, ZEND_INI_PARSER_ARG TSRMLS_CC);
283 19304 : free(Z_STRVAL($2));
284 : }
285 19304 : | TC_LABEL '=' string_or_value {
286 : #if DEBUG_CFG_PARSER
287 : printf("NORMAL: '%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3));
288 : #endif
289 746454 : ZEND_INI_PARSER_CB(&$1, &$3, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
290 746454 : free(Z_STRVAL($1));
291 746454 : free(Z_STRVAL($3));
292 : }
293 746454 : | TC_OFFSET option_offset ']' '=' string_or_value {
294 : #if DEBUG_CFG_PARSER
295 : printf("OFFSET: '%s'[%s] = '%s'\n", Z_STRVAL($1), Z_STRVAL($2), Z_STRVAL($5));
296 : #endif
297 21 : ZEND_INI_PARSER_CB(&$1, &$5, &$2, ZEND_INI_PARSER_POP_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
298 21 : free(Z_STRVAL($1));
299 21 : free(Z_STRVAL($2));
300 21 : free(Z_STRVAL($5));
301 : }
302 21 : | TC_LABEL { ZEND_INI_PARSER_CB(&$1, NULL, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); free(Z_STRVAL($1)); }
303 4 : | END_OF_LINE
304 : ;
305 :
306 : section_string_or_value:
307 19304 : var_string_list { $$ = $1; }
308 19304 : | /* empty */ { zend_ini_init_string(&$$); }
309 0 : ;
310 :
311 : string_or_value:
312 571173 : expr { $$ = $1; }
313 571173 : | BOOL_TRUE { $$ = $1; }
314 106 : | BOOL_FALSE { $$ = $1; }
315 35029 : | END_OF_LINE { zend_ini_init_string(&$$); }
316 140167 : ;
317 :
318 : option_offset:
319 14 : var_string_list { $$ = $1; }
320 14 : | /* empty */ { zend_ini_init_string(&$$); }
321 7 : ;
322 :
323 : encapsed_list:
324 13 : encapsed_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
325 13 : | encapsed_list TC_QUOTED_STRING { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
326 18134 : | /* empty */ { zend_ini_init_string(&$$); }
327 18139 : ;
328 :
329 : var_string_list:
330 6 : cfg_var_ref { $$ = $1; }
331 6 : | constant_string { $$ = $1; }
332 572423 : | '"' encapsed_list '"' { $$ = $2; }
333 18133 : | var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
334 7 : | var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
335 285 : | var_string_list '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); free(Z_STRVAL($3)); }
336 6 : ;
337 :
338 : expr:
339 571244 : var_string_list { $$ = $1; }
340 571244 : | expr '|' expr { zend_ini_do_op('|', &$$, &$1, &$3); }
341 28 : | expr '&' expr { zend_ini_do_op('&', &$$, &$1, &$3); }
342 43 : | '~' expr { zend_ini_do_op('~', &$$, &$2, NULL); }
343 43 : | '!' expr { zend_ini_do_op('!', &$$, &$2, NULL); }
344 0 : | '(' expr ')' { $$ = $2; }
345 0 : ;
346 :
347 : cfg_var_ref:
348 26 : TC_DOLLAR_CURLY TC_VARNAME '}' { zend_ini_get_var(&$$, &$2 TSRMLS_CC); free(Z_STRVAL($2)); }
349 26 : ;
350 :
351 : constant_string:
352 35840 : TC_CONSTANT { zend_ini_get_constant(&$$, &$1 TSRMLS_CC); }
353 35840 : | TC_RAW { $$ = $1; /*printf("TC_RAW: '%s'\n", Z_STRVAL($1));*/ }
354 79792 : | TC_NUMBER { $$ = $1; /*printf("TC_NUMBER: '%s'\n", Z_STRVAL($1));*/ }
355 368896 : | TC_STRING { $$ = $1; /*printf("TC_STRING: '%s'\n", Z_STRVAL($1));*/ }
356 88021 : | TC_WHITESPACE { $$ = $1; /*printf("TC_WHITESPACE: '%s'\n", Z_STRVAL($1));*/ }
357 : ;
358 :
359 : /*
360 : * Local variables:
361 : * tab-width: 4
362 : * c-basic-offset: 4
363 : * indent-tabs-mode: t
364 : * End:
365 : */
|