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@
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)
#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,
#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);
}
+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()
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;
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");
}
}
} 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:
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;
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)) {
}
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;
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;
}
+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);
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);
}
}
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)
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);
}
}
+#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)
{
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;
start_memory_manager(TSRMLS_C);
}
-
#if defined(__FreeBSD__) || defined(__DragonFly__)
/* FreeBSD and DragonFly floating point precision fix */
#include <floatingpoint.h>
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)
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
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();
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);
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;
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);
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)
#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();
}
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);
} zend_end_try();
}
-void zend_call_destructors(TSRMLS_D)
+void zend_call_destructors(TSRMLS_D)
{
zend_try {
shutdown_destructors(TSRMLS_C);
EG(opline_ptr) = NULL;
EG(active_symbol_table) = NULL;
+ shutdown_unicode_request_globals(TSRMLS_C);
+
zend_try {
shutdown_scanner(TSRMLS_C);
} zend_end_try();
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) {
#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, ...)
{
#endif
#include <stdio.h>
+#include <assert.h>
/*
* general definitions
#include "zend_types.h"
+#include <unicode/utypes.h>
+
#ifdef HAVE_LIMITS_H
# include <limits.h>
#endif
#define LONG_MIN (- LONG_MAX - 1)
#endif
+#define EMPTY_STR "\0\0"
+
#undef SUCCESS
#undef FAILURE
#define SUCCESS 0
# 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
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;
#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);
((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))
#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
#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);
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);
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);
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()
#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 */
/*
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));
}
case IS_RESOURCE:
return "resource";
+ case IS_UNICODE:
+ return "Unicode string";
+
+ case IS_BINARY:
+ return "binary data";
+
default:
return "unknown";
}
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++;
}
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:
}
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:
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);
*pl = Z_STRLEN_PP(arg);
*p = Z_STRVAL_PP(arg);
break;
+ } else {
+ return "string";
}
}
}
}
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 *);
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));
}
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;
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));
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),
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++;
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));
}
*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;
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;
}
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;
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);
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 {
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)
{
}
+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);
}
+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);
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)
{
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 */
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);
}
}
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;
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;
}
}
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++;
}
#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
}
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;
}
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));
}
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;
}
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;
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);
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;
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;
}
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) {
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;
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;
}
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;
}
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;
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);
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);
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
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; \
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);
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)
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)
#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)
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);
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);
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);
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);
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) { \
(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; \
#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; }
#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) { \
{ \
#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
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;
}
+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;
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)
{
#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
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;
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
#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))
#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))
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;
+ }
}
/* }}} */
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;
case IS_LONG:
case IS_DOUBLE:
case IS_STRING:
+ case IS_BINARY:
+ case IS_UNICODE:
case IS_BOOL:
case IS_RESOURCE:
case IS_NULL:
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;
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 {
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");
}
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);
+ }
}
/* }}} */
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;
}
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;
}
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;
}
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) {
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) {
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);
}
}
}
{
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);
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);
}
}
}
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;
}
}
|| ((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);
ZEND_FUNCTION(method_exists)
{
zval **klass, **method_name;
+ unsigned int lcname_len;
char *lcname;
zend_class_entry * ce, **pce;
}
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 {
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;
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;
{
zval **function_name;
zend_function *func;
+ unsigned int lcname_len;
char *lcname;
zend_bool retval;
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);
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;
}
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;
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);
*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;
}
while (ptr) {
char *free_class_name = NULL;
+ int function_name_string = 1;
class_name = call_type = NULL;
arg_array = NULL;
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;
}
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);
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);
}
#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);
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);
}
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);
+ }
}
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;
}
/* 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;
}
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 */
}
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 */
}
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;
}
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;
}
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;
}
}
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;
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;
}
-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);
}
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));
}
}
}
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;
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);
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;
}
opline->result = *result;
opline->op1 = *result;
opline->op2 = *op2;
+ opline->extended_value = CG(literal_type);
*result = opline->result;
}
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 */
}
}
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);
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);
}
}
}
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);
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)) {
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);
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);
}
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;
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: {
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:
*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;
}
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));
+ }
}
}
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;
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;
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);
* 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);
}
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;
}
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;
*/
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) {
/* 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;
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);
}
}
{
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 {
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) {
}
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 */
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);
}
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);
}
}
{
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;
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;
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 {
{
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
* 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 {
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) {
* 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 {
}
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);
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);
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) {
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;
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);
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) {
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));
{
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);
}
}
*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)
{
*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;
}
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);
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);
}
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);
}
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
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:
}
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 */
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);
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);
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));
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);
}
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;
+ }
+ }
+ }
}
}
-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);
}
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)
{
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));
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;
}
-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;
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
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! */
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);
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);
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
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
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 {
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);
{
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;
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;
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;
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) {
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 {
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 {
}
-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;
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)) {
}
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
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()
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);
_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);
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");
}
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);
}
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);
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);
}
}
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
/* 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
#include "zend_ini.h"
#include "zend_exceptions.h"
#include "zend_vm.h"
+#include "zend_unicode.h"
#define _CONST_CODE 0
#define _TMP_CODE 1
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)
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;
}
}
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;
}
}
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;
}
}
/* 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);
}
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)) {
}
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;
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;
}
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);
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;
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);
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); */
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;
*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--;
}
*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);
}
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) {
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;
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);
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:
}
break;
}
+ case IS_UNICODE:
+ case IS_BINARY:
case IS_STRING: {
zval tmp;
/* 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:
}
}
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)
{
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;
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;
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
/* 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 */
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)
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;
if (space) {
*space = "";
}
- return "";
+ return EMPTY_STR;
}
switch (EG(function_state_ptr)->function->type) {
case ZEND_USER_FUNCTION:
if (space) {
*space = ce ? "::" : "";
}
- return ce ? ce->name : "";
+ return ce ? ce->name : EMPTY_STR;
}
default:
if (space) {
*space = "";
}
- return "";
+ return EMPTY_STR;
}
}
if (function_name) {
return function_name;
+ } else if (UG(unicode)) {
+ return (char*) u_main;
} else {
return "main";
}
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);
}
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;
}
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;
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);
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 */
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");
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) &&
}
}
- 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) {
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) {
} 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);
}
}
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);
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;
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;
}
* (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;
}
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;
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)) {
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;
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);*/
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;
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)
{
}
-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;
}
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;
}
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 {
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),
}
}
-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
| 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 |
#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*/
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
};
zend_property_info std_property_info;
+#ifdef ZTS
+ HashTable *global_constants_table;
+ HashTable *global_u_constants_table;
+#endif
+
void *reserved[ZEND_MAX_RESERVED_RESOURCES];
};
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 */
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
#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()
| 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 |
/* $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); \
(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
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; \
-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;
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 *));
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)
{
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)
{
-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);
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;
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);
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) {
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);
}
}
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;
}
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;
}
if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext;
- } else {
+ } else {
/* Deleting the head of the list */
ht->pListHead = p->pListNext;
}
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)
{
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);
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);
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;
if (p->pListLast != NULL) {
p->pListLast->pListNext = p->pListNext;
- } else {
+ } else {
/* Deleting the head of the list */
ht->pListHead = p->pListNext;
}
}
/* 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
*/
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 {
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) {
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);
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);
}
}
{
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);
}
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);
}
}
}
+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);
}
* 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);
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);
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)
{
}
-/* 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)
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;
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;
}
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;
}
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]);
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;
}
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;
}
}
} 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;
p2 = p2->pListNext;
}
}
-
- HASH_UNPROTECT_RECURSION(ht1);
- HASH_UNPROTECT_RECURSION(ht2);
+
+ HASH_UNPROTECT_RECURSION(ht1);
+ HASH_UNPROTECT_RECURSION(ht2);
return 0;
}
}
+#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)
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;
}
}
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;
}
}
#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)
#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);
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;
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 {
Bucket **arBuckets;
dtor_func_t pDestructor;
zend_bool persistent;
+ zend_bool unicode;
unsigned char nApplyCount;
zend_bool bApplyProtection;
#if ZEND_DEBUG
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;
/* 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) \
_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
/* 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);
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 */
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 */
#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)
{
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() */
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;
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:
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;
}
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) {
if (ptr[LANG_SCNG(yy_leng) - 1] == ';') {
lex_scan(&token TSRMLS_CC);
}
- efree(token.value.str.val);
+ efree(Z_UNIVAL(token));
}
break;
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:
break;
default:
- efree(token.value.str.val);
+ efree(Z_UNIVAL(token));
break;
}
}
} 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);
}
}
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;
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;
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) {
*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:
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)
{
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,
}
/* }}} */
+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
ZEND_API void zend_register_interfaces(TSRMLS_D);
+void init_interfaces(TSRMLS_D);
+
END_EXTERN_C()
#endif /* ZEND_INTERFACES_H */
%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
%token T_DOLLAR_OPEN_CURLY_BRACES
%token T_CURLY_OPEN
%token T_PAAMAYIM_NEKUDOTAYIM
+%token T_BINARY_DOUBLE
+%token T_BINARY_HEREDOC
%% /* Rules */
| 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 ')' ';'
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); }
;
;
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); }
;
| 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); }
| '@' { 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); }
;
| 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); }
;
compound_variable:
T_VARIABLE { $$ = $1; }
- | '$' '{' expr '}' { $$ = $3; }
+ | '$' '{' expr '}' { zend_do_normalization(&$$, &$3 TSRMLS_CC); }
;
dim_offset:
variable_name:
T_STRING { $$ = $1; }
- | '{' expr '}' { $$ = $2; }
+ | '{' expr '}' { zend_do_normalization(&$$, &$2 TSRMLS_CC); }
;
simple_indirect_reference:
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;
%x ST_IN_SCRIPTING
%x ST_DOUBLE_QUOTES
-%x ST_SINGLE_QUOTE
%x ST_BACKQUOTE
%x ST_HEREDOC
%x ST_LOOKING_FOR_PROPERTY
#include "zend_operators.h"
#include "zend_API.h"
#include "zend_strtod.h"
+#include "zend_unicode.h"
#ifdef HAVE_STDARG_H
# include <stdarg.h>
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
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;
}
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()
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)
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));
}
- if (SCNG(script_filtered)) {
- efree(SCNG(script_filtered));
- SCNG(script_filtered) = NULL;
+ SCNG(input_conv) = lex_state->input_conv;
+ if (SCNG(output_conv)) {
+ ucnv_close(SCNG(output_conv));
}
- 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(output_conv) = lex_state->output_conv;
+ SCNG(encoding_checked) = lex_state->encoding_checked;
+ if (SCNG(rest_str)) {
+ efree(SCNG(rest_str));
+ }
+ SCNG(rest_str) = lex_state->rest_str;
+ SCNG(rest_len) = lex_state->rest_len;
}
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;
+}
-#ifdef ZEND_MULTIBYTE
- if (file_handle->handle.stream.interactive == 0) {
- if (zend_multibyte_read_script(TSRMLS_C) != 0) {
+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;
+
+ 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);
+}
- /* force flex to use buffer only */
- SCNG(yy_in) = NULL;
- SCNG(init) = 0;
- SCNG(start) = 1;
+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;
+
+ /* 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);
+ }
+ 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;
}
-#else /* !ZEND_MULTIBYTE */
+
+ 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);
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);
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;
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);
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;
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;
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};
+
+ zendlval->value.str.len--; /* for the 'x' */
- SCNG(script_org_size) += n;
- if (SCNG(script_org)) {
- SCNG(script_org) = (char*)erealloc(SCNG(script_org), SCNG(script_org_size)+1);
+ 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;
+}
+
+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);
- if (!SCNG(script_org)) {
- SCNG(script_org) = emalloc(SCNG(script_org_size)+1);
+ /* 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]+
<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;
}
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;
}
<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;
}
<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;
}
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;
}
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;
}
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;
}
}
<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;
}
} 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;
}
}
} 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;
}
}
} 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;
}
}
}
<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;
}
<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);
}
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;
}
-<ST_IN_SCRIPTING>['] {
- BEGIN(ST_SINGLE_QUOTE);
- return '\'';
-}
-
-
<ST_HEREDOC>^{LABEL}(";")?{NEWLINE} {
int label_len;
unsigned char unput_semicolon;
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;
}
}
<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;
}
}
-<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;
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':
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;
}
<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;
}
}
-<ST_SINGLE_QUOTE>['] {
- BEGIN(ST_IN_SCRIPTING);
- return '\'';
-}
-
-
<ST_DOUBLE_QUOTES,ST_BACKQUOTE,INITIAL,ST_IN_SCRIPTING,ST_LOOKING_FOR_PROPERTY><<EOF>> {
return 0;
}
-<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);
}
};
-
+#if 0
ZEND_API int zend_multibyte_set_script_encoding(char *encoding_list, int encoding_list_size TSRMLS_DC)
{
if (CG(script_encoding_list)) {
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;
}
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 */
}
+#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;
return 0;
}
-
+#endif
static zend_encoding* zend_multibyte_find_script_encoding(zend_encoding *onetime_encoding TSRMLS_DC)
{
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) {
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;
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;
/* 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 */
}
} 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);
}
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;
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);
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;
}
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;
}
}
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);
}
}
}
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;
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;
}
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) {
/* 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;
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 */
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);
}
}
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
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;
{
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;
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;
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;
*/
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;
}
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 */
*/
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);
}
}
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;
}
#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);
}
}
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;
}
/* 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);
}
}
}
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;
}
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;
}
*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;
}
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);
zval_ptr_dtor(&retval);
return SUCCESS;
}
+ if (UG(unicode)) {
+ zval_dtor(&fname);
+ }
break;
default:
break;
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;
}
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;
}
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;
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);
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);
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;
}
#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)
{
switch (op->type) {
case IS_STRING:
+ case IS_BINARY:
{
char *strval;
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;
} 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: \
(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; \
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; \
(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; \
(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; \
ZEND_API void convert_to_long_base(zval *op, int base)
{
- char *strval;
long tmp;
switch (op->type) {
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);
ZEND_API void convert_to_double(zval *op)
{
- char *strval;
double tmp;
switch (op->type) {
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);
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);
ZEND_API void convert_to_boolean(zval *op)
{
- char *strval;
int tmp;
switch (op->type) {
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);
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;
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) {
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;
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;
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;
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) {
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;
}
}
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;
break;
}
default:
- convert_scalar_to_array(op, IS_OBJECT);
+ convert_scalar_to_array(op, IS_OBJECT TSRMLS_CC);
break;
}
}
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++) {
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;
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++) {
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);
{
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;
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++) {
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);
{
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;
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++) {
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);
{
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;
{
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;
}
-
/* 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;
}
/* 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;
}
{
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
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);
}
}
- 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);
}
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;
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;
op1->value.lval = 1;
op1->type = IS_LONG;
break;
+ case IS_BINARY:
case IS_STRING: {
long lval;
double dval;
}
}
break;
+ case IS_UNICODE:
+ zend_error(E_ERROR, "Unsupported operand type");
+ break;
default:
return FAILURE;
}
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);
break;
}
break;
+ case IS_UNICODE:
+ zend_error(E_ERROR, "Unsupported operand type");
+ break;
default:
return FAILURE;
}
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;
}
}
+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;
}
}
+
+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;
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);
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)) {
}
+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;
}
}
+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;
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
#endif
#include "zend_strtod.h"
+#include "zend_unicode.h"
#if 0&&HAVE_BCMATH
#include "ext/bcmath/libbcmath/src/bcmath.h"
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)
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)
{
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);
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);
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);
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);
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) { \
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) { \
#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
#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)
#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)
#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)
/* 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; \
} \
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;
}
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");
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 ");
}
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);
}
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,
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");
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;
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);
}
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);
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;
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 */
}
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);
}
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;
}
{
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;
}
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;
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;
}
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;
}
/* 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;
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)) {
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;
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);
}
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);
}
}
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;
}
/* 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;
}
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;
(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);
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;
}
(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);
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;
}
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;
}
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) {
}
} 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));
}
}
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;
{
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 {
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;
}
}
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;
}
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) {
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;
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;
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));
/* 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;
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;
}
}
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));
property_reference *ref;
zval *object;
zval **member= NULL;
+ zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
METHOD_NOTSTATIC;
GET_REFLECTION_OBJECT_PTR(ref);
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 */
}
}
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);
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) {
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);
}
}
/* }}} */
/* {{{ _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
{
}
/* }}} */
+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
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
*/
#include <zend_strtod.h>
+#include <unicode/utypes.h>
+#include <unicode/ustdio.h>
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
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;
+ }
+}
--- /dev/null
+/*-
+ * 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);
+}
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | 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: */
--- /dev/null
+/*
+ +----------------------------------------------------------------------+
+ | 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 */
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();
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:
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;
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;
}
}
}
-
ZEND_API int zend_print_variable(zval *var)
{
return zend_print_zval(var, 0);
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();
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()
}
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;
{
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();
}
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();
}
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();
}
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);
}
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");
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);
/* 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) {
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);
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);
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 */
}
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) {
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);
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;
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) {
}
}
- 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();
}
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);
} 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);
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++;
}
/* 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);
}
}
}
}
}
*/
- 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);
}
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();
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);
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;
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);
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;
}
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;
}
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
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();
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);
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;
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;
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;
}
}
} 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;
}
}
}
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;
} 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) {
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;
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 */
}
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;
}
}
+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)
{
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();
}
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 */
}
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) {
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);
}
}
- 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();
}
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);
} 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);
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 */
}
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;
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");
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);
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);
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");
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);
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);
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");
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);
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);
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");
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);
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");
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);
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);
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();
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()
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
+ if (IS_CONST != IS_TMP_VAR) {
+
+ }
+ break;
case ZEND_FETCH_LOCAL:
break;
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;
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) {
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++;
}
/* 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);
}
}
}
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;
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);
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;
}
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;
}
}
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();
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);
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;
}
}
} 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;
}
}
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);
}
}
*/
- 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);
}
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();
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);
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);
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);
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);
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);
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);
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()
}
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;
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) {
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++;
}
/* 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);
}
}
}
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;
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);
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;
}
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;
}
}
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();
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);
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;
}
}
} 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;
}
}
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);
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();
}
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();
}
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);
/* 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) {
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);
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);
}
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);
/* 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) {
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);
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);
}
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);
/* 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) {
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);
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);
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);
}
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);
/* 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) {
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);
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);};
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()
}
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;
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) {
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++;
}
/* 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);
}
}
}
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;
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);
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;
}
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;
}
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();
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);
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;
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;
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;
}
}
} 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;
}
}
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);
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);
/* 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) {
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);
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
}
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;
} 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) {
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;
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);
/* 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) {
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);
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
}
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;
} 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) {
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;
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);
/* 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) {
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);
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
}
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;
} 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) {
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;
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);
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);
/* 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) {
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);
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
}
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;
} 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) {
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;
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++;
}
/* 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);
}
}
}
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);
/* 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) {
}
}
*/
- 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);
}
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();
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);
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
}
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;
} 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) {
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;
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);
/* 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) {
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);
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
}
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;
} 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) {
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;
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);
/* 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) {
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);
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
}
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;
} 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) {
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;
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);
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);
/* 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) {
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);
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
}
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;
} 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) {
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;
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();
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()
}
switch (opline->op2.u.EA.type) {
case ZEND_FETCH_GLOBAL:
+ if (IS_CV != IS_TMP_VAR) {
+
+ }
+ break;
case ZEND_FETCH_LOCAL:
break;
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) {
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++;
}
/* 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);
}
}
}
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;
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);
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;
}
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;
}
}
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();
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);
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;
}
}
} 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;
}
}
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);
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);
/* 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) {
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);
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
}
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;
} 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) {
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;
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);
/* 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) {
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);
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
}
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;
} 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) {
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;
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);
/* 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) {
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);
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
}
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;
} 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) {
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;
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);
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);
/* 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) {
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);
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) {
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;
}
}
}
}
+ if (free_offset) {
+ efree(offset_key);
+ }
break;
+ }
case IS_NULL:
zend_hash_del(ht, "", sizeof(""));
break;
}
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;
} 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) {
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;
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;
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");
}
fclose($f);
- echo "zend_vm_execute.h generated succesfull.\n";
+ echo "zend_vm_execute.h generated succesfully.\n";
}
function usage() {
#define ZEND_ISSET_ISEMPTY_PROP_OBJ 148
#define ZEND_HANDLE_EXCEPTION 149
#define ZEND_USER_OPCODE 150
+#define ZEND_U_NORMALIZE 151
/* 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; \
} \
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;
}
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");
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 ");
}
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);
}
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,
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");
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;
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);
}
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);
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;
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 */
}
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);
}
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;
}
{
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;
}
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;
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;
}
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;
}
/* 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;
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)) {
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;
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);
}
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);
}
}
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;
}
/* 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;
}
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;
(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);
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;
}
(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);
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;
}
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;
}
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) {
}
} 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));
}
}
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;
{
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 {
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;
}
}
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;
}
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) {
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;
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;
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));
/* 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;
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;
}
}
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));
property_reference *ref;
zval *object;
zval **member= NULL;
+ zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
METHOD_NOTSTATIC;
GET_REFLECTION_OBJECT_PTR(ref);
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 */
}
}
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);
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) {
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);
}
}
/* }}} */
/* {{{ _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
{
}
/* }}} */
+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
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