mirror of
https://github.com/php/php-src.git
synced 2024-11-27 11:53:33 +08:00
Merge branch 'PHP-5.6'
* PHP-5.6: Updated UPGRADING for #38409 Updated NEWS for #38409 Added test case Making ini parser typed - Added ZEND_INI_SCANNER_TYPED mode for parse_ini_string() and parse_ini_file() - Added NULL_NULL token to separate it from BOOL_FALSE and BOOL_TRUE - Added zend_ini_copy_typed_value() function for zval initialisation - Updated RETURN_TOKEN() to observe scanner_mode Conflicts: Zend/zend_ini_parser.y Zend/zend_ini_scanner.c
This commit is contained in:
commit
5d5a7b1f7f
@ -254,7 +254,7 @@ struct _zend_ini_scanner_globals {
|
||||
char *filename;
|
||||
int lineno;
|
||||
|
||||
/* Modes are: ZEND_INI_SCANNER_NORMAL, ZEND_INI_SCANNER_RAW */
|
||||
/* Modes are: ZEND_INI_SCANNER_NORMAL, ZEND_INI_SCANNER_RAW, ZEND_INI_SCANNER_TYPED */
|
||||
int scanner_mode;
|
||||
};
|
||||
|
||||
|
@ -264,6 +264,7 @@ ZEND_API int zend_parse_ini_string(char *str, zend_bool unbuffered_errors, int s
|
||||
%token TC_QUOTED_STRING
|
||||
%token BOOL_TRUE
|
||||
%token BOOL_FALSE
|
||||
%token NULL_NULL
|
||||
%token END_OF_LINE
|
||||
%token '=' ':' ',' '.' '"' '\'' '^' '+' '-' '/' '*' '%' '$' '~' '<' '>' '?' '@' '{' '}'
|
||||
%left '|' '&' '^'
|
||||
@ -290,7 +291,7 @@ statement:
|
||||
#endif
|
||||
ZEND_INI_PARSER_CB(&$1, &$3, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
|
||||
zend_string_release(Z_STR($1));
|
||||
zend_string_release(Z_STR($3));
|
||||
zval_ptr_dtor(&$3);
|
||||
}
|
||||
| TC_OFFSET option_offset ']' '=' string_or_value {
|
||||
#if DEBUG_CFG_PARSER
|
||||
@ -299,7 +300,7 @@ statement:
|
||||
ZEND_INI_PARSER_CB(&$1, &$5, &$2, ZEND_INI_PARSER_POP_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC);
|
||||
zend_string_release(Z_STR($1));
|
||||
zend_string_release(Z_STR($2));
|
||||
zend_string_release(Z_STR($5));
|
||||
zval_ptr_dtor(&$5);
|
||||
}
|
||||
| TC_LABEL { ZEND_INI_PARSER_CB(&$1, NULL, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG TSRMLS_CC); zend_string_release(Z_STR($1)); }
|
||||
| END_OF_LINE
|
||||
@ -314,6 +315,7 @@ string_or_value:
|
||||
expr { $$ = $1; }
|
||||
| BOOL_TRUE { $$ = $1; }
|
||||
| BOOL_FALSE { $$ = $1; }
|
||||
| NULL_NULL { $$ = $1; }
|
||||
| END_OF_LINE { zend_ini_init_string(&$$); }
|
||||
;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,6 +25,7 @@
|
||||
/* Scanner modes */
|
||||
#define ZEND_INI_SCANNER_NORMAL 0 /* Normal mode. [DEFAULT] */
|
||||
#define ZEND_INI_SCANNER_RAW 1 /* Raw mode. Option values are not parsed */
|
||||
#define ZEND_INI_SCANNER_TYPED 2 /* Typed mode. */
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
int zend_ini_scanner_get_lineno(TSRMLS_D);
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include "zend.h"
|
||||
#include "zend_API.h"
|
||||
#include "zend_globals.h"
|
||||
#include <zend_ini_parser.h>
|
||||
#include "zend_ini_scanner.h"
|
||||
@ -135,9 +136,55 @@ ZEND_API zend_ini_scanner_globals ini_scanner_globals;
|
||||
ZVAL_NEW_STR(retval, zend_string_init(str, len, 1))
|
||||
|
||||
|
||||
#define RETURN_TOKEN(type, str, len) { \
|
||||
zend_ini_copy_value(ini_lval, str, len); \
|
||||
return type; \
|
||||
#define RETURN_TOKEN(type, str, len) { \
|
||||
if (SCNG(scanner_mode) == ZEND_INI_SCANNER_TYPED) { \
|
||||
zend_ini_copy_typed_value(ini_lval, type, str, len); \
|
||||
} else { \
|
||||
zend_ini_copy_value(ini_lval, str, len); \
|
||||
} \
|
||||
return type; \
|
||||
}
|
||||
|
||||
static inline int convert_to_number(zval *retval, const char *str, const int str_len)
|
||||
{
|
||||
zend_uchar type;
|
||||
int overflow;
|
||||
long lval;
|
||||
double dval;
|
||||
|
||||
if ((type = is_numeric_string_ex(str, str_len, &lval, &dval, 0, &overflow)) != 0) {
|
||||
if (type == IS_LONG) {
|
||||
ZVAL_LONG(retval, lval);
|
||||
return SUCCESS;
|
||||
} else if (type == IS_DOUBLE && !overflow) {
|
||||
ZVAL_DOUBLE(retval, dval);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
static void zend_ini_copy_typed_value(zval *retval, const int type, const char *str, int len)
|
||||
{
|
||||
switch (type) {
|
||||
case BOOL_FALSE:
|
||||
case BOOL_TRUE:
|
||||
ZVAL_BOOL(retval, type == BOOL_TRUE);
|
||||
break;
|
||||
|
||||
case NULL_NULL:
|
||||
ZVAL_NULL(retval);
|
||||
break;
|
||||
|
||||
case TC_NUMBER:
|
||||
if (convert_to_number(retval, str, len) == SUCCESS) {
|
||||
break;
|
||||
}
|
||||
/* intentional fall-through */
|
||||
default:
|
||||
zend_ini_copy_value(retval, str, len);
|
||||
}
|
||||
}
|
||||
|
||||
static void _yy_push_state(int new_state TSRMLS_DC)
|
||||
@ -169,7 +216,7 @@ static void yy_scan_buffer(char *str, unsigned int len TSRMLS_DC)
|
||||
static int init_ini_scanner(int scanner_mode, zend_file_handle *fh TSRMLS_DC)
|
||||
{
|
||||
/* Sanity check */
|
||||
if (scanner_mode != ZEND_INI_SCANNER_NORMAL && scanner_mode != ZEND_INI_SCANNER_RAW) {
|
||||
if (scanner_mode != ZEND_INI_SCANNER_NORMAL && scanner_mode != ZEND_INI_SCANNER_RAW && scanner_mode != ZEND_INI_SCANNER_TYPED) {
|
||||
zend_error(E_WARNING, "Invalid scanner mode");
|
||||
return FAILURE;
|
||||
}
|
||||
@ -419,10 +466,14 @@ SECTION_VALUE_CHARS ([^$\n\r;"'\]\\]|("\\"{ANY_CHAR})|{LITERAL_DOLLAR})
|
||||
RETURN_TOKEN(BOOL_TRUE, "1", 1);
|
||||
}
|
||||
|
||||
<INITIAL,ST_VALUE>("false"|"off"|"no"|"none"|"null"){TABS_AND_SPACES}* { /* FALSE value (when used outside option value/offset this causes parse error!)*/
|
||||
<INITIAL,ST_VALUE>("false"|"off"|"no"|"none"){TABS_AND_SPACES}* { /* FALSE value (when used outside option value/offset this causes parse error!)*/
|
||||
RETURN_TOKEN(BOOL_FALSE, "", 0);
|
||||
}
|
||||
|
||||
<INITIAL,ST_VALUE>("null"){TABS_AND_SPACES}* {
|
||||
RETURN_TOKEN(NULL_NULL, "", 0);
|
||||
}
|
||||
|
||||
<INITIAL>{LABEL} { /* Get option name */
|
||||
/* Eat leading whitespace */
|
||||
EAT_LEADING_WHITESPACE();
|
||||
|
@ -3556,6 +3556,7 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */
|
||||
|
||||
REGISTER_LONG_CONSTANT("INI_SCANNER_NORMAL", ZEND_INI_SCANNER_NORMAL, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("INI_SCANNER_RAW", ZEND_INI_SCANNER_RAW, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("INI_SCANNER_TYPED", ZEND_INI_SCANNER_TYPED, CONST_CS | CONST_PERSISTENT);
|
||||
|
||||
REGISTER_LONG_CONSTANT("PHP_URL_SCHEME", PHP_URL_SCHEME, CONST_CS | CONST_PERSISTENT);
|
||||
REGISTER_LONG_CONSTANT("PHP_URL_HOST", PHP_URL_HOST, CONST_CS | CONST_PERSISTENT);
|
||||
|
@ -0,0 +1,40 @@
|
||||
--TEST--
|
||||
parse_ini_string() typed scanner mode
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$contents = <<<EOS
|
||||
foo = 1
|
||||
bar = 1.3
|
||||
baz = null
|
||||
qux[] = false
|
||||
qux[] = off
|
||||
qux[] = something
|
||||
qux[] = "something else"
|
||||
EOS;
|
||||
|
||||
var_dump(parse_ini_string($contents, false, INI_SCANNER_TYPED));
|
||||
|
||||
?>
|
||||
Done
|
||||
--EXPECTF--
|
||||
array(4) {
|
||||
["foo"]=>
|
||||
int(1)
|
||||
["bar"]=>
|
||||
float(1.3)
|
||||
["baz"]=>
|
||||
NULL
|
||||
["qux"]=>
|
||||
array(4) {
|
||||
[0]=>
|
||||
bool(false)
|
||||
[1]=>
|
||||
bool(false)
|
||||
[2]=>
|
||||
string(9) "something"
|
||||
[3]=>
|
||||
string(14) "something else"
|
||||
}
|
||||
}
|
||||
Done
|
Loading…
Reference in New Issue
Block a user