diff options
| author | Dmitry Stogov <dmitry@php.net> | 2012-01-17 08:09:13 +0000 |
|---|---|---|
| committer | Dmitry Stogov <dmitry@php.net> | 2012-01-17 08:09:13 +0000 |
| commit | 032d140fd6f8458e72a8df06618aca13337ef03c (patch) | |
| tree | e4797c5ff1def9150c50e18bfc94fac6d56befee /Zend/zend_constants.c | |
| parent | f32760bd40aa368beeccd8ce53b425b2ebae159c (diff) | |
| download | php-git-032d140fd6f8458e72a8df06618aca13337ef03c.tar.gz | |
Improved traits implementation. Now to support __CLASS__ constant in traits php doesn't have to copy the complete compiled method, but can reuse the same code. The resolution of __CLASS__ constants in methods defined in traits are delayed till run-time. This approach also made possible to use __CLASS__ constant as default value for traits properties and method arguments.
Diffstat (limited to 'Zend/zend_constants.c')
| -rw-r--r-- | Zend/zend_constants.c | 40 |
1 files changed, 36 insertions, 4 deletions
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c index b4fa150ab0..03b6309cc3 100644 --- a/Zend/zend_constants.c +++ b/Zend/zend_constants.c @@ -224,13 +224,45 @@ 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_halt_offset_constant(const char *name, uint name_len, zend_constant **c TSRMLS_DC) +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; @@ -265,7 +297,7 @@ ZEND_API int zend_get_constant(const char *name, uint name_len, zval *result TSR retval=0; } } else { - retval = zend_get_halt_offset_constant(name, name_len, &c TSRMLS_CC); + retval = zend_get_special_constant(name, name_len, &c TSRMLS_CC); } efree(lookup_name); } @@ -432,14 +464,14 @@ zend_constant *zend_quick_get_constant(const zend_literal *key, ulong flags TSRM (c->flags & CONST_CS) != 0) { key--; - if (!zend_get_halt_offset_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) { + if (!zend_get_special_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) { return NULL; } } } } else { key--; - if (!zend_get_halt_offset_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) { + if (!zend_get_special_constant(Z_STRVAL(key->constant), Z_STRLEN(key->constant), &c TSRMLS_CC)) { return NULL; } } |
