Hello PHPlers,
attached is a patch against 5.3 that brings three feature
additions to INI parsing.
1) Ternary support for values
setting = ${value?1:2}
If ${value} evaluates to true then setting becomes 1 otherwise 2.
This cannot be nested and only works for values, not for setting names.
2) if-elif-else-endif support
[IF ${value} == 1]
setting = 1
[ELIF ${value} == 2]
setting = 2
[ELSE]
setting = 3
[ENDIF]
This can be nested. Alternatively we could use apache style syntax that
looks more like XML. The reason I used square brackets is that this is the
smallest change to normal INI files.
3) Add more values to INI parsing, namely:
${php.version} = 50300
${php.debug} = 0
${php.zts} = 0
${php.sapi} = CLI
Any comments?
Best regards,
Marcus
Index: main/php_ini.c
===================================================================
RCS file: /repository/php-src/main/php_ini.c,v
retrieving revision 1.136.2.4.2.15.2.7
diff -u -p -d -r1.136.2.4.2.15.2.7 php_ini.c
--- main/php_ini.c 3 Feb 2008 14:35:59 -0000 1.136.2.4.2.15.2.7
+++ main/php_ini.c 9 Feb 2008 14:31:53 -0000
@@ -20,6 +20,7 @@
#include "php.h"
#include "ext/standard/info.h"
+#include "ext/standard/basic_functions.h"
#include "zend_ini.h"
#include "zend_ini_scanner.h"
#include "php_ini.h"
@@ -328,6 +329,43 @@ static void php_load_zend_extension_cb(v
}
/* }}} */
+static void php_ini_dump_config(TSRMLS_D) /* {{{ */
+{
+#if HELLY_0
+ zval tmp;
+ array_init(&tmp);
+ zend_hash_apply_with_arguments(&configuration_hash, (apply_func_args_t)
php_add_config_entry_cb, 1, &tmp TSRMLS_CC);
+ zend_print_hash(Z_ARRVAL(tmp), 0, 0 TSRMLS_CC);
+ zval_dtor(&tmp);
+#endif
+} /* }}} */
+
+PHPAPI void php_ini_add_config_stringl(const char* name, int name_size, const
char *value, int value_len TSRMLS_DC) /* {{{*/
+{
+ zval tmp;
+ ZVAL_STRINGL(&tmp, zend_strndup(value, value_len), value_len, 0);
+ Z_SET_REFCOUNT(tmp, 0);
+ Z_UNSET_ISREF(tmp);
+ zend_hash_update(&configuration_hash, name, name_size, (void *) &tmp,
sizeof(zval), NULL);
+} /* }}} */
+
+PHPAPI void php_ini_add_config_string(const char* name, int name_size, const
char *value TSRMLS_DC) /* {{{*/
+{
+ php_ini_add_config_stringl(name, name_size, value, strlen(value)
TSRMLS_CC);
+} /* }}} */
+
+PHPAPI void php_ini_add_config_long(const char* name, int name_size, long
value TSRMLS_DC) /* {{{*/
+{
+ char str_val[32];
+ int value_len = slprintf(str_val, sizeof(str_val), "%ld", value);
+ php_ini_add_config_stringl(name, name_size, str_val, value_len
TSRMLS_CC);
+} /* }}} */
+
+PHPAPI void php_ini_add_config_bool(const char* name, int name_size, int value
TSRMLS_DC) /* {{{*/
+{
+ php_ini_add_config_stringl(name, name_size, value ? "1" : "0", 1
TSRMLS_CC);
+} /* }}} */
+
/* {{{ php_init_config
*/
int php_init_config(TSRMLS_D)
@@ -347,6 +385,20 @@ int php_init_config(TSRMLS_D)
sapi_module.ini_defaults(&configuration_hash);
}
+ php_ini_add_config_long("php.version", sizeof("php.version"),
PHP_VERSION_ID TSRMLS_CC);
+ php_ini_add_config_string("php.sapi", sizeof("php.sapi"),
sapi_module.name TSRMLS_CC);
+#if ZTS
+ php_ini_add_config_bool("php.zts", sizeof("php.zts"), 1 TSRMLS_CC);
+#else
+ php_ini_add_config_bool("php.zts", sizeof("php.zts"), 0 TSRMLS_CC);
+#endif
+#if ZEND_DEBUG
+ php_ini_add_config_bool("php.debug", sizeof("php.debug"), 1 TSRMLS_CC);
+#else
+ php_ini_add_config_bool("php.debug", sizeof("php.debug"), 0 TSRMLS_CC);
+#endif
+ php_ini_dump_config(TSRMLS_C);
+
zend_llist_init(&extension_lists.engine, sizeof(char *),
(llist_dtor_func_t) free_estring, 1);
zend_llist_init(&extension_lists.functions, sizeof(char *),
(llist_dtor_func_t) free_estring, 1);
@@ -558,24 +610,19 @@ int php_init_config(TSRMLS_D)
PG(open_basedir) = open_basedir;
if (fh.handle.fp) {
+ int filename_len;
+ char *ftmp;
fh.type = ZEND_HANDLE_FP;
RESET_ACTIVE_INI_HASH();
zend_parse_ini_file(&fh, 1, ZEND_INI_SCANNER_NORMAL,
(zend_ini_parser_cb_t) php_ini_parser_cb, &configuration_hash TSRMLS_CC);
- {
- zval tmp;
-
- Z_STRLEN(tmp) = strlen(fh.filename);
- Z_STRVAL(tmp) = zend_strndup(fh.filename,
Z_STRLEN(tmp));
- Z_TYPE(tmp) = IS_STRING;
- Z_SET_REFCOUNT(tmp, 0);
-
- zend_hash_update(&configuration_hash, "cfg_file_path",
sizeof("cfg_file_path"), (void *) &tmp, sizeof(zval), NULL);
- if (php_ini_opened_path) {
- efree(php_ini_opened_path);
- }
- php_ini_opened_path = zend_strndup(Z_STRVAL(tmp),
Z_STRLEN(tmp));
+ filename_len = strlen(fh.filename);
+ php_ini_add_config_stringl("cfg_file_path",
sizeof("cfg_file_path"), fh.filename, filename_len TSRMLS_CC);
+ ftmp = php_ini_opened_path;
+ php_ini_opened_path = zend_strndup(fh.filename, filename_len);
+ if (ftmp) {
+ efree(ftmp);
}
}
Index: Zend/zend.c
===================================================================
RCS file: /repository/ZendEngine2/zend.c,v
retrieving revision 1.308.2.12.2.35.2.7
diff -u -p -d -r1.308.2.12.2.35.2.7 zend.c
--- Zend/zend.c 28 Jan 2008 20:34:02 -0000 1.308.2.12.2.35.2.7
+++ Zend/zend.c 9 Feb 2008 14:31:54 -0000
@@ -116,7 +116,7 @@ static uint zend_version_info_length;
#define ZEND_CORE_VERSION_INFO "Zend Engine v" ZEND_VERSION ", Copyright (c)
1998-2008 Zend Technologies\n"
#define PRINT_ZVAL_INDENT 4
-static void print_hash(HashTable *ht, int indent, zend_bool is_object
TSRMLS_DC) /* {{{ */
+ZEND_API void zend_print_hash(HashTable *ht, int indent, zend_bool is_object
TSRMLS_DC) /* {{{ */
{
zval **tmp;
char *string_key;
@@ -378,7 +378,7 @@ ZEND_API void zend_print_zval_r_ex(zend_
Z_ARRVAL_P(expr)->nApplyCount--;
return;
}
- print_hash(Z_ARRVAL_P(expr), indent, 0 TSRMLS_CC);
+ zend_print_hash(Z_ARRVAL_P(expr), indent, 0 TSRMLS_CC);
Z_ARRVAL_P(expr)->nApplyCount--;
break;
case IS_OBJECT:
@@ -407,7 +407,7 @@ ZEND_API void zend_print_zval_r_ex(zend_
properties->nApplyCount--;
return;
}
- print_hash(properties, indent, 1 TSRMLS_CC);
+ zend_print_hash(properties, indent, 1
TSRMLS_CC);
properties->nApplyCount--;
if (is_temp) {
zend_hash_destroy(properties);
Index: Zend/zend.h
===================================================================
RCS file: /repository/ZendEngine2/zend.h,v
retrieving revision 1.293.2.11.2.9.2.16
diff -u -p -d -r1.293.2.11.2.9.2.16 zend.h
--- Zend/zend.h 22 Jan 2008 09:27:46 -0000 1.293.2.11.2.9.2.16
+++ Zend/zend.h 9 Feb 2008 14:31:54 -0000
@@ -537,6 +537,7 @@ END_EXTERN_C()
BEGIN_EXTERN_C()
ZEND_API char *get_zend_version(void);
+ZEND_API void zend_print_hash(HashTable *ht, int indent, zend_bool is_object
TSRMLS_DC);
ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int
*use_copy);
ZEND_API int zend_print_zval(zval *expr, int indent);
ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int
indent);
Index: Zend/zend_globals.h
===================================================================
RCS file: /repository/ZendEngine2/zend_globals.h,v
retrieving revision 1.141.2.3.2.7.2.7
diff -u -p -d -r1.141.2.3.2.7.2.7 zend_globals.h
--- Zend/zend_globals.h 24 Jan 2008 09:41:37 -0000 1.141.2.3.2.7.2.7
+++ Zend/zend_globals.h 9 Feb 2008 14:31:54 -0000
@@ -52,6 +52,8 @@ END_EXTERN_C()
#endif
#define SYMTABLE_CACHE_SIZE 32
+#define ZEND_DEBUG_CFG_PARSER 1
+
#include "zend_compile.h"
@@ -272,6 +274,7 @@ struct _zend_scanner_globals {
/* For ini scanner. Modes are: ZEND_INI_SCANNER_NORMAL,
ZEND_INI_SCANNER_RAW */
int scanner_mode;
+ int if_level;
#ifdef ZEND_MULTIBYTE
/* original (unfiltered) script */
@@ -290,6 +293,12 @@ struct _zend_scanner_globals {
#endif /* ZEND_MULTIBYTE */
};
+typedef enum {
+ ZEND_INI_COND_READ,
+ ZEND_INI_COND_IGNORE,
+ ZEND_INI_COND_DONE,
+} ZEND_INI_CONDITIONAL;
+
#endif /* ZEND_GLOBALS_H */
/*
Index: Zend/zend_ini_parser.y
===================================================================
RCS file: /repository/ZendEngine2/zend_ini_parser.y,v
retrieving revision 1.41.2.2.2.2.2.4
diff -u -p -d -r1.41.2.2.2.2.2.4 zend_ini_parser.y
--- Zend/zend_ini_parser.y 4 Feb 2008 20:45:20 -0000 1.41.2.2.2.2.2.4
+++ Zend/zend_ini_parser.y 9 Feb 2008 14:31:54 -0000
@@ -15,13 +15,12 @@
+----------------------------------------------------------------------+
| Authors: Zeev Suraski <[EMAIL PROTECTED]> |
| Jani Taskinen <[EMAIL PROTECTED]>
|
+ | Marcus Boerger <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
/* $Id: zend_ini_parser.y,v 1.41.2.2.2.2.2.4 2008/02/04 20:45:20 jani Exp $ */
-#define DEBUG_CFG_PARSER 0
-
#include "zend.h"
#include "zend_API.h"
#include "zend_ini.h"
@@ -29,6 +28,9 @@
#include "zend_ini_scanner.h"
#include "zend_extensions.h"
+extern void zend_ini_set_ignore(ZEND_INI_CONDITIONAL ignore TSRMLS_DC);
+extern void zend_ini_error(int severity TSRMLS_DC, char *error);
+
#define YYERROR_VERBOSE
#define YYSTYPE zval
@@ -86,6 +88,106 @@ static void zend_ini_do_op(char type, zv
}
/* }}} */
+static void zend_ini_compare(int type, zval *result, zval *op1, zval *op2) /*
{{{ */
+{
+ int i_op1, i_op2, ret;
+ char *str2 = "";
+
+ if (type == T_IS_NOT_IDENTICAL || type == T_IS_NOT_IDENTICAL) {
+ if (op2) {
+ ret = !strcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2));
+ str2 = Z_STRVAL_P(op2);
+ } else {
+ ret = Z_STRLEN_P(op1) > 0;
+ }
+ if (type == T_IS_NOT_IDENTICAL) {
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "INI compare('%s' !== '%s')\n",
Z_STRVAL_P(op1), str2);
+#endif
+ ret = ret ? 0 : 1;
+ } else {
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "INI compare('%s' === '%s')\n",
Z_STRVAL_P(op1), str2);
+#endif
+ ret = ret ? 1 : 0;
+ }
+ } else {
+ i_op1 = atoi(Z_STRVAL_P(op1));
+ if (op2) {
+ i_op2 = atoi(Z_STRVAL_P(op2));
+ } else {
+ i_op2 = 0;
+ }
+
+ switch (type) {
+ case T_IS_EQ:
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "INI compare(%d == %d)\n",
i_op1, i_op2);
+#endif
+ ret = i_op1 == i_op2;
+ break;
+ case T_IS_NE:
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "INI compare(%d != %d)\n",
i_op1, i_op2);
+#endif
+ ret = i_op1 != i_op2;
+ break;
+ case T_IS_GE:
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "INI compare(%d >= %d)\n",
i_op1, i_op2);
+#endif
+ ret = i_op1 >= i_op2;
+ break;
+ case '>':
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "INI compare(%d > %d)\n",
i_op1, i_op2);
+#endif
+ ret = i_op1 > i_op2;
+ break;
+ case T_IS_LE:
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "INI compare(%d <= %d)\n",
i_op1, i_op2);
+#endif
+ ret = i_op1 <= i_op2;
+ break;
+ case '<':
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "INI compare(%d < %d)\n",
i_op1, i_op2);
+#endif
+ ret = i_op1 < i_op2;
+ break;
+ case T_L_AND:
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "INI compare(%d && %d)\n",
i_op1, i_op2);
+#endif
+ ret = i_op1 && i_op2;
+ break;
+ case T_L_OR:
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "INI compare(%d || %d)\n",
i_op1, i_op2);
+#endif
+ ret = i_op1 && i_op2;
+ break;
+ default:
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "INI compare(%d ? %d)\n",
i_op1, i_op2);
+#endif
+ ret = 0;
+ break;
+ }
+ }
+ free(Z_STRVAL_P(op1));
+ if (op2) {
+ free(Z_STRVAL_P(op2));
+ }
+ Z_STRVAL_P(result) = malloc(2);
+ Z_STRVAL_P(result)[0] = ret ? '1' : '0';
+ Z_STRVAL_P(result)[1] = 0;
+ Z_STRLEN_P(result) = 1;
+ Z_TYPE_P(result) = IS_STRING;
+}
+/* }}} */
+
/* {{{ zend_ini_init_string()
*/
static void zend_ini_init_string(zval *result)
@@ -159,31 +261,7 @@ static void zend_ini_get_var(zval *resul
*/
static void ini_error(char *msg)
{
- char *error_buf;
- int error_buf_len;
- char *currently_parsed_filename;
- TSRMLS_FETCH();
-
- currently_parsed_filename = zend_ini_scanner_get_filename(TSRMLS_C);
- if (currently_parsed_filename) {
- error_buf_len = 128 + strlen(msg) +
strlen(currently_parsed_filename); /* should be more than enough */
- error_buf = (char *) emalloc(error_buf_len);
-
- sprintf(error_buf, "%s in %s on line %d\n", msg,
currently_parsed_filename, zend_ini_scanner_get_lineno(TSRMLS_C));
- } else {
- error_buf = estrdup("Invalid configuration directive\n");
- }
-
- if (CG(ini_parser_unbuffered_errors)) {
-#ifdef PHP_WIN32
- MessageBox(NULL, error_buf, "PHP Error",
MB_OK|MB_TOPMOST|0x00200000L);
-#else
- fprintf(stderr, "PHP: %s", error_buf);
-#endif
- } else {
- zend_error(E_WARNING, "%s", error_buf);
- }
- efree(error_buf);
+ zend_ini_error(E_WARNING TSRMLS_CC, msg);
}
/* }}} */
@@ -244,12 +322,42 @@ ZEND_API int zend_parse_ini_string(char
}
/* }}} */
+void zend_ini_ternary(zval *result, zval *condition, zval *first, zval *second
TSRMLS_CC) /* {{{ */
+{
+ zval tmp;
+ int val;
+ zend_ini_get_var(&tmp, condition TSRMLS_CC);
+ free(Z_STRVAL_P(condition));
+ val = atoi(Z_STRVAL(tmp));
+ free(Z_STRVAL(tmp));
+ if (val) {
+ if (first) {
+ *result = *first;
+ } else {
+ ZVAL_STRINGL(result, "", 0, 1);
+ }
+ if (second) {
+ free(Z_STRVAL_P(second));
+ }
+ } else {
+ if (second) {
+ *result = *second;
+ } else {
+ ZVAL_STRINGL(result, "", 0, 1);
+ }
+ if (first) {
+ free(Z_STRVAL_P(first));
+ }
+ }
+} /* }}} */
+
%}
%expect 0
%pure_parser
%token TC_SECTION
+%token TC_CONDITION
%token TC_RAW
%token TC_CONSTANT
%token TC_NUMBER
@@ -263,7 +371,11 @@ ZEND_API int zend_parse_ini_string(char
%token BOOL_TRUE
%token BOOL_FALSE
%token END_OF_LINE
-%token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?'
'@' '{' '}'
+%left T_L_OR
+%left T_L_AND
+%left T_IS_EQ T_IS_NE T_IS_IDENTICAL T_IS_NOT_IDENTICAL
+%left T_IS_LE T_IS_GE
+%token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?'
'@' '{' '}' '(' ')'
%left '|' '&'
%right '~' '!'
@@ -276,33 +388,71 @@ statement_list:
statement:
TC_SECTION section_string_or_value ']' {
-#if DEBUG_CFG_PARSER
- printf("SECTION: [%s]\n", Z_STRVAL($2));
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "SECTION: [%s]\n", Z_STRVAL($2));
#endif
ZEND_INI_PARSER_CB(&$2, NULL, NULL,
ZEND_INI_PARSER_SECTION, ZEND_INI_PARSER_ARG TSRMLS_CC);
free(Z_STRVAL($2));
}
+ | TC_CONDITION compare ']' {
+ int ignore = Z_STRVAL($2)[0] == '1' ? 0 : 1;
+ free(Z_STRVAL($2));
+ zend_ini_set_ignore(ignore ? ZEND_INI_COND_IGNORE :
ZEND_INI_COND_READ TSRMLS_CC);
+ }
| TC_LABEL '=' string_or_value {
-#if DEBUG_CFG_PARSER
- printf("NORMAL: '%s' = '%s'\n", Z_STRVAL($1),
Z_STRVAL($3));
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "NORMAL: '%s' = '%s'\n", Z_STRVAL($1),
Z_STRVAL($3));
#endif
ZEND_INI_PARSER_CB(&$1, &$3, NULL,
ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
free(Z_STRVAL($1));
free(Z_STRVAL($3));
}
| TC_OFFSET option_offset ']' '=' string_or_value {
-#if DEBUG_CFG_PARSER
- printf("OFFSET: '%s'[%s] = '%s'\n", Z_STRVAL($1),
Z_STRVAL($2), Z_STRVAL($5));
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "OFFSET: '%s'[%s] = '%s'\n",
Z_STRVAL($1), Z_STRVAL($2), Z_STRVAL($5));
#endif
ZEND_INI_PARSER_CB(&$1, &$5, &$2,
ZEND_INI_PARSER_POP_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
free(Z_STRVAL($1));
free(Z_STRVAL($2));
free(Z_STRVAL($5));
}
- | TC_LABEL { ZEND_INI_PARSER_CB(&$1, NULL, NULL,
ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); free(Z_STRVAL($1)); }
+ | TC_LABEL {
+ ZEND_INI_PARSER_CB(&$1, NULL, NULL,
ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
+ free(Z_STRVAL($1));
+ }
| END_OF_LINE
;
+compare:
+ compare_right T_L_AND compare_right { zend_ini_compare(T_L_AND,
&$$, &$1, &$3); }
+ | compare_right T_L_OR compare_right { zend_ini_compare(T_L_OR,
&$$, &$1, &$3); }
+ | compare_right T_IS_GE compare_right { zend_ini_compare(T_IS_GE,
&$$, &$1, &$3); }
+ | compare_right '>' compare_right { zend_ini_compare('>',
&$$, &$1, &$3); }
+ | compare_right T_IS_LE compare_right { zend_ini_compare(T_IS_LE,
&$$, &$1, &$3); }
+ | compare_right '<' compare_right { zend_ini_compare('<',
&$$, &$1, &$3); }
+ | compare_right T_IS_EQ compare_right { zend_ini_compare(T_IS_EQ,
&$$, &$1, &$3); }
+ | compare_right T_IS_NE compare_right { zend_ini_compare(T_IS_NE,
&$$, &$1, &$3); }
+ | compare_right T_IS_IDENTICAL compare_right {
zend_ini_compare(T_IS_IDENTICAL, &$$, &$1, &$3); }
+ | compare_right T_IS_NOT_IDENTICAL compare_right {
zend_ini_compare(T_IS_NOT_IDENTICAL, &$$, &$1, &$3); }
+;
+
+compare_right:
+ compare_value { $$ = $1; }
+ | '(' compare ')' { $$ = $2; }
+;
+
+compare_value:
+ | TC_RAW { $$ =
$1; }
+ | TC_NUMBER { $$ =
$1; }
+ | TC_STRING { $$ =
$1; }
+ | BOOL_TRUE { $$ =
$1; }
+ | BOOL_FALSE { $$ =
$1; }
+ | TC_CONSTANT {
zend_ini_get_constant(&$$, &$1 TSRMLS_CC); }
+ | '"' encapsed_list '"' { $$ = $2; }
+ | cfg_var_ref { $$ =
$1; }
+ | '(' expr ')' { $$ = $2; }
+;
+
section_string_or_value:
var_string_list { $$ = $1; }
| /* empty */ {
zend_ini_init_string(&$$); }
@@ -345,15 +495,30 @@ expr:
;
cfg_var_ref:
- TC_DOLLAR_CURLY TC_VARNAME '}' { zend_ini_get_var(&$$, &$2
TSRMLS_CC); free(Z_STRVAL($2)); }
+ TC_DOLLAR_CURLY TC_VARNAME '}' {
+ zend_ini_get_var(&$$, &$2 TSRMLS_CC);
+ free(Z_STRVAL($2));
+ }
+ | TC_DOLLAR_CURLY TC_VARNAME '?' TC_RAW ':' TC_RAW '}' {
+ zend_ini_ternary(&$$, &$2, &$4, &$6 TSRMLS_CC);
+ }
+ | TC_DOLLAR_CURLY TC_VARNAME '?' ':' TC_RAW '}' {
+ zend_ini_ternary(&$$, &$2, NULL, &$5 TSRMLS_CC);
+ }
+ | TC_DOLLAR_CURLY TC_VARNAME '?' TC_RAW ':' '}' {
+ zend_ini_ternary(&$$, &$2, &$4, NULL TSRMLS_CC);
+ }
+ | TC_DOLLAR_CURLY TC_VARNAME '?' ':' '}' {
+ zend_ini_ternary(&$$, &$2, NULL, NULL TSRMLS_CC);
+ }
;
constant_string:
TC_CONSTANT {
zend_ini_get_constant(&$$, &$1 TSRMLS_CC); }
- | TC_RAW { $$ =
$1; /*printf("TC_RAW: '%s'\n", Z_STRVAL($1));*/ }
- | TC_NUMBER { $$ =
$1; /*printf("TC_NUMBER: '%s'\n", Z_STRVAL($1));*/ }
- | TC_STRING { $$ =
$1; /*printf("TC_STRING: '%s'\n", Z_STRVAL($1));*/ }
- | TC_WHITESPACE { $$ = $1;
/*printf("TC_WHITESPACE: '%s'\n", Z_STRVAL($1));*/ }
+ | TC_RAW { $$ =
$1; /*fprintf(stderr, "TC_RAW: '%s'\n", Z_STRVAL($1));*/ }
+ | TC_NUMBER { $$ =
$1; /*fprintf(stderr, "TC_NUMBER: '%s'\n", Z_STRVAL($1));*/ }
+ | TC_STRING { $$ =
$1; /*fprintf(stderr, "TC_STRING: '%s'\n", Z_STRVAL($1));*/ }
+ | TC_WHITESPACE { $$ = $1;
/*fprintf(stderr, "TC_WHITESPACE: '%s'\n", Z_STRVAL($1));*/ }
;
/*
Index: Zend/zend_ini_scanner.l
===================================================================
RCS file: /repository/ZendEngine2/zend_ini_scanner.l,v
retrieving revision 1.41.2.2.2.2.2.2
diff -u -p -d -r1.41.2.2.2.2.2.2 zend_ini_scanner.l
--- Zend/zend_ini_scanner.l 4 Feb 2008 20:45:20 -0000 1.41.2.2.2.2.2.2
+++ Zend/zend_ini_scanner.l 9 Feb 2008 14:31:54 -0000
@@ -15,6 +15,7 @@
+----------------------------------------------------------------------+
| Authors: Zeev Suraski <[EMAIL PROTECTED]> |
| Jani Taskinen <[EMAIL PROTECTED]>
|
+ | Marcus Boerger <[EMAIL PROTECTED]> |
+----------------------------------------------------------------------+
*/
@@ -68,13 +69,18 @@
%}
+%x IGNORE
+%x IFDONE
%x ST_DOUBLE_QUOTES
%x ST_OFFSET
%x ST_RAW
%x ST_SECTION_RAW
%x ST_SECTION_VALUE
+%x ST_CONDITION_VALUE
%x ST_VALUE
%x ST_VARNAME
+%x ST_TERNARY_FIRST
+%x ST_TERNARY_SECOND
%option stack
%{
@@ -122,6 +128,8 @@ ZEND_API zend_scanner_globals ini_scanne
return type; \
}
+void zend_ini_set_ignore(ZEND_INI_CONDITIONAL state TSRMLS_DC);
+
static char *ini_filename;
/* {{{ init_ini_scanner()
@@ -129,6 +137,7 @@ static char *ini_filename;
static void init_ini_scanner(TSRMLS_D)
{
SCNG(lineno) = 1;
+ SCNG(if_level) = 0;
SCNG(scanner_mode) = ZEND_INI_SCANNER_NORMAL;
SCNG(yy_start_stack_ptr) = 0;
SCNG(yy_start_stack_depth) = 0;
@@ -199,6 +208,35 @@ int zend_ini_prepare_string_for_scanning
}
/* }}} */
+void zend_ini_error(int severity TSRMLS_DC, char *error) /* {{{ */
+{
+ if (!error) {
+ error = "Error";
+ }
+ if (CG(ini_parser_unbuffered_errors)) {
+#ifdef PHP_WIN32
+ if (ini_filename) {
+ zend_spprintf(&error, 0, "%s at line %d of ini file
%s.", error, SCNG(lineno), ini_filename);
+ } else {
+ zend_spprintf(&error, 0, "%s in invalid configuration
directive.", error);
+ }
+ MessageBox(NULL, error, "PHP Error",
MB_OK|MB_TOPMOST|0x00200000L);
+ efree(error);
+#else
+ if (ini_filename) {
+ fprintf(stderr, "PHP: %s at line %d of ini file %s.\n",
error, SCNG(lineno), ini_filename);
+ } else {
+ fprintf(stderr, "PHP: %s in invalid configuration
directive.\n", error);
+ }
+#endif
+ } else if (ini_filename) {
+ zend_error(severity, "%s at line %d of ini file %s", error,
SCNG(lineno), ini_filename);
+ } else {
+ zend_error(severity, "%s in invalid configuration directive",
error);
+ }
+}
+/* }}} */
+
/* {{{ zend_ini_close_file()
*/
void zend_ini_close_file(zend_file_handle *fh TSRMLS_DC)
@@ -290,7 +328,9 @@ RAW_VALUE_CHARS [^=\n\r;]
LITERAL_DOLLAR ("$"([^a-zA-Z0-9{]|("\\"{ANY_CHAR})))
VALUE_CHARS ([^$= \t\n\r;&|~()!"']|{LITERAL_DOLLAR})
SECTION_VALUE_CHARS ([^$\n\r;"'\]\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
+CONDITION_VALUE_CHARS ([^$ \t\n\r;"'\]\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
+TERNARY_VALUE_CHARS ([^$"\\:?{}\r\n]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
/* " */
@@ -312,7 +352,81 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C
return TC_SECTION;
}
-<ST_VALUE,ST_SECTION_VALUE,ST_OFFSET>"'"{SINGLE_QUOTED_CHARS}+"'" { /* Raw
string */
+<IGNORE>"[ELSE]"{TABS_AND_SPACES}*{NEWLINE} { /* End of condition */
+ zend_ini_set_ignore(ZEND_INI_COND_READ TSRMLS_CC);
+ BEGIN(INITIAL);
+ SCNG(lineno)++;
+ return END_OF_LINE;
+}
+
+<IFDONE,INITIAL>"[ELSE]"{TABS_AND_SPACES}*{NEWLINE} { /* End of condition */
+ if (SCNG(scanner_mode) != ZEND_INI_SCANNER_RAW) {
+ if (!SCNG(if_level)) {
+ zend_ini_error(E_WARNING TSRMLS_CC, "[ELSE] without
[IF]");
+ yyterminate();
+ }
+ zend_ini_set_ignore(ZEND_INI_COND_IGNORE TSRMLS_CC);
+ BEGIN(IFDONE);
+ } else {
+ BEGIN(INITIAL);
+ }
+ SCNG(lineno)++;
+ return END_OF_LINE;
+}
+
+<INITIAL,IGNORE,IFDONE>"[ENDIF]"{TABS_AND_SPACES}*{NEWLINE} { /* End of
condition */
+ if (SCNG(scanner_mode) != ZEND_INI_SCANNER_RAW) {
+ if (!SCNG(if_level)--) {
+ zend_ini_error(E_WARNING TSRMLS_CC, "[ENDIF] without
[IF]");
+ yyterminate();
+ }
+ yy_pop_state(TSRMLS_C);
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "ENDIF\n");
+#endif
+ }
+ SCNG(lineno)++;
+ return END_OF_LINE;
+}
+
+<INITIAL,IGNORE>"[ELIF"{TABS_AND_SPACES}+ { /* Condition elif */
+ if (SCNG(scanner_mode) != ZEND_INI_SCANNER_RAW) {
+ if (!SCNG(if_level)) {
+ zend_error(E_WARNING, "[ELIF] without [IF]");
+ yyterminate();
+ }
+ BEGIN(ST_CONDITION_VALUE);
+ return TC_CONDITION;
+ } else {
+ BEGIN(IFDONE);
+ return END_OF_LINE;
+ }
+}
+
+<IFDONE>"[ELIF"{TABS_AND_SPACES}+ { /* Condition elif */
+ return END_OF_LINE;
+}
+
+<INITIAL>"[IF"{TABS_AND_SPACES}+ { /* Condition if */
+ if (SCNG(scanner_mode) != ZEND_INI_SCANNER_RAW) {
+ SCNG(if_level)++;
+ yy_push_state(ST_CONDITION_VALUE TSRMLS_CC);
+ return TC_CONDITION;
+ } else {
+ BEGIN(IFDONE);
+ return END_OF_LINE;
+ }
+}
+
+<IGNORE,IFDONE>[^\[]{NEWLINE} {
+ SCNG(lineno)++;
+ if (SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW) {
+ BEGIN(INITIAL);
+ }
+ return END_OF_LINE;
+}
+
+<ST_VALUE,ST_SECTION_VALUE,ST_CONDITION_VALUE,ST_OFFSET>"'"{SINGLE_QUOTED_CHARS}+"'"
{ /* Raw string */
/* Eat leading and trailing single quotes */
if (yytext[0] == '\'' && yytext[yyleng - 1] == '\'') {
yytext++;
@@ -328,6 +442,52 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C
return ']';
}
+<ST_CONDITION_VALUE>{TABS_AND_SPACES}*"]"{TABS_AND_SPACES}*{NEWLINE}? { /* End
of condition */
+ BEGIN(INITIAL);
+ SCNG(lineno)++;
+ return ']';
+}
+
+<ST_CONDITION_VALUE>{TABS_AND_SPACES}*"||"{TABS_AND_SPACES}* {
+ return T_L_OR;
+}
+
+<ST_CONDITION_VALUE>{TABS_AND_SPACES}*"&&"{TABS_AND_SPACES}* {
+ return T_L_AND;
+}
+
+<ST_CONDITION_VALUE>{TABS_AND_SPACES}*"=="{TABS_AND_SPACES}* {
+ return T_IS_EQ;
+}
+
+<ST_CONDITION_VALUE>{TABS_AND_SPACES}*"!="{TABS_AND_SPACES}* {
+ return T_IS_NE;
+}
+
+<ST_CONDITION_VALUE>{TABS_AND_SPACES}*"==="{TABS_AND_SPACES}* {
+ return T_IS_IDENTICAL;
+}
+
+<ST_CONDITION_VALUE>{TABS_AND_SPACES}*"!=="{TABS_AND_SPACES}* {
+ return T_IS_NOT_IDENTICAL;
+}
+
+<ST_CONDITION_VALUE>{TABS_AND_SPACES}*"<="{TABS_AND_SPACES}* {
+ return T_IS_LE;
+}
+
+<ST_CONDITION_VALUE>{TABS_AND_SPACES}*">="{TABS_AND_SPACES}* {
+ return T_IS_GE;
+}
+
+<ST_CONDITION_VALUE>{TABS_AND_SPACES}*"("{TABS_AND_SPACES}* {
+ return '(';
+}
+
+<ST_CONDITION_VALUE>{TABS_AND_SPACES}*")"{TABS_AND_SPACES}* {
+ return ')';
+}
+
<INITIAL>{LABEL}"["{TABS_AND_SPACES}* { /* Start of option with offset */
/* Eat trailing whitespace and [ */
EAT_TRAILING_WHITESPACE_EX('[');
@@ -343,7 +503,7 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C
return ']';
}
-<ST_DOUBLE_QUOTES,ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{DOLLAR_CURLY} { /*
Variable start */
+<ST_DOUBLE_QUOTES,ST_SECTION_VALUE,ST_CONDITION_VALUE,ST_VALUE,ST_OFFSET>{DOLLAR_CURLY}
{ /* Variable start */
yy_push_state(ST_VARNAME TSRMLS_CC);
return TC_DOLLAR_CURLY;
}
@@ -352,12 +512,26 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C
RETURN_TOKEN(TC_VARNAME, yytext, yyleng);
}
-<ST_VARNAME>"}" { /* Variable end */
+<ST_VARNAME>"?" { /* Variable ternary first value */
+ BEGIN(ST_TERNARY_FIRST);
+ return '?';
+}
+
+<ST_TERNARY_FIRST>":" { /* Variable ternary second value */
+ BEGIN(ST_TERNARY_SECOND);
+ return':';
+}
+
+<ST_TERNARY_FIRST,ST_TERNARY_SECOND>{TERNARY_VALUE_CHARS}* { /* ternary values
*/
+ RETURN_TOKEN(TC_RAW, yytext, yyleng);
+}
+
+<ST_VARNAME,ST_TERNARY_SECOND>"}" { /* Variable end */
yy_pop_state(TSRMLS_C);
return '}';
}
-<INITIAL,ST_VALUE>("true"|"on"|"yes"){TABS_AND_SPACES}* { /* TRUE value (when
used outside option value/offset this causes parse error!) */
+<INITIAL,ST_CONDITION_VALUE,ST_VALUE>("true"|"on"|"yes"){TABS_AND_SPACES}* {
/* TRUE value (when used outside option value/offset this causes parse error!)
*/
RETURN_TOKEN(BOOL_TRUE, "1", 1);
}
@@ -365,6 +539,10 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C
RETURN_TOKEN(BOOL_FALSE, "", 0);
}
+<ST_CONDITION_VALUE>("false"|"off"|"no"|"none"|"null"){TABS_AND_SPACES}* { /*
FALSE value (when used in conditions we want '0' rather than '')*/
+ RETURN_TOKEN(BOOL_FALSE, "0", 1);
+}
+
<INITIAL>{LABEL} { /* Get option name */
RETURN_TOKEN(TC_LABEL, yytext, yyleng);
}
@@ -398,11 +576,11 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C
return END_OF_LINE;
}
-<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{CONSTANT} { /* Get constant option value
*/
+<ST_SECTION_VALUE,ST_CONDITION_VALUE,ST_VALUE,ST_OFFSET>{CONSTANT} { /* Get
constant option value */
RETURN_TOKEN(TC_CONSTANT, yytext, yyleng);
}
-<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{NUMBER} { /* Get number option value as
string */
+<ST_SECTION_VALUE,ST_CONDITION_VALUE,ST_VALUE,ST_OFFSET>{NUMBER} { /* Get
number option value as string */
RETURN_TOKEN(TC_NUMBER, yytext, yyleng);
}
@@ -428,7 +606,7 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C
RETURN_TOKEN(TC_STRING, yytext, yyleng);
}
-<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{TABS_AND_SPACES}*["] { /* Double quoted
'"' string start */
+<ST_SECTION_VALUE,ST_CONDITION_VALUE,ST_VALUE,ST_OFFSET>{TABS_AND_SPACES}*["]
{ /* Double quoted '"' string start */
yy_push_state(ST_DOUBLE_QUOTES TSRMLS_CC);
return '"';
}
@@ -473,37 +651,46 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C
switch (YYSTATE) {
case INITIAL:
break;
+
+ case IGNORE:
+ case IFDONE:
+ zend_ini_error(E_ERROR TSRMLS_CC, "Unterminated [IF] in
ini");
+ break;
case ST_DOUBLE_QUOTES:
- fprintf(stderr, "ERROR: Unterminated ini option value
double quotes\n");
+ zend_ini_error(E_ERROR TSRMLS_CC, "Unterminated ini
option value double quotes");
break;
case ST_OFFSET:
- fprintf(stderr, "ERROR: Unterminated ini option
offset\n");
+ zend_ini_error(E_ERROR TSRMLS_CC, "Unterminated ini
option offset");
break;
case ST_RAW:
- fprintf(stderr, "ERROR: Unterminated raw ini option
value\n");
+ zend_ini_error(E_ERROR TSRMLS_CC, "Unterminated raw ini
option value");
break;
case ST_SECTION_RAW:
- fprintf(stderr, "ERROR: Unterminated raw ini section
value\n");
+ zend_ini_error(E_ERROR TSRMLS_CC, "Unterminated raw ini
section value");
break;
case ST_SECTION_VALUE:
- fprintf(stderr, "ERROR: Unterminated ini section
value\n");
+ zend_ini_error(E_ERROR TSRMLS_CC, "Unterminated ini
section value");
+ break;
+
+ case ST_CONDITION_VALUE:
+ zend_ini_error(E_ERROR TSRMLS_CC, "Unterminated ini
condition value");
break;
case ST_VALUE:
- fprintf(stderr, "ERROR: Unterminated ini option
value\n");
+ zend_ini_error(E_ERROR TSRMLS_CC, "Unterminated ini
option value");
break;
case ST_VARNAME:
- fprintf(stderr, "ERROR: Unterminated ini variable\n");
+ zend_ini_error(E_ERROR TSRMLS_CC, "Unterminated ini
variable");
break;
default:
- fprintf(stderr, "BUG: Unknown state (%d)\n", YYSTATE);
+ zend_ini_error(E_ERROR TSRMLS_CC, "Unknown state"); /*
(%d)\n", YYSTATE); */
break;
}
yy_pop_state(TSRMLS_C);
@@ -511,3 +698,30 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C
#endif
yyterminate();
}
+
+%%
+
+void zend_ini_set_ignore(ZEND_INI_CONDITIONAL state TSRMLS_DC) /* {{{ */
+{
+ switch(state) {
+ case ZEND_INI_COND_READ:
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "READ\n");
+#endif
+ BEGIN(INITIAL);
+ break;
+ case ZEND_INI_COND_IGNORE:
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "IGNORE\n");
+#endif
+ BEGIN(IGNORE);
+ break;
+ case ZEND_INI_COND_DONE:
+#if ZEND_DEBUG_CFG_PARSER
+ fprintf(stderr, "IF DONE\n");
+#endif
+ BEGIN(IFDONE);
+ break;
+ }
+}
+/* }}} */
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php