diff -u php-5.2.5/Zend/zend_API.h php-5.2.5-patched/Zend/zend_API.h --- php-5.2.5/Zend/zend_API.h 2007-04-16 04:09:54.000000000 -0400 +++ php-5.2.5-patched/Zend/zend_API.h 2008-03-07 09:49:20.000000000 -0500 @@ -69,7 +69,7 @@ #define ZEND_ARG_ARRAY_INFO(pass_by_ref, name, allow_null) { #name, sizeof(#name)-1, NULL, 0, 1, allow_null, pass_by_ref, 0, 0 }, #define ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, return_reference, required_num_args) \ zend_arg_info name[] = { \ - { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args }, + { NULL, 0, NULL, 0, 0, 0, pass_rest_by_reference, return_reference, required_num_args, 0, 0, 0, 0 }, #define ZEND_BEGIN_ARG_INFO(name, pass_rest_by_reference) \ ZEND_BEGIN_ARG_INFO_EX(name, pass_rest_by_reference, ZEND_RETURN_VALUE, -1) #define ZEND_END_ARG_INFO() }; diff -u php-5.2.5/Zend/zend_compile.c php-5.2.5-patched/Zend/zend_compile.c --- php-5.2.5/Zend/zend_compile.c 2007-09-20 10:11:31.000000000 -0400 +++ php-5.2.5-patched/Zend/zend_compile.c 2008-03-07 11:08:34.000000000 -0500 @@ -1295,23 +1295,44 @@ cur_arg_info->array_type_hint = 0; cur_arg_info->allow_null = 1; cur_arg_info->pass_by_reference = pass_by_reference; - + cur_arg_info->type_hint = 0; + cur_arg_info->scalar_type_hint = 0; + cur_arg_info->num_type_hint = 0; + cur_arg_info->resource_type_hint = 0; + cur_arg_info->class_name = NULL; + cur_arg_info->class_name_len = 0; + if (class_type->op_type != IS_UNUSED) { - cur_arg_info->allow_null = 0; if (class_type->u.constant.type == IS_STRING) { - cur_arg_info->class_name = class_type->u.constant.value.str.val; - cur_arg_info->class_name_len = class_type->u.constant.value.str.len; - if (op == ZEND_RECV_INIT) { - if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) { - cur_arg_info->allow_null = 1; - } else { - zend_error(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL"); + if (strcmp("scalar", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->scalar_type_hint = 1; + } else if (strcmp("resource", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->resource_type_hint = 1; + } else if (strcmp("num", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->num_type_hint = 1; + } else if (strcmp("int", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->type_hint = IS_LONG; + } else if (strcmp("float", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->type_hint = IS_DOUBLE; + } else if (strcmp("string", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->type_hint = IS_STRING; + } else if (strcmp("bool", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->type_hint = IS_BOOL; + } else if (strcmp("object", class_type->u.constant.value.str.val) == 0) { + cur_arg_info->type_hint = IS_OBJECT; + } else { + cur_arg_info->class_name = class_type->u.constant.value.str.val; + cur_arg_info->class_name_len = class_type->u.constant.value.str.len; + if (op == ZEND_RECV_INIT) { + if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) { + cur_arg_info->allow_null = 1; + } else { + zend_error(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL"); + } } } } else { cur_arg_info->array_type_hint = 1; - cur_arg_info->class_name = NULL; - cur_arg_info->class_name_len = 0; if (op == ZEND_RECV_INIT) { if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) { cur_arg_info->allow_null = 1; @@ -1320,9 +1341,6 @@ } } } - } else { - cur_arg_info->class_name = NULL; - cur_arg_info->class_name_len = 0; } opline->result.u.EA.type |= EXT_TYPE_UNUSED; } @@ -1983,7 +2001,7 @@ if (fe->common.return_reference != proto->common.return_reference) { return 0; } - + for (i=0; i < proto->common.num_args; i++) { if (ZEND_LOG_XOR(fe->common.arg_info[i].class_name, proto->common.arg_info[i].class_name)) { /* Only one has a type hint and the other one doesn't */ @@ -1993,6 +2011,18 @@ && strcmp(fe->common.arg_info[i].class_name, proto->common.arg_info[i].class_name)!=0) { return 0; } + if (fe->common.arg_info[i].scalar_type_hint != proto->common.arg_info[i].scalar_type_hint) { + return 0; + } + if (fe->common.arg_info[i].resource_type_hint != proto->common.arg_info[i].resource_type_hint) { + return 0; + } + if (fe->common.arg_info[i].num_type_hint != proto->common.arg_info[i].num_type_hint) { + return 0; + } + if (fe->common.arg_info[i].type_hint != proto->common.arg_info[i].type_hint) { + return 0; + } if (fe->common.arg_info[i].array_type_hint != proto->common.arg_info[i].array_type_hint) { /* Only one has an array type hint and the other one doesn't */ return 0; diff -u php-5.2.5/Zend/zend_compile.h php-5.2.5-patched/Zend/zend_compile.h --- php-5.2.5/Zend/zend_compile.h 2007-05-18 09:12:04.000000000 -0400 +++ php-5.2.5-patched/Zend/zend_compile.h 2008-03-07 09:57:39.000000000 -0500 @@ -167,6 +167,10 @@ zend_bool pass_by_reference; zend_bool return_reference; int required_num_args; + zend_bool scalar_type_hint; + zend_bool resource_type_hint; + zend_bool num_type_hint; + zend_bool type_hint; } zend_arg_info; typedef struct _zend_compiled_variable { diff -u php-5.2.5/Zend/zend_constants.c php-5.2.5-patched/Zend/zend_constants.c --- php-5.2.5/Zend/zend_constants.c 2007-07-27 12:29:11.000000000 -0400 +++ php-5.2.5-patched/Zend/zend_constants.c 2008-03-07 09:57:58.000000000 -0500 @@ -142,6 +142,14 @@ c.value.value.lval = ZTS_V; c.value.type = IS_BOOL; zend_register_constant(&c TSRMLS_CC); + + c.flags = CONST_PERSISTENT | CONST_CS; + + c.name = zend_strndup(ZEND_STRL("PATCH_SCALAR_TYPE_HINTING")); + c.name_len = sizeof("PATCH_SCALAR_TYPE_HINTING"); + c.value.value.lval = ZTS_V; + c.value.type = IS_BOOL; + zend_register_constant(&c TSRMLS_CC); } } diff -u php-5.2.5/Zend/zend_execute.c php-5.2.5-patched/Zend/zend_execute.c --- php-5.2.5/Zend/zend_execute.c 2007-07-19 11:29:30.000000000 -0400 +++ php-5.2.5-patched/Zend/zend_execute.c 2008-03-07 09:58:56.000000000 -0500 @@ -509,6 +509,34 @@ need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce TSRMLS_CC); return zend_verify_arg_error(zf, arg_num, cur_arg_info, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC); } + } else if (cur_arg_info->scalar_type_hint) { + if (!arg) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be a scalar type", "", "none", "" TSRMLS_CC); + } + if (Z_TYPE_P(arg) != IS_LONG && Z_TYPE_P(arg) != IS_DOUBLE && Z_TYPE_P(arg) != IS_BOOL && Z_TYPE_P(arg) != IS_STRING && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be a scalar type", "", zend_zval_type_name(arg), "" TSRMLS_CC); + } + } else if (cur_arg_info->resource_type_hint) { + if (!arg) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be a resource", "", "none", "" TSRMLS_CC); + } + if (Z_TYPE_P(arg) != IS_RESOURCE && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be a resource", "", zend_zval_type_name(arg), "" TSRMLS_CC); + } + } else if (cur_arg_info->num_type_hint) { + if (!arg) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be a number", "", "none", "" TSRMLS_CC); + } + if (Z_TYPE_P(arg) != IS_RESOURCE && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be a number", "", zend_zval_type_name(arg), "" TSRMLS_CC); + } + } else if (cur_arg_info->type_hint) { + if (!arg) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be of type ", zend_get_type_by_const(cur_arg_info->type_hint), "none", "" TSRMLS_CC); + } + if (Z_TYPE_P(arg) != cur_arg_info->type_hint && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { + return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be of type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "" TSRMLS_CC); + } } else if (cur_arg_info->array_type_hint) { if (!arg) { return zend_verify_arg_error(zf, arg_num, cur_arg_info, "be an array", "", "none", "" TSRMLS_CC);