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 13 Feb 2008 16:20:26 -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,32 @@ static void php_load_zend_extension_cb(v } /* }}} */ +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 +374,17 @@ int php_init_config(TSRMLS_D) sapi_module.ini_defaults(&configuration_hash); } +#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 + 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 +596,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_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 13 Feb 2008 16:20:27 -0000 @@ -52,6 +52,8 @@ END_EXTERN_C() #endif #define SYMTABLE_CACHE_SIZE 32 +#define ZEND_DEBUG_CFG_PARSER 0 + #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 13 Feb 2008 16:20:28 -0000 @@ -15,13 +15,12 @@ +----------------------------------------------------------------------+ | Authors: Zeev Suraski | | Jani Taskinen | + | Marcus Boerger | +----------------------------------------------------------------------+ */ /* $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); } /* }}} */ @@ -250,6 +328,7 @@ ZEND_API int zend_parse_ini_string(char %pure_parser %token TC_SECTION +%token TC_CONDITION %token TC_RAW %token TC_CONSTANT %token TC_NUMBER @@ -263,7 +342,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 +359,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 +466,18 @@ 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)); + } ; 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 13 Feb 2008 16:20:28 -0000 @@ -15,6 +15,7 @@ +----------------------------------------------------------------------+ | Authors: Zeev Suraski | | Jani Taskinen | + | Marcus Boerger | +----------------------------------------------------------------------+ */ @@ -68,11 +69,14 @@ %} +%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 %option stack @@ -122,6 +126,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 +135,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 +206,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,6 +326,7 @@ 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}) /* " */ @@ -312,7 +349,81 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C return TC_SECTION; } -"'"{SINGLE_QUOTED_CHARS}+"'" { /* Raw string */ +"[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; +} + +"[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; +} + +"[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; +} + +"[ELSEIF"{TABS_AND_SPACES}+ { /* Condition elseif */ + if (SCNG(scanner_mode) != ZEND_INI_SCANNER_RAW) { + if (!SCNG(if_level)) { + zend_error(E_WARNING, "[ELSEIF] without [IF]"); + yyterminate(); + } + BEGIN(ST_CONDITION_VALUE); + return TC_CONDITION; + } else { + BEGIN(IFDONE); + return END_OF_LINE; + } +} + +"[ELSEIF"{TABS_AND_SPACES}+ { /* Condition elseif */ + return END_OF_LINE; +} + +"[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; + } +} + +[^\[]{NEWLINE} { + SCNG(lineno)++; + if (SCNG(scanner_mode) == ZEND_INI_SCANNER_RAW) { + BEGIN(INITIAL); + } + return END_OF_LINE; +} + +"'"{SINGLE_QUOTED_CHARS}+"'" { /* Raw string */ /* Eat leading and trailing single quotes */ if (yytext[0] == '\'' && yytext[yyleng - 1] == '\'') { yytext++; @@ -328,6 +439,52 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C return ']'; } +{TABS_AND_SPACES}*"]"{TABS_AND_SPACES}*{NEWLINE}? { /* End of condition */ + BEGIN(INITIAL); + SCNG(lineno)++; + return ']'; +} + +{TABS_AND_SPACES}*"||"{TABS_AND_SPACES}* { + return T_L_OR; +} + +{TABS_AND_SPACES}*"&&"{TABS_AND_SPACES}* { + return T_L_AND; +} + +{TABS_AND_SPACES}*"=="{TABS_AND_SPACES}* { + return T_IS_EQ; +} + +{TABS_AND_SPACES}*"!="{TABS_AND_SPACES}* { + return T_IS_NE; +} + +{TABS_AND_SPACES}*"==="{TABS_AND_SPACES}* { + return T_IS_IDENTICAL; +} + +{TABS_AND_SPACES}*"!=="{TABS_AND_SPACES}* { + return T_IS_NOT_IDENTICAL; +} + +{TABS_AND_SPACES}*"<="{TABS_AND_SPACES}* { + return T_IS_LE; +} + +{TABS_AND_SPACES}*">="{TABS_AND_SPACES}* { + return T_IS_GE; +} + +{TABS_AND_SPACES}*"("{TABS_AND_SPACES}* { + return '('; +} + +{TABS_AND_SPACES}*")"{TABS_AND_SPACES}* { + return ')'; +} + {LABEL}"["{TABS_AND_SPACES}* { /* Start of option with offset */ /* Eat trailing whitespace and [ */ EAT_TRAILING_WHITESPACE_EX('['); @@ -343,7 +500,7 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C return ']'; } -{DOLLAR_CURLY} { /* Variable start */ +{DOLLAR_CURLY} { /* Variable start */ yy_push_state(ST_VARNAME TSRMLS_CC); return TC_DOLLAR_CURLY; } @@ -352,12 +509,7 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C RETURN_TOKEN(TC_VARNAME, yytext, yyleng); } -"}" { /* Variable end */ - yy_pop_state(TSRMLS_C); - return '}'; -} - -("true"|"on"|"yes"){TABS_AND_SPACES}* { /* TRUE value (when used outside option value/offset this causes parse error!) */ +("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 +517,10 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C RETURN_TOKEN(BOOL_FALSE, "", 0); } +("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); +} + {LABEL} { /* Get option name */ RETURN_TOKEN(TC_LABEL, yytext, yyleng); } @@ -398,11 +554,11 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C return END_OF_LINE; } -{CONSTANT} { /* Get constant option value */ +{CONSTANT} { /* Get constant option value */ RETURN_TOKEN(TC_CONSTANT, yytext, yyleng); } -{NUMBER} { /* Get number option value as string */ +{NUMBER} { /* Get number option value as string */ RETURN_TOKEN(TC_NUMBER, yytext, yyleng); } @@ -428,7 +584,7 @@ DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_C RETURN_TOKEN(TC_STRING, yytext, yyleng); } -{TABS_AND_SPACES}*["] { /* Double quoted '"' string start */ +{TABS_AND_SPACES}*["] { /* Double quoted '"' string start */ yy_push_state(ST_DOUBLE_QUOTES TSRMLS_CC); return '"'; } @@ -473,37 +629,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 +676,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; + } +} +/* }}} */