summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/Makefile.am2
-rw-r--r--Zend/Zend.m415
-rw-r--r--Zend/flex.skl12
-rw-r--r--Zend/zend.c920
-rw-r--r--Zend/zend.h49
-rw-r--r--Zend/zend_API.c691
-rw-r--r--Zend/zend_API.h109
-rw-r--r--Zend/zend_alloc.c51
-rw-r--r--Zend/zend_alloc.h15
-rw-r--r--Zend/zend_builtin_functions.c241
-rw-r--r--Zend/zend_compile.c623
-rw-r--r--Zend/zend_compile.h19
-rw-r--r--Zend/zend_constants.c64
-rw-r--r--Zend/zend_constants.h1
-rw-r--r--Zend/zend_exceptions.c28
-rw-r--r--Zend/zend_exceptions.h2
-rw-r--r--Zend/zend_execute.c212
-rw-r--r--Zend/zend_execute.h17
-rw-r--r--Zend/zend_execute_API.c241
-rw-r--r--Zend/zend_globals.h71
-rw-r--r--Zend/zend_globals_macros.h11
-rw-r--r--Zend/zend_hash.c659
-rw-r--r--Zend/zend_hash.h120
-rw-r--r--Zend/zend_highlight.c21
-rw-r--r--Zend/zend_ini.c3
-rw-r--r--Zend/zend_ini_scanner.l4
-rwxr-xr-xZend/zend_interfaces.c34
-rwxr-xr-xZend/zend_interfaces.h2
-rw-r--r--Zend/zend_language_parser.y29
-rw-r--r--Zend/zend_language_scanner.h20
-rw-r--r--Zend/zend_language_scanner.l1568
-rw-r--r--Zend/zend_multibyte.c18
-rw-r--r--Zend/zend_object_handlers.c148
-rw-r--r--Zend/zend_objects.c12
-rw-r--r--Zend/zend_objects_API.c2
-rw-r--r--Zend/zend_opcode.c5
-rw-r--r--Zend/zend_operators.c621
-rw-r--r--Zend/zend_operators.h169
-rw-r--r--Zend/zend_reflection_api.c294
-rw-r--r--Zend/zend_reflection_api.h2
-rw-r--r--Zend/zend_strtod.c22
-rw-r--r--Zend/zend_strtol.c122
-rw-r--r--Zend/zend_unicode.c597
-rw-r--r--Zend/zend_unicode.h90
-rw-r--r--Zend/zend_variables.c39
-rw-r--r--Zend/zend_vm_def.h350
-rw-r--r--Zend/zend_vm_execute.h2007
-rw-r--r--Zend/zend_vm_gen.php4
-rw-r--r--Zend/zend_vm_opcodes.h1
-rw-r--r--ext/reflection/php_reflection.c294
-rw-r--r--ext/reflection/php_reflection.h2
51 files changed, 8276 insertions, 2377 deletions
diff --git a/Zend/Makefile.am b/Zend/Makefile.am
index 42ae4d5424..93229c280d 100644
--- a/Zend/Makefile.am
+++ b/Zend/Makefile.am
@@ -17,7 +17,7 @@ libZend_la_SOURCES=\
zend_objects_API.c zend_ts_hash.c zend_stream.c zend_mm.c \
zend_default_classes.c zend_reflection_api.c \
zend_iterators.c zend_interfaces.c zend_exceptions.c \
- zend_strtod.c zend_multibyte.c
+ zend_strtod.c zend_multibyte.c zend_strtod.c zend_strtol.c
libZend_la_LDFLAGS =
libZend_la_LIBADD = @ZEND_EXTRA_LIBS@
diff --git a/Zend/Zend.m4 b/Zend/Zend.m4
index b1d4995988..ea3bf18ee6 100644
--- a/Zend/Zend.m4
+++ b/Zend/Zend.m4
@@ -160,12 +160,15 @@ AC_ARG_ENABLE(memory-limit,
ZEND_MEMORY_LIMIT=no
])
-AC_ARG_ENABLE(zend-multibyte,
-[ --enable-zend-multibyte Compile with zend multibyte support], [
- ZEND_MULTIBYTE=$enableval
-],[
- ZEND_MULTIBYTE=no
-])
+dnl AC_ARG_ENABLE(zend-multibyte,
+dnl [ --enable-zend-multibyte Compile with zend multibyte support], [
+dnl ZEND_MULTIBYTE=$enableval
+dnl ],[
+dnl ZEND_MULTIBYTE=no
+dnl ])
+
+dnl Unicode PHP doesn't need ZEND_MULTIBYTE
+ZEND_MULTIBYTE=no
AC_MSG_CHECKING([virtual machine dispatch method])
AC_MSG_RESULT($PHP_ZEND_VM)
diff --git a/Zend/flex.skl b/Zend/flex.skl
index 9a7c5cf873..060a34bbee 100644
--- a/Zend/flex.skl
+++ b/Zend/flex.skl
@@ -440,18 +440,6 @@ YY_MALLOC_DECL
#define ECHO /* There is no output */
#endif
-#ifdef ZEND_MULTIBYTE
-# define YY_INPUT(buf, result, max_size) \
- if ( ((result = zend_multibyte_yyinput(yyin, buf, max_size TSRMLS_CC)) == 0) \
- && zend_stream_ferror( yyin TSRMLS_CC) ) \
- YY_FATAL_ERROR( "input in flex scanner failed" );
-#else
-# define YY_INPUT(buf, result, max_size) \
- if ( ((result = zend_stream_read(yyin, buf, max_size TSRMLS_CC)) == 0) \
- && zend_stream_ferror( yyin TSRMLS_CC) ) \
- YY_FATAL_ERROR( "input in flex scanner failed" );
-#endif
-
#ifndef ECHO
%- Standard (non-C++) definition
/* This used to be an fputs(), but since the string might contain NUL's,
diff --git a/Zend/zend.c b/Zend/zend.c
index 52ee10b419..4604ace376 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -28,17 +28,9 @@
#include "zend_exceptions.h"
#include "zend_builtin_functions.h"
#include "zend_ini.h"
-
-#ifdef ZTS
-# define GLOBAL_FUNCTION_TABLE global_function_table
-# define GLOBAL_CLASS_TABLE global_class_table
-# define GLOBAL_CONSTANTS_TABLE global_constants_table
-# define GLOBAL_AUTO_GLOBALS_TABLE global_auto_globals_table
-#else
-# define GLOBAL_FUNCTION_TABLE CG(function_table)
-# define GLOBAL_CLASS_TABLE CG(class_table)
-# define GLOBAL_AUTO_GLOBALS_TABLE CG(auto_globals)
-#endif
+#include "zend_unicode.h"
+#include "zend_interfaces.h"
+#include "zend_reflection_api.h"
#if defined(ZEND_WIN32) && ZEND_DEBUG
BOOL WINAPI IsDebuggerPresent(VOID);
@@ -74,9 +66,145 @@ static ZEND_INI_MH(OnUpdateErrorReporting)
}
+static ZEND_INI_MH(OnUpdateEncoding)
+{
+ UConverter **converter;
+#ifndef ZTS
+ char *base = (char *) mh_arg2;
+#else
+ char *base;
+
+ base = (char *) ts_resource(*((int *) mh_arg2));
+#endif
+
+ converter = (UConverter **) (base+(size_t) mh_arg1);
+
+ if (!new_value && converter == &UG(fallback_encoding_conv)) {
+ new_value = "UTF-8";
+ }
+
+ if (new_value) {
+ if (zend_set_converter_encoding(converter, new_value) == FAILURE) {
+ zend_error(E_CORE_ERROR, "Unrecognized encoding '%s' used for %s", new_value ? new_value : "null", entry->name);
+ return FAILURE;
+ }
+ } else {
+ if (*converter) {
+ ucnv_close(*converter);
+ }
+ *converter = NULL;
+ }
+ if (*converter) {
+ zend_set_converter_error_mode(*converter, UG(from_u_error_mode));
+ zend_set_converter_subst_char(*converter, UG(subst_char), UG(subst_char_len));
+ }
+
+ return SUCCESS;
+}
+
+#if 0
+static ZEND_INI_MH(OnUpdateErrorMode)
+{
+ uint8_t *error_mode;
+#ifndef ZTS
+ char *base = (char *) mh_arg2;
+#else
+ char *base;
+
+ base = (char *) ts_resource(*((int *) mh_arg2));
+#endif
+
+ error_mode = (uint8_t *) (base+(size_t) mh_arg1);
+
+ if (new_value) {
+ if (!strcasecmp(new_value, "stop")) {
+ *error_mode = ZEND_FROM_U_ERROR_STOP;
+ } else if (!strcasecmp(new_value, "skip")) {
+ *error_mode = ZEND_FROM_U_ERROR_SKIP;
+ } else if (!strcasecmp(new_value, "escape")) {
+ *error_mode = ZEND_FROM_U_ERROR_ESCAPE;
+ } else if (!strcasecmp(new_value, "substitute")) {
+ *error_mode = ZEND_FROM_U_ERROR_SUBST;
+ } else {
+ zend_error(E_WARNING, "Illegal value for conversion error mode");
+ return FAILURE;
+ }
+ }
+
+ return SUCCESS;
+}
+#endif
+
+static void zend_update_converters_error_behavior(TSRMLS_D)
+{
+ if (UG(fallback_encoding_conv)) {
+ zend_set_converter_error_mode(UG(fallback_encoding_conv), UG(from_u_error_mode));
+ zend_set_converter_subst_char(UG(fallback_encoding_conv), UG(subst_char), UG(subst_char_len));
+ }
+ if (UG(runtime_encoding_conv)) {
+ zend_set_converter_error_mode(UG(runtime_encoding_conv), UG(from_u_error_mode));
+ zend_set_converter_subst_char(UG(runtime_encoding_conv), UG(subst_char), UG(subst_char_len));
+ }
+ if (UG(output_encoding_conv)) {
+ zend_set_converter_error_mode(UG(output_encoding_conv), UG(from_u_error_mode));
+ zend_set_converter_subst_char(UG(output_encoding_conv), UG(subst_char), UG(subst_char_len));
+ }
+ if (UG(http_input_encoding_conv)) {
+ zend_set_converter_error_mode(UG(http_input_encoding_conv), UG(from_u_error_mode));
+ }
+}
+
+
+static ZEND_INI_MH(OnUpdateConversionErrorMode)
+{
+ if (!new_value) {
+ UG(from_u_error_mode) = ZEND_FROM_U_ERROR_SUBST;
+ } else {
+ UG(from_u_error_mode) = atoi(new_value);
+ }
+ zend_update_converters_error_behavior(TSRMLS_C);
+ return SUCCESS;
+}
+
+
+static ZEND_INI_MH(OnUpdateConversionSubstChar)
+{
+ uint8_t i = 0;
+ UChar32 c = 0x3f; /*'?'*/
+ char *end_ptr;
+
+ if (new_value) {
+ c = (int32_t)strtol(new_value, &end_ptr, 16);
+ if (end_ptr < new_value + strlen(new_value)) {
+ zend_error(E_WARNING, "Substitution character string should be a hexadecimal Unicode codepoint value");
+ return FAILURE;
+ }
+ if (c < 0 || c >= 0x10FFFF) {
+ zend_error(E_WARNING, "Substitution character value U+%06x is out of range 0-10FFFF", c);
+ return FAILURE;
+ }
+ }
+ U16_APPEND_UNSAFE(UG(subst_char), i, c);
+ UG(subst_char)[i] = 0;
+ UG(subst_char_len) = i;
+ zend_update_converters_error_behavior(TSRMLS_C);
+
+ return SUCCESS;
+}
+
+
ZEND_INI_BEGIN()
- ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
+ ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
STD_ZEND_INI_BOOLEAN("zend.ze1_compatibility_mode", "0", ZEND_INI_ALL, OnUpdateBool, ze1_compatibility_mode, zend_executor_globals, executor_globals)
+
+ /* Unicode .ini entries */
+ STD_ZEND_INI_ENTRY("unicode_semantics", "off", ZEND_INI_SYSTEM|ZEND_INI_PERDIR, OnUpdateBool, unicode, zend_unicode_globals, unicode_globals)
+ STD_ZEND_INI_ENTRY("unicode.fallback_encoding", NULL, ZEND_INI_ALL, OnUpdateEncoding, fallback_encoding_conv, zend_unicode_globals, unicode_globals)
+ STD_ZEND_INI_ENTRY("unicode.runtime_encoding", NULL, ZEND_INI_ALL, OnUpdateEncoding, runtime_encoding_conv, zend_unicode_globals, unicode_globals)
+ STD_ZEND_INI_ENTRY("unicode.script_encoding", NULL, ZEND_INI_ALL, OnUpdateEncoding, script_encoding_conv, zend_unicode_globals, unicode_globals)
+ STD_ZEND_INI_ENTRY("unicode.http_input_encoding", NULL, ZEND_INI_ALL, OnUpdateEncoding, http_input_encoding_conv, zend_unicode_globals, unicode_globals)
+ ZEND_INI_ENTRY("unicode.from_error_mode", "2", ZEND_INI_ALL, OnUpdateConversionErrorMode)
+ ZEND_INI_ENTRY("unicode.from_error_subst_char", "3f", ZEND_INI_ALL, OnUpdateConversionSubstChar)
ZEND_INI_END()
@@ -84,11 +212,15 @@ ZEND_INI_END()
ZEND_API int compiler_globals_id;
ZEND_API int executor_globals_id;
ZEND_API int alloc_globals_id;
-HashTable *global_function_table;
-HashTable *global_class_table;
-HashTable *global_constants_table;
-HashTable *global_auto_globals_table;
#endif
+static HashTable *global_function_table = NULL;
+static HashTable *global_class_table = NULL;
+static HashTable *global_constants_table = NULL;
+static HashTable *global_auto_globals_table = NULL;
+static HashTable *global_u_function_table = NULL;
+static HashTable *global_u_class_table = NULL;
+static HashTable *global_u_constants_table = NULL;
+static HashTable *global_u_auto_globals_table = NULL;
ZEND_API zend_utility_values zend_uv;
@@ -118,17 +250,25 @@ static void print_hash(HashTable *ht, int indent, zend_bool is_object TSRMLS_DC)
indent += PRINT_ZVAL_INDENT;
zend_hash_internal_pointer_reset_ex(ht, &iterator);
while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) {
+ zend_uchar key_type;
+
for (i=0; i<indent; i++) {
ZEND_PUTS(" ");
}
ZEND_PUTS("[");
- switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) {
+ switch ((key_type = zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator))) {
case HASH_KEY_IS_STRING:
+ case HASH_KEY_IS_UNICODE:
+ case HASH_KEY_IS_BINARY:
if (is_object) {
char *prop_name, *class_name;
- zend_unmangle_property_name(string_key, &class_name, &prop_name);
- ZEND_PUTS(prop_name);
+ zend_u_unmangle_property_name(key_type==HASH_KEY_IS_UNICODE?IS_UNICODE:IS_STRING, string_key, &class_name, &prop_name);
+ if (key_type == HASH_KEY_IS_UNICODE) {
+ zend_printf("%r", prop_name);
+ } else {
+ ZEND_PUTS(prop_name);
+ }
if (class_name) {
if (class_name[0]=='*') {
ZEND_PUTS(":protected");
@@ -137,7 +277,11 @@ static void print_hash(HashTable *ht, int indent, zend_bool is_object TSRMLS_DC)
}
}
} else {
- ZEND_WRITE(string_key, str_len-1);
+ if (key_type == HASH_KEY_IS_UNICODE) {
+ zend_printf("%r", string_key);
+ } else {
+ ZEND_WRITE(string_key, str_len-1);
+ }
}
break;
case HASH_KEY_IS_LONG:
@@ -158,40 +302,100 @@ static void print_hash(HashTable *ht, int indent, zend_bool is_object TSRMLS_DC)
static void print_flat_hash(HashTable *ht TSRMLS_DC)
{
- zval **tmp;
- char *string_key;
- HashPosition iterator;
- ulong num_key;
- uint str_len;
- int i = 0;
-
- zend_hash_internal_pointer_reset_ex(ht, &iterator);
- while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) {
- if (i++ > 0) {
- ZEND_PUTS(",");
- }
- ZEND_PUTS("[");
- switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) {
- case HASH_KEY_IS_STRING:
- ZEND_PUTS(string_key);
- break;
- case HASH_KEY_IS_LONG:
- zend_printf("%ld", num_key);
- break;
- }
- ZEND_PUTS("] => ");
- zend_print_flat_zval_r(*tmp TSRMLS_CC);
- zend_hash_move_forward_ex(ht, &iterator);
- }
+ zval **tmp;
+ char *string_key;
+ HashPosition iterator;
+ ulong num_key;
+ uint str_len;
+ int i = 0;
+
+ zend_hash_internal_pointer_reset_ex(ht, &iterator);
+ while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) {
+ if (i++ > 0) {
+ ZEND_PUTS(",");
+ }
+ ZEND_PUTS("[");
+ switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) {
+ case HASH_KEY_IS_STRING:
+ ZEND_PUTS(string_key);
+ break;
+ case HASH_KEY_IS_LONG:
+ zend_printf("%ld", num_key);
+ break;
+ }
+ ZEND_PUTS("] => ");
+ zend_print_flat_zval_r(*tmp TSRMLS_CC);
+ zend_hash_move_forward_ex(ht, &iterator);
+ }
}
-ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy)
+ZEND_API void zend_make_string_zval(zval *expr, zval *expr_copy, int *use_copy)
{
if (expr->type==IS_STRING) {
*use_copy = 0;
return;
}
switch (expr->type) {
+ case IS_OBJECT:
+ {
+ TSRMLS_FETCH();
+#if 0
+ /* Standard PHP objects */
+ if (Z_OBJ_HT_P(expr) == &std_object_handlers || !Z_OBJ_HT_P(expr)->cast_object) {
+ if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ zend_error(E_NOTICE, "Object of class %v could not be converted to string", Z_OBJCE_P(expr)->name);
+ }
+#endif
+ if (Z_OBJ_HANDLER_P(expr, cast_object)) {
+ if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ } else {
+ if(Z_OBJ_HANDLER_P(expr, get)) {
+ zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
+ if(Z_TYPE_P(z) != IS_OBJECT) {
+ zend_make_printable_zval(z, expr_copy, use_copy);
+ FREE_ZVAL(z);
+ return;
+ }
+ }
+ }
+ if (EG(exception)) {
+ zval_dtor(expr_copy);
+ expr_copy->value.str.len = 0;
+ expr_copy->value.str.val = STR_EMPTY_ALLOC();
+ break;
+ }
+ }
+ expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG);
+ expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle);
+ expr_copy->type = IS_STRING;
+ break;
+ default:
+ *expr_copy = *expr;
+ zval_copy_ctor(expr_copy);
+ convert_to_string(expr_copy);
+ break;
+ }
+ *use_copy = 1;
+}
+
+ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy)
+{
+ UErrorCode temp = U_ZERO_ERROR;
+ TSRMLS_FETCH();
+
+ if (expr->type == IS_BINARY ||
+ /* UTODO: clean this up */
+ (expr->type == IS_STRING &&
+ (!strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &temp),
+ ucnv_getName(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &temp))))) {
+ *use_copy = 0;
+ return;
+ }
+ switch (expr->type) {
case IS_NULL:
expr_copy->value.str.len = 0;
expr_copy->value.str.val = STR_EMPTY_ALLOC();
@@ -215,14 +419,13 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
break;
case IS_OBJECT:
{
- TSRMLS_FETCH();
#if 0
/* Standard PHP objects */
if (Z_OBJ_HT_P(expr) == &std_object_handlers || !Z_OBJ_HT_P(expr)->cast_object) {
if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
break;
}
- zend_error(E_NOTICE, "Object of class %s could not be converted to string", Z_OBJCE_P(expr)->name);
+ zend_error(E_NOTICE, "Object of class %v could not be converted to string", Z_OBJCE_P(expr)->name);
}
#endif
if (Z_OBJ_HANDLER_P(expr, cast_object)) {
@@ -248,6 +451,7 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
}
expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG);
expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle);
+ expr_copy->type = IS_STRING;
break;
case IS_DOUBLE:
*expr_copy = *expr;
@@ -257,7 +461,11 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
default:
*expr_copy = *expr;
zval_copy_ctor(expr_copy);
- convert_to_string(expr_copy);
+ if (UG(unicode)) {
+ convert_to_string_with_converter(expr_copy, ZEND_U_CONVERTER(UG(output_encoding_conv)));
+ } else {
+ convert_to_string(expr_copy);
+ }
break;
}
expr_copy->type = IS_STRING;
@@ -265,6 +473,61 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_cop
}
+ZEND_API void zend_make_unicode_zval(zval *expr, zval *expr_copy, int *use_copy)
+{
+ TSRMLS_FETCH();
+
+ if (expr->type==IS_UNICODE) {
+ *use_copy = 0;
+ return;
+ }
+ switch (expr->type) {
+ case IS_OBJECT:
+ {
+#if 0
+ /* Standard PHP objects */
+ if (Z_OBJ_HT_P(expr) == &std_object_handlers || !Z_OBJ_HT_P(expr)->cast_object) {
+ if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ zend_error(E_NOTICE, "Object of class %v could not be converted to string", Z_OBJCE_P(expr)->name);
+ }
+#endif
+ if (Z_OBJ_HANDLER_P(expr, cast_object)) {
+ if(Z_OBJ_HANDLER_P(expr, cast_object)(expr, expr_copy, IS_UNICODE, 0 TSRMLS_CC) == SUCCESS) {
+ break;
+ }
+ } else {
+ if(Z_OBJ_HANDLER_P(expr, get)) {
+ zval *z = Z_OBJ_HANDLER_P(expr, get)(expr TSRMLS_CC);
+ if(Z_TYPE_P(z) != IS_OBJECT) {
+ zend_make_unicode_zval(z, expr_copy, use_copy);
+ FREE_ZVAL(z);
+ return;
+ }
+ }
+ }
+ if (EG(exception)) {
+ zval_dtor(expr_copy);
+ expr_copy->value.ustr.len = 0;
+ expr_copy->value.ustr.val = USTR_MAKE("");
+ break;
+ }
+ }
+ expr_copy->value.ustr.val = emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG + 1);
+ expr_copy->value.ustr.len = u_sprintf(expr_copy->value.ustr.val, "Object id #%ld", (long)expr->value.obj.handle);
+ expr_copy->type = IS_UNICODE;
+ break;
+ default:
+ *expr_copy = *expr;
+ zval_copy_ctor(expr_copy);
+ convert_to_unicode(expr_copy);
+ break;
+ }
+ *use_copy = 1;
+}
+
+
ZEND_API int zend_print_zval(zval *expr, int indent)
{
return zend_print_zval_ex(zend_write, expr, indent);
@@ -295,28 +558,32 @@ ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int in
ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC)
{
- switch (expr->type) {
- case IS_ARRAY:
- ZEND_PUTS("Array (");
- if (++expr->value.ht->nApplyCount>1) {
- ZEND_PUTS(" *RECURSION*");
- expr->value.ht->nApplyCount--;
- return;
- }
- print_flat_hash(expr->value.ht TSRMLS_CC);
- ZEND_PUTS(")");
- expr->value.ht->nApplyCount--;
- break;
- case IS_OBJECT:
- {
+ switch (expr->type) {
+ case IS_ARRAY:
+ ZEND_PUTS("Array (");
+ if (++expr->value.ht->nApplyCount>1) {
+ ZEND_PUTS(" *RECURSION*");
+ expr->value.ht->nApplyCount--;
+ return;
+ }
+ print_flat_hash(expr->value.ht TSRMLS_CC);
+ ZEND_PUTS(")");
+ expr->value.ht->nApplyCount--;
+ break;
+ case IS_OBJECT:
+ {
HashTable *properties = NULL;
char *class_name = NULL;
zend_uint clen;
-
+
if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
}
- zend_printf("%s Object (", class_name?class_name:"Unknown Class");
+ if (class_name) {
+ zend_printf("%v Object (", class_name);
+ } else {
+ zend_printf("%s Object (", "Unknown Class");
+ }
if (class_name) {
efree(class_name);
}
@@ -334,11 +601,11 @@ ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC)
}
ZEND_PUTS(")");
break;
- }
- default:
- zend_print_variable(expr);
- break;
- }
+ }
+ default:
+ zend_print_variable(expr);
+ break;
+ }
}
ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC)
@@ -365,11 +632,15 @@ ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int
HashTable *properties = NULL;
char *class_name = NULL;
zend_uint clen;
-
+
if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
}
- zend_printf("%s Object\n", class_name?class_name:"Unknown Class");
+ if (class_name) {
+ zend_printf("%v Object\n", class_name);
+ } else {
+ zend_printf("%s Object\n", "Unknown Class");
+ }
if (class_name) {
efree(class_name);
}
@@ -425,6 +696,186 @@ static void zend_set_default_compile_time_values(TSRMLS_D)
}
+#define ZEND_U_FUNCTION_DTOR (void (*)(void *)) zend_u_function_dtor
+#define ZEND_U_CONSTANT_DTOR (void (*)(void *)) free_u_zend_constant
+
+static void zval_copy_persistent(zval *zv)
+{
+ if (Z_TYPE_P(zv) == IS_BINARY) {
+ Z_BINVAL_P(zv) = zend_strndup(Z_BINVAL_P(zv), Z_BINLEN_P(zv));
+ } else if (Z_TYPE_P(zv) == IS_UNICODE) {
+ Z_USTRVAL_P(zv) = zend_ustrndup(Z_USTRVAL_P(zv), Z_USTRLEN_P(zv));
+ } else if (Z_TYPE_P(zv) == IS_STRING || Z_TYPE_P(zv) == IS_CONSTANT) {
+ UChar *ustr;
+
+ ustr = malloc(UBYTES(Z_STRLEN_P(zv)+1));
+ u_charsToUChars(Z_STRVAL_P(zv), ustr, Z_STRLEN_P(zv)+1);
+ Z_USTRVAL_P(zv) = ustr;
+ if (Z_TYPE_P(zv) == IS_STRING) Z_TYPE_P(zv) = IS_UNICODE;
+ }
+}
+
+static void zend_u_function_dtor(zend_function *function)
+{
+ TSRMLS_FETCH();
+
+ destroy_zend_function(function TSRMLS_CC);
+ if (function->type == ZEND_INTERNAL_FUNCTION && function->common.function_name) {
+ free(function->common.function_name);
+ }
+}
+
+static void free_u_zend_constant(zend_constant *c)
+{
+ if (!(c->flags & CONST_PERSISTENT)) {
+ zval_dtor(&c->value);
+ } else {
+ zval_internal_dtor(&c->value);
+ }
+ free(c->name);
+}
+
+static void copy_u_zend_constant(zend_constant *c)
+{
+ c->name = (char*)zend_ustrndup((UChar*)c->name, c->name_len - 1);
+ if (!(c->flags & CONST_PERSISTENT)) {
+ zval_copy_ctor(&c->value);
+ } else {
+ zval_copy_persistent(&c->value);
+ }
+}
+
+static void function_to_unicode(zend_function *func)
+{
+ if (func->common.function_name) {
+ UChar *uname;
+ int len = strlen(func->common.function_name)+1;
+
+ uname = malloc(UBYTES(len));
+ u_charsToUChars(func->common.function_name, uname, len);
+ func->common.function_name = (char*)uname;
+ }
+}
+
+static void property_info_to_unicode(zend_property_info *info)
+{
+ if (info->name) {
+ UChar *uname;
+
+ uname = malloc(UBYTES(info->name_length+1));
+ u_charsToUChars(info->name, uname, info->name_length+1);
+ info->name = (char*)uname;
+ info->h = zend_u_get_hash_value(IS_UNICODE, info->name, info->name_length+1);
+ }
+}
+
+static void zval_ptr_to_unicode(zval **zv)
+{
+ zval *new_zv = malloc(sizeof(zval));
+
+ memcpy(new_zv, *zv, sizeof(zval));
+ new_zv->refcount = 1;
+ zval_copy_persistent(new_zv);
+ *zv = new_zv;
+}
+
+static void const_to_unicode(zend_constant *c)
+{
+ UChar *uname;
+
+ if (c->name) {
+ uname = malloc(UBYTES(c->name_len));
+ u_charsToUChars(c->name, uname, c->name_len);
+ c->name = (char*)uname;
+ }
+ zval_copy_persistent(&c->value);
+}
+
+static void class_to_unicode(zend_class_entry **ce)
+{
+ zend_class_entry *new_ce = malloc(sizeof(zend_class_entry));
+ zend_function tmp_func;
+ zend_constant tmp_const;
+ zend_property_info tmp_info;
+ zval* tmp_zval;
+
+ memcpy(new_ce, *ce, sizeof(zend_class_entry));
+
+ /* Copy methods */
+ zend_u_hash_init_ex(&new_ce->function_table, (*ce)->function_table.nNumOfElements, NULL, ZEND_U_FUNCTION_DTOR, 1, 1, 0);
+ zend_hash_copy(&new_ce->function_table, &(*ce)->function_table, (copy_ctor_func_t) function_to_unicode, &tmp_func, sizeof(zend_function));
+
+ /* Copy constants */
+ zend_u_hash_init_ex(&new_ce->constants_table, (*ce)->constants_table.nNumOfElements, NULL, (*ce)->constants_table.pDestructor, 1, 1, 0);
+ zend_hash_copy(&new_ce->constants_table, &(*ce)->constants_table, (copy_ctor_func_t) zval_ptr_to_unicode, &tmp_const, sizeof(zend_constant));
+
+ /* Copy properties */
+ zend_u_hash_init_ex(&new_ce->properties_info, (*ce)->properties_info.nNumOfElements, NULL, (*ce)->properties_info.pDestructor/*(dtor_func_t)zend_destroy_property_info_internal*/, 1, 1, 0);
+ zend_hash_copy(&new_ce->properties_info, &(*ce)->properties_info, (copy_ctor_func_t) property_info_to_unicode, &tmp_info, sizeof(zend_property_info));
+
+ zend_u_hash_init_ex(&new_ce->default_properties, (*ce)->default_properties.nNumOfElements, NULL, (*ce)->default_properties.pDestructor, 1, 1, 0);
+ zend_hash_copy(&new_ce->default_properties, &(*ce)->default_properties, (copy_ctor_func_t) zval_ptr_to_unicode, &tmp_zval, sizeof(zval*));
+
+ if (new_ce->static_members) {
+ new_ce->static_members = (HashTable*)malloc(sizeof(HashTable));
+ zend_u_hash_init_ex(new_ce->static_members, (*ce)->static_members->nNumOfElements, NULL, (*ce)->static_members->pDestructor, 1, 1, 0);
+ zend_hash_copy(new_ce->static_members, (*ce)->static_members, (copy_ctor_func_t) zval_ptr_to_unicode, &tmp_zval, sizeof(zval*));
+ }
+
+ *ce = new_ce;
+}
+
+static void fix_classes(HashTable *ht) {
+ Bucket *p = ht->pListHead;
+
+ /* Fix parent classes */
+ while (p != NULL) {
+ zend_class_entry *ce = *(zend_class_entry**)p->pData;
+ zend_class_entry **parent;
+
+ if (ce->parent) {
+ char *lcname = do_alloca(ce->parent->name_length+1);
+
+ zend_str_tolower_copy(lcname, ce->parent->name, ce->parent->name_length);
+ if (zend_hash_find(ht, lcname, ce->parent->name_length+1, (void**)&parent) == SUCCESS) {
+ ce->parent = *parent;
+ }
+ free_alloca(lcname);
+ }
+ if (ce->num_interfaces > 0 && ce->interfaces) {
+ int i = sizeof(zend_class_entry*)*ce->num_interfaces;
+ zend_class_entry **new_interfaces;
+
+ new_interfaces = (zend_class_entry**)malloc(i);
+ memcpy(new_interfaces, ce->interfaces, i);
+ ce->interfaces = new_interfaces;
+ for (i = 0; i < ce->num_interfaces; i++) {
+ char *lcname = do_alloca(ce->interfaces[i]->name_length+1);
+
+ zend_str_tolower_copy(lcname, ce->interfaces[i]->name, ce->interfaces[i]->name_length);
+ if (zend_hash_find(ht, lcname, ce->interfaces[i]->name_length+1, (void**)&parent) == SUCCESS) {
+ ce->interfaces[i] = *parent;
+ }
+ free_alloca(lcname);
+
+ }
+ }
+ p = p->pListNext;
+ }
+
+ /* Convert Class Names to unicode */
+ p = ht->pListHead;
+ while (p != NULL) {
+ zend_class_entry *ce = *(zend_class_entry**)p->pData;
+ UChar *uname = malloc(UBYTES(ce->name_length+1));
+
+ u_charsToUChars(ce->name, uname, ce->name_length+1);
+ ce->name = (char*)uname;
+
+ p = p->pListNext;
+ }
+}
+
#ifdef ZTS
static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS_DC)
{
@@ -433,45 +884,102 @@ static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS
compiler_globals->compiled_filename = NULL;
- compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable));
- zend_hash_init_ex(compiler_globals->function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
- zend_hash_copy(compiler_globals->function_table, global_function_table, NULL, &tmp_func, sizeof(zend_function));
+ compiler_globals->global_function_table = compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable));
+ zend_u_hash_init_ex(compiler_globals->function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0, 0);
+ zend_hash_copy(compiler_globals->function_table, global_function_table, NULL, &tmp_func, sizeof(zend_function));
- compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable));
- zend_hash_init_ex(compiler_globals->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
- zend_hash_copy(compiler_globals->class_table, global_class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry *));
+ if (global_u_function_table) {
+ compiler_globals->global_u_function_table = (HashTable *) malloc(sizeof(HashTable));
+ zend_u_hash_init_ex(compiler_globals->global_u_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 1, 0);
+ zend_hash_copy(compiler_globals->global_u_function_table, global_u_function_table, NULL, &tmp_func, sizeof(zend_function));
+ } else {
+ compiler_globals->global_u_function_table = 0;
+ }
+
+ compiler_globals->global_class_table = compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable));
+ zend_u_hash_init_ex(compiler_globals->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0, 0);
+ zend_hash_copy(compiler_globals->class_table, global_class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry *));
+ if (global_u_class_table) {
+ compiler_globals->global_u_class_table = (HashTable *) malloc(sizeof(HashTable));
+ zend_u_hash_init_ex(compiler_globals->global_u_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 1, 0);
+ zend_hash_copy(compiler_globals->global_u_class_table, global_u_class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry *));
+ } else {
+ compiler_globals->global_u_class_table = NULL;
+ }
zend_set_default_compile_time_values(TSRMLS_C);
CG(interactive) = 0;
+ CG(literal_type) = IS_STRING;
- compiler_globals->auto_globals = (HashTable *) malloc(sizeof(HashTable));
- zend_hash_init_ex(compiler_globals->auto_globals, 8, NULL, NULL, 1, 0);
+ compiler_globals->global_auto_globals_table = compiler_globals->auto_globals = (HashTable *) malloc(sizeof(HashTable));
+ zend_u_hash_init_ex(compiler_globals->auto_globals, 8, NULL, NULL, 1, 0, 0);
zend_hash_copy(compiler_globals->auto_globals, global_auto_globals_table, NULL, NULL, sizeof(zend_auto_global) /* empty element */);
+
+ if (global_u_auto_globals_table) {
+ compiler_globals->global_u_auto_globals_table = (HashTable *) malloc(sizeof(HashTable));
+ zend_u_hash_init_ex(compiler_globals->global_u_auto_globals_table, 8, NULL, NULL, 1, 1, 0);
+ zend_hash_copy(compiler_globals->global_u_auto_globals_table, global_u_auto_globals_table, NULL, NULL, sizeof(zend_auto_global) /* empty element */);
+ } else {
+ compiler_globals->global_u_auto_globals_table = NULL;
+ }
}
static void compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS_DC)
{
- if (compiler_globals->function_table != GLOBAL_FUNCTION_TABLE) {
- zend_hash_destroy(compiler_globals->function_table);
- free(compiler_globals->function_table);
+ if (compiler_globals->function_table != global_function_table &&
+ compiler_globals->function_table != global_u_function_table) {
+ if (compiler_globals->global_function_table) {
+ zend_hash_destroy(compiler_globals->global_function_table);
+ free(compiler_globals->global_function_table);
+ }
+ if (compiler_globals->global_u_function_table) {
+ zend_hash_destroy(compiler_globals->global_u_function_table);
+ free(compiler_globals->global_u_function_table);
+ }
}
- if (compiler_globals->class_table != GLOBAL_CLASS_TABLE) {
- zend_hash_destroy(compiler_globals->class_table);
- free(compiler_globals->class_table);
+ if (compiler_globals->class_table != global_class_table &&
+ compiler_globals->class_table != global_u_class_table) {
+ if (compiler_globals->global_class_table) {
+ zend_hash_destroy(compiler_globals->global_class_table);
+ free(compiler_globals->global_class_table);
+ }
+ if (compiler_globals->global_u_class_table) {
+ zend_hash_destroy(compiler_globals->global_u_class_table);
+ free(compiler_globals->global_u_class_table);
+ }
}
- if (compiler_globals->auto_globals != GLOBAL_AUTO_GLOBALS_TABLE) {
- zend_hash_destroy(compiler_globals->auto_globals);
- free(compiler_globals->auto_globals);
+ if (compiler_globals->auto_globals != global_auto_globals_table &&
+ compiler_globals->auto_globals != global_u_auto_globals_table) {
+ if (compiler_globals->global_auto_globals_table) {
+ zend_hash_destroy(compiler_globals->global_auto_globals_table);
+ free(compiler_globals->global_auto_globals_table);
+ }
+ if (compiler_globals->global_u_auto_globals_table) {
+ zend_hash_destroy(compiler_globals->global_u_auto_globals_table);
+ free(compiler_globals->global_u_auto_globals_table);
+ }
}
}
static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS_DC)
{
+ zend_constant tmp_const;
+
zend_startup_constants(TSRMLS_C);
- zend_copy_constants(EG(zend_constants), GLOBAL_CONSTANTS_TABLE);
+ zend_copy_constants(EG(zend_constants), global_constants_table);
+ EG(global_constants_table) = EG(zend_constants);
+
+ if (global_u_constants_table) {
+ EG(global_u_constants_table) = (HashTable *) malloc(sizeof(HashTable));
+ zend_u_hash_init_ex(EG(global_u_constants_table), global_u_constants_table->nNumOfElements, NULL, ZEND_U_CONSTANT_DTOR, 1, 1, 0);
+ zend_hash_copy(EG(global_u_constants_table), global_u_constants_table, (copy_ctor_func_t) copy_u_zend_constant, &tmp_const, sizeof(zend_constant));
+ } else {
+ EG(global_u_constants_table) = NULL;
+ }
+
zend_init_rsrc_plist(TSRMLS_C);
EG(lambda_count)=0;
EG(user_error_handler) = NULL;
@@ -506,7 +1014,6 @@ static void alloc_globals_ctor(zend_alloc_globals *alloc_globals_p TSRMLS_DC)
start_memory_manager(TSRMLS_C);
}
-
#if defined(__FreeBSD__) || defined(__DragonFly__)
/* FreeBSD and DragonFly floating point precision fix */
#include <floatingpoint.h>
@@ -528,6 +1035,44 @@ static void scanner_globals_ctor(zend_scanner_globals *scanner_globals_p TSRMLS_
scanner_globals_p->yy_start_stack = 0;
}
+static void unicode_globals_ctor(zend_unicode_globals *unicode_globals TSRMLS_DC)
+{
+ unicode_globals->unicode = 0;
+ unicode_globals->utf8_conv = NULL;
+ unicode_globals->fallback_encoding_conv = NULL;
+ unicode_globals->runtime_encoding_conv = NULL;
+ unicode_globals->output_encoding_conv = NULL;
+ unicode_globals->script_encoding_conv = NULL;
+ unicode_globals->http_input_encoding_conv = NULL;
+ zend_set_converter_encoding(&unicode_globals->utf8_conv, "UTF-8");
+ unicode_globals->from_u_error_mode = ZEND_FROM_U_ERROR_SUBST;
+
+ zend_hash_init_ex(&unicode_globals->flex_compatible, 0, NULL, NULL, 1, 0);
+}
+
+static void unicode_globals_dtor(zend_unicode_globals *unicode_globals TSRMLS_DC)
+{
+ if (unicode_globals->fallback_encoding_conv) {
+ ucnv_close(unicode_globals->fallback_encoding_conv);
+ }
+ if (unicode_globals->runtime_encoding_conv) {
+ ucnv_close(unicode_globals->runtime_encoding_conv);
+ }
+ if (unicode_globals->output_encoding_conv) {
+ ucnv_close(unicode_globals->output_encoding_conv);
+ }
+ if (unicode_globals->script_encoding_conv) {
+ ucnv_close(unicode_globals->script_encoding_conv);
+ }
+ if (unicode_globals->http_input_encoding_conv) {
+ ucnv_close(unicode_globals->http_input_encoding_conv);
+ }
+ if (unicode_globals->utf8_conv) {
+ ucnv_close(unicode_globals->utf8_conv);
+ }
+ zend_hash_destroy(&unicode_globals->flex_compatible);
+}
+
void zend_init_opcodes_handlers();
int zend_startup(zend_utility_functions *utility_functions, char **extensions, int start_builtin_functions)
@@ -538,9 +1083,11 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
void ***tsrm_ls;
extern ZEND_API ts_rsrc_id ini_scanner_globals_id;
extern ZEND_API ts_rsrc_id language_scanner_globals_id;
+ extern ZEND_API ts_rsrc_id unicode_globals_id;
#else
extern zend_scanner_globals ini_scanner_globals;
extern zend_scanner_globals language_scanner_globals;
+ extern zend_unicode_globals unicode_globals;
#endif
#ifdef ZTS
@@ -585,14 +1132,15 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
zend_version_info = strdup(ZEND_CORE_VERSION_INFO);
zend_version_info_length = sizeof(ZEND_CORE_VERSION_INFO)-1;
- GLOBAL_FUNCTION_TABLE = (HashTable *) malloc(sizeof(HashTable));
- GLOBAL_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable));
- GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable));
-#ifdef ZTS
- GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable));
-#endif
- zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
- zend_hash_init_ex(GLOBAL_CLASS_TABLE, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
+ global_function_table = (HashTable *) malloc(sizeof(HashTable));
+ global_class_table = (HashTable *) malloc(sizeof(HashTable));
+ global_auto_globals_table = (HashTable *) malloc(sizeof(HashTable));
+ global_constants_table = (HashTable *) malloc(sizeof(HashTable));
+
+ zend_hash_init_ex(global_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
+ zend_hash_init_ex(global_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
+ zend_hash_init_ex(global_auto_globals_table, 8, NULL, (dtor_func_t) zend_auto_global_dtor, 1, 0);
+ zend_hash_init_ex(global_constants_table, 20, NULL, ZEND_CONSTANT_DTOR, 1, 0);
zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0);
zend_init_rsrc_list_dtors();
@@ -604,8 +1152,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
zval_used_for_init.type = IS_NULL;
#ifdef ZTS
- zend_hash_init_ex(GLOBAL_CONSTANTS_TABLE, 20, NULL, ZEND_CONSTANT_DTOR, 1, 0);
- zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, (dtor_func_t) zend_auto_global_dtor, 1, 0);
+ ts_allocate_id(&unicode_globals_id, sizeof(zend_unicode_globals), (ts_allocate_ctor) unicode_globals_ctor, (ts_allocate_dtor) unicode_globals_dtor);
ts_allocate_id(&compiler_globals_id, sizeof(zend_compiler_globals), (ts_allocate_ctor) compiler_globals_ctor, (ts_allocate_dtor) compiler_globals_dtor);
ts_allocate_id(&executor_globals_id, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor);
ts_allocate_id(&language_scanner_globals_id, sizeof(zend_scanner_globals), (ts_allocate_ctor) scanner_globals_ctor, NULL);
@@ -619,17 +1166,22 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable));
compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable));
- *compiler_globals->function_table = *GLOBAL_FUNCTION_TABLE;
- *compiler_globals->class_table = *GLOBAL_CLASS_TABLE;
- compiler_globals->auto_globals = GLOBAL_AUTO_GLOBALS_TABLE;
+ *compiler_globals->function_table = *global_function_table;
+ *compiler_globals->class_table = *global_class_table;
+ compiler_globals->auto_globals = global_auto_globals_table;
zend_hash_destroy(executor_globals->zend_constants);
- *executor_globals->zend_constants = *GLOBAL_CONSTANTS_TABLE;
+ *executor_globals->zend_constants = *global_constants_table;
#else
- zend_hash_init_ex(CG(auto_globals), 8, NULL, (dtor_func_t) zend_auto_global_dtor, 1, 0);
+ unicode_globals_ctor(&unicode_globals TSRMLS_CC);
scanner_globals_ctor(&ini_scanner_globals TSRMLS_CC);
scanner_globals_ctor(&language_scanner_globals TSRMLS_CC);
- zend_startup_constants();
+
+ CG(function_table) = global_function_table;
+ CG(class_table) = global_class_table;
+ CG(auto_globals) = global_auto_globals_table;
+ EG(zend_constants) = global_constants_table;
+
zend_set_default_compile_time_values(TSRMLS_C);
EG(user_error_handler) = NULL;
EG(user_exception_handler) = NULL;
@@ -663,19 +1215,51 @@ void zend_register_standard_ini_entries(TSRMLS_D)
REGISTER_INI_ENTRIES();
}
-
-#ifdef ZTS
/* Unlink the global (r/o) copies of the class, function and constant tables,
* and use a fresh r/w copy for the startup thread
*/
void zend_post_startup(TSRMLS_D)
{
+ UConverter *old_runtime_encoding_conv;
+ UErrorCode status = U_ZERO_ERROR;
+ zend_function tmp_func;
+ zend_class_entry *tmp_class;
+ zend_constant tmp_const;
+#ifdef ZTS
zend_compiler_globals *compiler_globals = ts_resource(compiler_globals_id);
zend_executor_globals *executor_globals = ts_resource(executor_globals_id);
- *GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table;
- *GLOBAL_CLASS_TABLE = *compiler_globals->class_table;
- *GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants;
+ *global_function_table = *compiler_globals->function_table;
+ *global_class_table = *compiler_globals->class_table;
+ *global_constants_table = *executor_globals->zend_constants;
+#endif
+
+ /* Make copies of HashTables with UNICODE */
+
+ old_runtime_encoding_conv = UG(runtime_encoding_conv);
+ UG(runtime_encoding_conv) = ucnv_open("ASCII", &status);
+
+ global_u_function_table = (HashTable *) malloc(sizeof(HashTable));
+ zend_u_hash_init_ex(global_u_function_table, global_function_table->nNumOfElements, NULL, ZEND_U_FUNCTION_DTOR, 1, 1, 0);
+ zend_hash_copy(global_u_function_table, global_function_table, (copy_ctor_func_t) function_to_unicode, &tmp_func, sizeof(zend_function));
+
+ global_u_class_table = (HashTable *) malloc(sizeof(HashTable));
+ zend_u_hash_init_ex(global_u_class_table, global_class_table->nNumOfElements, NULL, ZEND_CLASS_DTOR, 1, 1, 0);
+ zend_hash_copy(global_u_class_table, global_class_table, (copy_ctor_func_t) class_to_unicode, &tmp_class, sizeof(zend_class_entry *));
+ fix_classes(global_u_class_table);
+
+ global_u_auto_globals_table = (HashTable *) malloc(sizeof(HashTable));
+ zend_u_hash_init_ex(global_u_auto_globals_table, global_auto_globals_table->nNumOfElements, NULL, NULL, 1, 1, 0);
+ zend_hash_copy(global_u_auto_globals_table, global_auto_globals_table, NULL, NULL, sizeof(zend_auto_global));
+
+ global_u_constants_table = (HashTable *) malloc(sizeof(HashTable));
+ zend_u_hash_init_ex(global_u_constants_table, global_constants_table->nNumOfElements, NULL, ZEND_U_CONSTANT_DTOR, 1, 1, 0);
+ zend_hash_copy(global_u_constants_table, global_constants_table, (copy_ctor_func_t) const_to_unicode, &tmp_const, sizeof(zend_constant));
+
+ ucnv_close(UG(runtime_encoding_conv));
+ UG(runtime_encoding_conv) = old_runtime_encoding_conv;
+
+#ifdef ZTS
zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
free(compiler_globals->function_table);
free(compiler_globals->class_table);
@@ -683,8 +1267,8 @@ void zend_post_startup(TSRMLS_D)
free(EG(zend_constants));
executor_globals_ctor(executor_globals, tsrm_ls);
zend_new_thread_end_handler(tsrm_thread_id() TSRMLS_CC);
-}
#endif
+}
void zend_shutdown(TSRMLS_D)
@@ -697,25 +1281,57 @@ void zend_shutdown(TSRMLS_D)
#endif
zend_hash_graceful_reverse_destroy(&module_registry);
- zend_hash_destroy(GLOBAL_FUNCTION_TABLE);
- zend_hash_destroy(GLOBAL_CLASS_TABLE);
+ zend_hash_destroy(global_function_table);
+ zend_hash_destroy(global_class_table);
+ if (global_u_function_table) {
+ zend_hash_destroy(global_u_function_table);
+ }
+ if (global_u_class_table) {
+ zend_hash_destroy(global_u_class_table);
+ }
- zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE);
- free(GLOBAL_AUTO_GLOBALS_TABLE);
+ zend_hash_destroy(global_auto_globals_table);
+ free(global_auto_globals_table);
+ if (global_u_auto_globals_table) {
+ zend_hash_destroy(global_u_auto_globals_table);
+ free(global_u_auto_globals_table);
+ }
zend_shutdown_extensions(TSRMLS_C);
free(zend_version_info);
- zend_shutdown_constants(TSRMLS_C);
- free(GLOBAL_FUNCTION_TABLE);
- free(GLOBAL_CLASS_TABLE);
+#ifdef ZTS
+ if (EG(global_constants_table)) {
+ zend_hash_destroy(EG(global_constants_table));
+ free(EG(global_constants_table));
+ }
+ if (EG(global_u_constants_table)) {
+ zend_hash_destroy(EG(global_u_constants_table));
+ free(EG(global_u_constants_table));
+ }
+#endif
+ zend_hash_destroy(global_constants_table);
+ free(global_constants_table);
+ if (global_u_constants_table) {
+ zend_hash_destroy(global_u_constants_table);
+ free(global_u_constants_table);
+ }
+
+ free(global_function_table);
+ free(global_class_table);
+ if (global_u_function_table) {
+ free(global_u_function_table);
+ }
+ if (global_u_class_table) {
+ free(global_u_class_table);
+ }
#ifdef ZTS
zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
- zend_hash_destroy(GLOBAL_CONSTANTS_TABLE);
- free(GLOBAL_CONSTANTS_TABLE);
- GLOBAL_FUNCTION_TABLE = NULL;
- GLOBAL_CLASS_TABLE = NULL;
- GLOBAL_AUTO_GLOBALS_TABLE = NULL;
+ global_function_table = NULL;
+ global_class_table = NULL;
+ global_auto_globals_table = NULL;
+#else
+ unicode_globals_dtor(&unicode_globals TSRMLS_CC);
#endif
zend_destroy_rsrc_list_dtors();
}
@@ -779,9 +1395,54 @@ ZEND_API char *get_zend_version()
return zend_version_info;
}
+ZEND_API void zend_reset_locale_deps(TSRMLS_D)
+{
+ UErrorCode status = U_ZERO_ERROR;
+
+ if (UG(default_collator)) {
+ ucol_close(UG(default_collator));
+ }
+ UG(default_collator) = ucol_open(UG(default_locale), &status);
+ if (U_FAILURE(status)) {
+ zend_error(E_ERROR, "Could not open collator for locale %s", UG(default_locale));
+ }
+}
+
+static void init_unicode_request_globals(TSRMLS_D)
+{
+ UG(default_locale) = safe_estrdup(uloc_getDefault());
+ UG(default_collator) = NULL;
+
+ zend_reset_locale_deps(TSRMLS_C);
+}
+
+static void shutdown_unicode_request_globals(TSRMLS_D)
+{
+ ucol_close(UG(default_collator));
+ efree(UG(default_locale));
+}
void zend_activate(TSRMLS_D)
{
+#ifdef ZTS
+ CG(function_table) = UG(unicode)?CG(global_u_function_table):CG(global_function_table);
+ CG(class_table) = UG(unicode)?CG(global_u_class_table):CG(global_class_table);
+ CG(auto_globals) = UG(unicode)?CG(global_u_auto_globals_table):CG(global_auto_globals_table);
+ EG(zend_constants) = UG(unicode)?EG(global_u_constants_table):EG(global_constants_table);
+#else
+ CG(function_table) = UG(unicode)?global_u_function_table:global_function_table;
+ CG(class_table) = UG(unicode)?global_u_class_table:global_class_table;
+ CG(auto_globals) = UG(unicode)?global_u_auto_globals_table:global_auto_globals_table;
+ EG(zend_constants) = UG(unicode)?global_u_constants_table:global_constants_table;
+#endif
+ zend_standard_class_def = zend_get_named_class_entry("stdClass", sizeof("stdClass")-1 TSRMLS_CC);
+
+ init_unicode_request_globals(TSRMLS_C);
+
+ init_unicode_strings();
+ init_exceptions(TSRMLS_C);
+ init_interfaces(TSRMLS_C);
+ init_reflection_api(TSRMLS_C);
init_compiler(TSRMLS_C);
init_executor(TSRMLS_C);
startup_scanner(TSRMLS_C);
@@ -802,7 +1463,7 @@ void zend_deactivate_modules(TSRMLS_D)
} zend_end_try();
}
-void zend_call_destructors(TSRMLS_D)
+void zend_call_destructors(TSRMLS_D)
{
zend_try {
shutdown_destructors(TSRMLS_C);
@@ -815,6 +1476,8 @@ void zend_deactivate(TSRMLS_D)
EG(opline_ptr) = NULL;
EG(active_symbol_table) = NULL;
+ shutdown_unicode_request_globals(TSRMLS_C);
+
zend_try {
shutdown_scanner(TSRMLS_C);
} zend_end_try();
@@ -986,7 +1649,7 @@ ZEND_API void zend_error(int type, const char *format, ...)
orig_user_error_handler = EG(user_error_handler);
EG(user_error_handler) = NULL;
-
+
if (call_user_function_ex(CG(function_table), NULL, orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC)==SUCCESS) {
if (retval) {
if (Z_TYPE_P(retval) == IS_BOOL && Z_LVAL_P(retval) == 0) {
@@ -1052,6 +1715,9 @@ ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, ..
#endif
}
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(DARWIN)
+void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((alias("zend_error"),noreturn));
+#endif
ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...)
{
diff --git a/Zend/zend.h b/Zend/zend.h
index d2aa70b6ed..b517ceff95 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -35,6 +35,7 @@
#endif
#include <stdio.h>
+#include <assert.h>
/*
* general definitions
@@ -225,6 +226,8 @@ char *alloca ();
#include "zend_types.h"
+#include <unicode/utypes.h>
+
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
@@ -237,6 +240,8 @@ char *alloca ();
#define LONG_MIN (- LONG_MAX - 1)
#endif
+#define EMPTY_STR "\0\0"
+
#undef SUCCESS
#undef FAILURE
#define SUCCESS 0
@@ -258,6 +263,13 @@ void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((nore
# define zend_error_noreturn zend_error
#endif
+#if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(DARWIN)
+# define ZEND_VM_ALWAYS_INLINE __attribute__ ((always_inline))
+void zend_error_noreturn(int type, const char *format, ...) __attribute__ ((noreturn));
+#else
+# define ZEND_VM_ALWAYS_INLINE
+# define zend_error_noreturn zend_error
+#endif
/*
* zval
@@ -287,10 +299,14 @@ struct _zend_object_value {
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
- struct {
+ struct { /* 8-bit legacy string type */
char *val;
int len;
} str;
+ struct { /* Unicode string type */
+ UChar *val;
+ int32_t len;
+ } ustr;
HashTable *ht; /* hash table value */
zend_object_value obj;
} zvalue_value;
@@ -371,8 +387,8 @@ struct _zend_class_entry {
#include "zend_stream.h"
typedef struct _zend_utility_functions {
- void (*error_function)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
- int (*printf_function)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
+ void (*error_function)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
+ int (*printf_function)(const char *format, ...);
int (*write_function)(const char *str, uint str_length);
FILE *(*fopen_function)(const char *filename, char **opened_path);
void (*message_handler)(long message, void *data);
@@ -407,6 +423,8 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
((n) ? (((n)>0) ? 1 : -1) : 0)
#define ZEND_TRUTH(x) ((x) ? 1 : 0)
#define ZEND_LOG_XOR(a, b) (ZEND_TRUTH(a) ^ ZEND_TRUTH(b))
+#define ZEND_COLL_RESULT(n) \
+ ((n) == UCOL_EQUAL ? 0 : ((n) == UCOL_GREATER ? 1 : -1))
@@ -422,6 +440,8 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
#define IS_RESOURCE 7
#define IS_CONSTANT 8
#define IS_CONSTANT_ARRAY 9
+#define IS_UNICODE 10
+#define IS_BINARY 11
/* Ugly hack to support constants as static array indices */
#define IS_CONSTANT_INDEX 0x80
@@ -432,14 +452,13 @@ typedef int (*zend_write_func_t)(const char *str, uint str_length);
#define OE_IS_OBJECT (1<<1)
#define OE_IS_METHOD (1<<2)
-
int zend_startup(zend_utility_functions *utility_functions, char **extensions, int start_builtin_functions);
void zend_shutdown(TSRMLS_D);
void zend_register_standard_ini_entries(TSRMLS_D);
-#ifdef ZTS
+//#ifdef ZTS
void zend_post_startup(TSRMLS_D);
-#endif
+//#endif
void zend_set_utility_values(zend_utility_values *utility_values);
@@ -468,12 +487,14 @@ END_EXTERN_C()
BEGIN_EXTERN_C()
ZEND_API char *get_zend_version(void);
ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy);
+ZEND_API void zend_make_string_zval(zval *expr, zval *expr_copy, int *use_copy);
+ZEND_API void zend_make_unicode_zval(zval *expr, zval *expr_copy, int *use_copy);
ZEND_API int zend_print_zval(zval *expr, int indent);
ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent);
ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC);
ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC);
ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC);
-ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
+ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, ...);
END_EXTERN_C()
void zend_activate(TSRMLS_D);
@@ -510,20 +531,20 @@ END_EXTERN_C()
BEGIN_EXTERN_C()
-extern ZEND_API int (*zend_printf)(const char *format, ...) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 1, 2);
+extern ZEND_API int (*zend_printf)(const char *format, ...);
extern ZEND_API zend_write_func_t zend_write;
extern ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path);
extern ZEND_API void (*zend_block_interruptions)(void);
extern ZEND_API void (*zend_unblock_interruptions)(void);
extern ZEND_API void (*zend_ticks_function)(int ticks);
-extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) ZEND_ATTRIBUTE_PTR_FORMAT(printf, 4, 0);
+extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
extern void (*zend_on_timeout)(int seconds TSRMLS_DC);
extern ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
extern int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len TSRMLS_DC);
-ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
+ZEND_API void zend_error(int type, const char *format, ...);
void zenderror(char *error);
@@ -545,6 +566,7 @@ BEGIN_EXTERN_C()
ZEND_API void zend_message_dispatcher(long message, void *data);
ZEND_API int zend_get_configuration_directive(char *name, uint name_length, zval *contents);
+ZEND_API void zend_reset_locale_deps(TSRMLS_D);
END_EXTERN_C()
@@ -644,8 +666,15 @@ END_EXTERN_C()
#define ZEND_MAX_RESERVED_RESOURCES 4
+#define ZEND_INTERNAL_ENCODING "UTF-16"
+
#include "zend_variables.h"
+#define ZEND_U_EQUAL(type, ustr, ulen, str, slen) \
+ ((type == IS_STRING)? \
+ (!memcmp((ustr),(str),(slen))): \
+ (!zend_cmp_unicode_and_literal(((UChar*)(ustr)), ulen, str, slen)))
+
#endif /* ZEND_H */
/*
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 537cb9086e..852821c817 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -208,7 +208,7 @@ ZEND_API void zend_wrong_param_count(TSRMLS_D)
char *space;
char *class_name = get_active_class_name(&space TSRMLS_CC);
- zend_error(E_WARNING, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name(TSRMLS_C));
+ zend_error(E_WARNING, "Wrong parameter count for %v%s%v()", class_name, space, get_active_function_name(TSRMLS_C));
}
@@ -241,6 +241,12 @@ ZEND_API char *zend_zval_type_name(zval *arg)
case IS_RESOURCE:
return "resource";
+ case IS_UNICODE:
+ return "Unicode string";
+
+ case IS_BINARY:
+ return "binary data";
+
default:
return "unknown";
}
@@ -270,8 +276,22 @@ ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uin
return 0;
}
+#define RETURN_AS_STRING(arg, p, pl, type) \
+ *(char**)p = Z_STRVAL_PP(arg); \
+ *pl = Z_STRLEN_PP(arg); \
+ *type = IS_STRING;
+
+#define RETURN_AS_BINARY(arg, p, pl, type) \
+ *(char**)p = Z_BINVAL_PP(arg); \
+ *pl = Z_BINLEN_PP(arg); \
+ *type = IS_BINARY;
-static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec TSRMLS_DC)
+#define RETURN_AS_UNICODE(arg, p, pl, type) \
+ *(UChar**)p = Z_USTRVAL_PP(arg); \
+ *pl = Z_USTRLEN_PP(arg); \
+ *type = IS_UNICODE;
+
+static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec, char T_arg_type TSRMLS_DC)
{
char *spec_walk = *spec;
char c = *spec_walk++;
@@ -304,6 +324,19 @@ static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec TSRMLS_DC)
}
break;
+ case IS_UNICODE:
+ {
+ double d;
+ int type;
+
+ if ((type = is_numeric_unicode(Z_USTRVAL_PP(arg), Z_USTRLEN_PP(arg), p, &d, 0)) == 0) {
+ return "long";
+ } else if (type == IS_DOUBLE) {
+ *p = (long) d;
+ }
+ }
+ break;
+
case IS_NULL:
case IS_LONG:
case IS_DOUBLE:
@@ -338,6 +371,19 @@ static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec TSRMLS_DC)
}
break;
+ case IS_UNICODE:
+ {
+ long l;
+ int type;
+
+ if ((type = is_numeric_unicode(Z_USTRVAL_PP(arg), Z_USTRLEN_PP(arg), &l, p, 0)) == 0) {
+ return "double";
+ } else if (type == IS_LONG) {
+ *p = (double) l;
+ }
+ }
+ break;
+
case IS_NULL:
case IS_LONG:
case IS_DOUBLE:
@@ -372,10 +418,17 @@ static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec TSRMLS_DC)
case IS_LONG:
case IS_DOUBLE:
case IS_BOOL:
+ case IS_UNICODE:
convert_to_string_ex(arg);
*p = Z_STRVAL_PP(arg);
*pl = Z_STRLEN_PP(arg);
break;
+
+ case IS_BINARY:
+ *p = Z_BINVAL_PP(arg);
+ *pl = Z_BINLEN_PP(arg);
+ break;
+
case IS_OBJECT: {
if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
SEPARATE_ZVAL_IF_NOT_REF(arg);
@@ -383,6 +436,8 @@ static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec TSRMLS_DC)
*pl = Z_STRLEN_PP(arg);
*p = Z_STRVAL_PP(arg);
break;
+ } else {
+ return "string";
}
}
}
@@ -395,6 +450,175 @@ static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec TSRMLS_DC)
}
break;
+ case 'u':
+ {
+ UChar **p = va_arg(*va, UChar **);
+ int32_t *pl = va_arg(*va, int32_t *);
+ switch (Z_TYPE_PP(arg)) {
+ case IS_NULL:
+ if (return_null) {
+ *p = NULL;
+ *pl = 0;
+ break;
+ }
+ /* break omitted intentionally */
+
+ case IS_STRING:
+ case IS_LONG:
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_UNICODE:
+ convert_to_unicode_ex(arg);
+ *p = Z_USTRVAL_PP(arg);
+ *pl = Z_USTRLEN_PP(arg);
+ break;
+
+ case IS_OBJECT: {
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
+ SEPARATE_ZVAL_IF_NOT_REF(arg);
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_UNICODE, 0 TSRMLS_CC) == SUCCESS) {
+ *pl = Z_USTRLEN_PP(arg);
+ *p = Z_USTRVAL_PP(arg);
+ break;
+ } else {
+ return "string";
+ }
+ }
+ }
+
+ case IS_ARRAY:
+ case IS_RESOURCE:
+ default:
+ return "string";
+ }
+ }
+ break;
+
+ case 'T':
+ if (T_arg_type != -1)
+ {
+ void **p = va_arg(*va, void **);
+ int32_t *pl = va_arg(*va, int32_t *);
+ zend_uchar *type = va_arg(*va, zend_uchar *);
+ switch (Z_TYPE_PP(arg)) {
+ case IS_NULL:
+ if (return_null) {
+ *p = NULL;
+ *pl = 0;
+ *type = T_arg_type;
+ break;
+ }
+ /* break omitted intentionally */
+
+ case IS_LONG:
+ case IS_DOUBLE:
+ case IS_BOOL:
+ case IS_STRING:
+ case IS_UNICODE:
+ case IS_BINARY:
+ if (T_arg_type == IS_UNICODE) {
+ convert_to_unicode_ex(arg);
+ RETURN_AS_UNICODE(arg, p, pl, type);
+ } else if (T_arg_type == IS_STRING) {
+ convert_to_string_ex(arg);
+ RETURN_AS_STRING(arg, p, pl, type);
+ } else {
+ convert_to_binary_ex(arg);
+ RETURN_AS_BINARY(arg, p, pl, type);
+ }
+ break;
+
+ case IS_OBJECT: {
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
+ SEPARATE_ZVAL_IF_NOT_REF(arg);
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, T_arg_type, 0 TSRMLS_CC) == SUCCESS) {
+ *(char**)p = Z_UNIVAL_PP(arg);
+ *pl = Z_UNILEN_PP(arg);
+ *type = Z_TYPE_PP(arg);
+ RETURN_AS_UNICODE(arg, p, pl, type);
+ break;
+ }
+ }
+ }
+
+ case IS_ARRAY:
+ case IS_RESOURCE:
+ default:
+ return "string (legacy, Unicode, or binary)";
+ }
+
+ break;
+ }
+ /* break omitted intentionally */
+
+ case 't':
+ {
+ void **p = va_arg(*va, void **);
+ int32_t *pl = va_arg(*va, int32_t *);
+ zend_uchar *type = va_arg(*va, zend_uchar *);
+ switch (Z_TYPE_PP(arg)) {
+ case IS_NULL:
+ if (return_null) {
+ *p = NULL;
+ *pl = 0;
+ if (UG(unicode)) {
+ *type = IS_UNICODE;
+ } else {
+ *type = IS_STRING;
+ }
+ break;
+ }
+ /* break omitted intentionally */
+
+ case IS_LONG:
+ case IS_DOUBLE:
+ case IS_BOOL:
+ if (UG(unicode)) {
+ convert_to_unicode_ex(arg);
+ RETURN_AS_UNICODE(arg, p, pl, type);
+ } else {
+ convert_to_string_ex(arg);
+ RETURN_AS_STRING(arg, p, pl, type);
+ }
+ break;
+
+ case IS_STRING:
+ RETURN_AS_STRING(arg, p, pl, type);
+ break;
+
+ case IS_BINARY:
+ RETURN_AS_BINARY(arg, p, pl, type);
+ break;
+
+ case IS_UNICODE:
+ RETURN_AS_UNICODE(arg, p, pl, type);
+ break;
+
+ case IS_OBJECT: {
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)) {
+ SEPARATE_ZVAL_IF_NOT_REF(arg);
+ if (UG(unicode)) {
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_UNICODE, 0 TSRMLS_CC) == SUCCESS) {
+ RETURN_AS_UNICODE(arg, p, pl, type);
+ break;
+ }
+ } else {
+ if (Z_OBJ_HANDLER_PP(arg, cast_object)(*arg, *arg, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ RETURN_AS_STRING(arg, p, pl, type);
+ break;
+ }
+ }
+ }
+ }
+
+ case IS_ARRAY:
+ case IS_RESOURCE:
+ default:
+ return "string (legacy, Unicode, or binary)";
+ }
+ }
+ break;
+
case 'b':
{
zend_bool *p = va_arg(*va, zend_bool *);
@@ -506,17 +730,17 @@ static char *zend_parse_arg_impl(zval **arg, va_list *va, char **spec TSRMLS_DC)
return NULL;
}
-static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet TSRMLS_DC)
+static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet, char T_arg_type TSRMLS_DC)
{
char *expected_type = NULL;
- expected_type = zend_parse_arg_impl(arg, va, spec TSRMLS_CC);
+ expected_type = zend_parse_arg_impl(arg, va, spec, T_arg_type TSRMLS_CC);
if (expected_type) {
if (!quiet) {
char *space;
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",
+ zend_error(E_WARNING, "%v%s%v() expects parameter %d to be %s, %s given",
class_name, space, get_active_function_name(TSRMLS_C), arg_num, expected_type,
zend_zval_type_name(*arg));
}
@@ -536,15 +760,22 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
void **p;
int arg_count;
int quiet = flags & ZEND_PARSE_PARAMS_QUIET;
+ zend_bool T_present = 0;
+ char T_arg_type = -1;
for (spec_walk = type_spec; *spec_walk; spec_walk++) {
c = *spec_walk;
switch (c) {
+ case 'T':
+ T_present++;
+ /* break omitted intentionally */
case 'l': case 'd':
case 's': case 'b':
case 'r': case 'a':
case 'o': case 'O':
case 'z': case 'Z':
+ case 't':
+ case 'u':
max_num_args++;
break;
@@ -560,8 +791,8 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
default:
if (!quiet) {
zend_function *active_function = EG(function_state_ptr)->function;
- char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
- zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters",
+ char *class_name = active_function->common.scope ? active_function->common.scope->name : EMPTY_STR;
+ zend_error(E_WARNING, "%v%s%v(): bad type specifier while parsing parameters",
class_name,
class_name[0] ? "::" : "",
get_active_function_name(TSRMLS_C));
@@ -577,8 +808,8 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
if (num_args < min_num_args || num_args > max_num_args) {
if (!quiet) {
zend_function *active_function = EG(function_state_ptr)->function;
- char *class_name = active_function->common.scope ? active_function->common.scope->name : "";
- zend_error(E_WARNING, "%s%s%s() expects %s %d parameter%s, %d given",
+ char *class_name = active_function->common.scope ? active_function->common.scope->name : EMPTY_STR;
+ zend_error(E_WARNING, "%v%s%v() expects %s %d parameter%s, %d given",
class_name,
class_name[0] ? "::" : "",
get_active_function_name(TSRMLS_C),
@@ -594,18 +825,48 @@ static int zend_parse_va_args(int num_args, char *type_spec, va_list *va, int fl
arg_count = (ulong) *p;
if (num_args > arg_count) {
- zend_error(E_WARNING, "%s(): could not obtain parameters for parsing",
- get_active_function_name(TSRMLS_C));
+ zend_error(E_WARNING, "%v(): could not obtain parameters for parsing",
+ get_active_function_name(TSRMLS_C));
return FAILURE;
}
+ if (T_present > 1) {
+ /* determine 'T' target argument type */
+ for (spec_walk = type_spec, i = 0; *spec_walk && i < num_args; spec_walk++) {
+ switch (*spec_walk) {
+ case 'T':
+ arg = (zval **) p - (arg_count-i);
+ if (Z_TYPE_PP(arg) == IS_BINARY) {
+ /* we can always convert to binary */
+ T_arg_type = IS_BINARY;
+ } else if (Z_TYPE_PP(arg) == IS_UNICODE && (T_arg_type == -1 || T_arg_type == IS_STRING)) {
+ /* we can upgrade from strings to Unicode */
+ T_arg_type = IS_UNICODE;
+ } else if (Z_TYPE_PP(arg) == IS_STRING && T_arg_type == -1) {
+ T_arg_type = IS_STRING;
+ }
+ i++;
+ break;
+
+ case '|': case '!':
+ case '/':
+ /* pass */
+ break;
+
+ default:
+ i++;
+ break;
+ }
+ }
+ }
+
i = 0;
while (num_args-- > 0) {
arg = (zval **) p - (arg_count-i);
if (*type_spec == '|') {
type_spec++;
}
- if (zend_parse_arg(i+1, arg, va, &type_spec, quiet TSRMLS_CC) == FAILURE) {
+ if (zend_parse_arg(i+1, arg, va, &type_spec, quiet, T_arg_type TSRMLS_CC) == FAILURE) {
return FAILURE;
}
i++;
@@ -658,7 +919,7 @@ ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr
ce = va_arg(va, zend_class_entry *);
*object = this_ptr;
if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
- zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
+ zend_error(E_CORE_ERROR, "%v::%v() must be derived from %v::%v",
ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
}
@@ -691,7 +952,7 @@ ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC,
*object = this_ptr;
if (ce && !instanceof_function(Z_OBJCE_P(this_ptr), ce TSRMLS_CC)) {
if (!quiet) {
- zend_error(E_CORE_ERROR, "%s::%s() must be derived from %s::%s",
+ zend_error(E_CORE_ERROR, "%v::%v() must be derived from %v::%v",
ce->name, get_active_function_name(TSRMLS_C), Z_OBJCE_P(this_ptr)->name, get_active_function_name(TSRMLS_C));
}
return FAILURE;
@@ -709,9 +970,11 @@ ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC,
ZEND_API int _array_init(zval *arg ZEND_FILE_LINE_DC)
{
+ TSRMLS_FETCH();
+
ALLOC_HASHTABLE_REL(arg->value.ht);
- _zend_hash_init(arg->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0 ZEND_FILE_LINE_RELAY_CC);
+ zend_u_hash_init(arg->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
arg->type = IS_ARRAY;
return SUCCESS;
}
@@ -726,7 +989,7 @@ static int zend_merge_property(zval **value, int num_args, va_list args, zend_ha
zval member;
TSRMLS_FETCH();
- ZVAL_STRINGL(&member, hash_key->arKey, hash_key->nKeyLength-1, 0);
+ ZVAL_STRINGL(&member, hash_key->u.string, hash_key->nKeyLength-1, 0);
obj_ht->write_property(obj, &member, *value TSRMLS_CC);
}
return ZEND_HASH_APPLY_KEEP;
@@ -777,7 +1040,7 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type
if (class_type->ce_flags & (ZEND_ACC_INTERFACE|ZEND_ACC_IMPLICIT_ABSTRACT_CLASS|ZEND_ACC_EXPLICIT_ABSTRACT_CLASS)) {
char *what = class_type->ce_flags & ZEND_ACC_INTERFACE ? "interface" : "abstract class";
- zend_error(E_ERROR, "Cannot instantiate %s %s", what, class_type->name);
+ zend_error(E_ERROR, "Cannot instantiate %s %v", what, class_type->name);
}
zend_update_class_constants(class_type TSRMLS_CC);
@@ -789,7 +1052,7 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type
object->properties = properties;
} else {
ALLOC_HASHTABLE_REL(object->properties);
- zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
}
} else {
@@ -889,11 +1152,36 @@ ZEND_API int add_assoc_stringl_ex(zval *arg, char *key, uint key_len, char *str,
return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
}
+ZEND_API int add_assoc_unicode_ex(zval *arg, char *key, uint key_len, void *str, int duplicate)
+{
+ zval *tmp;
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_UNICODE(tmp, str, duplicate);
+
+ return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
+}
+
+
+ZEND_API int add_assoc_unicodel_ex(zval *arg, char *key, uint key_len, void *str, uint length, int duplicate)
+{
+ zval *tmp;
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_UNICODEL(tmp, str, length, duplicate);
+
+ return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL);
+}
+
ZEND_API int add_assoc_zval_ex(zval *arg, char *key, uint key_len, zval *value)
{
return zend_symtable_update(Z_ARRVAL_P(arg), key, key_len, (void *) &value, sizeof(zval *), NULL);
}
+ZEND_API int add_u_assoc_zval_ex(zval *arg, zend_uchar type, void *key, uint key_len, zval *value)
+{
+ return zend_u_symtable_update(Z_ARRVAL_P(arg), type, key, key_len, (void *) &value, sizeof(zval *), NULL);
+}
ZEND_API int add_index_long(zval *arg, uint index, long n)
{
@@ -971,6 +1259,50 @@ ZEND_API int add_index_stringl(zval *arg, uint index, char *str, uint length, in
}
+ZEND_API int add_index_binary(zval *arg, uint index, char *str, int duplicate)
+{
+ zval *tmp;
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_BINARY(tmp, str, duplicate);
+
+ return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
+}
+
+
+ZEND_API int add_index_binaryl(zval *arg, uint index, char *str, uint length, int duplicate)
+{
+ zval *tmp;
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_BINARYL(tmp, str, length, duplicate);
+
+ return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
+}
+
+
+ZEND_API int add_index_unicode(zval *arg, uint index, UChar *str, int duplicate)
+{
+ zval *tmp;
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_UNICODE(tmp, str, duplicate);
+
+ return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
+}
+
+
+ZEND_API int add_index_unicodel(zval *arg, uint index, UChar *str, uint length, int duplicate)
+{
+ zval *tmp;
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_UNICODEL(tmp, str, length, duplicate);
+
+ return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), NULL);
+}
+
+
ZEND_API int add_index_zval(zval *arg, uint index, zval *value)
{
return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &value, sizeof(zval *), NULL);
@@ -1054,6 +1386,51 @@ ZEND_API int add_next_index_stringl(zval *arg, char *str, uint length, int dupli
}
+ZEND_API int add_next_index_binary(zval *arg, char *str, int duplicate)
+{
+ zval *tmp;
+ TSRMLS_FETCH();
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_BINARY(tmp, str, duplicate);
+
+ return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
+}
+
+
+ZEND_API int add_next_index_binaryl(zval *arg, char *str, uint length, int duplicate)
+{
+ zval *tmp;
+ TSRMLS_FETCH();
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_BINARYL(tmp, str, length, duplicate);
+
+ return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
+}
+
+ZEND_API int add_next_index_unicode(zval *arg, UChar *str, int duplicate)
+{
+ zval *tmp;
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_UNICODE(tmp, str, duplicate);
+
+ return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
+}
+
+
+ZEND_API int add_next_index_unicodel(zval *arg, UChar *str, uint length, int duplicate)
+{
+ zval *tmp;
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_UNICODEL(tmp, str, length, duplicate);
+
+ return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &tmp, sizeof(zval *), NULL);
+}
+
+
ZEND_API int add_next_index_zval(zval *arg, zval *value)
{
return zend_hash_next_index_insert(Z_ARRVAL_P(arg), &value, sizeof(zval *), NULL);
@@ -1125,6 +1502,50 @@ ZEND_API int add_get_index_stringl(zval *arg, uint index, char *str, uint length
return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
}
+ZEND_API int add_get_index_binary(zval *arg, uint index, char *str, void **dest, int duplicate)
+{
+ zval *tmp;
+ TSRMLS_FETCH();
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_BINARY(tmp, str, duplicate);
+
+ return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
+}
+
+
+ZEND_API int add_get_index_binaryl(zval *arg, uint index, char *str, uint length, void **dest, int duplicate)
+{
+ zval *tmp;
+ TSRMLS_FETCH();
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_BINARYL(tmp, str, length, duplicate);
+
+ return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
+}
+
+
+ZEND_API int add_get_index_unicode(zval *arg, uint index, UChar *str, void **dest, int duplicate)
+{
+ zval *tmp;
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_UNICODE(tmp, str, duplicate);
+
+ return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
+}
+
+
+ZEND_API int add_get_index_unicodel(zval *arg, uint index, UChar *str, uint length, void **dest, int duplicate)
+{
+ zval *tmp;
+
+ MAKE_STD_ZVAL(tmp);
+ ZVAL_UNICODEL(tmp, str, length, duplicate);
+
+ return zend_hash_index_update(Z_ARRVAL_P(arg), index, (void *) &tmp, sizeof(zval *), dest);
+}
ZEND_API int add_property_long_ex(zval *arg, char *key, uint key_len, long n TSRMLS_DC)
{
@@ -1391,30 +1812,43 @@ ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *mod
ZEND_API void zend_check_magic_method_implementation(zend_class_entry *ce, zend_function *fptr, int error_type TSRMLS_DC)
{
- char lcname[16];
+ unsigned int lcname_len;
+ char *lcname;
int name_len;
+ zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
/* we don't care if the function name is longer, in fact lowercasing only
* the beginning of the name speeds up the check process */
- name_len = strlen(fptr->common.function_name);
- zend_str_tolower_copy(lcname, fptr->common.function_name, MIN(name_len, sizeof(lcname)-1));
- lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
-
- if (name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)) && fptr->common.num_args != 0) {
- zend_error(error_type, "Destuctor %s::%s() cannot take arguments", ce->name, ZEND_DESTRUCTOR_FUNC_NAME);
- } else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)) && fptr->common.num_args != 0) {
- zend_error(error_type, "Method %s::%s() cannot accept any arguments", ce->name, ZEND_CLONE_FUNC_NAME);
- } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)) && fptr->common.num_args != 1) {
- zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_GET_FUNC_NAME);
- } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)) && fptr->common.num_args != 2) {
- zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_SET_FUNC_NAME);
- } else if (name_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)) && fptr->common.num_args != 1) {
- zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_UNSET_FUNC_NAME);
- } else if (name_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)) && fptr->common.num_args != 1) {
- zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_ISSET_FUNC_NAME);
- } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)) && fptr->common.num_args != 2) {
- zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME);
+ if (UG(unicode)) {
+ name_len = u_strlen((UChar*)fptr->common.function_name);
+ } else {
+ name_len = strlen(fptr->common.function_name);
+ }
+ lcname = zend_u_str_case_fold(utype, fptr->common.function_name, name_len, 0, &lcname_len);
+
+ if (lcname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME) - 1 &&
+ ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && fptr->common.num_args != 0) {
+ zend_error(error_type, "Destuctor %v::%s() cannot take arguments", ce->name, ZEND_DESTRUCTOR_FUNC_NAME);
+ } else if (lcname_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 &&
+ ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1) && fptr->common.num_args != 0) {
+ zend_error(error_type, "Method %v::%s() cannot accept any arguments", ce->name, ZEND_CLONE_FUNC_NAME);
+ } else if (lcname_len == sizeof(ZEND_GET_FUNC_NAME) - 1 &&
+ ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1) && fptr->common.num_args != 1) {
+ zend_error(error_type, "Method %v::%s() must take exactly 1 argument", ce->name, ZEND_GET_FUNC_NAME);
+ } else if (lcname_len == sizeof(ZEND_SET_FUNC_NAME) - 1 &&
+ ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1) && fptr->common.num_args != 2) {
+ zend_error(error_type, "Method %v::%s() must take exactly 2 arguments", ce->name, ZEND_SET_FUNC_NAME);
+ } else if (lcname_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 &&
+ ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1) && fptr->common.num_args != 1) {
+ zend_error(error_type, "Method %v::%s() must take exactly 1 arguments", ce->name, ZEND_UNSET_FUNC_NAME);
+ } else if (lcname_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 &&
+ ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1) && fptr->common.num_args != 1) {
+ zend_error(error_type, "Method %v::%s() must take exactly 1 arguments", ce->name, ZEND_ISSET_FUNC_NAME);
+ } else if (lcname_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 &&
+ ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1) && fptr->common.num_args != 2) {
+ zend_error(error_type, "Method %v::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME);
}
+ efree(lcname);
}
/* registers all functions in *library_functions in the function hash */
@@ -1444,7 +1878,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
internal_function->type = ZEND_INTERNAL_FUNCTION;
if (scope) {
- class_name_len = strlen(scope->name);
+ class_name_len = scope->name_length;
lc_class_name = zend_str_tolower_dup(scope->name, class_name_len);
}
@@ -1473,7 +1907,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
}
if (ptr->flags) {
if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
- zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
+ zend_error(error_type, "Invalid access level for %s%s%s() - access must be exactly one of public, protected or private", scope ? scope->name : EMPTY_STR, scope ? "::" : "", ptr->fname);
internal_function->fn_flags = ZEND_ACC_PUBLIC;
} else {
internal_function->fn_flags = ptr->flags;
@@ -1498,7 +1932,7 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
return FAILURE;
}
if (!internal_function->handler) {
- zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
+ zend_error(error_type, "Method %s%s%s() cannot be a NULL function", scope ? scope->name : EMPTY_STR, scope ? "::" : "", ptr->fname);
zend_unregister_functions(functions, count, target_function_table TSRMLS_CC);
return FAILURE;
}
@@ -1550,11 +1984,11 @@ ZEND_API int zend_register_functions(zend_class_entry *scope, zend_function_entr
}
if (unload) { /* before unloading, display all remaining bad function in the module */
if (scope) {
- efree(lc_class_name);
+ free_alloca(lc_class_name);
}
while (ptr->fname) {
if (zend_hash_exists(target_function_table, ptr->fname, strlen(ptr->fname)+1)) {
- zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name : "", scope ? "::" : "", ptr->fname);
+ zend_error(error_type, "Function registration failed - duplicate name - %s%s%s", scope ? scope->name : EMPTY_STR, scope ? "::" : "", ptr->fname);
}
ptr++;
}
@@ -1694,9 +2128,9 @@ void module_destructor(zend_module_entry *module)
#if HAVE_LIBDL || defined(HAVE_MACH_O_DYLD_H)
#if !(defined(NETWARE) && defined(APACHE_1_BUILD))
- if (module->handle) {
- DL_UNLOAD(module->handle);
- }
+ if (module->handle) {
+ DL_UNLOAD(module->handle);
+ }
#endif
#endif
}
@@ -1832,21 +2266,21 @@ ZEND_API zend_class_entry *zend_register_internal_interface(zend_class_entry *or
ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length,
zend_bool is_ref, int num_symbol_tables, ...)
{
- HashTable *symbol_table;
- va_list symbol_table_list;
+ HashTable *symbol_table;
+ va_list symbol_table_list;
- if (num_symbol_tables <= 0) return FAILURE;
+ if (num_symbol_tables <= 0) return FAILURE;
- symbol->is_ref = is_ref;
+ symbol->is_ref = is_ref;
- va_start(symbol_table_list, num_symbol_tables);
- while (num_symbol_tables-- > 0) {
- symbol_table = va_arg(symbol_table_list, HashTable *);
- zend_hash_update(symbol_table, name, name_length + 1, &symbol, sizeof(zval *), NULL);
- zval_add_ref(&symbol);
- }
- va_end(symbol_table_list);
- return SUCCESS;
+ va_start(symbol_table_list, num_symbol_tables);
+ while (num_symbol_tables-- > 0) {
+ symbol_table = va_arg(symbol_table_list, HashTable *);
+ zend_hash_update(symbol_table, name, name_length + 1, &symbol, sizeof(zval *), NULL);
+ zval_add_ref(&symbol);
+ }
+ va_end(symbol_table_list);
+ return SUCCESS;
}
@@ -1856,7 +2290,7 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length,
ZEND_API ZEND_FUNCTION(display_disabled_function)
{
- zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name(TSRMLS_C));
+ zend_error(E_WARNING, "%v() has been disabled for security reasons", get_active_function_name(TSRMLS_C));
}
@@ -1881,8 +2315,8 @@ static zend_object_value display_disabled_class(zend_class_entry *class_type TSR
zend_object *intern;
retval = zend_objects_new(&intern, class_type TSRMLS_CC);
ALLOC_HASHTABLE(intern->properties);
- zend_hash_init(intern->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
- zend_error(E_WARNING, "%s() has been disabled for security reasons", class_type->name);
+ zend_u_hash_init(intern->properties, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
+ zend_error(E_WARNING, "%v() has been disabled for security reasons", class_type->name);
return retval;
}
@@ -1907,6 +2341,7 @@ ZEND_API int zend_disable_class(char *class_name, uint class_name_length TSRMLS_
ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **callable_name, int *callable_name_len, zend_function **fptr_ptr, zval ***zobj_ptr_ptr TSRMLS_DC)
{
+ unsigned int lcname_len;
char *lcname;
zend_bool retval = 0;
int callable_name_len_local;
@@ -1927,16 +2362,22 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **
switch (Z_TYPE_P(callable)) {
case IS_STRING:
+ case IS_UNICODE:
if (callable_name) {
- *callable_name = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
- *callable_name_len = Z_STRLEN_P(callable);
+ /* UTODO: we need to return callable name type as well */
+ if (Z_TYPE_P(callable) == IS_UNICODE) {
+ *callable_name = (char*)eustrndup(Z_USTRVAL_P(callable), Z_USTRLEN_P(callable));
+ } else {
+ *callable_name = estrndup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
+ }
+ *callable_name_len = Z_UNILEN_P(callable);
}
if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY) {
return 1;
}
- lcname = zend_str_tolower_dup(Z_STRVAL_P(callable), Z_STRLEN_P(callable));
- if (zend_hash_find(EG(function_table), lcname, Z_STRLEN_P(callable)+1, (void**)fptr_ptr) == SUCCESS) {
+ lcname = zend_u_str_case_fold(Z_TYPE_P(callable), Z_UNIVAL_P(callable), Z_UNILEN_P(callable), 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(callable), lcname, lcname_len+1, (void**)fptr_ptr) == SUCCESS) {
retval = 1;
}
efree(lcname);
@@ -1951,10 +2392,13 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **
if (zend_hash_num_elements(Z_ARRVAL_P(callable)) == 2 &&
zend_hash_index_find(Z_ARRVAL_P(callable), 0, (void **) &obj) == SUCCESS &&
zend_hash_index_find(Z_ARRVAL_P(callable), 1, (void **) &method) == SUCCESS &&
- (Z_TYPE_PP(obj) == IS_OBJECT || Z_TYPE_PP(obj) == IS_STRING) &&
- Z_TYPE_PP(method) == IS_STRING) {
+ (Z_TYPE_PP(obj) == IS_OBJECT ||
+ Z_TYPE_PP(obj) == IS_STRING ||
+ Z_TYPE_PP(obj) == IS_UNICODE) &&
+ (Z_TYPE_PP(method) == IS_STRING ||
+ Z_TYPE_PP(method) == IS_UNICODE)) {
- if (Z_TYPE_PP(obj) == IS_STRING) {
+ if (Z_TYPE_PP(obj) == IS_STRING || Z_TYPE_PP(obj) == IS_UNICODE) {
if (callable_name) {
char *ptr;
@@ -1970,13 +2414,17 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **
if (check_flags & IS_CALLABLE_CHECK_SYNTAX_ONLY)
return 1;
- lcname = zend_str_tolower_dup(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj));
+ lcname = zend_u_str_case_fold(Z_TYPE_PP(obj), Z_UNIVAL_PP(obj), Z_UNILEN_PP(obj), 1, &lcname_len);
- if (EG(active_op_array) && strcmp(lcname, "self") == 0) {
+ if (EG(active_op_array) &&
+ lcname_len == sizeof("self")-1 &&
+ ZEND_U_EQUAL(Z_TYPE_PP(obj), lcname, lcname_len, "self", sizeof("self")-1)) {
ce = EG(active_op_array)->scope;
- } else if (strcmp(lcname, "parent") == 0 && EG(active_op_array) && EG(active_op_array)->scope) {
+ } else if (EG(active_op_array) && EG(active_op_array)->scope &&
+ lcname_len == sizeof("parent")-1 &&
+ ZEND_U_EQUAL(Z_TYPE_PP(obj), lcname, lcname_len, "parent", sizeof("parent")-1)) {
ce = EG(active_op_array)->scope->parent;
- } else if (zend_lookup_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), &pce TSRMLS_CC) == SUCCESS) {
+ } else if (zend_u_lookup_class(Z_TYPE_PP(obj), Z_UNIVAL_PP(obj), Z_UNILEN_PP(obj), &pce TSRMLS_CC) == SUCCESS) {
ce = *pce;
}
@@ -2005,8 +2453,8 @@ ZEND_API zend_bool zend_is_callable_ex(zval *callable, uint check_flags, char **
if (ce) {
zend_function *fbc;
- lcname = zend_str_tolower_dup(Z_STRVAL_PP(method), Z_STRLEN_PP(method));
- if (zend_hash_find(&ce->function_table, lcname, Z_STRLEN_PP(method)+1, (void **)&fbc) == SUCCESS) {
+ lcname = zend_u_str_case_fold(Z_TYPE_PP(method), Z_STRVAL_PP(method), Z_STRLEN_PP(method), 1, &lcname_len);
+ if (zend_u_hash_find(&ce->function_table, Z_TYPE_PP(method), lcname, lcname_len+1, (void **)&fbc) == SUCCESS) {
retval = 1;
if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0) {
if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) {
@@ -2105,19 +2553,13 @@ ZEND_API char *zend_get_module_version(char *module_name)
zend_module_entry *module;
if (zend_hash_find(&module_registry, module_name, strlen(module_name) + 1,
- (void**)&module) == FAILURE) {
+ (void**)&module) == FAILURE) {
return NULL;
}
- return module->version;
-}
-
-
-ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC)
-{
- return zend_declare_property_ex(ce, name, name_length, property, access_type, NULL, 0 TSRMLS_CC);
+ return module->version;
}
-ZEND_API int zend_declare_property_ex(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC)
+ZEND_API int zend_u_declare_property_ex(zend_class_entry *ce, zend_uchar type, void *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC)
{
zend_property_info property_info;
HashTable *target_symbol_table;
@@ -2147,8 +2589,8 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, char *name, int name
char *priv_name;
int priv_name_length;
- zend_mangle_property_name(&priv_name, &priv_name_length, ce->name, ce->name_length, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
- zend_hash_update(target_symbol_table, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL);
+ zend_u_mangle_property_name(&priv_name, &priv_name_length, type, ce->name, ce->name_length, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
+ zend_u_hash_update(target_symbol_table, type, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL);
property_info.name = priv_name;
property_info.name_length = priv_name_length;
}
@@ -2157,8 +2599,8 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, char *name, int name
char *prot_name;
int prot_name_length;
- zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
- zend_hash_update(target_symbol_table, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
+ zend_u_mangle_property_name(&prot_name, &prot_name_length, type, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
+ zend_u_hash_update(target_symbol_table, type, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL);
property_info.name = prot_name;
property_info.name_length = prot_name_length;
}
@@ -2168,26 +2610,43 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, char *name, int name
char *prot_name;
int prot_name_length;
- zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
- zend_hash_del(target_symbol_table, prot_name, prot_name_length+1);
+ zend_u_mangle_property_name(&prot_name, &prot_name_length, type, "*", 1, name, name_length, ce->type & ZEND_INTERNAL_CLASS);
+ zend_u_hash_del(target_symbol_table, type, prot_name, prot_name_length+1);
pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
}
- zend_hash_update(target_symbol_table, name, name_length+1, &property, sizeof(zval *), NULL);
- property_info.name = ce->type & ZEND_INTERNAL_CLASS ? zend_strndup(name, name_length) : estrndup(name, name_length);
+ zend_u_hash_update(target_symbol_table, type, name, name_length+1, &property, sizeof(zval *), NULL);
+ property_info.name = ce->type & ZEND_INTERNAL_CLASS ?
+ (type==IS_UNICODE?(char*)zend_ustrndup(name, name_length):zend_strndup(name, name_length)) :
+ (type==IS_UNICODE?(char*)eustrndup(name, name_length):estrndup(name, name_length));
property_info.name_length = name_length;
break;
}
property_info.flags = access_type;
- property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1);
+ property_info.h = zend_u_get_hash_value(type, property_info.name, property_info.name_length+1);
property_info.doc_comment = doc_comment;
property_info.doc_comment_len = doc_comment_len;
- zend_hash_update(&ce->properties_info, name, name_length + 1, &property_info, sizeof(zend_property_info), NULL);
+ zend_u_hash_update(&ce->properties_info, type, name, name_length + 1, &property_info, sizeof(zend_property_info), NULL);
return SUCCESS;
}
+ZEND_API int zend_declare_property_ex(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type, char *doc_comment, int doc_comment_len TSRMLS_DC)
+{
+ return zend_u_declare_property_ex(ce, IS_STRING, name, name_length, property, access_type, NULL, 0 TSRMLS_CC);
+}
+
+ZEND_API int zend_u_declare_property(zend_class_entry *ce, zend_uchar type, void *name, int name_length, zval *property, int access_type TSRMLS_DC)
+{
+ return zend_u_declare_property_ex(ce, type, name, name_length, property, access_type, NULL, 0 TSRMLS_CC);
+}
+
+ZEND_API int zend_declare_property(zend_class_entry *ce, char *name, int name_length, zval *property, int access_type TSRMLS_DC)
+{
+ return zend_u_declare_property_ex(ce, IS_STRING, name, name_length, property, access_type, NULL, 0 TSRMLS_CC);
+}
+
ZEND_API int zend_declare_property_null(zend_class_entry *ce, char *name, int name_length, int access_type TSRMLS_DC)
{
zval *property;
@@ -2287,7 +2746,7 @@ ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *
zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
- zend_error(E_CORE_ERROR, "Property %s of class %s cannot be updated", name, class_name);
+ zend_error(E_CORE_ERROR, "Property %s of class %v cannot be updated", name, class_name);
}
ZVAL_STRINGL(&property, name, name_length, 0);
Z_OBJ_HT_P(object)->write_property(object, &property, value TSRMLS_CC);
@@ -2373,7 +2832,7 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *n
zend_uint class_name_len;
zend_get_object_classname(object, &class_name, &class_name_len TSRMLS_CC);
- zend_error(E_CORE_ERROR, "Property %s of class %s cannot be read", name, class_name);
+ zend_error(E_CORE_ERROR, "Property %s of class %v cannot be read", name, class_name);
}
ZVAL_STRINGL(&property, name, name_length, 0);
value = Z_OBJ_HT_P(object)->read_property(object, &property, silent TSRMLS_CC);
@@ -2382,6 +2841,50 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *n
return value;
}
+ZEND_API zend_class_entry* zend_get_named_class_entry(char* name, int name_length TSRMLS_DC)
+{
+ zend_class_entry **scope;
+ char *lcname = do_alloca(name_length+1);
+
+ zend_str_tolower_copy(lcname, name, name_length);
+ if (zend_hash_find(CG(class_table), lcname, name_length+1, (void**)&scope) == FAILURE) {
+ free_alloca(lcname);
+ zend_error(E_ERROR, "Class '%s' is not defined", name);
+ return NULL;
+ }
+ free_alloca(lcname);
+ return *scope;
+}
+
+
+/*
+ * Return the most precise string type out of the list.
+ * If none of the types are string types, IS_STRING is returned.
+ * Binary > Unicode > string.
+ */
+ZEND_API zend_uchar zend_get_best_string_type(int num_args, ...)
+{
+ va_list ap;
+ int best_type = IS_STRING;
+ int type;
+
+ if (num_args <= 0) return -1;
+
+ va_start(ap, num_args);
+ while (num_args--) {
+ type = va_arg(ap, int);
+ if (type == IS_BINARY) {
+ best_type = IS_BINARY;
+ break;
+ } else if (type == IS_UNICODE && best_type == IS_STRING) {
+ best_type = IS_UNICODE;
+ }
+ }
+ va_end(ap);
+
+ return best_type;
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index d42c914512..38b4a9f199 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -126,6 +126,8 @@ typedef struct _zend_function_entry {
class_container.constructor = NULL; \
class_container.destructor = NULL; \
class_container.clone = NULL; \
+ class_container.serialize = NULL; \
+ class_container.unserialize = NULL; \
class_container.create_object = NULL; \
class_container.interface_gets_implemented = NULL; \
class_container.__call = handle_fcall; \
@@ -212,6 +214,8 @@ ZEND_API int zend_declare_property_double(zend_class_entry *ce, char *name, int
ZEND_API int zend_declare_property_string(zend_class_entry *ce, char *name, int name_length, char *value, int access_type TSRMLS_DC);
ZEND_API int zend_declare_property_stringl(zend_class_entry *ce, char *name, int name_length, char *value, int value_len, int access_type TSRMLS_DC);
+ZEND_API int zend_u_declare_property(zend_class_entry *ce, zend_uchar type, void *name, int name_length, zval *property, int access_type TSRMLS_DC);
+
ZEND_API void zend_update_class_constants(zend_class_entry *class_type TSRMLS_DC);
ZEND_API void zend_update_property(zend_class_entry *scope, zval *object, char *name, int name_length, zval *value TSRMLS_DC);
ZEND_API void zend_update_property_null(zend_class_entry *scope, zval *object, char *name, int name_length TSRMLS_DC);
@@ -225,6 +229,7 @@ ZEND_API zval *zend_read_property(zend_class_entry *scope, zval *object, char *n
ZEND_API zend_class_entry *zend_get_class_entry(zval *zobject TSRMLS_DC);
ZEND_API int zend_get_object_classname(zval *object, char **class_name, zend_uint *class_name_len TSRMLS_DC);
+ZEND_API zend_uchar zend_get_best_string_type(int num_args, ...);
#define getThis() (this_ptr)
@@ -260,6 +265,8 @@ ZEND_API int add_assoc_resource_ex(zval *arg, char *key, uint key_len, int r);
ZEND_API int add_assoc_double_ex(zval *arg, char *key, uint key_len, double d);
ZEND_API int add_assoc_string_ex(zval *arg, char *key, uint key_len, char *str, int duplicate);
ZEND_API int add_assoc_stringl_ex(zval *arg, char *key, uint key_len, char *str, uint length, int duplicate);
+ZEND_API int add_assoc_unicode_ex(zval *arg, char *key, uint key_len, void *str, int duplicate);
+ZEND_API int add_assoc_unicodel_ex(zval *arg, char *key, uint key_len, void *str, uint length, int duplicate);
ZEND_API int add_assoc_zval_ex(zval *arg, char *key, uint key_len, zval *value);
#define add_assoc_long(__arg, __key, __n) add_assoc_long_ex(__arg, __key, strlen(__key)+1, __n)
@@ -269,8 +276,14 @@ ZEND_API int add_assoc_zval_ex(zval *arg, char *key, uint key_len, zval *value);
#define add_assoc_double(__arg, __key, __d) add_assoc_double_ex(__arg, __key, strlen(__key)+1, __d)
#define add_assoc_string(__arg, __key, __str, __duplicate) add_assoc_string_ex(__arg, __key, strlen(__key)+1, __str, __duplicate)
#define add_assoc_stringl(__arg, __key, __str, __length, __duplicate) add_assoc_stringl_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate)
+#define add_assoc_unicode(__arg, __key, __str, __duplicate) add_assoc_unicode_ex(__arg, __key, strlen(__key)+1, __str, __duplicate)
+#define add_assoc_unicodel(__arg, __key, __str, __length, __duplicate) add_assoc_unicodel_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate)
#define add_assoc_zval(__arg, __key, __value) add_assoc_zval_ex(__arg, __key, strlen(__key)+1, __value)
+ZEND_API int add_u_assoc_zval_ex(zval *arg, zend_uchar type, void *key, uint key_len, zval *value);
+
+#define add_u_assoc_zval(__arg, __type, __key, __value) add_u_assoc_zval_ex(__arg, __type, __key, (((__type)==IS_UNICODE)?u_strlen((UChar*)__key):strlen(__key))+1, __value)
+
/* unset() functions are only suported for legacy modules and null() functions should be used */
#define add_assoc_unset(__arg, __key) add_assoc_null_ex(__arg, __key, strlen(__key) + 1)
#define add_index_unset(__arg, __key) add_index_null(__arg, __key)
@@ -284,6 +297,10 @@ ZEND_API int add_index_resource(zval *arg, uint idx, int r);
ZEND_API int add_index_double(zval *arg, uint idx, double d);
ZEND_API int add_index_string(zval *arg, uint idx, char *str, int duplicate);
ZEND_API int add_index_stringl(zval *arg, uint idx, char *str, uint length, int duplicate);
+ZEND_API int add_index_binary(zval *arg, uint idx, char *str, int duplicate);
+ZEND_API int add_index_binaryl(zval *arg, uint idx, char *str, uint length, int duplicate);
+ZEND_API int add_index_unicode(zval *arg, uint idx, UChar *str, int duplicate);
+ZEND_API int add_index_unicodel(zval *arg, uint idx, UChar *str, uint length, int duplicate);
ZEND_API int add_index_zval(zval *arg, uint index, zval *value);
ZEND_API int add_next_index_long(zval *arg, long n);
@@ -293,6 +310,10 @@ ZEND_API int add_next_index_resource(zval *arg, int r);
ZEND_API int add_next_index_double(zval *arg, double d);
ZEND_API int add_next_index_string(zval *arg, char *str, int duplicate);
ZEND_API int add_next_index_stringl(zval *arg, char *str, uint length, int duplicate);
+ZEND_API int add_next_index_binary(zval *arg, char *str, int duplicate);
+ZEND_API int add_next_index_binaryl(zval *arg, char *str, uint length, int duplicate);
+ZEND_API int add_next_index_unicode(zval *arg, UChar *str, int duplicate);
+ZEND_API int add_next_index_unicodel(zval *arg, UChar *str, uint length, int duplicate);
ZEND_API int add_next_index_zval(zval *arg, zval *value);
ZEND_API int add_get_assoc_string_ex(zval *arg, char *key, uint key_len, char *str, void **dest, int duplicate);
@@ -305,6 +326,10 @@ ZEND_API int add_get_index_long(zval *arg, uint idx, long l, void **dest);
ZEND_API int add_get_index_double(zval *arg, uint idx, double d, void **dest);
ZEND_API int add_get_index_string(zval *arg, uint idx, char *str, void **dest, int duplicate);
ZEND_API int add_get_index_stringl(zval *arg, uint idx, char *str, uint length, void **dest, int duplicate);
+ZEND_API int add_get_index_binary(zval *arg, uint idx, char *str, void **dest, int duplicate);
+ZEND_API int add_get_index_binaryl(zval *arg, uint idx, char *str, uint length, void **dest, int duplicate);
+ZEND_API int add_get_index_unicode(zval *arg, uint idx, UChar *str, void **dest, int duplicate);
+ZEND_API int add_get_index_unicodel(zval *arg, uint idx, UChar *str, uint length, void **dest, int duplicate);
ZEND_API int add_property_long_ex(zval *arg, char *key, uint key_len, long l TSRMLS_DC);
ZEND_API int add_property_null_ex(zval *arg, char *key, uint key_len TSRMLS_DC);
@@ -358,6 +383,9 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, char *name, int name_length,
zend_bool is_ref, int num_symbol_tables, ...);
ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC);
+ZEND_API int zend_u_delete_global_variable(zend_uchar type, void *name, int name_len TSRMLS_DC);
+
+ZEND_API zend_class_entry* zend_get_named_class_entry(char* name, int name_length TSRMLS_DC);
ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC);
@@ -367,14 +395,24 @@ ZEND_API ZEND_FUNCTION(display_disabled_function);
ZEND_API ZEND_FUNCTION(display_disabled_class);
END_EXTERN_C()
+
+#define BINARY_TYPE (UG(unicode) ? IS_BINARY : IS_STRING)
+
+
#if ZEND_DEBUG
#define CHECK_ZVAL_STRING(z) \
if ((z)->value.str.val[ (z)->value.str.len ] != '\0') { zend_error(E_WARNING, "String is not zero-terminated (%s)", (z)->value.str.val); }
#define CHECK_ZVAL_STRING_REL(z) \
if ((z)->value.str.val[ (z)->value.str.len ] != '\0') { zend_error(E_WARNING, "String is not zero-terminated (%s) (source: %s:%d)", (z)->value.str.val ZEND_FILE_LINE_RELAY_CC); }
+#define CHECK_ZVAL_UNICODE(z) \
+ if ((z)->value.ustr.val[ (z)->value.ustr.len ] != 0 ) { zend_error(E_WARNING, "String is not zero-terminated"); }
+#define CHECK_ZVAL_UNICODE_REL(z) \
+ if ((z)->value.ustr.val[ (z)->value.ustr.len ] != 0) { zend_error(E_WARNING, "String is not zero-terminated (source: %s:%d)", ZEND_FILE_LINE_RELAY_C); }
#else
#define CHECK_ZVAL_STRING(z)
#define CHECK_ZVAL_STRING_REL(z)
+#define CHECK_ZVAL_UNICODE(z)
+#define CHECK_ZVAL_UNICODE_REL(z)
#endif
#define ZVAL_RESOURCE(z, l) { \
@@ -415,12 +453,52 @@ END_EXTERN_C()
(z)->type = IS_STRING; \
}
+#define ZVAL_UNICODE(z, u, duplicate) { \
+ UChar *__u=(u); \
+ (z)->value.ustr.len = u_strlen(__u); \
+ (z)->value.ustr.val = (duplicate?eustrndup(__u, (z)->value.ustr.len):__u); \
+ (z)->type = IS_UNICODE; \
+}
+
+#define ZVAL_UNICODEL(z, u, l, duplicate) { \
+ UChar *__u=(u); int32_t __l=l; \
+ (z)->value.ustr.len = __l; \
+ (z)->value.ustr.val = (duplicate?eustrndup(__u, __l):__u); \
+ (z)->type = IS_UNICODE; \
+}
+
+#define ZVAL_BINARY(z, s, duplicate) { \
+ char *__s=(s); \
+ (z)->value.str.len = strlen(__s); \
+ (z)->value.str.val = (duplicate?estrndup(__s, (z)->value.str.len):__s); \
+ (z)->type = BINARY_TYPE; \
+ }
+
+#define ZVAL_BINARYL(z, s, l, duplicate) { \
+ char *__s=(s); int __l=l; \
+ (z)->value.str.len = __l; \
+ (z)->value.str.val = (duplicate?estrndup(__s, __l):__s); \
+ (z)->type = BINARY_TYPE; \
+ }
+
#define ZVAL_EMPTY_STRING(z) { \
(z)->value.str.len = 0; \
(z)->value.str.val = STR_EMPTY_ALLOC(); \
(z)->type = IS_STRING; \
}
+#define ZVAL_EMPTY_UNICODE(z) { \
+ (z)->value.ustr.len = 0; \
+ (z)->value.ustr.val = USTR_MAKE(""); \
+ (z)->type = IS_UNICODE; \
+ }
+
+#define ZVAL_EMPTY_BINARY(z) { \
+ (z)->value.str.len = 0; \
+ (z)->value.str.val = STR_EMPTY_ALLOC(); \
+ (z)->type = BINARY_TYPE; \
+ }
+
#define ZVAL_ZVAL(z, zv, copy, dtor) { \
int is_ref, refcount; \
is_ref = (z)->is_ref; \
@@ -450,9 +528,32 @@ END_EXTERN_C()
#define RETVAL_STRING(s, duplicate) ZVAL_STRING(return_value, s, duplicate)
#define RETVAL_STRINGL(s, l, duplicate) ZVAL_STRINGL(return_value, s, l, duplicate)
#define RETVAL_EMPTY_STRING() ZVAL_EMPTY_STRING(return_value)
+#define RETVAL_UNICODE(u, duplicate) ZVAL_UNICODE(return_value, u, duplicate)
+#define RETVAL_UNICODEL(u, l, duplicate) ZVAL_UNICODEL(return_value, u, l, duplicate)
+#define RETVAL_EMPTY_UNICODE() ZVAL_EMPTY_UNICODE(return_value)
+#define RETVAL_BINARY(s, duplicate) ZVAL_BINARY(return_value, s, duplicate)
+#define RETVAL_BINARYL(s, l, duplicate) ZVAL_BINARYL(return_value, s, l, duplicate)
+#define RETVAL_EMPTY_BINARY() ZVAL_EMPTY_BINARY(return_value)
#define RETVAL_ZVAL(zv, copy, dtor) ZVAL_ZVAL(return_value, zv, copy, dtor)
#define RETVAL_FALSE ZVAL_BOOL(return_value, 0)
#define RETVAL_TRUE ZVAL_BOOL(return_value, 1)
+#define RETVAL_TEXT(t, duplicate) \
+ do { \
+ if (UG(unicode)) { \
+ RETVAL_UNICODE(t, duplicate); \
+ } else { \
+ RETVAL_STRING(t, duplicate); \
+ } \
+ } while (0);
+
+#define RETVAL_TEXTL(t, l, duplicate) \
+ do { \
+ if (UG(unicode)) { \
+ RETVAL_UNICODEL(t, l, duplicate); \
+ } else { \
+ RETVAL_STRINGL(t, l, duplicate); \
+ } \
+ } while (0);
#define RETURN_RESOURCE(l) { RETVAL_RESOURCE(l); return; }
#define RETURN_BOOL(b) { RETVAL_BOOL(b); return; }
@@ -462,9 +563,17 @@ END_EXTERN_C()
#define RETURN_STRING(s, duplicate) { RETVAL_STRING(s, duplicate); return; }
#define RETURN_STRINGL(s, l, duplicate) { RETVAL_STRINGL(s, l, duplicate); return; }
#define RETURN_EMPTY_STRING() { RETVAL_EMPTY_STRING(); return; }
+#define RETURN_UNICODE(u, duplicate) { RETVAL_UNICODE(u, duplicate); return; }
+#define RETURN_UNICODEL(u, l, duplicate) { RETVAL_UNICODEL(u, l, duplicate); return; }
+#define RETURN_EMPTY_UNICODE() { RETVAL_EMPTY_UNICODE(); return; }
+#define RETURN_BINARY(s, duplicate) { RETVAL_BINARY(s, duplicate); return; }
+#define RETURN_BINARYL(s, l, duplicate) { RETVAL_BINARYL(s, l, duplicate); return; }
+#define RETURN_EMPTY_BINARY() { RETVAL_EMPTY_BINARY(); return; }
#define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; }
#define RETURN_FALSE { RETVAL_FALSE; return; }
#define RETURN_TRUE { RETVAL_TRUE; return; }
+#define RETURN_TEXT(t, duplicate) { RETVAL_TEXT(t, duplicate); return; }
+#define RETURN_TEXTL(t, l, duplicate) { RETVAL_TEXTL(t, l, duplicate); return; }
#define SET_VAR_STRING(n, v) { \
{ \
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index f77c54ef9c..26b41adf51 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -23,6 +23,7 @@
#include "zend_alloc.h"
#include "zend_globals.h"
#include "zend_fast_cache.h"
+#include "zend_unicode.h"
#ifdef HAVE_SIGNAL_H
# include <signal.h>
#endif
@@ -409,6 +410,24 @@ ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
return p;
}
+ZEND_API UChar *_eustrdup(const UChar *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+{
+ int length;
+ UChar *p;
+
+ length = u_strlen(s)+1;
+ HANDLE_BLOCK_INTERRUPTIONS();
+ p = (UChar *) _emalloc(sizeof(UChar) * length ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ if (!p) {
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+ return (UChar *)NULL;
+ }
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+ u_memcpy(p, s, length);
+ return p;
+}
+
+
ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
{
char *p;
@@ -426,6 +445,23 @@ ZEND_API char *_estrndup(const char *s, uint length ZEND_FILE_LINE_DC ZEND_FILE_
}
+ZEND_API UChar *_eustrndup(const UChar *s, int32_t length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)
+{
+ UChar *p;
+
+ HANDLE_BLOCK_INTERRUPTIONS();
+ p = (UChar *) _emalloc(sizeof(UChar) * (length+1) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
+ if (!p) {
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+ return (UChar *)NULL;
+ }
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+ memcpy(p, s, length * sizeof(UChar));
+ p[length] = 0;
+ return p;
+}
+
+
ZEND_API char *zend_strndup(const char *s, uint length)
{
char *p;
@@ -441,6 +477,21 @@ ZEND_API char *zend_strndup(const char *s, uint length)
return p;
}
+ZEND_API UChar *zend_ustrndup(const UChar *s, uint length)
+{
+ UChar *p;
+
+ p = (UChar *) malloc(UBYTES(length+1));
+ if (!p) {
+ return (UChar *)NULL;
+ }
+ if (length) {
+ memcpy(p, s, UBYTES(length));
+ }
+ p[length] = 0;
+ return p;
+}
+
ZEND_API int zend_set_memory_limit(unsigned int memory_limit)
{
diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h
index 6d4b58192f..fc0edf0a4d 100644
--- a/Zend/zend_alloc.h
+++ b/Zend/zend_alloc.h
@@ -28,6 +28,7 @@
#include "zend_globals_macros.h"
#include "zend_mm.h"
+#include <unicode/utypes.h>
#define MEM_BLOCK_START_MAGIC 0x7312F8DCL
#define MEM_BLOCK_END_MAGIC 0x2A8FCC84L
@@ -75,6 +76,7 @@ typedef union _align_test {
BEGIN_EXTERN_C()
ZEND_API char *zend_strndup(const char *s, unsigned int length) ZEND_ATTRIBUTE_MALLOC;
+ZEND_API UChar *zend_ustrndup(const UChar *s, uint length) ZEND_ATTRIBUTE_MALLOC;
ZEND_API void *_emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
ZEND_API void *_safe_emalloc(size_t nmemb, size_t size, size_t offset ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
@@ -84,6 +86,8 @@ ZEND_API void *_ecalloc(size_t nmemb, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LI
ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);
ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
+ZEND_API UChar *_eustrdup(const UChar *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
+ZEND_API UChar *_eustrndup(const UChar *s, int32_t length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) ZEND_ATTRIBUTE_MALLOC;
#if USE_ZEND_ALLOC
@@ -96,16 +100,23 @@ ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZE
#define erealloc_recoverable(ptr, size) _erealloc((ptr), (size), 1 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define estrdup(s) _estrdup((s) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
#define estrndup(s, length) _estrndup((s), (length) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
+#define eumalloc(size) (UChar*)_emalloc(UBYTES(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
+#define eurealloc(ptr, size) (UChar*)_erealloc((ptr), UBYTES(size), 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
+#define eustrndup(s, length) _eustrndup((s), (length) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
+#define eustrdup(s) _eustrdup((s) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC)
/* Relay wrapper macros */
#define emalloc_rel(size) _emalloc((size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define safe_emalloc_rel(nmemb, size, offset) _safe_emalloc((nmemb), (size), (offset) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define efree_rel(ptr) _efree((ptr) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define ecalloc_rel(nmemb, size) _ecalloc((nmemb), (size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
-#define erealloc_rel(ptr, size) _erealloc((ptr), (size), 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
+#define erealloc_rel(ptr, size) _erealloc((ptr), (size), 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define erealloc_recoverable_rel(ptr, size) _erealloc((ptr), (size), 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define estrdup_rel(s) _estrdup((s) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
#define estrndup_rel(s, length) _estrndup((s), (length) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
+#define eumalloc_rel(size) (UChar*)_emalloc(UBYTES(size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
+#define eurealloc_rel(ptr, size) (UChar*)_erealloc((ptr), UBYTES(size), 0 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
+#define eustrndup_rel(s, length) _eustrndup((s), (length) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC)
/* Selective persistent/non persistent allocation macros */
#define pemalloc(size, persistent) ((persistent)?malloc(size):emalloc(size))
@@ -115,6 +126,8 @@ ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZE
#define perealloc(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc((ptr), (size)))
#define perealloc_recoverable(ptr, size, persistent) ((persistent)?realloc((ptr), (size)):erealloc_recoverable((ptr), (size)))
#define pestrdup(s, persistent) ((persistent)?strdup(s):estrdup(s))
+#define peumalloc(size, persistent) ((persistent)?malloc(UBYTES(size)):eumalloc(size))
+#define peurealloc(ptr, size, persistent) ((persistent)?realloc((ptr),UBYTES(size)):eurealloc((ptr),size))
#define pemalloc_rel(size, persistent) ((persistent)?malloc(size):emalloc_rel(size))
#define pefree_rel(ptr, persistent) ((persistent)?free(ptr):efree_rel(ptr))
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 0506d5f263..c1ca31c25e 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -279,8 +279,27 @@ ZEND_NAMED_FUNCTION(zend_if_strlen)
if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) {
ZEND_WRONG_PARAM_COUNT();
}
- convert_to_string_ex(str);
- RETVAL_LONG((*str)->value.str.len);
+
+ switch (Z_TYPE_PP(str)) {
+ case IS_UNICODE:
+ RETVAL_LONG(u_countChar32(Z_USTRVAL_PP(str), Z_USTRLEN_PP(str)));
+ break;
+
+ case IS_STRING:
+ case IS_BINARY:
+ RETVAL_LONG(Z_STRLEN_PP(str));
+ break;
+
+ default:
+ if (UG(unicode)) {
+ convert_to_unicode_ex(str);
+ RETVAL_LONG(Z_USTRLEN_PP(str));
+ } else {
+ convert_to_string_ex(str);
+ RETVAL_LONG(Z_STRLEN_PP(str));
+ }
+ break;
+ }
}
/* }}} */
@@ -396,6 +415,12 @@ ZEND_FUNCTION(each)
case HASH_KEY_IS_STRING:
add_get_index_stringl(return_value, 0, string_key, string_key_len-1, (void **) &inserted_pointer, 0);
break;
+ case HASH_KEY_IS_BINARY:
+ add_get_index_binaryl(return_value, 0, string_key, string_key_len-1, (void **) &inserted_pointer, 0);
+ break;
+ case HASH_KEY_IS_UNICODE:
+ add_get_index_unicodel(return_value, 0, (UChar*)string_key, string_key_len-1, (void **) &inserted_pointer, 0);
+ break;
case HASH_KEY_IS_LONG:
add_get_index_long(return_value, 0, num_key, (void **) &inserted_pointer);
break;
@@ -470,6 +495,8 @@ ZEND_FUNCTION(define)
case IS_LONG:
case IS_DOUBLE:
case IS_STRING:
+ case IS_BINARY:
+ case IS_UNICODE:
case IS_BOOL:
case IS_RESOURCE:
case IS_NULL:
@@ -479,15 +506,22 @@ ZEND_FUNCTION(define)
RETURN_FALSE;
break;
}
- convert_to_string_ex(var);
+
+ if (Z_TYPE_PP(var) != IS_STRING && Z_TYPE_PP(var) != IS_UNICODE) {
+ convert_to_string_ex(var);
+ }
c.value = **val;
zval_copy_ctor(&c.value);
c.flags = case_sensitive; /* non persistent */
- c.name = zend_strndup((*var)->value.str.val, (*var)->value.str.len);
- c.name_len = (*var)->value.str.len+1;
+ if (Z_TYPE_PP(var) == IS_UNICODE) {
+ c.name = (char*)zend_ustrndup(Z_USTRVAL_PP(var), Z_USTRLEN_PP(var));
+ } else {
+ c.name = zend_strndup(Z_STRVAL_PP(var), Z_STRLEN_PP(var));
+ }
+ c.name_len = Z_UNILEN_PP(var)+1;
c.module_number = PHP_USER_CONSTANT;
- if (zend_register_constant(&c TSRMLS_CC) == SUCCESS) {
+ if (zend_u_register_constant(Z_TYPE_PP(var), &c TSRMLS_CC) == SUCCESS) {
RETURN_TRUE;
} else {
RETURN_FALSE;
@@ -507,8 +541,8 @@ ZEND_FUNCTION(defined)
ZEND_WRONG_PARAM_COUNT();
}
- convert_to_string_ex(var);
- if (zend_get_constant((*var)->value.str.val, (*var)->value.str.len, &c TSRMLS_CC)) {
+ convert_to_text_ex(var);
+ if (zend_get_constant(Z_UNIVAL_PP(var), Z_UNILEN_PP(var), &c TSRMLS_CC)) {
zval_dtor(&c);
RETURN_TRUE;
} else {
@@ -523,13 +557,17 @@ ZEND_FUNCTION(defined)
ZEND_FUNCTION(get_class)
{
zval **arg;
- char *name = "";
+ char *name = EMPTY_STR;
zend_uint name_len = 0;
int dup;
if (!ZEND_NUM_ARGS()) {
if (EG(scope)) {
- RETURN_STRINGL(EG(scope)->name, EG(scope)->name_length, 1);
+ if (UG(unicode)) {
+ RETURN_UNICODEL((UChar*)EG(scope)->name, EG(scope)->name_length, 1);
+ } else {
+ RETURN_STRINGL(EG(scope)->name, EG(scope)->name_length, 1);
+ }
} else {
zend_error(E_ERROR, "get_class() called without object from outside a class");
}
@@ -543,7 +581,11 @@ ZEND_FUNCTION(get_class)
dup = zend_get_object_classname(*arg, &name, &name_len TSRMLS_CC);
- RETURN_STRINGL(name, name_len, dup);
+ if (UG(unicode)) {
+ RETURN_UNICODEL((UChar*)name, name_len, 0);
+ } else {
+ RETURN_STRINGL(name, name_len, 0);
+ }
}
/* }}} */
@@ -560,7 +602,11 @@ ZEND_FUNCTION(get_parent_class)
if (!ZEND_NUM_ARGS()) {
ce = EG(scope);
if (ce && ce->parent) {
- RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
+ if (UG(unicode)) {
+ RETURN_UNICODEL((UChar*)ce->parent->name, ce->parent->name_length, 1);
+ } else {
+ RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
+ }
} else {
RETURN_FALSE;
}
@@ -572,20 +618,28 @@ ZEND_FUNCTION(get_parent_class)
if (Z_TYPE_PP(arg) == IS_OBJECT) {
if (Z_OBJ_HT_PP(arg)->get_class_name
&& Z_OBJ_HT_PP(arg)->get_class_name(*arg, &name, &name_length, 1 TSRMLS_CC) == SUCCESS) {
- RETURN_STRINGL(name, name_length, 0);
+ if (UG(unicode)) {
+ RETURN_UNICODEL((UChar*)name, name_length, 0);
+ } else{
+ RETURN_STRINGL(name, name_length, 0);
+ }
} else {
ce = zend_get_class_entry(*arg TSRMLS_CC);
}
- } else if (Z_TYPE_PP(arg) == IS_STRING) {
+ } else if (Z_TYPE_PP(arg) == IS_STRING || Z_TYPE_PP(arg) == IS_UNICODE) {
zend_class_entry **pce;
- if (zend_lookup_class(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &pce TSRMLS_CC) == SUCCESS) {
+ if (zend_u_lookup_class(Z_TYPE_PP(arg), Z_UNIVAL_PP(arg), Z_UNILEN_PP(arg), &pce TSRMLS_CC) == SUCCESS) {
ce = *pce;
}
}
if (ce && ce->parent) {
- RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
+ if (UG(unicode)) {
+ RETURN_UNICODEL((UChar*)ce->parent->name, ce->parent->name_length, 1);
+ } else {
+ RETURN_STRINGL(ce->parent->name, ce->parent->name_length, 1);
+ }
} else {
RETURN_FALSE;
}
@@ -606,7 +660,7 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
if (only_subclass && Z_TYPE_PP(obj) == IS_STRING) {
zend_class_entry **the_ce;
- if (zend_lookup_class(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj), &the_ce TSRMLS_CC) == FAILURE) {
+ if (zend_u_lookup_class(Z_TYPE_PP(obj), Z_UNIVAL_PP(obj), Z_UNILEN_PP(obj), &the_ce TSRMLS_CC) == FAILURE) {
zend_error(E_WARNING, "Unknown class passed as parameter");
RETURN_FALSE;
}
@@ -624,7 +678,7 @@ static void is_a_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool only_subclass)
convert_to_string_ex(class_name);
- if (zend_lookup_class(Z_STRVAL_PP(class_name), Z_STRLEN_PP(class_name), &ce TSRMLS_CC) == FAILURE) {
+ if (zend_u_lookup_class(Z_TYPE_PP(class_name), Z_UNIVAL_PP(class_name), Z_UNILEN_PP(class_name), &ce TSRMLS_CC) == FAILURE) {
retval = 0;
} else {
if (only_subclass) {
@@ -686,8 +740,9 @@ static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *re
uint key_len;
ulong num_index;
zval *prop_copy;
+ zend_uchar key_type;
- zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos);
+ key_type = zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos);
zend_hash_move_forward_ex(properties, &pos);
zend_unmangle_property_name(key, &class_name, &prop_name);
if (class_name) {
@@ -712,7 +767,7 @@ static void add_class_vars(zend_class_entry *ce, HashTable *properties, zval *re
zval_update_constant(&prop_copy, 0 TSRMLS_CC);
}
- add_assoc_zval(return_value, prop_name, prop_copy);
+ add_u_assoc_zval(return_value, key_type==HASH_KEY_IS_UNICODE?IS_UNICODE:IS_STRING, prop_name, prop_copy);
}
}
}
@@ -725,13 +780,14 @@ ZEND_FUNCTION(get_class_vars)
{
char *class_name;
int class_name_len;
+ zend_uchar type;
zend_class_entry **pce;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &class_name, &class_name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &class_name, &class_name_len, &type) == FAILURE) {
return;
}
- if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC) == FAILURE) {
+ if (zend_u_lookup_class(type, class_name, class_name_len, &pce TSRMLS_CC) == FAILURE) {
RETURN_FALSE;
} else {
array_init(return_value);
@@ -774,17 +830,19 @@ ZEND_FUNCTION(get_object_vars)
zend_hash_internal_pointer_reset_ex(properties, &pos);
while (zend_hash_get_current_data_ex(properties, (void **) &value, &pos) == SUCCESS) {
- if (zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos) == HASH_KEY_IS_STRING) {
- if (key[0]) {
+ if (zend_hash_get_current_key_ex(properties, &key, &key_len, &num_index, 0, &pos) == (UG(unicode)?HASH_KEY_IS_UNICODE:HASH_KEY_IS_STRING)) {
+ zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, key, &class_name, &prop_name);
+ if (class_name == NULL) {
/* Not separating references */
(*value)->refcount++;
- add_assoc_zval_ex(return_value, key, key_len, *value);
+ add_u_assoc_zval_ex(return_value, UG(unicode)?IS_UNICODE:IS_STRING, key, key_len, *value);
} else if (instanceof) {
- zend_unmangle_property_name(key, &class_name, &prop_name);
- if (!memcmp(class_name, "*", 2) || (Z_OBJCE_P(EG(This)) == Z_OBJCE_PP(obj) && !strcmp(Z_OBJCE_P(EG(This))->name, class_name))) {
+ if (class_name[0] == '*' ||
+ (Z_OBJCE_P(EG(This)) == Z_OBJCE_PP(obj) &&
+ UG(unicode)?!u_strcmp((UChar*)Z_OBJCE_P(EG(This))->name, (UChar*)class_name):!strcmp(Z_OBJCE_P(EG(This))->name, class_name))) {
/* Not separating references */
(*value)->refcount++;
- add_assoc_zval_ex(return_value, prop_name, strlen(prop_name)+1, *value);
+ add_u_assoc_zval(return_value, UG(unicode)?IS_UNICODE:IS_STRING, prop_name, *value);
}
}
}
@@ -814,8 +872,8 @@ ZEND_FUNCTION(get_class_methods)
RETURN_FALSE;
}
ce = Z_OBJCE_PP(class);
- } else if (Z_TYPE_PP(class) == IS_STRING) {
- if (zend_lookup_class(Z_STRVAL_PP(class), Z_STRLEN_PP(class), &pce TSRMLS_CC) == SUCCESS) {
+ } else if (Z_TYPE_PP(class) == IS_STRING || Z_TYPE_PP(class) == IS_UNICODE) {
+ if (zend_u_lookup_class(Z_TYPE_PP(class), Z_UNIVAL_PP(class), Z_UNILEN_PP(class), &pce TSRMLS_CC) == SUCCESS) {
ce = *pce;
}
}
@@ -835,7 +893,11 @@ ZEND_FUNCTION(get_class_methods)
|| ((mptr->common.fn_flags & ZEND_ACC_PRIVATE) &&
EG(scope) == mptr->common.scope)))) {
MAKE_STD_ZVAL(method_name);
- ZVAL_STRING(method_name, mptr->common.function_name, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(method_name, (UChar*)mptr->common.function_name, 1);
+ } else {
+ ZVAL_STRING(method_name, mptr->common.function_name, 1);
+ }
zend_hash_next_index_insert(return_value->value.ht, &method_name, sizeof(zval *), NULL);
}
zend_hash_move_forward_ex(&ce->function_table, &pos);
@@ -849,6 +911,7 @@ ZEND_FUNCTION(get_class_methods)
ZEND_FUNCTION(method_exists)
{
zval **klass, **method_name;
+ unsigned int lcname_len;
char *lcname;
zend_class_entry * ce, **pce;
@@ -867,8 +930,8 @@ ZEND_FUNCTION(method_exists)
}
convert_to_string_ex(method_name);
- lcname = zend_str_tolower_dup(Z_STRVAL_PP(method_name), Z_STRLEN_PP(method_name));
- if (zend_hash_exists(&ce->function_table, lcname, Z_STRLEN_PP(method_name)+1)) {
+ lcname = zend_u_str_case_fold(Z_TYPE_PP(method_name), Z_UNIVAL_PP(method_name), Z_UNILEN_PP(method_name), 1, &lcname_len);
+ if (zend_u_hash_exists(&ce->function_table, Z_TYPE_PP(method_name), lcname, lcname_len+1)) {
efree(lcname);
RETURN_TRUE;
} else {
@@ -962,26 +1025,26 @@ ZEND_FUNCTION(property_exists)
Checks if the class exists */
ZEND_FUNCTION(class_exists)
{
- char *class_name, *lc_name;
+ unsigned int lc_name_len;
+ void *class_name, *lc_name;
zend_class_entry **ce;
int class_name_len;
zend_bool autoload = 1;
+ zend_uchar type;
int found;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &class_name, &class_name_len, &autoload) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|b", &class_name, &class_name_len, &type, &autoload) == FAILURE) {
return;
}
if (!autoload) {
- lc_name = do_alloca(class_name_len + 1);
- zend_str_tolower_copy(lc_name, class_name, class_name_len);
-
- found = zend_hash_find(EG(class_table), lc_name, class_name_len+1, (void **) &ce);
- free_alloca(lc_name);
+ lc_name = zend_u_str_case_fold(type, class_name, class_name_len, 1, &lc_name_len);
+ found = zend_u_hash_find(EG(class_table), type, lc_name, lc_name_len+1, (void **) &ce);
+ efree(lc_name);
RETURN_BOOL(found == SUCCESS && !((*ce)->ce_flags & ZEND_ACC_INTERFACE));
}
- if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) == SUCCESS) {
+ if (zend_u_lookup_class(type, class_name, class_name_len, &ce TSRMLS_CC) == SUCCESS) {
RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) == 0);
} else {
RETURN_FALSE;
@@ -993,26 +1056,26 @@ ZEND_FUNCTION(class_exists)
Checks if the class exists */
ZEND_FUNCTION(interface_exists)
{
- char *iface_name, *lc_name;
+ unsigned int lc_name_len;
+ void *iface_name, *lc_name;
zend_class_entry **ce;
int iface_name_len;
+ zend_uchar type;
zend_bool autoload = 1;
int found;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &iface_name, &iface_name_len, &autoload) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|b", &iface_name, &iface_name_len, &type, &autoload) == FAILURE) {
return;
}
if (!autoload) {
- lc_name = do_alloca(iface_name_len + 1);
- zend_str_tolower_copy(lc_name, iface_name, iface_name_len);
-
- found = zend_hash_find(EG(class_table), lc_name, iface_name_len+1, (void **) &ce);
- free_alloca(lc_name);
+ lc_name = zend_u_str_case_fold(type, iface_name, iface_name_len, 1, &lc_name_len);
+ found = zend_u_hash_find(EG(class_table), type, lc_name, lc_name_len+1, (void **) &ce);
+ efree(lc_name);
RETURN_BOOL(found == SUCCESS && (*ce)->ce_flags & ZEND_ACC_INTERFACE);
}
- if (zend_lookup_class(iface_name, iface_name_len, &ce TSRMLS_CC) == SUCCESS) {
+ if (zend_u_lookup_class(type, iface_name, iface_name_len, &ce TSRMLS_CC) == SUCCESS) {
RETURN_BOOL(((*ce)->ce_flags & ZEND_ACC_INTERFACE) > 0);
} else {
RETURN_FALSE;
@@ -1027,6 +1090,7 @@ ZEND_FUNCTION(function_exists)
{
zval **function_name;
zend_function *func;
+ unsigned int lcname_len;
char *lcname;
zend_bool retval;
@@ -1034,9 +1098,9 @@ ZEND_FUNCTION(function_exists)
ZEND_WRONG_PARAM_COUNT();
}
convert_to_string_ex(function_name);
- lcname = zend_str_tolower_dup((*function_name)->value.str.val, (*function_name)->value.str.len);
+ lcname = zend_u_str_case_fold(Z_TYPE_PP(function_name), Z_UNIVAL_PP(function_name), Z_UNILEN_PP(function_name), 1, &lcname_len);
- retval = (zend_hash_find(EG(function_table), lcname, (*function_name)->value.str.len+1, (void **)&func) == SUCCESS);
+ retval = (zend_u_hash_find(EG(function_table), Z_TYPE_PP(function_name), lcname, lcname_len+1, (void **)&func) == SUCCESS);
efree(lcname);
@@ -1283,10 +1347,17 @@ static int copy_class_or_interface_name(zend_class_entry **pce, int num_args, va
zend_uint comply = va_arg(args, zend_uint);
zend_uint comply_mask = (comply)? mask:0;
zend_class_entry *ce = *pce;
+ TSRMLS_FETCH();
- if ((hash_key->nKeyLength==0 || hash_key->arKey[0]!=0)
+ if ((hash_key->nKeyLength==0 ||
+ (hash_key->type == IS_UNICODE && hash_key->u.unicode[0] != 0) ||
+ (hash_key->type == IS_STRING && hash_key->u.string[0] != 0))
&& (comply_mask == (ce->ce_flags & mask))) {
- add_next_index_stringl(array, ce->name, ce->name_length, 1);
+ if (UG(unicode)) {
+ add_next_index_unicodel(array, (UChar*)ce->name, ce->name_length, 1);
+ } else {
+ add_next_index_stringl(array, ce->name, ce->name_length, 1);
+ }
}
return ZEND_HASH_APPLY_KEEP;
}
@@ -1330,14 +1401,29 @@ static int copy_function_name(zend_function *func, int num_args, va_list args, z
zval *internal_ar = va_arg(args, zval *),
*user_ar = va_arg(args, zval *);
- if (hash_key->nKeyLength == 0 || hash_key->arKey[0] == 0) {
+ if (hash_key->nKeyLength == 0 ||
+ hash_key->type == IS_BINARY ||
+ (hash_key->type == IS_UNICODE && hash_key->u.unicode[0] == 0) ||
+ (hash_key->type == IS_STRING && hash_key->u.unicode[0] == 0)) {
return 0;
}
if (func->type == ZEND_INTERNAL_FUNCTION) {
- add_next_index_stringl(internal_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
+ if (hash_key->type == IS_STRING) {
+ add_next_index_stringl(internal_ar, hash_key->u.string, hash_key->nKeyLength-1, 1);
+ } else if (hash_key->type == IS_BINARY) {
+ add_next_index_binaryl(internal_ar, hash_key->u.string, hash_key->nKeyLength-1, 1);
+ } else {
+ add_next_index_unicodel(internal_ar, hash_key->u.unicode, hash_key->nKeyLength-1, 1);
+ }
} else if (func->type == ZEND_USER_FUNCTION) {
- add_next_index_stringl(user_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
+ if (hash_key->type == IS_STRING) {
+ add_next_index_stringl(user_ar, hash_key->u.string, hash_key->nKeyLength-1, 1);
+ } else if (hash_key->type == IS_BINARY) {
+ add_next_index_binaryl(user_ar, hash_key->u.string, hash_key->nKeyLength-1, 1);
+ } else {
+ add_next_index_unicodel(user_ar, hash_key->u.unicode, hash_key->nKeyLength-1, 1);
+ }
}
return 0;
@@ -1431,7 +1517,7 @@ ZEND_FUNCTION(create_function)
RETURN_FALSE;
}
new_function = *func;
- function_add_ref(&new_function);
+ function_add_ref(&new_function TSRMLS_CC);
function_name = (char *) emalloc(sizeof("0lambda_")+MAX_LENGTH_OF_LONG);
@@ -1507,7 +1593,7 @@ static int add_constant_info(zend_constant *constant, void *arg TSRMLS_DC)
*const_val = constant->value;
zval_copy_ctor(const_val);
INIT_PZVAL(const_val);
- add_assoc_zval_ex(name_array, constant->name, constant->name_len, const_val);
+ add_u_assoc_zval_ex(name_array, UG(unicode)?IS_UNICODE:IS_STRING, constant->name, constant->name_len, const_val);
return 0;
}
@@ -1695,6 +1781,7 @@ ZEND_FUNCTION(debug_print_backtrace)
while (ptr) {
char *free_class_name = NULL;
+ int function_name_string = 1;
class_name = call_type = NULL;
arg_array = NULL;
@@ -1721,6 +1808,7 @@ ZEND_FUNCTION(debug_print_backtrace)
function_name = ptr->function_state.function->common.function_name;
if (function_name) {
+ function_name_string = !UG(unicode);
if (ptr->object) {
if (ptr->function_state.function->common.scope) {
class_name = ptr->function_state.function->common.scope->name;
@@ -1791,10 +1879,18 @@ ZEND_FUNCTION(debug_print_backtrace)
}
zend_printf("#%-2d ", indent);
if (class_name) {
- ZEND_PUTS(class_name);
+ if (UG(unicode)) {
+ zend_printf("%r(", class_name);
+ } else {
+ ZEND_PUTS(class_name);
+ }
ZEND_PUTS(call_type);
}
- zend_printf("%s(", function_name?function_name:"main");
+ if (function_name_string) {
+ zend_printf("%s(", function_name?function_name:"main");
+ } else {
+ zend_printf("%r(", function_name);
+ }
if (arg_array) {
debug_print_backtrace_args(arg_array TSRMLS_CC);
zval_ptr_dtor(&arg_array);
@@ -1898,22 +1994,37 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last TSRML
function_name = ptr->function_state.function->common.function_name;
if (function_name) {
- add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1);
+ if (UG(unicode)) {
+ add_assoc_unicode_ex(stack_frame, "function", sizeof("function"), function_name, 1);
+ } else {
+ add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1);
+ }
if (ptr->object && Z_TYPE_P(ptr->object) == IS_OBJECT) {
if (ptr->function_state.function->common.scope) {
- add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
+ if (UG(unicode)) {
+ add_assoc_unicode_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
+ } else {
+ add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
+ }
} else {
zend_uint class_name_len;
int dup;
dup = zend_get_object_classname(ptr->object, &class_name, &class_name_len TSRMLS_CC);
- add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, dup);
-
+ if (UG(unicode)) {
+ add_assoc_unicode_ex(stack_frame, "class", sizeof("class"), class_name, dup);
+ } else {
+ add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, dup);
+ }
}
add_assoc_string_ex(stack_frame, "type", sizeof("type"), "->", 1);
} else if (ptr->function_state.function->common.scope) {
- add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
+ if (UG(unicode)) {
+ add_assoc_unicode_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
+ } else {
+ add_assoc_string_ex(stack_frame, "class", sizeof("class"), ptr->function_state.function->common.scope->name, 1);
+ }
add_assoc_string_ex(stack_frame, "type", sizeof("type"), "::", 1);
}
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index a7c09b0a14..86c68cad13 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -27,10 +27,6 @@
#include "zend_API.h"
#include "zend_fast_cache.h"
-#ifdef ZEND_MULTIBYTE
-#include "zend_multibyte.h"
-#endif /* ZEND_MULTIBYTE */
-
ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
@@ -41,7 +37,13 @@ ZEND_API zend_executor_globals executor_globals;
static void zend_duplicate_property_info(zend_property_info *property_info)
{
- property_info->name = estrndup(property_info->name, property_info->name_length);
+ TSRMLS_FETCH();
+
+ if (UG(unicode)) {
+ property_info->name = (char*)eustrndup((UChar*)property_info->name, property_info->name_length);
+ } else {
+ property_info->name = estrndup(property_info->name, property_info->name_length);
+ }
if (property_info->doc_comment) {
property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len);
}
@@ -50,7 +52,13 @@ static void zend_duplicate_property_info(zend_property_info *property_info)
static void zend_duplicate_property_info_internal(zend_property_info *property_info)
{
- property_info->name = zend_strndup(property_info->name, property_info->name_length);
+ TSRMLS_FETCH();
+
+ if (UG(unicode)) {
+ property_info->name = (char*)zend_ustrndup((UChar*)property_info->name, property_info->name_length);
+ } else {
+ property_info->name = zend_strndup(property_info->name, property_info->name_length);
+ }
}
@@ -68,7 +76,7 @@ static void zend_destroy_property_info_internal(zend_property_info *property_inf
free(property_info->name);
}
-static void build_runtime_defined_function_key(zval *result, char *name, int name_length TSRMLS_DC)
+static void build_runtime_defined_function_key(zval *result, zend_uchar type, char *name, int name_length TSRMLS_DC)
{
char char_pos_buf[32];
uint char_pos_len;
@@ -82,16 +90,16 @@ static void build_runtime_defined_function_key(zval *result, char *name, int nam
}
/* NULL, name length, filename length, last accepting char position length */
+ if (type == IS_UNICODE) {
+ name_length *= sizeof(UChar);
+ }
result->value.str.len = 1+name_length+strlen(filename)+char_pos_len;
result->value.str.val = (char *) emalloc(result->value.str.len+1);
-#ifdef ZEND_MULTIBYTE
- /* must be binary safe */
+ /* UTODO: function key should probably store UTF-16 value instead of converting to
+ runtime encoding */
result->value.str.val[0] = '\0';
memcpy(result->value.str.val+1, name, name_length);
sprintf(result->value.str.val+1+name_length, "%s%s", filename, char_pos_buf);
-#else
- sprintf(result->value.str.val, "%c%s%s%s", '\0', name, filename, char_pos_buf);
-#endif /* ZEND_MULTIBYTE */
result->type = IS_STRING;
result->refcount = 1;
}
@@ -140,15 +148,6 @@ void zend_init_compiler_data_structures(TSRMLS_D)
CG(start_lineno) = 0;
init_compiler_declarables(TSRMLS_C);
zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_arm TSRMLS_CC);
-
-#ifdef ZEND_MULTIBYTE
- CG(script_encoding_list) = NULL;
- CG(script_encoding_list_size) = 0;
- CG(internal_encoding) = NULL;
- CG(encoding_detector) = NULL;
- CG(encoding_converter) = NULL;
- CG(encoding_oddlen) = NULL;
-#endif /* ZEND_MULTIBYTE */
}
@@ -173,12 +172,6 @@ void shutdown_compiler(TSRMLS_D)
zend_stack_destroy(&CG(list_stack));
zend_hash_destroy(&CG(filenames_table));
zend_llist_destroy(&CG(open_files));
-
-#ifdef ZEND_MULTIBYTE
- if (CG(script_encoding_list)) {
- efree(CG(script_encoding_list));
- }
-#endif /* ZEND_MULTIBYTE */
}
@@ -227,15 +220,15 @@ static zend_uint get_temporary_variable(zend_op_array *op_array)
return (op_array->T)++ * sizeof(temp_variable);
}
-static int lookup_cv(zend_op_array *op_array, char* name, int name_len)
+static int lookup_cv(zend_op_array *op_array, zend_uchar type, void *name, int name_len)
{
int i = 0;
- ulong hash_value = zend_inline_hash_func(name, name_len+1);
+ ulong hash_value = zend_u_inline_hash_func(type, name, name_len+1);
while (i < op_array->last_var) {
if (op_array->vars[i].hash_value == hash_value &&
op_array->vars[i].name_len == name_len &&
- strcmp(op_array->vars[i].name, name) == 0) {
+ !memcmp(op_array->vars[i].name, name, type==IS_UNICODE?UBYTES(name_len):name_len)) {
efree(name);
return i;
}
@@ -337,14 +330,16 @@ void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar
zend_op *opline_ptr;
zend_llist *fetch_list_ptr;
- if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING &&
- !zend_is_auto_global(varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC) &&
- !(varname->u.constant.value.str.len == (sizeof("this")-1) &&
- !memcmp(varname->u.constant.value.str.val, "this", sizeof("this"))) &&
+ if (varname->op_type == IS_CONST &&
+ (varname->u.constant.type == IS_STRING ||
+ varname->u.constant.type == IS_UNICODE) &&
+ !zend_u_is_auto_global(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant) TSRMLS_CC) &&
+ !(Z_UNILEN(varname->u.constant) == (sizeof("this")-1) &&
+ ZEND_U_EQUAL(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant), "this", sizeof("this")-1)) &&
(CG(active_op_array)->last == 0 ||
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
result->op_type = IS_CV;
- result->u.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len);
+ result->u.var = lookup_cv(CG(active_op_array), Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant));
result->u.EA.type = 0;
return;
}
@@ -365,8 +360,10 @@ void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar
SET_UNUSED(opline_ptr->op2);
opline_ptr->op2.u.EA.type = ZEND_FETCH_LOCAL;
- if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING) {
- if (zend_is_auto_global(varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC)) {
+ if (varname->op_type == IS_CONST &&
+ (varname->u.constant.type == IS_STRING ||
+ varname->u.constant.type == IS_UNICODE)) {
+ if (zend_u_is_auto_global(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant) TSRMLS_CC)) {
opline_ptr->op2.u.EA.type = ZEND_FETCH_GLOBAL;
}
}
@@ -399,9 +396,15 @@ void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC)
opline.result.u.EA.type = 0;
opline.result.u.var = get_temporary_variable(CG(active_op_array));
opline.op1.op_type = IS_CONST;
- opline.op1.u.constant.type = IS_STRING;
- opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[result->u.var].name);
- opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[result->u.var].name_len;
+ if (UG(unicode)) {
+ opline.op1.u.constant.type = IS_UNICODE;
+ Z_USTRVAL(opline.op1.u.constant) = eustrndup((UChar*)CG(active_op_array)->vars[result->u.var].name, CG(active_op_array)->vars[result->u.var].name_len);
+ Z_USTRLEN(opline.op1.u.constant) = CG(active_op_array)->vars[result->u.var].name_len;
+ } else {
+ opline.op1.u.constant.type = IS_STRING;
+ Z_STRVAL(opline.op1.u.constant) = estrndup(CG(active_op_array)->vars[result->u.var].name, CG(active_op_array)->vars[result->u.var].name_len);
+ Z_STRLEN(opline.op1.u.constant) = CG(active_op_array)->vars[result->u.var].name_len;
+ }
SET_UNUSED(opline.op2);
opline.op2 = *class_znode;
opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
@@ -419,9 +422,15 @@ void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC)
opline.result.u.EA.type = 0;
opline.result.u.var = get_temporary_variable(CG(active_op_array));
opline.op1.op_type = IS_CONST;
- opline.op1.u.constant.type = IS_STRING;
- opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[opline_ptr->op1.u.var].name);
- opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
+ if (UG(unicode)) {
+ opline.op1.u.constant.type = IS_UNICODE;
+ Z_USTRVAL(opline.op1.u.constant) = eustrndup((UChar*)CG(active_op_array)->vars[opline_ptr->op1.u.var].name, CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len);
+ Z_USTRLEN(opline.op1.u.constant) = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
+ } else {
+ opline.op1.u.constant.type = IS_STRING;
+ Z_STRVAL(opline.op1.u.constant) = estrndup(CG(active_op_array)->vars[opline_ptr->op1.u.var].name, CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len);
+ Z_STRLEN(opline.op1.u.constant) = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
+ }
SET_UNUSED(opline.op2);
opline.op2 = *class_znode;
opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
@@ -482,12 +491,13 @@ void zend_do_print(znode *result, znode *arg TSRMLS_DC)
}
-void zend_do_echo(znode *arg TSRMLS_DC)
+void zend_do_echo(znode *arg, zend_bool inline_html TSRMLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_ECHO;
opline->op1 = *arg;
+ opline->extended_value = inline_html;
SET_UNUSED(opline->op2);
}
@@ -514,11 +524,11 @@ void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body
SET_UNUSED(opline->op2);
} else {
/* we had code in the function body */
- zend_error(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body", method_type, CG(active_class_entry)->name, function_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "%s function %v::%R() cannot contain body", method_type, CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant));
}
} else {
if (body->u.constant.value.lval == ZEND_ACC_ABSTRACT) {
- zend_error(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body", CG(active_class_entry)->name, function_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Non-abstract method %v::%R() must contain body", CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant));
}
}
}
@@ -526,9 +536,10 @@ void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body
static zend_bool opline_is_fetch_this(zend_op *opline TSRMLS_DC)
{
if ((opline->opcode == ZEND_FETCH_W) && (opline->op1.op_type == IS_CONST)
- && (opline->op1.u.constant.type == IS_STRING)
- && (opline->op1.u.constant.value.str.len == (sizeof("this")-1))
- && !memcmp(opline->op1.u.constant.value.str.val, "this", sizeof("this"))) {
+ && (opline->op1.u.constant.type == IS_STRING ||
+ opline->op1.u.constant.type == IS_UNICODE)
+ && (Z_UNILEN(opline->op1.u.constant) == (sizeof("this")-1))
+ && ZEND_U_EQUAL(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), "this", sizeof("this")-1)) {
return 1;
} else {
return 0;
@@ -909,6 +920,7 @@ void zend_do_init_string(znode *result TSRMLS_DC)
opline->opcode = ZEND_INIT_STRING;
opline->result.op_type = IS_TMP_VAR;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
+ opline->extended_value = CG(literal_type);
*result = opline->result;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
@@ -923,6 +935,8 @@ void zend_do_add_char(znode *result, znode *op1, znode *op2 TSRMLS_DC)
opline->op1 = *op1;
opline->op2 = *op2;
opline->op2.op_type = IS_CONST;
+ opline->extended_value = CG(literal_type);
+ opline->extended_value = CG(literal_type);
opline->result = opline->op1;
*result = opline->result;
}
@@ -973,6 +987,7 @@ void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC)
opline->result = *result;
opline->op1 = *result;
opline->op2 = *op2;
+ opline->extended_value = CG(literal_type);
*result = opline->result;
}
@@ -1036,16 +1051,17 @@ int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier)
void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC)
{
zend_op_array op_array;
- char *name = function_name->u.constant.value.str.val;
- int name_len = function_name->u.constant.value.str.len;
+ char *name = Z_UNIVAL(function_name->u.constant);
+ int name_len = Z_UNILEN(function_name->u.constant);
int function_begin_line = function_token->u.opline_num;
zend_uint fn_flags;
+ unsigned int lcname_len;
char *lcname;
if (is_method) {
if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
if ((fn_flags_znode->u.constant.value.lval & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
- zend_error(E_COMPILE_ERROR, "Access type for interface method %s::%s() must be omitted", CG(active_class_entry)->name, function_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Access type for interface method %v::%R() must be omitted", CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant));
}
fn_flags_znode->u.constant.value.lval |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
}
@@ -1055,7 +1071,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
}
function_token->u.op_array = CG(active_op_array);
- lcname = zend_str_tolower_dup(name, name_len);
+ lcname = zend_u_str_case_fold(Z_TYPE(function_name->u.constant), name, name_len, 0, &lcname_len);
init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
@@ -1071,18 +1087,18 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
if (is_method) {
char *short_class_name = CG(active_class_entry)->name;
- int short_class_name_length = CG(active_class_entry)->name_length;
+ unsigned int short_class_name_length = CG(active_class_entry)->name_length;
- if (zend_hash_add(&CG(active_class_entry)->function_table, lcname, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
+ if (zend_u_hash_add(&CG(active_class_entry)->function_table, Z_TYPE(function_name->u.constant), lcname, lcname_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
zend_op_array *child_op_array, *parent_op_array;
if (CG(active_class_entry)->parent
- && (zend_hash_find(&CG(active_class_entry)->function_table, name, name_len+1, (void **) &child_op_array) == SUCCESS)
- && (zend_hash_find(&CG(active_class_entry)->parent->function_table, name, name_len+1, (void **) &parent_op_array) == SUCCESS)
+ && (zend_u_hash_find(&CG(active_class_entry)->function_table, Z_TYPE(function_name->u.constant), name, name_len+1, (void **) &child_op_array) == SUCCESS)
+ && (zend_u_hash_find(&CG(active_class_entry)->parent->function_table, Z_TYPE(function_name->u.constant), name, name_len+1, (void **) &parent_op_array) == SUCCESS)
&& (child_op_array == parent_op_array)) {
- zend_hash_update(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
+ zend_u_hash_update(&CG(active_class_entry)->function_table, Z_TYPE(function_name->u.constant), name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
} else {
efree(lcname);
- zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare %v::%R()", CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), name);
}
}
@@ -1095,39 +1111,38 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
}
if (!(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
- short_class_name = do_alloca(short_class_name_length + 1);
- zend_str_tolower_copy(short_class_name, CG(active_class_entry)->name, short_class_name_length);
+ short_class_name = zend_u_str_case_fold(UG(unicode)?IS_UNICODE:IS_STRING, CG(active_class_entry)->name, short_class_name_length, 0, &short_class_name_length);
/* Improve after RC: cache the lowercase class name */
- if ((short_class_name_length == name_len) && (!memcmp(short_class_name, lcname, name_len))) {
+ if ((short_class_name_length == name_len) && (!memcmp(short_class_name, lcname, UG(unicode)?UBYTES(lcname_len):lcname_len))) {
if (CG(active_class_entry)->constructor) {
- zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
+ zend_error(E_STRICT, "Redefining already defined constructor for class %v", CG(active_class_entry)->name);
} else {
CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
}
- } else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1))) {
if (CG(active_class_entry)->constructor) {
- zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
+ zend_error(E_STRICT, "Redefining already defined constructor for class %v", CG(active_class_entry)->name);
}
CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1))) {
CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1))) {
CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
} else if (!(fn_flags & ZEND_ACC_STATIC)) {
CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
}
- free_alloca(short_class_name);
+ efree(short_class_name);
}
efree(lcname);
@@ -1136,14 +1151,14 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
opline->opcode = ZEND_DECLARE_FUNCTION;
opline->op1.op_type = IS_CONST;
- build_runtime_defined_function_key(&opline->op1.u.constant, lcname, name_len TSRMLS_CC);
+ build_runtime_defined_function_key(&opline->op1.u.constant, Z_TYPE(function_name->u.constant), lcname, lcname_len TSRMLS_CC);
opline->op2.op_type = IS_CONST;
- opline->op2.u.constant.type = IS_STRING;
+ opline->op2.u.constant.type = Z_TYPE(function_name->u.constant);
opline->op2.u.constant.value.str.val = lcname;
- opline->op2.u.constant.value.str.len = name_len;
+ opline->op2.u.constant.value.str.len = lcname_len;
opline->op2.u.constant.refcount = 1;
opline->extended_value = ZEND_DECLARE_FUNCTION;
- zend_hash_update(CG(function_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
+ zend_u_hash_update(CG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
}
if (CG(extended_info)) {
@@ -1196,7 +1211,9 @@ void zend_do_handle_exception(TSRMLS_D)
void zend_do_end_function_declaration(znode *function_token TSRMLS_DC)
{
- char lcname[16];
+ unsigned int lcname_len;
+ char *lcname;
+ char lcname_buf[16];
int name_len;
zend_do_extended_info(TSRMLS_C);
@@ -1208,14 +1225,29 @@ void zend_do_end_function_declaration(znode *function_token TSRMLS_DC)
if (CG(active_class_entry)) {
zend_check_magic_method_implementation(CG(active_class_entry), (zend_function*)CG(active_op_array), E_COMPILE_ERROR TSRMLS_CC);
} else {
+ zend_uchar utype;
+
/* we don't care if the function name is longer, in fact lowercasing only
* the beginning of the name speeds up the check process */
- name_len = strlen(CG(active_op_array)->function_name);
- zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1));
- lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
- if (name_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)) && CG(active_op_array)->num_args != 1) {
+ if (UG(unicode)) {
+ utype = IS_UNICODE;
+ name_len = u_strlen((UChar*)CG(active_op_array)->function_name);
+ lcname = zend_u_str_case_fold(utype, CG(active_op_array)->function_name, name_len, 0, &lcname_len);
+ } else {
+ utype = IS_STRING;
+ lcname_len = name_len = strlen(CG(active_op_array)->function_name);
+ zend_str_tolower_copy(lcname_buf, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname_buf)-1));
+ lcname_buf[sizeof(lcname_buf)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
+ lcname = lcname_buf;
+ }
+ if (lcname_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 &&
+ ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1) &&
+ CG(active_op_array)->num_args != 1) {
zend_error(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
}
+ if (lcname != lcname_buf) {
+ efree(lcname);
+ }
}
CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
@@ -1245,16 +1277,20 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
}
CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
- cur_arg_info->name = estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len);
- cur_arg_info->name_len = varname->u.constant.value.str.len;
+ if (Z_TYPE(varname->u.constant) == IS_UNICODE) {
+ cur_arg_info->name = (char*)eustrndup(Z_USTRVAL(varname->u.constant), Z_USTRLEN(varname->u.constant));
+ } else {
+ cur_arg_info->name = estrndup(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant));
+ }
+ cur_arg_info->name_len = Z_UNILEN(varname->u.constant);
cur_arg_info->array_type_hint = 0;
cur_arg_info->allow_null = 1;
cur_arg_info->pass_by_reference = pass_by_reference;
if (class_type->op_type != IS_UNUSED) {
- 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 (class_type->u.constant.type == IS_STRING || class_type->u.constant.type == IS_UNICODE) {
+ cur_arg_info->class_name = Z_UNIVAL(class_type->u.constant);
+ cur_arg_info->class_name_len = Z_UNILEN(class_type->u.constant);
} else {
cur_arg_info->array_type_hint = 1;
cur_arg_info->class_name = NULL;
@@ -1272,16 +1308,22 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
int zend_do_begin_function_call(znode *function_name TSRMLS_DC)
{
zend_function *function;
+ unsigned int lcname_len;
char *lcname;
- lcname = zend_str_tolower_dup(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len);
- if (zend_hash_find(CG(function_table), lcname, function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) {
+ lcname = zend_u_str_case_fold(Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant), Z_UNILEN(function_name->u.constant), 0, &lcname_len);
+ if (zend_u_hash_find(CG(function_table), Z_TYPE(function_name->u.constant), lcname, lcname_len+1, (void **) &function)==FAILURE) {
zend_do_begin_dynamic_function_call(function_name TSRMLS_CC);
efree(lcname);
return 1; /* Dynamic */
}
- efree(function_name->u.constant.value.str.val);
- function_name->u.constant.value.str.val = lcname;
+ efree(Z_UNIVAL(function_name->u.constant));
+ if (Z_TYPE(function_name->u.constant) == IS_UNICODE) {
+ Z_USTRVAL(function_name->u.constant) = (UChar *)lcname;
+ Z_USTRLEN(function_name->u.constant) = lcname_len;
+ } else {
+ Z_STRVAL(function_name->u.constant) = lcname;
+ }
switch (function->type) {
case ZEND_USER_FUNCTION: {
@@ -1381,7 +1423,7 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC)
if (class_name->op_type == IS_CONST) {
int fetch_type;
- fetch_type = zend_get_class_fetch_type(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
+ fetch_type = zend_get_class_fetch_type(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant));
switch (fetch_type) {
case ZEND_FETCH_CLASS_SELF:
case ZEND_FETCH_CLASS_PARENT:
@@ -1413,11 +1455,19 @@ void zend_do_fetch_class_name(znode *result, znode *class_name_entry, znode *cla
*result = *class_name_entry;
}
- length = sizeof("::")-1 + result->u.constant.value.str.len + class_name->u.constant.value.str.len;
- result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1);
- memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], "::", sizeof("::")-1);
- memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len + sizeof("::")-1], class_name->u.constant.value.str.val, class_name->u.constant.value.str.len+1);
- STR_FREE(class_name->u.constant.value.str.val);
+ length = sizeof("::")-1 + Z_USTRLEN(result->u.constant) + Z_USTRLEN(class_name->u.constant);
+ if (Z_TYPE(result->u.constant) == IS_UNICODE) {
+ Z_USTRVAL(result->u.constant) = erealloc(Z_USTRVAL(result->u.constant), UBYTES(length+1));
+ Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant)] = ':';
+ Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant)+1] = ':';
+ memcpy(&Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant) + sizeof("::")-1], class_name->u.constant.value.str.val, UBYTES(Z_USTRLEN(class_name->u.constant)+1));
+ STR_FREE(Z_USTRVAL(class_name->u.constant));
+ } else {
+ result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1);
+ memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], "::", sizeof("::")-1);
+ memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len + sizeof("::")-1], class_name->u.constant.value.str.val, class_name->u.constant.value.str.len+1);
+ STR_FREE(class_name->u.constant.value.str.val);
+ }
result->u.constant.value.str.len = length;
}
@@ -1431,12 +1481,22 @@ void zend_do_begin_class_member_function_call(znode *class_name, znode *method_n
opline->op2 = *method_name;
if (opline->op2.op_type == IS_CONST) {
- if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(opline->op2.u.constant) &&
- memcmp(Z_STRVAL(opline->op2.u.constant), ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
+ if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_UNILEN(opline->op2.u.constant) &&
+ ZEND_U_EQUAL(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1)) {
zval_dtor(&opline->op2.u.constant);
SET_UNUSED(opline->op2);
} else {
- zend_str_tolower(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len);
+ if (Z_TYPE(opline->op2.u.constant) == IS_UNICODE) {
+ unsigned int lcname_len;
+ UChar *lcname;
+
+ lcname = zend_u_str_case_fold(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), 0, &lcname_len);
+ efree(Z_USTRVAL(opline->op2.u.constant));
+ Z_USTRVAL(opline->op2.u.constant) = lcname;
+ Z_USTRLEN(opline->op2.u.constant) = lcname_len;
+ } else {
+ zend_str_tolower(Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant));
+ }
}
}
@@ -1731,7 +1791,7 @@ void zend_do_throw(znode *expr TSRMLS_DC)
SET_UNUSED(opline->op2);
}
-ZEND_API void function_add_ref(zend_function *function)
+ZEND_API void function_add_ref(zend_function *function TSRMLS_DC)
{
if (function->type == ZEND_USER_FUNCTION) {
zend_op_array *op_array = &function->op_array;
@@ -1742,13 +1802,13 @@ ZEND_API void function_add_ref(zend_function *function)
zval *tmp_zval;
ALLOC_HASHTABLE(op_array->static_variables);
- zend_hash_init(op_array->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(op_array->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
}
}
}
-static void do_inherit_parent_constructor(zend_class_entry *ce)
+static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC)
{
zend_function *function;
@@ -1800,20 +1860,22 @@ static void do_inherit_parent_constructor(zend_class_entry *ce)
if (zend_hash_find(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), (void **)&function)==SUCCESS) {
/* inherit parent's constructor */
zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), NULL);
- function_add_ref(function);
+ function_add_ref(function TSRMLS_CC);
} else {
/* Don't inherit the old style constructor if we already have the new style constructor */
+ unsigned int lc_class_name_len, lc_parent_class_name_len;
char *lc_class_name;
char *lc_parent_class_name;
+ zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
- lc_class_name = zend_str_tolower_dup(ce->name, ce->name_length);
- if (!zend_hash_exists(&ce->function_table, lc_class_name, ce->name_length+1)) {
- lc_parent_class_name = zend_str_tolower_dup(ce->parent->name, ce->parent->name_length);
- if (zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
+ lc_class_name = zend_u_str_case_fold(utype, ce->name, ce->name_length, 0, &lc_class_name_len);
+ if (!zend_u_hash_exists(&ce->function_table, utype, lc_class_name, lc_class_name_len+1)) {
+ lc_parent_class_name = zend_u_str_case_fold(utype, ce->parent->name, ce->parent->name_length, 0, &lc_parent_class_name_len);
+ if (zend_u_hash_find(&ce->parent->function_table, utype, lc_parent_class_name, lc_parent_class_name_len+1, (void **)&function)==SUCCESS) {
if (function->common.fn_flags & ZEND_ACC_CTOR) {
/* inherit parent's constructor */
- zend_hash_update(&ce->function_table, lc_class_name, ce->name_length+1, function, sizeof(zend_function), NULL);
- function_add_ref(function);
+ zend_u_hash_update(&ce->function_table, utype, lc_class_name, lc_class_name_len+1, function, sizeof(zend_function), NULL);
+ function_add_ref(function TSRMLS_CC);
}
}
efree(lc_parent_class_name);
@@ -1845,7 +1907,8 @@ static void do_inherit_method(zend_function *function)
* as that of the parent class. That allows us to know in which context
* we're running, and handle private method calls properly.
*/
- function_add_ref(function);
+ TSRMLS_FETCH();
+ function_add_ref(function TSRMLS_CC);
}
@@ -1914,7 +1977,7 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
zend_function *child;
TSRMLS_FETCH();
- if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
+ if (zend_u_hash_quick_find(child_function_table, hash_key->type, hash_key->u.string, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
if (parent_flags & (ZEND_ACC_ABSTRACT)) {
child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
}
@@ -1924,14 +1987,14 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
if (parent->common.fn_flags & ZEND_ACC_ABSTRACT
&& parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
&& child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
- zend_error(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)",
+ zend_error(E_COMPILE_ERROR, "Can't inherit abstract function %v::%v() (previously declared abstract in %v)",
parent->common.scope->name,
child->common.function_name,
child->common.prototype ? child->common.prototype->common.scope->name : child->common.scope->name);
}
if (parent_flags & ZEND_ACC_FINAL) {
- zend_error(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name);
+ zend_error(E_COMPILE_ERROR, "Cannot override final method %v::%v()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name);
}
child_flags = child->common.fn_flags;
@@ -1939,15 +2002,15 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
*/
if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) {
if (child->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error(E_COMPILE_ERROR, "Cannot make non static method %s::%s() static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
+ zend_error(E_COMPILE_ERROR, "Cannot make non static method %v::%v() static in class %v", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
} else {
- zend_error(E_COMPILE_ERROR, "Cannot make static method %s::%s() non static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
+ zend_error(E_COMPILE_ERROR, "Cannot make static method %v::%v() non static in class %v", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
}
}
/* Disallow making an inherited method abstract. */
if ((child_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_ABSTRACT)) {
- zend_error(E_COMPILE_ERROR, "Cannot make non abstract method %s::%s() abstract in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
+ zend_error(E_COMPILE_ERROR, "Cannot make non abstract method %v::%v() abstract in class %v", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
}
if (parent_flags & ZEND_ACC_CHANGED) {
@@ -1956,7 +2019,7 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
/* Prevent derived classes from restricting access that was available in parent classes
*/
if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) {
- zend_error(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
+ zend_error(E_COMPILE_ERROR, "Access level to %v::%v() must be %s (as in class %v)%s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
} else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
&& ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
child->common.fn_flags |= ZEND_ACC_CHANGED;
@@ -1973,11 +2036,11 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
if (child->common.prototype) {
if (!zend_do_perform_implementation_check(child, child->common.prototype)) {
- zend_error(E_COMPILE_ERROR, "Declaration of %s::%s() must be compatible with that of %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(child->common.prototype), child->common.prototype->common.function_name);
+ zend_error(E_COMPILE_ERROR, "Declaration of %v::%v() must be compatible with that of %v::%v()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(child->common.prototype), child->common.prototype->common.function_name);
}
} else if (EG(error_reporting) & E_STRICT) { /* Check E_STRICT before the check so that we save some time */
if (!zend_do_perform_implementation_check(child, parent)) {
- zend_error(E_STRICT, "Declaration of %s::%s() should be compatible with that of %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(parent), parent->common.function_name);
+ zend_error(E_STRICT, "Declaration of %v::%v() should be compatible with that of %v::%v()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(parent), parent->common.function_name);
}
}
@@ -1989,12 +2052,15 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
{
zend_property_info *child_info;
zend_class_entry *parent_ce = ce->parent;
-
+ zend_uchar utype;
+ TSRMLS_FETCH();
+
+ utype = UG(unicode)?IS_UNICODE:IS_STRING;
if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
- if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
+ if (zend_u_hash_quick_find(&ce->properties_info, hash_key->type, hash_key->u.string, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
child_info->flags |= ZEND_ACC_CHANGED;
} else {
- zend_hash_quick_update(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, parent_info, sizeof(zend_property_info), (void **) &child_info);
+ zend_u_hash_quick_update(&ce->properties_info, hash_key->type, hash_key->u.string, hash_key->nKeyLength, hash_key->h, parent_info, sizeof(zend_property_info), (void **) &child_info);
if(ce->type & ZEND_INTERNAL_CLASS) {
zend_duplicate_property_info_internal(child_info);
} else {
@@ -2006,12 +2072,11 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
return 0; /* don't copy access information to child */
}
- if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
+ if (zend_u_hash_quick_find(&ce->properties_info, hash_key->type, hash_key->u.string, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
if ((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC)) {
- zend_error(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s",
- (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->arKey,
- (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey);
-
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare %s%v::$%R as %s%v::$%R",
+ (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->type, hash_key->u.string,
+ (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->type, hash_key->u.string);
}
if(parent_info->flags & ZEND_ACC_CHANGED) {
@@ -2019,16 +2084,16 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
}
if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
- zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
+ zend_error(E_COMPILE_ERROR, "Access level to %v::$%R must be %s (as in class %v)%s", ce->name, hash_key->type, hash_key->u.string, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
} else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
if (!(parent_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
/* Explicitly copy the default value from the parent (if it has one) */
zval **pvalue;
- if (zend_hash_quick_find(&parent_ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, (void **) &pvalue) == SUCCESS) {
+ if (zend_u_hash_quick_find(&parent_ce->default_properties, utype, parent_info->name, parent_info->name_length+1, parent_info->h, (void **) &pvalue) == SUCCESS) {
(*pvalue)->refcount++;
- zend_hash_del(&ce->default_properties, child_info->name, child_info->name_length+1);
- zend_hash_quick_update(&ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, pvalue, sizeof(zval *), NULL);
+ zend_u_hash_del(&ce->default_properties, utype, child_info->name, child_info->name_length+1);
+ zend_u_hash_quick_update(&ce->default_properties, utype, parent_info->name, parent_info->name_length+1, parent_info->h, pvalue, sizeof(zval *), NULL);
}
}
return 1; /* Inherit from the parent */
@@ -2036,26 +2101,26 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
char *prot_name;
int prot_name_length;
- zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS);
+ zend_u_mangle_property_name(&prot_name, &prot_name_length, utype, "*", 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS);
if (child_info->flags & ZEND_ACC_STATIC) {
zval **prop;
- if (zend_hash_find(parent_ce->static_members, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
+ if (zend_u_hash_find(parent_ce->static_members, utype, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
zval **new_prop;
- if (zend_hash_find(ce->static_members, child_info->name, child_info->name_length+1, (void**)&new_prop) == SUCCESS) {
+ if (zend_u_hash_find(ce->static_members, utype, child_info->name, child_info->name_length+1, (void**)&new_prop) == SUCCESS) {
if (Z_TYPE_PP(new_prop) != IS_NULL && Z_TYPE_PP(prop) != IS_NULL) {
char *prop_name, *tmp;
- zend_unmangle_property_name(child_info->name, &tmp, &prop_name);
-
- zend_error(E_COMPILE_ERROR, "Cannot change initial value of property static protected %s::$%s in class %s",
+
+ zend_u_unmangle_property_name(utype, child_info->name, &tmp, &prop_name);
+ zend_error(E_COMPILE_ERROR, "Cannot change initial value of property static protected %v::$%v in class %v",
parent_ce->name, prop_name, ce->name);
}
}
(*prop)->refcount++;
- zend_hash_update(ce->static_members, child_info->name, child_info->name_length+1, (void**)prop, sizeof(zval*), NULL);
- zend_hash_del(ce->static_members, prot_name, prot_name_length+1);
+ zend_u_hash_update(ce->static_members, utype, child_info->name, child_info->name_length+1, (void**)prop, sizeof(zval*), NULL);
+ zend_u_hash_del(ce->static_members, utype, prot_name, prot_name_length+1);
}
} else {
- zend_hash_del(&ce->default_properties, prot_name, prot_name_length+1);
+ zend_u_hash_del(&ce->default_properties, utype, prot_name, prot_name_length+1);
}
pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
}
@@ -2070,10 +2135,10 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC)
{
if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce TSRMLS_CC) == FAILURE) {
- zend_error(E_CORE_ERROR, "Class %s could not implement interface %s", ce->name, iface->name);
+ zend_error(E_CORE_ERROR, "Class %v could not implement interface %v", ce->name, iface->name);
}
if (ce == iface) {
- zend_error(E_ERROR, "Interface %s cannot not implement itself", ce->name);
+ zend_error(E_ERROR, "Interface %v cannot not implement itself", ce->name);
}
}
@@ -2126,10 +2191,10 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
{
if ((ce->ce_flags & ZEND_ACC_INTERFACE)
&& !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
- zend_error(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
+ zend_error(E_COMPILE_ERROR, "Interface %v may not inherit from class (%v)", ce->name, parent_ce->name);
}
if (parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
- zend_error(E_COMPILE_ERROR, "Class %s may not inherit from final class (%s)", ce->name, parent_ce->name);
+ zend_error(E_COMPILE_ERROR, "Class %v may not inherit from final class (%v)", ce->name, parent_ce->name);
}
ce->parent = parent_ce;
@@ -2155,8 +2220,8 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zval *parent_constant, zend_hash_key *hash_key, zend_class_entry *iface)
{
- if (zend_hash_quick_exists(child_constants_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h)) {
- zend_error(E_COMPILE_ERROR, "Cannot inherit previously-inherited constant %s from interface %s", hash_key->arKey, iface->name);
+ if (zend_u_hash_quick_exists(child_constants_table, hash_key->type, hash_key->u.string, hash_key->nKeyLength, hash_key->h)) {
+ zend_error(E_COMPILE_ERROR, "Cannot inherit previously-inherited constant %R from interface %v", hash_key->type, hash_key->u.string, iface->name);
return 0;
}
return 1;
@@ -2181,20 +2246,20 @@ ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, zend_b
zend_error(E_COMPILE_ERROR, "Internal compiler error. Please report!");
}
- zend_hash_find(function_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void *) &function);
- if (zend_hash_add(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, function, sizeof(zend_function), NULL)==FAILURE) {
+ zend_u_hash_find(function_table, Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (void *) &function);
+ if (zend_u_hash_add(function_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, function, sizeof(zend_function), NULL)==FAILURE) {
int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
zend_function *function;
- if (zend_hash_find(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void *) &function)==SUCCESS
+ if (zend_u_hash_find(function_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void *) &function)==SUCCESS
&& function->type==ZEND_USER_FUNCTION
&& ((zend_op_array *) function)->last>0) {
- zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
- opline->op2.u.constant.value.str.val,
+ zend_error(error_level, "Cannot redeclare %R() (previously declared in %s:%d)",
+ Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
((zend_op_array *) function)->filename,
((zend_op_array *) function)->opcodes[0].lineno);
} else {
- zend_error(error_level, "Cannot redeclare %s()", opline->op2.u.constant.value.str.val);
+ zend_error(error_level, "Cannot redeclare %R()", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
}
return FAILURE;
} else {
@@ -2209,14 +2274,14 @@ ZEND_API zend_class_entry *do_bind_class(zend_op *opline, HashTable *class_table
{
zend_class_entry *ce, **pce;
- if (zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce)==FAILURE) {
- zend_error(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", opline->op1.u.constant.value.str.val);
+ if (zend_u_hash_find(class_table, Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (void **) &pce)==FAILURE) {
+ zend_error(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %R", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
return NULL;
} else {
ce = *pce;
}
ce->refcount++;
- if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
+ if (zend_u_hash_add(class_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
ce->refcount--;
if (!compile_time) {
/* If we're in compile time, in practice, it's quite possible
@@ -2224,7 +2289,7 @@ ZEND_API zend_class_entry *do_bind_class(zend_op *opline, HashTable *class_table
* so we shut up about it. This allows the if (!defined('FOO')) { return; }
* approach to work.
*/
- zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare class %R", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
}
return NULL;
} else {
@@ -2241,7 +2306,7 @@ ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *c
zend_class_entry *ce, **pce;
int found_ce;
- found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce);
+ found_ce = zend_u_hash_find(class_table, Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (void **) &pce);
if (found_ce == FAILURE) {
if (!compile_time) {
@@ -2250,7 +2315,7 @@ ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *c
* so we shut up about it. This allows the if (!defined('FOO')) { return; }
* approach to work.
*/
- zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare class %R", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
}
return NULL;
} else {
@@ -2258,7 +2323,7 @@ ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *c
}
if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
- zend_error(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name, parent_ce->name);
+ zend_error(E_COMPILE_ERROR, "Class %v cannot extend from interface %v", ce->name, parent_ce->name);
}
zend_do_inheritance(ce, parent_ce TSRMLS_CC);
@@ -2266,8 +2331,8 @@ ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *c
ce->refcount++;
/* Register the derived class */
- if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
- zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
+ if (zend_u_hash_add(class_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare class %R", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
ce->refcount--;
zend_hash_destroy(&ce->function_table);
zend_hash_destroy(&ce->default_properties);
@@ -2315,7 +2380,7 @@ void zend_do_early_binding(TSRMLS_D)
zval *parent_name = &(opline-1)->op2.u.constant;
zend_class_entry **pce;
- if (zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) {
+ if (zend_u_lookup_class(Z_TYPE_P(parent_name), Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) {
return;
}
if (do_bind_inherited_class(opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
@@ -2357,7 +2422,7 @@ void zend_do_early_binding(TSRMLS_D)
return;
}
- zend_hash_del(table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len);
+ zend_u_hash_del(table, Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant));
zval_dtor(&opline->op1.u.constant);
zval_dtor(&opline->op2.u.constant);
opline->opcode = ZEND_NOP;
@@ -2624,21 +2689,25 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
zend_op *opline;
int doing_inheritance = 0;
zend_class_entry *new_class_entry = emalloc(sizeof(zend_class_entry));
- char *lcname = zend_str_tolower_dup(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
+ unsigned int lcname_len;
+ char *lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant), 0, &lcname_len);
if (CG(active_class_entry)) {
zend_error(E_COMPILE_ERROR, "Class declarations may not be nested");
return;
}
- if (!(strcmp(lcname, "self") && strcmp(lcname, "parent"))) {
+ if ((lcname_len == sizeof("self")-1 &&
+ ZEND_U_EQUAL(Z_TYPE(class_name->u.constant), lcname, lcname_len, "self", sizeof("self")-1)) ||
+ (lcname_len == sizeof("parent")-1 &&
+ ZEND_U_EQUAL(Z_TYPE(class_name->u.constant), lcname, lcname_len, "parent", sizeof("parent")-1))) {
efree(lcname);
- zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot use '%R' as class name as it is reserved", Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant));
}
new_class_entry->type = ZEND_USER_CLASS;
- new_class_entry->name = class_name->u.constant.value.str.val;
- new_class_entry->name_length = class_name->u.constant.value.str.len;
+ new_class_entry->name = Z_UNIVAL(class_name->u.constant);
+ new_class_entry->name_length = Z_UNILEN(class_name->u.constant);
zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
new_class_entry->filename = zend_get_compiled_filename(TSRMLS_C);
@@ -2661,10 +2730,10 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->op1.op_type = IS_CONST;
- build_runtime_defined_function_key(&opline->op1.u.constant, lcname, new_class_entry->name_length TSRMLS_CC);
+ build_runtime_defined_function_key(&opline->op1.u.constant, Z_TYPE(class_name->u.constant), lcname, lcname_len TSRMLS_CC);
opline->op2.op_type = IS_CONST;
- opline->op2.u.constant.type = IS_STRING;
+ opline->op2.u.constant.type = Z_TYPE(class_name->u.constant);
opline->op2.u.constant.refcount = 1;
if (doing_inheritance) {
@@ -2674,10 +2743,15 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
opline->opcode = ZEND_DECLARE_CLASS;
}
- opline->op2.u.constant.value.str.val = lcname;
- opline->op2.u.constant.value.str.len = new_class_entry->name_length;
+ if (Z_TYPE(opline->op2.u.constant) == IS_UNICODE) {
+ Z_USTRVAL(opline->op2.u.constant) = (UChar *)lcname;
+ Z_USTRLEN(opline->op2.u.constant) = lcname_len;
+ } else {
+ Z_STRVAL(opline->op2.u.constant) = lcname;
+ Z_STRLEN(opline->op2.u.constant) = lcname_len;
+ }
- zend_hash_update(CG(class_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &new_class_entry, sizeof(zend_class_entry *), NULL);
+ zend_u_hash_update(CG(class_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), &new_class_entry, sizeof(zend_class_entry *), NULL);
CG(active_class_entry) = new_class_entry;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
@@ -2707,24 +2781,24 @@ void zend_do_end_class_declaration(znode *class_token, znode *parent_token TSRML
{
zend_class_entry *ce = CG(active_class_entry);
- do_inherit_parent_constructor(ce);
+ do_inherit_parent_constructor(ce TSRMLS_CC);
if (ce->constructor) {
ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static", ce->name, ce->constructor->common.function_name);
+ zend_error(E_COMPILE_ERROR, "Constructor %v::%v() cannot be static", ce->name, ce->constructor->common.function_name);
}
}
if (ce->destructor) {
ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static", ce->name, ce->destructor->common.function_name);
+ zend_error(E_COMPILE_ERROR, "Destructor %v::%v() cannot be static", ce->name, ce->destructor->common.function_name);
}
}
if (ce->clone) {
ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static", ce->name, ce->clone->common.function_name);
+ zend_error(E_COMPILE_ERROR, "Clone method %v::%v() cannot be static", ce->name, ce->clone->common.function_name);
}
}
@@ -2790,6 +2864,29 @@ ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, char *src
*dest_length = prop_name_length;
}
+ZEND_API void zend_u_mangle_property_name(char **dest, int *dest_length, zend_uchar type, char *src1, int src1_length, char *src2, int src2_length, int internal)
+{
+ if (type == IS_UNICODE) {
+ UChar *prop_name;
+ int prop_name_length;
+
+ prop_name_length = 1 + src1_length + 1 + src2_length;
+ prop_name = pemalloc(UBYTES(prop_name_length + 1), internal);
+ prop_name[0] = 0;
+ if (src1_length == 1 && src1[0] == '*') {
+ prop_name[1] = '*';
+ prop_name[2] = 0;
+ } else {
+ memcpy(prop_name + 1, src1, UBYTES(src1_length+1));
+ }
+ memcpy(prop_name + 1 + src1_length + 1, src2, UBYTES(src2_length+1));
+
+ *dest = (char*)prop_name;
+ *dest_length = prop_name_length;
+ } else {
+ zend_mangle_property_name(dest, dest_length, src1, src1_length, src2, src2_length, internal);
+ }
+}
ZEND_API void zend_unmangle_property_name(char *mangled_property, char **class_name, char **prop_name)
{
@@ -2804,6 +2901,26 @@ ZEND_API void zend_unmangle_property_name(char *mangled_property, char **class_n
*prop_name = (*class_name)+strlen(*class_name)+1;
}
+ZEND_API void zend_u_unmangle_property_name(zend_uchar type, char *mangled_property, char **class_name, char **prop_name)
+{
+ if (type == IS_UNICODE) {
+ *prop_name = *class_name = NULL;
+
+ if (((UChar*)mangled_property)[0]!=0) {
+ *prop_name = mangled_property;
+ return;
+ }
+
+ *class_name = mangled_property+UBYTES(1);
+ *prop_name = (*class_name)+UBYTES(u_strlen((UChar*)*class_name)+1);
+ if ((*(UChar**)class_name)[0] == '*') {
+ *class_name = "*";
+ }
+ } else {
+ zend_unmangle_property_name(mangled_property, class_name, prop_name);
+ }
+}
+
void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_type TSRMLS_DC)
{
zval *property;
@@ -2820,13 +2937,13 @@ void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_ty
}
if (access_type & ZEND_ACC_FINAL) {
- zend_error(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, the final modifier is allowed only for methods",
- CG(active_class_entry)->name, var_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot declare property %v::$%R final, the final modifier is allowed only for methods",
+ CG(active_class_entry)->name, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant));
}
- if (zend_hash_find(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &existing_property_info)==SUCCESS) {
+ if (zend_u_hash_find(&CG(active_class_entry)->properties_info, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant), Z_UNILEN(var_name->u.constant)+1, (void **) &existing_property_info)==SUCCESS) {
if (!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
- zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare %v::$%R", CG(active_class_entry)->name, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant));
}
}
ALLOC_ZVAL(property);
@@ -2845,7 +2962,7 @@ void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_ty
CG(doc_comment_len) = 0;
}
- zend_declare_property_ex(CG(active_class_entry), var_name->u.constant.value.str.val, var_name->u.constant.value.str.len, property, access_type, comment, comment_len TSRMLS_CC);
+ zend_u_declare_property(CG(active_class_entry), Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant), Z_UNILEN(var_name->u.constant), property, access_type TSRMLS_CC);
efree(var_name->u.constant.value.str.val);
}
@@ -2867,9 +2984,9 @@ void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC)
property->type = IS_NULL;
}
- if (zend_hash_add(&CG(active_class_entry)->constants_table, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL)==FAILURE) {
+ if (zend_u_hash_add(&CG(active_class_entry)->constants_table, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant), Z_UNILEN(var_name->u.constant)+1, &property, sizeof(zval *), NULL)==FAILURE) {
FREE_ZVAL(property);
- zend_error(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot redefine class constant %v::%R", CG(active_class_entry)->name, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant));
}
FREE_PNODE(var_name);
}
@@ -2957,11 +3074,15 @@ void zend_do_declare_implicit_property(TSRMLS_D)
if (opline_ptr->op1.op_type == IS_UNUSED
&& CG(active_class_entry)
&& opline_ptr->op2.op_type == IS_CONST
- && !zend_hash_exists(&CG(active_class_entry)->properties_info, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len+1)) {
+ && !zend_u_hash_exists(&CG(active_class_entry)->properties_info, Z_TYPE(opline_ptr->op2.u.constant), Z_UNIVAL(opline_ptr->op2.u.constant), Z_UNILEN(opline_ptr->op2.u.constant)+1)) {
znode property;
property = opline_ptr->op2;
- property.u.constant.value.str.val = estrndup(opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len);
+ if (Z_TYPE(opline_ptr->op2.u.constant) == IS_UNICODE) {
+ Z_USTRVAL(property.u.constant) = eustrndup(Z_USTRVAL(opline_ptr->op2.u.constant), Z_USTRLEN(opline_ptr->op2.u.constant));
+ } else {
+ Z_STRVAL(property.u.constant) = estrndup(Z_STRVAL(opline_ptr->op2.u.constant), Z_STRLEN(opline_ptr->op2.u.constant));
+ }
zend_do_declare_property(&property, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_IMPLICIT_PUBLIC TSRMLS_CC);
}
#endif
@@ -3123,17 +3244,23 @@ void zend_do_add_array_element(znode *result, znode *expr, znode *offset, zend_b
void zend_do_add_static_array_element(znode *result, znode *offset, znode *expr)
{
zval *element;
+ TSRMLS_FETCH();
ALLOC_ZVAL(element);
*element = expr->u.constant;
if (offset) {
- switch (offset->u.constant.type) {
+ zend_uchar utype = Z_TYPE(offset->u.constant);
+
+ switch (Z_TYPE(offset->u.constant)) {
case IS_CONSTANT:
/* Ugly hack to denote that this value has a constant index */
element->type |= IS_CONSTANT_INDEX;
/* break missing intentionally */
+ utype = UG(unicode)?IS_UNICODE:IS_STRING;
case IS_STRING:
- zend_symtable_update(result->u.constant.value.ht, offset->u.constant.value.str.val, offset->u.constant.value.str.len+1, &element, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(result->u.constant.value.ht, utype, Z_UNIVAL(offset->u.constant), Z_UNILEN(offset->u.constant)+1, &element, sizeof(zval *), NULL);
zval_dtor(&offset->u.constant);
break;
case IS_NULL:
@@ -3278,9 +3405,9 @@ void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int
}
if (!CG(active_op_array)->static_variables) {
ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
- zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
}
- zend_hash_update(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1, &tmp, sizeof(zval *), NULL);
+ zend_u_hash_update(CG(active_op_array)->static_variables, Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant)+1, &tmp, sizeof(zval *), NULL);
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
@@ -3366,9 +3493,10 @@ void zend_do_indirect_references(znode *result, znode *num_references, znode *va
int i;
zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
+ zend_do_normalization(variable, variable TSRMLS_CC);
for (i=1; i<num_references->u.constant.value.lval; i++) {
fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
- *variable = *result;
+ zend_do_normalization(variable, result TSRMLS_CC);
}
zend_do_begin_variable_parse(TSRMLS_C);
fetch_simple_variable(result, variable, 1 TSRMLS_CC);
@@ -3385,9 +3513,15 @@ void zend_do_unset(znode *variable TSRMLS_DC)
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_UNSET_VAR;
opline->op1.op_type = IS_CONST;
- opline->op1.u.constant.type = IS_STRING;
- opline->op1.u.constant.value.str.len = CG(active_op_array)->vars[variable->u.var].name_len;
- opline->op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[variable->u.var].name);
+ if (UG(unicode)) {
+ opline->op1.u.constant.type = IS_UNICODE;
+ Z_USTRLEN(opline->op1.u.constant) = CG(active_op_array)->vars[variable->u.var].name_len;
+ Z_USTRVAL(opline->op1.u.constant) = eustrndup((UChar*)CG(active_op_array)->vars[variable->u.var].name, CG(active_op_array)->vars[variable->u.var].name_len);
+ } else {
+ opline->op1.u.constant.type = IS_STRING;
+ Z_STRLEN(opline->op1.u.constant) = CG(active_op_array)->vars[variable->u.var].name_len;
+ Z_STRVAL(opline->op1.u.constant) = estrndup(CG(active_op_array)->vars[variable->u.var].name, CG(active_op_array)->vars[variable->u.var].name_len);
+ }
SET_UNUSED(opline->op2);
opline->op2.u.EA.type = ZEND_FETCH_LOCAL;
SET_UNUSED(opline->result);
@@ -3422,9 +3556,15 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC
last_op = get_next_op(CG(active_op_array) TSRMLS_CC);
last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
last_op->op1.op_type = IS_CONST;
- last_op->op1.u.constant.type = IS_STRING;
- last_op->op1.u.constant.value.str.len = CG(active_op_array)->vars[variable->u.var].name_len;
- last_op->op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[variable->u.var].name);
+ if (UG(unicode)) {
+ last_op->op1.u.constant.type = IS_UNICODE;
+ Z_USTRLEN(last_op->op1.u.constant) = CG(active_op_array)->vars[variable->u.var].name_len;
+ Z_USTRVAL(last_op->op1.u.constant) = eustrndup((UChar*)CG(active_op_array)->vars[variable->u.var].name, CG(active_op_array)->vars[variable->u.var].name_len);
+ } else {
+ last_op->op1.u.constant.type = IS_STRING;
+ Z_STRLEN(last_op->op1.u.constant) = CG(active_op_array)->vars[variable->u.var].name_len;
+ Z_STRVAL(last_op->op1.u.constant) = estrndup(CG(active_op_array)->vars[variable->u.var].name, CG(active_op_array)->vars[variable->u.var].name_len);
+ }
SET_UNUSED(last_op->op2);
last_op->op2.u.EA.type = ZEND_FETCH_LOCAL;
last_op->result.u.var = get_temporary_variable(CG(active_op_array));
@@ -3634,35 +3774,19 @@ void zend_do_declare_begin(TSRMLS_D)
void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC)
{
- if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "ticks", sizeof("ticks")-1)) {
+ if (ZEND_U_EQUAL(Z_TYPE(var->u.constant), Z_UNIVAL(var->u.constant), Z_UNILEN(var->u.constant), "ticks", sizeof("ticks")-1)) {
convert_to_long(&val->u.constant);
CG(declarables).ticks = val->u.constant;
-#ifdef ZEND_MULTIBYTE
- } else if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "encoding", sizeof("encoding")-1)) {
- zend_encoding *new_encoding, *old_encoding;
- zend_encoding_filter old_input_filter;
+ } else if (UG(unicode) && ZEND_U_EQUAL(Z_TYPE(var->u.constant), Z_UNIVAL(var->u.constant), Z_UNILEN(var->u.constant), "encoding", sizeof("encoding")-1)) {
if (val->u.constant.type == IS_CONSTANT) {
zend_error(E_COMPILE_ERROR, "Cannot use constants as encoding");
}
convert_to_string(&val->u.constant);
- new_encoding = zend_multibyte_fetch_encoding(val->u.constant.value.str.val);
- if (!new_encoding) {
- zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", val->u.constant.value.str.val);
- } else {
- old_input_filter = LANG_SCNG(input_filter);
- old_encoding = LANG_SCNG(script_encoding);
- zend_multibyte_set_filter(new_encoding TSRMLS_CC);
-
- /* need to re-scan if input filter changed */
- if (old_input_filter != LANG_SCNG(input_filter) ||
- ((old_input_filter == zend_multibyte_script_encoding_filter) &&
- (new_encoding != old_encoding))) {
- zend_multibyte_yyinput_again(old_input_filter, old_encoding TSRMLS_CC);
- }
+ if (zend_prepare_scanner_converters(Z_STRVAL(val->u.constant), 1 TSRMLS_CC) == FAILURE) {
+ zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", Z_STRVAL(val->u.constant));
}
efree(val->u.constant.value.str.val);
-#endif /* ZEND_MULTIBYTE */
}
zval_dtor(&var->u.constant);
}
@@ -3689,12 +3813,21 @@ void zend_do_end_heredoc(TSRMLS_D)
return;
}
- opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0;
- if (opline->op2.u.constant.value.str.len>0) {
- if (opline->op2.u.constant.value.str.val[opline->op2.u.constant.value.str.len-1]=='\r') {
- opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0;
- }
- }
+ if (opline->op2.u.constant.type == IS_UNICODE) {
+ opline->op2.u.constant.value.ustr.val[(opline->op2.u.constant.value.ustr.len--)-1] = 0;
+ if (opline->op2.u.constant.value.ustr.len>0) {
+ if (opline->op2.u.constant.value.ustr.val[opline->op2.u.constant.value.ustr.len-1]=='\r') {
+ opline->op2.u.constant.value.ustr.val[(opline->op2.u.constant.value.ustr.len--)-1] = 0;
+ }
+ }
+ } else {
+ opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0;
+ if (opline->op2.u.constant.value.str.len>0) {
+ if (opline->op2.u.constant.value.str.val[opline->op2.u.constant.value.str.len-1]=='\r') {
+ opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0;
+ }
+ }
+ }
}
@@ -3856,11 +3989,11 @@ void zend_auto_global_dtor(zend_auto_global *auto_global)
}
-zend_bool zend_is_auto_global(char *name, uint name_len TSRMLS_DC)
+zend_bool zend_u_is_auto_global(zend_uchar type, void *name, uint name_len TSRMLS_DC)
{
zend_auto_global *auto_global;
- if (zend_hash_find(CG(auto_globals), name, name_len+1, (void **) &auto_global)==SUCCESS) {
+ if (zend_u_hash_find(CG(auto_globals), type, name, name_len+1, (void **) &auto_global)==SUCCESS) {
if (auto_global->armed) {
auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
}
@@ -3869,6 +4002,11 @@ zend_bool zend_is_auto_global(char *name, uint name_len TSRMLS_DC)
return 0;
}
+zend_bool zend_is_auto_global(char *name, uint name_len TSRMLS_DC)
+{
+ return zend_u_is_auto_global(IS_STRING, name, name_len TSRMLS_CC);
+}
+
int zend_register_auto_global(char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC)
{
@@ -3934,8 +4072,8 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
ce->doc_comment = NULL;
ce->doc_comment_len = 0;
- zend_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
- zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0);
+ zend_u_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, UG(unicode), 0);
+ zend_u_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, UG(unicode), 0);
if (persistent_hashes) {
ce->static_members = (HashTable *) malloc(sizeof(HashTable));
@@ -3943,9 +4081,9 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
ALLOC_HASHTABLE(ce->static_members);
}
- zend_hash_init_ex(ce->static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
- zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
- zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
+ zend_u_hash_init_ex(ce->static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, UG(unicode), 0);
+ zend_u_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, UG(unicode), 0);
+ zend_u_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, UG(unicode), 0);
if (nullify_handlers) {
ce->constructor = NULL;
@@ -3973,13 +4111,13 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
}
-int zend_get_class_fetch_type(char *class_name, uint class_name_len)
+int zend_get_class_fetch_type(zend_uchar type, char *class_name, uint class_name_len)
{
if ((class_name_len == sizeof("self")-1) &&
- !memcmp(class_name, "self", sizeof("self"))) {
+ ZEND_U_EQUAL(type, class_name, class_name_len, "self", sizeof("self")-1)) {
return ZEND_FETCH_CLASS_SELF;
} else if ((class_name_len == sizeof("parent")-1) &&
- !memcmp(class_name, "parent", sizeof("parent"))) {
+ ZEND_U_EQUAL(type, class_name, class_name_len, "parent", sizeof("parent")-1)) {
return ZEND_FETCH_CLASS_PARENT;
} else {
return ZEND_FETCH_CLASS_DEFAULT;
@@ -3994,6 +4132,23 @@ ZEND_API char* zend_get_compiled_variable_name(zend_op_array *op_array, zend_uin
return op_array->vars[var].name;
}
+void zend_do_normalization(znode *result, znode *str TSRMLS_DC)
+{
+ zend_op *opline;
+
+ if (!UG(unicode)) {
+ *result = *str;
+ return;
+ }
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_U_NORMALIZE;
+ opline->result.op_type = IS_TMP_VAR;
+ opline->result.u.var = get_temporary_variable(CG(active_op_array));
+ opline->op1 = *str;
+ SET_UNUSED(opline->op2);
+ *result = opline->result;
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index b63dd8c90a..869a0a89ea 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -237,7 +237,7 @@ typedef struct _zend_internal_function {
void (*handler)(INTERNAL_FUNCTION_PARAMETERS);
} zend_internal_function;
-#define ZEND_FN_SCOPE_NAME(function) ((function) && (function)->common.scope ? (function)->common.scope->name : "")
+#define ZEND_FN_SCOPE_NAME(function) ((function) && (function)->common.scope ? (function)->common.scope->name : EMPTY_STR)
typedef union _zend_function {
zend_uchar type; /* MUST be the first element of this struct! */
@@ -329,6 +329,10 @@ ZEND_API int zend_get_scanned_file_offset(TSRMLS_D);
ZEND_API char* zend_get_compiled_variable_name(zend_op_array *op_array, zend_uint var, int* name_len);
+ZEND_API int zend_prepare_scanner_converters(const char *onetime_encoding, int run_time TSRMLS_DC);
+ZEND_API int32_t zend_convert_scanner_output(UChar **target, int32_t *target_len, const char *source, int32_t source_len, UErrorCode *status TSRMLS_DC);
+int zend_unicode_yyinput(zend_file_handle *file_handle, char *buf, size_t len TSRMLS_DC);
+
#ifdef ZTS
const char *zend_get_zendtext(TSRMLS_D);
int zend_get_zendleng(TSRMLS_D);
@@ -352,7 +356,7 @@ void fetch_array_dim(znode *result, znode *parent, znode *dim TSRMLS_DC);
void fetch_string_offset(znode *result, znode *parent, znode *offset TSRMLS_DC);
void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC);
void zend_do_print(znode *result, znode *arg TSRMLS_DC);
-void zend_do_echo(znode *arg TSRMLS_DC);
+void zend_do_echo(znode *arg, zend_bool inline_html TSRMLS_DC);
typedef int (*unary_op_type)(zval *, zval *);
ZEND_API unary_op_type get_unary_op(int opcode);
ZEND_API void *get_binary_op(int opcode);
@@ -497,7 +501,9 @@ void zend_do_ticks(TSRMLS_D);
void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body TSRMLS_DC);
-ZEND_API void function_add_ref(zend_function *function);
+ZEND_API void function_add_ref(zend_function *function TSRMLS_DC);
+
+void zend_do_normalization(znode *result, znode *str TSRMLS_DC);
#define INITIAL_OP_ARRAY_SIZE 64
@@ -523,6 +529,10 @@ void zend_class_add_ref(zend_class_entry **ce);
ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, char *src1, int src1_length, char *src2, int src2_length, int internal);
ZEND_API void zend_unmangle_property_name(char *mangled_property, char **prop_name, char **class_name);
+ZEND_API void zend_u_mangle_property_name(char **dest, int *dest_length, zend_uchar type, char *src1, int src1_length, char *src2, int src2_length, int internal);
+ZEND_API void zend_u_unmangle_property_name(zend_uchar type, char *mangled_property, char **prop_name, char **class_name);
+
+
#define ZEND_FUNCTION_DTOR (void (*)(void *)) zend_function_dtor
#define ZEND_CLASS_DTOR (void (*)(void *)) destroy_zend_class
@@ -539,7 +549,7 @@ void zend_do_mark_last_catch(znode *first_catch, znode *last_additional_catch TS
ZEND_API zend_bool zend_is_compiling(TSRMLS_D);
ZEND_API char *zend_make_compiled_string_description(char *name TSRMLS_DC);
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers TSRMLS_DC);
-int zend_get_class_fetch_type(char *class_name, uint class_name_len);
+int zend_get_class_fetch_type(zend_uchar type, char *class_name, uint class_name_len);
typedef zend_bool (*zend_auto_global_callback)(char *name, uint name_len TSRMLS_DC);
typedef struct _zend_auto_global {
@@ -552,6 +562,7 @@ typedef struct _zend_auto_global {
void zend_auto_global_dtor(zend_auto_global *auto_global);
ZEND_API int zend_register_auto_global(char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC);
ZEND_API zend_bool zend_is_auto_global(char *name, uint name_len TSRMLS_DC);
+ZEND_API zend_bool zend_u_is_auto_global(zend_uchar type, void *name, uint name_len TSRMLS_DC);
ZEND_API int zend_auto_global_disable_jit(char *varname, zend_uint varname_length TSRMLS_DC);
int zendlex(znode *zendlval TSRMLS_DC);
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index ae06f837e7..613bc0a962 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -83,7 +83,7 @@ int zend_startup_constants(TSRMLS_D)
{
EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable));
- if (zend_hash_init(EG(zend_constants), 20, NULL, ZEND_CONSTANT_DTOR, 1)==FAILURE) {
+ if (zend_u_hash_init(EG(zend_constants), 20, NULL, ZEND_CONSTANT_DTOR, 1, UG(unicode))==FAILURE) {
return FAILURE;
}
return SUCCESS;
@@ -108,6 +108,11 @@ void zend_register_standard_constants(TSRMLS_D)
REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("U_INVALID_STOP", ZEND_FROM_U_ERROR_STOP, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("U_INVALID_SKIP", ZEND_FROM_U_ERROR_SKIP, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("U_INVALID_SUBSTITUTE", ZEND_FROM_U_ERROR_SUBST, CONST_PERSISTENT | CONST_CS);
+ REGISTER_MAIN_LONG_CONSTANT("U_INVALID_ESCAPE", ZEND_FROM_U_ERROR_ESCAPE, CONST_PERSISTENT | CONST_CS);
+
/* true/false constants */
{
zend_constant c;
@@ -215,13 +220,15 @@ ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC
int retval = 1;
char *lookup_name;
char *colon;
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
- if ((colon = memchr(name, ':', name_len)) && colon[1] == ':') {
+ if ((UG(unicode) && (colon = (char*)u_memchr((UChar*)name, ':', name_len)) && ((UChar*)colon)[1] == ':') ||
+ (!UG(unicode) && (colon = memchr(name, ':', name_len)) && colon[1] == ':')) {
/* class constant */
zend_class_entry **ce = NULL, *scope;
- int class_name_len = colon-name;
+ int class_name_len = UG(unicode)?((colon-name)/sizeof(UChar)):colon-name;
int const_name_len = name_len - class_name_len - 2;
- char *constant_name = colon+2;
+ char *constant_name = colon + (UG(unicode)?UBYTES(2):2);
zval **ret_constant;
char *class_name;
@@ -231,16 +238,22 @@ ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC
scope = CG(active_class_entry);
}
- class_name = estrndup(name, class_name_len);
+ if (UG(unicode)) {
+ class_name = (char*)eustrndup((UChar*)name, class_name_len);
+ } else {
+ class_name = estrndup(name, class_name_len);
+ }
- if (class_name_len == sizeof("self")-1 && strcmp(class_name, "self") == 0) {
+ if (class_name_len == sizeof("self")-1 &&
+ ZEND_U_EQUAL(type, class_name, class_name_len, "self", sizeof("self")-1)) {
if (scope) {
ce = &scope;
} else {
zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
retval = 0;
}
- } else if (class_name_len == sizeof("parent")-1 && strcmp(class_name, "parent") == 0) {
+ } else if (class_name_len == sizeof("parent")-1 &&
+ ZEND_U_EQUAL(type, class_name, class_name_len, "parent", sizeof("parent")-1)) {
if (!scope) {
zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
} else if (!scope->parent) {
@@ -249,14 +262,14 @@ ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC
ce = &scope->parent;
}
} else {
- if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS) {
+ if (zend_u_lookup_class(type, class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS) {
retval = 0;
}
}
efree(class_name);
if (retval && ce) {
- if (zend_hash_find(&((*ce)->constants_table), constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
+ if (zend_u_hash_find(&((*ce)->constants_table), type, constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
retval = 0;
}
} else {
@@ -272,12 +285,13 @@ ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC
return retval;
}
- if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) {
- lookup_name = estrndup(name, name_len);
- zend_str_tolower(lookup_name, name_len);
+ if (zend_u_hash_find(EG(zend_constants), type, name, name_len+1, (void **) &c) == FAILURE) {
+ int lookup_name_len;
+
+ lookup_name = zend_u_str_case_fold(type, name, name_len, 1, &lookup_name_len);
- if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) {
- if ((c->flags & CONST_CS) && memcmp(c->name, name, name_len)!=0) {
+ if (zend_u_hash_find(EG(zend_constants), type, lookup_name, lookup_name_len+1, (void **) &c)==SUCCESS) {
+ if ((c->flags & CONST_CS) && memcmp(c->name, name, UG(unicode)?UBYTES(name_len):name_len)!=0) {
retval=0;
}
} else {
@@ -297,9 +311,10 @@ ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC
}
-ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
+ZEND_API int zend_u_register_constant(zend_uchar type, zend_constant *c TSRMLS_DC)
{
- char *lowercase_name = NULL;
+ int lookup_name_len;
+ char *lookup_name = NULL;
char *name;
int ret = SUCCESS;
@@ -309,14 +324,14 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
if (!(c->flags & CONST_CS)) {
/* keep in mind that c->name_len already contains the '\0' */
- lowercase_name = estrndup(c->name, c->name_len);
- zend_str_tolower(lowercase_name, c->name_len);
- name = lowercase_name;
+ name = lookup_name = zend_u_str_case_fold(type, c->name, c->name_len-1, 1, &lookup_name_len);
+ lookup_name_len++;
} else {
+ lookup_name_len = c->name_len;
name = c->name;
}
- if (zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
+ if (zend_u_hash_add(EG(zend_constants), type, name, lookup_name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
zend_error(E_NOTICE,"Constant %s already defined", name);
free(c->name);
if (!(c->flags & CONST_PERSISTENT)) {
@@ -324,13 +339,16 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
}
ret = FAILURE;
}
- if (lowercase_name) {
- efree(lowercase_name);
+ if (lookup_name) {
+ efree(lookup_name);
}
return ret;
}
-
+ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
+{
+ return zend_u_register_constant(IS_STRING, c TSRMLS_CC);
+}
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h
index 241050da5b..a3ca212d3b 100644
--- a/Zend/zend_constants.h
+++ b/Zend/zend_constants.h
@@ -60,6 +60,7 @@ ZEND_API void zend_register_double_constant(char *name, uint name_len, double dv
ZEND_API void zend_register_string_constant(char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC);
ZEND_API void zend_register_stringl_constant(char *name, uint name_len, char *strval, uint strlen, int flags, int module_number TSRMLS_DC);
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC);
+ZEND_API int zend_u_register_constant(zend_uchar type, zend_constant *c TSRMLS_DC);
void zend_copy_constants(HashTable *target, HashTable *sourc);
void copy_zend_constant(zend_constant *c);
END_EXTERN_C()
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c
index ca410c56f0..b19a460f3a 100644
--- a/Zend/zend_exceptions.c
+++ b/Zend/zend_exceptions.c
@@ -86,7 +86,7 @@ static zend_object_value zend_default_exception_new_ex(zend_class_entry *class_t
obj.value.obj.handlers = &default_exception_handlers;
ALLOC_HASHTABLE(object->properties);
- zend_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(object->properties, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_hash_copy(object->properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
ALLOC_ZVAL(trace);
@@ -474,8 +474,8 @@ ZEND_METHOD(exception, __toString)
_default_exception_get_entry(getThis(), "file", sizeof("file")-1, &file TSRMLS_CC);
_default_exception_get_entry(getThis(), "line", sizeof("line")-1, &line TSRMLS_CC);
- convert_to_string(&message);
- convert_to_string(&file);
+ convert_to_text(&message);
+ convert_to_text(&file);
convert_to_long(&line);
ZVAL_STRINGL(&fname, "gettraceasstring", sizeof("gettraceasstring")-1, 0);
@@ -492,16 +492,16 @@ ZEND_METHOD(exception, __toString)
zend_call_function(&fci, NULL TSRMLS_CC);
- if (Z_TYPE_P(trace) != IS_STRING) {
+ if (Z_TYPE_P(trace) != IS_STRING && Z_TYPE_P(trace) != IS_UNICODE) {
trace = NULL;
}
- if (Z_STRLEN(message) > 0) {
- len = zend_spprintf(&str, 0, "exception '%s' with message '%s' in %s:%ld\nStack trace:\n%s",
- Z_OBJCE_P(getThis())->name, Z_STRVAL(message), Z_STRVAL(file), Z_LVAL(line),
+ if (Z_UNILEN(message) > 0) {
+ len = zend_spprintf(&str, 0, "exception '%v' with message '%R' in %s:%ld\nStack trace:\n%s",
+ Z_OBJCE_P(getThis())->name, Z_TYPE(message), Z_UNIVAL(message), Z_STRVAL(file), Z_LVAL(line),
(trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n");
} else {
- len = zend_spprintf(&str, 0, "exception '%s' in %s:%ld\nStack trace:\n%s",
+ len = zend_spprintf(&str, 0, "exception '%v' in %s:%ld\nStack trace:\n%s",
Z_OBJCE_P(getThis())->name, Z_STRVAL(file), Z_LVAL(line),
(trace && Z_STRLEN_P(trace)) ? Z_STRVAL_P(trace) : "#0 {main}\n");
}
@@ -670,7 +670,7 @@ ZEND_API void zend_exception_error(zval *exception TSRMLS_DC)
zend_call_method_with_0_params(&exception, ce_exception, NULL, "__tostring", &str);
if (!EG(exception)) {
if (Z_TYPE_P(str) != IS_STRING) {
- zend_error(E_WARNING, "%s::__toString() must return a string", ce_exception->name);
+ zend_error(E_WARNING, "%v::__toString() must return a string", ce_exception->name);
} else {
zend_update_property_string(default_exception_ce, exception, "string", sizeof("string")-1, EG(exception) ? ce_exception->name : Z_STRVAL_P(str) TSRMLS_CC);
}
@@ -686,7 +686,7 @@ ZEND_API void zend_exception_error(zval *exception TSRMLS_DC)
file = NULL;
line = NULL;
}
- zend_error_va(E_WARNING, file ? Z_STRVAL_P(file) : NULL, line ? Z_LVAL_P(line) : 0, "Uncaught %s in exception handling during call to %s::__tostring()", Z_OBJCE_P(EG(exception))->name, ce_exception->name);
+ zend_error_va(E_WARNING, file ? Z_STRVAL_P(file) : NULL, line ? Z_LVAL_P(line) : 0, "Uncaught %v in exception handling during call to %v::__tostring()", Z_OBJCE_P(EG(exception))->name, ce_exception->name);
}
str = zend_read_property(default_exception_ce, exception, "string", sizeof("string")-1, 1 TSRMLS_CC);
@@ -695,7 +695,7 @@ ZEND_API void zend_exception_error(zval *exception TSRMLS_DC)
zend_error_va(E_ERROR, Z_STRVAL_P(file), Z_LVAL_P(line), "Uncaught %s\n thrown", Z_STRVAL_P(str));
} else {
- zend_error(E_ERROR, "Uncaught exception '%s'", ce_exception->name);
+ zend_error(E_ERROR, "Uncaught exception '%v'", ce_exception->name);
}
}
@@ -716,6 +716,12 @@ ZEND_API void zend_throw_exception_object(zval *exception TSRMLS_DC)
zend_throw_exception_internal(exception TSRMLS_CC);
}
+void init_exceptions(TSRMLS_D)
+{
+ default_exception_ce = zend_get_named_class_entry("Exception", sizeof("Exception")-1 TSRMLS_CC);
+ error_exception_ce = zend_get_named_class_entry("ErrorException", sizeof("ErrorException")-1 TSRMLS_CC);
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h
index 0a47062265..b546b08c24 100644
--- a/Zend/zend_exceptions.h
+++ b/Zend/zend_exceptions.h
@@ -48,6 +48,8 @@ extern ZEND_API void (*zend_throw_exception_hook)(zval *ex TSRMLS_DC);
/* show an exception using zend_error(E_ERROR,...) */
ZEND_API void zend_exception_error(zval *exception TSRMLS_DC);
+void init_exceptions(TSRMLS_D);
+
END_EXTERN_C()
#endif
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 888b60e9d2..8aa30d3c86 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -35,6 +35,7 @@
#include "zend_ini.h"
#include "zend_exceptions.h"
#include "zend_vm.h"
+#include "zend_unicode.h"
#define _CONST_CODE 0
#define _TMP_CODE 1
@@ -148,12 +149,12 @@ ZEND_API zval** zend_get_compiled_variable_value(zend_execute_data *execute_data
return execute_data_ptr->CVs[var];
}
-static inline void zend_get_cv_address(zend_compiled_variable *cv, zval ***ptr, temp_variable *Ts TSRMLS_DC)
+static inline void zend_get_cv_address(zend_uchar utype, zend_compiled_variable *cv, zval ***ptr, temp_variable *Ts TSRMLS_DC)
{
- zval *new_zval = &EG(uninitialized_zval);
+ zval *new_zval = &EG(uninitialized_zval);
- new_zval->refcount++;
- zend_hash_quick_update(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, &new_zval, sizeof(zval *), (void **)ptr);
+ new_zval->refcount++;
+ zend_u_hash_quick_update(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, &new_zval, sizeof(zval *), (void **)ptr);
}
static inline zval *_get_zval_ptr_tmp(znode *node, temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
@@ -163,35 +164,53 @@ static inline zval *_get_zval_ptr_tmp(znode *node, temp_variable *Ts, zend_free_
static inline zval *_get_zval_ptr_var(znode *node, temp_variable *Ts, zend_free_op *should_free TSRMLS_DC)
{
- zval *ptr = T(node->u.var).var.ptr;
- if (ptr) {
- PZVAL_UNLOCK(ptr, should_free);
- return ptr;
+ if (T(node->u.var).var.ptr) {
+ PZVAL_UNLOCK(T(node->u.var).var.ptr, should_free);
+ return T(node->u.var).var.ptr;
} else {
temp_variable *T = &T(node->u.var);
zval *str = T->str_offset.str;
+ zval *ptr;
/* string offset */
ALLOC_ZVAL(ptr);
T->str_offset.ptr = ptr;
should_free->var = ptr;
- if (T->str_offset.str->type != IS_STRING
- || ((int)T->str_offset.offset<0)
- || (T->str_offset.str->value.str.len <= T->str_offset.offset)) {
- zend_error(E_NOTICE, "Uninitialized string offset: %d", T->str_offset.offset);
- ptr->value.str.val = STR_EMPTY_ALLOC();
- ptr->value.str.len = 0;
+ /* T->str_offset.str here is always IS_STRING or IS_UNICODE */
+ if (T->str_offset.str->type == IS_STRING || T->str_offset.str->type == IS_BINARY) {
+ if (((int)T->str_offset.offset<0)
+ || (T->str_offset.str->value.str.len <= T->str_offset.offset)) {
+ zend_error(E_NOTICE, "Uninitialized string offset: %d", T->str_offset.offset);
+ ptr->value.str.val = STR_EMPTY_ALLOC();
+ ptr->value.str.len = 0;
+ } else {
+ char c = str->value.str.val[T->str_offset.offset];
+
+ ptr->value.str.val = estrndup(&c, 1);
+ ptr->value.str.len = 1;
+ }
+ ptr->type = T->str_offset.str->type;
} else {
- char c = str->value.str.val[T->str_offset.offset];
+ if (((int)T->str_offset.offset<0)
+ || (Z_USTRCPLEN_P(T->str_offset.str) <= T->str_offset.offset)) {
+ zend_error(E_NOTICE, "Uninitialized string offset: %d", T->str_offset.offset);
+ ptr->value.ustr.val = USTR_MAKE("");
+ ptr->value.ustr.len = 0;
+ } else {
+ UChar32 c = zend_get_codepoint_at(str->value.ustr.val, str->value.ustr.len, T->str_offset.offset);
+ int32_t i = 0;
- ptr->value.str.val = estrndup(&c, 1);
- ptr->value.str.len = 1;
+ ptr->value.ustr.val = eumalloc(3); /* potentially 2 code units + null */
+ U16_APPEND_UNSAFE(ptr->value.ustr.val, i, c);
+ ptr->value.ustr.val[i] = 0;
+ ptr->value.ustr.len = i;
+ }
+ ptr->type = IS_UNICODE;
}
PZVAL_UNLOCK_FREE(str);
ptr->refcount=1;
ptr->is_ref=1;
- ptr->type = IS_STRING;
return ptr;
}
}
@@ -202,20 +221,22 @@ static inline zval *_get_zval_ptr_cv(znode *node, temp_variable *Ts, int type TS
if (!*ptr) {
zend_compiled_variable *cv = &CV_DEF_OF(node->u.var);
- if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
+ zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
+
+ if (zend_u_hash_quick_find(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
- zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
+ zend_error(E_NOTICE, "Undefined variable: %v", cv->name);
/* break missing intentionally */
case BP_VAR_IS:
return &EG(uninitialized_zval);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
+ zend_error(E_NOTICE, "Undefined variable: %v", cv->name);
/* break missing intentionally */
case BP_VAR_W:
- zend_get_cv_address(cv, ptr, Ts TSRMLS_CC);
+ zend_get_cv_address(utype, cv, ptr, Ts TSRMLS_CC);
break;
}
}
@@ -270,20 +291,22 @@ static inline zval **_get_zval_ptr_ptr_cv(znode *node, temp_variable *Ts, int ty
if (!*ptr) {
zend_compiled_variable *cv = &CV_DEF_OF(node->u.var);
- if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
+ zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
+
+ if (zend_u_hash_quick_find(EG(active_symbol_table), utype, cv->name, cv->name_len+1, cv->hash_value, (void **)ptr)==FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
- zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
+ zend_error(E_NOTICE, "Undefined variable: %v", cv->name);
/* break missing intentionally */
case BP_VAR_IS:
return &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE, "Undefined variable: %s", cv->name);
+ zend_error(E_NOTICE, "Undefined variable: %v", cv->name);
/* break missing intentionally */
case BP_VAR_W:
- zend_get_cv_address(cv, ptr, Ts TSRMLS_CC);
+ zend_get_cv_address(utype, cv, ptr, Ts TSRMLS_CC);
break;
}
}
@@ -435,7 +458,8 @@ static inline void make_real_object(zval **object_ptr TSRMLS_DC)
/* this should modify object only if it's empty */
if ((*object_ptr)->type == IS_NULL
|| ((*object_ptr)->type == IS_BOOL && (*object_ptr)->value.lval==0)
- || ((*object_ptr)->type == IS_STRING && (*object_ptr)->value.str.len == 0)) {
+ || (((*object_ptr)->type == IS_STRING && (*object_ptr)->type == IS_BINARY) && (*object_ptr)->value.str.len == 0)
+ || ((*object_ptr)->type == IS_UNICODE && (*object_ptr)->value.ustr.len == 0)) {
if (!PZVAL_IS_REF(*object_ptr)) {
SEPARATE_ZVAL(object_ptr);
}
@@ -459,9 +483,9 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
if (cur_arg_info->class_name) {
if (!arg) {
if(ptr && ptr->op_array) {
- zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %s, called in %s on line %d and defined", arg_num, cur_arg_info->class_name, ptr->op_array->filename, ptr->opline->lineno);
+ zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %v, called in %s on line %d and defined", arg_num, cur_arg_info->class_name, ptr->op_array->filename, ptr->opline->lineno);
} else {
- zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %s", arg_num, cur_arg_info->class_name);
+ zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %v", arg_num, cur_arg_info->class_name);
}
}
switch (Z_TYPE_P(arg)) {
@@ -475,7 +499,7 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
}
break;
case IS_OBJECT: {
- zend_class_entry *ce = zend_fetch_class(cur_arg_info->class_name, cur_arg_info->class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
+ zend_class_entry *ce = zend_u_fetch_class(UG(unicode)?IS_UNICODE:IS_STRING, cur_arg_info->class_name, cur_arg_info->class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
if (!instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
char *error_msg;
@@ -485,18 +509,18 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
error_msg = "be an instance of";
}
if(ptr && ptr->op_array) {
- zend_error_noreturn(E_ERROR, "Argument %d must %s %s, called in %s on line %d and defined", arg_num, error_msg, ce->name, ptr->op_array->filename, ptr->opline->lineno);
+ zend_error_noreturn(E_ERROR, "Argument %d must %s %v, called in %s on line %d and defined", arg_num, error_msg, ce->name, ptr->op_array->filename, ptr->opline->lineno);
} else {
- zend_error_noreturn(E_ERROR, "Argument %d must %s %s", arg_num, error_msg, ce->name);
+ zend_error_noreturn(E_ERROR, "Argument %d must %s %v", arg_num, error_msg, ce->name);
}
}
}
break;
default:
if(ptr && ptr->op_array) {
- zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %s, called in %s on line %d and defined", arg_num, cur_arg_info->class_name, ptr->op_array->filename, ptr->opline->lineno);
+ zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %v, called in %s on line %d and defined", arg_num, cur_arg_info->class_name, ptr->op_array->filename, ptr->opline->lineno);
} else {
- zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %s", arg_num, cur_arg_info->class_name);
+ zend_error_noreturn(E_ERROR, "Argument %d must be an object of class %v", arg_num, cur_arg_info->class_name);
}
break;
}
@@ -569,9 +593,9 @@ static inline void zend_assign_to_object(znode *result, zval **object_ptr, znode
value->refcount = 0;
dup = zend_get_object_classname(orig_value, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", class_name);
}
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", class_name);
value->value.obj = Z_OBJ_HANDLER_P(orig_value, clone_obj)(orig_value TSRMLS_CC);
if(!dup) {
efree(class_name);
@@ -635,7 +659,12 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
if (!variable_ptr_ptr) {
temp_variable *T = &T(op1->u.var);
- if (T->str_offset.str->type == IS_STRING) do {
+ if (UG(unicode) && Z_TYPE_P(T->str_offset.str) == IS_STRING && value->type != IS_STRING) {
+ convert_to_unicode(T->str_offset.str);
+ }
+
+ if (Z_TYPE_P(T->str_offset.str) == IS_STRING ||
+ Z_TYPE_P(T->str_offset.str) == IS_BINARY) do {
zval tmp;
zval *final_value = value;
@@ -659,9 +688,9 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
T->str_offset.str->value.str.len = T->str_offset.offset+1;
}
- if (value->type!=IS_STRING) {
+ if (value->type!=IS_STRING && value->type!=IS_BINARY) {
tmp = *value;
- if (op2->op_type & (IS_VAR|IS_CV)) {
+ if (op2->op_type & (IS_VAR|IS_CV|IS_CONST)) {
zval_copy_ctor(&tmp);
}
convert_to_string(&tmp);
@@ -686,6 +715,53 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
T(result->u.var).var = &T->str_offset.str;
*/
} while (0);
+ else if (T->str_offset.str->type == IS_UNICODE) do {
+ zval tmp;
+ zval *final_value = value;
+
+ if (((int)T->str_offset.offset < 0)) {
+ zend_error(E_WARNING, "Illegal string offset: %d", T->str_offset.offset);
+ break;
+ }
+ if (T->str_offset.offset >= T->str_offset.str->value.ustr.len) {
+ zend_uint i;
+
+ if (T->str_offset.str->value.ustr.len==0) {
+ USTR_FREE(T->str_offset.str->value.ustr.val);
+ T->str_offset.str->value.ustr.val = eumalloc(T->str_offset.offset+1+1);
+ } else {
+ T->str_offset.str->value.ustr.val = eurealloc(T->str_offset.str->value.ustr.val, T->str_offset.offset+1+1);
+ }
+ for (i=T->str_offset.str->value.ustr.len; i<T->str_offset.offset; i++) {
+ T->str_offset.str->value.ustr.val[i] = 0x20; /* ' ' */
+ }
+ T->str_offset.str->value.ustr.val[T->str_offset.offset+1] = 0;
+ T->str_offset.str->value.ustr.len = T->str_offset.offset+1;
+ }
+
+ if (value->type!=IS_UNICODE) {
+ tmp = *value;
+ if (op2->op_type & (IS_VAR|IS_CV|IS_CONST)) {
+ zval_copy_ctor(&tmp);
+ }
+ convert_to_unicode(&tmp);
+ final_value = &tmp;
+ }
+
+ T->str_offset.str->value.ustr.val[T->str_offset.offset] = final_value->value.ustr.val[0];
+
+ if (op2->op_type == IS_TMP_VAR) {
+ if (final_value == &T(op2->u.var).tmp_var) {
+ /* we can safely free final_value here
+ * because separation is done only
+ * in case op2->op_type == IS_VAR */
+ USTR_FREE(final_value->value.ustr.val);
+ }
+ }
+ if (final_value == &tmp) {
+ zval_dtor(final_value);
+ }
+ } while (0);
/* zval_ptr_dtor(&T->str_offset.str); Nuke this line if it doesn't cause a leak */
/* T(result->u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); */
@@ -727,7 +803,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
dup = zend_get_object_classname(value, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", class_name);
} else if (PZVAL_IS_REF(variable_ptr)) {
if (variable_ptr != value) {
zend_uint refcount = variable_ptr->refcount;
@@ -740,7 +816,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
*variable_ptr = *value;
variable_ptr->refcount = refcount;
variable_ptr->is_ref = 1;
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", class_name);
variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC);
if (type != IS_TMP_VAR) {
value->refcount--;
@@ -759,7 +835,7 @@ static inline void zend_assign_to_variable(znode *result, znode *op1, znode *op2
}
*variable_ptr = *value;
INIT_PZVAL(variable_ptr);
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", class_name);
variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC);
zval_ptr_dtor(&value);
}
@@ -867,14 +943,14 @@ static inline void zend_receive(zval **variable_ptr_ptr, zval *value TSRMLS_DC)
dup = zend_get_object_classname(value, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HANDLER_P(value, clone_obj) == NULL) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", class_name);
} else {
variable_ptr->refcount--;
ALLOC_ZVAL(variable_ptr);
*variable_ptr_ptr = variable_ptr;
*variable_ptr = *value;
INIT_PZVAL(variable_ptr);
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", class_name);
variable_ptr->value.obj = Z_OBJ_HANDLER_P(value, clone_obj)(value TSRMLS_CC);
}
if (!dup) {
@@ -925,7 +1001,7 @@ static inline HashTable *zend_get_target_symbol_table(zend_op *opline, temp_vari
case ZEND_FETCH_STATIC:
if (!EG(active_op_array)->static_variables) {
ALLOC_HASHTABLE(EG(active_op_array)->static_variables);
- zend_hash_init(EG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(EG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
}
return EG(active_op_array)->static_variables;
break;
@@ -939,39 +1015,61 @@ static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, zval *dim
zval **retval;
char *offset_key;
int offset_key_length;
+ zend_uchar ztype = dim->type;
+ int free_offset = 0;
- switch (dim->type) {
+ switch (ztype) {
case IS_NULL:
+ ztype = IS_STRING;
offset_key = "";
- offset_key_length = 0;
+ offset_key_length = 1;
goto fetch_string_dim;
case IS_STRING:
+ case IS_BINARY:
+ case IS_UNICODE:
- offset_key = dim->value.str.val;
- offset_key_length = dim->value.str.len;
+ offset_key = Z_UNIVAL_P(dim);
+ offset_key_length = Z_UNILEN_P(dim)+1;
fetch_string_dim:
- if (zend_symtable_find(ht, offset_key, offset_key_length+1, (void **) &retval) == FAILURE) {
+ if (UG(unicode) && ht == &EG(symbol_table) && ztype == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_key_length, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_key_length = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, ztype, offset_key, offset_key_length, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
- zend_error(E_NOTICE, "Undefined index: %s", offset_key);
+ zend_error(E_NOTICE, "Undefined index: %R", ztype, offset_key);
/* break missing intentionally */
case BP_VAR_UNSET:
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined index: %s", offset_key);
+ zend_error(E_NOTICE,"Undefined index: %R", ztype, offset_key);
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
- zend_symtable_update(ht, offset_key, offset_key_length+1, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_u_symtable_update(ht, ztype, offset_key, offset_key_length, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
case IS_RESOURCE:
zend_error(E_STRICT, "Resource ID#%ld used as offset, casting to integer (%ld)", dim->value.lval, dim->value.lval);
@@ -1049,7 +1147,8 @@ static void zend_fetch_dimension_address(temp_variable *result, zval **container
if (container->type==IS_NULL
|| (container->type==IS_BOOL && container->value.lval==0)
- || (container->type==IS_STRING && container->value.str.len==0)) {
+ || ((container->type==IS_STRING || container->type==IS_BINARY) && container->value.str.len==0)
+ || (container->type==IS_UNICODE && container->value.ustr.len==0)) {
switch (type) {
case BP_VAR_RW:
case BP_VAR_W:
@@ -1098,6 +1197,8 @@ static void zend_fetch_dimension_address(temp_variable *result, zval **container
}
break;
}
+ case IS_UNICODE:
+ case IS_BINARY:
case IS_STRING: {
zval tmp;
@@ -1220,7 +1321,8 @@ static void zend_fetch_property_address(temp_variable *result, zval **container_
/* this should modify object only if it's empty */
if (container->type == IS_NULL
|| (container->type == IS_BOOL && container->value.lval==0)
- || (container->type == IS_STRING && container->value.str.len == 0)) {
+ || ((container->type==IS_STRING || container->type==IS_BINARY) && container->value.str.len==0)
+ || (container->type==IS_UNICODE && container->value.ustr.len==0)) {
switch (type) {
case BP_VAR_RW:
case BP_VAR_W:
diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h
index bf7657ed0f..ad05ea7719 100644
--- a/Zend/zend_execute.h
+++ b/Zend/zend_execute.h
@@ -65,8 +65,11 @@ static inline void safe_free_zval_ptr_rel(zval *p ZEND_FILE_LINE_DC ZEND_FILE_LI
}
}
ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
+ZEND_API int zend_u_lookup_class(zend_uchar type, void *name, int name_length, zend_class_entry ***ce TSRMLS_DC);
ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC);
ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
+ZEND_API int zend_u_eval_string(zend_uchar type, void *str, zval *retval_ptr, char *string_name TSRMLS_DC);
+ZEND_API int zend_u_eval_string_ex(zend_uchar type, void *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
static inline int i_zend_is_true(zval *op)
{
@@ -85,6 +88,7 @@ static inline int i_zend_is_true(zval *op)
result = (op->value.dval ? 1 : 0);
break;
case IS_STRING:
+ case IS_BINARY:
if (op->value.str.len == 0
|| (op->value.str.len==1 && op->value.str.val[0]=='0')) {
result = 0;
@@ -92,6 +96,14 @@ static inline int i_zend_is_true(zval *op)
result = 1;
}
break;
+ case IS_UNICODE:
+ if (op->value.ustr.len == 0
+ || (op->value.ustr.len==1 && op->value.ustr.val[0]=='0')) {
+ result = 0;
+ } else {
+ result = 1;
+ }
+ break;
case IS_ARRAY:
result = (zend_hash_num_elements(op->value.ht)?1:0);
break;
@@ -155,6 +167,7 @@ ZEND_API void zend_set_timeout(long seconds);
ZEND_API void zend_unset_timeout(TSRMLS_D);
ZEND_API void zend_timeout(int dummy);
ZEND_API zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC);
+ZEND_API zend_class_entry *zend_u_fetch_class(zend_uchar type, void *class_name, uint class_name_len, int fetch_type TSRMLS_DC);
void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC);
#ifdef ZEND_WIN32
@@ -172,10 +185,12 @@ void zend_shutdown_timeout_thread();
/* The following tries to resolve the classname of a zval of type object.
* Since it is slow it should be only used in error messages.
*/
-#define Z_OBJ_CLASS_NAME_P(zval) ((zval) && (zval)->type == IS_OBJECT && Z_OBJ_HT_P(zval)->get_class_entry != NULL && Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC) ? Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC)->name : "")
+#define Z_OBJ_CLASS_NAME_P(zval) ((zval) && (zval)->type == IS_OBJECT && Z_OBJ_HT_P(zval)->get_class_entry != NULL && Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC) ? Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC)->name : EMPTY_STR)
ZEND_API zval** zend_get_compiled_variable_value(zend_execute_data *execute_data_ptr, zend_uint var);
+void init_unicode_strings();
+
#define ZEND_USER_OPCODE_CONTINUE 0 /* execute next opcode */
#define ZEND_USER_OPCODE_RETURN 1 /* exit from executor (return from function) */
#define ZEND_USER_OPCODE_DISPATCH 2 /* call original opcode handler */
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 4a131ccf29..94e462a33e 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -50,6 +50,16 @@ static DWORD timeout_thread_id;
static int timeout_thread_initialized=0;
#endif
+static UChar u_main[sizeof("main")];
+static UChar u_return[sizeof("return ")];
+static UChar u_semicolon[sizeof(" ;")];
+
+void init_unicode_strings() {
+ u_charsToUChars("main", u_main, sizeof("main"));
+ u_charsToUChars("return ", u_return, sizeof("return "));
+ u_charsToUChars(" ;", u_semicolon, sizeof(" ;"));
+}
+
#if ZEND_DEBUG
static void (*original_sigsegv_handler)(int);
static void zend_handle_sigsegv(int dummy)
@@ -143,7 +153,7 @@ void init_executor(TSRMLS_D)
zend_ptr_stack_init(&EG(argument_stack));
zend_ptr_stack_push(&EG(argument_stack), (void *) NULL);
- zend_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(&EG(symbol_table), 50, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
{
zval *globals;
@@ -303,7 +313,7 @@ ZEND_API char *get_active_class_name(char **space TSRMLS_DC)
if (space) {
*space = "";
}
- return "";
+ return EMPTY_STR;
}
switch (EG(function_state_ptr)->function->type) {
case ZEND_USER_FUNCTION:
@@ -314,13 +324,13 @@ ZEND_API char *get_active_class_name(char **space TSRMLS_DC)
if (space) {
*space = ce ? "::" : "";
}
- return ce ? ce->name : "";
+ return ce ? ce->name : EMPTY_STR;
}
default:
if (space) {
*space = "";
}
- return "";
+ return EMPTY_STR;
}
}
@@ -336,6 +346,8 @@ ZEND_API char *get_active_function_name(TSRMLS_D)
if (function_name) {
return function_name;
+ } else if (UG(unicode)) {
+ return (char*) u_main;
} else {
return "main";
}
@@ -429,11 +441,11 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
refcount = p->refcount;
is_ref = p->is_ref;
- if (!zend_get_constant(p->value.str.val, p->value.str.len, &const_value TSRMLS_CC)) {
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
- p->value.str.val,
- p->value.str.val);
- p->type = IS_STRING;
+ if (!zend_get_constant(Z_UNIVAL_P(p), Z_UNILEN_P(p), &const_value TSRMLS_CC)) {
+ zend_error(E_NOTICE, "Use of undefined constant %v - assumed '%v'",
+ Z_UNIVAL_P(p),
+ Z_UNIVAL_P(p));
+ p->type = UG(unicode)?IS_UNICODE:IS_STRING;
if (!inline_change) {
zval_copy_ctor(p);
}
@@ -464,7 +476,7 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
continue;
}
Z_TYPE_PP(element) &= ~IS_CONSTANT_INDEX;
- if (zend_hash_get_current_key_ex(p->value.ht, &str_index, &str_index_len, &num_index, 0, NULL)!=HASH_KEY_IS_STRING) {
+ if (zend_hash_get_current_key_ex(p->value.ht, &str_index, &str_index_len, &num_index, 0, NULL) != (UG(unicode)?HASH_KEY_IS_UNICODE:HASH_KEY_IS_STRING)) {
zend_hash_move_forward(p->value.ht);
continue;
}
@@ -474,13 +486,25 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
continue;
}
- if (const_value.type == IS_STRING && const_value.value.str.len == str_index_len-1 &&
+ if (UG(unicode)) {
+ if (const_value.type == IS_UNICODE &&
+ const_value.value.ustr.len == str_index_len-1 &&
+ !u_strncmp(Z_USTRVAL(const_value), (UChar*)str_index, str_index_len)) {
+ /* constant value is the same as its name */
+ zval_dtor(&const_value);
+ zend_hash_move_forward(p->value.ht);
+ continue;
+ }
+ } else {
+ if (const_value.type == IS_STRING &&
+ const_value.value.str.len == str_index_len-1 &&
!strncmp(const_value.value.str.val, str_index, str_index_len)) {
/* constant value is the same as its name */
zval_dtor(&const_value);
zend_hash_move_forward(p->value.ht);
continue;
}
+ }
ALLOC_ZVAL(new_val);
*new_val = **element;
@@ -498,13 +522,27 @@ ZEND_API int zval_update_constant(zval **pp, void *arg TSRMLS_DC)
long lval;
double dval;
- if (is_numeric_string(const_value.value.str.val, const_value.value.str.len, &lval, &dval, 0) == IS_LONG) {
+ if (is_numeric_string(Z_STRVAL(const_value), Z_STRLEN(const_value), &lval, &dval, 0) == IS_LONG) {
+ zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_LONG, NULL, 0, lval);
+ } else {
+ zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_STRING, Z_STRVAL(const_value), Z_STRLEN(const_value)+1, 0);
+ }
+ break;
+ }
+ case IS_UNICODE: {
+ long lval;
+ double dval;
+
+ if (is_numeric_unicode(Z_USTRVAL(const_value), Z_USTRLEN(const_value), &lval, &dval, 0) == IS_LONG) {
zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_LONG, NULL, 0, lval);
} else {
- zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_STRING, const_value.value.str.val, const_value.value.str.len+1, 0);
+ zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_UNICODE, Z_USTRVAL(const_value), Z_USTRLEN(const_value)+1, 0);
}
break;
}
+ case IS_BINARY:
+ zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_BINARY, Z_STRVAL(const_value), Z_STRLEN(const_value)+1, 0);
+ break;
case IS_BOOL:
case IS_LONG:
zend_hash_update_current_key(p->value.ht, HASH_KEY_IS_LONG, NULL, 0, const_value.value.lval);
@@ -587,6 +625,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zval *method_name;
zval *params_array;
int call_via_handler = 0;
+ char *old_func_name = NULL;
if (EG(exception)) {
return FAILURE; /* we would result in an instable executor otherwise */
@@ -649,18 +688,23 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
calling_scope = Z_OBJCE_PP(fci->object_pp);
fci->function_table = &calling_scope->function_table;
EX(object) = *fci->object_pp;
- } else if (Z_TYPE_PP(fci->object_pp) == IS_STRING) {
+ } else if (Z_TYPE_PP(fci->object_pp) == IS_STRING ||
+ Z_TYPE_PP(fci->object_pp) == IS_UNICODE) {
zend_class_entry **ce;
int found = FAILURE;
- if (EG(active_op_array) && strcmp(Z_STRVAL_PP(fci->object_pp), "self") == 0) {
+ if (EG(active_op_array) &&
+ Z_UNILEN_PP(fci->object_pp) == sizeof("self")-1 &&
+ ZEND_U_EQUAL(Z_TYPE_PP(fci->object_pp), Z_UNIVAL_PP(fci->object_pp), Z_UNILEN_PP(fci->object_pp), "self", sizeof("self")-1)) {
if (!EG(active_op_array)->scope) {
zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
}
ce = &(EG(active_op_array)->scope);
found = (*ce != NULL?SUCCESS:FAILURE);
fci->object_pp = EG(This)?&EG(This):NULL;
- } else if (strcmp(Z_STRVAL_PP(fci->object_pp), "parent") == 0 && EG(active_op_array)) {
+ } else if (EG(active_op_array) &&
+ Z_UNILEN_PP(fci->object_pp) == sizeof("parent")-1 &&
+ ZEND_U_EQUAL(Z_TYPE_PP(fci->object_pp), Z_UNIVAL_PP(fci->object_pp), Z_UNILEN_PP(fci->object_pp), "parent", sizeof("parent")-1)) {
if (!EG(active_op_array)->scope) {
zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
@@ -675,9 +719,9 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
zend_class_entry *scope;
scope = EG(active_op_array) ? EG(active_op_array)->scope : NULL;
- found = zend_lookup_class(Z_STRVAL_PP(fci->object_pp), Z_STRLEN_PP(fci->object_pp), &ce TSRMLS_CC);
+ found = zend_u_lookup_class(Z_TYPE_PP(fci->object_pp), Z_UNIVAL_PP(fci->object_pp), Z_UNILEN_PP(fci->object_pp), &ce TSRMLS_CC);
if (found == FAILURE) {
- zend_error(E_ERROR, "Class '%s' not found", Z_STRVAL_PP(fci->object_pp));
+ zend_error(E_ERROR, "Class '%R' not found", Z_TYPE_PP(fci->object_pp), Z_UNIVAL_PP(fci->object_pp));
}
if (scope && EG(This) &&
instanceof_function(Z_OBJCE_P(EG(This)), scope TSRMLS_CC) &&
@@ -702,16 +746,24 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
}
}
- if (fci->function_name->type!=IS_STRING) {
+ if (fci->function_name->type != IS_STRING &&
+ fci->function_name->type != IS_UNICODE) {
return FAILURE;
}
+ if (UG(unicode) && fci->function_name->type == IS_STRING) {
+ old_func_name = Z_STRVAL_P(fci->function_name);
+
+ Z_STRVAL_P(fci->function_name) = estrndup(Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name));
+ convert_to_unicode(fci->function_name);
+ }
+
if (fci->object_pp) {
if (Z_OBJ_HT_PP(fci->object_pp)->get_method == NULL) {
zend_error(E_ERROR, "Object does not support method calls");
}
EX(function_state).function =
- Z_OBJ_HT_PP(fci->object_pp)->get_method(fci->object_pp, Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name) TSRMLS_CC);
+ Z_OBJ_HT_PP(fci->object_pp)->get_method(fci->object_pp, Z_UNIVAL_P(fci->function_name), Z_UNILEN_P(fci->function_name) TSRMLS_CC);
if (EX(function_state).function && calling_scope != EX(function_state).function->common.scope) {
char *function_name_lc = zend_str_tolower_dup(Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name));
if (zend_hash_find(&calling_scope->function_table, function_name_lc, fci->function_name->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
@@ -721,18 +773,20 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
efree(function_name_lc);
}
} else if (calling_scope) {
- char *function_name_lc = zend_str_tolower_dup(Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name));
+ unsigned int lcname_len;
+ char *lcname = zend_u_str_case_fold(Z_TYPE_P(fci->function_name), Z_UNIVAL_P(fci->function_name), Z_UNILEN_P(fci->function_name), 1, &lcname_len);
EX(function_state).function =
- zend_std_get_static_method(calling_scope, function_name_lc, Z_STRLEN_P(fci->function_name) TSRMLS_CC);
- efree(function_name_lc);
+ zend_std_get_static_method(calling_scope, lcname, lcname_len TSRMLS_CC);
+ efree(lcname);
} else {
- char *function_name_lc = zend_str_tolower_dup(Z_STRVAL_P(fci->function_name), Z_STRLEN_P(fci->function_name));
+ unsigned int lcname_len;
+ char *lcname = zend_u_str_case_fold(Z_TYPE_P(fci->function_name), Z_UNIVAL_P(fci->function_name), Z_UNILEN_P(fci->function_name), 1, &lcname_len);
- if (zend_hash_find(fci->function_table, function_name_lc, fci->function_name->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
+ if (zend_u_hash_find(fci->function_table, Z_TYPE_P(fci->function_name), lcname, lcname_len+1, (void **) &EX(function_state).function)==FAILURE) {
EX(function_state).function = NULL;
}
- efree(function_name_lc);
+ efree(lcname);
}
if (EX(function_state).function == NULL) {
@@ -846,7 +900,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
} else {
severity = E_ERROR;
}
- zend_error(severity, "Non-static method %s::%s() cannot be called statically", calling_scope->name, EX(function_state).function->common.function_name);
+ zend_error(severity, "Non-static method %v::%v() cannot be called statically", calling_scope->name, EX(function_state).function->common.function_name);
}
}
@@ -860,7 +914,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
EG(active_symbol_table) = fci->symbol_table;
} else {
ALLOC_HASHTABLE(EG(active_symbol_table));
- zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
}
original_return_value = EG(return_value_ptr_ptr);
@@ -902,17 +956,23 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
if (EG(exception)) {
zend_throw_exception_internal(NULL TSRMLS_CC);
}
+ if (old_func_name) {
+ efree(Z_STRVAL_P(fci->function_name));
+ Z_TYPE_P(fci->function_name) = IS_STRING;
+ Z_STRVAL_P(fci->function_name) = old_func_name;
+ }
return SUCCESS;
}
-ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC)
+ZEND_API int zend_u_lookup_class(zend_uchar type, void *name, int name_length, zend_class_entry ***ce TSRMLS_DC)
{
zval **args[1];
zval autoload_function;
zval *class_name_ptr;
zval *retval_ptr;
int retval;
+ unsigned int lc_name_len;
char *lc_name;
zval *exception;
char dummy = 1;
@@ -923,11 +983,10 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
return FAILURE;
}
- lc_name = do_alloca(name_length + 1);
- zend_str_tolower_copy(lc_name, name, name_length);
+ lc_name = zend_u_str_case_fold(type, name, name_length, 1, &lc_name_len);
- if (zend_hash_find(EG(class_table), lc_name, name_length+1, (void **) ce) == SUCCESS) {
- free_alloca(lc_name);
+ if (zend_u_hash_find(EG(class_table), type, lc_name, lc_name_len+1, (void **) ce) == SUCCESS) {
+ efree(lc_name);
return SUCCESS;
}
@@ -935,17 +994,17 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
* (doesn't impact fuctionality of __autoload()
*/
if (zend_is_compiling(TSRMLS_C)) {
- free_alloca(lc_name);
+ efree(lc_name);
return FAILURE;
}
if (EG(in_autoload) == NULL) {
ALLOC_HASHTABLE(EG(in_autoload));
- zend_hash_init(EG(in_autoload), 0, NULL, NULL, 0);
+ zend_u_hash_init(EG(in_autoload), 0, NULL, NULL, 0, UG(unicode));
}
- if (zend_hash_add(EG(in_autoload), lc_name, name_length+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
- free_alloca(lc_name);
+ if (zend_u_hash_add(EG(in_autoload), type, lc_name, lc_name_len+1, (void**)&dummy, sizeof(char), NULL) == FAILURE) {
+ efree(lc_name);
return FAILURE;
}
@@ -953,7 +1012,11 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
ALLOC_ZVAL(class_name_ptr);
INIT_PZVAL(class_name_ptr);
- ZVAL_STRINGL(class_name_ptr, name, name_length, 1);
+ if (type == IS_UNICODE) {
+ ZVAL_UNICODEL(class_name_ptr, name, name_length, 1);
+ } else {
+ ZVAL_STRINGL(class_name_ptr, name, name_length, 1);
+ }
args[0] = &class_name_ptr;
@@ -979,17 +1042,17 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
zval_ptr_dtor(&class_name_ptr);
- zend_hash_del(EG(in_autoload), lc_name, name_length+1);
+ zend_u_hash_del(EG(in_autoload), type, lc_name, lc_name_len+1);
if (retval == FAILURE) {
EG(exception) = exception;
- free_alloca(lc_name);
+ efree(lc_name);
return FAILURE;
}
if (EG(exception) && exception) {
- free_alloca(lc_name);
- zend_error(E_ERROR, "Function %s(%s) threw an exception of type '%s'", ZEND_AUTOLOAD_FUNC_NAME, name, Z_OBJCE_P(EG(exception))->name);
+ efree(lc_name);
+ zend_error(E_ERROR, "Function %s(%R) threw an exception of type '%v'", ZEND_AUTOLOAD_FUNC_NAME, type, name, Z_OBJCE_P(EG(exception))->name);
return FAILURE;
}
if (!EG(exception)) {
@@ -997,12 +1060,17 @@ ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***
zval_ptr_dtor(&retval_ptr);
}
- retval = zend_hash_find(EG(class_table), lc_name, name_length + 1, (void **) ce);
- free_alloca(lc_name);
+ retval = zend_u_hash_find(EG(class_table), type, lc_name, lc_name_len + 1, (void **) ce);
+ efree(lc_name);
return retval;
}
-ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
+ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC)
+{
+ return zend_u_lookup_class(IS_STRING, name, name_length, ce TSRMLS_CC);
+}
+
+ZEND_API int zend_u_eval_string(zend_uchar type, void *string, zval *retval_ptr, char *string_name TSRMLS_DC)
{
zval pv;
zend_op_array *new_op_array;
@@ -1011,17 +1079,34 @@ ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSR
zend_uchar original_handle_op_arrays;
int retval;
- if (retval_ptr) {
- pv.value.str.len = strlen(str)+sizeof("return ;")-1;
- pv.value.str.val = emalloc(pv.value.str.len+1);
- strcpy(pv.value.str.val, "return ");
- strcat(pv.value.str.val, str);
- strcat(pv.value.str.val, " ;");
+ if (type == IS_UNICODE) {
+ UChar *str = (UChar*)string;
+
+ if (retval_ptr) {
+ pv.value.ustr.len = u_strlen(str)+sizeof("return ;")-1;
+ pv.value.ustr.val = eumalloc(pv.value.ustr.len+1);
+ u_strcpy(pv.value.ustr.val, u_return);
+ u_strcat(pv.value.ustr.val, str);
+ u_strcat(pv.value.ustr.val, u_semicolon);
+ } else {
+ pv.value.ustr.len = u_strlen(str);
+ pv.value.ustr.val = eustrndup(str, pv.value.str.len);
+ }
} else {
- pv.value.str.len = strlen(str);
- pv.value.str.val = estrndup(str, pv.value.str.len);
+ char *str = (char*)string;
+
+ if (retval_ptr) {
+ pv.value.str.len = strlen(str)+sizeof("return ;")-1;
+ pv.value.str.val = emalloc(pv.value.str.len+1);
+ strcpy(pv.value.str.val, "return ");
+ strcat(pv.value.str.val, str);
+ strcat(pv.value.str.val, " ;");
+ } else {
+ pv.value.str.len = strlen(str);
+ pv.value.str.val = estrndup(str, pv.value.str.len);
+ }
}
- pv.type = IS_STRING;
+ pv.type = type;
/*printf("Evaluating '%s'\n", pv.value.str.val);*/
@@ -1068,8 +1153,12 @@ ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSR
return retval;
}
+ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC)
+{
+ return zend_u_eval_string(IS_STRING, str, retval_ptr, string_name TSRMLS_CC);
+}
-ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC)
+ZEND_API int zend_u_eval_string_ex(zend_uchar type, void *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC)
{
int result;
@@ -1081,6 +1170,11 @@ ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name,
return result;
}
+ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC)
+{
+ return zend_u_eval_string_ex(IS_STRING, str, retval_ptr, string_name, handle_exceptions TSRMLS_CC);
+}
+
void execute_new_code(TSRMLS_D)
{
@@ -1324,7 +1418,7 @@ void zend_unset_timeout(TSRMLS_D)
}
-zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC)
+ZEND_API zend_class_entry *zend_u_fetch_class(zend_uchar type, void *class_name, uint class_name_len, int fetch_type TSRMLS_DC)
{
zend_class_entry **pce;
@@ -1344,7 +1438,7 @@ check_fetch_type:
}
return EG(scope)->parent;
case ZEND_FETCH_CLASS_AUTO: {
- fetch_type = zend_get_class_fetch_type(class_name, class_name_len);
+ fetch_type = zend_get_class_fetch_type(type, class_name, class_name_len);
if (fetch_type!=ZEND_FETCH_CLASS_DEFAULT) {
goto check_fetch_type;
}
@@ -1352,24 +1446,28 @@ check_fetch_type:
break;
}
- if (zend_lookup_class(class_name, class_name_len, &pce TSRMLS_CC)==FAILURE) {
+ if (zend_u_lookup_class(type, class_name, class_name_len, &pce TSRMLS_CC)==FAILURE) {
if (fetch_type == ZEND_FETCH_CLASS_INTERFACE) {
- zend_error(E_ERROR, "Interface '%s' not found", class_name);
+ zend_error(E_ERROR, "Interface '%R' not found", type, class_name);
} else {
- zend_error(E_ERROR, "Class '%s' not found", class_name);
+ zend_error(E_ERROR, "Class '%R' not found", type, class_name);
}
}
return *pce;
}
+zend_class_entry *zend_fetch_class(char *class_name, uint class_name_len, int fetch_type TSRMLS_DC)
+{
+ return zend_u_fetch_class(IS_STRING, class_name, class_name_len, fetch_type TSRMLS_CC);
+}
#define MAX_ABSTRACT_INFO_CNT 3
-#define MAX_ABSTRACT_INFO_FMT "%s%s%s%s"
+#define MAX_ABSTRACT_INFO_FMT "%v%s%v%s"
#define DISPLAY_ABSTRACT_FN(idx) \
- ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : "", \
+ ai.afn[idx] ? ZEND_FN_SCOPE_NAME(ai.afn[idx]) : EMPTY_STR, \
ai.afn[idx] ? "::" : "", \
- ai.afn[idx] ? ai.afn[idx]->common.function_name : "", \
+ ai.afn[idx] ? ai.afn[idx]->common.function_name : EMPTY_STR, \
ai.afn[idx] && ai.afn[idx+1] ? ", " : (ai.afn[idx] && ai.cnt > MAX_ABSTRACT_INFO_CNT ? ", ..." : "")
typedef struct _zend_abstract_info {
@@ -1400,7 +1498,7 @@ void zend_verify_abstract_class(zend_class_entry *ce TSRMLS_DC)
zend_hash_apply_with_argument(&ce->function_table, (apply_func_arg_t) zend_verify_abstract_class_function, &ai TSRMLS_CC);
if (ai.cnt) {
- zend_error(E_ERROR, "Class %s contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")",
+ zend_error(E_ERROR, "Class %v contains %d abstract method%s and must therefore be declared abstract or implement the remaining methods (" MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT MAX_ABSTRACT_INFO_FMT ")",
ce->name, ai.cnt,
ai.cnt > 1 ? "s" : "",
DISPLAY_ABSTRACT_FN(0),
@@ -1425,30 +1523,35 @@ ZEND_API void zend_reset_all_cv(HashTable *symbol_table TSRMLS_DC)
}
}
-ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC)
+ZEND_API int zend_u_delete_global_variable(zend_uchar type, void *name, int name_len TSRMLS_DC)
{
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(name, name_len+1);
+ ulong hash_value = zend_u_inline_hash_func(type, name, name_len+1);
- if (zend_hash_quick_exists(&EG(symbol_table), name, name_len+1, hash_value)) {
+ if (zend_u_hash_quick_exists(&EG(symbol_table), type, name, name_len+1, hash_value)) {
for (ex = EG(current_execute_data); ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == &EG(symbol_table)) {
int i;
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
ex->op_array->vars[i].name_len == name_len &&
- !memcmp(ex->op_array->vars[i].name, name, name_len)) {
+ !memcmp(ex->op_array->vars[i].name, name, type==IS_UNICODE?UBYTES(name_len):name_len)) {
ex->CVs[i] = NULL;
break;
}
}
}
}
- return zend_hash_del(&EG(symbol_table), name, name_len+1);
+ return zend_u_hash_del(&EG(symbol_table), type, name, name_len+1);
}
return FAILURE;
}
+ZEND_API int zend_delete_global_variable(char *name, int name_len TSRMLS_DC)
+{
+ return zend_u_delete_global_variable(IS_STRING, name, name_len TSRMLS_CC);
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h
index bdbf72e659..1182b4a833 100644
--- a/Zend/zend_globals.h
+++ b/Zend/zend_globals.h
@@ -5,7 +5,7 @@
| Copyright (c) 1998-2005 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
- | that is bundled with this package in the file LICENSE, and is |
+ | that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
@@ -36,9 +36,8 @@
#include "zend_objects_API.h"
#include "zend_modules.h"
-#ifdef ZEND_MULTIBYTE
-#include "zend_multibyte.h"
-#endif /* ZEND_MULTIBYTE */
+#include <unicode/ucnv.h>
+#include <unicode/ucol.h>
/* Define ZTS if you want a thread-safe Zend */
/*#undef ZTS*/
@@ -132,17 +131,16 @@ struct _zend_compiler_globals {
char *doc_comment;
zend_uint doc_comment_len;
-#ifdef ZEND_MULTIBYTE
- zend_encoding **script_encoding_list;
- int script_encoding_list_size;
+ zend_uchar literal_type;
- zend_encoding *internal_encoding;
-
- /* multibyte utility functions */
- zend_encoding_detector encoding_detector;
- zend_encoding_converter encoding_converter;
- zend_encoding_oddlen encoding_oddlen;
-#endif /* ZEND_MULTIBYTE */
+#ifdef ZTS
+ HashTable *global_function_table;
+ HashTable *global_class_table;
+ HashTable *global_auto_globals_table;
+ HashTable *global_u_function_table;
+ HashTable *global_u_class_table;
+ HashTable *global_u_auto_globals_table;
+#endif
};
@@ -232,6 +230,11 @@ struct _zend_executor_globals {
zend_property_info std_property_info;
+#ifdef ZTS
+ HashTable *global_constants_table;
+ HashTable *global_u_constants_table;
+#endif
+
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};
@@ -286,21 +289,31 @@ struct _zend_scanner_globals {
int yy_start_stack_depth;
int *yy_start_stack;
-#ifdef ZEND_MULTIBYTE
- /* original (unfiltered) script */
- char *script_org;
- int script_org_size;
-
- /* filtered script */
- char *script_filtered;
- int script_filtered_size;
-
- /* input/ouput filters */
- zend_encoding_filter input_filter;
- zend_encoding_filter output_filter;
- zend_encoding *script_encoding;
- zend_encoding *internal_encoding;
-#endif /* ZEND_MULTIBYTE */
+ UConverter *input_conv; /* converter for flex input */
+ UConverter *output_conv; /* converter for data from flex output */
+ zend_bool encoding_checked;
+ char* rest_str;
+ int rest_len;
+};
+
+struct _zend_unicode_globals {
+ zend_bool unicode; /* indicates whether full Unicode mode is enabled */
+
+ UConverter *fallback_encoding_conv; /* converter for default encoding for IS_STRING type */
+ UConverter *runtime_encoding_conv; /* runtime encoding converter */
+ UConverter *output_encoding_conv; /* output layer converter */
+ UConverter *script_encoding_conv; /* default script encoding converter */
+ UConverter *http_input_encoding_conv;/* http input encoding converter */
+ UConverter *utf8_conv; /* all-purpose UTF-8 converter */
+
+ uint8_t from_u_error_mode;
+ UChar subst_char[3];
+ uint8_t subst_char_len;
+
+ char *default_locale;
+ UCollator *default_collator;
+
+ HashTable flex_compatible;
};
#endif /* ZEND_GLOBALS_H */
diff --git a/Zend/zend_globals_macros.h b/Zend/zend_globals_macros.h
index ce98d15d5b..58d43080fe 100644
--- a/Zend/zend_globals_macros.h
+++ b/Zend/zend_globals_macros.h
@@ -26,6 +26,7 @@ typedef struct _zend_compiler_globals zend_compiler_globals;
typedef struct _zend_executor_globals zend_executor_globals;
typedef struct _zend_alloc_globals zend_alloc_globals;
typedef struct _zend_scanner_globals zend_scanner_globals;
+typedef struct _zend_unicode_globals zend_unicode_globals;
/* Compiler */
#ifdef ZTS
@@ -78,6 +79,16 @@ extern ZEND_API zend_scanner_globals ini_scanner_globals;
#endif
+/* Unicode */
+#ifdef ZTS
+# define UG(v) TSRMG(unicode_globals_id, zend_unicode_globals *, v)
+extern ZEND_API ts_rsrc_id unicode_globals_id;
+#else
+# define UG(v) (unicode_globals.v)
+extern ZEND_API zend_unicode_globals unicode_globals;
+#endif
+
+
/* For limited downwards source compatibility */
#define CLS_FETCH()
#define ELS_FETCH()
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 407b7627b9..41178883fb 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -5,7 +5,7 @@
| Copyright (c) 1998-2005 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend license, |
- | that is bundled with this package in the file LICENSE, and is |
+ | that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
@@ -20,6 +20,11 @@
/* $Id$ */
#include "zend.h"
+#include "zend_operators.h"
+#include "zend_globals.h"
+
+#include <unicode/utypes.h>
+#include <unicode/uchar.h>
#define CONNECT_TO_BUCKET_DLLIST(element, list_head) \
(element)->pNext = (list_head); \
@@ -42,6 +47,21 @@
(ht)->pInternalPointer = (element); \
}
+#define UNICODE_KEY(ht, type, arKey, nKeyLength, tmp) \
+ if (ht->unicode && type == IS_STRING) { \
+ UErrorCode status = U_ZERO_ERROR; \
+ UChar *u = NULL; \
+ int32_t u_len; \
+ TSRMLS_FETCH(); \
+ zend_convert_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u, &u_len, (char*)arKey, nKeyLength-1, &status); \
+ if (U_FAILURE(status)) { \
+ /* UTODO: */ \
+ } \
+ type = IS_UNICODE; \
+ tmp = arKey = u; \
+ }
+
+
#if ZEND_DEBUG
#define HT_OK 0
#define HT_IS_DESTROYING 1
@@ -94,16 +114,20 @@ static void _zend_is_inconsistent(HashTable *ht, char *file, int line)
static int zend_hash_do_resize(HashTable *ht);
-ZEND_API ulong zend_hash_func(char *arKey, uint nKeyLength)
+ZEND_API ulong zend_u_hash_func(zend_uchar type, char *arKey, uint nKeyLength)
{
- return zend_inline_hash_func(arKey, nKeyLength);
+ return zend_u_inline_hash_func(type, arKey, nKeyLength);
}
+ZEND_API ulong zend_hash_func(char *arKey, uint nKeyLength)
+{
+ return zend_u_hash_func(IS_STRING, arKey, nKeyLength);
+}
#define UPDATE_DATA(ht, p, pData, nDataSize) \
if (nDataSize == sizeof(void*)) { \
- if (!(p)->pDataPtr) { \
- pefree_rel((p)->pData, (ht)->persistent); \
+ if ((p)->pData && (p)->pData != &(p)->pDataPtr) { \
+ pefree_rel(p->pData, ht->persistent); \
} \
memcpy(&(p)->pDataPtr, pData, sizeof(void *)); \
(p)->pData = &(p)->pDataPtr; \
@@ -134,7 +158,7 @@ ZEND_API ulong zend_hash_func(char *arKey, uint nKeyLength)
-ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
+ZEND_API int _zend_u_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool unicode ZEND_FILE_LINE_DC)
{
uint i = 3;
Bucket **tmp;
@@ -155,9 +179,10 @@ ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunctio
ht->nNextFreeElement = 0;
ht->pInternalPointer = NULL;
ht->persistent = persistent;
+ ht->unicode = unicode;
ht->nApplyCount = 0;
ht->bApplyProtection = 1;
-
+
/* Uses ecalloc() so that Bucket* == NULL */
if (persistent) {
tmp = (Bucket **) calloc(ht->nTableSize, sizeof(Bucket *));
@@ -171,10 +196,14 @@ ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunctio
ht->arBuckets = tmp;
}
}
-
+
return SUCCESS;
}
+ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC)
+{
+ return _zend_u_hash_init(ht, nSize, pHashFunction, pDestructor, persistent, 0 ZEND_FILE_LINE_CC);
+}
ZEND_API int _zend_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
{
@@ -184,6 +213,13 @@ ZEND_API int _zend_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunc
return retval;
}
+ZEND_API int _zend_u_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool unicode, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
+{
+ int retval = _zend_u_hash_init(ht, nSize, pHashFunction, pDestructor, persistent, unicode ZEND_FILE_LINE_CC);
+
+ ht->bApplyProtection = bApplyProtection;
+ return retval;
+}
ZEND_API void zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProtection)
{
@@ -192,11 +228,13 @@ ZEND_API void zend_hash_set_apply_protection(HashTable *ht, zend_bool bApplyProt
-ZEND_API int _zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
+ZEND_API int _zend_u_hash_add_or_update(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
{
ulong h;
uint nIndex;
Bucket *p;
+ void *tmp = NULL;
+ uint realKeyLength;
IS_CONSISTENT(ht);
@@ -207,43 +245,52 @@ ZEND_API int _zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLengt
return FAILURE;
}
- h = zend_inline_hash_func(arKey, nKeyLength);
+ UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
+ realKeyLength = REAL_KEY_SIZE(type, nKeyLength);
+
+ h = zend_u_inline_hash_func(type, arKey, nKeyLength);
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
- if (flag & HASH_ADD) {
- return FAILURE;
- }
- HANDLE_BLOCK_INTERRUPTIONS();
+ if ((p->h == h) &&
+ (p->key.type == type) &&
+ (p->nKeyLength == nKeyLength) &&
+ !memcmp(&p->key.u, arKey, realKeyLength)) {
+ if (flag & HASH_ADD) {
+ if (tmp) efree(tmp);
+ return FAILURE;
+ }
+ HANDLE_BLOCK_INTERRUPTIONS();
#if ZEND_DEBUG
- if (p->pData == pData) {
- ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n");
- HANDLE_UNBLOCK_INTERRUPTIONS();
- return FAILURE;
- }
-#endif
- if (ht->pDestructor) {
- ht->pDestructor(p->pData);
- }
- UPDATE_DATA(ht, p, pData, nDataSize);
- if (pDest) {
- *pDest = p->pData;
- }
+ if (p->pData == pData) {
+ ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n");
HANDLE_UNBLOCK_INTERRUPTIONS();
- return SUCCESS;
+ if (tmp) efree(tmp);
+ return FAILURE;
}
+#endif
+ if (ht->pDestructor) {
+ ht->pDestructor(p->pData);
+ }
+ UPDATE_DATA(ht, p, pData, nDataSize);
+ if (pDest) {
+ *pDest = p->pData;
+ }
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+ if (tmp) efree(tmp);
+ return SUCCESS;
}
p = p->pNext;
}
-
- p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent);
+
+ p = (Bucket *) pemalloc(sizeof(Bucket)-sizeof(p->key.u)+realKeyLength, ht->persistent);
if (!p) {
+ if (tmp) efree(tmp);
return FAILURE;
}
- memcpy(p->arKey, arKey, nKeyLength);
+ p->key.type = type;
+ memcpy(&p->key.u, arKey, realKeyLength);
p->nKeyLength = nKeyLength;
INIT_DATA(ht, p, pData, nDataSize);
p->h = h;
@@ -259,13 +306,21 @@ ZEND_API int _zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLengt
ht->nNumOfElements++;
ZEND_HASH_IF_FULL_DO_RESIZE(ht); /* If the Hash table is full, resize it */
+ if (tmp) efree(tmp);
return SUCCESS;
}
-ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
+ZEND_API int _zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
+{
+ return _zend_u_hash_add_or_update(ht, IS_STRING, arKey, nKeyLength, pData, nDataSize, pDest, flag ZEND_FILE_LINE_CC);
+}
+
+ZEND_API int _zend_u_hash_quick_add_or_update(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
{
uint nIndex;
Bucket *p;
+ void *tmp = NULL;
+ uint realKeyLength;
IS_CONSISTENT(ht);
@@ -273,47 +328,59 @@ ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, char *arKey, uint nKe
return zend_hash_index_update(ht, h, pData, nDataSize, pDest);
}
+ if (ht->unicode && type == IS_STRING) {
+ UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
+ h = zend_u_inline_hash_func(IS_UNICODE, arKey, nKeyLength);
+ }
+ realKeyLength = REAL_KEY_SIZE(type, nKeyLength);
+
nIndex = h & ht->nTableMask;
-
+
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
- if (flag & HASH_ADD) {
- return FAILURE;
- }
- HANDLE_BLOCK_INTERRUPTIONS();
+ if ((p->h == h) &&
+ (p->key.type == type) &&
+ (p->nKeyLength == nKeyLength) &&
+ !memcmp(&p->key.u, arKey, realKeyLength)) {
+ if (flag & HASH_ADD) {
+ if (tmp) efree(tmp);
+ return FAILURE;
+ }
+ HANDLE_BLOCK_INTERRUPTIONS();
#if ZEND_DEBUG
- if (p->pData == pData) {
- ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n");
- HANDLE_UNBLOCK_INTERRUPTIONS();
- return FAILURE;
- }
-#endif
- if (ht->pDestructor) {
- ht->pDestructor(p->pData);
- }
- UPDATE_DATA(ht, p, pData, nDataSize);
- if (pDest) {
- *pDest = p->pData;
- }
+ if (p->pData == pData) {
+ ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n");
HANDLE_UNBLOCK_INTERRUPTIONS();
- return SUCCESS;
+ if (tmp) efree(tmp);
+ return FAILURE;
}
+#endif
+ if (ht->pDestructor) {
+ ht->pDestructor(p->pData);
+ }
+ UPDATE_DATA(ht, p, pData, nDataSize);
+ if (pDest) {
+ *pDest = p->pData;
+ }
+ HANDLE_UNBLOCK_INTERRUPTIONS();
+ if (tmp) efree(tmp);
+ return SUCCESS;
}
p = p->pNext;
}
-
- p = (Bucket *) pemalloc(sizeof(Bucket) - 1 + nKeyLength, ht->persistent);
+
+ p = (Bucket *) pemalloc(sizeof(Bucket)-sizeof(p->key.u)+realKeyLength, ht->persistent);
if (!p) {
+ if (tmp) efree(tmp);
return FAILURE;
}
- memcpy(p->arKey, arKey, nKeyLength);
+ p->key.type = type;
+ memcpy(&p->key.u, arKey, realKeyLength);
p->nKeyLength = nKeyLength;
INIT_DATA(ht, p, pData, nDataSize);
p->h = h;
-
+
CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[nIndex]);
if (pDest) {
@@ -327,15 +394,27 @@ ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, char *arKey, uint nKe
ht->nNumOfElements++;
ZEND_HASH_IF_FULL_DO_RESIZE(ht); /* If the Hash table is full, resize it */
+ if (tmp) efree(tmp);
return SUCCESS;
}
+ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC)
+{
+ return _zend_u_hash_quick_add_or_update(ht, IS_STRING, arKey, nKeyLength, h, pData, nDataSize, pDest, flag ZEND_FILE_LINE_CC);
+}
+
+ZEND_API int zend_u_hash_add_empty_element(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength)
+{
+ void *dummy = (void *) 1;
+
+ return zend_u_hash_add(ht, type, arKey, nKeyLength, &dummy, sizeof(void *), NULL);
+}
ZEND_API int zend_hash_add_empty_element(HashTable *ht, char *arKey, uint nKeyLength)
{
void *dummy = (void *) 1;
- return zend_hash_add(ht, arKey, nKeyLength, &dummy, sizeof(void *), NULL);
+ return zend_u_hash_add(ht, IS_STRING, arKey, nKeyLength, &dummy, sizeof(void *), NULL);
}
@@ -380,7 +459,7 @@ ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void
}
p = p->pNext;
}
- p = (Bucket *) pemalloc_rel(sizeof(Bucket) - 1, ht->persistent);
+ p = (Bucket *) pemalloc_rel(sizeof(Bucket) - sizeof(p->key.u), ht->persistent);
if (!p) {
return FAILURE;
}
@@ -447,22 +526,29 @@ ZEND_API int zend_hash_rehash(HashTable *ht)
return SUCCESS;
}
-ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLength, ulong h, int flag)
+ZEND_API int zend_u_hash_del_key_or_index(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, ulong h, int flag)
{
uint nIndex;
Bucket *p;
+ void *tmp = NULL;
+ uint realKeyLength;
IS_CONSISTENT(ht);
if (flag == HASH_DEL_KEY) {
- h = zend_inline_hash_func(arKey, nKeyLength);
+ UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
+ realKeyLength = REAL_KEY_SIZE(type, nKeyLength);
+ h = zend_u_inline_hash_func(type, arKey, nKeyLength);
}
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && ((p->nKeyLength == 0) || /* Numeric index */
- ((p->nKeyLength == nKeyLength) && (!memcmp(p->arKey, arKey, nKeyLength))))) {
+ if ((p->h == h) &&
+ ((p->nKeyLength == 0) || /* Numeric index */
+ ((p->nKeyLength == nKeyLength) &&
+ (p->key.type == type) &&
+ (!memcmp(&p->key.u, arKey, realKeyLength))))) {
HANDLE_BLOCK_INTERRUPTIONS();
if (p == ht->arBuckets[nIndex]) {
ht->arBuckets[nIndex] = p->pNext;
@@ -474,7 +560,7 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLen
}
if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext;
- } else {
+ } else {
/* Deleting the head of the list */
ht->pListHead = p->pListNext;
}
@@ -489,19 +575,25 @@ ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLen
if (ht->pDestructor) {
ht->pDestructor(p->pData);
}
- if (!p->pDataPtr) {
+ if (p->pData && p->pData != &p->pDataPtr) {
pefree(p->pData, ht->persistent);
}
pefree(p, ht->persistent);
HANDLE_UNBLOCK_INTERRUPTIONS();
ht->nNumOfElements--;
+ if (tmp) efree(tmp);
return SUCCESS;
}
p = p->pNext;
}
+ if (tmp) efree(tmp);
return FAILURE;
}
+ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLength, ulong h, int flag)
+{
+ return zend_u_hash_del_key_or_index(ht, IS_STRING, arKey, nKeyLength, h, flag);
+}
ZEND_API void zend_hash_destroy(HashTable *ht)
{
@@ -518,7 +610,7 @@ ZEND_API void zend_hash_destroy(HashTable *ht)
if (ht->pDestructor) {
ht->pDestructor(q->pData);
}
- if (!q->pDataPtr && q->pData) {
+ if (q->pData && q->pData != &q->pDataPtr) {
pefree(q->pData, ht->persistent);
}
pefree(q, ht->persistent);
@@ -544,7 +636,7 @@ ZEND_API void zend_hash_clean(HashTable *ht)
if (ht->pDestructor) {
ht->pDestructor(q->pData);
}
- if (!q->pDataPtr && q->pData) {
+ if (q->pData && q->pData != &q->pDataPtr) {
pefree(q->pData, ht->persistent);
}
pefree(q, ht->persistent);
@@ -573,7 +665,7 @@ static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
if (ht->pDestructor) {
ht->pDestructor(p->pData);
}
- if (!p->pDataPtr) {
+ if (p->pData && p->pData != &p->pDataPtr) {
pefree(p->pData, ht->persistent);
}
retval = p->pListNext;
@@ -594,7 +686,7 @@ static Bucket *zend_hash_apply_deleter(HashTable *ht, Bucket *p)
if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext;
- } else {
+ } else {
/* Deleting the head of the list */
ht->pListHead = p->pListNext;
}
@@ -647,7 +739,7 @@ ZEND_API void zend_hash_graceful_reverse_destroy(HashTable *ht)
}
/* This is used to selectively delete certain entries from a hashtable.
- * destruct() receives the data and decides if the entry should be deleted
+ * destruct() receives the data and decides if the entry should be deleted
* or not
*/
@@ -703,9 +795,14 @@ ZEND_API void zend_hash_apply_with_arguments(HashTable *ht, apply_func_args_t de
p = ht->pListHead;
while (p != NULL) {
va_start(args, num_args);
- hash_key.arKey = p->arKey;
hash_key.nKeyLength = p->nKeyLength;
hash_key.h = p->h;
+ hash_key.type = p->key.type;
+ if (hash_key.type == IS_UNICODE) {
+ hash_key.u.unicode = p->key.u.unicode;
+ } else {
+ hash_key.u.string = p->key.u.string;
+ }
if (destruct(p->pData, num_args, args, &hash_key)) {
p = zend_hash_apply_deleter(ht, p);
} else {
@@ -732,10 +829,10 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR
q = p;
p = p->pListLast;
if (result & ZEND_HASH_APPLY_REMOVE) {
- if (q->nKeyLength>0) {
- zend_hash_del(ht, q->arKey, q->nKeyLength);
- } else {
+ if (q->nKeyLength==0) {
zend_hash_index_del(ht, q->h);
+ } else {
+ zend_u_hash_del(ht, q->key.type, &q->key.u.unicode, q->nKeyLength);
}
}
if (result & ZEND_HASH_APPLY_STOP) {
@@ -756,10 +853,10 @@ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_fun
p = source->pListHead;
while (p) {
- if (p->nKeyLength) {
- zend_hash_update(target, p->arKey, p->nKeyLength, p->pData, size, &new_entry);
+ if (p->nKeyLength == 0) {
+ zend_hash_index_update(target, p->h, p->pData, size, &new_entry);
} else {
- zend_hash_index_update(target, p->h, p->pData, size, &new_entry);
+ zend_u_hash_update(target, p->key.type, &p->key.u, p->nKeyLength, p->pData, size, &new_entry);
}
if (pCopyConstructor) {
pCopyConstructor(new_entry);
@@ -781,12 +878,12 @@ ZEND_API void _zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_f
p = source->pListHead;
while (p) {
- if (p->nKeyLength>0) {
- if (_zend_hash_add_or_update(target, p->arKey, p->nKeyLength, p->pData, size, &t, mode ZEND_FILE_LINE_RELAY_CC)==SUCCESS && pCopyConstructor) {
+ if (p->nKeyLength==0) {
+ if ((mode==HASH_UPDATE || !zend_hash_index_exists(target, p->h)) && zend_hash_index_update(target, p->h, p->pData, size, &t)==SUCCESS && pCopyConstructor) {
pCopyConstructor(t);
}
} else {
- if ((mode==HASH_UPDATE || !zend_hash_index_exists(target, p->h)) && zend_hash_index_update(target, p->h, p->pData, size, &t)==SUCCESS && pCopyConstructor) {
+ if (_zend_u_hash_add_or_update(target, p->key.type, &p->key.u, p->nKeyLength, p->pData, size, &t, mode ZEND_FILE_LINE_RELAY_CC)==SUCCESS && pCopyConstructor) {
pCopyConstructor(t);
}
}
@@ -800,9 +897,14 @@ static zend_bool zend_hash_replace_checker_wrapper(HashTable *target, void *sour
{
zend_hash_key hash_key;
- hash_key.arKey = p->arKey;
hash_key.nKeyLength = p->nKeyLength;
hash_key.h = p->h;
+ hash_key.type = p->key.type;
+ if (hash_key.type == IS_UNICODE) {
+ hash_key.u.unicode = p->key.u.unicode;
+ } else {
+ hash_key.u.string = p->key.u.string;
+ }
return merge_checker_func(target, source_data, &hash_key, pParam);
}
@@ -818,7 +920,7 @@ ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor
p = source->pListHead;
while (p) {
if (zend_hash_replace_checker_wrapper(target, p->pData, p, pParam, pMergeSource)) {
- if (zend_hash_quick_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t)==SUCCESS && pCopyConstructor) {
+ if (zend_u_hash_quick_update(target, p->key.type, &p->key.u, p->nKeyLength, p->h, p->pData, size, &t)==SUCCESS && pCopyConstructor) {
pCopyConstructor(t);
}
}
@@ -828,9 +930,14 @@ ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor
}
+ZEND_API ulong zend_u_get_hash_value(zend_uchar type, char *arKey, uint nKeyLength)
+{
+ return zend_u_inline_hash_func(type, arKey, nKeyLength);
+}
+
ZEND_API ulong zend_get_hash_value(char *arKey, uint nKeyLength)
{
- return zend_inline_hash_func(arKey, nKeyLength);
+ return zend_u_get_hash_value(IS_STRING, arKey, nKeyLength);
}
@@ -838,35 +945,50 @@ ZEND_API ulong zend_get_hash_value(char *arKey, uint nKeyLength)
* data is returned in pData. The reason is that there's no reason
* someone using the hash table might not want to have NULL data
*/
-ZEND_API int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData)
+ZEND_API int zend_u_hash_find(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, void **pData)
{
ulong h;
uint nIndex;
Bucket *p;
+ void *tmp = NULL;
+ uint realKeyLength;
IS_CONSISTENT(ht);
- h = zend_inline_hash_func(arKey, nKeyLength);
+ UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
+ realKeyLength = REAL_KEY_SIZE(type, nKeyLength);
+
+ h = zend_u_inline_hash_func(type, arKey, nKeyLength);
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
- *pData = p->pData;
- return SUCCESS;
- }
+ if ((p->h == h) &&
+ (p->key.type == type) &&
+ (p->nKeyLength == nKeyLength) &&
+ !memcmp(&p->key.u, arKey, realKeyLength)) {
+ *pData = p->pData;
+ if (tmp) efree(tmp);
+ return SUCCESS;
}
p = p->pNext;
}
+ if (tmp) efree(tmp);
return FAILURE;
}
+ZEND_API int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData)
+{
+ return zend_u_hash_find(ht, IS_STRING, arKey, nKeyLength, pData);
+}
-ZEND_API int zend_hash_quick_find(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void **pData)
+
+ZEND_API int zend_u_hash_quick_find(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, ulong h, void **pData)
{
uint nIndex;
Bucket *p;
+ void *tmp = NULL;
+ uint realKeyLength;
if (nKeyLength==0) {
return zend_hash_index_find(ht, h, pData);
@@ -874,50 +996,77 @@ ZEND_API int zend_hash_quick_find(HashTable *ht, char *arKey, uint nKeyLength, u
IS_CONSISTENT(ht);
+ if (ht->unicode && type == IS_STRING) {
+ UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
+ h = zend_u_inline_hash_func(IS_UNICODE, arKey, nKeyLength);
+ }
+ realKeyLength = REAL_KEY_SIZE(type, nKeyLength);
+
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
- *pData = p->pData;
- return SUCCESS;
- }
+ if ((p->h == h) &&
+ (p->key.type == type) &&
+ (p->nKeyLength == nKeyLength) &&
+ !memcmp(&p->key.u, arKey, realKeyLength)) {
+ *pData = p->pData;
+ if (tmp) efree(tmp);
+ return SUCCESS;
}
p = p->pNext;
}
+ if (tmp) efree(tmp);
return FAILURE;
}
+ZEND_API int zend_hash_quick_find(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void **pData)
+{
+ return zend_u_hash_quick_find(ht, IS_STRING, arKey, nKeyLength, h, pData);
+}
-ZEND_API int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLength)
+ZEND_API int zend_u_hash_exists(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength)
{
ulong h;
uint nIndex;
Bucket *p;
+ void *tmp = NULL;
+ uint realKeyLength;
IS_CONSISTENT(ht);
- h = zend_inline_hash_func(arKey, nKeyLength);
+ UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
+ realKeyLength = REAL_KEY_SIZE(type, nKeyLength);
+
+ h = zend_u_inline_hash_func(type, arKey, nKeyLength);
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
- return 1;
- }
+ if ((p->h == h) &&
+ (p->key.type == type) &&
+ (p->nKeyLength == nKeyLength) &&
+ !memcmp(&p->key.u, arKey, realKeyLength)) {
+ if (tmp) efree(tmp);
+ return 1;
}
p = p->pNext;
}
+ if (tmp) efree(tmp);
return 0;
}
+ZEND_API int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLength)
+{
+ return zend_u_hash_exists(ht, IS_STRING, arKey, nKeyLength);
+}
-ZEND_API int zend_hash_quick_exists(HashTable *ht, char *arKey, uint nKeyLength, ulong h)
+ZEND_API int zend_u_hash_quick_exists(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, ulong h)
{
uint nIndex;
Bucket *p;
+ void *tmp = NULL;
+ uint realKeyLength;
if (nKeyLength==0) {
return zend_hash_index_exists(ht, h);
@@ -925,21 +1074,33 @@ ZEND_API int zend_hash_quick_exists(HashTable *ht, char *arKey, uint nKeyLength,
IS_CONSISTENT(ht);
+ if (ht->unicode && type == IS_STRING) {
+ UNICODE_KEY(ht, type, arKey, nKeyLength, tmp);
+ h = zend_u_inline_hash_func(type, arKey, nKeyLength);
+ }
+ realKeyLength = REAL_KEY_SIZE(type, nKeyLength);
+
nIndex = h & ht->nTableMask;
p = ht->arBuckets[nIndex];
while (p != NULL) {
- if ((p->h == h) && (p->nKeyLength == nKeyLength)) {
- if (!memcmp(p->arKey, arKey, nKeyLength)) {
- return 1;
- }
+ if ((p->h == h) &&
+ (p->key.type == type) &&
+ (p->nKeyLength == nKeyLength) &&
+ !memcmp(&p->key.u, arKey, realKeyLength)) {
+ if (tmp) efree(tmp);
+ return 1;
}
p = p->pNext;
}
+ if (tmp) efree(tmp);
return 0;
-
}
+ZEND_API int zend_hash_quick_exists(HashTable *ht, char *arKey, uint nKeyLength, ulong h)
+{
+ return zend_u_hash_quick_exists(ht, IS_STRING, arKey, nKeyLength, h);
+}
ZEND_API int zend_hash_index_find(HashTable *ht, ulong h, void **pData)
{
@@ -1001,7 +1162,7 @@ ZEND_API void zend_hash_internal_pointer_reset_ex(HashTable *ht, HashPosition *p
}
-/* This function will be extremely optimized by remembering
+/* This function will be extremely optimized by remembering
* the end of the list
*/
ZEND_API void zend_hash_internal_pointer_end_ex(HashTable *ht, HashPosition *pos)
@@ -1053,15 +1214,31 @@ ZEND_API int zend_hash_get_current_key_ex(HashTable *ht, char **str_index, uint
if (p) {
if (p->nKeyLength) {
- if (duplicate) {
- *str_index = estrndup(p->arKey, p->nKeyLength - 1);
- } else {
- *str_index = p->arKey;
- }
- if (str_length) {
- *str_length = p->nKeyLength;
+ if (p->key.type == IS_STRING || p->key.type == IS_BINARY) {
+ if (duplicate) {
+ *str_index = estrndup(p->key.u.string, p->nKeyLength-1);
+ } else {
+ *str_index = p->key.u.string;
+ }
+ if (str_length) {
+ *str_length = p->nKeyLength;
+ }
+ if (p->key.type == IS_BINARY) {
+ return HASH_KEY_IS_BINARY;
+ } else {
+ return HASH_KEY_IS_STRING;
+ }
+ } else if (p->key.type == IS_UNICODE) {
+ if (duplicate) {
+ *str_index = (char*)eustrndup(p->key.u.unicode, p->nKeyLength-1);
+ } else {
+ *str_index = p->key.u.string;
+ }
+ if (str_length) {
+ *str_length = p->nKeyLength;
+ }
+ return HASH_KEY_IS_UNICODE;
}
- return HASH_KEY_IS_STRING;
} else {
*num_index = p->h;
return HASH_KEY_IS_LONG;
@@ -1081,7 +1258,13 @@ ZEND_API int zend_hash_get_current_key_type_ex(HashTable *ht, HashPosition *pos)
if (p) {
if (p->nKeyLength) {
- return HASH_KEY_IS_STRING;
+ if (p->key.type == IS_UNICODE) {
+ return HASH_KEY_IS_UNICODE;
+ } else if (p->key.type == IS_BINARY) {
+ return HASH_KEY_IS_BINARY;
+ } else {
+ return HASH_KEY_IS_STRING;
+ }
} else {
return HASH_KEY_IS_LONG;
}
@@ -1124,12 +1307,20 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, char *
return SUCCESS;
}
zend_hash_index_del(ht, num_index);
- } else if (key_type == HASH_KEY_IS_STRING) {
+ } else if (key_type == HASH_KEY_IS_STRING || key_type == HASH_KEY_IS_BINARY) {
+ if (p->nKeyLength == str_length &&
+ p->key.type == ((key_type == HASH_KEY_IS_STRING)?IS_STRING:IS_BINARY) &&
+ memcmp(p->key.u.string, str_index, str_length) == 0) {
+ return SUCCESS;
+ }
+ zend_u_hash_del(ht, (key_type == HASH_KEY_IS_STRING)?IS_STRING:IS_BINARY, str_index, str_length);
+ } else if (key_type == HASH_KEY_IS_UNICODE) {
if (p->nKeyLength == str_length &&
- memcmp(p->arKey, str_index, str_length) == 0) {
+ p->key.type == IS_UNICODE &&
+ memcmp(p->key.u.string, str_index, str_length * sizeof(UChar*)) == 0) {
return SUCCESS;
}
- zend_hash_del(ht, str_index, str_length);
+ zend_u_hash_del(ht, IS_UNICODE, str_index, str_length);
} else {
return FAILURE;
}
@@ -1179,9 +1370,14 @@ ZEND_API int zend_hash_update_current_key_ex(HashTable *ht, int key_type, char *
if (key_type == HASH_KEY_IS_LONG) {
p->h = num_index;
+ } else if (key_type == HASH_KEY_IS_UNICODE) {
+ memcpy(p->key.u.unicode, str_index, str_length * sizeof(UChar));
+ p->key.type = IS_UNICODE;
+ p->h = zend_u_inline_hash_func(IS_UNICODE, str_index, str_length);
} else {
- memcpy(p->arKey, str_index, str_length);
- p->h = zend_inline_hash_func(str_index, str_length);
+ memcpy(p->key.u.string, str_index, str_length);
+ p->key.type = (key_type == HASH_KEY_IS_STRING)?IS_STRING:IS_BINARY;
+ p->h = zend_u_inline_hash_func(p->key.type, str_index, str_length);
}
CONNECT_TO_BUCKET_DLLIST(p, ht->arBuckets[p->h & ht->nTableMask]);
@@ -1266,13 +1462,13 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
IS_CONSISTENT(ht1);
IS_CONSISTENT(ht2);
- HASH_PROTECT_RECURSION(ht1);
- HASH_PROTECT_RECURSION(ht2);
+ HASH_PROTECT_RECURSION(ht1);
+ HASH_PROTECT_RECURSION(ht2);
result = ht1->nNumOfElements - ht2->nNumOfElements;
if (result!=0) {
- HASH_UNPROTECT_RECURSION(ht1);
- HASH_UNPROTECT_RECURSION(ht2);
+ HASH_UNPROTECT_RECURSION(ht1);
+ HASH_UNPROTECT_RECURSION(ht2);
return result;
}
@@ -1283,29 +1479,29 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
while (p1) {
if (ordered && !p2) {
- HASH_UNPROTECT_RECURSION(ht1);
- HASH_UNPROTECT_RECURSION(ht2);
+ HASH_UNPROTECT_RECURSION(ht1);
+ HASH_UNPROTECT_RECURSION(ht2);
return 1; /* That's not supposed to happen */
}
if (ordered) {
if (p1->nKeyLength==0 && p2->nKeyLength==0) { /* numeric indices */
result = p1->h - p2->h;
if (result!=0) {
- HASH_UNPROTECT_RECURSION(ht1);
- HASH_UNPROTECT_RECURSION(ht2);
+ HASH_UNPROTECT_RECURSION(ht1);
+ HASH_UNPROTECT_RECURSION(ht2);
return result;
}
} else { /* string indices */
- result = p1->nKeyLength - p2->nKeyLength;
- if (result!=0) {
- HASH_UNPROTECT_RECURSION(ht1);
- HASH_UNPROTECT_RECURSION(ht2);
- return result;
+ result = p1->key.type - p2->key.type;
+ if (result==0) {
+ result = p1->nKeyLength - p2->nKeyLength;
+ }
+ if (result==0) {
+ result = memcmp(&p1->key.u, &p2->key.u, REAL_KEY_SIZE(p1->key.type, p1->nKeyLength));
}
- result = memcmp(p1->arKey, p2->arKey, p1->nKeyLength);
if (result!=0) {
- HASH_UNPROTECT_RECURSION(ht1);
- HASH_UNPROTECT_RECURSION(ht2);
+ HASH_UNPROTECT_RECURSION(ht1);
+ HASH_UNPROTECT_RECURSION(ht2);
return result;
}
}
@@ -1313,22 +1509,22 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
} else {
if (p1->nKeyLength==0) { /* numeric index */
if (zend_hash_index_find(ht2, p1->h, &pData2)==FAILURE) {
- HASH_UNPROTECT_RECURSION(ht1);
- HASH_UNPROTECT_RECURSION(ht2);
+ HASH_UNPROTECT_RECURSION(ht1);
+ HASH_UNPROTECT_RECURSION(ht2);
return 1;
}
- } else { /* string index */
- if (zend_hash_find(ht2, p1->arKey, p1->nKeyLength, &pData2)==FAILURE) {
- HASH_UNPROTECT_RECURSION(ht1);
- HASH_UNPROTECT_RECURSION(ht2);
+ } else { /* string, binary or unicode index */
+ if (zend_u_hash_find(ht2, p1->key.type, &p1->key.u, p1->nKeyLength, &pData2)==FAILURE) {
+ HASH_UNPROTECT_RECURSION(ht1);
+ HASH_UNPROTECT_RECURSION(ht2);
return 1;
}
}
}
result = compar(p1->pData, pData2 TSRMLS_CC);
if (result!=0) {
- HASH_UNPROTECT_RECURSION(ht1);
- HASH_UNPROTECT_RECURSION(ht2);
+ HASH_UNPROTECT_RECURSION(ht1);
+ HASH_UNPROTECT_RECURSION(ht2);
return result;
}
p1 = p1->pListNext;
@@ -1336,9 +1532,9 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
p2 = p2->pListNext;
}
}
-
- HASH_UNPROTECT_RECURSION(ht1);
- HASH_UNPROTECT_RECURSION(ht2);
+
+ HASH_UNPROTECT_RECURSION(ht1);
+ HASH_UNPROTECT_RECURSION(ht2);
return 0;
}
@@ -1378,6 +1574,147 @@ ZEND_API ulong zend_hash_next_free_element(HashTable *ht)
}
+#define HANDLE_NUMERIC(key, length, func) { \
+ register char *tmp=key; \
+ \
+ if (*tmp=='-') { \
+ tmp++; \
+ } \
+ if ((*tmp>='0' && *tmp<='9')) do { /* possibly a numeric index */ \
+ char *end=key+length-1; \
+ long idx; \
+ \
+ if (*tmp++=='0' && length>2) { /* don't accept numbers with leading zeros */ \
+ break; \
+ } \
+ while (tmp<end) { \
+ if (!(*tmp>='0' && *tmp<='9')) { \
+ break; \
+ } \
+ tmp++; \
+ } \
+ if (tmp==end && *tmp=='\0') { /* a numeric index */ \
+ if (*key=='-') { \
+ idx = strtol(key, NULL, 10); \
+ if (idx!=LONG_MIN) { \
+ return func; \
+ } \
+ } else { \
+ idx = strtol(key, NULL, 10); \
+ if (idx!=LONG_MAX) { \
+ return func; \
+ } \
+ } \
+ } \
+ } while (0); \
+}
+
+#define HANDLE_U_NUMERIC(key, length, func) { \
+ register UChar *tmp=key; \
+ register int32_t val; \
+ \
+ if (*tmp=='-') { \
+ tmp++; \
+ } \
+ if ((val = u_digit(*tmp, 10)) >= 0) do { /* possibly a numeric index */ \
+ UChar *end=key+length-1; \
+ long idx; \
+ \
+ if (val==0 && length>2) { /* don't accept numbers with leading zeros */ \
+ break; \
+ } \
+ tmp++; \
+ while (tmp<end) { \
+ if (u_digit(*tmp, 10) < 0) { \
+ break; \
+ } \
+ tmp++; \
+ } \
+ if (tmp==end && *tmp==0) { /* a numeric index */ \
+ if (*key=='-') { \
+ idx = zend_u_strtol(key, NULL, 10); \
+ if (idx!=LONG_MIN) { \
+ return func; \
+ } \
+ } else { \
+ idx = zend_u_strtol(key, NULL, 10); \
+ if (idx!=LONG_MAX) { \
+ return func; \
+ } \
+ } \
+ } \
+ } while (0); \
+}
+
+ZEND_API int zend_u_symtable_update(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest)
+{
+ if (type == IS_STRING) {
+ HANDLE_NUMERIC((char*)arKey, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
+ } else if (type == IS_UNICODE) {
+ HANDLE_U_NUMERIC((UChar*)arKey, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
+ }
+ return zend_u_hash_update(ht, type, arKey, nKeyLength, pData, nDataSize, pDest);
+}
+
+
+ZEND_API int zend_u_symtable_del(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength)
+{
+ if (type == IS_STRING) {
+ HANDLE_NUMERIC((char*)arKey, nKeyLength, zend_hash_index_del(ht, idx));
+ } else if (type == IS_UNICODE) {
+ HANDLE_U_NUMERIC((UChar*)arKey, nKeyLength, zend_hash_index_del(ht, idx));
+ }
+ return zend_u_hash_del(ht, type, arKey, nKeyLength);
+}
+
+
+ZEND_API int zend_u_symtable_find(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, void **pData)
+{
+ if (type == IS_STRING) {
+ HANDLE_NUMERIC((char*)arKey, nKeyLength, zend_hash_index_find(ht, idx, pData));
+ } else if (type == IS_UNICODE) {
+ HANDLE_U_NUMERIC((UChar*)arKey, nKeyLength, zend_hash_index_find(ht, idx, pData));
+ }
+ return zend_u_hash_find(ht, type, arKey, nKeyLength, pData);
+}
+
+
+ZEND_API int zend_u_symtable_exists(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength)
+{
+ if (type == IS_STRING) {
+ HANDLE_NUMERIC((char*)arKey, nKeyLength, zend_hash_index_exists(ht, idx));
+ } else if (type == IS_UNICODE) {
+ HANDLE_U_NUMERIC((UChar*)arKey, nKeyLength, zend_hash_index_exists(ht, idx));
+ }
+ return zend_u_hash_exists(ht, type, arKey, nKeyLength);
+}
+
+ZEND_API int zend_symtable_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest)
+{
+ HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
+ return zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest);
+}
+
+
+ZEND_API int zend_symtable_del(HashTable *ht, char *arKey, uint nKeyLength)
+{
+ HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_del(ht, idx))
+ return zend_hash_del(ht, arKey, nKeyLength);
+}
+
+
+ZEND_API int zend_symtable_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData)
+{
+ HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_find(ht, idx, pData));
+ return zend_hash_find(ht, arKey, nKeyLength, pData);
+}
+
+
+ZEND_API int zend_symtable_exists(HashTable *ht, char *arKey, uint nKeyLength)
+{
+ HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_exists(ht, idx));
+ return zend_hash_exists(ht, arKey, nKeyLength);
+}
#if ZEND_DEBUG
void zend_hash_display_pListTail(HashTable *ht)
@@ -1386,7 +1723,11 @@ void zend_hash_display_pListTail(HashTable *ht)
p = ht->pListTail;
while (p != NULL) {
- zend_output_debug_string(0, "pListTail has key %s\n", p->arKey);
+ if (p->key.type == IS_UNICODE) {
+ /* TODO: ??? */
+ } else {
+ zend_output_debug_string(0, "pListTail has key %s\n", p->key.u.string);
+ }
p = p->pListLast;
}
}
@@ -1399,14 +1740,22 @@ void zend_hash_display(HashTable *ht)
for (i = 0; i < ht->nTableSize; i++) {
p = ht->arBuckets[i];
while (p != NULL) {
- zend_output_debug_string(0, "%s <==> 0x%lX\n", p->arKey, p->h);
+ if (p->key.type == IS_UNICODE) {
+ /* TODO: ??? */
+ } else {
+ zend_output_debug_string(0, "%s <==> 0x%lX\n", p->key.u.string, p->h);
+ }
p = p->pNext;
}
}
p = ht->pListTail;
while (p != NULL) {
- zend_output_debug_string(0, "%s <==> 0x%lX\n", p->arKey, p->h);
+ if (p->key.type == IS_UNICODE) {
+ /* TODO: ??? */
+ } else {
+ zend_output_debug_string(0, "%s <==> 0x%lX\n", p->key.u.string, p->h);
+ }
p = p->pListLast;
}
}
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index 774c607418..f0aa3e6034 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -28,6 +28,8 @@
#define HASH_KEY_IS_STRING 1
#define HASH_KEY_IS_LONG 2
#define HASH_KEY_NON_EXISTANT 3
+#define HASH_KEY_IS_BINARY 4
+#define HASH_KEY_IS_UNICODE 5
#define HASH_UPDATE (1<<0)
#define HASH_ADD (1<<1)
@@ -36,6 +38,10 @@
#define HASH_DEL_KEY 0
#define HASH_DEL_INDEX 1
+#define REAL_KEY_SIZE(type, nKeyLength) \
+ ((type == IS_UNICODE)?UBYTES(nKeyLength):nKeyLength)
+
+
typedef ulong (*hash_func_t)(char *arKey, uint nKeyLength);
typedef int (*compare_func_t)(const void *, const void * TSRMLS_DC);
typedef void (*sort_func_t)(void *, size_t, register size_t, compare_func_t TSRMLS_DC);
@@ -45,6 +51,14 @@ typedef void (*copy_ctor_param_func_t)(void *pElement, void *pParam);
struct _hashtable;
+typedef struct _key {
+ zend_uchar type;
+ union {
+ char string[1]; /* Must be last element */
+ UChar unicode[1]; /* Must be last element */
+ } u;
+} HashKey;
+
typedef struct bucket {
ulong h; /* Used for numeric indexing */
uint nKeyLength;
@@ -54,7 +68,7 @@ typedef struct bucket {
struct bucket *pListLast;
struct bucket *pNext;
struct bucket *pLast;
- char arKey[1]; /* Must be last element */
+ HashKey key; /* Must be last element */
} Bucket;
typedef struct _hashtable {
@@ -68,6 +82,7 @@ typedef struct _hashtable {
Bucket **arBuckets;
dtor_func_t pDestructor;
zend_bool persistent;
+ zend_bool unicode;
unsigned char nApplyCount;
zend_bool bApplyProtection;
#if ZEND_DEBUG
@@ -77,9 +92,13 @@ typedef struct _hashtable {
typedef struct _zend_hash_key {
- char *arKey;
- uint nKeyLength;
ulong h;
+ uint nKeyLength;
+ zend_uchar type;
+ union {
+ char *string;
+ UChar *unicode;
+ } u;
} zend_hash_key;
@@ -91,24 +110,38 @@ BEGIN_EXTERN_C()
/* startup/shutdown */
ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC);
+ZEND_API int _zend_u_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool unicode ZEND_FILE_LINE_DC);
ZEND_API int _zend_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
+ZEND_API int _zend_u_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool unicode, zend_bool bApplyProtection ZEND_FILE_LINE_DC);
ZEND_API void zend_hash_destroy(HashTable *ht);
ZEND_API void zend_hash_clean(HashTable *ht);
#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent) _zend_hash_init((ht), (nSize), (pHashFunction), (pDestructor), (persistent) ZEND_FILE_LINE_CC)
+#define zend_u_hash_init(ht, nSize, pHashFunction, pDestructor, persistent, unicode) _zend_u_hash_init((ht), (nSize), (pHashFunction), (pDestructor), (persistent), (unicode) ZEND_FILE_LINE_CC)
#define zend_hash_init_ex(ht, nSize, pHashFunction, pDestructor, persistent, bApplyProtection) _zend_hash_init_ex((ht), (nSize), (pHashFunction), (pDestructor), (persistent), (bApplyProtection) ZEND_FILE_LINE_CC)
+#define zend_u_hash_init_ex(ht, nSize, pHashFunction, pDestructor, persistent, unicode, bApplyProtection) _zend_u_hash_init_ex((ht), (nSize), (pHashFunction), (pDestructor), (persistent), (unicode), (bApplyProtection) ZEND_FILE_LINE_CC)
/* additions/updates/changes */
ZEND_API int _zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
+ZEND_API int _zend_u_hash_add_or_update(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
#define zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest) \
_zend_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
+#define zend_u_hash_update(ht, type, arKey, nKeyLength, pData, nDataSize, pDest) \
+ _zend_u_hash_add_or_update(ht, type, arKey, nKeyLength, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
#define zend_hash_add(ht, arKey, nKeyLength, pData, nDataSize, pDest) \
_zend_hash_add_or_update(ht, arKey, nKeyLength, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
+#define zend_u_hash_add(ht, type, arKey, nKeyLength, pData, nDataSize, pDest) \
+ _zend_u_hash_add_or_update(ht, type, arKey, nKeyLength, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
ZEND_API int _zend_hash_quick_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
+ZEND_API int _zend_u_hash_quick_add_or_update(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
#define zend_hash_quick_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest) \
_zend_hash_quick_add_or_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
+#define zend_u_hash_quick_update(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest) \
+ _zend_u_hash_quick_add_or_update(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_UPDATE ZEND_FILE_LINE_CC)
#define zend_hash_quick_add(ht, arKey, nKeyLength, h, pData, nDataSize, pDest) \
_zend_hash_quick_add_or_update(ht, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
+#define zend_u_hash_quick_add(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest) \
+ _zend_u_hash_quick_add_or_update(ht, type, arKey, nKeyLength, h, pData, nDataSize, pDest, HASH_ADD ZEND_FILE_LINE_CC)
ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag ZEND_FILE_LINE_DC);
#define zend_hash_index_update(ht, h, pData, nDataSize, pDest) \
@@ -117,6 +150,7 @@ ZEND_API int _zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void
_zend_hash_index_update_or_next_insert(ht, 0, pData, nDataSize, pDest, HASH_NEXT_INSERT ZEND_FILE_LINE_CC)
ZEND_API int zend_hash_add_empty_element(HashTable *ht, char *arKey, uint nKeyLength);
+ZEND_API int zend_u_hash_add_empty_element(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength);
#define ZEND_HASH_APPLY_KEEP 0
@@ -145,21 +179,29 @@ ZEND_API void zend_hash_reverse_apply(HashTable *ht, apply_func_t apply_func TSR
/* Deletes */
ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLength, ulong h, int flag);
+ZEND_API int zend_u_hash_del_key_or_index(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, ulong h, int flag);
#define zend_hash_del(ht, arKey, nKeyLength) \
zend_hash_del_key_or_index(ht, arKey, nKeyLength, 0, HASH_DEL_KEY)
+#define zend_u_hash_del(ht, type, arKey, nKeyLength) \
+ zend_u_hash_del_key_or_index(ht, type, arKey, nKeyLength, 0, HASH_DEL_KEY)
#define zend_hash_index_del(ht, h) \
zend_hash_del_key_or_index(ht, NULL, 0, h, HASH_DEL_INDEX)
ZEND_API ulong zend_get_hash_value(char *arKey, uint nKeyLength);
+ZEND_API ulong zend_u_get_hash_value(zend_uchar type, char *arKey, uint nKeyLength);
/* Data retreival */
ZEND_API int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData);
+ZEND_API int zend_u_hash_find(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, void **pData);
ZEND_API int zend_hash_quick_find(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void **pData);
+ZEND_API int zend_u_hash_quick_find(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, ulong h, void **pData);
ZEND_API int zend_hash_index_find(HashTable *ht, ulong h, void **pData);
/* Misc */
ZEND_API int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLength);
+ZEND_API int zend_u_hash_exists(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength);
ZEND_API int zend_hash_quick_exists(HashTable *ht, char *arKey, uint nKeyLength, ulong h);
+ZEND_API int zend_u_hash_quick_exists(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, ulong h);
ZEND_API int zend_hash_index_exists(HashTable *ht, ulong h);
ZEND_API ulong zend_hash_next_free_element(HashTable *ht);
@@ -272,8 +314,11 @@ EMPTY_SWITCH_DEFAULT_CASE()
return hash;
}
+#define zend_u_inline_hash_func(type, arKey, nKeyLength) \
+ zend_inline_hash_func(arKey, REAL_KEY_SIZE(type, nKeyLength))
ZEND_API ulong zend_hash_func(char *arKey, uint nKeyLength);
+ZEND_API ulong zend_u_hash_func(zend_uchar type, char *arKey, uint nKeyLength);
#if ZEND_DEBUG
/* debug */
@@ -290,68 +335,15 @@ END_EXTERN_C()
zend_hash_init(ht, n, NULL, ZVAL_PTR_DTOR, persistent)
-#define HANDLE_NUMERIC(key, length, func) { \
- register char *tmp=key; \
- \
- if (*tmp=='-') { \
- tmp++; \
- } \
- if ((*tmp>='0' && *tmp<='9')) do { /* possibly a numeric index */ \
- char *end=key+length-1; \
- long idx; \
- \
- if (*tmp++=='0' && length>2) { /* don't accept numbers with leading zeros */ \
- break; \
- } \
- while (tmp<end) { \
- if (!(*tmp>='0' && *tmp<='9')) { \
- break; \
- } \
- tmp++; \
- } \
- if (tmp==end && *tmp=='\0') { /* a numeric index */ \
- if (*key=='-') { \
- idx = strtol(key, NULL, 10); \
- if (idx!=LONG_MIN) { \
- return func; \
- } \
- } else { \
- idx = strtol(key, NULL, 10); \
- if (idx!=LONG_MAX) { \
- return func; \
- } \
- } \
- } \
- } while (0); \
-}
-
-
-static inline int zend_symtable_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest) \
-{
- HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_update(ht, idx, pData, nDataSize, pDest));
- return zend_hash_update(ht, arKey, nKeyLength, pData, nDataSize, pDest);
-}
-
+ZEND_API int zend_symtable_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest);
+ZEND_API int zend_symtable_del(HashTable *ht, char *arKey, uint nKeyLength);
+ZEND_API int zend_symtable_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData);
+ZEND_API int zend_symtable_exists(HashTable *ht, char *arKey, uint nKeyLength);
-static inline int zend_symtable_del(HashTable *ht, char *arKey, uint nKeyLength)
-{
- HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_del(ht, idx))
- return zend_hash_del(ht, arKey, nKeyLength);
-}
-
-
-static inline int zend_symtable_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData)
-{
- HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_find(ht, idx, pData));
- return zend_hash_find(ht, arKey, nKeyLength, pData);
-}
-
-
-static inline int zend_symtable_exists(HashTable *ht, char *arKey, uint nKeyLength)
-{
- HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_exists(ht, idx));
- return zend_hash_exists(ht, arKey, nKeyLength);
-}
+ZEND_API int zend_u_symtable_update(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest);
+ZEND_API int zend_u_symtable_del(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength);
+ZEND_API int zend_u_symtable_find(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength, void **pData);
+ZEND_API int zend_u_symtable_exists(HashTable *ht, zend_uchar type, void *arKey, uint nKeyLength);
#endif /* ZEND_HASH_H */
diff --git a/Zend/zend_highlight.c b/Zend/zend_highlight.c
index cbd269ed29..980616ebf0 100644
--- a/Zend/zend_highlight.c
+++ b/Zend/zend_highlight.c
@@ -25,6 +25,7 @@
#include "zend_highlight.h"
#include "zend_ptr_stack.h"
#include "zend_globals.h"
+#include "zend_operators.h"
ZEND_API void zend_html_putc(char c)
{
@@ -96,6 +97,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
char *next_color;
int in_string=0, post_heredoc = 0;
+ CG(literal_type) = IS_STRING;
zend_printf("<code>");
zend_printf("<span style=\"color: %s\">\n", last_color);
/* highlight stuff coming back from zendlex() */
@@ -119,7 +121,7 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
case T_CONSTANT_ENCAPSED_STRING:
next_color = syntax_highlighter_ini->highlight_string;
break;
- case '"':
+ case '"':
next_color = syntax_highlighter_ini->highlight_string;
in_string = !in_string;
break;
@@ -162,7 +164,9 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
break;
}
- if (token.type == IS_STRING) {
+ if (token.type == IS_STRING ||
+ token.type == IS_BINARY ||
+ token.type == IS_UNICODE) {
switch (token_type) {
case T_OPEN_TAG:
case T_OPEN_TAG_WITH_ECHO:
@@ -172,11 +176,11 @@ ZEND_API void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini
case T_DOC_COMMENT:
break;
default:
- efree(token.value.str.val);
+ efree(Z_UNIVAL(token));
break;
}
} else if (token_type == T_END_HEREDOC) {
- efree(token.value.str.val);
+ efree(Z_UNIVAL(token));
}
token.type = 0;
}
@@ -195,6 +199,7 @@ ZEND_API void zend_strip(TSRMLS_D)
int token_type;
int prev_space = 0;
+ CG(literal_type) = IS_STRING;
token.type = 0;
while ((token_type=lex_scan(&token TSRMLS_CC))) {
switch (token_type) {
@@ -218,7 +223,7 @@ ZEND_API void zend_strip(TSRMLS_D)
if (ptr[LANG_SCNG(yy_leng) - 1] == ';') {
lex_scan(&token TSRMLS_CC);
}
- efree(token.value.str.val);
+ efree(Z_UNIVAL(token));
}
break;
@@ -227,7 +232,9 @@ ZEND_API void zend_strip(TSRMLS_D)
break;
}
- if (token.type == IS_STRING) {
+ if (token.type == IS_STRING ||
+ token.type == IS_BINARY ||
+ token.type == IS_UNICODE) {
switch (token_type) {
case T_OPEN_TAG:
case T_OPEN_TAG_WITH_ECHO:
@@ -238,7 +245,7 @@ ZEND_API void zend_strip(TSRMLS_D)
break;
default:
- efree(token.value.str.val);
+ efree(Z_UNIVAL(token));
break;
}
}
diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c
index 91e320b621..61976052e4 100644
--- a/Zend/zend_ini.c
+++ b/Zend/zend_ini.c
@@ -134,7 +134,8 @@ static int ini_key_compare(const void *a, const void *b TSRMLS_DC)
} else if (s->nKeyLength==0) { /* s is numeric, f is not */
return 1;
} else { /* both strings */
- return zend_binary_strcasecmp(f->arKey, f->nKeyLength, s->arKey, s->nKeyLength);
+ /*FIXME: unicode hash*/
+ return zend_binary_strcasecmp(f->key.u.string, f->nKeyLength, s->key.u.string, s->nKeyLength);
}
}
diff --git a/Zend/zend_ini_scanner.l b/Zend/zend_ini_scanner.l
index c18a0695a4..9fb3461c95 100644
--- a/Zend/zend_ini_scanner.l
+++ b/Zend/zend_ini_scanner.l
@@ -48,6 +48,10 @@ ZEND_API ts_rsrc_id ini_scanner_globals_id;
ZEND_API zend_scanner_globals ini_scanner_globals;
#endif
+# define YY_INPUT(buf, result, max_size) \
+ if ( ((result = zend_stream_read(yyin, buf, max_size TSRMLS_CC)) == 0) \
+ && zend_stream_ferror( yyin TSRMLS_CC) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
static char *ini_filename;
diff --git a/Zend/zend_interfaces.c b/Zend/zend_interfaces.c
index 7454311d61..c53a657c66 100755
--- a/Zend/zend_interfaces.c
+++ b/Zend/zend_interfaces.c
@@ -74,7 +74,7 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
if (!fn_proxy || !*fn_proxy) {
if (zend_hash_find(function_table, function_name, function_name_len+1, (void **) &fcic.function_handler) == FAILURE) {
/* error at c-level */
- zend_error(E_CORE_ERROR, "Couldn't find implementation for method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
+ zend_error(E_CORE_ERROR, "Couldn't find implementation for method %v%s%s", obj_ce ? obj_ce->name : EMPTY_STR, obj_ce ? "::" : "", function_name);
}
if (fn_proxy) {
*fn_proxy = fcic.function_handler;
@@ -91,7 +91,7 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
if (!obj_ce) {
obj_ce = object_pp ? Z_OBJCE_PP(object_pp) : NULL;
}
- zend_error(E_CORE_ERROR, "Couldn't execute method %s%s%s", obj_ce ? obj_ce->name : "", obj_ce ? "::" : "", function_name);
+ zend_error(E_CORE_ERROR, "Couldn't execute method %v%s%s", obj_ce ? obj_ce->name : EMPTY_STR, obj_ce ? "::" : "", function_name);
}
if (!retval_ptr_ptr) {
if (retval) {
@@ -195,24 +195,36 @@ static int zend_user_it_get_current_key(zend_object_iterator *_iter, char **str_
*int_key = 0;
if (!EG(exception))
{
- zend_error(E_WARNING, "Nothing returned from %s::key()", iter->ce->name);
+ zend_error(E_WARNING, "Nothing returned from %v::key()", iter->ce->name);
}
return HASH_KEY_IS_LONG;
}
switch (retval->type) {
default:
- zend_error(E_WARNING, "Illegal type returned from %s::key()", iter->ce->name);
+ zend_error(E_WARNING, "Illegal type returned from %v::key()", iter->ce->name);
case IS_NULL:
*int_key = 0;
zval_ptr_dtor(&retval);
return HASH_KEY_IS_LONG;
case IS_STRING:
- *str_key = estrndup(retval->value.str.val, retval->value.str.len);
+ *str_key = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
*str_key_len = retval->value.str.len+1;
zval_ptr_dtor(&retval);
return HASH_KEY_IS_STRING;
+ case IS_BINARY:
+ *str_key = estrndup(Z_STRVAL_P(retval), Z_STRLEN_P(retval));
+ *str_key_len = retval->value.str.len+1;
+ zval_ptr_dtor(&retval);
+ return HASH_KEY_IS_BINARY;
+
+ case IS_UNICODE:
+ *str_key = (char*)eustrndup(Z_USTRVAL_P(retval), Z_USTRLEN_P(retval));
+ *str_key_len = retval->value.str.len+1;
+ zval_ptr_dtor(&retval);
+ return HASH_KEY_IS_UNICODE;
+
case IS_DOUBLE:
case IS_RESOURCE:
case IS_BOOL:
@@ -286,7 +298,7 @@ static zend_object_iterator *zend_user_it_get_new_iterator(zend_class_entry *ce,
if (!ce || !ce_it || !ce_it->get_iterator || (ce_it->get_iterator == zend_user_it_get_new_iterator && iterator == object)) {
if (!EG(exception))
{
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Objects returned by %s::getIterator() must be traversable or implement interface Iterator", ce->name);
+ zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Objects returned by %v::getIterator() must be traversable or implement interface Iterator", ce->name);
}
if (iterator)
{
@@ -314,7 +326,7 @@ static int zend_implement_traversable(zend_class_entry *interface, zend_class_en
return SUCCESS;
}
}
- zend_error(E_CORE_ERROR, "Class %s must implement interface %s as part of either %s or %s",
+ zend_error(E_CORE_ERROR, "Class %v must implement interface %v as part of either %v or %v",
class_type->name,
zend_ce_traversable->name,
zend_ce_iterator->name,
@@ -550,6 +562,14 @@ ZEND_API void zend_register_interfaces(TSRMLS_D)
}
/* }}} */
+void init_interfaces(TSRMLS_D)
+{
+ zend_ce_traversable = zend_get_named_class_entry("Traversable", sizeof("Traversable")-1 TSRMLS_CC);
+ zend_ce_aggregate = zend_get_named_class_entry("IteratorAggregate", sizeof("IteratorAggregate")-1 TSRMLS_CC);
+ zend_ce_iterator = zend_get_named_class_entry("Iterator", sizeof("Iterator")-1 TSRMLS_CC);
+ zend_ce_arrayaccess = zend_get_named_class_entry("ArrayAccess", sizeof("ArrayAccess")-1 TSRMLS_CC);
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_interfaces.h b/Zend/zend_interfaces.h
index f2ebdbac37..0894e8ae17 100755
--- a/Zend/zend_interfaces.h
+++ b/Zend/zend_interfaces.h
@@ -51,6 +51,8 @@ ZEND_API zval* zend_call_method(zval **object_pp, zend_class_entry *obj_ce, zend
ZEND_API void zend_register_interfaces(TSRMLS_D);
+void init_interfaces(TSRMLS_D);
+
END_EXTERN_C()
#endif /* ZEND_INTERFACES_H */
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 5861031321..8286e266e0 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -71,7 +71,7 @@
%left '*' '/' '%'
%right '!'
%nonassoc T_INSTANCEOF
-%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
+%right '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_UNICODE_CAST T_BINARY_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@'
%right '['
%nonassoc T_NEW T_CLONE
%token T_EXIT
@@ -145,6 +145,8 @@
%token T_DOLLAR_OPEN_CURLY_BRACES
%token T_CURLY_OPEN
%token T_PAAMAYIM_NEKUDOTAYIM
+%token T_BINARY_DOUBLE
+%token T_BINARY_HEREDOC
%% /* Rules */
@@ -210,7 +212,7 @@ unticked_statement:
| T_GLOBAL global_var_list ';'
| T_STATIC static_var_list ';'
| T_ECHO echo_expr_list ';'
- | T_INLINE_HTML { zend_do_echo(&$1 TSRMLS_CC); }
+ | T_INLINE_HTML { zend_do_echo(&$1, 1 TSRMLS_CC); }
| expr ';' { zend_do_free(&$1 TSRMLS_CC); }
| T_USE use_filename ';' { zend_error(E_COMPILE_ERROR,"use: Not yet supported. Please use include_once() or require_once()"); zval_dtor(&$2.u.constant); }
| T_UNSET '(' unset_variables ')' ';'
@@ -466,8 +468,8 @@ global_var_list:
global_var:
T_VARIABLE { $$ = $1; }
- | '$' r_variable { $$ = $2; }
- | '$' '{' expr '}' { $$ = $3; }
+ | '$' r_variable { zend_do_normalization(&$$, &$2 TSRMLS_CC); }
+ | '$' '{' expr '}' { zend_do_normalization(&$$, &$3 TSRMLS_CC); }
;
@@ -536,8 +538,8 @@ class_constant_declaration:
;
echo_expr_list:
- echo_expr_list ',' expr { zend_do_echo(&$3 TSRMLS_CC); }
- | expr { zend_do_echo(&$1 TSRMLS_CC); }
+ echo_expr_list ',' expr { zend_do_echo(&$3, 0 TSRMLS_CC); }
+ | expr { zend_do_echo(&$1, 0 TSRMLS_CC); }
;
@@ -610,6 +612,8 @@ expr_without_variable:
| T_INT_CAST expr { zend_do_cast(&$$, &$2, IS_LONG TSRMLS_CC); }
| T_DOUBLE_CAST expr { zend_do_cast(&$$, &$2, IS_DOUBLE TSRMLS_CC); }
| T_STRING_CAST expr { zend_do_cast(&$$, &$2, IS_STRING TSRMLS_CC); }
+ | T_UNICODE_CAST expr { zend_do_cast(&$$, &$2, IS_UNICODE TSRMLS_CC); }
+ | T_BINARY_CAST expr { zend_do_cast(&$$, &$2, UG(unicode)?IS_BINARY:IS_STRING TSRMLS_CC); }
| T_ARRAY_CAST expr { zend_do_cast(&$$, &$2, IS_ARRAY TSRMLS_CC); }
| T_OBJECT_CAST expr { zend_do_cast(&$$, &$2, IS_OBJECT TSRMLS_CC); }
| T_BOOL_CAST expr { zend_do_cast(&$$, &$2, IS_BOOL TSRMLS_CC); }
@@ -618,7 +622,7 @@ expr_without_variable:
| '@' { zend_do_begin_silence(&$1 TSRMLS_CC); } expr { zend_do_end_silence(&$1 TSRMLS_CC); $$ = $3; }
| scalar { $$ = $1; }
| T_ARRAY '(' array_pair_list ')' { $$ = $3; }
- | '`' encaps_list '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
+ | '`' encaps_list '`' { zend_do_shell_exec(&$$, &$2 TSRMLS_CC); }
| T_PRINT expr { zend_do_print(&$$, &$2 TSRMLS_CC); }
;
@@ -708,9 +712,10 @@ scalar:
| T_STRING_VARNAME { $$ = $1; }
| class_constant { $$ = $1; }
| common_scalar { $$ = $1; }
- | '"' encaps_list '"' { $$ = $2; }
- | '\'' encaps_list '\'' { $$ = $2; }
- | T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; zend_do_end_heredoc(TSRMLS_C); }
+ | '"' { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } encaps_list '"' { $$ = $3; }
+ | T_START_HEREDOC { CG(literal_type) = UG(unicode)?IS_UNICODE:IS_STRING; } encaps_list T_END_HEREDOC { $$ = $3; zend_do_end_heredoc(TSRMLS_C); }
+ | T_BINARY_DOUBLE { CG(literal_type) = UG(unicode)?IS_BINARY:IS_STRING; } encaps_list '"' { $$ = $3; }
+ | T_BINARY_HEREDOC { CG(literal_type) = UG(unicode)?IS_BINARY:IS_STRING; } encaps_list T_END_HEREDOC { $$ = $3; zend_do_end_heredoc(TSRMLS_C); }
;
@@ -808,7 +813,7 @@ reference_variable:
compound_variable:
T_VARIABLE { $$ = $1; }
- | '$' '{' expr '}' { $$ = $3; }
+ | '$' '{' expr '}' { zend_do_normalization(&$$, &$3 TSRMLS_CC); }
;
dim_offset:
@@ -830,7 +835,7 @@ object_dim_list:
variable_name:
T_STRING { $$ = $1; }
- | '{' expr '}' { $$ = $2; }
+ | '{' expr '}' { zend_do_normalization(&$$, &$2 TSRMLS_CC); }
;
simple_indirect_reference:
diff --git a/Zend/zend_language_scanner.h b/Zend/zend_language_scanner.h
index 7928198f3f..a7778d8d02 100644
--- a/Zend/zend_language_scanner.h
+++ b/Zend/zend_language_scanner.h
@@ -29,21 +29,11 @@ typedef struct _zend_lex_state {
uint lineno;
char *filename;
-#ifdef ZEND_MULTIBYTE
- /* original (unfiltered) script */
- char *script_org;
- int script_org_size;
-
- /* filtered script */
- char *script_filtered;
- int script_filtered_size;
-
- /* input/ouput filters */
- zend_encoding_filter input_filter;
- zend_encoding_filter output_filter;
- zend_encoding *script_encoding;
- zend_encoding *internal_encoding;
-#endif /* ZEND_MULTIBYTE */
+ UConverter *input_conv; /* converter for flex input */
+ UConverter *output_conv; /* converter for data from flex output */
+ zend_bool encoding_checked;
+ char* rest_str;
+ int rest_len;
} zend_lex_state;
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index cd6c17f06e..a7ab4ea4e8 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -35,7 +35,6 @@
%x ST_IN_SCRIPTING
%x ST_DOUBLE_QUOTES
-%x ST_SINGLE_QUOTE
%x ST_BACKQUOTE
%x ST_HEREDOC
%x ST_LOOKING_FOR_PROPERTY
@@ -59,6 +58,7 @@
#include "zend_operators.h"
#include "zend_API.h"
#include "zend_strtod.h"
+#include "zend_unicode.h"
#ifdef HAVE_STDARG_H
# include <stdarg.h>
@@ -87,6 +87,10 @@ ZEND_API ts_rsrc_id language_scanner_globals_id;
ZEND_API zend_scanner_globals language_scanner_globals;
#endif
+#define YY_INPUT(buf, result, max_size) \
+ if ( ((result = zend_unicode_yyinput(yyin, buf, max_size TSRMLS_CC)) == 0) \
+ && zend_stream_ferror( yyin TSRMLS_CC) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" );
#define YY_FATAL_ERROR zend_fatal_scanner_error
@@ -131,16 +135,12 @@ void startup_scanner(TSRMLS_D)
SCNG(yy_start_stack_ptr) = 0;
SCNG(yy_start_stack_depth) = 0;
SCNG(current_buffer) = NULL;
-#ifdef ZEND_MULTIBYTE
- SCNG(script_org) = NULL;
- SCNG(script_org_size) = 0;
- SCNG(script_filtered) = NULL;
- SCNG(script_filtered_size) = 0;
- SCNG(input_filter) = NULL;
- SCNG(output_filter) = NULL;
- SCNG(script_encoding) = NULL;
- SCNG(internal_encoding) = NULL;
-#endif /* ZEND_MULTIBYTE */
+
+ SCNG(input_conv) = NULL;
+ SCNG(output_conv) = NULL;
+ SCNG(encoding_checked) = 0;
+ SCNG(rest_str) = NULL;
+ SCNG(rest_len) = 0;
}
@@ -155,23 +155,21 @@ void shutdown_scanner(TSRMLS_D)
SCNG(yy_start_stack) = NULL;
}
RESET_DOC_COMMENT();
-
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
- if (SCNG(script_filtered)) {
- efree(SCNG(script_filtered));
- SCNG(script_filtered) = NULL;
- }
- SCNG(script_org_size) = 0;
- SCNG(script_filtered_size) = 0;
- SCNG(input_filter) = NULL;
- SCNG(output_filter) = NULL;
- SCNG(script_encoding) = NULL;
- SCNG(internal_encoding) = NULL;
-#endif /* ZEND_MULTIBYTE */
+
+ if (SCNG(input_conv)) {
+ ucnv_close(SCNG(input_conv));
+ SCNG(input_conv) = NULL;
+ }
+ if (SCNG(output_conv)) {
+ ucnv_close(SCNG(output_conv));
+ SCNG(output_conv) = NULL;
+ }
+ SCNG(encoding_checked) = 0;
+ if (SCNG(rest_str)) {
+ efree(SCNG(rest_str));
+ SCNG(rest_str) = NULL;
+ }
+ SCNG(rest_len) = 0;
}
END_EXTERN_C()
@@ -184,16 +182,16 @@ ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
lex_state->filename = zend_get_compiled_filename(TSRMLS_C);
lex_state->lineno = CG(zend_lineno);
-#ifdef ZEND_MULTIBYTE
- lex_state->script_org = SCNG(script_org);
- lex_state->script_org_size = SCNG(script_org_size);
- lex_state->script_filtered = SCNG(script_filtered);
- lex_state->script_filtered_size = SCNG(script_filtered_size);
- lex_state->input_filter = SCNG(input_filter);
- lex_state->output_filter = SCNG(output_filter);
- lex_state->script_encoding = SCNG(script_encoding);
- lex_state->internal_encoding = SCNG(internal_encoding);
-#endif /* ZEND_MULTIBYTE */
+ lex_state->input_conv = SCNG(input_conv);
+ lex_state->output_conv = SCNG(output_conv);
+ lex_state->encoding_checked = SCNG(encoding_checked);
+ lex_state->rest_str = SCNG(rest_str);
+ lex_state->rest_len = SCNG(rest_len);
+ SCNG(input_conv) = NULL;
+ SCNG(output_conv) = NULL;
+ SCNG(encoding_checked) = 0;
+ SCNG(rest_str) = NULL;
+ SCNG(rest_len) = 0;
}
ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
@@ -212,24 +210,20 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state TSRMLS_DC)
CG(zend_lineno) = lex_state->lineno;
zend_restore_compiled_filename(lex_state->filename TSRMLS_CC);
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
+ if (SCNG(input_conv)) {
+ ucnv_close(SCNG(input_conv));
+ }
+ SCNG(input_conv) = lex_state->input_conv;
+ if (SCNG(output_conv)) {
+ ucnv_close(SCNG(output_conv));
}
- if (SCNG(script_filtered)) {
- efree(SCNG(script_filtered));
- SCNG(script_filtered) = NULL;
+ SCNG(output_conv) = lex_state->output_conv;
+ SCNG(encoding_checked) = lex_state->encoding_checked;
+ if (SCNG(rest_str)) {
+ efree(SCNG(rest_str));
}
- SCNG(script_org) = lex_state->script_org;
- SCNG(script_org_size) = lex_state->script_org_size;
- SCNG(script_filtered) = lex_state->script_filtered;
- SCNG(script_filtered_size) = lex_state->script_filtered_size;
- SCNG(input_filter) = lex_state->input_filter;
- SCNG(output_filter) = lex_state->output_filter;
- SCNG(script_encoding) = lex_state->script_encoding;
- SCNG(internal_encoding) = lex_state->internal_encoding;
-#endif /* ZEND_MULTIBYTE */
+ SCNG(rest_str) = lex_state->rest_str;
+ SCNG(rest_len) = lex_state->rest_len;
}
@@ -288,52 +282,472 @@ ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC)
zend_llist_del_element(&CG(open_files), file_handle, (int (*)(void *, void *)) zend_compare_file_handles);
}
+/* Convert one octal digit to a numeric value 0..7, or -1 on failure */
+static inline int8_t zend_get_octal_digit(UChar c) {
+ if (c >= 0x0030 && c <= 0x0037) {
+ return (int8_t)(c - 0x0030);
+ }
+ return -1;
+}
-ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
+/*
+ * Convert one hex digit to a numeric value 0..F, or -1 on failure.
+ * Borrowed from ICU.
+ */
+static inline int8_t zend_get_hex_digit(UChar c) {
+ if (c >= 0x0030 && c <= 0x0039) {
+ return (int8_t)(c - 0x0030);
+ }
+ if (c >= 0x0041 && c <= 0x0046) {
+ return (int8_t)(c - (0x0041 - 10));
+ }
+ if (c >= 0x0061 && c <= 0x0066) {
+ return (int8_t)(c - (0x0061 - 10));
+ }
+ return -1;
+}
+
+static inline zend_bool zend_digits_to_codepoint(char *s, char *end, UChar32 *c, int8_t digits)
{
- char *file_path=NULL;
+ int8_t n = 0;
+ int8_t digit = 0;
+ UChar32 codepoint = 0;
- if (FAILURE == zend_stream_fixup(file_handle TSRMLS_CC)) {
- return FAILURE;
+ while (s < end && n < digits) {
+ digit = zend_get_hex_digit((UChar)*s);
+ if (digit < 0) {
+ break;
+ }
+ codepoint = (codepoint << 4) | digit;
+ ++s;
+ ++n;
}
- zend_llist_add_element(&CG(open_files), file_handle);
-
- /* Reset the scanner for scanning the new file */
- SCNG(yy_in) = file_handle;
+ if (n < digits) {
+ return 0;
+ }
+
+ *c = codepoint;
+ return 1;
+}
+
+static inline zend_bool zend_udigits_to_codepoint(UChar *s, UChar *end, UChar32 *c, int8_t digits)
+{
+ int8_t n = 0;
+ int8_t digit = 0;
+ UChar32 codepoint = 0;
-#ifdef ZEND_MULTIBYTE
- if (file_handle->handle.stream.interactive == 0) {
- if (zend_multibyte_read_script(TSRMLS_C) != 0) {
+ while (s < end && n < digits) {
+ digit = zend_get_hex_digit(*s);
+ if (digit < 0) {
+ break;
+ }
+ codepoint = (codepoint << 4) | digit;
+ ++s;
+ ++n;
+ }
+
+ if (n < digits) {
+ return 0;
+ }
+
+ *c = codepoint;
+ return 1;
+}
+
+static inline int zend_uchar_from_name(char *name, UChar32 *c)
+{
+ UChar32 codepoint = 0;
+ UErrorCode status = U_ZERO_ERROR;
+
+ codepoint = u_charFromName(U_UNICODE_CHAR_NAME, name, &status);
+ if (U_SUCCESS(status)) {
+ *c = codepoint;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static inline int zend_uchar_from_uname(UChar *name, int32_t name_len, UChar32 *c)
+{
+ UChar32 codepoint = 0;
+ UErrorCode status = U_ZERO_ERROR;
+ char buf[128];
+
+ u_UCharsToChars(name, buf, name_len);
+ buf[name_len] = 0;
+ codepoint = u_charFromName(U_UNICODE_CHAR_NAME, buf, &status);
+ if (U_SUCCESS(status)) {
+ *c = codepoint;
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+static inline int zend_parse_charname_sequence(UChar **s, UChar *end, UChar32 *c)
+{
+ UChar *start;
+
+ if (**s == '{') {
+ start = ++(*s);
+ while ((*s)++ != end) {
+ if (**s == '}') {
+ if (zend_uchar_from_uname(start, *s - start, c)) {
+ return 1;
+ } else {
+ /* safe, since *s points to '}' */
+ **s = 0;
+ zend_error(E_COMPILE_WARNING, "Invalid Unicode character name: '%r'", start);
+ break;
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static inline int zend_copy_string_value(zval *zendlval, char *str, zend_uint str_len, zend_uchar type TSRMLS_DC)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int32_t consumed = 0;
+
+ if (type == IS_UNICODE) {
+ consumed = zend_convert_scanner_output(&zendlval->value.ustr.val, &zendlval->value.ustr.len, str, str_len, &status TSRMLS_CC);
+
+ if (U_FAILURE(status)) {
+ zend_error(E_COMPILE_WARNING,"Illegal or truncated character in input: offset %d, state=%d", consumed, YYSTATE);
+ efree(zendlval->value.ustr.val);
+ return 0;
+ }
+ zendlval->type = IS_UNICODE;
+ } else {
+ zendlval->value.str.val = (char *)estrndup(str, str_len);
+ zendlval->value.str.len = str_len;
+ zendlval->type = type;
+ }
+
+ return 1;
+}
+
+static inline int zend_check_and_normalize_identifier(zval *zendlval)
+{
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_is_valid_identifier(Z_USTRVAL_P(zendlval), Z_USTRLEN_P(zendlval))) {
+ zend_error(E_COMPILE_WARNING, "Invalid identifier syntax: %r", Z_USTRVAL_P(zendlval));
+ efree(Z_USTRVAL_P(zendlval));
+ return 0;
+ }
+ if (!zend_normalize_identifier(&norm, &norm_len, Z_USTRVAL_P(zendlval), Z_USTRLEN_P(zendlval), 0)) {
+ zend_error(E_COMPILE_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(zendlval));
+ efree(Z_USTRVAL_P(zendlval));
+ return 0;
+ }
+ if (norm != Z_USTRVAL_P(zendlval)) {
+ efree(Z_USTRVAL_P(zendlval));
+ ZVAL_UNICODEL(zendlval, norm, norm_len, 0);
+ }
+ return 1;
+}
+
+static void zend_scanner_output_callback(
+ const void *context,
+ UConverterToUnicodeArgs *toUArgs,
+ const char *codeUnits,
+ int32_t length,
+ UConverterCallbackReason reason,
+ UErrorCode *err
+ )
+{
+ if (*err == U_TRUNCATED_CHAR_FOUND ||
+ *err == U_ILLEGAL_CHAR_FOUND ||
+ *err == U_INVALID_CHAR_FOUND) {
+ *(const char **)context = toUArgs->source - length;
+ }
+
+ return;
+}
+
+static int is_encoding_flex_compatible(const char *enc TSRMLS_DC)
+{
+ int key_len = strlen(enc)+1;
+ unsigned char ret;
+ unsigned char *ret_ptr;
+
+ if (zend_hash_find(&UG(flex_compatible), (char*)enc, key_len, (void**)&ret_ptr) == SUCCESS) {
+ return *ret_ptr;
+ } else {
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *conv = ucnv_open(enc, &status);
+
+ if (U_FAILURE(status)) {
+ return 0;
+ }
+
+ switch (ucnv_getType(conv)) {
+ case UCNV_DBCS:
+ case UCNV_UTF16_BigEndian:
+ case UCNV_UTF16_LittleEndian:
+ case UCNV_UTF32_BigEndian:
+ case UCNV_UTF32_LittleEndian:
+ case UCNV_EBCDIC_STATEFUL:
+ case UCNV_ISO_2022:
+ case UCNV_LMBCS_1:
+ case UCNV_LMBCS_2:
+ case UCNV_LMBCS_3:
+ case UCNV_LMBCS_4:
+ case UCNV_LMBCS_5:
+ case UCNV_LMBCS_6:
+ case UCNV_LMBCS_8:
+ case UCNV_LMBCS_11:
+ case UCNV_LMBCS_16:
+ case UCNV_LMBCS_17:
+ case UCNV_LMBCS_18:
+ case UCNV_LMBCS_19:
+ case UCNV_HZ:
+ case UCNV_SCSU:
+ case UCNV_UTF7:
+ case UCNV_BOCU1:
+ case UCNV_UTF16:
+ case UCNV_UTF32:
+ case UCNV_IMAP_MAILBOX:
+ ret = 0;
+ break;
+ case UCNV_LATIN_1:
+ case UCNV_UTF8:
+ case UCNV_ISCII:
+ case UCNV_US_ASCII:
+ case UCNV_CESU8:
+ ret = 1;
+ break;
+ default: {
+ static const UChar ascii[] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
+ 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
+ 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
+ 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
+ 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E
+ };
+ static const char expected[] =
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
+ "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"
+ "\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F"
+ "\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F"
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F"
+ "\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F"
+ "\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F"
+ "\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E";
+ char output[sizeof(expected)];
+
+ if (ucnv_fromUChars(conv,
+ output, sizeof(output),
+ ascii, sizeof(expected),
+ &status) != sizeof(expected) ||
+ U_FAILURE(status)) {
+ ret = 0;
+ } else {
+ ret = (memcmp(expected, output, sizeof(expected)) == 0);
+ }
+ }
+ }
+ ucnv_close(conv);
+
+ zend_hash_add(&UG(flex_compatible), (char*)enc, key_len, (void**)&ret, sizeof(ret), NULL);
+
+ return ret;
+ }
+}
+
+ZEND_API int zend_prepare_scanner_converters(const char *onetime_encoding, int run_time TSRMLS_DC)
+{
+ const char *encoding = NULL;
+
+ if (SCNG(input_conv)) {
+ /* Script is already converted to UTF-8 */
+ return zend_set_converter_encoding(&SCNG(output_conv), "UTF-8");
+ } else {
+ encoding = onetime_encoding;
+ }
+
+ /* We need to convert the input stream only if script_encoding is not ASCII compatible */
+ if (!is_encoding_flex_compatible(encoding TSRMLS_CC)) {
+ if (zend_set_converter_encoding(&SCNG(input_conv), encoding) == FAILURE) {
return FAILURE;
}
+ if (run_time) {
+ /* Convert rest of the buffer to unicode.runtime_encoding. */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+ int offset, length, size;
+ const char *src, *old_src;
+ char rt_buf[8192];
+ char *target = rt_buf;
+ UErrorCode status = U_ZERO_ERROR;
+
+ old_src = src = yy_c_buf_p;
+ offset = yy_c_buf_p - b->yy_ch_buf;
+ length = b->yy_n_chars - offset;
+ size = b->yy_buf_size - offset;
+
+ ucnv_convertEx(UG(utf8_conv),
+ SCNG(input_conv),
+ &target, rt_buf+size-2,
+ &src, src+length,
+ NULL, NULL, NULL, NULL,
+ TRUE, TRUE,
+ &status);
+
+ if (src - old_src < length) {
+ /* Cannot fit into buffer. Schedule for next read. */
+ SCNG(rest_len) = length - (src - old_src);
+ SCNG(rest_str) = emalloc(SCNG(rest_len));
+ memcpy(SCNG(rest_str), src, SCNG(rest_len));
+ }
+ length = target - rt_buf;
+ memcpy(yy_c_buf_p, rt_buf, length);
+ SCNG(yy_n_chars) = b->yy_n_chars = length + offset;
+ b->yy_ch_buf[b->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[b->yy_n_chars+1] = YY_END_OF_BUFFER_CHAR;
+ }
+ encoding = "UTF-8";
+ }
+ return zend_set_converter_encoding(&SCNG(output_conv), encoding);
+}
+
+ZEND_API int32_t zend_convert_scanner_output(UChar **target, int32_t *target_len, const char *source, int32_t source_len, UErrorCode *status TSRMLS_DC)
+{
+ const char *source_consumed = NULL;
- /* force flex to use buffer only */
- SCNG(yy_in) = NULL;
- SCNG(init) = 0;
- SCNG(start) = 1;
+ /* set our custom callback with context */
+ ucnv_setToUCallBack(SCNG(output_conv), zend_scanner_output_callback, &source_consumed, NULL, NULL, status);
- zend_multibyte_set_filter(NULL TSRMLS_CC);
+ /* reset the error and perform conversion */
+ *status = U_ZERO_ERROR;
+ zend_convert_to_unicode(SCNG(output_conv), target, target_len, source, source_len, status);
- if (!SCNG(input_filter)) {
- SCNG(script_filtered) = (char*)emalloc(SCNG(script_org_size)+1);
- memcpy(SCNG(script_filtered), SCNG(script_org), SCNG(script_org_size)+1);
- SCNG(script_filtered_size) = SCNG(script_org_size);
+ /* figure out how many source bytes were consumed */
+ if (U_SUCCESS(*status)) {
+ return source_len;
+ } else if (source_consumed) {
+ return source_consumed - source;
+ } else {
+ return 0;
+ }
+}
+
+int zend_unicode_yyinput(zend_file_handle *file_handle, char *buf, size_t len TSRMLS_DC)
+{
+ size_t n;
+ int c = '*';
+ const char *src = buf;
+
+ /* Look of we have rest from previous call */
+ if (SCNG(rest_str)) {
+ if (len >= SCNG(rest_len)) {
+ memcpy(buf, SCNG(rest_str), SCNG(rest_len));
+ efree(SCNG(rest_str));
+ SCNG(rest_str) = NULL;
+ n = SCNG(rest_len);
+ SCNG(rest_len) = 0;
} else {
- SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC);
+ memcpy(buf, SCNG(rest_str), len);
+ memcpy(SCNG(rest_str), SCNG(rest_str)+len, SCNG(rest_len)-len);
+ n = len;
+ SCNG(rest_len) -= len;
}
-
- /* flex requires doubled null */
- SCNG(script_filtered) = (char*)erealloc(SCNG(script_filtered), SCNG(script_filtered_size)+2);
- *(SCNG(script_filtered)+SCNG(script_filtered_size)) = (char)NULL;
- *(SCNG(script_filtered)+SCNG(script_filtered_size)+1) = (char)NULL;
- yy_scan_buffer(SCNG(script_filtered), SCNG(script_filtered_size)+2 TSRMLS_CC);
} else {
- yy_switch_to_buffer(yy_create_buffer(SCNG(yy_in), YY_BUF_SIZE TSRMLS_CC) TSRMLS_CC);
+ if (file_handle->handle.stream.interactive) {
+ for (n = 0; n < sizeof(buf) && (c = zend_stream_getc(yyin TSRMLS_CC)) != EOF && c != '\n'; ++n) {
+ buf[n] = (char)c;
+ }
+ if (c == '\n') {
+ buf[n++] = (char) c;
+ }
+ } else {
+ n = zend_stream_read(file_handle, buf, len TSRMLS_CC);
+ }
+ }
+
+ /* Don't make any conversions if unicode=off */
+ if (!UG(unicode)) {
+ return n;
+ }
+
+ /* Autodetect encoding */
+ if (!SCNG(encoding_checked)) {
+ int32_t signatureLength;
+ UErrorCode status = U_ZERO_ERROR;
+ const char *encoding;
+
+ encoding = ucnv_detectUnicodeSignature(buf, n, &signatureLength, &status);
+ if (encoding && U_SUCCESS(status)) {
+ src += signatureLength;
+ n -= signatureLength;
+ if (is_encoding_flex_compatible(encoding TSRMLS_CC)) {
+ if (SCNG(input_conv)) {
+ ucnv_close(SCNG(input_conv));
+ SCNG(input_conv) = NULL;
+ }
+ zend_set_converter_encoding(&SCNG(output_conv), encoding);
+ if (signatureLength > 0) {
+ memcpy(buf, src, n);
+ }
+ } else {
+ zend_set_converter_encoding(&SCNG(input_conv), encoding);
+ zend_set_converter_encoding(&SCNG(output_conv), "UTF-8");
+ }
+ }
+ status = U_ZERO_ERROR;
+ SCNG(encoding_checked) = 1;
+ }
+
+ if (SCNG(input_conv) && n >= 0) {
+ UErrorCode status = U_ZERO_ERROR;
+ char rt_buf[8192];
+ char *target = rt_buf;
+ const char *old_src = src;
+
+ ucnv_convertEx(UG(utf8_conv),
+ SCNG(input_conv),
+ &target, rt_buf+len,
+ &src, src+n,
+ NULL, NULL, NULL, NULL,
+ TRUE, TRUE,
+ &status);
+ if (src - old_src < n) {
+ /* Cannot fit into buffer. Schedule for next read. */
+ SCNG(rest_len) = n - (src - old_src);
+ SCNG(rest_str) = emalloc(SCNG(rest_len));
+ memcpy(SCNG(rest_str), src, SCNG(rest_len));
+ }
+ n = target - rt_buf;
+ memcpy(buf, rt_buf, n);
}
-#else /* !ZEND_MULTIBYTE */
+ return n;
+}
+
+ZEND_API int open_file_for_scanning(zend_file_handle *file_handle TSRMLS_DC)
+{
+ char *file_path=NULL;
+ UErrorCode status = U_ZERO_ERROR;
+
+ if (FAILURE == zend_stream_fixup(file_handle TSRMLS_CC)) {
+ return FAILURE;
+ }
+
+ zend_llist_add_element(&CG(open_files), file_handle);
+
+ /* Reset the scanner for scanning the new file */
+ SCNG(yy_in) = file_handle;
+
+ zend_prepare_scanner_converters(ucnv_getName(ZEND_U_CONVERTER(UG(script_encoding_conv)), &status), 0 TSRMLS_CC);
yy_switch_to_buffer(yy_create_buffer(SCNG(yy_in), YY_BUF_SIZE TSRMLS_CC) TSRMLS_CC);
-#endif /* ZEND_MULTIBYTE */
BEGIN(INITIAL);
@@ -460,6 +874,16 @@ zend_op_array *compile_filename(int type, zval *filename TSRMLS_DC)
ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_DC)
{
+ const char *encoding;
+
+ if (Z_TYPE_P(str) == IS_UNICODE) {
+ convert_to_string_with_converter(str, UG(utf8_conv));
+ encoding = "UTF-8";
+ } else {
+ UErrorCode status = U_ZERO_ERROR;
+ encoding = ucnv_getName(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &status);
+ }
+
/* enforce two trailing NULLs for flex... */
STR_REALLOC(str->value.str.val, str->value.str.len+2);
@@ -467,28 +891,8 @@ ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename TSRMLS_D
SCNG(yy_in)=NULL;
-#ifdef ZEND_MULTIBYTE
- SCNG(script_org) = estrdup(str->value.str.val);
- SCNG(script_org_size) = str->value.str.len;
-
- zend_multibyte_set_filter(CG(internal_encoding) TSRMLS_CC);
-
- if (!SCNG(input_filter)) {
- SCNG(script_filtered) = (char*)emalloc(SCNG(script_org_size)+1);
- memcpy(SCNG(script_filtered), SCNG(script_org), SCNG(script_org_size)+1);
- SCNG(script_filtered_size) = SCNG(script_org_size);
- } else {
- SCNG(input_filter)(&SCNG(script_filtered), &SCNG(script_filtered_size), SCNG(script_org), SCNG(script_org_size) TSRMLS_CC);
- }
-
- /* flex requires doubled null */
- SCNG(script_filtered) = (char*)erealloc(SCNG(script_filtered), SCNG(script_filtered_size)+2);
- *(SCNG(script_filtered)+SCNG(script_filtered_size)) = (char)NULL;
- *(SCNG(script_filtered)+SCNG(script_filtered_size)+1) = (char)NULL;
- yy_scan_buffer(SCNG(script_filtered), SCNG(script_filtered_size)+2 TSRMLS_CC);
-#else /* !ZEND_MULTIBYTE */
+ zend_prepare_scanner_converters(encoding, 0 TSRMLS_CC);
yy_scan_buffer(str->value.str.val, str->value.str.len+2 TSRMLS_CC);
-#endif /* ZEND_MULTIBYTE */
zend_set_compiled_filename(filename TSRMLS_CC);
CG(zend_lineno) = 1;
@@ -521,18 +925,21 @@ zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
int compiler_result;
zend_bool original_in_compilation = CG(in_compilation);
- if (source_string->value.str.len==0) {
+ tmp = *source_string;
+ zval_copy_ctor(&tmp);
+ if (Z_TYPE(tmp) != IS_STRING && Z_TYPE(tmp) != IS_UNICODE) {
+ convert_to_text(&tmp);
+ }
+ source_string = &tmp;
+
+ if (Z_USTRLEN_P(source_string)==0) {
efree(op_array);
+ zval_dtor(&tmp);
return NULL;
}
CG(in_compilation) = 1;
- tmp = *source_string;
- zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
- source_string = &tmp;
-
zend_save_lexical_state(&original_lex_state TSRMLS_CC);
if (zend_prepare_string_for_scanning(source_string, filename TSRMLS_CC)==FAILURE) {
efree(op_array);
@@ -543,17 +950,6 @@ zend_op_array *compile_string(zval *source_string, char *filename TSRMLS_DC)
BEGIN(ST_IN_SCRIPTING);
compiler_result = zendparse(TSRMLS_C);
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
- if (SCNG(script_filtered)) {
- efree(SCNG(script_filtered));
- SCNG(script_filtered) = NULL;
- }
-#endif /* ZEND_MULTIBYTE */
-
if (compiler_result==1) {
CG(active_op_array) = original_active_op_array;
CG(unclean_shutdown)=1;
@@ -589,16 +985,6 @@ int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlight
return FAILURE;
}
zend_highlight(syntax_highlighter_ini TSRMLS_CC);
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
- if (SCNG(script_filtered)) {
- efree(SCNG(script_filtered));
- SCNG(script_filtered) = NULL;
- }
-#endif /* ZEND_MULTIBYTE */
zend_destroy_file_handle(&file_handle TSRMLS_CC);
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
return SUCCESS;
@@ -616,166 +1002,384 @@ int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_
return FAILURE;
}
zend_highlight(syntax_highlighter_ini TSRMLS_CC);
-#ifdef ZEND_MULTIBYTE
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- SCNG(script_org) = NULL;
- }
- if (SCNG(script_filtered)) {
- efree(SCNG(script_filtered));
- SCNG(script_filtered) = NULL;
- }
-#endif /* ZEND_MULTIBYTE */
zend_restore_lexical_state(&original_lex_state TSRMLS_CC);
zval_dtor(str);
return SUCCESS;
}
END_EXTERN_C()
-#ifdef ZEND_MULTIBYTE
-BEGIN_EXTERN_C()
-ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, zend_encoding *old_encoding TSRMLS_DC)
+#define zend_copy_value(zendlval, yytext, yyleng) \
+ zendlval->value.str.val = (char *)estrndup(yytext, yyleng); \
+ zendlval->value.str.len = yyleng;
+
+int zend_scan_unicode_double_string(zval *zendlval TSRMLS_DC)
{
- YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
- int offset, original_offset, length, free_flag;
- char *p;
- zend_encoding *new_encoding;
-
- /* calculate current position */
- offset = original_offset = yy_c_buf_p - b->yy_ch_buf;
- if (old_input_filter && original_offset > 0) {
- new_encoding = SCNG(script_encoding);
- SCNG(script_encoding) = old_encoding;
- do {
- (old_input_filter)(&p, &length, SCNG(script_org), offset TSRMLS_CC);
- if (!p) {
- SCNG(script_encoding) = new_encoding;
- return;
+ register UChar *s, *t, c;
+ UChar *end;
+ UChar32 codepoint = 0;
+ int8_t digit;
+ int8_t min_digits = 0, max_digits = 0;
+ int8_t bits;
+ int8_t n;
+
+ HANDLE_NEWLINES(yytext, yyleng);
+
+ if (!zend_copy_string_value(zendlval, yytext+1, yyleng-2, IS_UNICODE TSRMLS_CC)) {
+ return 0;
+ }
+
+ /* convert escape sequences */
+ s = t = zendlval->value.ustr.val;
+ end = s+zendlval->value.ustr.len;
+ while (s<end) {
+ if (*s==0x5C /*'\\'*/) {
+ s++;
+ c = *s;
+ if (s>=end) {
+ continue;
}
- efree(p);
- if (length > original_offset) {
- offset--;
- } else if (length < original_offset) {
- offset++;
+
+ min_digits = 0;
+ codepoint = 0;
+ bits = 4;
+ n = 0;
+
+ switch(c) {
+ case 0x6E: /*'n'*/
+ *t++ = (UChar) 0x0A; /*'\n'*/
+ zendlval->value.ustr.len--;
+ break;
+ case 0x72: /*'r'*/
+ *t++ = (UChar) 0x0D; /*'\r'*/
+ zendlval->value.ustr.len--;
+ break;
+ case 0x74: /*'t'*/
+ *t++ = (UChar) 0x09; /*'\t'*/
+ zendlval->value.ustr.len--;
+ break;
+ case 0x5C: /*'\\'*/
+ case 0x24: /*'$'*/
+ case 0x22: /*'"'*/
+ *t++ = *s;
+ zendlval->value.ustr.len--;
+ break;
+ case 0x43: /*'C'*/
+ {
+ UChar *p = s+1;
+ if (p < end && zend_parse_charname_sequence(&p, end, &codepoint)) {
+ zendlval->value.ustr.len -= p - s + 1;
+ s = p;
+ if (U_IS_BMP(codepoint)) {
+ *t++ = (UChar) codepoint;
+ } else {
+ *t++ = (UChar) U16_LEAD(codepoint);
+ *t++ = (UChar) U16_TRAIL(codepoint);
+ zendlval->value.ustr.len++;
+ }
+ } else {
+ zend_error(E_COMPILE_WARNING, "Invalid \\C{..} sequence");
+ efree(zendlval->value.ustr.val);
+ return 0;
+ }
+ break;
+ }
+ case 0x75: /*'u'*/
+ min_digits = 4;
+ max_digits = 4;
+ zendlval->value.ustr.len--;
+ break;
+ case 0x55: /*'U'*/
+ min_digits = 6;
+ max_digits = 6;
+ zendlval->value.ustr.len--;
+ break;
+ default:
+ digit = zend_get_octal_digit(*s);
+ if (digit >= 0) {
+ min_digits = 1;
+ max_digits = 3;
+ bits = 3;
+ n = 1; /* already have one digit */
+ codepoint = digit;
+ } else if (c == 0x78 /*'x'*/
+ && (s+1) < end && (digit = zend_get_hex_digit(*(s+1))) >= 0) {
+ min_digits = 1;
+ max_digits = 2;
+ zendlval->value.ustr.len--;
+ s++;
+ n = 1; /* already have one digit */
+ codepoint = digit;
+ } else {
+ *t++ = 0x5C; /*'\\'*/
+ *t++ = *s;
+ }
+ break;
}
- } while (original_offset != length);
- SCNG(script_encoding) = new_encoding;
- }
- /* convert and set */
- if (!SCNG(input_filter)) {
- length = SCNG(script_org_size)-offset-1;
- p = SCNG(script_org)+offset+1;
- free_flag = 0;
- } else {
- SCNG(input_filter)(&p, &length, SCNG(script_org)+offset+1, SCNG(script_org_size)-offset-1 TSRMLS_CC);
- free_flag = 1;
- }
- if (original_offset+length+1 > (int)b->yy_buf_size) {
- b->yy_buf_size = original_offset+length+1;
- b->yy_ch_buf = (char*)erealloc(b->yy_ch_buf, b->yy_buf_size+2);
- SCNG(script_filtered) = b->yy_ch_buf;
- SCNG(script_filtered_size) = b->yy_buf_size;
+ /* need to parse a number for one of the escape sequences */
+ if (min_digits != 0) {
+ while (s++ < end && n < max_digits) {
+ digit = (bits == 4) ? zend_get_hex_digit(*s) : zend_get_octal_digit(*s);
+ if (digit < 0) {
+ break;
+ }
+ codepoint = (codepoint << bits) | digit;
+ n++;
+ }
+
+ if (n < min_digits) {
+ /* can only happen for \u and \U sequences */
+ zend_error(E_COMPILE_WARNING,"\\%c escape sequence requires exactly %d hexadecimal digits", (char) c, min_digits);
+ efree(zendlval->value.ustr.val);
+ return 0;
+ }
+
+ if (U_IS_BMP(codepoint)) {
+ *t++ = (UChar) codepoint;
+ zendlval->value.ustr.len -= n;
+ } else if (codepoint <= 0x10FFFF) {
+ *t++ = (UChar) U16_LEAD(codepoint);
+ *t++ = (UChar) U16_TRAIL(codepoint);
+ zendlval->value.ustr.len -= n-1;
+ } else {
+ zend_error(E_COMPILE_WARNING,"\\U%06x is above the highest valid codepoint 0x10FFFF", codepoint);
+ efree(zendlval->value.ustr.val);
+ return 0;
+ }
+ } else {
+ s++;
+ }
+ } else {
+ *t++ = *s++;
+ }
}
- yy_c_buf_p = b->yy_ch_buf + original_offset;
- strncpy(yy_c_buf_p+1, p, length);
- b->yy_n_chars = original_offset + length + 1;
- SCNG(yy_n_chars) = b->yy_n_chars;
- b->yy_ch_buf[SCNG(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
- b->yy_ch_buf[SCNG(yy_n_chars)+1] = YY_END_OF_BUFFER_CHAR;
+ *t = 0;
- if (free_flag) {
- efree(p);
- }
+ return T_CONSTANT_ENCAPSED_STRING;
}
-
-ZEND_API int zend_multibyte_yyinput(zend_file_handle *file_handle, char *buf, size_t len TSRMLS_DC)
+int zend_scan_unicode_single_string(zval *zendlval TSRMLS_DC)
{
- int c = '*', n;
+ register UChar *s, *t;
+ UChar *end;
+ UChar32 codepoint = 0;
- if (file_handle->handle.stream.interactive == 0) {
- return zend_stream_read(file_handle, buf, len TSRMLS_CC);
- }
+ HANDLE_NEWLINES(yytext, yyleng);
- /* interactive */
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- }
- if (SCNG(script_filtered)) {
- efree(SCNG(script_filtered));
+ if (!zend_copy_string_value(zendlval, yytext+1, yyleng-2, IS_UNICODE TSRMLS_CC)) {
+ return 0;
}
- SCNG(script_org) = NULL;
- SCNG(script_org_size) = 0;
-
- /* TODO: support widechars */
- for (n = 0; n < sizeof(buf) && (c = zend_stream_getc(yyin TSRMLS_CC)) != EOF && c != '\n'; ++n) {
- buf[n] = (char)c;
- }
- if (c == '\n') {
- buf[n++] = (char) c;
+ /* convert escape sequences */
+ s = t = zendlval->value.ustr.val;
+ end = s+zendlval->value.ustr.len;
+ while (s<end) {
+ if (*s==0x5C /*'\\'*/) {
+ s++;
+ if (s>=end) {
+ continue;
+ }
+ switch(*s) {
+ case 0x5C: /*'\\'*/
+ case 0x27: /*'\''*/
+ *t++ = *s;
+ zendlval->value.ustr.len--;
+ break;
+ case 0x43: /*'C'*/
+ {
+ UChar *p = s+1;
+ if (p < end && zend_parse_charname_sequence(&p, end, &codepoint)) {
+ zendlval->value.ustr.len -= p - s + 1;
+ s = p;
+ if (U_IS_BMP(codepoint)) {
+ *t++ = (UChar) codepoint;
+ } else {
+ *t++ = (UChar) U16_LEAD(codepoint);
+ *t++ = (UChar) U16_TRAIL(codepoint);
+ zendlval->value.ustr.len++;
+ }
+ } else {
+ zend_error(E_COMPILE_WARNING, "Invalid \\C{..} sequence");
+ efree(zendlval->value.ustr.val);
+ return 0;
+ }
+ break;
+ }
+ case 0x75 /*'u'*/:
+ {
+ codepoint = 0;
+ if (zend_udigits_to_codepoint(s+1, end, &codepoint, 4)) {
+ *t++ = (UChar) codepoint;
+ s += 4;
+ zendlval->value.ustr.len -= 5;
+ } else {
+ zend_error(E_COMPILE_WARNING,"\\u escape sequence requires exactly 4 hexadecimal digits");
+ efree(zendlval->value.ustr.val);
+ return 0;
+ }
+ break;
+ }
+ case 0x55 /*'U'*/:
+ {
+ codepoint = 0;
+ if (zend_udigits_to_codepoint(s+1, end, &codepoint, 6)) {
+ if (U_IS_BMP(codepoint)) {
+ *t++ = (UChar) codepoint;
+ zendlval->value.ustr.len -= 7;
+ } else if (codepoint <= 0x10FFFF) {
+ *t++ = (UChar) U16_LEAD(codepoint);
+ *t++ = (UChar) U16_TRAIL(codepoint);
+ zendlval->value.ustr.len -= 6;
+ } else {
+ zend_error(E_COMPILE_WARNING,"\\U%06x is above the highest valid codepoint 0x10FFFF", codepoint);
+ efree(zendlval->value.ustr.val);
+ return 0;
+ }
+ s += 6;
+ } else {
+ zend_error(E_COMPILE_WARNING,"\\U escape sequence requires exactly 6 hexadecimal digits");
+ efree(zendlval->value.ustr.val);
+ return 0;
+ }
+ break;
+ }
+ default:
+ *t++ = 0x5C; /*'\\'*/
+ *t++ = *s;
+ break;
+ }
+ s++;
+ } else {
+ *t++ = *s++;
+ }
}
+ *t = 0;
- SCNG(script_org_size) = n;
- SCNG(script_org) = (char*)emalloc(SCNG(script_org_size)+1);
- memcpy(SCNG(script_org)+SCNG(script_org_size)-n, buf, n);
-
- return n;
+ return T_CONSTANT_ENCAPSED_STRING;
}
-
-ZEND_API int zend_multibyte_read_script(TSRMLS_D)
+int zend_scan_binary_double_string(zval *zendlval TSRMLS_DC)
{
- char buf[8192];
- int n;
+ register char *s, *t;
+ char *end;
- if (SCNG(script_org)) {
- efree(SCNG(script_org));
- }
- SCNG(script_org) = NULL;
- SCNG(script_org_size) = 0;
+ zendlval->value.str.val = estrndup(yytext+1, yyleng-2);
+ zendlval->value.str.len = yyleng-2;
+ zendlval->type = UG(unicode) ? IS_BINARY : IS_STRING;
+ HANDLE_NEWLINES(yytext, yyleng);
- for (;;) {
- n = zend_stream_read(yyin, buf, sizeof(buf) TSRMLS_CC);
- if (n <= 0) {
- break;
- }
+ /* convert escape sequences */
+ s = t = zendlval->value.str.val;
+ end = s+zendlval->value.str.len;
+ while (s<end) {
+ if (*s=='\\') {
+ s++;
+ if (s>=end) {
+ continue;
+ }
+ switch(*s) {
+ case 'n':
+ *t++ = '\n';
+ zendlval->value.str.len--;
+ break;
+ case 'r':
+ *t++ = '\r';
+ zendlval->value.str.len--;
+ break;
+ case 't':
+ *t++ = '\t';
+ zendlval->value.str.len--;
+ break;
+ case '\\':
+ case '$':
+ case '"':
+ *t++ = *s;
+ zendlval->value.str.len--;
+ break;
+ default:
+ /* check for an octal */
+ if (ZEND_IS_OCT(*s)) {
+ char octal_buf[4] = { 0, 0, 0, 0 };
+
+ octal_buf[0] = *s;
+ zendlval->value.str.len--;
+ if ((s+1)<end && ZEND_IS_OCT(*(s+1))) {
+ octal_buf[1] = *(++s);
+ zendlval->value.str.len--;
+ if ((s+1)<end && ZEND_IS_OCT(*(s+1))) {
+ octal_buf[2] = *(++s);
+ zendlval->value.str.len--;
+ }
+ }
+ *t++ = (char) strtol(octal_buf, NULL, 8);
+ } else if (*s=='x' && (s+1)<end && ZEND_IS_HEX(*(s+1))) {
+ char hex_buf[3] = { 0, 0, 0};
- SCNG(script_org_size) += n;
- if (SCNG(script_org)) {
- SCNG(script_org) = (char*)erealloc(SCNG(script_org), SCNG(script_org_size)+1);
+ zendlval->value.str.len--; /* for the 'x' */
+
+ hex_buf[0] = *(++s);
+ zendlval->value.str.len--;
+ if ((s+1)<end && ZEND_IS_HEX(*(s+1))) {
+ hex_buf[1] = *(++s);
+ zendlval->value.str.len--;
+ }
+ *t++ = (char) strtol(hex_buf, NULL, 16);
+ } else {
+ *t++ = '\\';
+ *t++ = *s;
+ }
+ break;
+ }
+ s++;
} else {
- SCNG(script_org) = (char*)emalloc(SCNG(script_org_size)+1);
+ *t++ = *s++;
}
- memcpy(SCNG(script_org)+SCNG(script_org_size)-n, buf, n);
}
+ *t = 0;
- if (n < 0) {
- return -1;
- }
+ return T_CONSTANT_ENCAPSED_STRING;
+}
- if (!SCNG(script_org)) {
- SCNG(script_org) = emalloc(SCNG(script_org_size)+1);
+int zend_scan_binary_single_string(zval *zendlval TSRMLS_DC)
+{
+ register char *s, *t;
+ char *end;
+
+ zendlval->value.str.val = estrndup(yytext+1, yyleng-2);
+ zendlval->value.str.len = yyleng-2;
+ zendlval->type = UG(unicode) ? IS_BINARY : IS_STRING;
+ HANDLE_NEWLINES(yytext, yyleng);
+
+ /* convert escape sequences */
+ s = t = zendlval->value.str.val;
+ end = s+zendlval->value.str.len;
+ while (s<end) {
+ if (*s=='\\') {
+ s++;
+ if (s>=end) {
+ continue;
+ }
+ switch(*s) {
+ case '\\':
+ case '\'':
+ *t++ = *s;
+ zendlval->value.str.len--;
+ break;
+ default:
+ *t++ = '\\';
+ *t++ = *s;
+ break;
+ }
+ s++;
+ } else {
+ *t++ = *s++;
+ }
}
- *(SCNG(script_org)+SCNG(script_org_size)) = (char)NULL;
+ *t = 0;
- return 0;
+ return T_CONSTANT_ENCAPSED_STRING;
}
-
-# define zend_copy_value(zendlval, yytext, yyleng) \
- if (SCNG(output_filter)) { \
- SCNG(output_filter)(&(zendlval->value.str.val), &(zendlval->value.str.len), yytext, yyleng TSRMLS_CC); \
- } else { \
- zendlval->value.str.val = (char *) estrndup(yytext, yyleng); \
- zendlval->value.str.len = yyleng; \
- }
-#else /* ZEND_MULTIBYTE */
-# define zend_copy_value(zendlval, yytext, yyleng) \
- zendlval->value.str.val = (char *)estrndup(yytext, yyleng); \
- zendlval->value.str.len = yyleng;
-#endif /* ZEND_MULTIBYTE */
%}
LNUM [0-9]+
@@ -942,8 +1546,12 @@ NEWLINE ("\r"|"\n"|"\r\n")
<ST_LOOKING_FOR_PROPERTY>{LABEL} {
yy_pop_state(TSRMLS_C);
- zend_copy_value(zendlval, yytext, yyleng);
- zendlval->type = IS_STRING;
+ if (!zend_copy_string_value(zendlval, yytext, yyleng, UG(unicode)?IS_UNICODE:IS_STRING TSRMLS_CC)) {
+ return 0;
+ }
+ if (UG(unicode) && !zend_check_and_normalize_identifier(zendlval)) {
+ return 0;
+ }
return T_STRING;
}
@@ -980,6 +1588,14 @@ NEWLINE ("\r"|"\n"|"\r\n")
return T_STRING_CAST;
}
+<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"unicode"{TABS_AND_SPACES}")" {
+ return T_UNICODE_CAST;
+}
+
+<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"binary"{TABS_AND_SPACES}")" {
+ return T_BINARY_CAST;
+}
+
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"array"{TABS_AND_SPACES}")" {
return T_ARRAY_CAST;
}
@@ -1208,8 +1824,12 @@ NEWLINE ("\r"|"\n"|"\r\n")
<ST_LOOKING_FOR_VARNAME>{LABEL} {
- zend_copy_value(zendlval, yytext, yyleng);
- zendlval->type = IS_STRING;
+ if (!zend_copy_string_value(zendlval, yytext, yyleng, UG(unicode)?IS_UNICODE:IS_STRING TSRMLS_CC)) {
+ return 0;
+ }
+ if (UG(unicode) && !zend_check_and_normalize_identifier(zendlval)) {
+ return 0;
+ }
yy_pop_state(TSRMLS_C);
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
return T_STRING_VARNAME;
@@ -1257,9 +1877,9 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
<ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>{LNUM}|{HNUM} { /* treat numbers (almost) as strings inside encapsulated strings */
- zendlval->value.str.val = (char *)estrndup(yytext, yyleng);
- zendlval->value.str.len = yyleng;
- zendlval->type = IS_STRING;
+ if (!zend_copy_string_value(zendlval, yytext, yyleng, CG(literal_type) TSRMLS_CC)) {
+ return 0;
+ }
return T_NUM_STRING;
}
@@ -1276,12 +1896,25 @@ NEWLINE ("\r"|"\n"|"\r\n")
class_name = CG(active_class_entry)->name;
}
- if (!class_name) {
- class_name = "";
+ if (UG(unicode)) {
+ if (!class_name) {
+ zendlval->value.ustr.len = 0;
+ zendlval->value.ustr.val = USTR_MAKE("");
+ } else {
+ zendlval->value.ustr.len = u_strlen((UChar*)class_name);
+ zendlval->value.ustr.val = eustrndup((UChar*)class_name, zendlval->value.ustr.len);
+ }
+ zendlval->type = IS_UNICODE;
+ } else {
+ if (!class_name) {
+ zendlval->value.str.len = 0;
+ zendlval->value.str.val = estrndup("", 0);
+ } else {
+ zendlval->value.str.len = strlen(class_name);
+ zendlval->value.str.val = estrndup(class_name, zendlval->value.str.len);
+ }
+ zendlval->type = IS_STRING;
}
- zendlval->value.str.len = strlen(class_name);
- zendlval->value.str.val = estrndup(class_name, zendlval->value.str.len);
- zendlval->type = IS_STRING;
return T_CLASS_C;
}
@@ -1295,9 +1928,25 @@ NEWLINE ("\r"|"\n"|"\r\n")
if (!func_name) {
func_name = "";
}
- zendlval->value.str.len = strlen(func_name);
- zendlval->value.str.val = estrndup(func_name, zendlval->value.str.len);
- zendlval->type = IS_STRING;
+ if (UG(unicode)) {
+ if (!func_name) {
+ zendlval->value.ustr.len = 0;
+ zendlval->value.ustr.val = USTR_MAKE("");
+ } else {
+ zendlval->value.ustr.len = u_strlen((UChar*)func_name);
+ zendlval->value.ustr.val = eustrndup((UChar*)func_name, zendlval->value.ustr.len);
+ }
+ zendlval->type = IS_UNICODE;
+ } else {
+ if (!func_name) {
+ zendlval->value.str.len = 0;
+ zendlval->value.str.val = estrndup("", 0);
+ } else {
+ zendlval->value.str.len = strlen(func_name);
+ zendlval->value.str.val = estrndup(func_name, zendlval->value.str.len);
+ }
+ zendlval->type = IS_STRING;
+ }
return T_FUNC_C;
}
@@ -1306,21 +1955,47 @@ NEWLINE ("\r"|"\n"|"\r\n")
char *func_name = CG(active_op_array)? CG(active_op_array)->function_name : NULL;
size_t len = 0;
- if (class_name) {
- len += strlen(class_name) + 2;
- }
- if (func_name) {
- len += strlen(func_name);
- }
+ if (UG(unicode)) {
+ size_t len1;
- zendlval->value.str.val = emalloc(len+1);
- zendlval->value.str.len = sprintf(zendlval->value.str.val, "%s%s%s",
- class_name ? class_name : "",
- class_name && func_name ? "::" : "",
- func_name ? func_name : ""
- );
- zendlval->value.str.len = strlen(zendlval->value.str.val);
- zendlval->type = IS_STRING;
+ if (class_name) {
+ len += len1 = u_strlen((UChar*)class_name);
+ len += 2;
+ }
+ if (func_name) {
+ len += u_strlen((UChar*)func_name);
+ } else {
+ func_name = EMPTY_STR;
+ }
+ zendlval->value.str.len = len;
+ Z_USTRVAL_P(zendlval) = eumalloc(len+1);
+ if (class_name) {
+ u_strcpy(Z_USTRVAL_P(zendlval), (UChar*)class_name);
+ Z_USTRVAL_P(zendlval)[len1] = 0x3a; /* ':' */
+ Z_USTRVAL_P(zendlval)[len1+1] = 0x3a; /* ':' */
+ Z_USTRVAL_P(zendlval)[len1+2] = 0;
+ } else {
+ Z_USTRVAL_P(zendlval)[0] = 0;
+ }
+ u_strcat(Z_USTRVAL_P(zendlval), (UChar*)func_name);
+ zendlval->type = IS_UNICODE;
+ } else {
+ if (class_name) {
+ len += strlen(class_name) + 2;
+ }
+ if (func_name) {
+ len += strlen(func_name);
+ }
+
+ zendlval->value.str.val = emalloc(len+1);
+ zendlval->value.str.len = sprintf(zendlval->value.str.val, "%s%s%s",
+ class_name ? class_name : "",
+ class_name && func_name ? "::" : "",
+ func_name ? func_name : ""
+ );
+ zendlval->value.str.len = strlen(zendlval->value.str.val);
+ zendlval->type = IS_STRING;
+ }
return T_METHOD_C;
}
@@ -1343,22 +2018,9 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
<INITIAL>(([^<]|"<"[^?%s<]){1,400})|"<s"|"<" {
-#ifdef ZEND_MULTIBYTE
- if (SCNG(output_filter)) {
- int readsize;
- readsize = SCNG(output_filter)(&(zendlval->value.str.val), &(zendlval->value.str.len), yytext, yyleng TSRMLS_CC);
- if (readsize < yyleng) {
- yyless(readsize);
- }
- } else {
- zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
- zendlval->value.str.len = yyleng;
- }
-#else /* !ZEND_MULTIBYTE */
zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
zendlval->value.str.len = yyleng;
-#endif /* ZEND_MULTIBYTE */
- zendlval->type = IS_STRING;
+ zendlval->type = IS_BINARY;
HANDLE_NEWLINES(yytext, yyleng);
return T_INLINE_HTML;
}
@@ -1374,7 +2036,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
} else {
zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
zendlval->value.str.len = yyleng;
- zendlval->type = IS_STRING;
+ zendlval->type = IS_BINARY;
return T_INLINE_HTML;
}
}
@@ -1390,7 +2052,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
} else {
zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
zendlval->value.str.len = yyleng;
- zendlval->type = IS_STRING;
+ zendlval->type = IS_BINARY;
return T_INLINE_HTML;
}
}
@@ -1406,7 +2068,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
} else {
zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
zendlval->value.str.len = yyleng;
- zendlval->type = IS_STRING;
+ zendlval->type = IS_BINARY;
return T_INLINE_HTML;
}
}
@@ -1422,20 +2084,29 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
<ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE>"$"{LABEL} {
- zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- zendlval->type = IS_STRING;
+ if (!zend_copy_string_value(zendlval, (yytext+1), (yyleng-1), UG(unicode)?IS_UNICODE:IS_STRING TSRMLS_CC)) {
+ return 0;
+ }
+ if (UG(unicode) && !zend_check_and_normalize_identifier(zendlval)) {
+ return 0;
+ }
return T_VARIABLE;
}
<ST_IN_SCRIPTING>{LABEL} {
- zend_copy_value(zendlval, yytext, yyleng);
- zendlval->type = IS_STRING;
+ if (!zend_copy_string_value(zendlval, yytext, yyleng, UG(unicode)?IS_UNICODE:IS_STRING TSRMLS_CC)) {
+ return 0;
+ }
+ if (UG(unicode) && !zend_check_and_normalize_identifier(zendlval)) {
+ return 0;
+ }
return T_STRING;
}
<ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>{LABEL} {
- zend_copy_value(zendlval, yytext, yyleng);
- zendlval->type = IS_STRING;
+ if (!zend_copy_string_value(zendlval, yytext, yyleng, CG(literal_type) TSRMLS_CC)) {
+ return 0;
+ }
return T_STRING;
}
@@ -1544,140 +2215,34 @@ NEWLINE ("\r"|"\n"|"\r\n")
<ST_IN_SCRIPTING>(["]([^$"\\]|("\\".))*["]) {
- register char *s, *t;
- char *end;
-
- zendlval->value.str.val = estrndup(yytext+1, yyleng-2);
- zendlval->value.str.len = yyleng-2;
- zendlval->type = IS_STRING;
- HANDLE_NEWLINES(yytext, yyleng);
-
- /* convert escape sequences */
- s = t = zendlval->value.str.val;
- end = s+zendlval->value.str.len;
- while (s<end) {
- if (*s=='\\') {
- s++;
- if (s>=end) {
- continue;
- }
- switch(*s) {
- case 'n':
- *t++ = '\n';
- zendlval->value.str.len--;
- break;
- case 'r':
- *t++ = '\r';
- zendlval->value.str.len--;
- break;
- case 't':
- *t++ = '\t';
- zendlval->value.str.len--;
- break;
- case '\\':
- case '$':
- case '"':
- *t++ = *s;
- zendlval->value.str.len--;
- break;
- default:
- /* check for an octal */
- if (ZEND_IS_OCT(*s)) {
- char octal_buf[4] = { 0, 0, 0, 0 };
-
- octal_buf[0] = *s;
- zendlval->value.str.len--;
- if ((s+1)<end && ZEND_IS_OCT(*(s+1))) {
- octal_buf[1] = *(++s);
- zendlval->value.str.len--;
- if ((s+1)<end && ZEND_IS_OCT(*(s+1))) {
- octal_buf[2] = *(++s);
- zendlval->value.str.len--;
- }
- }
- *t++ = (char) strtol(octal_buf, NULL, 8);
- } else if (*s=='x' && (s+1)<end && ZEND_IS_HEX(*(s+1))) {
- char hex_buf[3] = { 0, 0, 0};
-
- zendlval->value.str.len--; /* for the 'x' */
-
- hex_buf[0] = *(++s);
- zendlval->value.str.len--;
- if ((s+1)<end && ZEND_IS_HEX(*(s+1))) {
- hex_buf[1] = *(++s);
- zendlval->value.str.len--;
- }
- *t++ = (char) strtol(hex_buf, NULL, 16);
- } else {
- *t++ = '\\';
- *t++ = *s;
- }
- break;
- }
- s++;
- } else {
- *t++ = *s++;
- }
+ if (UG(unicode)) {
+ return zend_scan_unicode_double_string(zendlval TSRMLS_CC);
+ } else {
+ return zend_scan_binary_double_string(zendlval TSRMLS_CC);
}
- *t = 0;
+}
-#ifdef ZEND_MULTIBYTE
- if (SCNG(output_filter)) {
- s = zendlval->value.str.val;
- SCNG(output_filter)(&(zendlval->value.str.val), &(zendlval->value.str.len), s, zendlval->value.str.len TSRMLS_CC);
- efree(s);
- }
-#endif /* ZEND_MULTIBYTE */
- return T_CONSTANT_ENCAPSED_STRING;
+<ST_IN_SCRIPTING>(b["]([^$"\\]|("\\".))*["]) {
+ yytext++; /* adjust for 'b' */
+ yyleng--;
+ return zend_scan_binary_double_string(zendlval TSRMLS_CC);
}
<ST_IN_SCRIPTING>([']([^'\\]|("\\".))*[']) {
- register char *s, *t;
- char *end;
-
- zendlval->value.str.val = estrndup(yytext+1, yyleng-2);
- zendlval->value.str.len = yyleng-2;
- zendlval->type = IS_STRING;
- HANDLE_NEWLINES(yytext, yyleng);
-
- /* convert escape sequences */
- s = t = zendlval->value.str.val;
- end = s+zendlval->value.str.len;
- while (s<end) {
- if (*s=='\\') {
- s++;
- if (s>=end) {
- continue;
- }
- switch(*s) {
- case '\\':
- case '\'':
- *t++ = *s;
- zendlval->value.str.len--;
- break;
- default:
- *t++ = '\\';
- *t++ = *s;
- break;
- }
- s++;
- } else {
- *t++ = *s++;
- }
+ if (UG(unicode)) {
+ return zend_scan_unicode_single_string(zendlval TSRMLS_CC);
+ } else {
+ return zend_scan_binary_single_string(zendlval TSRMLS_CC);
}
- *t = 0;
+}
-#ifdef ZEND_MULTIBYTE
- if (SCNG(output_filter)) {
- s = zendlval->value.str.val;
- SCNG(output_filter)(&(zendlval->value.str.val), &(zendlval->value.str.len), s, zendlval->value.str.len TSRMLS_CC);
- efree(s);
- }
-#endif /* ZEND_MULTIBYTE */
- return T_CONSTANT_ENCAPSED_STRING;
+<ST_IN_SCRIPTING>("b'"([^'\\]|("\\".))*[']) {
+ yytext++; /* adjust for 'b' */
+ yyleng--;
+ return zend_scan_binary_single_string(zendlval TSRMLS_CC);
}
@@ -1686,6 +2251,25 @@ NEWLINE ("\r"|"\n"|"\r\n")
return '\"';
}
+<ST_IN_SCRIPTING>b["] {
+ BEGIN(ST_DOUBLE_QUOTES);
+ return T_BINARY_DOUBLE;
+}
+
+<ST_IN_SCRIPTING>b"<<<"{TABS_AND_SPACES}{LABEL}{NEWLINE} {
+ char *s;
+ CG(zend_lineno)++;
+ CG(heredoc_len) = yyleng-4-1-(yytext[yyleng-2]=='\r'?1:0);
+ s = yytext+4;
+ while ((*s == ' ') || (*s == '\t')) {
+ s++;
+ CG(heredoc_len)--;
+ }
+ CG(heredoc) = estrndup(s, CG(heredoc_len));
+ BEGIN(ST_HEREDOC);
+ return T_BINARY_HEREDOC;
+}
+
<ST_IN_SCRIPTING>"<<<"{TABS_AND_SPACES}{LABEL}{NEWLINE} {
char *s;
@@ -1708,12 +2292,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
-<ST_IN_SCRIPTING>['] {
- BEGIN(ST_SINGLE_QUOTE);
- return '\'';
-}
-
-
<ST_HEREDOC>^{LABEL}(";")?{NEWLINE} {
int label_len;
unsigned char unput_semicolon;
@@ -1744,8 +2322,9 @@ NEWLINE ("\r"|"\n"|"\r\n")
BEGIN(ST_IN_SCRIPTING);
return T_END_HEREDOC;
} else {
- zend_copy_value(zendlval, yytext, yyleng);
- zendlval->type = IS_STRING;
+ if (!zend_copy_string_value(zendlval, yytext, yyleng, CG(literal_type) TSRMLS_CC)) {
+ return 0;
+ }
return T_STRING;
}
}
@@ -1753,30 +2332,24 @@ NEWLINE ("\r"|"\n"|"\r\n")
<ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>{ESCAPED_AND_WHITESPACE} {
HANDLE_NEWLINES(yytext, yyleng);
- zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
- zendlval->value.str.len = yyleng;
- zendlval->type = IS_STRING;
- return T_ENCAPSED_AND_WHITESPACE;
-}
-
-<ST_SINGLE_QUOTE>([^'\\]|\\[^'\\])+ {
- HANDLE_NEWLINES(yytext, yyleng);
- zend_copy_value(zendlval, yytext, yyleng);
- zendlval->type = IS_STRING;
+ if (!zend_copy_string_value(zendlval, yytext, yyleng, CG(literal_type) TSRMLS_CC)) {
+ return 0;
+ }
return T_ENCAPSED_AND_WHITESPACE;
}
-
<ST_DOUBLE_QUOTES>[`]+ {
- zend_copy_value(zendlval, yytext, yyleng);
- zendlval->type = IS_STRING;
+ if (!zend_copy_string_value(zendlval, yytext, yyleng, CG(literal_type) TSRMLS_CC)) {
+ return 0;
+ }
return T_ENCAPSED_AND_WHITESPACE;
}
<ST_BACKQUOTE>["]+ {
- zend_copy_value(zendlval, yytext, yyleng);
- zendlval->type = IS_STRING;
+ if (!zend_copy_string_value(zendlval, yytext, yyleng, CG(literal_type) TSRMLS_CC)) {
+ return 0;
+ }
return T_ENCAPSED_AND_WHITESPACE;
}
@@ -1803,16 +2376,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
-<ST_SINGLE_QUOTE>"\\'" {
- zendlval->value.lval = (long) '\'';
- return T_CHARACTER;
-}
-
-<ST_SINGLE_QUOTE>"\\\\" {
- zendlval->value.lval = (long)'\\';
- return T_CHARACTER;
-}
-
<ST_DOUBLE_QUOTES>"\\\"" {
zendlval->value.lval = (long) '"';
return T_CHARACTER;
@@ -1833,6 +2396,61 @@ NEWLINE ("\r"|"\n"|"\r\n")
return T_CHARACTER;
}
+
+<ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"\\u"[0-9A-Fa-f]{0,6} {
+ UChar32 codepoint;
+ int req_digits = (yytext[1] == 'U') ? 6 : 4;
+
+ if (CG(literal_type) == IS_UNICODE) {
+ if (zend_digits_to_codepoint(yytext+2, yytext+yyleng, &codepoint, req_digits)) {
+ if (codepoint <= 0x10FFFF) {
+ zendlval->value.lval = (long) codepoint;
+ /* give back if we grabbed more than needed for \u case */
+ if (yyleng > req_digits + 2) {
+ yyless(req_digits + 2);
+ }
+ return T_CHARACTER;
+ } else {
+ zend_error(E_COMPILE_WARNING,"\\U%06x is above the highest valid codepoint 0x10FFFF", codepoint);
+ return 0;
+ }
+ } else {
+ zend_error(E_COMPILE_WARNING,"\\%c escape sequence requires exactly %d hexadecimal digits", yytext[1], req_digits);
+ return 0;
+ }
+ } else {
+ zend_copy_string_value(zendlval, yytext, yyleng, CG(literal_type) TSRMLS_CC);
+ return T_STRING;
+ }
+}
+
+
+<ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"\\C"("{"[A-Z0-9 -]+"}")? {
+ UChar32 codepoint;
+
+ if (CG(literal_type) == IS_UNICODE && (yytext[1] == 'C')) {
+ /* minimum valid string is \C{.} */
+ if (yyleng >= 5) {
+ /* safe, since we have } at the end */
+ yytext[yyleng-1] = 0;
+ if (zend_uchar_from_name(yytext+3, &codepoint)) {
+ zendlval->value.lval = (long) codepoint;
+ return T_CHARACTER;
+ } else {
+ zend_error(E_COMPILE_WARNING, "Invalid Unicode character name: '%s'", yytext+3);
+ return 0;
+ }
+ } else {
+ zend_error(E_COMPILE_WARNING, "Invalid \\C{..} sequence");
+ return 0;
+ }
+ } else {
+ zend_copy_string_value(zendlval, yytext, yyleng, CG(literal_type) TSRMLS_CC);
+ return T_STRING;
+ }
+}
+
+
<ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"\\"{ANY_CHAR} {
switch (yytext[1]) {
case 'n':
@@ -1854,9 +2472,9 @@ NEWLINE ("\r"|"\n"|"\r\n")
zendlval->value.lval = (long) yytext[1];
break;
default:
- zendlval->value.str.val = estrndup(yytext, yyleng);
- zendlval->value.str.len = yyleng;
- zendlval->type = IS_STRING;
+ if (!zend_copy_string_value(zendlval, yytext, yyleng, CG(literal_type) TSRMLS_CC)) {
+ return 0;
+ }
return T_BAD_CHARACTER;
break;
}
@@ -1865,9 +2483,9 @@ NEWLINE ("\r"|"\n"|"\r\n")
<ST_HEREDOC>["'`]+ {
- zendlval->value.str.val = (char *) estrndup(yytext, yyleng);
- zendlval->value.str.len = yyleng;
- zendlval->type = IS_STRING;
+ if (!zend_copy_string_value(zendlval, yytext, yyleng, CG(literal_type) TSRMLS_CC)) {
+ return 0;
+ }
return T_ENCAPSED_AND_WHITESPACE;
}
@@ -1884,12 +2502,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
-<ST_SINGLE_QUOTE>['] {
- BEGIN(ST_IN_SCRIPTING);
- return '\'';
-}
-
-
<ST_DOUBLE_QUOTES,ST_BACKQUOTE,INITIAL,ST_IN_SCRIPTING,ST_LOOKING_FOR_PROPERTY><<EOF>> {
return 0;
}
@@ -1901,6 +2513,6 @@ NEWLINE ("\r"|"\n"|"\r\n")
-<ST_IN_SCRIPTING,INITIAL,ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_SINGLE_QUOTE,ST_HEREDOC>{ANY_CHAR} {
+<ST_IN_SCRIPTING,INITIAL,ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>{ANY_CHAR} {
zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
}
diff --git a/Zend/zend_multibyte.c b/Zend/zend_multibyte.c
index d7a444b32e..6dde60ad95 100644
--- a/Zend/zend_multibyte.c
+++ b/Zend/zend_multibyte.c
@@ -474,7 +474,7 @@ zend_encoding *zend_encoding_table[] = {
};
-
+#if 0
ZEND_API int zend_multibyte_set_script_encoding(char *encoding_list, int encoding_list_size TSRMLS_DC)
{
if (CG(script_encoding_list)) {
@@ -491,11 +491,14 @@ ZEND_API int zend_multibyte_set_script_encoding(char *encoding_list, int encodin
return 0;
}
-
+#endif
ZEND_API int zend_multibyte_set_internal_encoding(char *encoding_name, int encoding_name_size TSRMLS_DC)
{
- CG(internal_encoding) = zend_multibyte_fetch_encoding(encoding_name);
+ //CG(internal_encoding) = zend_multibyte_fetch_encoding(encoding_name);
+ //CG(internal_encoding) = zend_multibyte_fetch_encoding(ZEND_INTERNAL_ENCODING);
+ /* set this to NULL so that input filtering is done only when really necessary */
+ CG(internal_encoding) = NULL;
return 0;
}
@@ -523,17 +526,19 @@ ZEND_API int zend_multibyte_set_filter(zend_encoding *onetime_encoding TSRMLS_DC
if (!LANG_SCNG(internal_encoding) || LANG_SCNG(script_encoding) == LANG_SCNG(internal_encoding)) {
/* if encoding specfic filters exist, use them */
+ /*
if (LANG_SCNG(script_encoding)->input_filter && LANG_SCNG(script_encoding)->output_filter) {
LANG_SCNG(input_filter) = LANG_SCNG(script_encoding)->input_filter;
LANG_SCNG(output_filter) = LANG_SCNG(script_encoding)->output_filter;
return 0;
}
+ */
if (!LANG_SCNG(script_encoding)->compatible) {
/* and if not, work around w/ script_encoding -> utf-8 -> script_encoding conversion */
- LANG_SCNG(internal_encoding) = LANG_SCNG(script_encoding);
+ //LANG_SCNG(internal_encoding) = LANG_SCNG(script_encoding);
LANG_SCNG(input_filter) = zend_multibyte_script_encoding_filter;
- LANG_SCNG(output_filter) = zend_multibyte_internal_encoding_filter;
+ //LANG_SCNG(output_filter) = zend_multibyte_internal_encoding_filter;
return 0;
} else {
/* nothing to do in this case */
@@ -916,6 +921,7 @@ static char* zend_multibyte_assemble_encoding_list(zend_encoding **encoding_list
}
+#if 0
static int zend_multibyte_parse_encoding_list(const char *encoding_list, int encoding_list_size, zend_encoding ***result, int *result_size)
{
int n, size;
@@ -982,7 +988,7 @@ static int zend_multibyte_parse_encoding_list(const char *encoding_list, int enc
return 0;
}
-
+#endif
static zend_encoding* zend_multibyte_find_script_encoding(zend_encoding *onetime_encoding TSRMLS_DC)
{
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 6f385c1b51..795868f314 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -220,7 +220,7 @@ ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce
if (EG(scope) != ce
&& is_derived_class(ce, EG(scope))
&& EG(scope)
- && zend_hash_quick_find(&EG(scope)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS
+ && zend_u_hash_quick_find(&EG(scope)->properties_info, Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member)+1, h, (void **) &scope_property_info)==SUCCESS
&& scope_property_info->flags & ZEND_ACC_PRIVATE) {
return scope_property_info;
} else if (property_info) {
@@ -229,15 +229,15 @@ ZEND_API struct _zend_property_info *zend_get_property_info(zend_class_entry *ce
if (silent) {
return NULL;
}
- zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, Z_STRVAL_P(member));
+ zend_error(E_ERROR, "Cannot access %s property %v::$%s", zend_visibility_string(property_info->flags), ce->name, Z_STRVAL_P(member));
} else {
/* fall through, return property_info... */
}
} else {
EG(std_property_info).flags = ZEND_ACC_PUBLIC;
- EG(std_property_info).name = Z_STRVAL_P(member);
- EG(std_property_info).name_length = Z_STRLEN_P(member);
- EG(std_property_info).h = zend_get_hash_value(EG(std_property_info).name, EG(std_property_info).name_length+1);
+ EG(std_property_info).name = Z_UNIVAL_P(member);
+ EG(std_property_info).name_length = Z_UNILEN_P(member);
+ EG(std_property_info).h = zend_u_get_hash_value(Z_TYPE_P(member), EG(std_property_info).name, EG(std_property_info).name_length+1);
property_info = &EG(std_property_info);
}
return property_info;
@@ -249,14 +249,19 @@ ZEND_API int zend_check_property_access(zend_object *zobj, char *prop_info_name
zend_property_info *property_info;
char *class_name, *prop_name;
zval member;
+ zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
- zend_unmangle_property_name(prop_info_name, &class_name, &prop_name);
- ZVAL_STRING(&member, prop_name, 0);
+ zend_u_unmangle_property_name(utype, prop_info_name, &class_name, &prop_name);
+ if (utype == IS_UNICODE) {
+ ZVAL_UNICODE(&member, (UChar*)prop_name, 0);
+ } else {
+ ZVAL_STRING(&member, prop_name, 0);
+ }
property_info = zend_get_property_info(zobj->ce, &member, 1 TSRMLS_CC);
if (!property_info) {
return FAILURE;
}
- if (prop_info_name[0] == '\0' && prop_info_name[1] != '*') {
+ if (class_name && class_name[0] != '*') {
if (!(property_info->flags & ZEND_ACC_PRIVATE)) {
/* we we're looking for a private prop but found a non private one of the same name */
return FAILURE;
@@ -298,7 +303,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
/* make zend_get_property_info silent if we have getter - we may want to use it */
property_info = zend_get_property_info(zobj->ce, member, use_get TSRMLS_CC);
- if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
+ if (!property_info || zend_u_hash_quick_find(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
if (use_get) {
/* have getter - try with it! */
zobj->in_get = 1; /* prevent circular getting */
@@ -312,7 +317,7 @@ zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC)
}
} else {
if (!silent) {
- zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name, Z_STRVAL_P(member));
+ zend_error(E_NOTICE,"Undefined property: %v::$%s", zobj->ce->name, Z_STRVAL_P(member));
}
retval = &EG(uninitialized_zval_ptr);
}
@@ -338,18 +343,18 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
zobj = Z_OBJ_P(object);
use_set = (zobj->ce->__set && !zobj->in_set);
- if (member->type != IS_STRING) {
+ if (member->type != IS_STRING && member->type != IS_UNICODE) {
ALLOC_ZVAL(tmp_member);
*tmp_member = *member;
INIT_PZVAL(tmp_member);
zval_copy_ctor(tmp_member);
- convert_to_string(tmp_member);
+ convert_to_text(tmp_member);
member = tmp_member;
}
property_info = zend_get_property_info(zobj->ce, member, use_set TSRMLS_CC);
- if (property_info && zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS) {
+ if (property_info && zend_u_hash_quick_find(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS) {
if (*variable_ptr == value) {
/* if we already have this value there, we don't actually need to do anything */
setter_done = 1;
@@ -386,7 +391,7 @@ static void zend_std_write_property(zval *object, zval *member, zval *value TSRM
if (PZVAL_IS_REF(value)) {
SEPARATE_ZVAL(&value);
}
- zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void **) &foo);
+ zend_u_hash_quick_update(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void **) &foo);
}
if (tmp_member) {
zval_ptr_dtor(&tmp_member);
@@ -411,7 +416,7 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
if (!retval) {
if (!EG(exception)) {
- zend_error(E_ERROR, "Undefined offset for object of type %s used as array", ce->name);
+ zend_error(E_ERROR, "Undefined offset for object of type %v used as array", ce->name);
}
return 0;
}
@@ -421,7 +426,7 @@ zval *zend_std_read_dimension(zval *object, zval *offset, int type TSRMLS_DC)
return retval;
} else {
- zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
+ zend_error(E_ERROR, "Cannot use object of type %v as array", ce->name);
return 0;
}
}
@@ -440,7 +445,7 @@ static void zend_std_write_dimension(zval *object, zval *offset, zval *value TSR
zend_call_method_with_2_params(&object, ce, NULL, "offsetset", NULL, offset, value);
zval_ptr_dtor(&offset);
} else {
- zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
+ zend_error(E_ERROR, "Cannot use object of type %v as array", ce->name);
}
}
@@ -469,7 +474,7 @@ static int zend_std_has_dimension(zval *object, zval *offset, int check_empty TS
}
zval_ptr_dtor(&offset);
} else {
- zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
+ zend_error(E_ERROR, "Cannot use object of type %v as array", ce->name);
return 0;
}
return result;
@@ -485,10 +490,10 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC
zobj = Z_OBJ_P(object);
- if (member->type != IS_STRING) {
+ if (member->type != IS_STRING && member->type != IS_UNICODE) {
tmp_member = *member;
zval_copy_ctor(&tmp_member);
- convert_to_string(&tmp_member);
+ convert_to_text(&tmp_member);
member = &tmp_member;
}
@@ -498,7 +503,7 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC
property_info = zend_get_property_info(zobj->ce, member, 0 TSRMLS_CC);
- if (zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
+ if (zend_u_hash_quick_find(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) {
zval *new_zval;
if (!zobj->ce->__get && !zobj->ce->__set) {
@@ -507,7 +512,7 @@ static zval **zend_std_get_property_ptr_ptr(zval *object, zval *member TSRMLS_DC
/* zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member)); */
new_zval->refcount++;
- zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_u_hash_quick_update(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval);
} else {
/* we do have getter - fail and let it try again with usual get/set */
retval = NULL;
@@ -530,18 +535,18 @@ static void zend_std_unset_property(zval *object, zval *member TSRMLS_DC)
zobj = Z_OBJ_P(object);
use_unset = (zobj->ce->__unset && !zobj->in_unset);
- if (member->type != IS_STRING) {
+ if (member->type != IS_STRING && member->type != IS_UNICODE) {
ALLOC_ZVAL(tmp_member);
*tmp_member = *member;
INIT_PZVAL(tmp_member);
zval_copy_ctor(tmp_member);
- convert_to_string(tmp_member);
+ convert_to_text(tmp_member);
member = tmp_member;
}
property_info = zend_get_property_info(zobj->ce, member, 0 TSRMLS_CC);
- if (!property_info || zend_hash_del(zobj->properties, property_info->name, property_info->name_length+1) == FAILURE) {
+ if (!property_info || zend_u_hash_del(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1)) {
if (use_unset) {
/* have unseter - try with it! */
zobj->in_unset = 1; /* prevent circular unsetting */
@@ -565,7 +570,7 @@ static void zend_std_unset_dimension(zval *object, zval *offset TSRMLS_DC)
zend_call_method_with_1_params(&object, ce, NULL, "offsetunset", NULL, offset);
zval_ptr_dtor(&offset);
} else {
- zend_error(E_ERROR, "Cannot use object of type %s as array", ce->name);
+ zend_error(E_ERROR, "Cannot use object of type %v as array", ce->name);
}
}
@@ -589,7 +594,11 @@ ZEND_API void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS)
ALLOC_ZVAL(method_name_ptr);
INIT_PZVAL(method_name_ptr);
- ZVAL_STRING(method_name_ptr, func->function_name, 0); /* no dup - it's a copy */
+ if (UG(unicode)) {
+ ZVAL_UNICODE(method_name_ptr, (UChar*)func->function_name, 0); /* no dup - it's a copy */
+ } else {
+ ZVAL_STRING(method_name_ptr, func->function_name, 0); /* no dup - it's a copy */
+ }
/* __call handler is called with two arguments:
method name
@@ -640,7 +649,7 @@ static inline zend_function *zend_check_private_int(zend_function *fbc, zend_cla
ce = ce->parent;
while (ce) {
if (ce == EG(scope)) {
- if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &fbc)==SUCCESS
+ if (zend_u_hash_find(&ce->function_table, UG(unicode)?IS_UNICODE:IS_STRING, function_name_strval, function_name_strlen+1, (void **) &fbc)==SUCCESS
&& fbc->op_array.fn_flags & ZEND_ACC_PRIVATE
&& fbc->common.scope == EG(scope)) {
return fbc;
@@ -692,16 +701,19 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
{
zend_object *zobj;
zend_function *fbc;
+ unsigned int lc_method_name_len;
char *lc_method_name;
zval *object = *object_ptr;
- lc_method_name = do_alloca(method_len+1);
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
+
/* Create a zend_copy_str_tolower(dest, src, src_length); */
- zend_str_tolower_copy(lc_method_name, method_name, method_len);
+ lc_method_name = zend_u_str_case_fold(type, method_name, method_len, 1, &lc_method_name_len);
zobj = Z_OBJ_P(object);
- if (zend_hash_find(&zobj->ce->function_table, lc_method_name, method_len+1, (void **)&fbc) == FAILURE) {
- free_alloca(lc_method_name);
+ if (zend_u_hash_find(&zobj->ce->function_table, type, lc_method_name, lc_method_name_len+1, (void **)&fbc) == FAILURE) {
+ efree(lc_method_name);
if (zobj->ce->__call) {
zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function));
call_user_call->type = ZEND_INTERNAL_FUNCTION;
@@ -710,7 +722,11 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
call_user_call->num_args = 0;
call_user_call->scope = zobj->ce;
call_user_call->fn_flags = 0;
- call_user_call->function_name = estrndup(method_name, method_len);
+ if (UG(unicode)) {
+ call_user_call->function_name = (char*)eustrndup((UChar*)method_name, method_len);
+ } else {
+ call_user_call->function_name = estrndup(method_name, method_len);
+ }
call_user_call->pass_rest_by_reference = 0;
call_user_call->return_reference = ZEND_RETURN_VALUE;
@@ -728,7 +744,7 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
if (EG(scope) && fbc->op_array.fn_flags & ZEND_ACC_CHANGED) {
zend_function *priv_fbc;
- if (zend_hash_find(&EG(scope)->function_table, lc_method_name, method_len+1, (void **) &priv_fbc)==SUCCESS
+ if (zend_u_hash_find(&EG(scope)->function_table, type, lc_method_name, lc_method_name_len+1, (void **) &priv_fbc)==SUCCESS
&& priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
&& priv_fbc->common.scope == EG(scope)) {
fbc = priv_fbc;
@@ -741,18 +757,18 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
*/
updated_fbc = zend_check_private_int(fbc, object->value.obj.handlers->get_class_entry(object TSRMLS_CC), lc_method_name, method_len TSRMLS_CC);
if (!updated_fbc) {
- zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
+ zend_error(E_ERROR, "Call to %s method %v::%v() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
}
fbc = updated_fbc;
} else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(fbc->common.scope, EG(scope))) {
- zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
+ zend_error(E_ERROR, "Call to %s method %v::%v() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : "");
}
}
- free_alloca(lc_method_name);
+ efree(lc_method_name);
return fbc;
}
@@ -761,14 +777,16 @@ static union _zend_function *zend_std_get_method(zval **object_ptr, char *method
ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC)
{
zend_function *fbc;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
- if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &fbc)==FAILURE) {
+ if (zend_u_hash_find(&ce->function_table, type, function_name_strval, function_name_strlen+1, (void **) &fbc)==FAILURE) {
char *class_name = ce->name;
if (!class_name) {
- class_name = "";
+ class_name = EMPTY_STR;
}
- zend_error(E_ERROR, "Call to undefined method %s::%s()", class_name, function_name_strval);
+ zend_error(E_ERROR, "Call to undefined method %R::%R()", type, class_name, type, function_name_strval);
}
if (fbc->op_array.fn_flags & ZEND_ACC_PUBLIC) {
/* No further checks necessary, most common case */
@@ -779,14 +797,14 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, char *f
*/
updated_fbc = zend_check_private_int(fbc, EG(scope), function_name_strval, function_name_strlen TSRMLS_CC);
if (!updated_fbc) {
- zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : "");
+ zend_error(E_ERROR, "Call to %s method %v::%v() from context '%v'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
fbc = updated_fbc;
} else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(EG(scope), fbc->common.scope)) {
- zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : "");
+ zend_error(E_ERROR, "Call to %s method %v::%v() from context '%v'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
@@ -800,8 +818,9 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert
zend_class_entry *tmp_ce = ce;
zend_property_info *property_info;
zend_property_info std_property_info;
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
- if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) {
+ if (zend_u_hash_find(&ce->properties_info, type, property_name, property_name_len+1, (void **) &property_info)==FAILURE) {
std_property_info.flags = ZEND_ACC_PUBLIC;
std_property_info.name = property_name;
std_property_info.name_length = property_name_len;
@@ -810,23 +829,23 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert
}
#if DEBUG_OBJECT_HANDLERS
- zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
+ zend_printf("Access type for %v::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags));
#endif
if (!zend_verify_property_access(property_info, ce TSRMLS_CC)) {
if (!silent) {
- zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
+ zend_error(E_ERROR, "Cannot access %s property %v::$%s", zend_visibility_string(property_info->flags), ce->name, property_name);
}
return NULL;
}
- zend_hash_quick_find(tmp_ce->static_members, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval);
+ zend_u_hash_quick_find(tmp_ce->static_members, type, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval);
if (!retval) {
if (silent) {
return NULL;
} else {
- zend_error(E_ERROR, "Access to undeclared static property: %s::$%s", ce->name, property_name);
+ zend_error(E_ERROR, "Access to undeclared static property: %v::$%s", ce->name, property_name);
}
}
@@ -837,7 +856,7 @@ ZEND_API zval **zend_std_get_static_property(zend_class_entry *ce, char *propert
ZEND_API zend_bool zend_std_unset_static_property(zend_class_entry *ce, char *property_name, int property_name_len TSRMLS_DC)
{
- zend_error(E_ERROR, "Attempt to unset static property %s::$%s", ce->name, property_name);
+ zend_error(E_ERROR, "Attempt to unset static property %v::$%s", ce->name, property_name);
return 0;
}
@@ -854,13 +873,13 @@ static union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (object->value.obj.handlers->get_class_entry(object TSRMLS_CC) != EG(scope)) {
- zend_error(E_ERROR, "Call to private %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope) ? EG(scope)->name : "");
+ zend_error(E_ERROR, "Call to private %v::%v() from context '%v'", constructor->common.scope->name, constructor->common.function_name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((constructor->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(constructor->common.scope, EG(scope))) {
- zend_error(E_ERROR, "Call to protected %s::%s() from context '%s'", constructor->common.scope->name, constructor->common.function_name, EG(scope) ? EG(scope)->name : "");
+ zend_error(E_ERROR, "Call to protected %v::%v() from context '%v'", constructor->common.scope->name, constructor->common.function_name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@@ -897,12 +916,12 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists
zobj = Z_OBJ_P(object);
use_isset = (zobj->ce->__isset && !zobj->in_isset);
- if (member->type != IS_STRING) {
+ if (member->type != IS_STRING && member->type != IS_UNICODE) {
ALLOC_ZVAL(tmp_member);
*tmp_member = *member;
INIT_PZVAL(tmp_member);
zval_copy_ctor(tmp_member);
- convert_to_string(tmp_member);
+ convert_to_text(tmp_member);
member = tmp_member;
}
@@ -912,7 +931,7 @@ static int zend_std_has_property(zval *object, zval *member, int has_set_exists
property_info = zend_get_property_info(zobj->ce, member, 1 TSRMLS_CC);
- if (!property_info || zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE) {
+ if (!property_info || zend_u_hash_quick_find(zobj->properties, Z_TYPE_P(member), property_info->name, property_info->name_length+1, property_info->h, (void **) &value) == FAILURE) {
result = 0;
if (use_isset && (has_set_exists != 2)) {
zval *rv;
@@ -979,7 +998,11 @@ int zend_std_object_get_class_name(zval *object, char **class_name, zend_uint *c
}
*class_name_len = ce->name_length;
- *class_name = estrndup(ce->name, ce->name_length);
+ if (UG(unicode)) {
+ *class_name = (char*)eustrndup((UChar*)ce->name, ce->name_length);
+ } else {
+ *class_name = estrndup(ce->name, ce->name_length);
+ }
return SUCCESS;
}
@@ -989,14 +1012,22 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty
switch (type) {
case IS_STRING:
+ case IS_UNICODE:
if (!zend_hash_exists(&Z_OBJCE_P(readobj)->function_table, "__tostring", sizeof("__tostring"))) {
return FAILURE;
}
- ZVAL_STRING(&fname, "__tostring", 0);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(&fname, USTR_MAKE("__tostring"), 0);
+ } else {
+ ZVAL_STRING(&fname, "__tostring", 0);
+ }
if (call_user_function_ex(NULL, &readobj, &fname, &retval, 0, NULL, 0, NULL TSRMLS_CC) == SUCCESS) {
+ if (UG(unicode)) {
+ zval_dtor(&fname);
+ }
if (retval) {
- if (Z_TYPE_P(retval) != IS_STRING) {
- zend_error(E_ERROR, "Method %s::__toString() must return a string value", Z_OBJCE_P(readobj)->name);
+ if (Z_TYPE_P(retval) != IS_STRING && Z_TYPE_P(retval) != IS_UNICODE) {
+ zend_error(E_ERROR, "Method %v::__toString() must return a string value", Z_OBJCE_P(readobj)->name);
}
} else {
MAKE_STD_ZVAL(retval);
@@ -1008,6 +1039,9 @@ ZEND_API int zend_std_cast_object_tostring(zval *readobj, zval *writeobj, int ty
zval_ptr_dtor(&retval);
return SUCCESS;
}
+ if (UG(unicode)) {
+ zval_dtor(&fname);
+ }
break;
default:
break;
diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c
index 9b5b854220..83f0d809b5 100644
--- a/Zend/zend_objects.c
+++ b/Zend/zend_objects.c
@@ -42,9 +42,9 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
zend_class_entry *ce = object->ce;
zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
- "Call to private %s::__destruct() from context '%s'%s",
+ "Call to private %v::__destruct() from context '%v'%s",
ce->name,
- EG(scope) ? EG(scope)->name : "",
+ EG(scope) ? EG(scope)->name : EMPTY_STR,
EG(in_execution) ? "" : " during shutdown ignored");
return;
}
@@ -55,9 +55,9 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
zend_class_entry *ce = object->ce;
zend_error(EG(in_execution) ? E_ERROR : E_WARNING,
- "Call to protected %s::__destruct() from context '%s'%s",
+ "Call to protected %v::__destruct() from context '%v'%s",
ce->name,
- EG(scope) ? EG(scope)->name : "",
+ EG(scope) ? EG(scope)->name : EMPTY_STR,
EG(in_execution) ? "" : " during shutdown ignored");
return;
}
@@ -78,7 +78,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handl
zend_call_method_with_0_params(&obj, object->ce, &object->ce->destructor, ZEND_DESTRUCTOR_FUNC_NAME, NULL);
if (old_exception) {
if (EG(exception)) {
- zend_error(E_ERROR, "Ignoring exception from %s::__destruct() while an exception is already active", object->ce->name);
+ zend_error(E_ERROR, "Ignoring exception from %v::__destruct() while an exception is already active", object->ce->name);
zval_ptr_dtor(&EG(exception));
}
EG(exception) = old_exception;
@@ -167,7 +167,7 @@ ZEND_API zend_object_value zend_objects_clone_obj(zval *zobject TSRMLS_DC)
new_obj_val = zend_objects_new(&new_object, old_object->ce TSRMLS_CC);
ALLOC_HASHTABLE(new_object->properties);
- zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_objects_clone_members(new_object, new_obj_val, old_object, handle TSRMLS_CC);
diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c
index a13181c5cc..ab62dcfe48 100644
--- a/Zend/zend_objects_API.c
+++ b/Zend/zend_objects_API.c
@@ -186,7 +186,7 @@ ZEND_API zend_object_value zend_objects_store_clone_obj(zval *zobject TSRMLS_DC)
obj = &EG(objects_store).object_buckets[handle].bucket.obj;
if (obj->clone == NULL) {
- zend_error(E_CORE_ERROR, "Trying to clone uncloneable object of class %s", Z_OBJCE_P(zobject)->name);
+ zend_error(E_CORE_ERROR, "Trying to clone uncloneable object of class %v", Z_OBJCE_P(zobject)->name);
}
obj->clone(obj->object, &new_object TSRMLS_CC);
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 37bb6b604a..56823cccdf 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -386,9 +386,10 @@ int pass_two(zend_op_array *op_array TSRMLS_DC)
int print_class(zend_class_entry *class_entry TSRMLS_DC)
{
- printf("Class %s:\n", class_entry->name);
+ /* UTODO: fix these to use spprintf() */
+ printf("Class %v:\n", class_entry->name);
zend_hash_apply(&class_entry->function_table, (apply_func_t) pass_two TSRMLS_CC);
- printf("End of class %s.\n\n", class_entry->name);
+ printf("End of class %v.\n\n", class_entry->name);
return 0;
}
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 509f9e2315..bb09fb3bb9 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -31,6 +31,8 @@
#include "zend_multiply.h"
#include "zend_strtod.h"
+#include "unicode/uchar.h"
+
#define LONG_SIGN_MASK (1L << (8*sizeof(long)-1))
ZEND_API int zend_atoi(const char *str, int str_len)
@@ -111,6 +113,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
{
switch (op->type) {
case IS_STRING:
+ case IS_BINARY:
{
char *strval;
@@ -127,6 +130,24 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
STR_FREE(strval);
break;
}
+ case IS_UNICODE:
+ {
+ UChar *strval;
+
+ strval = op->value.ustr.val;
+ switch ((op->type=is_numeric_unicode(strval, op->value.ustr.len, &op->value.lval, &op->value.dval, 1))) {
+ case IS_DOUBLE:
+ case IS_LONG:
+ break;
+ default:
+ op->value.lval = zend_u_strtol(op->value.ustr.val, NULL, 10);
+ op->type = IS_LONG;
+ break;
+ }
+ USTR_FREE(strval);
+ break;
+ }
+ break;
case IS_BOOL:
op->type = IS_LONG;
break;
@@ -152,6 +173,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
} else { \
switch ((op)->type) { \
case IS_STRING: \
+ case IS_BINARY: \
{ \
switch (((holder).type=is_numeric_string((op)->value.str.val, (op)->value.str.len, &(holder).value.lval, &(holder).value.dval, 1))) { \
case IS_DOUBLE: \
@@ -165,6 +187,20 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
(op) = &(holder); \
break; \
} \
+ case IS_UNICODE: \
+ { \
+ switch (((holder).type=is_numeric_unicode((op)->value.ustr.val, (op)->value.ustr.len, &(holder).value.lval, &(holder).value.dval, 1))) { \
+ case IS_DOUBLE: \
+ case IS_LONG: \
+ break; \
+ default: \
+ (holder).value.lval = zend_u_strtol((op)->value.ustr.val, NULL, 10); \
+ (holder).type = IS_LONG; \
+ break; \
+ } \
+ (op) = &(holder); \
+ break; \
+ } \
case IS_BOOL: \
case IS_RESOURCE: \
(holder).value.lval = (op)->value.lval; \
@@ -202,8 +238,12 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
DVAL_TO_LVAL((op)->value.dval, (holder).value.lval); \
break; \
case IS_STRING: \
+ case IS_BINARY: \
(holder).value.lval = strtol((op)->value.str.val, NULL, 10); \
break; \
+ case IS_UNICODE: \
+ (holder).value.lval = zend_u_strtol((op)->value.ustr.val, NULL, 10); \
+ break; \
case IS_ARRAY: \
(holder).value.lval = (zend_hash_num_elements((op)->value.ht)?1:0); \
break; \
@@ -242,6 +282,7 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
(holder).value.lval = ((op)->value.dval ? 1 : 0); \
break; \
case IS_STRING: \
+ case IS_BINARY: \
if ((op)->value.str.len == 0 \
|| ((op)->value.str.len==1 && (op)->value.str.val[0]=='0')) { \
(holder).value.lval = 0; \
@@ -249,6 +290,15 @@ ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC)
(holder).value.lval = 1; \
} \
break; \
+ case IS_UNICODE: \
+ if ((op)->value.ustr.len == 0 \
+ || ((op)->value.ustr.len==1 && \
+ ((op)->value.ustr.val[0]=='0'))) { \
+ (holder).value.lval = 0; \
+ } else { \
+ (holder).value.lval = 1; \
+ } \
+ break; \
case IS_ARRAY: \
(holder).value.lval = (zend_hash_num_elements((op)->value.ht)?1:0); \
break; \
@@ -293,7 +343,6 @@ ZEND_API void convert_to_long(zval *op)
ZEND_API void convert_to_long_base(zval *op, int base)
{
- char *strval;
long tmp;
switch (op->type) {
@@ -313,9 +362,19 @@ ZEND_API void convert_to_long_base(zval *op, int base)
DVAL_TO_LVAL(op->value.dval, op->value.lval);
break;
case IS_STRING:
- strval = op->value.str.val;
- op->value.lval = strtol(strval, NULL, base);
- STR_FREE(strval);
+ case IS_BINARY:
+ {
+ char *strval = op->value.str.val;
+ op->value.lval = strtol(strval, NULL, base);
+ STR_FREE(strval);
+ }
+ break;
+ case IS_UNICODE:
+ {
+ UChar *strval = op->value.ustr.val;
+ op->value.lval = zend_u_strtol(strval, NULL, base);
+ USTR_FREE(strval);
+ }
break;
case IS_ARRAY:
tmp = (zend_hash_num_elements(op->value.ht)?1:0);
@@ -358,7 +417,6 @@ ZEND_API void convert_to_long_base(zval *op, int base)
ZEND_API void convert_to_double(zval *op)
{
- char *strval;
double tmp;
switch (op->type) {
@@ -378,10 +436,21 @@ ZEND_API void convert_to_double(zval *op)
case IS_DOUBLE:
break;
case IS_STRING:
- strval = op->value.str.val;
+ case IS_BINARY:
+ {
+ char *strval = op->value.str.val;
- op->value.dval = zend_strtod(strval, NULL);
- STR_FREE(strval);
+ op->value.dval = zend_strtod(strval, NULL);
+ STR_FREE(strval);
+ }
+ break;
+ case IS_UNICODE:
+ {
+ UChar *strval = op->value.ustr.val;
+
+ op->value.dval = zend_u_strtod(strval, NULL);
+ USTR_FREE(strval);
+ }
break;
case IS_ARRAY:
tmp = (zend_hash_num_elements(op->value.ht)?1:0);
@@ -405,7 +474,7 @@ ZEND_API void convert_to_double(zval *op)
retval = (zend_hash_num_elements(ht)?1.0:0.0);
}
} else {
- zend_error(E_NOTICE, "Object of class %s could not be converted to double", Z_OBJCE_P(op)->name);
+ zend_error(E_NOTICE, "Object of class %v could not be converted to double", Z_OBJCE_P(op)->name);
}
zval_dtor(op);
@@ -440,7 +509,6 @@ ZEND_API void convert_to_null(zval *op)
ZEND_API void convert_to_boolean(zval *op)
{
- char *strval;
int tmp;
switch (op->type) {
@@ -462,15 +530,32 @@ ZEND_API void convert_to_boolean(zval *op)
op->value.lval = (op->value.dval ? 1 : 0);
break;
case IS_STRING:
- strval = op->value.str.val;
+ case IS_BINARY:
+ {
+ char *strval = op->value.str.val;
- if (op->value.str.len == 0
- || (op->value.str.len==1 && op->value.str.val[0]=='0')) {
- op->value.lval = 0;
- } else {
- op->value.lval = 1;
+ if (op->value.str.len == 0
+ || (op->value.str.len==1 && op->value.str.val[0]=='0')) {
+ op->value.lval = 0;
+ } else {
+ op->value.lval = 1;
+ }
+ STR_FREE(strval);
+ }
+ break;
+ case IS_UNICODE:
+ {
+ UChar *strval = op->value.ustr.val;
+
+ if (op->value.ustr.len == 0
+ || (op->value.ustr.len==1 &&
+ (op->value.ustr.val[0]=='0'))) {
+ op->value.lval = 0;
+ } else {
+ op->value.lval = 1;
+ }
+ USTR_FREE(strval);
}
- STR_FREE(strval);
break;
case IS_ARRAY:
tmp = (zend_hash_num_elements(op->value.ht)?1:0);
@@ -507,8 +592,95 @@ ZEND_API void convert_to_boolean(zval *op)
op->type = IS_BOOL;
}
+ZEND_API void _convert_to_unicode(zval *op TSRMLS_DC ZEND_FILE_LINE_DC)
+{
+ switch (op->type) {
+ case IS_NULL:
+ op->value.ustr.val = USTR_MAKE_REL("");
+ op->value.ustr.len = 0;
+ break;
+ case IS_UNICODE:
+ break;
+ case IS_STRING:
+ zval_string_to_unicode(op TSRMLS_CC);
+ break;
+ case IS_BINARY:
+ zend_error(E_ERROR, "Cannot convert binary type to Unicode type");
+ return;
+ case IS_BOOL:
+ if (op->value.lval) {
+ op->value.ustr.val = USTR_MAKE_REL("1");
+ op->value.ustr.len = 1;
+ } else {
+ op->value.ustr.val = USTR_MAKE_REL("");
+ op->value.ustr.len = 0;
+ }
+ break;
+ case IS_RESOURCE: {
+ long tmp = op->value.lval;
+ TSRMLS_FETCH();
+
+ zend_list_delete(op->value.lval);
+ op->value.ustr.val = eumalloc_rel(sizeof("Resource id #")-1 + MAX_LENGTH_OF_LONG + 1);
+ op->value.ustr.len = u_sprintf(op->value.ustr.val, "Resource id #%ld", tmp);
+ break;
+ }
+ case IS_LONG: {
+ int32_t capacity = MAX_LENGTH_OF_LONG + 1;
+ long lval = op->value.lval;
+
+ op->value.ustr.val = eumalloc_rel(capacity);
+ op->value.ustr.len = u_sprintf(op->value.ustr.val, "%ld", lval);
+ break;
+ }
+ case IS_DOUBLE: {
+ int32_t capacity;
+ double dval = op->value.dval;
+ TSRMLS_FETCH();
+
+ capacity = MAX_LENGTH_OF_DOUBLE + EG(precision) + 1;
+ op->value.ustr.val = eumalloc_rel(capacity);
+ op->value.ustr.len = u_sprintf(op->value.ustr.val, "%.*G", (int) EG(precision), dval);
+ break;
+ }
+ case IS_ARRAY:
+ zend_error(E_NOTICE, "Array to string conversion");
+ zval_dtor(op);
+ op->value.ustr.val = USTR_MAKE_REL("Array");
+ op->value.ustr.len = sizeof("Array")-1;
+ break;
+ case IS_OBJECT: {
+ TSRMLS_FETCH();
+
+ convert_object_to_type(op, IS_UNICODE, convert_to_unicode);
+
+ if (op->type == IS_UNICODE) {
+ return;
+ }
+
+ zend_error(E_NOTICE, "Object of class %v to string conversion", Z_OBJCE_P(op)->name);
+ zval_dtor(op);
+ op->value.ustr.val = USTR_MAKE_REL("Object");
+ op->value.ustr.len = sizeof("Object")-1;
+ break;
+ }
+ default:
+ zval_dtor(op);
+ ZVAL_BOOL(op, 0);
+ break;
+ }
+ op->type = IS_UNICODE;
+}
+
+
ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
{
+ TSRMLS_FETCH();
+ _convert_to_string_with_converter(op, ZEND_U_CONVERTER(UG(runtime_encoding_conv)) TSRMLS_CC ZEND_FILE_LINE_CC);
+}
+
+ZEND_API void _convert_to_string_with_converter(zval *op, UConverter *conv TSRMLS_DC ZEND_FILE_LINE_DC)
+{
long lval;
double dval;
@@ -518,6 +690,26 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
op->value.str.len = 0;
break;
case IS_STRING:
+ if (conv == ZEND_U_CONVERTER(UG(runtime_encoding_conv))) {
+ break;
+ } else {
+ char *s;
+ int32_t s_len;
+ UErrorCode status = U_ZERO_ERROR;
+ s = op->value.str.val;
+ s_len = op->value.str.len;
+ zend_convert_encodings(conv, ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &op->value.str.val, &op->value.str.len, s, s_len, &status);
+ efree(s);
+ if (U_FAILURE(status)) {
+ zend_error(E_WARNING, "Error converting string for printing");
+ }
+ }
+ break;
+ case IS_BINARY:
+ zend_error(E_ERROR, "Cannot convert binary type to string type");
+ return;
+ case IS_UNICODE:
+ zval_unicode_to_string(op, conv TSRMLS_CC);
break;
case IS_BOOL:
if (op->value.lval) {
@@ -566,7 +758,7 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
return;
}
- zend_error(E_NOTICE, "Object of class %s to string conversion", Z_OBJCE_P(op)->name);
+ zend_error(E_NOTICE, "Object of class %v to string conversion", Z_OBJCE_P(op)->name);
zval_dtor(op);
op->value.str.val = estrndup_rel("Object", sizeof("Object")-1);
op->value.str.len = sizeof("Object")-1;
@@ -580,8 +772,35 @@ ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC)
op->type = IS_STRING;
}
+ZEND_API void convert_to_binary(zval *op)
+{
+ switch (op->type) {
+ case IS_BINARY:
+ break;
+ case IS_OBJECT: {
+ TSRMLS_FETCH();
+
+ convert_object_to_type(op, IS_BINARY, convert_to_binary);
-static void convert_scalar_to_array(zval *op, int type)
+ if (op->type == IS_BINARY) {
+ return;
+ }
+
+ zend_error(E_NOTICE, "Object of class %v to binary conversion", Z_OBJCE_P(op)->name);
+ zval_dtor(op);
+ op->value.str.val = estrndup("Object", sizeof("Object")-1);
+ op->value.str.len = sizeof("Object")-1;
+ break;
+ }
+ default:
+ convert_to_string(op);
+ break;
+ }
+ op->type = IS_BINARY;
+}
+
+
+static void convert_scalar_to_array(zval *op, int type TSRMLS_DC)
{
zval *entry;
@@ -592,7 +811,7 @@ static void convert_scalar_to_array(zval *op, int type)
switch (type) {
case IS_ARRAY:
ALLOC_HASHTABLE(op->value.ht);
- zend_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_hash_index_update(op->value.ht, 0, (void *) &entry, sizeof(zval *), NULL);
op->type = IS_ARRAY;
break;
@@ -624,7 +843,7 @@ ZEND_API void convert_to_array(zval *op)
HashTable *ht;
ALLOC_HASHTABLE(ht);
- zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
if (Z_OBJ_HT_P(op)->get_properties) {
HashTable *obj_ht = Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC);
if(obj_ht) {
@@ -644,11 +863,11 @@ ZEND_API void convert_to_array(zval *op)
return;
case IS_NULL:
ALLOC_HASHTABLE(op->value.ht);
- zend_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(op->value.ht, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
op->type = IS_ARRAY;
break;
default:
- convert_scalar_to_array(op, IS_ARRAY);
+ convert_scalar_to_array(op, IS_ARRAY TSRMLS_CC);
break;
}
}
@@ -656,12 +875,10 @@ ZEND_API void convert_to_array(zval *op)
ZEND_API void convert_to_object(zval *op)
{
+ TSRMLS_FETCH();
switch (op->type) {
case IS_ARRAY:
{
- /* OBJECTS_OPTIMIZE */
- TSRMLS_FETCH();
-
object_and_properties_init(op, zend_standard_class_def, op->value.ht);
return;
break;
@@ -677,7 +894,7 @@ ZEND_API void convert_to_object(zval *op)
break;
}
default:
- convert_scalar_to_array(op, IS_OBJECT);
+ convert_scalar_to_array(op, IS_OBJECT TSRMLS_CC);
break;
}
}
@@ -957,10 +1174,10 @@ ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC)
result->type = IS_LONG;
return SUCCESS;
}
- if (op1->type == IS_STRING) {
+ if (op1->type == IS_STRING || op1->type == IS_BINARY) {
int i;
- result->type = IS_STRING;
+ result->type = op1->type;
result->value.str.val = estrndup(op1->value.str.val, op1->value.str.len);
result->value.str.len = op1->value.str.len;
for (i = 0; i < op1->value.str.len; i++) {
@@ -976,8 +1193,9 @@ ZEND_API int bitwise_not_function(zval *result, zval *op1 TSRMLS_DC)
ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
zval op1_copy, op2_copy;
-
- if (op1->type == IS_STRING && op2->type == IS_STRING) {
+
+ if ((op1->type == IS_STRING && op2->type == IS_STRING) ||
+ (op1->type == IS_BINARY && op2->type == IS_BINARY)) {
zval *longer, *shorter;
char *result_str;
int i, result_len;
@@ -990,7 +1208,7 @@ ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
shorter = op1;
}
- result->type = IS_STRING;
+ result->type = op1->type;
result_len = longer->value.str.len;
result_str = estrndup(longer->value.str.val, longer->value.str.len);
for (i = 0; i < shorter->value.str.len; i++) {
@@ -1003,6 +1221,10 @@ ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
result->value.str.len = result_len;
return SUCCESS;
}
+ if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
+ zend_error(E_ERROR, "Unsupported operand types");
+ return FAILURE;
+ }
zendi_convert_to_long(op1, op1_copy, result);
zendi_convert_to_long(op2, op2_copy, result);
@@ -1016,7 +1238,8 @@ ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
zval op1_copy, op2_copy;
- if (op1->type == IS_STRING && op2->type == IS_STRING) {
+ if ((op1->type == IS_STRING && op2->type == IS_STRING) ||
+ (op1->type == IS_BINARY && op2->type == IS_BINARY)) {
zval *longer, *shorter;
char *result_str;
int i, result_len;
@@ -1029,7 +1252,7 @@ ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
shorter = op1;
}
- result->type = IS_STRING;
+ result->type = op1->type;
result_len = shorter->value.str.len;
result_str = estrndup(shorter->value.str.val, shorter->value.str.len);
for (i = 0; i < shorter->value.str.len; i++) {
@@ -1043,6 +1266,10 @@ ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
return SUCCESS;
}
+ if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
+ zend_error(E_ERROR, "Unsupported operand types");
+ return FAILURE;
+ }
zendi_convert_to_long(op1, op1_copy, result);
zendi_convert_to_long(op2, op2_copy, result);
@@ -1057,7 +1284,8 @@ ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
zval op1_copy, op2_copy;
- if (op1->type == IS_STRING && op2->type == IS_STRING) {
+ if ((op1->type == IS_STRING && op2->type == IS_STRING) ||
+ (op1->type == IS_BINARY && op2->type == IS_BINARY)) {
zval *longer, *shorter;
char *result_str;
int i, result_len;
@@ -1070,7 +1298,7 @@ ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
shorter = op1;
}
- result->type = IS_STRING;
+ result->type = op1->type;
result_len = shorter->value.str.len;
result_str = estrndup(shorter->value.str.val, shorter->value.str.len);
for (i = 0; i < shorter->value.str.len; i++) {
@@ -1084,6 +1312,11 @@ ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
return SUCCESS;
}
+ if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
+ zend_error(E_ERROR, "Unsupported operand types");
+ return FAILURE;
+ }
+
zendi_convert_to_long(op1, op1_copy, result);
zendi_convert_to_long(op2, op2_copy, result);
@@ -1097,6 +1330,11 @@ ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
zval op1_copy, op2_copy;
+ if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
+ zend_error(E_ERROR, "Unsupported operand types");
+ return FAILURE;
+ }
+
zendi_convert_to_long(op1, op1_copy, result);
zendi_convert_to_long(op2, op2_copy, result);
result->value.lval = op1->value.lval << op2->value.lval;
@@ -1109,6 +1347,11 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
zval op1_copy, op2_copy;
+ if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
+ zend_error(E_ERROR, "Unsupported operand types");
+ return FAILURE;
+ }
+
zendi_convert_to_long(op1, op1_copy, result);
zendi_convert_to_long(op2, op2_copy, result);
result->value.lval = op1->value.lval >> op2->value.lval;
@@ -1117,15 +1360,31 @@ ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
}
-
/* must support result==op1 */
ZEND_API int add_char_to_string(zval *result, zval *op1, zval *op2)
{
- result->value.str.len = op1->value.str.len + 1;
- result->value.str.val = (char *) erealloc(op1->value.str.val, result->value.str.len+1);
- result->value.str.val[result->value.str.len - 1] = (char) op2->value.lval;
- result->value.str.val[result->value.str.len] = 0;
- result->type = IS_STRING;
+ if (op1->type == IS_UNICODE) {
+ UChar32 codepoint = (UChar32) op2->value.lval;
+
+ if (U_IS_BMP(codepoint)) {
+ result->value.ustr.len = op1->value.ustr.len + 1;
+ result->value.ustr.val = eurealloc(op1->value.ustr.val, result->value.ustr.len+1);
+ result->value.ustr.val[result->value.ustr.len - 1] = (UChar) op2->value.lval;
+ } else {
+ result->value.ustr.len = op1->value.ustr.len + 2;
+ result->value.ustr.val = eurealloc(op1->value.ustr.val, result->value.ustr.len+1);
+ result->value.ustr.val[result->value.ustr.len - 2] = (UChar) U16_LEAD(codepoint);
+ result->value.ustr.val[result->value.ustr.len - 1] = (UChar) U16_TRAIL(codepoint);
+ }
+ result->value.ustr.val[result->value.ustr.len] = 0;
+ result->type = IS_UNICODE;
+ } else {
+ result->value.str.len = op1->value.str.len + 1;
+ result->value.str.val = (char *) erealloc(op1->value.str.val, result->value.str.len+1);
+ result->value.str.val[result->value.str.len - 1] = (char) op2->value.lval;
+ result->value.str.val[result->value.str.len] = 0;
+ result->type = op1->type;
+ }
return SUCCESS;
}
@@ -1133,13 +1392,25 @@ ZEND_API int add_char_to_string(zval *result, zval *op1, zval *op2)
/* must support result==op1 */
ZEND_API int add_string_to_string(zval *result, zval *op1, zval *op2)
{
- int length = op1->value.str.len + op2->value.str.len;
+ assert(op1->type == op2->type);
- result->value.str.val = (char *) erealloc(op1->value.str.val, length+1);
- memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len);
- result->value.str.val[length] = 0;
- result->value.str.len = length;
- result->type = IS_STRING;
+ if (op1->type == IS_UNICODE) {
+ int32_t length = op1->value.ustr.len + op2->value.ustr.len;
+
+ result->value.ustr.val = eurealloc(op1->value.ustr.val, length+1);
+ u_memcpy(result->value.ustr.val+op1->value.ustr.len, op2->value.ustr.val, op2->value.ustr.len);
+ result->value.ustr.val[length] = 0;
+ result->value.ustr.len = length;
+ result->type = IS_UNICODE;
+ } else {
+ int length = op1->value.str.len + op2->value.str.len;
+
+ result->value.str.val = (char *) erealloc(op1->value.str.val, length+1);
+ memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len);
+ result->value.str.val[length] = 0;
+ result->value.str.len = length;
+ result->type = op1->type;
+ }
return SUCCESS;
}
@@ -1148,10 +1419,21 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
{
zval op1_copy, op2_copy;
int use_copy1, use_copy2;
-
-
- zend_make_printable_zval(op1, &op1_copy, &use_copy1);
- zend_make_printable_zval(op2, &op2_copy, &use_copy2);
+ zend_uchar result_type;
+
+ if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
+ zend_make_unicode_zval(op1, &op1_copy, &use_copy1);
+ zend_make_unicode_zval(op2, &op2_copy, &use_copy2);
+ result_type = IS_UNICODE;
+ } else if (op1->type == IS_BINARY && op2->type == IS_BINARY) {
+ result_type = IS_BINARY;
+ /* no conversion necessary */
+ use_copy1 = use_copy2 = 0;
+ } else {
+ result_type = IS_STRING;
+ zend_make_string_zval(op1, &op1_copy, &use_copy1);
+ zend_make_string_zval(op2, &op2_copy, &use_copy2);
+ }
if (use_copy1) {
/* We have created a converted copy of op1. Therefore, op1 won't become the result so
@@ -1166,20 +1448,23 @@ ZEND_API int concat_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
op2 = &op2_copy;
}
if (result==op1) { /* special case, perform operations on result */
- uint res_len = op1->value.str.len + op2->value.str.len;
-
- result->value.str.val = erealloc(result->value.str.val, res_len+1);
-
- memcpy(result->value.str.val+result->value.str.len, op2->value.str.val, op2->value.str.len);
- result->value.str.val[res_len]=0;
- result->value.str.len = res_len;
+ add_string_to_string(result, op1, op2);
} else {
- result->value.str.len = op1->value.str.len + op2->value.str.len;
- result->value.str.val = (char *) emalloc(result->value.str.len + 1);
- memcpy(result->value.str.val, op1->value.str.val, op1->value.str.len);
- memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len);
- result->value.str.val[result->value.str.len] = 0;
- result->type = IS_STRING;
+ if (result_type == IS_UNICODE) {
+ result->value.ustr.len = op1->value.ustr.len + op2->value.ustr.len;
+ result->value.ustr.val = eumalloc(result->value.ustr.len + 1);
+ u_memcpy(result->value.ustr.val, op1->value.ustr.val, op1->value.ustr.len);
+ u_memcpy(result->value.ustr.val+op1->value.ustr.len, op2->value.ustr.val, op2->value.ustr.len);
+ result->value.ustr.val[result->value.ustr.len] = 0;
+ result->type = IS_UNICODE;
+ } else {
+ result->value.str.len = op1->value.str.len + op2->value.str.len;
+ result->value.str.val = (char *) emalloc(result->value.str.len + 1);
+ memcpy(result->value.str.val, op1->value.str.val, op1->value.str.len);
+ memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len);
+ result->value.str.val[result->value.str.len] = 0;
+ result->type = result_type;
+ }
}
if (use_copy1) {
zval_dtor(op1);
@@ -1314,8 +1599,18 @@ ZEND_API int compare_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
}
}
- if (op1->type == IS_STRING && op2->type == IS_STRING) {
- zendi_smart_strcmp(result, op1, op2);
+ if ((op1->type == IS_UNICODE || op1->type == IS_STRING || op1->type == IS_BINARY) &&
+ (op2->type == IS_UNICODE || op2->type == IS_STRING || op2->type == IS_BINARY)) {
+
+ if (op1->type == IS_UNICODE || op2->type == IS_UNICODE) {
+ zendi_u_smart_strcmp(result, op1, op2);
+ } else if (op1->type == IS_STRING || op2->type == IS_STRING) {
+ zendi_smart_strcmp(result, op1, op2);
+ } else {
+ result->value.lval = zend_binary_zval_strcmp(op1, op2);
+ result->value.lval = ZEND_NORMALIZE_BOOL(result->value.lval);
+ result->type = IS_LONG;
+ }
COMPARE_RETURN_AND_FREE(SUCCESS);
}
@@ -1421,6 +1716,7 @@ ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
result->value.lval = (op1->value.dval == op2->value.dval);
break;
case IS_STRING:
+ case IS_BINARY:
if ((op1->value.str.len == op2->value.str.len)
&& (!memcmp(op1->value.str.val, op2->value.str.val, op1->value.str.len))) {
result->value.lval = 1;
@@ -1428,6 +1724,14 @@ ZEND_API int is_identical_function(zval *result, zval *op1, zval *op2 TSRMLS_DC)
result->value.lval = 0;
}
break;
+ case IS_UNICODE:
+ if ((op1->value.ustr.len == op2->value.ustr.len)
+ && (!memcmp(op1->value.ustr.val, op2->value.ustr.val, UBYTES(op1->value.ustr.len)))) {
+ result->value.lval = 1;
+ } else {
+ result->value.lval = 0;
+ }
+ break;
case IS_ARRAY:
if (zend_hash_compare(op1->value.ht, op2->value.ht, (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0) {
result->value.lval = 1;
@@ -1682,6 +1986,7 @@ ZEND_API int increment_function(zval *op1)
op1->value.lval = 1;
op1->type = IS_LONG;
break;
+ case IS_BINARY:
case IS_STRING: {
long lval;
double dval;
@@ -1711,6 +2016,9 @@ ZEND_API int increment_function(zval *op1)
}
}
break;
+ case IS_UNICODE:
+ zend_error(E_ERROR, "Unsupported operand type");
+ break;
default:
return FAILURE;
}
@@ -1735,6 +2043,7 @@ ZEND_API int decrement_function(zval *op1)
case IS_DOUBLE:
op1->value.dval = op1->value.dval - 1;
break;
+ case IS_BINARY:
case IS_STRING: /* Like perl we only support string increment */
if (op1->value.str.len == 0) { /* consider as 0 */
STR_FREE(op1->value.str.val);
@@ -1760,6 +2069,9 @@ ZEND_API int decrement_function(zval *op1)
break;
}
break;
+ case IS_UNICODE:
+ zend_error(E_ERROR, "Unsupported operand type");
+ break;
default:
return FAILURE;
}
@@ -1788,6 +2100,38 @@ ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned in
return dest;
}
+ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length)
+{
+ return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
+}
+
+ZEND_API void *zend_u_str_tolower_copy(zend_uchar type, void *dest, const void *source, unsigned int length)
+{
+ if (type == IS_UNICODE) {
+ register UChar *str = (UChar*)source;
+ register UChar *result = (UChar*)dest;
+ register UChar *end = str + length;
+
+ while (str < end) {
+ *result++ = u_tolower((int)*str++);
+ }
+ *result = *end;
+
+ return dest;
+ } else {
+ return zend_str_tolower_copy(dest, source, length);
+ }
+}
+
+ZEND_API void *zend_u_str_tolower_dup(zend_uchar type, const void *source, unsigned int length)
+{
+ if (type == IS_UNICODE) {
+ return zend_u_str_tolower_copy(IS_UNICODE, emalloc(UBYTES(length+1)), source, length);
+ } else {
+ return zend_str_tolower_copy((char*)emalloc(length+1), (char*)source, length);
+ }
+}
+
ZEND_API void zend_str_tolower(char *str, unsigned int length)
{
register unsigned char *p = (unsigned char*)str;
@@ -1799,6 +2143,42 @@ ZEND_API void zend_str_tolower(char *str, unsigned int length)
}
}
+ZEND_API void zend_u_str_tolower(zend_uchar type, void *str, unsigned int length) {
+ if (type == IS_UNICODE) {
+ register UChar *p = (UChar*)str;
+ register UChar *end = p + length;
+
+ while (p < end) {
+ *p = u_tolower((int)*p);
+ p++;
+ }
+ } else {
+ zend_str_tolower((char*)str, length);
+ }
+}
+
+ZEND_API void *zend_u_str_case_fold(zend_uchar type, const void *source, unsigned int length, zend_bool normalize, unsigned int *new_len)
+{
+ if (type == IS_UNICODE) {
+ UChar *ret;
+ int32_t ret_len;
+
+ if (normalize) {
+ zend_normalize_identifier(&ret, &ret_len, (UChar*)source, length, 1);
+ } else {
+ UErrorCode status = U_ZERO_ERROR;
+
+ zend_case_fold_string(&ret, &ret_len, (UChar*)source, length, U_FOLD_CASE_DEFAULT, &status);
+ }
+
+ *new_len = ret_len;
+ return ret;
+ } else {
+ *new_len = length;
+ return zend_str_tolower_dup(source, length);
+ }
+}
+
ZEND_API int zend_binary_strcmp(char *s1, uint len1, char *s2, uint len2)
{
int retval;
@@ -1811,6 +2191,20 @@ ZEND_API int zend_binary_strcmp(char *s1, uint len1, char *s2, uint len2)
}
}
+
+ZEND_API int zend_u_binary_strcmp(UChar *s1, int32_t len1, UChar *s2, int32_t len2)
+{
+ int retval;
+
+ retval = u_memcmpCodePointOrder(s1, s2, MIN(len1, len2));
+ if (!retval) {
+ return (len1 - len2);
+ } else {
+ return retval;
+ }
+}
+
+
ZEND_API int zend_binary_strncmp(char *s1, uint len1, char *s2, uint len2, uint length)
{
int retval;
@@ -1867,6 +2261,13 @@ ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2)
return zend_binary_strcmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len);
}
+
+ZEND_API int zend_u_binary_zval_strcmp(zval *s1, zval *s2)
+{
+ return zend_u_binary_strcmp(s1->value.ustr.val, s1->value.ustr.len, s2->value.ustr.val, s2->value.ustr.len);
+}
+
+
ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3)
{
return zend_binary_strncmp(s1->value.str.val, s1->value.str.len, s2->value.str.val, s2->value.str.len, s3->value.lval);
@@ -1891,6 +2292,11 @@ ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2)
long lval1, lval2;
double dval1, dval2;
+ if (s1->type == IS_BINARY || s2->type == IS_BINARY) {
+ zend_error(E_ERROR, "Cannot convert binary type to string type");
+ return;
+ }
+
if ((ret1=is_numeric_string(s1->value.str.val, s1->value.str.len, &lval1, &dval1, 0)) &&
(ret2=is_numeric_string(s2->value.str.val, s2->value.str.len, &lval2, &dval2, 0))) {
if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
@@ -1916,6 +2322,57 @@ ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2)
}
+ZEND_API void zendi_u_smart_strcmp(zval *result, zval *s1, zval *s2)
+{
+ int ret1, ret2;
+ long lval1, lval2;
+ double dval1, dval2;
+ zval s1_copy, s2_copy;
+ int use_copy1 = 0, use_copy2 = 0;
+
+ if (s1->type != IS_UNICODE || s2->type != IS_UNICODE) {
+ zend_make_unicode_zval(s1, &s1_copy, &use_copy1);
+ zend_make_unicode_zval(s2, &s2_copy, &use_copy2);
+ if (use_copy1) {
+ s1 = &s1_copy;
+ }
+ if (use_copy2) {
+ s2 = &s2_copy;
+ }
+ }
+
+ if ((ret1=is_numeric_unicode(s1->value.ustr.val, s1->value.ustr.len, &lval1, &dval1, 0)) &&
+ (ret2=is_numeric_unicode(s2->value.ustr.val, s2->value.ustr.len, &lval2, &dval2, 0))) {
+ if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) {
+ if (ret1!=IS_DOUBLE) {
+ dval1 = zend_u_strtod(s1->value.ustr.val, NULL);
+ } else if (ret2!=IS_DOUBLE) {
+ dval2 = zend_u_strtod(s2->value.ustr.val, NULL);
+ }
+ result->value.dval = dval1 - dval2;
+ result->value.lval = ZEND_NORMALIZE_BOOL(result->value.dval);
+ result->type = IS_LONG;
+ } else { /* they both have to be long's */
+ result->value.lval = lval1 - lval2;
+ result->value.lval = ZEND_NORMALIZE_BOOL(result->value.lval);
+ result->type = IS_LONG;
+ }
+ } else {
+ result->value.lval = zend_u_binary_zval_strcmp(s1, s2);
+ result->value.lval = ZEND_NORMALIZE_BOOL(result->value.lval);
+ result->type = IS_LONG;
+ }
+
+ if (use_copy1) {
+ zval_dtor(s1);
+ }
+ if (use_copy2) {
+ zval_dtor(s2);
+ }
+ return;
+}
+
+
static int hash_zval_compare_function(const zval **z1, const zval **z2 TSRMLS_DC)
{
zval result;
@@ -1962,6 +2419,22 @@ ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC)
}
}
+ZEND_API void zend_locale_usprintf_double(zval *op ZEND_FILE_LINE_DC)
+{
+ double dval = op->value.dval;
+ UFILE *strf;
+ int32_t capacity;
+
+ TSRMLS_FETCH();
+
+ capacity = MAX_LENGTH_OF_DOUBLE + EG(precision) + 1;
+ op->value.ustr.val = eumalloc_rel(capacity);
+ /* UTODO uses default locale for now */
+ strf = u_fstropen(op->value.ustr.val, capacity, NULL);
+ op->value.ustr.len = u_fprintf(strf, "%.*G", (int) EG(precision), dval);
+ u_fclose(strf);
+}
+
ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC)
{
double dval = op->value.dval;
@@ -1973,6 +2446,20 @@ ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC)
op->value.str.len = strlen(op->value.str.val);
}
+ZEND_API void zend_locale_usprintf_long(zval *op ZEND_FILE_LINE_DC)
+{
+ long lval = op->value.lval;
+ UFILE *strf;
+ int32_t capacity;
+
+ capacity = MAX_LENGTH_OF_LONG + 1;
+ op->value.ustr.val = eumalloc_rel(capacity);
+ /* UTODO uses default locale for now */
+ strf = u_fstropen(op->value.ustr.val, capacity, NULL);
+ op->value.ustr.len = u_fprintf(strf, "%ld", lval);
+ u_fclose(strf);
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index 0f1f23e469..af0b99d1b4 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -30,6 +30,7 @@
#endif
#include "zend_strtod.h"
+#include "zend_unicode.h"
#if 0&&HAVE_BCMATH
#include "ext/bcmath/libbcmath/src/bcmath.h"
@@ -63,6 +64,8 @@ ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSR
ZEND_API zend_bool instanceof_function_ex(zend_class_entry *instance_ce, zend_class_entry *ce, zend_bool interfaces_only TSRMLS_DC);
ZEND_API zend_bool instanceof_function(zend_class_entry *instance_ce, zend_class_entry *ce TSRMLS_DC);
+ZEND_API long zend_u_strtol(const UChar *nptr, UChar **endptr, int base);
+ZEND_API double zend_u_strtod(const UChar *nptr, UChar **endptr);
END_EXTERN_C()
static inline zend_bool is_numeric_string(char *str, int length, long *lval, double *dval, zend_bool allow_errors)
@@ -128,6 +131,77 @@ static inline zend_bool is_numeric_string(char *str, int length, long *lval, dou
return 0;
}
+static inline zend_bool is_numeric_unicode(UChar *str, int32_t length, long *lval, double *dval, zend_bool allow_errors)
+{
+ int32_t local_lval;
+ double local_dval;
+ UChar *end_ptr_long, *end_ptr_double;
+ int conv_base=10;
+
+ if (!length) {
+ return 0;
+ }
+
+ /* handle hex numbers */
+ if (length>=2 && str[0]=='0' && (str[1]=='x' || str[1]=='X')) {
+ conv_base=16;
+ }
+
+ errno=0;
+ local_lval = zend_u_strtol(str, &end_ptr_long, conv_base);
+ if (errno != ERANGE) {
+ if (end_ptr_long == str+length) { /* integer string */
+ if (lval) {
+ *lval = local_lval;
+ }
+ return IS_LONG;
+ } else if (end_ptr_long == str && *end_ptr_long != '\0' && *str != '.' && *str != '-') { /* ignore partial string matches */
+ return 0;
+ }
+ } else {
+ end_ptr_long = NULL;
+ }
+
+ if (conv_base == 16) { /* hex string, under UNIX strtod() messes it up */
+ /* UTODO: keep compatibility with is_numeric_string() here? */
+ return 0;
+ }
+
+ local_dval = zend_u_strtod(str, &end_ptr_double);
+ if (local_dval == 0 && end_ptr_double == str) {
+ end_ptr_double = NULL;
+ } else {
+ if (end_ptr_double == str+length) { /* floating point string */
+ if (!zend_finite(local_dval)) {
+ /* "inf","nan" and maybe other weird ones */
+ return 0;
+ }
+
+ if (dval) {
+ *dval = local_dval;
+ }
+ return IS_DOUBLE;
+ }
+ }
+
+ if (allow_errors) {
+ if (end_ptr_double > end_ptr_long && dval) {
+ *dval = local_dval;
+ return IS_DOUBLE;
+ } else if (end_ptr_long && lval) {
+ *lval = local_lval;
+ return IS_LONG;
+ }
+ }
+ return 0;
+}
+
+static inline UChar*
+zend_u_memnstr(UChar *haystack, UChar *needle, int32_t needle_len, UChar *end)
+{
+ return u_strFindFirst(haystack, end - haystack, needle, needle_len);
+}
+
static inline char *
zend_memnstr(char *haystack, char *needle, int needle_len, char *end)
{
@@ -160,6 +234,10 @@ ZEND_API int decrement_function(zval *op2);
ZEND_API void convert_scalar_to_number(zval *op TSRMLS_DC);
ZEND_API void _convert_to_string(zval *op ZEND_FILE_LINE_DC);
+ZEND_API void _convert_to_string_with_converter(zval *op, UConverter *conv TSRMLS_DC ZEND_FILE_LINE_DC);
+ZEND_API void _convert_to_unicode(zval *op TSRMLS_DC ZEND_FILE_LINE_DC);
+ZEND_API void _convert_to_unicode_with_converter(zval *op, UConverter *conv TSRMLS_DC ZEND_FILE_LINE_DC);
+ZEND_API void convert_to_binary(zval *op);
ZEND_API void convert_to_long(zval *op);
ZEND_API void convert_to_double(zval *op);
ZEND_API void convert_to_long_base(zval *op, int base);
@@ -172,7 +250,11 @@ ZEND_API void multi_convert_to_double_ex(int argc, ...);
ZEND_API void multi_convert_to_string_ex(int argc, ...);
ZEND_API int add_char_to_string(zval *result, zval *op1, zval *op2);
ZEND_API int add_string_to_string(zval *result, zval *op1, zval *op2);
-#define convert_to_string(op) _convert_to_string((op) ZEND_FILE_LINE_CC)
+#define convert_to_string(op) _convert_to_string((op) ZEND_FILE_LINE_CC)
+#define convert_to_string_with_converter(op, conv) _convert_to_string_with_converter((op), (conv) TSRMLS_CC ZEND_FILE_LINE_CC)
+#define convert_to_unicode(op) _convert_to_unicode((op) TSRMLS_CC ZEND_FILE_LINE_CC)
+#define convert_to_unicode_with_converter(op, conv) _convert_to_unicode_with_converter((op), (conv) TSRMLS_CC ZEND_FILE_LINE_CC)
+#define convert_to_text(op) (UG(unicode)?convert_to_unicode(op):convert_to_string(op))
ZEND_API double zend_string_to_double(const char *number, zend_uint length);
@@ -186,15 +268,14 @@ ZEND_API int string_locale_compare_function(zval *result, zval *op1, zval *op2 T
ZEND_API void zend_str_tolower(char *str, unsigned int length);
ZEND_API char *zend_str_tolower_copy(char *dest, const char *source, unsigned int length);
-END_EXTERN_C()
+ZEND_API char *zend_str_tolower_dup(const char *source, unsigned int length);
-static inline char *
-zend_str_tolower_dup(const char *source, unsigned int length)
-{
- return zend_str_tolower_copy((char *)emalloc(length+1), source, length);
-}
+ZEND_API void zend_u_str_tolower(zend_uchar type, void *str, unsigned int length);
+ZEND_API void *zend_u_str_tolower_copy(zend_uchar type, void *dest, const void *source, unsigned int length);
+ZEND_API void *zend_u_str_tolower_dup(zend_uchar type, const void *source, unsigned int length);
+
+ZEND_API void *zend_u_str_case_fold(zend_uchar type, const void *source, unsigned int length, zend_bool normalize, unsigned int *new_len);
-BEGIN_EXTERN_C()
ZEND_API int zend_binary_zval_strcmp(zval *s1, zval *s2);
ZEND_API int zend_binary_zval_strncmp(zval *s1, zval *s2, zval *s3);
ZEND_API int zend_binary_zval_strcasecmp(zval *s1, zval *s2);
@@ -204,7 +285,11 @@ ZEND_API int zend_binary_strncmp(char *s1, uint len1, char *s2, uint len2, uint
ZEND_API int zend_binary_strcasecmp(char *s1, uint len1, char *s2, uint len2);
ZEND_API int zend_binary_strncasecmp(char *s1, uint len1, char *s2, uint len2, uint length);
+ZEND_API int zend_u_binary_zval_strcmp(zval *s1, zval *s2);
+ZEND_API int zend_u_binary_strcmp(UChar *s1, int32_t len1, UChar *s2, int32_t len2);
+
ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2);
+ZEND_API void zendi_u_smart_strcmp(zval *result, zval *s1, zval *s2);
ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC);
ZEND_API void zend_compare_arrays(zval *result, zval *a1, zval *a2 TSRMLS_DC);
ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC);
@@ -212,6 +297,8 @@ ZEND_API void zend_compare_objects(zval *result, zval *o1, zval *o2 TSRMLS_DC);
ZEND_API int zend_atoi(const char *str, int str_len);
ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC);
+ZEND_API void zend_locale_usprintf_double(zval *op ZEND_FILE_LINE_DC);
+ZEND_API void zend_locale_usprintf_long(zval *op ZEND_FILE_LINE_DC);
END_EXTERN_C()
#define convert_to_ex_master(ppzv, lower_type, upper_type) \
if ((*ppzv)->type!=IS_##upper_type) { \
@@ -219,14 +306,59 @@ END_EXTERN_C()
convert_to_##lower_type(*ppzv); \
}
+#define convert_to_explicit_type(pzv, type) \
+ do { \
+ switch (type) { \
+ case IS_NULL: \
+ convert_to_null(pzv); \
+ break; \
+ case IS_LONG: \
+ convert_to_long(pzv); \
+ break; \
+ case IS_DOUBLE: \
+ convert_to_double(pzv); \
+ break; \
+ case IS_BOOL: \
+ convert_to_bool(pzv); \
+ break; \
+ case IS_ARRAY: \
+ convert_to_array(pzv); \
+ break; \
+ case IS_OBJECT: \
+ convert_to_object(pzv); \
+ break; \
+ case IS_STRING: \
+ convert_to_string(pzv); \
+ break; \
+ case IS_UNICODE: \
+ convert_to_unicode(pzv); \
+ break; \
+ case IS_BINARY: \
+ convert_to_binary(pzv); \
+ break; \
+ default: \
+ assert(0); \
+ break; \
+ } \
+ } while (0); \
+
+#define convert_to_explicit_type_ex(ppzv, type) \
+ if ((*ppzv)->type != type) { \
+ SEPARATE_ZVAL_IF_NOT_REF(ppzv); \
+ convert_to_explicit_type(*ppzv, type); \
+ } \
+}
#define convert_to_boolean_ex(ppzv) convert_to_ex_master(ppzv, boolean, BOOL)
#define convert_to_long_ex(ppzv) convert_to_ex_master(ppzv, long, LONG)
#define convert_to_double_ex(ppzv) convert_to_ex_master(ppzv, double, DOUBLE)
#define convert_to_string_ex(ppzv) convert_to_ex_master(ppzv, string, STRING)
+#define convert_to_unicode_ex(ppzv) convert_to_ex_master(ppzv, unicode, UNICODE)
+#define convert_to_binary_ex(ppzv) convert_to_ex_master(ppzv, binary, BINARY)
#define convert_to_array_ex(ppzv) convert_to_ex_master(ppzv, array, ARRAY)
#define convert_to_object_ex(ppzv) convert_to_ex_master(ppzv, object, OBJECT)
#define convert_to_null_ex(ppzv) convert_to_ex_master(ppzv, null, NULL)
+#define convert_to_text_ex(ppzv) if (UG(unicode)) {convert_to_unicode_ex(ppzv);} else {convert_to_string_ex(ppzv);}
#define convert_scalar_to_number_ex(ppzv) \
if ((*ppzv)->type!=IS_LONG && (*ppzv)->type!=IS_DOUBLE) { \
@@ -242,6 +374,11 @@ END_EXTERN_C()
#define Z_DVAL(zval) (zval).value.dval
#define Z_STRVAL(zval) (zval).value.str.val
#define Z_STRLEN(zval) (zval).value.str.len
+#define Z_USTRVAL(zval) (zval).value.ustr.val
+#define Z_USTRLEN(zval) (zval).value.ustr.len
+#define Z_USTRCPLEN(zval) (u_countChar32((zval).value.ustr.val, (zval).value.ustr.len))
+#define Z_BINVAL(zval) Z_STRVAL(zval)
+#define Z_BINLEN(zval) Z_STRLEN(zval)
#define Z_ARRVAL(zval) (zval).value.ht
#define Z_OBJ_HANDLE(zval) (zval).value.obj.handle
#define Z_OBJ_HT(zval) (zval).value.obj.handlers
@@ -249,12 +386,19 @@ END_EXTERN_C()
#define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC)
#define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf
#define Z_RESVAL(zval) (zval).value.lval
+#define Z_UNIVAL(zval) ((zval).type==IS_UNICODE?(char*)(zval).value.ustr.val:(zval).value.str.val)
+#define Z_UNILEN(zval) ((zval).type==IS_UNICODE?(zval).value.ustr.len:(zval).value.str.len)
#define Z_LVAL_P(zval_p) Z_LVAL(*zval_p)
#define Z_BVAL_P(zval_p) Z_BVAL(*zval_p)
#define Z_DVAL_P(zval_p) Z_DVAL(*zval_p)
#define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p)
#define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p)
+#define Z_USTRVAL_P(zval_p) Z_USTRVAL(*zval_p)
+#define Z_USTRLEN_P(zval_p) Z_USTRLEN(*zval_p)
+#define Z_USTRCPLEN_P(zval_p) Z_USTRCPLEN(*zval_p)
+#define Z_BINVAL_P(zval) Z_STRVAL_P(zval)
+#define Z_BINLEN_P(zval) Z_STRLEN_P(zval)
#define Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p)
#define Z_OBJPROP_P(zval_p) Z_OBJPROP(*zval_p)
#define Z_OBJCE_P(zval_p) Z_OBJCE(*zval_p)
@@ -262,12 +406,19 @@ END_EXTERN_C()
#define Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*zval_p)
#define Z_OBJ_HT_P(zval_p) Z_OBJ_HT(*zval_p)
#define Z_OBJ_HANDLER_P(zval_p, h) Z_OBJ_HANDLER(*zval_p, h)
+#define Z_UNIVAL_P(zval_p) Z_UNIVAL(*zval_p)
+#define Z_UNILEN_P(zval_p) Z_UNILEN(*zval_p)
#define Z_LVAL_PP(zval_pp) Z_LVAL(**zval_pp)
#define Z_BVAL_PP(zval_pp) Z_BVAL(**zval_pp)
#define Z_DVAL_PP(zval_pp) Z_DVAL(**zval_pp)
#define Z_STRVAL_PP(zval_pp) Z_STRVAL(**zval_pp)
#define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp)
+#define Z_USTRVAL_PP(zval_pp) Z_USTRVAL(**zval_pp)
+#define Z_USTRLEN_PP(zval_pp) Z_USTRLEN(**zval_pp)
+#define Z_USTRCPLEN_PP(zval_pp) Z_USTRCPLEN(**zval_pp)
+#define Z_BINVAL_PP(zval) Z_STRVAL_PP(zval)
+#define Z_BINLEN_PP(zval) Z_STRLEN_PP(zval)
#define Z_ARRVAL_PP(zval_pp) Z_ARRVAL(**zval_pp)
#define Z_OBJPROP_PP(zval_pp) Z_OBJPROP(**zval_pp)
#define Z_OBJCE_PP(zval_pp) Z_OBJCE(**zval_pp)
@@ -275,6 +426,8 @@ END_EXTERN_C()
#define Z_OBJ_HANDLE_PP(zval_p) Z_OBJ_HANDLE(**zval_p)
#define Z_OBJ_HT_PP(zval_p) Z_OBJ_HT(**zval_p)
#define Z_OBJ_HANDLER_PP(zval_p, h) Z_OBJ_HANDLER(**zval_p, h)
+#define Z_UNIVAL_PP(zval_pp) Z_UNIVAL(**zval_pp)
+#define Z_UNILEN_PP(zval_pp) Z_UNILEN(**zval_pp)
#define Z_TYPE(zval) (zval).type
#define Z_TYPE_P(zval_p) Z_TYPE(*zval_p)
diff --git a/Zend/zend_reflection_api.c b/Zend/zend_reflection_api.c
index 2bbd91bc98..fa001dc9b9 100644
--- a/Zend/zend_reflection_api.c
+++ b/Zend/zend_reflection_api.c
@@ -43,7 +43,7 @@ zend_class_entry *reflection_extension_ptr;
/* Method macros */
#define METHOD_NOTSTATIC \
if (!this_ptr) { \
- zend_error(E_ERROR, "%s() cannot be called statically", get_active_function_name(TSRMLS_C)); \
+ zend_error(E_ERROR, "%v() cannot be called statically", get_active_function_name(TSRMLS_C)); \
return; \
} \
@@ -233,7 +233,7 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR
intern->free_ptr = 0;
ALLOC_HASHTABLE(intern->zo.properties);
- zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, reflection_objects_clone TSRMLS_CC);
retval.handlers = &reflection_object_handlers;
@@ -297,17 +297,17 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
string_printf(str, "class ");
}
- string_write(str, ce->name, ce->name_length);
+ string_printf(str, "%v", ce->name);
if (ce->parent) {
- string_printf(str, " extends %s", ce->parent->name);
+ string_printf(str, " extends %v", ce->parent->name);
}
if (ce->num_interfaces) {
zend_uint i;
- string_printf(str, " implements %s", ce->interfaces[0]->name);
+ string_printf(str, " implements %v", ce->interfaces[0]->name);
for (i = 1; i < ce->num_interfaces; ++i) {
- string_printf(str, ", %s", ce->interfaces[i]->name);
+ string_printf(str, ", %v", ce->interfaces[i]->name);
}
}
string_printf(str, " ] {\n");
@@ -540,7 +540,7 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
string_printf(str, "<required> ");
}
if (arg_info->class_name) {
- string_printf(str, "%s ", arg_info->class_name);
+ string_printf(str, "%v ", arg_info->class_name);
if (arg_info->allow_null) {
string_printf(str, "or NULL ");
}
@@ -554,7 +554,7 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
string_write(str, "&", sizeof("&")-1);
}
if (arg_info->name) {
- string_printf(str, "$%s", arg_info->name);
+ string_printf(str, "$%v", arg_info->name);
} else {
string_printf(str, "$param%d", offset);
}
@@ -671,7 +671,7 @@ static void _function_string(string *str, zend_function *fptr, char* indent TSRM
if (fptr->op_array.return_reference) {
string_printf(str, "&");
}
- string_printf(str, "%s ] {\n", fptr->common.function_name);
+ string_printf(str, "%v ] {\n", fptr->common.function_name);
/* The information where a function is declared is only available for user classes */
if (fptr->type == ZEND_USER_FUNCTION) {
string_printf(str, "%s @@ %s %d - %d\n", indent,
@@ -720,8 +720,8 @@ static void _property_string(string *str, zend_property_info *prop, char *prop_n
string_printf(str, "static ");
}
- zend_unmangle_property_name(prop->name, &class_name, &prop_name);
- string_printf(str, "$%s", prop_name);
+ zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, prop->name, &class_name, &prop_name);
+ string_printf(str, "$%v", prop_name);
}
string_printf(str, " ]\n");
@@ -865,7 +865,11 @@ ZEND_API void zend_reflection_class_factory(zend_class_entry *ce, zval *object T
zval *name;
MAKE_STD_ZVAL(name);
- ZVAL_STRINGL(name, ce->name, ce->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(name, (UChar*)ce->name, ce->name_length, 1);
+ } else {
+ ZVAL_STRINGL(name, ce->name, ce->name_length, 1);
+ }
reflection_instanciate(reflection_class_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
intern->ptr = ce;
@@ -912,7 +916,11 @@ static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_i
MAKE_STD_ZVAL(name);
if (arg_info->name) {
- ZVAL_STRINGL(name, arg_info->name, arg_info->name_len, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(name, (UChar*)arg_info->name, arg_info->name_len, 1);
+ } else {
+ ZVAL_STRINGL(name, arg_info->name, arg_info->name_len, 1);
+ }
} else {
ZVAL_NULL(name);
}
@@ -937,7 +945,11 @@ static void reflection_function_factory(zend_function *function, zval *object TS
zval *name;
MAKE_STD_ZVAL(name);
- ZVAL_STRING(name, function->common.function_name, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(name, (UChar*)function->common.function_name, 1);
+ } else {
+ ZVAL_STRING(name, function->common.function_name, 1);
+ }
reflection_instanciate(reflection_function_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
@@ -956,9 +968,14 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
zval *classname;
MAKE_STD_ZVAL(name);
- ZVAL_STRING(name, method->common.function_name, 1);
MAKE_STD_ZVAL(classname);
- ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(name, (UChar*)method->common.function_name, 1);
+ ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
+ } else {
+ ZVAL_STRING(name, method->common.function_name, 1);
+ ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ }
reflection_instanciate(reflection_method_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
intern->ptr = method;
@@ -978,7 +995,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
property_reference *reference;
char *class_name, *prop_name;
- zend_unmangle_property_name(prop->name, &class_name, &prop_name);
+ zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, prop->name, &class_name, &prop_name);
if (!(prop->flags & ZEND_ACC_PRIVATE)) {
/* we have to seach the class hierarchy for this (implicit) public or protected property */
@@ -997,10 +1014,14 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
}
MAKE_STD_ZVAL(name);
- ZVAL_STRING(name, prop_name, 1);
-
MAKE_STD_ZVAL(classname);
- ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(name, (UChar*)prop_name, 1);
+ ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
+ } else {
+ ZVAL_STRING(name, prop_name, 1);
+ ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ }
reflection_instanciate(reflection_property_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
@@ -1144,7 +1165,7 @@ ZEND_METHOD(reflection, export)
}
if (!retval_ptr) {
- zend_error(E_WARNING, "%s::__toString() did not return anything", Z_OBJCE_P(object)->name);
+ zend_error(E_WARNING, "%v::__toString() did not return anything", Z_OBJCE_P(object)->name);
RETURN_FALSE;
}
@@ -1211,13 +1232,15 @@ ZEND_METHOD(reflection_function, __construct)
{
zval *name;
zval *object;
+ unsigned int lcname_len;
char *lcname;
reflection_object *intern;
zend_function *fptr;
char *name_str;
int name_len;
+ zend_uchar type;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name_str, &name_len, &type) == FAILURE) {
return;
}
@@ -1226,17 +1249,20 @@ ZEND_METHOD(reflection_function, __construct)
if (intern == NULL) {
return;
}
- lcname = do_alloca(name_len + 1);
- zend_str_tolower_copy(lcname, name_str, name_len);
- if (zend_hash_find(EG(function_table), lcname, name_len + 1, (void **)&fptr) == FAILURE) {
- free_alloca(lcname);
+ lcname = zend_u_str_case_fold(type, name_str, name_len, 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), type, lcname, lcname_len + 1, (void **)&fptr) == FAILURE) {
+ efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Function %s() does not exist", name_str);
+ "Function %R() does not exist", type, name_str);
return;
}
- free_alloca(lcname);
+ efree(lcname);
MAKE_STD_ZVAL(name);
- ZVAL_STRING(name, fptr->common.function_name, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(name, (UChar*)fptr->common.function_name, 1);
+ } else {
+ ZVAL_STRING(name, fptr->common.function_name, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
intern->ptr = fptr;
intern->free_ptr = 0;
@@ -1421,7 +1447,7 @@ ZEND_METHOD(reflection_function, invoke)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Invocation of function %s() failed", fptr->common.function_name);
+ "Invocation of function %v() failed", fptr->common.function_name);
return;
}
@@ -1485,7 +1511,7 @@ ZEND_METHOD(reflection_function, invokeArgs)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Invocation of function %s() failed", fptr->common.function_name);
+ "Invocation of function %v() failed", fptr->common.function_name);
return;
}
@@ -1598,19 +1624,20 @@ ZEND_METHOD(reflection_parameter, __construct)
/* First, find the function */
switch (Z_TYPE_P(reference)) {
+ case IS_UNICODE:
case IS_STRING: {
- char *lcname;
+ unsigned int lcname_len;
+ char *lcname;
- convert_to_string_ex(&reference);
- lcname = do_alloca(Z_STRLEN_P(reference) + 1);
- zend_str_tolower_copy(lcname, Z_STRVAL_P(reference), Z_STRLEN_P(reference));
- if (zend_hash_find(EG(function_table), lcname, (int) Z_STRLEN_P(reference) + 1, (void**) &fptr) == FAILURE) {
- free_alloca(lcname);
+ convert_to_text_ex(&reference);
+ lcname = zend_u_str_case_fold(Z_TYPE_P(reference), Z_STRVAL_P(reference), Z_STRLEN_P(reference), 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(reference), lcname, lcname_len + 1, (void**) &fptr) == FAILURE) {
+ efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Function %s() does not exist", Z_STRVAL_P(reference));
+ "Function %R() does not exist", Z_TYPE_P(reference), Z_STRVAL_P(reference));
return;
}
- free_alloca(lcname);
+ efree(lcname);
}
break;
@@ -1618,7 +1645,8 @@ ZEND_METHOD(reflection_parameter, __construct)
zval **classref;
zval **method;
zend_class_entry **pce;
- char *lcname;
+ unsigned int lcname_len;
+ char *lcname;
if ((zend_hash_index_find(Z_ARRVAL_P(reference), 0, (void **) &classref) == FAILURE)
|| (zend_hash_index_find(Z_ARRVAL_P(reference), 1, (void **) &method) == FAILURE)) {
@@ -1629,25 +1657,24 @@ ZEND_METHOD(reflection_parameter, __construct)
if (Z_TYPE_PP(classref) == IS_OBJECT) {
ce = Z_OBJCE_PP(classref);
} else {
- convert_to_string_ex(classref);
- if (zend_lookup_class(Z_STRVAL_PP(classref), Z_STRLEN_PP(classref), &pce TSRMLS_CC) == FAILURE) {
+ convert_to_text_ex(classref);
+ if (zend_u_lookup_class(Z_TYPE_PP(classref), Z_UNIVAL_PP(classref), Z_UNILEN_PP(classref), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Class %s does not exist", Z_STRVAL_PP(classref));
+ "Class %R does not exist", Z_TYPE_PP(classref), Z_UNIVAL_PP(classref));
return;
}
ce = *pce;
}
- convert_to_string_ex(method);
- lcname = do_alloca(Z_STRLEN_PP(method) + 1);
- zend_str_tolower_copy(lcname, Z_STRVAL_PP(method), Z_STRLEN_PP(method));
- if (zend_hash_find(&ce->function_table, lcname, (int)(Z_STRLEN_PP(method) + 1), (void **) &fptr) == FAILURE) {
- free_alloca(lcname);
+ convert_to_text_ex(method);
+ lcname = zend_u_str_case_fold(Z_TYPE_PP(method), Z_UNIVAL_PP(method), Z_UNILEN_PP(method), 1, &lcname_len);
+ if (zend_u_hash_find(&ce->function_table, Z_TYPE_PP(method), lcname, lcname_len + 1, (void **) &fptr) == FAILURE) {
+ efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Method %s::%s() does not exist", Z_STRVAL_PP(classref), Z_STRVAL_PP(method));
+ "Method %R::%R() does not exist", Z_TYPE_PP(classref), Z_UNIVAL_PP(classref), Z_TYPE_PP(method), Z_UNIVAL_PP(method));
return;
}
- free_alloca(lcname);
+ efree(lcname);
}
break;
@@ -1683,7 +1710,11 @@ ZEND_METHOD(reflection_parameter, __construct)
MAKE_STD_ZVAL(name);
if (arg_info[position].name) {
- ZVAL_STRINGL(name, arg_info[position].name, arg_info[position].name_len, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(name, (UChar*)arg_info[position].name, arg_info[position].name_len, 1);
+ } else {
+ ZVAL_STRINGL(name, arg_info[position].name, arg_info[position].name_len, 1);
+ }
} else {
ZVAL_NULL(name);
}
@@ -1739,15 +1770,16 @@ ZEND_METHOD(reflection_parameter, getClass)
RETURN_NULL();
} else {
zend_class_entry **pce;
- char *lcname = do_alloca(param->arg_info->class_name_len + 1);
- zend_str_tolower_copy(lcname, param->arg_info->class_name, param->arg_info->class_name_len);
- if (zend_hash_find(EG(class_table), lcname, param->arg_info->class_name_len + 1, (void **) &pce) == FAILURE) {
- free_alloca(lcname);
+ unsigned int lcname_len;
+ char *lcname = zend_u_str_case_fold(UG(unicode)?IS_UNICODE:IS_STRING, param->arg_info->class_name, param->arg_info->class_name_len, 0, &lcname_len);
+
+ if (zend_u_hash_find(EG(class_table), UG(unicode)?IS_UNICODE:IS_STRING, lcname, lcname_len + 1, (void **) &pce) == FAILURE) {
+ efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Class %s does not exist", param->arg_info->class_name);
+ "Class %v does not exist", param->arg_info->class_name);
return;
}
- free_alloca(lcname);
+ efree(lcname);
zend_reflection_class_factory(*pce, return_value TSRMLS_CC);
}
}
@@ -1884,14 +1916,16 @@ ZEND_METHOD(reflection_method, __construct)
zval *name, *classname;
zval *object;
reflection_object *intern;
+ unsigned int lcname_len;
char *lcname;
zend_class_entry **pce;
zend_class_entry *ce;
zend_function *mptr;
char *name_str;
int name_len;
+ zend_uchar type;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &classname, &name_str, &name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zt", &classname, &name_str, &name_len, &type) == FAILURE) {
return;
}
@@ -1904,9 +1938,10 @@ ZEND_METHOD(reflection_method, __construct)
/* Find the class entry */
switch (Z_TYPE_P(classname)) {
case IS_STRING:
- if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
+ case IS_UNICODE:
+ if (zend_u_lookup_class(Z_TYPE_P(classname), Z_UNIVAL_P(classname), Z_UNILEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Class %s does not exist", Z_STRVAL_P(classname));
+ "Class %v does not exist", Z_UNIVAL_P(classname));
return;
}
ce = *pce;
@@ -1922,22 +1957,29 @@ ZEND_METHOD(reflection_method, __construct)
}
MAKE_STD_ZVAL(classname);
- ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
+ } else {
+ ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
- lcname = do_alloca(name_len + 1);
- zend_str_tolower_copy(lcname, name_str, name_len);
+ lcname = zend_u_str_case_fold(type, name_str, name_len, 1, &lcname_len);
- if (zend_hash_find(&ce->function_table, lcname, name_len + 1, (void **) &mptr) == FAILURE) {
- free_alloca(lcname);
+ if (zend_u_hash_find(&ce->function_table, type, lcname, lcname_len + 1, (void **) &mptr) == FAILURE) {
+ efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Method %s::%s() does not exist", ce->name, name_str);
+ "Method %v::%R() does not exist", ce->name, type, name_str);
return;
}
- free_alloca(lcname);
+ efree(lcname);
MAKE_STD_ZVAL(name);
- ZVAL_STRING(name, mptr->common.function_name, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(name, (UChar*)mptr->common.function_name, 1);
+ } else {
+ ZVAL_STRING(name, mptr->common.function_name, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
intern->ptr = mptr;
intern->free_ptr = 0;
@@ -1989,11 +2031,11 @@ ZEND_METHOD(reflection_method, invoke)
(mptr->common.fn_flags & ZEND_ACC_ABSTRACT)) {
if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke abstract method %s::%s()",
+ "Trying to invoke abstract method %v::%v()",
mptr->common.scope->name, mptr->common.function_name);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke %s method %s::%s() from scope %s",
+ "Trying to invoke %s method %v::%v() from scope %v",
mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
mptr->common.scope->name, mptr->common.function_name,
Z_OBJCE_P(getThis())->name);
@@ -2054,7 +2096,7 @@ ZEND_METHOD(reflection_method, invoke)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
+ "Invocation of method %v::%v() failed", mptr->common.scope->name, mptr->common.function_name);
return;
}
@@ -2092,11 +2134,11 @@ ZEND_METHOD(reflection_method, invokeArgs)
(mptr->common.fn_flags & ZEND_ACC_ABSTRACT)) {
if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke abstract method %s::%s",
+ "Trying to invoke abstract method %v::%v",
mptr->common.scope->name, mptr->common.function_name);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke %s method %s::%s from scope %s",
+ "Trying to invoke %s method %v::%v from scope %v",
mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
mptr->common.scope->name, mptr->common.function_name,
Z_OBJCE_P(getThis())->name);
@@ -2123,7 +2165,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
if (!object) {
efree(params);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke non static method %s::%s without an object",
+ "Trying to invoke non static method %v::%v without an object",
mptr->common.scope->name, mptr->common.function_name);
return;
}
@@ -2158,7 +2200,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
+ "Invocation of method %v::%v() failed", mptr->common.scope->name, mptr->common.function_name);
return;
}
@@ -2308,7 +2350,11 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
if (Z_TYPE_P(argument) == IS_OBJECT) {
MAKE_STD_ZVAL(classname);
- ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(classname, (UChar*)Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
+ } else {
+ ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
intern->ptr = Z_OBJCE_P(argument);
if (is_object) {
@@ -2317,7 +2363,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
}
} else {
convert_to_string_ex(&argument);
- if (zend_lookup_class(Z_STRVAL_P(argument), Z_STRLEN_P(argument), &ce TSRMLS_CC) == FAILURE) {
+ if (zend_u_lookup_class(Z_TYPE_P(argument), Z_UNIVAL_P(argument), Z_UNILEN_P(argument), &ce TSRMLS_CC) == FAILURE) {
if (!EG(exception)) {
zend_throw_exception_ex(reflection_exception_ptr, -1 TSRMLS_CC, "Class %s does not exist", Z_STRVAL_P(argument));
}
@@ -2325,7 +2371,11 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
}
MAKE_STD_ZVAL(classname);
- ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(classname, (UChar*)((*ce)->name), (*ce)->name_length, 1);
+ } else {
+ ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
intern->ptr = *ce;
@@ -2613,17 +2663,19 @@ ZEND_METHOD(reflection_class, hasMethod)
{
reflection_object *intern;
zend_class_entry *ce;
+ unsigned int lc_name_len;
char *name, *lc_name;
int name_len;
+ zend_uchar type;
METHOD_NOTSTATIC;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &type) == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
- lc_name = zend_str_tolower_dup(name, name_len);
- if (zend_hash_exists(&ce->function_table, lc_name, name_len + 1)) {
+ lc_name = zend_u_str_case_fold(type, name, name_len, 1, &lc_name_len);
+ if (zend_u_hash_exists(&ce->function_table, type, lc_name, lc_name_len + 1)) {
efree(lc_name);
RETURN_TRUE;
} else {
@@ -2640,23 +2692,25 @@ ZEND_METHOD(reflection_class, getMethod)
reflection_object *intern;
zend_class_entry *ce;
zend_function *mptr;
+ unsigned int lc_name_len;
char *name, *lc_name;
int name_len;
+ zend_uchar type;
METHOD_NOTSTATIC;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &type) == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
- lc_name = zend_str_tolower_dup(name, name_len);
- if (zend_hash_find(&ce->function_table, lc_name, name_len + 1, (void**) &mptr) == SUCCESS) {
+ lc_name = zend_u_str_case_fold(type, name, name_len, 1, &lc_name_len);
+ if (zend_u_hash_find(&ce->function_table, type, lc_name, lc_name_len + 1, (void**) &mptr) == SUCCESS) {
reflection_method_factory(ce, mptr, return_value TSRMLS_CC);
efree(lc_name);
} else {
efree(lc_name);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Method %s does not exist", name);
+ "Method %R does not exist", type, name);
return;
}
}
@@ -2989,7 +3043,7 @@ ZEND_METHOD(reflection_class, newInstance)
zend_fcall_info_cache fcc;
if (!(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %s", ce->name);
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %v", ce->name);
return;
}
@@ -3017,7 +3071,7 @@ ZEND_METHOD(reflection_class, newInstance)
if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
efree(params);
zval_ptr_dtor(&retval_ptr);
- zend_error(E_WARNING, "Invocation of %s's constructor failed", ce->name);
+ zend_error(E_WARNING, "Invocation of %v's constructor failed", ce->name);
RETURN_NULL();
}
if (retval_ptr) {
@@ -3089,7 +3143,8 @@ ZEND_METHOD(reflection_class, isSubclassOf)
switch(class_name->type) {
case IS_STRING:
- if (zend_lookup_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
+ case IS_UNICODE:
+ if (zend_u_lookup_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s does not exist", Z_STRVAL_P(class_name));
return;
@@ -3135,7 +3190,8 @@ ZEND_METHOD(reflection_class, implementsInterface)
switch(interface->type) {
case IS_STRING:
- if (zend_lookup_class(Z_STRVAL_P(interface), Z_STRLEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
+ case IS_UNICODE:
+ if (zend_u_lookup_class(Z_TYPE_P(interface), Z_UNIVAL_P(interface), Z_UNILEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s does not exist", Z_STRVAL_P(interface));
return;
@@ -3161,7 +3217,7 @@ ZEND_METHOD(reflection_class, implementsInterface)
if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Interface %s is a Class", interface_ce->name);
+ "Interface %v is a Class", interface_ce->name);
return;
}
RETURN_BOOL(instanceof_function(ce, interface_ce TSRMLS_CC));
@@ -3267,7 +3323,8 @@ ZEND_METHOD(reflection_property, __construct)
/* Find the class entry */
switch (Z_TYPE_P(classname)) {
case IS_STRING:
- if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
+ case IS_UNICODE:
+ if (zend_u_lookup_class(Z_TYPE_P(classname), Z_UNIVAL_P(classname), Z_UNILEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", Z_STRVAL_P(classname));
return;
@@ -3286,7 +3343,7 @@ ZEND_METHOD(reflection_property, __construct)
if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Property %s::$%s does not exist", ce->name, name_str);
+ "Property %v::$%s does not exist", ce->name, name_str);
return;
}
@@ -3307,12 +3364,20 @@ ZEND_METHOD(reflection_property, __construct)
}
MAKE_STD_ZVAL(classname);
- ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
+ } else {
+ ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
- zend_unmangle_property_name(property_info->name, &class_name, &prop_name);
+ zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, property_info->name, &class_name, &prop_name);
MAKE_STD_ZVAL(propname);
- ZVAL_STRING(propname, prop_name, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(propname, (UChar*)prop_name, 1);
+ } else {
+ ZVAL_STRING(propname, prop_name, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL);
reference = (property_reference*) emalloc(sizeof(property_reference));
@@ -3421,6 +3486,7 @@ ZEND_METHOD(reflection_property, getValue)
property_reference *ref;
zval *object;
zval **member= NULL;
+ zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
METHOD_NOTSTATIC;
GET_REFLECTION_OBJECT_PTR(ref);
@@ -3432,16 +3498,16 @@ ZEND_METHOD(reflection_property, getValue)
if ((ref->prop->flags & ZEND_ACC_STATIC)) {
zend_update_class_constants(intern->ce TSRMLS_CC);
- if (zend_hash_quick_find(intern->ce->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
- zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
+ if (zend_u_hash_quick_find(intern->ce->static_members, utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
+ zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name);
/* Bails out */
}
} else {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
return;
}
- if (zend_hash_quick_find(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
- zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
+ if (zend_u_hash_quick_find(Z_OBJPROP_P(object), utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
+ zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name);
/* Bails out */
}
}
@@ -3463,6 +3529,7 @@ ZEND_METHOD(reflection_property, setValue)
int setter_done = 0;
zval *tmp;
HashTable *prop_table;
+ zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
METHOD_NOTSTATIC;
GET_REFLECTION_OBJECT_PTR(ref);
@@ -3486,8 +3553,8 @@ ZEND_METHOD(reflection_property, setValue)
prop_table = Z_OBJPROP_P(object);
}
- if (zend_hash_quick_find(prop_table, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) {
- zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
+ if (zend_u_hash_quick_find(prop_table, utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) {
+ zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name);
/* Bails out */
}
if (*variable_ptr == value) {
@@ -3510,7 +3577,7 @@ ZEND_METHOD(reflection_property, setValue)
if (PZVAL_IS_REF(value)) {
SEPARATE_ZVAL(&value);
}
- zend_hash_quick_update(prop_table, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo);
+ zend_u_hash_quick_update(prop_table, utype, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo);
}
}
/* }}} */
@@ -3943,12 +4010,13 @@ static zend_object_handlers *zend_std_obj_handlers;
/* {{{ _reflection_write_property */
static void _reflection_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
{
- if (Z_TYPE_P(member) == IS_STRING
- && zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
- && (!strcmp(Z_STRVAL_P(member), "name") || !strcmp(Z_STRVAL_P(member), "class")))
+ if ((Z_TYPE_P(member) == IS_STRING || Z_TYPE_P(member) == IS_UNICODE)
+ && zend_u_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member)+1)
+ && (ZEND_U_EQUAL(Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member), "name", sizeof("name")-1) ||
+ ZEND_U_EQUAL(Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member), "class", sizeof("class")-1)))
{
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Cannot set read-only property %s::$%s", Z_OBJCE_P(object)->name, Z_STRVAL_P(member));
+ "Cannot set read-only property %v::$%R", Z_OBJCE_P(object)->name, Z_TYPE_P(member), Z_UNIVAL_P(member));
}
else
{
@@ -4038,6 +4106,20 @@ ZEND_API void zend_register_reflection_api(TSRMLS_D) {
}
/* }}} */
+void init_reflection_api(TSRMLS_D)
+{
+ reflection_exception_ptr = zend_get_named_class_entry("ReflectionException", sizeof("ReflectionException")-1 TSRMLS_CC);
+ reflection_ptr = zend_get_named_class_entry("Reflection", sizeof("Reflection")-1 TSRMLS_CC);
+ reflector_ptr = zend_get_named_class_entry("Reflector", sizeof("Reflector")-1 TSRMLS_CC);
+ reflection_function_ptr = zend_get_named_class_entry("ReflectionFunction", sizeof("ReflectionFunction")-1 TSRMLS_CC);
+ reflection_parameter_ptr = zend_get_named_class_entry("ReflectionParameter", sizeof("ReflectionParameter")-1 TSRMLS_CC);
+ reflection_method_ptr = zend_get_named_class_entry("ReflectionMethod", sizeof("ReflectionMethod")-1 TSRMLS_CC);
+ reflection_class_ptr = zend_get_named_class_entry("ReflectionClass", sizeof("ReflectionClass")-1 TSRMLS_CC);
+ reflection_object_ptr = zend_get_named_class_entry("ReflectionObject", sizeof("ReflectionObject")-1 TSRMLS_CC);
+ reflection_property_ptr = zend_get_named_class_entry("ReflectionProperty", sizeof("ReflectionProperty")-1 TSRMLS_CC);
+ reflection_extension_ptr = zend_get_named_class_entry("ReflectionExtension", sizeof("ReflectionExtension")-1 TSRMLS_CC);
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/Zend/zend_reflection_api.h b/Zend/zend_reflection_api.h
index fb06af4687..a16ed9b7f9 100644
--- a/Zend/zend_reflection_api.h
+++ b/Zend/zend_reflection_api.h
@@ -26,6 +26,8 @@ BEGIN_EXTERN_C()
ZEND_API void zend_register_reflection_api(TSRMLS_D);
ZEND_API void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_DC);
+void init_reflection_api(TSRMLS_D);
+
END_EXTERN_C()
#endif
diff --git a/Zend/zend_strtod.c b/Zend/zend_strtod.c
index 87d755006a..1810c5bf27 100644
--- a/Zend/zend_strtod.c
+++ b/Zend/zend_strtod.c
@@ -90,6 +90,8 @@
*/
#include <zend_strtod.h>
+#include <unicode/utypes.h>
+#include <unicode/ustdio.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -1778,3 +1780,23 @@ zend_strtod
result = sign ? -value(rv) : value(rv);
return result;
}
+
+/* UTODO: someone can reimplement this using the code above, if they really want to. */
+ZEND_API double zend_u_strtod(const UChar *nptr, UChar **endptr)
+{
+ double value;
+ int32_t num_conv = 0, num_read = 0;
+
+ num_conv = u_sscanf(nptr, "%f%n", &value, &num_read);
+ if (num_conv != EOF) {
+ if (endptr != 0) {
+ *endptr = (UChar *)nptr + num_read;
+ }
+ return value;
+ } else {
+ if (endptr != 0) {
+ *endptr = (UChar *)nptr;
+ }
+ return 0;
+ }
+}
diff --git a/Zend/zend_strtol.c b/Zend/zend_strtol.c
new file mode 100644
index 0000000000..9a56cac107
--- /dev/null
+++ b/Zend/zend_strtol.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unicode/utypes.h>
+#include <unicode/uchar.h>
+
+/*
+ * Convert a Unicode string to a long integer.
+ *
+ * Ignores `locale' stuff.
+ */
+long
+zend_u_strtol(nptr, endptr, base)
+ const UChar *nptr;
+ UChar **endptr;
+ register int base;
+{
+ register const UChar *s = nptr;
+ register unsigned long acc;
+ register UChar c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
+ register int32_t val;
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ do {
+ c = *s++;
+ } while (u_isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ (c == '0')
+ && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = (c == '0') ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+ cutlim = cutoff % (unsigned long)base;
+ cutoff /= (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if ((val = u_digit(c, base)) < 0)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += val;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (UChar *)(any ? s - 1 : nptr);
+ return (acc);
+}
diff --git a/Zend/zend_unicode.c b/Zend/zend_unicode.c
new file mode 100644
index 0000000000..edaf9568a2
--- /dev/null
+++ b/Zend/zend_unicode.c
@@ -0,0 +1,597 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2004 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrei Zmievski <andrei@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+#include "zend.h"
+#include "zend_globals.h"
+#include "zend_operators.h"
+#include "zend_API.h"
+#include "zend_unicode.h"
+#include <unicode/unorm.h>
+
+#ifdef ZTS
+ZEND_API ts_rsrc_id unicode_globals_id;
+#else
+ZEND_API zend_unicode_globals unicode_globals;
+#endif
+
+static void zend_from_unicode_substitute_cb(
+ const void *context,
+ UConverterFromUnicodeArgs *toUArgs,
+ const char *codeUnits,
+ int32_t length,
+ UConverterCallbackReason reason,
+ UErrorCode *err
+ )
+{
+ if (context == NULL) {
+ if (reason > UCNV_IRREGULAR)
+ {
+ return;
+ }
+
+ *err = U_ZERO_ERROR;
+ //ucnv_cbFromUWriteSub(fromArgs, 0, err);
+ return;
+ } else if (*((char*)context)=='i') {
+ if (reason != UCNV_UNASSIGNED)
+ {
+ /* the caller must have set
+ * the error code accordingly
+ */
+ return;
+ } else {
+ *err = U_ZERO_ERROR;
+ //ucnv_cbFromUWriteSub(fromArgs, 0, err);
+ return;
+ }
+ }
+}
+
+/* {{{ zend_set_converter_error_mode */
+void zend_set_converter_error_mode(UConverter *conv, uint8_t error_mode)
+{
+ UErrorCode status = U_ZERO_ERROR;
+
+ switch (error_mode) {
+ case ZEND_FROM_U_ERROR_STOP:
+ ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_STOP, NULL, NULL, NULL, &status);
+ break;
+
+ case ZEND_FROM_U_ERROR_SKIP:
+ ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_SKIP, UCNV_SKIP_STOP_ON_ILLEGAL, NULL, NULL, &status);
+ break;
+
+ case ZEND_FROM_U_ERROR_ESCAPE:
+ /* UTODO replace with custom callback for various substitution patterns */
+ ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_UNICODE, NULL, NULL, &status);
+ break;
+
+ case ZEND_FROM_U_ERROR_SUBST:
+ ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_SUBSTITUTE, UCNV_SKIP_STOP_ON_ILLEGAL, NULL, NULL, &status);
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+}
+/* }}} */
+
+/* {{{ zend_set_converter_subst_char */
+void zend_set_converter_subst_char(UConverter *conv, UChar *subst_char, int8_t subst_char_len)
+{
+ char dest[8];
+ int8_t dest_len = 8;
+ UErrorCode status = U_ZERO_ERROR;
+ UErrorCode temp = U_ZERO_ERROR;
+ const void *old_context;
+ UConverterFromUCallback old_cb;
+
+ if (!subst_char_len)
+ return;
+
+ ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_STOP, NULL, &old_cb, &old_context, &temp);
+ dest_len = ucnv_fromUChars(conv, dest, dest_len, subst_char, subst_char_len, &status);
+ ucnv_setFromUCallBack(conv, old_cb, old_context, NULL, NULL, &temp);
+ if (U_FAILURE(status)) {
+ zend_error(E_WARNING, "Could not set substitution character for the converter");
+ return;
+ }
+ ucnv_setSubstChars(conv, dest, dest_len, &status);
+ if (status == U_ILLEGAL_ARGUMENT_ERROR) {
+ zend_error(E_WARNING, "Substitution character byte sequence is too short or long for this converter");
+ return;
+ }
+}
+/* }}} */
+
+/* {{{ zend_set_converter_encoding */
+int zend_set_converter_encoding(UConverter **converter, const char *encoding)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UConverter *new_converter = NULL;
+
+ if (!converter) {
+ return FAILURE;
+ }
+
+ /*
+ * The specified encoding might be the same as converter's existing one,
+ * which results in a no-op.
+ */
+ if (*converter && encoding && encoding[0]) {
+ const char *current = ucnv_getName(*converter, &status);
+ status = U_ZERO_ERROR; /* reset error */
+ if (!ucnv_compareNames(current, encoding)) {
+ return SUCCESS;
+ }
+ }
+
+ /*
+ * If encoding is NULL, ucnv_open() will return a converter based on
+ * the default platform encoding as determined by ucnv_getDefaultName().
+ */
+ new_converter = ucnv_open(encoding, &status);
+ if (U_FAILURE(status)) {
+ return FAILURE;
+ }
+
+ if (*converter) {
+ ucnv_close(*converter);
+ }
+ *converter = new_converter;
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ zend_copy_converter */
+int zend_copy_converter(UConverter **target, UConverter *source)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ const char *encoding;
+
+ assert(source != NULL);
+
+ encoding = ucnv_getName(source, &status);
+ if (U_FAILURE(status)) {
+ return FAILURE;
+ }
+
+ return zend_set_converter_encoding(target, encoding);
+}
+/* }}} */
+
+/* {{{ zend_convert_to_unicode */
+ZEND_API void zend_convert_to_unicode(UConverter *conv, UChar **target, int32_t *target_len, const char *source, int32_t source_len, UErrorCode *status)
+{
+ UChar *buffer = NULL;
+ UChar *output;
+ int32_t buffer_len = 0;
+ int32_t converted = 0;
+ const char *input = source;
+ UConverterType conv_type;
+
+ if (U_FAILURE(*status)) {
+ return;
+ }
+
+ ucnv_resetToUnicode(conv);
+ conv_type = ucnv_getType(conv);
+
+ switch (conv_type) {
+ case UCNV_SBCS:
+ case UCNV_LATIN_1:
+ case UCNV_US_ASCII:
+ /*
+ * For single-byte charsets, 1 input byte = 1 output UChar
+ */
+ buffer_len = source_len;
+ break;
+
+ default:
+ /*
+ * Initial estimate: 1.25 UChar's for every 2 source bytes + 2 (past a
+ * certain limit (2)). The rationale behind this is that (atleast
+ * in the case of GB2312) it is possible that there are single byte
+ * characters in the input string. By using an GD2312 text as
+ * example it seemed that a value of 1.25 allowed for as little
+ * re-allocations as possible without over estimating the buffer
+ * too much. In case there is a lot of single-byte characters
+ * around a single multi-byte character this estimation is too low,
+ * and then the re-allocation routines in the loop below kick in.
+ * Here we multiply by 1.33 and add 1 so that it's even quite
+ * efficient for smaller input strings without causing too much
+ * iterations of this loop.
+ */
+ buffer_len = (source_len > 2) ? ((source_len >> 1) + (source_len >> 3) + 2) : source_len;
+ break;
+ }
+
+ while (1) {
+ buffer = eurealloc(buffer, buffer_len + 1);
+ output = buffer + converted;
+ ucnv_toUnicode(conv, &output, buffer + buffer_len, &input, source + source_len, NULL, TRUE, status);
+ converted = (int32_t) (output - buffer);
+ if (*status == U_BUFFER_OVERFLOW_ERROR) {
+ buffer_len = (buffer_len * 1.33) + 1;
+ *status = U_ZERO_ERROR;
+ } else {
+ break;
+ }
+ }
+
+ /*
+ * We return the buffer in case of failure anyway. The caller may want to
+ * use partially converted string for something.
+ */
+
+ buffer[converted] = 0;
+ *target = buffer;
+ *target_len = converted;
+}
+/* }}} */
+
+/* {{{ zend_convert_from_unicode */
+ZEND_API void zend_convert_from_unicode(UConverter *conv, char **target, int32_t *target_len, const UChar *source, int32_t source_len, UErrorCode *status)
+{
+ char *buffer = NULL;
+ char *output;
+ int32_t buffer_len = 0;
+ int32_t converted = 0;
+ const UChar *input = source;
+
+ if (U_FAILURE(*status)) {
+ return;
+ }
+
+ ucnv_resetFromUnicode(conv);
+
+ buffer_len = ucnv_getMaxCharSize(conv) * source_len;
+
+ while (1) {
+ buffer = erealloc(buffer, buffer_len + 1);
+ output = buffer + converted;
+ ucnv_fromUnicode(conv, &output, buffer + buffer_len, &input, source + source_len, NULL, TRUE, status);
+ converted = (int32_t) (output - buffer);
+ if (*status == U_BUFFER_OVERFLOW_ERROR) {
+ buffer_len += 64;
+ *status = U_ZERO_ERROR;
+ } else {
+ break;
+ }
+ }
+
+ /*
+ * We return the buffer in case of failure anyway. The caller may want to
+ * use partially converted string for something.
+ */
+
+ buffer[converted] = 0; /* NULL-terminate the output string */
+ *target = buffer;
+ *target_len = converted;
+
+ /* Report the conversion error */
+ if (U_FAILURE(*status)) {
+ zend_error(E_NOTICE, "Error converting from Unicode to codepage string: %s", u_errorName(*status));
+ }
+}
+/* }}} */
+
+/* {{{ zend_convert_encodings */
+ZEND_API void zend_convert_encodings(UConverter *target_conv, UConverter *source_conv,
+ char **target, int32_t *target_len,
+ const char *source, int32_t source_len, UErrorCode *status)
+{
+ char *buffer = NULL;
+ char *output;
+ const char *input = source;
+ int32_t allocated = 0;
+ int32_t converted = 0;
+ int8_t null_size;
+ UChar pivot_buf[1024], *pivot, *pivot2;
+
+ if (U_FAILURE(*status)) {
+ return;
+ }
+
+ null_size = ucnv_getMinCharSize(target_conv);
+ allocated = source_len + null_size;
+
+ ucnv_resetToUnicode(source_conv);
+ ucnv_resetFromUnicode(target_conv);
+ pivot = pivot2 = pivot_buf;
+
+ while (1) {
+ buffer = (char *) erealloc(buffer, allocated);
+ output = buffer + converted;
+ ucnv_convertEx(target_conv, source_conv, &output, buffer + allocated - null_size,
+ &input, source + source_len, pivot_buf, &pivot, &pivot2, pivot_buf + 1024, FALSE, TRUE, status);
+ converted = (int32_t) (output - buffer);
+ if (*status == U_BUFFER_OVERFLOW_ERROR) {
+ allocated += 1024;
+ *status = U_ZERO_ERROR;
+ } else {
+ break;
+ }
+ }
+
+ memset(buffer + converted, 0, null_size); /* NULL-terminate the output string */
+ *target = buffer;
+ *target_len = converted;
+
+ /* Report the conversion error */
+ if (U_FAILURE(*status)) {
+ zend_error(E_NOTICE, "Error converting from codepage string to Unicode: %s", u_errorName(*status));
+ }
+}
+/* }}} */
+
+/* {{{ zval_unicode_to_string */
+ZEND_API int zval_unicode_to_string(zval *string, UConverter *conv TSRMLS_DC)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int retval = TRUE;
+ char *s = NULL;
+ int s_len;
+
+#if 0
+ /* UTODO Putting it here for now, until we figure out the framework */
+ switch (UG(from_u_error_mode)) {
+ case ZEND_FROM_U_ERROR_STOP:
+ ucnv_setFromUCallBack(UG(runtime_encoding_conv), UCNV_FROM_U_CALLBACK_STOP, NULL, NULL, NULL, &status);
+ break;
+
+ case ZEND_FROM_U_ERROR_SKIP:
+ ucnv_setFromUCallBack(UG(runtime_encoding_conv), UCNV_FROM_U_CALLBACK_SKIP, NULL, NULL, NULL, &status);
+ break;
+
+ case ZEND_FROM_U_ERROR_ESCAPE:
+ ucnv_setFromUCallBack(UG(runtime_encoding_conv), UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_UNICODE, NULL, NULL, &status);
+ break;
+
+ case ZEND_FROM_U_ERROR_SUBST:
+ ucnv_setFromUCallBack(UG(runtime_encoding_conv), UCNV_FROM_U_CALLBACK_SUBSTITUTE, NULL, NULL, NULL, &status);
+ break;
+
+ default:
+ assert(0);
+ break;
+ }
+
+ if (UG(subst_chars)) {
+ char subchar[16];
+ int8_t char_len = 16;
+ status = U_ZERO_ERROR;
+ ucnv_getSubstChars(UG(runtime_encoding_conv), subchar, &char_len, &status);
+ if (U_FAILURE(status)) {
+ zend_error(E_WARNING, "Could not get substitution characters");
+ return FAILURE;
+ }
+ status = U_ZERO_ERROR;
+ ucnv_setSubstChars(UG(runtime_encoding_conv), UG(subst_chars), MIN(char_len, UG(subst_chars_len)), &status);
+ if (U_FAILURE(status)) {
+ zend_error(E_WARNING, "Could not set substitution characters");
+ return FAILURE;
+ }
+ }
+
+ status = U_ZERO_ERROR;
+#endif
+
+ UChar *u = Z_USTRVAL_P(string);
+ int32_t u_len = Z_USTRLEN_P(string);
+
+ Z_TYPE_P(string) = IS_STRING;
+ zend_convert_from_unicode(conv, &s, &s_len, u, u_len, &status);
+ ZVAL_STRINGL(string, s, s_len, 0);
+
+ if (U_FAILURE(status)) {
+ retval = FAILURE;
+ }
+
+ efree(u);
+ return retval;
+}
+/* }}} */
+
+/* {{{ zval_string_to_unicode */
+ZEND_API int zval_string_to_unicode(zval *string TSRMLS_DC)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ int retval = TRUE;
+ UChar *u = NULL;
+ int32_t u_len;
+
+ char *s = Z_STRVAL_P(string);
+ int s_len = Z_STRLEN_P(string);
+
+ Z_TYPE_P(string) = IS_UNICODE;
+ zend_convert_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u, &u_len, s, s_len, &status);
+ ZVAL_UNICODEL(string, u, u_len, 0);
+
+ if (U_FAILURE(status)) {
+ retval = FALSE;
+ }
+
+ efree(s);
+ return retval;
+}
+/* }}} */
+
+/* {{{ zend_cmp_unicode_and_string */
+ZEND_API int zend_cmp_unicode_and_string(UChar *ustr, char* str, uint len)
+{
+ UErrorCode status = U_ZERO_ERROR;
+ UChar *u = NULL;
+ int32_t u_len;
+ int retval = TRUE;
+ TSRMLS_FETCH();
+
+ zend_convert_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u, &u_len, str, len, &status);
+ if (U_FAILURE(status)) {
+ efree(u);
+ return FALSE;
+ }
+ retval = u_memcmp(ustr, u, u_len);
+ efree(u);
+ return retval;
+}
+/* }}} */
+
+/* {{{ zend_cmp_unicode_and_literal */
+/*
+ * Compare a Unicode string and an ASCII literal. Because ASCII maps nicely onto Unicode
+ * range U+0000 .. U+007F, we can simply casst ASCII chars to Unicode values and avoid
+ * memory allocation.
+ */
+ZEND_API int zend_cmp_unicode_and_literal(UChar *ustr, int32_t ulen, char *str, int32_t slen)
+{
+ int32_t result;
+ uint len = MIN(ulen, slen);
+
+ while (len--) {
+ result = (int32_t)(uint16_t)*ustr - (int32_t)(uint16_t)*str;
+ if (result != 0)
+ return result;
+ ustr++;
+ str++;
+ }
+
+ return ulen - slen;
+}
+/* }}} */
+
+/* {{{ zend_is_valid_identifier */
+ZEND_API int zend_is_valid_identifier(UChar *ident, int32_t ident_len)
+{
+ UChar32 codepoint;
+ int32_t i;
+ UProperty id_prop = UCHAR_XID_START;
+
+ for (i = 0; i < ident_len; ) {
+ U16_NEXT(ident, i, ident_len, codepoint);
+ if (!u_hasBinaryProperty(codepoint, id_prop) &&
+ codepoint != 0x5f) { /* special case for starting '_' */
+ return 0;
+ }
+ id_prop = UCHAR_XID_CONTINUE;
+ }
+
+ return 1;
+}
+/* }}} */
+
+/* {{{ zend_normalize_string */
+static inline void zend_normalize_string(UChar **dest, int32_t *dest_len, UChar *src, int32_t src_len, UErrorCode *status)
+{
+ UChar *buffer = NULL;
+ int32_t buffer_len;
+
+ buffer_len = src_len;
+ while (1) {
+ *status = U_ZERO_ERROR;
+ buffer = eurealloc(buffer, buffer_len+1);
+ buffer_len = unorm_normalize(src, src_len, UNORM_NFKC, 0, buffer, buffer_len, status);
+ if (*status != U_BUFFER_OVERFLOW_ERROR) {
+ break;
+ }
+ }
+ if (U_SUCCESS(*status)) {
+ buffer[buffer_len] = 0;
+ *dest = buffer;
+ *dest_len = buffer_len;
+ } else {
+ efree(buffer);
+ }
+}
+/* }}} */
+
+/* {{{ zend_case_fold_string */
+ZEND_API void zend_case_fold_string(UChar **dest, int32_t *dest_len, UChar *src, int32_t src_len, uint32_t options, UErrorCode *status)
+{
+ UChar *buffer = NULL;
+ int32_t buffer_len;
+
+ buffer_len = src_len;
+ while (1) {
+ *status = U_ZERO_ERROR;
+ buffer = eurealloc(buffer, buffer_len+1);
+ buffer_len = u_strFoldCase(buffer, buffer_len, src, src_len, options, status);
+ if (*status != U_BUFFER_OVERFLOW_ERROR) {
+ break;
+ }
+ }
+ if (U_SUCCESS(*status)) {
+ buffer[buffer_len] = 0;
+ *dest = buffer;
+ *dest_len = buffer_len;
+ } else {
+ efree(buffer);
+ }
+}
+/* }}} */
+
+/* {{{ zend_normalize_identifier */
+ZEND_API int zend_normalize_identifier(UChar **dest, int32_t *dest_len, UChar *ident, int32_t ident_len, zend_bool fold_case)
+{
+ UChar *buffer = NULL;
+ UChar *orig_ident = ident;
+ int32_t buffer_len;
+ UErrorCode status = U_ZERO_ERROR;
+
+ if (unorm_quickCheck(ident, ident_len, UNORM_NFKC, &status) != UNORM_YES) {
+ zend_normalize_string(&buffer, &buffer_len, ident, ident_len, &status);
+ if (U_FAILURE(status)) {
+ return 0;
+ }
+ ident = buffer;
+ ident_len = buffer_len;
+ }
+
+ if (fold_case) {
+ zend_case_fold_string(&buffer, &buffer_len, ident, ident_len, U_FOLD_CASE_DEFAULT, &status);
+ if (ident != orig_ident) {
+ efree(ident);
+ }
+ if (U_FAILURE(status)) {
+ return 0;
+ }
+ ident = buffer;
+ ident_len = buffer_len;
+
+ if (unorm_quickCheck(ident, ident_len, UNORM_NFKC, &status) != UNORM_YES) {
+ zend_normalize_string(&buffer, &buffer_len, ident, ident_len, &status);
+ if (ident != orig_ident) {
+ efree(ident);
+ }
+ if (U_FAILURE(status)) {
+ return 0;
+ }
+ ident = buffer;
+ ident_len = buffer_len;
+ }
+ }
+
+ *dest = ident;
+ *dest_len = ident_len;
+ return 1;
+}
+/* }}} */
+
+/* vim: set fdm=marker et sts=4: */
diff --git a/Zend/zend_unicode.h b/Zend/zend_unicode.h
new file mode 100644
index 0000000000..950dc7c1fd
--- /dev/null
+++ b/Zend/zend_unicode.h
@@ -0,0 +1,90 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2004 Zend Technologies Ltd. (http://www.zend.com) |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 2.00 of the Zend license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available at through the world-wide-web at |
+ | http://www.zend.com/license/2_00.txt. |
+ | If you did not receive a copy of the Zend license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@zend.com so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrei Zmievski <andrei@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef ZEND_UNICODE_H
+#define ZEND_UNICODE_H
+
+#include "zend.h"
+#include <unicode/utypes.h>
+#include <unicode/ustring.h>
+#include <unicode/ucnv.h>
+#include <unicode/ustdio.h>
+#include <unicode/uchar.h>
+#include <unicode/uloc.h>
+#include <unicode/ucol.h>
+
+#define ZEND_FROM_U_ERROR_STOP 0
+#define ZEND_FROM_U_ERROR_SKIP 1
+#define ZEND_FROM_U_ERROR_SUBST 2
+#define ZEND_FROM_U_ERROR_ESCAPE 3
+
+/* internal functions */
+
+int zend_set_converter_encoding(UConverter **converter, const char *encoding);
+void zend_set_converter_subst_char(UConverter *conv, UChar *subst_char, int8_t subst_char_len);
+void zend_set_converter_error_mode(UConverter *conv, uint8_t error_mode);
+
+
+/* API functions */
+
+ZEND_API void zend_convert_to_unicode(UConverter *conv, UChar **target, int32_t *target_len, const char *source, int32_t source_len, UErrorCode *status);
+ZEND_API void zend_convert_from_unicode(UConverter *conv, char **target, int32_t *target_len, const UChar *source, int32_t source_len, UErrorCode *status);
+ZEND_API void zend_convert_encodings(UConverter *target_conv, UConverter *source_conv, char **target, int32_t *target_len, const char *source, int32_t source_len, UErrorCode *status);
+ZEND_API int zval_string_to_unicode(zval *string TSRMLS_DC);
+ZEND_API int zval_unicode_to_string(zval *string, UConverter *conv TSRMLS_DC);
+
+ZEND_API int zend_cmp_unicode_and_string(UChar *ustr, char* str, uint len);
+ZEND_API int zend_cmp_unicode_and_literal(UChar *ustr, int32_t ulen, char* str, int32_t slen);
+
+ZEND_API void zend_case_fold_string(UChar **dest, int32_t *dest_len, UChar *src, int32_t src_len, uint32_t options, UErrorCode *status);
+
+ZEND_API int zend_is_valid_identifier(UChar *ident, int32_t ident_len);
+ZEND_API int zend_normalize_identifier(UChar **dest, int32_t *dest_len, UChar *ident, int32_t ident_len, zend_bool fold_case);
+
+/*
+ * Function to get a codepoint at position n. Iterates over codepoints starting from the
+ * beginning of the string. Does not check for n > length, this is left up to the caller.
+ */
+static inline UChar32 zend_get_codepoint_at(UChar *str, int32_t length, int32_t n)
+{
+ int32_t offset = 0;
+ UChar32 c = 0;
+
+ U16_FWD_N(str, offset, length, n);
+ U16_GET(str, 0, offset, length, c);
+
+ return c;
+}
+
+#define ZEND_U_CONVERTER(c) ((c)?(c):UG(fallback_encoding_conv))
+
+#define USTR_FREE(ustr) do { if (ustr) { efree(ustr); } } while (0);
+#define UBYTES(len) ((len) * sizeof(UChar))
+#define USTR_LEN(str) (UG(unicode)?u_strlen((UChar*)(str)):strlen((char*)(str)))
+
+#define USTR_MAKE(cs) zend_ascii_to_unicode(cs, sizeof(cs) ZEND_FILE_LINE_CC)
+#define USTR_MAKE_REL(cs) zend_ascii_to_unicode(cs, sizeof(cs) ZEND_FILE_LINE_RELAY_CC)
+static inline UChar* zend_ascii_to_unicode(const char *cs, size_t cs_size ZEND_FILE_LINE_DC)
+{
+ /* u_charsToUChars() takes care of the terminating NULL */
+ UChar *us = eumalloc_rel(cs_size);
+ u_charsToUChars(cs, us, cs_size);
+ return us;
+}
+
+#endif /* ZEND_UNICODE_H */
diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c
index 3bedc0a4ad..7d5b208ca1 100644
--- a/Zend/zend_variables.c
+++ b/Zend/zend_variables.c
@@ -30,11 +30,21 @@
ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
{
switch (zvalue->type & ~IS_CONSTANT_INDEX) {
+ case IS_CONSTANT: {
+ TSRMLS_FETCH();
+
+ if (UG(unicode)) goto dtor_unicode;
+ }
case IS_STRING:
- case IS_CONSTANT:
+ case IS_BINARY:
CHECK_ZVAL_STRING_REL(zvalue);
STR_FREE_REL(zvalue->value.str.val);
break;
+ case IS_UNICODE:
+dtor_unicode:
+ CHECK_ZVAL_UNICODE_REL(zvalue);
+ STR_FREE_REL(zvalue->value.ustr.val);
+ break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY: {
TSRMLS_FETCH();
@@ -74,11 +84,21 @@ ZEND_API void _zval_dtor_func(zval *zvalue ZEND_FILE_LINE_DC)
ZEND_API void _zval_internal_dtor(zval *zvalue ZEND_FILE_LINE_DC)
{
switch (zvalue->type & ~IS_CONSTANT_INDEX) {
+ case IS_CONSTANT: {
+ TSRMLS_FETCH();
+
+ if (UG(unicode)) goto dtor_unicode;
+ }
case IS_STRING:
- case IS_CONSTANT:
+ case IS_BINARY:
CHECK_ZVAL_STRING_REL(zvalue);
free(zvalue->value.str.val);
break;
+ case IS_UNICODE:
+dtor_unicode:
+ CHECK_ZVAL_UNICODE_REL(zvalue);
+ free(zvalue->value.ustr.val);
+ break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY:
case IS_OBJECT:
@@ -114,11 +134,21 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
case IS_LONG:
case IS_NULL:
break;
- case IS_CONSTANT:
+ case IS_CONSTANT: {
+ TSRMLS_FETCH();
+
+ if (UG(unicode)) goto copy_unicode;
+ }
case IS_STRING:
+ case IS_BINARY:
CHECK_ZVAL_STRING_REL(zvalue);
zvalue->value.str.val = (char *) estrndup_rel(zvalue->value.str.val, zvalue->value.str.len);
break;
+ case IS_UNICODE:
+copy_unicode:
+ CHECK_ZVAL_UNICODE_REL(zvalue);
+ zvalue->value.ustr.val = eustrndup_rel(zvalue->value.ustr.val, zvalue->value.ustr.len);
+ break;
case IS_ARRAY:
case IS_CONSTANT_ARRAY: {
zval *tmp;
@@ -130,7 +160,7 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
return; /* do nothing */
}
ALLOC_HASHTABLE_REL(tmp_ht);
- zend_hash_init(tmp_ht, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(tmp_ht, 0, NULL, ZVAL_PTR_DTOR, 0, original_ht->unicode);
zend_hash_copy(tmp_ht, original_ht, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
zvalue->value.ht = tmp_ht;
}
@@ -144,7 +174,6 @@ ZEND_API void _zval_copy_ctor_func(zval *zvalue ZEND_FILE_LINE_DC)
}
}
-
ZEND_API int zend_print_variable(zval *var)
{
return zend_print_zval(var, 0);
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index b96d1a1e7f..52bfccf37d 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -886,11 +886,27 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMP|VAR|CV, ANY)
zval *z = GET_OP1_ZVAL_PTR(BP_VAR_R);
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
- zend_std_cast_object_tostring(z, &z_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
- zend_print_variable(z);
+ UErrorCode status = U_ZERO_ERROR;
+ /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+ if (opline->extended_value &&
+ strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+ ucnv_getName(ZEND_U_CONVERTER(UG(script_encoding_conv)), &status))) {
+ zval z_conv;
+ zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_U_CONVERTER(UG(script_encoding_conv)), &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+ z_conv.type = IS_BINARY;
+ if (U_SUCCESS(status)) {
+ zend_print_variable(&z_conv);
+ } else {
+ zend_error(E_WARNING, "Could not convert inline HTML for output");
+ }
+ zval_dtor(&z_conv);
+ } else {
+ zend_print_variable(z);
+ }
}
FREE_OP1();
@@ -932,23 +948,23 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, ANY, int type
ZEND_VM_NEXT_OPCODE();
}
*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_u_hash_update(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
@@ -956,6 +972,10 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMP|VAR|CV, ANY, int type
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
+ if (OP1_TYPE != IS_TMP_VAR) {
+ FREE_OP1();
+ }
+ break;
case ZEND_FETCH_LOCAL:
FREE_OP1();
break;
@@ -1519,11 +1539,18 @@ ZEND_VM_HANDLER(53, ZEND_INIT_STRING, ANY, ANY)
{
zval *tmp = &EX_T(EX(opline)->result.u.var).tmp_var;
- tmp->value.str.val = emalloc(1);
- tmp->value.str.val[0] = 0;
- tmp->value.str.len = 0;
+ if (EX(opline)->extended_value == IS_UNICODE) {
+ tmp->value.ustr.val = eumalloc(1);
+ tmp->value.ustr.val[0] = 0;
+ tmp->value.ustr.len = 0;
+ tmp->type = IS_UNICODE;
+ } else {
+ tmp->value.str.val = emalloc(1);
+ tmp->value.str.val[0] = 0;
+ tmp->value.str.len = 0;
+ tmp->type = EX(opline)->extended_value;
+ }
tmp->refcount = 1;
- tmp->type = IS_STRING;
tmp->is_ref = 0;
ZEND_VM_NEXT_OPCODE();
}
@@ -1534,8 +1561,8 @@ ZEND_VM_HANDLER(54, ZEND_ADD_CHAR, TMP, CONST)
zend_free_op free_op1;
add_char_to_string(&EX_T(opline->result.u.var).tmp_var,
- GET_OP1_ZVAL_PTR(BP_VAR_NA),
- &opline->op2.u.constant);
+ GET_OP1_ZVAL_PTR(BP_VAR_NA),
+ &opline->op2.u.constant);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
ZEND_VM_NEXT_OPCODE();
}
@@ -1546,8 +1573,8 @@ ZEND_VM_HANDLER(55, ZEND_ADD_STRING, TMP, CONST)
zend_free_op free_op1;
add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
- GET_OP1_ZVAL_PTR(BP_VAR_NA),
- &opline->op2.u.constant);
+ GET_OP1_ZVAL_PTR(BP_VAR_NA),
+ &opline->op2.u.constant);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
ZEND_VM_NEXT_OPCODE();
}
@@ -1560,13 +1587,16 @@ ZEND_VM_HANDLER(56, ZEND_ADD_VAR, TMP, TMP|VAR|CV)
zval var_copy;
int use_copy;
- zend_make_printable_zval(var, &var_copy, &use_copy);
+ if (opline->extended_value == IS_UNICODE) {
+ zend_make_unicode_zval(var, &var_copy, &use_copy);
+ } else {
+ zend_make_printable_zval(var, &var_copy, &use_copy);
+ }
if (use_copy) {
var = &var_copy;
}
- add_string_to_string( &EX_T(opline->result.u.var).tmp_var,
- GET_OP1_ZVAL_PTR(BP_VAR_NA),
- var);
+ add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
+ GET_OP1_ZVAL_PTR(BP_VAR_NA), var);
if (use_copy) {
zval_dtor(var);
}
@@ -1600,7 +1630,8 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMP|VAR|UNUSED|CV)
EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
break;
case IS_STRING:
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ case IS_UNICODE:
+ EX_T(opline->result.u.var).class_entry = zend_u_fetch_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), opline->extended_value TSRMLS_CC);
break;
default:
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
@@ -1618,17 +1649,19 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -1642,10 +1675,10 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, TMP|VAR|UNUSED|CV, CONST|TMP|VAR|CV)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -1685,21 +1718,20 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, ANY, CONST|TMP|VAR|UNUSED|CV)
ce = EX_T(opline->op1.u.var).class_entry;
if(OP2_TYPE != IS_UNUSED) {
char *function_name_strval;
- int function_name_strlen;
+ unsigned int function_name_strlen;
zend_bool is_const = (OP2_TYPE == IS_CONST);
zend_free_op free_op2;
if (is_const) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name_strval = Z_UNIVAL(opline->op2.u.constant);
+ function_name_strlen = Z_UNILEN(opline->op2.u.constant);
} else {
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen);
}
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
@@ -1733,29 +1765,28 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST|TMP|VAR|CV)
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function;
- char *function_name_strval, *lcname;
- int function_name_strlen;
+ void *function_name_strval, *lcname;
+ unsigned int function_name_strlen, lcname_len;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
if (OP2_TYPE == IS_CONST) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name = &opline->op2.u.constant;
} else {
function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
}
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
+ lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_STRVAL_P(function_name), function_name_strlen, 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
efree(lcname);
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
}
efree(lcname);
@@ -1782,7 +1813,8 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
zend_bool should_change_scope;
if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
+ /* FIXME: output identifiers properly */
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %v::%v()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
@@ -1814,7 +1846,8 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
severity = E_ERROR;
severity_word = "cannot";
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name, severity_word);
+ /* FIXME: output identifiers properly */
+ zend_error(severity, "Non-static method %v::%v() %s be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name, severity_word);
}
}
if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
@@ -1862,7 +1895,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
EX(function_state).function_symbol_table = *(EG(symtable_cache_ptr)--);
} else {
ALLOC_HASHTABLE(EX(function_state).function_symbol_table);
- zend_hash_init(EX(function_state).function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(EX(function_state).function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
/*printf("Cache miss! Initialized %x\n", function_state.function_symbol_table);*/
}
calling_symbol_table = EG(active_symbol_table);
@@ -1968,8 +2001,9 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
- if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
- zend_error_noreturn(E_ERROR, "Unknown function: %s()\n", fname->value.str.val);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(fname), Z_UNIVAL_P(fname), Z_UNILEN_P(fname)+1, (void **) &EX(function_state).function)==FAILURE) {
+ /* FIXME: output identifiers properly */
+ zend_error_noreturn(E_ERROR, "Unknown function: %R()\n", Z_TYPE_P(fname), Z_UNIVAL_P(fname));
}
EX(object) = NULL;
EX(calling_scope) = EX(function_state).function->common.scope;
@@ -2031,9 +2065,9 @@ ZEND_VM_C_LABEL(return_by_value):
INIT_PZVAL_COPY(ret, retval_ptr);
dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", Z_OBJCE_P(retval_ptr)->name);
}
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(retval_ptr)->name);
ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC);
*EG(return_value_ptr_ptr) = ret;
if (!dup) {
@@ -2110,8 +2144,8 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, ANY, ANY)
}
}
- zend_hash_update(EG(active_symbol_table), opline->op2.u.constant.value.str.val,
- opline->op2.u.constant.value.str.len+1, &EG(exception), sizeof(zval *), (void **) NULL);
+ zend_u_hash_update(EG(active_symbol_table), Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
+ Z_UNILEN(opline->op2.u.constant)+1, &EG(exception), sizeof(zval *), (void **) NULL);
EG(exception) = NULL;
ZEND_VM_NEXT_OPCODE();
}
@@ -2243,9 +2277,9 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC);
if(ptr && ptr->op_array) {
- zend_error(E_WARNING, "Missing argument %ld for %s%s%s(), called in %s on line %d and defined", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
+ zend_error(E_WARNING, "Missing argument %ld for %v%s%v(), called in %s on line %d and defined", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
} else {
- zend_error(E_WARNING, "Missing argument %ld for %s%s%s()", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C));
+ zend_error(E_WARNING, "Missing argument %ld for %v%s%v()", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C));
}
if (opline->result.op_type == IS_VAR) {
PZVAL_UNLOCK_FREE(*EX_T(opline->result.u.var).var.ptr_ptr);
@@ -2400,7 +2434,7 @@ ZEND_VM_HANDLER(68, ZEND_NEW, ANY, ANY)
} else {
class_type = "abstract class";
}
- zend_error_noreturn(E_ERROR, "Cannot instantiate %s %s", class_type, EX_T(opline->op1.u.var).class_entry->name);
+ zend_error_noreturn(E_ERROR, "Cannot instantiate %s %v", class_type, EX_T(opline->op1.u.var).class_entry->name);
}
ALLOC_ZVAL(object_zval);
object_init_ex(object_zval, EX_T(opline->op1.u.var).class_entry);
@@ -2458,7 +2492,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY)
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (!clone_call) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", ce->name);
EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr);
EX_T(opline->result.u.var).var.ptr->refcount++;
}
@@ -2468,13 +2502,13 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMP|VAR|UNUSED|CV, ANY)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (ce != EG(scope)) {
- zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to private %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(clone->common.scope, EG(scope))) {
- zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@@ -2511,10 +2545,12 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, CONST|UNUSED, CONST)
}
}
*/
- if (!zend_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
- opline->op2.u.constant.value.str.val,
- opline->op2.u.constant.value.str.val);
+ if (!zend_get_constant(Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+ zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
+ Z_TYPE(opline->op2.u.constant),
+ Z_UNIVAL(opline->op2.u.constant),
+ Z_TYPE(opline->op2.u.constant),
+ Z_UNIVAL(opline->op2.u.constant));
EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
}
@@ -2523,12 +2559,12 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, CONST|UNUSED, CONST)
ce = EX_T(opline->op1.u.var).class_entry;
- if (zend_hash_find(&ce->constants_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
+ if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EX_T(opline->result.u.var).tmp_var = **value;
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
} else {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", opline->op2.u.constant.value.str.val);
+ zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
}
ZEND_VM_NEXT_OPCODE();
@@ -2587,7 +2623,9 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|UNUSED|CV, CONST|TMP|V
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -2643,13 +2681,27 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
zval var_copy;
int use_copy;
- zend_make_printable_zval(result, &var_copy, &use_copy);
+ zend_make_string_zval(result, &var_copy, &use_copy);
if (use_copy) {
zval_dtor(result);
*result = var_copy;
}
break;
}
+ case IS_UNICODE: {
+ zval var_copy;
+ int use_copy;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ break;
+ }
+ case IS_BINARY:
+ convert_to_binary(result);
+ break;
case IS_ARRAY:
convert_to_array(result);
break;
@@ -2672,7 +2724,14 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
zval tmp_inc_filename;
zend_bool failure_retval=0;
- if (inc_filename->type!=IS_STRING) {
+ if (UG(unicode) && opline->op2.u.constant.value.lval == ZEND_EVAL) {
+ if (inc_filename->type != IS_UNICODE) {
+ tmp_inc_filename = *inc_filename;
+ zval_copy_ctor(&tmp_inc_filename);
+ convert_to_unicode(&tmp_inc_filename);
+ inc_filename = &tmp_inc_filename;
+ }
+ } else if (inc_filename->type!=IS_STRING) {
tmp_inc_filename = *inc_filename;
zval_copy_ctor(&tmp_inc_filename);
convert_to_string(&tmp_inc_filename);
@@ -2789,10 +2848,10 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, ANY)
varname = GET_OP1_ZVAL_PTR(BP_VAR_R);
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -2800,17 +2859,17 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMP|VAR|CV, ANY)
zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1) == SUCCESS) {
+ if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) {
zend_execute_data *ex = EXECUTE_DATA;
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1);
do {
int i;
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
+ ex->op_array->vars[i].name_len == Z_UNILEN_P(varname) &&
+ !memcmp(ex->op_array->vars[i].name, Z_UNIVAL_P(varname), Z_TYPE_P(varname)==IS_UNICODE?UBYTES(Z_UNILEN_P(varname)):Z_UNILEN_P(varname))) {
ex->CVs[i] = NULL;
break;
}
@@ -2857,10 +2916,31 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = EXECUTE_DATA; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -2868,8 +2948,8 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -2877,7 +2957,11 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMP|VAR|CV)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -3008,7 +3092,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
FREE_OP1_IF_VAR();
}
if (!EG(exception)) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
+ zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %v did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
@@ -3043,8 +3127,11 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET, CONST|TMP|VAR|CV, ANY)
char *str_key;
uint str_key_len;
ulong int_key;
- if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
- && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ zend_uchar key_type;
+
+ key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
+ if (key_type != HASH_KEY_NON_EXISTANT &&
+ zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
break;
}
zend_hash_move_forward(fe_ht);
@@ -3106,11 +3193,16 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
zend_hash_move_forward(fe_ht);
- } while (key_type != HASH_KEY_IS_STRING || zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS);
+ } while (key_type == HASH_KEY_NON_EXISTANT || zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS);
if (use_key) {
- zend_unmangle_property_name(str_key, &class_name, &prop_name);
- str_key_len = strlen(prop_name);
- str_key = estrndup(prop_name, str_key_len);
+ zend_u_unmangle_property_name(key_type == HASH_KEY_IS_UNICODE?IS_UNICODE:IS_STRING, str_key, &class_name, &prop_name);
+ if (key_type == HASH_KEY_IS_UNICODE) {
+ str_key_len = u_strlen((UChar*)prop_name);
+ str_key = (char*)eustrndup((UChar*)prop_name, str_key_len);
+ } else {
+ str_key_len = strlen(prop_name);
+ str_key = estrndup(prop_name, str_key_len);
+ }
str_key_len++;
}
break;
@@ -3200,6 +3292,16 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH, VAR, ANY)
key->value.str.len = str_key_len-1;
key->type = IS_STRING;
break;
+ case HASH_KEY_IS_BINARY:
+ key->value.str.val = str_key;
+ key->value.str.len = str_key_len-1;
+ key->type = IS_BINARY;
+ break;
+ case HASH_KEY_IS_UNICODE:
+ key->value.ustr.val = (UChar*)str_key;
+ key->value.ustr.len = str_key_len-1;
+ key->type = IS_UNICODE;
+ break;
case HASH_KEY_IS_LONG:
key->value.lval = int_key;
key->type = IS_LONG;
@@ -3221,10 +3323,10 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, ANY)
zend_bool isset = 1;
HashTable *target_symbol_table;
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -3235,7 +3337,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMP|VAR|CV, ANY)
}
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) {
isset = 0;
}
}
@@ -3301,10 +3403,34 @@ ZEND_VM_HELPER_EX(zend_isset_isempty_dim_prop_obj_handler, VAR|UNUSED|CV, CONST|
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -3347,7 +3473,9 @@ ZEND_VM_HELPER_EX(zend_isset_isempty_dim_prop_obj_handler, VAR|UNUSED|CV, CONST|
} else {
FREE_OP2();
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -3359,12 +3487,17 @@ ZEND_VM_HELPER_EX(zend_isset_isempty_dim_prop_obj_handler, VAR|UNUSED|CV, CONST|
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -3432,7 +3565,7 @@ ZEND_VM_HANDLER(57, ZEND_BEGIN_SILENCE, ANY, ANY)
ZEND_VM_HANDLER(142, ZEND_RAISE_ABSTRACT_ERROR, ANY, ANY)
{
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name, EX(op_array)->function_name);
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %v::%v()", EG(scope)->name, EX(op_array)->function_name);
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
@@ -3558,7 +3691,7 @@ ZEND_VM_HANDLER(144, ZEND_ADD_INTERFACE, ANY, ANY)
zend_class_entry *iface = EX_T(opline->op2.u.var).class_entry;
if (!(iface->ce_flags & ZEND_ACC_INTERFACE)) {
- zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
+ zend_error_noreturn(E_ERROR, "%v cannot implement %v - it is not an interface", ce->name, iface->name);
}
ce->interfaces[opline->extended_value] = iface;
@@ -3631,4 +3764,39 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY)
}
}
+ZEND_VM_HANDLER(151, ZEND_U_NORMALIZE, CONST|TMP|VAR|CV, ANY)
+{
+ zend_op *opline = EX(opline);
+ zend_free_op free_op1;
+ zval *string = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ zval *result = &EX_T(opline->result.u.var).tmp_var;
+
+ *result = *string;
+ if (!IS_OP1_TMP_FREE()) {
+ zendi_zval_copy_ctor(*result);
+ }
+
+ if (UG(unicode)) {
+ zval var_copy;
+ int use_copy;
+ UChar *norm;
+ int32_t norm_len;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ Z_USTRVAL_P(result), Z_USTRLEN_P(result), 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(result));
+ } else if (norm != Z_USTRVAL_P(result)) {
+ efree(Z_USTRVAL_P(result));
+ ZVAL_UNICODEL(result, norm, norm_len, 0);
+ }
+ }
+ FREE_OP1_IF_VAR();
+ ZEND_VM_NEXT_OPCODE();
+}
+
ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index c60cef5c88..4328aac4ce 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -108,11 +108,18 @@ static int ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *tmp = &EX_T(EX(opline)->result.u.var).tmp_var;
- tmp->value.str.val = emalloc(1);
- tmp->value.str.val[0] = 0;
- tmp->value.str.len = 0;
+ if (EX(opline)->extended_value == IS_UNICODE) {
+ tmp->value.ustr.val = eumalloc(1);
+ tmp->value.ustr.val[0] = 0;
+ tmp->value.ustr.len = 0;
+ tmp->type = IS_UNICODE;
+ } else {
+ tmp->value.str.val = emalloc(1);
+ tmp->value.str.val[0] = 0;
+ tmp->value.str.len = 0;
+ tmp->type = EX(opline)->extended_value;
+ }
tmp->refcount = 1;
- tmp->type = IS_STRING;
tmp->is_ref = 0;
ZEND_VM_NEXT_OPCODE();
}
@@ -127,7 +134,8 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
zend_bool should_change_scope;
if (EX(function_state).function->common.fn_flags & ZEND_ACC_ABSTRACT) {
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
+ /* FIXME: output identifiers properly */
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %v::%v()", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name);
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
@@ -159,7 +167,8 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
severity = E_ERROR;
severity_word = "cannot";
}
- zend_error(severity, "Non-static method %s::%s() %s be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name, severity_word);
+ /* FIXME: output identifiers properly */
+ zend_error(severity, "Non-static method %v::%v() %s be called statically", EX(function_state).function->common.scope->name, EX(function_state).function->common.function_name, severity_word);
}
}
if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
@@ -207,7 +216,7 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
EX(function_state).function_symbol_table = *(EG(symtable_cache_ptr)--);
} else {
ALLOC_HASHTABLE(EX(function_state).function_symbol_table);
- zend_hash_init(EX(function_state).function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(EX(function_state).function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
/*printf("Cache miss! Initialized %x\n", function_state.function_symbol_table);*/
}
calling_symbol_table = EG(active_symbol_table);
@@ -327,8 +336,8 @@ static int ZEND_CATCH_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
- zend_hash_update(EG(active_symbol_table), opline->op2.u.constant.value.str.val,
- opline->op2.u.constant.value.str.len+1, &EG(exception), sizeof(zval *), (void **) NULL);
+ zend_u_hash_update(EG(active_symbol_table), Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
+ Z_UNILEN(opline->op2.u.constant)+1, &EG(exception), sizeof(zval *), (void **) NULL);
EG(exception) = NULL;
ZEND_VM_NEXT_OPCODE();
}
@@ -346,9 +355,9 @@ static int ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC);
if(ptr && ptr->op_array) {
- zend_error(E_WARNING, "Missing argument %ld for %s%s%s(), called in %s on line %d and defined", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
+ zend_error(E_WARNING, "Missing argument %ld for %v%s%v(), called in %s on line %d and defined", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
} else {
- zend_error(E_WARNING, "Missing argument %ld for %s%s%s()", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C));
+ zend_error(E_WARNING, "Missing argument %ld for %v%s%v()", opline->op1.u.constant.value.lval, class_name, space, get_active_function_name(TSRMLS_C));
}
if (opline->result.op_type == IS_VAR) {
PZVAL_UNLOCK_FREE(*EX_T(opline->result.u.var).var.ptr_ptr);
@@ -383,7 +392,7 @@ static int ZEND_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
} else {
class_type = "abstract class";
}
- zend_error_noreturn(E_ERROR, "Cannot instantiate %s %s", class_type, EX_T(opline->op1.u.var).class_entry->name);
+ zend_error_noreturn(E_ERROR, "Cannot instantiate %s %v", class_type, EX_T(opline->op1.u.var).class_entry->name);
}
ALLOC_ZVAL(object_zval);
object_init_ex(object_zval, EX_T(opline->op1.u.var).class_entry);
@@ -432,7 +441,7 @@ static int ZEND_BEGIN_SILENCE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_RAISE_ABSTRACT_ERROR_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name, EX(op_array)->function_name);
+ zend_error_noreturn(E_ERROR, "Cannot call abstract method %v::%v()", EG(scope)->name, EX(op_array)->function_name);
ZEND_VM_NEXT_OPCODE(); /* Never reached */
}
@@ -499,7 +508,7 @@ static int ZEND_ADD_INTERFACE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_class_entry *iface = EX_T(opline->op2.u.var).class_entry;
if (!(iface->ce_flags & ZEND_ACC_INTERFACE)) {
- zend_error_noreturn(E_ERROR, "%s cannot implement %s - it is not an interface", ce->name, iface->name);
+ zend_error_noreturn(E_ERROR, "%v cannot implement %v - it is not an interface", ce->name, iface->name);
}
ce->interfaces[opline->extended_value] = iface;
@@ -591,7 +600,8 @@ static int ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
break;
case IS_STRING:
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ case IS_UNICODE:
+ EX_T(opline->result.u.var).class_entry = zend_u_fetch_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), opline->extended_value TSRMLS_CC);
break;
default:
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
@@ -612,21 +622,20 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
ce = EX_T(opline->op1.u.var).class_entry;
if(IS_CONST != IS_UNUSED) {
char *function_name_strval;
- int function_name_strlen;
+ unsigned int function_name_strlen;
zend_bool is_const = (IS_CONST == IS_CONST);
if (is_const) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name_strval = Z_UNIVAL(opline->op2.u.constant);
+ function_name_strlen = Z_UNILEN(opline->op2.u.constant);
} else {
function_name = &opline->op2.u.constant;
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen);
}
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
@@ -660,29 +669,28 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function;
- char *function_name_strval, *lcname;
- int function_name_strlen;
+ void *function_name_strval, *lcname;
+ unsigned int function_name_strlen, lcname_len;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
if (IS_CONST == IS_CONST) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name = &opline->op2.u.constant;
} else {
function_name = &opline->op2.u.constant;
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
}
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
+ lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_STRVAL_P(function_name), function_name_strlen, 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
efree(lcname);
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
}
efree(lcname);
@@ -787,7 +795,8 @@ static int ZEND_FETCH_CLASS_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
break;
case IS_STRING:
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ case IS_UNICODE:
+ EX_T(opline->result.u.var).class_entry = zend_u_fetch_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), opline->extended_value TSRMLS_CC);
break;
default:
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
@@ -809,21 +818,20 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
ce = EX_T(opline->op1.u.var).class_entry;
if(IS_TMP_VAR != IS_UNUSED) {
char *function_name_strval;
- int function_name_strlen;
+ unsigned int function_name_strlen;
zend_bool is_const = (IS_TMP_VAR == IS_CONST);
zend_free_op free_op2;
if (is_const) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name_strval = Z_UNIVAL(opline->op2.u.constant);
+ function_name_strlen = Z_UNILEN(opline->op2.u.constant);
} else {
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen);
}
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
@@ -857,29 +865,28 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function;
- char *function_name_strval, *lcname;
- int function_name_strlen;
+ void *function_name_strval, *lcname;
+ unsigned int function_name_strlen, lcname_len;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
if (IS_TMP_VAR == IS_CONST) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name = &opline->op2.u.constant;
} else {
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
}
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
+ lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_STRVAL_P(function_name), function_name_strlen, 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
efree(lcname);
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
}
efree(lcname);
@@ -941,7 +948,8 @@ static int ZEND_FETCH_CLASS_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
break;
case IS_STRING:
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ case IS_UNICODE:
+ EX_T(opline->result.u.var).class_entry = zend_u_fetch_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), opline->extended_value TSRMLS_CC);
break;
default:
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
@@ -963,21 +971,20 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
ce = EX_T(opline->op1.u.var).class_entry;
if(IS_VAR != IS_UNUSED) {
char *function_name_strval;
- int function_name_strlen;
+ unsigned int function_name_strlen;
zend_bool is_const = (IS_VAR == IS_CONST);
zend_free_op free_op2;
if (is_const) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name_strval = Z_UNIVAL(opline->op2.u.constant);
+ function_name_strlen = Z_UNILEN(opline->op2.u.constant);
} else {
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen);
}
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
@@ -1011,29 +1018,28 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function;
- char *function_name_strval, *lcname;
- int function_name_strlen;
+ void *function_name_strval, *lcname;
+ unsigned int function_name_strlen, lcname_len;
zend_free_op free_op2;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
if (IS_VAR == IS_CONST) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name = &opline->op2.u.constant;
} else {
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
}
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
+ lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_STRVAL_P(function_name), function_name_strlen, 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
efree(lcname);
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
}
efree(lcname);
@@ -1095,7 +1101,8 @@ static int ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
break;
case IS_STRING:
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ case IS_UNICODE:
+ EX_T(opline->result.u.var).class_entry = zend_u_fetch_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), opline->extended_value TSRMLS_CC);
break;
default:
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
@@ -1116,21 +1123,20 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_
ce = EX_T(opline->op1.u.var).class_entry;
if(IS_UNUSED != IS_UNUSED) {
char *function_name_strval;
- int function_name_strlen;
+ unsigned int function_name_strlen;
zend_bool is_const = (IS_UNUSED == IS_CONST);
if (is_const) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name_strval = Z_UNIVAL(opline->op2.u.constant);
+ function_name_strlen = Z_UNILEN(opline->op2.u.constant);
} else {
function_name = NULL;
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen);
}
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
@@ -1178,7 +1184,8 @@ static int ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
EX_T(opline->result.u.var).class_entry = Z_OBJCE_P(class_name);
break;
case IS_STRING:
- EX_T(opline->result.u.var).class_entry = zend_fetch_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), opline->extended_value TSRMLS_CC);
+ case IS_UNICODE:
+ EX_T(opline->result.u.var).class_entry = zend_u_fetch_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), opline->extended_value TSRMLS_CC);
break;
default:
zend_error_noreturn(E_ERROR, "Class name must be a valid object or a string");
@@ -1199,21 +1206,20 @@ static int ZEND_INIT_STATIC_METHOD_CALL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ce = EX_T(opline->op1.u.var).class_entry;
if(IS_CV != IS_UNUSED) {
char *function_name_strval;
- int function_name_strlen;
+ unsigned int function_name_strlen;
zend_bool is_const = (IS_CV == IS_CONST);
if (is_const) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name_strval = Z_UNIVAL(opline->op2.u.constant);
+ function_name_strlen = Z_UNILEN(opline->op2.u.constant);
} else {
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = zend_str_tolower_dup(function_name->value.str.val, function_name->value.str.len);
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_UNIVAL_P(function_name), Z_UNILEN_P(function_name), 1, &function_name_strlen);
}
EX(fbc) = zend_std_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC);
@@ -1247,29 +1253,28 @@ static int ZEND_INIT_FCALL_BY_NAME_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_op *opline = EX(opline);
zval *function_name;
zend_function *function;
- char *function_name_strval, *lcname;
- int function_name_strlen;
+ void *function_name_strval, *lcname;
+ unsigned int function_name_strlen, lcname_len;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
if (IS_CV == IS_CONST) {
- function_name_strval = opline->op2.u.constant.value.str.val;
- function_name_strlen = opline->op2.u.constant.value.str.len;
+ function_name = &opline->op2.u.constant;
} else {
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (Z_TYPE_P(function_name) != IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Function name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
}
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
- lcname = zend_str_tolower_dup(function_name_strval, function_name_strlen);
- if (zend_hash_find(EG(function_table), lcname, function_name_strlen+1, (void **) &function)==FAILURE) {
+ lcname = zend_u_str_case_fold(Z_TYPE_P(function_name), Z_STRVAL_P(function_name), function_name_strlen, 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(function_name), lcname, lcname_len+1, (void **) &function)==FAILURE) {
efree(lcname);
- zend_error_noreturn(E_ERROR, "Call to undefined function %s()", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined function %R()", Z_TYPE_P(function_name), function_name_strval);
}
efree(lcname);
@@ -1342,11 +1347,27 @@ static int ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval *z = &opline->op1.u.constant;
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
- zend_std_cast_object_tostring(z, &z_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
- zend_print_variable(z);
+ UErrorCode status = U_ZERO_ERROR;
+ /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+ if (opline->extended_value &&
+ strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+ ucnv_getName(ZEND_U_CONVERTER(UG(script_encoding_conv)), &status))) {
+ zval z_conv;
+ zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_U_CONVERTER(UG(script_encoding_conv)), &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+ z_conv.type = IS_BINARY;
+ if (U_SUCCESS(status)) {
+ zend_print_variable(&z_conv);
+ } else {
+ zend_error(E_WARNING, "Could not convert inline HTML for output");
+ }
+ zval_dtor(&z_conv);
+ } else {
+ zend_print_variable(z);
+ }
}
ZEND_VM_NEXT_OPCODE();
@@ -1387,23 +1408,23 @@ static int zend_fetch_var_address_helper_SPEC_CONST(int type, ZEND_OPCODE_HANDLE
ZEND_VM_NEXT_OPCODE();
}
*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_u_hash_update(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
@@ -1411,6 +1432,10 @@ static int zend_fetch_var_address_helper_SPEC_CONST(int type, ZEND_OPCODE_HANDLE
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
+ if (IS_CONST != IS_TMP_VAR) {
+
+ }
+ break;
case ZEND_FETCH_LOCAL:
break;
@@ -1577,8 +1602,9 @@ static int ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
- if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) {
- zend_error_noreturn(E_ERROR, "Unknown function: %s()\n", fname->value.str.val);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(fname), Z_UNIVAL_P(fname), Z_UNILEN_P(fname)+1, (void **) &EX(function_state).function)==FAILURE) {
+ /* FIXME: output identifiers properly */
+ zend_error_noreturn(E_ERROR, "Unknown function: %R()\n", Z_TYPE_P(fname), Z_UNIVAL_P(fname));
}
EX(object) = NULL;
EX(calling_scope) = EX(function_state).function->common.scope;
@@ -1638,9 +1664,9 @@ return_by_value:
INIT_PZVAL_COPY(ret, retval_ptr);
dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", Z_OBJCE_P(retval_ptr)->name);
}
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(retval_ptr)->name);
ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC);
*EG(return_value_ptr_ptr) = ret;
if (!dup) {
@@ -1753,7 +1779,7 @@ static int ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (!clone_call) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", ce->name);
EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr);
EX_T(opline->result.u.var).var.ptr->refcount++;
}
@@ -1763,13 +1789,13 @@ static int ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (ce != EG(scope)) {
- zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to private %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(clone->common.scope, EG(scope))) {
- zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@@ -1816,13 +1842,27 @@ static int ZEND_CAST_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(result, &var_copy, &use_copy);
+ zend_make_string_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ break;
+ }
+ case IS_UNICODE: {
+ zval var_copy;
+ int use_copy;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
if (use_copy) {
zval_dtor(result);
*result = var_copy;
}
break;
}
+ case IS_BINARY:
+ convert_to_binary(result);
+ break;
case IS_ARRAY:
convert_to_array(result);
break;
@@ -1845,7 +1885,14 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval tmp_inc_filename;
zend_bool failure_retval=0;
- if (inc_filename->type!=IS_STRING) {
+ if (UG(unicode) && opline->op2.u.constant.value.lval == ZEND_EVAL) {
+ if (inc_filename->type != IS_UNICODE) {
+ tmp_inc_filename = *inc_filename;
+ zval_copy_ctor(&tmp_inc_filename);
+ convert_to_unicode(&tmp_inc_filename);
+ inc_filename = &tmp_inc_filename;
+ }
+ } else if (inc_filename->type!=IS_STRING) {
tmp_inc_filename = *inc_filename;
zval_copy_ctor(&tmp_inc_filename);
convert_to_string(&tmp_inc_filename);
@@ -1962,10 +2009,10 @@ static int ZEND_UNSET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
varname = &opline->op1.u.constant;
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -1973,17 +2020,17 @@ static int ZEND_UNSET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1) == SUCCESS) {
+ if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) {
zend_execute_data *ex = execute_data;
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1);
do {
int i;
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
+ ex->op_array->vars[i].name_len == Z_UNILEN_P(varname) &&
+ !memcmp(ex->op_array->vars[i].name, Z_UNIVAL_P(varname), Z_TYPE_P(varname)==IS_UNICODE?UBYTES(Z_UNILEN_P(varname)):Z_UNILEN_P(varname))) {
ex->CVs[i] = NULL;
break;
}
@@ -2059,7 +2106,7 @@ static int ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
if (!EG(exception)) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
+ zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %v did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
@@ -2094,8 +2141,11 @@ static int ZEND_FE_RESET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *str_key;
uint str_key_len;
ulong int_key;
- if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
- && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ zend_uchar key_type;
+
+ key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
+ if (key_type != HASH_KEY_NON_EXISTANT &&
+ zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
break;
}
zend_hash_move_forward(fe_ht);
@@ -2129,10 +2179,10 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_bool isset = 1;
HashTable *target_symbol_table;
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -2143,7 +2193,7 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) {
isset = 0;
}
}
@@ -2219,6 +2269,41 @@ static int ZEND_TICKS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_U_NORMALIZE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_op *opline = EX(opline);
+
+ zval *string = &opline->op1.u.constant;
+ zval *result = &EX_T(opline->result.u.var).tmp_var;
+
+ *result = *string;
+ if (!0) {
+ zendi_zval_copy_ctor(*result);
+ }
+
+ if (UG(unicode)) {
+ zval var_copy;
+ int use_copy;
+ UChar *norm;
+ int32_t norm_len;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ Z_USTRVAL_P(result), Z_USTRLEN_P(result), 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(result));
+ } else if (norm != Z_USTRVAL_P(result)) {
+ efree(Z_USTRVAL_P(result));
+ ZVAL_UNICODEL(result, norm, norm_len, 0);
+ }
+ }
+
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
@@ -2502,10 +2587,12 @@ static int ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
}
*/
- if (!zend_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
- opline->op2.u.constant.value.str.val,
- opline->op2.u.constant.value.str.val);
+ if (!zend_get_constant(Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+ zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
+ Z_TYPE(opline->op2.u.constant),
+ Z_UNIVAL(opline->op2.u.constant),
+ Z_TYPE(opline->op2.u.constant),
+ Z_UNIVAL(opline->op2.u.constant));
EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
}
@@ -2514,12 +2601,12 @@ static int ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
ce = EX_T(opline->op1.u.var).class_entry;
- if (zend_hash_find(&ce->constants_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
+ if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EX_T(opline->result.u.var).tmp_var = **value;
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
} else {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", opline->op2.u.constant.value.str.val);
+ zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
}
ZEND_VM_NEXT_OPCODE();
@@ -2578,7 +2665,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -2925,7 +3014,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -3272,7 +3363,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -3353,7 +3446,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -3699,7 +3794,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -3757,11 +3854,27 @@ static int ZEND_ECHO_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval *z = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
- zend_std_cast_object_tostring(z, &z_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
- zend_print_variable(z);
+ UErrorCode status = U_ZERO_ERROR;
+ /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+ if (opline->extended_value &&
+ strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+ ucnv_getName(ZEND_U_CONVERTER(UG(script_encoding_conv)), &status))) {
+ zval z_conv;
+ zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_U_CONVERTER(UG(script_encoding_conv)), &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+ z_conv.type = IS_BINARY;
+ if (U_SUCCESS(status)) {
+ zend_print_variable(&z_conv);
+ } else {
+ zend_error(E_WARNING, "Could not convert inline HTML for output");
+ }
+ zval_dtor(&z_conv);
+ } else {
+ zend_print_variable(z);
+ }
}
zval_dtor(free_op1.var);
@@ -3803,23 +3916,23 @@ static int zend_fetch_var_address_helper_SPEC_TMP(int type, ZEND_OPCODE_HANDLER_
ZEND_VM_NEXT_OPCODE();
}
*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_u_hash_update(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
@@ -3827,6 +3940,10 @@ static int zend_fetch_var_address_helper_SPEC_TMP(int type, ZEND_OPCODE_HANDLER_
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
+ if (IS_TMP_VAR != IS_TMP_VAR) {
+ zval_dtor(free_op1.var);
+ }
+ break;
case ZEND_FETCH_LOCAL:
zval_dtor(free_op1.var);
break;
@@ -4048,9 +4165,9 @@ return_by_value:
INIT_PZVAL_COPY(ret, retval_ptr);
dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", Z_OBJCE_P(retval_ptr)->name);
}
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(retval_ptr)->name);
ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC);
*EG(return_value_ptr_ptr) = ret;
if (!dup) {
@@ -4170,7 +4287,7 @@ static int ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (!clone_call) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", ce->name);
EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr);
EX_T(opline->result.u.var).var.ptr->refcount++;
}
@@ -4180,13 +4297,13 @@ static int ZEND_CLONE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (ce != EG(scope)) {
- zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to private %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(clone->common.scope, EG(scope))) {
- zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@@ -4233,13 +4350,27 @@ static int ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(result, &var_copy, &use_copy);
+ zend_make_string_zval(result, &var_copy, &use_copy);
if (use_copy) {
zval_dtor(result);
*result = var_copy;
}
break;
}
+ case IS_UNICODE: {
+ zval var_copy;
+ int use_copy;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ break;
+ }
+ case IS_BINARY:
+ convert_to_binary(result);
+ break;
case IS_ARRAY:
convert_to_array(result);
break;
@@ -4262,7 +4393,14 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval tmp_inc_filename;
zend_bool failure_retval=0;
- if (inc_filename->type!=IS_STRING) {
+ if (UG(unicode) && opline->op2.u.constant.value.lval == ZEND_EVAL) {
+ if (inc_filename->type != IS_UNICODE) {
+ tmp_inc_filename = *inc_filename;
+ zval_copy_ctor(&tmp_inc_filename);
+ convert_to_unicode(&tmp_inc_filename);
+ inc_filename = &tmp_inc_filename;
+ }
+ } else if (inc_filename->type!=IS_STRING) {
tmp_inc_filename = *inc_filename;
zval_copy_ctor(&tmp_inc_filename);
convert_to_string(&tmp_inc_filename);
@@ -4379,10 +4517,10 @@ static int ZEND_UNSET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
varname = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -4390,17 +4528,17 @@ static int ZEND_UNSET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1) == SUCCESS) {
+ if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) {
zend_execute_data *ex = execute_data;
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1);
do {
int i;
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
+ ex->op_array->vars[i].name_len == Z_UNILEN_P(varname) &&
+ !memcmp(ex->op_array->vars[i].name, Z_UNIVAL_P(varname), Z_TYPE_P(varname)==IS_UNICODE?UBYTES(Z_UNILEN_P(varname)):Z_UNILEN_P(varname))) {
ex->CVs[i] = NULL;
break;
}
@@ -4476,7 +4614,7 @@ static int ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
if (!EG(exception)) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
+ zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %v did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
@@ -4511,8 +4649,11 @@ static int ZEND_FE_RESET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *str_key;
uint str_key_len;
ulong int_key;
- if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
- && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ zend_uchar key_type;
+
+ key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
+ if (key_type != HASH_KEY_NON_EXISTANT &&
+ zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
break;
}
zend_hash_move_forward(fe_ht);
@@ -4546,10 +4687,10 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_bool isset = 1;
HashTable *target_symbol_table;
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -4560,7 +4701,7 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) {
isset = 0;
}
}
@@ -4656,6 +4797,41 @@ static int ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_U_NORMALIZE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_op *opline = EX(opline);
+ zend_free_op free_op1;
+ zval *string = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *result = &EX_T(opline->result.u.var).tmp_var;
+
+ *result = *string;
+ if (!1) {
+ zendi_zval_copy_ctor(*result);
+ }
+
+ if (UG(unicode)) {
+ zval var_copy;
+ int use_copy;
+ UChar *norm;
+ int32_t norm_len;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ Z_USTRVAL_P(result), Z_USTRLEN_P(result), 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(result));
+ } else if (norm != Z_USTRVAL_P(result)) {
+ efree(Z_USTRVAL_P(result));
+ ZVAL_UNICODEL(result, norm, norm_len, 0);
+ }
+ }
+
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_ADD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
@@ -4919,8 +5095,8 @@ static int ZEND_ADD_CHAR_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_free_op free_op1;
add_char_to_string(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant);
+ _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
+ &opline->op2.u.constant);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
ZEND_VM_NEXT_OPCODE();
}
@@ -4931,8 +5107,8 @@ static int ZEND_ADD_STRING_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_free_op free_op1;
add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- &opline->op2.u.constant);
+ _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
+ &opline->op2.u.constant);
/* FREE_OP is missing intentionally here - we're always working on the same temporary variable */
ZEND_VM_NEXT_OPCODE();
}
@@ -4944,17 +5120,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = &opline->op2.u.constant;
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -4968,10 +5146,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -5082,7 +5260,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -5352,13 +5532,16 @@ static int ZEND_ADD_VAR_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(var, &var_copy, &use_copy);
+ if (opline->extended_value == IS_UNICODE) {
+ zend_make_unicode_zval(var, &var_copy, &use_copy);
+ } else {
+ zend_make_printable_zval(var, &var_copy, &use_copy);
+ }
if (use_copy) {
var = &var_copy;
}
- add_string_to_string( &EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- var);
+ add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
+ _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), var);
if (use_copy) {
zval_dtor(var);
}
@@ -5380,17 +5563,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -5404,10 +5589,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -5520,7 +5705,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -5790,13 +5977,16 @@ static int ZEND_ADD_VAR_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(var, &var_copy, &use_copy);
+ if (opline->extended_value == IS_UNICODE) {
+ zend_make_unicode_zval(var, &var_copy, &use_copy);
+ } else {
+ zend_make_printable_zval(var, &var_copy, &use_copy);
+ }
if (use_copy) {
var = &var_copy;
}
- add_string_to_string( &EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- var);
+ add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
+ _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), var);
if (use_copy) {
zval_dtor(var);
}
@@ -5818,17 +6008,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -5842,10 +6034,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -5958,7 +6150,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -6039,7 +6233,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_AR
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -6309,13 +6505,16 @@ static int ZEND_ADD_VAR_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(var, &var_copy, &use_copy);
+ if (opline->extended_value == IS_UNICODE) {
+ zend_make_unicode_zval(var, &var_copy, &use_copy);
+ } else {
+ zend_make_printable_zval(var, &var_copy, &use_copy);
+ }
if (use_copy) {
var = &var_copy;
}
- add_string_to_string( &EX_T(opline->result.u.var).tmp_var,
- _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC),
- var);
+ add_string_to_string(&EX_T(opline->result.u.var).tmp_var,
+ _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC), var);
if (use_copy) {
zval_dtor(var);
}
@@ -6336,17 +6535,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -6360,10 +6561,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -6474,7 +6675,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -6694,11 +6897,27 @@ static int ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval *z = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
- zend_std_cast_object_tostring(z, &z_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
- zend_print_variable(z);
+ UErrorCode status = U_ZERO_ERROR;
+ /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+ if (opline->extended_value &&
+ strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+ ucnv_getName(ZEND_U_CONVERTER(UG(script_encoding_conv)), &status))) {
+ zval z_conv;
+ zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_U_CONVERTER(UG(script_encoding_conv)), &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+ z_conv.type = IS_BINARY;
+ if (U_SUCCESS(status)) {
+ zend_print_variable(&z_conv);
+ } else {
+ zend_error(E_WARNING, "Could not convert inline HTML for output");
+ }
+ zval_dtor(&z_conv);
+ } else {
+ zend_print_variable(z);
+ }
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
@@ -6740,23 +6959,23 @@ static int zend_fetch_var_address_helper_SPEC_VAR(int type, ZEND_OPCODE_HANDLER_
ZEND_VM_NEXT_OPCODE();
}
*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_u_hash_update(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
@@ -6764,6 +6983,10 @@ static int zend_fetch_var_address_helper_SPEC_VAR(int type, ZEND_OPCODE_HANDLER_
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
+ if (IS_VAR != IS_TMP_VAR) {
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ }
+ break;
case ZEND_FETCH_LOCAL:
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
break;
@@ -6979,9 +7202,9 @@ return_by_value:
INIT_PZVAL_COPY(ret, retval_ptr);
dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", Z_OBJCE_P(retval_ptr)->name);
}
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(retval_ptr)->name);
ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC);
*EG(return_value_ptr_ptr) = ret;
if (!dup) {
@@ -7190,7 +7413,7 @@ static int ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (!clone_call) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", ce->name);
EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr);
EX_T(opline->result.u.var).var.ptr->refcount++;
}
@@ -7200,13 +7423,13 @@ static int ZEND_CLONE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (ce != EG(scope)) {
- zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to private %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(clone->common.scope, EG(scope))) {
- zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@@ -7253,13 +7476,27 @@ static int ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(result, &var_copy, &use_copy);
+ zend_make_string_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ break;
+ }
+ case IS_UNICODE: {
+ zval var_copy;
+ int use_copy;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
if (use_copy) {
zval_dtor(result);
*result = var_copy;
}
break;
}
+ case IS_BINARY:
+ convert_to_binary(result);
+ break;
case IS_ARRAY:
convert_to_array(result);
break;
@@ -7282,7 +7519,14 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval tmp_inc_filename;
zend_bool failure_retval=0;
- if (inc_filename->type!=IS_STRING) {
+ if (UG(unicode) && opline->op2.u.constant.value.lval == ZEND_EVAL) {
+ if (inc_filename->type != IS_UNICODE) {
+ tmp_inc_filename = *inc_filename;
+ zval_copy_ctor(&tmp_inc_filename);
+ convert_to_unicode(&tmp_inc_filename);
+ inc_filename = &tmp_inc_filename;
+ }
+ } else if (inc_filename->type!=IS_STRING) {
tmp_inc_filename = *inc_filename;
zval_copy_ctor(&tmp_inc_filename);
convert_to_string(&tmp_inc_filename);
@@ -7399,10 +7643,10 @@ static int ZEND_UNSET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
varname = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -7410,17 +7654,17 @@ static int ZEND_UNSET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1) == SUCCESS) {
+ if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) {
zend_execute_data *ex = execute_data;
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1);
do {
int i;
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
+ ex->op_array->vars[i].name_len == Z_UNILEN_P(varname) &&
+ !memcmp(ex->op_array->vars[i].name, Z_UNIVAL_P(varname), Z_TYPE_P(varname)==IS_UNICODE?UBYTES(Z_UNILEN_P(varname)):Z_UNILEN_P(varname))) {
ex->CVs[i] = NULL;
break;
}
@@ -7496,7 +7740,7 @@ static int ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
}
if (!EG(exception)) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
+ zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %v did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
@@ -7531,8 +7775,11 @@ static int ZEND_FE_RESET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *str_key;
uint str_key_len;
ulong int_key;
- if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
- && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ zend_uchar key_type;
+
+ key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
+ if (key_type != HASH_KEY_NON_EXISTANT &&
+ zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
break;
}
zend_hash_move_forward(fe_ht);
@@ -7594,11 +7841,16 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
zend_hash_move_forward(fe_ht);
- } while (key_type != HASH_KEY_IS_STRING || zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS);
+ } while (key_type == HASH_KEY_NON_EXISTANT || zend_check_property_access(zobj, str_key TSRMLS_CC) != SUCCESS);
if (use_key) {
- zend_unmangle_property_name(str_key, &class_name, &prop_name);
- str_key_len = strlen(prop_name);
- str_key = estrndup(prop_name, str_key_len);
+ zend_u_unmangle_property_name(key_type == HASH_KEY_IS_UNICODE?IS_UNICODE:IS_STRING, str_key, &class_name, &prop_name);
+ if (key_type == HASH_KEY_IS_UNICODE) {
+ str_key_len = u_strlen((UChar*)prop_name);
+ str_key = (char*)eustrndup((UChar*)prop_name, str_key_len);
+ } else {
+ str_key_len = strlen(prop_name);
+ str_key = estrndup(prop_name, str_key_len);
+ }
str_key_len++;
}
break;
@@ -7688,6 +7940,16 @@ static int ZEND_FE_FETCH_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
key->value.str.len = str_key_len-1;
key->type = IS_STRING;
break;
+ case HASH_KEY_IS_BINARY:
+ key->value.str.val = str_key;
+ key->value.str.len = str_key_len-1;
+ key->type = IS_BINARY;
+ break;
+ case HASH_KEY_IS_UNICODE:
+ key->value.ustr.val = (UChar*)str_key;
+ key->value.ustr.len = str_key_len-1;
+ key->type = IS_UNICODE;
+ break;
case HASH_KEY_IS_LONG:
key->value.lval = int_key;
key->type = IS_LONG;
@@ -7709,10 +7971,10 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_bool isset = 1;
HashTable *target_symbol_table;
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -7723,7 +7985,7 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) {
isset = 0;
}
}
@@ -7804,6 +8066,41 @@ static int ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_U_NORMALIZE_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_op *opline = EX(opline);
+ zend_free_op free_op1;
+ zval *string = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+ zval *result = &EX_T(opline->result.u.var).tmp_var;
+
+ *result = *string;
+ if (!0) {
+ zendi_zval_copy_ctor(*result);
+ }
+
+ if (UG(unicode)) {
+ zval var_copy;
+ int use_copy;
+ UChar *norm;
+ int32_t norm_len;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ Z_USTRVAL_P(result), Z_USTRLEN_P(result), 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(result));
+ } else if (norm != Z_USTRVAL_P(result)) {
+ efree(Z_USTRVAL_P(result));
+ ZVAL_UNICODEL(result, norm, norm_len, 0);
+ }
+ }
+ if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_ADD_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
@@ -8799,17 +9096,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = &opline->op2.u.constant;
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -8823,10 +9122,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -8938,7 +9237,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -8996,10 +9297,31 @@ static int ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -9007,8 +9329,8 @@ static int ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -9016,7 +9338,11 @@ static int ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -9122,10 +9448,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST(int prop_dim,
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -9168,7 +9518,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST(int prop_dim,
} else {
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -9180,12 +9532,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CONST(int prop_dim,
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -10220,17 +10577,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -10244,10 +10603,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -10361,7 +10720,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -10419,10 +10780,31 @@ static int ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -10430,8 +10812,8 @@ static int ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -10439,7 +10821,11 @@ static int ZEND_UNSET_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -10545,10 +10931,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(int prop_dim, ZE
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -10591,7 +11001,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(int prop_dim, ZE
} else {
zval_dtor(free_op2.var);
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -10603,12 +11015,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_TMP(int prop_dim, ZE
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -11681,17 +12098,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1, free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -11705,10 +12124,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -11822,7 +12241,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -11880,10 +12301,31 @@ static int ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -11891,8 +12333,8 @@ static int ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -11900,7 +12342,11 @@ static int ZEND_UNSET_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -12006,10 +12452,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(int prop_dim, ZE
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -12052,7 +12522,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(int prop_dim, ZE
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -12064,12 +12536,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_VAR(int prop_dim, ZE
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -12487,7 +12964,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_AR
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -13546,17 +14025,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op1;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -13570,10 +14051,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -13685,7 +14166,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -13743,10 +14226,31 @@ static int ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -13754,8 +14258,8 @@ static int ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -13763,7 +14267,11 @@ static int ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -13869,10 +14377,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(int prop_dim, ZEN
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -13915,7 +14447,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(int prop_dim, ZEN
} else {
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -13927,12 +14461,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_VAR_CV(int prop_dim, ZEN
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -13991,7 +14530,7 @@ static int ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (!clone_call) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", ce->name);
EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr);
EX_T(opline->result.u.var).var.ptr->refcount++;
}
@@ -14001,13 +14540,13 @@ static int ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (ce != EG(scope)) {
- zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to private %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(clone->common.scope, EG(scope))) {
- zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@@ -14693,17 +15232,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
char *function_name_strval;
int function_name_strlen;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = &opline->op2.u.constant;
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -14717,10 +15258,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -14765,10 +15306,12 @@ static int ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
}
}
*/
- if (!zend_get_constant(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len, &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
- opline->op2.u.constant.value.str.val,
- opline->op2.u.constant.value.str.val);
+ if (!zend_get_constant(Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), &EX_T(opline->result.u.var).tmp_var TSRMLS_CC)) {
+ zend_error(E_NOTICE, "Use of undefined constant %R - assumed '%R'",
+ Z_TYPE(opline->op2.u.constant),
+ Z_UNIVAL(opline->op2.u.constant),
+ Z_TYPE(opline->op2.u.constant),
+ Z_UNIVAL(opline->op2.u.constant));
EX_T(opline->result.u.var).tmp_var = opline->op2.u.constant;
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
}
@@ -14777,12 +15320,12 @@ static int ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
ce = EX_T(opline->op1.u.var).class_entry;
- if (zend_hash_find(&ce->constants_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) {
+ if (zend_u_hash_find(&ce->constants_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void **) &value) == SUCCESS) {
zval_update_constant(value, (void *) 1 TSRMLS_CC);
EX_T(opline->result.u.var).tmp_var = **value;
zval_copy_ctor(&EX_T(opline->result.u.var).tmp_var);
} else {
- zend_error_noreturn(E_ERROR, "Undefined class constant '%s'", opline->op2.u.constant.value.str.val);
+ zend_error_noreturn(E_ERROR, "Undefined class constant '%R'", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
}
ZEND_VM_NEXT_OPCODE();
@@ -14841,7 +15384,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -14899,10 +15444,31 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -14910,8 +15476,8 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -14919,7 +15485,11 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -15023,10 +15593,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CONST(int prop_di
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -15069,7 +15663,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CONST(int prop_di
} else {
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -15081,12 +15677,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CONST(int prop_di
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -15773,17 +16374,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -15797,10 +16400,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -15881,7 +16484,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -15939,10 +16544,31 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -15950,8 +16576,8 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -15959,7 +16585,11 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -16063,10 +16693,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP(int prop_dim,
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -16109,7 +16763,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP(int prop_dim,
} else {
zval_dtor(free_op2.var);
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -16121,12 +16777,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_TMP(int prop_dim,
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -16813,17 +17474,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -16837,10 +17500,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -16921,7 +17584,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -16979,10 +17644,31 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -16990,8 +17676,8 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -16999,7 +17685,11 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -17103,10 +17793,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR(int prop_dim,
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -17149,7 +17863,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR(int prop_dim,
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -17161,12 +17877,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_VAR(int prop_dim,
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -17540,7 +18261,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -18217,17 +18940,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
char *function_name_strval;
int function_name_strlen;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -18241,10 +18966,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -18324,7 +19049,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -18382,10 +19109,31 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -18393,8 +19141,8 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -18402,7 +19150,11 @@ static int ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -18506,10 +19258,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV(int prop_dim,
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -18552,7 +19328,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV(int prop_dim,
} else {
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -18564,12 +19342,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_UNUSED_CV(int prop_dim,
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -18793,11 +19576,27 @@ static int ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval *z = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get_method != NULL &&
- zend_std_cast_object_tostring(z, &z_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
+ zend_std_cast_object_tostring(z, &z_copy, UG(unicode) ? IS_UNICODE : IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
zend_print_variable(&z_copy);
zval_dtor(&z_copy);
} else {
- zend_print_variable(z);
+ UErrorCode status = U_ZERO_ERROR;
+ /* Convert inline HTML blocks to the output encoding, but only if necessary. */
+ if (opline->extended_value &&
+ strcmp(ucnv_getName(ZEND_U_CONVERTER(UG(output_encoding_conv)), &status),
+ ucnv_getName(ZEND_U_CONVERTER(UG(script_encoding_conv)), &status))) {
+ zval z_conv;
+ zend_convert_encodings(ZEND_U_CONVERTER(UG(output_encoding_conv)), ZEND_U_CONVERTER(UG(script_encoding_conv)), &z_conv.value.str.val, &z_conv.value.str.len, z->value.str.val, z->value.str.len, &status);
+ z_conv.type = IS_BINARY;
+ if (U_SUCCESS(status)) {
+ zend_print_variable(&z_conv);
+ } else {
+ zend_error(E_WARNING, "Could not convert inline HTML for output");
+ }
+ zval_dtor(&z_conv);
+ } else {
+ zend_print_variable(z);
+ }
}
ZEND_VM_NEXT_OPCODE();
@@ -18838,23 +19637,23 @@ static int zend_fetch_var_address_helper_SPEC_CV(int type, ZEND_OPCODE_HANDLER_A
ZEND_VM_NEXT_OPCODE();
}
*/
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &retval) == FAILURE) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_IS:
retval = &EG(uninitialized_zval_ptr);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val);
+ zend_error(E_NOTICE,"Undefined variable: %R", Z_TYPE_P(varname), Z_UNIVAL_P(varname));
/* break missing intentionally */
case BP_VAR_W: {
zval *new_zval = &EG(uninitialized_zval);
new_zval->refcount++;
- zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval);
+ zend_u_hash_update(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, &new_zval, sizeof(zval *), (void **) &retval);
}
break;
EMPTY_SWITCH_DEFAULT_CASE()
@@ -18862,6 +19661,10 @@ static int zend_fetch_var_address_helper_SPEC_CV(int type, ZEND_OPCODE_HANDLER_A
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
+ if (IS_CV != IS_TMP_VAR) {
+
+ }
+ break;
case ZEND_FETCH_LOCAL:
break;
@@ -19072,9 +19875,9 @@ return_by_value:
INIT_PZVAL_COPY(ret, retval_ptr);
dup = zend_get_object_classname(retval_ptr, &class_name, &class_name_len TSRMLS_CC);
if (Z_OBJ_HT_P(retval_ptr)->clone_obj == NULL) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", class_name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", Z_OBJCE_P(retval_ptr)->name);
}
- zend_error(E_STRICT, "Implicit cloning object of class '%s' because of 'zend.ze1_compatibility_mode'", class_name);
+ zend_error(E_STRICT, "Implicit cloning object of class '%v' because of 'zend.ze1_compatibility_mode'", Z_OBJCE_P(retval_ptr)->name);
ret->value.obj = Z_OBJ_HT_P(retval_ptr)->clone_obj(retval_ptr TSRMLS_CC);
*EG(return_value_ptr_ptr) = ret;
if (!dup) {
@@ -19275,7 +20078,7 @@ static int ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
clone = ce ? ce->clone : NULL;
clone_call = Z_OBJ_HT_P(obj)->clone_obj;
if (!clone_call) {
- zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %s", ce->name);
+ zend_error_noreturn(E_ERROR, "Trying to clone an uncloneable object of class %v", ce->name);
EX_T(opline->result.u.var).var.ptr = EG(error_zval_ptr);
EX_T(opline->result.u.var).var.ptr->refcount++;
}
@@ -19285,13 +20088,13 @@ static int ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* Ensure that if we're calling a private function, we're allowed to do so.
*/
if (ce != EG(scope)) {
- zend_error_noreturn(E_ERROR, "Call to private %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to private %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
} else if ((clone->common.fn_flags & ZEND_ACC_PROTECTED)) {
/* Ensure that if we're calling a protected function, we're allowed to do so.
*/
if (!zend_check_protected(clone->common.scope, EG(scope))) {
- zend_error_noreturn(E_ERROR, "Call to protected %s::__clone() from context '%s'", ce->name, EG(scope) ? EG(scope)->name : "");
+ zend_error_noreturn(E_ERROR, "Call to protected %v::__clone() from context '%v'", ce->name, EG(scope) ? EG(scope)->name : EMPTY_STR);
}
}
}
@@ -19338,13 +20141,27 @@ static int ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval var_copy;
int use_copy;
- zend_make_printable_zval(result, &var_copy, &use_copy);
+ zend_make_string_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ break;
+ }
+ case IS_UNICODE: {
+ zval var_copy;
+ int use_copy;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
if (use_copy) {
zval_dtor(result);
*result = var_copy;
}
break;
}
+ case IS_BINARY:
+ convert_to_binary(result);
+ break;
case IS_ARRAY:
convert_to_array(result);
break;
@@ -19367,7 +20184,14 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zval tmp_inc_filename;
zend_bool failure_retval=0;
- if (inc_filename->type!=IS_STRING) {
+ if (UG(unicode) && opline->op2.u.constant.value.lval == ZEND_EVAL) {
+ if (inc_filename->type != IS_UNICODE) {
+ tmp_inc_filename = *inc_filename;
+ zval_copy_ctor(&tmp_inc_filename);
+ convert_to_unicode(&tmp_inc_filename);
+ inc_filename = &tmp_inc_filename;
+ }
+ } else if (inc_filename->type!=IS_STRING) {
tmp_inc_filename = *inc_filename;
zval_copy_ctor(&tmp_inc_filename);
convert_to_string(&tmp_inc_filename);
@@ -19484,10 +20308,10 @@ static int ZEND_UNSET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
varname = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -19495,17 +20319,17 @@ static int ZEND_UNSET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_std_unset_static_property(EX_T(opline->op2.u.var).class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname) TSRMLS_CC);
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_del(target_symbol_table, varname->value.str.val, varname->value.str.len+1) == SUCCESS) {
+ if (zend_u_hash_del(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1) == SUCCESS) {
zend_execute_data *ex = execute_data;
- ulong hash_value = zend_inline_hash_func(varname->value.str.val, varname->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1);
do {
int i;
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == varname->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, varname->value.str.val, varname->value.str.len)) {
+ ex->op_array->vars[i].name_len == Z_UNILEN_P(varname) &&
+ !memcmp(ex->op_array->vars[i].name, Z_UNIVAL_P(varname), Z_TYPE_P(varname)==IS_UNICODE?UBYTES(Z_UNILEN_P(varname)):Z_UNILEN_P(varname))) {
ex->CVs[i] = NULL;
break;
}
@@ -19581,7 +20405,7 @@ static int ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
if (!EG(exception)) {
- zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %s did not create an Iterator", ce->name);
+ zend_throw_exception_ex(NULL, 0 TSRMLS_CC, "Object of type %v did not create an Iterator", ce->name);
}
zend_throw_exception_internal(NULL TSRMLS_CC);
ZEND_VM_NEXT_OPCODE();
@@ -19616,8 +20440,11 @@ static int ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *str_key;
uint str_key_len;
ulong int_key;
- if (zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL) == HASH_KEY_IS_STRING
- && zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
+ zend_uchar key_type;
+
+ key_type = zend_hash_get_current_key_ex(fe_ht, &str_key, &str_key_len, &int_key, 0, NULL);
+ if (key_type != HASH_KEY_NON_EXISTANT &&
+ zend_check_property_access(zobj, str_key TSRMLS_CC) == SUCCESS) {
break;
}
zend_hash_move_forward(fe_ht);
@@ -19651,10 +20478,10 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_bool isset = 1;
HashTable *target_symbol_table;
- if (varname->type != IS_STRING) {
+ if (varname->type != IS_STRING && varname->type != IS_UNICODE) {
tmp = *varname;
zval_copy_ctor(&tmp);
- convert_to_string(&tmp);
+ convert_to_text(&tmp);
varname = &tmp;
}
@@ -19665,7 +20492,7 @@ static int ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
} else {
target_symbol_table = zend_get_target_symbol_table(opline, EX(Ts), BP_VAR_IS, varname TSRMLS_CC);
- if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &value) == FAILURE) {
+ if (zend_u_hash_find(target_symbol_table, Z_TYPE_P(varname), Z_UNIVAL_P(varname), Z_UNILEN_P(varname)+1, (void **) &value) == FAILURE) {
isset = 0;
}
}
@@ -19745,6 +20572,41 @@ static int ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
ZEND_VM_NEXT_OPCODE();
}
+static int ZEND_U_NORMALIZE_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_op *opline = EX(opline);
+
+ zval *string = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+ zval *result = &EX_T(opline->result.u.var).tmp_var;
+
+ *result = *string;
+ if (!0) {
+ zendi_zval_copy_ctor(*result);
+ }
+
+ if (UG(unicode)) {
+ zval var_copy;
+ int use_copy;
+ UChar *norm;
+ int32_t norm_len;
+
+ zend_make_unicode_zval(result, &var_copy, &use_copy);
+ if (use_copy) {
+ zval_dtor(result);
+ *result = var_copy;
+ }
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ Z_USTRVAL_P(result), Z_USTRLEN_P(result), 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", Z_USTRVAL_P(result));
+ } else if (norm != Z_USTRVAL_P(result)) {
+ efree(Z_USTRVAL_P(result));
+ ZVAL_UNICODEL(result, norm, norm_len, 0);
+ }
+ }
+
+ ZEND_VM_NEXT_OPCODE();
+}
+
static int ZEND_ADD_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
@@ -20737,17 +21599,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = &opline->op2.u.constant;
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -20761,10 +21625,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -20875,7 +21739,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -20933,10 +21799,31 @@ static int ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -20944,8 +21831,8 @@ static int ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -20953,7 +21840,11 @@ static int ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -21057,10 +21948,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(int prop_dim, Z
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -21103,7 +22018,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(int prop_dim, Z
} else {
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -21115,12 +22032,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CONST(int prop_dim, Z
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -22150,17 +23072,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_tmp(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -22174,10 +23098,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -22290,7 +23214,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -22348,10 +23274,31 @@ static int ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -22359,8 +23306,8 @@ static int ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -22368,7 +23315,11 @@ static int ZEND_UNSET_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -22472,10 +23423,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(int prop_dim, ZEN
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -22518,7 +23493,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(int prop_dim, ZEN
} else {
zval_dtor(free_op2.var);
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -22530,12 +23507,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_TMP(int prop_dim, ZEN
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -23602,17 +24584,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
zend_free_op free_op2;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_var(&opline->op2, EX(Ts), &free_op2 TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -23626,10 +24610,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -23742,7 +24726,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -23800,10 +24786,31 @@ static int ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -23811,8 +24818,8 @@ static int ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -23820,7 +24827,11 @@ static int ZEND_UNSET_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -23924,10 +24935,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int prop_dim, ZEN
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -23970,7 +25005,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int prop_dim, ZEN
} else {
if (free_op2.var) {zval_ptr_dtor(&free_op2.var);};
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -23982,12 +25019,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_VAR(int prop_dim, ZEN
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -24402,7 +25444,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARG
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -25457,17 +26501,19 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
char *function_name_strval;
int function_name_strlen;
+ /* FIXME: type is default */
+ zend_uchar type = UG(unicode)?IS_UNICODE:IS_STRING;
zend_ptr_stack_3_push(&EG(arg_types_stack), EX(fbc), EX(object), EX(calling_scope));
function_name = _get_zval_ptr_cv(&opline->op2, EX(Ts), BP_VAR_R TSRMLS_CC);
- if (Z_TYPE_P(function_name)!=IS_STRING) {
+ if (Z_TYPE_P(function_name) != IS_STRING && Z_TYPE_P(function_name) != IS_UNICODE) {
zend_error_noreturn(E_ERROR, "Method name must be a string");
}
- function_name_strval = function_name->value.str.val;
- function_name_strlen = function_name->value.str.len;
+ function_name_strval = Z_UNIVAL_P(function_name);
+ function_name_strlen = Z_UNILEN_P(function_name);
EX(calling_scope) = EG(scope);
@@ -25481,10 +26527,10 @@ static int ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
/* First, locate the function. */
EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(&EX(object), function_name_strval, function_name_strlen TSRMLS_CC);
if (!EX(fbc)) {
- zend_error_noreturn(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to undefined method %R::%R()", type, Z_OBJ_CLASS_NAME_P(EX(object)), Z_TYPE_P(function_name), function_name_strval);
}
} else {
- zend_error_noreturn(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval);
+ zend_error_noreturn(E_ERROR, "Call to a member function %R() on a non-object", Z_TYPE_P(function_name), function_name_strval);
}
if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) {
@@ -25595,7 +26641,9 @@ static int ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_STRING:
- zend_symtable_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(array_ptr->value.ht, Z_TYPE_P(offset), Z_UNIVAL_P(offset), Z_UNILEN_P(offset)+1, &expr_ptr, sizeof(zval *), NULL);
break;
case IS_NULL:
zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL);
@@ -25653,10 +26701,31 @@ static int ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
zend_hash_index_del(ht, index);
break;
case IS_STRING:
- if (zend_symtable_del(ht, offset->value.str.val, offset->value.str.len+1) == SUCCESS &&
- ht == &EG(symbol_table)) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ void *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && offset->type == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+
+ if (zend_u_symtable_del(ht, Z_TYPE_P(offset), offset_key, offset_len+1) == SUCCESS &&
+ ht == &EG(symbol_table)) {
zend_execute_data *ex;
- ulong hash_value = zend_inline_hash_func(offset->value.str.val, offset->value.str.len+1);
+ ulong hash_value = zend_u_inline_hash_func(Z_TYPE_P(offset), offset_key, offset_len+1);
for (ex = execute_data; ex; ex = ex->prev_execute_data) {
if (ex->symbol_table == ht) {
@@ -25664,8 +26733,8 @@ static int ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
for (i = 0; i < ex->op_array->last_var; i++) {
if (ex->op_array->vars[i].hash_value == hash_value &&
- ex->op_array->vars[i].name_len == offset->value.str.len &&
- !memcmp(ex->op_array->vars[i].name, offset->value.str.val, offset->value.str.len)) {
+ ex->op_array->vars[i].name_len == offset_len &&
+ !memcmp(ex->op_array->vars[i].name, offset_key, Z_TYPE_P(offset)==IS_UNICODE?UBYTES(offset_len):offset_len)) {
ex->CVs[i] = NULL;
break;
}
@@ -25673,7 +26742,11 @@ static int ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
@@ -25777,10 +26850,34 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(int prop_dim, ZEND
}
break;
case IS_STRING:
- if (zend_symtable_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) {
+ case IS_BINARY:
+ case IS_UNICODE: {
+ char *offset_key = Z_UNIVAL_P(offset);
+ int offset_len = Z_UNILEN_P(offset);
+ int free_offset = 0;
+
+ if (UG(unicode) && ht == &EG(symbol_table) && Z_TYPE_P(offset) == IS_UNICODE) {
+ /* Identifier normalization */
+ UChar *norm;
+ int32_t norm_len;
+
+ if (!zend_normalize_identifier(&norm, &norm_len,
+ (UChar*)offset_key, offset_len, 0)) {
+ zend_error(E_WARNING, "Could not normalize identifier: %r", offset_key);
+ } else if ((char*)norm != offset_key) {
+ offset_key = (char*)norm;
+ offset_len = norm_len;
+ free_offset = 1;
+ }
+ }
+ if (zend_u_symtable_find(ht, Z_TYPE_P(offset), offset_key, offset_len+1, (void **) &value) == SUCCESS) {
isset = 1;
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) {
isset = 1;
@@ -25823,7 +26920,9 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(int prop_dim, ZEND
} else {
}
- } else if ((*container)->type == IS_STRING && !prop_dim) { /* string offsets */
+ } else if (((*container)->type == IS_STRING ||
+ (*container)->type == IS_BINARY ||
+ (*container)->type == IS_UNICODE) && !prop_dim) { /* string offsets */
zval tmp;
if (offset->type != IS_LONG) {
@@ -25835,12 +26934,17 @@ static int zend_isset_isempty_dim_prop_obj_handler_SPEC_CV_CV(int prop_dim, ZEND
if (offset->type == IS_LONG) {
switch (opline->extended_value) {
case ZEND_ISSET:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container)) {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container)) {
result = 1;
}
break;
case ZEND_ISEMPTY:
- if (offset->value.lval >= 0 && offset->value.lval < Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') {
+ if (offset->value.lval >= 0 &&
+ offset->value.lval < Z_UNILEN_PP(container) &&
+ ((Z_TYPE_PP(container) == IS_UNICODE)?
+ (Z_USTRVAL_PP(container)[offset->value.lval] != 0):
+ (Z_STRVAL_PP(container)[offset->value.lval] != '0'))) {
result = 1;
}
break;
@@ -29661,6 +30765,31 @@ void zend_init_opcodes_handlers()
ZEND_USER_OPCODE_SPEC_HANDLER,
ZEND_USER_OPCODE_SPEC_HANDLER,
ZEND_USER_OPCODE_SPEC_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CONST_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CONST_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CONST_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CONST_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CONST_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_TMP_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_TMP_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_TMP_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_TMP_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_TMP_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_VAR_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_VAR_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_VAR_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_VAR_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CV_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CV_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CV_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CV_HANDLER,
+ ZEND_U_NORMALIZE_SPEC_CV_HANDLER,
ZEND_NULL_HANDLER
};
zend_opcode_handlers = (opcode_handler_t*)labels;
diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php
index 235735d983..c30eed096e 100644
--- a/Zend/zend_vm_gen.php
+++ b/Zend/zend_vm_gen.php
@@ -1058,7 +1058,7 @@ function gen_vm($def, $skel) {
fputs($f,"#define $op $code\n");
}
fclose($f);
- echo "zend_vm_opcodes.h generated succesfull.\n";
+ echo "zend_vm_opcodes.h generated succesfully.\n";
// Generate zend_vm_execute.h
$f = fopen("zend_vm_execute.h", "w+") or die("ERROR: Cannot create zend_vm_execute.h\n");
@@ -1198,7 +1198,7 @@ function gen_vm($def, $skel) {
}
fclose($f);
- echo "zend_vm_execute.h generated succesfull.\n";
+ echo "zend_vm_execute.h generated succesfully.\n";
}
function usage() {
diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h
index 319b5483ea..b10683c584 100644
--- a/Zend/zend_vm_opcodes.h
+++ b/Zend/zend_vm_opcodes.h
@@ -147,3 +147,4 @@
#define ZEND_ISSET_ISEMPTY_PROP_OBJ 148
#define ZEND_HANDLE_EXCEPTION 149
#define ZEND_USER_OPCODE 150
+#define ZEND_U_NORMALIZE 151
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 2bbd91bc98..fa001dc9b9 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -43,7 +43,7 @@ zend_class_entry *reflection_extension_ptr;
/* Method macros */
#define METHOD_NOTSTATIC \
if (!this_ptr) { \
- zend_error(E_ERROR, "%s() cannot be called statically", get_active_function_name(TSRMLS_C)); \
+ zend_error(E_ERROR, "%v() cannot be called statically", get_active_function_name(TSRMLS_C)); \
return; \
} \
@@ -233,7 +233,7 @@ static zend_object_value reflection_objects_new(zend_class_entry *class_type TSR
intern->free_ptr = 0;
ALLOC_HASHTABLE(intern->zo.properties);
- zend_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(intern->zo.properties, 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_hash_copy(intern->zo.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
retval.handle = zend_objects_store_put(intern, NULL, reflection_free_objects_storage, reflection_objects_clone TSRMLS_CC);
retval.handlers = &reflection_object_handlers;
@@ -297,17 +297,17 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in
}
string_printf(str, "class ");
}
- string_write(str, ce->name, ce->name_length);
+ string_printf(str, "%v", ce->name);
if (ce->parent) {
- string_printf(str, " extends %s", ce->parent->name);
+ string_printf(str, " extends %v", ce->parent->name);
}
if (ce->num_interfaces) {
zend_uint i;
- string_printf(str, " implements %s", ce->interfaces[0]->name);
+ string_printf(str, " implements %v", ce->interfaces[0]->name);
for (i = 1; i < ce->num_interfaces; ++i) {
- string_printf(str, ", %s", ce->interfaces[i]->name);
+ string_printf(str, ", %v", ce->interfaces[i]->name);
}
}
string_printf(str, " ] {\n");
@@ -540,7 +540,7 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
string_printf(str, "<required> ");
}
if (arg_info->class_name) {
- string_printf(str, "%s ", arg_info->class_name);
+ string_printf(str, "%v ", arg_info->class_name);
if (arg_info->allow_null) {
string_printf(str, "or NULL ");
}
@@ -554,7 +554,7 @@ static void _parameter_string(string *str, zend_function *fptr, struct _zend_arg
string_write(str, "&", sizeof("&")-1);
}
if (arg_info->name) {
- string_printf(str, "$%s", arg_info->name);
+ string_printf(str, "$%v", arg_info->name);
} else {
string_printf(str, "$param%d", offset);
}
@@ -671,7 +671,7 @@ static void _function_string(string *str, zend_function *fptr, char* indent TSRM
if (fptr->op_array.return_reference) {
string_printf(str, "&");
}
- string_printf(str, "%s ] {\n", fptr->common.function_name);
+ string_printf(str, "%v ] {\n", fptr->common.function_name);
/* The information where a function is declared is only available for user classes */
if (fptr->type == ZEND_USER_FUNCTION) {
string_printf(str, "%s @@ %s %d - %d\n", indent,
@@ -720,8 +720,8 @@ static void _property_string(string *str, zend_property_info *prop, char *prop_n
string_printf(str, "static ");
}
- zend_unmangle_property_name(prop->name, &class_name, &prop_name);
- string_printf(str, "$%s", prop_name);
+ zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, prop->name, &class_name, &prop_name);
+ string_printf(str, "$%v", prop_name);
}
string_printf(str, " ]\n");
@@ -865,7 +865,11 @@ ZEND_API void zend_reflection_class_factory(zend_class_entry *ce, zval *object T
zval *name;
MAKE_STD_ZVAL(name);
- ZVAL_STRINGL(name, ce->name, ce->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(name, (UChar*)ce->name, ce->name_length, 1);
+ } else {
+ ZVAL_STRINGL(name, ce->name, ce->name_length, 1);
+ }
reflection_instanciate(reflection_class_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
intern->ptr = ce;
@@ -912,7 +916,11 @@ static void reflection_parameter_factory(zend_function *fptr, struct _zend_arg_i
MAKE_STD_ZVAL(name);
if (arg_info->name) {
- ZVAL_STRINGL(name, arg_info->name, arg_info->name_len, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(name, (UChar*)arg_info->name, arg_info->name_len, 1);
+ } else {
+ ZVAL_STRINGL(name, arg_info->name, arg_info->name_len, 1);
+ }
} else {
ZVAL_NULL(name);
}
@@ -937,7 +945,11 @@ static void reflection_function_factory(zend_function *function, zval *object TS
zval *name;
MAKE_STD_ZVAL(name);
- ZVAL_STRING(name, function->common.function_name, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(name, (UChar*)function->common.function_name, 1);
+ } else {
+ ZVAL_STRING(name, function->common.function_name, 1);
+ }
reflection_instanciate(reflection_function_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
@@ -956,9 +968,14 @@ static void reflection_method_factory(zend_class_entry *ce, zend_function *metho
zval *classname;
MAKE_STD_ZVAL(name);
- ZVAL_STRING(name, method->common.function_name, 1);
MAKE_STD_ZVAL(classname);
- ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(name, (UChar*)method->common.function_name, 1);
+ ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
+ } else {
+ ZVAL_STRING(name, method->common.function_name, 1);
+ ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ }
reflection_instanciate(reflection_method_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
intern->ptr = method;
@@ -978,7 +995,7 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
property_reference *reference;
char *class_name, *prop_name;
- zend_unmangle_property_name(prop->name, &class_name, &prop_name);
+ zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, prop->name, &class_name, &prop_name);
if (!(prop->flags & ZEND_ACC_PRIVATE)) {
/* we have to seach the class hierarchy for this (implicit) public or protected property */
@@ -997,10 +1014,14 @@ static void reflection_property_factory(zend_class_entry *ce, zend_property_info
}
MAKE_STD_ZVAL(name);
- ZVAL_STRING(name, prop_name, 1);
-
MAKE_STD_ZVAL(classname);
- ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(name, (UChar*)prop_name, 1);
+ ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
+ } else {
+ ZVAL_STRING(name, prop_name, 1);
+ ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ }
reflection_instanciate(reflection_property_ptr, object TSRMLS_CC);
intern = (reflection_object *) zend_object_store_get_object(object TSRMLS_CC);
@@ -1144,7 +1165,7 @@ ZEND_METHOD(reflection, export)
}
if (!retval_ptr) {
- zend_error(E_WARNING, "%s::__toString() did not return anything", Z_OBJCE_P(object)->name);
+ zend_error(E_WARNING, "%v::__toString() did not return anything", Z_OBJCE_P(object)->name);
RETURN_FALSE;
}
@@ -1211,13 +1232,15 @@ ZEND_METHOD(reflection_function, __construct)
{
zval *name;
zval *object;
+ unsigned int lcname_len;
char *lcname;
reflection_object *intern;
zend_function *fptr;
char *name_str;
int name_len;
+ zend_uchar type;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name_str, &name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name_str, &name_len, &type) == FAILURE) {
return;
}
@@ -1226,17 +1249,20 @@ ZEND_METHOD(reflection_function, __construct)
if (intern == NULL) {
return;
}
- lcname = do_alloca(name_len + 1);
- zend_str_tolower_copy(lcname, name_str, name_len);
- if (zend_hash_find(EG(function_table), lcname, name_len + 1, (void **)&fptr) == FAILURE) {
- free_alloca(lcname);
+ lcname = zend_u_str_case_fold(type, name_str, name_len, 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), type, lcname, lcname_len + 1, (void **)&fptr) == FAILURE) {
+ efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Function %s() does not exist", name_str);
+ "Function %R() does not exist", type, name_str);
return;
}
- free_alloca(lcname);
+ efree(lcname);
MAKE_STD_ZVAL(name);
- ZVAL_STRING(name, fptr->common.function_name, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(name, (UChar*)fptr->common.function_name, 1);
+ } else {
+ ZVAL_STRING(name, fptr->common.function_name, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
intern->ptr = fptr;
intern->free_ptr = 0;
@@ -1421,7 +1447,7 @@ ZEND_METHOD(reflection_function, invoke)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Invocation of function %s() failed", fptr->common.function_name);
+ "Invocation of function %v() failed", fptr->common.function_name);
return;
}
@@ -1485,7 +1511,7 @@ ZEND_METHOD(reflection_function, invokeArgs)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Invocation of function %s() failed", fptr->common.function_name);
+ "Invocation of function %v() failed", fptr->common.function_name);
return;
}
@@ -1598,19 +1624,20 @@ ZEND_METHOD(reflection_parameter, __construct)
/* First, find the function */
switch (Z_TYPE_P(reference)) {
+ case IS_UNICODE:
case IS_STRING: {
- char *lcname;
+ unsigned int lcname_len;
+ char *lcname;
- convert_to_string_ex(&reference);
- lcname = do_alloca(Z_STRLEN_P(reference) + 1);
- zend_str_tolower_copy(lcname, Z_STRVAL_P(reference), Z_STRLEN_P(reference));
- if (zend_hash_find(EG(function_table), lcname, (int) Z_STRLEN_P(reference) + 1, (void**) &fptr) == FAILURE) {
- free_alloca(lcname);
+ convert_to_text_ex(&reference);
+ lcname = zend_u_str_case_fold(Z_TYPE_P(reference), Z_STRVAL_P(reference), Z_STRLEN_P(reference), 1, &lcname_len);
+ if (zend_u_hash_find(EG(function_table), Z_TYPE_P(reference), lcname, lcname_len + 1, (void**) &fptr) == FAILURE) {
+ efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Function %s() does not exist", Z_STRVAL_P(reference));
+ "Function %R() does not exist", Z_TYPE_P(reference), Z_STRVAL_P(reference));
return;
}
- free_alloca(lcname);
+ efree(lcname);
}
break;
@@ -1618,7 +1645,8 @@ ZEND_METHOD(reflection_parameter, __construct)
zval **classref;
zval **method;
zend_class_entry **pce;
- char *lcname;
+ unsigned int lcname_len;
+ char *lcname;
if ((zend_hash_index_find(Z_ARRVAL_P(reference), 0, (void **) &classref) == FAILURE)
|| (zend_hash_index_find(Z_ARRVAL_P(reference), 1, (void **) &method) == FAILURE)) {
@@ -1629,25 +1657,24 @@ ZEND_METHOD(reflection_parameter, __construct)
if (Z_TYPE_PP(classref) == IS_OBJECT) {
ce = Z_OBJCE_PP(classref);
} else {
- convert_to_string_ex(classref);
- if (zend_lookup_class(Z_STRVAL_PP(classref), Z_STRLEN_PP(classref), &pce TSRMLS_CC) == FAILURE) {
+ convert_to_text_ex(classref);
+ if (zend_u_lookup_class(Z_TYPE_PP(classref), Z_UNIVAL_PP(classref), Z_UNILEN_PP(classref), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Class %s does not exist", Z_STRVAL_PP(classref));
+ "Class %R does not exist", Z_TYPE_PP(classref), Z_UNIVAL_PP(classref));
return;
}
ce = *pce;
}
- convert_to_string_ex(method);
- lcname = do_alloca(Z_STRLEN_PP(method) + 1);
- zend_str_tolower_copy(lcname, Z_STRVAL_PP(method), Z_STRLEN_PP(method));
- if (zend_hash_find(&ce->function_table, lcname, (int)(Z_STRLEN_PP(method) + 1), (void **) &fptr) == FAILURE) {
- free_alloca(lcname);
+ convert_to_text_ex(method);
+ lcname = zend_u_str_case_fold(Z_TYPE_PP(method), Z_UNIVAL_PP(method), Z_UNILEN_PP(method), 1, &lcname_len);
+ if (zend_u_hash_find(&ce->function_table, Z_TYPE_PP(method), lcname, lcname_len + 1, (void **) &fptr) == FAILURE) {
+ efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Method %s::%s() does not exist", Z_STRVAL_PP(classref), Z_STRVAL_PP(method));
+ "Method %R::%R() does not exist", Z_TYPE_PP(classref), Z_UNIVAL_PP(classref), Z_TYPE_PP(method), Z_UNIVAL_PP(method));
return;
}
- free_alloca(lcname);
+ efree(lcname);
}
break;
@@ -1683,7 +1710,11 @@ ZEND_METHOD(reflection_parameter, __construct)
MAKE_STD_ZVAL(name);
if (arg_info[position].name) {
- ZVAL_STRINGL(name, arg_info[position].name, arg_info[position].name_len, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(name, (UChar*)arg_info[position].name, arg_info[position].name_len, 1);
+ } else {
+ ZVAL_STRINGL(name, arg_info[position].name, arg_info[position].name_len, 1);
+ }
} else {
ZVAL_NULL(name);
}
@@ -1739,15 +1770,16 @@ ZEND_METHOD(reflection_parameter, getClass)
RETURN_NULL();
} else {
zend_class_entry **pce;
- char *lcname = do_alloca(param->arg_info->class_name_len + 1);
- zend_str_tolower_copy(lcname, param->arg_info->class_name, param->arg_info->class_name_len);
- if (zend_hash_find(EG(class_table), lcname, param->arg_info->class_name_len + 1, (void **) &pce) == FAILURE) {
- free_alloca(lcname);
+ unsigned int lcname_len;
+ char *lcname = zend_u_str_case_fold(UG(unicode)?IS_UNICODE:IS_STRING, param->arg_info->class_name, param->arg_info->class_name_len, 0, &lcname_len);
+
+ if (zend_u_hash_find(EG(class_table), UG(unicode)?IS_UNICODE:IS_STRING, lcname, lcname_len + 1, (void **) &pce) == FAILURE) {
+ efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Class %s does not exist", param->arg_info->class_name);
+ "Class %v does not exist", param->arg_info->class_name);
return;
}
- free_alloca(lcname);
+ efree(lcname);
zend_reflection_class_factory(*pce, return_value TSRMLS_CC);
}
}
@@ -1884,14 +1916,16 @@ ZEND_METHOD(reflection_method, __construct)
zval *name, *classname;
zval *object;
reflection_object *intern;
+ unsigned int lcname_len;
char *lcname;
zend_class_entry **pce;
zend_class_entry *ce;
zend_function *mptr;
char *name_str;
int name_len;
+ zend_uchar type;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zs", &classname, &name_str, &name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zt", &classname, &name_str, &name_len, &type) == FAILURE) {
return;
}
@@ -1904,9 +1938,10 @@ ZEND_METHOD(reflection_method, __construct)
/* Find the class entry */
switch (Z_TYPE_P(classname)) {
case IS_STRING:
- if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
+ case IS_UNICODE:
+ if (zend_u_lookup_class(Z_TYPE_P(classname), Z_UNIVAL_P(classname), Z_UNILEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Class %s does not exist", Z_STRVAL_P(classname));
+ "Class %v does not exist", Z_UNIVAL_P(classname));
return;
}
ce = *pce;
@@ -1922,22 +1957,29 @@ ZEND_METHOD(reflection_method, __construct)
}
MAKE_STD_ZVAL(classname);
- ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
+ } else {
+ ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
- lcname = do_alloca(name_len + 1);
- zend_str_tolower_copy(lcname, name_str, name_len);
+ lcname = zend_u_str_case_fold(type, name_str, name_len, 1, &lcname_len);
- if (zend_hash_find(&ce->function_table, lcname, name_len + 1, (void **) &mptr) == FAILURE) {
- free_alloca(lcname);
+ if (zend_u_hash_find(&ce->function_table, type, lcname, lcname_len + 1, (void **) &mptr) == FAILURE) {
+ efree(lcname);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Method %s::%s() does not exist", ce->name, name_str);
+ "Method %v::%R() does not exist", ce->name, type, name_str);
return;
}
- free_alloca(lcname);
+ efree(lcname);
MAKE_STD_ZVAL(name);
- ZVAL_STRING(name, mptr->common.function_name, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(name, (UChar*)mptr->common.function_name, 1);
+ } else {
+ ZVAL_STRING(name, mptr->common.function_name, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &name, sizeof(zval *), NULL);
intern->ptr = mptr;
intern->free_ptr = 0;
@@ -1989,11 +2031,11 @@ ZEND_METHOD(reflection_method, invoke)
(mptr->common.fn_flags & ZEND_ACC_ABSTRACT)) {
if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke abstract method %s::%s()",
+ "Trying to invoke abstract method %v::%v()",
mptr->common.scope->name, mptr->common.function_name);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke %s method %s::%s() from scope %s",
+ "Trying to invoke %s method %v::%v() from scope %v",
mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
mptr->common.scope->name, mptr->common.function_name,
Z_OBJCE_P(getThis())->name);
@@ -2054,7 +2096,7 @@ ZEND_METHOD(reflection_method, invoke)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
+ "Invocation of method %v::%v() failed", mptr->common.scope->name, mptr->common.function_name);
return;
}
@@ -2092,11 +2134,11 @@ ZEND_METHOD(reflection_method, invokeArgs)
(mptr->common.fn_flags & ZEND_ACC_ABSTRACT)) {
if (mptr->common.fn_flags & ZEND_ACC_ABSTRACT) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke abstract method %s::%s",
+ "Trying to invoke abstract method %v::%v",
mptr->common.scope->name, mptr->common.function_name);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke %s method %s::%s from scope %s",
+ "Trying to invoke %s method %v::%v from scope %v",
mptr->common.fn_flags & ZEND_ACC_PROTECTED ? "protected" : "private",
mptr->common.scope->name, mptr->common.function_name,
Z_OBJCE_P(getThis())->name);
@@ -2123,7 +2165,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
if (!object) {
efree(params);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Trying to invoke non static method %s::%s without an object",
+ "Trying to invoke non static method %v::%v without an object",
mptr->common.scope->name, mptr->common.function_name);
return;
}
@@ -2158,7 +2200,7 @@ ZEND_METHOD(reflection_method, invokeArgs)
if (result == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Invocation of method %s::%s() failed", mptr->common.scope->name, mptr->common.function_name);
+ "Invocation of method %v::%v() failed", mptr->common.scope->name, mptr->common.function_name);
return;
}
@@ -2308,7 +2350,11 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
if (Z_TYPE_P(argument) == IS_OBJECT) {
MAKE_STD_ZVAL(classname);
- ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(classname, (UChar*)Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
+ } else {
+ ZVAL_STRINGL(classname, Z_OBJCE_P(argument)->name, Z_OBJCE_P(argument)->name_length, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
intern->ptr = Z_OBJCE_P(argument);
if (is_object) {
@@ -2317,7 +2363,7 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
}
} else {
convert_to_string_ex(&argument);
- if (zend_lookup_class(Z_STRVAL_P(argument), Z_STRLEN_P(argument), &ce TSRMLS_CC) == FAILURE) {
+ if (zend_u_lookup_class(Z_TYPE_P(argument), Z_UNIVAL_P(argument), Z_UNILEN_P(argument), &ce TSRMLS_CC) == FAILURE) {
if (!EG(exception)) {
zend_throw_exception_ex(reflection_exception_ptr, -1 TSRMLS_CC, "Class %s does not exist", Z_STRVAL_P(argument));
}
@@ -2325,7 +2371,11 @@ static void reflection_class_object_ctor(INTERNAL_FUNCTION_PARAMETERS, int is_ob
}
MAKE_STD_ZVAL(classname);
- ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(classname, (UChar*)((*ce)->name), (*ce)->name_length, 1);
+ } else {
+ ZVAL_STRINGL(classname, (*ce)->name, (*ce)->name_length, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &classname, sizeof(zval *), NULL);
intern->ptr = *ce;
@@ -2613,17 +2663,19 @@ ZEND_METHOD(reflection_class, hasMethod)
{
reflection_object *intern;
zend_class_entry *ce;
+ unsigned int lc_name_len;
char *name, *lc_name;
int name_len;
+ zend_uchar type;
METHOD_NOTSTATIC;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &type) == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
- lc_name = zend_str_tolower_dup(name, name_len);
- if (zend_hash_exists(&ce->function_table, lc_name, name_len + 1)) {
+ lc_name = zend_u_str_case_fold(type, name, name_len, 1, &lc_name_len);
+ if (zend_u_hash_exists(&ce->function_table, type, lc_name, lc_name_len + 1)) {
efree(lc_name);
RETURN_TRUE;
} else {
@@ -2640,23 +2692,25 @@ ZEND_METHOD(reflection_class, getMethod)
reflection_object *intern;
zend_class_entry *ce;
zend_function *mptr;
+ unsigned int lc_name_len;
char *name, *lc_name;
int name_len;
+ zend_uchar type;
METHOD_NOTSTATIC;
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &name, &name_len, &type) == FAILURE) {
return;
}
GET_REFLECTION_OBJECT_PTR(ce);
- lc_name = zend_str_tolower_dup(name, name_len);
- if (zend_hash_find(&ce->function_table, lc_name, name_len + 1, (void**) &mptr) == SUCCESS) {
+ lc_name = zend_u_str_case_fold(type, name, name_len, 1, &lc_name_len);
+ if (zend_u_hash_find(&ce->function_table, type, lc_name, lc_name_len + 1, (void**) &mptr) == SUCCESS) {
reflection_method_factory(ce, mptr, return_value TSRMLS_CC);
efree(lc_name);
} else {
efree(lc_name);
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Method %s does not exist", name);
+ "Method %R does not exist", type, name);
return;
}
}
@@ -2989,7 +3043,7 @@ ZEND_METHOD(reflection_class, newInstance)
zend_fcall_info_cache fcc;
if (!(ce->constructor->common.fn_flags & ZEND_ACC_PUBLIC)) {
- zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %s", ce->name);
+ zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC, "Access to non-public constructor of class %v", ce->name);
return;
}
@@ -3017,7 +3071,7 @@ ZEND_METHOD(reflection_class, newInstance)
if (zend_call_function(&fci, &fcc TSRMLS_CC) == FAILURE) {
efree(params);
zval_ptr_dtor(&retval_ptr);
- zend_error(E_WARNING, "Invocation of %s's constructor failed", ce->name);
+ zend_error(E_WARNING, "Invocation of %v's constructor failed", ce->name);
RETURN_NULL();
}
if (retval_ptr) {
@@ -3089,7 +3143,8 @@ ZEND_METHOD(reflection_class, isSubclassOf)
switch(class_name->type) {
case IS_STRING:
- if (zend_lookup_class(Z_STRVAL_P(class_name), Z_STRLEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
+ case IS_UNICODE:
+ if (zend_u_lookup_class(Z_TYPE_P(class_name), Z_UNIVAL_P(class_name), Z_UNILEN_P(class_name), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s does not exist", Z_STRVAL_P(class_name));
return;
@@ -3135,7 +3190,8 @@ ZEND_METHOD(reflection_class, implementsInterface)
switch(interface->type) {
case IS_STRING:
- if (zend_lookup_class(Z_STRVAL_P(interface), Z_STRLEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
+ case IS_UNICODE:
+ if (zend_u_lookup_class(Z_TYPE_P(interface), Z_UNIVAL_P(interface), Z_UNILEN_P(interface), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Interface %s does not exist", Z_STRVAL_P(interface));
return;
@@ -3161,7 +3217,7 @@ ZEND_METHOD(reflection_class, implementsInterface)
if (!(interface_ce->ce_flags & ZEND_ACC_INTERFACE)) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Interface %s is a Class", interface_ce->name);
+ "Interface %v is a Class", interface_ce->name);
return;
}
RETURN_BOOL(instanceof_function(ce, interface_ce TSRMLS_CC));
@@ -3267,7 +3323,8 @@ ZEND_METHOD(reflection_property, __construct)
/* Find the class entry */
switch (Z_TYPE_P(classname)) {
case IS_STRING:
- if (zend_lookup_class(Z_STRVAL_P(classname), Z_STRLEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
+ case IS_UNICODE:
+ if (zend_u_lookup_class(Z_TYPE_P(classname), Z_UNIVAL_P(classname), Z_UNILEN_P(classname), &pce TSRMLS_CC) == FAILURE) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
"Class %s does not exist", Z_STRVAL_P(classname));
return;
@@ -3286,7 +3343,7 @@ ZEND_METHOD(reflection_property, __construct)
if (zend_hash_find(&ce->properties_info, name_str, name_len + 1, (void **) &property_info) == FAILURE || (property_info->flags & ZEND_ACC_SHADOW)) {
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Property %s::$%s does not exist", ce->name, name_str);
+ "Property %v::$%s does not exist", ce->name, name_str);
return;
}
@@ -3307,12 +3364,20 @@ ZEND_METHOD(reflection_property, __construct)
}
MAKE_STD_ZVAL(classname);
- ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODEL(classname, (UChar*)ce->name, ce->name_length, 1);
+ } else {
+ ZVAL_STRINGL(classname, ce->name, ce->name_length, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "class", sizeof("class"), (void **) &classname, sizeof(zval *), NULL);
- zend_unmangle_property_name(property_info->name, &class_name, &prop_name);
+ zend_u_unmangle_property_name(UG(unicode)?IS_UNICODE:IS_STRING, property_info->name, &class_name, &prop_name);
MAKE_STD_ZVAL(propname);
- ZVAL_STRING(propname, prop_name, 1);
+ if (UG(unicode)) {
+ ZVAL_UNICODE(propname, (UChar*)prop_name, 1);
+ } else {
+ ZVAL_STRING(propname, prop_name, 1);
+ }
zend_hash_update(Z_OBJPROP_P(object), "name", sizeof("name"), (void **) &propname, sizeof(zval *), NULL);
reference = (property_reference*) emalloc(sizeof(property_reference));
@@ -3421,6 +3486,7 @@ ZEND_METHOD(reflection_property, getValue)
property_reference *ref;
zval *object;
zval **member= NULL;
+ zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
METHOD_NOTSTATIC;
GET_REFLECTION_OBJECT_PTR(ref);
@@ -3432,16 +3498,16 @@ ZEND_METHOD(reflection_property, getValue)
if ((ref->prop->flags & ZEND_ACC_STATIC)) {
zend_update_class_constants(intern->ce TSRMLS_CC);
- if (zend_hash_quick_find(intern->ce->static_members, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
- zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
+ if (zend_u_hash_quick_find(intern->ce->static_members, utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
+ zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name);
/* Bails out */
}
} else {
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o", &object) == FAILURE) {
return;
}
- if (zend_hash_quick_find(Z_OBJPROP_P(object), ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
- zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
+ if (zend_u_hash_quick_find(Z_OBJPROP_P(object), utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &member) == FAILURE) {
+ zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name);
/* Bails out */
}
}
@@ -3463,6 +3529,7 @@ ZEND_METHOD(reflection_property, setValue)
int setter_done = 0;
zval *tmp;
HashTable *prop_table;
+ zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
METHOD_NOTSTATIC;
GET_REFLECTION_OBJECT_PTR(ref);
@@ -3486,8 +3553,8 @@ ZEND_METHOD(reflection_property, setValue)
prop_table = Z_OBJPROP_P(object);
}
- if (zend_hash_quick_find(prop_table, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) {
- zend_error(E_ERROR, "Internal error: Could not find the property %s", ref->prop->name);
+ if (zend_u_hash_quick_find(prop_table, utype, ref->prop->name, ref->prop->name_length + 1, ref->prop->h, (void **) &variable_ptr) == FAILURE) {
+ zend_error(E_ERROR, "Internal error: Could not find the property %v", ref->prop->name);
/* Bails out */
}
if (*variable_ptr == value) {
@@ -3510,7 +3577,7 @@ ZEND_METHOD(reflection_property, setValue)
if (PZVAL_IS_REF(value)) {
SEPARATE_ZVAL(&value);
}
- zend_hash_quick_update(prop_table, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo);
+ zend_u_hash_quick_update(prop_table, utype, ref->prop->name, ref->prop->name_length+1, ref->prop->h, &value, sizeof(zval *), (void **) &foo);
}
}
/* }}} */
@@ -3943,12 +4010,13 @@ static zend_object_handlers *zend_std_obj_handlers;
/* {{{ _reflection_write_property */
static void _reflection_write_property(zval *object, zval *member, zval *value TSRMLS_DC)
{
- if (Z_TYPE_P(member) == IS_STRING
- && zend_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1)
- && (!strcmp(Z_STRVAL_P(member), "name") || !strcmp(Z_STRVAL_P(member), "class")))
+ if ((Z_TYPE_P(member) == IS_STRING || Z_TYPE_P(member) == IS_UNICODE)
+ && zend_u_hash_exists(&Z_OBJCE_P(object)->default_properties, Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member)+1)
+ && (ZEND_U_EQUAL(Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member), "name", sizeof("name")-1) ||
+ ZEND_U_EQUAL(Z_TYPE_P(member), Z_UNIVAL_P(member), Z_UNILEN_P(member), "class", sizeof("class")-1)))
{
zend_throw_exception_ex(reflection_exception_ptr, 0 TSRMLS_CC,
- "Cannot set read-only property %s::$%s", Z_OBJCE_P(object)->name, Z_STRVAL_P(member));
+ "Cannot set read-only property %v::$%R", Z_OBJCE_P(object)->name, Z_TYPE_P(member), Z_UNIVAL_P(member));
}
else
{
@@ -4038,6 +4106,20 @@ ZEND_API void zend_register_reflection_api(TSRMLS_D) {
}
/* }}} */
+void init_reflection_api(TSRMLS_D)
+{
+ reflection_exception_ptr = zend_get_named_class_entry("ReflectionException", sizeof("ReflectionException")-1 TSRMLS_CC);
+ reflection_ptr = zend_get_named_class_entry("Reflection", sizeof("Reflection")-1 TSRMLS_CC);
+ reflector_ptr = zend_get_named_class_entry("Reflector", sizeof("Reflector")-1 TSRMLS_CC);
+ reflection_function_ptr = zend_get_named_class_entry("ReflectionFunction", sizeof("ReflectionFunction")-1 TSRMLS_CC);
+ reflection_parameter_ptr = zend_get_named_class_entry("ReflectionParameter", sizeof("ReflectionParameter")-1 TSRMLS_CC);
+ reflection_method_ptr = zend_get_named_class_entry("ReflectionMethod", sizeof("ReflectionMethod")-1 TSRMLS_CC);
+ reflection_class_ptr = zend_get_named_class_entry("ReflectionClass", sizeof("ReflectionClass")-1 TSRMLS_CC);
+ reflection_object_ptr = zend_get_named_class_entry("ReflectionObject", sizeof("ReflectionObject")-1 TSRMLS_CC);
+ reflection_property_ptr = zend_get_named_class_entry("ReflectionProperty", sizeof("ReflectionProperty")-1 TSRMLS_CC);
+ reflection_extension_ptr = zend_get_named_class_entry("ReflectionExtension", sizeof("ReflectionExtension")-1 TSRMLS_CC);
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/reflection/php_reflection.h b/ext/reflection/php_reflection.h
index fb06af4687..a16ed9b7f9 100644
--- a/ext/reflection/php_reflection.h
+++ b/ext/reflection/php_reflection.h
@@ -26,6 +26,8 @@ BEGIN_EXTERN_C()
ZEND_API void zend_register_reflection_api(TSRMLS_D);
ZEND_API void zend_reflection_class_factory(zend_class_entry *ce, zval *object TSRMLS_DC);
+void init_reflection_api(TSRMLS_D);
+
END_EXTERN_C()
#endif