1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2007 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,v 1.71.2.5.2.5 2007/04/04 00:42:42 iliaa Exp $ */
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 107904 : {
32 107904 : if (!(c->flags & CONST_PERSISTENT)) {
33 156 : zval_dtor(&c->value);
34 : }
35 107904 : free(c->name);
36 107904 : }
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 369 : {
58 369 : 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 220 : {
86 220 : EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable));
87 :
88 220 : if (zend_hash_init(EG(zend_constants), 20, NULL, ZEND_CONSTANT_DTOR, 1)==FAILURE) {
89 0 : return FAILURE;
90 : }
91 220 : return SUCCESS;
92 : }
93 :
94 :
95 :
96 : void zend_register_standard_constants(TSRMLS_D)
97 220 : {
98 220 : REGISTER_MAIN_LONG_CONSTANT("E_ERROR", E_ERROR, CONST_PERSISTENT | CONST_CS);
99 220 : REGISTER_MAIN_LONG_CONSTANT("E_RECOVERABLE_ERROR", E_RECOVERABLE_ERROR, CONST_PERSISTENT | CONST_CS);
100 220 : REGISTER_MAIN_LONG_CONSTANT("E_WARNING", E_WARNING, CONST_PERSISTENT | CONST_CS);
101 220 : REGISTER_MAIN_LONG_CONSTANT("E_PARSE", E_PARSE, CONST_PERSISTENT | CONST_CS);
102 220 : REGISTER_MAIN_LONG_CONSTANT("E_NOTICE", E_NOTICE, CONST_PERSISTENT | CONST_CS);
103 220 : REGISTER_MAIN_LONG_CONSTANT("E_STRICT", E_STRICT, CONST_PERSISTENT | CONST_CS);
104 220 : REGISTER_MAIN_LONG_CONSTANT("E_CORE_ERROR", E_CORE_ERROR, CONST_PERSISTENT | CONST_CS);
105 220 : REGISTER_MAIN_LONG_CONSTANT("E_CORE_WARNING", E_CORE_WARNING, CONST_PERSISTENT | CONST_CS);
106 220 : REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_ERROR", E_COMPILE_ERROR, CONST_PERSISTENT | CONST_CS);
107 220 : REGISTER_MAIN_LONG_CONSTANT("E_COMPILE_WARNING", E_COMPILE_WARNING, CONST_PERSISTENT | CONST_CS);
108 220 : REGISTER_MAIN_LONG_CONSTANT("E_USER_ERROR", E_USER_ERROR, CONST_PERSISTENT | CONST_CS);
109 220 : REGISTER_MAIN_LONG_CONSTANT("E_USER_WARNING", E_USER_WARNING, CONST_PERSISTENT | CONST_CS);
110 220 : REGISTER_MAIN_LONG_CONSTANT("E_USER_NOTICE", E_USER_NOTICE, CONST_PERSISTENT | CONST_CS);
111 :
112 220 : REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS);
113 :
114 : /* true/false constants */
115 : {
116 : zend_constant c;
117 :
118 220 : c.flags = CONST_PERSISTENT | CONST_CT_SUBST;
119 220 : c.module_number = 0;
120 :
121 220 : c.name = zend_strndup(ZEND_STRL("TRUE"));
122 220 : c.name_len = sizeof("TRUE");
123 220 : c.value.value.lval = 1;
124 220 : c.value.type = IS_BOOL;
125 220 : zend_register_constant(&c TSRMLS_CC);
126 :
127 220 : c.name = zend_strndup(ZEND_STRL("FALSE"));
128 220 : c.name_len = sizeof("FALSE");
129 220 : c.value.value.lval = 0;
130 220 : c.value.type = IS_BOOL;
131 220 : zend_register_constant(&c TSRMLS_CC);
132 :
133 220 : c.name = zend_strndup(ZEND_STRL("NULL"));
134 220 : c.name_len = sizeof("NULL");
135 220 : c.value.type = IS_NULL;
136 220 : zend_register_constant(&c TSRMLS_CC);
137 :
138 220 : c.flags = CONST_PERSISTENT;
139 :
140 220 : c.name = zend_strndup(ZEND_STRL("ZEND_THREAD_SAFE"));
141 220 : c.name_len = sizeof("ZEND_THREAD_SAFE");
142 220 : c.value.value.lval = ZTS_V;
143 220 : c.value.type = IS_BOOL;
144 220 : zend_register_constant(&c TSRMLS_CC);
145 : }
146 220 : }
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 219 : {
159 219 : 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 219 : zend_hash_reverse_apply(EG(zend_constants), (apply_func_t) clean_non_persistent_constant TSRMLS_CC);
163 : }
164 219 : }
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 96146 : {
169 : zend_constant c;
170 :
171 96146 : c.value.type = IS_LONG;
172 96146 : c.value.value.lval = lval;
173 96146 : c.flags = flags;
174 96146 : c.name = zend_strndup(name, name_len-1);
175 96146 : c.name_len = name_len;
176 96146 : c.module_number = module_number;
177 96146 : zend_register_constant(&c TSRMLS_CC);
178 96146 : }
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 4180 : {
183 : zend_constant c;
184 :
185 4180 : c.value.type = IS_DOUBLE;
186 4180 : c.value.value.dval = dval;
187 4180 : c.flags = flags;
188 4180 : c.name = zend_strndup(name, name_len-1);
189 4180 : c.name_len = name_len;
190 4180 : c.module_number = module_number;
191 4180 : zend_register_constant(&c TSRMLS_CC);
192 4180 : }
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 7041 : {
197 : zend_constant c;
198 :
199 7041 : c.value.type = IS_STRING;
200 7041 : c.value.value.str.val = strval;
201 7041 : c.value.value.str.len = strlen;
202 7041 : c.flags = flags;
203 7041 : c.name = zend_strndup(name, name_len-1);
204 7041 : c.name_len = name_len;
205 7041 : c.module_number = module_number;
206 7041 : zend_register_constant(&c TSRMLS_CC);
207 7041 : }
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 3300 : {
212 3300 : zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number TSRMLS_CC);
213 3300 : }
214 :
215 :
216 : ZEND_API int zend_get_constant_ex(char *name, uint name_len, zval *result, zend_class_entry *scope TSRMLS_DC)
217 4356 : {
218 : zend_constant *c;
219 4356 : int retval = 1;
220 : char *lookup_name;
221 : char *colon;
222 :
223 4356 : if ((colon = memchr(name, ':', name_len)) && colon[1] == ':') {
224 : /* class constant */
225 0 : zend_class_entry **ce = NULL;
226 0 : int class_name_len = colon-name;
227 0 : int const_name_len = name_len - class_name_len - 2;
228 0 : char *constant_name = colon+2;
229 : zval **ret_constant;
230 : char *class_name;
231 :
232 0 : if (!scope) {
233 0 : if (EG(in_execution)) {
234 0 : scope = EG(scope);
235 : } else {
236 0 : scope = CG(active_class_entry);
237 : }
238 : }
239 :
240 0 : class_name = estrndup(name, class_name_len);
241 :
242 0 : if (class_name_len == sizeof("self")-1 && strcmp(class_name, "self") == 0) {
243 0 : if (scope) {
244 0 : 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 0 : } else if (class_name_len == sizeof("parent")-1 && strcmp(class_name, "parent") == 0) {
250 0 : if (!scope) {
251 0 : zend_error(E_ERROR, "Cannot access parent:: when no class scope is active");
252 0 : } else if (!scope->parent) {
253 0 : zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent");
254 : } else {
255 0 : ce = &scope->parent;
256 : }
257 : } else {
258 0 : if (zend_lookup_class(class_name, class_name_len, &ce TSRMLS_CC) != SUCCESS) {
259 0 : retval = 0;
260 : }
261 : }
262 0 : efree(class_name);
263 :
264 0 : if (retval && ce) {
265 0 : if (zend_hash_find(&((*ce)->constants_table), constant_name, const_name_len+1, (void **) &ret_constant) != SUCCESS) {
266 0 : retval = 0;
267 : }
268 : } else {
269 0 : retval = 0;
270 : }
271 :
272 0 : if (retval) {
273 0 : zval_update_constant(ret_constant, (void*)1 TSRMLS_CC);
274 0 : *result = **ret_constant;
275 0 : zval_copy_ctor(result);
276 : }
277 :
278 0 : return retval;
279 : }
280 :
281 4356 : if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) {
282 2296 : lookup_name = estrndup(name, name_len);
283 2296 : zend_str_tolower(lookup_name, name_len);
284 :
285 2296 : if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) {
286 0 : if ((c->flags & CONST_CS) && memcmp(c->name, name, name_len)!=0) {
287 0 : retval=0;
288 : }
289 : } else {
290 2296 : char haltoff[] = "__COMPILER_HALT_OFFSET__";
291 2296 : if (!EG(in_execution)) {
292 2188 : retval = 0;
293 108 : } else if (name_len == sizeof("__COMPILER_HALT_OFFSET__") - 1 && memcmp(haltoff, name, name_len) == 0) {
294 : char *cfilename, *haltname;
295 : int len, clen;
296 0 : cfilename = zend_get_executed_filename(TSRMLS_C);
297 0 : clen = strlen(cfilename);
298 : /* check for __COMPILER_HALT_OFFSET__ */
299 0 : zend_mangle_property_name(&haltname, &len, haltoff,
300 : sizeof("__COMPILER_HALT_OFFSET__") - 1, cfilename, clen, 0);
301 0 : if (zend_hash_find(EG(zend_constants), haltname, len+1, (void **) &c) == SUCCESS) {
302 0 : retval = 1;
303 : } else {
304 0 : retval=0;
305 : }
306 0 : pefree(haltname, 0);
307 : } else {
308 108 : retval = 0;
309 : }
310 : }
311 2296 : efree(lookup_name);
312 : }
313 :
314 4356 : if (retval) {
315 2060 : *result = c->value;
316 2060 : zval_copy_ctor(result);
317 2060 : result->refcount = 1;
318 2060 : result->is_ref = 0;
319 : }
320 :
321 4356 : return retval;
322 : }
323 :
324 : ZEND_API int zend_get_constant(char *name, uint name_len, zval *result TSRMLS_DC)
325 4356 : {
326 4356 : return zend_get_constant_ex(name, name_len, result, NULL TSRMLS_CC);
327 : }
328 :
329 : ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC)
330 108396 : {
331 108396 : char *lowercase_name = NULL;
332 : char *name;
333 108396 : int ret = SUCCESS;
334 :
335 : #if 0
336 : printf("Registering constant for module %d\n", c->module_number);
337 : #endif
338 :
339 108396 : if (!(c->flags & CONST_CS)) {
340 : /* keep in mind that c->name_len already contains the '\0' */
341 881 : lowercase_name = estrndup(c->name, c->name_len-1);
342 881 : zend_str_tolower(lowercase_name, c->name_len-1);
343 881 : name = lowercase_name;
344 : } else {
345 107515 : name = c->name;
346 : }
347 :
348 108396 : if ((strncmp(name, "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) ||
349 : zend_hash_add(EG(zend_constants), name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) {
350 0 : zend_error(E_NOTICE,"Constant %s already defined", name);
351 0 : free(c->name);
352 0 : if (!(c->flags & CONST_PERSISTENT)) {
353 0 : zval_dtor(&c->value);
354 : }
355 0 : ret = FAILURE;
356 : }
357 108396 : if (lowercase_name) {
358 881 : efree(lowercase_name);
359 : }
360 108396 : return ret;
361 : }
362 :
363 :
364 : /*
365 : * Local variables:
366 : * tab-width: 4
367 : * c-basic-offset: 4
368 : * indent-tabs-mode: t
369 : * End:
370 : */
|