1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2009 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 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: zend_constants.c 272374 2008-12-31 11:17:49Z sebastian $ */
21 :
22 : #include "zend.h"
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"
28 :
29 :
30 : void free_zend_constant(zend_constant *c)
31 26255914 : {
32 26255914 : if (!(c->flags & CONST_PERSISTENT)) {
33 40898 : zval_dtor(&c->value);
34 : }
35 26255914 : free(c->name);
36 26255914 : }
37 :
38 :
39 : void copy_zend_constant(zend_constant *c)
40 0 : {
41 0 : c->name = zend_strndup(c->name, c->name_len - 1);
42 0 : if (!(c->flags & CONST_PERSISTENT)) {
43 0 : zval_copy_ctor(&c->value);
44 : }
45 0 : }
46 :
47 :
48 : void zend_copy_constants(HashTable *target, HashTable *source)
49 0 : {
50 : zend_constant tmp_constant;
51 :
52 0 : zend_hash_copy(target, source, (copy_ctor_func_t) copy_zend_constant, &tmp_constant, sizeof(zend_constant));
53 0 : }
54 :
55 :
56 : static int clean_non_persistent_constant(zend_constant *c TSRMLS_DC)
57 54309 : {
58 54309 : return (c->flags & CONST_PERSISTENT) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE;
59 : }
60 :
61 :
62 : static int clean_non_persistent_constant_full(zend_constant *c TSRMLS_DC)
63 0 : {
64 0 : return (c->flags & CONST_PERSISTENT) ? 0 : 1;
65 : }
66 :
67 :
68 : static int clean_module_constant(zend_constant *c, int *module_number TSRMLS_DC)
69 0 : {
70 0 : if (c->module_number == *module_number) {
71 0 : return 1;
72 : } else {
73 0 : return 0;
74 : }
75 : }
76 :
77 :
78 : void clean_module_constants(int module_number TSRMLS_DC)
79 0 : {
80 0 : zend_hash_apply_with_argument(EG(zend_constants), (apply_func_arg_t) clean_module_constant, (void *) &module_number TSRMLS_CC);
81 0 : }
82 :
83 :
84 : int zend_startup_constants(TSRMLS_D)
85 13565 : {
86 13565 : EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable));
87 :
88 13565 : if (zend_hash_init(EG(zend_constants), 20, NULL, ZEND_CONSTANT_DTOR, 1)==FAILURE) {
89 0 : return FAILURE;
90 : }
91 13565 : return SUCCESS;
92 : }
93 :
94 :
95 :
96 : void zend_register_standard_constants(TSRMLS_D)
97 13565 : {
98 13565 : REGISTER_MAIN_LONG_CONSTANT("E_ERROR", E_ERROR, CONST_PERSISTENT | CONST_CS);
99 13565 : REGISTER_MAIN_LONG_CONSTANT("E_RECOVERABLE_ERROR", E_RECOVERABLE_ERROR, CONST_PERSISTENT | CONST_CS);
100 13565 : REGISTER_MAIN_LONG_CONSTANT("E_WARNING", E_WARNING, CONST_PERSISTENT | CONST_CS);
101 13565 : REGISTER_MAIN_LONG_CONSTANT("E_PARSE", E_PARSE, CONST_PERSISTENT | CONST_CS);
102 13565 : REGISTER_MAIN_LONG_CONSTANT("E_NOTICE", E_NOTICE, CONST_PERSISTENT | CONST_CS);
103 13565 : REGISTER_MAIN_LONG_CONSTANT("E_STRICT", E_STRICT, CONST_PERSISTENT | CONST_CS);
104 13565 : REGISTER_MAIN_LONG_CONSTANT("E_CORE_ERROR", E_CORE_ERROR, CONST_PERSISTENT | CONST_CS);
105 13565 : REGISTER_MAIN_LONG_CONSTANT("E_CORE_WARNING", E_CORE_WARNING, CONST_PERSISTENT | CONST_CS);
106 13565 : REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_ERROR", E_COMPILE_ERROR, CONST_PERSISTENT | CONST_CS);
107 13565 : REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_WARNING", E_COMPILE_WARNING, CONST_PERSISTENT | CONST_CS);
108 13565 : REGISTER_MAIN_LONG_CONSTANT("E_USER_ERROR", E_USER_ERROR, CONST_PERSISTENT | CONST_CS);
109 13565 : REGISTER_MAIN_LONG_CONSTANT("E_USER_WARNING", E_USER_WARNING, CONST_PERSISTENT | CONST_CS);
110 13565 : REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
111 :
112 13565 : REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
113 :
114 : /* true/false constants */
115 : {
116 : zend_constant c;
117 :
118 13565 : c.flags = CONST_PERSISTENT | CONST_CT_SUBST;
119 13565 : c.module_number = 0;
120 :
121 13565 : c.name = zend_strndup(ZEND_STRL("TRUE"));
122 13565 : c.name_len = sizeof("TRUE");
123 13565 : c.value.value.lval = 1;
124 13565 : c.value.type = IS_BOOL;
125 13565 : zend_register_constant(&c TSRMLS_CC);
126 :
127 13565 : c.name = zend_strndup(ZEND_STRL("FALSE"));
128 13565 : c.name_len = sizeof("FALSE");
129 13565 : c.value.value.lval = 0;
130 13565 : c.value.type = IS_BOOL;
131 13565 : zend_register_constant(&c TSRMLS_CC);
132 :
133 13565 : c.name = zend_strndup(ZEND_STRL("NULL"));
134 13565 : c.name_len = sizeof("NULL");
135 13565 : c.value.type = IS_NULL;
136 13565 : zend_register_constant(&c TSRMLS_CC);
137 :
138 13565 : c.flags = CONST_PERSISTENT;
139 :
140 13565 : c.name = zend_strndup(ZEND_STRL("ZEND_THREAD_SAFE"));
141 13565 : c.name_len = sizeof("ZEND_THREAD_SAFE");
142 13565 : c.value.value.lval = ZTS_V;
143 13565 : c.value.type = IS_BOOL;
144 13565 : zend_register_constant(&c TSRMLS_CC);
145 : }
146 13565 : }
147 :
148 :
149 : int zend_shutdown_constants(TSRMLS_D)
150 0 : {
151 0 : zend_hash_destroy(EG(zend_constants));
152 0 : free(EG(zend_constants));
153 0 : return SUCCESS;
154 : }
155 :
156 :
157 : void clean_non_persistent_constants(TSRMLS_D)
158 13584 : {
159 13584 : if (EG(full_tables_cleanup)) {
160 0 : zend_hash_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant_full TSRMLS_CC);
161 : } else {
162 13584 : zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant TSRMLS_CC);
163 : }
164 13584 : }
165 :
166 :
167 : ZEND_API void zend_register_long_constant(char *name, uint name_len, long lval, int flags, int module_number TSRMLS_DC)
168 24742567 : {
169 : zend_constant c;
170 :
171 24742567 : c.value.type = IS_LONG;
172 24742567 : c.value.value.lval = lval;
173 24742567 : c.flags = flags;
174 24742567 : c.name = zend_strndup(name, name_len-1);
175 24742567 : c.name_len = name_len;
176 24742567 : c.module_number = module_number;
177 24742567 : zend_register_constant(&c TSRMLS_CC);
178 24742567 : }
179 :
180 :
181 : ZEND_API void zend_register_double_constant(char *name, uint name_len, double dval, int flags, int module_number TSRMLS_DC)
182 257735 : {
183 : zend_constant c;
184 :
185 257735 : c.value.type = IS_DOUBLE;
186 257735 : c.value.value.dval = dval;
187 257735 : c.flags = flags;
188 257735 : c.name = zend_strndup(name, name_len-1);
189 257735 : c.name_len = name_len;
190 257735 : c.module_number = module_number;
191 257735 : zend_register_constant(&c TSRMLS_CC);
192 257735 : }
193 :
194 :
195 : ZEND_API void zend_register_stringl_constant(char *name, uint name_len, char *strval, uint strlen, int flags, int module_number TSRMLS_DC)
196 1099076 : {
197 : zend_constant c;
198 :
199 1099076 : c.value.type = IS_STRING;
200 1099076 : c.value.value.str.val = strval;
201 1099076 : c.value.value.str.len = strlen;
202 1099076 : c.flags = flags;
203 1099076 : c.name = zend_strndup(name, name_len-1);
204 1099076 : c.name_len = name_len;
205 1099076 : c.module_number = module_number;
206 1099076 : zend_register_constant(&c TSRMLS_CC);
207 1099076 : }
208 :
209 :
210 : ZEND_API void zend_register_string_constant(char *name, uint name_len, char *strval, int flags, int module_number TSRMLS_DC)
211 854595 : {
212 854595 : zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number TSRMLS_CC);
213 854595 : }
214 :
215 :
216 : ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope TSRMLS_DC)
217 591158 : {
218 : zend_constant *c;
219 591158 : int retval = 1;
220 : char *lookup_name;
221 : char *colon;
222 :
223 591158 : if ((colon = memchr(name, ':', name_len)) && colon[1] == ':') {
224 : /* class constant */
225 90 : zend_class_entry **ce = NULL;
226 90 : int class_name_len = colon-name;
227 90 : int const_name_len = name_len - class_name_len - 2;
228 90 : char *constant_name = colon+2;
229 : zval **ret_constant;
230 : char *class_name;
231 :
232 90 : if (!scope) {
233 76 : if (EG(in_execution)) {
234 76 : scope = EG(scope);
235 : } else {
236 0 : scope = CG(active_class_entry);
237 : }
238 : }
239 :
240 90 : class_name = estrndup(name, class_name_len);
241 :
242 132 : if (class_name_len == sizeof("self")-1 && strcmp(class_name, "self") == 0) {
243 42 : if (scope) {
244 42 : ce = &scope;
245 : } else {
246 0 : zend_error(E_ERROR, "Cannot access self:: when no class scope is active");
247 0 : retval = 0;
248 : }
249 54 : } else if (class_name_len == sizeof("parent")-1 && strcmp(class_name, "parent") == 0) {
250 6 : if (!scope) {
251 0 : zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
252 6 : } else if (!scope->parent) {
253 0 : zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
254 : } else {
255 6 : ce = &scope->parent;
256 : }
257 : } else {
258 42 : if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS) {
259 3 : retval = 0;
260 : }
261 : }
262 :
263 177 : if (retval && ce) {
264 87 : if (zend_hash_find(&((*ce)->constants_table), constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
265 1 : retval = 0;
266 : }
267 : } else {
268 3 : zend_error(E_ERROR, "Class '%s' not found", class_name);
269 0 : retval = 0;
270 : }
271 87 : efree(class_name);
272 :
273 87 : if (retval) {
274 86 : zval_update_constant_ex(ret_constant, (void*)1, *ce TSRMLS_CC);
275 84 : *result = **ret_constant;
276 84 : zval_copy_ctor(result);
277 84 : INIT_PZVAL(result);
278 : }
279 :
280 85 : return retval;
281 : }
282 :
283 591068 : if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) {
284 365432 : lookup_name = estrndup(name, name_len);
285 365432 : zend_str_tolower(lookup_name, name_len);
286 :
287 365432 : if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) {
288 244 : if ((c->flags & CONST_CS) && memcmp(c->name, name, name_len)!=0) {
289 0 : retval=0;
290 : }
291 : } else {
292 365188 : char haltoff[] = "__COMPILER_HALT_OFFSET__";
293 365188 : if (!EG(in_execution)) {
294 365003 : retval = 0;
295 189 : } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__") - 1 && memcmp(haltoff, name, name_len) == 0) {
296 : char *cfilename, *haltname;
297 : int len, clen;
298 4 : cfilename = zend_get_executed_filename(TSRMLS_C);
299 4 : clen = strlen(cfilename);
300 : /* check for __COMPILER_HALT_OFFSET__ */
301 4 : zend_mangle_property_name(&haltname, &len, haltoff,
302 : sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
303 4 : if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) {
304 4 : retval = 1;
305 : } else {
306 0 : retval=0;
307 : }
308 4 : pefree(haltname, 0);
309 : } else {
310 181 : retval = 0;
311 : }
312 : }
313 365432 : efree(lookup_name);
314 : }
315 :
316 591068 : if (retval) {
317 225884 : *result = c->value;
318 225884 : zval_copy_ctor(result);
319 225884 : result->refcount = 1;
320 225884 : result->is_ref = 0;
321 : }
322 :
323 591068 : return retval;
324 : }
325 :
326 : ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC)
327 591038 : {
328 591038 : return zend_get_constant_ex(name, name_len, result, NULL TSRMLS_CC);
329 : }
330 :
331 : ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
332 26194114 : {
333 26194114 : char *lowercase_name = NULL;
334 : char *name;
335 26194114 : int ret = SUCCESS;
336 :
337 : #if 0
338 : printf("Registering constant for module %d\n", c->module_number);
339 : #endif
340 :
341 26194114 : if (!(c->flags & CONST_CS)) {
342 : /* keep in mind that c->name_len already contains the '\0' */
343 610860 : lowercase_name = estrndup(c->name, c->name_len-1);
344 610860 : zend_str_tolower(lowercase_name, c->name_len-1);
345 610860 : name = lowercase_name;
346 : } else {
347 25583254 : name = c->name;
348 : }
349 :
350 26194114 : if ((strncmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) ||
351 : zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
352 4 : zend_error(E_NOTICE,"Constant %s already defined", name);
353 4 : free(c->name);
354 4 : if (!(c->flags & CONST_PERSISTENT)) {
355 4 : zval_dtor(&c->value);
356 : }
357 4 : ret = FAILURE;
358 : }
359 26194114 : if (lowercase_name) {
360 610860 : efree(lowercase_name);
361 : }
362 26194114 : return ret;
363 : }
364 :
365 :
366 : /*
367 : * Local variables:
368 : * tab-width: 4
369 : * c-basic-offset: 4
370 : * indent-tabs-mode: t
371 : * End:
372 : */
|