summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend.h8
-rw-r--r--Zend/zend_API.c90
-rw-r--r--Zend/zend_API.h604
-rw-r--r--Zend/zend_builtin_functions.c73
-rw-r--r--Zend/zend_operators.c4
-rw-r--r--Zend/zend_operators.h2
6 files changed, 780 insertions, 1 deletions
diff --git a/Zend/zend.h b/Zend/zend.h
index 2f1f239732..1021829c3b 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -179,6 +179,14 @@ char *alloca ();
# define ZEND_ATTRIBUTE_DEPRECATED
#endif
+#if defined(__GNUC__) && ZEND_GCC_VERSION >= 4003
+# define ZEND_ATTRIBUTE_UNUSED __attribute__((unused))
+# define ZEND_ATTRIBUTE_UNUSED_LABEL __attribute__((cold, unused));
+#else
+# define ZEND_ATTRIBUTE_UNUSED
+# define ZEND_ATTRIBUTE_UNUSED_LABEL
+#endif
+
#if defined(__GNUC__) && ZEND_GCC_VERSION >= 3004 && defined(__i386__)
# define ZEND_FASTCALL __attribute__((fastcall))
#elif defined(_MSC_VER) && defined(_M_IX86)
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 0edff3e1a7..5770b9b030 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -262,7 +262,7 @@ static int parse_arg_object_to_string(zval *arg, char **p, int *pl, int type TSR
}
/* }}} */
-static int parse_arg_object_to_str(zval *arg, zend_string **str, int type TSRMLS_DC) /* {{{ */
+ZEND_API int parse_arg_object_to_str(zval *arg, zend_string **str, int type TSRMLS_DC) /* {{{ */
{
if (Z_OBJ_HANDLER_P(arg, cast_object)) {
zval obj;
@@ -300,6 +300,94 @@ static int parse_arg_object_to_str(zval *arg, zend_string **str, int type TSRMLS
}
/* }}} */
+#ifdef FAST_ZPP
+ZEND_API void zend_wrong_paramers_count_error(int num_args, int min_num_args, int max_num_args TSRMLS_DC) /* {{{ */
+{
+ zend_function *active_function = EG(current_execute_data)->func;
+ const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : "";
+
+ zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
+ class_name, \
+ class_name[0] ? "::" : "", \
+ active_function->common.function_name->val,
+ min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
+ num_args < min_num_args ? min_num_args : max_num_args,
+ (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
+ num_args);
+}
+/* }}} */
+
+ZEND_API void zend_wrong_paramer_type_error(int num, zend_expected_type expected_type, zval *arg TSRMLS_DC) /* {{{ */
+{
+ const char *space;
+ const char *class_name = get_active_class_name(&space TSRMLS_CC);
+ static const char * const expected_error[] = {
+ Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR)
+ NULL
+ };
+
+ zend_error(E_WARNING, "%s%s%s() expects parameter %d to be %s, %s given",
+ class_name, space, get_active_function_name(TSRMLS_C), num, expected_error[expected_type], zend_zval_type_name(arg));
+}
+/* }}} */
+
+ZEND_API void zend_wrong_paramer_class_error(int num, char *name, zval *arg TSRMLS_DC) /* {{{ */
+{
+ const char *space;
+ const char *class_name = get_active_class_name(&space TSRMLS_CC);
+
+ zend_error(E_WARNING, "%s%s%s() expects parameter %d to be %s, %s given",
+ class_name, space, get_active_function_name(TSRMLS_C), num, name, zend_zval_type_name(arg));
+}
+/* }}} */
+
+ZEND_API void zend_wrong_callback_error(int severity, int num, char *error TSRMLS_DC) /* {{{ */
+{
+ const char *space;
+ const char *class_name = get_active_class_name(&space TSRMLS_CC);
+
+ zend_error(severity, "%s%s%s() expects parameter %d to be a valid callback, %s",
+ class_name, space, get_active_function_name(TSRMLS_C), num, error);
+ efree(error);
+}
+/* }}} */
+
+ZEND_API int _z_param_class(zval *arg, zend_class_entry **pce, int num, int check_null TSRMLS_CC) /* {{{ */
+{
+ zend_class_entry *ce_base = *pce;
+
+ if (check_null && Z_TYPE_P(arg) == IS_NULL) {
+ *pce = NULL;
+ return 1;
+ }
+ convert_to_string_ex(arg);
+ *pce = zend_lookup_class(Z_STR_P(arg) TSRMLS_CC);
+ if (ce_base) {
+ if ((!*pce || !instanceof_function(*pce, ce_base TSRMLS_CC))) {
+ const char *space;
+ const char *class_name = get_active_class_name(&space TSRMLS_CC);
+
+ zend_error(E_WARNING, "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given",
+ class_name, space, get_active_function_name(TSRMLS_C), num,
+ ce_base->name->val, Z_STRVAL_P(arg));
+ *pce = NULL;
+ return 0;
+ }
+ }
+ if (!*pce) {
+ const char *space;
+ const char *class_name = get_active_class_name(&space TSRMLS_CC);
+
+ zend_error(E_WARNING, "%s%s%s() expects parameter %d to be a valid class name, '%s' given",
+ class_name, space, get_active_function_name(TSRMLS_C), num,
+ Z_STRVAL_P(arg));
+ return 0;
+ }
+ return 1;
+}
+/* }}} */
+#endif
+
static const char *zend_parse_arg_impl(int arg_num, zval *arg, va_list *va, const char **spec, char **error, int *severity TSRMLS_DC) /* {{{ */
{
const char *spec_walk = *spec;
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index beca63c50b..9278224c72 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -680,6 +680,610 @@ END_EXTERN_C()
#define ZEND_GINIT_FUNCTION ZEND_MODULE_GLOBALS_CTOR_D
#define ZEND_GSHUTDOWN_FUNCTION ZEND_MODULE_GLOBALS_DTOR_D
+/* Fast parameter parsing API */
+
+/* TODO: This API is experemental. It may be changed or removed ???
+ * It should be used only for really often used functions.
+ * (Keep the original parsing code and wrap usage with #ifndef FAST_ZPP)
+ */
+#define FAST_ZPP 1
+
+#ifdef FAST_ZPP
+
+#define Z_EXPECTED_TYPES(_) \
+ _(Z_EXPECTED_LONG, "long") \
+ _(Z_EXPECTED_BOOL, "boolean") \
+ _(Z_EXPECTED_STRING, "string") \
+ _(Z_EXPECTED_ARRAY, "array") \
+ _(Z_EXPECTED_FUNC, "valid callback") \
+ _(Z_EXPECTED_RESOURCE, "resource") \
+ _(Z_EXPECTED_PATH, "a valid path") \
+ _(Z_EXPECTED_OBJECT, "object") \
+ _(Z_EXPECTED_DOUBLE, "double")
+
+#define Z_EXPECTED_TYPE_ENUM(id, str) id,
+#define Z_EXPECTED_TYPE_STR(id, str) str,
+
+typedef enum _zend_expected_type {
+ Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_ENUM)
+ Z_EXPECTED_LAST
+} zend_expected_type;
+
+ZEND_API int parse_arg_object_to_str(zval *arg, zend_string **str, int type TSRMLS_DC);
+ZEND_API void zend_wrong_paramers_count_error(int num_args, int min_num_args, int max_num_args TSRMLS_DC);
+ZEND_API void zend_wrong_paramer_type_error(int num, zend_expected_type expected_type, zval *arg TSRMLS_DC);
+ZEND_API void zend_wrong_paramer_class_error(int num, char *name, zval *arg TSRMLS_DC);
+ZEND_API void zend_wrong_callback_error(int severity, int num, char *error TSRMLS_DC);
+ZEND_API int _z_param_class(zval *arg, zend_class_entry **pce, int num, int check_null TSRMLS_CC);
+
+#define ZEND_PARSE_PARAMETERS_START_EX(flags, min_num_args, max_num_args) do { \
+ const int _flags = (flags); \
+ int _min_num_args = (min_num_args); \
+ int _max_num_args = (max_num_args); \
+ int _num_args = EG(current_execute_data)->num_args; \
+ int _i; \
+ zval *_real_arg, *_arg; \
+ zend_expected_type _expected_type; \
+ char *_error; \
+ zend_bool _dummy; \
+ ((void)_i); \
+ ((void)_real_arg); \
+ ((void)_arg); \
+ ((void)_expected_type); \
+ ((void)_error); \
+ ((void)_dummy); \
+ if (UNEXPECTED(_num_args < _min_num_args) || \
+ (UNEXPECTED(_num_args > _max_num_args) && \
+ EXPECTED(_max_num_args >= 0))) { \
+ if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
+ zend_wrong_paramers_count_error(_num_args, _min_num_args, _max_num_args); \
+ } \
+ goto zend_parse_params_failure; \
+ } \
+ _i = 0; \
+ _real_arg = ZEND_CALL_ARG(EG(current_execute_data), 0);
+
+#define ZEND_PARSE_PARAMETERS_START(min_num_args, max_num_args) \
+ ZEND_PARSE_PARAMETERS_START_EX(0, min_num_args, max_num_args)
+
+#define ZEND_PARSE_PARAMETERS_END_EX(failure) \
+ if (0) { \
+zend_parse_params_wrong_callback: ZEND_ATTRIBUTE_UNUSED_LABEL \
+ if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
+ zend_wrong_callback_error(E_WARNING, _i, _error TSRMLS_DC); \
+ } \
+ goto zend_parse_params_failure; \
+zend_parse_params_wrong_class: ZEND_ATTRIBUTE_UNUSED_LABEL \
+ if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
+ zend_wrong_paramer_class_error(_i, _error, _arg TSRMLS_DC); \
+ } \
+ goto zend_parse_params_failure; \
+zend_parse_params_wrong_arg: ZEND_ATTRIBUTE_UNUSED_LABEL \
+ if (!(_flags & ZEND_PARSE_PARAMS_QUIET)) { \
+ zend_wrong_paramer_type_error(_i, _expected_type, _arg TSRMLS_DC); \
+ } \
+zend_parse_params_failure: ZEND_ATTRIBUTE_UNUSED_LABEL \
+ failure; \
+ } \
+ } while (0)
+
+#define ZEND_PARSE_PARAMETERS_END() \
+ ZEND_PARSE_PARAMETERS_END_EX(return)
+
+#define Z_PARAM_PROLOGUE(separate) \
+ if (UNEXPECTED(++_i >_num_args)) break; \
+ _real_arg++; \
+ _arg = _real_arg; \
+ ZVAL_DEREF(_arg); \
+ if (separate) { \
+ SEPARATE_ZVAL_NOREF(_arg); \
+ }
+
+/* old "|" */
+#define Z_PARAM_OPTIONAL
+
+/* old "a" */
+#define Z_PARAM_ARRAY_EX(dest, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_array(_arg, &dest, check_null, 0)) { \
+ _expected_type = Z_EXPECTED_ARRAY; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_ARRAY(dest) \
+ Z_PARAM_ARRAY_EX(dest, 0, 0)
+
+/* old "A" */
+#define Z_PARAM_ARRAY_OR_OBJECT_EX(dest, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_array(_arg, &dest, check_null, 1)) { \
+ _expected_type = Z_EXPECTED_ARRAY; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_ARRAY_OR_OBJECT(dest, check_null, separate) \
+ Z_PARAM_ARRAY_OR_OBJECT_EX(dest, 0, 0)
+
+/* old "b" */
+#define Z_PARAM_BOOL_EX(dest, is_null, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_bool(_arg, &dest, &is_null, check_null)) { \
+ _expected_type = Z_EXPECTED_BOOL; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_BOOL(dest) \
+ Z_PARAM_BOOL_EX(dest, _dummy, 0, 0)
+
+/* old "C" */
+#define Z_PARAM_CLASS_EX(dest, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_class(_arg, &dest, _i, check_null TSRMLS_CC)) { \
+ goto zend_parse_params_failure; \
+ } \
+ } while (0);
+
+#define Z_PARAM_CLASS(dest) \
+ Z_PARAM_CLASS_EX(dest, 0, 0)
+
+/* old "d" */
+#define Z_PARAM_DOUBLE_EX(dest, is_null, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_double(_arg, &dest, &is_null, check_null)) { \
+ _expected_type = Z_EXPECTED_DOUBLE; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_DOUBLE(dest) \
+ Z_PARAM_DOUBLE_EX(dest, _dummy, 0, 0)
+
+/* old "f" */
+#define Z_PARAM_FUNC_EX(dest_fci, dest_fcc, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_func(_arg, &dest_fci, &dest_fcc, check_null, &_error)) { \
+ if (!_error) { \
+ _expected_type = Z_EXPECTED_FUNC; \
+ goto zend_parse_params_wrong_arg; \
+ } else { \
+ goto zend_parse_params_wrong_callback; \
+ } \
+ } else if (_error) { \
+ zend_wrong_callback_error(E_STRICT, _i, _error TSRMLS_DC); \
+ } \
+ } while (0);
+
+#define Z_PARAM_FUNC(dest_fci, dest_fcc) \
+ Z_PARAM_FUNC_EX(dest_fci, dest_fcc, 0, 0)
+
+/* old "h" */
+#define Z_PARAM_ARRAY_HT_EX(dest, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_array_ht(_arg, &dest, check_null, 0)) { \
+ _expected_type = Z_EXPECTED_ARRAY; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_ARRAY_HT(dest) \
+ Z_PARAM_ARRAY_HT_EX(dest, 0, 0)
+
+/* old "H" */
+#define Z_PARAM_ARRAY_OR_OBJECT_HT_EX(dest, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_array_ht(_arg, &dest, check_null, 1)) { \
+ _expected_type = Z_EXPECTED_ARRAY; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_ARRAY_OR_OBJECT_HT(dest) \
+ Z_PARAM_ARRAY_OR_OBJECT_HT_EX(dest, 0, 0)
+
+/* old "l" */
+#define Z_PARAM_LONG_EX(dest, is_null, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_long(_arg, &dest, &is_null, check_null, 0)) { \
+ _expected_type = Z_EXPECTED_LONG; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_LONG(dest) \
+ Z_PARAM_LONG_EX(dest, _dummy, 0, 0)
+
+/* old "L" */
+#define Z_PARAM_STRICT_LONG_EX(dest, is_null, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_long(_arg, &dest, &is_null, check_null, 1)) { \
+ _expected_type = Z_EXPECTED_LONG; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_STRICT_LONG(dest) \
+ Z_PARAM_STRICT_LONG_EX(dest, _dummy, 0, 0)
+
+/* old "o" */
+#define Z_PARAM_OBJECT_EX(dest, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_object(_arg, &dest, NULL, check_null)) { \
+ _expected_type = Z_EXPECTED_OBJECT; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_OBJECT(dest) \
+ Z_PARAM_OBJECT_EX(dest, 0, 0)
+
+/* old "O" */
+#define Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_object(_arg, &dest, _ce, check_null)) { \
+ if (_ce) { \
+ _error = (_ce)->name->val; \
+ goto zend_parse_params_wrong_class; \
+ } else { \
+ _expected_type = Z_EXPECTED_OBJECT; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } \
+ } while (0);
+
+#define Z_PARAM_OBJECT_OF_CLASS(dest, _ce) \
+ Z_PARAM_OBJECT_OF_CLASS_EX(dest, _ce, 0, 0)
+
+/* old "p" */
+#define Z_PARAM_PATH_EX(dest, dest_len, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_path(_arg, &dest, &dest_len, check_null)) { \
+ _expected_type = Z_EXPECTED_PATH; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_PATH(dest, dest_len) \
+ Z_PARAM_PATH_EX(dest, dest_len, 0, 0)
+
+/* old "P" */
+#define Z_PARAM_PATH_STR_EX(dest, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_path_str(_arg, &dest, check_null)) { \
+ _expected_type = Z_EXPECTED_PATH; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_PATH_STR(dest) \
+ Z_PARAM_PATH_STR_EX(dest, 0, 0)
+
+/* old "r" */
+#define Z_PARAM_RESOURCE_EX(dest, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_resource(_arg, &dest, check_null)) { \
+ _expected_type = Z_EXPECTED_RESOURCE; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_RESOURCE(dest) \
+ Z_PARAM_RESOURCE_EX(dest, 0, 0)
+
+/* old "s" */
+#define Z_PARAM_STRING_EX(dest, dest_len, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_string(_arg, &dest, &dest_len, check_null)) { \
+ _expected_type = Z_EXPECTED_STRING; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_STRING(dest, dest_len) \
+ Z_PARAM_STRING_EX(dest, dest_len, 0, 0)
+
+/* old "S" */
+#define Z_PARAM_STR_EX(dest, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ if (!_z_param_str(_arg, &dest, check_null)) { \
+ _expected_type = Z_EXPECTED_STRING; \
+ goto zend_parse_params_wrong_arg; \
+ } \
+ } while (0);
+
+#define Z_PARAM_STR(dest) \
+ Z_PARAM_STR_EX(dest, 0, 0)
+
+/* old "z" */
+#define Z_PARAM_ZVAL_EX(dest, check_null, separate) do { \
+ if (separate) { \
+ Z_PARAM_PROLOGUE(separate); \
+ _z_param_zval_deref(_arg, &dest, check_null); \
+ } else { \
+ if (UNEXPECTED(++_i >_num_args)) break; \
+ _real_arg++; \
+ _z_param_zval(_real_arg, &dest, check_null); \
+ } \
+ } while (0);
+
+#define Z_PARAM_ZVAL(dest) \
+ Z_PARAM_ZVAL_EX(dest, 0, 0)
+
+/* old "z" (with dereference) */
+#define Z_PARAM_ZVAL_DEREF_EX(dest, check_null, separate) do { \
+ Z_PARAM_PROLOGUE(separate); \
+ _z_param_zval_deref(_arg, &dest, check_null); \
+ } while (0);
+
+#define Z_PARAM_ZVAL_DEREF(dest) \
+ Z_PARAM_ZVAL_DEREF_EX(dest, 0, 0)
+
+/* old "+" and "*" */
+#define Z_PARAM_VARIADIC_EX(spec, dest, dest_num, post_varargs) do { \
+ int _num_varargs = _num_args - _i - (post_varargs); \
+ if (_num_varargs > 0) { \
+ dest = _real_arg + 1; \
+ dest_num = _num_varargs; \
+ _i += _num_varargs; \
+ _real_arg += _num_varargs; \
+ } else { \
+ dest = NULL; \
+ dest_num = 0; \
+ } \
+ } while (0);
+
+#define Z_PARAM_VARIADIC(spec, dest, dest_num) \
+ Z_PARAM_VARIADIC_EX(spec, dest, dest_num, 0)
+
+/* Private part of new parameter parsing API */
+
+static zend_always_inline int _z_param_bool(zval *arg, zend_bool *dest, zend_bool *is_null, int check_null)
+{
+ if (check_null) {
+ *is_null = 0;
+ }
+ if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
+ *dest = 1;
+ } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
+ if (check_null) {
+ *is_null = (Z_TYPE_P(arg) == IS_NULL);
+ }
+ *dest = 0;
+ } else if (EXPECTED(Z_TYPE_P(arg) <= IS_STRING)) {
+ *dest = zend_is_true(arg);
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+static zend_always_inline int _z_param_long(zval *arg, long *dest, zend_bool *is_null, int check_null, int strict)
+{
+ if (check_null) {
+ *is_null = 0;
+ }
+ if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
+ if (strict && UNEXPECTED(Z_DVAL_P(arg) > LONG_MAX)) {
+ *dest = LONG_MAX;
+ } else if (strict && UNEXPECTED(Z_DVAL_P(arg) < LONG_MIN)) {
+ *dest = LONG_MIN;
+ } else {
+ *dest = Z_LVAL_P(arg);
+ }
+ } else if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
+ *dest = zend_dval_to_lval(Z_DVAL_P(arg));
+ } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
+ double d;
+ int type;
+
+ if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), dest, &d)) != IS_LONG)) {
+ if (EXPECTED(type != 0)) {
+ if (strict && UNEXPECTED(d > LONG_MAX)) {
+ *dest = LONG_MAX;
+ } else if (strict && UNEXPECTED(d < LONG_MIN)) {
+ *dest = LONG_MIN;
+ } else {
+ *dest = zend_dval_to_lval(d);
+ }
+ } else {
+ return 0;
+ }
+ }
+ } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
+ if (check_null) {
+ *is_null = (Z_TYPE_P(arg) == IS_NULL);
+ }
+ *dest = 0;
+ } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
+ *dest = 1;
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+static zend_always_inline int _z_param_double(zval *arg, double *dest, zend_bool *is_null, int check_null)
+{
+ if (check_null) {
+ *is_null = 0;
+ }
+ if (EXPECTED(Z_TYPE_P(arg) == IS_DOUBLE)) {
+ *dest = Z_DVAL_P(arg);
+ } else if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) {
+ *dest = (double)Z_LVAL_P(arg);
+ } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
+ long l;
+ int type;
+
+ if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, dest)) != IS_DOUBLE)) {
+ if (EXPECTED(type != 0)) {
+ *dest = (double)(l);
+ } else {
+ return 0;
+ }
+ }
+ } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) {
+ if (check_null) {
+ *is_null = (Z_TYPE_P(arg) == IS_NULL);
+ }
+ *dest = 0.0;
+ } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) {
+ *dest = 1.0;
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+static zend_always_inline int _z_param_str(zval *arg, zend_string **dest, int check_null)
+{
+ if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
+ *dest = Z_STR_P(arg);
+ } else if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) {
+ if (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
+ *dest = NULL;
+ } else {
+ if (Z_COPYABLE_P(arg) && Z_REFCOUNT_P(arg) > 1) {
+ Z_DELREF_P(arg);
+ zval_copy_ctor_func(arg);
+ }
+ convert_to_string(arg);
+ *dest = Z_STR_P(arg);
+ }
+ } else if (UNEXPECTED(Z_TYPE_P(arg) != IS_OBJECT) ||
+ UNEXPECTED(parse_arg_object_to_str(arg, dest, IS_STRING TSRMLS_CC) != SUCCESS)) {
+ return 0;
+ }
+ return 1;
+}
+
+static zend_always_inline int _z_param_string(zval *arg, char **dest, int *dest_len, int check_null)
+{
+ zend_string *str;
+
+ if (!_z_param_str(arg, &str, check_null)) {
+ return 0;
+ }
+ if (check_null && UNEXPECTED(!str)) {
+ *dest = NULL;
+ *dest_len = 0;
+ } else {
+ *dest = str->val;
+ *dest_len = str->len;
+ }
+ return 1;
+}
+
+static zend_always_inline int _z_param_path_str(zval *arg, zend_string **dest, int check_null)
+{
+ if (!_z_param_str(arg, dest, check_null) ||
+ (check_null && UNEXPECTED(!(*dest)->val)) ||
+ UNEXPECTED(CHECK_NULL_PATH((*dest)->val, (*dest)->len))) {
+ return 0;
+ }
+ return 1;
+}
+
+static zend_always_inline int _z_param_path(zval *arg, char **dest, int *dest_len, int check_null)
+{
+ zend_string *str;
+
+ if (!_z_param_path_str(arg, &str, check_null)) {
+ return 0;
+ }
+ if (check_null && UNEXPECTED(!str)) {
+ *dest = NULL;
+ *dest_len = 0;
+ } else {
+ *dest = str->val;
+ *dest_len = str->len;
+ }
+ return 1;
+}
+
+static zend_always_inline int _z_param_array(zval *arg, zval **dest, int check_null, int or_object)
+{
+ if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY) ||
+ (or_object && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT))) {
+ *dest = arg;
+ } else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
+ *dest = NULL;
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+static zend_always_inline int _z_param_array_ht(zval *arg, HashTable **dest, int check_null, int or_object)
+{
+ if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY)) {
+ *dest = Z_ARRVAL_P(arg);
+ } else if (or_object && EXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) {
+ *dest = Z_OBJ_HT_P(arg)->get_properties(arg TSRMLS_CC);
+ } else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
+ *dest = NULL;
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+static zend_always_inline int _z_param_object(zval *arg, zval **dest, zend_class_entry *ce, int check_null)
+{
+ if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT) &&
+ (!ce || EXPECTED(instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC) != 0))) {
+ *dest = arg;
+ } else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
+ *dest = NULL;
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+static zend_always_inline int _z_param_resource(zval *arg, zval **dest, int check_null)
+{
+ if (EXPECTED(Z_TYPE_P(arg) == IS_RESOURCE)) {
+ *dest = arg;
+ } else if (check_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
+ *dest = NULL;
+ } else {
+ return 0;
+ }
+ return 1;
+}
+
+static zend_always_inline int _z_param_func(zval *arg, zend_fcall_info *dest_fci, zend_fcall_info_cache *dest_fcc, int check_null, char **error)
+{
+ if (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
+ dest_fci->size = 0;
+ dest_fcc->initialized = 0;
+ *error = NULL;
+ } else if (UNEXPECTED(zend_fcall_info_init(arg, 0, dest_fci, dest_fcc, NULL, error TSRMLS_CC) != SUCCESS)) {
+ return 0;
+ }
+ return 1;
+}
+
+static zend_always_inline void _z_param_zval(zval *arg, zval **dest, int check_null)
+{
+ *dest = (check_null &&
+ (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) ||
+ (UNEXPECTED(Z_ISREF_P(arg)) &&
+ UNEXPECTED(Z_TYPE_P(Z_REFVAL_P(arg)) == IS_NULL)))) ? NULL : arg;
+}
+
+static zend_always_inline void _z_param_zval_deref(zval *arg, zval **dest, int check_null)
+{
+ *dest = (check_null && UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) ? NULL : arg;
+}
+
+#endif /* FAST_ZPP */
+
+/* End of new parameter parsing API */
+
END_EXTERN_C()
#endif /* ZEND_API_H */
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 51265ecb40..1e29ea4db1 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -518,9 +518,15 @@ ZEND_FUNCTION(strlen)
{
zend_string *s;
+#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &s) == FAILURE) {
return;
}
+#else
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_STR(s)
+ ZEND_PARSE_PARAMETERS_END();
+#endif
RETVAL_LONG(s->len);
}
@@ -697,9 +703,18 @@ ZEND_FUNCTION(define)
int case_sensitive = CONST_CS;
zend_constant c;
+#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Sz|b", &name, &val, &non_cs) == FAILURE) {
return;
}
+#else
+ ZEND_PARSE_PARAMETERS_START(2, 3)
+ Z_PARAM_STR(name)
+ Z_PARAM_ZVAL(val)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_BOOL(non_cs)
+ ZEND_PARSE_PARAMETERS_END();
+#endif
if(non_cs) {
case_sensitive = 0;
@@ -764,9 +779,15 @@ ZEND_FUNCTION(defined)
{
zend_string *name;
+#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &name) == FAILURE) {
return;
}
+#else
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_STR(name)
+ ZEND_PARSE_PARAMETERS_END();
+#endif
if (zend_get_constant_ex(name, NULL, ZEND_FETCH_CLASS_SILENT TSRMLS_CC)) {
RETURN_TRUE;
@@ -869,9 +890,18 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
zend_bool allow_string = only_subclass;
zend_bool retval;
+#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zS|b", &obj, &class_name, &allow_string) == FAILURE) {
return;
}
+#else
+ ZEND_PARSE_PARAMETERS_START(2, 3)
+ Z_PARAM_ZVAL(obj)
+ Z_PARAM_STR(class_name)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_BOOL(allow_string)
+ ZEND_PARSE_PARAMETERS_END();
+#endif
/*
* allow_string - is_a default is no, is_subclass_of is yes.
* if it's allowed, then the autoloader will be called if the class does not exist.
@@ -1007,9 +1037,15 @@ ZEND_FUNCTION(get_object_vars)
uint prop_len;
zend_object *zobj;
+#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &obj) == FAILURE) {
return;
}
+#else
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_OBJECT(obj)
+ ZEND_PARSE_PARAMETERS_END();
+#endif
if (Z_OBJ_HT_P(obj)->get_properties == NULL) {
RETURN_FALSE;
@@ -1124,9 +1160,16 @@ ZEND_FUNCTION(method_exists)
zend_string *lcname;
zend_class_entry * ce;
+#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zS", &klass, &method_name) == FAILURE) {
return;
}
+#else
+ ZEND_PARSE_PARAMETERS_START(2, 2)
+ Z_PARAM_ZVAL(klass)
+ Z_PARAM_STR(method_name)
+ ZEND_PARSE_PARAMETERS_END();
+#endif
if (Z_TYPE_P(klass) == IS_OBJECT) {
ce = Z_OBJCE_P(klass);
} else if (Z_TYPE_P(klass) == IS_STRING) {
@@ -1227,9 +1270,17 @@ ZEND_FUNCTION(class_exists)
zend_class_entry *ce;
zend_bool autoload = 1;
+#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S|b", &class_name, &autoload) == FAILURE) {
return;
}
+#else
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_STR(class_name)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_BOOL(autoload)
+ ZEND_PARSE_PARAMETERS_END();
+#endif
if (!autoload) {
if (class_name->val[0] == '\\') {
@@ -1262,9 +1313,17 @@ ZEND_FUNCTION(interface_exists)
zend_class_entry *ce;
zend_bool autoload = 1;
+#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S|b", &iface_name, &autoload) == FAILURE) {
return;
}
+#else
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_STR(iface_name)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_BOOL(autoload)
+ ZEND_PARSE_PARAMETERS_END();
+#endif
if (!autoload) {
if (iface_name->val[0] == '\\') {
@@ -1297,9 +1356,17 @@ ZEND_FUNCTION(trait_exists)
zend_class_entry *ce;
zend_bool autoload = 1;
+#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S|b", &trait_name, &autoload) == FAILURE) {
return;
}
+#else
+ ZEND_PARSE_PARAMETERS_START(1, 2)
+ Z_PARAM_STR(trait_name)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_BOOL(autoload)
+ ZEND_PARSE_PARAMETERS_END();
+#endif
if (!autoload) {
if (trait_name->val[0] == '\\') {
@@ -1334,9 +1401,15 @@ ZEND_FUNCTION(function_exists)
zend_function *func;
zend_string *lcname;
+#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
return;
}
+#else
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_STRING(name, name_len)
+ ZEND_PARSE_PARAMETERS_END();
+#endif
if (name[0] == '\\') {
/* Ignore leading "\" */
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 76c732732e..dc2756fe09 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -2561,6 +2561,10 @@ ZEND_API zend_string *zend_long_to_str(long num) /* {{{ */
}
/* }}} */
+ZEND_API zend_uchar is_numeric_str_function(const zend_string *str, long *lval, double *dval) {
+ return is_numeric_string_ex(str->val, str->len, lval, dval, -1, NULL);
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index b952b9889e..1ab9518b9a 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -270,6 +270,8 @@ static inline zend_uchar is_numeric_string(const char *str, int length, long *lv
return is_numeric_string_ex(str, length, lval, dval, allow_errors, NULL);
}
+ZEND_API zend_uchar is_numeric_str_function(const zend_string *str, long *lval, double *dval);
+
static inline const char *
zend_memnstr(const char *haystack, const char *needle, int needle_len, char *end)
{