summaryrefslogtreecommitdiff
path: root/Zend/zend_constants.c
diff options
context:
space:
mode:
Diffstat (limited to 'Zend/zend_constants.c')
-rw-r--r--Zend/zend_constants.c143
1 files changed, 111 insertions, 32 deletions
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index 94c3b4cf02..03b6309cc3 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -32,13 +32,15 @@ void free_zend_constant(zend_constant *c)
if (!(c->flags & CONST_PERSISTENT)) {
zval_dtor(&c->value);
}
- free(c->name);
+ str_free(c->name);
}
void copy_zend_constant(zend_constant *c)
{
- c->name = zend_strndup(c->name, c->name_len - 1);
+ if (!IS_INTERNED(c->name)) {
+ c->name = zend_strndup(c->name, c->name_len - 1);
+ }
if (!(c->flags & CONST_PERSISTENT)) {
zval_copy_ctor(&c->value);
}
@@ -139,7 +141,7 @@ void zend_register_standard_constants(TSRMLS_D)
c.value.type = IS_NULL;
zend_register_constant(&c TSRMLS_CC);
- c.flags = CONST_PERSISTENT;
+ c.flags = CONST_PERSISTENT | CONST_CS;
c.name = zend_strndup(ZEND_STRL("ZEND_THREAD_SAFE"));
c.name_len = sizeof("ZEND_THREAD_SAFE");
@@ -222,6 +224,64 @@ ZEND_API void zend_register_string_constant(const char *name, uint name_len, cha
zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number TSRMLS_CC);
}
+static int zend_get_special_constant(const char *name, uint name_len, zend_constant **c TSRMLS_DC)
+{
+ int ret;
+ static char haltoff[] = "__COMPILER_HALT_OFFSET__";
+
+ if (!EG(in_execution)) {
+ return 0;
+ } else if (name_len == sizeof("__CLASS__")-1 &&
+ !memcmp(name, "__CLASS__", sizeof("__CLASS__")-1)) {
+ zend_constant tmp;
+
+ /* Returned constants may be cached, so they have to be stored */
+ if (EG(scope) && EG(scope)->name) {
+ int const_name_len;
+ char *const_name;
+ ALLOCA_FLAG(use_heap)
+
+ const_name_len = sizeof("\0__CLASS__") + EG(scope)->name_length;
+ const_name = do_alloca(const_name_len, use_heap);
+ memcpy(const_name, "\0__CLASS__", sizeof("\0__CLASS__")-1);
+ zend_str_tolower_copy(const_name + sizeof("\0__CLASS__")-1, EG(scope)->name, EG(scope)->name_length);
+ if (zend_hash_find(EG(zend_constants), const_name, const_name_len, (void**)c) == FAILURE) {
+ zend_hash_add(EG(zend_constants), const_name, const_name_len, (void*)&tmp, sizeof(zend_constant), (void**)c);
+ memset(*c, 0, sizeof(zend_constant));
+ Z_STRVAL((**c).value) = estrndup(EG(scope)->name, EG(scope)->name_length);
+ Z_STRLEN((**c).value) = EG(scope)->name_length;
+ Z_TYPE((**c).value) = IS_STRING;
+ }
+ free_alloca(const_name, use_heap);
+ } else {
+ if (zend_hash_find(EG(zend_constants), "\0__CLASS__", sizeof("\0__CLASS__"), (void**)c) == FAILURE) {
+ zend_hash_add(EG(zend_constants), "\0__CLASS__", sizeof("\0__CLASS__"), (void*)&tmp, sizeof(zend_constant), (void**)c);
+ memset(*c, 0, sizeof(zend_constant));
+ Z_STRVAL((**c).value) = estrndup("", 0);
+ Z_STRLEN((**c).value) = 0;
+ Z_TYPE((**c).value) = IS_STRING;
+ }
+ }
+ return 1;
+ } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
+ !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
+ const char *cfilename;
+ char *haltname;
+ int len, clen;
+
+ cfilename = zend_get_executed_filename(TSRMLS_C);
+ clen = strlen(cfilename);
+ /* check for __COMPILER_HALT_OFFSET__ */
+ zend_mangle_property_name(&haltname, &len, haltoff,
+ sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
+ ret = zend_hash_find(EG(zend_constants), haltname, len+1, (void **) c);
+ efree(haltname);
+ return (ret == SUCCESS);
+ } else {
+ return 0;
+ }
+}
+
ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSRMLS_DC)
{
@@ -237,29 +297,7 @@ ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSR
retval=0;
}
} else {
- static char haltoff[] = "__COMPILER_HALT_OFFSET__";
-
- if (!EG(in_execution)) {
- retval = 0;
- } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__")-1 &&
- !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
- char *cfilename, *haltname;
- int len, clen;
-
- cfilename = zend_get_executed_filename(TSRMLS_C);
- clen = strlen(cfilename);
- /* check for __COMPILER_HALT_OFFSET__ */
- zend_mangle_property_name(&haltname, &len, haltoff,
- sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
- if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) {
- retval = 1;
- } else {
- retval=0;
- }
- pefree(haltname, 0);
- } else {
- retval=0;
- }
+ retval = zend_get_special_constant(name, name_len, &c TSRMLS_CC);
}
efree(lookup_name);
}
@@ -278,7 +316,7 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
{
zend_constant *c;
int retval = 1;
- char *colon;
+ const char *colon;
zend_class_entry *ce = NULL;
char *class_name;
zval **ret_constant;
@@ -294,7 +332,7 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
colon > name && (*(colon - 1) == ':')) {
int class_name_len = colon - name - 1;
int const_name_len = name_len - class_name_len - 2;
- char *constant_name = colon + 1;
+ const char *constant_name = colon + 1;
char *lcname;
class_name = estrndup(name, class_name_len);
@@ -357,7 +395,7 @@ ZEND_API int zend_get_constant_ex(const char *name, uint name_len, zval *result,
/* compound constant name */
int prefix_len = colon - name;
int const_name_len = name_len - prefix_len - 1;
- char *constant_name = colon + 1;
+ const char *constant_name = colon + 1;
char *lcname;
int found_const = 0;
@@ -410,11 +448,44 @@ finish:
return zend_get_constant(name, name_len, result TSRMLS_CC);
}
+zend_constant *zend_quick_get_constant(const zend_literal *key, ulong flags TSRMLS_DC)
+{
+ zend_constant *c;
+
+ if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE) {
+ key++;
+ if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE ||
+ (c->flags & CONST_CS) != 0) {
+ if ((flags & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
+ key++;
+ if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE) {
+ key++;
+ if (zend_hash_quick_find(EG(zend_constants), Z_STRVAL(key->constant), Z_STRLEN(key->constant) + 1, key->hash_value, (void **) &c) == FAILURE ||
+ (c->flags & CONST_CS) != 0) {
+
+ key--;
+ if (!zend_get_special_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) {
+ return NULL;
+ }
+ }
+ }
+ } else {
+ key--;
+ if (!zend_get_special_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) {
+ return NULL;
+ }
+ }
+ }
+ }
+ return c;
+}
+
ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
{
char *lowercase_name = NULL;
char *name;
int ret = SUCCESS;
+ ulong chash = 0;
#if 0
printf("Registering constant for module %d\n", c->module_number);
@@ -424,22 +495,30 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
/* keep in mind that c->name_len already contains the '\0' */
lowercase_name = estrndup(c->name, c->name_len-1);
zend_str_tolower(lowercase_name, c->name_len-1);
+ lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
name = lowercase_name;
+ chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0;
} else {
char *slash = strrchr(c->name, '\\');
if(slash) {
lowercase_name = estrndup(c->name, c->name_len-1);
zend_str_tolower(lowercase_name, slash-c->name);
+ lowercase_name = (char*)zend_new_interned_string(lowercase_name, c->name_len, 1 TSRMLS_CC);
name = lowercase_name;
+
+ chash = IS_INTERNED(lowercase_name) ? INTERNED_HASH(lowercase_name) : 0;
} else {
name = c->name;
}
}
+ if (chash == 0) {
+ chash = zend_hash_func(name, c->name_len);
+ }
/* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */
if ((c->name_len == sizeof("__COMPILER_HALT_OFFSET__")
&& !memcmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1))
- || zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
+ || zend_hash_quick_add(EG(zend_constants), name, c->name_len, chash, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
/* The internal __COMPILER_HALT_OFFSET__ is prefixed by NULL byte */
if (c->name[0] == '\0' && c->name_len > sizeof("\0__COMPILER_HALT_OFFSET__")
@@ -447,13 +526,13 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
name++;
}
zend_error(E_NOTICE,"Constant %s already defined", name);
- free(c->name);
+ str_free(c->name);
if (!(c->flags & CONST_PERSISTENT)) {
zval_dtor(&c->value);
}
ret = FAILURE;
}
- if (lowercase_name) {
+ if (lowercase_name && !IS_INTERNED(lowercase_name)) {
efree(lowercase_name);
}
return ret;