}
/* }}} */
-void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, znode *fn_flags_znode TSRMLS_DC) /* {{{ */
+static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
{
- zend_op_array op_array;
- char *name = Z_STRVAL(function_name->u.constant);
- int name_len = Z_STRLEN(function_name->u.constant);
- int function_begin_line = function_token->u.op.opline_num;
- zend_uint fn_flags;
- const char *lcname;
- zend_bool orig_interactive;
- ALLOCA_FLAG(use_heap)
+ uint32_t fetch_type = zend_get_class_fetch_type(class_name);
+ zval *c;
- if (is_method) {
- if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
- if ((Z_LVAL(fn_flags_znode->u.constant) & ~(ZEND_ACC_STATIC|ZEND_ACC_PUBLIC))) {
- zend_error_noreturn(E_COMPILE_ERROR, "Access type for interface method %s::%s() must be omitted", CG(active_class_entry)->name, Z_STRVAL(function_name->u.constant));
- }
- Z_LVAL(fn_flags_znode->u.constant) |= ZEND_ACC_ABSTRACT; /* propagates to the rest of the parser */
+ if (CG(active_class_entry) && (fetch_type == ZEND_FETCH_CLASS_SELF || (fetch_type == ZEND_FETCH_CLASS_DEFAULT && zend_string_equals_ci(class_name, CG(active_class_entry)->name)))) {
+ c = zend_hash_find(&CG(active_class_entry)->constants_table, name);
+ } else if (fetch_type == ZEND_FETCH_CLASS_DEFAULT && !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
+ zend_class_entry *ce = zend_hash_find_ptr_lc(CG(class_table), class_name->val, class_name->len);
+ if (ce) {
+ c = zend_hash_find(&ce->constants_table, name);
+ } else {
+ return 0;
}
- fn_flags = Z_LVAL(fn_flags_znode->u.constant); /* must be done *after* the above check */
} else {
- fn_flags = 0;
- }
- if ((fn_flags & ZEND_ACC_STATIC) && (fn_flags & ZEND_ACC_ABSTRACT) && !(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
- zend_error(E_STRICT, "Static function %s%s%s() should not be abstract", is_method ? CG(active_class_entry)->name : "", is_method ? "::" : "", Z_STRVAL(function_name->u.constant));
+ return 0;
}
- function_token->u.op_array = CG(active_op_array);
-
- orig_interactive = CG(interactive);
- CG(interactive) = 0;
- init_op_array(&op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE TSRMLS_CC);
- CG(interactive) = orig_interactive;
-
- op_array.function_name = name;
- if (return_reference) {
- op_array.fn_flags |= ZEND_ACC_RETURN_REFERENCE;
+ if (CG(compiler_options) & ZEND_COMPILE_NO_PERSISTENT_CONSTANT_SUBSTITUTION) {
+ return 0;
}
- op_array.fn_flags |= fn_flags;
-
- op_array.scope = is_method?CG(active_class_entry):NULL;
- op_array.prototype = NULL;
-
- op_array.line_start = zend_get_compiled_lineno(TSRMLS_C);
-
- if (is_method) {
- zend_ulong hash;
-
- lcname = zend_new_interned_string(zend_str_tolower_dup(name, name_len), name_len + 1, 1 TSRMLS_CC);
- hash = str_hash(lcname, name_len);
- if (zend_hash_quick_add(&CG(active_class_entry)->function_table, lcname, name_len+1, hash, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", CG(active_class_entry)->name, name);
- }
-
- zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
- zend_init_compiler_context(TSRMLS_C);
-
- if (fn_flags & ZEND_ACC_ABSTRACT) {
- CG(active_class_entry)->ce_flags |= ZEND_ACC_IMPLICIT_ABSTRACT_CLASS;
- }
-
- if (!(fn_flags & ZEND_ACC_PPP_MASK)) {
- fn_flags |= ZEND_ACC_PUBLIC;
- }
-
- if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
- if ((name_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
- }
- } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
- if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
- zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
- }
- } else if ((name_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
- }
- } else if ((name_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
- }
- } else if ((name_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
- }
- } else if ((name_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
- }
- } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
- }
- } else if ((name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __invoke() must have public visibility and cannot be static");
- }
-
- } else if ((name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __debugInfo() must have public visibility and cannot be static");
- }
- }
- } else {
- char *class_lcname;
- class_lcname = do_alloca(CG(active_class_entry)->name_length + 1, use_heap);
- zend_str_tolower_copy(class_lcname, CG(active_class_entry)->name, CG(active_class_entry)->name_length);
- /* Improve after RC: cache the lowercase class name */
+ /* Substitute case-sensitive (or lowercase) persistent class constants */
+ if (c && Z_TYPE_P(c) < IS_OBJECT) {
+ ZVAL_DUP(zv, c);
+ return 1;
+ }
- if ((CG(active_class_entry)->name_length == name_len) && ((CG(active_class_entry)->ce_flags & ZEND_ACC_TRAIT) != ZEND_ACC_TRAIT) && (!memcmp(class_lcname, lcname, name_len))) {
- if (!CG(active_class_entry)->constructor) {
- 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)))) {
- if (CG(active_class_entry)->constructor) {
- zend_error(E_STRICT, "Redefining already defined constructor for class %s", 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)-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)-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)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __call() must have public visibility and cannot be static");
- }
- CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
- if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
- zend_error(E_WARNING, "The magic method __callStatic() must have public visibility and be static");
- }
- CG(active_class_entry)->__callstatic = (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)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __get() must have public visibility and cannot be static");
- }
- 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)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __set() must have public visibility and cannot be static");
- }
- 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)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __unset() must have public visibility and cannot be static");
- }
- 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)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __isset() must have public visibility and cannot be static");
- }
- CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __toString() must have public visibility and cannot be static");
- }
- CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array);
- } else if ((name_len == sizeof(ZEND_INVOKE_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_INVOKE_FUNC_NAME, sizeof(ZEND_INVOKE_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __invoke() must have public visibility and cannot be static");
- }
- } else if ((name_len == sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1) && (!memcmp(lcname, ZEND_DEBUGINFO_FUNC_NAME, sizeof(ZEND_DEBUGINFO_FUNC_NAME)-1))) {
- if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
- zend_error(E_WARNING, "The magic method __debugInfo() must have public visibility and cannot be static");
- }
- CG(active_class_entry)->__debugInfo = (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(class_lcname, use_heap);
- }
+ return 0;
+}
++/* }}} */
- str_efree(lcname);
- } else {
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- zval key;
- zval **ns_name;
+void zend_init_list(void *result, void *item) /* {{{ */
+{
+ void** list = emalloc(sizeof(void*) * 2);
- if (CG(current_namespace)) {
- /* Prefix function name with current namespace name */
- znode tmp;
-
- tmp.u.constant = *CG(current_namespace);
- zval_copy_ctor(&tmp.u.constant);
- zend_do_build_namespace_name(&tmp, &tmp, function_name TSRMLS_CC);
- op_array.function_name = Z_STRVAL(tmp.u.constant);
- name_len = Z_STRLEN(tmp.u.constant);
- lcname = zend_str_tolower_dup(Z_STRVAL(tmp.u.constant), name_len);
- } else {
- lcname = zend_str_tolower_dup(name, name_len);
- }
+ list[0] = item;
+ list[1] = NULL;
- /* Function name must not conflict with import names */
- if (CG(current_import_function) &&
- zend_hash_find(CG(current_import_function), lcname, Z_STRLEN(function_name->u.constant)+1, (void**)&ns_name) == SUCCESS) {
+ *(void**)result = list;
+}
+/* }}} */
- char *tmp = zend_str_tolower_dup(Z_STRVAL_PP(ns_name), Z_STRLEN_PP(ns_name));
+void zend_add_to_list(void *result, void *item) /* {{{ */
+{
+ void** list = *(void**)result;
+ size_t n = 0;
- if (Z_STRLEN_PP(ns_name) != Z_STRLEN(function_name->u.constant) ||
- memcmp(tmp, lcname, Z_STRLEN(function_name->u.constant))) {
- zend_error(E_COMPILE_ERROR, "Cannot declare function %s because the name is already in use", Z_STRVAL(function_name->u.constant));
- }
- efree(tmp);
+ if (list) {
+ while (list[n]) {
+ n++;
}
-
- opline->opcode = ZEND_DECLARE_FUNCTION;
- opline->op1_type = IS_CONST;
- build_runtime_defined_function_key(&key, lcname, name_len TSRMLS_CC);
- opline->op1.constant = zend_add_literal(CG(active_op_array), &key TSRMLS_CC);
- Z_HASH_P(&CONSTANT(opline->op1.constant)) = zend_hash_func(Z_STRVAL(CONSTANT(opline->op1.constant)), Z_STRLEN(CONSTANT(opline->op1.constant)));
- opline->op2_type = IS_CONST;
- LITERAL_STRINGL(opline->op2, lcname, name_len, 1);
- CALCULATE_LITERAL_HASH(opline->op2.constant);
- opline->extended_value = ZEND_DECLARE_FUNCTION;
- zend_hash_quick_update(CG(function_table), Z_STRVAL(key), Z_STRLEN(key), Z_HASH_P(&CONSTANT(opline->op1.constant)), &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array));
- zend_stack_push(&CG(context_stack), (void *) &CG(context), sizeof(CG(context)));
- zend_init_compiler_context(TSRMLS_C);
- str_efree(lcname);
}
- if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
- zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+ list = erealloc(list, sizeof(void*) * (n+2));
- opline->opcode = ZEND_EXT_NOP;
- opline->lineno = function_begin_line;
- SET_UNUSED(opline->op1);
- SET_UNUSED(opline->op2);
- }
+ list[n] = item;
+ list[n+1] = NULL;
- {
- /* Push a separator to the switch stack */
- zend_switch_entry switch_entry;
+ *(void**)result = list;
+}
+/* }}} */
- switch_entry.cond.op_type = IS_UNUSED;
- switch_entry.default_case = 0;
- switch_entry.control_var = 0;
+void zend_do_extended_info(void) /* {{{ */
+{
+ zend_op *opline;
- zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry));
+ if (!(CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO)) {
+ return;
}
- {
- /* Push a separator to the foreach stack */
- zend_op dummy_opline;
-
- dummy_opline.result_type = IS_UNUSED;
-
- zend_stack_push(&CG(foreach_copy_stack), (void *) &dummy_opline, sizeof(zend_op));
- }
+ opline = get_next_op(CG(active_op_array));
- if (CG(doc_comment)) {
- CG(active_op_array)->doc_comment = CG(doc_comment);
- CG(active_op_array)->doc_comment_len = CG(doc_comment_len);
- CG(doc_comment) = NULL;
- CG(doc_comment_len) = 0;
- }
+ opline->opcode = ZEND_EXT_STMT;
+ SET_UNUSED(opline->op1);
+ SET_UNUSED(opline->op2);
}
/* }}} */
}
/* }}} */
-void zend_do_end_function_declaration(const znode *function_token TSRMLS_DC) /* {{{ */
-{
- char lcname[16];
- int name_len;
-
- zend_do_extended_info(TSRMLS_C);
- zend_do_return(NULL, 0 TSRMLS_CC);
-
- pass_two(CG(active_op_array) TSRMLS_CC);
- zend_release_labels(0 TSRMLS_CC);
++zend_bool zend_is_auto_global_str(char *name, size_t len) /* {{{ */ {
++ zend_auto_global *auto_global;
+
- 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 {
- /* 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) {
- zend_error_noreturn(E_COMPILE_ERROR, "%s() must take exactly 1 argument", ZEND_AUTOLOAD_FUNC_NAME);
++ if ((auto_global = zend_hash_str_find_ptr(CG(auto_globals), name, len)) != NULL) {
++ if (auto_global->armed) {
++ auto_global->armed = auto_global->auto_global_callback(auto_global->name);
+ }
++ return 1;
+ }
-
- CG(active_op_array)->line_end = zend_get_compiled_lineno(TSRMLS_C);
- CG(active_op_array) = function_token->u.op_array;
-
-
- /* Pop the switch and foreach separators */
- zend_stack_del_top(&CG(switch_cond_stack));
- zend_stack_del_top(&CG(foreach_copy_stack));
++ return 0;
+ }
+ /* }}} */
+
-void zend_do_receive_param(zend_uchar op, znode *varname, const znode *initialization, znode *class_type, zend_uchar pass_by_reference, zend_bool is_variadic TSRMLS_DC) /* {{{ */
+zend_bool zend_is_auto_global(zend_string *name) /* {{{ */
{
- zend_op *opline;
- zend_arg_info *cur_arg_info;
- znode var;
+ zend_auto_global *auto_global;
- if (zend_is_auto_global(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant) TSRMLS_CC)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign auto-global variable %s", Z_STRVAL(varname->u.constant));
- } else {
- var.op_type = IS_CV;
- var.u.op.var = lookup_cv(CG(active_op_array), Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant), 0 TSRMLS_CC);
- Z_STRVAL(varname->u.constant) = (char*)CG(active_op_array)->vars[var.u.op.var].name;
- var.EA = 0;
- if (CG(active_op_array)->vars[var.u.op.var].hash_value == THIS_HASHVAL &&
- Z_STRLEN(varname->u.constant) == sizeof("this")-1 &&
- !memcmp(Z_STRVAL(varname->u.constant), "this", sizeof("this")-1)) {
- if (CG(active_op_array)->scope &&
- (CG(active_op_array)->fn_flags & ZEND_ACC_STATIC) == 0) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
- }
- CG(active_op_array)->this_var = var.u.op.var;
- }
- }
-
- if (CG(active_op_array)->fn_flags & ZEND_ACC_VARIADIC) {
- zend_error_noreturn(E_COMPILE_ERROR, "Only the last parameter can be variadic");
- }
-
- if (is_variadic) {
- if (op == ZEND_RECV_INIT) {
- zend_error_noreturn(E_COMPILE_ERROR, "Variadic parameter cannot have a default value");
- }
-
- op = ZEND_RECV_VARIADIC;
- CG(active_op_array)->fn_flags |= ZEND_ACC_VARIADIC;
- }
-
- opline = get_next_op(CG(active_op_array) TSRMLS_CC);
- CG(active_op_array)->num_args++;
- opline->opcode = op;
- SET_NODE(opline->result, &var);
- opline->op1_type = IS_UNUSED;
- opline->op1.num = CG(active_op_array)->num_args;
- if (op == ZEND_RECV_INIT) {
- SET_NODE(opline->op2, initialization);
- } else {
- SET_UNUSED(opline->op2);
- if (!is_variadic) {
- CG(active_op_array)->required_num_args = CG(active_op_array)->num_args;
- }
- }
- 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 = zend_new_interned_string(estrndup(Z_STRVAL(varname->u.constant), Z_STRLEN(varname->u.constant)), Z_STRLEN(varname->u.constant) + 1, 1 TSRMLS_CC);
- cur_arg_info->name_len = Z_STRLEN(varname->u.constant);
- cur_arg_info->type_hint = 0;
- cur_arg_info->pass_by_reference = pass_by_reference;
- cur_arg_info->allow_null = 1;
- cur_arg_info->is_variadic = is_variadic;
- cur_arg_info->class_name = NULL;
- cur_arg_info->class_name_len = 0;
-
- if (class_type->op_type != IS_UNUSED) {
- cur_arg_info->allow_null = 0;
-
- if (class_type->u.constant.type != IS_NULL) {
- if (class_type->u.constant.type == IS_ARRAY) {
- cur_arg_info->type_hint = IS_ARRAY;
- if (op == ZEND_RECV_INIT) {
- if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
- cur_arg_info->allow_null = 1;
- } else if (IS_CONSTANT_TYPE(Z_TYPE(initialization->u.constant))) {
- /* delay constant resolution and check to run-time */
- cur_arg_info->allow_null = 0;
- } else if (Z_TYPE(initialization->u.constant) != IS_ARRAY) {
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with array type hint can only be an array or NULL");
- }
- }
- } else if (class_type->u.constant.type == IS_CALLABLE) {
- cur_arg_info->type_hint = IS_CALLABLE;
- if (op == ZEND_RECV_INIT) {
- if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
- cur_arg_info->allow_null = 1;
- } else if (IS_CONSTANT_TYPE(Z_TYPE(initialization->u.constant))) {
- /* delay constant resolution and check to run-time */
- cur_arg_info->allow_null = 0;
- } else {
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with callable type hint can only be NULL");
- }
- }
- } else {
- cur_arg_info->type_hint = IS_OBJECT;
- if (ZEND_FETCH_CLASS_DEFAULT == zend_get_class_fetch_type(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant))) {
- zend_resolve_class_name(class_type TSRMLS_CC);
- }
- Z_STRVAL(class_type->u.constant) = (char*)zend_new_interned_string(Z_STRVAL(class_type->u.constant), Z_STRLEN(class_type->u.constant) + 1, 1 TSRMLS_CC);
- cur_arg_info->class_name = Z_STRVAL(class_type->u.constant);
- cur_arg_info->class_name_len = Z_STRLEN(class_type->u.constant);
- if (op == ZEND_RECV_INIT) {
- if (Z_TYPE(initialization->u.constant) == IS_NULL || (Z_TYPE(initialization->u.constant) == IS_CONSTANT && !strcasecmp(Z_STRVAL(initialization->u.constant), "NULL"))) {
- cur_arg_info->allow_null = 1;
- } else if (IS_CONSTANT_TYPE(Z_TYPE(initialization->u.constant))) {
- /* delay constant resolution and check to run-time */
- cur_arg_info->allow_null = 0;
- } else {
- zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters with a class type hint can only be NULL");
- }
- }
- }
+ if ((auto_global = zend_hash_find_ptr(CG(auto_globals), name)) != NULL) {
+ if (auto_global->armed) {
+ auto_global->armed = auto_global->auto_global_callback(auto_global->name);
}
+ return 1;
}
+ return 0;
}
/* }}} */
#endif
return columns;
} /* }}} */
- int ret;
- zend_string *str = zend_string_init(name, len, 0);
- ret = zend_is_auto_global(str);
- efree(str);
- return ret;
+
+PHPDBG_API void phpdbg_set_async_io(int fd) {
+#ifndef _WIN32
+ int flags;
+ fcntl(STDIN_FILENO, F_SETOWN, getpid());
+ flags = fcntl(STDIN_FILENO, F_GETFL);
+ fcntl(STDIN_FILENO, F_SETFL, flags | FASYNC);
+#endif
+}
+
+int phpdbg_safe_class_lookup(const char *name, int name_length, zend_class_entry **ce) {
+ if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) {
+ char *lc_name, *lc_free;
+ int lc_length;
+
+ if (name == NULL || !name_length) {
+ return FAILURE;
+ }
+
+ lc_free = lc_name = emalloc(name_length + 1);
+ zend_str_tolower_copy(lc_name, name, name_length);
+ lc_length = name_length + 1;
+
+ if (lc_name[0] == '\\') {
+ lc_name += 1;
+ lc_length -= 1;
+ }
+
+ phpdbg_try_access {
+ *ce = zend_hash_str_find_ptr(EG(class_table), lc_name, lc_length);
+ } phpdbg_catch_access {
+ phpdbg_error("signalsegv", "class=\"%.*s\"", "Could not fetch class %.*s, invalid data source", name_length, name);
+ } phpdbg_end_try_access();
+
+ efree(lc_free);
+ } else {
+ zend_string *str_name = zend_string_init(name, name_length, 0);
+ *ce = zend_lookup_class(str_name);
+ efree(str_name);
+ }
+
+ return ce ? SUCCESS : FAILURE;
+}
+
+char *phpdbg_get_property_key(char *key) {
+ if (*key != 0) {
+ return key;
+ }
+ return strchr(key + 1, 0) + 1;
+}
+
+static int phpdbg_parse_variable_arg_wrapper(char *name, size_t len, char *keyname, size_t keylen, HashTable *parent, zval *zv, phpdbg_parse_var_func callback) {
+ return callback(name, len, keyname, keylen, parent, zv);
+}
+
+PHPDBG_API int phpdbg_parse_variable(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_func callback, zend_bool silent) {
+ return phpdbg_parse_variable_with_arg(input, len, parent, i, (phpdbg_parse_var_with_arg_func) phpdbg_parse_variable_arg_wrapper, silent, callback);
+}
+
+PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable *parent, size_t i, phpdbg_parse_var_with_arg_func callback, zend_bool silent, void *arg) {
+ int ret = FAILURE;
+ zend_bool new_index = 1;
+ char *last_index;
+ size_t index_len = 0;
+ zval *zv;
+
+ if (len < 2 || *input != '$') {
+ goto error;
+ }
+
+ while (i++ < len) {
+ if (i == len) {
+ new_index = 1;
+ } else {
+ switch (input[i]) {
+ case '[':
+ new_index = 1;
+ break;
+ case ']':
+ break;
+ case '>':
+ if (last_index[index_len - 1] == '-') {
+ new_index = 1;
+ index_len--;
+ }
+ break;
+
+ default:
+ if (new_index) {
+ last_index = input + i;
+ new_index = 0;
+ }
+ if (input[i - 1] == ']') {
+ goto error;
+ }
+ index_len++;
+ }
+ }
+
+ if (new_index && index_len == 0) {
+ zend_ulong numkey;
+ zend_string *strkey;
+ ZEND_HASH_FOREACH_KEY_PTR(parent, numkey, strkey, zv) {
+ while (Z_TYPE_P(zv) == IS_INDIRECT) {
+ zv = Z_INDIRECT_P(zv);
+ }
+
+ if (i == len || (i == len - 1 && input[len - 1] == ']')) {
+ char *key, *propkey;
+ size_t namelen, keylen;
+ char *name;
+ char *keyname = estrndup(last_index, index_len);
+ if (strkey) {
+ key = strkey->val;
+ keylen = strkey->len;
+ } else {
+ keylen = spprintf(&key, 0, "%llu", numkey);
+ }
+ propkey = phpdbg_get_property_key(key);
+ name = emalloc(i + keylen + 2);
+ namelen = sprintf(name, "%.*s%.*s%s", (int) i, input, keylen - (propkey - key), propkey, input[len - 1] == ']'?"]":"");
+ if (!strkey) {
+ efree(key);
+ }
+
+ ret = callback(name, namelen, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
+ } else if (Z_TYPE_P(zv) == IS_OBJECT) {
+ phpdbg_parse_variable_with_arg(input, len, Z_OBJPROP_P(zv), i, callback, silent, arg);
+ } else if (Z_TYPE_P(zv) == IS_ARRAY) {
+ phpdbg_parse_variable_with_arg(input, len, Z_ARRVAL_P(zv), i, callback, silent, arg);
+ } else {
+ /* Ignore silently */
+ }
+ } ZEND_HASH_FOREACH_END();
+ return ret;
+ } else if (new_index) {
+ char last_chr = last_index[index_len];
+ last_index[index_len] = 0;
+ if (!(zv = zend_symtable_str_find(parent, last_index, index_len))) {
+ if (!silent) {
+ phpdbg_error("variable", "type=\"undefined\" variable=\"%.*s\"", "%.*s is undefined", (int) i, input);
+ }
+ return FAILURE;
+ }
+ while (Z_TYPE_P(zv) == IS_INDIRECT) {
+ zv = Z_INDIRECT_P(zv);
+ }
+
+ last_index[index_len] = last_chr;
+ if (i == len) {
+ char *name = estrndup(input, len);
+ char *keyname = estrndup(last_index, index_len);
+
+ ret = callback(name, len, keyname, index_len, parent, zv, arg) == SUCCESS || ret == SUCCESS?SUCCESS:FAILURE;
+ } else if (Z_TYPE_P(zv) == IS_OBJECT) {
+ parent = Z_OBJPROP_P(zv);
+ } else if (Z_TYPE_P(zv) == IS_ARRAY) {
+ parent = Z_ARRVAL_P(zv);
+ } else {
+ phpdbg_error("variable", "type=\"notiterable\" variable=\"%.*s\"", "%.*s is nor an array nor an object", (int) i, input);
+ return FAILURE;
+ }
+ index_len = 0;
+ }
+ }
+
+ return ret;
+ error:
+ phpdbg_error("variable", "type=\"invalidinput\"", "Malformed input");
+ return FAILURE;
+}
+
+int phpdbg_is_auto_global(char *name, int len) {
++ return zend_is_auto_global_str(name, len);
+}
+
+static int phpdbg_xml_array_element_dump(zval *zv, zend_string *key, zend_ulong num) {
+ phpdbg_xml("<element");
+
+ phpdbg_try_access {
+ if (key) { /* string key */
+ phpdbg_xml(" name=\"%.*s\"", key->len, key->val);
+ } else { /* numeric key */
+ phpdbg_xml(" name=\"%ld\"", num);
+ }
+ } phpdbg_catch_access {
+ phpdbg_xml(" severity=\"error\" ></element>");
+ return 0;
+ } phpdbg_end_try_access();
+
+ phpdbg_xml(">");
+
+ phpdbg_xml_var_dump(zv);
+
+ phpdbg_xml("</element>");
+
+ return 0;
+}
+
+static int phpdbg_xml_object_property_dump(zval *zv, zend_string *key, zend_ulong num) {
+ phpdbg_xml("<property");
+
+ phpdbg_try_access {
+ if (key) { /* string key */
+ const char *prop_name, *class_name;
+ int unmangle = zend_unmangle_property_name(key, &class_name, &prop_name);
+
+ if (class_name && unmangle == SUCCESS) {
+ phpdbg_xml(" name=\"%s\"", prop_name);
+ if (class_name[0] == '*') {
+ phpdbg_xml(" protection=\"protected\"");
+ } else {
+ phpdbg_xml(" class=\"%s\" protection=\"private\"", class_name);
+ }
+ } else {
+ phpdbg_xml(" name=\"%.*s\" protection=\"public\"", key->len, key->val);
+ }
+ } else { /* numeric key */
+ phpdbg_xml(" name=\"%ld\" protection=\"public\"", num);
+ }
+ } phpdbg_catch_access {
+ phpdbg_xml(" severity=\"error\" ></property>");
+ return 0;
+ } phpdbg_end_try_access();
+
+ phpdbg_xml(">");
+
+ phpdbg_xml_var_dump(zv);
+
+ phpdbg_xml("</property>");
+
+ return 0;
+}
+
+#define COMMON (is_ref ? "&" : "")
+
+PHPDBG_API void phpdbg_xml_var_dump(zval *zv) {
+ HashTable *myht;
+ zend_string *class_name, *key;
+ zend_ulong num;
+ zval *val;
+ int (*element_dump_func)(zval *zv, zend_string *key, zend_ulong num);
+ zend_bool is_ref = 0;
+
+ int is_temp;
+
+ phpdbg_try_access {
+ is_ref = Z_ISREF_P(zv) && GC_REFCOUNT(Z_COUNTED_P(zv)) > 1;
+ ZVAL_DEREF(zv);
+
+ switch (Z_TYPE_P(zv)) {
+ case IS_TRUE:
+ phpdbg_xml("<bool refstatus=\"%s\" value=\"true\" />", COMMON);
+ break;
+ case IS_FALSE:
+ phpdbg_xml("<bool refstatus=\"%s\" value=\"false\" />", COMMON);
+ break;
+ case IS_NULL:
+ phpdbg_xml("<null refstatus=\"%s\" />", COMMON);
+ break;
+ case IS_LONG:
+ phpdbg_xml("<int refstatus=\"%s\" value=\"" ZEND_LONG_FMT "\" />", COMMON, Z_LVAL_P(zv));
+ break;
+ case IS_DOUBLE:
+ phpdbg_xml("<float refstatus=\"%s\" value=\"%.*G\" />", COMMON, (int) EG(precision), Z_DVAL_P(zv));
+ break;
+ case IS_STRING:
+ phpdbg_xml("<string refstatus=\"%s\" length=\"%d\" value=\"%.*s\" />", COMMON, Z_STRLEN_P(zv), Z_STRLEN_P(zv), Z_STRVAL_P(zv));
+ break;
+ case IS_ARRAY:
+ myht = Z_ARRVAL_P(zv);
+ if (ZEND_HASH_APPLY_PROTECTION(myht) && ++myht->u.v.nApplyCount > 1) {
+ phpdbg_xml("<recursion />");
+ --myht->u.v.nApplyCount;
+ break;
+ }
+ phpdbg_xml("<array refstatus=\"%s\" num=\"%d\">", COMMON, zend_hash_num_elements(myht));
+ element_dump_func = phpdbg_xml_array_element_dump;
+ is_temp = 0;
+ goto head_done;
+ case IS_OBJECT:
+ myht = Z_OBJDEBUG_P(zv, is_temp);
+ if (myht && ++myht->u.v.nApplyCount > 1) {
+ phpdbg_xml("<recursion />");
+ --myht->u.v.nApplyCount;
+ break;
+ }
+
+ class_name = Z_OBJ_HANDLER_P(zv, get_class_name)(Z_OBJ_P(zv));
+ phpdbg_xml("<object refstatus=\"%s\" class=\"%.*s\" id=\"%d\" num=\"%d\">", COMMON, class_name->len, class_name->val, Z_OBJ_HANDLE_P(zv), myht ? zend_hash_num_elements(myht) : 0);
+ zend_string_release(class_name);
+
+ element_dump_func = phpdbg_xml_object_property_dump;
+head_done:
+ if (myht) {
+ ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
+ element_dump_func(val, key, num);
+ } ZEND_HASH_FOREACH_END();
+ zend_hash_apply_with_arguments(myht, (apply_func_args_t) element_dump_func, 0);
+ --myht->u.v.nApplyCount;
+ if (is_temp) {
+ zend_hash_destroy(myht);
+ efree(myht);
+ }
+ }
+ if (Z_TYPE_P(zv) == IS_ARRAY) {
+ phpdbg_xml("</array>");
+ } else {
+ phpdbg_xml("</object>");
+ }
+ break;
+ case IS_RESOURCE: {
+ const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(zv));
+ phpdbg_xml("<resource refstatus=\"%s\" id=\"%pd\" type=\"%ld\" />", COMMON, Z_RES_P(zv)->handle, type_name ? type_name : "unknown");
+ break;
+ }
+ default:
+ break;
+ }
+ } phpdbg_end_try_access();
+}