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
This commit is contained in:
Tjerk Meesters 2014-09-01 21:22:28 +08:00
parent d7368c2531
commit 5270ee1aef
6 changed files with 4890 additions and 4671 deletions

View File

@ -283,7 +283,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;
};

View File

@ -265,6 +265,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 '|' '&' '^'
@ -291,7 +292,7 @@ statement:
#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));
zval_internal_dtor(&$3);
}
| TC_OFFSET option_offset ']' '=' string_or_value {
#if DEBUG_CFG_PARSER
@ -300,7 +301,7 @@ statement:
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));
zval_internal_dtor(&$5);
}
| 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
@ -315,6 +316,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

View File

@ -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);

View File

@ -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"
@ -137,9 +138,55 @@ ZEND_API zend_ini_scanner_globals ini_scanner_globals;
Z_TYPE_P(retval) = IS_STRING; \
}
#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)
@ -172,7 +219,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;
}
@ -422,10 +469,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();

View File

@ -3561,6 +3561,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);