if (p) {
ZVAL_STRING(name, p+1, 1);
} else {
- *name = *ns;
- zval_copy_ctor(name);
+ ZVAL_ZVAL(name, ns, 1, 0);
- warn = !is_global && !CG(current_namespace);
+ warn = !CG(current_namespace);
}
}
}
/* }}} */
- void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, int is_function, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC) /* {{{ */
-void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
++void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_function, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC) /* {{{ */
{
- zend_op *opline;
+ char *lookup_name;
+ zval *name, *ns, tmp;
+ zend_bool warn = 0;
- if(Z_TYPE(value->u.constant) == IS_CONSTANT_ARRAY) {
- zend_error(E_COMPILE_ERROR, "Arrays are not allowed as constants");
+ MAKE_STD_ZVAL(ns);
+ ZVAL_ZVAL(ns, &ns_name->u.constant, 0, 0);
+ if (new_name) {
+ name = &new_name->u.constant;
+ } else {
+ const char *p;
+
+ /* The form "use A\B" is eqivalent to "use A\B as B".
+ So we extract the last part of compound name to use as a new_name */
+ name = &tmp;
+ p = zend_memrchr(Z_STRVAL_P(ns), '\\', Z_STRLEN_P(ns));
+ if (p) {
+ ZVAL_STRING(name, p+1, 1);
+ } else {
+ ZVAL_ZVAL(name, ns, 1, 0);
- warn = !is_global && !CG(current_namespace);
++ warn = !CG(current_namespace);
+ }
}
- void zend_do_use_function(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{{ */
+ if (case_sensitive) {
+ lookup_name = estrndup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+ } else {
+ lookup_name = zend_str_tolower_dup(Z_STRVAL_P(name), Z_STRLEN_P(name));
+ }
+
+ if (CG(current_namespace)) {
+ /* Prefix import name with current namespace name to avoid conflicts with functions/consts */
+ char *c_ns_name = emalloc(Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) + 1);
+
+ zend_str_tolower_copy(c_ns_name, Z_STRVAL_P(CG(current_namespace)), Z_STRLEN_P(CG(current_namespace)));
+ c_ns_name[Z_STRLEN_P(CG(current_namespace))] = '\\';
+ memcpy(c_ns_name+Z_STRLEN_P(CG(current_namespace))+1, lookup_name, Z_STRLEN_P(name)+1);
+ if (zend_hash_exists(lookup_table, c_ns_name, Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name)+1)) {
+ char *tmp2 = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
+
+ if (Z_STRLEN_P(ns) != Z_STRLEN_P(CG(current_namespace)) + 1 + Z_STRLEN_P(name) ||
+ memcmp(tmp2, c_ns_name, Z_STRLEN_P(ns))) {
+ zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", is_function ? "function" : "const", Z_STRVAL_P(ns), Z_STRVAL_P(name));
+ }
+ efree(tmp2);
+ }
+ efree(c_ns_name);
+ } else if (is_function) {
+ zend_function *function;
+
+ if (zend_hash_find(lookup_table, lookup_name, Z_STRLEN_P(name)+1, (void **) &function) == SUCCESS && function->type == ZEND_USER_FUNCTION && strcmp(function->op_array.filename, CG(compiled_filename)) == 0) {
+ char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
+
+ if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
+ memcmp(c_tmp, lookup_name, Z_STRLEN_P(ns))) {
+ zend_error(E_COMPILE_ERROR, "Cannot use function %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
+ }
+ efree(c_tmp);
+ }
+ } else {
+ const char *filename;
+
+ if (zend_hash_find(lookup_table, lookup_name, Z_STRLEN_P(name)+1, (void **) &filename) == SUCCESS && strcmp(filename, CG(compiled_filename)) == 0) {
+ char *c_tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), Z_STRLEN_P(ns));
+
+ if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
+ memcmp(c_tmp, lookup_name, Z_STRLEN_P(ns))) {
+ zend_error(E_COMPILE_ERROR, "Cannot use const %s as %s because the name is already in use", Z_STRVAL_P(ns), Z_STRVAL_P(name));
+ }
+ efree(c_tmp);
+ }
+ }
+
+ if (zend_hash_add(current_import_sub, lookup_name, Z_STRLEN_P(name)+1, &ns, sizeof(zval*), NULL) != SUCCESS) {
+ zend_error(E_COMPILE_ERROR, "Cannot use %s %s as %s because the name is already in use", is_function ? "function" : "const", Z_STRVAL_P(ns), Z_STRVAL_P(name));
+ }
+ if (warn) {
+ zend_error(E_WARNING, "The use %s statement with non-compound name '%s' has no effect", is_function ? "function" : "const", Z_STRVAL_P(name));
+ }
+ efree(lookup_name);
+ zval_dtor(name);
+}
+/* }}} */
+
- zend_do_use_non_class(ns_name, new_name, is_global, 1, 0, CG(current_import_function), CG(function_table) TSRMLS_CC);
++void zend_do_use_function(znode *ns_name, znode *new_name TSRMLS_DC) /* {{{ */
+{
+ if (!CG(current_import_function)) {
+ CG(current_import_function) = emalloc(sizeof(HashTable));
+ zend_hash_init(CG(current_import_function), 0, NULL, ZVAL_PTR_DTOR, 0);
+ }
+
- void zend_do_use_const(znode *ns_name, znode *new_name, int is_global TSRMLS_DC) /* {{{ */
++ zend_do_use_non_class(ns_name, new_name, 1, 0, CG(current_import_function), CG(function_table) TSRMLS_CC);
+}
+/* }}} */
+
- zend_do_use_non_class(ns_name, new_name, is_global, 0, 1, CG(current_import_const), &CG(const_filenames) TSRMLS_CC);
++void zend_do_use_const(znode *ns_name, znode *new_name TSRMLS_DC) /* {{{ */
+{
+ if (!CG(current_import_const)) {
+ CG(current_import_const) = emalloc(sizeof(HashTable));
+ zend_hash_init(CG(current_import_const), 0, NULL, ZVAL_PTR_DTOR, 0);
+ }
+
++ zend_do_use_non_class(ns_name, new_name, 0, 1, CG(current_import_const), &CG(const_filenames) TSRMLS_CC);
+}
+/* }}} */
+
+void zend_do_declare_constant(znode *name, znode *value TSRMLS_DC) /* {{{ */
+{
+ zend_op *opline;
+ zval **ns_name;
+
if (zend_get_ct_const(&name->u.constant, 0 TSRMLS_CC)) {
- zend_error(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", Z_STRVAL(name->u.constant));
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare constant '%s'", Z_STRVAL(name->u.constant));
}
if (CG(current_namespace)) {
void zend_do_begin_namespace(const znode *name, zend_bool with_brackets TSRMLS_DC);
void zend_do_end_namespace(TSRMLS_D);
void zend_verify_namespace(TSRMLS_D);
- void zend_do_use(znode *name, znode *new_name, int is_global TSRMLS_DC);
- void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_global, int is_function, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC);
- void zend_do_use_function(znode *name, znode *new_name, int is_global TSRMLS_DC);
- void zend_do_use_const(znode *name, znode *new_name, int is_global TSRMLS_DC);
+ void zend_do_use(znode *name, znode *new_name TSRMLS_DC);
++void zend_do_use_non_class(znode *ns_name, znode *new_name, int is_function, zend_bool case_sensitive, HashTable *current_import_sub, HashTable *lookup_table TSRMLS_DC);
++void zend_do_use_function(znode *name, znode *new_name TSRMLS_DC);
++void zend_do_use_const(znode *name, znode *new_name TSRMLS_DC);
void zend_do_end_compilation(TSRMLS_D);
+void zend_do_constant_expression(znode *result, zend_ast *ast TSRMLS_DC);
void zend_do_resolve_class_name(znode *result, znode *class_name, int is_static TSRMLS_DC);
;
use_declaration:
- namespace_name { zend_do_use(&$1, NULL, 0 TSRMLS_CC); }
- | namespace_name T_AS T_STRING { zend_do_use(&$1, &$3, 0 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name { zend_do_use(&$2, NULL, 1 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use(&$2, &$4, 1 TSRMLS_CC); }
+ namespace_name { zend_do_use(&$1, NULL TSRMLS_CC); }
+ | namespace_name T_AS T_STRING { zend_do_use(&$1, &$3 TSRMLS_CC); }
+ | T_NS_SEPARATOR namespace_name { zend_do_use(&$2, NULL TSRMLS_CC); }
+ | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use(&$2, &$4 TSRMLS_CC); }
;
- namespace_name { zend_do_use_function(&$1, NULL, 0 TSRMLS_CC); }
- | namespace_name T_AS T_STRING { zend_do_use_function(&$1, &$3, 0 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name { zend_do_use_function(&$2, NULL, 1 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use_function(&$2, &$4, 1 TSRMLS_CC); }
+use_function_declarations:
+ use_function_declarations ',' use_function_declaration
+ | use_function_declaration
+;
+
+use_function_declaration:
- namespace_name { zend_do_use_const(&$1, NULL, 0 TSRMLS_CC); }
- | namespace_name T_AS T_STRING { zend_do_use_const(&$1, &$3, 0 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name { zend_do_use_const(&$2, NULL, 1 TSRMLS_CC); }
- | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use_const(&$2, &$4, 1 TSRMLS_CC); }
++ namespace_name { zend_do_use_function(&$1, NULL TSRMLS_CC); }
++ | namespace_name T_AS T_STRING { zend_do_use_function(&$1, &$3 TSRMLS_CC); }
++ | T_NS_SEPARATOR namespace_name { zend_do_use_function(&$2, NULL TSRMLS_CC); }
++ | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use_function(&$2, &$4 TSRMLS_CC); }
+;
+
+use_const_declarations:
+ use_const_declarations ',' use_const_declaration
+ | use_const_declaration
+;
+
+use_const_declaration:
++ namespace_name { zend_do_use_const(&$1, NULL TSRMLS_CC); }
++ | namespace_name T_AS T_STRING { zend_do_use_const(&$1, &$3 TSRMLS_CC); }
++ | T_NS_SEPARATOR namespace_name { zend_do_use_const(&$2, NULL TSRMLS_CC); }
++ | T_NS_SEPARATOR namespace_name T_AS T_STRING { zend_do_use_const(&$2, &$4 TSRMLS_CC); }
+;
+
constant_declaration:
constant_declaration ',' T_STRING '=' static_scalar { zend_do_declare_constant(&$3, &$5 TSRMLS_CC); }
| T_CONST T_STRING '=' static_scalar { zend_do_declare_constant(&$2, &$4 TSRMLS_CC); }