zend.c (4c283fff) zend.c (6535933f)
1/*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2004 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$ */
21
22#include "zend.h"
23#include "zend_extensions.h"
24#include "zend_modules.h"
25#include "zend_constants.h"
26#include "zend_list.h"
27#include "zend_API.h"
28#include "zend_exceptions.h"
29#include "zend_builtin_functions.h"
30#include "zend_ini.h"
31
32#ifdef ZTS
33# define GLOBAL_FUNCTION_TABLE global_function_table
34# define GLOBAL_CLASS_TABLE global_class_table
35# define GLOBAL_CONSTANTS_TABLE global_constants_table
36# define GLOBAL_AUTO_GLOBALS_TABLE global_auto_globals_table
37#else
38# define GLOBAL_FUNCTION_TABLE CG(function_table)
39# define GLOBAL_CLASS_TABLE CG(class_table)
40# define GLOBAL_AUTO_GLOBALS_TABLE CG(auto_globals)
41#endif
42
43#if defined(ZEND_WIN32) && ZEND_DEBUG
44BOOL WINAPI IsDebuggerPresent(VOID);
45#endif
46
47/* true multithread-shared globals */
48ZEND_API zend_class_entry *zend_standard_class_def = NULL;
49ZEND_API int (*zend_printf)(const char *format, ...);
50ZEND_API zend_write_func_t zend_write;
51ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path);
52ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
53ZEND_API void (*zend_block_interruptions)(void);
54ZEND_API void (*zend_unblock_interruptions)(void);
55ZEND_API void (*zend_ticks_function)(int ticks);
56ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
57int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
58
59void (*zend_on_timeout)(int seconds TSRMLS_DC);
60
61static void (*zend_message_dispatcher_p)(long message, void *data);
62static int (*zend_get_configuration_directive_p)(char *name, uint name_length, zval *contents);
63
64
65static ZEND_INI_MH(OnUpdateErrorReporting)
66{
67 if (!new_value) {
68 EG(error_reporting) = E_ALL & ~E_NOTICE & ~E_STRICT;
69 } else {
70 EG(error_reporting) = atoi(new_value);
71 }
72 return SUCCESS;
73}
74
75
76ZEND_INI_BEGIN()
77 ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
78 STD_ZEND_INI_BOOLEAN("zend.ze1_compatibility_mode", "0", ZEND_INI_ALL, OnUpdateBool, ze1_compatibility_mode, zend_executor_globals, executor_globals)
79ZEND_INI_END()
80
81
82#ifdef ZTS
83ZEND_API int compiler_globals_id;
84ZEND_API int executor_globals_id;
85ZEND_API int alloc_globals_id;
86zend_class_entry global_main_class;
87HashTable *global_function_table;
88HashTable *global_class_table;
89HashTable *global_constants_table;
90HashTable *global_auto_globals_table;
91#endif
92
93ZEND_API zend_utility_values zend_uv;
94
95ZEND_API zval zval_used_for_init; /* True global variable */
96
97/* version information */
98static char *zend_version_info;
99static uint zend_version_info_length;
100#define ZEND_CORE_VERSION_INFO "Zend Engine v" ZEND_VERSION ", Copyright (c) 1998-2004 Zend Technologies\n"
101
102
103#define PRINT_ZVAL_INDENT 4
104
105static void print_hash(HashTable *ht, int indent, zend_bool is_object TSRMLS_DC)
106{
107 zval **tmp;
108 char *string_key;
109 HashPosition iterator;
110 ulong num_key;
111 uint str_len;
112 int i;
113
114 for (i=0; i<indent; i++) {
115 ZEND_PUTS(" ");
116 }
117 ZEND_PUTS("(\n");
118 indent += PRINT_ZVAL_INDENT;
119 zend_hash_internal_pointer_reset_ex(ht, &iterator);
120 while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) {
121 for (i=0; i<indent; i++) {
122 ZEND_PUTS(" ");
123 }
124 ZEND_PUTS("[");
125 switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) {
126 case HASH_KEY_IS_STRING:
127 if (is_object) {
128 char *prop_name, *class_name;
129
130 zend_unmangle_property_name(string_key, &class_name, &prop_name);
131 ZEND_PUTS(prop_name);
132 if (class_name) {
133 if (class_name[0]=='*') {
134 ZEND_PUTS(":protected");
135 } else {
136 ZEND_PUTS(":private");
137 }
138 }
139 } else {
140 ZEND_WRITE(string_key, str_len-1);
141 }
142 break;
143 case HASH_KEY_IS_LONG:
144 zend_printf("%ld", num_key);
145 break;
146 }
147 ZEND_PUTS("] => ");
148 zend_print_zval_r(*tmp, indent+PRINT_ZVAL_INDENT TSRMLS_CC);
149 ZEND_PUTS("\n");
150 zend_hash_move_forward_ex(ht, &iterator);
151 }
152 indent -= PRINT_ZVAL_INDENT;
153 for (i=0; i<indent; i++) {
154 ZEND_PUTS(" ");
155 }
156 ZEND_PUTS(")\n");
157}
158
159static void print_flat_hash(HashTable *ht TSRMLS_DC)
160{
161 zval **tmp;
162 char *string_key;
163 HashPosition iterator;
164 ulong num_key;
165 uint str_len;
166 int i = 0;
167
168 zend_hash_internal_pointer_reset_ex(ht, &iterator);
169 while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) {
170 if (i++ > 0) {
171 ZEND_PUTS(",");
172 }
173 ZEND_PUTS("[");
174 switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) {
175 case HASH_KEY_IS_STRING:
176 ZEND_PUTS(string_key);
177 break;
178 case HASH_KEY_IS_LONG:
179 zend_printf("%ld", num_key);
180 break;
181 }
182 ZEND_PUTS("] => ");
183 zend_print_flat_zval_r(*tmp TSRMLS_CC);
184 zend_hash_move_forward_ex(ht, &iterator);
185 }
186}
187
188ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy)
189{
190 if (expr->type==IS_STRING) {
191 *use_copy = 0;
192 return;
193 }
194 switch (expr->type) {
195 case IS_NULL:
196 expr_copy->value.str.len = 0;
197 expr_copy->value.str.val = empty_string;
198 break;
199 case IS_BOOL:
200 if (expr->value.lval) {
201 expr_copy->value.str.len = 1;
202 expr_copy->value.str.val = estrndup("1", 1);
203 } else {
204 expr_copy->value.str.len = 0;
205 expr_copy->value.str.val = empty_string;
206 }
207 break;
208 case IS_RESOURCE:
209 expr_copy->value.str.val = (char *) emalloc(sizeof("Resource id #")-1 + MAX_LENGTH_OF_LONG);
210 expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Resource id #%ld", expr->value.lval);
211 break;
212 case IS_ARRAY:
213 expr_copy->value.str.len = sizeof("Array")-1;
214 expr_copy->value.str.val = estrndup("Array", expr_copy->value.str.len);
215 break;
216 case IS_OBJECT:
217 {
218 TSRMLS_FETCH();
219 /* Standard PHP objects */
220 if (expr->value.obj.handlers == &std_object_handlers) {
221 if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
222 break;
223 }
224 zend_error(E_NOTICE, "Object of class %s could not be converted to string", Z_OBJCE_P(expr)->name);
225 }
226 if (expr->value.obj.handlers->cast_object &&
227 expr->value.obj.handlers->cast_object(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
228 break;
229 }
230 if (EG(exception)) {
231 zval_dtor(expr_copy);
232 expr_copy->value.str.len = 0;
233 expr_copy->value.str.val = empty_string;
234 break;
235 }
236 }
237 expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG);
238 expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle);
239 break;
240 case IS_DOUBLE:
241 *expr_copy = *expr;
242 zval_copy_ctor(expr_copy);
243 zend_locale_sprintf_double(expr_copy ZEND_FILE_LINE_CC);
244 break;
245 default:
246 *expr_copy = *expr;
247 zval_copy_ctor(expr_copy);
248 convert_to_string(expr_copy);
249 break;
250 }
251 expr_copy->type = IS_STRING;
252 *use_copy = 1;
253}
254
255
256ZEND_API int zend_print_zval(zval *expr, int indent)
257{
258 return zend_print_zval_ex(zend_write, expr, indent);
259}
260
261
262ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent)
263{
264 zval expr_copy;
265 int use_copy;
266
267 zend_make_printable_zval(expr, &expr_copy, &use_copy);
268 if (use_copy) {
269 expr = &expr_copy;
270 }
271 if (expr->value.str.len==0) { /* optimize away empty strings */
272 if (use_copy) {
273 zval_dtor(expr);
274 }
275 return 0;
276 }
277 write_func(expr->value.str.val, expr->value.str.len);
278 if (use_copy) {
279 zval_dtor(expr);
280 }
281 return expr->value.str.len;
282}
283
284ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC)
285{
286 switch (expr->type) {
287 case IS_ARRAY:
288 ZEND_PUTS("Array (");
289 if (++expr->value.ht->nApplyCount>1) {
290 ZEND_PUTS(" *RECURSION*");
291 expr->value.ht->nApplyCount--;
292 return;
293 }
294 print_flat_hash(expr->value.ht TSRMLS_CC);
295 ZEND_PUTS(")");
296 expr->value.ht->nApplyCount--;
297 break;
298 case IS_OBJECT:
299 {
300 HashTable *properties = NULL;
301 char *class_name = NULL;
302 zend_uint clen;
303
304 if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
305 Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
306 }
307 zend_printf("%s Object (", class_name?class_name:"Unknown Class");
308 if (class_name) {
309 efree(class_name);
310 }
311 if (Z_OBJ_HANDLER_P(expr, get_properties)) {
312 properties = Z_OBJPROP_P(expr);
313 }
314 if (properties) {
315 if (++properties->nApplyCount>1) {
316 ZEND_PUTS(" *RECURSION*");
317 properties->nApplyCount--;
318 return;
319 }
320 print_flat_hash(properties TSRMLS_CC);
321 properties->nApplyCount--;
322 }
323 ZEND_PUTS(")");
324 break;
325 }
326 default:
327 zend_print_variable(expr);
328 break;
329 }
330}
331
332ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC)
333{
334 zend_print_zval_r_ex(zend_write, expr, indent TSRMLS_CC);
335}
336
337
338ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC)
339{
340 switch (expr->type) {
341 case IS_ARRAY:
342 ZEND_PUTS("Array\n");
343 if (++expr->value.ht->nApplyCount>1) {
344 ZEND_PUTS(" *RECURSION*");
345 expr->value.ht->nApplyCount--;
346 return;
347 }
348 print_hash(expr->value.ht, indent, 0 TSRMLS_CC);
349 expr->value.ht->nApplyCount--;
350 break;
351 case IS_OBJECT:
352 {
353 HashTable *properties = NULL;
354 char *class_name = NULL;
355 zend_uint clen;
356
357 if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
358 Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
359 }
360 zend_printf("%s Object\n", class_name?class_name:"Unknown Class");
361 if (class_name) {
362 efree(class_name);
363 }
364 if (Z_OBJ_HANDLER_P(expr, get_properties)) {
365 properties = Z_OBJPROP_P(expr);
366 }
367 if (properties) {
368 if (++properties->nApplyCount>1) {
369 ZEND_PUTS(" *RECURSION*");
370 properties->nApplyCount--;
371 return;
372 }
373 print_hash(properties, indent, 1 TSRMLS_CC);
374 properties->nApplyCount--;
375 }
376 break;
377 }
378 default:
379 zend_print_variable(expr);
380 break;
381 }
382}
383
384
385static FILE *zend_fopen_wrapper(const char *filename, char **opened_path)
386{
387 if (opened_path) {
388 *opened_path = estrdup(filename);
389 }
390 return fopen(filename, "rb");
391}
392
393
394static void register_standard_class(TSRMLS_D)
395{
396 zend_standard_class_def = malloc(sizeof(zend_class_entry));
397
398 zend_standard_class_def->type = ZEND_INTERNAL_CLASS;
399 zend_standard_class_def->name_length = sizeof("stdClass") - 1;
400 zend_standard_class_def->name = zend_strndup("stdClass", zend_standard_class_def->name_length);
401 zend_initialize_class_data(zend_standard_class_def, 1 TSRMLS_CC);
402
403 zend_hash_add(CG(class_table), "stdclass", sizeof("stdclass"), &zend_standard_class_def, sizeof(zend_class_entry *), NULL);
404}
405
406static void zend_set_default_compile_time_values(TSRMLS_D)
407{
408 /* default compile-time values */
409 CG(asp_tags) = 0;
410 CG(short_tags) = 1;
411 CG(allow_call_time_pass_reference) = 1;
412 CG(extended_info) = 0;
413}
414
415
416#ifdef ZTS
417static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS_DC)
418{
419 zend_function tmp_func;
420 zend_class_entry tmp_class;
421
422 compiler_globals->compiled_filename = NULL;
423
424 compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable));
425 zend_hash_init_ex(compiler_globals->function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
426 zend_hash_copy(compiler_globals->function_table, global_function_table, NULL, &tmp_func, sizeof(zend_function));
427
428 compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable));
429 zend_hash_init_ex(compiler_globals->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
430 zend_hash_copy(compiler_globals->class_table, global_class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry));
431
432 zend_set_default_compile_time_values(TSRMLS_C);
433
434 CG(interactive) = 0;
435
436 compiler_globals->auto_globals = (HashTable *) malloc(sizeof(HashTable));
437 zend_hash_init_ex(compiler_globals->auto_globals, 8, NULL, NULL, 1, 0);
438 zend_hash_copy(compiler_globals->auto_globals, global_auto_globals_table, NULL, NULL, sizeof(zend_auto_global) /* empty element */);
439}
440
441
442static void compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS_DC)
443{
444 if (compiler_globals->function_table != GLOBAL_FUNCTION_TABLE) {
445 zend_hash_destroy(compiler_globals->function_table);
446 free(compiler_globals->function_table);
447 }
448 if (compiler_globals->class_table != GLOBAL_CLASS_TABLE) {
449 zend_hash_destroy(compiler_globals->class_table);
450 free(compiler_globals->class_table);
451 }
452 if (compiler_globals->auto_globals != GLOBAL_AUTO_GLOBALS_TABLE) {
453 zend_hash_destroy(compiler_globals->auto_globals);
454 free(compiler_globals->auto_globals);
455 }
456}
457
458
459static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS_DC)
460{
461 zend_startup_constants(TSRMLS_C);
462 zend_copy_constants(EG(zend_constants), GLOBAL_CONSTANTS_TABLE);
463 zend_init_rsrc_plist(TSRMLS_C);
464 EG(lambda_count)=0;
465 EG(user_error_handler) = NULL;
466 EG(user_exception_handler) = NULL;
467 EG(in_execution) = 0;
468 EG(in_autoload) = 0;
469 EG(current_execute_data) = NULL;
470}
471
472
473static void executor_globals_dtor(zend_executor_globals *executor_globals TSRMLS_DC)
474{
475 zend_ini_shutdown(TSRMLS_C);
476}
477
478
479static void zend_new_thread_end_handler(THREAD_T thread_id TSRMLS_DC)
480{
481 zend_copy_ini_directives(TSRMLS_C);
482 zend_ini_refresh_caches(ZEND_INI_STAGE_STARTUP TSRMLS_CC);
483}
484
485#endif
486
487
488static void alloc_globals_ctor(zend_alloc_globals *alloc_globals_p TSRMLS_DC)
489{
490 start_memory_manager(TSRMLS_C);
491}
492
493
494#ifdef ZTS
495static void alloc_globals_dtor(zend_alloc_globals *alloc_globals_p TSRMLS_DC)
496{
497 shutdown_memory_manager(0, 1 TSRMLS_CC);
498}
499#endif
500
501
502#ifdef __FreeBSD__
503/* FreeBSD floating point precision fix */
504#include <floatingpoint.h>
505#endif
506
507
508static void scanner_globals_ctor(zend_scanner_globals *scanner_globals_p TSRMLS_DC)
509{
510 scanner_globals_p->c_buf_p = (char *) 0;
511 scanner_globals_p->init = 1;
512 scanner_globals_p->start = 0;
513 scanner_globals_p->current_buffer = NULL;
514 scanner_globals_p->yy_in = NULL;
515 scanner_globals_p->yy_out = NULL;
516 scanner_globals_p->_yy_more_flag = 0;
517 scanner_globals_p->_yy_more_len = 0;
518 scanner_globals_p->yy_start_stack_ptr = 0;
519 scanner_globals_p->yy_start_stack_depth = 0;
520 scanner_globals_p->yy_start_stack = 0;
521}
522
523void zend_init_opcodes_handlers();
524
525int zend_startup(zend_utility_functions *utility_functions, char **extensions, int start_builtin_functions)
526{
527#ifdef ZTS
528 zend_compiler_globals *compiler_globals;
529 zend_executor_globals *executor_globals;
530 void ***tsrm_ls;
531 extern ZEND_API ts_rsrc_id ini_scanner_globals_id;
532 extern ZEND_API ts_rsrc_id language_scanner_globals_id;
533#else
534 extern zend_scanner_globals ini_scanner_globals;
535 extern zend_scanner_globals language_scanner_globals;
536#endif
537
538#ifdef ZTS
539 ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
540#else
541 alloc_globals_ctor(&alloc_globals TSRMLS_CC);
542#endif
543
544#ifdef __FreeBSD__
545 /* FreeBSD floating point precision fix */
546 fpsetmask(0);
547#endif
548
549 zend_startup_extensions_mechanism();
550
551 /* Set up utility functions and values */
552 zend_error_cb = utility_functions->error_function;
553 zend_printf = utility_functions->printf_function;
554 zend_write = (zend_write_func_t) utility_functions->write_function;
555 zend_fopen = utility_functions->fopen_function;
556 if (!zend_fopen) {
557 zend_fopen = zend_fopen_wrapper;
558 }
559 zend_stream_open_function = utility_functions->stream_open_function;
560 zend_message_dispatcher_p = utility_functions->message_handler;
561 zend_block_interruptions = utility_functions->block_interruptions;
562 zend_unblock_interruptions = utility_functions->unblock_interruptions;
563 zend_get_configuration_directive_p = utility_functions->get_configuration_directive;
564 zend_ticks_function = utility_functions->ticks_function;
565 zend_on_timeout = utility_functions->on_timeout;
566 zend_vspprintf = utility_functions->vspprintf_function;
567
568 zend_compile_file = compile_file;
569 zend_execute = execute;
570 zend_execute_internal = NULL;
571
572 zend_init_opcodes_handlers();
573
574 /* set up version */
575 zend_version_info = strdup(ZEND_CORE_VERSION_INFO);
576 zend_version_info_length = sizeof(ZEND_CORE_VERSION_INFO)-1;
577
578 GLOBAL_FUNCTION_TABLE = (HashTable *) malloc(sizeof(HashTable));
579 GLOBAL_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable));
580 GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable));
581#ifdef ZTS
582 GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable));
583#endif
584 zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
585 zend_hash_init_ex(GLOBAL_CLASS_TABLE, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
586
587 zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0);
588 zend_init_rsrc_list_dtors();
589
590
591 /* This zval can be used to initialize allocate zval's to an uninit'ed value */
592 zval_used_for_init.is_ref = 0;
593 zval_used_for_init.refcount = 1;
594 zval_used_for_init.type = IS_NULL;
595
596#ifdef ZTS
597 zend_hash_init_ex(GLOBAL_CONSTANTS_TABLE, 20, NULL, ZEND_CONSTANT_DTOR, 1, 0);
598 zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, (dtor_func_t) zend_auto_global_dtor, 1, 0);
599 ts_allocate_id(&compiler_globals_id, sizeof(zend_compiler_globals), (ts_allocate_ctor) compiler_globals_ctor, (ts_allocate_dtor) compiler_globals_dtor);
600 ts_allocate_id(&executor_globals_id, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor);
601 ts_allocate_id(&language_scanner_globals_id, sizeof(zend_scanner_globals), (ts_allocate_ctor) scanner_globals_ctor, NULL);
602 ts_allocate_id(&ini_scanner_globals_id, sizeof(zend_scanner_globals), (ts_allocate_ctor) scanner_globals_ctor, NULL);
603 compiler_globals = ts_resource(compiler_globals_id);
604 executor_globals = ts_resource(executor_globals_id);
605 tsrm_ls = ts_resource_ex(0, NULL);
606
607 compiler_globals_dtor(compiler_globals TSRMLS_CC);
608 compiler_globals->in_compilation = 0;
609 compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable));
610 compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable));
611
612 *compiler_globals->function_table = *GLOBAL_FUNCTION_TABLE;
613 *compiler_globals->class_table = *GLOBAL_CLASS_TABLE;
614 compiler_globals->auto_globals = GLOBAL_AUTO_GLOBALS_TABLE;
615
616 zend_hash_destroy(executor_globals->zend_constants);
617 *executor_globals->zend_constants = *GLOBAL_CONSTANTS_TABLE;
618#else
619 zend_hash_init_ex(CG(auto_globals), 8, NULL, (dtor_func_t) zend_auto_global_dtor, 1, 0);
620 scanner_globals_ctor(&ini_scanner_globals TSRMLS_CC);
621 scanner_globals_ctor(&language_scanner_globals TSRMLS_CC);
622 zend_startup_constants();
623 zend_set_default_compile_time_values(TSRMLS_C);
624 EG(user_error_handler) = NULL;
625 EG(user_exception_handler) = NULL;
626#endif
627 register_standard_class(TSRMLS_C);
628 zend_register_standard_constants(TSRMLS_C);
629 zend_register_auto_global("GLOBALS", sizeof("GLOBALS")-1, NULL TSRMLS_CC);
630
631#ifndef ZTS
632 zend_init_rsrc_plist(TSRMLS_C);
633#endif
634
635 if (start_builtin_functions) {
636 zend_startup_builtin_functions(TSRMLS_C);
637 }
638
639 zend_ini_startup(TSRMLS_C);
640
641#ifdef ZTS
642 tsrm_set_new_thread_end_handler(zend_new_thread_end_handler);
643#endif
644
645 return SUCCESS;
646}
647
648
649void zend_register_standard_ini_entries(TSRMLS_D)
650{
651 int module_number = 0;
652
653 REGISTER_INI_ENTRIES();
654}
655
656
657#ifdef ZTS
658/* Unlink the global (r/o) copies of the class, function and constant tables,
659 * and use a fresh r/w copy for the startup thread
660 */
661void zend_post_startup(TSRMLS_D)
662{
663 zend_compiler_globals *compiler_globals = ts_resource(compiler_globals_id);
664 zend_executor_globals *executor_globals = ts_resource(executor_globals_id);
665
666 *GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table;
667 *GLOBAL_CLASS_TABLE = *compiler_globals->class_table;
668 *GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants;
669 zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
670 free(compiler_globals->function_table);
671 free(compiler_globals->class_table);
672 compiler_globals_ctor(compiler_globals, tsrm_ls);
673 free(EG(zend_constants));
674 executor_globals_ctor(executor_globals, tsrm_ls);
675 zend_new_thread_end_handler(tsrm_thread_id() TSRMLS_CC);
676}
677#endif
678
679
680void zend_shutdown(TSRMLS_D)
681{
682#ifdef ZEND_WIN32
683 zend_shutdown_timeout_thread();
684#endif
685#ifndef ZTS
686 zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
687#endif
688 zend_hash_graceful_reverse_destroy(&module_registry);
689
690 zend_hash_destroy(GLOBAL_FUNCTION_TABLE);
691 zend_hash_destroy(GLOBAL_CLASS_TABLE);
692
693 zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE);
694 free(GLOBAL_AUTO_GLOBALS_TABLE);
695 zend_shutdown_extensions(TSRMLS_C);
696 free(zend_version_info);
697
698 zend_shutdown_constants(TSRMLS_C);
699 free(GLOBAL_FUNCTION_TABLE);
700 free(GLOBAL_CLASS_TABLE);
701#ifdef ZTS
702 zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
703 zend_hash_destroy(GLOBAL_CONSTANTS_TABLE);
704 free(GLOBAL_CONSTANTS_TABLE);
705 GLOBAL_FUNCTION_TABLE = NULL;
706 GLOBAL_CLASS_TABLE = NULL;
707 GLOBAL_AUTO_GLOBALS_TABLE = NULL;
708#endif
709 zend_destroy_rsrc_list_dtors();
710}
711
712
713void zend_set_utility_values(zend_utility_values *utility_values)
714{
715 zend_uv = *utility_values;
716 zend_uv.import_use_extension_length = strlen(zend_uv.import_use_extension);
717}
718
719
720/* this should be compatible with the standard zenderror */
721void zenderror(char *error)
722{
723 zend_error(E_PARSE, "%s", error);
724}
725
726
727BEGIN_EXTERN_C()
728ZEND_API void _zend_bailout(char *filename, uint lineno)
729{
730 TSRMLS_FETCH();
731
732 if (!EG(bailout_set)) {
733 zend_output_debug_string(1, "%s(%d) : Bailed out without a bailout address!", filename, lineno);
734 exit(-1);
735 }
736 CG(unclean_shutdown) = 1;
737 CG(in_compilation) = EG(in_execution) = 0;
738 EG(current_execute_data) = NULL;
739 longjmp(EG(bailout), FAILURE);
740}
741END_EXTERN_C()
742
743
744void zend_append_version_info(zend_extension *extension)
745{
746 char *new_info;
747 uint new_info_length;
748
749 new_info_length = sizeof(" with v, by \n")
750 + strlen(extension->name)
751 + strlen(extension->version)
752 + strlen(extension->copyright)
753 + strlen(extension->author);
754
755 new_info = (char *) malloc(new_info_length+1);
756
757 sprintf(new_info, " with %s v%s, %s, by %s\n", extension->name, extension->version, extension->copyright, extension->author);
758
759 zend_version_info = (char *) realloc(zend_version_info, zend_version_info_length+new_info_length+1);
760 strcat(zend_version_info, new_info);
761 zend_version_info_length += new_info_length;
762 free(new_info);
763}
764
765
766ZEND_API char *get_zend_version()
767{
768 return zend_version_info;
769}
770
771
772void zend_activate(TSRMLS_D)
773{
774 init_compiler(TSRMLS_C);
775 init_executor(TSRMLS_C);
776 startup_scanner(TSRMLS_C);
777}
778
779
780void zend_activate_modules(TSRMLS_D)
781{
782 zend_hash_apply(&module_registry, (apply_func_t) module_registry_request_startup TSRMLS_CC);
783}
784
785void zend_deactivate_modules(TSRMLS_D)
786{
787 EG(opline_ptr) = NULL; /* we're no longer executing anything */
788
789 zend_try {
790 zend_hash_apply(&module_registry, (apply_func_t) module_registry_cleanup TSRMLS_CC);
791 } zend_end_try();
792}
793
794void zend_deactivate(TSRMLS_D)
795{
796 /* we're no longer executing anything */
797 EG(opline_ptr) = NULL;
798 EG(active_symbol_table) = NULL;
799
800 zend_try {
801 shutdown_scanner(TSRMLS_C);
802 } zend_end_try();
803
804 /* shutdown_executor() takes care of its own bailout handling */
805 shutdown_executor(TSRMLS_C);
806
807 zend_try {
808 shutdown_compiler(TSRMLS_C);
809 } zend_end_try();
810
811 zend_try {
812 zend_ini_deactivate(TSRMLS_C);
813 } zend_end_try();
814}
815
816
817static int exec_done_cb(zend_module_entry *module TSRMLS_DC)
818{
1/*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2004 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$ */
21
22#include "zend.h"
23#include "zend_extensions.h"
24#include "zend_modules.h"
25#include "zend_constants.h"
26#include "zend_list.h"
27#include "zend_API.h"
28#include "zend_exceptions.h"
29#include "zend_builtin_functions.h"
30#include "zend_ini.h"
31
32#ifdef ZTS
33# define GLOBAL_FUNCTION_TABLE global_function_table
34# define GLOBAL_CLASS_TABLE global_class_table
35# define GLOBAL_CONSTANTS_TABLE global_constants_table
36# define GLOBAL_AUTO_GLOBALS_TABLE global_auto_globals_table
37#else
38# define GLOBAL_FUNCTION_TABLE CG(function_table)
39# define GLOBAL_CLASS_TABLE CG(class_table)
40# define GLOBAL_AUTO_GLOBALS_TABLE CG(auto_globals)
41#endif
42
43#if defined(ZEND_WIN32) && ZEND_DEBUG
44BOOL WINAPI IsDebuggerPresent(VOID);
45#endif
46
47/* true multithread-shared globals */
48ZEND_API zend_class_entry *zend_standard_class_def = NULL;
49ZEND_API int (*zend_printf)(const char *format, ...);
50ZEND_API zend_write_func_t zend_write;
51ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path);
52ZEND_API int (*zend_stream_open_function)(const char *filename, zend_file_handle *handle TSRMLS_DC);
53ZEND_API void (*zend_block_interruptions)(void);
54ZEND_API void (*zend_unblock_interruptions)(void);
55ZEND_API void (*zend_ticks_function)(int ticks);
56ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args);
57int (*zend_vspprintf)(char **pbuf, size_t max_len, const char *format, va_list ap);
58
59void (*zend_on_timeout)(int seconds TSRMLS_DC);
60
61static void (*zend_message_dispatcher_p)(long message, void *data);
62static int (*zend_get_configuration_directive_p)(char *name, uint name_length, zval *contents);
63
64
65static ZEND_INI_MH(OnUpdateErrorReporting)
66{
67 if (!new_value) {
68 EG(error_reporting) = E_ALL & ~E_NOTICE & ~E_STRICT;
69 } else {
70 EG(error_reporting) = atoi(new_value);
71 }
72 return SUCCESS;
73}
74
75
76ZEND_INI_BEGIN()
77 ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting)
78 STD_ZEND_INI_BOOLEAN("zend.ze1_compatibility_mode", "0", ZEND_INI_ALL, OnUpdateBool, ze1_compatibility_mode, zend_executor_globals, executor_globals)
79ZEND_INI_END()
80
81
82#ifdef ZTS
83ZEND_API int compiler_globals_id;
84ZEND_API int executor_globals_id;
85ZEND_API int alloc_globals_id;
86zend_class_entry global_main_class;
87HashTable *global_function_table;
88HashTable *global_class_table;
89HashTable *global_constants_table;
90HashTable *global_auto_globals_table;
91#endif
92
93ZEND_API zend_utility_values zend_uv;
94
95ZEND_API zval zval_used_for_init; /* True global variable */
96
97/* version information */
98static char *zend_version_info;
99static uint zend_version_info_length;
100#define ZEND_CORE_VERSION_INFO "Zend Engine v" ZEND_VERSION ", Copyright (c) 1998-2004 Zend Technologies\n"
101
102
103#define PRINT_ZVAL_INDENT 4
104
105static void print_hash(HashTable *ht, int indent, zend_bool is_object TSRMLS_DC)
106{
107 zval **tmp;
108 char *string_key;
109 HashPosition iterator;
110 ulong num_key;
111 uint str_len;
112 int i;
113
114 for (i=0; i<indent; i++) {
115 ZEND_PUTS(" ");
116 }
117 ZEND_PUTS("(\n");
118 indent += PRINT_ZVAL_INDENT;
119 zend_hash_internal_pointer_reset_ex(ht, &iterator);
120 while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) {
121 for (i=0; i<indent; i++) {
122 ZEND_PUTS(" ");
123 }
124 ZEND_PUTS("[");
125 switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) {
126 case HASH_KEY_IS_STRING:
127 if (is_object) {
128 char *prop_name, *class_name;
129
130 zend_unmangle_property_name(string_key, &class_name, &prop_name);
131 ZEND_PUTS(prop_name);
132 if (class_name) {
133 if (class_name[0]=='*') {
134 ZEND_PUTS(":protected");
135 } else {
136 ZEND_PUTS(":private");
137 }
138 }
139 } else {
140 ZEND_WRITE(string_key, str_len-1);
141 }
142 break;
143 case HASH_KEY_IS_LONG:
144 zend_printf("%ld", num_key);
145 break;
146 }
147 ZEND_PUTS("] => ");
148 zend_print_zval_r(*tmp, indent+PRINT_ZVAL_INDENT TSRMLS_CC);
149 ZEND_PUTS("\n");
150 zend_hash_move_forward_ex(ht, &iterator);
151 }
152 indent -= PRINT_ZVAL_INDENT;
153 for (i=0; i<indent; i++) {
154 ZEND_PUTS(" ");
155 }
156 ZEND_PUTS(")\n");
157}
158
159static void print_flat_hash(HashTable *ht TSRMLS_DC)
160{
161 zval **tmp;
162 char *string_key;
163 HashPosition iterator;
164 ulong num_key;
165 uint str_len;
166 int i = 0;
167
168 zend_hash_internal_pointer_reset_ex(ht, &iterator);
169 while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) {
170 if (i++ > 0) {
171 ZEND_PUTS(",");
172 }
173 ZEND_PUTS("[");
174 switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) {
175 case HASH_KEY_IS_STRING:
176 ZEND_PUTS(string_key);
177 break;
178 case HASH_KEY_IS_LONG:
179 zend_printf("%ld", num_key);
180 break;
181 }
182 ZEND_PUTS("] => ");
183 zend_print_flat_zval_r(*tmp TSRMLS_CC);
184 zend_hash_move_forward_ex(ht, &iterator);
185 }
186}
187
188ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy)
189{
190 if (expr->type==IS_STRING) {
191 *use_copy = 0;
192 return;
193 }
194 switch (expr->type) {
195 case IS_NULL:
196 expr_copy->value.str.len = 0;
197 expr_copy->value.str.val = empty_string;
198 break;
199 case IS_BOOL:
200 if (expr->value.lval) {
201 expr_copy->value.str.len = 1;
202 expr_copy->value.str.val = estrndup("1", 1);
203 } else {
204 expr_copy->value.str.len = 0;
205 expr_copy->value.str.val = empty_string;
206 }
207 break;
208 case IS_RESOURCE:
209 expr_copy->value.str.val = (char *) emalloc(sizeof("Resource id #")-1 + MAX_LENGTH_OF_LONG);
210 expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Resource id #%ld", expr->value.lval);
211 break;
212 case IS_ARRAY:
213 expr_copy->value.str.len = sizeof("Array")-1;
214 expr_copy->value.str.val = estrndup("Array", expr_copy->value.str.len);
215 break;
216 case IS_OBJECT:
217 {
218 TSRMLS_FETCH();
219 /* Standard PHP objects */
220 if (expr->value.obj.handlers == &std_object_handlers) {
221 if (zend_std_cast_object_tostring(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
222 break;
223 }
224 zend_error(E_NOTICE, "Object of class %s could not be converted to string", Z_OBJCE_P(expr)->name);
225 }
226 if (expr->value.obj.handlers->cast_object &&
227 expr->value.obj.handlers->cast_object(expr, expr_copy, IS_STRING, 0 TSRMLS_CC) == SUCCESS) {
228 break;
229 }
230 if (EG(exception)) {
231 zval_dtor(expr_copy);
232 expr_copy->value.str.len = 0;
233 expr_copy->value.str.val = empty_string;
234 break;
235 }
236 }
237 expr_copy->value.str.val = (char *) emalloc(sizeof("Object id #")-1 + MAX_LENGTH_OF_LONG);
238 expr_copy->value.str.len = sprintf(expr_copy->value.str.val, "Object id #%ld", (long)expr->value.obj.handle);
239 break;
240 case IS_DOUBLE:
241 *expr_copy = *expr;
242 zval_copy_ctor(expr_copy);
243 zend_locale_sprintf_double(expr_copy ZEND_FILE_LINE_CC);
244 break;
245 default:
246 *expr_copy = *expr;
247 zval_copy_ctor(expr_copy);
248 convert_to_string(expr_copy);
249 break;
250 }
251 expr_copy->type = IS_STRING;
252 *use_copy = 1;
253}
254
255
256ZEND_API int zend_print_zval(zval *expr, int indent)
257{
258 return zend_print_zval_ex(zend_write, expr, indent);
259}
260
261
262ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent)
263{
264 zval expr_copy;
265 int use_copy;
266
267 zend_make_printable_zval(expr, &expr_copy, &use_copy);
268 if (use_copy) {
269 expr = &expr_copy;
270 }
271 if (expr->value.str.len==0) { /* optimize away empty strings */
272 if (use_copy) {
273 zval_dtor(expr);
274 }
275 return 0;
276 }
277 write_func(expr->value.str.val, expr->value.str.len);
278 if (use_copy) {
279 zval_dtor(expr);
280 }
281 return expr->value.str.len;
282}
283
284ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC)
285{
286 switch (expr->type) {
287 case IS_ARRAY:
288 ZEND_PUTS("Array (");
289 if (++expr->value.ht->nApplyCount>1) {
290 ZEND_PUTS(" *RECURSION*");
291 expr->value.ht->nApplyCount--;
292 return;
293 }
294 print_flat_hash(expr->value.ht TSRMLS_CC);
295 ZEND_PUTS(")");
296 expr->value.ht->nApplyCount--;
297 break;
298 case IS_OBJECT:
299 {
300 HashTable *properties = NULL;
301 char *class_name = NULL;
302 zend_uint clen;
303
304 if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
305 Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
306 }
307 zend_printf("%s Object (", class_name?class_name:"Unknown Class");
308 if (class_name) {
309 efree(class_name);
310 }
311 if (Z_OBJ_HANDLER_P(expr, get_properties)) {
312 properties = Z_OBJPROP_P(expr);
313 }
314 if (properties) {
315 if (++properties->nApplyCount>1) {
316 ZEND_PUTS(" *RECURSION*");
317 properties->nApplyCount--;
318 return;
319 }
320 print_flat_hash(properties TSRMLS_CC);
321 properties->nApplyCount--;
322 }
323 ZEND_PUTS(")");
324 break;
325 }
326 default:
327 zend_print_variable(expr);
328 break;
329 }
330}
331
332ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC)
333{
334 zend_print_zval_r_ex(zend_write, expr, indent TSRMLS_CC);
335}
336
337
338ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC)
339{
340 switch (expr->type) {
341 case IS_ARRAY:
342 ZEND_PUTS("Array\n");
343 if (++expr->value.ht->nApplyCount>1) {
344 ZEND_PUTS(" *RECURSION*");
345 expr->value.ht->nApplyCount--;
346 return;
347 }
348 print_hash(expr->value.ht, indent, 0 TSRMLS_CC);
349 expr->value.ht->nApplyCount--;
350 break;
351 case IS_OBJECT:
352 {
353 HashTable *properties = NULL;
354 char *class_name = NULL;
355 zend_uint clen;
356
357 if (Z_OBJ_HANDLER_P(expr, get_class_name)) {
358 Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC);
359 }
360 zend_printf("%s Object\n", class_name?class_name:"Unknown Class");
361 if (class_name) {
362 efree(class_name);
363 }
364 if (Z_OBJ_HANDLER_P(expr, get_properties)) {
365 properties = Z_OBJPROP_P(expr);
366 }
367 if (properties) {
368 if (++properties->nApplyCount>1) {
369 ZEND_PUTS(" *RECURSION*");
370 properties->nApplyCount--;
371 return;
372 }
373 print_hash(properties, indent, 1 TSRMLS_CC);
374 properties->nApplyCount--;
375 }
376 break;
377 }
378 default:
379 zend_print_variable(expr);
380 break;
381 }
382}
383
384
385static FILE *zend_fopen_wrapper(const char *filename, char **opened_path)
386{
387 if (opened_path) {
388 *opened_path = estrdup(filename);
389 }
390 return fopen(filename, "rb");
391}
392
393
394static void register_standard_class(TSRMLS_D)
395{
396 zend_standard_class_def = malloc(sizeof(zend_class_entry));
397
398 zend_standard_class_def->type = ZEND_INTERNAL_CLASS;
399 zend_standard_class_def->name_length = sizeof("stdClass") - 1;
400 zend_standard_class_def->name = zend_strndup("stdClass", zend_standard_class_def->name_length);
401 zend_initialize_class_data(zend_standard_class_def, 1 TSRMLS_CC);
402
403 zend_hash_add(CG(class_table), "stdclass", sizeof("stdclass"), &zend_standard_class_def, sizeof(zend_class_entry *), NULL);
404}
405
406static void zend_set_default_compile_time_values(TSRMLS_D)
407{
408 /* default compile-time values */
409 CG(asp_tags) = 0;
410 CG(short_tags) = 1;
411 CG(allow_call_time_pass_reference) = 1;
412 CG(extended_info) = 0;
413}
414
415
416#ifdef ZTS
417static void compiler_globals_ctor(zend_compiler_globals *compiler_globals TSRMLS_DC)
418{
419 zend_function tmp_func;
420 zend_class_entry tmp_class;
421
422 compiler_globals->compiled_filename = NULL;
423
424 compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable));
425 zend_hash_init_ex(compiler_globals->function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
426 zend_hash_copy(compiler_globals->function_table, global_function_table, NULL, &tmp_func, sizeof(zend_function));
427
428 compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable));
429 zend_hash_init_ex(compiler_globals->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
430 zend_hash_copy(compiler_globals->class_table, global_class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry));
431
432 zend_set_default_compile_time_values(TSRMLS_C);
433
434 CG(interactive) = 0;
435
436 compiler_globals->auto_globals = (HashTable *) malloc(sizeof(HashTable));
437 zend_hash_init_ex(compiler_globals->auto_globals, 8, NULL, NULL, 1, 0);
438 zend_hash_copy(compiler_globals->auto_globals, global_auto_globals_table, NULL, NULL, sizeof(zend_auto_global) /* empty element */);
439}
440
441
442static void compiler_globals_dtor(zend_compiler_globals *compiler_globals TSRMLS_DC)
443{
444 if (compiler_globals->function_table != GLOBAL_FUNCTION_TABLE) {
445 zend_hash_destroy(compiler_globals->function_table);
446 free(compiler_globals->function_table);
447 }
448 if (compiler_globals->class_table != GLOBAL_CLASS_TABLE) {
449 zend_hash_destroy(compiler_globals->class_table);
450 free(compiler_globals->class_table);
451 }
452 if (compiler_globals->auto_globals != GLOBAL_AUTO_GLOBALS_TABLE) {
453 zend_hash_destroy(compiler_globals->auto_globals);
454 free(compiler_globals->auto_globals);
455 }
456}
457
458
459static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS_DC)
460{
461 zend_startup_constants(TSRMLS_C);
462 zend_copy_constants(EG(zend_constants), GLOBAL_CONSTANTS_TABLE);
463 zend_init_rsrc_plist(TSRMLS_C);
464 EG(lambda_count)=0;
465 EG(user_error_handler) = NULL;
466 EG(user_exception_handler) = NULL;
467 EG(in_execution) = 0;
468 EG(in_autoload) = 0;
469 EG(current_execute_data) = NULL;
470}
471
472
473static void executor_globals_dtor(zend_executor_globals *executor_globals TSRMLS_DC)
474{
475 zend_ini_shutdown(TSRMLS_C);
476}
477
478
479static void zend_new_thread_end_handler(THREAD_T thread_id TSRMLS_DC)
480{
481 zend_copy_ini_directives(TSRMLS_C);
482 zend_ini_refresh_caches(ZEND_INI_STAGE_STARTUP TSRMLS_CC);
483}
484
485#endif
486
487
488static void alloc_globals_ctor(zend_alloc_globals *alloc_globals_p TSRMLS_DC)
489{
490 start_memory_manager(TSRMLS_C);
491}
492
493
494#ifdef ZTS
495static void alloc_globals_dtor(zend_alloc_globals *alloc_globals_p TSRMLS_DC)
496{
497 shutdown_memory_manager(0, 1 TSRMLS_CC);
498}
499#endif
500
501
502#ifdef __FreeBSD__
503/* FreeBSD floating point precision fix */
504#include <floatingpoint.h>
505#endif
506
507
508static void scanner_globals_ctor(zend_scanner_globals *scanner_globals_p TSRMLS_DC)
509{
510 scanner_globals_p->c_buf_p = (char *) 0;
511 scanner_globals_p->init = 1;
512 scanner_globals_p->start = 0;
513 scanner_globals_p->current_buffer = NULL;
514 scanner_globals_p->yy_in = NULL;
515 scanner_globals_p->yy_out = NULL;
516 scanner_globals_p->_yy_more_flag = 0;
517 scanner_globals_p->_yy_more_len = 0;
518 scanner_globals_p->yy_start_stack_ptr = 0;
519 scanner_globals_p->yy_start_stack_depth = 0;
520 scanner_globals_p->yy_start_stack = 0;
521}
522
523void zend_init_opcodes_handlers();
524
525int zend_startup(zend_utility_functions *utility_functions, char **extensions, int start_builtin_functions)
526{
527#ifdef ZTS
528 zend_compiler_globals *compiler_globals;
529 zend_executor_globals *executor_globals;
530 void ***tsrm_ls;
531 extern ZEND_API ts_rsrc_id ini_scanner_globals_id;
532 extern ZEND_API ts_rsrc_id language_scanner_globals_id;
533#else
534 extern zend_scanner_globals ini_scanner_globals;
535 extern zend_scanner_globals language_scanner_globals;
536#endif
537
538#ifdef ZTS
539 ts_allocate_id(&alloc_globals_id, sizeof(zend_alloc_globals), (ts_allocate_ctor) alloc_globals_ctor, (ts_allocate_dtor) alloc_globals_dtor);
540#else
541 alloc_globals_ctor(&alloc_globals TSRMLS_CC);
542#endif
543
544#ifdef __FreeBSD__
545 /* FreeBSD floating point precision fix */
546 fpsetmask(0);
547#endif
548
549 zend_startup_extensions_mechanism();
550
551 /* Set up utility functions and values */
552 zend_error_cb = utility_functions->error_function;
553 zend_printf = utility_functions->printf_function;
554 zend_write = (zend_write_func_t) utility_functions->write_function;
555 zend_fopen = utility_functions->fopen_function;
556 if (!zend_fopen) {
557 zend_fopen = zend_fopen_wrapper;
558 }
559 zend_stream_open_function = utility_functions->stream_open_function;
560 zend_message_dispatcher_p = utility_functions->message_handler;
561 zend_block_interruptions = utility_functions->block_interruptions;
562 zend_unblock_interruptions = utility_functions->unblock_interruptions;
563 zend_get_configuration_directive_p = utility_functions->get_configuration_directive;
564 zend_ticks_function = utility_functions->ticks_function;
565 zend_on_timeout = utility_functions->on_timeout;
566 zend_vspprintf = utility_functions->vspprintf_function;
567
568 zend_compile_file = compile_file;
569 zend_execute = execute;
570 zend_execute_internal = NULL;
571
572 zend_init_opcodes_handlers();
573
574 /* set up version */
575 zend_version_info = strdup(ZEND_CORE_VERSION_INFO);
576 zend_version_info_length = sizeof(ZEND_CORE_VERSION_INFO)-1;
577
578 GLOBAL_FUNCTION_TABLE = (HashTable *) malloc(sizeof(HashTable));
579 GLOBAL_CLASS_TABLE = (HashTable *) malloc(sizeof(HashTable));
580 GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable));
581#ifdef ZTS
582 GLOBAL_CONSTANTS_TABLE = (HashTable *) malloc(sizeof(HashTable));
583#endif
584 zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
585 zend_hash_init_ex(GLOBAL_CLASS_TABLE, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
586
587 zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0);
588 zend_init_rsrc_list_dtors();
589
590
591 /* This zval can be used to initialize allocate zval's to an uninit'ed value */
592 zval_used_for_init.is_ref = 0;
593 zval_used_for_init.refcount = 1;
594 zval_used_for_init.type = IS_NULL;
595
596#ifdef ZTS
597 zend_hash_init_ex(GLOBAL_CONSTANTS_TABLE, 20, NULL, ZEND_CONSTANT_DTOR, 1, 0);
598 zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, (dtor_func_t) zend_auto_global_dtor, 1, 0);
599 ts_allocate_id(&compiler_globals_id, sizeof(zend_compiler_globals), (ts_allocate_ctor) compiler_globals_ctor, (ts_allocate_dtor) compiler_globals_dtor);
600 ts_allocate_id(&executor_globals_id, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor);
601 ts_allocate_id(&language_scanner_globals_id, sizeof(zend_scanner_globals), (ts_allocate_ctor) scanner_globals_ctor, NULL);
602 ts_allocate_id(&ini_scanner_globals_id, sizeof(zend_scanner_globals), (ts_allocate_ctor) scanner_globals_ctor, NULL);
603 compiler_globals = ts_resource(compiler_globals_id);
604 executor_globals = ts_resource(executor_globals_id);
605 tsrm_ls = ts_resource_ex(0, NULL);
606
607 compiler_globals_dtor(compiler_globals TSRMLS_CC);
608 compiler_globals->in_compilation = 0;
609 compiler_globals->function_table = (HashTable *) malloc(sizeof(HashTable));
610 compiler_globals->class_table = (HashTable *) malloc(sizeof(HashTable));
611
612 *compiler_globals->function_table = *GLOBAL_FUNCTION_TABLE;
613 *compiler_globals->class_table = *GLOBAL_CLASS_TABLE;
614 compiler_globals->auto_globals = GLOBAL_AUTO_GLOBALS_TABLE;
615
616 zend_hash_destroy(executor_globals->zend_constants);
617 *executor_globals->zend_constants = *GLOBAL_CONSTANTS_TABLE;
618#else
619 zend_hash_init_ex(CG(auto_globals), 8, NULL, (dtor_func_t) zend_auto_global_dtor, 1, 0);
620 scanner_globals_ctor(&ini_scanner_globals TSRMLS_CC);
621 scanner_globals_ctor(&language_scanner_globals TSRMLS_CC);
622 zend_startup_constants();
623 zend_set_default_compile_time_values(TSRMLS_C);
624 EG(user_error_handler) = NULL;
625 EG(user_exception_handler) = NULL;
626#endif
627 register_standard_class(TSRMLS_C);
628 zend_register_standard_constants(TSRMLS_C);
629 zend_register_auto_global("GLOBALS", sizeof("GLOBALS")-1, NULL TSRMLS_CC);
630
631#ifndef ZTS
632 zend_init_rsrc_plist(TSRMLS_C);
633#endif
634
635 if (start_builtin_functions) {
636 zend_startup_builtin_functions(TSRMLS_C);
637 }
638
639 zend_ini_startup(TSRMLS_C);
640
641#ifdef ZTS
642 tsrm_set_new_thread_end_handler(zend_new_thread_end_handler);
643#endif
644
645 return SUCCESS;
646}
647
648
649void zend_register_standard_ini_entries(TSRMLS_D)
650{
651 int module_number = 0;
652
653 REGISTER_INI_ENTRIES();
654}
655
656
657#ifdef ZTS
658/* Unlink the global (r/o) copies of the class, function and constant tables,
659 * and use a fresh r/w copy for the startup thread
660 */
661void zend_post_startup(TSRMLS_D)
662{
663 zend_compiler_globals *compiler_globals = ts_resource(compiler_globals_id);
664 zend_executor_globals *executor_globals = ts_resource(executor_globals_id);
665
666 *GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table;
667 *GLOBAL_CLASS_TABLE = *compiler_globals->class_table;
668 *GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants;
669 zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
670 free(compiler_globals->function_table);
671 free(compiler_globals->class_table);
672 compiler_globals_ctor(compiler_globals, tsrm_ls);
673 free(EG(zend_constants));
674 executor_globals_ctor(executor_globals, tsrm_ls);
675 zend_new_thread_end_handler(tsrm_thread_id() TSRMLS_CC);
676}
677#endif
678
679
680void zend_shutdown(TSRMLS_D)
681{
682#ifdef ZEND_WIN32
683 zend_shutdown_timeout_thread();
684#endif
685#ifndef ZTS
686 zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
687#endif
688 zend_hash_graceful_reverse_destroy(&module_registry);
689
690 zend_hash_destroy(GLOBAL_FUNCTION_TABLE);
691 zend_hash_destroy(GLOBAL_CLASS_TABLE);
692
693 zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE);
694 free(GLOBAL_AUTO_GLOBALS_TABLE);
695 zend_shutdown_extensions(TSRMLS_C);
696 free(zend_version_info);
697
698 zend_shutdown_constants(TSRMLS_C);
699 free(GLOBAL_FUNCTION_TABLE);
700 free(GLOBAL_CLASS_TABLE);
701#ifdef ZTS
702 zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC);
703 zend_hash_destroy(GLOBAL_CONSTANTS_TABLE);
704 free(GLOBAL_CONSTANTS_TABLE);
705 GLOBAL_FUNCTION_TABLE = NULL;
706 GLOBAL_CLASS_TABLE = NULL;
707 GLOBAL_AUTO_GLOBALS_TABLE = NULL;
708#endif
709 zend_destroy_rsrc_list_dtors();
710}
711
712
713void zend_set_utility_values(zend_utility_values *utility_values)
714{
715 zend_uv = *utility_values;
716 zend_uv.import_use_extension_length = strlen(zend_uv.import_use_extension);
717}
718
719
720/* this should be compatible with the standard zenderror */
721void zenderror(char *error)
722{
723 zend_error(E_PARSE, "%s", error);
724}
725
726
727BEGIN_EXTERN_C()
728ZEND_API void _zend_bailout(char *filename, uint lineno)
729{
730 TSRMLS_FETCH();
731
732 if (!EG(bailout_set)) {
733 zend_output_debug_string(1, "%s(%d) : Bailed out without a bailout address!", filename, lineno);
734 exit(-1);
735 }
736 CG(unclean_shutdown) = 1;
737 CG(in_compilation) = EG(in_execution) = 0;
738 EG(current_execute_data) = NULL;
739 longjmp(EG(bailout), FAILURE);
740}
741END_EXTERN_C()
742
743
744void zend_append_version_info(zend_extension *extension)
745{
746 char *new_info;
747 uint new_info_length;
748
749 new_info_length = sizeof(" with v, by \n")
750 + strlen(extension->name)
751 + strlen(extension->version)
752 + strlen(extension->copyright)
753 + strlen(extension->author);
754
755 new_info = (char *) malloc(new_info_length+1);
756
757 sprintf(new_info, " with %s v%s, %s, by %s\n", extension->name, extension->version, extension->copyright, extension->author);
758
759 zend_version_info = (char *) realloc(zend_version_info, zend_version_info_length+new_info_length+1);
760 strcat(zend_version_info, new_info);
761 zend_version_info_length += new_info_length;
762 free(new_info);
763}
764
765
766ZEND_API char *get_zend_version()
767{
768 return zend_version_info;
769}
770
771
772void zend_activate(TSRMLS_D)
773{
774 init_compiler(TSRMLS_C);
775 init_executor(TSRMLS_C);
776 startup_scanner(TSRMLS_C);
777}
778
779
780void zend_activate_modules(TSRMLS_D)
781{
782 zend_hash_apply(&module_registry, (apply_func_t) module_registry_request_startup TSRMLS_CC);
783}
784
785void zend_deactivate_modules(TSRMLS_D)
786{
787 EG(opline_ptr) = NULL; /* we're no longer executing anything */
788
789 zend_try {
790 zend_hash_apply(&module_registry, (apply_func_t) module_registry_cleanup TSRMLS_CC);
791 } zend_end_try();
792}
793
794void zend_deactivate(TSRMLS_D)
795{
796 /* we're no longer executing anything */
797 EG(opline_ptr) = NULL;
798 EG(active_symbol_table) = NULL;
799
800 zend_try {
801 shutdown_scanner(TSRMLS_C);
802 } zend_end_try();
803
804 /* shutdown_executor() takes care of its own bailout handling */
805 shutdown_executor(TSRMLS_C);
806
807 zend_try {
808 shutdown_compiler(TSRMLS_C);
809 } zend_end_try();
810
811 zend_try {
812 zend_ini_deactivate(TSRMLS_C);
813 } zend_end_try();
814}
815
816
817static int exec_done_cb(zend_module_entry *module TSRMLS_DC)
818{
819 if (module->exec_finished_func) {
820 module->exec_finished_func();
819 if (module->post_deactivate_func) {
820 module->post_deactivate_func();
821 }
822 return 0;
823}
824
825
821 }
822 return 0;
823}
824
825
826void zend_exec_finished(TSRMLS_D)
826void zend_post_deactivate_modules(TSRMLS_D)
827{
828 zend_hash_apply(&module_registry, (apply_func_t) exec_done_cb TSRMLS_CC);
829}
830
831
832BEGIN_EXTERN_C()
833ZEND_API void zend_message_dispatcher(long message, void *data)
834{
835 if (zend_message_dispatcher_p) {
836 zend_message_dispatcher_p(message, data);
837 }
838}
839END_EXTERN_C()
840
841
842ZEND_API int zend_get_configuration_directive(char *name, uint name_length, zval *contents)
843{
844 if (zend_get_configuration_directive_p) {
845 return zend_get_configuration_directive_p(name, name_length, contents);
846 } else {
847 return FAILURE;
848 }
849}
850
851
852ZEND_API void zend_error(int type, const char *format, ...)
853{
854 va_list args;
855 zval ***params;
856 zval *retval;
857 zval *z_error_type, *z_error_message, *z_error_filename, *z_error_lineno, *z_context;
858 char *error_filename;
859 uint error_lineno;
860 zval *orig_user_error_handler;
861 zval *orig_garbage[2];
862 int orig_garbage_ptr;
863 TSRMLS_FETCH();
864
865 /* Obtain relevant filename and lineno */
866 switch (type) {
867 case E_CORE_ERROR:
868 case E_CORE_WARNING:
869 error_filename = NULL;
870 error_lineno = 0;
871 break;
872 case E_PARSE:
873 case E_COMPILE_ERROR:
874 case E_COMPILE_WARNING:
875 case E_ERROR:
876 case E_NOTICE:
877 case E_STRICT:
878 case E_WARNING:
879 case E_USER_ERROR:
880 case E_USER_WARNING:
881 case E_USER_NOTICE:
882 if (zend_is_compiling(TSRMLS_C)) {
883 error_filename = zend_get_compiled_filename(TSRMLS_C);
884 error_lineno = zend_get_compiled_lineno(TSRMLS_C);
885 } else if (zend_is_executing(TSRMLS_C)) {
886 error_filename = zend_get_executed_filename(TSRMLS_C);
887 error_lineno = zend_get_executed_lineno(TSRMLS_C);
888 } else {
889 error_filename = NULL;
890 error_lineno = 0;
891 }
892 break;
893 default:
894 error_filename = NULL;
895 error_lineno = 0;
896 break;
897 }
898 if (!error_filename) {
899 error_filename = "Unknown";
900 }
901
902 va_start(args, format);
903
904 /* if we don't have a user defined error handler */
905 if (!EG(user_error_handler)
906 || !(EG(user_error_handler_error_reporting) & type)) {
907 zend_error_cb(type, error_filename, error_lineno, format, args);
908 } else switch (type) {
909 case E_ERROR:
910 case E_PARSE:
911 case E_CORE_ERROR:
912 case E_CORE_WARNING:
913 case E_COMPILE_ERROR:
914 case E_COMPILE_WARNING:
915 /* The error may not be safe to handle in user-space */
916 zend_error_cb(type, error_filename, error_lineno, format, args);
917 break;
918 default:
919 /* Handle the error in user space */
920 ALLOC_INIT_ZVAL(z_error_message);
921 ALLOC_INIT_ZVAL(z_error_type);
922 ALLOC_INIT_ZVAL(z_error_filename);
923 ALLOC_INIT_ZVAL(z_error_lineno);
924 ALLOC_INIT_ZVAL(z_context);
925
926 z_error_message->value.str.len = zend_vspprintf(&z_error_message->value.str.val, 0, format, args);
927 z_error_message->type = IS_STRING;
928
929 z_error_type->value.lval = type;
930 z_error_type->type = IS_LONG;
931
932 if (error_filename) {
933 z_error_filename->value.str.len = strlen(error_filename);
934 z_error_filename->value.str.val = estrndup(error_filename, z_error_filename->value.str.len);
935 z_error_filename->type = IS_STRING;
936 }
937
938 z_error_lineno->value.lval = error_lineno;
939 z_error_lineno->type = IS_LONG;
940
941 z_context->value.ht = EG(active_symbol_table);
942 z_context->type = IS_ARRAY;
943 ZVAL_ADDREF(z_context); /* we don't want this one to be freed */
944
945 params = (zval ***) emalloc(sizeof(zval **)*5);
946 params[0] = &z_error_type;
947 params[1] = &z_error_message;
948 params[2] = &z_error_filename;
949 params[3] = &z_error_lineno;
950 params[4] = &z_context;
951
952 orig_user_error_handler = EG(user_error_handler);
953 EG(user_error_handler) = NULL;
954
955 orig_garbage_ptr = EG(garbage_ptr);
956 EG(garbage_ptr) = 0;
957 if (orig_garbage_ptr > 0) {
958 memcpy(&orig_garbage, &EG(garbage), sizeof(zval*)*orig_garbage_ptr);
959 }
960
961 if (call_user_function_ex(CG(function_table), NULL, orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC)==SUCCESS) {
962 if (retval) {
963 zval_ptr_dtor(&retval);
964 }
965 } else {
966 /* The user error handler failed, use built-in error handler */
967 zend_error_cb(type, error_filename, error_lineno, format, args);
968 }
969
970 if (orig_garbage_ptr > 0) {
971 while (EG(garbage_ptr)) {
972 zval_ptr_dtor(&EG(garbage)[--EG(garbage_ptr)]);
973 }
974 EG(garbage_ptr) = orig_garbage_ptr;
975 memcpy(&EG(garbage), &orig_garbage, sizeof(zval*)*orig_garbage_ptr);
976 }
977
978 EG(user_error_handler) = orig_user_error_handler;
979
980 efree(params);
981 zval_ptr_dtor(&z_error_message);
982 zval_ptr_dtor(&z_error_type);
983 zval_ptr_dtor(&z_error_filename);
984 zval_ptr_dtor(&z_error_lineno);
985 if (ZVAL_REFCOUNT(z_context) == 2) {
986 FREE_ZVAL(z_context);
987 }
988 break;
989 }
990
991 va_end(args);
992
993 if (type == E_PARSE) {
994 EG(exit_status) = 255;
995 zend_init_compiler_data_structures(TSRMLS_C);
996 }
997}
998
999
1000ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, ...)
1001{
1002#if ZEND_DEBUG
1003 va_list args;
1004
1005 va_start(args, format);
1006# ifdef ZEND_WIN32
1007 {
1008 char output_buf[1024];
1009
1010 vsnprintf(output_buf, 1024, format, args);
1011 OutputDebugString(output_buf);
1012 OutputDebugString("\n");
1013 if (trigger_break && IsDebuggerPresent()) {
1014 DebugBreak();
1015 }
1016 }
1017# else
1018 vfprintf(stderr, format, args);
1019 fprintf(stderr, "\n");
1020# endif
1021 va_end(args);
1022#endif
1023}
1024
1025
1026ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...)
1027{
1028 va_list files;
1029 int i;
1030 zend_file_handle *file_handle;
1031 zend_op_array *orig_op_array = EG(active_op_array);
1032 zval *local_retval=NULL;
1033
1034 va_start(files, file_count);
1035 for (i=0; i<file_count; i++) {
1036 file_handle = va_arg(files, zend_file_handle *);
1037 if (!file_handle) {
1038 continue;
1039 }
1040 EG(active_op_array) = zend_compile_file(file_handle, ZEND_INCLUDE TSRMLS_CC);
1041 zend_destroy_file_handle(file_handle TSRMLS_CC);
1042 if (EG(active_op_array)) {
1043 EG(return_value_ptr_ptr) = retval ? retval : &local_retval;
1044 zend_execute(EG(active_op_array) TSRMLS_CC);
1045 if (EG(exception)) {
1046 char ex_class_name[128];
1047 if (Z_TYPE_P(EG(exception)) == IS_OBJECT) {
1048 strncpy(ex_class_name, Z_OBJ_CLASS_NAME_P(EG(exception)), 127);
1049 ex_class_name[127] = '\0';
1050 } else {
1051 strcpy(ex_class_name, "Unknown Exception");
1052 }
1053 if (EG(user_exception_handler)) {
1054 zval *orig_user_exception_handler;
1055 zval ***params, *retval2, *old_exception;
1056 params = (zval ***)emalloc(sizeof(zval **));
1057 old_exception = EG(exception);
1058 EG(exception) = NULL;
1059 params[0] = &old_exception;
1060 orig_user_exception_handler = EG(user_exception_handler);
1061 if (call_user_function_ex(CG(function_table), NULL, orig_user_exception_handler, &retval2, 1, params, 1, NULL TSRMLS_CC) == SUCCESS) {
1062 if (retval2 != NULL) {
1063 zval_ptr_dtor(&retval2);
1064 }
1065 } else {
1066 zend_exception_error(EG(exception) TSRMLS_CC);
1067 }
1068 efree(params);
1069 zval_ptr_dtor(&old_exception);
1070 if (EG(exception)) {
1071 zval_ptr_dtor(&EG(exception));
1072 EG(exception) = NULL;
1073 }
1074 } else {
1075 zend_exception_error(EG(exception) TSRMLS_CC);
1076 }
1077 if (retval == NULL && *EG(return_value_ptr_ptr) != NULL) {
1078 zval_ptr_dtor(EG(return_value_ptr_ptr));
1079 local_retval = NULL;
1080 }
1081 } else if (!retval) {
1082 zval_ptr_dtor(EG(return_value_ptr_ptr));
1083 local_retval = NULL;
1084 }
1085 destroy_op_array(EG(active_op_array) TSRMLS_CC);
1086 efree(EG(active_op_array));
1087 } else if (type==ZEND_REQUIRE) {
1088 va_end(files);
1089 EG(active_op_array) = orig_op_array;
1090 return FAILURE;
1091 }
1092 }
1093 va_end(files);
1094 EG(active_op_array) = orig_op_array;
1095
1096 return SUCCESS;
1097}
1098
1099#define COMPILED_STRING_DESCRIPTION_FORMAT "%s(%d) : %s"
1100
1101ZEND_API char *zend_make_compiled_string_description(char *name TSRMLS_DC)
1102{
1103 char *cur_filename;
1104 int cur_lineno;
1105 char *compiled_string_description;
1106
1107 if (zend_is_compiling(TSRMLS_C)) {
1108 cur_filename = zend_get_compiled_filename(TSRMLS_C);
1109 cur_lineno = zend_get_compiled_lineno(TSRMLS_C);
1110 } else if (zend_is_executing(TSRMLS_C)) {
1111 cur_filename = zend_get_executed_filename(TSRMLS_C);
1112 cur_lineno = zend_get_executed_lineno(TSRMLS_C);
1113 } else {
1114 cur_filename = "Unknown";
1115 cur_lineno = 0;
1116 }
1117
1118 compiled_string_description = emalloc(sizeof(COMPILED_STRING_DESCRIPTION_FORMAT)+strlen(name)+strlen(cur_filename)+MAX_LENGTH_OF_LONG);
1119 sprintf(compiled_string_description, COMPILED_STRING_DESCRIPTION_FORMAT, cur_filename, cur_lineno, name);
1120 return compiled_string_description;
1121}
1122
1123
1124void free_estring(char **str_p)
1125{
1126 efree(*str_p);
1127}
1128
1129
1130/*
1131 * Local variables:
1132 * tab-width: 4
1133 * c-basic-offset: 4
1134 * indent-tabs-mode: t
1135 * End:
1136 */
827{
828 zend_hash_apply(&module_registry, (apply_func_t) exec_done_cb TSRMLS_CC);
829}
830
831
832BEGIN_EXTERN_C()
833ZEND_API void zend_message_dispatcher(long message, void *data)
834{
835 if (zend_message_dispatcher_p) {
836 zend_message_dispatcher_p(message, data);
837 }
838}
839END_EXTERN_C()
840
841
842ZEND_API int zend_get_configuration_directive(char *name, uint name_length, zval *contents)
843{
844 if (zend_get_configuration_directive_p) {
845 return zend_get_configuration_directive_p(name, name_length, contents);
846 } else {
847 return FAILURE;
848 }
849}
850
851
852ZEND_API void zend_error(int type, const char *format, ...)
853{
854 va_list args;
855 zval ***params;
856 zval *retval;
857 zval *z_error_type, *z_error_message, *z_error_filename, *z_error_lineno, *z_context;
858 char *error_filename;
859 uint error_lineno;
860 zval *orig_user_error_handler;
861 zval *orig_garbage[2];
862 int orig_garbage_ptr;
863 TSRMLS_FETCH();
864
865 /* Obtain relevant filename and lineno */
866 switch (type) {
867 case E_CORE_ERROR:
868 case E_CORE_WARNING:
869 error_filename = NULL;
870 error_lineno = 0;
871 break;
872 case E_PARSE:
873 case E_COMPILE_ERROR:
874 case E_COMPILE_WARNING:
875 case E_ERROR:
876 case E_NOTICE:
877 case E_STRICT:
878 case E_WARNING:
879 case E_USER_ERROR:
880 case E_USER_WARNING:
881 case E_USER_NOTICE:
882 if (zend_is_compiling(TSRMLS_C)) {
883 error_filename = zend_get_compiled_filename(TSRMLS_C);
884 error_lineno = zend_get_compiled_lineno(TSRMLS_C);
885 } else if (zend_is_executing(TSRMLS_C)) {
886 error_filename = zend_get_executed_filename(TSRMLS_C);
887 error_lineno = zend_get_executed_lineno(TSRMLS_C);
888 } else {
889 error_filename = NULL;
890 error_lineno = 0;
891 }
892 break;
893 default:
894 error_filename = NULL;
895 error_lineno = 0;
896 break;
897 }
898 if (!error_filename) {
899 error_filename = "Unknown";
900 }
901
902 va_start(args, format);
903
904 /* if we don't have a user defined error handler */
905 if (!EG(user_error_handler)
906 || !(EG(user_error_handler_error_reporting) & type)) {
907 zend_error_cb(type, error_filename, error_lineno, format, args);
908 } else switch (type) {
909 case E_ERROR:
910 case E_PARSE:
911 case E_CORE_ERROR:
912 case E_CORE_WARNING:
913 case E_COMPILE_ERROR:
914 case E_COMPILE_WARNING:
915 /* The error may not be safe to handle in user-space */
916 zend_error_cb(type, error_filename, error_lineno, format, args);
917 break;
918 default:
919 /* Handle the error in user space */
920 ALLOC_INIT_ZVAL(z_error_message);
921 ALLOC_INIT_ZVAL(z_error_type);
922 ALLOC_INIT_ZVAL(z_error_filename);
923 ALLOC_INIT_ZVAL(z_error_lineno);
924 ALLOC_INIT_ZVAL(z_context);
925
926 z_error_message->value.str.len = zend_vspprintf(&z_error_message->value.str.val, 0, format, args);
927 z_error_message->type = IS_STRING;
928
929 z_error_type->value.lval = type;
930 z_error_type->type = IS_LONG;
931
932 if (error_filename) {
933 z_error_filename->value.str.len = strlen(error_filename);
934 z_error_filename->value.str.val = estrndup(error_filename, z_error_filename->value.str.len);
935 z_error_filename->type = IS_STRING;
936 }
937
938 z_error_lineno->value.lval = error_lineno;
939 z_error_lineno->type = IS_LONG;
940
941 z_context->value.ht = EG(active_symbol_table);
942 z_context->type = IS_ARRAY;
943 ZVAL_ADDREF(z_context); /* we don't want this one to be freed */
944
945 params = (zval ***) emalloc(sizeof(zval **)*5);
946 params[0] = &z_error_type;
947 params[1] = &z_error_message;
948 params[2] = &z_error_filename;
949 params[3] = &z_error_lineno;
950 params[4] = &z_context;
951
952 orig_user_error_handler = EG(user_error_handler);
953 EG(user_error_handler) = NULL;
954
955 orig_garbage_ptr = EG(garbage_ptr);
956 EG(garbage_ptr) = 0;
957 if (orig_garbage_ptr > 0) {
958 memcpy(&orig_garbage, &EG(garbage), sizeof(zval*)*orig_garbage_ptr);
959 }
960
961 if (call_user_function_ex(CG(function_table), NULL, orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC)==SUCCESS) {
962 if (retval) {
963 zval_ptr_dtor(&retval);
964 }
965 } else {
966 /* The user error handler failed, use built-in error handler */
967 zend_error_cb(type, error_filename, error_lineno, format, args);
968 }
969
970 if (orig_garbage_ptr > 0) {
971 while (EG(garbage_ptr)) {
972 zval_ptr_dtor(&EG(garbage)[--EG(garbage_ptr)]);
973 }
974 EG(garbage_ptr) = orig_garbage_ptr;
975 memcpy(&EG(garbage), &orig_garbage, sizeof(zval*)*orig_garbage_ptr);
976 }
977
978 EG(user_error_handler) = orig_user_error_handler;
979
980 efree(params);
981 zval_ptr_dtor(&z_error_message);
982 zval_ptr_dtor(&z_error_type);
983 zval_ptr_dtor(&z_error_filename);
984 zval_ptr_dtor(&z_error_lineno);
985 if (ZVAL_REFCOUNT(z_context) == 2) {
986 FREE_ZVAL(z_context);
987 }
988 break;
989 }
990
991 va_end(args);
992
993 if (type == E_PARSE) {
994 EG(exit_status) = 255;
995 zend_init_compiler_data_structures(TSRMLS_C);
996 }
997}
998
999
1000ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, ...)
1001{
1002#if ZEND_DEBUG
1003 va_list args;
1004
1005 va_start(args, format);
1006# ifdef ZEND_WIN32
1007 {
1008 char output_buf[1024];
1009
1010 vsnprintf(output_buf, 1024, format, args);
1011 OutputDebugString(output_buf);
1012 OutputDebugString("\n");
1013 if (trigger_break && IsDebuggerPresent()) {
1014 DebugBreak();
1015 }
1016 }
1017# else
1018 vfprintf(stderr, format, args);
1019 fprintf(stderr, "\n");
1020# endif
1021 va_end(args);
1022#endif
1023}
1024
1025
1026ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_count, ...)
1027{
1028 va_list files;
1029 int i;
1030 zend_file_handle *file_handle;
1031 zend_op_array *orig_op_array = EG(active_op_array);
1032 zval *local_retval=NULL;
1033
1034 va_start(files, file_count);
1035 for (i=0; i<file_count; i++) {
1036 file_handle = va_arg(files, zend_file_handle *);
1037 if (!file_handle) {
1038 continue;
1039 }
1040 EG(active_op_array) = zend_compile_file(file_handle, ZEND_INCLUDE TSRMLS_CC);
1041 zend_destroy_file_handle(file_handle TSRMLS_CC);
1042 if (EG(active_op_array)) {
1043 EG(return_value_ptr_ptr) = retval ? retval : &local_retval;
1044 zend_execute(EG(active_op_array) TSRMLS_CC);
1045 if (EG(exception)) {
1046 char ex_class_name[128];
1047 if (Z_TYPE_P(EG(exception)) == IS_OBJECT) {
1048 strncpy(ex_class_name, Z_OBJ_CLASS_NAME_P(EG(exception)), 127);
1049 ex_class_name[127] = '\0';
1050 } else {
1051 strcpy(ex_class_name, "Unknown Exception");
1052 }
1053 if (EG(user_exception_handler)) {
1054 zval *orig_user_exception_handler;
1055 zval ***params, *retval2, *old_exception;
1056 params = (zval ***)emalloc(sizeof(zval **));
1057 old_exception = EG(exception);
1058 EG(exception) = NULL;
1059 params[0] = &old_exception;
1060 orig_user_exception_handler = EG(user_exception_handler);
1061 if (call_user_function_ex(CG(function_table), NULL, orig_user_exception_handler, &retval2, 1, params, 1, NULL TSRMLS_CC) == SUCCESS) {
1062 if (retval2 != NULL) {
1063 zval_ptr_dtor(&retval2);
1064 }
1065 } else {
1066 zend_exception_error(EG(exception) TSRMLS_CC);
1067 }
1068 efree(params);
1069 zval_ptr_dtor(&old_exception);
1070 if (EG(exception)) {
1071 zval_ptr_dtor(&EG(exception));
1072 EG(exception) = NULL;
1073 }
1074 } else {
1075 zend_exception_error(EG(exception) TSRMLS_CC);
1076 }
1077 if (retval == NULL && *EG(return_value_ptr_ptr) != NULL) {
1078 zval_ptr_dtor(EG(return_value_ptr_ptr));
1079 local_retval = NULL;
1080 }
1081 } else if (!retval) {
1082 zval_ptr_dtor(EG(return_value_ptr_ptr));
1083 local_retval = NULL;
1084 }
1085 destroy_op_array(EG(active_op_array) TSRMLS_CC);
1086 efree(EG(active_op_array));
1087 } else if (type==ZEND_REQUIRE) {
1088 va_end(files);
1089 EG(active_op_array) = orig_op_array;
1090 return FAILURE;
1091 }
1092 }
1093 va_end(files);
1094 EG(active_op_array) = orig_op_array;
1095
1096 return SUCCESS;
1097}
1098
1099#define COMPILED_STRING_DESCRIPTION_FORMAT "%s(%d) : %s"
1100
1101ZEND_API char *zend_make_compiled_string_description(char *name TSRMLS_DC)
1102{
1103 char *cur_filename;
1104 int cur_lineno;
1105 char *compiled_string_description;
1106
1107 if (zend_is_compiling(TSRMLS_C)) {
1108 cur_filename = zend_get_compiled_filename(TSRMLS_C);
1109 cur_lineno = zend_get_compiled_lineno(TSRMLS_C);
1110 } else if (zend_is_executing(TSRMLS_C)) {
1111 cur_filename = zend_get_executed_filename(TSRMLS_C);
1112 cur_lineno = zend_get_executed_lineno(TSRMLS_C);
1113 } else {
1114 cur_filename = "Unknown";
1115 cur_lineno = 0;
1116 }
1117
1118 compiled_string_description = emalloc(sizeof(COMPILED_STRING_DESCRIPTION_FORMAT)+strlen(name)+strlen(cur_filename)+MAX_LENGTH_OF_LONG);
1119 sprintf(compiled_string_description, COMPILED_STRING_DESCRIPTION_FORMAT, cur_filename, cur_lineno, name);
1120 return compiled_string_description;
1121}
1122
1123
1124void free_estring(char **str_p)
1125{
1126 efree(*str_p);
1127}
1128
1129
1130/*
1131 * Local variables:
1132 * tab-width: 4
1133 * c-basic-offset: 4
1134 * indent-tabs-mode: t
1135 * End:
1136 */