PageRenderTime 27ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/Zend/zend_ini_parser.y

https://github.com/php/php-src
Happy | 413 lines | 358 code | 55 blank | 0 comment | 0 complexity | a069b730b15946cfb688c8c4479571cc MD5 | raw file
Possible License(s): BSD-2-Clause, BSD-3-Clause, MPL-2.0-no-copyleft-exception, LGPL-2.1
  1. %require "3.0"
  2. %{
  3. /*
  4. +----------------------------------------------------------------------+
  5. | Zend Engine |
  6. +----------------------------------------------------------------------+
  7. | Copyright (c) Zend Technologies Ltd. (http://www.zend.com) |
  8. +----------------------------------------------------------------------+
  9. | This source file is subject to version 2.00 of the Zend license, |
  10. | that is bundled with this package in the file LICENSE, and is |
  11. | available through the world-wide-web at the following url: |
  12. | http://www.zend.com/license/2_00.txt. |
  13. | If you did not receive a copy of the Zend license and are unable to |
  14. | obtain it through the world-wide-web, please send a note to |
  15. | license@zend.com so we can mail you a copy immediately. |
  16. +----------------------------------------------------------------------+
  17. | Authors: Zeev Suraski <zeev@php.net> |
  18. | Jani Taskinen <jani@php.net> |
  19. +----------------------------------------------------------------------+
  20. */
  21. #define DEBUG_CFG_PARSER 0
  22. #include "zend.h"
  23. #include "zend_API.h"
  24. #include "zend_ini.h"
  25. #include "zend_constants.h"
  26. #include "zend_ini_scanner.h"
  27. #include "zend_extensions.h"
  28. #ifdef ZEND_WIN32
  29. #include "win32/syslog.h"
  30. #endif
  31. int ini_parse(void);
  32. #define ZEND_INI_PARSER_CB (CG(ini_parser_param))->ini_parser_cb
  33. #define ZEND_INI_PARSER_ARG (CG(ini_parser_param))->arg
  34. #ifdef _MSC_VER
  35. #define YYMALLOC malloc
  36. #define YYFREE free
  37. #endif
  38. #define ZEND_SYSTEM_INI CG(ini_parser_unbuffered_errors)
  39. static int get_int_val(zval *op) {
  40. switch (Z_TYPE_P(op)) {
  41. case IS_LONG:
  42. return Z_LVAL_P(op);
  43. case IS_DOUBLE:
  44. return (int)Z_DVAL_P(op);
  45. case IS_STRING:
  46. {
  47. int val = atoi(Z_STRVAL_P(op));
  48. zend_string_free(Z_STR_P(op));
  49. return val;
  50. }
  51. EMPTY_SWITCH_DEFAULT_CASE()
  52. }
  53. }
  54. /* {{{ zend_ini_do_op() */
  55. static void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
  56. {
  57. int i_result;
  58. int i_op1, i_op2;
  59. int str_len;
  60. char str_result[MAX_LENGTH_OF_LONG+1];
  61. i_op1 = get_int_val(op1);
  62. i_op2 = op2 ? get_int_val(op2) : 0;
  63. switch (type) {
  64. case '|':
  65. i_result = i_op1 | i_op2;
  66. break;
  67. case '&':
  68. i_result = i_op1 & i_op2;
  69. break;
  70. case '^':
  71. i_result = i_op1 ^ i_op2;
  72. break;
  73. case '~':
  74. i_result = ~i_op1;
  75. break;
  76. case '!':
  77. i_result = !i_op1;
  78. break;
  79. default:
  80. i_result = 0;
  81. break;
  82. }
  83. str_len = sprintf(str_result, "%d", i_result);
  84. ZVAL_NEW_STR(result, zend_string_init(str_result, str_len, ZEND_SYSTEM_INI));
  85. }
  86. /* }}} */
  87. /* {{{ zend_ini_init_string() */
  88. static void zend_ini_init_string(zval *result)
  89. {
  90. if (ZEND_SYSTEM_INI) {
  91. ZVAL_EMPTY_PSTRING(result);
  92. } else {
  93. ZVAL_EMPTY_STRING(result);
  94. }
  95. }
  96. /* }}} */
  97. /* {{{ zend_ini_add_string() */
  98. static void zend_ini_add_string(zval *result, zval *op1, zval *op2)
  99. {
  100. int length, op1_len;
  101. if (Z_TYPE_P(op1) != IS_STRING) {
  102. /* ZEND_ASSERT(!Z_REFCOUNTED_P(op1)); */
  103. if (ZEND_SYSTEM_INI) {
  104. zend_string *tmp_str;
  105. zend_string *str = zval_get_tmp_string(op1, &tmp_str);
  106. ZVAL_PSTRINGL(op1, ZSTR_VAL(str), ZSTR_LEN(str));
  107. zend_tmp_string_release(tmp_str);
  108. } else {
  109. ZVAL_STR(op1, zval_get_string_func(op1));
  110. }
  111. }
  112. op1_len = (int)Z_STRLEN_P(op1);
  113. if (Z_TYPE_P(op2) != IS_STRING) {
  114. convert_to_string(op2);
  115. }
  116. length = op1_len + (int)Z_STRLEN_P(op2);
  117. ZVAL_NEW_STR(result, zend_string_extend(Z_STR_P(op1), length, ZEND_SYSTEM_INI));
  118. memcpy(Z_STRVAL_P(result) + op1_len, Z_STRVAL_P(op2), Z_STRLEN_P(op2) + 1);
  119. }
  120. /* }}} */
  121. /* {{{ zend_ini_get_constant() */
  122. static void zend_ini_get_constant(zval *result, zval *name)
  123. {
  124. zval *c, tmp;
  125. /* If name contains ':' it is not a constant. Bug #26893. */
  126. if (!memchr(Z_STRVAL_P(name), ':', Z_STRLEN_P(name))
  127. && (c = zend_get_constant(Z_STR_P(name))) != 0) {
  128. if (Z_TYPE_P(c) != IS_STRING) {
  129. ZVAL_COPY_OR_DUP(&tmp, c);
  130. if (Z_OPT_CONSTANT(tmp)) {
  131. zval_update_constant_ex(&tmp, NULL);
  132. }
  133. convert_to_string(&tmp);
  134. c = &tmp;
  135. }
  136. ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(c), Z_STRLEN_P(c), ZEND_SYSTEM_INI));
  137. if (c == &tmp) {
  138. zend_string_release(Z_STR(tmp));
  139. }
  140. zend_string_free(Z_STR_P(name));
  141. } else {
  142. *result = *name;
  143. }
  144. }
  145. /* }}} */
  146. /* {{{ zend_ini_get_var() */
  147. static void zend_ini_get_var(zval *result, zval *name)
  148. {
  149. zval *curval;
  150. char *envvar;
  151. /* Fetch configuration option value */
  152. if ((curval = zend_get_configuration_directive(Z_STR_P(name))) != NULL) {
  153. ZVAL_NEW_STR(result, zend_string_init(Z_STRVAL_P(curval), Z_STRLEN_P(curval), ZEND_SYSTEM_INI));
  154. /* ..or if not found, try ENV */
  155. } else if ((envvar = zend_getenv(Z_STRVAL_P(name), Z_STRLEN_P(name))) != NULL ||
  156. (envvar = getenv(Z_STRVAL_P(name))) != NULL) {
  157. ZVAL_NEW_STR(result, zend_string_init(envvar, strlen(envvar), ZEND_SYSTEM_INI));
  158. } else {
  159. zend_ini_init_string(result);
  160. }
  161. }
  162. /* }}} */
  163. /* {{{ ini_error() */
  164. static ZEND_COLD void ini_error(const char *msg)
  165. {
  166. char *error_buf;
  167. int error_buf_len;
  168. char *currently_parsed_filename;
  169. currently_parsed_filename = zend_ini_scanner_get_filename();
  170. if (currently_parsed_filename) {
  171. error_buf_len = 128 + (int)strlen(msg) + (int)strlen(currently_parsed_filename); /* should be more than enough */
  172. error_buf = (char *) emalloc(error_buf_len);
  173. sprintf(error_buf, "%s in %s on line %d\n", msg, currently_parsed_filename, zend_ini_scanner_get_lineno());
  174. } else {
  175. error_buf = estrdup("Invalid configuration directive\n");
  176. }
  177. if (CG(ini_parser_unbuffered_errors)) {
  178. #ifdef ZEND_WIN32
  179. syslog(LOG_ALERT, "PHP: %s (%s)", error_buf, GetCommandLine());
  180. #endif
  181. fprintf(stderr, "PHP: %s", error_buf);
  182. } else {
  183. zend_error(E_WARNING, "%s", error_buf);
  184. }
  185. efree(error_buf);
  186. }
  187. /* }}} */
  188. /* {{{ zend_parse_ini_file() */
  189. ZEND_API zend_result zend_parse_ini_file(zend_file_handle *fh, bool unbuffered_errors, int scanner_mode, zend_ini_parser_cb_t ini_parser_cb, void *arg)
  190. {
  191. int retval;
  192. zend_ini_parser_param ini_parser_param;
  193. ini_parser_param.ini_parser_cb = ini_parser_cb;
  194. ini_parser_param.arg = arg;
  195. CG(ini_parser_param) = &ini_parser_param;
  196. if (zend_ini_open_file_for_scanning(fh, scanner_mode) == FAILURE) {
  197. return FAILURE;
  198. }
  199. CG(ini_parser_unbuffered_errors) = unbuffered_errors;
  200. retval = ini_parse();
  201. shutdown_ini_scanner();
  202. if (retval == 0) {
  203. return SUCCESS;
  204. } else {
  205. return FAILURE;
  206. }
  207. }
  208. /* }}} */
  209. /* {{{ zend_parse_ini_string() */
  210. ZEND_API zend_result zend_parse_ini_string(char *str, bool unbuffered_errors, int scanner_mode, zend_ini_parser_cb_t ini_parser_cb, void *arg)
  211. {
  212. int retval;
  213. zend_ini_parser_param ini_parser_param;
  214. ini_parser_param.ini_parser_cb = ini_parser_cb;
  215. ini_parser_param.arg = arg;
  216. CG(ini_parser_param) = &ini_parser_param;
  217. if (zend_ini_prepare_string_for_scanning(str, scanner_mode) == FAILURE) {
  218. return FAILURE;
  219. }
  220. CG(ini_parser_unbuffered_errors) = unbuffered_errors;
  221. retval = ini_parse();
  222. shutdown_ini_scanner();
  223. if (retval == 0) {
  224. return SUCCESS;
  225. } else {
  226. return FAILURE;
  227. }
  228. }
  229. /* }}} */
  230. /* {{{ zval_ini_dtor() */
  231. static void zval_ini_dtor(zval *zv)
  232. {
  233. if (Z_TYPE_P(zv) == IS_STRING) {
  234. zend_string_release(Z_STR_P(zv));
  235. }
  236. }
  237. /* }}} */
  238. %}
  239. %expect 0
  240. %define api.prefix {ini_}
  241. %define api.pure full
  242. %define api.value.type {zval}
  243. %define parse.error verbose
  244. %token END 0 "end of file"
  245. %token TC_SECTION
  246. %token TC_RAW
  247. %token TC_CONSTANT
  248. %token TC_NUMBER
  249. %token TC_STRING
  250. %token TC_WHITESPACE
  251. %token TC_LABEL
  252. %token TC_OFFSET
  253. %token TC_DOLLAR_CURLY
  254. %token TC_VARNAME
  255. %token TC_QUOTED_STRING
  256. %token BOOL_TRUE
  257. %token BOOL_FALSE
  258. %token NULL_NULL
  259. %token END_OF_LINE
  260. %token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?' '@' '{' '}'
  261. %left '|' '&' '^'
  262. %precedence '~' '!'
  263. %destructor { zval_ini_dtor(&$$); } TC_RAW TC_CONSTANT TC_NUMBER TC_STRING TC_WHITESPACE TC_LABEL TC_OFFSET TC_VARNAME BOOL_TRUE BOOL_FALSE NULL_NULL cfg_var_ref constant_literal constant_string encapsed_list expr option_offset section_string_or_value string_or_value var_string_list var_string_list_section
  264. %%
  265. statement_list:
  266. statement_list statement
  267. | %empty
  268. ;
  269. statement:
  270. TC_SECTION section_string_or_value ']' {
  271. #if DEBUG_CFG_PARSER
  272. printf("SECTION: [%s]\n", Z_STRVAL($2));
  273. #endif
  274. ZEND_INI_PARSER_CB(&$2, NULL, NULL, ZEND_INI_PARSER_SECTION, ZEND_INI_PARSER_ARG);
  275. zend_string_release(Z_STR($2));
  276. }
  277. | TC_LABEL '=' string_or_value {
  278. #if DEBUG_CFG_PARSER
  279. printf("NORMAL: '%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3));
  280. #endif
  281. ZEND_INI_PARSER_CB(&$1, &$3, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG);
  282. zend_string_release(Z_STR($1));
  283. zval_ini_dtor(&$3);
  284. }
  285. | TC_OFFSET option_offset ']' '=' string_or_value {
  286. #if DEBUG_CFG_PARSER
  287. printf("OFFSET: '%s'[%s] = '%s'\n", Z_STRVAL($1), Z_STRVAL($2), Z_STRVAL($5));
  288. #endif
  289. ZEND_INI_PARSER_CB(&$1, &$5, &$2, ZEND_INI_PARSER_POP_ENTRY, ZEND_INI_PARSER_ARG);
  290. zend_string_release(Z_STR($1));
  291. zval_ini_dtor(&$2);
  292. zval_ini_dtor(&$5);
  293. }
  294. | TC_LABEL { ZEND_INI_PARSER_CB(&$1, NULL, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG); zend_string_release(Z_STR($1)); }
  295. | END_OF_LINE
  296. ;
  297. section_string_or_value:
  298. var_string_list_section { $$ = $1; }
  299. | %empty { zend_ini_init_string(&$$); }
  300. ;
  301. string_or_value:
  302. expr { $$ = $1; }
  303. | BOOL_TRUE { $$ = $1; }
  304. | BOOL_FALSE { $$ = $1; }
  305. | NULL_NULL { $$ = $1; }
  306. | END_OF_LINE { zend_ini_init_string(&$$); }
  307. ;
  308. option_offset:
  309. var_string_list { $$ = $1; }
  310. | %empty { zend_ini_init_string(&$$); }
  311. ;
  312. encapsed_list:
  313. encapsed_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
  314. | encapsed_list TC_QUOTED_STRING { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
  315. | %empty { zend_ini_init_string(&$$); }
  316. ;
  317. var_string_list_section:
  318. cfg_var_ref { $$ = $1; }
  319. | constant_literal { $$ = $1; }
  320. | '"' encapsed_list '"' { $$ = $2; }
  321. | var_string_list_section cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
  322. | var_string_list_section constant_literal { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
  323. | var_string_list_section '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); zend_string_free(Z_STR($3)); }
  324. ;
  325. var_string_list:
  326. cfg_var_ref { $$ = $1; }
  327. | constant_string { $$ = $1; }
  328. | '"' encapsed_list '"' { $$ = $2; }
  329. | var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
  330. | var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); zend_string_free(Z_STR($2)); }
  331. | var_string_list '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); zend_string_free(Z_STR($3)); }
  332. ;
  333. expr:
  334. var_string_list { $$ = $1; }
  335. | expr '|' expr { zend_ini_do_op('|', &$$, &$1, &$3); }
  336. | expr '&' expr { zend_ini_do_op('&', &$$, &$1, &$3); }
  337. | expr '^' expr { zend_ini_do_op('^', &$$, &$1, &$3); }
  338. | '~' expr { zend_ini_do_op('~', &$$, &$2, NULL); }
  339. | '!' expr { zend_ini_do_op('!', &$$, &$2, NULL); }
  340. | '(' expr ')' { $$ = $2; }
  341. ;
  342. cfg_var_ref:
  343. TC_DOLLAR_CURLY TC_VARNAME '}' { zend_ini_get_var(&$$, &$2); zend_string_free(Z_STR($2)); }
  344. ;
  345. constant_literal:
  346. TC_CONSTANT { $$ = $1; }
  347. | TC_RAW { $$ = $1; /*printf("TC_RAW: '%s'\n", Z_STRVAL($1));*/ }
  348. | TC_NUMBER { $$ = $1; /*printf("TC_NUMBER: '%s'\n", Z_STRVAL($1));*/ }
  349. | TC_STRING { $$ = $1; /*printf("TC_STRING: '%s'\n", Z_STRVAL($1));*/ }
  350. | TC_WHITESPACE { $$ = $1; /*printf("TC_WHITESPACE: '%s'\n", Z_STRVAL($1));*/ }
  351. ;
  352. constant_string:
  353. TC_CONSTANT { zend_ini_get_constant(&$$, &$1); }
  354. | TC_RAW { $$ = $1; /*printf("TC_RAW: '%s'\n", Z_STRVAL($1));*/ }
  355. | TC_NUMBER { $$ = $1; /*printf("TC_NUMBER: '%s'\n", Z_STRVAL($1));*/ }
  356. | TC_STRING { $$ = $1; /*printf("TC_STRING: '%s'\n", Z_STRVAL($1));*/ }
  357. | TC_WHITESPACE { $$ = $1; /*printf("TC_WHITESPACE: '%s'\n", Z_STRVAL($1));*/ }
  358. ;