summaryrefslogtreecommitdiff
path: root/Zend/zend_compile.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_compile.c')
-rw-r--r--Zend/zend_compile.c623
1 files changed, 389 insertions, 234 deletions
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index a7c09b0a14..86c68cad13 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -27,10 +27,6 @@
#include "zend_API.h"
#include "zend_fast_cache.h"
-#ifdef ZEND_MULTIBYTE
-#include "zend_multibyte.h"
-#endif /* ZEND_MULTIBYTE */
-
ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
@@ -41,7 +37,13 @@ ZEND_API zend_executor_globals executor_globals;
static void zend_duplicate_property_info(zend_property_info *property_info)
{
- property_info->name = estrndup(property_info->name, property_info->name_length);
+ TSRMLS_FETCH();
+
+ if (UG(unicode)) {
+ property_info->name = (char*)eustrndup((UChar*)property_info->name, property_info->name_length);
+ } else {
+ property_info->name = estrndup(property_info->name, property_info->name_length);
+ }
if (property_info->doc_comment) {
property_info->doc_comment = estrndup(property_info->doc_comment, property_info->doc_comment_len);
}
@@ -50,7 +52,13 @@ static void zend_duplicate_property_info(zend_property_info *property_info)
static void zend_duplicate_property_info_internal(zend_property_info *property_info)
{
- property_info->name = zend_strndup(property_info->name, property_info->name_length);
+ TSRMLS_FETCH();
+
+ if (UG(unicode)) {
+ property_info->name = (char*)zend_ustrndup((UChar*)property_info->name, property_info->name_length);
+ } else {
+ property_info->name = zend_strndup(property_info->name, property_info->name_length);
+ }
}
@@ -68,7 +76,7 @@ static void zend_destroy_property_info_internal(zend_property_info *property_inf
free(property_info->name);
}
-static void build_runtime_defined_function_key(zval *result, char *name, int name_length TSRMLS_DC)
+static void build_runtime_defined_function_key(zval *result, zend_uchar type, char *name, int name_length TSRMLS_DC)
{
char char_pos_buf[32];
uint char_pos_len;
@@ -82,16 +90,16 @@ static void build_runtime_defined_function_key(zval *result, char *name, int nam
}
/* NULL, name length, filename length, last accepting char position length */
+ if (type == IS_UNICODE) {
+ name_length *= sizeof(UChar);
+ }
result->value.str.len = 1+name_length+strlen(filename)+char_pos_len;
result->value.str.val = (char *) emalloc(result->value.str.len+1);
-#ifdef ZEND_MULTIBYTE
- /* must be binary safe */
+ /* UTODO: function key should probably store UTF-16 value instead of converting to
+ runtime encoding */
result->value.str.val[0] = '\0';
memcpy(result->value.str.val+1, name, name_length);
sprintf(result->value.str.val+1+name_length, "%s%s", filename, char_pos_buf);
-#else
- sprintf(result->value.str.val, "%c%s%s%s", '\0', name, filename, char_pos_buf);
-#endif /* ZEND_MULTIBYTE */
result->type = IS_STRING;
result->refcount = 1;
}
@@ -140,15 +148,6 @@ void zend_init_compiler_data_structures(TSRMLS_D)
CG(start_lineno) = 0;
init_compiler_declarables(TSRMLS_C);
zend_hash_apply(CG(auto_globals), (apply_func_t) zend_auto_global_arm TSRMLS_CC);
-
-#ifdef ZEND_MULTIBYTE
- CG(script_encoding_list) = NULL;
- CG(script_encoding_list_size) = 0;
- CG(internal_encoding) = NULL;
- CG(encoding_detector) = NULL;
- CG(encoding_converter) = NULL;
- CG(encoding_oddlen) = NULL;
-#endif /* ZEND_MULTIBYTE */
}
@@ -173,12 +172,6 @@ void shutdown_compiler(TSRMLS_D)
zend_stack_destroy(&CG(list_stack));
zend_hash_destroy(&CG(filenames_table));
zend_llist_destroy(&CG(open_files));
-
-#ifdef ZEND_MULTIBYTE
- if (CG(script_encoding_list)) {
- efree(CG(script_encoding_list));
- }
-#endif /* ZEND_MULTIBYTE */
}
@@ -227,15 +220,15 @@ static zend_uint get_temporary_variable(zend_op_array *op_array)
return (op_array->T)++ * sizeof(temp_variable);
}
-static int lookup_cv(zend_op_array *op_array, char* name, int name_len)
+static int lookup_cv(zend_op_array *op_array, zend_uchar type, void *name, int name_len)
{
int i = 0;
- ulong hash_value = zend_inline_hash_func(name, name_len+1);
+ ulong hash_value = zend_u_inline_hash_func(type, name, name_len+1);
while (i < op_array->last_var) {
if (op_array->vars[i].hash_value == hash_value &&
op_array->vars[i].name_len == name_len &&
- strcmp(op_array->vars[i].name, name) == 0) {
+ !memcmp(op_array->vars[i].name, name, type==IS_UNICODE?UBYTES(name_len):name_len)) {
efree(name);
return i;
}
@@ -337,14 +330,16 @@ void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar
zend_op *opline_ptr;
zend_llist *fetch_list_ptr;
- if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING &&
- !zend_is_auto_global(varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC) &&
- !(varname->u.constant.value.str.len == (sizeof("this")-1) &&
- !memcmp(varname->u.constant.value.str.val, "this", sizeof("this"))) &&
+ if (varname->op_type == IS_CONST &&
+ (varname->u.constant.type == IS_STRING ||
+ varname->u.constant.type == IS_UNICODE) &&
+ !zend_u_is_auto_global(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant) TSRMLS_CC) &&
+ !(Z_UNILEN(varname->u.constant) == (sizeof("this")-1) &&
+ ZEND_U_EQUAL(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant), "this", sizeof("this")-1)) &&
(CG(active_op_array)->last == 0 ||
CG(active_op_array)->opcodes[CG(active_op_array)->last-1].opcode != ZEND_BEGIN_SILENCE)) {
result->op_type = IS_CV;
- result->u.var = lookup_cv(CG(active_op_array), varname->u.constant.value.str.val, varname->u.constant.value.str.len);
+ result->u.var = lookup_cv(CG(active_op_array), Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant));
result->u.EA.type = 0;
return;
}
@@ -365,8 +360,10 @@ void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar
SET_UNUSED(opline_ptr->op2);
opline_ptr->op2.u.EA.type = ZEND_FETCH_LOCAL;
- if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING) {
- if (zend_is_auto_global(varname->u.constant.value.str.val, varname->u.constant.value.str.len TSRMLS_CC)) {
+ if (varname->op_type == IS_CONST &&
+ (varname->u.constant.type == IS_STRING ||
+ varname->u.constant.type == IS_UNICODE)) {
+ if (zend_u_is_auto_global(Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant) TSRMLS_CC)) {
opline_ptr->op2.u.EA.type = ZEND_FETCH_GLOBAL;
}
}
@@ -399,9 +396,15 @@ void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC)
opline.result.u.EA.type = 0;
opline.result.u.var = get_temporary_variable(CG(active_op_array));
opline.op1.op_type = IS_CONST;
- opline.op1.u.constant.type = IS_STRING;
- opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[result->u.var].name);
- opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[result->u.var].name_len;
+ if (UG(unicode)) {
+ opline.op1.u.constant.type = IS_UNICODE;
+ Z_USTRVAL(opline.op1.u.constant) = eustrndup((UChar*)CG(active_op_array)->vars[result->u.var].name, CG(active_op_array)->vars[result->u.var].name_len);
+ Z_USTRLEN(opline.op1.u.constant) = CG(active_op_array)->vars[result->u.var].name_len;
+ } else {
+ opline.op1.u.constant.type = IS_STRING;
+ Z_STRVAL(opline.op1.u.constant) = estrndup(CG(active_op_array)->vars[result->u.var].name, CG(active_op_array)->vars[result->u.var].name_len);
+ Z_STRLEN(opline.op1.u.constant) = CG(active_op_array)->vars[result->u.var].name_len;
+ }
SET_UNUSED(opline.op2);
opline.op2 = *class_znode;
opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
@@ -419,9 +422,15 @@ void zend_do_fetch_static_member(znode *result, znode *class_znode TSRMLS_DC)
opline.result.u.EA.type = 0;
opline.result.u.var = get_temporary_variable(CG(active_op_array));
opline.op1.op_type = IS_CONST;
- opline.op1.u.constant.type = IS_STRING;
- opline.op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[opline_ptr->op1.u.var].name);
- opline.op1.u.constant.value.str.len = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
+ if (UG(unicode)) {
+ opline.op1.u.constant.type = IS_UNICODE;
+ Z_USTRVAL(opline.op1.u.constant) = eustrndup((UChar*)CG(active_op_array)->vars[opline_ptr->op1.u.var].name, CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len);
+ Z_USTRLEN(opline.op1.u.constant) = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
+ } else {
+ opline.op1.u.constant.type = IS_STRING;
+ Z_STRVAL(opline.op1.u.constant) = estrndup(CG(active_op_array)->vars[opline_ptr->op1.u.var].name, CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len);
+ Z_STRLEN(opline.op1.u.constant) = CG(active_op_array)->vars[opline_ptr->op1.u.var].name_len;
+ }
SET_UNUSED(opline.op2);
opline.op2 = *class_znode;
opline.op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER;
@@ -482,12 +491,13 @@ void zend_do_print(znode *result, znode *arg TSRMLS_DC)
}
-void zend_do_echo(znode *arg TSRMLS_DC)
+void zend_do_echo(znode *arg, zend_bool inline_html TSRMLS_DC)
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_ECHO;
opline->op1 = *arg;
+ opline->extended_value = inline_html;
SET_UNUSED(opline->op2);
}
@@ -514,11 +524,11 @@ void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body
SET_UNUSED(opline->op2);
} else {
/* we had code in the function body */
- zend_error(E_COMPILE_ERROR, "%s function %s::%s() cannot contain body", method_type, CG(active_class_entry)->name, function_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "%s function %v::%R() cannot contain body", method_type, CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant));
}
} else {
if (body->u.constant.value.lval == ZEND_ACC_ABSTRACT) {
- zend_error(E_COMPILE_ERROR, "Non-abstract method %s::%s() must contain body", CG(active_class_entry)->name, function_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Non-abstract method %v::%R() must contain body", CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant));
}
}
}
@@ -526,9 +536,10 @@ void zend_do_abstract_method(znode *function_name, znode *modifiers, znode *body
static zend_bool opline_is_fetch_this(zend_op *opline TSRMLS_DC)
{
if ((opline->opcode == ZEND_FETCH_W) && (opline->op1.op_type == IS_CONST)
- && (opline->op1.u.constant.type == IS_STRING)
- && (opline->op1.u.constant.value.str.len == (sizeof("this")-1))
- && !memcmp(opline->op1.u.constant.value.str.val, "this", sizeof("this"))) {
+ && (opline->op1.u.constant.type == IS_STRING ||
+ opline->op1.u.constant.type == IS_UNICODE)
+ && (Z_UNILEN(opline->op1.u.constant) == (sizeof("this")-1))
+ && ZEND_U_EQUAL(Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), "this", sizeof("this")-1)) {
return 1;
} else {
return 0;
@@ -909,6 +920,7 @@ void zend_do_init_string(znode *result TSRMLS_DC)
opline->opcode = ZEND_INIT_STRING;
opline->result.op_type = IS_TMP_VAR;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
+ opline->extended_value = CG(literal_type);
*result = opline->result;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
@@ -923,6 +935,8 @@ void zend_do_add_char(znode *result, znode *op1, znode *op2 TSRMLS_DC)
opline->op1 = *op1;
opline->op2 = *op2;
opline->op2.op_type = IS_CONST;
+ opline->extended_value = CG(literal_type);
+ opline->extended_value = CG(literal_type);
opline->result = opline->op1;
*result = opline->result;
}
@@ -973,6 +987,7 @@ void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC)
opline->result = *result;
opline->op1 = *result;
opline->op2 = *op2;
+ opline->extended_value = CG(literal_type);
*result = opline->result;
}
@@ -1036,16 +1051,17 @@ int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier)
void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC)
{
zend_op_array op_array;
- char *name = function_name->u.constant.value.str.val;
- int name_len = function_name->u.constant.value.str.len;
+ char *name = Z_UNIVAL(function_name->u.constant);
+ int name_len = Z_UNILEN(function_name->u.constant);
int function_begin_line = function_token->u.opline_num;
zend_uint fn_flags;
+ unsigned int lcname_len;
char *lcname;
if (is_method) {
if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
if ((fn_flags_znode->u.constant.value.lval & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
- zend_error(E_COMPILE_ERROR, "Access type for interface method %s::%s() must be omitted", CG(active_class_entry)->name, function_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Access type for interface method %v::%R() must be omitted", CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant));
}
fn_flags_znode->u.constant.value.lval |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
}
@@ -1055,7 +1071,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
}
function_token->u.op_array = CG(active_op_array);
- lcname = zend_str_tolower_dup(name, name_len);
+ lcname = zend_u_str_case_fold(Z_TYPE(function_name->u.constant), name, name_len, 0, &lcname_len);
init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
@@ -1071,18 +1087,18 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
if (is_method) {
char *short_class_name = CG(active_class_entry)->name;
- int short_class_name_length = CG(active_class_entry)->name_length;
+ unsigned int short_class_name_length = CG(active_class_entry)->name_length;
- if (zend_hash_add(&CG(active_class_entry)->function_table, lcname, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
+ if (zend_u_hash_add(&CG(active_class_entry)->function_table, Z_TYPE(function_name->u.constant), lcname, lcname_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
zend_op_array *child_op_array, *parent_op_array;
if (CG(active_class_entry)->parent
- && (zend_hash_find(&CG(active_class_entry)->function_table, name, name_len+1, (void **) &child_op_array) == SUCCESS)
- && (zend_hash_find(&CG(active_class_entry)->parent->function_table, name, name_len+1, (void **) &parent_op_array) == SUCCESS)
+ && (zend_u_hash_find(&CG(active_class_entry)->function_table, Z_TYPE(function_name->u.constant), name, name_len+1, (void **) &child_op_array) == SUCCESS)
+ && (zend_u_hash_find(&CG(active_class_entry)->parent->function_table, Z_TYPE(function_name->u.constant), name, name_len+1, (void **) &parent_op_array) == SUCCESS)
&& (child_op_array == parent_op_array)) {
- zend_hash_update(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
+ zend_u_hash_update(&CG(active_class_entry)->function_table, Z_TYPE(function_name->u.constant), name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
} else {
efree(lcname);
- zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare %v::%R()", CG(active_class_entry)->name, Z_TYPE(function_name->u.constant), name);
}
}
@@ -1095,39 +1111,38 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
}
if (!(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
- short_class_name = do_alloca(short_class_name_length + 1);
- zend_str_tolower_copy(short_class_name, CG(active_class_entry)->name, short_class_name_length);
+ short_class_name = zend_u_str_case_fold(UG(unicode)?IS_UNICODE:IS_STRING, CG(active_class_entry)->name, short_class_name_length, 0, &short_class_name_length);
/* Improve after RC: cache the lowercase class name */
- if ((short_class_name_length == name_len) && (!memcmp(short_class_name, lcname, name_len))) {
+ if ((short_class_name_length == name_len) && (!memcmp(short_class_name, lcname, UG(unicode)?UBYTES(lcname_len):lcname_len))) {
if (CG(active_class_entry)->constructor) {
- zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
+ zend_error(E_STRICT, "Redefining already defined constructor for class %v", CG(active_class_entry)->name);
} else {
CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
}
- } else if ((name_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1))) {
if (CG(active_class_entry)->constructor) {
- zend_error(E_STRICT, "Redefining already defined constructor for class %s", CG(active_class_entry)->name);
+ zend_error(E_STRICT, "Redefining already defined constructor for class %v", CG(active_class_entry)->name);
}
CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_DESTRUCTOR_FUNC_NAME, sizeof(ZEND_DESTRUCTOR_FUNC_NAME)-1))) {
CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1))) {
CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)))) {
+ } else if ((lcname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
} else if (!(fn_flags & ZEND_ACC_STATIC)) {
CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
}
- free_alloca(short_class_name);
+ efree(short_class_name);
}
efree(lcname);
@@ -1136,14 +1151,14 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
opline->opcode = ZEND_DECLARE_FUNCTION;
opline->op1.op_type = IS_CONST;
- build_runtime_defined_function_key(&opline->op1.u.constant, lcname, name_len TSRMLS_CC);
+ build_runtime_defined_function_key(&opline->op1.u.constant, Z_TYPE(function_name->u.constant), lcname, lcname_len TSRMLS_CC);
opline->op2.op_type = IS_CONST;
- opline->op2.u.constant.type = IS_STRING;
+ opline->op2.u.constant.type = Z_TYPE(function_name->u.constant);
opline->op2.u.constant.value.str.val = lcname;
- opline->op2.u.constant.value.str.len = name_len;
+ opline->op2.u.constant.value.str.len = lcname_len;
opline->op2.u.constant.refcount = 1;
opline->extended_value = ZEND_DECLARE_FUNCTION;
- zend_hash_update(CG(function_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
+ zend_u_hash_update(CG(function_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
}
if (CG(extended_info)) {
@@ -1196,7 +1211,9 @@ void zend_do_handle_exception(TSRMLS_D)
void zend_do_end_function_declaration(znode *function_token TSRMLS_DC)
{
- char lcname[16];
+ unsigned int lcname_len;
+ char *lcname;
+ char lcname_buf[16];
int name_len;
zend_do_extended_info(TSRMLS_C);
@@ -1208,14 +1225,29 @@ void zend_do_end_function_declaration(znode *function_token TSRMLS_DC)
if (CG(active_class_entry)) {
zend_check_magic_method_implementation(CG(active_class_entry), (zend_function*)CG(active_op_array), E_COMPILE_ERROR TSRMLS_CC);
} else {
+ zend_uchar utype;
+
/* we don't care if the function name is longer, in fact lowercasing only
* the beginning of the name speeds up the check process */
- name_len = strlen(CG(active_op_array)->function_name);
- zend_str_tolower_copy(lcname, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname)-1));
- lcname[sizeof(lcname)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
- if (name_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)) && CG(active_op_array)->num_args != 1) {
+ if (UG(unicode)) {
+ utype = IS_UNICODE;
+ name_len = u_strlen((UChar*)CG(active_op_array)->function_name);
+ lcname = zend_u_str_case_fold(utype, CG(active_op_array)->function_name, name_len, 0, &lcname_len);
+ } else {
+ utype = IS_STRING;
+ lcname_len = name_len = strlen(CG(active_op_array)->function_name);
+ zend_str_tolower_copy(lcname_buf, CG(active_op_array)->function_name, MIN(name_len, sizeof(lcname_buf)-1));
+ lcname_buf[sizeof(lcname_buf)-1] = '\0'; /* zend_str_tolower_copy won't necessarily set the zero byte */
+ lcname = lcname_buf;
+ }
+ if (lcname_len == sizeof(ZEND_AUTOLOAD_FUNC_NAME) - 1 &&
+ ZEND_U_EQUAL(utype, lcname, lcname_len, ZEND_AUTOLOAD_FUNC_NAME, sizeof(ZEND_AUTOLOAD_FUNC_NAME)-1) &&
+ CG(active_op_array)->num_args != 1) {
zend_error(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
}
+ if (lcname != lcname_buf) {
+ efree(lcname);
+ }
}
CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
@@ -1245,16 +1277,20 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
}
CG(active_op_array)->arg_info = erealloc(CG(active_op_array)->arg_info, sizeof(zend_arg_info)*(CG(active_op_array)->num_args));
cur_arg_info = &CG(active_op_array)->arg_info[CG(active_op_array)->num_args-1];
- cur_arg_info->name = estrndup(varname->u.constant.value.str.val, varname->u.constant.value.str.len);
- cur_arg_info->name_len = varname->u.constant.value.str.len;
+ if (Z_TYPE(varname->u.constant) == IS_UNICODE) {
+ cur_arg_info->name = (char*)eustrndup(Z_USTRVAL(varname->u.constant), Z_USTRLEN(varname->u.constant));
+ } else {
+ cur_arg_info->name = estrndup(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant));
+ }
+ cur_arg_info->name_len = Z_UNILEN(varname->u.constant);
cur_arg_info->array_type_hint = 0;
cur_arg_info->allow_null = 1;
cur_arg_info->pass_by_reference = pass_by_reference;
if (class_type->op_type != IS_UNUSED) {
- if (class_type->u.constant.type == IS_STRING) {
- cur_arg_info->class_name = class_type->u.constant.value.str.val;
- cur_arg_info->class_name_len = class_type->u.constant.value.str.len;
+ if (class_type->u.constant.type == IS_STRING || class_type->u.constant.type == IS_UNICODE) {
+ cur_arg_info->class_name = Z_UNIVAL(class_type->u.constant);
+ cur_arg_info->class_name_len = Z_UNILEN(class_type->u.constant);
} else {
cur_arg_info->array_type_hint = 1;
cur_arg_info->class_name = NULL;
@@ -1272,16 +1308,22 @@ void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initia
int zend_do_begin_function_call(znode *function_name TSRMLS_DC)
{
zend_function *function;
+ unsigned int lcname_len;
char *lcname;
- lcname = zend_str_tolower_dup(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len);
- if (zend_hash_find(CG(function_table), lcname, function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) {
+ lcname = zend_u_str_case_fold(Z_TYPE(function_name->u.constant), Z_UNIVAL(function_name->u.constant), Z_UNILEN(function_name->u.constant), 0, &lcname_len);
+ if (zend_u_hash_find(CG(function_table), Z_TYPE(function_name->u.constant), lcname, lcname_len+1, (void **) &function)==FAILURE) {
zend_do_begin_dynamic_function_call(function_name TSRMLS_CC);
efree(lcname);
return 1; /* Dynamic */
}
- efree(function_name->u.constant.value.str.val);
- function_name->u.constant.value.str.val = lcname;
+ efree(Z_UNIVAL(function_name->u.constant));
+ if (Z_TYPE(function_name->u.constant) == IS_UNICODE) {
+ Z_USTRVAL(function_name->u.constant) = (UChar *)lcname;
+ Z_USTRLEN(function_name->u.constant) = lcname_len;
+ } else {
+ Z_STRVAL(function_name->u.constant) = lcname;
+ }
switch (function->type) {
case ZEND_USER_FUNCTION: {
@@ -1381,7 +1423,7 @@ void zend_do_fetch_class(znode *result, znode *class_name TSRMLS_DC)
if (class_name->op_type == IS_CONST) {
int fetch_type;
- fetch_type = zend_get_class_fetch_type(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
+ fetch_type = zend_get_class_fetch_type(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant));
switch (fetch_type) {
case ZEND_FETCH_CLASS_SELF:
case ZEND_FETCH_CLASS_PARENT:
@@ -1413,11 +1455,19 @@ void zend_do_fetch_class_name(znode *result, znode *class_name_entry, znode *cla
*result = *class_name_entry;
}
- length = sizeof("::")-1 + result->u.constant.value.str.len + class_name->u.constant.value.str.len;
- result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1);
- memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], "::", sizeof("::")-1);
- memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len + sizeof("::")-1], class_name->u.constant.value.str.val, class_name->u.constant.value.str.len+1);
- STR_FREE(class_name->u.constant.value.str.val);
+ length = sizeof("::")-1 + Z_USTRLEN(result->u.constant) + Z_USTRLEN(class_name->u.constant);
+ if (Z_TYPE(result->u.constant) == IS_UNICODE) {
+ Z_USTRVAL(result->u.constant) = erealloc(Z_USTRVAL(result->u.constant), UBYTES(length+1));
+ Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant)] = ':';
+ Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant)+1] = ':';
+ memcpy(&Z_USTRVAL(result->u.constant)[Z_USTRLEN(result->u.constant) + sizeof("::")-1], class_name->u.constant.value.str.val, UBYTES(Z_USTRLEN(class_name->u.constant)+1));
+ STR_FREE(Z_USTRVAL(class_name->u.constant));
+ } else {
+ result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1);
+ memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], "::", sizeof("::")-1);
+ memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len + sizeof("::")-1], class_name->u.constant.value.str.val, class_name->u.constant.value.str.len+1);
+ STR_FREE(class_name->u.constant.value.str.val);
+ }
result->u.constant.value.str.len = length;
}
@@ -1431,12 +1481,22 @@ void zend_do_begin_class_member_function_call(znode *class_name, znode *method_n
opline->op2 = *method_name;
if (opline->op2.op_type == IS_CONST) {
- if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_STRLEN(opline->op2.u.constant) &&
- memcmp(Z_STRVAL(opline->op2.u.constant), ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == 0) {
+ if ((sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) == Z_UNILEN(opline->op2.u.constant) &&
+ ZEND_U_EQUAL(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1)) {
zval_dtor(&opline->op2.u.constant);
SET_UNUSED(opline->op2);
} else {
- zend_str_tolower(opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len);
+ if (Z_TYPE(opline->op2.u.constant) == IS_UNICODE) {
+ unsigned int lcname_len;
+ UChar *lcname;
+
+ lcname = zend_u_str_case_fold(Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant), 0, &lcname_len);
+ efree(Z_USTRVAL(opline->op2.u.constant));
+ Z_USTRVAL(opline->op2.u.constant) = lcname;
+ Z_USTRLEN(opline->op2.u.constant) = lcname_len;
+ } else {
+ zend_str_tolower(Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant));
+ }
}
}
@@ -1731,7 +1791,7 @@ void zend_do_throw(znode *expr TSRMLS_DC)
SET_UNUSED(opline->op2);
}
-ZEND_API void function_add_ref(zend_function *function)
+ZEND_API void function_add_ref(zend_function *function TSRMLS_DC)
{
if (function->type == ZEND_USER_FUNCTION) {
zend_op_array *op_array = &function->op_array;
@@ -1742,13 +1802,13 @@ ZEND_API void function_add_ref(zend_function *function)
zval *tmp_zval;
ALLOC_HASHTABLE(op_array->static_variables);
- zend_hash_init(op_array->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(op_array->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
zend_hash_copy(op_array->static_variables, static_variables, (copy_ctor_func_t) zval_add_ref, (void *) &tmp_zval, sizeof(zval *));
}
}
}
-static void do_inherit_parent_constructor(zend_class_entry *ce)
+static void do_inherit_parent_constructor(zend_class_entry *ce TSRMLS_DC)
{
zend_function *function;
@@ -1800,20 +1860,22 @@ static void do_inherit_parent_constructor(zend_class_entry *ce)
if (zend_hash_find(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), (void **)&function)==SUCCESS) {
/* inherit parent's constructor */
zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), NULL);
- function_add_ref(function);
+ function_add_ref(function TSRMLS_CC);
} else {
/* Don't inherit the old style constructor if we already have the new style constructor */
+ unsigned int lc_class_name_len, lc_parent_class_name_len;
char *lc_class_name;
char *lc_parent_class_name;
+ zend_uchar utype = UG(unicode)?IS_UNICODE:IS_STRING;
- lc_class_name = zend_str_tolower_dup(ce->name, ce->name_length);
- if (!zend_hash_exists(&ce->function_table, lc_class_name, ce->name_length+1)) {
- lc_parent_class_name = zend_str_tolower_dup(ce->parent->name, ce->parent->name_length);
- if (zend_hash_find(&ce->parent->function_table, lc_parent_class_name, ce->parent->name_length+1, (void **)&function)==SUCCESS) {
+ lc_class_name = zend_u_str_case_fold(utype, ce->name, ce->name_length, 0, &lc_class_name_len);
+ if (!zend_u_hash_exists(&ce->function_table, utype, lc_class_name, lc_class_name_len+1)) {
+ lc_parent_class_name = zend_u_str_case_fold(utype, ce->parent->name, ce->parent->name_length, 0, &lc_parent_class_name_len);
+ if (zend_u_hash_find(&ce->parent->function_table, utype, lc_parent_class_name, lc_parent_class_name_len+1, (void **)&function)==SUCCESS) {
if (function->common.fn_flags & ZEND_ACC_CTOR) {
/* inherit parent's constructor */
- zend_hash_update(&ce->function_table, lc_class_name, ce->name_length+1, function, sizeof(zend_function), NULL);
- function_add_ref(function);
+ zend_u_hash_update(&ce->function_table, utype, lc_class_name, lc_class_name_len+1, function, sizeof(zend_function), NULL);
+ function_add_ref(function TSRMLS_CC);
}
}
efree(lc_parent_class_name);
@@ -1845,7 +1907,8 @@ static void do_inherit_method(zend_function *function)
* as that of the parent class. That allows us to know in which context
* we're running, and handle private method calls properly.
*/
- function_add_ref(function);
+ TSRMLS_FETCH();
+ function_add_ref(function TSRMLS_CC);
}
@@ -1914,7 +1977,7 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
zend_function *child;
TSRMLS_FETCH();
- if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
+ if (zend_u_hash_quick_find(child_function_table, hash_key->type, hash_key->u.string, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) {
if (parent_flags & (ZEND_ACC_ABSTRACT)) {
child_ce->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
}
@@ -1924,14 +1987,14 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
if (parent->common.fn_flags & ZEND_ACC_ABSTRACT
&& parent->common.scope != (child->common.prototype ? child->common.prototype->common.scope : child->common.scope)
&& child->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_IMPLEMENTED_ABSTRACT)) {
- zend_error(E_COMPILE_ERROR, "Can't inherit abstract function %s::%s() (previously declared abstract in %s)",
+ zend_error(E_COMPILE_ERROR, "Can't inherit abstract function %v::%v() (previously declared abstract in %v)",
parent->common.scope->name,
child->common.function_name,
child->common.prototype ? child->common.prototype->common.scope->name : child->common.scope->name);
}
if (parent_flags & ZEND_ACC_FINAL) {
- zend_error(E_COMPILE_ERROR, "Cannot override final method %s::%s()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name);
+ zend_error(E_COMPILE_ERROR, "Cannot override final method %v::%v()", ZEND_FN_SCOPE_NAME(parent), child->common.function_name);
}
child_flags = child->common.fn_flags;
@@ -1939,15 +2002,15 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
*/
if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) {
if (child->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error(E_COMPILE_ERROR, "Cannot make non static method %s::%s() static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
+ zend_error(E_COMPILE_ERROR, "Cannot make non static method %v::%v() static in class %v", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
} else {
- zend_error(E_COMPILE_ERROR, "Cannot make static method %s::%s() non static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
+ zend_error(E_COMPILE_ERROR, "Cannot make static method %v::%v() non static in class %v", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
}
}
/* Disallow making an inherited method abstract. */
if ((child_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_ABSTRACT)) {
- zend_error(E_COMPILE_ERROR, "Cannot make non abstract method %s::%s() abstract in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
+ zend_error(E_COMPILE_ERROR, "Cannot make non abstract method %v::%v() abstract in class %v", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child));
}
if (parent_flags & ZEND_ACC_CHANGED) {
@@ -1956,7 +2019,7 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
/* Prevent derived classes from restricting access that was available in parent classes
*/
if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) {
- zend_error(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
+ zend_error(E_COMPILE_ERROR, "Access level to %v::%v() must be %s (as in class %v)%s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
} else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK))
&& ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) {
child->common.fn_flags |= ZEND_ACC_CHANGED;
@@ -1973,11 +2036,11 @@ static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_f
if (child->common.prototype) {
if (!zend_do_perform_implementation_check(child, child->common.prototype)) {
- zend_error(E_COMPILE_ERROR, "Declaration of %s::%s() must be compatible with that of %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(child->common.prototype), child->common.prototype->common.function_name);
+ zend_error(E_COMPILE_ERROR, "Declaration of %v::%v() must be compatible with that of %v::%v()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(child->common.prototype), child->common.prototype->common.function_name);
}
} else if (EG(error_reporting) & E_STRICT) { /* Check E_STRICT before the check so that we save some time */
if (!zend_do_perform_implementation_check(child, parent)) {
- zend_error(E_STRICT, "Declaration of %s::%s() should be compatible with that of %s::%s()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(parent), parent->common.function_name);
+ zend_error(E_STRICT, "Declaration of %v::%v() should be compatible with that of %v::%v()", ZEND_FN_SCOPE_NAME(child), child->common.function_name, ZEND_FN_SCOPE_NAME(parent), parent->common.function_name);
}
}
@@ -1989,12 +2052,15 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
{
zend_property_info *child_info;
zend_class_entry *parent_ce = ce->parent;
-
+ zend_uchar utype;
+ TSRMLS_FETCH();
+
+ utype = UG(unicode)?IS_UNICODE:IS_STRING;
if (parent_info->flags & (ZEND_ACC_PRIVATE|ZEND_ACC_SHADOW)) {
- if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
+ if (zend_u_hash_quick_find(&ce->properties_info, hash_key->type, hash_key->u.string, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
child_info->flags |= ZEND_ACC_CHANGED;
} else {
- zend_hash_quick_update(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, parent_info, sizeof(zend_property_info), (void **) &child_info);
+ zend_u_hash_quick_update(&ce->properties_info, hash_key->type, hash_key->u.string, hash_key->nKeyLength, hash_key->h, parent_info, sizeof(zend_property_info), (void **) &child_info);
if(ce->type & ZEND_INTERNAL_CLASS) {
zend_duplicate_property_info_internal(child_info);
} else {
@@ -2006,12 +2072,11 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
return 0; /* don't copy access information to child */
}
- if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
+ if (zend_u_hash_quick_find(&ce->properties_info, hash_key->type, hash_key->u.string, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) {
if ((parent_info->flags & ZEND_ACC_STATIC) != (child_info->flags & ZEND_ACC_STATIC)) {
- zend_error(E_COMPILE_ERROR, "Cannot redeclare %s%s::$%s as %s%s::$%s",
- (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->arKey,
- (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->arKey);
-
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare %s%v::$%R as %s%v::$%R",
+ (parent_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", parent_ce->name, hash_key->type, hash_key->u.string,
+ (child_info->flags & ZEND_ACC_STATIC) ? "static " : "non static ", ce->name, hash_key->type, hash_key->u.string);
}
if(parent_info->flags & ZEND_ACC_CHANGED) {
@@ -2019,16 +2084,16 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
}
if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) {
- zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
+ zend_error(E_COMPILE_ERROR, "Access level to %v::$%R must be %s (as in class %v)%s", ce->name, hash_key->type, hash_key->u.string, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker");
} else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) {
if (!(parent_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
/* Explicitly copy the default value from the parent (if it has one) */
zval **pvalue;
- if (zend_hash_quick_find(&parent_ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, (void **) &pvalue) == SUCCESS) {
+ if (zend_u_hash_quick_find(&parent_ce->default_properties, utype, parent_info->name, parent_info->name_length+1, parent_info->h, (void **) &pvalue) == SUCCESS) {
(*pvalue)->refcount++;
- zend_hash_del(&ce->default_properties, child_info->name, child_info->name_length+1);
- zend_hash_quick_update(&ce->default_properties, parent_info->name, parent_info->name_length+1, parent_info->h, pvalue, sizeof(zval *), NULL);
+ zend_u_hash_del(&ce->default_properties, utype, child_info->name, child_info->name_length+1);
+ zend_u_hash_quick_update(&ce->default_properties, utype, parent_info->name, parent_info->name_length+1, parent_info->h, pvalue, sizeof(zval *), NULL);
}
}
return 1; /* Inherit from the parent */
@@ -2036,26 +2101,26 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
char *prot_name;
int prot_name_length;
- zend_mangle_property_name(&prot_name, &prot_name_length, "*", 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS);
+ zend_u_mangle_property_name(&prot_name, &prot_name_length, utype, "*", 1, child_info->name, child_info->name_length, ce->type & ZEND_INTERNAL_CLASS);
if (child_info->flags & ZEND_ACC_STATIC) {
zval **prop;
- if (zend_hash_find(parent_ce->static_members, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
+ if (zend_u_hash_find(parent_ce->static_members, utype, prot_name, prot_name_length+1, (void**)&prop) == SUCCESS) {
zval **new_prop;
- if (zend_hash_find(ce->static_members, child_info->name, child_info->name_length+1, (void**)&new_prop) == SUCCESS) {
+ if (zend_u_hash_find(ce->static_members, utype, child_info->name, child_info->name_length+1, (void**)&new_prop) == SUCCESS) {
if (Z_TYPE_PP(new_prop) != IS_NULL && Z_TYPE_PP(prop) != IS_NULL) {
char *prop_name, *tmp;
- zend_unmangle_property_name(child_info->name, &tmp, &prop_name);
-
- zend_error(E_COMPILE_ERROR, "Cannot change initial value of property static protected %s::$%s in class %s",
+
+ zend_u_unmangle_property_name(utype, child_info->name, &tmp, &prop_name);
+ zend_error(E_COMPILE_ERROR, "Cannot change initial value of property static protected %v::$%v in class %v",
parent_ce->name, prop_name, ce->name);
}
}
(*prop)->refcount++;
- zend_hash_update(ce->static_members, child_info->name, child_info->name_length+1, (void**)prop, sizeof(zval*), NULL);
- zend_hash_del(ce->static_members, prot_name, prot_name_length+1);
+ zend_u_hash_update(ce->static_members, utype, child_info->name, child_info->name_length+1, (void**)prop, sizeof(zval*), NULL);
+ zend_u_hash_del(ce->static_members, utype, prot_name, prot_name_length+1);
}
} else {
- zend_hash_del(&ce->default_properties, prot_name, prot_name_length+1);
+ zend_u_hash_del(&ce->default_properties, utype, prot_name, prot_name_length+1);
}
pefree(prot_name, ce->type & ZEND_INTERNAL_CLASS);
}
@@ -2070,10 +2135,10 @@ static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_pro
static inline void do_implement_interface(zend_class_entry *ce, zend_class_entry *iface TSRMLS_DC)
{
if (!(ce->ce_flags & ZEND_ACC_INTERFACE) && iface->interface_gets_implemented && iface->interface_gets_implemented(iface, ce TSRMLS_CC) == FAILURE) {
- zend_error(E_CORE_ERROR, "Class %s could not implement interface %s", ce->name, iface->name);
+ zend_error(E_CORE_ERROR, "Class %v could not implement interface %v", ce->name, iface->name);
}
if (ce == iface) {
- zend_error(E_ERROR, "Interface %s cannot not implement itself", ce->name);
+ zend_error(E_ERROR, "Interface %v cannot not implement itself", ce->name);
}
}
@@ -2126,10 +2191,10 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
{
if ((ce->ce_flags & ZEND_ACC_INTERFACE)
&& !(parent_ce->ce_flags & ZEND_ACC_INTERFACE)) {
- zend_error(E_COMPILE_ERROR, "Interface %s may not inherit from class (%s)", ce->name, parent_ce->name);
+ zend_error(E_COMPILE_ERROR, "Interface %v may not inherit from class (%v)", ce->name, parent_ce->name);
}
if (parent_ce->ce_flags & ZEND_ACC_FINAL_CLASS) {
- zend_error(E_COMPILE_ERROR, "Class %s may not inherit from final class (%s)", ce->name, parent_ce->name);
+ zend_error(E_COMPILE_ERROR, "Class %v may not inherit from final class (%v)", ce->name, parent_ce->name);
}
ce->parent = parent_ce;
@@ -2155,8 +2220,8 @@ ZEND_API void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent
static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zval *parent_constant, zend_hash_key *hash_key, zend_class_entry *iface)
{
- if (zend_hash_quick_exists(child_constants_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h)) {
- zend_error(E_COMPILE_ERROR, "Cannot inherit previously-inherited constant %s from interface %s", hash_key->arKey, iface->name);
+ if (zend_u_hash_quick_exists(child_constants_table, hash_key->type, hash_key->u.string, hash_key->nKeyLength, hash_key->h)) {
+ zend_error(E_COMPILE_ERROR, "Cannot inherit previously-inherited constant %R from interface %v", hash_key->type, hash_key->u.string, iface->name);
return 0;
}
return 1;
@@ -2181,20 +2246,20 @@ ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, zend_b
zend_error(E_COMPILE_ERROR, "Internal compiler error. Please report!");
}
- zend_hash_find(function_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void *) &function);
- if (zend_hash_add(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, function, sizeof(zend_function), NULL)==FAILURE) {
+ zend_u_hash_find(function_table, Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (void *) &function);
+ if (zend_u_hash_add(function_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, function, sizeof(zend_function), NULL)==FAILURE) {
int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR;
zend_function *function;
- if (zend_hash_find(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void *) &function)==SUCCESS
+ if (zend_u_hash_find(function_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, (void *) &function)==SUCCESS
&& function->type==ZEND_USER_FUNCTION
&& ((zend_op_array *) function)->last>0) {
- zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)",
- opline->op2.u.constant.value.str.val,
+ zend_error(error_level, "Cannot redeclare %R() (previously declared in %s:%d)",
+ Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant),
((zend_op_array *) function)->filename,
((zend_op_array *) function)->opcodes[0].lineno);
} else {
- zend_error(error_level, "Cannot redeclare %s()", opline->op2.u.constant.value.str.val);
+ zend_error(error_level, "Cannot redeclare %R()", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
}
return FAILURE;
} else {
@@ -2209,14 +2274,14 @@ ZEND_API zend_class_entry *do_bind_class(zend_op *opline, HashTable *class_table
{
zend_class_entry *ce, **pce;
- if (zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce)==FAILURE) {
- zend_error(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %s", opline->op1.u.constant.value.str.val);
+ if (zend_u_hash_find(class_table, Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (void **) &pce)==FAILURE) {
+ zend_error(E_COMPILE_ERROR, "Internal Zend error - Missing class information for %R", Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant));
return NULL;
} else {
ce = *pce;
}
ce->refcount++;
- if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
+ if (zend_u_hash_add(class_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) {
ce->refcount--;
if (!compile_time) {
/* If we're in compile time, in practice, it's quite possible
@@ -2224,7 +2289,7 @@ ZEND_API zend_class_entry *do_bind_class(zend_op *opline, HashTable *class_table
* so we shut up about it. This allows the if (!defined('FOO')) { return; }
* approach to work.
*/
- zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare class %R", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
}
return NULL;
} else {
@@ -2241,7 +2306,7 @@ ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *c
zend_class_entry *ce, **pce;
int found_ce;
- found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce);
+ found_ce = zend_u_hash_find(class_table, Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), (void **) &pce);
if (found_ce == FAILURE) {
if (!compile_time) {
@@ -2250,7 +2315,7 @@ ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *c
* so we shut up about it. This allows the if (!defined('FOO')) { return; }
* approach to work.
*/
- zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare class %R", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
}
return NULL;
} else {
@@ -2258,7 +2323,7 @@ ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *c
}
if (parent_ce->ce_flags & ZEND_ACC_INTERFACE) {
- zend_error(E_COMPILE_ERROR, "Class %s cannot extend from interface %s", ce->name, parent_ce->name);
+ zend_error(E_COMPILE_ERROR, "Class %v cannot extend from interface %v", ce->name, parent_ce->name);
}
zend_do_inheritance(ce, parent_ce TSRMLS_CC);
@@ -2266,8 +2331,8 @@ ZEND_API zend_class_entry *do_bind_inherited_class(zend_op *opline, HashTable *c
ce->refcount++;
/* Register the derived class */
- if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
- zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val);
+ if (zend_u_hash_add(class_table, Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant), Z_UNILEN(opline->op2.u.constant)+1, pce, sizeof(zend_class_entry *), NULL)==FAILURE) {
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare class %R", Z_TYPE(opline->op2.u.constant), Z_UNIVAL(opline->op2.u.constant));
ce->refcount--;
zend_hash_destroy(&ce->function_table);
zend_hash_destroy(&ce->default_properties);
@@ -2315,7 +2380,7 @@ void zend_do_early_binding(TSRMLS_D)
zval *parent_name = &(opline-1)->op2.u.constant;
zend_class_entry **pce;
- if (zend_lookup_class(Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) {
+ if (zend_u_lookup_class(Z_TYPE_P(parent_name), Z_STRVAL_P(parent_name), Z_STRLEN_P(parent_name), &pce TSRMLS_CC) == FAILURE) {
return;
}
if (do_bind_inherited_class(opline, CG(class_table), *pce, 1 TSRMLS_CC) == NULL) {
@@ -2357,7 +2422,7 @@ void zend_do_early_binding(TSRMLS_D)
return;
}
- zend_hash_del(table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len);
+ zend_u_hash_del(table, Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant));
zval_dtor(&opline->op1.u.constant);
zval_dtor(&opline->op2.u.constant);
opline->opcode = ZEND_NOP;
@@ -2624,21 +2689,25 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
zend_op *opline;
int doing_inheritance = 0;
zend_class_entry *new_class_entry = emalloc(sizeof(zend_class_entry));
- char *lcname = zend_str_tolower_dup(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len);
+ unsigned int lcname_len;
+ char *lcname = zend_u_str_case_fold(Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant), Z_UNILEN(class_name->u.constant), 0, &lcname_len);
if (CG(active_class_entry)) {
zend_error(E_COMPILE_ERROR, "Class declarations may not be nested");
return;
}
- if (!(strcmp(lcname, "self") && strcmp(lcname, "parent"))) {
+ if ((lcname_len == sizeof("self")-1 &&
+ ZEND_U_EQUAL(Z_TYPE(class_name->u.constant), lcname, lcname_len, "self", sizeof("self")-1)) ||
+ (lcname_len == sizeof("parent")-1 &&
+ ZEND_U_EQUAL(Z_TYPE(class_name->u.constant), lcname, lcname_len, "parent", sizeof("parent")-1))) {
efree(lcname);
- zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot use '%R' as class name as it is reserved", Z_TYPE(class_name->u.constant), Z_UNIVAL(class_name->u.constant));
}
new_class_entry->type = ZEND_USER_CLASS;
- new_class_entry->name = class_name->u.constant.value.str.val;
- new_class_entry->name_length = class_name->u.constant.value.str.len;
+ new_class_entry->name = Z_UNIVAL(class_name->u.constant);
+ new_class_entry->name_length = Z_UNILEN(class_name->u.constant);
zend_initialize_class_data(new_class_entry, 1 TSRMLS_CC);
new_class_entry->filename = zend_get_compiled_filename(TSRMLS_C);
@@ -2661,10 +2730,10 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->op1.op_type = IS_CONST;
- build_runtime_defined_function_key(&opline->op1.u.constant, lcname, new_class_entry->name_length TSRMLS_CC);
+ build_runtime_defined_function_key(&opline->op1.u.constant, Z_TYPE(class_name->u.constant), lcname, lcname_len TSRMLS_CC);
opline->op2.op_type = IS_CONST;
- opline->op2.u.constant.type = IS_STRING;
+ opline->op2.u.constant.type = Z_TYPE(class_name->u.constant);
opline->op2.u.constant.refcount = 1;
if (doing_inheritance) {
@@ -2674,10 +2743,15 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod
opline->opcode = ZEND_DECLARE_CLASS;
}
- opline->op2.u.constant.value.str.val = lcname;
- opline->op2.u.constant.value.str.len = new_class_entry->name_length;
+ if (Z_TYPE(opline->op2.u.constant) == IS_UNICODE) {
+ Z_USTRVAL(opline->op2.u.constant) = (UChar *)lcname;
+ Z_USTRLEN(opline->op2.u.constant) = lcname_len;
+ } else {
+ Z_STRVAL(opline->op2.u.constant) = lcname;
+ Z_STRLEN(opline->op2.u.constant) = lcname_len;
+ }
- zend_hash_update(CG(class_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &new_class_entry, sizeof(zend_class_entry *), NULL);
+ zend_u_hash_update(CG(class_table), Z_TYPE(opline->op1.u.constant), Z_UNIVAL(opline->op1.u.constant), Z_UNILEN(opline->op1.u.constant), &new_class_entry, sizeof(zend_class_entry *), NULL);
CG(active_class_entry) = new_class_entry;
opline->result.u.var = get_temporary_variable(CG(active_op_array));
@@ -2707,24 +2781,24 @@ void zend_do_end_class_declaration(znode *class_token, znode *parent_token TSRML
{
zend_class_entry *ce = CG(active_class_entry);
- do_inherit_parent_constructor(ce);
+ do_inherit_parent_constructor(ce TSRMLS_CC);
if (ce->constructor) {
ce->constructor->common.fn_flags |= ZEND_ACC_CTOR;
if (ce->constructor->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error(E_COMPILE_ERROR, "Constructor %s::%s() cannot be static", ce->name, ce->constructor->common.function_name);
+ zend_error(E_COMPILE_ERROR, "Constructor %v::%v() cannot be static", ce->name, ce->constructor->common.function_name);
}
}
if (ce->destructor) {
ce->destructor->common.fn_flags |= ZEND_ACC_DTOR;
if (ce->destructor->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error(E_COMPILE_ERROR, "Destructor %s::%s() cannot be static", ce->name, ce->destructor->common.function_name);
+ zend_error(E_COMPILE_ERROR, "Destructor %v::%v() cannot be static", ce->name, ce->destructor->common.function_name);
}
}
if (ce->clone) {
ce->clone->common.fn_flags |= ZEND_ACC_CLONE;
if (ce->clone->common.fn_flags & ZEND_ACC_STATIC) {
- zend_error(E_COMPILE_ERROR, "Clone method %s::%s() cannot be static", ce->name, ce->clone->common.function_name);
+ zend_error(E_COMPILE_ERROR, "Clone method %v::%v() cannot be static", ce->name, ce->clone->common.function_name);
}
}
@@ -2790,6 +2864,29 @@ ZEND_API void zend_mangle_property_name(char **dest, int *dest_length, char *src
*dest_length = prop_name_length;
}
+ZEND_API void zend_u_mangle_property_name(char **dest, int *dest_length, zend_uchar type, char *src1, int src1_length, char *src2, int src2_length, int internal)
+{
+ if (type == IS_UNICODE) {
+ UChar *prop_name;
+ int prop_name_length;
+
+ prop_name_length = 1 + src1_length + 1 + src2_length;
+ prop_name = pemalloc(UBYTES(prop_name_length + 1), internal);
+ prop_name[0] = 0;
+ if (src1_length == 1 && src1[0] == '*') {
+ prop_name[1] = '*';
+ prop_name[2] = 0;
+ } else {
+ memcpy(prop_name + 1, src1, UBYTES(src1_length+1));
+ }
+ memcpy(prop_name + 1 + src1_length + 1, src2, UBYTES(src2_length+1));
+
+ *dest = (char*)prop_name;
+ *dest_length = prop_name_length;
+ } else {
+ zend_mangle_property_name(dest, dest_length, src1, src1_length, src2, src2_length, internal);
+ }
+}
ZEND_API void zend_unmangle_property_name(char *mangled_property, char **class_name, char **prop_name)
{
@@ -2804,6 +2901,26 @@ ZEND_API void zend_unmangle_property_name(char *mangled_property, char **class_n
*prop_name = (*class_name)+strlen(*class_name)+1;
}
+ZEND_API void zend_u_unmangle_property_name(zend_uchar type, char *mangled_property, char **class_name, char **prop_name)
+{
+ if (type == IS_UNICODE) {
+ *prop_name = *class_name = NULL;
+
+ if (((UChar*)mangled_property)[0]!=0) {
+ *prop_name = mangled_property;
+ return;
+ }
+
+ *class_name = mangled_property+UBYTES(1);
+ *prop_name = (*class_name)+UBYTES(u_strlen((UChar*)*class_name)+1);
+ if ((*(UChar**)class_name)[0] == '*') {
+ *class_name = "*";
+ }
+ } else {
+ zend_unmangle_property_name(mangled_property, class_name, prop_name);
+ }
+}
+
void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_type TSRMLS_DC)
{
zval *property;
@@ -2820,13 +2937,13 @@ void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_ty
}
if (access_type & ZEND_ACC_FINAL) {
- zend_error(E_COMPILE_ERROR, "Cannot declare property %s::$%s final, the final modifier is allowed only for methods",
- CG(active_class_entry)->name, var_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot declare property %v::$%R final, the final modifier is allowed only for methods",
+ CG(active_class_entry)->name, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant));
}
- if (zend_hash_find(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &existing_property_info)==SUCCESS) {
+ if (zend_u_hash_find(&CG(active_class_entry)->properties_info, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant), Z_UNILEN(var_name->u.constant)+1, (void **) &existing_property_info)==SUCCESS) {
if (!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) {
- zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot redeclare %v::$%R", CG(active_class_entry)->name, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant));
}
}
ALLOC_ZVAL(property);
@@ -2845,7 +2962,7 @@ void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_ty
CG(doc_comment_len) = 0;
}
- zend_declare_property_ex(CG(active_class_entry), var_name->u.constant.value.str.val, var_name->u.constant.value.str.len, property, access_type, comment, comment_len TSRMLS_CC);
+ zend_u_declare_property(CG(active_class_entry), Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant), Z_UNILEN(var_name->u.constant), property, access_type TSRMLS_CC);
efree(var_name->u.constant.value.str.val);
}
@@ -2867,9 +2984,9 @@ void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC)
property->type = IS_NULL;
}
- if (zend_hash_add(&CG(active_class_entry)->constants_table, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL)==FAILURE) {
+ if (zend_u_hash_add(&CG(active_class_entry)->constants_table, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant), Z_UNILEN(var_name->u.constant)+1, &property, sizeof(zval *), NULL)==FAILURE) {
FREE_ZVAL(property);
- zend_error(E_COMPILE_ERROR, "Cannot redefine class constant %s::%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val);
+ zend_error(E_COMPILE_ERROR, "Cannot redefine class constant %v::%R", CG(active_class_entry)->name, Z_TYPE(var_name->u.constant), Z_UNIVAL(var_name->u.constant));
}
FREE_PNODE(var_name);
}
@@ -2957,11 +3074,15 @@ void zend_do_declare_implicit_property(TSRMLS_D)
if (opline_ptr->op1.op_type == IS_UNUSED
&& CG(active_class_entry)
&& opline_ptr->op2.op_type == IS_CONST
- && !zend_hash_exists(&CG(active_class_entry)->properties_info, opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len+1)) {
+ && !zend_u_hash_exists(&CG(active_class_entry)->properties_info, Z_TYPE(opline_ptr->op2.u.constant), Z_UNIVAL(opline_ptr->op2.u.constant), Z_UNILEN(opline_ptr->op2.u.constant)+1)) {
znode property;
property = opline_ptr->op2;
- property.u.constant.value.str.val = estrndup(opline_ptr->op2.u.constant.value.str.val, opline_ptr->op2.u.constant.value.str.len);
+ if (Z_TYPE(opline_ptr->op2.u.constant) == IS_UNICODE) {
+ Z_USTRVAL(property.u.constant) = eustrndup(Z_USTRVAL(opline_ptr->op2.u.constant), Z_USTRLEN(opline_ptr->op2.u.constant));
+ } else {
+ Z_STRVAL(property.u.constant) = estrndup(Z_STRVAL(opline_ptr->op2.u.constant), Z_STRLEN(opline_ptr->op2.u.constant));
+ }
zend_do_declare_property(&property, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_IMPLICIT_PUBLIC TSRMLS_CC);
}
#endif
@@ -3123,17 +3244,23 @@ void zend_do_add_array_element(znode *result, znode *expr, znode *offset, zend_b
void zend_do_add_static_array_element(znode *result, znode *offset, znode *expr)
{
zval *element;
+ TSRMLS_FETCH();
ALLOC_ZVAL(element);
*element = expr->u.constant;
if (offset) {
- switch (offset->u.constant.type) {
+ zend_uchar utype = Z_TYPE(offset->u.constant);
+
+ switch (Z_TYPE(offset->u.constant)) {
case IS_CONSTANT:
/* Ugly hack to denote that this value has a constant index */
element->type |= IS_CONSTANT_INDEX;
/* break missing intentionally */
+ utype = UG(unicode)?IS_UNICODE:IS_STRING;
case IS_STRING:
- zend_symtable_update(result->u.constant.value.ht, offset->u.constant.value.str.val, offset->u.constant.value.str.len+1, &element, sizeof(zval *), NULL);
+ case IS_BINARY:
+ case IS_UNICODE:
+ zend_u_symtable_update(result->u.constant.value.ht, utype, Z_UNIVAL(offset->u.constant), Z_UNILEN(offset->u.constant)+1, &element, sizeof(zval *), NULL);
zval_dtor(&offset->u.constant);
break;
case IS_NULL:
@@ -3278,9 +3405,9 @@ void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int
}
if (!CG(active_op_array)->static_variables) {
ALLOC_HASHTABLE(CG(active_op_array)->static_variables);
- zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0);
+ zend_u_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
}
- zend_hash_update(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1, &tmp, sizeof(zval *), NULL);
+ zend_u_hash_update(CG(active_op_array)->static_variables, Z_TYPE(varname->u.constant), Z_UNIVAL(varname->u.constant), Z_UNILEN(varname->u.constant)+1, &tmp, sizeof(zval *), NULL);
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */
@@ -3366,9 +3493,10 @@ void zend_do_indirect_references(znode *result, znode *num_references, znode *va
int i;
zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC);
+ zend_do_normalization(variable, variable TSRMLS_CC);
for (i=1; i<num_references->u.constant.value.lval; i++) {
fetch_simple_variable_ex(result, variable, 0, ZEND_FETCH_R TSRMLS_CC);
- *variable = *result;
+ zend_do_normalization(variable, result TSRMLS_CC);
}
zend_do_begin_variable_parse(TSRMLS_C);
fetch_simple_variable(result, variable, 1 TSRMLS_CC);
@@ -3385,9 +3513,15 @@ void zend_do_unset(znode *variable TSRMLS_DC)
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_UNSET_VAR;
opline->op1.op_type = IS_CONST;
- opline->op1.u.constant.type = IS_STRING;
- opline->op1.u.constant.value.str.len = CG(active_op_array)->vars[variable->u.var].name_len;
- opline->op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[variable->u.var].name);
+ if (UG(unicode)) {
+ opline->op1.u.constant.type = IS_UNICODE;
+ Z_USTRLEN(opline->op1.u.constant) = CG(active_op_array)->vars[variable->u.var].name_len;
+ Z_USTRVAL(opline->op1.u.constant) = eustrndup((UChar*)CG(active_op_array)->vars[variable->u.var].name, CG(active_op_array)->vars[variable->u.var].name_len);
+ } else {
+ opline->op1.u.constant.type = IS_STRING;
+ Z_STRLEN(opline->op1.u.constant) = CG(active_op_array)->vars[variable->u.var].name_len;
+ Z_STRVAL(opline->op1.u.constant) = estrndup(CG(active_op_array)->vars[variable->u.var].name, CG(active_op_array)->vars[variable->u.var].name_len);
+ }
SET_UNUSED(opline->op2);
opline->op2.u.EA.type = ZEND_FETCH_LOCAL;
SET_UNUSED(opline->result);
@@ -3422,9 +3556,15 @@ void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC
last_op = get_next_op(CG(active_op_array) TSRMLS_CC);
last_op->opcode = ZEND_ISSET_ISEMPTY_VAR;
last_op->op1.op_type = IS_CONST;
- last_op->op1.u.constant.type = IS_STRING;
- last_op->op1.u.constant.value.str.len = CG(active_op_array)->vars[variable->u.var].name_len;
- last_op->op1.u.constant.value.str.val = estrdup(CG(active_op_array)->vars[variable->u.var].name);
+ if (UG(unicode)) {
+ last_op->op1.u.constant.type = IS_UNICODE;
+ Z_USTRLEN(last_op->op1.u.constant) = CG(active_op_array)->vars[variable->u.var].name_len;
+ Z_USTRVAL(last_op->op1.u.constant) = eustrndup((UChar*)CG(active_op_array)->vars[variable->u.var].name, CG(active_op_array)->vars[variable->u.var].name_len);
+ } else {
+ last_op->op1.u.constant.type = IS_STRING;
+ Z_STRLEN(last_op->op1.u.constant) = CG(active_op_array)->vars[variable->u.var].name_len;
+ Z_STRVAL(last_op->op1.u.constant) = estrndup(CG(active_op_array)->vars[variable->u.var].name, CG(active_op_array)->vars[variable->u.var].name_len);
+ }
SET_UNUSED(last_op->op2);
last_op->op2.u.EA.type = ZEND_FETCH_LOCAL;
last_op->result.u.var = get_temporary_variable(CG(active_op_array));
@@ -3634,35 +3774,19 @@ void zend_do_declare_begin(TSRMLS_D)
void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC)
{
- if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "ticks", sizeof("ticks")-1)) {
+ if (ZEND_U_EQUAL(Z_TYPE(var->u.constant), Z_UNIVAL(var->u.constant), Z_UNILEN(var->u.constant), "ticks", sizeof("ticks")-1)) {
convert_to_long(&val->u.constant);
CG(declarables).ticks = val->u.constant;
-#ifdef ZEND_MULTIBYTE
- } else if (!zend_binary_strcasecmp(var->u.constant.value.str.val, var->u.constant.value.str.len, "encoding", sizeof("encoding")-1)) {
- zend_encoding *new_encoding, *old_encoding;
- zend_encoding_filter old_input_filter;
+ } else if (UG(unicode) && ZEND_U_EQUAL(Z_TYPE(var->u.constant), Z_UNIVAL(var->u.constant), Z_UNILEN(var->u.constant), "encoding", sizeof("encoding")-1)) {
if (val->u.constant.type == IS_CONSTANT) {
zend_error(E_COMPILE_ERROR, "Cannot use constants as encoding");
}
convert_to_string(&val->u.constant);
- new_encoding = zend_multibyte_fetch_encoding(val->u.constant.value.str.val);
- if (!new_encoding) {
- zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", val->u.constant.value.str.val);
- } else {
- old_input_filter = LANG_SCNG(input_filter);
- old_encoding = LANG_SCNG(script_encoding);
- zend_multibyte_set_filter(new_encoding TSRMLS_CC);
-
- /* need to re-scan if input filter changed */
- if (old_input_filter != LANG_SCNG(input_filter) ||
- ((old_input_filter == zend_multibyte_script_encoding_filter) &&
- (new_encoding != old_encoding))) {
- zend_multibyte_yyinput_again(old_input_filter, old_encoding TSRMLS_CC);
- }
+ if (zend_prepare_scanner_converters(Z_STRVAL(val->u.constant), 1 TSRMLS_CC) == FAILURE) {
+ zend_error(E_COMPILE_WARNING, "Unsupported encoding [%s]", Z_STRVAL(val->u.constant));
}
efree(val->u.constant.value.str.val);
-#endif /* ZEND_MULTIBYTE */
}
zval_dtor(&var->u.constant);
}
@@ -3689,12 +3813,21 @@ void zend_do_end_heredoc(TSRMLS_D)
return;
}
- opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0;
- if (opline->op2.u.constant.value.str.len>0) {
- if (opline->op2.u.constant.value.str.val[opline->op2.u.constant.value.str.len-1]=='\r') {
- opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0;
- }
- }
+ if (opline->op2.u.constant.type == IS_UNICODE) {
+ opline->op2.u.constant.value.ustr.val[(opline->op2.u.constant.value.ustr.len--)-1] = 0;
+ if (opline->op2.u.constant.value.ustr.len>0) {
+ if (opline->op2.u.constant.value.ustr.val[opline->op2.u.constant.value.ustr.len-1]=='\r') {
+ opline->op2.u.constant.value.ustr.val[(opline->op2.u.constant.value.ustr.len--)-1] = 0;
+ }
+ }
+ } else {
+ opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0;
+ if (opline->op2.u.constant.value.str.len>0) {
+ if (opline->op2.u.constant.value.str.val[opline->op2.u.constant.value.str.len-1]=='\r') {
+ opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0;
+ }
+ }
+ }
}
@@ -3856,11 +3989,11 @@ void zend_auto_global_dtor(zend_auto_global *auto_global)
}
-zend_bool zend_is_auto_global(char *name, uint name_len TSRMLS_DC)
+zend_bool zend_u_is_auto_global(zend_uchar type, void *name, uint name_len TSRMLS_DC)
{
zend_auto_global *auto_global;
- if (zend_hash_find(CG(auto_globals), name, name_len+1, (void **) &auto_global)==SUCCESS) {
+ if (zend_u_hash_find(CG(auto_globals), type, name, name_len+1, (void **) &auto_global)==SUCCESS) {
if (auto_global->armed) {
auto_global->armed = auto_global->auto_global_callback(auto_global->name, auto_global->name_len TSRMLS_CC);
}
@@ -3869,6 +4002,11 @@ zend_bool zend_is_auto_global(char *name, uint name_len TSRMLS_DC)
return 0;
}
+zend_bool zend_is_auto_global(char *name, uint name_len TSRMLS_DC)
+{
+ return zend_u_is_auto_global(IS_STRING, name, name_len TSRMLS_CC);
+}
+
int zend_register_auto_global(char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC)
{
@@ -3934,8 +4072,8 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
ce->doc_comment = NULL;
ce->doc_comment_len = 0;
- zend_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
- zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, 0);
+ zend_u_hash_init_ex(&ce->default_properties, 0, NULL, zval_ptr_dtor_func, persistent_hashes, UG(unicode), 0);
+ zend_u_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) (persistent_hashes ? zend_destroy_property_info_internal : zend_destroy_property_info), persistent_hashes, UG(unicode), 0);
if (persistent_hashes) {
ce->static_members = (HashTable *) malloc(sizeof(HashTable));
@@ -3943,9 +4081,9 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
ALLOC_HASHTABLE(ce->static_members);
}
- zend_hash_init_ex(ce->static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
- zend_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, 0);
- zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0);
+ zend_u_hash_init_ex(ce->static_members, 0, NULL, zval_ptr_dtor_func, persistent_hashes, UG(unicode), 0);
+ zend_u_hash_init_ex(&ce->constants_table, 0, NULL, zval_ptr_dtor_func, persistent_hashes, UG(unicode), 0);
+ zend_u_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, UG(unicode), 0);
if (nullify_handlers) {
ce->constructor = NULL;
@@ -3973,13 +4111,13 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
}
-int zend_get_class_fetch_type(char *class_name, uint class_name_len)
+int zend_get_class_fetch_type(zend_uchar type, char *class_name, uint class_name_len)
{
if ((class_name_len == sizeof("self")-1) &&
- !memcmp(class_name, "self", sizeof("self"))) {
+ ZEND_U_EQUAL(type, class_name, class_name_len, "self", sizeof("self")-1)) {
return ZEND_FETCH_CLASS_SELF;
} else if ((class_name_len == sizeof("parent")-1) &&
- !memcmp(class_name, "parent", sizeof("parent"))) {
+ ZEND_U_EQUAL(type, class_name, class_name_len, "parent", sizeof("parent")-1)) {
return ZEND_FETCH_CLASS_PARENT;
} else {
return ZEND_FETCH_CLASS_DEFAULT;
@@ -3994,6 +4132,23 @@ ZEND_API char* zend_get_compiled_variable_name(zend_op_array *op_array, zend_uin
return op_array->vars[var].name;
}
+void zend_do_normalization(znode *result, znode *str TSRMLS_DC)
+{
+ zend_op *opline;
+
+ if (!UG(unicode)) {
+ *result = *str;
+ return;
+ }
+ opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ opline->opcode = ZEND_U_NORMALIZE;
+ opline->result.op_type = IS_TMP_VAR;
+ opline->result.u.var = get_temporary_variable(CG(active_op_array));
+ opline->op1 = *str;
+ SET_UNUSED(opline->op2);
+ *result = opline->result;
+}
+
/*
* Local variables:
* tab-width: 4