%}
-%expect 1
+%expect 0
%pure_parser
%token TC_SECTION
%token TC_RAW
+%token TC_CONSTANT
%token TC_NUMBER
%token TC_STRING
+%token TC_WHITESPACE
+%token TC_LABEL
%token TC_OFFSET
%token TC_DOLLAR_CURLY
%token TC_VARNAME
%token BOOL_TRUE
%token BOOL_FALSE
%token END_OF_LINE
-%token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?' '@'
+%token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?' '@' '{' '}'
%left '|' '&'
%right '~' '!'
ZEND_INI_PARSER_CB(&$2, NULL, NULL, ZEND_INI_PARSER_SECTION, ZEND_INI_PARSER_ARG TSRMLS_CC);
free(Z_STRVAL($2));
}
- | TC_STRING '=' string_or_value {
+ | TC_LABEL '=' string_or_value {
#if DEBUG_CFG_PARSER
printf("NORMAL: '%s' = '%s'\n", Z_STRVAL($1), Z_STRVAL($3));
#endif
free(Z_STRVAL($2));
free(Z_STRVAL($5));
}
- | TC_STRING { 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
;
section_string_or_value:
- TC_RAW { $$ = $1; }
- | section_var_list { $$ = $1; }
- | '"' encapsed_list '"' { $$ = $2; }
+ var_string_list { $$ = $1; }
| /* empty */ { zend_ini_init_string(&$$); }
;
string_or_value:
expr { $$ = $1; }
- | TC_RAW { $$ = $1; }
- | TC_NUMBER { $$ = $1; }
| BOOL_TRUE { $$ = $1; }
| BOOL_FALSE { $$ = $1; }
- | '"' encapsed_list '"' { $$ = $2; }
| END_OF_LINE { zend_ini_init_string(&$$); }
;
option_offset:
- TC_NUMBER { $$ = $1; }
- | TC_RAW { $$ = $1; }
- | var_string_list { $$ = $1; }
- | '"' encapsed_list '"' { $$ = $2; }
+ var_string_list { $$ = $1; }
| /* empty */ { zend_ini_init_string(&$$); }
;
| /* empty */ { zend_ini_init_string(&$$); }
;
-section_var_list:
- cfg_var_ref { $$ = $1; }
- | TC_STRING { $$ = $1; }
- | section_var_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
- | section_var_list TC_STRING { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
-;
-
var_string_list:
cfg_var_ref { $$ = $1; }
| constant_string { $$ = $1; }
+ | '"' encapsed_list '"' { $$ = $2; }
| var_string_list cfg_var_ref { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
| var_string_list constant_string { zend_ini_add_string(&$$, &$1, &$2); free(Z_STRVAL($2)); }
+ | var_string_list '"' encapsed_list '"' { zend_ini_add_string(&$$, &$1, &$3); free(Z_STRVAL($3)); }
;
expr:
;
constant_string:
- TC_STRING { zend_ini_get_constant(&$$, &$1 TSRMLS_CC); }
+ 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));*/ }
;
/*
} else {
*t++ = *s;
}
-
if (*s == '\n' || (*s == '\r' && (*(s+1) != '\n'))) {
SCNG(lineno)++;
}
LNUM [0-9]+
DNUM ([0-9]*[\.][0-9]+)|([0-9]+[\.][0-9]*)
-NUMBER {LNUM}|{DNUM}
-ANY_CHAR (.|[\n])
+NUMBER [-]?{LNUM}|{DNUM}
+ANY_CHAR (.|[\n\t])
NEWLINE ("\r"|"\n"|"\r\n")
TABS_AND_SPACES [ \t]
+WHITESPACE [ \t]+
CONSTANT [a-zA-Z][a-zA-Z0-9_]*
-LABEL [a-zA-Z0-9][a-zA-Z0-9._]*
-TOKENS [:,.\[\]"'()|^&+-/*=%$!~<>?@]
+LABEL [a-zA-Z0-9][a-zA-Z0-9._-]*
+TOKENS [:,.\[\]"'()|^&+-/*=%$!~<>?@{}]
OPERATORS [&|~()!]
+DOLLAR_CURLY "${"
-LITERAL_DOLLAR ("$"+([^a-zA-Z0-9$"'\\{]|("\\"{ANY_CHAR})))
-VALUE_CHARS ("{"*([^=\n\r;&|~()!$"'\\{]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR})
-RAW_VALUE_CHARS [^=\n\r;]
-SINGLE_QUOTED_CHARS [^']
-
-SECTION_VALUE_CHARS ("{"*([^\n\r;$"'\\{\]]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR})
SECTION_RAW_CHARS [^\]\n\r]
+SINGLE_QUOTED_CHARS [^']
+RAW_VALUE_CHARS [^=\n\r;]
-/* Allow using ${foobar} inside quoted strings */
-DOUBLE_QUOTES_CHARS ("{"*([^$"\\{]|("\\"{ANY_CHAR}))|{LITERAL_DOLLAR})
+/* Allow using ${foobar} in sections, quoted strings and values */
+LITERAL_DOLLAR ("$"([^a-zA-Z0-9{]|("\\"{ANY_CHAR})))
+VALUE_CHARS ([^$= \t\n\r;&|~()!"']|{LITERAL_DOLLAR})
+SECTION_VALUE_CHARS ([^$\n\r;"'\]\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
+DOUBLE_QUOTES_CHARS ([^$"\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
/* " */
return ']';
}
-<ST_DOUBLE_QUOTES,ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>"${" { /* Variable start */
+<ST_DOUBLE_QUOTES,ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{DOLLAR_CURLY} { /* Variable start */
yy_push_state(ST_VARNAME TSRMLS_CC);
return TC_DOLLAR_CURLY;
}
RETURN_TOKEN(BOOL_FALSE, "", 0);
}
-<INITIAL,ST_OFFSET>{LABEL} { /* Get option name or option offset value */
- RETURN_TOKEN(TC_STRING, yytext, yyleng);
+<INITIAL>{LABEL} { /* Get option name */
+ RETURN_TOKEN(TC_LABEL, yytext, yyleng);
}
<INITIAL>{TABS_AND_SPACES}*[=]{TABS_AND_SPACES}* { /* Start option value */
RETURN_TOKEN(TC_RAW, yytext, yyleng);
}
-<ST_VALUE,ST_RAW>{NEWLINE} { /* End of option value */
+<ST_VALUE,ST_RAW>{TABS_AND_SPACES}*{NEWLINE} { /* End of option value */
BEGIN(INITIAL);
SCNG(lineno)++;
return END_OF_LINE;
}
-<ST_VALUE,ST_OFFSET>{CONSTANT} { /* Get constant option value */
- RETURN_TOKEN(TC_STRING, yytext, yyleng);
+<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{CONSTANT} { /* Get constant option value */
+ RETURN_TOKEN(TC_CONSTANT, yytext, yyleng);
}
-<ST_VALUE,ST_OFFSET>{NUMBER} { /* Get number option value as string */
+<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{NUMBER} { /* Get number option value as string */
RETURN_TOKEN(TC_NUMBER, yytext, yyleng);
}
}
<ST_VALUE>{VALUE_CHARS}+ { /* Get everything else as option/offset value */
- /* Eat trailing tabs and spaces */
- EAT_TRAILING_WHITESPACE();
RETURN_TOKEN(TC_STRING, yytext, yyleng);
}
RETURN_TOKEN(TC_STRING, yytext, yyleng);
}
-<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>["] { /* Double quoted '"' string start */
+<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{TABS_AND_SPACES}*["] { /* Double quoted '"' string start */
yy_push_state(ST_DOUBLE_QUOTES TSRMLS_CC);
return '"';
}
return TC_QUOTED_STRING;
}
-<ST_DOUBLE_QUOTES>["] { /* Double quoted '"' string ends */
+<ST_DOUBLE_QUOTES>["]{TABS_AND_SPACES}* { /* Double quoted '"' string ends */
yy_pop_state(TSRMLS_C);
return '"';
}
-<INITIAL,ST_VALUE,ST_RAW,ST_OFFSET>{TABS_AND_SPACES} {
+<ST_SECTION_VALUE,ST_VALUE,ST_OFFSET>{WHITESPACE} {
+ RETURN_TOKEN(TC_WHITESPACE, yytext, yyleng);
+}
+
+<INITIAL,ST_RAW>{TABS_AND_SPACES}+ {
/* eat whitespace */
}
-<INITIAL>{NEWLINE} {
+<INITIAL>{TABS_AND_SPACES}*{NEWLINE} {
SCNG(lineno)++;
return END_OF_LINE;
}
-<INITIAL,ST_VALUE,ST_RAW>[;][^\r\n]*{NEWLINE} { /* Comment */
+<INITIAL,ST_VALUE,ST_RAW>{TABS_AND_SPACES}*[;][^\r\n]*{NEWLINE} { /* Comment */
BEGIN(INITIAL);
SCNG(lineno)++;
return END_OF_LINE;
sqstring = 'adsasdadasdasd'
dqstring = "asdadfsdjkslkj ¡@£$$ { } !^~|¥¥{[()/)&/% ¤ # #"
php_constant = E_ALL
+user_constant = TEST_CONSTANT
[basic with whitespace]
basicval = bar
;[PATH="${basicval}/path/quoted"]
["PATH=${basicval}/all/quoted"]
-; The rest is from bug #29306
+; This is test for bug #29306
[01]
e=e
f=f
d=d
[0815]
bla=bla
+
+;Test for bug #43923
+[bug #43923]
+curly1 = {
+curly2 = "{"
+curly3 = '{'
+
+;Test for bug #44019
+[bug #44019]
+concatenation_before = TEST_CONSTANT "+some_text_after"
+concatenation_middle = "some_text_before+" TEST_CONSTANT "+some_text_after"
+concatenation_after = "some_text_before+" TEST_CONSTANT
+concatenation_nows_before = TEST_CONSTANT"+some_text_after"
+concatenation_nows_middle = "some_text_before+"TEST_CONSTANT"+some_text_after"
+concatenation_nows_after = "some_text_before+"TEST_CONSTANT
+
+;Test for bug #43915
+[bug #43915]
+ini_with-hyphen = with hyphen and underscore
+ini.with-hyphen = dot and hyphen
+ini-with.hyphen = hyphen and dot
+
$ini_file = dirname(__FILE__)."/parse_ini_basic.data";
+define('TEST_CONSTANT', 'this_is_test_constant');
+
var_dump(parse_ini_file($ini_file, 1));
echo "Done.\n";
?>
--EXPECTF--
-array(22) {
+array(25) {
["basic"]=>
- array(14) {
+ array(15) {
["basicval"]=>
string(3) "bar"
["longval"]=>
string(51) "asdadfsdjkslkj ¡@£$$ { } !^~|¥¥{[()/)&/% ¤ # #"
["php_constant"]=>
string(4) "8191"
+ ["user_constant"]=>
+ string(21) "this_is_test_constant"
}
["basic with whitespace"]=>
array(13) {
["bla"]=>
string(3) "bla"
}
+ ["bug #43923"]=>
+ array(3) {
+ ["curly1"]=>
+ string(1) "{"
+ ["curly2"]=>
+ string(1) "{"
+ ["curly3"]=>
+ string(1) "{"
+ }
+ ["bug #44019"]=>
+ array(6) {
+ ["concatenation_before"]=>
+ string(37) "this_is_test_constant+some_text_after"
+ ["concatenation_middle"]=>
+ string(54) "some_text_before+this_is_test_constant+some_text_after"
+ ["concatenation_after"]=>
+ string(38) "some_text_before+this_is_test_constant"
+ ["concatenation_nows_before"]=>
+ string(37) "this_is_test_constant+some_text_after"
+ ["concatenation_nows_middle"]=>
+ string(54) "some_text_before+this_is_test_constant+some_text_after"
+ ["concatenation_nows_after"]=>
+ string(38) "some_text_before+this_is_test_constant"
+ }
+ ["bug #43915"]=>
+ array(3) {
+ ["ini_with-hyphen"]=>
+ string(26) "with hyphen and underscore"
+ ["ini.with-hyphen"]=>
+ string(14) "dot and hyphen"
+ ["ini-with.hyphen"]=>
+ string(14) "hyphen and dot"
+ }
}
Done.
error_reporting3 = E_ALL & ~E_NOTICE
error_reporting4 = E_ALL & ~E_NOTICE | E_STRICT
-[true or false]
+['true or false']
bool_true = true
bool_yes = yes
bool_on = on
["error_reporting values"]=>
array(6) {
["foo"]=>
- string(14) "E_ALL E_NOTICE"
+ string(6) "8191 8"
["error_reporting"]=>
string(4) "8191"
["error_reporting1"]=>