2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2013 Zend Technologies Ltd. (http://www.zend.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 2.00 of the Zend license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.zend.com/license/2_00.txt. |
11 | If you did not receive a copy of the Zend license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@zend.com so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
15 | Authors: Andi Gutmans <andi@zend.com> |
16 | Zeev Suraski <zeev@zend.com> |
17 +----------------------------------------------------------------------+
23 #include "zend_constants.h"
24 #include "zend_execute.h"
25 #include "zend_variables.h"
26 #include "zend_operators.h"
27 #include "zend_globals.h"
30 void free_zend_constant(zend_constant
*c
)
32 if (!(c
->flags
& CONST_PERSISTENT
)) {
39 void copy_zend_constant(zend_constant
*c
)
41 if (!IS_INTERNED(c
->name
)) {
42 c
->name
= zend_strndup(c
->name
, c
->name_len
- 1);
44 if (!(c
->flags
& CONST_PERSISTENT
)) {
45 zval_copy_ctor(&c
->value
);
50 void zend_copy_constants(HashTable
*target
, HashTable
*source
)
52 zend_constant tmp_constant
;
54 zend_hash_copy(target
, source
, (copy_ctor_func_t
) copy_zend_constant
, &tmp_constant
, sizeof(zend_constant
));
58 static int clean_non_persistent_constant(const zend_constant
*c TSRMLS_DC
)
60 return (c
->flags
& CONST_PERSISTENT
) ? ZEND_HASH_APPLY_STOP
: ZEND_HASH_APPLY_REMOVE
;
64 static int clean_non_persistent_constant_full(const zend_constant
*c TSRMLS_DC
)
66 return (c
->flags
& CONST_PERSISTENT
) ? 0 : 1;
70 static int clean_module_constant(const zend_constant
*c
, int *module_number TSRMLS_DC
)
72 if (c
->module_number
== *module_number
) {
80 void clean_module_constants(int module_number TSRMLS_DC
)
82 zend_hash_apply_with_argument(EG(zend_constants
), (apply_func_arg_t
) clean_module_constant
, (void *) &module_number TSRMLS_CC
);
86 int zend_startup_constants(TSRMLS_D
)
88 EG(zend_constants
) = (HashTable
*) malloc(sizeof(HashTable
));
90 if (zend_hash_init(EG(zend_constants
), 20, NULL
, ZEND_CONSTANT_DTOR
, 1)==FAILURE
) {
98 void zend_register_standard_constants(TSRMLS_D
)
100 REGISTER_MAIN_LONG_CONSTANT("E_ERROR", E_ERROR
, CONST_PERSISTENT
| CONST_CS
);
101 REGISTER_MAIN_LONG_CONSTANT("E_RECOVERABLE_ERROR", E_RECOVERABLE_ERROR
, CONST_PERSISTENT
| CONST_CS
);
102 REGISTER_MAIN_LONG_CONSTANT("E_WARNING", E_WARNING
, CONST_PERSISTENT
| CONST_CS
);
103 REGISTER_MAIN_LONG_CONSTANT("E_PARSE", E_PARSE
, CONST_PERSISTENT
| CONST_CS
);
104 REGISTER_MAIN_LONG_CONSTANT("E_NOTICE", E_NOTICE
, CONST_PERSISTENT
| CONST_CS
);
105 REGISTER_MAIN_LONG_CONSTANT("E_STRICT", E_STRICT
, CONST_PERSISTENT
| CONST_CS
);
106 REGISTER_MAIN_LONG_CONSTANT("E_DEPRECATED", E_DEPRECATED
, CONST_PERSISTENT
| CONST_CS
);
107 REGISTER_MAIN_LONG_CONSTANT("E_CORE_ERROR", E_CORE_ERROR
, CONST_PERSISTENT
| CONST_CS
);
108 REGISTER_MAIN_LONG_CONSTANT("E_CORE_WARNING", E_CORE_WARNING
, CONST_PERSISTENT
| CONST_CS
);
109 REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_ERROR", E_COMPILE_ERROR
, CONST_PERSISTENT
| CONST_CS
);
110 REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_WARNING", E_COMPILE_WARNING
, CONST_PERSISTENT
| CONST_CS
);
111 REGISTER_MAIN_LONG_CONSTANT("E_USER_ERROR", E_USER_ERROR
, CONST_PERSISTENT
| CONST_CS
);
112 REGISTER_MAIN_LONG_CONSTANT("E_USER_WARNING", E_USER_WARNING
, CONST_PERSISTENT
| CONST_CS
);
113 REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE
, CONST_PERSISTENT
| CONST_CS
);
114 REGISTER_MAIN_LONG_CONSTANT("E_USER_DEPRECATED", E_USER_DEPRECATED
, CONST_PERSISTENT
| CONST_CS
);
116 REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL
, CONST_PERSISTENT
| CONST_CS
);
118 REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_PROVIDE_OBJECT", DEBUG_BACKTRACE_PROVIDE_OBJECT
, CONST_PERSISTENT
| CONST_CS
);
119 REGISTER_MAIN_LONG_CONSTANT("DEBUG_BACKTRACE_IGNORE_ARGS", DEBUG_BACKTRACE_IGNORE_ARGS
, CONST_PERSISTENT
| CONST_CS
);
120 /* true/false constants */
124 c
.flags
= CONST_PERSISTENT
| CONST_CT_SUBST
;
127 c
.name
= zend_strndup(ZEND_STRL("TRUE"));
128 c
.name_len
= sizeof("TRUE");
129 c
.value
.value
.lval
= 1;
130 c
.value
.type
= IS_BOOL
;
131 zend_register_constant(&c TSRMLS_CC
);
133 c
.name
= zend_strndup(ZEND_STRL("FALSE"));
134 c
.name_len
= sizeof("FALSE");
135 c
.value
.value
.lval
= 0;
136 c
.value
.type
= IS_BOOL
;
137 zend_register_constant(&c TSRMLS_CC
);
139 c
.name
= zend_strndup(ZEND_STRL("NULL"));
140 c
.name_len
= sizeof("NULL");
141 c
.value
.type
= IS_NULL
;
142 zend_register_constant(&c TSRMLS_CC
);
144 c
.flags
= CONST_PERSISTENT
| CONST_CS
;
146 c
.name
= zend_strndup(ZEND_STRL("ZEND_THREAD_SAFE"));
147 c
.name_len
= sizeof("ZEND_THREAD_SAFE");
148 c
.value
.value
.lval
= ZTS_V
;
149 c
.value
.type
= IS_BOOL
;
150 zend_register_constant(&c TSRMLS_CC
);
152 c
.name
= zend_strndup(ZEND_STRL("ZEND_DEBUG_BUILD"));
153 c
.name_len
= sizeof("ZEND_DEBUG_BUILD");
154 c
.value
.value
.lval
= ZEND_DEBUG
;
155 c
.value
.type
= IS_BOOL
;
156 zend_register_constant(&c TSRMLS_CC
);
161 int zend_shutdown_constants(TSRMLS_D
)
163 zend_hash_destroy(EG(zend_constants
));
164 free(EG(zend_constants
));
169 void clean_non_persistent_constants(TSRMLS_D
)
171 if (EG(full_tables_cleanup
)) {
172 zend_hash_apply(EG(zend_constants
), (apply_func_t
) clean_non_persistent_constant_full TSRMLS_CC
);
174 zend_hash_reverse_apply(EG(zend_constants
), (apply_func_t
) clean_non_persistent_constant TSRMLS_CC
);
179 ZEND_API
void zend_register_long_constant(const char *name
, uint name_len
, long lval
, int flags
, int module_number TSRMLS_DC
)
183 c
.value
.type
= IS_LONG
;
184 c
.value
.value
.lval
= lval
;
186 c
.name
= zend_strndup(name
, name_len
-1);
187 c
.name_len
= name_len
;
188 c
.module_number
= module_number
;
189 zend_register_constant(&c TSRMLS_CC
);
193 ZEND_API
void zend_register_double_constant(const char *name
, uint name_len
, double dval
, int flags
, int module_number TSRMLS_DC
)
197 c
.value
.type
= IS_DOUBLE
;
198 c
.value
.value
.dval
= dval
;
200 c
.name
= zend_strndup(name
, name_len
-1);
201 c
.name_len
= name_len
;
202 c
.module_number
= module_number
;
203 zend_register_constant(&c TSRMLS_CC
);
207 ZEND_API
void zend_register_stringl_constant(const char *name
, uint name_len
, char *strval
, uint strlen
, int flags
, int module_number TSRMLS_DC
)
211 c
.value
.type
= IS_STRING
;
212 c
.value
.value
.str
.val
= strval
;
213 c
.value
.value
.str
.len
= strlen
;
215 c
.name
= zend_strndup(name
, name_len
-1);
216 c
.name_len
= name_len
;
217 c
.module_number
= module_number
;
218 zend_register_constant(&c TSRMLS_CC
);
222 ZEND_API
void zend_register_string_constant(const char *name
, uint name_len
, char *strval
, int flags
, int module_number TSRMLS_DC
)
224 zend_register_stringl_constant(name
, name_len
, strval
, strlen(strval
), flags
, module_number TSRMLS_CC
);
227 static int zend_get_special_constant(const char *name
, uint name_len
, zend_constant
**c TSRMLS_DC
)
230 static char haltoff
[] = "__COMPILER_HALT_OFFSET__";
232 if (!EG(in_execution
)) {
234 } else if (name_len
== sizeof("__CLASS__")-1 &&
235 !memcmp(name
, "__CLASS__", sizeof("__CLASS__")-1)) {
238 /* Returned constants may be cached, so they have to be stored */
239 if (EG(scope
) && EG(scope
)->name
) {
242 ALLOCA_FLAG(use_heap
)
244 const_name_len
= sizeof("\0__CLASS__") + EG(scope
)->name_length
;
245 const_name
= do_alloca(const_name_len
, use_heap
);
246 memcpy(const_name
, "\0__CLASS__", sizeof("\0__CLASS__")-1);
247 zend_str_tolower_copy(const_name
+ sizeof("\0__CLASS__")-1, EG(scope
)->name
, EG(scope
)->name_length
);
248 if (zend_hash_find(EG(zend_constants
), const_name
, const_name_len
, (void**)c
) == FAILURE
) {
249 zend_hash_add(EG(zend_constants
), const_name
, const_name_len
, (void*)&tmp
, sizeof(zend_constant
), (void**)c
);
250 memset(*c
, 0, sizeof(zend_constant
));
251 Z_STRVAL((**c
).value
) = estrndup(EG(scope
)->name
, EG(scope
)->name_length
);
252 Z_STRLEN((**c
).value
) = EG(scope
)->name_length
;
253 Z_TYPE((**c
).value
) = IS_STRING
;
255 free_alloca(const_name
, use_heap
);
257 if (zend_hash_find(EG(zend_constants
), "\0__CLASS__", sizeof("\0__CLASS__"), (void**)c
) == FAILURE
) {
258 zend_hash_add(EG(zend_constants
), "\0__CLASS__", sizeof("\0__CLASS__"), (void*)&tmp
, sizeof(zend_constant
), (void**)c
);
259 memset(*c
, 0, sizeof(zend_constant
));
260 Z_STRVAL((**c
).value
) = estrndup("", 0);
261 Z_STRLEN((**c
).value
) = 0;
262 Z_TYPE((**c
).value
) = IS_STRING
;
266 } else if (name_len
== sizeof("__COMPILER_HALT_OFFSET__")-1 &&
267 !memcmp(name
, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1)) {
268 const char *cfilename
;
272 cfilename
= zend_get_executed_filename(TSRMLS_C
);
273 clen
= strlen(cfilename
);
274 /* check for __COMPILER_HALT_OFFSET__ */
275 zend_mangle_property_name(&haltname
, &len
, haltoff
,
276 sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename
, clen
, 0);
277 ret
= zend_hash_find(EG(zend_constants
), haltname
, len
+1, (void **) c
);
279 return (ret
== SUCCESS
);
286 ZEND_API
int zend_get_constant(const char *name
, uint name_len
, zval
*result TSRMLS_DC
)
292 if (zend_hash_find(EG(zend_constants
), name
, name_len
+1, (void **) &c
) == FAILURE
) {
293 lookup_name
= zend_str_tolower_dup(name
, name_len
);
295 if (zend_hash_find(EG(zend_constants
), lookup_name
, name_len
+1, (void **) &c
)==SUCCESS
) {
296 if (c
->flags
& CONST_CS
) {
300 retval
= zend_get_special_constant(name
, name_len
, &c TSRMLS_CC
);
307 zval_copy_ctor(result
);
308 Z_SET_REFCOUNT_P(result
, 1);
309 Z_UNSET_ISREF_P(result
);
315 ZEND_API
int zend_get_constant_ex(const char *name
, uint name_len
, zval
*result
, zend_class_entry
*scope
, ulong flags TSRMLS_DC
)
320 zend_class_entry
*ce
= NULL
;
324 /* Skip leading \\ */
325 if (name
[0] == '\\') {
331 if ((colon
= zend_memrchr(name
, ':', name_len
)) &&
332 colon
> name
&& (*(colon
- 1) == ':')) {
333 int class_name_len
= colon
- name
- 1;
334 int const_name_len
= name_len
- class_name_len
- 2;
335 const char *constant_name
= colon
+ 1;
338 class_name
= estrndup(name
, class_name_len
);
339 lcname
= zend_str_tolower_dup(class_name
, class_name_len
);
341 if (EG(in_execution
)) {
344 scope
= CG(active_class_entry
);
348 if (class_name_len
== sizeof("self")-1 &&
349 !memcmp(lcname
, "self", sizeof("self")-1)) {
353 zend_error(E_ERROR
, "Cannot access self:: when no class scope is active");
357 } else if (class_name_len
== sizeof("parent")-1 &&
358 !memcmp(lcname
, "parent", sizeof("parent")-1)) {
360 zend_error(E_ERROR
, "Cannot access parent:: when no class scope is active");
361 } else if (!scope
->parent
) {
362 zend_error(E_ERROR
, "Cannot access parent:: when current class scope has no parent");
367 } else if (class_name_len
== sizeof("static")-1 &&
368 !memcmp(lcname
, "static", sizeof("static")-1)) {
369 if (EG(called_scope
)) {
370 ce
= EG(called_scope
);
372 zend_error(E_ERROR
, "Cannot access static:: when no class scope is active");
377 ce
= zend_fetch_class(class_name
, class_name_len
, flags TSRMLS_CC
);
380 if (zend_hash_find(&ce
->constants_table
, constant_name
, const_name_len
+1, (void **) &ret_constant
) != SUCCESS
) {
382 if ((flags
& ZEND_FETCH_CLASS_SILENT
) == 0) {
383 zend_error(E_ERROR
, "Undefined class constant '%s::%s'", class_name
, constant_name
);
393 /* non-class constant */
394 if ((colon
= zend_memrchr(name
, '\\', name_len
)) != NULL
) {
395 /* compound constant name */
396 int prefix_len
= colon
- name
;
397 int const_name_len
= name_len
- prefix_len
- 1;
398 const char *constant_name
= colon
+ 1;
402 lcname
= zend_str_tolower_dup(name
, prefix_len
);
403 /* Check for namespace constant */
405 /* Concatenate lowercase namespace name and constant name */
406 lcname
= erealloc(lcname
, prefix_len
+ 1 + const_name_len
+ 1);
407 lcname
[prefix_len
] = '\\';
408 memcpy(lcname
+ prefix_len
+ 1, constant_name
, const_name_len
+ 1);
410 if (zend_hash_find(EG(zend_constants
), lcname
, prefix_len
+ 1 + const_name_len
+ 1, (void **) &c
) == SUCCESS
) {
414 zend_str_tolower(lcname
+ prefix_len
+ 1, const_name_len
);
415 if (zend_hash_find(EG(zend_constants
), lcname
, prefix_len
+ 1 + const_name_len
+ 1, (void **) &c
) == SUCCESS
) {
416 if ((c
->flags
& CONST_CS
) == 0) {
424 zval_update_constant_ex(&result
, (void*)1, NULL TSRMLS_CC
);
425 zval_copy_ctor(result
);
426 Z_SET_REFCOUNT_P(result
, 1);
427 Z_UNSET_ISREF_P(result
);
430 /* name requires runtime resolution, need to check non-namespaced name */
431 if ((flags
& IS_CONSTANT_UNQUALIFIED
) != 0) {
432 name
= constant_name
;
433 name_len
= const_name_len
;
434 return zend_get_constant(name
, name_len
, result TSRMLS_CC
);
439 zval_update_constant_ex(ret_constant
, (void*)1, ce TSRMLS_CC
);
440 *result
= **ret_constant
;
441 zval_copy_ctor(result
);
448 return zend_get_constant(name
, name_len
, result TSRMLS_CC
);
451 zend_constant
*zend_quick_get_constant(const zend_literal
*key
, ulong flags TSRMLS_DC
)
455 if (zend_hash_quick_find(EG(zend_constants
), Z_STRVAL(key
->constant
), Z_STRLEN(key
->constant
) + 1, key
->hash_value
, (void **) &c
) == FAILURE
) {
457 if (zend_hash_quick_find(EG(zend_constants
), Z_STRVAL(key
->constant
), Z_STRLEN(key
->constant
) + 1, key
->hash_value
, (void **) &c
) == FAILURE
||
458 (c
->flags
& CONST_CS
) != 0) {
459 if ((flags
& (IS_CONSTANT_IN_NAMESPACE
|IS_CONSTANT_UNQUALIFIED
)) == (IS_CONSTANT_IN_NAMESPACE
|IS_CONSTANT_UNQUALIFIED
)) {
461 if (zend_hash_quick_find(EG(zend_constants
), Z_STRVAL(key
->constant
), Z_STRLEN(key
->constant
) + 1, key
->hash_value
, (void **) &c
) == FAILURE
) {
463 if (zend_hash_quick_find(EG(zend_constants
), Z_STRVAL(key
->constant
), Z_STRLEN(key
->constant
) + 1, key
->hash_value
, (void **) &c
) == FAILURE
||
464 (c
->flags
& CONST_CS
) != 0) {
467 if (!zend_get_special_constant(Z_STRVAL(key
->constant
), Z_STRLEN(key
->constant
), &c TSRMLS_CC
)) {
474 if (!zend_get_special_constant(Z_STRVAL(key
->constant
), Z_STRLEN(key
->constant
), &c TSRMLS_CC
)) {
483 ZEND_API
int zend_register_constant(zend_constant
*c TSRMLS_DC
)
485 char *lowercase_name
= NULL
;
491 printf("Registering constant for module %d\n", c
->module_number
);
494 if (!(c
->flags
& CONST_CS
)) {
495 /* keep in mind that c->name_len already contains the '\0' */
496 lowercase_name
= estrndup(c
->name
, c
->name_len
-1);
497 zend_str_tolower(lowercase_name
, c
->name_len
-1);
498 lowercase_name
= (char*)zend_new_interned_string(lowercase_name
, c
->name_len
, 1 TSRMLS_CC
);
499 name
= lowercase_name
;
500 chash
= IS_INTERNED(lowercase_name
) ? INTERNED_HASH(lowercase_name
) : 0;
502 char *slash
= strrchr(c
->name
, '\\');
504 lowercase_name
= estrndup(c
->name
, c
->name_len
-1);
505 zend_str_tolower(lowercase_name
, slash
-c
->name
);
506 lowercase_name
= (char*)zend_new_interned_string(lowercase_name
, c
->name_len
, 1 TSRMLS_CC
);
507 name
= lowercase_name
;
509 chash
= IS_INTERNED(lowercase_name
) ? INTERNED_HASH(lowercase_name
) : 0;
515 chash
= zend_hash_func(name
, c
->name_len
);
518 /* Check if the user is trying to define the internal pseudo constant name __COMPILER_HALT_OFFSET__ */
519 if ((c
->name_len
== sizeof("__COMPILER_HALT_OFFSET__")
520 && !memcmp(name
, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__")-1))
521 || zend_hash_quick_add(EG(zend_constants
), name
, c
->name_len
, chash
, (void *) c
, sizeof(zend_constant
), NULL
)==FAILURE
) {
523 /* The internal __COMPILER_HALT_OFFSET__ is prefixed by NULL byte */
524 if (c
->name
[0] == '\0' && c
->name_len
> sizeof("\0__COMPILER_HALT_OFFSET__")
525 && memcmp(name
, "\0__COMPILER_HALT_OFFSET__", sizeof("\0__COMPILER_HALT_OFFSET__")) == 0) {
528 zend_error(E_NOTICE
,"Constant %s already defined", name
);
530 if (!(c
->flags
& CONST_PERSISTENT
)) {
531 zval_dtor(&c
->value
);
535 if (lowercase_name
&& !IS_INTERNED(lowercase_name
)) {
536 efree(lowercase_name
);
546 * indent-tabs-mode: t