tsukada
ttsuk****@users*****
2003年 2月 11日 (火) 11:40:22 JST
ttsukada 03/02/11 11:40:21 Modified: . ChangeLog LICENSE Makefile.am OBJECTS2_HOWTO ZEND_CHANGES Zend.dsp Zend.m4 ZendTS.dsp acconfig.h configure.in flex.skl zend.c zend.h zend_API.c zend_API.h zend_alloc.c zend_alloc.h zend_builtin_functions.c zend_builtin_functions.h zend_compile.c zend_compile.h zend_config.nw.h zend_config.w32.h zend_constants.c zend_constants.h zend_dynamic_array.c zend_dynamic_array.h zend_errors.h zend_execute.c zend_execute.h zend_execute_API.c zend_execute_locks.h zend_extensions.c zend_extensions.h zend_fast_cache.h zend_globals.h zend_globals_macros.h zend_hash.c zend_hash.h zend_highlight.c zend_highlight.h zend_indent.c zend_indent.h zend_ini.c zend_ini.h zend_ini_parser.y zend_ini_scanner.h zend_ini_scanner.l zend_istdiostream.h zend_language_parser.y zend_language_scanner.h zend_language_scanner.l zend_list.c zend_list.h zend_llist.c zend_llist.h zend_mm.c zend_mm.h zend_modules.h zend_multibyte.c zend_object_handlers.c zend_object_handlers.h zend_objects.c zend_objects.h zend_objects_API.c zend_objects_API.h zend_opcode.c zend_operators.c zend_operators.h zend_ptr_stack.c zend_ptr_stack.h zend_qsort.c zend_qsort.h zend_sprintf.c zend_stack.c zend_stack.h zend_static_allocator.c zend_static_allocator.h zend_ts_hash.c zend_ts_hash.h zend_types.h zend_variables.c zend_variables.h Log: merge Revision Changes Path 1.9 +2154 -0 ZendEngine2/ChangeLog Index: ChangeLog =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/ChangeLog,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- ChangeLog 3 Aug 2002 08:56:16 -0000 1.8 +++ ChangeLog 11 Feb 2003 02:40:18 -0000 1.9 @@ -1,3 +1,2157 @@ +2003-02-09 Zeev Suraski <zeev****@zend*****> + + * zend_execute.c: + Fix the array() problem (and probably some other problems too) + +2003-02-08 Georg Richter <georg****@phpev*****> + + * zend_API.c + zend_API.h: + fixed zend_parse_method_param + +2003-02-08 Sebastian Bergmann <sb****@sebas*****> + + * zend_builtin_functions.c: + zend_config.h (and its Win32 version) is already included by zend.h + +2003-02-08 Ilia Alshanetsky <ilia****@proho*****> + + * zend_builtin_functions.c: + The string.h is already avaliable through zend.h, so the manual inclusion + is not necessary. + +2003-02-07 Ilia Alshanetsky <ilia****@proho*****> + + * zend_builtin_functions.c: + Added a check to ensure that string.h is avaliable before trying to use it. + + Thanks Andi. + + * zend_builtin_functions.c: + Added missing header. + +2003-02-07 Zeev Suraski <zeev****@zend*****> + + * zend_globals.h + zend_object_handlers.c: + Improve PPP handling of properties + + * zend_config.w32.h: + Better fix + + * zend_config.w32.h: + Fix Windows build + +2003-02-07 Ilia Alshanetsky <ilia****@proho*****> + + * zend_builtin_functions.c: + Fixed bug #15734 (Added an optional parameter to get_defined_constants(), + which if passed, will include information regarding who created the + constant). + +2003-02-06 Ilia Alshanetsky <ilia****@proho*****> + + * zend_builtin_functions.c: + Fixed bug #19506 (get_extension_funcs() can now retrieve a list of built-in + Zend Engine functions, if "zend" is specified as the module name). + Made get_extension_funcs() on failure. + +2003-02-06 Zeev Suraski <zeev****@zend*****> + + * zend_compile.c: + Fix the 2nd buglet in the error message :) + + * zend_object_handlers.c: + Fix check + + * zend_hash.c + zend_hash.h: + Fix prototype (may have caused stack corruption) + +2003-02-05 Zeev Suraski <zeev****@zend*****> + + * zend_execute.c + zend_object_handlers.c + zend_object_handlers.h + zend_objects_API.c: + - read_property cleanup + - Implement unset/isset/empty for PPP + + * zend.c + zend.h + zend_API.c + zend_compile.c + zend_execute.c + zend_object_handlers.c + zend_object_handlers.h + zend_opcode.c: + Rework static class properties - now supports access restrictions + + * zend_hash.c + zend_hash.h: + Add quick_exists() + + * zend_object_handlers.c: + Add PPP support for arrays + + * zend_compile.c: + Fix buglet in error message + +2003-02-04 Zeev Suraski <zeev****@zend*****> + + * zend_object_handlers.c: + Missing update + + * zend.c + zend.h + zend_API.c + zend_compile.c + zend_compile.h + zend_globals.h + zend_hash.c + zend_hash.h + zend_object_handlers.c + zend_opcode.c + zend_ts_hash.c + zend_ts_hash.h: + Reimplement PPP properties + +2003-02-03 Sebastian Bergmann <sb****@sebas*****> + + * zend_API.h: + Build fix. + +2003-02-02 Harald Radi <haral****@nme*****> + + * zend_API.c + zend_API.h: + extend the parameter parsing API by two functions + for parsing method parameters with automatic + detection if the function was called as such or as + a class method (with a valid this ptr). + if called as a function the first parameter has to be + the object it is operating on, if called as a method + this is used. + + +2003-02-02 Zeev Suraski <zeev****@zend*****> + + * zend.h + zend_operators.h: + whitespace + + * zend_execute.c + zend_object_handlers.c + zend_object_handlers.h: + Core rearrangements - move Zend Objects specific code to their + specific implementation file + +2003-02-02 Andi Gutmans <andi****@zend*****> + + * zend_compile.c: + - Fix warning + +2003-02-01 Sebastian Bergmann <sb****@sebas*****> + + * zend_ini_scanner.l + zend_language_scanner.l: + Fix build. + +2003-02-01 Jani Taskinen <snipe****@iki*****> + + * acconfig.h + zend.c + zend.h + zend_API.c + zend_API.h + zend_alloc.c + zend_alloc.h + zend_builtin_functions.c + zend_builtin_functions.h + zend_compile.c + zend_compile.h + zend_config.nw.h + zend_config.w32.h + zend_constants.c + zend_constants.h + zend_dynamic_array.c + zend_dynamic_array.h + zend_errors.h + zend_execute.c + zend_execute.h + zend_execute_API.c + zend_execute_locks.h + zend_extensions.c + zend_extensions.h + zend_fast_cache.h + zend_globals.h + zend_globals_macros.h + zend_hash.c + zend_hash.h + zend_highlight.c + zend_highlight.h + zend_indent.c + zend_indent.h + zend_ini.c + zend_ini.h + zend_ini_parser.y + zend_ini_scanner.h + zend_ini_scanner.l + zend_istdiostream.h + zend_language_parser.y + zend_language_scanner.h + zend_language_scanner.l + zend_list.c + zend_list.h + zend_llist.c + zend_llist.h + zend_mm.c + zend_mm.h + zend_modules.h + zend_object_handlers.c + zend_object_handlers.h + zend_objects.c + zend_objects.h + zend_objects_API.c + zend_objects_API.h + zend_opcode.c + zend_operators.c + zend_operators.h + zend_ptr_stack.c + zend_ptr_stack.h + zend_qsort.h + zend_sprintf.c + zend_stack.c + zend_stack.h + zend_static_allocator.c + zend_static_allocator.h + zend_ts_hash.c + zend_ts_hash.h + zend_types.h + zend_variables.c + zend_variables.h: + - Added some missing CVS $Id: ChangeLog,v 1.168 2003/02/10 01:32:53 changelog Exp $ tags, headers and footers. + +2003-01-30 Ilia Alshanetsky <ilia****@proho*****> + + * zend_operators.c: + Fixed compiler warning regarding signed/unsigned int comparisons. + +2003-01-30 Harald Radi <haral****@nme*****> + + * zend_ts_hash.c + zend_ts_hash.h: + fix non-zts build for wez + +2003-01-30 Ilia Alshanetsky <ilia****@proho*****> + + * zend_execute_API.c: + Fix ZTS build. + +2003-01-29 Stanislav Malyshev <stas****@zend*****> + + * zend_compile.h + zend_execute_API.c + zend_opcode.c: + Add additional stage to post-session cleanup. + We need separate cleanup stage because of the following problem: + Suppose we destroy class X, which destroys function table, + and in function table we have function foo() that has static $bar. Now if + object of class X was assigned to $bar, its destructor will be called and + will + fail since X's function table is in mid-destruction. + So we want first of all to clean up all data and then move to tables + destruction. + Note that only run-time accessed data need to be cleaned up, pre-defined + data can not contain objects and thus are not probelmatic. + +2003-01-29 Zeev Suraski <zeev****@zend*****> + + * zend_execute.c + zend_object_handlers.c: + Code rearrangements + +2003-01-29 Stanislav Malyshev <stas****@zend*****> + + * zend_execute_API.c: + Fix object destructors: + zend_objects_store_call_destructors is not used anymore, we rely on + symbol tables cleaners to destroy all objects. + + * zend_objects_API.c: + extra safety + + * zend_compile.c: + fix memory leak + +2003-01-29 Zeev Suraski <zeev****@zend*****> + + * zend_execute.c + zend_object_handlers.c: + Fix assignments to $this. + Fixes the 'make install' problem reported on php-dev + +2003-01-28 Zeev Suraski <zeev****@zend*****> + + * zend_compile.c: + Fix a ticks related crash + + * (PHP_5_0_dev_before_13561_fix) + zend_execute.c: + Allow methods in parent classes to call protected methods in derived + classes + +2003-01-27 Stanislav Malyshev <stas****@zend*****> + + * zend_compile.c + zend_compile.h + zend_execute.c: + Replace MAKE_VAR opcode with special 'data' opcode + This opcode is not executeable but only holds data for opcodes + that need more than two arguments (presently only ASSIGN_OBJ and the ilk + but + in the future also ASSIGN_DIM) + +2003-01-26 Sascha Schumann <sasch****@schum*****> + + * zend_API.c: + Replace snprintf() call using zend_error's capabilities + +2003-01-23 Zeev Suraski <zeev****@zend*****> + + * zend_execute.c: + Let the scope propagate to internal functions + +2003-01-23 Jani Taskinen <snipe****@iki*****> + + * zend_execute_API.c: + Fixed bug: #14542, register_shutdown_function() timeout problem + +2003-01-22 Stanislav Malyshev <stas****@zend*****> + + * OBJECTS2_HOWTO: + some small refinements for get_class_* + +2003-01-22 Ilia Alshanetsky <ilia****@proho*****> + + * zend_execute.c: + Fixed bug #21814 (Allow booleans to be used as array keys). + +2003-01-21 Sterling Hughes <sterl****@bumbl*****> + + * zend_objects_API.c: + fix by phanto to the cloning + +2003-01-19 Zeev Suraski <zeev****@zend*****> + + * Zend.m4: + relabel + +2003-01-19 Stanislav Malyshev <stas****@zend*****> + + * zend_compile.c: + Restore for now old statics behaviour (so that indirect $$var references + would work again). Comprehensive fix will follow later. + +2003-01-19 Harald Radi <haral****@nme*****> + + * zend_ini.h + zend_ini_parser.y + zend_ini_scanner.l: + ini patch to allow 'entry[] = value' entries + +2003-01-17 Harald Radi <haral****@nme*****> + + * zend_objects.c + zend_objects.h: + export zend_objects_destroy_object() + static inline was meaningless anyways as the function + was only used as a callback handler and was never + called directly + + * zend_objects_API.c + zend_objects_API.h: + make std_object_handlers struct available for shared modules + +2003-01-16 Ilia Alshanetsky <ilia****@proho*****> + + * zend_execute.c: + Fixed bug #20933 (isset/empty didn't work when used on string offsets). + +2003-01-15 Andi Gutmans <andi****@zend*****> + + * zend_compile.c: + - Revert int -> unsigned int change for str.len + +2003-01-15 Sascha Schumann <sasch****@schum*****> + + * zend.h: + Revert commit which turned the lengths of strings into zend_uint. + +2003-01-14 Andi Gutmans <andi****@zend*****> + + * ZEND_CHANGES + zend_compile.c + zend_compile.h + zend_execute.c + zend_language_parser.y + zend_language_scanner.l + zend_operators.c + zend_operators.h: + - Change "is" to "instanceof" as it explains better what the operator + means. + - "is_a" was also appropriate but ugly. + +2003-01-14 Stanislav Malyshev <stas****@zend*****> + + * zend_API.c: + fix memory leaks and key size + +2003-01-14 Ilia Alshanetsky <ilia****@proho*****> + + * zend_ini_parser.y: + MFZE2 + +2003-01-14 Stanislav Malyshev <stas****@zend*****> + + * zend_compile.c: + fix warning + + * zend_API.c + zend_API.h: + Make add_property_ functions work via write_property handler + + * zend.c + zend_object_handlers.c: + ws + +2003-01-14 Ilia Alshanetsky <ilia****@proho*****> + + * zend_ini_parser.y: + Reverting previous patch. + +2003-01-13 Ilia Alshanetsky <ilia****@proho*****> + + * zend_ini_parser.y: + MFZE2 + +2003-01-13 Andi Gutmans <andi****@zend*****> + + * zend_objects_API.c: + - Don't check if the handle is bogus. We should crash. + +2003-01-12 Harald Radi <haral****@nme*****> + + * zend_modules.h: + fix wrong dereferenciation + +2003-01-12 Stanislav Malyshev <stas****@zend*****> + + * zend_compile.c: + fix inheritance + + * zend_API.h: + Remove handle_property from here too + + * zend.c + zend.h + zend_compile.c: + RIP handle_* functions. ZE2 will use __ handlers instead. + + * zend_object_handlers.c: + Move Z_OBJ_P here. + + * zend_operators.h: + Remove Z_OBJ - it's internal to Zend objects, no generic function except + those in zend_object_handlers.c should use it. + Add Z_OBJ_HANDLER macro for easy access to handlers + +2003-01-12 Sebastian Bergmann <sb****@sebas*****> + + * zend.c + zend.h + zend_builtin_functions.c: + ZTS fixes. + +2003-01-12 Stanislav Malyshev <stas****@zend*****> + + * zend_object_handlers.c: + add get_class_name handler + + * zend.c: + Use generic handlers instead of Z_OBJ + +2003-01-12 Harald Radi <haral****@nme*****> + + * zend_modules.h: + + + * zend_ini.h + zend_ini_entry.h + zend_modules.h: + partially revert previous commit and + change zend_modules.h to include + a forward declaration to zend_ini_entry + + * zend_ini.h + zend_ini_entry.h + zend_modules.h: + added zend_ini_entry to zend_modules_entry as + discussed with zeev + + * zend_builtin_functions.c: + fix 'use of uninitialized variable' warning + +2003-01-12 Stanislav Malyshev <stas****@zend*****> + + * zend_objects_API.c: + validate handle + +2003-01-12 Zeev Suraski <zeev****@zend*****> + + * zend.c + zend_compile.c + zend_execute.c + zend_execute_API.c + zend_globals.h + zend_ini.c + zend_ini.h + zend_variables.c: + Implemented compatibility mode + To enable - zend2.implicit_clone = on in php.ini or using ini_set() + +2003-01-11 Andi Gutmans <andi****@zend*****> + + * zend_execute.c: + - Fix typo and whitespace + +2003-01-11 Derick Rethans <d.ret****@jdime*****> + + * zend.c + zend_execute.c + zend_execute.h + zend_execute_API.c: + - Ported the zend_execute_internal hook to ZendEngine2. + +2003-01-11 Harald Radi <haral****@nme*****> + + * zend_ts_hash.c: + freed reader twice instead of writer and reader + +2003-01-10 Ilia Alshanetsky <ilia****@proho*****> + + * zend_alloc.c: + MFZE2 + +2003-01-10 Andrei Zmievski <andre****@gravi*****> + + * zend_API.c: + Automatically register constructor, destructor, and clone function when + class methods are registered. + +2003-01-09 Zeev Suraski <zeev****@zend*****> + + * zend_compile.c: + Found some more occurences of that elusive bug... + + * zend_compile.c: + Fix one lousy, annoying lurking bug (memory corruption) + Sebastian - try coWiki again please... + + * zend_API.h: + Unify and make it easy to add code into the broken-string error handler + + * zend_language_parser.y: + Fix writability checks + + * zend.c: + Fix leak + +2003-01-08 James Cox <james****@imaje*****> + + * zend.h: + cvs is dev not alpha. + +2003-01-08 Ilia Alshanetsky <ilia****@proho*****> + + * zend_builtin_functions.c: + MFZE2 + +2003-01-05 Zeev Suraski <zeev****@zend*****> + + * zend_compile.c + zend_globals.h + zend_language_scanner.l: + MFZE1 - lineno fix + +2003-01-02 Zeev Suraski <zeev****@zend*****> + + * zend_compile.c + zend_compile.h + zend_execute.c: + Fix incorrect linkage of access-levels, when using private methods + +2003-01-01 Zeev Suraski <zeev****@zend*****> + + * zend_API.c + zend_operators.h: + Win32 build fix + +2003-01-01 Stanislav Malyshev <stas****@zend*****> + + * zend_operators.h: + use handler for Z_OBJPROP + +2003-01-01 Zeev Suraski <zeev****@zend*****> + + * zend_API.c: + Fix Wez's problem + +2002-12-31 Sebastian Bergmann <sb****@sebas*****> + + * LICENSE + zend.c + zend.h + zend_API.c + zend_API.h + zend_alloc.c + zend_alloc.h + zend_builtin_functions.c + zend_builtin_functions.h + zend_compile.c + zend_compile.h + zend_config.nw.h + zend_config.w32.h + zend_constants.c + zend_constants.h + zend_dynamic_array.c + zend_dynamic_array.h + zend_errors.h + zend_execute.c + zend_execute.h + zend_execute_API.c + zend_extensions.c + zend_extensions.h + zend_fast_cache.h + zend_globals.h + zend_globals_macros.h + zend_hash.c + zend_hash.h + zend_highlight.c + zend_highlight.h + zend_indent.c + zend_indent.h + zend_ini.c + zend_ini.h + zend_language_scanner.h + zend_list.c + zend_list.h + zend_llist.c + zend_llist.h + zend_mm.c + zend_mm.h + zend_modules.h + zend_opcode.c + zend_operators.c + zend_operators.h + zend_ptr_stack.c + zend_ptr_stack.h + zend_qsort.c + zend_qsort.h + zend_sprintf.c + zend_stack.c + zend_stack.h + zend_static_allocator.c + zend_static_allocator.h + zend_ts_hash.c + zend_ts_hash.h + zend_types.h + zend_variables.c + zend_variables.h: + Bump year. + +2002-12-31 Stanislav Malyshev <stas****@zend*****> + + * zend_object_handlers.h: + fix level of indirection + +2002-12-30 Andrei Zmievski <andre****@gravi*****> + + * zend_execute_API.c: + Adjust the error message. + +2002-12-30 Stanislav Malyshev <stas****@zend*****> + + * zend_object_handlers.h: + Oops, fix it indeed + + * zend_object_handlers.h: + Better check + +2002-12-26 Andrei Zmievski <andre****@gravi*****> + + * zend_compile.c: + do_inherit_method_check() is supposed to return 0 or 1, not SUCCESS or + FAILURE. + +2002-12-14 Ilia Alshanetsky <ilia****@proho*****> + + * zend_language_scanner.l: + MFZE2 + +2002-12-10 Zeev Suraski <zeev****@zend*****> + + * zend_compile.c: + Fix check to allow for static+access level modifiers + + * zend_compile.c + zend_compile.h + zend_language_parser.y: + - Allow variables to have both 'static' modifier and an access level. + NOTE: This only works at the syntax level right now (parser). It + doesn't actually work as of yet - all statics are considered + public for now + - Prevent users from putting more restrictions on methods in derived + classes + (i.e., you cannot make a public method private in a derived class, etc.) + +2002-12-09 Andi Gutmans <andi****@zend*****> + + * zend_mm.c: + - Fix a bug which I just introduced. + + * zend_mm.c: + - Fix typo + + * zend_mm.c: + - Improvements + + * zend_mm.c + zend_mm.h: + - First attempt to improve memory manager during realloc()'s + +2002-12-08 Zeev Suraski <zeev****@zend*****> + + * zend_compile.c: + Remove comment + + * zend_compile.c + zend_compile.h + zend_language_parser.y: + Treat the absence of an access type just as if 'public' was supplied + + * zend_compile.c: + Simplify/fix inheritance checks + + * zend_execute.c: + Support private/protected constructors + +2002-12-07 Sebastian Bergmann <sb****@sebas*****> + + * ZEND_CHANGES: + Update. + +2002-12-07 Zeev Suraski <zeev****@zend*****> + + * zend_execute.c: + Fix error messages + + * zend_language_parser.y + zend_language_scanner.l: + Remove unintentional code + +2002-12-07 Andi Gutmans <andi****@zend*****> + + * zend_compile.c: + - Dissallow using parent, self and main as class names + +2002-12-06 Zeev Suraski <zeev****@zend*****> + + * zend.c + zend.h + zend_API.c + zend_compile.c + zend_compile.h + zend_execute.c + zend_globals.h + zend_hash.h + zend_language_parser.y + zend_language_scanner.l: + - Implement public/protected/private methods. + - Prevent instantiation of classes with abstract methods. + Based in part on Marcus's patch. + +2002-12-01 Andi Gutmans <andi****@zend*****> + + * zend_alloc.c: + - Allow enabling of memory cache with zend_mm + + * zend.c + zend.c + zend.h + zend.h + zend_builtin_functions.c + zend_builtin_functions.c: + - MFZE1 + + * zend.c + zend.h + zend_builtin_functions.c: + - Revert as the patch doesn't compile + + * zend.c + zend_API.c + zend_builtin_functions.c + zend_compile.c + zend_execute.c + zend_execute_API.c + zend_indent.c + zend_object_handlers.c + zend_opcode.c + zend_operators.c + zend_operators.h + zend_variables.c: + h WHitespace + + * zend.c: + - Initialize constants_updated (by Marcus) + + * zend_builtin_functions.c: + - Nuke use of deprecated macro + + * zend_compile.c + zend_compile.h + zend_execute.c + zend_language_parser.y: + - FN_IS_STATIC -> FN_STATIC + + * zend.c: + - Fix crash + + * zend_compile.c + zend_compile.h: + - My personal cleanups + + * zend_API.c + zend_API.h + zend_builtin_functions.c + zend_compile.c + zend_compile.h + zend_execute.c + zend_execute.h + zend_language_parser.y + zend_object_handlers.c: + - Commit Marcus' cleanup of abstract and static inheritance and improve + - error messages + +2002-11-22 Derick Rethans <d.ret****@jdime*****> + + * zend_API.c: + - Initialize all functions to non-static (patch by Marcus B〓rger + <marcu****@t-onl*****>. + +2002-11-22 Sebastian Bergmann <sb****@sebas*****> + + * zend_execute.c: + Show class name as well. Patch by Marcus B〓rger. + + * zend_execute.c: + Show the name of the abstract method in the error. + + * zend_compile.h: + Fix prototype. + +2002-11-20 Derick Rethans <d.ret****@jdime*****> + + * zend_builtin_functions.c: + - MFZE1: Disable leak() and crash() when not using debug mode + +2002-11-20 Andi Gutmans <andi****@zend*****> + + * ZEND_CHANGES: + - Add abstract methods + + * zend_compile.c + zend_compile.h + zend_execute.c + zend_language_parser.y + zend_language_scanner.l: + - Fix build (thanks Marcus) + - Implement abstract methods, syntax: + - abstract function foo($vars); + - I don't see any reason why modifiers such as static/public need to be + - used with abstract. PHP is weakly typed and there would be no meaning to + - this anyway. People who want a strictly typed compiled language are + - looking in the wrong place. + +2002-11-19 Zeev Suraski <zeev****@zend*****> + + * zend.c + zend.h + zend_builtin_functions.c + zend_execute.c + zend_execute_API.c: + MFZE1 - error_reporting fix + +2002-11-18 Andi Gutmans <andi****@zend*****> + + * zend_language_scanner.l: + - MFZE1 + +2002-11-17 Stanislav Malyshev <stas****@zend*****> + + * zend_execute.c: + fix the leak + +2002-11-16 Andi Gutmans <andi****@zend*****> + + * zend_language_scanner.l + zend_language_scanner.l: + - MFZE1 + + * Zend.m4 + configure.in: + - MFZE1 + + * zend_hash.c: + - Commit fix for bug #19566 (I think it's by Marcus :) + +2002-11-14 Andrei Zmievski <andre****@gravi*****> + + * zend_llist.h: + MFZE1 + +2002-11-13 Stanislav Malyshev <stas****@zend*****> + + * zend_execute.c: + semi-fix string offsets crash - now it doesn't crash, but still leaks + + * zend_object_handlers.c: + fix static + +2002-11-11 Andi Gutmans <andi****@zend*****> + + * ZEND_CHANGES: + - Update with statics + +2002-11-11 Sebastian Bergmann <sb****@sebas*****> + + * zend_execute.c: + Fugbix typo. + +2002-11-11 Ilia Alshanetsky <ilia****@proho*****> + + * zend.h: + MFZE1 + +2002-11-10 Andi Gutmans <andi****@zend*****> + + * zend_compile.c: + - MFZE1 + +2002-11-10 Stanislav Malyshev <stas****@zend*****> + + * zend_compile.c + zend_compile.h + zend_language_parser.y: + fix statics - make it behave like $this (fetch type "static") + Side effect: indirect references to statics won't work. + +2002-11-06 Sebastian Bergmann <sb****@sebas*****> + + * zend_execute.c: + Fix ZTS build. + +2002-11-06 Stanislav Malyshev <stas****@zend*****> + + * zend_execute.c: + fix zend_assign_to_object_op + +2002-11-05 Ilia Alshanetsky <ilia****@proho*****> + + * zend_language_scanner.l: + MFZE1 + +2002-11-05 Andi Gutmans <andi****@zend*****> + + * zend_compile.h: + - Shift around zend_op members + + * ZEND_CHANGES: + - A couple of updates + + * zend_compile.c + zend_compile.h + zend_execute.c + zend_language_parser.y: + - Add support for static methods. Basically methods which are defined as + - static don't have $this. That's the whole difference. + + * tests/zend2.php: + - $clone -> $that + + * zend_execute_API.c: + - Fix bug introduced with type change of free_op1/2 + + * zend_language_parser.y + zend_language_scanner.l: + - ATTENTION: Finally nuke old_function and cfunction. I think it is time + - to get rid of these BC notations. This is from the days of the move from + - PHP/FI 2 -> PHP 3 + +2002-11-05 Ilia Alshanetsky <ilia****@proho*****> + + * zend_hash.c: + Revert of previous patch. + +2002-11-05 Andi Gutmans <andi****@zend*****> + + * zend_compile.c + zend_objects.c: + - Change the automatically created variable $clone in __clone() to + - $that as discussed at the PHP Conference. If there are any objections + - alternative names please let me know. The reason for changing it from + - $clone is because $clone sounds as if it's the newly cloned object and + - not the old one. + +2002-11-05 Stanislav Malyshev <stas****@zend*****> + + * zend_compile.c + zend_compile.h: + avoid using 'class' in exported functions - it annoys c++ + +2002-11-05 Stig Bakken <ssb****@fast*****> + + * zend.c: + Fixed some special cases that were crashing for the exception default + handler. + +2002-11-04 Ilia Alshanetsky <ilia****@proho*****> + + * zend_compile.c: + Silence compiler warnings. + + * zend_hash.c: + If ordered is not set a random compiler assigned value of *p2 would be + used, + this patch fixes the problem by initializing *p2 to NULL. + + * zend_operators.c: + Silence compile warning, ctype.h is needed for tolower() function. + + * zend_language_scanner.l: + MFZE1 + +2002-11-02 Derick Rethans <d.ret****@jdime*****> + + * zend_language_scanner.l: + - Fix segfault when __CLASS__ was used outside a class definition + + * zend.c: + - MFZE1 + +2002-11-02 Ilia Alshanetsky <ilia****@proho*****> + + * zend_language_scanner.l: + MFZE1 (20214). + +2002-11-01 Andi Gutmans <andi****@zend*****> + + * zend_execute.c: - Fix unset($this->foo) + +2002-10-24 Andi Gutmans <andi****@zend*****> + + * zend_execute.c + zend_opcode.c: - Also tune jmpz_ex + + * zend_execute.c + zend_opcode.c + zend_compile.h: + - Improve performance of part of the jmps. More to follow. + +2002-10-23 Andi Gutmans <andi****@zend*****> + + * zend_execute.c + zend_compile.c: + - This might improve performance. Commiting it so that I can check it on + - Linux + + * zend_execute.c: + - Make Ts access a macro. I need this for my next patch which should + - improve performance but not sure yet if it will. + +2002-10-22 Andi Gutmans <andi****@zend*****> + + * zend_execute.c: - Nuke unused get_incdec_op() + - Nuke old comment + + * zend_compile.h + zend_execute.c + zend_globals.h: - Improve overall engine performance + + * zend_execute.c: - Fix bug reported by Daniel T. Gorski + +2002-10-21 Thies C. Arntzen <thies****@thies*****> + + * zend_builtin_functions.c: MFZE1 + +2002-10-20 Stanislav Malyshev <stas****@zend*****> + + * zend_object_handlers.c: looks like this message should go + + * zend_compile.c: Fix private handling + +2002-10-20 Sebastian Bergmann <sb****@sebas*****> + + * zend_highlight.c + zend_highlight.h: Sync zend_html_puts parameter list with Zend Engine 1. + +2002-10-19 Andi Gutmans <andi****@zend*****> + + * zend_compile.h: - Fix compile warning. + + * zend_opcode.c + zend_compile.h + zend_execute.c: - Improve opcode dispatching + +2002-10-18 Andi Gutmans <andi****@zend*****> + + * zend.c + zend_compile.c + zend_execute.c: + - Change opcode dispatch mechanism to use a function per opcode and use + - a lookup table using the opcode # to call the correct function. + - Still have lots of tuning to do. + + * zend_execute.c: - Cleanup + +2002-10-16 Sebastian Bergmann <sb****@sebas*****> + + * zend_execute.c: Fix ZTS build. + +2002-10-16 Stanislav Malyshev <stas****@zend*****> + + * zend_compile.c + zend_execute.c: Fix class static members: now the following code works: + <?php + + class Foo { + static $c = "Parent"; + } + + class Child extends Foo { + } + + Foo::$c = "Hello"; + + var_dump(Child::$c); + ?> + and returns "Hello" (class statics are not copied anymore, but looked up in + runtime) + + * zend_compile.c + zend_compile.h + zend_execute.c: Fix and generalize $this handling. + ZEND_FETCH_FROM_THIS is removed, IS_UNUSED type on class variables will be + used instead as the sign that it's a fetch from $this + +2002-10-14 Ilia Alshanetsky <ilia****@proho*****> + + * zend_ini_parser.y + zend_ini_scanner.l + zend_globals.h: MFZE1 + +2002-10-14 Andi Gutmans <andi****@zend*****> + + * zend_execute.c + zend_language_parser.y: - Support new classname::$class_name, e.g.: + <? + + class foo::bar { + public $hello = "Hello, World\n"; + } + + $name = "bar"; + $obj = new foo::$name; + print $obj->hello; + ?> + +2002-10-13 Ilia Alshanetsky <ilia****@proho*****> + + * zend_extensions.h: Increased the API number. (re: floats patch) + +2002-10-12 Ilia Alshanetsky <ilia****@proho*****> + + * zend_operators.c + zend_operators.h + zend.c + zend_execute_API.c + zend_globals.h: MFZE1 (floats & locale issue) + +2002-10-10 Sebastian Bergmann <sb****@sebas*****> + + * ZEND_CHANGES: Fugbix typo. + +2002-10-10 Stanislav Malyshev <stas****@zend*****> + + * zend_object_handlers.c: add comment + + * zend_object_handlers.c: fix memory leaks + +2002-10-09 Stanislav Malyshev <stas****@zend*****> + + * zend_object_handlers.c: Fix object write handler behaviour: + * If this value is already set to given value, don't try to set it again. + * If we have reference, we should not move it. + * If we are assigning referenced variable, we should separate it. + +2002-10-09 Ilia Alshanetsky <ilia****@proho*****> + + * zend_API.c + zend_builtin_functions.c + zend_compile.c + zend_constants.c + zend_execute.c + zend_execute_API.c + zend_language_parser.y + zend_object_handlers.c + zend_operators.c + zend_operators.h: MFZE1 zend_str_tolower issue. + +2002-10-07 Andi Gutmans <andi****@zend*****> + + * tests/zend2.php: - Fix test + + * zend_execute.c: + - Require $this-> when calling a methods. This whole automatic lookup + - first in the class and then in the global scope is confusing, slow and + - not quite BC compatible. + + * zend.c + zend_compile.c + zend_globals.h: + - Allow access to private/protected variables of $clone inside the __clone() + - method + +2002-10-06 Andi Gutmans <andi****@zend*****> + + * zend_execute.c: - Fix problem with unsetting object members. + +2002-10-01 Andi Gutmans <andi****@zend*****> + + * zend_language_parser.y: + - Fix problem when crashing on illegal tokens in class name during class + - definition. + +2002-09-30 Derick Rethans <d.ret****@jdime*****> + + * ZEND_CHANGES: - No tabs :) + +2002-09-28 Derick Rethans <d.ret****@jdime*****> + + * zend_builtin_functions.c: - Fix for defines... + + * zend_builtin_functions.c: - Fix build in non-ZTS mode + +2002-09-26 Ilia Alshanetsky <ilia****@proho*****> + + * zend_API.c + zend_builtin_functions.c + zend_compile.c + zend_constants.c + zend_execute.c + zend_execute_API.c + zend_language_parser.y + zend_object_handlers.c + zend_operators.c + zend_operators.h: MFZE1 + +2002-09-25 Stanislav Malyshev <stas****@zend*****> + + * zend_extensions.h: + Propmote API NO year, so that it will never be the same as ZE1 API NO + +2002-09-24 Andi Gutmans <andi****@zend*****> + + * zend_compile.c: - Fix leak + + * zend_language_parser.y + zend_compile.c + zend_compile.h + zend_execute.c: + - Megapatch to try and support inheritance from sub-classes. Things might + - be *very* buggy now so don't get too upset if that happens. + - I still need to improve some stuff but it's a good step (hopefully). + +2002-09-23 Andi Gutmans <andi****@zend*****> + + * zend_globals.h + zend_ini.c + zend_language_parser.y: - MFZE1. + +2002-09-21 Andi Gutmans <andi****@zend*****> + + * zend_extensions.h: - Someone screwed this up. + +2002-09-19 Derick Rethans <d.ret****@jdime*****> + + * zend_ini.c: - Make Colin happy + +2002-09-19 Zeev Suraski <zeev****@zend*****> + + * zend.c + zend.h + zend_execute_API.c: MFZE1 - connection_status() fix + + * zend.c: Fix non ZTS build + + * zend.c: Fix that obscure crash in Debug_TS mode + +2002-09-18 Zeev Suraski <zeev****@zend*****> + + * zend.c: + Fix the thread-safe initialization of the ZE2. This should solve some + sporadic crashes, as well as the problem with the built-in constants. + + * zend_constants.c: Remove dead code + + * zend_builtin_functions.c: Add useful debugging function + +2002-09-17 Zeev Suraski <zeev****@zend*****> + + * zend_hash.c + zend_hash.h: Add tracking for hashtable allocation + + * zend.c: ZE2 fix + + * zend_compile.c: whitespace + + * zend.c + zend.h: MFZE1 - threading fix + +2002-09-16 Andrei Zmievski <andre****@php*****> + + * zend_API.h + zend_builtin_functions.c + zend_API.c + zend_execute_API.c: MFZE1 + +2002-09-15 Ilia Alshanetsky <ilia****@proho*****> + + * zend_highlight.c: Make zend actually strip comments. Bug #18151 + + * zend.c: + Make zend return a proper exit error code when it encounters a parse error. + +2002-09-15 Andi Gutmans <andi****@zend*****> + + * zend_compile.c: + - Hopefully fix problem with __autoload not working well with inherited classes. + - There might still be some weird situations I haven't thought of. + + * zend_list.c + zend_execute.c: - WS fix - "while (" instead of "while(" + + * zend_execute_API.c + zend_ini.c + zend_list.c + zend_object_handlers.c + zend_objects_API.c + zend_operators.c + zend_API.c + zend_builtin_functions.c + zend_compile.c + zend_execute.c: - WS - Always use "if (" and not "if(" + + * zend_execute_API.c: - WS + +2002-09-10 Stanislav Malyshev <stas****@zend*****> + + * zend_execute_API.c + zend_variables.c: MFZE1 + +2002-09-09 Stanislav Malyshev <stas****@zend*****> + + * zend_object_handlers.c: remove comment + +2002-09-08 Andi Gutmans <andi****@zend*****> + + * zend.h: - Prepare for alpha 3 + +2002-09-05 Stanislav Malyshev <stas****@zend*****> + + * zend_compile.c: quick-n-dirty inheritance support for __handlers + +2002-09-04 Sebastian Bergmann <sb****@sebas*****> + + * ZEND_CHANGES: Whitespace fixes. + +2002-09-04 Stanislav Malyshev <stas****@zend*****> + + * zend_object_handlers.c: remove dead code + + * ZEND_CHANGES + zend_object_handlers.c: Fix __call and add some docs + +2002-09-04 Sebastian Bergmann <sb****@sebas*****> + + * zend_object_handlers.c: Fix ZTS build. + + * ZEND_CHANGES: TBD: __call(), __get(), __set(). + +2002-09-04 Stanislav Malyshev <stas****@zend*****> + + * zend.h + zend_compile.c + zend_compile.h + zend_execute.c + zend_extensions.h + zend_object_handlers.c + zend_objects.c: Support for __get, __set and __call in classes. + This should work as follows: if class hasn't member with given name, + __get/__set is called. If class has no method with given name, __call is called. + __get/__set are not recursive, __call can be. + +2002-09-04 Sebastian Bergmann <sb****@sebas*****> + + * ZEND_CHANGES: Workaround for superfluous comma in var_export() result. + + * ZEND_CHANGES: + Let debug_backtrace() example print out the class name, if applicable, and the function/method arguments. + +2002-09-03 Thies C. Arntzen <thies****@thies*****> + + * zend_builtin_functions.c: nuke warning + + * zend_builtin_functions.c: nuke unneeded stuff + +2002-09-03 Zeev Suraski <zeev****@zend*****> + + * zend.c + zend.h + zend_ini.c: MFZE1 + +2002-09-03 Derick Rethans <d.ret****@jdime*****> + + * zend_ini.c: - Revert + + * zend_ini.c: + - MFH for: Apply rest of html errors fix (Patch by Jan Lehnardt <jan****@php*****>) + +2002-09-03 Sebastian Bergmann <sb****@sebas*****> + + * zend.h: + Add html_errors to zend_utility_values. Patch by Jan Lehnardt <jan****@php*****>. + +2002-09-03 Andi Gutmans <andi****@zend*****> + + * zend_builtin_functions.c: - Fix typo + +2002-09-02 Thies C. Arntzen <thies****@thies*****> + + * zend_builtin_functions.c: + refine last patch. if the argument-stack is not consistent don't try to show + arguments. no call to zend_error is made as we might end up in an infinite + recursion if called from an error_handler. + so: if the arguments to functions aren't shown in debug_backtrace this is 'cause + the arument stack was not consistent when debug_backtrace was called. + + * zend_builtin_functions.c: + debug_backtrace() now checks the complete argument-stack for consistency. + +2002-09-02 Stanislav Malyshev <stas****@zend*****> + + * zend_execute.c: MFZE1 + +2002-09-01 Andi Gutmans <andi****@zend*****> + + * zend_llist.c: - Fix leak reported by "l0t3k" <cshmo****@hotma*****> + +2002-09-01 Stanislav Malyshev <stas****@zend*****> + + * zend_operators.c: MFZE1 + +2002-08-28 Thies Arntzen <thies****@pb1*****> + + * zend_builtin_functions.c + zend_execute_API.c: debug_backtrace() + - make args passed to functions called vy call_user_function available again. + + * zend_builtin_functions.c: debug_backtrace(): + - make args work if called from the error_handler + - fix refcount for args + + * zend.c: + clear current_execute_data on bailout as it would point into some freed area + on the stack. + +2002-08-28 derick <deric****@pb1*****> + + * zend.c: - MFZE1 + +2002-08-26 Thies Arntzen <thies****@pb1*****> + + * zend_builtin_functions.c: + debug_backtrace(): show name of included file for include and require calls + plus some small fixes suggested by andi. + +2002-08-24 Andi Gutmans <andi****@pb1*****> + + * zend_builtin_functions.c: - Whitespace + + * zend_builtin_functions.c: - Whitespace and better variable name + +2002-08-24 Thies Arntzen <thies****@pb1*****> + + * zend_builtin_functions.c: fix warning + +2002-08-23 Andi Gutmans <andi****@pb1*****> + + * Zend.m4: - Add \n to configure fprintf + + * zend_extensions.c: - dlerror -> DL_ERROR + +2002-08-23 Thies Arntzen <thies****@pb1*****> + + * zend_builtin_functions.c: + debug_backtrace: show include/require/eval as normal functions on the stack + +2002-08-23 derick <deric****@pb1*****> + + * zend_builtin_functions.c: - No spaces :) + +2002-08-23 Thies Arntzen <thies****@pb1*****> + + * zend_builtin_functions.c: + - debug_backtrace now also returns an array containing the arguments of the + called function. + + zeev, andi - is knowing the structure of the stack considered a bad thing in + zend_builtin_function? if yes i would have to create a new function in + zend_ptr_stack.c (but i think we are save this way) + + * zend_builtin_functions.c + zend_execute_API.c: - debug_backtrace: + added "type" ('->' or '::') for object calls. + made calls done thru call_user_func show-up correct in backtraces. + + andi, + does this look correct to you? + + * zend_execute.c: those are set by RETURN_FROM_EXECUTE + +2002-08-21 Thies Arntzen <thies****@pb1*****> + + * zend_execute.c: + zend_execute: make sure that current_execute_data points to the right thing + after coming back from recursion. + +2002-08-19 Zeev Suraski <zeev****@pb1*****> + + * zend_operators.c: MFZE1 + +2002-08-17 Andi Gutmans <andi****@pb1*****> + + * zend_execute.c: MFZE1 + +2002-08-17 Zeev Suraski <zeev****@pb1*****> + + * zend_execute.c + zend_hash.c: MFZE1 + +2002-08-16 Stig Bakken <ssb****@pb1*****> + + * zend.c: * append emacs footer + + * zend.c: * remove builtin exception class + +2002-08-16 Andi Gutmans <andi****@pb1*****> + + * zend.c: - Fix whitespace + +2002-08-16 Stig Bakken <ssb****@pb1*****> + + * zend_execute_API.c + zend_globals.h + zend.c + zend_builtin_functions.c: + - Added set_exception_handler() function for registering a global, + catch-all exception handling function + - Added set_exception_handler() function for registering a global, + catch-all exception handling function (Stig) + +2002-08-15 Zeev Suraski <zeev****@pb1*****> + + * flex.skl + zend.c + zend_globals.h + zend_language_scanner.l: MFZE1 + +2002-08-14 jason <jason****@pb1*****> + + * zend_compile.c + zend_compile.h + zend_globals.h + zend_language_parser.y: + MFZE1 (use token instead of global for opcode counting) + +2002-08-13 Andi Gutmans <andi****@pb1*****> + + * zend_execute_API.c: + - Fix crash when exception is raised in __autoload function + +2002-08-13 Zeev Suraski <zeev****@pb1*****> + + * zend.h: MFZE1 + +2002-08-08 sebastian <sebas****@pb1*****> + + * zend_objects.c: Fix warning. + +2002-08-08 stas <stas****@pb1*****> + + * zend_objects.c + zend_objects.h + zend_objects_API.c + zend_objects_API.h: Add ZEND_API to functions + +2002-08-08 Andi Gutmans <andi****@pb1*****> + + * zend_compile.c + zend_compile.h + zend_execute.c + zend_language_parser.y + zend_language_scanner.l + zend_operators.c + zend_operators.h: + - Make new 'is' operator work with classes only and return false when + - the object isn't of the said class or the value isn't an object. + + * zend_static_allocator.c: - Bad Harald! :) + +2002-08-08 Zeev Suraski <zeev****@pb1*****> + + * zend_alloc.c: MFZE1 + +2002-08-07 phanto <phant****@pb1*****> + + * zend_static_allocator.c + zend_alloc.c + zend_config.w32.h + zend_hash.c + zend_ini.c + zend_llist.h + zend_mm.c + zend_operators.c: make win32 debug output more verbose + +2002-08-03 Andi Gutmans <andi****@pb1*****> + + * tests/zend2.php: - Small fix + +2002-08-03 Zeev Suraski <zeev****@pb1*****> + + * zend_execute.c: MFZE1 + +2002-08-01 stas <stas****@pb1*****> + + * zend_execute.c + zend_hash.c: MFZE1 + +2002-07-30 jason <jason****@pb1*****> + + * zend_compile.c + zend_execute.c + zend_globals.h: MFZE1 global declare + + * zend_compile.c: Fix segfault + +2002-07-30 Andrei Zmievski <andre****@pb1*****> + + * zend_compile.c + zend_compile.h + zend_execute.c + zend_language_parser.y + zend_language_scanner.l + zend_operators.c + zend_operators.h: + - Adding 'is' operator that can be used to check the type of a variable, + or its class. + +2002-07-28 phanto <phant****@pb1*****> + + * OBJECTS2_HOWTO: update the handlers struct + +2002-07-27 Andi Gutmans <andi****@pb1*****> + + * zend_compile.c + zend_execute_API.c: + - Make sure classes are first looked for in the current scope. + - Make sure that during inheritance the global scope is searched if the + - current one doesn't work. + +2002-07-26 Andi Gutmans <andi****@pb1*****> + + * zend_execute.c + zend.c + zend_builtin_functions.c + zend_compile.h: + - Fix problem with debug_backtrace() reported by Stig. We weren't reporting + - global function information because it wasn't available. We have to do + - an additional assignment per-function call so that it'll be available. + - Also don't define the global scope as function name _main_ but leave it + - empty so that frameworks like Pear can decide what they want to do. + +2002-07-25 sniper <snipe****@pb1*****> + + * Zend.m4: Fixed 3 major failures in this test: + + 1. Tests work better when they are actually run.. + 2. When file is opened, it should be closed sometime too. + 3. AC_TRY_RUN cleans after itself (rm -f conftest.*), so it's + good idea to read the values while the file still exists. + + +2002-07-24 Andi Gutmans <andi****@pb1*****> + + * zend_mm.c: - Fix some compile problems with the new configure checks. + +2002-07-24 James Cox <imaje****@pb1*****> + + * Zend.m4 + zend_mm.c: move testing for the alignment values into configure. + + * Zend.m4: ws fixes. + +2002-07-23 Andi Gutmans <andi****@pb1*****> + + * zend_hash.c: - Fix WS. + +2002-07-21 Andi Gutmans <andi****@pb1*****> + + * zend_compile.c: + - Fix bug reported by Sebastian where old constructors didn't work in + - nested classes. + +2002-07-18 derick <deric****@pb1*****> + + * zend.h + zend_extensions.c: - MFZE1 - MacOSX fixes by Marko Karppinen + +2002-07-17 Andi Gutmans <andi****@pb1*****> + + * zend_compile.c: + - Remove code which wasn't supposed to go into the patch. + + * zend_compile.c + zend_language_parser.y: - Rejuggle some code. + +2002-07-17 sniper <snipe****@pb1*****> + + * ZEND_CHANGES: This was mentioned already above (with an example too :) + +2002-07-16 Andi Gutmans <andi****@pb1*****> + + * ZEND_CHANGES: - Before I forget to list it, this was also added. + + * zend_language_scanner.l: + - Syntactic sugar - Add "public" as a synonym for "var". + - Now we have the three P's. + You can do: + + <? + class MyClass { + public $a; + private $b; + protected $c; + } + + ?> + +2002-07-15 derick <deric****@pb1*****> + + * zend_operators.c: - MFH of the crap removal + +2002-07-15 Andi Gutmans <andi****@pb1*****> + + * ZEND_CHANGES + zend.c + zend.h + zend_API.c + zend_compile.c + zend_language_parser.y + zend_language_scanner.l + zend_opcode.c: + - Commit patch to support protected member variables (by Timm Friebe w/ + - some fixes by me). + - You can't access protected variables from outside the object. If you want + - to see a protected member from your ancestors you need to declare the + - member as protected in the class you want to use it in. You can't + - redeclare a protected variable as private nor the other way around. + + * zend_operators.c: + - Really implement bool increment/decrement as flip-flop. + +2002-07-14 Andi Gutmans <andi****@pb1*****> + + * zend_compile.c + zend_compile.h + zend_execute.c + zend_language_parser.y + zend_language_scanner.l + ZEND_CHANGES: + - Nuke delete(). It was a big mistake to introduce it and I finally + - understand why Java didn't do so. + - If you still want to control destruction of your object then either make + - sure you kill all references or create a destruction method which you + - call yourself. + + * zend_execute.c: - Nuke some unused code + +2002-07-14 derick <deric****@pb1*****> + + * zend_operators.c: MFZE1 + + * zend_operators.c: - MFZE1 + +2002-07-07 Andi Gutmans <andi****@zend*****> + + * zend_objects_API.c: - Path which should improve previous fix. + + * zend_objects_API.c: + - First try at solving problem with different objects being allocated the + - same id. + +2002-07-07 Stanislav Malyshev <stas****@zend*****> + + * zend_object_handlers.c: name length should be strlen+1 + +2002-07-07 Sebastian Bergmann <sb****@sebas*****> + + * zend_language_parser.y: + Allow for 'class Namespace::Bar extends Foo' syntax. Patch by Timm Friebe <theki****@theki*****>. + +2002-07-06 Andi Gutmans <andi****@zend*****> + + * zend_execute.c: + - Fix problem where scope was lost in nested function calls. + - Thanks to Timm Friebe for diving into this one. + +2002-07-06 Zeev Suraski <zeev****@zend*****> + + * zend_language_parser.y: spelling fix + +2002-07-05 Stig Bakken <ssb****@fast*****> + + * zend_builtin_functions.c: * folding fixes + +2002-07-01 Andi Gutmans <andi****@zend*****> + + * zend_compile.c: - Fix bug when acccessing $this not in class scope. + + * zend_objects.h + zend_objects.c: - Export zend_object_get_address() + +2002-06-30 Andi Gutmans <andi****@zend*****> + + * ZEND_CHANGES: - Remember to document autoload when I have time. + +2002-06-30 Derick Rethans <d.ret****@jdime*****> + + * zend_modules.h: - MFZE1 + +2002-06-29 Andi Gutmans <andi****@zend*****> + + * zend.h: - Get ready for alpha2 + + * zend_execute_API.c: - Invalid -> Undefined + + * zend_language_parser.y: - Add missing semi-colon. + + * zend_execute_API.c + zend_execute.c: - Improve some error messages. + + * zend_compile.c: - Revert previous fix. + + * zend_compile.c: - Change E_ERROR -> E_COMPILE_ERROR where needed. + + * zend_compile.c: + - Fix for bug #17882. We complain if the same method is declared twice. + + * zend.h + zend_operators.c: - Fix bug 15037 + - Bump version to alpha2-dev + +2002-06-28 Andi Gutmans <andi****@zend*****> + + * zend_operators.c: - WS fix + +2002-06-26 Andi Gutmans <andi****@zend*****> + + * zend_execute_API.c: + - Autoloading support based on patch from Ivan Ristic. + - Again I hope this feature ends up working well because if it doesn't we + - might need to nuke it. This only works for global scoped classes and it + - will never work for sub-classes so don't even ask!!!!! + - Just define an __autoload() function in the global scope and it will be + - called with the class name as the parameter if it doesn't manage to find + - the class. + + * zend_API.c + zend_builtin_functions.c + zend_mm.h: - Centralize global class fetch + + * zend_alloc.c + zend_execute.c: + - Fix problem with scope's not changing correctly during method calls. + - Reapply a tiny optimization to the allocator so that in non-debug mode + - we clean memory without detecting leaks. + +2002-06-24 Andi Gutmans <andi****@zend*****> + + * zend_fast_cache.h: + - MFZE1 (Turn off fast cache until we make sure it performs well.) + + * zend_alloc.c: - More fixes (warnings, bug fixes etc.) + + * zend_execute.c: + - Revert patch which checks at run-time if you're allowed to assign + - certain values by reference. + - We still need to find a solution for cases when this shouldn't be allowed + - as it might cause leaks. + + * zend_alloc.c: - Fix crash bug and clean up a bit. + +2002-06-24 Sebastian Bergmann <sb****@sebas*****> + + * Zend.m4: IMHO, ZTS should no longer be labeled experimental. + +2002-06-24 Andi Gutmans <andi****@zend*****> + + * zend_alloc.c: - MFZE1 + + * zend_alloc.c: - Don't use cache if we're using ZEND_MM + + * zend_mm.c: + - Hardcode alignment to 8. We might need a configure check for this. + + * zend_mm.c + zend_mm.h: - Improve memory manager to allocate small blocks quickly. + + * zend_alloc.h + zend_mm.h + zend_alloc.c: + - Don't keep allocated blocks in a linked list if we're in non-debug mode + - as now the memory manager takes care to nuke all leaking blocks. + + * zend.h + zend_types.h: - MFZE1 + +2002-06-23 Andi Gutmans <andi****@zend*****> + + * zend_compile.c + zend_execute.c: + - Fix problem with constructor not being inherited and called correctly. + + * zend_mm.c: - Fix small bug + + * zend_mm.c: + - Almost completely implement realloc(). It now resizes in place when + - possible. + +2002-06-22 Andi Gutmans <andi****@zend*****> + + * zend_alloc.c + zend_mm.c: - Fix crash when zend_mm_shutdown is called more than once. + + * zend_alloc.c + zend_alloc.h + zend_globals.h + zend_language_parser.y: - MFZE1 + + * zend_constants.h + zend_objects.c + zend_variables.c + zend_variables.h + zend_constants.c + zend_alloc.c + zend_alloc.h: - Nuke persist_alloc(). + +2002-06-19 Andi Gutmans <andi****@zend*****> + + * zend_globals.h: + - This was also supposed to be part of the previous ZEND_MM commit :) + + * zend_alloc.c: + - Oops, this was supposed to be part of the previous #ifdef ZEND_MM change + + * zend_mm.h: - Use #ifdef for ZEND_MM + + * zend_mm.c: - Make sure MAX is defined + + * zend_constants.c: + - Fix problem where you couldn't define constants with different cases but + - the same name. + +2002-06-18 Derick Rethans <d.ret****@jdime*****> + + * zend.c: - MFZE1 + +2002-06-17 Andi Gutmans <andi****@zend*****> + + * zend_mm.c: - Improve speed of alignment calculation + + * zend_mm.c + zend_mm.h + zend_alloc.c: + - Fix a bug and add code which frees actual allocated segments at the end + - of execution (this still doesn't work because some blocks remain + - referenced after the memory manager is killed. + + * zend_mm.c + zend_mm.h: - Save space per-allocated block. + +2002-06-16 Andi Gutmans <andi****@zend*****> + + * zend_execute.c + zend_execute.h + zend_execute_API.c: - Fix bug in class constants + - Start centralizing main class lookups. This will help implement + - __autload() + + * zend_mm.c + zend_mm.h: + - Remove debug code which doesn't work anymore and add headers. + + * zend_globals.h + zend_mm.c + zend_mm.h + zend_alloc.c + ZendTS.dsp: - Commit an initial version of a home made memory manager. + - It's just for seeing if this would be an advantage to PHP in MT + - environments. If this is to become production material there is still + - a long way to go. + +2002-06-15 Andi Gutmans <andi****@zend*****> + + * zend_objects.h + zend_objects_API.c: + - Fix copy&paste problem where we allocated according to an old structure + - decleration and not the new one. + +2002-06-11 Andi Gutmans <andi****@zend*****> + + * zend_builtin_functions.c: + - Don't show debug_backtrace() in the trace itself. + - This patch is a bit ugly because the whole code itself is pretty complex + - and hard to re-order. + + * zend_execute.c + zend_language_parser.y: + - Fix problem with assigning functions by reference. + +2002-06-11 Sebastian Bergmann <sb****@sebas*****> + + * RFCs/004.txt: Add __delegate(). + +2002-06-10 Harald Radi <haral****@nme*****> + + * zend_ts_hash.h + zend_ts_hash.c: added TS_HASH macro + +2002-06-10 Stanislav Malyshev <stas****@zend*****> + + * zend_execute.c: Fix leak + +2002-06-09 Harald Radi <haral****@nme*****> + + * zend_API.h + zend_builtin_functions.c + zend_object_handlers.h: + only check for an available class entry instead of + the std_object_handlers on some places + + +2002-06-08 Andi Gutmans <andi****@zend*****> + + * zend_hash.h + zend.h: - This should improve performance on Windows + + * zend_hash.h: + - Add a loop unrolled version of the hash function and a bit of an + - explanation about our hash function (Ralf S. Engelschall) + +2002-06-06 Sebastian Bergmann <sb****@sebas*****> + + * RFCs/004.txt: Add RFC on delegation. + +2002-06-05 Sebastian Bergmann <sb****@sebas*****> + + * zend_execute.c: Remove unused local variable. + +2002-06-05 Andi Gutmans <andi****@zend*****> + + * zend_compile.c + zend_execute.c + zend_object_handlers.c: + - Allow overloaded objects to receive the method name in its original + - case. + +2002-06-05 Derick Rethans <d.ret****@jdime*****> + + * zend_llist.c: - Fix memleak (patch by Stefan Sesser) + +2002-06-04 Derick Rethans <d.ret****@jdime*****> + + * zend_ini_scanner.l: - Fix for bug #17462 (Patch by Edin Kadribasic) + +2002-05-31 Andi Gutmans <andi****@zend*****> + + * ZendTS.dsp: - Add zend_objects_API.* to dsp + + * zend_objects_API.c: - Fix build (one more coming up) + + * zend_objects.c: - Fix build + +2002-05-31 Sebastian Bergmann <sb****@sebas*****> + + * Zend.dsp: Add zend_objects_API.c to project. + +2002-05-31 Stanislav Malyshev <stas****@zend*****> + + * Makefile.am + zend_execute_API.c + zend_globals.h + zend_object_handlers.c + zend_objects.c + zend_objects.h + zend_objects_API.c + zend_objects_API.h: Generalize object storage and reference bookkeeping + +2002-05-30 Venkat Raghavan S <rvenk****@novel*****> + + * zend.h + zend_config.nw.h + acconfig.h: NetWare changes + +2002-05-26 Andi Gutmans <andi****@zend*****> + + * zend_multibyte.c: + - Add empty zend_multibyte.c to allow build with 4.3.0-dev. + +2002-05-24 Sebastian Bergmann <sb****@sebas*****> + + * ZEND_CHANGES: Fugbix typo. + +2002-05-24 Andi Gutmans <andi****@zend*****> + + * ZEND_CHANGES: - Add a bit of information. + +2002-05-20 Zeev Suraski <zeev****@zend*****> + + * zend_API.h + zend_execute.h + zend_list.h: MFZE1 (Expose more C++ APIs) + 2002-05-14 Andi Gutmans <andi****@zend*****> * zend_objects.c 1.3 +2 -2 ZendEngine2/LICENSE Index: LICENSE =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/LICENSE,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- LICENSE 29 Apr 2002 02:25:26 -0000 1.2 +++ LICENSE 11 Feb 2003 02:40:18 -0000 1.3 @@ -1,6 +1,6 @@ -------------------------------------------------------------------- - The Zend Engine License, version 2.00 -Copyright (c) 1999-2002 Zend Technologies Ltd. All rights reserved. + The Zend Engine License, Version 2.00 +Copyright (c) 1999-2003 Zend Technologies Ltd. All rights reserved. -------------------------------------------------------------------- Redistribution and use in source and binary forms, with or without 1.5 +2 -1 ZendEngine2/Makefile.am Index: Makefile.am =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/Makefile.am,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- Makefile.am 3 Aug 2002 08:56:16 -0000 1.4 +++ Makefile.am 11 Feb 2003 02:40:18 -0000 1.5 @@ -13,7 +13,8 @@ zend_opcode.c zend_operators.c zend_ptr_stack.c zend_stack.c \ zend_variables.c zend.c zend_API.c zend_extensions.c zend_hash.c \ zend_list.c zend_indent.c zend_builtin_functions.c zend_sprintf.c \ - zend_ini.c zend_qsort.c zend_objects.c zend_object_handlers.c + zend_ini.c zend_qsort.c zend_objects.c zend_object_handlers.c \ + zend_object_API.c libZend_la_LDFLAGS = libZend_la_LIBADD = @ZEND_EXTRA_LIBS@ 1.3 +7 -2 ZendEngine2/OBJECTS2_HOWTO Index: OBJECTS2_HOWTO =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/OBJECTS2_HOWTO,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- OBJECTS2_HOWTO 29 Apr 2002 02:25:26 -0000 1.2 +++ OBJECTS2_HOWTO 11 Feb 2003 02:40:18 -0000 1.3 @@ -101,8 +101,10 @@ Objects - reflection -------------------- -get_class_name is used to retrieve class name of the object. No other -reflection functions are currently implemented. +get_class_name is used to retrieve class name of the object. +get_class_entry returns class entry (zend_class_entry) for the object, +in case there exists PHP class for it. +No other reflection functions are currently implemented. Objects - data structures and handlers --------------------------------------- @@ -135,6 +137,7 @@ zend_object_get_method_t get_method; zend_object_call_method_t call_method; zend_object_get_constructor_t get_constructor; + zend_object_get_class_entry_t get_class_entry; zend_object_get_class_name_t get_class_name; zend_object_compare_t compare_objects; } zend_object_handlers; @@ -184,6 +187,8 @@ for any other PHP internal function). get_constructor - get description for the object constructor method + +get_class_entry - should return the class entry for the object get_class_name - get the name of the class the object belongs to 1.6 +149 -83 ZendEngine2/ZEND_CHANGES Index: ZEND_CHANGES =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/ZEND_CHANGES,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- ZEND_CHANGES 3 Aug 2002 08:56:16 -0000 1.5 +++ ZEND_CHANGES 11 Feb 2003 02:40:18 -0000 1.6 @@ -19,47 +19,60 @@ the box or after a very small amount of modifications would be high. - [Not sure if the following will be implemented after all] - To simplify migration, the Zend Engine 2.0 supports an optional - 'auto-clone' feature, which performs a cloning of the object - whenever it would have been copied in the Zend Engine 1.0. - Optionally, it emits an E_NOTICE message whenever such an - automatic clone occurs, in order to allow developers to - gradually migrate to the behavior of the Zend Engine 2 (without - automatic clones). - - * Private Members. - - The Zend Engine 2.0 introduces private member variables. Note - that for performance reasons no error message is emitted in - case of an illegal access to a private member variable. + * Private and Protected Members. + + The Zend Engine 2.0 introduces private and protected member + variables. Note that for performance reasons no error message is + emitted in case of an illegal access to a private or protectecd + member variable. Example: <?php class MyClass { private $Hello = "Hello, World!\n"; + protected $Bar = "Hello, Foo!\n"; + protected $Foo = "Hello, Bar!\n"; function printHello() { - print $this->Hello; + print "MyClass::printHello() " . $this->Hello; + print "MyClass::printHello() " . $this->Bar; + print "MyClass::printHello() " . $this->Foo; } } class MyClass2 extends MyClass { + protected $Foo; + function printHello() { - MyClass::printHello(); /* Should print */ - print $this->Hello; /* Shouldn't print out anything */ + MyClass::printHello(); /* Should print */ + print "MyClass2::printHello() " . $this->Hello; /* Shouldn't print out anything */ + print "MyClass2::printHello() " . $this->Bar; /* Shouldn't print (not declared)*/ + print "MyClass2::printHello() " . $this->Foo; /* Should print */ } } $obj = new MyClass(); print $obj->Hello; /* Shouldn't print out anything */ + print $obj->Bar; /* Shouldn't print out anything */ + print $obj->Foo; /* Shouldn't print out anything */ $obj->printHello(); /* Should print */ $obj = new MyClass2(); print $obj->Hello; /* Shouldn't print out anything */ + print $obj->Bar; /* Shouldn't print out anything */ + print $obj->Foo; /* Shouldn't print out anything */ $obj->printHello(); ?> + + Protected member variables can be accessed in classes extending the + class they are declared in, whereas private member variables can + only be accessed by the class they belong to. + + Note: Protected member variables have to be declared in every class + they are used! + + * Private and protected methods. (TBD) * Object Cloning. @@ -68,18 +81,18 @@ duplication, the Zend Engine 1.0 did a bitwise copy making an identical replica of all the object's properties. - Creating a copy of an object with fully replicated properties is - not always the wanted behavior. A good example of the need for + Creating a copy of an object with fully replicated properties is + not always the wanted behavior. A good example of the need for copy constructors, is if you have an object which represents a GTK window and the object holds the resource of this GTK window, when you create a duplicate you might want to create a new window with the same properties and have the new object hold the - resource of the new window. Another example is if your object - holds a reference to another object which it uses and when you - replicate the parent object you want to create a new instance of + resource of the new window. Another example is if your object + holds a reference to another object which it uses and when you + replicate the parent object you want to create a new instance of this other object so that the replica has its own separate copy. - An object copy is created by calling the object's __clone() + An object copy is created by calling the object's __clone() method. Example: @@ -88,15 +101,15 @@ $copy_of_object = $object->__clone(); ?> - When the developer asks to create a new copy of an object, the - Zend Engine will check if a __clone() method has been defined or - not. If not, it will call a default __clone() which will copy - all of the object's properties. If a __clone() method is - defined, then it will be responsible to set the necessary - properties in the created object. For convenience, the engine - will supply a function that imports all of the properties from - the source object, so that they can start with a by-value - replica of the source object, and only override properties that + When the developer asks to create a new copy of an object, the + Zend Engine will check if a __clone() method has been defined or + not. If not, it will call a default __clone() which will copy + all of the object's properties. If a __clone() method is + defined, then it will be responsible to set the necessary + properties in the created object. For convenience, the engine + will supply a function that imports all of the properties from + the source object, so that they can start with a by-value + replica of the source object, and only override properties that need to be changed. [The function hasn't been implemented yet] Example: @@ -110,7 +123,7 @@ } function __clone() { - $this->name = $clone->name; + $this->name = $that->name; $this->address = 'New York'; $this->id = self::$id++; } @@ -130,20 +143,7 @@ print $obj->address . "\n"; ?> - * Forced deletion of objects. - - The Zend Engine 1.0 had no means to force deletion of an object - if there are still references to it. The newly introduced delete - statement calls the object's destructor and frees it even if the - object is referenced by some other places in the engine. Other - references to the deleted object become stale and trying to - access them results in a fatal error. - - Note that if you have a user-defined function delete() in an old - script, this script will yield a parser error with the Zend - Engine 2.0, since 'delete' is now a reserved word. - - * Namespaces. + * Nested classes (namespaces). The Zend Engine 1.0 provided only three scopes: the global scope, the class scope and the function scope. All scopes but @@ -153,21 +153,31 @@ Zend Engine 1.0's scoping methods were inherently limited for solving symbol name collision problems. - The Zend Engine 2.0 introduces the concept of namespaces to - manage the symbol collision problem by making it possible to + The Zend Engine 2.0 introduces the concept of nested classes + to solve the symbol collision problem by making it possible to define multiple symbol tables able to contain all types of - symbols. The Zend Engine is aware of a current namespace, - defaulting to the current global one. The current namespace may - be changed on a file-by-file basis. Symbols in other namespaces - than the current one may be referenced using a new namespace - operator. - - Namespaces and classes are the same with the Zend Engine 2.0, - except that you can't instantiate a namespace with "new". This - essentially also makes a class a namespace, so the scoping rules - for namespaces apply for classes. Some of the consequences of - this are: [Not finalized. Right now we basically have nested - classes so you can instantiate any nested class] + symbols. The Zend Engine is aware of a current class, + defaulting to the global scope. Each class can contain it's + own set of constants, functions and static variables. In order + to access a class's local symbols you can use the self:: class + accessor, for example, you can do self::$my_static_name = "Hello". + You can also use the class's name such as + MyClass::$my_static_name = "Hello". With both constants and + functions, if you don't specify a class context the current class + will be searched first and if the search fails then the global + scope will be searched. If you want to force PHP to only check the + global scope you can use the main:: accessor. For example, + main::strlen() to make sure you're calling the strlen() in the main + scope. You will only need to worry about this if you are defining + methods which have the same name as global functions. For + constants you can use the same notation such as self::MY_CONSTANT + or main::MY_CONSTANT. + Sometimes you will not want to access constants, functions or classes + via the class accessor (i.e. MyClass::) because you use them very + often and are an extremely slow typist. In this case, you can import + functions, classes and constants from classes with the import keyword. + It's quite self explanatory and there are a few examples below. + * Classes may contain classes. @@ -188,7 +198,7 @@ function db_connect($user) { print "Connecting to Oracle database '$this->host' as $user\n"; } - } + } $MySQL_obj = new DB::MySQL(); $MySQL_obj->db_connect('Susan'); @@ -252,7 +262,7 @@ $obj->foo(); ?> - This prints "foobar" two times, since a bar() method exists + This prints "foobar" two times, since a bar() method exists in the current namespace. * It is possible to "import" symbols from one namespace into @@ -307,7 +317,7 @@ class MyOuterClass { const Hello = "Hello, World\n"; } - + import const Hello from MyOuterClass; print Hello; ?> @@ -339,14 +349,14 @@ <?php class BaseClass { function __construct() { - print "In BaseClass constructor\n"; + print "In BaseClass constructor\n"; } } class SubClass extends BaseClass { function __construct() { parent::__construct(); - print "In SubClass constructor\n"; + print "In SubClass constructor\n"; } } @@ -389,7 +399,7 @@ function __destruct() { print 'Destroying ' . $this->name . "\n"; - } + } } $obj = new MyDestructableClass(); @@ -441,20 +451,20 @@ Old code that has no user-defined functions 'catch', 'throw' and 'try' will run without modifications. - * Derefencing objects returned from functions. + * Dereferencing objects returned from functions. Example: <?php class Circle { function draw() { - print "Circle\n"; + print "Circle\n"; } } class Square { function draw() { - print "Square\n"; + print "Square\n"; } } @@ -476,12 +486,25 @@ <?php class foo { - static $my_static = 5; + static $my_static = 5; } print foo::$my_static; ?> + * Static methods. (TBD) + + * Abstract methods. (TBD) + + * instanceof (TBD) + + * Static function variables. + + Statics are now treated at compile-time which allows developers + to assign variables to statics by reference. This change also + greatly improves their performance but means that indirect + references to statics will not work anymore. + * Parameters that are passed by reference to a function may now have default values. @@ -495,23 +518,66 @@ } ?> - * Built-In Backtracing. + * __autoload(). TBD. - Example: + * Method calls and property accesses can be overloaded + by class methods __call(), __get() and __set(). + + __get() and __set() Example: <?php - $backtrace = debug_backtrace(); + class Setter { + public $n; + public $x = array('a' => 1, 'b' => 2, 'c' => 3); + + function __get($nm) { + print "Getting [$nm]\n"; + + if(isset($this->x[$nm])) { + $r = $this->x[$nm]; + print "Returning: $r\n"; + return $r; + } else { + print "Nothing!\n"; + } + } - foreach ($backtrace as $step) { - $class = isset($step['class']) ? $step['class'] . '::' : ''; + function __set($nm, $val) { + print "Setting [$nm] to $val\n"; - printf( - "%s [%s:%s]\n", - $step['function'], - $step['file'], - $step['line'] - ); - } + if(isset($this->x[$nm])) { + $this->x[$nm] = $val; + print "OK!\n"; + } else { + print "Not OK!\n"; + } + } + } + + $foo = new Setter(); + $foo->n = 1; + $foo->a = 100; + $foo->a++; + $foo->z++; + var_dump($foo); + ?> + + __call() Example: + + <?php + class Caller { + var $x = array(1, 2, 3); + + function __call($m, $a) { + print "Method $m called:\n"; + var_dump($a); + return $this->x; + } + } + + $foo = new Caller(); + $a = $foo->test(1, '2', 3.4, true); + var_dump($a); ?> 1.5 +4 -0 ZendEngine2/Zend.dsp Index: Zend.dsp =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/Zend.dsp,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- Zend.dsp 3 Aug 2002 08:56:16 -0000 1.4 +++ Zend.dsp 11 Feb 2003 02:40:18 -0000 1.5 @@ -187,6 +187,10 @@ # End Source File # Begin Source File +SOURCE=.\zend_objects_API.c +# End Source File +# Begin Source File + SOURCE=.\zend_opcode.c # End Source File # Begin Source File 1.5 +58 -24 ZendEngine2/Zend.m4 Index: Zend.m4 =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/Zend.m4,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- Zend.m4 3 Aug 2002 08:56:16 -0000 1.4 +++ Zend.m4 11 Feb 2003 02:40:18 -0000 1.5 @@ -1,5 +1,5 @@ dnl -dnl $Id: Zend.m4,v 1.30 2002/04/22 11:06:22 sebastian Exp $ +dnl $Id: Zend.m4,v 1.37 2003/01/19 21:37:01 zeev Exp $ dnl dnl This file contains Zend specific autoconf functions. dnl @@ -57,9 +57,12 @@ AC_TYPE_SIZE_T AC_TYPE_SIGNAL +AC_DEFUN(LIBZEND_LIBDL_CHECKS,[ AC_CHECK_LIB(dl, dlopen, [LIBS="-ldl $LIBS"]) AC_CHECK_FUNC(dlopen,[AC_DEFINE(HAVE_LIBDL, 1,[ ])]) +]) +AC_DEFUN(LIBZEND_DLSYM_CHECK,[ dnl dnl Ugly hack to check if dlsym() requires a leading underscore in symbol name. dnl @@ -72,12 +75,12 @@ ], [ AC_MSG_RESULT(no) ], []) +]) dnl This is required for QNX and may be some BSD derived systems AC_CHECK_TYPE( uint, unsigned int ) AC_CHECK_TYPE( ulong, unsigned long ) - dnl Checks for library functions. AC_FUNC_VPRINTF AC_FUNC_MEMCMP @@ -91,10 +94,6 @@ ]) - - - - AC_DEFUN(LIBZEND_ENABLE_DEBUG,[ AC_ARG_ENABLE(debug, @@ -106,24 +105,13 @@ ]) - - - - - - - - - - - AC_DEFUN(LIBZEND_OTHER_CHECKS,[ -AC_ARG_ENABLE(experimental-zts, -[ --enable-experimental-zts This will most likely break your build],[ - ZEND_EXPERIMENTAL_ZTS=$enableval +AC_ARG_ENABLE(maintainer-zts, +[ --enable-maintainer-zts Enable thread safety - for code maintainers only],[ + ZEND_MAINTAINER_ZTS=$enableval ],[ - ZEND_EXPERIMENTAL_ZTS=no + ZEND_MAINTAINER_ZTS=no ]) AC_ARG_ENABLE(inline-optimization, @@ -141,8 +129,8 @@ ZEND_MEMORY_LIMIT=no ]) -AC_MSG_CHECKING(whether to enable experimental ZTS) -AC_MSG_RESULT($ZEND_EXPERIMENTAL_ZTS) +AC_MSG_CHECKING(whether to enable thread-safety) +AC_MSG_RESULT($ZEND_MAINTAINER_ZTS) AC_MSG_CHECKING(whether to enable inline optimization for GCC) AC_MSG_RESULT($ZEND_INLINE_OPTIMIZATION) @@ -168,7 +156,7 @@ test -n "$DEBUG_CFLAGS" && CFLAGS="$CFLAGS $DEBUG_CFLAGS" -if test "$ZEND_EXPERIMENTAL_ZTS" = "yes"; then +if test "$ZEND_MAINTAINER_ZTS" = "yes"; then AC_DEFINE(ZTS,1,[ ]) CFLAGS="$CFLAGS -DZTS" LIBZEND_CPLUSPLUS_CHECKS @@ -192,6 +180,52 @@ AC_C_INLINE AC_SUBST(INLINE_CFLAGS) + + +dnl test and set the alignment define for ZEND_MM +dnl this also does the logarithmic test for ZEND_MM. +AC_MSG_CHECKING(for MM alignment and log values) + +AC_TRY_RUN([ +#include <stdio.h> + +typedef union _mm_align_test { + void *ptr; + double dbl; + long lng; +} mm_align_test; + +#if (defined (__GNUC__) && __GNUC__ >= 2) +#define ZEND_MM_ALIGNMENT (__alignof__ (mm_align_test)) +#else +#define ZEND_MM_ALIGNMENT (sizeof(mm_align_test)) +#endif + +int main() +{ + int i = ZEND_MM_ALIGNMENT; + int zeros = 0; + FILE *fp; + + while (i & ~0x1) { + zeros++; + i = i >> 1; + } + + fp = fopen("conftest.zend", "w"); + fprintf(fp, "%d %d\n", ZEND_MM_ALIGNMENT, zeros); + fclose(fp); + + exit(0); +} +], [ + LIBZEND_MM_ALIGN=`cat conftest.zend | cut -d ' ' -f 1` + LIBZEND_MM_ALIGN_LOG2=`cat conftest.zend | cut -d ' ' -f 2` + AC_DEFINE_UNQUOTED(ZEND_MM_ALIGNMENT, $LIBZEND_MM_ALIGN, [ ]) + AC_DEFINE_UNQUOTED(ZEND_MM_ALIGNMENT_LOG2, $LIBZEND_MM_ALIGN_LOG2, [ ]) +]) + +AC_MSG_RESULT(done) ]) 1.5 +16 -0 ZendEngine2/ZendTS.dsp Index: ZendTS.dsp =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/ZendTS.dsp,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- ZendTS.dsp 3 Aug 2002 08:56:16 -0000 1.4 +++ ZendTS.dsp 11 Feb 2003 02:40:18 -0000 1.5 @@ -212,6 +212,10 @@ # End Source File # Begin Source File +SOURCE=.\zend_mm.c +# End Source File +# Begin Source File + SOURCE=.\zend_object_handlers.c # End Source File # Begin Source File @@ -220,6 +224,10 @@ # End Source File # Begin Source File +SOURCE=.\zend_objects_API.c +# End Source File +# Begin Source File + SOURCE=.\zend_opcode.c # End Source File # Begin Source File @@ -364,6 +372,10 @@ # End Source File # Begin Source File +SOURCE=.\zend_mm.h +# End Source File +# Begin Source File + SOURCE=.\zend_modules.h # End Source File # Begin Source File @@ -373,6 +385,10 @@ # Begin Source File SOURCE=.\zend_objects.h +# End Source File +# Begin Source File + +SOURCE=.\zend_objects_API.h # End Source File # Begin Source File 1.5 +26 -0 ZendEngine2/acconfig.h Index: acconfig.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/acconfig.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- acconfig.h 3 Aug 2002 08:56:16 -0000 1.4 +++ acconfig.h 11 Feb 2003 02:40:18 -0000 1.5 @@ -1,8 +1,31 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | licen****@zend***** so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans <andi****@zend*****> | + | Zeev Suraski <zeev****@zend*****> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: acconfig.h,v 1.29 2003/02/01 01:49:14 sniper Exp $ */ + #define ZEND_API #define ZEND_DLEXPORT #define ZEND_DLIMPORT +#ifndef NETWARE @TOP@ +#endif #undef uint #undef ulong @@ -10,7 +33,9 @@ /* Define if you want to enable memory limit support */ #define MEMORY_LIMIT 0 +#ifndef NETWARE @BOTTOM@ +#endif #ifdef HAVE_STDLIB_H # include <stdlib.h> @@ -73,5 +98,6 @@ * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.3 +3 -1 ZendEngine2/configure.in Index: configure.in =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/configure.in,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- configure.in 29 Apr 2002 02:25:26 -0000 1.2 +++ configure.in 11 Feb 2003 02:40:18 -0000 1.3 @@ -1,4 +1,4 @@ -dnl $Id: configure.in,v 1.33 2002/02/07 14:08:43 stas Exp $ +dnl $Id: configure.in,v 1.34 2002/11/15 14:30:40 andi Exp $ dnl Process this file with autoconf to produce a configure script. AC_INIT(zend.c) @@ -17,6 +17,8 @@ sinclude(Zend.m4) LIBZEND_BASIC_CHECKS +LIBZEND_LIBDL_CHECKS +LIBZEND_DLSYM_CHECK AM_PROG_LIBTOOL if test "$enable_debug" != "yes"; then 1.3 +8 -3 ZendEngine2/flex.skl Index: flex.skl =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/flex.skl,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- flex.skl 29 Apr 2002 02:25:26 -0000 1.2 +++ flex.skl 11 Feb 2003 02:40:18 -0000 1.3 @@ -1,7 +1,7 @@ /* A Lexical scanner generated by flex */ /* Scanner skeleton version: - * $Header: /repository/ZendEngine2/flex.skl,v 1.27 2002/04/22 09:33:24 phanto Exp $ + * $Header: /repository/ZendEngine2/flex.skl,v 1.28 2002/08/15 00:25:27 zeev Exp $ */ #define FLEX_SCANNER @@ -388,9 +388,14 @@ #endif #if YY_STACK_USED +#define yy_start_stack_ptr SCNG(yy_start_stack_ptr) +#define yy_start_stack_depth SCNG(yy_start_stack_depth) +#define yy_start_stack SCNG(yy_start_stack) +/* static int yy_start_stack_ptr = 0; static int yy_start_stack_depth = 0; static int *yy_start_stack = 0; +*/ #ifndef YY_NO_PUSH_STATE static void yy_push_state YY_PROTO(( int new_state TSRMLS_DC )); #endif @@ -398,7 +403,7 @@ static void yy_pop_state YY_PROTO(( TSRMLS_D )); #endif #ifndef YY_NO_TOP_STATE -static int yy_top_state YY_PROTO(( void )); +static int yy_top_state YY_PROTO(( TSRMLS_D )); #endif #else @@ -1495,7 +1500,7 @@ #ifndef YY_NO_TOP_STATE %- -static int yy_top_state() +static int yy_top_state(TSRMLS_D) %+ int yyFlexLexer::yy_top_state() %* 1.6 +247 -60 ZendEngine2/zend.c Index: zend.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- zend.c 3 Aug 2002 08:56:16 -0000 1.5 +++ zend.c 11 Feb 2003 02:40:18 -0000 1.6 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend.c,v 1.209 2003/02/10 16:11:24 zeev Exp $ */ #include "zend.h" #include "zend_extensions.h" @@ -35,7 +36,6 @@ #else # define GLOBAL_FUNCTION_TABLE CG(function_table) # define GLOBAL_CLASS_TABLE CG(class_table) -# define GLOBAL_CONSTANTS_TABLE CG(zend_constants) # define GLOBAL_AUTO_GLOBALS_TABLE CG(auto_globals) #endif @@ -53,10 +53,40 @@ ZEND_API void (*zend_ticks_function)(int ticks); ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); +void (*zend_on_timeout)(int seconds TSRMLS_DC); + static void (*zend_message_dispatcher_p)(long message, void *data); static int (*zend_get_configuration_directive_p)(char *name, uint name_length, zval *contents); +static ZEND_INI_MH(OnUpdateErrorReporting) +{ + if (!new_value) { + EG(error_reporting) = E_ALL & ~E_NOTICE; + } else { + EG(error_reporting) = atoi(new_value); + } + return SUCCESS; +} + + +static ZEND_INI_MH(OnUpdateImplicitClone) +{ + if (!new_value) { + EG(implicit_clone) = 0; + } else { + EG(implicit_clone) = atoi(new_value) ? 1 : 0; + } + return SUCCESS; +} + + +ZEND_INI_BEGIN() + ZEND_INI_ENTRY("error_reporting", NULL, ZEND_INI_ALL, OnUpdateErrorReporting) + ZEND_INI_ENTRY("zend2.implicit_clone", NULL, ZEND_INI_ALL, OnUpdateImplicitClone) +ZEND_INI_END() + + #ifdef ZTS ZEND_API int compiler_globals_id; ZEND_API int executor_globals_id; @@ -65,19 +95,19 @@ HashTable *global_auto_globals_table; #endif -zend_utility_values zend_uv; +ZEND_API zend_utility_values zend_uv; ZEND_API zval zval_used_for_init; /* True global variable */ /* version information */ static char *zend_version_info; static uint zend_version_info_length; -#define ZEND_CORE_VERSION_INFO "Zend Engine v" ZEND_VERSION ", Copyright (c) 1998-2002 Zend Technologies\n" +#define ZEND_CORE_VERSION_INFO "Zend Engine v" ZEND_VERSION ", Copyright (c) 1998-2003 Zend Technologies\n" #define PRINT_ZVAL_INDENT 4 -static void print_hash(HashTable *ht, int indent) +static void print_hash(HashTable *ht, int indent TSRMLS_DC) { zval **tmp; char *string_key; @@ -106,7 +136,7 @@ break; } ZEND_PUTS("] => "); - zend_print_zval_r(*tmp, indent+PRINT_ZVAL_INDENT); + zend_print_zval_r(*tmp, indent+PRINT_ZVAL_INDENT TSRMLS_CC); ZEND_PUTS("\n"); zend_hash_move_forward_ex(ht, &iterator); } @@ -117,6 +147,34 @@ ZEND_PUTS(")\n"); } +static void print_flat_hash(HashTable *ht TSRMLS_DC) +{ + zval **tmp; + char *string_key; + HashPosition iterator; + ulong num_key; + uint str_len; + int i = 0; + + zend_hash_internal_pointer_reset_ex(ht, &iterator); + while (zend_hash_get_current_data_ex(ht, (void **) &tmp, &iterator) == SUCCESS) { + if (i++ > 0) { + ZEND_PUTS(","); + } + ZEND_PUTS("["); + switch (zend_hash_get_current_key_ex(ht, &string_key, &str_len, &num_key, 0, &iterator)) { + case HASH_KEY_IS_STRING: + ZEND_PUTS(string_key); + break; + case HASH_KEY_IS_LONG: + zend_printf("%ld", num_key); + break; + } + ZEND_PUTS("] => "); + zend_print_flat_zval_r(*tmp TSRMLS_CC); + zend_hash_move_forward_ex(ht, &iterator); + } +} ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy) { @@ -155,6 +213,11 @@ expr_copy->value.str.val = estrndup("Object", expr_copy->value.str.len); #endif break; + case IS_DOUBLE: + *expr_copy = *expr; + zval_copy_ctor(expr_copy); + zend_locale_sprintf_double(expr_copy ZEND_FILE_LINE_CC); + break; default: *expr_copy = *expr; zval_copy_ctor(expr_copy); @@ -194,38 +257,100 @@ return expr->value.str.len; } +ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC) +{ + zend_write_func_t write_func = zend_write; + + switch (expr->type) { + case IS_ARRAY: + ZEND_PUTS("Array ("); + if (++expr->value.ht->nApplyCount>1) { + ZEND_PUTS(" *RECURSION*"); + expr->value.ht->nApplyCount--; + return; + } + print_flat_hash(expr->value.ht TSRMLS_CC); + ZEND_PUTS(")"); + expr->value.ht->nApplyCount--; + break; + case IS_OBJECT: + { + HashTable *properties = NULL; + char *class_name = NULL; + zend_uint clen; + + if (Z_OBJ_HANDLER_P(expr, get_class_name)) { + Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC); + } + if (class_name == NULL) { + class_name = "Unknown Class"; + } + zend_printf("%s Object (", class_name); + if (Z_OBJ_HANDLER_P(expr, get_properties)) { + properties = Z_OBJPROP_P(expr); + } + if (properties) { + if (++properties->nApplyCount>1) { + ZEND_PUTS(" *RECURSION*"); + properties->nApplyCount--; + return; + } + print_flat_hash(properties TSRMLS_CC); + properties->nApplyCount--; + } + ZEND_PUTS(")"); + break; + } + default: + zend_print_variable(expr); + break; + } +} -ZEND_API void zend_print_zval_r(zval *expr, int indent) +ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC) { - zend_print_zval_r_ex(zend_write, expr, indent); + zend_print_zval_r_ex(zend_write, expr, indent TSRMLS_CC); } -ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent) +ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC) { - switch(expr->type) { + switch (expr->type) { case IS_ARRAY: ZEND_PUTS("Array\n"); if (++expr->value.ht->nApplyCount>1) { ZEND_PUTS(" *RECURSION*"); - expr->value.ht->nApplyCount=0; + expr->value.ht->nApplyCount--; return; } - print_hash(expr->value.ht, indent); + print_hash(expr->value.ht, indent TSRMLS_CC); expr->value.ht->nApplyCount--; break; case IS_OBJECT: { - zend_object *object = Z_OBJ_P(expr); - - if (++object->properties->nApplyCount>1) { - ZEND_PUTS(" *RECURSION*"); - object->properties->nApplyCount=0; - return; + HashTable *properties = NULL; + char *class_name = NULL; + zend_uint clen; + + if (Z_OBJ_HANDLER_P(expr, get_class_name)) { + Z_OBJ_HANDLER_P(expr, get_class_name)(expr, &class_name, &clen, 0 TSRMLS_CC); + } + if (class_name == NULL) { + class_name = "Unknown Class"; + } + zend_printf("%s Object\n", class_name); + if (Z_OBJ_HANDLER_P(expr, get_properties)) { + properties = Z_OBJPROP_P(expr); + } + if (properties) { + if (++properties->nApplyCount>1) { + ZEND_PUTS(" *RECURSION*"); + properties->nApplyCount--; + return; + } + print_hash(properties, indent TSRMLS_CC); + properties->nApplyCount--; } - zend_printf("%s Object\n", object->ce->name); - print_hash(object->properties, indent); - object->properties->nApplyCount--; break; } default: @@ -247,25 +372,13 @@ static void register_standard_class(void) { zend_standard_class_def = malloc(sizeof(zend_class_entry)); - + zend_standard_class_def->type = ZEND_INTERNAL_CLASS; - zend_standard_class_def->name_length = sizeof("stdClass") - 1; zend_standard_class_def->name = zend_strndup("stdClass", zend_standard_class_def->name_length); + zend_standard_class_def->name_length = sizeof("stdClass") - 1; zend_standard_class_def->parent = NULL; - zend_hash_init_ex(&zend_standard_class_def->default_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0); - zend_hash_init_ex(&zend_standard_class_def->private_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0); - zend_standard_class_def->static_members = (HashTable *) malloc(sizeof(HashTable)); - zend_hash_init_ex(zend_standard_class_def->static_members, 0, NULL, ZVAL_PTR_DTOR, 1, 0); - zend_hash_init_ex(&zend_standard_class_def->constants_table, 0, NULL, ZVAL_PTR_DTOR, 1, 0); - zend_hash_init_ex(&zend_standard_class_def->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0); - zend_hash_init_ex(&zend_standard_class_def->function_table, 0, NULL, ZEND_FUNCTION_DTOR, 1, 0); - zend_standard_class_def->constructor = NULL; - zend_standard_class_def->destructor = NULL; - zend_standard_class_def->clone = NULL; - zend_standard_class_def->handle_function_call = NULL; - zend_standard_class_def->handle_property_get = NULL; - zend_standard_class_def->handle_property_set = NULL; - zend_standard_class_def->refcount = 1; + zend_initialize_class_data(zend_standard_class_def, 1); + zend_hash_add(GLOBAL_CLASS_TABLE, "stdclass", sizeof("stdclass"), &zend_standard_class_def, sizeof(zend_class_entry *), NULL); } @@ -294,7 +407,7 @@ compiler_globals->class_table = &compiler_globals->main_class.class_table; zend_hash_init_ex(compiler_globals->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0); - zend_hash_copy(compiler_globals->class_table, GLOBAL_CLASS_TABLE, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry)); + zend_hash_copy(compiler_globals->class_table, GLOBAL_CLASS_TABLE, (copy_ctor_func_t) zend_class_add_ref, &tmp_class, sizeof(zend_class_entry *)); zend_set_default_compile_time_values(TSRMLS_C); @@ -323,14 +436,14 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS_DC) { - if (GLOBAL_CONSTANTS_TABLE) { - zend_startup_constants(TSRMLS_C); - zend_copy_constants(EG(zend_constants), GLOBAL_CONSTANTS_TABLE); - } + zend_startup_constants(TSRMLS_C); + zend_copy_constants(EG(zend_constants), GLOBAL_CONSTANTS_TABLE); zend_init_rsrc_plist(TSRMLS_C); EG(lambda_count)=0; EG(user_error_handler) = NULL; + EG(user_exception_handler) = NULL; EG(in_execution) = 0; + EG(current_execute_data) = NULL; } @@ -379,9 +492,12 @@ scanner_globals_p->yy_out = NULL; scanner_globals_p->_yy_more_flag = 0; scanner_globals_p->_yy_more_len = 0; - + scanner_globals_p->yy_start_stack_ptr = 0; + scanner_globals_p->yy_start_stack_depth = 0; + scanner_globals_p->yy_start_stack = 0; } +void zend_init_opcodes_handlers(); int zend_startup(zend_utility_functions *utility_functions, char **extensions, int start_builtin_functions) { @@ -422,9 +538,13 @@ zend_unblock_interruptions = utility_functions->unblock_interruptions; zend_get_configuration_directive_p = utility_functions->get_configuration_directive; zend_ticks_function = utility_functions->ticks_function; + zend_on_timeout = utility_functions->on_timeout; zend_compile_file = compile_file; zend_execute = execute; + zend_execute_internal = NULL; + + zend_init_opcodes_handlers(); /* set up version */ zend_version_info = strdup(ZEND_CORE_VERSION_INFO); @@ -437,18 +557,20 @@ GLOBAL_AUTO_GLOBALS_TABLE = (HashTable *) malloc(sizeof(HashTable)); zend_hash_init_ex(GLOBAL_FUNCTION_TABLE, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0); zend_hash_init_ex(GLOBAL_CLASS_TABLE, 10, NULL, ZEND_CLASS_DTOR, 1, 0); - zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, NULL, 1, 0); register_standard_class(); zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0); zend_init_rsrc_list_dtors(); + /* This zval can be used to initialize allocate zval's to an uninit'ed value */ zval_used_for_init.is_ref = 0; zval_used_for_init.refcount = 1; zval_used_for_init.type = IS_NULL; #ifdef ZTS + zend_hash_init_ex(GLOBAL_CONSTANTS_TABLE, 20, NULL, ZEND_CONSTANT_DTOR, 1, 0); + zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, NULL, 1, 0); ts_allocate_id(&compiler_globals_id, sizeof(zend_compiler_globals), (ts_allocate_ctor) compiler_globals_ctor, (ts_allocate_dtor) compiler_globals_dtor); ts_allocate_id(&executor_globals_id, sizeof(zend_executor_globals), (ts_allocate_ctor) executor_globals_ctor, (ts_allocate_dtor) executor_globals_dtor); ts_allocate_id(&language_scanner_globals_id, sizeof(zend_scanner_globals), (ts_allocate_ctor) scanner_globals_ctor, NULL); @@ -456,11 +578,14 @@ compiler_globals = ts_resource(compiler_globals_id); executor_globals = ts_resource(executor_globals_id); tsrm_ls = ts_resource_ex(0, NULL); + compiler_globals_dtor(compiler_globals, tsrm_ls); *compiler_globals->function_table = *GLOBAL_FUNCTION_TABLE; *compiler_globals->class_table = *GLOBAL_CLASS_TABLE; compiler_globals->auto_globals = GLOBAL_AUTO_GLOBALS_TABLE; - zend_startup_constants(tsrm_ls); + + zend_hash_destroy(executor_globals->zend_constants); + *executor_globals->zend_constants = *GLOBAL_CONSTANTS_TABLE; #else zend_hash_init_ex(CG(auto_globals), 8, NULL, NULL, 1, 0); scanner_globals_ctor(&ini_scanner_globals TSRMLS_CC); @@ -468,6 +593,7 @@ zend_startup_constants(); zend_set_default_compile_time_values(TSRMLS_C); EG(user_error_handler) = NULL; + EG(user_exception_handler) = NULL; #endif zend_register_standard_constants(TSRMLS_C); @@ -483,14 +609,39 @@ #ifdef ZTS tsrm_set_new_thread_end_handler(zend_new_thread_end_handler); - *GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table; - *GLOBAL_CLASS_TABLE = *compiler_globals->class_table; #endif return SUCCESS; } +void zend_register_standard_ini_entries(TSRMLS_D) +{ + int module_number = 0; + + REGISTER_INI_ENTRIES(); +} + + +#ifdef ZTS +/* Unlink the global (r/o) copies of the class, function and constant tables, + * and use a fresh r/w copy for the startup thread + */ +void zend_post_startup(TSRMLS_D) +{ + zend_compiler_globals *compiler_globals = ts_resource(compiler_globals_id); + zend_executor_globals *executor_globals = ts_resource(executor_globals_id); + + *GLOBAL_FUNCTION_TABLE = *compiler_globals->function_table; + *GLOBAL_CLASS_TABLE = *compiler_globals->class_table; + *GLOBAL_CONSTANTS_TABLE = *executor_globals->zend_constants; + zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC); + compiler_globals_ctor(compiler_globals, tsrm_ls); + executor_globals_ctor(executor_globals, tsrm_ls); +} +#endif + + void zend_shutdown(TSRMLS_D) { #ifdef ZEND_WIN32 @@ -500,7 +651,7 @@ zend_destroy_rsrc_list(&EG(persistent_list) TSRMLS_CC); #endif zend_destroy_rsrc_list_dtors(); - zend_hash_destroy(&module_registry); + zend_hash_graceful_reverse_destroy(&module_registry); #ifndef ZTS /* In ZTS mode these are freed by compiler_globals_dtor() */ @@ -543,6 +694,7 @@ } CG(unclean_shutdown) = 1; CG(in_compilation) = EG(in_execution) = 0; + EG(current_execute_data) = NULL; longjmp(EG(bailout), FAILURE); } END_EXTERN_C() @@ -601,7 +753,7 @@ void zend_deactivate(TSRMLS_D) { /* we're no longer executing anything */ - EG(opline_ptr) = NULL; + EG(opline_ptr) = NULL; EG(active_symbol_table) = NULL; zend_try { @@ -735,7 +887,7 @@ z_error_filename->value.str.val = estrndup(error_filename, z_error_filename->value.str.len); z_error_filename->type = IS_STRING; } - + z_error_lineno->value.lval = error_lineno; z_error_lineno->type = IS_LONG; @@ -753,7 +905,9 @@ orig_user_error_handler = EG(user_error_handler); EG(user_error_handler) = NULL; if (call_user_function_ex(CG(function_table), NULL, orig_user_error_handler, &retval, 5, params, 1, NULL TSRMLS_CC)==SUCCESS) { - zval_ptr_dtor(&retval); + if (retval) { + zval_ptr_dtor(&retval); + } } else { /* The user error handler failed, use built-in error handler */ zend_error_cb(type, error_filename, error_lineno, format, args); @@ -765,7 +919,7 @@ zval_ptr_dtor(&z_error_type); zval_ptr_dtor(&z_error_filename); zval_ptr_dtor(&z_error_lineno); - if (ZVAL_REFCOUNT(z_context)==2) { + if (ZVAL_REFCOUNT(z_context) == 2) { FREE_ZVAL(z_context); } break; @@ -773,7 +927,8 @@ va_end(args); - if (type==E_PARSE) { + if (type == E_PARSE) { + EG(exit_status) = 255; zend_init_compiler_data_structures(TSRMLS_C); } } @@ -812,12 +967,6 @@ zend_file_handle *file_handle; zend_op_array *orig_op_array = EG(active_op_array); zval *local_retval=NULL; - zend_execute_data execute_data; - - EX(prev_execute_data) = NULL; - EG(current_execute_data) = &execute_data; - EX(object) = NULL; - EX(opline) = NULL; va_start(files, file_count); for (i=0; i<file_count; i++) { @@ -828,12 +977,41 @@ EG(active_op_array) = zend_compile_file(file_handle, ZEND_INCLUDE TSRMLS_CC); zend_destroy_file_handle(file_handle TSRMLS_CC); if (EG(active_op_array)) { - EX(function_state).function = (zend_function *) EG(active_op_array); EG(return_value_ptr_ptr) = retval ? retval : &local_retval; zend_execute(EG(active_op_array) TSRMLS_CC); if (EG(exception)) { +#if 1 /* support set_exception_handler() */ + if (EG(user_exception_handler)) { + zval *orig_user_exception_handler; + zval ***params, *retval2; + params = (zval ***)emalloc(sizeof(zval **)); + params[0] = &EG(exception); + orig_user_exception_handler = EG(user_exception_handler); + if (call_user_function_ex(CG(function_table), NULL, orig_user_exception_handler, &retval2, 1, params, 1, NULL TSRMLS_CC) == SUCCESS) { + if (retval2 != NULL) { + zval_ptr_dtor(&retval2); + } + } else { + zval_ptr_dtor(&EG(exception)); + EG(exception) = NULL; + zend_error(E_ERROR, "Uncaught exception!"); + } + efree(params); + zval_ptr_dtor(&EG(exception)); + EG(exception) = NULL; + } else { + zval_ptr_dtor(&EG(exception)); + EG(exception) = NULL; + zend_error(E_ERROR, "Uncaught exception!"); + } + if (retval == NULL && *EG(return_value_ptr_ptr) != NULL) { + zval_ptr_dtor(EG(return_value_ptr_ptr)); + local_retval = NULL; + } +#else zval_ptr_dtor(&EG(exception)); zend_error(E_ERROR, "Uncaught exception!"); +#endif } else if (!retval) { zval_ptr_dtor(EG(return_value_ptr_ptr)); local_retval = NULL; @@ -881,3 +1059,12 @@ { efree(*str_p); } + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.7 +64 -33 ZendEngine2/zend.h Index: zend.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend.h,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- zend.h 3 Aug 2002 08:56:16 -0000 1.6 +++ zend.h 11 Feb 2003 02:40:18 -0000 1.7 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend.h,v 1.170 2002/05/02 17:20:48 andi Exp $ */ +/* $Id: zend.h,v 1.200 2003/02/10 16:11:24 zeev Exp $ */ #ifndef ZEND_H #define ZEND_H @@ -25,7 +25,6 @@ #define ZEND_VERSION "2.0.0-dev" #define ZEND_ENGINE_2 -#define ZEND_MULTIBYTE #ifdef __cplusplus #define BEGIN_EXTERN_C() extern "C" { @@ -44,6 +43,9 @@ #ifdef ZEND_WIN32 # include "zend_config.w32.h" # define ZEND_PATHS_SEPARATOR ';' +#elif defined(NETWARE) +# include "zend_config.nw.h" +# include "acconfig.h" #elif defined(__riscos__) # include "zend_config.h" # define ZEND_PATHS_SEPARATOR ';' @@ -52,6 +54,18 @@ # define ZEND_PATHS_SEPARATOR ':' #endif + +#ifdef ZEND_WIN32 +/* Only use this macro if you know for sure that all of the switches values + are covered by its case statements */ +#define EMPTY_SWITCH_DEFAULT_CASE() \ + default: \ + __assume(0); \ + break; +#else +#define EMPTY_SWITCH_DEFAULT_CASE() +#endif + /* all HAVE_XXX test have to be after the include of zend_config above */ #ifdef HAVE_UNIX_H @@ -66,6 +80,17 @@ # include <dlfcn.h> #endif +#if HAVE_MACH_O_DYLD_H +#include <mach-o/dyld.h> + +/* MH_BUNDLE loading functions for Mac OS X / Darwin */ +void *zend_mh_bundle_load (char* bundle_path); +int zend_mh_bundle_unload (void *bundle_handle); +void *zend_mh_bundle_symbol(void *bundle_handle, const char *symbol_name); +const char *zend_mh_bundle_error(void); + +#endif /* HAVE_MACH_O_DYLD_H */ + #if defined(HAVE_LIBDL) # ifndef RTLD_LAZY @@ -79,7 +104,7 @@ # define DL_LOAD(libname) dlopen(libname, RTLD_LAZY | RTLD_GLOBAL) # define DL_UNLOAD dlclose # if defined(DLSYM_NEEDS_UNDERSCORE) -# define DL_FETCH_SYMBOL(h,s) dlsym((h), "_" ## s) +# define DL_FETCH_SYMBOL(h,s) dlsym((h), "_" s) # else # define DL_FETCH_SYMBOL dlsym # endif @@ -104,11 +129,13 @@ # define ZEND_EXTENSIONS_SUPPORT 0 #endif +#if HAVE_ALLOCA_H && !defined(_ALLOCA_H) +# include <alloca.h> +#endif + /* AIX requires this to be the first thing in the file. */ #ifndef __GNUC__ -# if HAVE_ALLOCA_H -# include <alloca.h> -# else +# ifndef HAVE_ALLOCA_H # ifdef _AIX #pragma alloca # else @@ -119,7 +146,7 @@ # endif #endif -#if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2)) && !(defined(ZTS) && defined(ZEND_WIN32)) +#if (HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2)) && !(defined(ZTS) && defined(ZEND_WIN32)) && !(defined(ZTS) && defined(NETWARE)) # define do_alloca(p) alloca(p) # define free_alloca(p) #else @@ -164,11 +191,7 @@ #include "zend_errors.h" #include "zend_alloc.h" -typedef unsigned char zend_bool; -typedef unsigned char zend_uchar; -typedef unsigned int zend_uint; -typedef unsigned long zend_ulong; -typedef unsigned short zend_ushort; +#include "zend_types.h" #ifdef HAVE_LIMITS_H # include <limits.h> @@ -205,6 +228,8 @@ typedef struct _zend_object { zend_class_entry *ce; HashTable *properties; + int in_get:1; + int in_set:1; } zend_object; typedef unsigned int zend_object_handle; @@ -222,14 +247,9 @@ double dval; /* double value */ struct { char *val; - zend_uint len; + int len; } str; HashTable *ht; /* hash table value */ -/* struct { - zend_class_entry *ce; - HashTable *properties; - } obj; -*/ zend_object_value obj; } zvalue_value; @@ -270,6 +290,8 @@ /* A lot of stuff needs shifiting around in order to include zend_compile.h here */ union _zend_function; +#define ZEND_CE_ABSTRACT ZEND_ACC_ABSTRACT /* same as ZEND_ACC_ABSTRACT */ + struct _zend_class_entry { char type; char *name; @@ -277,10 +299,11 @@ struct _zend_class_entry *parent; int refcount; zend_bool constants_updated; + zend_uint ce_flags; HashTable function_table; HashTable default_properties; - HashTable private_properties; /* This is only needed at compile-time */ + HashTable properties_info; HashTable class_table; HashTable *static_members; HashTable constants_table; @@ -289,12 +312,19 @@ union _zend_function *constructor; union _zend_function *destructor; union _zend_function *clone; + union _zend_function *__get; + union _zend_function *__set; + union _zend_function *__call; /* handlers */ zend_object_value (*create_object)(zend_class_entry *class_type TSRMLS_DC); + + /* old handlers */ +#if 0 void (*handle_function_call)(INTERNAL_FUNCTION_PARAMETERS, zend_property_reference *property_reference); zval (*handle_property_get)(zend_property_reference *property_reference); int (*handle_property_set)(zend_property_reference *property_reference, zval *value); +#endif }; @@ -308,12 +338,14 @@ void (*unblock_interruptions)(void); int (*get_configuration_directive)(char *name, uint name_length, zval *contents); void (*ticks_function)(int ticks); + void (*on_timeout)(int seconds TSRMLS_DC); } zend_utility_functions; typedef struct _zend_utility_values { char *import_use_extension; uint import_use_extension_length; + zend_bool html_errors; } zend_utility_values; @@ -363,6 +395,11 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, int start_builtin_functions); void zend_shutdown(TSRMLS_D); +void zend_register_standard_ini_entries(TSRMLS_D); + +#ifdef ZTS +void zend_post_startup(TSRMLS_D); +#endif void zend_set_utility_values(zend_utility_values *utility_values); @@ -392,8 +429,9 @@ ZEND_API void zend_make_printable_zval(zval *expr, zval *expr_copy, int *use_copy); ZEND_API int zend_print_zval(zval *expr, int indent); ZEND_API int zend_print_zval_ex(zend_write_func_t write_func, zval *expr, int indent); -ZEND_API void zend_print_zval_r(zval *expr, int indent); -ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent); +ZEND_API void zend_print_zval_r(zval *expr, int indent TSRMLS_DC); +ZEND_API void zend_print_flat_zval_r(zval *expr TSRMLS_DC); +ZEND_API void zend_print_zval_r_ex(zend_write_func_t write_func, zval *expr, int indent TSRMLS_DC); ZEND_API void zend_output_debug_string(zend_bool trigger_break, char *format, ...); #if ZEND_DEBUG @@ -406,6 +444,7 @@ ZEND_API void free_estring(char **str_p); + #define STR_FREE(ptr) if (ptr && ptr!=empty_string) { efree(ptr); } #define STR_FREE_REL(ptr) if (ptr && ptr!=empty_string) { efree_rel(ptr); } @@ -431,6 +470,7 @@ extern ZEND_API void (*zend_unblock_interruptions)(void); extern ZEND_API void (*zend_ticks_function)(int ticks); extern ZEND_API void (*zend_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); +extern void (*zend_on_timeout)(int seconds TSRMLS_DC); ZEND_API void zend_error(int type, const char *format, ...); @@ -440,7 +480,7 @@ /* The following #define is used for code duality in PHP for Engine 1 & 2 */ #define ZEND_STANDARD_CLASS_DEF_PTR zend_standard_class_def extern ZEND_API zend_class_entry *zend_standard_class_def; -extern zend_utility_values zend_uv; +extern ZEND_API zend_utility_values zend_uv; extern ZEND_API zval zval_used_for_init; END_EXTERN_C() @@ -539,16 +579,6 @@ #define ZEND_MAX_RESERVED_RESOURCES 4 -#ifdef ZEND_WIN32 -/* Only use this macro if you know for sure that all of the switches values - are covered by its case statements */ -#define EMPTY_SWITCH_DEFAULT_CASE() \ - default: \ - __assume(0); \ - break; -#else -#define EMPTY_SWITCH_DEFAULT_CASE() -#endif #endif /* ZEND_H */ @@ -556,5 +586,6 @@ * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.6 +172 -44 ZendEngine2/zend_API.c Index: zend_API.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_API.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- zend_API.c 3 Aug 2002 08:56:16 -0000 1.5 +++ zend_API.c 11 Feb 2003 02:40:18 -0000 1.6 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -18,6 +18,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_API.c,v 1.152 2003/02/10 16:11:24 zeev Exp $ */ #include "zend.h" #include "zend_execute.h" @@ -443,16 +444,13 @@ static int zend_parse_arg(int arg_num, zval **arg, va_list *va, char **spec, int quiet TSRMLS_DC) { char *expected_type = NULL; - char buf[1024]; expected_type = zend_parse_arg_impl(arg, va, spec); if (expected_type) { if (!quiet) { - snprintf(buf, sizeof(buf)-1, "%s() expects parameter %d to be %s, %s given", + zend_error(E_WARNING, "%s() expects parameter %d to be %s, %s given", get_active_function_name(TSRMLS_C), arg_num, expected_type, zend_zval_type_name(*arg)); - buf[sizeof(buf)-1] = '\0'; - zend_error(E_WARNING, buf); } return FAILURE; } @@ -565,6 +563,78 @@ return retval; } +ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...) +{ + va_list va; + int retval; + char *p = type_spec; + zval **object; + zend_class_entry *ce; + + if (!this_ptr) { + va_start(va, type_spec); + retval = zend_parse_va_args(num_args, type_spec, &va, 0 TSRMLS_CC); + va_end(va); + } + else { + p++; + va_start(va, type_spec); + + object = va_arg(va, zval **); + ce = va_arg(va, zend_class_entry *); + *object = this_ptr; + + retval = zend_parse_va_args(num_args, p, &va, 0 TSRMLS_CC); + va_end(va); + } + return retval; +} + +ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, zend_class_entry *ce, void **object, ...) +{ + void **arg_stack = EG(argument_stack).top_element; + va_list va; + int retval; + int quiet = flags & ZEND_PARSE_PARAMS_QUIET; + + *object = this_ptr; + + if (!*object) { + zval **parameter; + + if (zend_get_parameters_ex(1, ¶meter) != SUCCESS) { + if (!quiet) { + zend_error(E_WARNING, "%s() expects an object of class %s as first parameter, none was given", + get_active_function_name(TSRMLS_C), ce->name); + } + + return FAILURE; + } else { + if (!zend_check_class(*parameter, ce)) { + if (!quiet) { + zend_error(E_WARNING, "%s() expects parameter 1 to be %s, %s given", + get_active_function_name(TSRMLS_C), ce->name, + zend_zval_type_name(*parameter)); + } + + return FAILURE; + } else { + *object = *parameter; + } + + EG(argument_stack).top_element++; + } + } + + va_start(va, type_spec); + retval = zend_parse_va_args(num_args, type_spec, &va, flags TSRMLS_CC); + va_end(va); + + EG(argument_stack).top_element = arg_stack; + + return retval; +} + /* Argument parsing API -- andrei */ @@ -590,7 +660,7 @@ } arg->type = IS_OBJECT; - if(class_type->create_object == NULL) { + if (class_type->create_object == NULL) { arg->value.obj = zend_objects_new(&object, class_type); if (properties) { object->properties = properties; @@ -933,81 +1003,118 @@ } -ZEND_API int add_property_long_ex(zval *arg, char *key, uint key_len, long n) +ZEND_API int add_property_long_ex(zval *arg, char *key, uint key_len, long n TSRMLS_DC) { zval *tmp; + zval z_key; MAKE_STD_ZVAL(tmp); ZVAL_LONG(tmp, n); + ZVAL_STRINGL(&z_key, key, key_len-1, 0); - return zend_hash_update(Z_OBJPROP_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); + Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC); + zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ + return SUCCESS; } -ZEND_API int add_property_bool_ex(zval *arg, char *key, uint key_len, int b) +ZEND_API int add_property_bool_ex(zval *arg, char *key, uint key_len, int b TSRMLS_DC) { zval *tmp; + zval z_key; MAKE_STD_ZVAL(tmp); ZVAL_BOOL(tmp, b); - return zend_hash_update(Z_OBJPROP_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); + ZVAL_STRINGL(&z_key, key, key_len-1, 0); + + Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC); + zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ + return SUCCESS; } -ZEND_API int add_property_null_ex(zval *arg, char *key, uint key_len) +ZEND_API int add_property_null_ex(zval *arg, char *key, uint key_len TSRMLS_DC) { zval *tmp; + zval z_key; MAKE_STD_ZVAL(tmp); ZVAL_NULL(tmp); - return zend_hash_update(Z_OBJPROP_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); + ZVAL_STRINGL(&z_key, key, key_len-1, 0); + + Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC); + zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ + return SUCCESS; } -ZEND_API int add_property_resource_ex(zval *arg, char *key, uint key_len, long n) +ZEND_API int add_property_resource_ex(zval *arg, char *key, uint key_len, long n TSRMLS_DC) { zval *tmp; + zval z_key; MAKE_STD_ZVAL(tmp); ZVAL_RESOURCE(tmp, n); + ZVAL_STRINGL(&z_key, key, key_len-1, 0); - return zend_hash_update(Z_OBJPROP_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); + Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC); + zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ + return SUCCESS; } -ZEND_API int add_property_double_ex(zval *arg, char *key, uint key_len, double d) +ZEND_API int add_property_double_ex(zval *arg, char *key, uint key_len, double d TSRMLS_DC) { zval *tmp; - + zval z_key; + MAKE_STD_ZVAL(tmp); ZVAL_DOUBLE(tmp, d); + ZVAL_STRINGL(&z_key, key, key_len-1, 0); - return zend_hash_update(Z_OBJPROP_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); + Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC); + zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ + return SUCCESS; } -ZEND_API int add_property_string_ex(zval *arg, char *key, uint key_len, char *str, int duplicate) +ZEND_API int add_property_string_ex(zval *arg, char *key, uint key_len, char *str, int duplicate TSRMLS_DC) { zval *tmp; + zval z_key; MAKE_STD_ZVAL(tmp); ZVAL_STRING(tmp, str, duplicate); - return zend_hash_update(Z_OBJPROP_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); + ZVAL_STRINGL(&z_key, key, key_len-1, 0); + + Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC); + zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ + return SUCCESS; } -ZEND_API int add_property_stringl_ex(zval *arg, char *key, uint key_len, char *str, uint length, int duplicate) +ZEND_API int add_property_stringl_ex(zval *arg, char *key, uint key_len, char *str, uint length, int duplicate TSRMLS_DC) { zval *tmp; + zval z_key; MAKE_STD_ZVAL(tmp); ZVAL_STRINGL(tmp, str, length, duplicate); - return zend_hash_update(Z_OBJPROP_P(arg), key, key_len, (void *) &tmp, sizeof(zval *), NULL); + ZVAL_STRINGL(&z_key, key, key_len-1, 0); + + Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, tmp TSRMLS_CC); + zval_ptr_dtor(&tmp); /* write_property will add 1 to refcount */ + return SUCCESS; } -ZEND_API int add_property_zval_ex(zval *arg, char *key, uint key_len, zval *value) +ZEND_API int add_property_zval_ex(zval *arg, char *key, uint key_len, zval *value TSRMLS_DC) { - return zend_hash_update(Z_OBJPROP_P(arg), key, key_len, (void *) &value, sizeof(zval *), NULL); + zval z_key; + + ZVAL_STRINGL(&z_key, key, key_len-1, 0); + + Z_OBJ_HANDLER_P(arg, write_property)(arg, &z_key, value TSRMLS_CC); + return SUCCESS; } ZEND_API int zend_startup_module(zend_module_entry *module) @@ -1030,14 +1137,15 @@ /* registers all functions in *library_functions in the function hash */ -int zend_register_functions(zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) +int zend_register_functions(zend_class_entry *scope, zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC) { zend_function_entry *ptr = functions; - zend_function function; + zend_function function, *reg_function; zend_internal_function *internal_function = (zend_internal_function *)&function; int count=0, unload=0; HashTable *target_function_table = function_table; int error_type; + zend_function *ctor = NULL, *dtor = NULL, *clone = NULL; if (type==MODULE_PERSISTENT) { error_type = E_CORE_WARNING; @@ -1054,16 +1162,32 @@ internal_function->handler = ptr->handler; internal_function->arg_types = ptr->func_arg_types; internal_function->function_name = ptr->fname; - internal_function->scope = NULL; + internal_function->scope = scope; + internal_function->fn_flags = ZEND_ACC_PUBLIC; if (!internal_function->handler) { zend_error(error_type, "Null function defined as active function"); zend_unregister_functions(functions, count, target_function_table TSRMLS_CC); return FAILURE; } - if (zend_hash_add(target_function_table, ptr->fname, strlen(ptr->fname)+1, &function, sizeof(zend_function), NULL) == FAILURE) { + if (zend_hash_add(target_function_table, ptr->fname, strlen(ptr->fname)+1, &function, sizeof(zend_function), (void**)®_function) == FAILURE) { unload=1; break; } + if (scope) { + /* + * If it's an old-style constructor, store it only if we don't have + * a constructor already. + */ + if (!strcmp(ptr->fname, scope->name) && !ctor) { + ctor = reg_function; + } else if (!strcmp(ptr->fname, ZEND_CONSTRUCTOR_FUNC_NAME)) { + ctor = reg_function; + } else if (!strcmp(ptr->fname, ZEND_DESTRUCTOR_FUNC_NAME)) { + dtor = reg_function; + } else if (!strcmp(ptr->fname, ZEND_CLONE_FUNC_NAME)) { + clone = reg_function; + } + } ptr++; count++; } @@ -1077,6 +1201,11 @@ zend_unregister_functions(functions, count, target_function_table TSRMLS_CC); return FAILURE; } + if (scope) { + scope->constructor = ctor; + scope->destructor = dtor; + scope->clone = clone; + } return SUCCESS; } @@ -1113,7 +1242,7 @@ #if 0 zend_printf("%s: Registering module %d\n", module->name, module->module_number); #endif - if (module->functions && zend_register_functions(module->functions, NULL, module->type TSRMLS_CC)==FAILURE) { + if (module->functions && zend_register_functions(NULL, module->functions, NULL, module->type TSRMLS_CC)==FAILURE) { zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load", module->name); return FAILURE; } @@ -1173,7 +1302,7 @@ */ int module_registry_cleanup(zend_module_entry *module TSRMLS_DC) { - switch(module->type) { + switch (module->type) { case MODULE_PERSISTENT: if (module->request_shutdown_func) { #if 0 @@ -1229,24 +1358,15 @@ char *lowercase_name = zend_strndup(orig_class_entry->name, orig_class_entry->name_length); *class_entry = *orig_class_entry; - zend_str_tolower(lowercase_name, class_entry->name_length); - class_entry->type = ZEND_INTERNAL_CLASS; class_entry->parent = NULL; - class_entry->refcount = 1; - class_entry->constants_updated = 0; - zend_hash_init(&class_entry->default_properties, 0, NULL, ZVAL_PTR_DTOR, 1); - zend_hash_init(&class_entry->private_properties, 0, NULL, ZVAL_PTR_DTOR, 1); - class_entry->static_members = (HashTable *) malloc(sizeof(HashTable)); - zend_hash_init(class_entry->static_members, 0, NULL, ZVAL_PTR_DTOR, 1); - zend_hash_init(&class_entry->constants_table, 0, NULL, ZVAL_PTR_DTOR, 1); - zend_hash_init(&class_entry->function_table, 0, NULL, ZEND_FUNCTION_DTOR, 1); - zend_hash_init(&class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 1); + zend_initialize_class_data(class_entry, 0); if (class_entry->builtin_functions) { - zend_register_functions(class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC); + zend_register_functions(class_entry, class_entry->builtin_functions, &class_entry->function_table, MODULE_PERSISTENT TSRMLS_CC); } + zend_str_tolower(lowercase_name, class_entry->name_length); zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, &class_entry, sizeof(zend_class_entry *), NULL); free(lowercase_name); return class_entry; @@ -1289,7 +1409,7 @@ /* Disabled functions support */ -static ZEND_FUNCTION(display_disabled_function) +ZEND_API ZEND_FUNCTION(display_disabled_function) { zend_error(E_WARNING, "%s() has been disabled for security reasons", get_active_function_name(TSRMLS_C)); } @@ -1307,7 +1427,7 @@ return FAILURE; } disabled_function[0].fname = function_name; - return zend_register_functions(disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC); + return zend_register_functions(NULL, disabled_function, CG(function_table), MODULE_PERSISTENT TSRMLS_CC); } zend_bool zend_is_callable(zval *callable, zend_bool syntax_only, char **callable_name) @@ -1362,7 +1482,7 @@ lcname = estrndup(Z_STRVAL_PP(obj), Z_STRLEN_PP(obj)); zend_str_tolower(lcname, Z_STRLEN_PP(obj)); - if(zend_hash_find(EG(class_table), lcname, Z_STRLEN_PP(obj) + 1, (void**)&pce) == SUCCESS) { + if (zend_lookup_class(lcname, Z_STRLEN_PP(obj), &pce TSRMLS_CC) == SUCCESS) { ce = *pce; } @@ -1423,3 +1543,11 @@ } return module->version; } + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.6 +36 -37 ZendEngine2/zend_API.h Index: zend_API.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_API.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- zend_API.h 3 Aug 2002 08:56:16 -0000 1.5 +++ zend_API.h 11 Feb 2003 02:40:18 -0000 1.6 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -18,6 +18,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_API.h,v 1.129 2003/02/08 20:54:02 georg Exp $ */ #ifndef ZEND_API_H #define ZEND_API_H @@ -29,6 +30,8 @@ #include "zend_variables.h" #include "zend_execute.h" + +BEGIN_EXTERN_C() #define ZEND_FN(name) zif_##name #define ZEND_NAMED_FUNCTION(name) void name(INTERNAL_FUNCTION_PARAMETERS) #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name)) @@ -82,19 +85,7 @@ -#define INIT_CLASS_ENTRY(class_container, class_name, functions) \ - { \ - class_container.name = strdup(class_name); \ - class_container.name_length = sizeof(class_name)-1; \ - class_container.builtin_functions = functions; \ - class_container.constructor = NULL; \ - class_container.destructor = NULL; \ - class_container.clone = NULL; \ - class_container.create_object = NULL; \ - class_container.handle_function_call = NULL; \ - class_container.handle_property_get = NULL; \ - class_container.handle_property_set = NULL; \ - } +#define INIT_CLASS_ENTRY(class_container, class_name, functions) INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, NULL, NULL, NULL) #define INIT_OVERLOADED_CLASS_ENTRY(class_container, class_name, functions, handle_fcall, handle_propget, handle_propset) \ { \ @@ -105,9 +96,9 @@ class_container.destructor = NULL; \ class_container.clone = NULL; \ class_container.create_object = NULL; \ - class_container.handle_function_call = handle_fcall; \ - class_container.handle_property_get = handle_propget; \ - class_container.handle_property_set = handle_propset; \ + class_container.__call = handle_fcall; \ + class_container.__get = handle_propget; \ + class_container.__set = handle_propset; \ } @@ -132,9 +123,12 @@ ZEND_API int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...); ZEND_API char *zend_zval_type_name(zval *arg); +ZEND_API int zend_parse_method_parameters(int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, ...); +ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args TSRMLS_DC, zval *this_ptr, char *type_spec, zend_class_entry *ce, void **object, ...); + /* End of parameter parsing API -- andrei */ -int zend_register_functions(zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC); +int zend_register_functions(zend_class_entry *scope, zend_function_entry *functions, HashTable *function_table, int type TSRMLS_DC); void zend_unregister_functions(zend_function_entry *functions, int count, HashTable *function_table TSRMLS_DC); ZEND_API int zend_register_module(zend_module_entry *module_entry); @@ -230,23 +224,23 @@ ZEND_API int add_get_index_string(zval *arg, uint idx, char *str, void **dest, int duplicate); ZEND_API int add_get_index_stringl(zval *arg, uint idx, char *str, uint length, void **dest, int duplicate); -ZEND_API int add_property_long_ex(zval *arg, char *key, uint key_len, long l); -ZEND_API int add_property_null_ex(zval *arg, char *key, uint key_len); -ZEND_API int add_property_bool_ex(zval *arg, char *key, uint key_len, int b); -ZEND_API int add_property_resource_ex(zval *arg, char *key, uint key_len, long r); -ZEND_API int add_property_double_ex(zval *arg, char *key, uint key_len, double d); -ZEND_API int add_property_string_ex(zval *arg, char *key, uint key_len, char *str, int duplicate); -ZEND_API int add_property_stringl_ex(zval *arg, char *key, uint key_len, char *str, uint length, int duplicate); -ZEND_API int add_property_zval_ex(zval *arg, char *key, uint key_len, zval *value); - -#define add_property_long(__arg, __key, __n) add_property_long_ex(__arg, __key, strlen(__key)+1, __n) -#define add_property_null(__arg, __key) add_property_null_ex(__arg, __key, strlen(__key) + 1) -#define add_property_bool(__arg, __key, __b) add_property_bool_ex(__arg, __key, strlen(__key)+1, __b) -#define add_property_resource(__arg, __key, __r) add_property_resource_ex(__arg, __key, strlen(__key)+1, __r) -#define add_property_double(__arg, __key, __d) add_property_double_ex(__arg, __key, strlen(__key)+1, __d) -#define add_property_string(__arg, __key, __str, __duplicate) add_property_string_ex(__arg, __key, strlen(__key)+1, __str, __duplicate) -#define add_property_stringl(__arg, __key, __str, __length, __duplicate) add_property_stringl_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate) -#define add_property_zval(__arg, __key, __value) add_property_zval_ex(__arg, __key, strlen(__key)+1, __value) +ZEND_API int add_property_long_ex(zval *arg, char *key, uint key_len, long l TSRMLS_DC); +ZEND_API int add_property_null_ex(zval *arg, char *key, uint key_len TSRMLS_DC); +ZEND_API int add_property_bool_ex(zval *arg, char *key, uint key_len, int b TSRMLS_DC); +ZEND_API int add_property_resource_ex(zval *arg, char *key, uint key_len, long r TSRMLS_DC); +ZEND_API int add_property_double_ex(zval *arg, char *key, uint key_len, double d TSRMLS_DC); +ZEND_API int add_property_string_ex(zval *arg, char *key, uint key_len, char *str, int duplicate TSRMLS_DC); +ZEND_API int add_property_stringl_ex(zval *arg, char *key, uint key_len, char *str, uint length, int duplicate TSRMLS_DC); +ZEND_API int add_property_zval_ex(zval *arg, char *key, uint key_len, zval *value TSRMLS_DC); + +#define add_property_long(__arg, __key, __n) add_property_long_ex(__arg, __key, strlen(__key)+1, __n TSRMLS_CC) +#define add_property_null(__arg, __key) add_property_null_ex(__arg, __key, strlen(__key) + 1 TSRMLS_CC) +#define add_property_bool(__arg, __key, __b) add_property_bool_ex(__arg, __key, strlen(__key)+1, __b TSRMLS_CC) +#define add_property_resource(__arg, __key, __r) add_property_resource_ex(__arg, __key, strlen(__key)+1, __r TSRMLS_CC) +#define add_property_double(__arg, __key, __d) add_property_double_ex(__arg, __key, strlen(__key)+1, __d TSRMLS_CC) +#define add_property_string(__arg, __key, __str, __duplicate) add_property_string_ex(__arg, __key, strlen(__key)+1, __str, __duplicate TSRMLS_CC) +#define add_property_stringl(__arg, __key, __str, __length, __duplicate) add_property_stringl_ex(__arg, __key, strlen(__key)+1, __str, __length, __duplicate TSRMLS_CC) +#define add_property_zval(__arg, __key, __value) add_property_zval_ex(__arg, __key, strlen(__key)+1, __value TSRMLS_CC) ZEND_API int call_user_function(HashTable *function_table, zval **object_pp, zval *function_name, zval *retval_ptr, int param_count, zval *params[] TSRMLS_DC); ZEND_API int call_user_function_ex(HashTable *function_table, zval **object_pp, zval *function_name, zval **retval_ptr_ptr, int param_count, zval **params[], int no_separation, HashTable *symbol_table TSRMLS_DC); @@ -256,11 +250,13 @@ #define add_method(arg, key, method) add_assoc_function((arg), (key), (method)) +ZEND_API ZEND_FUNCTION(display_disabled_function); + #if ZEND_DEBUG #define CHECK_ZVAL_STRING(z) \ - if ((z)->value.str.val[ (z)->value.str.len ] != '\0') zend_error(E_WARNING, "String is not zero-terminated (%s)", (z)->value.str.val); + if ((z)->value.str.val[ (z)->value.str.len ] != '\0') { zend_error(E_WARNING, "String is not zero-terminated (%s)", (z)->value.str.val); } #define CHECK_ZVAL_STRING_REL(z) \ - if ((z)->value.str.val[ (z)->value.str.len ] != '\0') zend_error(E_WARNING, "String is not zero-terminated (%s) (source: %s:%d)", (z)->value.str.val ZEND_FILE_LINE_RELAY_CC); + if ((z)->value.str.val[ (z)->value.str.len ] != '\0') { zend_error(E_WARNING, "String is not zero-terminated (%s) (source: %s:%d)", (z)->value.str.val ZEND_FILE_LINE_RELAY_CC); } #else #define CHECK_ZVAL_STRING(z) #define CHECK_ZVAL_STRING_REL(z) @@ -426,6 +422,8 @@ #define ZEND_RSHUTDOWN_FUNCTION ZEND_MODULE_DEACTIVATE_D #define ZEND_MINFO_FUNCTION ZEND_MODULE_INFO_D +END_EXTERN_C() + #endif /* ZEND_API_H */ @@ -433,5 +431,6 @@ * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.5 +90 -99 ZendEngine2/zend_alloc.c Index: zend_alloc.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_alloc.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_alloc.c 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_alloc.c 11 Feb 2003 02:40:18 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,8 +17,7 @@ +----------------------------------------------------------------------+ */ - -#include <stdlib.h> +/* $Id: zend_alloc.c,v 1.115 2003/02/01 01:49:14 sniper Exp $ */ #include "zend.h" #include "zend_alloc.h" @@ -31,15 +30,24 @@ # include <unistd.h> #endif +#include "zend_mm.h" + #ifndef ZTS ZEND_API zend_alloc_globals alloc_globals; #endif +#ifdef ZEND_MM +#define ZEND_DISABLE_MEMORY_CACHE 1 +#else #define ZEND_DISABLE_MEMORY_CACHE 0 +#endif - -#ifdef ZEND_WIN32 +#ifdef ZEND_MM +#define ZEND_DO_MALLOC(size) zend_mm_alloc(&AG(mm_heap), size) +#define ZEND_DO_FREE(ptr) zend_mm_free(&AG(mm_heap), ptr) +#define ZEND_DO_REALLOC(ptr, size) zend_mm_realloc(&AG(mm_heap), ptr, size) +#elif defined(ZEND_WIN32) #define ZEND_DO_MALLOC(size) (AG(memory_heap) ? HeapAlloc(AG(memory_heap), HEAP_NO_SERIALIZE, size) : malloc(size)) #define ZEND_DO_FREE(ptr) (AG(memory_heap) ? HeapFree(AG(memory_heap), HEAP_NO_SERIALIZE, ptr) : free(ptr)) #define ZEND_DO_REALLOC(ptr, size) (AG(memory_heap) ? HeapReAlloc(AG(memory_heap), HEAP_NO_SERIALIZE, ptr, size) : realloc(ptr, size)) @@ -66,18 +74,22 @@ #define _CHECK_MEMORY_LIMIT(s, rs, file, lineno) { AG(allocated_memory) += rs;\ if (AG(memory_limit)<AG(allocated_memory)) {\ - if ((AG(memory_limit)+1048576)<AG(allocated_memory)) { \ - /* failed to handle this gracefully, exit() */ \ - exit(1); \ - } \ - if (!AG(memory_exhausted)) { \ - if (!file) { \ - zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted (tried to allocate %d bytes)", AG(memory_limit), s); \ + int php_mem_limit = AG(memory_limit); \ + if (AG(memory_limit)+1048576 > AG(allocated_memory) - rs) { \ + AG(memory_limit) = AG(allocated_memory) + 1048576; \ + if (file) { \ + zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted (tried to allocate %d bytes)", php_mem_limit, s); \ + } else { \ + zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted at %s:%d (tried to allocate %d bytes)", php_mem_limit, file, lineno, s); \ + } \ + } else { \ + if (file) { \ + fprintf(stderr, "Allowed memory size of %d bytes exhausted at %s:%d (tried to allocate %d bytes)\n", php_mem_limit, file, lineno, s); \ } else { \ - zend_error(E_ERROR,"Allowed memory size of %d bytes exhausted at %s:%d (tried to allocate %d bytes)", AG(memory_limit), file, lineno, s); \ + fprintf(stderr, "Allowed memory size of %d bytes exhausted (tried to allocate %d bytes)\n", php_mem_limit, s); \ } \ - AG(memory_exhausted)=1; \ - } \ + exit(1); \ + } \ } \ } # endif @@ -88,10 +100,8 @@ #define REMOVE_POINTER_FROM_LIST(p) \ - if (!p->persistent && p==AG(head)) { \ + if (p==AG(head)) { \ AG(head) = p->pNext; \ - } else if (p->persistent && p==AG(phead)) { \ - AG(phead) = p->pNext; \ } else { \ p->pLast->pNext = p->pNext; \ } \ @@ -100,19 +110,11 @@ } #define ADD_POINTER_TO_LIST(p) \ - if (p->persistent) { \ - p->pNext = AG(phead); \ - if (AG(phead)) { \ - AG(phead)->pLast = p; \ - } \ - AG(phead) = p; \ - } else { \ - p->pNext = AG(head); \ - if (AG(head)) { \ - AG(head)->pLast = p; \ - } \ - AG(head) = p; \ - } \ + p->pNext = AG(head); \ + if (AG(head)) { \ + AG(head)->pLast = p; \ + } \ + AG(head) = p; \ p->pLast = (zend_mem_header *) NULL; #define DECLARE_CACHE_VARS() \ @@ -152,7 +154,6 @@ AG(cache_stats)[CACHE_INDEX][1]++; memcpy((((char *) p) + sizeof(zend_mem_header) + MEM_HEADER_PADDING + size), &mem_block_end_magic, sizeof(long)); #endif - p->persistent = 0; p->cached = 0; p->size = size; return (void *)((char *)p + sizeof(zend_mem_header) + MEM_HEADER_PADDING); @@ -177,8 +178,10 @@ HANDLE_UNBLOCK_INTERRUPTIONS(); return (void *)p; } - p->persistent = p->cached = 0; + p->cached = 0; +#if ZEND_DEBUG || !defined(ZEND_MM) ADD_POINTER_TO_LIST(p); +#endif p->size = size; /* Save real size for correct cache output */ #if ZEND_DEBUG p->filename = __zend_filename; @@ -228,7 +231,7 @@ #endif if (!ZEND_DISABLE_MEMORY_CACHE - && !p->persistent && (CACHE_INDEX < MAX_CACHED_MEMORY) && (AG(cache_count)[CACHE_INDEX] < MAX_CACHED_ENTRIES)) { + && (CACHE_INDEX < MAX_CACHED_MEMORY) && (AG(cache_count)[CACHE_INDEX] < MAX_CACHED_ENTRIES)) { AG(cache)[CACHE_INDEX][AG(cache_count)[CACHE_INDEX]++] = p; p->cached = 1; #if ZEND_DEBUG @@ -237,7 +240,9 @@ return; } HANDLE_BLOCK_INTERRUPTIONS(); +#if ZEND_DEBUG || !defined(ZEND_MM) REMOVE_POINTER_FROM_LIST(p); +#endif #if MEMORY_LIMIT AG(allocated_memory) -= SIZE; @@ -294,7 +299,9 @@ CALCULATE_REAL_SIZE_AND_CACHE_INDEX(size); HANDLE_BLOCK_INTERRUPTIONS(); +#if ZEND_DEBUG || !defined(ZEND_MM) REMOVE_POINTER_FROM_LIST(p); +#endif p = (zend_mem_header *) ZEND_DO_REALLOC(p, sizeof(zend_mem_header)+MEM_HEADER_PADDING+SIZE+END_MAGIC_SIZE); if (!p) { if (!allow_failure) { @@ -305,11 +312,15 @@ exit(1); #endif } +#if ZEND_DEBUG || !defined(ZEND_MM) ADD_POINTER_TO_LIST(orig); +#endif HANDLE_UNBLOCK_INTERRUPTIONS(); return (void *)NULL; } +#if ZEND_DEBUG || !defined(ZEND_MM) ADD_POINTER_TO_LIST(p); +#endif #if ZEND_DEBUG p->filename = __zend_filename; p->lineno = __zend_lineno; @@ -396,14 +407,7 @@ ZEND_API void start_memory_manager(TSRMLS_D) { -#if 0 -#ifndef ZTS - int i, j; - void *cached_entries[MAX_CACHED_MEMORY][MAX_CACHED_ENTRIES]; -#endif -#endif - - AG(phead) = AG(head) = NULL; + AG(head) = NULL; #if MEMORY_LIMIT AG(memory_limit) = 1<<30; /* ridiculous limit, effectively no limit */ @@ -412,30 +416,17 @@ AG(allocated_memory_peak) = 0; #endif +#if ZEND_ENABLE_FAST_CACHE memset(AG(fast_cache_list_head), 0, sizeof(AG(fast_cache_list_head))); +#endif +#if !ZEND_DISABLE_MEMORY_CACHE memset(AG(cache_count), 0, sizeof(AG(cache_count))); - -#ifdef ZEND_WIN32 - AG(memory_heap) = HeapCreate(HEAP_NO_SERIALIZE, 256*1024, 0); #endif -#if 0 -#ifndef ZTS - /* Initialize cache, to prevent fragmentation */ - /* We can't do this in ZTS mode, because calling emalloc() from within start_memory_manager() - * will yield an endless recursion calling to alloc_globals_ctor() - */ - for (i=1; i<MAX_CACHED_MEMORY; i++) { - for (j=0; j<PRE_INIT_CACHE_ENTRIES; j++) { - cached_entries[i][j] = emalloc(8*i); - } - } - for (i=1; i<MAX_CACHED_MEMORY; i++) { - for (j=0; j<PRE_INIT_CACHE_ENTRIES; j++) { - efree(cached_entries[i][j]); - } - } -#endif +#ifdef ZEND_MM + zend_mm_startup(&AG(mm_heap), 256*1024); +#elif defined(ZEND_WIN32) + AG(memory_heap) = HeapCreate(HEAP_NO_SERIALIZE, 256*1024, 0); #endif #if ZEND_DEBUG @@ -448,30 +439,43 @@ ZEND_API void shutdown_memory_manager(int silent, int clean_cache TSRMLS_DC) { zend_mem_header *p, *t; - unsigned int fci, i, j; + #if ZEND_DEBUG int had_leaks = 0; #endif - zend_fast_cache_list_entry *fast_cache_list_entry, *next_fast_cache_list_entry; -#if defined(ZEND_WIN32) && !ZEND_DEBUG +#if defined(ZEND_MM) && !ZEND_DEBUG + if (clean_cache) { + zend_mm_shutdown(&AG(mm_heap)); + return; + } +#elif defined(ZEND_WIN32) && !ZEND_DEBUG if (clean_cache && AG(memory_heap)) { HeapDestroy(AG(memory_heap)); return; } #endif - for (fci=0; fci<MAX_FAST_CACHE_TYPES; fci++) { - fast_cache_list_entry = AG(fast_cache_list_head)[fci]; - while (fast_cache_list_entry) { - next_fast_cache_list_entry = fast_cache_list_entry->next; - efree(fast_cache_list_entry); - fast_cache_list_entry = next_fast_cache_list_entry; +#if ZEND_ENABLE_FAST_CACHE + { + zend_fast_cache_list_entry *fast_cache_list_entry, *next_fast_cache_list_entry; + unsigned int fci; + + for (fci=0; fci<MAX_FAST_CACHE_TYPES; fci++) { + fast_cache_list_entry = AG(fast_cache_list_head)[fci]; + while (fast_cache_list_entry) { + next_fast_cache_list_entry = fast_cache_list_entry->next; + efree(fast_cache_list_entry); + fast_cache_list_entry = next_fast_cache_list_entry; + } + AG(fast_cache_list_head)[fci] = NULL; } - AG(fast_cache_list_head)[fci] = NULL; } +#endif /* ZEND_ENABLE_FAST_CACHE */ +#if !ZEND_DISABLE_MEMORY_CACHE && !defined(ZEND_MM) if (1 || clean_cache) { + unsigned int i, j; zend_mem_header *ptr; for (i=1; i<MAX_CACHED_MEMORY; i++) { @@ -486,7 +490,9 @@ AG(cache_count)[i] = 0; } } +#endif /* !ZEND_DISABLE_MEMORY_CACHE */ +#if ZEND_DEBUG || !defined(ZEND_MM) p = AG(head); t = AG(head); while (t) { @@ -516,7 +522,7 @@ } #endif #if MEMORY_LIMIT - AG(allocated_memory) -= t->size; + AG(allocated_memory) -= REAL_SIZE(t->size); #endif p = t->pNext; REMOVE_POINTER_FROM_LIST(t); @@ -571,14 +577,21 @@ } } while (0); +#endif + +#endif -#if defined(ZEND_WIN32) && ZEND_DEBUG +#if defined(ZEND_MM) && ZEND_DEBUG + if (clean_cache) { + zend_mm_shutdown(&AG(mm_heap)); + return; + } +#elif defined(ZEND_WIN32) && ZEND_DEBUG if (clean_cache && AG(memory_heap)) { HeapDestroy(AG(memory_heap)); + return; } #endif - -#endif } @@ -737,32 +750,10 @@ #endif -ZEND_API int _persist_alloc(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) -{ - zend_mem_header *p = (zend_mem_header *) ((char *)ptr-sizeof(zend_mem_header)-MEM_HEADER_PADDING); - TSRMLS_FETCH(); - -#if ZEND_DEBUG - _mem_block_check(ptr, 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); -#endif - - HANDLE_BLOCK_INTERRUPTIONS(); - - /* remove the block from the non persistent list */ - REMOVE_POINTER_FROM_LIST(p); - - p->persistent = 1; - - /* add the block to the persistent list */ - ADD_POINTER_TO_LIST(p); - HANDLE_UNBLOCK_INTERRUPTIONS(); - return REAL_SIZE(p->size)+sizeof(zend_mem_header)+MEM_HEADER_PADDING; -} - - /* * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.5 +8 -6 ZendEngine2/zend_alloc.h Index: zend_alloc.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_alloc.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_alloc.h 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_alloc.h 11 Feb 2003 02:40:18 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_alloc.h,v 1.41 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_ALLOC_H #define ZEND_ALLOC_H @@ -26,6 +27,8 @@ #include "../TSRM/TSRM.h" #include "zend_globals_macros.h" +#include "zend_mm.h" + #define MEM_BLOCK_START_MAGIC 0x7312F8DCL #define MEM_BLOCK_END_MAGIC 0x2A8FCC84L #define MEM_BLOCK_FREED_MAGIC 0x99954317L @@ -43,10 +46,11 @@ THREAD_T thread_id; # endif #endif +#if ZEND_DEBUG || !defined(ZEND_MM) struct _zend_mem_header *pNext; struct _zend_mem_header *pLast; - unsigned int size:30; - unsigned int persistent:1; +#endif + unsigned int size:31; unsigned int cached:1; } zend_mem_header; @@ -79,7 +83,6 @@ ZEND_API void *_erealloc(void *ptr, size_t size, int allow_failure ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ZEND_API char *_estrdup(const char *s ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); ZEND_API char *_estrndup(const char *s, unsigned int length ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); -ZEND_API int _persist_alloc(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); /* Standard wrapper macros */ #define emalloc(size) _emalloc((size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) @@ -89,7 +92,6 @@ #define erealloc_recoverable(ptr, size) _erealloc((ptr), (size), 1 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) #define estrdup(s) _estrdup((s) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) #define estrndup(s, length) _estrndup((s), (length) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) -#define persist_alloc(p) _persist_alloc((p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) /* Relay wrapper macros */ #define emalloc_rel(size) _emalloc((size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) @@ -99,7 +101,6 @@ #define erealloc_recoverable_rel(ptr, size) _erealloc((ptr), (size), 1 ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) #define estrdup_rel(s) _estrdup((s) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) #define estrndup_rel(s, length) _estrndup((s), (length) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) -#define persist_alloc_rel(p) _persist_alloc((p) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) /* Selective persistent/non persistent allocation macros */ #define pemalloc(size, persistent) ((persistent)?malloc(size):emalloc(size)) @@ -137,5 +138,6 @@ * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.8 +474 -70 ZendEngine2/zend_builtin_functions.c Index: zend_builtin_functions.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_builtin_functions.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- zend_builtin_functions.c 3 Aug 2002 08:56:16 -0000 1.7 +++ zend_builtin_functions.c 11 Feb 2003 02:40:18 -0000 1.8 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,11 +17,13 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_builtin_functions.c,v 1.174 2003/02/10 10:04:08 zeev Exp $ */ #include "zend.h" #include "zend_API.h" #include "zend_builtin_functions.h" #include "zend_constants.h" +#include "zend_ini.h" #undef ZEND_TEST_EXCEPTIONS @@ -43,10 +45,12 @@ static ZEND_FUNCTION(method_exists); static ZEND_FUNCTION(class_exists); static ZEND_FUNCTION(function_exists); +#if ZEND_DEBUG static ZEND_FUNCTION(leak); #ifdef ZEND_TEST_EXCEPTIONS static ZEND_FUNCTION(crash); #endif +#endif static ZEND_FUNCTION(get_included_files); static ZEND_FUNCTION(is_subclass_of); static ZEND_FUNCTION(is_a); @@ -56,6 +60,8 @@ static ZEND_FUNCTION(trigger_error); static ZEND_FUNCTION(set_error_handler); static ZEND_FUNCTION(restore_error_handler); +static ZEND_FUNCTION(set_exception_handler); +static ZEND_FUNCTION(restore_exception_handler); static ZEND_FUNCTION(get_declared_classes); static ZEND_FUNCTION(get_defined_functions); static ZEND_FUNCTION(get_defined_vars); @@ -66,8 +72,12 @@ static ZEND_FUNCTION(get_extension_funcs); static ZEND_FUNCTION(get_defined_constants); static ZEND_FUNCTION(debug_backtrace); +static ZEND_FUNCTION(debug_print_backtrace); #if ZEND_DEBUG static ZEND_FUNCTION(zend_test_func); +#ifdef ZTS +static ZEND_FUNCTION(zend_thread_id); +#endif #endif ZEND_API unsigned char first_arg_force_ref[] = { 1, BYREF_FORCE }; @@ -93,10 +103,12 @@ ZEND_FE(method_exists, NULL) ZEND_FE(class_exists, NULL) ZEND_FE(function_exists, NULL) +#if ZEND_DEBUG ZEND_FE(leak, NULL) #ifdef ZEND_TEST_EXCEPTIONS ZEND_FE(crash, NULL) #endif +#endif ZEND_FE(get_included_files, NULL) ZEND_FALIAS(get_required_files, get_included_files, NULL) ZEND_FE(is_subclass_of, NULL) @@ -108,6 +120,8 @@ ZEND_FALIAS(user_error, trigger_error, NULL) ZEND_FE(set_error_handler, NULL) ZEND_FE(restore_error_handler, NULL) + ZEND_FE(set_exception_handler, NULL) + ZEND_FE(restore_exception_handler, NULL) ZEND_FE(get_declared_classes, NULL) ZEND_FE(get_defined_functions, NULL) ZEND_FE(get_defined_vars, NULL) @@ -118,8 +132,12 @@ ZEND_FE(get_extension_funcs, NULL) ZEND_FE(get_defined_constants, NULL) ZEND_FE(debug_backtrace, NULL) + ZEND_FE(debug_print_backtrace, NULL) #if ZEND_DEBUG ZEND_FE(zend_test_func, NULL) +#ifdef ZTS + ZEND_FE(zend_thread_id, NULL) +#endif #endif { NULL, NULL, NULL } }; @@ -127,7 +145,7 @@ int zend_startup_builtin_functions(TSRMLS_D) { - return zend_register_functions(builtin_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); + return zend_register_functions(NULL, builtin_functions, NULL, MODULE_PERSISTENT TSRMLS_CC); } @@ -398,8 +416,8 @@ if (zend_get_parameters_ex(1, &arg) == FAILURE) { RETURN_FALSE; } - convert_to_long_ex(arg); - EG(error_reporting)=(*arg)->value.lval; + convert_to_string_ex(arg); + zend_alter_ini_entry("error_reporting", sizeof("error_reporting"), Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME); break; default: ZEND_WRONG_PARAM_COUNT(); @@ -419,7 +437,7 @@ int case_sensitive; zend_constant c; - switch(ZEND_NUM_ARGS()) { + switch (ZEND_NUM_ARGS()) { case 2: if (zend_get_parameters_ex(2, &var, &val)==FAILURE) { RETURN_FALSE; @@ -442,7 +460,7 @@ break; } - switch((*val)->type) { + switch ((*val)->type) { case IS_LONG: case IS_DOUBLE: case IS_STRING: @@ -541,17 +559,12 @@ char *name; zend_uint name_length; - /* first try asking handler for parent class name */ - if (Z_OBJ_HT_PP(arg)->get_class_name != NULL && - Z_OBJ_HT_PP(arg)->get_class_name(*arg, &name, &name_length, 1 TSRMLS_CC) == SUCCESS) { - name = ce->name; - name_length = ce->name_length; - + if (Z_OBJ_HT_PP(arg)->get_class_name + && Z_OBJ_HT_PP(arg)->get_class_name(*arg, &name, &name_length, 1 TSRMLS_CC) == SUCCESS) { RETURN_STRINGL(name, name_length, 1); - } - /* then try getting the class entry - if successfull, will fall through to standard ce handling */ - if(!Z_OBJ_HT_PP(arg)->get_class_entry || !(ce = zend_get_class_entry(*arg))) { + } else if (Z_OBJ_HT_PP(arg)->get_class_entry && (ce = zend_get_class_entry(*arg))) { + RETURN_STRINGL(ce->name, ce->name_length, 1); + } else { RETURN_FALSE; } } else if (Z_TYPE_PP(arg) == IS_STRING) { @@ -559,7 +572,7 @@ SEPARATE_ZVAL(arg); zend_str_tolower(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg)); - if(zend_hash_find(EG(class_table), Z_STRVAL_PP(arg), Z_STRLEN_PP(arg)+1, (void **)&pce) == SUCCESS) { + if (zend_lookup_class(Z_STRVAL_PP(arg), Z_STRLEN_PP(arg), &pce TSRMLS_CC) == SUCCESS) { ce = *pce; } } @@ -588,7 +601,7 @@ } /* TBI!! new object handlers */ - if(!IS_ZEND_STD_OBJECT(**obj)) { + if (!HAS_CLASS_ENTRY(**obj)) { RETURN_FALSE; } @@ -610,7 +623,7 @@ efree(lcname); RETURN_FALSE; } -/* }}} */ + /* {{{ proto bool is_subclass_of(object object, string class_name) Returns true if the object has this class as one of its parents */ @@ -647,7 +660,7 @@ lcname = estrndup((*class_name)->value.str.val, (*class_name)->value.str.len); zend_str_tolower(lcname, (*class_name)->value.str.len); - if (zend_hash_find(EG(class_table), lcname, (*class_name)->value.str.len+1, (void **)&pce) == FAILURE) { + if (zend_lookup_class(lcname, Z_STRLEN_PP(class_name), &pce TSRMLS_CC) == FAILURE) { efree(lcname); RETURN_FALSE; } else { @@ -678,7 +691,7 @@ if ((*obj)->type != IS_OBJECT) { RETURN_FALSE; } - if(Z_OBJ_HT_PP(obj)->get_properties == NULL) { + if (Z_OBJ_HT_PP(obj)->get_properties == NULL) { RETURN_FALSE; } @@ -706,14 +719,15 @@ if (Z_TYPE_PP(class) == IS_OBJECT) { /* TBI!! new object handlers */ - if(!IS_ZEND_STD_OBJECT(**class)) { + if (!HAS_CLASS_ENTRY(**class)) { RETURN_FALSE; } ce = Z_OBJCE_PP(class); } else if (Z_TYPE_PP(class) == IS_STRING) { SEPARATE_ZVAL(class); zend_str_tolower(Z_STRVAL_PP(class), Z_STRLEN_PP(class)); - if(zend_hash_find(EG(class_table), Z_STRVAL_PP(class), Z_STRLEN_PP(class)+1, (void **)&pce) == SUCCESS) { + + if (zend_lookup_class(Z_STRVAL_PP(class), Z_STRLEN_PP(class), &pce TSRMLS_CC) == SUCCESS) { ce = *pce; } } @@ -751,7 +765,7 @@ } /* TBI!! new object handlers */ - if(!IS_ZEND_STD_OBJECT(**klass)) { + if (!HAS_CLASS_ENTRY(**klass)) { RETURN_FALSE; } @@ -798,8 +812,9 @@ ZEND_FUNCTION(function_exists) { zval **function_name; + zend_function *func; char *lcname; - int retval; + zend_bool retval; if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &function_name)==FAILURE) { ZEND_WRONG_PARAM_COUNT(); @@ -808,14 +823,23 @@ lcname = estrndup((*function_name)->value.str.val, (*function_name)->value.str.len); zend_str_tolower(lcname, (*function_name)->value.str.len); - retval = zend_hash_exists(EG(function_table), lcname, (*function_name)->value.str.len+1); + retval = (zend_hash_find(EG(function_table), lcname, (*function_name)->value.str.len+1, (void **)&func) == SUCCESS); efree(lcname); + /* + * A bit of a hack, but not a bad one: we see if the handler of the function + * is actually one that displays "function is disabled" message. + */ + if (retval && + func->internal_function.handler == zif_display_disabled_function) { + retval = 0; + } + RETURN_BOOL(retval); } /* }}} */ - +#if ZEND_DEBUG /* {{{ proto void leak(int num_bytes=3) Cause an intentional memory leak, for testing/debugging purposes */ ZEND_FUNCTION(leak) @@ -844,6 +868,7 @@ } #endif +#endif /* ZEND_DEBUG */ /* {{{ proto array get_included_files(void) Returns an array with the file names that were include_once()'d */ @@ -871,7 +896,7 @@ int error_type = E_USER_NOTICE; zval **z_error_type, **z_error_message; - switch(ZEND_NUM_ARGS()) { + switch (ZEND_NUM_ARGS()) { case 1: if (zend_get_parameters_ex(1, &z_error_message)==FAILURE) { ZEND_WRONG_PARAM_COUNT(); @@ -954,6 +979,60 @@ } RETURN_TRUE; } +/* }}} */ + + +/* {{{ proto string set_exception_handler(string exception_handler) + Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */ +ZEND_FUNCTION(set_exception_handler) +{ + zval **exception_handler; + zend_bool had_orig_exception_handler=0; + + if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &exception_handler)==FAILURE) { + ZEND_WRONG_PARAM_COUNT(); + } + + convert_to_string_ex(exception_handler); + if (EG(user_exception_handler)) { + had_orig_exception_handler = 1; + *return_value = *EG(user_exception_handler); + zval_copy_ctor(return_value); + zend_ptr_stack_push(&EG(user_exception_handlers), EG(user_exception_handler)); + } + ALLOC_ZVAL(EG(user_exception_handler)); + + if (Z_STRLEN_PP(exception_handler)==0) { /* unset user-defined handler */ + FREE_ZVAL(EG(user_exception_handler)); + EG(user_exception_handler) = NULL; + RETURN_TRUE; + } + + *EG(user_exception_handler) = **exception_handler; + zval_copy_ctor(EG(user_exception_handler)); + + if (!had_orig_exception_handler) { + RETURN_NULL(); + } +} +/* }}} */ + + +/* {{{ proto void restore_exception_handler(void) + Restores the previously defined exception handler function */ +ZEND_FUNCTION(restore_exception_handler) +{ + if (EG(user_exception_handler)) { + zval_ptr_dtor(&EG(user_exception_handler)); + } + if (zend_ptr_stack_num_elements(&EG(user_exception_handlers))==0) { + EG(user_exception_handler) = NULL; + } else { + EG(user_exception_handler) = zend_ptr_stack_pop(&EG(user_exception_handlers)); + } + RETURN_TRUE; +} +/* }}} */ static int copy_class_name(zend_class_entry **pce, int num_args, va_list args, zend_hash_key *hash_key) @@ -1111,6 +1190,14 @@ zend_get_parameters(ht, 2, &arg1, &arg2); } + + +#ifdef ZTS +ZEND_FUNCTION(zend_thread_id) +{ + RETURN_LONG(tsrm_thread_id()); +} +#endif #endif /* {{{ proto string get_resource_type(resource res) @@ -1165,7 +1252,7 @@ ZEND_FUNCTION(get_loaded_extensions) { if (ZEND_NUM_ARGS() != 0) { - WRONG_PARAM_COUNT; + ZEND_WRONG_PARAM_COUNT(); } array_init(return_value); @@ -1178,15 +1265,237 @@ Return an array containing the names and values of all defined constants */ ZEND_FUNCTION(get_defined_constants) { - if (ZEND_NUM_ARGS() != 0) { - WRONG_PARAM_COUNT; + int argc = ZEND_NUM_ARGS(); + + if (argc != 0 && argc != 1) { + ZEND_WRONG_PARAM_COUNT(); } array_init(return_value); - zend_hash_apply_with_argument(EG(zend_constants), (apply_func_arg_t) add_constant_info, return_value TSRMLS_CC); + + if (argc) { + HashPosition pos; + zend_constant *val; + int prev_module_number = -1; + char **module_names; + zval *module_constants = NULL; + zend_module_entry *module; + int i = 1; + + module_names = emalloc((zend_hash_num_elements(&module_registry) + 1) * sizeof(char *)); + zend_hash_internal_pointer_reset_ex(&module_registry, &pos); + while (zend_hash_get_current_data_ex(EG(zend_constants), (void **) &module, &pos) != FAILURE) { + module_names[i++] = module->name; + zend_hash_move_forward_ex(&module_registry, &pos); + } + + zend_hash_internal_pointer_reset_ex(EG(zend_constants), &pos); + + while (zend_hash_get_current_data_ex(EG(zend_constants), (void **) &val, &pos) != FAILURE) { + zval *const_val; + + if (val->module_number != prev_module_number) { + if (prev_module_number != -1) { + if (prev_module_number == 0) { + add_assoc_zval(return_value, "internal", module_constants); + } else if (prev_module_number <= i) { + add_assoc_zval(return_value, module_names[prev_module_number], module_constants); + } else { + add_assoc_zval(return_value, "user", module_constants); + } + } + + MAKE_STD_ZVAL(module_constants); + array_init(module_constants); + + prev_module_number = val->module_number; + } + + MAKE_STD_ZVAL(const_val); + *const_val = val->value; + zval_copy_ctor(const_val); + INIT_PZVAL(const_val); + + add_assoc_zval_ex(module_constants, val->name, val->name_len, const_val); + + zend_hash_move_forward_ex(EG(zend_constants), &pos); + } + if (module_constants) { + if (prev_module_number == 0) { + add_assoc_zval(return_value, "internal", module_constants); + } else if (prev_module_number <= i) { + add_assoc_zval(return_value, module_names[prev_module_number], module_constants); + } else { + add_assoc_zval(return_value, "user", module_constants); + } + } + efree(module_names); + } else { + zend_hash_apply_with_argument(EG(zend_constants), (apply_func_arg_t) add_constant_info, return_value TSRMLS_CC); + } } +/* }}} */ + +static zval *debug_backtrace_get_args(void ***curpos TSRMLS_DC) { + void **p = *curpos - 2; + zval *arg_array, **arg; + int arg_count = (ulong) *p; + + *curpos -= (arg_count+2); + + MAKE_STD_ZVAL(arg_array); + array_init(arg_array); + p -= arg_count; + + while (--arg_count >= 0) { + arg = (zval **) p++; + SEPARATE_ZVAL_TO_MAKE_IS_REF(arg); + (*arg)->refcount++; + add_next_index_zval(arg_array, *arg); + } + return arg_array; +} + +void debug_print_backtrace_args(zval *arg_array TSRMLS_DC) +{ + zval **tmp; + HashPosition iterator; + int i = 0; + + zend_hash_internal_pointer_reset_ex(arg_array->value.ht, &iterator); + while (zend_hash_get_current_data_ex(arg_array->value.ht, (void **) &tmp, &iterator) == SUCCESS) { + if (i++) { + ZEND_PUTS(", "); + } + zend_print_flat_zval_r(*tmp TSRMLS_CC); + zend_hash_move_forward_ex(arg_array->value.ht, &iterator); + } +} + +/* {{{ proto void debug_print_backtrace(void) */ +ZEND_FUNCTION(debug_print_backtrace) +{ + zend_execute_data *ptr; + int lineno; + char *function_name; + char *filename; + char *class_name = NULL; + char *call_type; + char *include_filename = NULL; + zval *arg_array = NULL; + void **cur_arg_pos = EG(argument_stack).top_element; + void **args = cur_arg_pos; + int arg_stack_consistent = 0; + int frames_on_stack = 0; + int indent = 0; + + if (ZEND_NUM_ARGS()) { + ZEND_WRONG_PARAM_COUNT(); + } + + while (--args >= EG(argument_stack).elements) { + if (*args--) { + break; + } + args -= *(ulong*)args; + frames_on_stack++; + if (args == EG(argument_stack).elements) { + arg_stack_consistent = 1; + break; + } + } + + ptr = EG(current_execute_data); + + /* skip debug_backtrace() */ + ptr = ptr->prev_execute_data; + cur_arg_pos -= 2; + frames_on_stack--; + + array_init(return_value); + + while (ptr) { + if (ptr->op_array) { + filename = ptr->op_array->filename; + lineno = ptr->opline->lineno; + } else { + filename = NULL; + } + + function_name = ptr->function_state.function->common.function_name; + + if (function_name) { + if (ptr->object) { + class_name = Z_OBJCE(*ptr->object)->name; + call_type = "->"; + } else if (ptr->function_state.function->common.scope) { + class_name = ptr->function_state.function->common.scope->name; + call_type = "::"; + } else { + class_name = NULL; + call_type = NULL; + } + if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) { + if (arg_stack_consistent && (frames_on_stack > 0)) { + arg_array = debug_backtrace_get_args(&cur_arg_pos TSRMLS_CC); + frames_on_stack--; + } + } + } else { + /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */ + zend_bool build_filename_arg = 1; + + switch (ptr->opline->op2.u.constant.value.lval) { + case ZEND_EVAL: + function_name = "eval"; + build_filename_arg = 0; + break; + case ZEND_INCLUDE: + function_name = "include"; + break; + case ZEND_REQUIRE: + function_name = "require"; + break; + case ZEND_INCLUDE_ONCE: + function_name = "include_once"; + break; + case ZEND_REQUIRE_ONCE: + function_name = "require_once"; + break; + default: + /* this can actually happen if you use debug_backtrace() in your error_handler and + * you're in the top-scope */ + function_name = "unknown"; + build_filename_arg = 0; + break; + } + + if (build_filename_arg && include_filename) { + MAKE_STD_ZVAL(arg_array); + array_init(arg_array); + add_next_index_string(arg_array, include_filename, 1); + } + } + zend_printf("#%-2d ", indent); + if (class_name) { + ZEND_PUTS(class_name); + ZEND_PUTS(call_type); + } + zend_printf("%s(", function_name?function_name:"main"); + if (arg_array) { + debug_print_backtrace_args(arg_array TSRMLS_CC); + zval_ptr_dtor(&arg_array); + } + zend_printf(") called at [%s:%d]\n", filename, lineno); + include_filename = filename; + ptr = ptr->prev_execute_data; + ++indent; + } +} + +/* }}} */ /* {{{ proto void debug_backtrace(void) Prints out a backtrace */ ZEND_FUNCTION(debug_backtrace) @@ -1196,55 +1505,138 @@ char *function_name; char *filename; char *class_name; - zend_uint class_name_length; + char *call_type; + char *include_filename = NULL; zval *stack_frame; + void **cur_arg_pos = EG(argument_stack).top_element; + void **args = cur_arg_pos; + int arg_stack_consistent = 0; + int frames_on_stack = 0; + + if (ZEND_NUM_ARGS()) { + ZEND_WRONG_PARAM_COUNT(); + } + + while (--args >= EG(argument_stack).elements) { + if (*args--) { + break; + } + args -= *(ulong*)args; + frames_on_stack++; + + if (args == EG(argument_stack).elements) { + arg_stack_consistent = 1; + break; + } + } ptr = EG(current_execute_data); - lineno = ptr->opline->lineno; - + + /* skip debug_backtrace() */ + ptr = ptr->prev_execute_data; + cur_arg_pos -= 2; + frames_on_stack--; + array_init(return_value); while (ptr) { MAKE_STD_ZVAL(stack_frame); array_init(stack_frame); - class_name = NULL; + if (ptr->op_array) { + filename = ptr->op_array->filename; + lineno = ptr->opline->lineno; + add_assoc_string_ex(stack_frame, "file", sizeof("file"), filename, 1); + add_assoc_long_ex(stack_frame, "line", sizeof("line"), lineno); - if (ptr->object) { - class_name = Z_OBJCE(*ptr->object)->name; - class_name_length = Z_OBJCE(*ptr->object)->name_length; - } - if (ptr->function_state.function->common.scope) { - class_name = ptr->function_state.function->common.scope->name; + /* try to fetch args only if an FCALL was just made - elsewise we're in the middle of a function + * and debug_baktrace() might have been called by the error_handler. in this case we don't + * want to pop anything of the argument-stack */ + } else { + filename = NULL; } + function_name = ptr->function_state.function->common.function_name; - if (!function_name) { - function_name = "_main_"; - } - ptr = ptr->prev_execute_data; - if (!ptr) { - zval_ptr_dtor(&stack_frame); - break; - } + if (function_name) { + add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1); - filename = ptr->function_state.function->op_array.filename; + if (ptr->object) { + class_name = Z_OBJCE(*ptr->object)->name; + call_type = "->"; + } else if (ptr->function_state.function->common.scope) { + class_name = ptr->function_state.function->common.scope->name; + call_type = "::"; + } else { + class_name = NULL; + call_type = NULL; + } - add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1); - if (class_name) { - add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, 1); + if (class_name) { + add_assoc_string_ex(stack_frame, "class", sizeof("class"), class_name, 1); + add_assoc_string_ex(stack_frame, "type", sizeof("type"), call_type, 1); + } + + if ((! ptr->opline) || ((ptr->opline->opcode == ZEND_DO_FCALL_BY_NAME) || (ptr->opline->opcode == ZEND_DO_FCALL))) { + if (arg_stack_consistent && (frames_on_stack > 0)) { + add_assoc_zval_ex(stack_frame, "args", sizeof("args"), debug_backtrace_get_args(&cur_arg_pos TSRMLS_CC)); + frames_on_stack--; + } + } + } else { + /* i know this is kinda ugly, but i'm trying to avoid extra cycles in the main execution loop */ + zend_bool build_filename_arg = 1; + + switch (ptr->opline->op2.u.constant.value.lval) { + case ZEND_EVAL: + function_name = "eval"; + build_filename_arg = 0; + break; + case ZEND_INCLUDE: + function_name = "include"; + break; + case ZEND_REQUIRE: + function_name = "require"; + break; + case ZEND_INCLUDE_ONCE: + function_name = "include_once"; + break; + case ZEND_REQUIRE_ONCE: + function_name = "require_once"; + break; + default: + /* this can actually happen if you use debug_backtrace() in your error_handler and + * you're in the top-scope */ + function_name = "unknown"; + build_filename_arg = 0; + break; + } + + if (build_filename_arg && include_filename) { + zval *arg_array; + + MAKE_STD_ZVAL(arg_array); + array_init(arg_array); + + /* include_filename always points to the last filename of the last last called-fuction. + if we have called include in the frame above - this is the file we have included. + */ + + add_next_index_string(arg_array, include_filename, 1); + add_assoc_zval_ex(stack_frame, "args", sizeof("args"), arg_array); + } + + add_assoc_string_ex(stack_frame, "function", sizeof("function"), function_name, 1); } - add_assoc_string_ex(stack_frame, "file", sizeof("file"), filename, 1); - add_assoc_long_ex(stack_frame, "line", sizeof("line"), lineno); - /* add_assoc_stringl_ex(stack_frame, "class", sizeof("class")-1, class_name, class_name_length, 1); */ - + add_next_index_zval(return_value, stack_frame); - if (ptr->opline) { - lineno = ptr->opline->lineno; - } + include_filename = filename; + + ptr = ptr->prev_execute_data; } } +/* }}} */ /* {{{ proto bool extension_loaded(string extension_name) @@ -1254,7 +1646,7 @@ zval **extension_name; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &extension_name)) { - WRONG_PARAM_COUNT; + ZEND_WRONG_PARAM_COUNT(); } convert_to_string_ex(extension_name); @@ -1276,20 +1668,24 @@ zend_function_entry *func; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &extension_name)) { - WRONG_PARAM_COUNT; + ZEND_WRONG_PARAM_COUNT(); } convert_to_string_ex(extension_name); - if (zend_hash_find(&module_registry, Z_STRVAL_PP(extension_name), - Z_STRLEN_PP(extension_name)+1, (void**)&module) == FAILURE) { - return; + if (strncasecmp(Z_STRVAL_PP(extension_name), "zend", sizeof("zend"))) { + if (zend_hash_find(&module_registry, Z_STRVAL_PP(extension_name), + Z_STRLEN_PP(extension_name)+1, (void**)&module) == FAILURE) { + RETURN_FALSE; + } + + if (!(func = module->functions)) { + RETURN_FALSE; + } + } else { + func = builtin_functions; } array_init(return_value); - func = module->functions; - if (!func) { - return; - } while (func->fname) { add_next_index_string(return_value, func->fname, 1); @@ -1297,3 +1693,11 @@ } } /* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +10 -1 ZendEngine2/zend_builtin_functions.h Index: zend_builtin_functions.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_builtin_functions.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_builtin_functions.h 29 Apr 2002 02:25:26 -0000 1.2 +++ zend_builtin_functions.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_builtin_functions.h,v 1.11 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_BUILTIN_FUNCTIONS_H #define ZEND_BUILTIN_FUNCTIONS_H @@ -24,3 +25,11 @@ int zend_startup_builtin_functions(TSRMLS_D); #endif /* ZEND_BUILTIN_FUNCTIONS_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.5 +598 -426 ZendEngine2/zend_compile.c Index: zend_compile.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_compile.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_compile.c 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_compile.c 11 Feb 2003 02:40:18 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_compile.c,v 1.361 2003/02/10 16:46:05 zeev Exp $ */ #include "zend_language_parser.h" #include "zend.h" @@ -34,8 +35,7 @@ ZEND_API zend_executor_globals executor_globals; #endif - -static void build_runtime_defined_function_key(zval *result, zval *name, zend_op *opline TSRMLS_DC) +static void build_runtime_defined_function_key(zval *result, char *name, int name_length, zend_op *opline TSRMLS_DC) { char lineno_buf[32]; uint lineno_len; @@ -49,9 +49,9 @@ } /* NULL, name length, filename length, line number length */ - result->value.str.len = 1+name->value.str.len+strlen(filename)+lineno_len; + result->value.str.len = 1+name_length+strlen(filename)+lineno_len; result->value.str.val = (char *) emalloc(result->value.str.len+1); - sprintf(result->value.str.val, "%c%s%s%s", '\0', name->value.str.val, filename, lineno_buf); + sprintf(result->value.str.val, "%c%s%s%s", '\0', name, filename, lineno_buf); result->type = IS_STRING; result->refcount = 1; } @@ -80,9 +80,11 @@ zend_stack_init(&CG(list_stack)); CG(handle_op_arrays) = 1; CG(in_compilation) = 0; + CG(start_lineno) = 0; init_compiler_declarables(TSRMLS_C); CG(throw_list) = NULL; - zend_register_auto_global("GLOBALS", sizeof("GLOBALS")-1 TSRMLS_CC); + zend_register_auto_global("GLOBALS", sizeof("GLOBALS")-1 TSRMLS_CC); + CG(in_clone_method) = 0; } @@ -152,7 +154,7 @@ static zend_uint get_temporary_variable(zend_op_array *op_array) { - return (op_array->T)++; + return (op_array->T)++ * sizeof(temp_variable); } @@ -183,84 +185,71 @@ #define MAKE_NOP(opline) { opline->opcode = ZEND_NOP; memset(&opline->result,0,sizeof(znode)); memset(&opline->op1,0,sizeof(znode)); memset(&opline->op2,0,sizeof(znode)); opline->result.op_type=opline->op1.op_type=opline->op2.op_type=IS_UNUSED; } -static void zend_replace_object_fetch(zend_op *last_op, znode *value TSRMLS_DC) + +static void zend_do_op_data(zend_op *data_op, znode *value TSRMLS_DC) { - if(value->op_type != IS_VAR) { - last_op->opcode = ZEND_MAKE_VAR; - last_op->result.op_type = IS_VAR; - last_op->result.u.EA.type = 0; - last_op->result.u.var = get_temporary_variable(CG(active_op_array)); - last_op->op1 = *value; - SET_UNUSED(last_op->op2); - value->op_type = IS_VAR; - value->u.EA.type = 0; - value->u.var = last_op->result.u.var; - } else { - MAKE_NOP(last_op); - } + data_op->opcode = ZEND_OP_DATA; + data_op->op1 = *value; + SET_UNUSED(data_op->op2); } void zend_do_binary_assign_op(zend_uchar op, znode *result, znode *op1, znode *op2 TSRMLS_DC) { int last_op_number = get_next_op_number(CG(active_op_array))-1; - zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number]; zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - - if(last_op->opcode == ZEND_FETCH_OBJ_RW) { - - switch(op) { + zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number]; + + if (last_op->opcode == ZEND_FETCH_OBJ_RW) { + switch (op) { case ZEND_ASSIGN_ADD: - opline->opcode = ZEND_ASSIGN_ADD_OBJ; + last_op->opcode = ZEND_ASSIGN_ADD_OBJ; break; case ZEND_ASSIGN_SUB: - opline->opcode = ZEND_ASSIGN_SUB_OBJ; + last_op->opcode = ZEND_ASSIGN_SUB_OBJ; break; case ZEND_ASSIGN_MUL: - opline->opcode = ZEND_ASSIGN_MUL_OBJ; + last_op->opcode = ZEND_ASSIGN_MUL_OBJ; break; case ZEND_ASSIGN_DIV: - opline->opcode = ZEND_ASSIGN_DIV_OBJ; + last_op->opcode = ZEND_ASSIGN_DIV_OBJ; break; case ZEND_ASSIGN_MOD: - opline->opcode = ZEND_ASSIGN_MOD_OBJ; + last_op->opcode = ZEND_ASSIGN_MOD_OBJ; break; case ZEND_ASSIGN_SL: - opline->opcode = ZEND_ASSIGN_SL_OBJ; + last_op->opcode = ZEND_ASSIGN_SL_OBJ; break; case ZEND_ASSIGN_SR: - opline->opcode = ZEND_ASSIGN_SR_OBJ; + last_op->opcode = ZEND_ASSIGN_SR_OBJ; break; case ZEND_ASSIGN_CONCAT: - opline->opcode = ZEND_ASSIGN_CONCAT_OBJ; + last_op->opcode = ZEND_ASSIGN_CONCAT_OBJ; break; case ZEND_ASSIGN_BW_OR: - opline->opcode = ZEND_ASSIGN_BW_OR_OBJ; + last_op->opcode = ZEND_ASSIGN_BW_OR_OBJ; break; case ZEND_ASSIGN_BW_AND: - opline->opcode = ZEND_ASSIGN_BW_AND_OBJ; + last_op->opcode = ZEND_ASSIGN_BW_AND_OBJ; break; case ZEND_ASSIGN_BW_XOR: - opline->opcode = ZEND_ASSIGN_BW_XOR_OBJ; + last_op->opcode = ZEND_ASSIGN_BW_XOR_OBJ; break; default: - zend_error(E_ERROR, "Unknown binary op opcode %d", op); + zend_error(E_COMPILE_ERROR, "Unknown binary op opcode %d", op); } - - opline->op2 = last_op->op2; - opline->op1 = last_op->op1; - zend_replace_object_fetch(last_op, op2 TSRMLS_CC); - opline->extended_value = op2->u.var; - + + zend_do_op_data(opline, op2 TSRMLS_CC); + SET_UNUSED(opline->result); + *result = last_op->result; } else { opline->opcode = op; opline->op1 = *op1; opline->op2 = *op2; + opline->result.op_type = IS_VAR; + opline->result.u.EA.type = 0; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + *result = opline->result; } - - opline->result.op_type = IS_VAR; - opline->result.u.EA.type = 0; - opline->result.u.var = get_temporary_variable(CG(active_op_array)); - *result = opline->result; } @@ -285,11 +274,15 @@ *result = opline_ptr->result; SET_UNUSED(opline_ptr->op2); - if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING - && zend_hash_exists(CG(auto_globals), varname->u.constant.value.str.val, varname->u.constant.value.str.len+1)) { - opline_ptr->op2.u.EA.type = ZEND_FETCH_GLOBAL; - } else { - opline_ptr->op2.u.EA.type = ZEND_FETCH_LOCAL; + opline_ptr->op2.u.EA.type = ZEND_FETCH_LOCAL; + if (varname->op_type == IS_CONST && varname->u.constant.type == IS_STRING) { + if (zend_hash_exists(CG(auto_globals), varname->u.constant.value.str.val, varname->u.constant.value.str.len+1)) { + opline_ptr->op2.u.EA.type = ZEND_FETCH_GLOBAL; + } else { +/* if (CG(active_op_array)->static_variables && zend_hash_exists(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1)) { + opline_ptr->op2.u.EA.type = ZEND_FETCH_STATIC; + } +*/ } } if (bp) { @@ -304,7 +297,7 @@ fetch_simple_variable_ex(result, varname, bp, ZEND_FETCH_W TSRMLS_CC); } -void zend_do_fetch_static_member(znode *class TSRMLS_DC) +void zend_do_fetch_static_member(znode *class_znode TSRMLS_DC) { zend_llist *fetch_list_ptr; zend_llist_element *le; @@ -314,7 +307,7 @@ le = fetch_list_ptr->head; opline_ptr = (zend_op *)le->data; - opline_ptr->op2 = *class; + opline_ptr->op2 = *class_znode; opline_ptr->op2.u.EA.type = ZEND_FETCH_STATIC_MEMBER; } @@ -374,30 +367,37 @@ SET_UNUSED(opline->op2); } +void zend_do_abstract_method(TSRMLS_D) +{ + zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + + opline->opcode = ZEND_RAISE_ABSTRACT_ERROR; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); +} + void zend_do_assign(znode *result, znode *variable, znode *value TSRMLS_DC) { int last_op_number = get_next_op_number(CG(active_op_array))-1; - zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number]; zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number]; - if(last_op->opcode == ZEND_FETCH_OBJ_W) { - opline->opcode = ZEND_ASSIGN_OBJ; - opline->op1 = last_op->op1; - opline->op2 = last_op->op2; - - zend_replace_object_fetch(last_op, value TSRMLS_CC); + if (last_op->opcode == ZEND_FETCH_OBJ_W) { + last_op->opcode = ZEND_ASSIGN_OBJ; - opline->extended_value = value->u.var; + zend_do_op_data(opline, value TSRMLS_CC); + SET_UNUSED(opline->result); + *result = last_op->result; } else { opline->opcode = ZEND_ASSIGN; opline->op1 = *variable; opline->op2 = *value; + opline->result.op_type = IS_VAR; + opline->result.u.EA.type = 0; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + *result = opline->result; } - opline->result.op_type = IS_VAR; - opline->result.u.EA.type = 0; - opline->result.u.var = get_temporary_variable(CG(active_op_array)); - *result = opline->result; } @@ -521,10 +521,10 @@ void zend_do_pre_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC) { int last_op_number = get_next_op_number(CG(active_op_array))-1; - zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number]; zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number]; - if(last_op->opcode == ZEND_FETCH_OBJ_RW) { + if (last_op->opcode == ZEND_FETCH_OBJ_RW) { opline->opcode = (op==ZEND_PRE_INC)?ZEND_PRE_INC_OBJ:ZEND_PRE_DEC_OBJ; opline->op1 = last_op->op1; opline->op2 = last_op->op2; @@ -546,10 +546,10 @@ void zend_do_post_incdec(znode *result, znode *op1, zend_uchar op TSRMLS_DC) { int last_op_number = get_next_op_number(CG(active_op_array))-1; - zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number]; zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + zend_op *last_op = &CG(active_op_array)->opcodes[last_op_number]; - if(last_op->opcode == ZEND_FETCH_OBJ_RW) { + if (last_op->opcode == ZEND_FETCH_OBJ_RW) { opline->opcode = (op==ZEND_POST_INC)?ZEND_POST_INC_OBJ:ZEND_POST_DEC_OBJ; opline->op1 = last_op->op1; opline->op2 = last_op->op2; @@ -632,10 +632,10 @@ zend_uint type = variable->u.EA.type; if (type & ZEND_PARSED_METHOD_CALL) { - zend_error(E_ERROR, "Can't use method return value in write context"); + zend_error(E_COMPILE_ERROR, "Can't use method return value in write context"); } if (type == ZEND_PARSED_FUNCTION_CALL) { - zend_error(E_ERROR, "Can't use function return value in write context"); + zend_error(E_COMPILE_ERROR, "Can't use function return value in write context"); } } @@ -714,14 +714,9 @@ { zend_llist *fetch_list_ptr; zend_llist_element *le; - zend_op *opline, *opline_ptr; + zend_op *opline, *opline_ptr=NULL; int num_of_created_opcodes = 0; - /* - if (zend_variable_buffer_empty(TSRMLS_C) && (type == BP_VAR_W || type == BP_VAR_RW)) { - zend_error(E_ERROR, "Method can't be used as l-value"); - } - */ zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); le = fetch_list_ptr->head; @@ -865,7 +860,7 @@ } else if (op1->op_type==IS_VAR) { zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; - while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END) { + while (opline->opcode == ZEND_END_SILENCE || opline->opcode == ZEND_EXT_FCALL_END || opline->opcode == ZEND_OP_DATA) { opline--; } if (opline->result.op_type == op1->op_type @@ -901,11 +896,18 @@ } } -#define ZEND_CLONE_FUNC_NAME "__clone" -#define ZEND_CONSTRUCTOR_FUNC_NAME "__construct" -#define ZEND_DESTRUCTOR_FUNC_NAME "__destruct" -void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference TSRMLS_DC) +int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier) +{ + if ((new_modifier->u.constant.value.lval & ZEND_ACC_PPP_MASK) + && ((current_access_type->u.constant.value.lval & ZEND_ACC_PPP_MASK) != (new_modifier->u.constant.value.lval & ZEND_ACC_PPP_MASK))) { + zend_error(E_COMPILE_ERROR, "Multiple access type modifiers are not allowed"); + } + return (current_access_type->u.constant.value.lval | new_modifier->u.constant.value.lval); +} + + +void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, zend_uint fn_flags TSRMLS_DC) { zend_op_array op_array; char *name = function_name->u.constant.value.str.val; @@ -920,12 +922,37 @@ op_array.function_name = name; op_array.arg_types = NULL; op_array.return_reference = return_reference; + op_array.fn_flags = fn_flags; op_array.scope = CG(active_class_entry); if (is_method) { - zend_hash_update(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)); - if ((CG(active_class_entry)->name_length == (uint) name_len) && (!memcmp(CG(active_class_entry)->name, name, name_len))) { + char *short_class_name = CG(active_class_entry)->name; + int short_class_name_length = CG(active_class_entry)->name_length; + zend_uint i; + + for (i=0; i < CG(active_class_entry)->name_length; i++) { + if (CG(active_class_entry)->name[i] == ':') { + short_class_name = &CG(active_class_entry)->name[i+1]; + short_class_name_length = strlen(short_class_name); + } + } + if (zend_hash_add(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)) == FAILURE) { + zend_op_array *child_op_array, *parent_op_array; + if (CG(active_class_entry)->parent + && (zend_hash_find(&CG(active_class_entry)->function_table, name, name_len+1, (void **) &child_op_array) == SUCCESS) + && (zend_hash_find(&CG(active_class_entry)->parent->function_table, name, name_len+1, (void **) &parent_op_array) == SUCCESS) + && (child_op_array == parent_op_array)) { + zend_hash_update(&CG(active_class_entry)->function_table, name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)); + } else { + zend_error(E_COMPILE_ERROR, "Cannot redeclare %s()", name); + } + } + if (fn_flags & ZEND_ACC_ABSTRACT) { + CG(active_class_entry)->ce_flags |= ZEND_ACC_ABSTRACT; + } + + if ((short_class_name_length == name_len) && (!memcmp(short_class_name, name, name_len))) { CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array); } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME)))) { CG(active_class_entry)->constructor = (zend_function *) CG(active_op_array); @@ -933,13 +960,20 @@ CG(active_class_entry)->destructor = (zend_function *) CG(active_op_array); } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)))) { CG(active_class_entry)->clone = (zend_function *) CG(active_op_array); + CG(in_clone_method) = 1; + } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)))) { + CG(active_class_entry)->__call = (zend_function *) CG(active_op_array); + } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_GET_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)))) { + CG(active_class_entry)->__get = (zend_function *) CG(active_op_array); + } else if ((function_name->u.constant.value.str.len == sizeof(ZEND_SET_FUNC_NAME)-1) && (!memcmp(function_name->u.constant.value.str.val, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)))) { + CG(active_class_entry)->__set = (zend_function *) CG(active_op_array); } } else { zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_DECLARE_FUNCTION_OR_CLASS; + opline->opcode = ZEND_DECLARE_FUNCTION; opline->op1.op_type = IS_CONST; - build_runtime_defined_function_key(&opline->op1.u.constant, &function_name->u.constant, opline TSRMLS_CC); + build_runtime_defined_function_key(&opline->op1.u.constant, function_name->u.constant.value.str.val, function_name->u.constant.value.str.len, opline TSRMLS_CC); opline->op2.op_type = IS_CONST; opline->op2.u.constant.type = IS_STRING; opline->op2.u.constant.value.str.val = estrndup(name, name_len); @@ -987,6 +1021,8 @@ zend_stack_del_top(&CG(foreach_copy_stack)); CG(throw_list) = function_token->throw_list; + + CG(in_clone_method) = 0; } @@ -1074,15 +1110,6 @@ last_op->opcode = ZEND_INIT_METHOD_CALL; - if (last_op->op2.op_type == IS_UNUSED && last_op->op2.u.EA.type == ZEND_FETCH_FROM_THIS) { - last_op->op2 = last_op->op1; - memset(&last_op->op1, 0, sizeof(znode)); - SET_UNUSED(last_op->op1); - last_op->extended_value = ZEND_FETCH_FROM_THIS; - } - - zend_lowercase_znode_if_const(&last_op->op2); - left_bracket->u.constant.value.lval = ZEND_INIT_FCALL_BY_NAME; zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(zend_function *)); @@ -1158,10 +1185,11 @@ if (!case_sensitive) { zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len); } - length = 1 + result->u.constant.value.str.len + class_name->u.constant.value.str.len; + + length = sizeof("::")-1 + result->u.constant.value.str.len + class_name->u.constant.value.str.len; result->u.constant.value.str.val = erealloc(result->u.constant.value.str.val, length+1); - memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], ":", sizeof(":")-1); - memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len+1], class_name->u.constant.value.str.val, class_name->u.constant.value.str.len+1); + memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len], "::", sizeof("::")-1); + memcpy(&result->u.constant.value.str.val[result->u.constant.value.str.len + sizeof("::")-1], class_name->u.constant.value.str.val, class_name->u.constant.value.str.len+1); STR_FREE(class_name->u.constant.value.str.val); result->u.constant.value.str.len = length; } @@ -1186,7 +1214,7 @@ if (is_method && function_name && function_name->u.constant.value.lval == ZEND_CLONE) { if (argument_list->u.constant.value.lval > 0) { - zend_error(E_ERROR, "Can't pass arguments to __clone()"); + zend_error(E_COMPILE_ERROR, "Can't pass arguments to __clone()"); } /* FIXME: throw_list */ zend_stack_del_top(&CG(function_call_stack)); @@ -1277,7 +1305,7 @@ } if (original_op == ZEND_SEND_VAR) { - switch(op) { + switch (op) { case ZEND_SEND_VAR_NO_REF: zend_do_end_variable_parse(BP_VAR_R, 0 TSRMLS_CC); break; @@ -1411,7 +1439,7 @@ opline->op2.u.opline_num = *catch_opline; break; default: - zend_error(E_ERROR, "Bad opcode in throw list"); + zend_error(E_COMPILE_ERROR, "Bad opcode in throw list"); break; } } @@ -1475,39 +1503,144 @@ } } - static void do_inherit_parent_constructor(zend_class_entry *ce) { - if (ce->parent - && !zend_hash_exists(&ce->function_table, ce->name, ce->name_length+1)) { - zend_function *function; + zend_function *function; + if (!ce->parent || ce->constructor) { + return; + } + + if (!zend_hash_exists(&ce->function_table, ce->name, ce->name_length+1)) { if (zend_hash_find(&ce->parent->function_table, ce->parent->name, ce->parent->name_length+1, (void **) &function)==SUCCESS) { /* inherit parent's constructor */ zend_hash_update(&ce->function_table, ce->name, ce->name_length+1, function, sizeof(zend_function), NULL); function_add_ref(function); } } + if (zend_hash_find(&ce->parent->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), (void **) &function)==SUCCESS) { + /* inherit parent's constructor */ + zend_hash_update(&ce->function_table, ZEND_CONSTRUCTOR_FUNC_NAME, sizeof(ZEND_CONSTRUCTOR_FUNC_NAME), function, sizeof(zend_function), NULL); + function_add_ref(function); + } + ce->constructor = ce->parent->constructor; + if (!ce->__get) { + ce->__get = ce->parent->__get; + } + if (!ce->__set) { + ce->__set = ce->parent->__set; + } + if (!ce->__call) { + ce->__call = ce->parent->__call; + } } + +char *zend_visibility_string(zend_uint fn_flags) +{ + if (fn_flags & ZEND_ACC_PRIVATE) { + return "private"; + } + if (fn_flags & ZEND_ACC_PROTECTED) { + return "protected"; + } + if (fn_flags & ZEND_ACC_PUBLIC) { + return "public"; + } + return ""; +} + + +static void do_inherit_method(zend_function *function) +{ + /* The class entry of the derived function intentionally remains the same + * as that of the parent class. That allows us to know in which context + * we're running, and handle private method calls properly. + */ + if (function->common.fn_flags & ZEND_ACC_ABSTRACT) { + function->op_array.scope->ce_flags |= ZEND_ACC_ABSTRACT; + } + function_add_ref(function); +} + + +static zend_bool do_inherit_method_check(HashTable *child_function_table, zend_function *parent, zend_hash_key *hash_key, void *pData) +{ + zend_uint child_flags; + zend_uint parent_flags = parent->common.fn_flags; + zend_function *child; + + if (zend_hash_quick_find(child_function_table, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child)==FAILURE) { + return 1; /* method doesn't exist in child, copy from parent */ + } + child_flags = child->common.fn_flags; + /* You cannot change from static to non static and vice versa. + */ + if ((child_flags & ZEND_ACC_STATIC) != (parent_flags & ZEND_ACC_STATIC)) { + if (child->common.fn_flags & ZEND_ACC_STATIC) { + zend_error(E_COMPILE_ERROR, "Cannot make non static method %s::%s() static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child)); + } else { + zend_error(E_COMPILE_ERROR, "Cannot make static method %s::%s() non static in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child)); + } + } + + /* Disallow making an inherited method abstract. + */ + if ((child_flags & ZEND_ACC_ABSTRACT) && !(parent_flags & ZEND_ACC_ABSTRACT)) { + zend_error(E_COMPILE_ERROR, "Cannot make non abstract method %s::%s() abstract in class %s", ZEND_FN_SCOPE_NAME(parent), child->common.function_name, ZEND_FN_SCOPE_NAME(child)); + } + + if (parent_flags & ZEND_ACC_CHANGED) { + child->common.fn_flags |= ZEND_ACC_CHANGED; + } else { + /* Prevent derived classes from restricting access that was available in parent classes + */ + if ((child_flags & ZEND_ACC_PPP_MASK) > (parent_flags & ZEND_ACC_PPP_MASK)) { + zend_error(E_COMPILE_ERROR, "Access level to %s::%s() must be %s (as in class %s)%s", ZEND_FN_SCOPE_NAME(child), child->common.function_name, zend_visibility_string(parent_flags), ZEND_FN_SCOPE_NAME(parent), (parent_flags&ZEND_ACC_PUBLIC) ? "" : " or weaker"); + } else if (((child_flags & ZEND_ACC_PPP_MASK) < (parent_flags & ZEND_ACC_PPP_MASK)) + && ((parent_flags & ZEND_ACC_PPP_MASK) & ZEND_ACC_PRIVATE)) { + child->common.fn_flags |= ZEND_ACC_CHANGED; + } + } + + return 0; +} + + +static zend_bool do_inherit_property_access_check(HashTable *target_ht, zend_property_info *parent_info, zend_hash_key *hash_key, zend_class_entry *ce) +{ + zend_property_info *child_info; + zend_class_entry *parent_ce = ce->parent; + + if (parent_info->flags & ZEND_ACC_PRIVATE) { + return 0; /* don't copy access information to child */ + } + + if (zend_hash_quick_find(&ce->properties_info, hash_key->arKey, hash_key->nKeyLength, hash_key->h, (void **) &child_info)==SUCCESS) { + if ((child_info->flags & ZEND_ACC_PPP_MASK) > (parent_info->flags & ZEND_ACC_PPP_MASK)) { + zend_error(E_COMPILE_ERROR, "Access level to %s::$%s must be %s (as in class %s)%s", ce->name, hash_key->arKey, zend_visibility_string(parent_info->flags), parent_ce->name, (parent_info->flags&ZEND_ACC_PUBLIC) ? "" : " or weaker"); + } else if (child_info->flags & ZEND_ACC_IMPLICIT_PUBLIC) { + return 1; /* Inherit from the parent */ + } + return 0; /* Don't copy from parent */ + } else { + return 1; /* Copy from parent */ + } +} + + void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce) { - zend_function tmp_zend_function; - zval *tmp; + ce->parent = parent_ce; + + /* Inherit properties */ + zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0); + zend_hash_merge_ex(&ce->properties_info, &parent_ce->properties_info, (copy_ctor_func_t) zend_duplicate_property_info, sizeof(zend_property_info), (merge_checker_func_t) do_inherit_property_access_check, ce); - /* Perform inheritance */ - zend_hash_merge(&ce->default_properties, &parent_ce->default_properties, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); /* STATIC_MEMBERS_FIXME */ - zend_hash_merge(ce->static_members, parent_ce->static_members, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); - zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); - zend_hash_merge(&ce->function_table, &parent_ce->function_table, (void (*)(void *)) function_add_ref, &tmp_zend_function, sizeof(zend_function), 0); - ce->parent = parent_ce; - if (!ce->handle_property_get) - ce->handle_property_get = parent_ce->handle_property_get; - if (!ce->handle_property_set) - ce->handle_property_set = parent_ce->handle_property_set; - if (!ce->handle_function_call) - ce->handle_function_call = parent_ce->handle_function_call; +/* zend_hash_merge(ce->static_members, parent_ce->static_members, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *), 0); */ + zend_hash_merge(&ce->constants_table, &parent_ce->constants_table, (void (*)(void *)) zval_add_ref, NULL, sizeof(zval *), 0); + zend_hash_merge_ex(&ce->function_table, &parent_ce->function_table, (copy_ctor_func_t) do_inherit_method, sizeof(zend_function), (merge_checker_func_t) do_inherit_method_check, NULL); do_inherit_parent_constructor(ce); } @@ -1517,35 +1650,16 @@ new_class_entry = emalloc(sizeof(zend_class_entry)); *ce = new_class_entry; + new_class_entry->type = ZEND_USER_CLASS; new_class_entry->name = estrndup(name, name_length); new_class_entry->name_length = name_length; - new_class_entry->refcount = 1; - new_class_entry->constants_updated = 0; - - zend_str_tolower(new_class_entry->name, new_class_entry->name_length); - - zend_hash_init(&new_class_entry->function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0); - zend_hash_init(&new_class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 0); - zend_hash_init(&new_class_entry->default_properties, 10, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_init(&new_class_entry->private_properties, 10, NULL, ZVAL_PTR_DTOR, 0); - ALLOC_HASHTABLE(new_class_entry->static_members); - zend_hash_init(new_class_entry->static_members, 10, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_init(&new_class_entry->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0); - - new_class_entry->constructor = NULL; - new_class_entry->destructor = NULL; - new_class_entry->clone = NULL; - - new_class_entry->create_object = NULL; - new_class_entry->handle_function_call = NULL; - new_class_entry->handle_property_set = NULL; - new_class_entry->handle_property_get = NULL; - new_class_entry->parent = NULL; + zend_initialize_class_data(new_class_entry, 1); + zend_str_tolower(new_class_entry->name, new_class_entry->name_length); if (zend_hash_update(class_table, new_class_entry->name, name_length+1, &new_class_entry, sizeof(zend_class_entry *), NULL) == FAILURE) { - zend_error(E_ERROR, "Can't create class. Fatal error, please report!"); + zend_error(E_COMPILE_ERROR, "Can't create class. Fatal error, please report!"); } } @@ -1584,148 +1698,117 @@ new_ce->refcount++; if (zend_hash_add(&ce->class_table, last, strlen(last)+1, &new_ce, sizeof(zend_class_entry *), NULL) == FAILURE) { new_ce->refcount--; - zend_error(E_ERROR, "Cannot redeclare class %s", last); + zend_error(E_COMPILE_ERROR, "Cannot redeclare class %s", last); return FAILURE; } return SUCCESS; } -ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_table, HashTable *class_table, int compile_time) +ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, HashTable *class_table, int compile_time) { - switch (opline->extended_value) { - case ZEND_DECLARE_FUNCTION: { - zend_function *function; - - zend_hash_find(function_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void *) &function); - if (zend_hash_add(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, function, sizeof(zend_function), NULL)==FAILURE) { - int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR; - zend_function *function; - - if (zend_hash_find(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void *) &function)==SUCCESS - && function->type==ZEND_USER_FUNCTION - && ((zend_op_array *) function)->last>0) { - zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)", - opline->op2.u.constant.value.str.val, - ((zend_op_array *) function)->filename, - ((zend_op_array *) function)->opcodes[0].lineno); - } else { - zend_error(error_level, "Cannot redeclare %s()", opline->op2.u.constant.value.str.val); - } - return FAILURE; - } else { - (*function->op_array.refcount)++; - function->op_array.static_variables = NULL; /* NULL out the unbound function */ - return SUCCESS; - } - } - break; - case ZEND_DECLARE_CLASS: { - zend_class_entry *ce, **pce; + zend_function *function; - if (zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce)==FAILURE) { - zend_error(E_ERROR, "Internal Zend error - Missing class information for %s", opline->op1.u.constant.value.str.val); - return FAILURE; - } else { - ce = *pce; - } - if (strchr(opline->op2.u.constant.value.str.val, ':')) { - return create_nested_class(class_table, opline->op2.u.constant.value.str.val, ce); - } - ce->refcount++; - if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) { - ce->refcount--; - if (!compile_time) { - zend_error(E_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); - } - return FAILURE; - } else { - return SUCCESS; - } - } - break; - case ZEND_DECLARE_INHERITED_CLASS: { - zend_class_entry **parent_pce, *ce, **pce; - int parent_name_length; - char *class_name, *parent_name; - int found_ce; + if (opline->opcode != ZEND_DECLARE_FUNCTION) { + zend_error(E_ERROR, "Internal compiler error. Please report!"); + } - - found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce); + zend_hash_find(function_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void *) &function); + if (zend_hash_add(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, function, sizeof(zend_function), NULL)==FAILURE) { + int error_level = compile_time ? E_COMPILE_ERROR : E_ERROR; + zend_function *function; - /* Restore base class / derived class names */ - class_name = strchr(opline->op2.u.constant.value.str.val, ':'); - if (!class_name) { - zend_error(E_CORE_ERROR, "Invalid runtime class entry"); - } - class_name++; + if (zend_hash_find(function_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, (void *) &function)==SUCCESS + && function->type==ZEND_USER_FUNCTION + && ((zend_op_array *) function)->last>0) { + zend_error(error_level, "Cannot redeclare %s() (previously declared in %s:%d)", + opline->op2.u.constant.value.str.val, + ((zend_op_array *) function)->filename, + ((zend_op_array *) function)->opcodes[0].lineno); + } else { + zend_error(error_level, "Cannot redeclare %s()", opline->op2.u.constant.value.str.val); + } + return FAILURE; + } else { + (*function->op_array.refcount)++; + function->op_array.static_variables = NULL; /* NULL out the unbound function */ + return SUCCESS; + } +} + - if (found_ce==FAILURE) { - zend_error(E_ERROR, "Cannot redeclare class %s", class_name); - return FAILURE; - } else { - ce = *pce; - } - ce->refcount++; +ZEND_API int do_bind_class(zend_op *opline, HashTable *function_table, HashTable *class_table) +{ + zend_class_entry *ce, **pce; - /* Obtain parent class */ - parent_name_length = class_name - opline->op2.u.constant.value.str.val - 1; - parent_name = estrndup(opline->op2.u.constant.value.str.val, parent_name_length); - if (zend_hash_find(class_table, parent_name, parent_name_length+1, (void **) &parent_pce)==FAILURE) { - if (!compile_time) { - zend_error(E_ERROR, "Class %s: Cannot inherit from undefined class %s", class_name, parent_name); - } - ce->refcount--; - efree(parent_name); - return FAILURE; - } - efree(parent_name); + if (zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce)==FAILURE) { + zend_error(E_ERROR, "Internal Zend error - Missing class information for %s", opline->op1.u.constant.value.str.val); + return FAILURE; + } else { + ce = *pce; + } + if (strchr(opline->op2.u.constant.value.str.val, ':')) { + return create_nested_class(class_table, opline->op2.u.constant.value.str.val, ce); + } + ce->refcount++; + if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, &ce, sizeof(zend_class_entry *), NULL)==FAILURE) { + ce->refcount--; + zend_error(E_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); + return FAILURE; + } else { + return SUCCESS; + } +} - zend_do_inheritance(ce, *parent_pce); +ZEND_API int do_bind_inherited_class(zend_op *opline, HashTable *function_table, HashTable *class_table, zend_class_entry *parent_ce) +{ + zend_class_entry *ce, **pce; + int found_ce; - /* Register the derived class */ - if (zend_hash_add(class_table, class_name, strlen(class_name)+1, pce, sizeof(zend_class_entry *), NULL)==FAILURE) { - if (!compile_time) { - zend_error(E_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); - } - ce->refcount--; - zend_hash_destroy(&ce->function_table); - zend_hash_destroy(&ce->default_properties); - zend_hash_destroy(&ce->private_properties); - zend_hash_destroy(ce->static_members); - zend_hash_destroy(&ce->constants_table); - return FAILURE; - } - return SUCCESS; - } - break; + found_ce = zend_hash_find(class_table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, (void **) &pce); + + if (found_ce == FAILURE) { + zend_error(E_ERROR, "Cannot redeclare class %s", (*pce)->name); + return FAILURE; + } else { + ce = *pce; } - return FAILURE; + + zend_do_inheritance(ce, parent_ce); + + if (strchr(opline->op2.u.constant.value.str.val, ':')) { + return create_nested_class(class_table, opline->op2.u.constant.value.str.val, ce); + } + + ce->refcount++; + + /* Register the derived class */ + if (zend_hash_add(class_table, opline->op2.u.constant.value.str.val, opline->op2.u.constant.value.str.len+1, pce, sizeof(zend_class_entry *), NULL)==FAILURE) { + zend_error(E_ERROR, "Cannot redeclare class %s", opline->op2.u.constant.value.str.val); + ce->refcount--; + zend_hash_destroy(&ce->function_table); + zend_hash_destroy(&ce->default_properties); + zend_hash_destroy(&ce->properties_info); + zend_hash_destroy(ce->static_members); + zend_hash_destroy(&ce->constants_table); + return FAILURE; + } + return SUCCESS; } void zend_do_early_binding(TSRMLS_D) { zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; - HashTable *table; - if (strchr(opline->op2.u.constant.value.str.val, ':')) { - return; + while (opline->opcode == ZEND_TICKS && opline > CG(active_op_array)->opcodes) { + opline--; } - if (do_bind_function_or_class(opline, CG(function_table), CG(class_table), 1)==FAILURE) { + + if (do_bind_function(opline, CG(function_table), CG(class_table), 1) == FAILURE) { return; } - switch (opline->extended_value) { - case ZEND_DECLARE_FUNCTION: - table = CG(function_table); - break; - case ZEND_DECLARE_CLASS: - table = CG(class_table); - break; - default: - zend_error(E_COMPILE_ERROR, "Invalid binding type"); - return; - } - zend_hash_del(table, opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len); + + zend_hash_del(CG(function_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len); zval_dtor(&opline->op1.u.constant); zval_dtor(&opline->op2.u.constant); opline->opcode = ZEND_NOP; @@ -2011,117 +2094,54 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znode *parent_class_name TSRMLS_DC) { zend_op *opline; - int runtime_inheritance = 0; + int doing_inheritance = 0; zend_class_entry *new_class_entry = emalloc(sizeof(zend_class_entry)); class_token->u.previously_active_class_entry = CG(active_class_entry); - new_class_entry->type = ZEND_USER_CLASS; - new_class_entry->name = class_name->u.constant.value.str.val; - new_class_entry->name_length = class_name->u.constant.value.str.len; - new_class_entry->refcount = 1; - new_class_entry->constants_updated = 0; - - zend_str_tolower(new_class_entry->name, new_class_entry->name_length); - - zend_hash_init(&new_class_entry->function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0); - zend_hash_init(&new_class_entry->class_table, 10, NULL, ZEND_CLASS_DTOR, 0); - zend_hash_init(&new_class_entry->default_properties, 10, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_init(&new_class_entry->private_properties, 10, NULL, ZVAL_PTR_DTOR, 0); - ALLOC_HASHTABLE(new_class_entry->static_members); - zend_hash_init(new_class_entry->static_members, 10, NULL, ZVAL_PTR_DTOR, 0); - zend_hash_init(&new_class_entry->constants_table, 10, NULL, ZVAL_PTR_DTOR, 0); - - new_class_entry->constructor = NULL; - new_class_entry->destructor = NULL; - new_class_entry->clone = NULL; - - new_class_entry->create_object = NULL; - new_class_entry->handle_function_call = NULL; - new_class_entry->handle_property_set = NULL; - new_class_entry->handle_property_get = NULL; - - /* code for inheritance from parent class */ - if (parent_class_name) { - zend_class_entry *parent_class, **parent_class_p; - zend_function tmp_zend_function; - zval *tmp; - - zend_str_tolower(parent_class_name->u.constant.value.str.val, parent_class_name->u.constant.value.str.len); - CG(active_ce_parent_class_name).value.str.val = estrndup(parent_class_name->u.constant.value.str.val, parent_class_name->u.constant.value.str.len); - CG(active_ce_parent_class_name).value.str.len = parent_class_name->u.constant.value.str.len; - - if (zend_hash_find(CG(active_class_entry)?&CG(active_class_entry)->class_table:CG(class_table), parent_class_name->u.constant.value.str.val, parent_class_name->u.constant.value.str.len+1, (void **) &parent_class_p)==SUCCESS) { - parent_class = *parent_class_p; - /* copy functions */ - zend_hash_copy(&new_class_entry->function_table, &parent_class->function_table, (copy_ctor_func_t) function_add_ref, &tmp_zend_function, sizeof(zend_function)); - - /* copy default properties */ - zend_hash_copy(&new_class_entry->default_properties, &parent_class->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - - /* copy static members */ - zend_hash_copy(new_class_entry->static_members, parent_class->static_members, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - - /* copy constants */ - zend_hash_copy(&new_class_entry->constants_table, &parent_class->constants_table, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); - - new_class_entry->constructor = parent_class->constructor; - new_class_entry->destructor = parent_class->destructor; - - /* FIXME: What do we do with clone? */ - - /* copy overloaded handlers */ - new_class_entry->handle_function_call = parent_class->handle_function_call; - new_class_entry->handle_property_get = parent_class->handle_property_get; - new_class_entry->handle_property_set = parent_class->handle_property_set; - - new_class_entry->parent = parent_class; + if (!(strcmp(class_name->u.constant.value.str.val, "main") && strcmp(class_name->u.constant.value.str.val, "self") && + strcmp(class_name->u.constant.value.str.val, "parent"))) { + zend_error(E_COMPILE_ERROR, "Cannot use '%s' as class name as it is reserved", class_name->u.constant.value.str.val); + } - zval_dtor(&parent_class_name->u.constant); - } else { - runtime_inheritance = 1; - new_class_entry->parent = NULL; - } + if (CG(active_class_entry)) { + new_class_entry->name_length = sizeof("::")-1 + class_name->u.constant.value.str.len + CG(active_class_entry)->name_length; + new_class_entry->name = emalloc(new_class_entry->name_length+1); + strcpy(new_class_entry->name, CG(active_class_entry)->name); + strcat(new_class_entry->name, "::"); + strcat(new_class_entry->name, class_name->u.constant.value.str.val); + STR_FREE(class_name->u.constant.value.str.val); } else { - new_class_entry->parent = NULL; + new_class_entry->name = class_name->u.constant.value.str.val; + new_class_entry->name_length = class_name->u.constant.value.str.len; } - if (CG(active_class_entry)) { - if (runtime_inheritance) { - zend_error(E_ERROR, "Only first level classes can inherit from undefined classes"); - } - zend_hash_update(&CG(active_class_entry)->class_table, new_class_entry->name, new_class_entry->name_length+1, &new_class_entry, sizeof(zend_class_entry *), NULL); - CG(active_class_entry) = new_class_entry; - return; + new_class_entry->type = ZEND_USER_CLASS; + new_class_entry->parent = NULL; + zend_initialize_class_data(new_class_entry, 1); + + if (parent_class_name->op_type != IS_UNUSED) { + doing_inheritance = 1; } + zend_str_tolower(new_class_entry->name, new_class_entry->name_length); opline = get_next_op(CG(active_op_array) TSRMLS_CC); - opline->opcode = ZEND_DECLARE_FUNCTION_OR_CLASS; opline->op1.op_type = IS_CONST; - build_runtime_defined_function_key(&opline->op1.u.constant, &class_name->u.constant, opline TSRMLS_CC); + build_runtime_defined_function_key(&opline->op1.u.constant, new_class_entry->name, new_class_entry->name_length, opline TSRMLS_CC); + opline->op2.op_type = IS_CONST; opline->op2.u.constant.type = IS_STRING; opline->op2.u.constant.refcount = 1; - if (runtime_inheritance) { - char *full_class_name; - - opline->op2.u.constant.value.str.len = parent_class_name->u.constant.value.str.len+1+new_class_entry->name_length; - full_class_name = opline->op2.u.constant.value.str.val = (char *) emalloc(opline->op2.u.constant.value.str.len+1); - memcpy(full_class_name, parent_class_name->u.constant.value.str.val, parent_class_name->u.constant.value.str.len); - full_class_name += parent_class_name->u.constant.value.str.len; - full_class_name[0] = ':'; - full_class_name++; - memcpy(full_class_name, new_class_entry->name, new_class_entry->name_length); - zval_dtor(&parent_class_name->u.constant); - full_class_name += new_class_entry->name_length; - full_class_name[0] = 0; - opline->extended_value = ZEND_DECLARE_INHERITED_CLASS; - } else { - opline->op2.u.constant.value.str.val = estrndup(new_class_entry->name, new_class_entry->name_length); - opline->op2.u.constant.value.str.len = new_class_entry->name_length; - opline->extended_value = ZEND_DECLARE_CLASS; + if (doing_inheritance) { + opline->extended_value = parent_class_name->u.var; + opline->opcode = ZEND_DECLARE_INHERITED_CLASS; + } else { + opline->opcode = ZEND_DECLARE_CLASS; } - + + opline->op2.u.constant.value.str.val = estrndup(new_class_entry->name, new_class_entry->name_length); + opline->op2.u.constant.value.str.len = new_class_entry->name_length; + zend_hash_update(CG(class_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &new_class_entry, sizeof(zend_class_entry *), NULL); CG(active_class_entry) = new_class_entry; } @@ -2137,25 +2157,34 @@ } } -void mangle_private_property_name(char **dest, int *dest_length, char *src1, int src1_length, char *src2, int src2_length) +void mangle_property_name(char **dest, int *dest_length, char *src1, int src1_length, char *src2, int src2_length) { - char *priv_name; - int priv_name_length; - - priv_name_length = 1 + src1_length + 1 + src2_length; - priv_name = emalloc(priv_name_length+1); - priv_name[0] = '\0'; - memcpy(priv_name + 1, src1, src1_length+1); - memcpy(priv_name + 1 + src1_length + 1, src2, src2_length+1); + char *prop_name; + int prop_name_length; + + prop_name_length = 1 + src1_length + 1 + src2_length; + prop_name = emalloc(prop_name_length+1); + prop_name[0] = '\0'; + memcpy(prop_name + 1, src1, src1_length+1); + memcpy(prop_name + 1 + src1_length + 1, src2, src2_length+1); - *dest = priv_name; - *dest_length = priv_name_length; + *dest = prop_name; + *dest_length = prop_name_length; } -void zend_do_declare_property(znode *var_name, znode *value, int declaration_type TSRMLS_DC) + +void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_type TSRMLS_DC) { zval *property; - + zend_property_info property_info; + zend_property_info *existing_property_info; + HashTable *target_symbol_table; + + if (zend_hash_find(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, (void **) &existing_property_info)==SUCCESS) { + if (!(existing_property_info->flags & ZEND_ACC_IMPLICIT_PUBLIC)) { + zend_error(E_COMPILE_ERROR, "Cannot redeclare %s::$%s", CG(active_class_entry)->name, var_name->u.constant.value.str.val); + } + } ALLOC_ZVAL(property); if (value) { @@ -2165,67 +2194,113 @@ property->type = IS_NULL; } - switch (declaration_type) { - case T_PRIVATE: - { + if (access_type & ZEND_ACC_STATIC) { + target_symbol_table = CG(active_class_entry)->static_members; + } else { + target_symbol_table = &CG(active_class_entry)->default_properties; + } + + switch (access_type & ZEND_ACC_PPP_MASK) { + case ZEND_ACC_PRIVATE: { char *priv_name; int priv_name_length; - mangle_private_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len); - zend_hash_update(&CG(active_class_entry)->default_properties, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL); - efree(priv_name); - - property->refcount++; - zend_hash_update(&CG(active_class_entry)->private_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL); - break; + mangle_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len); + zend_hash_update(target_symbol_table, priv_name, priv_name_length+1, &property, sizeof(zval *), NULL); + property_info.name = priv_name; + property_info.name_length = priv_name_length; } - case T_VAR: - zend_hash_update(&CG(active_class_entry)->default_properties, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL); break; - case T_STATIC: - zend_hash_update(CG(active_class_entry)->static_members, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL); + case ZEND_ACC_PROTECTED: { + char *prot_name; + int prot_name_length; + + mangle_property_name(&prot_name, &prot_name_length, "*", 1, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len); + zend_hash_update(target_symbol_table, prot_name, prot_name_length+1, &property, sizeof(zval *), NULL); + property_info.name = prot_name; + property_info.name_length = prot_name_length; + } break; - case T_CONST: - zend_hash_update(&CG(active_class_entry)->constants_table, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL); + case ZEND_ACC_PUBLIC: + zend_hash_update(target_symbol_table, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL); + property_info.name = var_name->u.constant.value.str.val; + property_info.name_length = var_name->u.constant.value.str.len; break; } + property_info.flags = access_type; + property_info.h = zend_get_hash_value(property_info.name, property_info.name_length+1); + + zend_hash_update(&CG(active_class_entry)->properties_info, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property_info, sizeof(zend_property_info), NULL); +} + + +void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC) +{ + zval *property; + + ALLOC_ZVAL(property); + + if (value) { + *property = value->u.constant; + } else { + INIT_PZVAL(property); + property->type = IS_NULL; + } + + zend_hash_update(&CG(active_class_entry)->constants_table, var_name->u.constant.value.str.val, var_name->u.constant.value.str.len+1, &property, sizeof(zval *), NULL); + FREE_PNODE(var_name); } + void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS_DC) { zend_op opline; zend_llist *fetch_list_ptr; - + zend_op *opline_ptr=NULL; + zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); - + if (fetch_list_ptr->count == 1) { zend_llist_element *le; - zend_op *opline_ptr; le = fetch_list_ptr->head; opline_ptr = (zend_op *) le->data; + if ((opline_ptr->op1.op_type == IS_CONST) && (opline_ptr->op1.u.constant.type == IS_STRING) && - (opline_ptr->op1.u.constant.value.str.len == (sizeof("this")-1)) && - !memcmp(opline_ptr->op1.u.constant.value.str.val, "this", sizeof("this"))) { + (opline_ptr->op1.u.constant.value.str.len == (sizeof("this")-1)) && + !memcmp(opline_ptr->op1.u.constant.value.str.val, "this", sizeof("this"))) { efree(opline_ptr->op1.u.constant.value.str.val); - opline_ptr->op1 = *property; - SET_UNUSED(opline_ptr->op2); - opline_ptr->op2.u.EA.type = ZEND_FETCH_FROM_THIS; - - if ((opline_ptr->op1.op_type == IS_CONST) && zend_hash_exists(&CG(active_class_entry)->private_properties, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len+1)) { - char *priv_name; - int priv_name_length; - - mangle_private_property_name(&priv_name, &priv_name_length, CG(active_class_entry)->name, CG(active_class_entry)->name_length, opline_ptr->op1.u.constant.value.str.val, opline_ptr->op1.u.constant.value.str.len); - - STR_FREE(opline_ptr->op1.u.constant.value.str.val); - opline_ptr->op1.u.constant.value.str.val = priv_name; - opline_ptr->op1.u.constant.value.str.len = priv_name_length; + SET_UNUSED(opline_ptr->op1); /* this means $this for objects */ + opline_ptr->op2 = *property; + /* if it was usual fetch, we change it to object fetch */ + switch (opline_ptr->opcode) { + case ZEND_FETCH_W: + opline_ptr->opcode = ZEND_FETCH_OBJ_W; + break; + case ZEND_FETCH_R: + opline_ptr->opcode = ZEND_FETCH_OBJ_R; + break; + case ZEND_FETCH_RW: + opline_ptr->opcode = ZEND_FETCH_OBJ_RW; + break; + case ZEND_FETCH_IS: + opline_ptr->opcode = ZEND_FETCH_OBJ_IS; + break; + case ZEND_FETCH_UNSET: + opline_ptr->opcode = ZEND_FETCH_OBJ_UNSET; + break; + case ZEND_FETCH_FUNC_ARG: + opline_ptr->opcode = ZEND_FETCH_OBJ_FUNC_ARG; + break; } - *result = opline_ptr->result; + if (CG(active_class_entry) + && !zend_hash_exists(&CG(active_class_entry)->properties_info, property->u.constant.value.str.val, property->u.constant.value.str.len+1)) { + property->u.constant.value.str.val = estrndup(property->u.constant.value.str.val, property->u.constant.value.str.len); + zend_do_declare_property(property, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_IMPLICIT_PUBLIC TSRMLS_CC); + } return; } } @@ -2236,7 +2311,7 @@ opline.result.u.EA.type = 0; opline.result.u.var = get_temporary_variable(CG(active_op_array)); opline.op1 = *object; - opline. op2 = *property; + opline.op2 = *property; *result = opline.result; zend_llist_add_element(fetch_list_ptr, &opline); @@ -2483,7 +2558,7 @@ opline = get_next_op(CG(active_op_array) TSRMLS_CC); if (dimension == tmp_dimension_llist->head) { /* first */ last_container = *expr; - switch(expr->op_type) { + switch (expr->op_type) { case IS_VAR: opline->opcode = ZEND_FETCH_DIM_R; break; @@ -2533,27 +2608,54 @@ } } - -void zend_do_fetch_global_or_static_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC) +void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC) { - zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + zval *tmp; + zend_op *opline; znode lval; znode result; - if (fetch_type==ZEND_FETCH_STATIC && static_assignment) { - zval *tmp; - - ALLOC_ZVAL(tmp); - convert_to_string(&varname->u.constant); + ALLOC_ZVAL(tmp); + convert_to_string(&varname->u.constant); + if (static_assignment) { *tmp = static_assignment->u.constant; - if (!CG(active_op_array)->static_variables) { - ALLOC_HASHTABLE(CG(active_op_array)->static_variables); - zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0); - } - zend_hash_update(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1, &tmp, sizeof(zval *), NULL); + } else { + INIT_ZVAL(*tmp); + } + if (!CG(active_op_array)->static_variables) { + ALLOC_HASHTABLE(CG(active_op_array)->static_variables); + zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, ZVAL_PTR_DTOR, 0); + } + zend_hash_update(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1, &tmp, sizeof(zval *), NULL); + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + opline->opcode = ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */ + opline->result.op_type = IS_VAR; + opline->result.u.EA.type = 0; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *varname; + SET_UNUSED(opline->op2); + opline->op2.u.EA.type = fetch_type; + result = opline->result; + + if (varname->op_type == IS_CONST) { + zval_copy_ctor(&varname->u.constant); } + fetch_simple_variable(&lval, varname, 0 TSRMLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */ + + zend_do_assign_ref(NULL, &lval, &result TSRMLS_CC); + CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED; +/* zval_dtor(&varname->u.constant); */ +} + +void zend_do_fetch_global_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC) +{ + zend_op *opline; + znode lval; + znode result; + opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline->opcode = ZEND_FETCH_W; /* the default mode must be Write, since fetch_simple_variable() is used to define function arguments */ opline->result.op_type = IS_VAR; opline->result.u.EA.type = 0; @@ -2622,7 +2724,7 @@ } -void zend_do_unset(znode *variable, int type TSRMLS_DC) +void zend_do_unset(znode *variable TSRMLS_DC) { zend_op *last_op; @@ -2640,7 +2742,6 @@ break; } - last_op->extended_value = type; } @@ -2670,6 +2771,21 @@ } +void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type TSRMLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC); + + opline->opcode = ZEND_INSTANCEOF; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *expr; + + opline->op2 = *class_znode; + + *result = opline->result; +} + + void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC) { zend_op *opline; @@ -2803,12 +2919,15 @@ } -void zend_do_declare_end(TSRMLS_D) +void zend_do_declare_end(znode *declare_token TSRMLS_DC) { zend_declarables *declarables; zend_stack_top(&CG(declare_stack), (void **) &declarables); - CG(declarables) = *declarables; + /* We should restore if there was more than (current - start) - (ticks?1:0) opcodes */ + if ((get_next_op_number(CG(active_op_array)) - declare_token->u.opline_num) - ((CG(declarables).ticks.value.lval)?1:0)) { + CG(declarables) = *declarables; + } } @@ -3001,7 +3120,7 @@ zendlval->u.constant.type = IS_LONG; retval = lex_scan(&zendlval->u.constant TSRMLS_CC); - switch(retval) { + switch (retval) { case T_COMMENT: case T_OPEN_TAG: case T_WHITESPACE: @@ -3026,3 +3145,56 @@ zendlval->op_type = IS_CONST; return retval; } + + +void zend_duplicate_property_info(zend_property_info *property_info) +{ + property_info->name = estrndup(property_info->name, property_info->name_length); +} + + +void zend_destroy_property_info(zend_property_info *property_info) +{ + efree(property_info->name); +} + + +void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers) +{ + zend_bool persistent_hashes = (ce->type == ZEND_INTERNAL_CLASS) ? 1 : 0; + + ce->refcount = 1; + ce->constants_updated = 0; + ce->ce_flags = 0; + + zend_hash_init_ex(&ce->default_properties, 0, NULL, ZVAL_PTR_DTOR, persistent_hashes, 0); + zend_hash_init_ex(&ce->properties_info, 0, NULL, (dtor_func_t) zend_destroy_property_info, persistent_hashes, 0); + + if (persistent_hashes) { + ce->static_members = (HashTable *) malloc(sizeof(HashTable)); + } else { + ALLOC_HASHTABLE(ce->static_members); + } + zend_hash_init_ex(ce->static_members, 0, NULL, ZVAL_PTR_DTOR, persistent_hashes, 0); + zend_hash_init_ex(&ce->constants_table, 0, NULL, ZVAL_PTR_DTOR, persistent_hashes, 0); + zend_hash_init_ex(&ce->function_table, 0, NULL, ZEND_FUNCTION_DTOR, persistent_hashes, 0); + zend_hash_init_ex(&ce->class_table, 10, NULL, ZEND_CLASS_DTOR, persistent_hashes, 0); + + if (nullify_handlers) { + ce->constructor = NULL; + ce->destructor = NULL; + ce->clone = NULL; + ce->__get = NULL; + ce->__set = NULL; + ce->__call = NULL; + ce->create_object = NULL; + } +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.4 +99 -36 ZendEngine2/zend_compile.h Index: zend_compile.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_compile.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- zend_compile.h 9 May 2002 04:31:04 -0000 1.3 +++ zend_compile.h 11 Feb 2003 02:40:18 -0000 1.4 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_compile.h,v 1.209 2003/02/10 16:11:24 zeev Exp $ */ #ifndef ZEND_COMPILE_H #define ZEND_COMPILE_H @@ -32,7 +33,7 @@ #define DEBUG_ZEND 0 #define FREE_PNODE(znode) zval_dtor(&znode->u.constant); -#define FREE_OP(Ts, op, should_free) if (should_free) zval_dtor(&Ts[(op)->u.var].tmp_var); +#define FREE_OP(Ts, op, should_free) if (should_free) zval_dtor(should_free); #define SET_UNUSED(op) (op).op_type = IS_UNUSED @@ -41,6 +42,7 @@ #define HANDLE_INTERACTIVE() if (CG(interactive)) { execute_new_code(TSRMLS_C); } typedef struct _zend_op_array zend_op_array; +typedef struct _zend_op zend_op; typedef struct _znode { int op_type; @@ -52,6 +54,7 @@ zend_uint opline_num; /* Needs to be signed */ zend_op_array *op_array; zend_class_entry *previously_active_class_entry; /* Used at compile-time */ + zend_op *jmp_addr; struct { zend_uint var; /* dummy */ zend_uint type; @@ -59,15 +62,24 @@ } u; } znode; +typedef struct _zend_execute_data zend_execute_data; -typedef struct _zend_op { - zend_uchar opcode; +#define ZEND_OPCODE_HANDLER_ARGS zend_execute_data *execute_data, zend_op_array *op_array TSRMLS_DC +#define ZEND_OPCODE_HANDLER_ARGS_PASSTHRU execute_data, op_array TSRMLS_CC + +typedef int (*opcode_handler_t) (ZEND_OPCODE_HANDLER_ARGS); + +extern opcode_handler_t zend_opcode_handlers[512]; + +struct _zend_op { + opcode_handler_t handler; znode result; znode op1; znode op2; ulong extended_value; uint lineno; -} zend_op; + zend_uchar opcode; +}; typedef struct _zend_brk_cont_element { @@ -77,12 +89,36 @@ } zend_brk_cont_element; +#define ZEND_ACC_STATIC 0x01 +#define ZEND_ACC_ABSTRACT 0x02 + +/* The order of those must be kept - public < protected < private */ +#define ZEND_ACC_PUBLIC 0x10 +#define ZEND_ACC_PROTECTED 0x20 +#define ZEND_ACC_PRIVATE 0x40 +#define ZEND_ACC_PPP_MASK (ZEND_ACC_PUBLIC | ZEND_ACC_PROTECTED | ZEND_ACC_PRIVATE) + +#define ZEND_ACC_CHANGED 0x80 +#define ZEND_ACC_IMPLICIT_PUBLIC 0x100 + +char *zend_visibility_string(zend_uint fn_flags); + + +typedef struct _zend_property_info { + zend_uint flags; + char *name; + int name_length; + ulong h; +} zend_property_info; + + struct _zend_op_array { zend_uchar type; /* MUST be the first element of this struct! */ zend_uchar *arg_types; /* MUST be the second element of this struct! */ char *function_name; /* MUST be the third element of this struct! */ zend_class_entry *scope; /* MUST be the fourth element of this struct! */ + zend_uint fn_flags; /* MUST be the fifth element of this struct! */ zend_uint *refcount; @@ -117,21 +153,12 @@ zend_uchar *arg_types; /* MUST be the second element of this struct! */ char *function_name; /* MUST be the third element of this struct! */ zend_class_entry *scope; /* MUST be the fourth element of this struct! */ + zend_uint fn_flags; /* MUST be the fifth element of this struct! */ void (*handler)(INTERNAL_FUNCTION_PARAMETERS); } zend_internal_function; - -typedef struct _zend_overloaded_function { - zend_uchar type; /* MUST be the first element of this struct! */ - - zend_uchar *arg_types; /* MUST be the second element of this struct! */ - char *function_name; /* MUST be the third element of this struct! */ - zend_class_entry *scope; /* MUST be the fourth element of this struct! */ - - zend_uint var; -} zend_overloaded_function; - +#define ZEND_FN_SCOPE_NAME(function) ((function) && (function)->common.scope ? (function)->common.scope->name : "") typedef union _zend_function { zend_uchar type; /* MUST be the first element of this struct! */ @@ -141,11 +168,11 @@ zend_uchar *arg_types; char *function_name; zend_class_entry *scope; + zend_uint fn_flags; } common; zend_op_array op_array; zend_internal_function internal_function; - zend_overloaded_function overloaded_function; } zend_function; @@ -183,17 +210,18 @@ union _temp_variable; -typedef struct _zend_execute_data { +struct _zend_execute_data { struct _zend_op *opline; zend_function_state function_state; zend_function *fbc; /* Function Being Called */ zend_function *fbc_constructor; + zend_op_array *op_array; zval *object; union _temp_variable *Ts; zend_bool original_in_execution; zend_class_entry *calling_scope; struct _zend_execute_data *prev_execute_data; -} zend_execute_data; +}; #define EX(element) execute_data.element @@ -203,7 +231,6 @@ #define IS_VAR (1<<2) #define IS_UNUSED (1<<3) /* Unused variable */ - #define EXT_TYPE_UNUSED (1<<0) #include "zend_globals.h" @@ -246,12 +273,13 @@ void fetch_simple_variable(znode *result, znode *varname, int bp TSRMLS_DC); void fetch_simple_variable_ex(znode *result, znode *varname, int bp, zend_uchar op TSRMLS_DC); void zend_do_indirect_references(znode *result, znode *num_references, znode *variable TSRMLS_DC); -void zend_do_fetch_global_or_static_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC); +void zend_do_fetch_static_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC); +void zend_do_fetch_global_variable(znode *varname, znode *static_assignment, int fetch_type TSRMLS_DC); void fetch_array_begin(znode *result, znode *varname, znode *first_dim TSRMLS_DC); void fetch_array_dim(znode *result, znode *parent, znode *dim TSRMLS_DC); void fetch_string_offset(znode *result, znode *parent, znode *offset TSRMLS_DC); -void zend_do_fetch_static_member(znode *class TSRMLS_DC); +void zend_do_fetch_static_member(znode *class_znode TSRMLS_DC); void zend_do_print(znode *result, znode *arg TSRMLS_DC); void zend_do_echo(znode *arg TSRMLS_DC); typedef int (*unary_op_type)(zval *, zval *); @@ -287,7 +315,8 @@ void zend_do_add_string(znode *result, znode *op1, znode *op2 TSRMLS_DC); void zend_do_add_variable(znode *result, znode *op1, znode *op2 TSRMLS_DC); -void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference TSRMLS_DC); +int zend_do_verify_access_types(znode *current_access_type, znode *new_modifier); +void zend_do_begin_function_declaration(znode *function_token, znode *function_name, int is_method, int return_reference, zend_uint fn_flags TSRMLS_DC); void zend_do_end_function_declaration(znode *function_token TSRMLS_DC); void zend_do_receive_arg(zend_uchar op, znode *var, znode *offset, znode *initialization, zend_uchar pass_type TSRMLS_DC); int zend_do_begin_function_call(znode *function_name TSRMLS_DC); @@ -304,7 +333,10 @@ void zend_do_end_catch(znode *try_token TSRMLS_DC); void zend_do_throw(znode *expr TSRMLS_DC); -ZEND_API int do_bind_function_or_class(zend_op *opline, HashTable *function_table, HashTable *class_table, int compile_time); +ZEND_API int do_bind_function(zend_op *opline, HashTable *function_table, HashTable *class_table, int compile_time); +ZEND_API int do_bind_class(zend_op *opline, HashTable *function_table, HashTable *class_table); +ZEND_API int do_bind_inherited_class(zend_op *opline, HashTable *function_table, HashTable *class_table, zend_class_entry *parent_ce); + void zend_do_inheritance(zend_class_entry *ce, zend_class_entry *parent_ce); void zend_do_early_binding(TSRMLS_D); @@ -313,7 +345,7 @@ void zend_do_boolean_or_begin(znode *expr1, znode *op_token TSRMLS_DC); void zend_do_boolean_or_end(znode *result, znode *expr1, znode *expr2, znode *op_token TSRMLS_DC); -void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC); +void zend_do_boolean_and_begin(znode *expr1, znode *op_token TSRMLS_DC); void zend_do_boolean_and_end(znode *result, znode *expr1, znode *expr2, znode *op_token TSRMLS_DC); void zend_do_brk_cont(zend_uchar op, znode *expr TSRMLS_DC); @@ -326,7 +358,8 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znode *parent_class_name TSRMLS_DC); void zend_do_end_class_declaration(znode *class_token TSRMLS_DC); -void zend_do_declare_property(znode *var_name, znode *value, int declaration_type TSRMLS_DC); +void zend_do_declare_property(znode *var_name, znode *value, zend_uint access_type TSRMLS_DC); +void zend_do_declare_class_constant(znode *var_name, znode *value TSRMLS_DC); void zend_do_fetch_property(znode *result, znode *object, znode *property TSRMLS_DC); @@ -354,16 +387,18 @@ void zend_do_cast(znode *result, znode *expr, int type TSRMLS_DC); void zend_do_include_or_eval(int type, znode *result, znode *op1 TSRMLS_DC); -void zend_do_unset(znode *variable, int type TSRMLS_DC); +void zend_do_unset(znode *variable TSRMLS_DC); void zend_do_isset_or_isempty(int type, znode *result, znode *variable TSRMLS_DC); +void zend_do_instanceof(znode *result, znode *expr, znode *class_znode, int type TSRMLS_DC); + void zend_do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token, int variable TSRMLS_DC); void zend_do_foreach_cont(znode *value, znode *key, znode *as_token TSRMLS_DC); void zend_do_foreach_end(znode *foreach_token, znode *open_brackets_token TSRMLS_DC); void zend_do_declare_begin(TSRMLS_D); void zend_do_declare_stmt(znode *var, znode *val TSRMLS_DC); -void zend_do_declare_end(TSRMLS_D); +void zend_do_declare_end(znode *declare_token TSRMLS_DC); void zend_do_end_heredoc(TSRMLS_D); @@ -386,6 +421,8 @@ void zend_do_import(int type, znode *what TSRMLS_DC); void zend_do_end_import(znode *import_from TSRMLS_DC); +void zend_do_abstract_method(TSRMLS_D); + ZEND_API void function_add_ref(zend_function *function); #define INITIAL_OP_ARRAY_SIZE 64 @@ -401,11 +438,17 @@ ZEND_API void destroy_op_array(zend_op_array *op_array); ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC); ZEND_API void zend_file_handle_dtor(zend_file_handle *fh); +ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC); +ZEND_API int zend_cleanup_function_data(zend_function *function TSRMLS_DC); ZEND_API void destroy_zend_function(zend_function *function); ZEND_API void destroy_zend_class(zend_class_entry **pce); void zend_class_add_ref(zend_class_entry **ce); + +void zend_duplicate_property_info(zend_property_info *property_info); +void zend_destroy_property_info(zend_property_info *property_info); + #define ZEND_FUNCTION_DTOR (void (*)(void *)) destroy_zend_function #define ZEND_CLASS_DTOR (void (*)(void *)) destroy_zend_class @@ -418,6 +461,8 @@ zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array); ZEND_API zend_bool zend_is_compiling(TSRMLS_D); ZEND_API char *zend_make_compiled_string_description(char *name TSRMLS_DC); +void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers); + int zend_register_auto_global(char *name, uint name_len TSRMLS_DC); @@ -546,7 +591,7 @@ #define ZEND_FETCH_DIM_TMP_VAR 98 #define ZEND_FETCH_CONSTANT 99 -#define ZEND_DECLARE_FUNCTION_OR_CLASS 100 +/* Hole - 100 */ #define ZEND_EXT_STMT 101 #define ZEND_EXT_FCALL_BEGIN 102 @@ -593,7 +638,16 @@ #define ZEND_POST_DEC_OBJ 135 #define ZEND_ASSIGN_OBJ 136 -#define ZEND_MAKE_VAR 137 +#define ZEND_OP_DATA 137 + +#define ZEND_INSTANCEOF 138 + +#define ZEND_DECLARE_CLASS 139 +#define ZEND_DECLARE_INHERITED_CLASS 140 +#define ZEND_DECLARE_FUNCTION 141 + +#define ZEND_RAISE_ABSTRACT_ERROR 142 + /* end of block */ @@ -604,7 +658,6 @@ #define ZEND_FETCH_LOCAL 1 #define ZEND_FETCH_STATIC 2 #define ZEND_FETCH_STATIC_MEMBER 3 -#define ZEND_FETCH_FROM_THIS 4 /* class fetches */ #define ZEND_FETCH_CLASS_DEFAULT 0 @@ -623,7 +676,6 @@ /* unset types */ #define ZEND_UNSET_REG 0 -#define ZEND_UNSET_OBJ 1 /* var status for backpatching */ #define BP_VAR_R 0 @@ -662,10 +714,6 @@ #define ZEND_HANDLE_STDIOSTREAM 3 #define ZEND_HANDLE_FSTREAM 4 -#define ZEND_DECLARE_CLASS 1 -#define ZEND_DECLARE_FUNCTION 2 -#define ZEND_DECLARE_INHERITED_CLASS 3 - #define ZEND_FETCH_STANDARD 0 #define ZEND_FETCH_ADD_LOCK 1 @@ -705,4 +753,19 @@ END_EXTERN_C() +#define ZEND_CLONE_FUNC_NAME "__clone" +#define ZEND_CONSTRUCTOR_FUNC_NAME "__construct" +#define ZEND_DESTRUCTOR_FUNC_NAME "__destruct" +#define ZEND_GET_FUNC_NAME "__get" +#define ZEND_SET_FUNC_NAME "__set" +#define ZEND_CALL_FUNC_NAME "__call" + #endif /* ZEND_COMPILE_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +10 -1 ZendEngine2/zend_config.nw.h Index: zend_config.nw.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_config.nw.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_config.nw.h 2 Aug 2002 09:48:15 -0000 1.2 +++ zend_config.nw.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_config.nw.h,v 1.3 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_CONFIG_NW_H #define ZEND_CONFIG_NW_H @@ -77,3 +78,11 @@ */ #endif /* ZEND_CONFIG_NW_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +19 -5 ZendEngine2/zend_config.w32.h Index: zend_config.w32.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_config.w32.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_config.w32.h 29 Apr 2002 02:25:26 -0000 1.2 +++ zend_config.w32.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,10 +17,18 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_config.w32.h,v 1.32 2003/02/07 09:39:29 zeev Exp $ */ #ifndef ZEND_CONFIG_W32_H #define ZEND_CONFIG_W32_H +#define HAVE_ALLOCA 1 +#define HAVE_LIMITS_H 1 +#define _CRTDBG_MAP_ALLOC + +#include <malloc.h> +#include <stdlib.h> +#include <crtdbg.h> #include <string.h> #include <windows.h> @@ -29,10 +37,6 @@ typedef unsigned long ulong; typedef unsigned int uint; -#define HAVE_ALLOCA 1 -#define HAVE_LIMITS_H 1 -#include <malloc.h> - #undef HAVE_KILL #define HAVE_GETPID 1 /* #define HAVE_ALLOCA_H 1 */ @@ -48,6 +52,8 @@ #define snprintf _snprintf #define vsnprintf _vsnprintf +#define strcasecmp(s1, s2) stricmp(s1, s2) +#define strncasecmp(s1, s2, n) strnicmp(s1, s2, n) #define zend_isinf(a) 0 #define zend_finite(x) _finite(x) #define zend_isnan(x) _isnan(x) @@ -88,3 +94,11 @@ #define ZEND_SERVICE_MB_STYLE (MB_TOPMOST|MB_SERVICE_NOTIFICATION) #endif /* ZEND_CONFIG_W32_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.5 +31 -33 ZendEngine2/zend_constants.c Index: zend_constants.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_constants.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_constants.c 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_constants.c 11 Feb 2003 02:40:18 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_constants.c,v 1.46 2003/02/01 01:49:14 sniper Exp $ */ #include "zend.h" #include "zend_constants.h" @@ -27,8 +28,7 @@ void free_zend_constant(zend_constant *c) { - if (!(c->flags & CONST_PERSISTENT) - || (c->flags & CONST_EFREE_PERSISTENT)) { + if (!(c->flags & CONST_PERSISTENT)) { zval_dtor(&c->value); } free(c->name); @@ -40,9 +40,6 @@ c->name = zend_strndup(c->name, c->name_len); if (!(c->flags & CONST_PERSISTENT)) { zval_copy_ctor(&c->value); - if (c->flags & CONST_EFREE_PERSISTENT) { /* persist_alloc()'d data */ - persist_alloc(&c->value); - } } } @@ -83,13 +80,6 @@ int zend_startup_constants(TSRMLS_D) { -#ifdef ZEND_WIN32 - DWORD dwBuild=0; - DWORD dwVersion = GetVersion(); - DWORD dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); - DWORD dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); -#endif - EG(zend_constants) = &CG(main_class).constants_table; if (zend_hash_init(EG(zend_constants), 20, NULL, ZEND_CONSTANT_DTOR, 1)==FAILURE) { @@ -220,26 +210,27 @@ { zend_constant *c; char *lookup_name; - int retval; + int retval = 1; - lookup_name = do_alloca(name_len+1); - memcpy(lookup_name, name, name_len+1); - - zend_str_tolower(lookup_name, name_len); - - if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) { - if ((c->flags & CONST_CS) && memcmp(c->name, name, name_len)!=0) { - retval=0; + if (zend_hash_find(EG(zend_constants), name, name_len+1, (void **) &c) == FAILURE) { + lookup_name = do_alloca(name_len+1); + memcpy(lookup_name, name, name_len+1); + zend_str_tolower(lookup_name, name_len); + + if (zend_hash_find(EG(zend_constants), lookup_name, name_len+1, (void **) &c)==SUCCESS) { + if ((c->flags & CONST_CS) && memcmp(c->name, name, name_len)!=0) { + retval=0; + } } else { - retval=1; - *result = c->value; - zval_copy_ctor(result); + retval=0; } - } else { - retval=0; + free_alloca(lookup_name); } - free_alloca(lookup_name); + if (retval) { + *result = c->value; + zval_copy_ctor(result); + } return retval; } @@ -247,24 +238,30 @@ ZEND_API int zend_register_constant(zend_constant *c TSRMLS_DC) { - char *lowercase_name = zend_strndup(c->name, c->name_len); + char *lowercase_name; int ret = SUCCESS; #if 0 printf("Registering constant for module %d\n", c->module_number); #endif - zend_str_tolower(lowercase_name, c->name_len); + lowercase_name = do_alloca(c->name_len); + + memcpy(lowercase_name, c->name, c->name_len); + + if (!(c->flags & CONST_CS)) { + zend_str_tolower(lowercase_name, c->name_len); + } + if (zend_hash_add(EG(zend_constants), lowercase_name, c->name_len, (void *) c, sizeof(zend_constant), NULL)==FAILURE) { free(c->name); - if (!(c->flags & CONST_PERSISTENT) - || (c->flags & CONST_EFREE_PERSISTENT)) { + if (!(c->flags & CONST_PERSISTENT)) { zval_dtor(&c->value); } zend_error(E_NOTICE,"Constant %s already defined", lowercase_name); ret = FAILURE; } - free(lowercase_name); + free_alloca(lowercase_name); return ret; } @@ -273,5 +270,6 @@ * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.5 +10 -5 ZendEngine2/zend_constants.h Index: zend_constants.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_constants.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_constants.h 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_constants.h 11 Feb 2003 02:40:18 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_constants.h,v 1.24 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_CONSTANTS_H #define ZEND_CONSTANTS_H @@ -25,10 +26,6 @@ #define CONST_CS (1<<0) /* Case Sensitive */ #define CONST_PERSISTENT (1<<1) /* Persistent */ -#define CONST_EFREE_PERSISTENT (1<<2) /* In conjunction with CONST_PERSISTENT, - * means that the constant should be freed - * using zval_dtor() on shutdown. - */ typedef struct _zend_constant { zval value; @@ -66,3 +63,11 @@ #define ZEND_CONSTANT_DTOR (void (*)(void *)) free_zend_constant #endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +11 -1 ZendEngine2/zend_dynamic_array.c Index: zend_dynamic_array.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_dynamic_array.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_dynamic_array.c 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_dynamic_array.c 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,8 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_dynamic_array.c,v 1.10 2003/02/01 01:49:14 sniper Exp $ */ + #include "zend.h" typedef struct _dynamic_array { @@ -60,3 +62,11 @@ } return (void *)(da->array+index*da->element_size); } + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +10 -1 ZendEngine2/zend_dynamic_array.h Index: zend_dynamic_array.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_dynamic_array.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_dynamic_array.h 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_dynamic_array.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_dynamic_array.h,v 1.10 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_DYNAMIC_ARRAY_H #define ZEND_DYNAMIC_ARRAY_H @@ -36,3 +37,11 @@ END_EXTERN_C() #endif /* ZEND_DYNAMIC_ARRAY_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +9 -1 ZendEngine2/zend_errors.h Index: zend_errors.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_errors.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_errors.h 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_errors.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_errors.h,v 1.13 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_ERRORS_H #define ZEND_ERRORS_H @@ -38,3 +39,10 @@ #endif /* ZEND_ERRORS_H */ +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.8 +2984 -2138ZendEngine2/zend_execute.c Index: zend_execute.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_execute.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -r1.7 -r1.8 --- zend_execute.c 3 Aug 2002 08:56:16 -0000 1.7 +++ zend_execute.c 11 Feb 2003 02:40:18 -0000 1.8 @@ -2,10 +2,10 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | - | that is bundled with this package in the file LICENSE, and is | + | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.zend.com/license/2_00.txt. | | If you did not receive a copy of the Zend license and are unable to | @@ -17,6 +17,8 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_execute.c,v 1.424 2003/02/10 11:49:21 zeev Exp $ */ + #define ZEND_INTENSIVE_DEBUGGING 0 #include <stdio.h> @@ -31,32 +33,11 @@ #include "zend_extensions.h" #include "zend_fast_cache.h" #include "zend_execute_locks.h" +#include "zend_ini.h" #define get_zval_ptr(node, Ts, should_free, type) _get_zval_ptr(node, Ts, should_free TSRMLS_CC) #define get_zval_ptr_ptr(node, Ts, type) _get_zval_ptr_ptr(node, Ts TSRMLS_CC) -#define get_incdec_op(op, opcode) \ - switch (opcode) { \ - case ZEND_PRE_INC: \ - case ZEND_POST_INC: \ - case ZEND_PRE_INC_OBJ: \ - case ZEND_POST_INC_OBJ: \ - (op) = increment_function; \ - break; \ - case ZEND_PRE_DEC: \ - case ZEND_POST_DEC: \ - case ZEND_PRE_DEC_OBJ: \ - case ZEND_POST_DEC_OBJ: \ - (op) = decrement_function; \ - break; \ - default: \ - (op) = NULL; \ - break; \ - } \ - -/* These globals don't have to be thread safe since they're never modified */ - - /* Prototypes */ static void zend_fetch_var_address(zend_op *opline, temp_variable *Ts, int type TSRMLS_DC); static void zend_fetch_dimension_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type TSRMLS_DC); @@ -68,28 +49,30 @@ #define RETURN_VALUE_USED(opline) (!((opline)->result.u.EA.type & EXT_TYPE_UNUSED)) -static inline zval *_get_zval_ptr(znode *node, temp_variable *Ts, int *should_free TSRMLS_DC) +#define EX_T(offset) (*(temp_variable *)((char *) EX(Ts) + offset)) +#define T(offset) (*(temp_variable *)((char *) Ts + offset)) + +static inline zval *_get_zval_ptr(znode *node, temp_variable *Ts, zval **should_free TSRMLS_DC) { - switch(node->op_type) { + switch (node->op_type) { case IS_CONST: *should_free = 0; return &node->u.constant; break; case IS_TMP_VAR: - *should_free = 1; - return &Ts[node->u.var].tmp_var; + return *should_free = &T(node->u.var).tmp_var; break; case IS_VAR: - if (Ts[node->u.var].var.ptr) { - PZVAL_UNLOCK(Ts[node->u.var].var.ptr); + if (T(node->u.var).var.ptr) { + PZVAL_UNLOCK(T(node->u.var).var.ptr); *should_free = 0; - return Ts[node->u.var].var.ptr; + return T(node->u.var).var.ptr; } else { - *should_free = 1; + *should_free = &T(node->u.var).tmp_var; - switch (Ts[node->u.var].EA.type) { + switch (T(node->u.var).EA.type) { case IS_STRING_OFFSET: { - temp_variable *T = &Ts[node->u.var]; + temp_variable *T = &T(node->u.var); zval *str = T->EA.data.str_offset.str; if (T->EA.data.str_offset.str->type != IS_STRING @@ -123,44 +106,15 @@ return NULL; } -static inline zval *_get_object_zval_ptr(znode *node, temp_variable *Ts, int *should_free TSRMLS_DC) -{ - switch(node->op_type) { - case IS_TMP_VAR: - *should_free = 1; - return &Ts[node->u.var].tmp_var; - break; - case IS_VAR: - if (Ts[node->u.var].var.ptr_ptr) { - PZVAL_UNLOCK(*Ts[node->u.var].var.ptr_ptr); - *should_free = 0; - return *Ts[node->u.var].var.ptr_ptr; - } else { - if (Ts[node->u.var].EA.type==IS_STRING_OFFSET) { - PZVAL_UNLOCK(Ts[node->u.var].EA.data.str_offset.str); - } - *should_free = 1; - return NULL; - } - break; - case IS_UNUSED: - return NULL; - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - return NULL; -} - - static inline zval **_get_zval_ptr_ptr(znode *node, temp_variable *Ts TSRMLS_DC) { if (node->op_type==IS_VAR) { - if (Ts[node->u.var].var.ptr_ptr) { - PZVAL_UNLOCK(*Ts[node->u.var].var.ptr_ptr); - } else if (Ts[node->u.var].EA.type==IS_STRING_OFFSET) { - PZVAL_UNLOCK(Ts[node->u.var].EA.data.str_offset.str); + if (T(node->u.var).var.ptr_ptr) { + PZVAL_UNLOCK(*T(node->u.var).var.ptr_ptr); + } else if (T(node->u.var).EA.type==IS_STRING_OFFSET) { + PZVAL_UNLOCK(T(node->u.var).EA.data.str_offset.str); } - return Ts[node->u.var].var.ptr_ptr; + return T(node->u.var).var.ptr_ptr; } else { return NULL; } @@ -169,7 +123,7 @@ static inline zval **zend_fetch_property_address_inner(zval *object, znode *op2, temp_variable *Ts, int type TSRMLS_DC) { zval *prop_ptr = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); - zval **retval; + zval **retval = NULL; zval tmp; @@ -188,9 +142,11 @@ break; } - if(Z_OBJ_HT_P(object)->get_property_ptr != NULL) { + if (Z_OBJ_HT_P(object)->get_property_ptr != NULL) { retval = Z_OBJ_HT_P(object)->get_property_ptr(object, prop_ptr TSRMLS_CC); - } else { + } + + if (retval == NULL) { zend_error(E_WARNING, "This object doesn't support property references"); retval = &EG(error_zval_ptr); } @@ -208,18 +164,18 @@ { switch (opline->op1.op_type) { case IS_VAR: - if (!Ts[opline->op1.u.var].var.ptr_ptr) { + if (!T(opline->op1.u.var).var.ptr_ptr) { get_zval_ptr(&opline->op1, Ts, &EG(free_op1), BP_VAR_R); FREE_OP(Ts, &opline->op1, EG(free_op1)); } else { - zval_ptr_dtor(&Ts[opline->op1.u.var].var.ptr); + zval_ptr_dtor(&T(opline->op1.u.var).var.ptr); if (opline->extended_value) { /* foreach() free */ - zval_ptr_dtor(&Ts[opline->op1.u.var].var.ptr); + zval_ptr_dtor(&T(opline->op1.u.var).var.ptr); } } break; case IS_TMP_VAR: - zendi_zval_dtor(Ts[opline->op1.u.var].tmp_var); + zendi_zval_dtor(T(opline->op1.u.var).tmp_var); break; EMPTY_SWITCH_DEFAULT_CASE() } @@ -271,14 +227,15 @@ } if (result && !(result->u.EA.type & EXT_TYPE_UNUSED)) { - Ts[result->u.var].var.ptr_ptr = variable_ptr_ptr; + T(result->u.var).var.ptr_ptr = variable_ptr_ptr; SELECTIVE_PZVAL_LOCK(*variable_ptr_ptr, result); - AI_USE_PTR(Ts[result->u.var].var); + AI_USE_PTR(T(result->u.var).var); } } static inline void make_real_object(zval **object_ptr TSRMLS_DC) { +/* this should modify object only if it's empty */ if ((*object_ptr)->type == IS_NULL || ((*object_ptr)->type == IS_BOOL && (*object_ptr)->value.lval==0) || ((*object_ptr)->type == IS_STRING && (*object_ptr)->value.str.len == 0)) { @@ -289,16 +246,44 @@ object_init(*object_ptr); } } - -static inline void zend_assign_to_object(znode *result, znode *op1, znode *op2, zval *value, temp_variable *Ts TSRMLS_DC) + +static inline zval **get_obj_zval_ptr_ptr(znode *op, temp_variable *Ts, int type TSRMLS_DC) +{ + if (op->op_type == IS_UNUSED) { + if (EG(This)) { + /* this should actually never be modified, _ptr_ptr is modified only when + the object is empty */ + return &EG(This); + } else { + zend_error(E_ERROR, "Using $this when not in object context"); + } + } + return get_zval_ptr_ptr(op, Ts, type); +} + +static inline zval *get_obj_zval_ptr(znode *op, temp_variable *Ts, zval **freeop, int type TSRMLS_DC) +{ + if (op->op_type == IS_UNUSED) { + if (EG(This)) { + return EG(This); + } else { + zend_error(E_ERROR, "Using $this when not in object context"); + } + } + return get_zval_ptr(op, Ts, freeop, type); +} + +static inline void zend_assign_to_object(znode *result, znode *op1, znode *op2, znode *value_op, temp_variable *Ts TSRMLS_DC) { - zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W); + zval **object_ptr = get_obj_zval_ptr_ptr(op1, Ts, BP_VAR_W TSRMLS_CC); zval *object; zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); + zval *free_value; + zval *value = get_zval_ptr(value_op, Ts, &free_value, BP_VAR_R); zval tmp; - zval **retval = &Ts[result->u.var].var.ptr; + zval **retval = &T(result->u.var).var.ptr; - make_real_object(object_ptr TSRMLS_CC); + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; if (object->type != IS_OBJECT) { @@ -307,6 +292,7 @@ *retval = EG(uninitialized_zval_ptr); SELECTIVE_PZVAL_LOCK(*retval, result); + PZVAL_UNLOCK(value); return; } @@ -326,9 +312,22 @@ break; } - /* here property is a string */ - PZVAL_UNLOCK(value); - + if (EG(implicit_clone)) { + SEPARATE_ZVAL_IF_NOT_REF(object_ptr); + object = *object_ptr; + } + /* by now, property is a string */ + + + /* separate our value if necessary */ + if (value_op->op_type == IS_TMP_VAR) { + zval *orig_value = value; + + ALLOC_ZVAL(value); + *value = *orig_value; + value->is_ref = 0; + value->refcount = 0; + } Z_OBJ_HT_P(object)->write_property(object, property, value TSRMLS_CC); if (property == &tmp) { zval_dtor(property); @@ -336,21 +335,24 @@ FREE_OP(Ts, op2, EG(free_op2)); if (result) { - Ts[result->u.var].var.ptr = value; - Ts[result->u.var].var.ptr_ptr = NULL; /* see if we can nuke this */ + T(result->u.var).var.ptr = value; + T(result->u.var).var.ptr_ptr = NULL; /* see if we can nuke this */ SELECTIVE_PZVAL_LOCK(value, result); } } -static inline void zend_assign_to_object_op(znode *result, znode *op1, znode *op2, zval *value, temp_variable *Ts, int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) TSRMLS_DC) +static inline void zend_assign_to_object_op(znode *result, znode *op1, znode *op2, znode *value_op, temp_variable *Ts, int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) TSRMLS_DC) { - zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W); + zval **object_ptr = get_obj_zval_ptr_ptr(op1, Ts, BP_VAR_W TSRMLS_CC); zval *object; zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); + zval *free_value; + zval *value = get_zval_ptr(value_op, Ts, &free_value, BP_VAR_R); zval tmp; - zval **retval = &Ts[result->u.var].var.ptr; + zval **retval = &T(result->u.var).var.ptr; + int have_get_ptr = 0; - Ts[result->u.var].var.ptr_ptr = NULL; + T(result->u.var).var.ptr_ptr = NULL; make_real_object(object_ptr TSRMLS_CC); object = *object_ptr; @@ -380,23 +382,26 @@ } /* here property is a string */ - PZVAL_UNLOCK(value); - - if(Z_OBJ_HT_P(object)->get_property_zval_ptr) { + if (Z_OBJ_HT_P(object)->get_property_zval_ptr) { zval **zptr = Z_OBJ_HT_P(object)->get_property_zval_ptr(object, property TSRMLS_CC); - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (zptr != NULL) { /* NULL means no success in getting PTR */ + SEPARATE_ZVAL_IF_NOT_REF(zptr); - binary_op(*zptr, *zptr, value TSRMLS_CC); - *retval = *zptr; - SELECTIVE_PZVAL_LOCK(*retval, result); - } else { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC); + have_get_ptr = 1; + binary_op(*zptr, *zptr, value TSRMLS_CC); + *retval = *zptr; + SELECTIVE_PZVAL_LOCK(*retval, result); + } + } + + if (!have_get_ptr) { + zval *z = Z_OBJ_HT_P(object)->read_property(object, property TSRMLS_CC); SEPARATE_ZVAL_IF_NOT_REF(&z); binary_op(z, z, value TSRMLS_CC); Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); *retval = z; SELECTIVE_PZVAL_LOCK(*retval, result); - if(z->refcount <= 1) { + if (z->refcount <= 1) { zval_dtor(z); } } @@ -414,9 +419,9 @@ zval *variable_ptr; if (!variable_ptr_ptr) { - switch (Ts[op1->u.var].EA.type) { + switch (T(op1->u.var).EA.type) { case IS_STRING_OFFSET: { - temp_variable *T = &Ts[op1->u.var]; + temp_variable *T = &T(op1->u.var); if (T->EA.data.str_offset.str->type == IS_STRING) do { zval tmp; @@ -454,7 +459,7 @@ T->EA.data.str_offset.str->value.str.val[T->EA.data.str_offset.offset] = final_value->value.str.val[0]; if (op2 && op2->op_type == IS_VAR - && value==&Ts[op2->u.var].tmp_var) { + && value==&T(op2->u.var).tmp_var) { STR_FREE(value->value.str.val); } if (final_value == &tmp) { @@ -462,18 +467,18 @@ } /* * the value of an assignment to a string offset is undefined - Ts[result->u.var].var = &T->EA.data.str_offset.str; + T(result->u.var).var = &T->EA.data.str_offset.str; */ - } while(0); + } while (0); /* zval_ptr_dtor(&T->EA.data.str_offset.str); Nuke this line if it doesn't cause a leak */ T->tmp_var.type = IS_STRING; } break; EMPTY_SWITCH_DEFAULT_CASE() } - Ts[result->u.var].var.ptr_ptr = &EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*Ts[result->u.var].var.ptr_ptr, result); - AI_USE_PTR(Ts[result->u.var].var); + T(result->u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); + SELECTIVE_PZVAL_LOCK(*T(result->u.var).var.ptr_ptr, result); + AI_USE_PTR(T(result->u.var).var); return; } @@ -481,9 +486,9 @@ if (variable_ptr == EG(error_zval_ptr)) { if (result) { - Ts[result->u.var].var.ptr_ptr = &EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*Ts[result->u.var].var.ptr_ptr, result); - AI_USE_PTR(Ts[result->u.var].var); + T(result->u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); + SELECTIVE_PZVAL_LOCK(*T(result->u.var).var.ptr_ptr, result); + AI_USE_PTR(T(result->u.var).var); } if (type==IS_TMP_VAR) { zval_dtor(value); @@ -567,9 +572,9 @@ (*variable_ptr_ptr)->is_ref=0; } if (result) { - Ts[result->u.var].var.ptr_ptr = variable_ptr_ptr; + T(result->u.var).var.ptr_ptr = variable_ptr_ptr; SELECTIVE_PZVAL_LOCK(*variable_ptr_ptr, result); - AI_USE_PTR(Ts[result->u.var].var); + AI_USE_PTR(T(result->u.var).var); } } @@ -604,7 +609,8 @@ print_refcount(NULL, NULL); } -static inline HashTable *zend_get_target_symbol_table(zend_op *opline, temp_variable *Ts, int type TSRMLS_DC) + +static inline HashTable *zend_get_target_symbol_table(zend_op *opline, temp_variable *Ts, int type, zval *variable TSRMLS_DC) { switch (opline->op2.u.EA.type) { case ZEND_FETCH_LOCAL: @@ -625,16 +631,6 @@ } return EG(active_op_array)->static_variables; break; - case ZEND_FETCH_STATIC_MEMBER: - return Ts[opline->op2.u.var].EA.class_entry->static_members; - break; - case ZEND_FETCH_FROM_THIS: - if (!EG(This)) { - zend_error(E_ERROR, "Using $this when not in object context"); - } - /* HACK!! 'this' should be always zend_object */ - return Z_OBJPROP_P(EG(This)); - break; EMPTY_SWITCH_DEFAULT_CASE() } return NULL; @@ -643,17 +639,12 @@ static void zend_fetch_var_address(zend_op *opline, temp_variable *Ts, int type TSRMLS_DC) { - int free_op1; + zval *free_op1; zval *varname = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); zval **retval; zval tmp_varname; HashTable *target_symbol_table; - target_symbol_table = zend_get_target_symbol_table(opline, Ts, type TSRMLS_CC); - if (!target_symbol_table) { - return; - } - if (varname->type != IS_STRING) { tmp_varname = *varname; zval_copy_ctor(&tmp_varname); @@ -661,37 +652,50 @@ varname = &tmp_varname; } - if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) { - switch (type) { - case BP_VAR_R: - zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval_ptr); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val); - /* break missing intentionally */ - case BP_VAR_W: { - zval *new_zval = &EG(uninitialized_zval); + if (opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { + target_symbol_table = NULL; + retval = zend_get_static_property(T(opline->op2.u.var).EA.class_entry, Z_STRVAL_P(varname), Z_STRLEN_P(varname), type TSRMLS_CC); + } else { + target_symbol_table = zend_get_target_symbol_table(opline, Ts, type, varname TSRMLS_CC); + if (!target_symbol_table) { + return; + } + if (zend_hash_find(target_symbol_table, varname->value.str.val, varname->value.str.len+1, (void **) &retval) == FAILURE) { + switch (type) { + case BP_VAR_R: + zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval_ptr); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s", varname->value.str.val); + /* break missing intentionally */ + case BP_VAR_W: { + zval *new_zval = &EG(uninitialized_zval); - new_zval->refcount++; - zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval); - } + new_zval->refcount++; + zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval); + } + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } + switch (opline->op2.u.EA.type) { + case ZEND_FETCH_LOCAL: + FREE_OP(Ts, &opline->op1, free_op1); + break; + case ZEND_FETCH_STATIC: + zval_update_constant(retval, (void *) 1 TSRMLS_CC); break; - EMPTY_SWITCH_DEFAULT_CASE() } } - if (opline->op2.u.EA.type == ZEND_FETCH_LOCAL) { - FREE_OP(Ts, &opline->op1, free_op1); - } else if (opline->op2.u.EA.type == ZEND_FETCH_STATIC || opline->op2.u.EA.type == ZEND_FETCH_STATIC_MEMBER) { - zval_update_constant(retval, (void *) 1 TSRMLS_CC); - } + if (varname == &tmp_varname) { zval_dtor(varname); } - Ts[opline->result.u.var].var.ptr_ptr = retval; + T(opline->result.u.var).var.ptr_ptr = retval; SELECTIVE_PZVAL_LOCK(*retval, &opline->result); } @@ -784,8 +788,21 @@ { zval **container_ptr = get_zval_ptr_ptr(op1, Ts, type); zval *container; - zval ***retval = &Ts[result->u.var].var.ptr_ptr; + zval ***retval = &T(result->u.var).var.ptr_ptr; + + if (!container_ptr) { + if (T(op1->u.var).EA.type == IS_STRING_OFFSET) { + zval *offset; + zend_error(E_WARNING, "Cannot use string offset as an array"); + offset = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); + FREE_OP(Ts, op2, EG(free_op2)); + } + *retval = &EG(error_zval_ptr); + SELECTIVE_PZVAL_LOCK(**retval, result); + return; + } + container = *container_ptr; if (container == EG(error_zval_ptr)) { @@ -819,7 +836,11 @@ zval *new_zval = &EG(uninitialized_zval); new_zval->refcount++; - zend_hash_next_index_insert(container->value.ht, &new_zval, sizeof(zval *), (void **) retval); + if (zend_hash_next_index_insert(container->value.ht, &new_zval, sizeof(zval *), (void **) retval) == FAILURE) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + *retval = &EG(uninitialized_zval_ptr); + new_zval->refcount--; + } } else { *retval = zend_fetch_dimension_address_inner(container->value.ht, op2, Ts, type TSRMLS_CC); } @@ -855,10 +876,10 @@ SEPARATE_ZVAL_IF_NOT_REF(container_ptr); } container = *container_ptr; - Ts[result->u.var].EA.data.str_offset.str = container; + T(result->u.var).EA.data.str_offset.str = container; PZVAL_LOCK(container); - Ts[result->u.var].EA.data.str_offset.offset = offset->value.lval; - Ts[result->u.var].EA.type = IS_STRING_OFFSET; + T(result->u.var).EA.data.str_offset.offset = offset->value.lval; + T(result->u.var).EA.type = IS_STRING_OFFSET; FREE_OP(Ts, op2, EG(free_op2)); *retval = NULL; return; @@ -886,24 +907,24 @@ static void zend_fetch_dimension_address_from_tmp_var(znode *result, znode *op1, znode *op2, temp_variable *Ts TSRMLS_DC) { - int free_op1; + zval *free_op1; zval *container = get_zval_ptr(op1, Ts, &free_op1, BP_VAR_R); if (container->type != IS_ARRAY) { - Ts[result->u.var].var.ptr_ptr = &EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*Ts[result->u.var].var.ptr_ptr, result); + T(result->u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); + SELECTIVE_PZVAL_LOCK(*T(result->u.var).var.ptr_ptr, result); return; } - Ts[result->u.var].var.ptr_ptr = zend_fetch_dimension_address_inner(container->value.ht, op2, Ts, BP_VAR_R TSRMLS_CC); - SELECTIVE_PZVAL_LOCK(*Ts[result->u.var].var.ptr_ptr, result); + T(result->u.var).var.ptr_ptr = zend_fetch_dimension_address_inner(container->value.ht, op2, Ts, BP_VAR_R TSRMLS_CC); + SELECTIVE_PZVAL_LOCK(*T(result->u.var).var.ptr_ptr, result); } static void zend_fetch_property_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type TSRMLS_DC) { - zval **container_ptr = get_zval_ptr_ptr(op1, Ts, type); + zval **container_ptr = get_obj_zval_ptr_ptr(op1, Ts, type TSRMLS_CC); zval *container; - zval ***retval = &Ts[result->u.var].var.ptr_ptr; + zval ***retval = &T(result->u.var).var.ptr_ptr; container = *container_ptr; if (container == EG(error_zval_ptr)) { @@ -911,7 +932,7 @@ SELECTIVE_PZVAL_LOCK(**retval, result); return; } - + /* this should modify object only if it's empty */ if (container->type == IS_NULL || (container->type == IS_BOOL && container->value.lval==0) || (container->type == IS_STRING && container->value.str.len == 0)) { @@ -955,10 +976,10 @@ zval *container; zval **retval; - retval = &Ts[result->u.var].var.ptr; - Ts[result->u.var].var.ptr_ptr = retval; + retval = &T(result->u.var).var.ptr; + T(result->u.var).var.ptr_ptr = retval; - container = get_zval_ptr(op1, Ts, &EG(free_op1), type); + container = get_obj_zval_ptr(op1, Ts, &EG(free_op1), type TSRMLS_CC); if (container == EG(error_zval_ptr)) { *retval = EG(error_zval_ptr); @@ -967,7 +988,7 @@ } - if(container->type != IS_OBJECT) { + if (container->type != IS_OBJECT) { zend_error(E_NOTICE, "Trying to get property of non-object"); if (type==BP_VAR_R || type==BP_VAR_IS) { @@ -996,7 +1017,7 @@ } /* here we are sure we are dealing with an object */ - *retval = Z_OBJ_HT_P(container)->read_property(container, offset, type TSRMLS_CC); + *retval = Z_OBJ_HT_P(container)->read_property(container, offset TSRMLS_CC); if (offset == &tmp) { zval_dtor(offset); } @@ -1009,12 +1030,13 @@ static void zend_pre_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC) { - zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W); + zval **object_ptr = get_obj_zval_ptr_ptr(op1, Ts, BP_VAR_W TSRMLS_CC); zval *object; zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); - zval **retval = &Ts[result->u.var].var.ptr; + zval **retval = &T(result->u.var).var.ptr; + int have_get_ptr = 0; - make_real_object(object_ptr TSRMLS_CC); + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; if (object->type != IS_OBJECT) { @@ -1028,19 +1050,24 @@ /* here we are sure we are dealing with an object */ - if(Z_OBJ_HT_P(object)->get_property_zval_ptr) { + if (Z_OBJ_HT_P(object)->get_property_zval_ptr) { zval **zptr = Z_OBJ_HT_P(object)->get_property_zval_ptr(object, property TSRMLS_CC); - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (zptr != NULL) { /* NULL means no success in getting PTR */ + SEPARATE_ZVAL_IF_NOT_REF(zptr); - incdec_op(*zptr); - *retval = *zptr; - SELECTIVE_PZVAL_LOCK(*retval, result); - } else { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC); + have_get_ptr = 1; + incdec_op(*zptr); + *retval = *zptr; + SELECTIVE_PZVAL_LOCK(*retval, result); + } + } + + if (!have_get_ptr) { + zval *z = Z_OBJ_HT_P(object)->read_property(object, property TSRMLS_CC); SEPARATE_ZVAL_IF_NOT_REF(&z); incdec_op(z); Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - if(z->refcount <= 1) { + if (z->refcount <= 1) { zval_dtor(z); } } @@ -1050,12 +1077,13 @@ static void zend_post_incdec_property(znode *result, znode *op1, znode *op2, temp_variable * Ts, int (*incdec_op)(zval *) TSRMLS_DC) { - zval **object_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W); + zval **object_ptr = get_obj_zval_ptr_ptr(op1, Ts, BP_VAR_W TSRMLS_CC); zval *object; zval *property = get_zval_ptr(op2, Ts, &EG(free_op2), BP_VAR_R); - zval *retval = &Ts[result->u.var].tmp_var; + zval *retval = &T(result->u.var).tmp_var; + int have_get_ptr = 0; - make_real_object(object_ptr TSRMLS_CC); + make_real_object(object_ptr TSRMLS_CC); /* this should modify object only if it's empty */ object = *object_ptr; if (object->type != IS_OBJECT) { @@ -1067,22 +1095,28 @@ /* here we are sure we are dealing with an object */ - if(Z_OBJ_HT_P(object)->get_property_zval_ptr) { + if (Z_OBJ_HT_P(object)->get_property_zval_ptr) { zval **zptr = Z_OBJ_HT_P(object)->get_property_zval_ptr(object, property TSRMLS_CC); - SEPARATE_ZVAL_IF_NOT_REF(zptr); + if (zptr != NULL) { /* NULL means no success in getting PTR */ + have_get_ptr = 1; + SEPARATE_ZVAL_IF_NOT_REF(zptr); + + *retval = **zptr; + zendi_zval_copy_ctor(*retval); + + incdec_op(*zptr); - *retval = **zptr; - zendi_zval_copy_ctor(*retval); + } + } - incdec_op(*zptr); - } else { - zval *z = Z_OBJ_HT_P(object)->read_property(object, property, BP_VAR_RW TSRMLS_CC); + if (!have_get_ptr) { + zval *z = Z_OBJ_HT_P(object)->read_property(object, property TSRMLS_CC); SEPARATE_ZVAL_IF_NOT_REF(&z); *retval = *z; zendi_zval_copy_ctor(*retval); incdec_op(z); Z_OBJ_HT_P(object)->write_property(object, property, z TSRMLS_CC); - if(z->refcount <= 1) { + if (z->refcount <= 1) { zval_dtor(z); } } @@ -1122,13 +1156,20 @@ #define NEXT_OPCODE() \ CHECK_SYMBOL_TABLES() \ EX(opline)++; \ - continue; + return 0; /* CHECK_ME */ #define RETURN_FROM_EXECUTE_LOOP(execute_data) \ free_alloca(EX(Ts)); \ EG(in_execution) = EX(original_in_execution); \ EG(current_execute_data) = EX(prev_execute_data); \ - return; + return 1; /* CHECK_ME */ + +opcode_handler_t zend_opcode_handlers[512]; + +ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC) +{ + ((zend_internal_function *) execute_data_ptr->function_state.function)->handler(execute_data_ptr->opline->extended_value, (*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.u.var)).var.ptr, execute_data_ptr->object, return_value_used TSRMLS_CC); +} ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) { @@ -1138,6 +1179,7 @@ EX(fbc) = NULL; EX(object) = NULL; EX(Ts) = (temp_variable *) do_alloca(sizeof(temp_variable)*op_array->T); + EX(op_array) = op_array; EX(original_in_execution) = EG(in_execution); EX(prev_execute_data) = EG(current_execute_data); EG(current_execute_data) = &execute_data; @@ -1166,7 +1208,7 @@ */ EX(function_state).function_symbol_table = NULL; #endif - + while (1) { #ifdef ZEND_WIN32 if (EG(timed_out)) { @@ -1175,2042 +1217,2846 @@ #endif zend_clean_garbage(TSRMLS_C); + if (EX(opline)->handler(&execute_data, op_array TSRMLS_CC)) { + return; + } + } + zend_error(E_ERROR, "Arrived at end of main loop which shouldn't happen"); +} - switch(EX(opline)->opcode) { - case ZEND_ADD: - EG(binary_op) = add_function; - goto binary_op_addr; - case ZEND_SUB: - EG(binary_op) = sub_function; - goto binary_op_addr; - case ZEND_MUL: - EG(binary_op) = mul_function; - goto binary_op_addr; - case ZEND_DIV: - EG(binary_op) = div_function; - goto binary_op_addr; - case ZEND_MOD: - EG(binary_op) = mod_function; - goto binary_op_addr; - case ZEND_SL: - EG(binary_op) = shift_left_function; - goto binary_op_addr; - case ZEND_SR: - EG(binary_op) = shift_right_function; - goto binary_op_addr; - case ZEND_CONCAT: - EG(binary_op) = concat_function; - goto binary_op_addr; - case ZEND_IS_IDENTICAL: - EG(binary_op) = is_identical_function; - goto binary_op_addr; - case ZEND_IS_NOT_IDENTICAL: - EG(binary_op) = is_not_identical_function; - goto binary_op_addr; - case ZEND_IS_EQUAL: - EG(binary_op) = is_equal_function; - goto binary_op_addr; - case ZEND_IS_NOT_EQUAL: - EG(binary_op) = is_not_equal_function; - goto binary_op_addr; - case ZEND_IS_SMALLER: - EG(binary_op) = is_smaller_function; - goto binary_op_addr; - case ZEND_IS_SMALLER_OR_EQUAL: - EG(binary_op) = is_smaller_or_equal_function; - goto binary_op_addr; - case ZEND_BW_OR: - EG(binary_op) = bitwise_or_function; - goto binary_op_addr; - case ZEND_BW_AND: - EG(binary_op) = bitwise_and_function; - goto binary_op_addr; - case ZEND_BW_XOR: - EG(binary_op) = bitwise_xor_function; - goto binary_op_addr; - case ZEND_BOOL_XOR: - EG(binary_op) = boolean_xor_function; - /* Fall through */ -binary_op_addr: - EG(binary_op)(&EX(Ts)[EX(opline)->result.u.var].tmp_var, - get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), - get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - NEXT_OPCODE(); - case ZEND_BW_NOT: - case ZEND_BOOL_NOT: - EG(unary_op) = get_unary_op(EX(opline)->opcode); - EG(unary_op)(&EX(Ts)[EX(opline)->result.u.var].tmp_var, - get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R) ); - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); - NEXT_OPCODE(); - case ZEND_ASSIGN_ADD: - EG(binary_op) = add_function; - goto binary_assign_op_addr; - case ZEND_ASSIGN_SUB: - EG(binary_op) = sub_function; - goto binary_assign_op_addr; - case ZEND_ASSIGN_MUL: - EG(binary_op) = mul_function; - goto binary_assign_op_addr; - case ZEND_ASSIGN_DIV: - EG(binary_op) = div_function; - goto binary_assign_op_addr; - case ZEND_ASSIGN_MOD: - EG(binary_op) = mod_function; - goto binary_assign_op_addr; - case ZEND_ASSIGN_SL: - EG(binary_op) = shift_left_function; - goto binary_assign_op_addr; - case ZEND_ASSIGN_SR: - EG(binary_op) = shift_right_function; - goto binary_assign_op_addr; - case ZEND_ASSIGN_CONCAT: - EG(binary_op) = concat_function; - goto binary_assign_op_addr; - case ZEND_ASSIGN_BW_OR: - EG(binary_op) = bitwise_or_function; - goto binary_assign_op_addr; - case ZEND_ASSIGN_BW_AND: - EG(binary_op) = bitwise_and_function; - goto binary_assign_op_addr; - case ZEND_ASSIGN_BW_XOR: - EG(binary_op) = bitwise_xor_function; - /* Fall through */ -binary_assign_op_addr: { - zval **var_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_RW); - - if (!var_ptr) { - zend_error(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); - } - if (*var_ptr == EG(error_zval_ptr)) { - EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr, &EX(opline)->result); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - EX(opline)++; - continue; - } - - SEPARATE_ZVAL_IF_NOT_REF(var_ptr); - - EG(binary_op)(*var_ptr, *var_ptr, get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); - EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = var_ptr; - SELECTIVE_PZVAL_LOCK(*var_ptr, &EX(opline)->result); - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - } - NEXT_OPCODE(); +/* CHECK_ME */ +#undef EX +#define EX(element) execute_data->element - case ZEND_ASSIGN_ADD_OBJ: - EG(binary_op) = add_function; - goto binary_assign_op_addr_obj; - case ZEND_ASSIGN_SUB_OBJ: - EG(binary_op) = sub_function; - goto binary_assign_op_addr_obj; - case ZEND_ASSIGN_MUL_OBJ: - EG(binary_op) = mul_function; - goto binary_assign_op_addr_obj; - case ZEND_ASSIGN_DIV_OBJ: - EG(binary_op) = div_function; - goto binary_assign_op_addr_obj; - case ZEND_ASSIGN_MOD_OBJ: - EG(binary_op) = mod_function; - goto binary_assign_op_addr_obj; - case ZEND_ASSIGN_SL_OBJ: - EG(binary_op) = shift_left_function; - goto binary_assign_op_addr_obj; - case ZEND_ASSIGN_SR_OBJ: - EG(binary_op) = shift_right_function; - goto binary_assign_op_addr_obj; - case ZEND_ASSIGN_CONCAT_OBJ: - EG(binary_op) = concat_function; - goto binary_assign_op_addr_obj; - case ZEND_ASSIGN_BW_OR_OBJ: - EG(binary_op) = bitwise_or_function; - goto binary_assign_op_addr_obj; - case ZEND_ASSIGN_BW_AND_OBJ: - EG(binary_op) = bitwise_and_function; - goto binary_assign_op_addr_obj; - case ZEND_ASSIGN_BW_XOR_OBJ: - EG(binary_op) = bitwise_xor_function; - /* Fall through */ -binary_assign_op_addr_obj: - zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts)[EX(opline)->extended_value].var.ptr, EX(Ts), EG(binary_op) TSRMLS_CC); - NEXT_OPCODE(); - case ZEND_PRE_INC_OBJ: - case ZEND_PRE_DEC_OBJ: { - int (*incdec_op)(zval *op); +int zend_add_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + add_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - get_incdec_op(incdec_op, EX(opline)->opcode); - zend_pre_incdec_property(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), incdec_op TSRMLS_CC); - } - NEXT_OPCODE(); - case ZEND_POST_INC_OBJ: - case ZEND_POST_DEC_OBJ: { - int (*incdec_op)(zval *op); - get_incdec_op(incdec_op, EX(opline)->opcode); - zend_post_incdec_property(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), incdec_op TSRMLS_CC); - } - NEXT_OPCODE(); - case ZEND_PRE_INC: - case ZEND_PRE_DEC: - case ZEND_POST_INC: - case ZEND_POST_DEC: { - int (*incdec_op)(zval *op); - zval **var_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_RW); +int zend_sub_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + sub_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - if (!var_ptr) { - zend_error(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); - } - if (*var_ptr == EG(error_zval_ptr)) { - EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EG(uninitialized_zval_ptr); - SELECTIVE_PZVAL_LOCK(*EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr, &EX(opline)->result); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - EX(opline)++; - continue; - } - get_incdec_op(incdec_op, EX(opline)->opcode); +int zend_mul_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + mul_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - switch (EX(opline)->opcode) { - case ZEND_POST_INC: - case ZEND_POST_DEC: - EX(Ts)[EX(opline)->result.u.var].tmp_var = **var_ptr; - zendi_zval_copy_ctor(EX(Ts)[EX(opline)->result.u.var].tmp_var); - break; - } - - SEPARATE_ZVAL_IF_NOT_REF(var_ptr); - incdec_op(*var_ptr); - switch (EX(opline)->opcode) { - case ZEND_PRE_INC: - case ZEND_PRE_DEC: - EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = var_ptr; - SELECTIVE_PZVAL_LOCK(*var_ptr, &EX(opline)->result); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - break; - } - } - NEXT_OPCODE(); - case ZEND_PRINT: - zend_print_variable(get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R)); - EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = 1; - EX(Ts)[EX(opline)->result.u.var].tmp_var.type = IS_LONG; - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); - NEXT_OPCODE(); - case ZEND_ECHO: - zend_print_variable(get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R)); - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); - NEXT_OPCODE(); - case ZEND_FETCH_R: - zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_R TSRMLS_CC); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - NEXT_OPCODE(); - case ZEND_FETCH_W: - zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_W TSRMLS_CC); - NEXT_OPCODE(); - case ZEND_FETCH_RW: - zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_RW TSRMLS_CC); - NEXT_OPCODE(); - case ZEND_FETCH_FUNC_ARG: - if (ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->extended_value, EX(fbc), EX(fbc)->common.arg_types)) { - /* Behave like FETCH_W */ - zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_W TSRMLS_CC); - } else { - /* Behave like FETCH_R */ - zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_R TSRMLS_CC); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - } - NEXT_OPCODE(); - case ZEND_FETCH_UNSET: - zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_R TSRMLS_CC); - PZVAL_UNLOCK(*EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr); - if (EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr != &EG(uninitialized_zval_ptr)) { - SEPARATE_ZVAL_IF_NOT_REF(EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr); - } - PZVAL_LOCK(*EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr); - NEXT_OPCODE(); - case ZEND_FETCH_IS: - zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_IS TSRMLS_CC); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - NEXT_OPCODE(); - case ZEND_FETCH_DIM_R: - if (EX(opline)->extended_value == ZEND_FETCH_ADD_LOCK) { - PZVAL_LOCK(*EX(Ts)[EX(opline)->op1.u.var].var.ptr_ptr); - } - zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - NEXT_OPCODE(); - case ZEND_FETCH_DIM_W: - zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_W TSRMLS_CC); - NEXT_OPCODE(); - case ZEND_FETCH_DIM_RW: - zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_RW TSRMLS_CC); - NEXT_OPCODE(); - case ZEND_FETCH_DIM_IS: - zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_IS TSRMLS_CC); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - NEXT_OPCODE(); - case ZEND_FETCH_DIM_FUNC_ARG: - if (ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->extended_value, EX(fbc), EX(fbc)->common.arg_types)) { - /* Behave like FETCH_DIM_W */ - zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_W TSRMLS_CC); - } else { - /* Behave like FETCH_DIM_R, except for locking used for list() */ - zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - } - NEXT_OPCODE(); - case ZEND_FETCH_DIM_UNSET: - /* Not needed in DIM_UNSET - if (EX(opline)->extended_value == ZEND_FETCH_ADD_LOCK) { - PZVAL_LOCK(*EX(Ts)[EX(opline)->op1.u.var].var.ptr_ptr); - } - */ - zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - PZVAL_UNLOCK(*EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr); - if (EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr != &EG(uninitialized_zval_ptr)) { - SEPARATE_ZVAL_IF_NOT_REF(EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr); - } - PZVAL_LOCK(*EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr); - NEXT_OPCODE(); - case ZEND_FETCH_OBJ_R: - zend_fetch_property_address_read(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - NEXT_OPCODE(); - case ZEND_FETCH_OBJ_W: - zend_fetch_property_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_W TSRMLS_CC); - NEXT_OPCODE(); - case ZEND_FETCH_OBJ_RW: - zend_fetch_property_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_RW TSRMLS_CC); - NEXT_OPCODE(); - case ZEND_FETCH_OBJ_IS: - zend_fetch_property_address_read(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_IS TSRMLS_CC); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - NEXT_OPCODE(); - case ZEND_FETCH_OBJ_FUNC_ARG: - if (ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->extended_value, EX(fbc), EX(fbc)->common.arg_types)) { - /* Behave like FETCH_OBJ_W */ - zend_fetch_property_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_W TSRMLS_CC); - } else { - zend_fetch_property_address_read(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_R TSRMLS_CC); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - } - NEXT_OPCODE(); - case ZEND_FETCH_OBJ_UNSET: - zend_fetch_property_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_R TSRMLS_CC); +int zend_div_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + div_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - PZVAL_UNLOCK(*EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr); - if (EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr != &EG(uninitialized_zval_ptr)) { - SEPARATE_ZVAL_IF_NOT_REF(EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr); - } - PZVAL_LOCK(*EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr); - NEXT_OPCODE(); - case ZEND_FETCH_DIM_TMP_VAR: - zend_fetch_dimension_address_from_tmp_var(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts) TSRMLS_CC); - AI_USE_PTR(EX(Ts)[EX(opline)->result.u.var].var); - NEXT_OPCODE(); - case ZEND_MAKE_VAR: { - zval *value, *value2; - value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - switch(EX(opline)->op1.op_type) { - case IS_TMP_VAR: - value2 = value; - ALLOC_ZVAL(value); - *value = *value2; - value->is_ref = 0; - value->refcount = 0; /* lock will increase this */ - break; - case IS_CONST: - value2 = value; - ALLOC_ZVAL(value); - *value = *value2; - zval_copy_ctor(value); - value->is_ref = 0; - value->refcount = 0; /* lock will increase this */ - break; - } - - EX(Ts)[EX(opline)->result.u.var].var.ptr = value; - PZVAL_LOCK(EX(Ts)[EX(opline)->result.u.var].var.ptr); - } - NEXT_OPCODE(); - case ZEND_ASSIGN_OBJ: - zend_assign_to_object(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts)[EX(opline)->extended_value].var.ptr, EX(Ts) TSRMLS_CC); - NEXT_OPCODE(); - case ZEND_ASSIGN: { - zval *value; - value = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); +int zend_mod_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + mod_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - zend_assign_to_variable(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, value, (EG(free_op2)?IS_TMP_VAR:EX(opline)->op2.op_type), EX(Ts) TSRMLS_CC); - /* zend_assign_to_variable() always takes care of op2, never free it! */ - } - NEXT_OPCODE(); - case ZEND_ASSIGN_REF: - zend_assign_to_variable_reference(&EX(opline)->result, get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_W), get_zval_ptr_ptr(&EX(opline)->op2, EX(Ts), BP_VAR_W), EX(Ts) TSRMLS_CC); - NEXT_OPCODE(); - case ZEND_JMP: -#if DEBUG_ZEND>=2 - printf("Jumping to %d\n", EX(opline)->op1.u.opline_num); -#endif - EX(opline) = &op_array->opcodes[EX(opline)->op1.u.opline_num]; - continue; - break; - case ZEND_JMPZ: { - znode *op1 = &EX(opline)->op1; - - if (!i_zend_is_true(get_zval_ptr(op1, EX(Ts), &EG(free_op1), BP_VAR_R))) { -#if DEBUG_ZEND>=2 - printf("Conditional jmp to %d\n", EX(opline)->op2.u.opline_num); -#endif - EX(opline) = &op_array->opcodes[EX(opline)->op2.u.opline_num]; - FREE_OP(EX(Ts), op1, EG(free_op1)); - continue; - } - FREE_OP(EX(Ts), op1, EG(free_op1)); - } - NEXT_OPCODE(); - case ZEND_JMPNZ: { - znode *op1 = &EX(opline)->op1; - - if (zend_is_true(get_zval_ptr(op1, EX(Ts), &EG(free_op1), BP_VAR_R))) { -#if DEBUG_ZEND>=2 - printf("Conditional jmp to %d\n", EX(opline)->op2.u.opline_num); -#endif - EX(opline) = &op_array->opcodes[EX(opline)->op2.u.opline_num]; - FREE_OP(EX(Ts), op1, EG(free_op1)); - continue; - } - FREE_OP(EX(Ts), op1, EG(free_op1)); - } - NEXT_OPCODE(); - case ZEND_JMPZNZ: { - znode *res = &EX(opline)->op1; - - if (zend_is_true(get_zval_ptr(res, EX(Ts), &EG(free_op1), BP_VAR_R))) { -#if DEBUG_ZEND>=2 - printf("Conditional jmp on true to %d\n", EX(opline)->extended_value); -#endif - EX(opline) = &op_array->opcodes[EX(opline)->extended_value]; - } else { -#if DEBUG_ZEND>=2 - printf("Conditional jmp on false to %d\n", EX(opline)->op2.u.opline_num); -#endif - EX(opline) = &op_array->opcodes[EX(opline)->op2.u.opline_num]; - } - FREE_OP(EX(Ts), res, EG(free_op1)); - } - continue; - break; - case ZEND_JMPZ_EX: { - zend_op *original_opline = EX(opline); - int retval = zend_is_true(get_zval_ptr(&original_opline->op1, EX(Ts), &EG(free_op1), BP_VAR_R)); - - FREE_OP(EX(Ts), &original_opline->op1, EG(free_op1)); - EX(Ts)[original_opline->result.u.var].tmp_var.value.lval = retval; - EX(Ts)[original_opline->result.u.var].tmp_var.type = IS_BOOL; - if (!retval) { -#if DEBUG_ZEND>=2 - printf("Conditional jmp to %d\n", EX(opline)->op2.u.opline_num); -#endif - EX(opline) = &op_array->opcodes[EX(opline)->op2.u.opline_num]; - continue; - } - } - NEXT_OPCODE(); - case ZEND_JMPNZ_EX: { - zend_op *original_opline = EX(opline); - int retval = zend_is_true(get_zval_ptr(&original_opline->op1, EX(Ts), &EG(free_op1), BP_VAR_R)); - - FREE_OP(EX(Ts), &original_opline->op1, EG(free_op1)); - EX(Ts)[original_opline->result.u.var].tmp_var.value.lval = retval; - EX(Ts)[original_opline->result.u.var].tmp_var.type = IS_BOOL; - if (retval) { -#if DEBUG_ZEND>=2 - printf("Conditional jmp to %d\n", EX(opline)->op2.u.opline_num); -#endif - EX(opline) = &op_array->opcodes[EX(opline)->op2.u.opline_num]; - continue; - } - } - NEXT_OPCODE(); - case ZEND_FREE: - zendi_zval_dtor(EX(Ts)[EX(opline)->op1.u.var].tmp_var); - NEXT_OPCODE(); - case ZEND_INIT_STRING: - EX(Ts)[EX(opline)->result.u.var].tmp_var.value.str.val = emalloc(1); - EX(Ts)[EX(opline)->result.u.var].tmp_var.value.str.val[0] = 0; - EX(Ts)[EX(opline)->result.u.var].tmp_var.value.str.len = 0; - EX(Ts)[EX(opline)->result.u.var].tmp_var.refcount = 1; - NEXT_OPCODE(); - case ZEND_ADD_CHAR: - add_char_to_string( &EX(Ts)[EX(opline)->result.u.var].tmp_var, - get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_NA), - &EX(opline)->op2.u.constant); - /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */ - NEXT_OPCODE(); - case ZEND_ADD_STRING: - add_string_to_string( &EX(Ts)[EX(opline)->result.u.var].tmp_var, - get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_NA), - &EX(opline)->op2.u.constant); - /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */ - NEXT_OPCODE(); - case ZEND_ADD_VAR: { - zval *var = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); - zval var_copy; - int use_copy; - - zend_make_printable_zval(var, &var_copy, &use_copy); - if (use_copy) { - var = &var_copy; - } - add_string_to_string( &EX(Ts)[EX(opline)->result.u.var].tmp_var, - get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_NA), - var); - if (use_copy) { - zval_dtor(var); - } - /* original comment, possibly problematic: - * FREE_OP is missing intentionally here - we're always working on the same temporary variable - * (Zeev): I don't think it's problematic, we only use variables - * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're - * string offsets or overloaded objects - */ - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - } - NEXT_OPCODE(); - case ZEND_IMPORT_FUNCTION: - { - zend_class_entry *ce; - zend_function *function; - - ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry; - if (EX(opline)->op2.op_type != IS_UNUSED) { - char *function_name_strval; - int function_name_strlen; +int zend_sl_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + shift_left_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - function_name_strval = EX(opline)->op2.u.constant.value.str.val; - function_name_strlen = EX(opline)->op2.u.constant.value.str.len; - if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen + 1, (void **) &function)==FAILURE) { - zend_error(E_ERROR, "Import: function %s() not found", function_name_strval); - } - if (zend_hash_add(EG(function_table), function_name_strval, function_name_strlen + 1, function, sizeof(zend_function), NULL) == FAILURE) { - zend_error(E_ERROR, "Import: function %s() already exists in current scope", function_name_strval); - } - function_add_ref(function); - } else { - zend_function tmp_zend_function; +int zend_sr_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + shift_right_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - zend_hash_copy(EG(function_table), &ce->function_table, (copy_ctor_func_t) function_add_ref, &tmp_zend_function, sizeof(zend_function)); - } - NEXT_OPCODE(); - } - case ZEND_IMPORT_CLASS: - { - zend_class_entry *ce; - zend_class_entry **import_ce; - - ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry; - if (EX(opline)->op2.op_type != IS_UNUSED) { - char *class_name_strval; - int class_name_strlen; - - class_name_strval = EX(opline)->op2.u.constant.value.str.val; - class_name_strlen = EX(opline)->op2.u.constant.value.str.len; - - if (zend_hash_find(&ce->class_table, class_name_strval, class_name_strlen + 1, (void **) &import_ce)==FAILURE) { - zend_error(E_ERROR, "Import: class %s not found", class_name_strval); - } - if (zend_hash_add(EG(class_table), class_name_strval, class_name_strlen + 1, import_ce, sizeof(zend_class_entry *), NULL) == FAILURE) { - zend_error(E_ERROR, "Import: class %s already exists in current scope", class_name_strval); - } - zend_class_add_ref(import_ce); - } else { - zend_class_entry *tmp_zend_class_entry; +int zend_concat_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + concat_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - zend_hash_copy(EG(class_table), &ce->class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_zend_class_entry, sizeof(zend_class_entry *)); - } - NEXT_OPCODE(); - } - case ZEND_IMPORT_CONST: - { - zend_class_entry *ce; - zval **import_constant; - zend_constant c; - - ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry; - if (EX(opline)->op2.op_type != IS_UNUSED) { - char *const_name_strval; - int const_name_strlen; - - const_name_strval = EX(opline)->op2.u.constant.value.str.val; - const_name_strlen = EX(opline)->op2.u.constant.value.str.len; - - if (zend_hash_find(&ce->constants_table, const_name_strval, const_name_strlen + 1, (void **) &import_constant)==FAILURE) { - zend_error(E_ERROR, "Import: constant %s not found", const_name_strval); - } - c.value = **import_constant; - zval_copy_ctor(&c.value); - c.flags = CONST_CS; - c.name = zend_strndup(const_name_strval, const_name_strlen); - c.name_len = const_name_strlen + 1; +int zend_is_identical_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + is_identical_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - if (zend_register_constant(&c TSRMLS_CC) == FAILURE) { - zend_error(E_ERROR, "Import: unable to register constant %s", const_name_strval); - } - } else { - HashPosition pos; - char *key; - uint key_length; - int key_type; - ulong dummy; - - zend_hash_internal_pointer_reset_ex(&ce->constants_table, &pos); - while(zend_hash_get_current_data_ex(&ce->constants_table, (void **)&import_constant, &pos) == SUCCESS) { - key_type = zend_hash_get_current_key_ex(&ce->constants_table, &key, &key_length, &dummy, 0, &pos); - - c.value = **import_constant; - zval_copy_ctor(&c.value); - c.flags = CONST_CS; - c.name = zend_strndup(key, key_length - 1); - c.name_len = key_length; - if (zend_register_constant(&c TSRMLS_CC) == FAILURE) { - zend_error(E_ERROR, "Import: unable to register constant %s", key); - } - zend_hash_move_forward_ex(&ce->constants_table, &pos); - } - } - NEXT_OPCODE(); - } - case ZEND_FETCH_CLASS: - { - zend_class_entry **pce; - - if (EX(opline)->op1.op_type == IS_UNUSED) { - zval tmp; - zval *class_name; - zend_bool is_const; - char *class_name_strval; - zend_uint class_name_strlen; - - if (EX(opline)->extended_value == ZEND_FETCH_CLASS_SELF) { - if (!EG(scope)) { - zend_error(E_ERROR, "Cannot fetch self:: when no class scope is active"); - } - EX(Ts)[EX(opline)->result.u.var].EA.class_entry = EG(scope); - NEXT_OPCODE(); - } else if (EX(opline)->extended_value == ZEND_FETCH_CLASS_MAIN) { - EX(Ts)[EX(opline)->result.u.var].EA.class_entry = EG(main_class_ptr); - NEXT_OPCODE(); - } else if (EX(opline)->extended_value == ZEND_FETCH_CLASS_PARENT) { - if (!EG(scope)) { - zend_error(E_ERROR, "Cannot fetch parent:: when no class scope is active"); - } - if (!EG(scope)->parent) { - zend_error(E_ERROR, "Cannot fetch parent:: as current class scope has no parent"); - } - EX(Ts)[EX(opline)->result.u.var].EA.class_entry = EG(scope)->parent; - NEXT_OPCODE(); - } - - is_const = (EX(opline)->op2.op_type == IS_CONST); - - if (is_const) { - class_name_strval = EX(opline)->op2.u.constant.value.str.val; - class_name_strlen = EX(opline)->op2.u.constant.value.str.len; - } else { - class_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); +int zend_is_not_identical_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + is_not_identical_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - tmp = *class_name; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - zend_str_tolower(tmp.value.str.val, tmp.value.str.len); - class_name_strval = tmp.value.str.val; - class_name_strlen = tmp.value.str.len; - } - - if (zend_hash_find(EG(class_table), class_name_strval, class_name_strlen+1, (void **) &pce) == FAILURE) { - zend_error(E_ERROR, "Class '%s' not found", class_name_strval); - } else { - EX(Ts)[EX(opline)->result.u.var].EA.class_entry = *pce; - } - if (!is_const) { - zval_dtor(&tmp); - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - } - } else { - if (zend_hash_find(&EX(Ts)[EX(opline)->op1.u.var].EA.class_entry->class_table, EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, (void **)&pce) == FAILURE) { - zend_error(E_ERROR, "Class '%s' not found", EX(opline)->op2.u.constant.value.str.val); - } else { - EX(Ts)[EX(opline)->result.u.var].EA.class_entry = *pce; - } - } - NEXT_OPCODE(); - } - case ZEND_INIT_CTOR_CALL: - { - zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object)); +int zend_is_equal_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + is_equal_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - if (EX(opline)->op1.op_type == IS_VAR) { - SELECTIVE_PZVAL_LOCK(*EX(Ts)[EX(opline)->op1.u.var].var.ptr_ptr, &EX(opline)->op1); - } - /* We are not handling overloaded classes right now */ - EX(object) = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - if (!PZVAL_IS_REF(EX(object))) { - EX(object)->refcount++; /* For $this pointer */ - } else { - zval *this_ptr; +int zend_is_not_equal_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + is_not_equal_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - ALLOC_ZVAL(this_ptr); - *this_ptr = *EX(object); - INIT_PZVAL(this_ptr); - zval_copy_ctor(this_ptr); - EX(object) = this_ptr; - } - EX(fbc) = EX(fbc_constructor); - if(EX(fbc)->type == ZEND_USER_FUNCTION) { /* HACK!! */ - EX(calling_scope) = Z_OBJCE_P(EX(object)); - } else { - EX(calling_scope) = NULL; - } +int zend_is_smaller_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + is_smaller_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - NEXT_OPCODE(); - } - case ZEND_INIT_METHOD_CALL: - { - zval *function_name; - zval tmp; - zend_bool is_const; - char *function_name_strval; - int function_name_strlen; - - zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object)); - is_const = (EX(opline)->op2.op_type == IS_CONST); +int zend_is_smaller_or_equal_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + is_smaller_or_equal_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - if (is_const) { - function_name_strval = EX(opline)->op2.u.constant.value.str.val; - function_name_strlen = EX(opline)->op2.u.constant.value.str.len; - } else { - function_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); - tmp = *function_name; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - function_name = &tmp; - zend_str_tolower(tmp.value.str.val, tmp.value.str.len); +int zend_bw_or_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + bitwise_or_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - function_name_strval = tmp.value.str.val; - function_name_strlen = tmp.value.str.len; - } - - EX(calling_scope) = EG(scope); - if (EX(opline)->extended_value == ZEND_FETCH_FROM_THIS) { - if (!EG(This)) { - zend_error(E_ERROR, "Can't fetch $this as not in object context"); - } - EX(object) = EG(This); - } else { - EX(object) = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - } - - if (EX(object) && EX(object)->type == IS_OBJECT) { - EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(EX(object), function_name_strval, function_name_strlen TSRMLS_CC); - } else { - zend_error(E_ERROR, "Call to a member function on a non-object"); - } - if (!EX(fbc)) { - zend_error(E_ERROR, "Call to undefined function: %s()", function_name_strval); - } +int zend_bw_and_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + bitwise_and_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - if (!PZVAL_IS_REF(EX(object))) { - EX(object)->refcount++; /* For $this pointer */ - } else { - zval *this_ptr; - ALLOC_ZVAL(this_ptr); - *this_ptr = *EX(object); - INIT_PZVAL(this_ptr); - zval_copy_ctor(this_ptr); - EX(object) = this_ptr; - } - if(EX(fbc)->type == ZEND_USER_FUNCTION) { - EX(calling_scope) = Z_OBJCE_P(EX(object)); - } else { - EX(calling_scope) = NULL; - } +int zend_bw_xor_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + bitwise_xor_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - if (!is_const) { - zval_dtor(&tmp); - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - } - - NEXT_OPCODE(); - } - case ZEND_INIT_STATIC_METHOD_CALL: - { - zval *function_name; - zend_function *function; - zval tmp; - zend_class_entry *ce; - zend_bool is_const; - char *function_name_strval; - int function_name_strlen; - - zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object)); - - is_const = (EX(opline)->op2.op_type == IS_CONST); - - if (is_const) { - function_name_strval = EX(opline)->op2.u.constant.value.str.val; - function_name_strlen = EX(opline)->op2.u.constant.value.str.len; - } else { - function_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); - tmp = *function_name; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - zend_str_tolower(tmp.value.str.val, tmp.value.str.len); +int zend_bool_xor_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + boolean_xor_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + NEXT_OPCODE(); +} - function_name_strval = tmp.value.str.val; - function_name_strlen = tmp.value.str.len; - } - - if ((EX(object) = EG(This))) { - EX(object)->refcount++; - } - ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry; +int zend_bw_not_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + bitwise_not_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + NEXT_OPCODE(); +} - EX(calling_scope) = ce; - if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &function)==FAILURE) { - zend_error(E_ERROR, "Call to undefined function: %s()", function_name_strval); - } +int zend_bool_not_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + boolean_not_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R) TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + NEXT_OPCODE(); +} - if (!is_const) { - zval_dtor(&tmp); - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - } - EX(fbc) = function; +inline int zend_binary_assign_op_helper(void *binary_op_arg, ZEND_OPCODE_HANDLER_ARGS) +{ + zval **var_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_RW); + int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC) = binary_op_arg; - NEXT_OPCODE(); - } - case ZEND_INIT_FCALL_BY_NAME: - { - zval *function_name; - zend_function *function; - zval tmp; - zend_bool is_const; - char *function_name_strval; - int function_name_strlen; - - zend_ptr_stack_n_push(&EG(arg_types_stack), 2, EX(fbc), EX(object)); - - is_const = (EX(opline)->op2.op_type == IS_CONST); - - if (is_const) { - function_name_strval = EX(opline)->op2.u.constant.value.str.val; - function_name_strlen = EX(opline)->op2.u.constant.value.str.len; - } else { - function_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + if (!var_ptr) { + zend_error(E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets"); + } - tmp = *function_name; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - zend_str_tolower(tmp.value.str.val, tmp.value.str.len); + if (*var_ptr == EG(error_zval_ptr)) { + EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); + SELECTIVE_PZVAL_LOCK(*EX_T(EX(opline)->result.u.var).var.ptr_ptr, &EX(opline)->result); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + NEXT_OPCODE(); + } + + SEPARATE_ZVAL_IF_NOT_REF(var_ptr); - function_name_strval = tmp.value.str.val; - function_name_strlen = tmp.value.str.len; - } - + binary_op(*var_ptr, *var_ptr, get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + EX_T(EX(opline)->result.u.var).var.ptr_ptr = var_ptr; + SELECTIVE_PZVAL_LOCK(*var_ptr, &EX(opline)->result); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); - do { - if (EG(scope)) { - if (zend_hash_find(&EG(scope)->function_table, function_name_strval, function_name_strlen+1, (void **) &function) == SUCCESS) { - if ((EX(object) = EG(This))) { - EX(object)->refcount++; - } - EX(calling_scope) = EG(scope); - break; - } - } - if (zend_hash_find(EG(function_table), function_name_strval, function_name_strlen+1, (void **) &function)==FAILURE) { - zend_error(E_ERROR, "Call to undefined function: %s()", function_name_strval); - } - EX(calling_scope) = function->common.scope; - EX(object) = NULL; - } while (0); - - if (!is_const) { - zval_dtor(&tmp); - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - } - EX(fbc) = function; + NEXT_OPCODE(); +} - NEXT_OPCODE(); - } - case ZEND_DO_FCALL_BY_NAME: - EX(function_state).function = EX(fbc); - goto do_fcall_common; - case ZEND_DO_FCALL: { - zval *fname = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - - zend_ptr_stack_push(&EG(arg_types_stack), EX(object)); - do { - if (EG(scope)) { - if (zend_hash_find(&EG(scope)->function_table, fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function) == SUCCESS) { - if ((EX(object) = EG(This))) { - EX(object)->refcount++; - } - EX(calling_scope) = EG(scope); - break; - } - } - if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) { - zend_error(E_ERROR, "Unknown function: %s()\n", fname->value.str.val); - } - EX(object) = NULL; - EX(calling_scope) = EX(function_state).function->common.scope; - } while (0); +int zend_assign_add_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper(add_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); - - goto do_fcall_common; - } -do_fcall_common: - { - zval **original_return_value; - zend_class_entry *current_scope; - zval *current_this; - int return_value_used = RETURN_VALUE_USED(EX(opline)); - - zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) EX(opline)->extended_value, NULL); - current_scope = EG(scope); - EG(scope) = EX(calling_scope); - - current_this = EG(This); - EG(This) = EX(object); - - EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr; - - if (EX(function_state).function->type==ZEND_INTERNAL_FUNCTION) { - ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr); - INIT_ZVAL(*(EX(Ts)[EX(opline)->result.u.var].var.ptr)); - ((zend_internal_function *) EX(function_state).function)->handler(EX(opline)->extended_value, EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(object), return_value_used TSRMLS_CC); - EX(Ts)[EX(opline)->result.u.var].var.ptr->is_ref = 0; - EX(Ts)[EX(opline)->result.u.var].var.ptr->refcount = 1; - if (!return_value_used) { - zval_ptr_dtor(&EX(Ts)[EX(opline)->result.u.var].var.ptr); - } - } else if (EX(function_state).function->type==ZEND_USER_FUNCTION) { - HashTable *calling_symbol_table; - EX(Ts)[EX(opline)->result.u.var].var.ptr = NULL; - if (EG(symtable_cache_ptr)>=EG(symtable_cache)) { - /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/ - EX(function_state).function_symbol_table = *(EG(symtable_cache_ptr)--); - } else { - ALLOC_HASHTABLE(EX(function_state).function_symbol_table); - zend_hash_init(EX(function_state).function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0); - /*printf("Cache miss! Initialized %x\n", function_state.function_symbol_table);*/ - } - calling_symbol_table = EG(active_symbol_table); - EG(active_symbol_table) = EX(function_state).function_symbol_table; - original_return_value = EG(return_value_ptr_ptr); - EG(return_value_ptr_ptr) = EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr; - EG(active_op_array) = (zend_op_array *) EX(function_state).function; - - zend_execute(EG(active_op_array) TSRMLS_CC); - - if (return_value_used && !EX(Ts)[EX(opline)->result.u.var].var.ptr) { - if (!EG(exception)) { - ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr); - INIT_ZVAL(*EX(Ts)[EX(opline)->result.u.var].var.ptr); - } - } else if (!return_value_used && EX(Ts)[EX(opline)->result.u.var].var.ptr) { - zval_ptr_dtor(&EX(Ts)[EX(opline)->result.u.var].var.ptr); - } +int zend_assign_sub_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper(sub_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = op_array; - EG(return_value_ptr_ptr)=original_return_value; - if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { - zend_hash_destroy(EX(function_state).function_symbol_table); - FREE_HASHTABLE(EX(function_state).function_symbol_table); - } else { - *(++EG(symtable_cache_ptr)) = EX(function_state).function_symbol_table; - zend_hash_clean(*EG(symtable_cache_ptr)); - } - EG(active_symbol_table) = calling_symbol_table; - } else { /* ZEND_OVERLOADED_FUNCTION */ - ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr); - INIT_ZVAL(*(EX(Ts)[EX(opline)->result.u.var].var.ptr)); - if(EX(object)) { - Z_OBJ_HT_P(EX(object))->call_method(EX(fbc)->common.function_name, EX(opline)->extended_value, EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(object), return_value_used TSRMLS_CC); - } else { - zend_error(E_ERROR, "Cannot call overloaded function for non-object"); - } - - efree(EX(fbc)); - if (!return_value_used) { - zval_ptr_dtor(&EX(Ts)[EX(opline)->result.u.var].var.ptr); - } - } - if (EX(opline)->opcode == ZEND_DO_FCALL_BY_NAME) { - zend_ptr_stack_n_pop(&EG(arg_types_stack), 2, &EX(object), &EX(fbc)); - } else { - EX(object) = zend_ptr_stack_pop(&EG(arg_types_stack)); - } - EX(function_state).function = (zend_function *) op_array; - EG(function_state_ptr) = &EX(function_state); - zend_ptr_stack_clear_multiple(TSRMLS_C); +int zend_assign_mul_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper(mul_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - EG(scope) = current_scope; - if (EG(This)) { - zval_ptr_dtor(&EG(This)); - } +int zend_assign_div_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper(div_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - EG(This) = current_this; - - if (EG(exception)) { - if (EX(opline)->op2.u.opline_num == -1) { - RETURN_FROM_EXECUTE_LOOP(execute_data); - } else { - EX(opline) = &op_array->opcodes[EX(opline)->op2.u.opline_num]; - continue; - } - } - } - NEXT_OPCODE(); - case ZEND_RETURN: { - zval *retval_ptr; - zval **retval_ptr_ptr; - - if ((EG(active_op_array)->return_reference == ZEND_RETURN_REF) && - (EX(opline)->op1.op_type != IS_CONST) && - (EX(opline)->op1.op_type != IS_TMP_VAR)) { - - retval_ptr_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_W); - - SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr); - (*retval_ptr_ptr)->refcount++; - - (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr); - } else { - retval_ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - - if (!EG(free_op1)) { /* Not a temp var */ - if (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0) { - ALLOC_ZVAL(*(EG(return_value_ptr_ptr))); - **EG(return_value_ptr_ptr) = *retval_ptr; - (*EG(return_value_ptr_ptr))->is_ref = 0; - (*EG(return_value_ptr_ptr))->refcount = 1; - zval_copy_ctor(*EG(return_value_ptr_ptr)); - } else { - *EG(return_value_ptr_ptr) = retval_ptr; - retval_ptr->refcount++; - } - } else { - ALLOC_ZVAL(*(EG(return_value_ptr_ptr))); - **EG(return_value_ptr_ptr) = *retval_ptr; - (*EG(return_value_ptr_ptr))->refcount = 1; - (*EG(return_value_ptr_ptr))->is_ref = 0; - } - } - RETURN_FROM_EXECUTE_LOOP(execute_data); - } - break; - case ZEND_THROW: - { - zval *value; - zval *exception; - value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - - if (value->type != IS_OBJECT) { - zend_error(E_ERROR, "Can only throw objects"); - } - /* Not sure if a complete copy is what we want here */ - MAKE_STD_ZVAL(exception); - *exception = *value; - if (!EG(free_op1)) { - zval_copy_ctor(exception); - } - INIT_PZVAL(exception); - EG(exception) = exception; - - if (EX(opline)->op2.u.opline_num == -1) { - RETURN_FROM_EXECUTE_LOOP(execute_data); - } else { - EX(opline) = &op_array->opcodes[EX(opline)->op2.u.opline_num]; - continue; - } - } - NEXT_OPCODE(); - case ZEND_CATCH: - { - zend_class_entry *ce; - - /* Check if this is really an exception, if not, jump over code */ - if (EG(exception) == NULL) { - EX(opline) = &op_array->opcodes[EX(opline)->extended_value]; - continue; - } - ce = Z_OBJCE_P(EG(exception)); - if (ce != EX(Ts)[EX(opline)->op1.u.var].EA.class_entry) { - while (ce->parent) { - if (ce->parent == EX(Ts)[EX(opline)->op1.u.var].EA.class_entry) { - goto exception_should_be_taken; - } - ce = ce->parent; - } - EX(opline) = &op_array->opcodes[EX(opline)->extended_value]; - continue; - } -exception_should_be_taken: - zend_hash_update(EG(active_symbol_table), EX(opline)->op2.u.constant.value.str.val, - EX(opline)->op2.u.constant.value.str.len+1, &EG(exception), sizeof(zval *), (void **) NULL); - EG(exception) = NULL; - NEXT_OPCODE(); - } - case ZEND_SEND_VAL: - if (EX(opline)->extended_value==ZEND_DO_FCALL_BY_NAME - && ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->op2.u.opline_num, EX(fbc), EX(fbc)->common.arg_types)) { - zend_error(E_ERROR, "Cannot pass parameter %d by reference", EX(opline)->op2.u.opline_num); - } - { - zval *valptr; - zval *value; - - value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - - ALLOC_ZVAL(valptr); - *valptr = *value; - if (!EG(free_op1)) { - zval_copy_ctor(valptr); - } - INIT_PZVAL(valptr); - zend_ptr_stack_push(&EG(argument_stack), valptr); - } - NEXT_OPCODE(); - case ZEND_SEND_VAR_NO_REF: - if (EX(opline)->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */ - if (!(EX(opline)->extended_value & ZEND_ARG_SEND_BY_REF)) { - goto send_by_var; - } - } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->op2.u.opline_num, EX(fbc), EX(fbc)->common.arg_types)) { - goto send_by_var; - } - { - zval *varptr; - varptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - - if (varptr != &EG(uninitialized_zval) && (PZVAL_IS_REF(varptr) || varptr->refcount == 1)) { - varptr->is_ref = 1; - varptr->refcount++; - zend_ptr_stack_push(&EG(argument_stack), varptr); - NEXT_OPCODE(); - } - zend_error(E_ERROR, "Only variables can be passed by reference"); - } - NEXT_OPCODE(); - case ZEND_SEND_VAR: - if ((EX(opline)->extended_value == ZEND_DO_FCALL_BY_NAME) - && ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->op2.u.opline_num, EX(fbc), EX(fbc)->common.arg_types)) { - goto send_by_ref; - } -send_by_var: - { - zval *varptr; - varptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); +int zend_assign_mod_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper(mod_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - if (varptr == &EG(uninitialized_zval)) { - ALLOC_ZVAL(varptr); - INIT_ZVAL(*varptr); - varptr->refcount = 0; - } else if (PZVAL_IS_REF(varptr)) { - zval *original_var = varptr; - - ALLOC_ZVAL(varptr); - *varptr = *original_var; - varptr->is_ref = 0; - varptr->refcount = 0; - zval_copy_ctor(varptr); - } - varptr->refcount++; - zend_ptr_stack_push(&EG(argument_stack), varptr); - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); /* for string offsets */ - } - NEXT_OPCODE(); -send_by_ref: - case ZEND_SEND_REF: { - zval **varptr_ptr; - zval *varptr; - varptr_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_W); - if (!varptr_ptr) { - zend_error(E_ERROR, "Only variables can be passed by reference"); - } +int zend_assign_sl_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper(shift_left_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr_ptr); - varptr = *varptr_ptr; - varptr->refcount++; - zend_ptr_stack_push(&EG(argument_stack), varptr); - } - NEXT_OPCODE(); - case ZEND_RECV: { - zval **param; - if (zend_ptr_stack_get_arg(EX(opline)->op1.u.constant.value.lval, (void **) ¶m TSRMLS_CC)==FAILURE) { - zend_error(E_WARNING, "Missing argument %d for %s()\n", EX(opline)->op1.u.constant.value.lval, get_active_function_name(TSRMLS_C)); - if (EX(opline)->result.op_type == IS_VAR) { - PZVAL_UNLOCK(*EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr); - } - } else if (PZVAL_IS_REF(*param)) { - zend_assign_to_variable_reference(NULL, get_zval_ptr_ptr(&EX(opline)->result, EX(Ts), BP_VAR_W), param, NULL TSRMLS_CC); - } else { - zend_assign_to_variable(NULL, &EX(opline)->result, NULL, *param, IS_VAR, EX(Ts) TSRMLS_CC); - } - } - NEXT_OPCODE(); - case ZEND_RECV_INIT: { - zval **param, *assignment_value; +int zend_assign_sr_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper(shift_right_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - if (zend_ptr_stack_get_arg(EX(opline)->op1.u.constant.value.lval, (void **) ¶m TSRMLS_CC)==FAILURE) { - if (EX(opline)->op2.u.constant.type == IS_CONSTANT || EX(opline)->op2.u.constant.type==IS_CONSTANT_ARRAY) { - zval *default_value; - - ALLOC_ZVAL(default_value); - *default_value = EX(opline)->op2.u.constant; - if (EX(opline)->op2.u.constant.type==IS_CONSTANT_ARRAY) { - zval_copy_ctor(default_value); - } - default_value->refcount=1; - zval_update_constant(&default_value, 0 TSRMLS_CC); - default_value->refcount=0; - default_value->is_ref=0; - param = &default_value; - assignment_value = default_value; - } else { - param = NULL; - assignment_value = &EX(opline)->op2.u.constant; - } - zend_assign_to_variable(NULL, &EX(opline)->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC); - } else { - assignment_value = *param; - if (PZVAL_IS_REF(assignment_value)) { - zend_assign_to_variable_reference(NULL, get_zval_ptr_ptr(&EX(opline)->result, EX(Ts), BP_VAR_W), param, NULL TSRMLS_CC); - } else { - zend_assign_to_variable(NULL, &EX(opline)->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC); - } - } - } - NEXT_OPCODE(); - case ZEND_BOOL: - /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ - EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = zend_is_true(get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R)); - EX(Ts)[EX(opline)->result.u.var].tmp_var.type = IS_BOOL; - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); - NEXT_OPCODE(); - case ZEND_BRK: - case ZEND_CONT: { - zval *nest_levels_zval = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); - zval tmp; - int array_offset, nest_levels, original_nest_levels; - zend_brk_cont_element *jmp_to; - if (nest_levels_zval->type != IS_LONG) { - tmp = *nest_levels_zval; - zval_copy_ctor(&tmp); - convert_to_long(&tmp); - nest_levels = tmp.value.lval; - } else { - nest_levels = nest_levels_zval->value.lval; - } - original_nest_levels = nest_levels; - array_offset = EX(opline)->op1.u.opline_num; - do { - if (array_offset==-1) { - zend_error(E_ERROR, "Cannot break/continue %d level%s", original_nest_levels, (original_nest_levels == 1) ? "" : "s"); - } - jmp_to = &op_array->brk_cont_array[array_offset]; - if (nest_levels>1) { - zend_op *brk_opline = &op_array->opcodes[jmp_to->brk]; - - switch (brk_opline->opcode) { - case ZEND_SWITCH_FREE: - zend_switch_free(brk_opline, EX(Ts) TSRMLS_CC); - break; - case ZEND_FREE: - zendi_zval_dtor(EX(Ts)[brk_opline->op1.u.var].tmp_var); - break; - } - } - array_offset = jmp_to->parent; - } while (--nest_levels > 0); +int zend_assign_concat_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper(concat_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - if (EX(opline)->opcode == ZEND_BRK) { - EX(opline) = op_array->opcodes+jmp_to->brk; - } else { - EX(opline) = op_array->opcodes+jmp_to->cont; - } - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - continue; - } - /* Never reaches this point */ - case ZEND_CASE: { - int switch_expr_is_overloaded=0; - - if (EX(opline)->op1.op_type==IS_VAR) { - if (EX(Ts)[EX(opline)->op1.u.var].var.ptr_ptr) { - PZVAL_LOCK(*EX(Ts)[EX(opline)->op1.u.var].var.ptr_ptr); - } else { - switch_expr_is_overloaded = 1; - if (EX(Ts)[EX(opline)->op1.u.var].EA.type==IS_STRING_OFFSET) { - EX(Ts)[EX(opline)->op1.u.var].EA.data.str_offset.str->refcount++; - } - } - } - is_equal_function(&EX(Ts)[EX(opline)->result.u.var].tmp_var, - get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), - get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); - - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - if (switch_expr_is_overloaded) { - /* We only free op1 if this is a string offset, - * Since if it is a TMP_VAR, it'll be reused by - * other CASE opcodes (whereas string offsets - * are allocated at each get_zval_ptr()) - */ - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); - EX(Ts)[EX(opline)->op1.u.var].var.ptr_ptr = NULL; - AI_USE_PTR(EX(Ts)[EX(opline)->op1.u.var].var); - } - } - NEXT_OPCODE(); - case ZEND_SWITCH_FREE: - zend_switch_free(EX(opline), EX(Ts) TSRMLS_CC); - NEXT_OPCODE(); - case ZEND_NEW: - { - EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr; - ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr); - object_init_ex(EX(Ts)[EX(opline)->result.u.var].var.ptr, EX(Ts)[EX(opline)->op1.u.var].EA.class_entry); - EX(Ts)[EX(opline)->result.u.var].var.ptr->refcount=1; - EX(Ts)[EX(opline)->result.u.var].var.ptr->is_ref=1; - } - NEXT_OPCODE(); - case ZEND_CLONE: - { - zval *obj = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - - EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr; - ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr); - EX(Ts)[EX(opline)->result.u.var].var.ptr->value.obj = Z_OBJ_HT_P(obj)->clone_obj(obj TSRMLS_CC); - EX(Ts)[EX(opline)->result.u.var].var.ptr->type = IS_OBJECT; - EX(Ts)[EX(opline)->result.u.var].var.ptr->refcount=1; - EX(Ts)[EX(opline)->result.u.var].var.ptr->is_ref=1; - NEXT_OPCODE(); - } - case ZEND_FETCH_CONSTANT: - { - zend_class_entry *ce; - zval **value; - - if (EX(opline)->op1.op_type == IS_UNUSED) { - if (EG(scope)) { - ce = EG(scope); - if (zend_hash_find(&ce->constants_table, EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) { - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EX(Ts)[EX(opline)->result.u.var].tmp_var = **value; - zval_copy_ctor(&EX(Ts)[EX(opline)->result.u.var].tmp_var); - NEXT_OPCODE(); - } - } - if (!zend_get_constant(EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len, &EX(Ts)[EX(opline)->result.u.var].tmp_var TSRMLS_CC)) { - zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", - EX(opline)->op2.u.constant.value.str.val, - EX(opline)->op2.u.constant.value.str.val); - EX(Ts)[EX(opline)->result.u.var].tmp_var = EX(opline)->op2.u.constant; - zval_copy_ctor(&EX(Ts)[EX(opline)->result.u.var].tmp_var); - } - NEXT_OPCODE(); - } - - ce = EX(Ts)[EX(opline)->op1.u.var].EA.class_entry; - - if (&ce->constants_table == &EG(main_class_ptr)->constants_table) { - if (!zend_get_constant(EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len, &EX(Ts)[EX(opline)->result.u.var].tmp_var TSRMLS_CC)) { - zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", - EX(opline)->op2.u.constant.value.str.val, - EX(opline)->op2.u.constant.value.str.val); - EX(Ts)[EX(opline)->result.u.var].tmp_var = EX(opline)->op2.u.constant; - zval_copy_ctor(&EX(Ts)[EX(opline)->result.u.var].tmp_var); - } - NEXT_OPCODE(); - } - if (zend_hash_find(&ce->constants_table, EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) { - zval_update_constant(value, (void *) 1 TSRMLS_CC); - EX(Ts)[EX(opline)->result.u.var].tmp_var = **value; - zval_copy_ctor(&EX(Ts)[EX(opline)->result.u.var].tmp_var); - } else { - zend_error(E_ERROR, "Undefined constant. Improve this error message"); - } - } - NEXT_OPCODE(); - case ZEND_INIT_ARRAY: - case ZEND_ADD_ARRAY_ELEMENT: { - zval *array_ptr = &EX(Ts)[EX(opline)->result.u.var].tmp_var; - zval *expr_ptr, **expr_ptr_ptr = NULL; - zval *offset=get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); - - if (EX(opline)->extended_value) { - expr_ptr_ptr=get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_R); - expr_ptr = *expr_ptr_ptr; - } else { - expr_ptr=get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - } - - if (EX(opline)->opcode==ZEND_INIT_ARRAY) { - array_init(array_ptr); - if (!expr_ptr) { - NEXT_OPCODE(); - } - } - if (!EX(opline)->extended_value && EG(free_op1)) { /* temporary variable */ - zval *new_expr; - ALLOC_ZVAL(new_expr); - *new_expr = *expr_ptr; - expr_ptr = new_expr; - INIT_PZVAL(expr_ptr); - } else { - if (EX(opline)->extended_value) { - SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr); - expr_ptr = *expr_ptr_ptr; - expr_ptr->refcount++; - } else if (PZVAL_IS_REF(expr_ptr)) { - zval *new_expr; - - ALLOC_ZVAL(new_expr); - *new_expr = *expr_ptr; - expr_ptr = new_expr; - zendi_zval_copy_ctor(*expr_ptr); - INIT_PZVAL(expr_ptr); - } else { - expr_ptr->refcount++; - } - } - if (offset) { - switch(offset->type) { - case IS_DOUBLE: - zend_hash_index_update(array_ptr->value.ht, (long) offset->value.dval, &expr_ptr, sizeof(zval *), NULL); - break; - case IS_LONG: - zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL); - break; - case IS_STRING: - zend_hash_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL); - break; - case IS_NULL: - zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL); - break; - default: - zval_ptr_dtor(&expr_ptr); - /* do nothing */ - break; - } - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - } else { - zend_hash_next_index_insert(array_ptr->value.ht, &expr_ptr, sizeof(zval *), NULL); - } - } - NEXT_OPCODE(); - case ZEND_CAST: { - zval *expr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - zval *result = &EX(Ts)[EX(opline)->result.u.var].tmp_var; - - *result = *expr; - if (!EG(free_op1)) { - zendi_zval_copy_ctor(*result); - } - switch (EX(opline)->extended_value) { - case IS_NULL: - convert_to_null(result); - break; - case IS_BOOL: - convert_to_boolean(result); - break; - case IS_LONG: - convert_to_long(result); - break; - case IS_DOUBLE: - convert_to_double(result); - break; - case IS_STRING: - convert_to_string(result); - break; - case IS_ARRAY: - convert_to_array(result); - break; - case IS_OBJECT: - convert_to_object(result); - break; - } - } - NEXT_OPCODE(); - case ZEND_INCLUDE_OR_EVAL: { - zend_op_array *new_op_array=NULL; - zval **original_return_value = EG(return_value_ptr_ptr); - int return_value_used; - zval *inc_filename = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - zval tmp_inc_filename; - zend_bool failure_retval=0; - - if (inc_filename->type!=IS_STRING) { - tmp_inc_filename = *inc_filename; - zval_copy_ctor(&tmp_inc_filename); - convert_to_string(&tmp_inc_filename); - inc_filename = &tmp_inc_filename; - } - - return_value_used = RETURN_VALUE_USED(EX(opline)); +int zend_assign_bw_or_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper(bitwise_or_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} - switch (EX(opline)->op2.u.constant.value.lval) { - case ZEND_INCLUDE_ONCE: - case ZEND_REQUIRE_ONCE: { - char *opened_path=NULL; - int dummy = 1; - zend_file_handle file_handle; - - file_handle.handle.fp = zend_fopen(inc_filename->value.str.val, &opened_path); - file_handle.type = ZEND_HANDLE_FP; - file_handle.filename = inc_filename->value.str.val; - file_handle.opened_path = opened_path; - file_handle.free_filename = 0; - - if (file_handle.handle.fp) { - if (!opened_path || zend_hash_add(&EG(included_files), opened_path, strlen(opened_path)+1, (void *)&dummy, sizeof(int), NULL)==SUCCESS) { - new_op_array = zend_compile_file(&file_handle, (EX(opline)->op2.u.constant.value.lval==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC); - zend_destroy_file_handle(&file_handle TSRMLS_CC); - opened_path = NULL; /* zend_destroy_file_handle() already frees it */ - } else { - fclose(file_handle.handle.fp); - failure_retval=1; - } - } else { - if (EX(opline)->op2.u.constant.value.lval==ZEND_INCLUDE_ONCE) { - zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle.filename); - } else { - zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle.filename); - } - } - if (opened_path) { - efree(opened_path); - } - break; - } - break; - case ZEND_INCLUDE: - case ZEND_REQUIRE: - new_op_array = compile_filename(EX(opline)->op2.u.constant.value.lval, inc_filename TSRMLS_CC); - break; - case ZEND_EVAL: { - char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); - new_op_array = compile_string(inc_filename, eval_desc TSRMLS_CC); - efree(eval_desc); - } - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - if (inc_filename==&tmp_inc_filename) { - zval_dtor(&tmp_inc_filename); - } - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); - EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr; - if (new_op_array) { - zval *saved_object; - zend_function *saved_function; - - - EG(return_value_ptr_ptr) = EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr; - EG(active_op_array) = new_op_array; - EX(Ts)[EX(opline)->result.u.var].var.ptr = NULL; - - saved_object = EX(object); - saved_function = EX(function_state).function; - - EX(function_state).function = (zend_function *) new_op_array; - EX(object) = NULL; - - zend_execute(new_op_array TSRMLS_CC); - - EX(function_state).function = saved_function; - EX(object) = saved_object; - - if (!return_value_used) { - if (EX(Ts)[EX(opline)->result.u.var].var.ptr) { - zval_ptr_dtor(&EX(Ts)[EX(opline)->result.u.var].var.ptr); - } - } else { /* return value is used */ - if (!EX(Ts)[EX(opline)->result.u.var].var.ptr) { /* there was no return statement */ - ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr); - INIT_PZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr); - EX(Ts)[EX(opline)->result.u.var].var.ptr->value.lval = 1; - EX(Ts)[EX(opline)->result.u.var].var.ptr->type = IS_BOOL; - } - } +int zend_assign_bw_and_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper(bitwise_and_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_assign_bw_xor_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_binary_assign_op_helper(bitwise_xor_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_assign_add_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *op_data = EX(opline)+1; + zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, &op_data->op1, EX(Ts), add_function TSRMLS_CC); + /* assign_obj has two opcodes! */ + EX(opline)++; + NEXT_OPCODE(); +} + + +int zend_assign_sub_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *op_data = EX(opline)+1; + zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, &op_data->op1, EX(Ts), sub_function TSRMLS_CC); + /* assign_obj has two opcodes! */ + EX(opline)++; + NEXT_OPCODE(); +} + + +int zend_assign_mul_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *op_data = EX(opline)+1; + zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, &op_data->op1, EX(Ts), mul_function TSRMLS_CC); + /* assign_obj has two opcodes! */ + EX(opline)++; + NEXT_OPCODE(); +} + + +int zend_assign_div_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *op_data = EX(opline)+1; + zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, &op_data->op1, EX(Ts), div_function TSRMLS_CC); + /* assign_obj has two opcodes! */ + EX(opline)++; + NEXT_OPCODE(); +} + + +int zend_assign_mod_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *op_data = EX(opline)+1; + zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, &op_data->op1, EX(Ts), mod_function TSRMLS_CC); + /* assign_obj has two opcodes! */ + EX(opline)++; + NEXT_OPCODE(); +} + + +int zend_assign_sl_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *op_data = EX(opline)+1; + zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, &op_data->op1, EX(Ts), shift_left_function TSRMLS_CC); + /* assign_obj has two opcodes! */ + EX(opline)++; + NEXT_OPCODE(); +} + + +int zend_assign_sr_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *op_data = EX(opline)+1; + zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, &op_data->op1, EX(Ts), shift_right_function TSRMLS_CC); + /* assign_obj has two opcodes! */ + EX(opline)++; + NEXT_OPCODE(); +} + + +int zend_assign_concat_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *op_data = EX(opline)+1; + zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, &op_data->op1, EX(Ts), concat_function TSRMLS_CC); + /* assign_obj has two opcodes! */ + EX(opline)++; + NEXT_OPCODE(); +} + + +int zend_assign_bw_or_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *op_data = EX(opline)+1; + zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, &op_data->op1, EX(Ts), bitwise_or_function TSRMLS_CC); + /* assign_obj has two opcodes! */ + EX(opline)++; + NEXT_OPCODE(); +} + + +int zend_assign_bw_and_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *op_data = EX(opline)+1; + zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, &op_data->op1, EX(Ts), bitwise_and_function TSRMLS_CC); + /* assign_obj has two opcodes! */ + EX(opline)++; + NEXT_OPCODE(); +} + + +int zend_assign_bw_xor_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *op_data = EX(opline)+1; + zend_assign_to_object_op(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, &op_data->op1, EX(Ts), bitwise_xor_function TSRMLS_CC); + /* assign_obj has two opcodes! */ + EX(opline)++; + NEXT_OPCODE(); +} + + +int zend_pre_inc_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_pre_incdec_property(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), increment_function TSRMLS_CC); + NEXT_OPCODE(); +} + + +int zend_pre_dec_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_pre_incdec_property(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), decrement_function TSRMLS_CC); + NEXT_OPCODE(); +} + + +int zend_post_inc_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_post_incdec_property(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), increment_function TSRMLS_CC); + NEXT_OPCODE(); +} + + +int zend_post_dec_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_post_incdec_property(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), decrement_function TSRMLS_CC); + NEXT_OPCODE(); +} + + +inline int zend_incdec_op_helper(void *incdec_op_arg, ZEND_OPCODE_HANDLER_ARGS) +{ + zval **var_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_RW); + int (*incdec_op)(zval *op1) = incdec_op_arg; + + if (!var_ptr) { + zend_error(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (*var_ptr == EG(error_zval_ptr)) { + EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EG(uninitialized_zval_ptr); + SELECTIVE_PZVAL_LOCK(*EX_T(EX(opline)->result.u.var).var.ptr_ptr, &EX(opline)->result); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + NEXT_OPCODE(); + } + + switch (EX(opline)->opcode) { + case ZEND_POST_INC: + case ZEND_POST_DEC: + EX_T(EX(opline)->result.u.var).tmp_var = **var_ptr; + zendi_zval_copy_ctor(EX_T(EX(opline)->result.u.var).tmp_var); + break; + } + + SEPARATE_ZVAL_IF_NOT_REF(var_ptr); + + incdec_op(*var_ptr); + + switch (EX(opline)->opcode) { + case ZEND_PRE_INC: + case ZEND_PRE_DEC: + EX_T(EX(opline)->result.u.var).var.ptr_ptr = var_ptr; + SELECTIVE_PZVAL_LOCK(*var_ptr, &EX(opline)->result); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + break; + } + NEXT_OPCODE(); +} + + +int zend_pre_inc_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_incdec_op_helper(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_pre_dec_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_incdec_op_helper(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_post_inc_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_incdec_op_helper(increment_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_post_dec_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_incdec_op_helper(decrement_function, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_print_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_print_variable(get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R)); + EX_T(EX(opline)->result.u.var).tmp_var.value.lval = 1; + EX_T(EX(opline)->result.u.var).tmp_var.type = IS_LONG; + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + NEXT_OPCODE(); +} + + +int zend_echo_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_print_variable(get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R)); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + NEXT_OPCODE(); +} + + +int zend_fetch_r_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_R TSRMLS_CC); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + NEXT_OPCODE(); +} + + +int zend_fetch_w_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_W TSRMLS_CC); + NEXT_OPCODE(); +} + + +int zend_fetch_rw_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_RW TSRMLS_CC); + NEXT_OPCODE(); +} + + +int zend_fetch_func_arg_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if (ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->extended_value, EX(fbc), EX(fbc)->common.arg_types)) { + /* Behave like FETCH_W */ + zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_W TSRMLS_CC); + } else { + /* Behave like FETCH_R */ + zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_R TSRMLS_CC); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + } + NEXT_OPCODE(); +} + + +int zend_fetch_unset_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_R TSRMLS_CC); + PZVAL_UNLOCK(*EX_T(EX(opline)->result.u.var).var.ptr_ptr); + if (EX_T(EX(opline)->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) { + SEPARATE_ZVAL_IF_NOT_REF(EX_T(EX(opline)->result.u.var).var.ptr_ptr); + } + PZVAL_LOCK(*EX_T(EX(opline)->result.u.var).var.ptr_ptr); + NEXT_OPCODE(); +} + + +int zend_fetch_is_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_var_address(EX(opline), EX(Ts), BP_VAR_IS TSRMLS_CC); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + NEXT_OPCODE(); +} + + +int zend_fetch_dim_r_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if (EX(opline)->extended_value == ZEND_FETCH_ADD_LOCK) { + PZVAL_LOCK(*EX_T(EX(opline)->op1.u.var).var.ptr_ptr); + } + zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + NEXT_OPCODE(); +} + + +int zend_fetch_dim_w_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_W TSRMLS_CC); + NEXT_OPCODE(); +} + + +int zend_fetch_dim_rw_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_RW TSRMLS_CC); + NEXT_OPCODE(); +} + + +int zend_fetch_dim_is_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_IS TSRMLS_CC); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + NEXT_OPCODE(); +} + + +int zend_fetch_dim_func_arg_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if (ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->extended_value, EX(fbc), EX(fbc)->common.arg_types)) { + /* Behave like FETCH_DIM_W */ + zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_W TSRMLS_CC); + } else { + /* Behave like FETCH_DIM_R, except for locking used for list() */ + zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + } + NEXT_OPCODE(); +} + + +int zend_fetch_dim_unset_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + /* Not needed in DIM_UNSET + if (EX(opline)->extended_value == ZEND_FETCH_ADD_LOCK) { + PZVAL_LOCK(*EX_T(EX(opline)->op1.u.var).var.ptr_ptr); + } + */ + zend_fetch_dimension_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + PZVAL_UNLOCK(*EX_T(EX(opline)->result.u.var).var.ptr_ptr); + if (EX_T(EX(opline)->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) { + SEPARATE_ZVAL_IF_NOT_REF(EX_T(EX(opline)->result.u.var).var.ptr_ptr); + } + PZVAL_LOCK(*EX_T(EX(opline)->result.u.var).var.ptr_ptr); + NEXT_OPCODE(); +} + + +int zend_fetch_obj_r_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_property_address_read(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + NEXT_OPCODE(); +} + + +int zend_fetch_obj_w_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_property_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_W TSRMLS_CC); + NEXT_OPCODE(); +} + + +int zend_fetch_obj_rw_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_property_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_RW TSRMLS_CC); + NEXT_OPCODE(); +} + + +int zend_fetch_obj_is_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_property_address_read(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_IS TSRMLS_CC); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + NEXT_OPCODE(); +} + + +int zend_fetch_obj_func_arg_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if (ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->extended_value, EX(fbc), EX(fbc)->common.arg_types)) { + /* Behave like FETCH_OBJ_W */ + zend_fetch_property_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_W TSRMLS_CC); + } else { + zend_fetch_property_address_read(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + } + NEXT_OPCODE(); +} + + +int zend_fetch_obj_unset_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_property_address(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts), BP_VAR_R TSRMLS_CC); + + PZVAL_UNLOCK(*EX_T(EX(opline)->result.u.var).var.ptr_ptr); + if (EX_T(EX(opline)->result.u.var).var.ptr_ptr != &EG(uninitialized_zval_ptr)) { + SEPARATE_ZVAL_IF_NOT_REF(EX_T(EX(opline)->result.u.var).var.ptr_ptr); + } + PZVAL_LOCK(*EX_T(EX(opline)->result.u.var).var.ptr_ptr); + NEXT_OPCODE(); +} + + +int zend_fetch_dim_tmp_var_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_fetch_dimension_address_from_tmp_var(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, EX(Ts) TSRMLS_CC); + AI_USE_PTR(EX_T(EX(opline)->result.u.var).var); + NEXT_OPCODE(); +} + + +int zend_make_var_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *value, *value2; + + value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + switch (EX(opline)->op1.op_type) { + case IS_TMP_VAR: + value2 = value; + ALLOC_ZVAL(value); + *value = *value2; + value->is_ref = 0; + value->refcount = 0; /* lock will increase this */ + break; + case IS_CONST: + value2 = value; + ALLOC_ZVAL(value); + *value = *value2; + zval_copy_ctor(value); + value->is_ref = 0; + value->refcount = 0; /* lock will increase this */ + break; + } + + EX_T(EX(opline)->result.u.var).var.ptr = value; + PZVAL_LOCK(EX_T(EX(opline)->result.u.var).var.ptr); + + NEXT_OPCODE(); +} + + +int zend_assign_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *op_data = EX(opline)+1; + zend_assign_to_object(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, &op_data->op1, EX(Ts) TSRMLS_CC); + /* assign_obj has two opcodes! */ + EX(opline)++; + NEXT_OPCODE(); +} + + +int zend_assign_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *value; + value = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + + zend_assign_to_variable(&EX(opline)->result, &EX(opline)->op1, &EX(opline)->op2, value, (EG(free_op2)?IS_TMP_VAR:EX(opline)->op2.op_type), EX(Ts) TSRMLS_CC); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + + NEXT_OPCODE(); +} + + +int zend_assign_ref_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval **value_ptr_ptr = get_zval_ptr_ptr(&EX(opline)->op2, EX(Ts), BP_VAR_W); + + zend_assign_to_variable_reference(&EX(opline)->result, get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_W), value_ptr_ptr, EX(Ts) TSRMLS_CC); + + NEXT_OPCODE(); +} + + +int zend_jmp_handler(ZEND_OPCODE_HANDLER_ARGS) +{ +#if DEBUG_ZEND>=2 + printf("Jumping to %d\n", EX(opline)->op1.u.opline_num); +#endif + EX(opline) = EX(opline)->op1.u.jmp_addr; + return 0; /* CHECK_ME */ +} + + +int zend_jmpz_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + znode *op1 = &EX(opline)->op1; + + if (!i_zend_is_true(get_zval_ptr(op1, EX(Ts), &EG(free_op1), BP_VAR_R))) { +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", EX(opline)->op2.u.opline_num); +#endif + EX(opline) = EX(opline)->op2.u.jmp_addr; + FREE_OP(EX(Ts), op1, EG(free_op1)); + return 0; /* CHECK_ME */ + } + FREE_OP(EX(Ts), op1, EG(free_op1)); + + NEXT_OPCODE(); +} + + +int zend_jmpnz_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + znode *op1 = &EX(opline)->op1; + + if (zend_is_true(get_zval_ptr(op1, EX(Ts), &EG(free_op1), BP_VAR_R))) { +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", EX(opline)->op2.u.opline_num); +#endif + EX(opline) = EX(opline)->op2.u.jmp_addr; + FREE_OP(EX(Ts), op1, EG(free_op1)); + return 0; /* CHECK_ME */ + } + FREE_OP(EX(Ts), op1, EG(free_op1)); + + NEXT_OPCODE(); +} + + +int zend_jmpznz_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + znode *res = &EX(opline)->op1; + + if (zend_is_true(get_zval_ptr(res, EX(Ts), &EG(free_op1), BP_VAR_R))) { +#if DEBUG_ZEND>=2 + printf("Conditional jmp on true to %d\n", EX(opline)->extended_value); +#endif + EX(opline) = &op_array->opcodes[EX(opline)->extended_value]; + } else { +#if DEBUG_ZEND>=2 + printf("Conditional jmp on false to %d\n", EX(opline)->op2.u.opline_num); +#endif + EX(opline) = &op_array->opcodes[EX(opline)->op2.u.opline_num]; + } + FREE_OP(EX(Ts), res, EG(free_op1)); + + return 0; /* CHECK_ME */ +} + + +int zend_jmpz_ex_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *original_opline = EX(opline); + int retval = zend_is_true(get_zval_ptr(&original_opline->op1, EX(Ts), &EG(free_op1), BP_VAR_R)); + + FREE_OP(EX(Ts), &original_opline->op1, EG(free_op1)); + EX_T(original_opline->result.u.var).tmp_var.value.lval = retval; + EX_T(original_opline->result.u.var).tmp_var.type = IS_BOOL; + if (!retval) { +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", EX(opline)->op2.u.opline_num); +#endif + EX(opline) = EX(opline)->op2.u.jmp_addr; + return 0; /* CHECK_ME */ + } + NEXT_OPCODE(); +} + + +int zend_jmpnz_ex_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op *original_opline = EX(opline); + int retval = zend_is_true(get_zval_ptr(&original_opline->op1, EX(Ts), &EG(free_op1), BP_VAR_R)); + + FREE_OP(EX(Ts), &original_opline->op1, EG(free_op1)); + EX_T(original_opline->result.u.var).tmp_var.value.lval = retval; + EX_T(original_opline->result.u.var).tmp_var.type = IS_BOOL; + if (retval) { +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", EX(opline)->op2.u.opline_num); +#endif + EX(opline) = EX(opline)->op2.u.jmp_addr; + return 0; /* CHECK_ME */ + } + NEXT_OPCODE(); +} + + +int zend_free_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zendi_zval_dtor(EX_T(EX(opline)->op1.u.var).tmp_var); + NEXT_OPCODE(); +} + + +int zend_init_string_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + EX_T(EX(opline)->result.u.var).tmp_var.value.str.val = emalloc(1); + EX_T(EX(opline)->result.u.var).tmp_var.value.str.val[0] = 0; + EX_T(EX(opline)->result.u.var).tmp_var.value.str.len = 0; + EX_T(EX(opline)->result.u.var).tmp_var.refcount = 1; + EX_T(EX(opline)->result.u.var).tmp_var.type = IS_STRING; + EX_T(EX(opline)->result.u.var).tmp_var.is_ref = 0; + NEXT_OPCODE(); +} + + +int zend_add_char_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + add_char_to_string(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_NA), + &EX(opline)->op2.u.constant); + /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */ + NEXT_OPCODE(); +} + + +int zend_add_string_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + add_string_to_string(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_NA), + &EX(opline)->op2.u.constant); + /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */ + NEXT_OPCODE(); +} + + +int zend_add_var_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *var = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + zval var_copy; + int use_copy; + + zend_make_printable_zval(var, &var_copy, &use_copy); + if (use_copy) { + var = &var_copy; + } + add_string_to_string( &EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_NA), + var); + if (use_copy) { + zval_dtor(var); + } + /* original comment, possibly problematic: + * FREE_OP is missing intentionally here - we're always working on the same temporary variable + * (Zeev): I don't think it's problematic, we only use variables + * which aren't affected by FREE_OP(Ts, )'s anyway, unless they're + * string offsets or overloaded objects + */ + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + + NEXT_OPCODE(); +} + + +int zend_import_function_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry *ce; + zend_function *function; + + ce = EX_T(EX(opline)->op1.u.var).EA.class_entry; + + if (EX(opline)->op2.op_type != IS_UNUSED) { + char *function_name_strval; + int function_name_strlen; + + function_name_strval = EX(opline)->op2.u.constant.value.str.val; + function_name_strlen = EX(opline)->op2.u.constant.value.str.len; + + if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen + 1, (void **) &function)==FAILURE) { + zend_error(E_ERROR, "Import: function %s() not found", function_name_strval); + } + if (zend_hash_add(EG(function_table), function_name_strval, function_name_strlen + 1, function, sizeof(zend_function), NULL) == FAILURE) { + zend_error(E_ERROR, "Import: function %s() already exists in current scope", function_name_strval); + } + function_add_ref(function); + } else { + zend_function tmp_zend_function; + + zend_hash_copy(EG(function_table), &ce->function_table, (copy_ctor_func_t) function_add_ref, &tmp_zend_function, sizeof(zend_function)); + } + NEXT_OPCODE(); +} + + +int zend_import_class_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry *ce; + zend_class_entry **import_ce; + + ce = EX_T(EX(opline)->op1.u.var).EA.class_entry; + + if (EX(opline)->op2.op_type != IS_UNUSED) { + char *class_name_strval; + int class_name_strlen; + + class_name_strval = EX(opline)->op2.u.constant.value.str.val; + class_name_strlen = EX(opline)->op2.u.constant.value.str.len; + + if (zend_hash_find(&ce->class_table, class_name_strval, class_name_strlen + 1, (void **) &import_ce)==FAILURE) { + zend_error(E_ERROR, "Import: class %s not found", class_name_strval); + } + if (zend_hash_add(EG(class_table), class_name_strval, class_name_strlen + 1, import_ce, sizeof(zend_class_entry *), NULL) == FAILURE) { + zend_error(E_ERROR, "Import: class %s already exists in current scope", class_name_strval); + } + zend_class_add_ref(import_ce); + } else { + zend_class_entry *tmp_zend_class_entry; + + zend_hash_copy(EG(class_table), &ce->class_table, (copy_ctor_func_t) zend_class_add_ref, &tmp_zend_class_entry, sizeof(zend_class_entry *)); + } + + NEXT_OPCODE(); +} + + +int zend_import_const_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry *ce; + zval **import_constant; + zend_constant c; + + ce = EX_T(EX(opline)->op1.u.var).EA.class_entry; + if (EX(opline)->op2.op_type != IS_UNUSED) { + char *const_name_strval; + int const_name_strlen; + + const_name_strval = EX(opline)->op2.u.constant.value.str.val; + const_name_strlen = EX(opline)->op2.u.constant.value.str.len; + + if (zend_hash_find(&ce->constants_table, const_name_strval, const_name_strlen + 1, (void **) &import_constant)==FAILURE) { + zend_error(E_ERROR, "Import: constant %s not found", const_name_strval); + } + c.value = **import_constant; + zval_copy_ctor(&c.value); + c.flags = CONST_CS; + c.name = zend_strndup(const_name_strval, const_name_strlen); + c.name_len = const_name_strlen + 1; + + if (zend_register_constant(&c TSRMLS_CC) == FAILURE) { + zend_error(E_ERROR, "Import: unable to register constant %s", const_name_strval); + } + } else { + HashPosition pos; + char *key; + uint key_length; + int key_type; + ulong dummy; + + zend_hash_internal_pointer_reset_ex(&ce->constants_table, &pos); + while (zend_hash_get_current_data_ex(&ce->constants_table, (void **)&import_constant, &pos) == SUCCESS) { + key_type = zend_hash_get_current_key_ex(&ce->constants_table, &key, &key_length, &dummy, 0, &pos); + + c.value = **import_constant; + zval_copy_ctor(&c.value); + c.flags = CONST_CS; + c.name = zend_strndup(key, key_length - 1); + c.name_len = key_length; + + if (zend_register_constant(&c TSRMLS_CC) == FAILURE) { + zend_error(E_ERROR, "Import: unable to register constant %s", key); + } + zend_hash_move_forward_ex(&ce->constants_table, &pos); + } + } + NEXT_OPCODE(); +} + + +int zend_fetch_class_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry **pce; + zend_bool is_const; + char *class_name_strval; + zend_uint class_name_strlen; + zval *class_name; + zval tmp; + int retval; + + if (EX(opline)->op1.op_type == IS_UNUSED) { + if (EX(opline)->extended_value == ZEND_FETCH_CLASS_SELF) { + if (!EG(scope)) { + zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); + } + EX_T(EX(opline)->result.u.var).EA.class_entry = EG(scope); + NEXT_OPCODE(); + } else if (EX(opline)->extended_value == ZEND_FETCH_CLASS_MAIN) { + EX_T(EX(opline)->result.u.var).EA.class_entry = EG(main_class_ptr); + NEXT_OPCODE(); + } else if (EX(opline)->extended_value == ZEND_FETCH_CLASS_PARENT) { + if (!EG(scope)) { + zend_error(E_ERROR, "Cannot access parent:: when no class scope is active"); + } + if (!EG(scope)->parent) { + zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent"); + } + EX_T(EX(opline)->result.u.var).EA.class_entry = EG(scope)->parent; + NEXT_OPCODE(); + } + } + + is_const = (EX(opline)->op2.op_type == IS_CONST); + + if (is_const) { + class_name_strval = EX(opline)->op2.u.constant.value.str.val; + class_name_strlen = EX(opline)->op2.u.constant.value.str.len; + } else { + class_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + + tmp = *class_name; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + zend_str_tolower(tmp.value.str.val, tmp.value.str.len); + + class_name_strval = tmp.value.str.val; + class_name_strlen = tmp.value.str.len; + } + + if (EX(opline)->op1.op_type == IS_UNUSED) { + retval = zend_lookup_class(class_name_strval, class_name_strlen, &pce TSRMLS_CC); + } else { + retval = zend_hash_find(&EX_T(EX(opline)->op1.u.var).EA.class_entry->class_table, class_name_strval, class_name_strlen+1, (void **)&pce); + } + + if (retval == FAILURE) { + zend_error(E_ERROR, "Class '%s' not found", class_name_strval); + } else { + EX_T(EX(opline)->result.u.var).EA.class_entry = *pce; + } + if (!is_const) { + zval_dtor(&tmp); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + } + NEXT_OPCODE(); +} + + +int zend_init_ctor_call_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_ptr_stack_n_push(&EG(arg_types_stack), 3, EX(fbc), EX(object), EX(calling_scope)); + + if (EX(opline)->op1.op_type == IS_VAR) { + SELECTIVE_PZVAL_LOCK(*EX_T(EX(opline)->op1.u.var).var.ptr_ptr, &EX(opline)->op1); + } + + /* We are not handling overloaded classes right now */ + EX(object) = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + if (!PZVAL_IS_REF(EX(object))) { + EX(object)->refcount++; /* For $this pointer */ + } else { + zval *this_ptr; + + ALLOC_ZVAL(this_ptr); + *this_ptr = *EX(object); + INIT_PZVAL(this_ptr); + zval_copy_ctor(this_ptr); + EX(object) = this_ptr; + } + + EX(fbc) = EX(fbc_constructor); + if (EX(fbc)->type == ZEND_USER_FUNCTION) { /* HACK!! */ + EX(calling_scope) = EX(fbc)->common.scope; + } else { + EX(calling_scope) = NULL; + } + + NEXT_OPCODE(); +} + + +int zend_init_method_call_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *function_name; + char *function_name_strval; + int function_name_strlen; + + zend_ptr_stack_n_push(&EG(arg_types_stack), 3, EX(fbc), EX(object), EX(calling_scope)); + + function_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + function_name_strval = function_name->value.str.val; + function_name_strlen = function_name->value.str.len; + + EX(calling_scope) = EG(scope); + + EX(object) = get_obj_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R TSRMLS_CC); + + if (EX(object) && EX(object)->type == IS_OBJECT) { + /* First, locate the function. */ + EX(fbc) = Z_OBJ_HT_P(EX(object))->get_method(EX(object), function_name_strval, function_name_strlen TSRMLS_CC); + if (!EX(fbc)) { + zend_error(E_ERROR, "Call to undefined method %s::%s()", Z_OBJ_CLASS_NAME_P(EX(object)), function_name_strval); + } + } else { + zend_error(E_ERROR, "Call to a member function %s() on a non-object", function_name_strval); + } + + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { + EX(object) = NULL; + } else { + if (!PZVAL_IS_REF(EX(object))) { + EX(object)->refcount++; /* For $this pointer */ + } else { + zval *this_ptr; + ALLOC_ZVAL(this_ptr); + *this_ptr = *EX(object); + INIT_PZVAL(this_ptr); + zval_copy_ctor(this_ptr); + EX(object) = this_ptr; + } + } + + if (EX(fbc)->type == ZEND_USER_FUNCTION) { + EX(calling_scope) = EX(fbc)->common.scope; + } else { + EX(calling_scope) = NULL; + } + + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + + NEXT_OPCODE(); +} + + +int zend_init_static_method_call_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *function_name; + zval tmp; + zend_class_entry *ce; + zend_bool is_const; + char *function_name_strval; + int function_name_strlen; + + zend_ptr_stack_n_push(&EG(arg_types_stack), 3, EX(fbc), EX(object), EX(calling_scope)); + + is_const = (EX(opline)->op2.op_type == IS_CONST); + + if (is_const) { + function_name_strval = EX(opline)->op2.u.constant.value.str.val; + function_name_strlen = EX(opline)->op2.u.constant.value.str.len; + } else { + function_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + + tmp = *function_name; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + zend_str_tolower(tmp.value.str.val, tmp.value.str.len); + + function_name_strval = tmp.value.str.val; + function_name_strlen = tmp.value.str.len; + } + + ce = EX_T(EX(opline)->op1.u.var).EA.class_entry; + + EX(fbc) = zend_get_static_method(ce, function_name_strval, function_name_strlen TSRMLS_CC); + EX(calling_scope) = EX(fbc)->common.scope; + + if (!is_const) { + zval_dtor(&tmp); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + } + + if (EX(fbc)->common.fn_flags & ZEND_ACC_STATIC) { + EX(object) = NULL; + } else { + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + } + + NEXT_OPCODE(); +} + + +int zend_init_fcall_by_name_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *function_name; + zend_function *function; + zval tmp; + zend_bool is_const; + char *function_name_strval; + int function_name_strlen; + + zend_ptr_stack_n_push(&EG(arg_types_stack), 3, EX(fbc), EX(object), EX(calling_scope)); + + is_const = (EX(opline)->op2.op_type == IS_CONST); + + if (is_const) { + function_name_strval = EX(opline)->op2.u.constant.value.str.val; + function_name_strlen = EX(opline)->op2.u.constant.value.str.len; + } else { + function_name = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + + tmp = *function_name; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + zend_str_tolower(tmp.value.str.val, tmp.value.str.len); + + function_name_strval = tmp.value.str.val; + function_name_strlen = tmp.value.str.len; + } + + + do { + /* + if (EG(scope)) { + if (zend_hash_find(&EG(scope)->function_table, function_name_strval, function_name_strlen+1, (void **) &function) == SUCCESS) { + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + EX(calling_scope) = EG(scope); + break; + } + } + */ + if (zend_hash_find(EG(function_table), function_name_strval, function_name_strlen+1, (void **) &function)==FAILURE) { + zend_error(E_ERROR, "Call to undefined function: %s()", function_name_strval); + } + EX(calling_scope) = function->common.scope; + EX(object) = NULL; + } while (0); + + if (!is_const) { + zval_dtor(&tmp); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + } + EX(fbc) = function; + + NEXT_OPCODE(); +} + + +int zend_do_fcall_common_helper(ZEND_OPCODE_HANDLER_ARGS) +{ + zval **original_return_value; + zend_class_entry *current_scope; + zval *current_this; + int return_value_used = RETURN_VALUE_USED(EX(opline)); + + zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) EX(opline)->extended_value, NULL); + + EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr; + + if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) { + ALLOC_ZVAL(EX_T(EX(opline)->result.u.var).var.ptr); + INIT_ZVAL(*(EX_T(EX(opline)->result.u.var).var.ptr)); + + if (!zend_execute_internal) { + /* saves one function call if zend_execute_internal is not used */ + ((zend_internal_function *) EX(function_state).function)->handler(EX(opline)->extended_value, EX_T(EX(opline)->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC); + } else { + zend_execute_internal(execute_data, return_value_used TSRMLS_CC); + } + + EG(current_execute_data) = execute_data; + EX_T(EX(opline)->result.u.var).var.ptr->is_ref = 0; + EX_T(EX(opline)->result.u.var).var.ptr->refcount = 1; + if (!return_value_used) { + zval_ptr_dtor(&EX_T(EX(opline)->result.u.var).var.ptr); + } + } else if (EX(function_state).function->type == ZEND_USER_FUNCTION) { + HashTable *calling_symbol_table; + + current_this = EG(This); + EG(This) = EX(object); + current_scope = EG(scope); + EG(scope) = EX(calling_scope); + + EX_T(EX(opline)->result.u.var).var.ptr = NULL; + if (EG(symtable_cache_ptr)>=EG(symtable_cache)) { + /*printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]);*/ + EX(function_state).function_symbol_table = *(EG(symtable_cache_ptr)--); + } else { + ALLOC_HASHTABLE(EX(function_state).function_symbol_table); + zend_hash_init(EX(function_state).function_symbol_table, 0, NULL, ZVAL_PTR_DTOR, 0); + /*printf("Cache miss! Initialized %x\n", function_state.function_symbol_table);*/ + } + calling_symbol_table = EG(active_symbol_table); + EG(active_symbol_table) = EX(function_state).function_symbol_table; + original_return_value = EG(return_value_ptr_ptr); + EG(return_value_ptr_ptr) = EX_T(EX(opline)->result.u.var).var.ptr_ptr; + EG(active_op_array) = (zend_op_array *) EX(function_state).function; + + zend_execute(EG(active_op_array) TSRMLS_CC); + + if (return_value_used && !EX_T(EX(opline)->result.u.var).var.ptr) { + if (!EG(exception)) { + ALLOC_ZVAL(EX_T(EX(opline)->result.u.var).var.ptr); + INIT_ZVAL(*EX_T(EX(opline)->result.u.var).var.ptr); + } + } else if (!return_value_used && EX_T(EX(opline)->result.u.var).var.ptr) { + zval_ptr_dtor(&EX_T(EX(opline)->result.u.var).var.ptr); + } + + EG(opline_ptr) = &EX(opline); + EG(active_op_array) = op_array; + EG(return_value_ptr_ptr)=original_return_value; + if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { + zend_hash_destroy(EX(function_state).function_symbol_table); + FREE_HASHTABLE(EX(function_state).function_symbol_table); + } else { + *(++EG(symtable_cache_ptr)) = EX(function_state).function_symbol_table; + zend_hash_clean(*EG(symtable_cache_ptr)); + } + EG(active_symbol_table) = calling_symbol_table; + if (EG(This)) { + zval_ptr_dtor(&EG(This)); + } + EG(This) = current_this; + EG(scope) = current_scope; + } else { /* ZEND_OVERLOADED_FUNCTION */ + ALLOC_ZVAL(EX_T(EX(opline)->result.u.var).var.ptr); + INIT_ZVAL(*(EX_T(EX(opline)->result.u.var).var.ptr)); + + /* Not sure what should be done here if it's a static method */ + if (EX(object)) { + Z_OBJ_HT_P(EX(object))->call_method(EX(fbc)->common.function_name, EX(opline)->extended_value, EX_T(EX(opline)->result.u.var).var.ptr, EX(object), return_value_used TSRMLS_CC); + } else { + zend_error(E_ERROR, "Cannot call overloaded function for non-object"); + } + + efree(EX(fbc)); + if (!return_value_used) { + zval_ptr_dtor(&EX_T(EX(opline)->result.u.var).var.ptr); + } + } + zend_ptr_stack_n_pop(&EG(arg_types_stack), 3, &EX(calling_scope), &EX(object), &EX(fbc)); + + EX(function_state).function = (zend_function *) op_array; + EG(function_state_ptr) = &EX(function_state); + zend_ptr_stack_clear_multiple(TSRMLS_C); + + if (EG(exception)) { + if (EX(opline)->op2.u.opline_num == -1) { + RETURN_FROM_EXECUTE_LOOP(execute_data); + } else { + EX(opline) = &op_array->opcodes[EX(opline)->op2.u.opline_num]; + return 0; /* CHECK_ME */ + } + } + + NEXT_OPCODE(); +} + + +int zend_do_fcall_by_name_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + EX(function_state).function = EX(fbc); + return zend_do_fcall_common_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_do_fcall_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *fname = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + + zend_ptr_stack_n_push(&EG(arg_types_stack), 3, EX(fbc), EX(object), EX(calling_scope)); + + do { + /* + if (EG(scope)) { + if (zend_hash_find(&EG(scope)->function_table, fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function) == SUCCESS) { + if ((EX(object) = EG(This))) { + EX(object)->refcount++; + } + EX(calling_scope) = EG(scope); + break; + } + } + */ + if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &EX(function_state).function)==FAILURE) { + zend_error(E_ERROR, "Unknown function: %s()\n", fname->value.str.val); + } + EX(object) = NULL; + EX(calling_scope) = EX(function_state).function->common.scope; + } while (0); + + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + + return zend_do_fcall_common_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_return_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *retval_ptr; + zval **retval_ptr_ptr; + + if ((EG(active_op_array)->return_reference == ZEND_RETURN_REF) && + (EX(opline)->op1.op_type != IS_CONST) && + (EX(opline)->op1.op_type != IS_TMP_VAR)) { + + retval_ptr_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_W); + + if (!retval_ptr_ptr) { + zend_error(E_ERROR, "Cannot return overloaded elements or string offsets by reference"); + } + + SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr); + (*retval_ptr_ptr)->refcount++; + + (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr); + } else { + retval_ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + + if (!EG(free_op1)) { /* Not a temp var */ + if (PZVAL_IS_REF(retval_ptr) && retval_ptr->refcount > 0) { + ALLOC_ZVAL(*(EG(return_value_ptr_ptr))); + **EG(return_value_ptr_ptr) = *retval_ptr; + (*EG(return_value_ptr_ptr))->is_ref = 0; + (*EG(return_value_ptr_ptr))->refcount = 1; + zval_copy_ctor(*EG(return_value_ptr_ptr)); + } else { + *EG(return_value_ptr_ptr) = retval_ptr; + retval_ptr->refcount++; + } + } else { + ALLOC_ZVAL(*(EG(return_value_ptr_ptr))); + **EG(return_value_ptr_ptr) = *retval_ptr; + (*EG(return_value_ptr_ptr))->refcount = 1; + (*EG(return_value_ptr_ptr))->is_ref = 0; + } + } + RETURN_FROM_EXECUTE_LOOP(execute_data); +} + + +int zend_throw_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *value; + zval *exception; + + value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + + if (value->type != IS_OBJECT) { + zend_error(E_ERROR, "Can only throw objects"); + } + /* Not sure if a complete copy is what we want here */ + MAKE_STD_ZVAL(exception); + *exception = *value; + if (!EG(free_op1)) { + zval_copy_ctor(exception); + } + INIT_PZVAL(exception); + EG(exception) = exception; + + if (EX(opline)->op2.u.opline_num == -1) { + RETURN_FROM_EXECUTE_LOOP(execute_data); + } else { + EX(opline) = &op_array->opcodes[EX(opline)->op2.u.opline_num]; + return 0; /* CHECK_ME */ + } + NEXT_OPCODE(); +} + + +int zend_catch_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry *ce; + + /* Check if this is really an exception, if not, jump over code */ + if (EG(exception) == NULL) { + EX(opline) = &op_array->opcodes[EX(opline)->extended_value]; + return 0; /* CHECK_ME */ + } + ce = Z_OBJCE_P(EG(exception)); + if (ce != EX_T(EX(opline)->op1.u.var).EA.class_entry) { + while (ce->parent) { + if (ce->parent == EX_T(EX(opline)->op1.u.var).EA.class_entry) { + goto exception_should_be_taken; + } + ce = ce->parent; + } + EX(opline) = &op_array->opcodes[EX(opline)->extended_value]; + return 0; /* CHECK_ME */ + } + +exception_should_be_taken: + zend_hash_update(EG(active_symbol_table), EX(opline)->op2.u.constant.value.str.val, + EX(opline)->op2.u.constant.value.str.len+1, &EG(exception), sizeof(zval *), (void **) NULL); + EG(exception) = NULL; + NEXT_OPCODE(); +} + + +int zend_send_val_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if (EX(opline)->extended_value==ZEND_DO_FCALL_BY_NAME + && ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->op2.u.opline_num, EX(fbc), EX(fbc)->common.arg_types)) { + zend_error(E_ERROR, "Cannot pass parameter %d by reference", EX(opline)->op2.u.opline_num); + } + { + zval *valptr; + zval *value; + + value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + + ALLOC_ZVAL(valptr); + *valptr = *value; + if (!EG(free_op1)) { + zval_copy_ctor(valptr); + } + INIT_PZVAL(valptr); + zend_ptr_stack_push(&EG(argument_stack), valptr); + } + NEXT_OPCODE(); +} + + +inline int zend_send_by_var_helper(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *varptr; + varptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + + if (varptr == &EG(uninitialized_zval)) { + ALLOC_ZVAL(varptr); + INIT_ZVAL(*varptr); + varptr->refcount = 0; + } else if (PZVAL_IS_REF(varptr)) { + zval *original_var = varptr; + + ALLOC_ZVAL(varptr); + *varptr = *original_var; + varptr->is_ref = 0; + varptr->refcount = 0; + zval_copy_ctor(varptr); + } + varptr->refcount++; + zend_ptr_stack_push(&EG(argument_stack), varptr); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); /* for string offsets */ + + NEXT_OPCODE(); +} + + +int zend_send_var_no_ref_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if (EX(opline)->extended_value & ZEND_ARG_COMPILE_TIME_BOUND) { /* Had function_ptr at compile_time */ + if (!(EX(opline)->extended_value & ZEND_ARG_SEND_BY_REF)) { + return zend_send_by_var_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + } else if (!ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->op2.u.opline_num, EX(fbc), EX(fbc)->common.arg_types)) { + return zend_send_by_var_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + { + zval *varptr; + varptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + + if (varptr != &EG(uninitialized_zval) && (PZVAL_IS_REF(varptr) || varptr->refcount == 1)) { + varptr->is_ref = 1; + varptr->refcount++; + zend_ptr_stack_push(&EG(argument_stack), varptr); + NEXT_OPCODE(); + } + zend_error(E_ERROR, "Only variables can be passed by reference"); + } + NEXT_OPCODE(); +} + + +int zend_send_ref_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval **varptr_ptr; + zval *varptr; + varptr_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_W); + + if (!varptr_ptr) { + zend_error(E_ERROR, "Only variables can be passed by reference"); + } + + SEPARATE_ZVAL_TO_MAKE_IS_REF(varptr_ptr); + varptr = *varptr_ptr; + varptr->refcount++; + zend_ptr_stack_push(&EG(argument_stack), varptr); + + NEXT_OPCODE(); +} + + +int zend_send_var_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if ((EX(opline)->extended_value == ZEND_DO_FCALL_BY_NAME) + && ARG_SHOULD_BE_SENT_BY_REF(EX(opline)->op2.u.opline_num, EX(fbc), EX(fbc)->common.arg_types)) { + return zend_send_ref_handler(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + return zend_send_by_var_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_recv_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval **param; + + if (zend_ptr_stack_get_arg(EX(opline)->op1.u.constant.value.lval, (void **) ¶m TSRMLS_CC)==FAILURE) { + zend_error(E_WARNING, "Missing argument %d for %s()\n", EX(opline)->op1.u.constant.value.lval, get_active_function_name(TSRMLS_C)); + if (EX(opline)->result.op_type == IS_VAR) { + PZVAL_UNLOCK(*EX_T(EX(opline)->result.u.var).var.ptr_ptr); + } + } else if (PZVAL_IS_REF(*param)) { + zend_assign_to_variable_reference(NULL, get_zval_ptr_ptr(&EX(opline)->result, EX(Ts), BP_VAR_W), param, NULL TSRMLS_CC); + } else { + zend_assign_to_variable(NULL, &EX(opline)->result, NULL, *param, IS_VAR, EX(Ts) TSRMLS_CC); + } + + NEXT_OPCODE(); +} + + +int zend_recv_init_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval **param, *assignment_value; + + if (zend_ptr_stack_get_arg(EX(opline)->op1.u.constant.value.lval, (void **) ¶m TSRMLS_CC)==FAILURE) { + if (EX(opline)->op2.u.constant.type == IS_CONSTANT || EX(opline)->op2.u.constant.type==IS_CONSTANT_ARRAY) { + zval *default_value; + + ALLOC_ZVAL(default_value); + *default_value = EX(opline)->op2.u.constant; + if (EX(opline)->op2.u.constant.type==IS_CONSTANT_ARRAY) { + zval_copy_ctor(default_value); + } + default_value->refcount=1; + zval_update_constant(&default_value, 0 TSRMLS_CC); + default_value->refcount=0; + default_value->is_ref=0; + param = &default_value; + assignment_value = default_value; + } else { + param = NULL; + assignment_value = &EX(opline)->op2.u.constant; + } + zend_assign_to_variable(NULL, &EX(opline)->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC); + } else { + assignment_value = *param; + if (PZVAL_IS_REF(assignment_value)) { + zend_assign_to_variable_reference(NULL, get_zval_ptr_ptr(&EX(opline)->result, EX(Ts), BP_VAR_W), param, NULL TSRMLS_CC); + } else { + zend_assign_to_variable(NULL, &EX(opline)->result, NULL, assignment_value, IS_VAR, EX(Ts) TSRMLS_CC); + } + } + + NEXT_OPCODE(); +} + + +int zend_bool_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ + EX_T(EX(opline)->result.u.var).tmp_var.value.lval = zend_is_true(get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R)); + EX_T(EX(opline)->result.u.var).tmp_var.type = IS_BOOL; + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + + NEXT_OPCODE(); +} + + +inline int zend_brk_cont_helper(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *nest_levels_zval = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + zval tmp; + int array_offset, nest_levels, original_nest_levels; + zend_brk_cont_element *jmp_to; + + if (nest_levels_zval->type != IS_LONG) { + tmp = *nest_levels_zval; + zval_copy_ctor(&tmp); + convert_to_long(&tmp); + nest_levels = tmp.value.lval; + } else { + nest_levels = nest_levels_zval->value.lval; + } + original_nest_levels = nest_levels; + array_offset = EX(opline)->op1.u.opline_num; + do { + if (array_offset==-1) { + zend_error(E_ERROR, "Cannot break/continue %d level%s", original_nest_levels, (original_nest_levels == 1) ? "" : "s"); + } + jmp_to = &op_array->brk_cont_array[array_offset]; + if (nest_levels>1) { + zend_op *brk_opline = &op_array->opcodes[jmp_to->brk]; + + switch (brk_opline->opcode) { + case ZEND_SWITCH_FREE: + zend_switch_free(brk_opline, EX(Ts) TSRMLS_CC); + break; + case ZEND_FREE: + zendi_zval_dtor(EX_T(brk_opline->op1.u.var).tmp_var); + break; + } + } + array_offset = jmp_to->parent; + } while (--nest_levels > 0); + + if (EX(opline)->opcode == ZEND_BRK) { + EX(opline) = op_array->opcodes+jmp_to->brk; + } else { + EX(opline) = op_array->opcodes+jmp_to->cont; + } + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + return 0; /* CHECK_ME */ +} + + +int zend_brk_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_brk_cont_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_cont_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_brk_cont_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_case_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + int switch_expr_is_overloaded=0; + + if (EX(opline)->op1.op_type==IS_VAR) { + if (EX_T(EX(opline)->op1.u.var).var.ptr_ptr) { + PZVAL_LOCK(*EX_T(EX(opline)->op1.u.var).var.ptr_ptr); + } else { + switch_expr_is_overloaded = 1; + if (EX_T(EX(opline)->op1.u.var).EA.type==IS_STRING_OFFSET) { + EX_T(EX(opline)->op1.u.var).EA.data.str_offset.str->refcount++; + } + } + } + is_equal_function(&EX_T(EX(opline)->result.u.var).tmp_var, + get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R), + get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R) TSRMLS_CC); + + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + if (switch_expr_is_overloaded) { + /* We only free op1 if this is a string offset, + * Since if it is a TMP_VAR, it'll be reused by + * other CASE opcodes (whereas string offsets + * are allocated at each get_zval_ptr()) + */ + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + EX_T(EX(opline)->op1.u.var).var.ptr_ptr = NULL; + AI_USE_PTR(EX_T(EX(opline)->op1.u.var).var); + } + NEXT_OPCODE(); +} + + +int zend_switch_free_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_switch_free(EX(opline), EX(Ts) TSRMLS_CC); + NEXT_OPCODE(); +} + + +int zend_new_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if (EX_T(EX(opline)->op1.u.var).EA.class_entry->ce_flags & ZEND_ACC_ABSTRACT) { + zend_error(E_ERROR, "Cannot instantiate abstract class %s", EX_T(EX(opline)->op1.u.var).EA.class_entry->name); + } + EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr; + ALLOC_ZVAL(EX_T(EX(opline)->result.u.var).var.ptr); + object_init_ex(EX_T(EX(opline)->result.u.var).var.ptr, EX_T(EX(opline)->op1.u.var).EA.class_entry); + EX_T(EX(opline)->result.u.var).var.ptr->refcount=1; + EX_T(EX(opline)->result.u.var).var.ptr->is_ref=1; + + NEXT_OPCODE(); +} + + +int zend_clone_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *obj = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + + EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr; + ALLOC_ZVAL(EX_T(EX(opline)->result.u.var).var.ptr); + EX_T(EX(opline)->result.u.var).var.ptr->value.obj = Z_OBJ_HT_P(obj)->clone_obj(obj TSRMLS_CC); + EX_T(EX(opline)->result.u.var).var.ptr->type = IS_OBJECT; + EX_T(EX(opline)->result.u.var).var.ptr->refcount=1; + EX_T(EX(opline)->result.u.var).var.ptr->is_ref=1; + NEXT_OPCODE(); +} + + +int zend_fetch_constant_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_class_entry *ce; + zval **value; + + if (EX(opline)->op1.op_type == IS_UNUSED) { + if (EG(scope)) { + ce = EG(scope); + if (zend_hash_find(&ce->constants_table, EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) { + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EX_T(EX(opline)->result.u.var).tmp_var = **value; + zval_copy_ctor(&EX_T(EX(opline)->result.u.var).tmp_var); + NEXT_OPCODE(); + } + } + if (!zend_get_constant(EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len, &EX_T(EX(opline)->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", + EX(opline)->op2.u.constant.value.str.val, + EX(opline)->op2.u.constant.value.str.val); + EX_T(EX(opline)->result.u.var).tmp_var = EX(opline)->op2.u.constant; + zval_copy_ctor(&EX_T(EX(opline)->result.u.var).tmp_var); + } + NEXT_OPCODE(); + } + + ce = EX_T(EX(opline)->op1.u.var).EA.class_entry; + + if (&ce->constants_table == &EG(main_class_ptr)->constants_table) { + if (!zend_get_constant(EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len, &EX_T(EX(opline)->result.u.var).tmp_var TSRMLS_CC)) { + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", + EX(opline)->op2.u.constant.value.str.val, + EX(opline)->op2.u.constant.value.str.val); + EX_T(EX(opline)->result.u.var).tmp_var = EX(opline)->op2.u.constant; + zval_copy_ctor(&EX_T(EX(opline)->result.u.var).tmp_var); + } + NEXT_OPCODE(); + } + if (zend_hash_find(&ce->constants_table, EX(opline)->op2.u.constant.value.str.val, EX(opline)->op2.u.constant.value.str.len+1, (void **) &value) == SUCCESS) { + zval_update_constant(value, (void *) 1 TSRMLS_CC); + EX_T(EX(opline)->result.u.var).tmp_var = **value; + zval_copy_ctor(&EX_T(EX(opline)->result.u.var).tmp_var); + } else { + zend_error(E_ERROR, "Undefined class constant '%s'", EX(opline)->op2.u.constant.value.str.val); + } + + NEXT_OPCODE(); +} + + +inline int zend_init_add_array_helper(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array_ptr = &EX_T(EX(opline)->result.u.var).tmp_var; + zval *expr_ptr, **expr_ptr_ptr = NULL; + zval *offset=get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + + if (EX(opline)->extended_value) { + expr_ptr_ptr=get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_R); + expr_ptr = *expr_ptr_ptr; + } else { + expr_ptr=get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + } + + if (EX(opline)->opcode == ZEND_INIT_ARRAY) { + array_init(array_ptr); + if (!expr_ptr) { + NEXT_OPCODE(); + } + } + if (!EX(opline)->extended_value && EG(free_op1)) { /* temporary variable */ + zval *new_expr; + + ALLOC_ZVAL(new_expr); + *new_expr = *expr_ptr; + expr_ptr = new_expr; + INIT_PZVAL(expr_ptr); + } else { + if (EX(opline)->extended_value) { + SEPARATE_ZVAL_TO_MAKE_IS_REF(expr_ptr_ptr); + expr_ptr = *expr_ptr_ptr; + expr_ptr->refcount++; + } else if (PZVAL_IS_REF(expr_ptr)) { + zval *new_expr; + + ALLOC_ZVAL(new_expr); + *new_expr = *expr_ptr; + expr_ptr = new_expr; + zendi_zval_copy_ctor(*expr_ptr); + INIT_PZVAL(expr_ptr); + } else { + expr_ptr->refcount++; + } + } + if (offset) { + switch (offset->type) { + case IS_DOUBLE: + zend_hash_index_update(array_ptr->value.ht, (long) offset->value.dval, &expr_ptr, sizeof(zval *), NULL); + break; + case IS_LONG: + case IS_BOOL: + zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr_ptr, sizeof(zval *), NULL); + break; + case IS_STRING: + zend_hash_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr_ptr, sizeof(zval *), NULL); + break; + case IS_NULL: + zend_hash_update(array_ptr->value.ht, "", sizeof(""), &expr_ptr, sizeof(zval *), NULL); + break; + default: + zval_ptr_dtor(&expr_ptr); + /* do nothing */ + break; + } + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + } else { + zend_hash_next_index_insert(array_ptr->value.ht, &expr_ptr, sizeof(zval *), NULL); + } + NEXT_OPCODE(); +} + + +int zend_init_array_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_init_add_array_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_add_array_element_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + return zend_init_add_array_helper(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + + +int zend_cast_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *expr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + zval *result = &EX_T(EX(opline)->result.u.var).tmp_var; + + *result = *expr; + if (!EG(free_op1)) { + zendi_zval_copy_ctor(*result); + } + switch (EX(opline)->extended_value) { + case IS_NULL: + convert_to_null(result); + break; + case IS_BOOL: + convert_to_boolean(result); + break; + case IS_LONG: + convert_to_long(result); + break; + case IS_DOUBLE: + convert_to_double(result); + break; + case IS_STRING: + convert_to_string(result); + break; + case IS_ARRAY: + convert_to_array(result); + break; + case IS_OBJECT: + convert_to_object(result); + break; + } + NEXT_OPCODE(); +} + + +int zend_include_or_eval_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_op_array *new_op_array=NULL; + zval **original_return_value = EG(return_value_ptr_ptr); + int return_value_used; + zval *inc_filename = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + zval tmp_inc_filename; + zend_bool failure_retval=0; + + if (inc_filename->type!=IS_STRING) { + tmp_inc_filename = *inc_filename; + zval_copy_ctor(&tmp_inc_filename); + convert_to_string(&tmp_inc_filename); + inc_filename = &tmp_inc_filename; + } + + return_value_used = RETURN_VALUE_USED(EX(opline)); + + switch (EX(opline)->op2.u.constant.value.lval) { + case ZEND_INCLUDE_ONCE: + case ZEND_REQUIRE_ONCE: { + char *opened_path=NULL; + int dummy = 1; + zend_file_handle file_handle; + + file_handle.handle.fp = zend_fopen(inc_filename->value.str.val, &opened_path); + file_handle.type = ZEND_HANDLE_FP; + file_handle.filename = inc_filename->value.str.val; + file_handle.opened_path = opened_path; + file_handle.free_filename = 0; + + if (file_handle.handle.fp) { + if (!opened_path) { + opened_path = file_handle.opened_path = estrndup(inc_filename->value.str.val, inc_filename->value.str.len); + } + + if (zend_hash_add(&EG(included_files), opened_path, strlen(opened_path)+1, (void *)&dummy, sizeof(int), NULL)==SUCCESS) { + new_op_array = zend_compile_file(&file_handle, (EX(opline)->op2.u.constant.value.lval==ZEND_INCLUDE_ONCE?ZEND_INCLUDE:ZEND_REQUIRE) TSRMLS_CC); + zend_destroy_file_handle(&file_handle TSRMLS_CC); + opened_path = NULL; /* zend_destroy_file_handle() already frees it */ + } else { + fclose(file_handle.handle.fp); + failure_retval=1; + } + } else { + if (EX(opline)->op2.u.constant.value.lval==ZEND_INCLUDE_ONCE) { + zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle.filename); + } else { + zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle.filename); + } + } + if (opened_path) { + efree(opened_path); + } + break; + } + break; + case ZEND_INCLUDE: + case ZEND_REQUIRE: + new_op_array = compile_filename(EX(opline)->op2.u.constant.value.lval, inc_filename TSRMLS_CC); + break; + case ZEND_EVAL: { + char *eval_desc = zend_make_compiled_string_description("eval()'d code" TSRMLS_CC); + + new_op_array = compile_string(inc_filename, eval_desc TSRMLS_CC); + efree(eval_desc); + } + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + if (inc_filename==&tmp_inc_filename) { + zval_dtor(&tmp_inc_filename); + } + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr; + if (new_op_array) { + zval *saved_object; + zend_function *saved_function; + + + EG(return_value_ptr_ptr) = EX_T(EX(opline)->result.u.var).var.ptr_ptr; + EG(active_op_array) = new_op_array; + EX_T(EX(opline)->result.u.var).var.ptr = NULL; + + saved_object = EX(object); + saved_function = EX(function_state).function; + + EX(function_state).function = (zend_function *) new_op_array; + EX(object) = NULL; + + zend_execute(new_op_array TSRMLS_CC); + + EX(function_state).function = saved_function; + EX(object) = saved_object; + + if (!return_value_used) { + if (EX_T(EX(opline)->result.u.var).var.ptr) { + zval_ptr_dtor(&EX_T(EX(opline)->result.u.var).var.ptr); + } + } else { /* return value is used */ + if (!EX_T(EX(opline)->result.u.var).var.ptr) { /* there was no return statement */ + ALLOC_ZVAL(EX_T(EX(opline)->result.u.var).var.ptr); + INIT_PZVAL(EX_T(EX(opline)->result.u.var).var.ptr); + EX_T(EX(opline)->result.u.var).var.ptr->value.lval = 1; + EX_T(EX(opline)->result.u.var).var.ptr->type = IS_BOOL; + } + } + + EG(opline_ptr) = &EX(opline); + EG(active_op_array) = op_array; + EG(function_state_ptr) = &EX(function_state); + destroy_op_array(new_op_array); + efree(new_op_array); + } else { + if (return_value_used) { + ALLOC_ZVAL(EX_T(EX(opline)->result.u.var).var.ptr); + INIT_ZVAL(*EX_T(EX(opline)->result.u.var).var.ptr); + EX_T(EX(opline)->result.u.var).var.ptr->value.lval = failure_retval; + EX_T(EX(opline)->result.u.var).var.ptr->type = IS_BOOL; + } + } + EG(return_value_ptr_ptr) = original_return_value; + NEXT_OPCODE(); +} + + +int zend_unset_var_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval tmp, *variable; + HashTable *target_symbol_table; + + variable = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + + if (variable->type != IS_STRING) { + tmp = *variable; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + variable = &tmp; + } + + target_symbol_table = zend_get_target_symbol_table(EX(opline), EX(Ts), BP_VAR_IS, variable TSRMLS_CC); + + zend_hash_del(target_symbol_table, variable->value.str.val, variable->value.str.len+1); + + if (variable == &tmp) { + zval_dtor(&tmp); + } + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + NEXT_OPCODE(); +} + + +int zend_unset_dim_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval **container = get_obj_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_R TSRMLS_CC); + zval *offset = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + + if (container) { + HashTable *ht; + + if ((*container)->type == IS_ARRAY) { + ht = (*container)->value.ht; + } else { + ht = NULL; + if ((*container)->type == IS_OBJECT) { + Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC); + } + } + if (ht) { + switch (offset->type) { + case IS_DOUBLE: + case IS_RESOURCE: + case IS_BOOL: + case IS_LONG: + { + long index; + + if (offset->type == IS_DOUBLE) { + index = (long) offset->value.lval; + } else { + index = offset->value.lval; + } + + zend_hash_index_del(ht, index); + break; + } + case IS_STRING: + zend_hash_del(ht, offset->value.str.val, offset->value.str.len+1); + break; + case IS_NULL: + zend_hash_del(ht, "", sizeof("")); + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); + break; + } + } + } else { + /* overloaded element */ + } + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); + + NEXT_OPCODE(); +} + + +int zend_fe_reset_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array_ptr, **array_ptr_ptr; + HashTable *fe_ht; + + if (EX(opline)->extended_value) { + array_ptr_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_R); + if (array_ptr_ptr == NULL) { + MAKE_STD_ZVAL(array_ptr); + } else { + SEPARATE_ZVAL_IF_NOT_REF(array_ptr_ptr); + array_ptr = *array_ptr_ptr; + array_ptr->refcount++; + } + } else { + array_ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + if (EG(free_op1)) { /* IS_TMP_VAR */ + zval *tmp; + + ALLOC_ZVAL(tmp); + *tmp = *array_ptr; + INIT_PZVAL(tmp); + array_ptr = tmp; + } else { + array_ptr->refcount++; + } + } + PZVAL_LOCK(array_ptr); + EX_T(EX(opline)->result.u.var).var.ptr = array_ptr; + EX_T(EX(opline)->result.u.var).var.ptr_ptr = &EX_T(EX(opline)->result.u.var).var.ptr; + + if ((fe_ht = HASH_OF(array_ptr)) != NULL) { + /* probably redundant */ + zend_hash_internal_pointer_reset(fe_ht); + } else { + /* JMP to the end of foreach - TBD */ + } + NEXT_OPCODE(); +} + + +int zend_fe_fetch_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *array = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + zval *result = &EX_T(EX(opline)->result.u.var).tmp_var; + zval **value, *key; + char *str_key; + ulong int_key; + HashTable *fe_ht; + + PZVAL_LOCK(array); + + fe_ht = HASH_OF(array); + if (!fe_ht) { + zend_error(E_WARNING, "Invalid argument supplied for foreach()"); + EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num; + return 0; /* CHECK_ME */ + } else if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) { + EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num; + return 0; /* CHECK_ME */ + } + array_init(result); + + + (*value)->refcount++; + zend_hash_index_update(result->value.ht, 0, value, sizeof(zval *), NULL); + + ALLOC_ZVAL(key); + INIT_PZVAL(key); + switch (zend_hash_get_current_key(fe_ht, &str_key, &int_key, 1)) { + case HASH_KEY_IS_STRING: + key->value.str.val = str_key; + key->value.str.len = strlen(str_key); + key->type = IS_STRING; + break; + case HASH_KEY_IS_LONG: + key->value.lval = int_key; + key->type = IS_LONG; + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL); + zend_hash_move_forward(fe_ht); + + NEXT_OPCODE(); +} - EG(opline_ptr) = &EX(opline); - EG(active_op_array) = op_array; - EG(function_state_ptr) = &EX(function_state); - destroy_op_array(new_op_array); - efree(new_op_array); - } else { - if (return_value_used) { - ALLOC_ZVAL(EX(Ts)[EX(opline)->result.u.var].var.ptr); - INIT_ZVAL(*EX(Ts)[EX(opline)->result.u.var].var.ptr); - EX(Ts)[EX(opline)->result.u.var].var.ptr->value.lval = failure_retval; - EX(Ts)[EX(opline)->result.u.var].var.ptr->type = IS_BOOL; - } - } - EG(return_value_ptr_ptr) = original_return_value; - } - NEXT_OPCODE(); - case ZEND_UNSET_VAR: - { - zval tmp, *variable = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - zval **object; - zend_bool unset_object; - - unset_object = (EX(opline)->extended_value == ZEND_UNSET_OBJ); - if (variable->type != IS_STRING) { - tmp = *variable; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - variable = &tmp; - } +int zend_jmp_no_ctor_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *object_zval; + zend_function *constructor; - if (unset_object) { - if (zend_hash_find(EG(active_symbol_table), variable->value.str.val, variable->value.str.len+1, (void **)&object) == FAILURE) { - zend_error(E_ERROR, "Cannot delete non-existing object"); - } - if (Z_TYPE_PP(object) != IS_OBJECT) { - zend_error(E_ERROR, "Cannot call delete on non-object type"); - } - Z_OBJ_HT_PP(object)->delete_obj(*object TSRMLS_CC); - } + if (EX(opline)->op1.op_type == IS_VAR) { + PZVAL_LOCK(*EX_T(EX(opline)->op1.u.var).var.ptr_ptr); + } + + object_zval = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + constructor = Z_OBJ_HT_P(object_zval)->get_constructor(object_zval TSRMLS_CC); - zend_hash_del(EG(active_symbol_table), variable->value.str.val, variable->value.str.len+1); + EX(fbc_constructor) = NULL; + if (constructor == NULL) { + EX(opline) = op_array->opcodes + EX(opline)->op2.u.opline_num; + return 0; /* CHECK_ME */ + } else { + EX(fbc_constructor) = constructor; + } - if (variable == &tmp) { - zval_dtor(&tmp); - } - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); - } - NEXT_OPCODE(); - case ZEND_UNSET_DIM_OBJ: { - zval **container = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_R); - zval *offset = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); - zend_bool unset_object; - zval **object; + NEXT_OPCODE(); +} - unset_object = (EX(opline)->extended_value == ZEND_UNSET_OBJ); - - if (container) { - HashTable *ht; - if((*container)->type == IS_ARRAY) { - ht = (*container)->value.ht; +int zend_isset_isempty_var_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval tmp, *variable = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + zval **value; + zend_bool isset = 1; + HashTable *target_symbol_table; + + if (variable->type != IS_STRING) { + tmp = *variable; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + variable = &tmp; + } + + target_symbol_table = zend_get_target_symbol_table(EX(opline), EX(Ts), BP_VAR_IS, variable TSRMLS_CC); + + if (zend_hash_find(target_symbol_table, variable->value.str.val, variable->value.str.len+1, (void **) &value) == FAILURE) { + isset = 0; + } + + EX_T(EX(opline)->result.u.var).tmp_var.type = IS_BOOL; + + switch (EX(opline)->extended_value) { + case ZEND_ISSET: + if (isset && Z_TYPE_PP(value) == IS_NULL) { + EX_T(EX(opline)->result.u.var).tmp_var.value.lval = 0; + } else { + EX_T(EX(opline)->result.u.var).tmp_var.value.lval = isset; + } + break; + case ZEND_ISEMPTY: + if (!isset || !zend_is_true(*value)) { + EX_T(EX(opline)->result.u.var).tmp_var.value.lval = 1; + } else { + EX_T(EX(opline)->result.u.var).tmp_var.value.lval = 0; + } + break; + } + + if (variable == &tmp) { + zval_dtor(&tmp); + } + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + + NEXT_OPCODE(); +} + + +int zend_isset_isempty_dim_obj_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval **container = get_obj_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_R TSRMLS_CC); + zval *offset = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); + zval **value = NULL; + int result = 0; + + if (container) { + if ((*container)->type == IS_ARRAY) { + HashTable *ht; + int isset = 0; + + ht = (*container)->value.ht; + + switch (offset->type) { + case IS_DOUBLE: + case IS_RESOURCE: + case IS_BOOL: + case IS_LONG: + { + long index; + + if (offset->type == IS_DOUBLE) { + index = (long) offset->value.lval; } else { - ht = NULL; - if((*container)->type == IS_OBJECT) { - Z_OBJ_HT_P(*container)->unset_property(*container, offset TSRMLS_CC); - } + index = offset->value.lval; } - if (ht) { - switch (offset->type) { - case IS_DOUBLE: - case IS_RESOURCE: - case IS_BOOL: - case IS_LONG: - { - long index; - - if (offset->type == IS_DOUBLE) { - index = (long) offset->value.lval; - } else { - index = offset->value.lval; - } - - if (unset_object) { - if (zend_hash_index_find(ht, index, (void **)&object) == FAILURE) { - zend_error(E_ERROR, "Cannot delete non-existing object"); - } - if (Z_TYPE_PP(object) != IS_OBJECT) { - zend_error(E_ERROR, "Cannot call delete on non-object type"); - } - Z_OBJ_HT_PP(object)->delete_obj(*object TSRMLS_CC); - } - - zend_hash_index_del(ht, index); - break; - } - case IS_STRING: - if (unset_object) { - if (zend_hash_find(ht, offset->value.str.val, offset->value.str.len+1, (void **)&object) == FAILURE) { - zend_error(E_ERROR, "Cannot delete non-existing object"); - } - if (Z_TYPE_PP(object) != IS_OBJECT) { - zend_error(E_ERROR, "Cannot call delete on non-object type"); - } - Z_OBJ_HT_PP(object)->delete_obj(*object TSRMLS_CC); - } - - zend_hash_del(ht, offset->value.str.val, offset->value.str.len+1); - break; - case IS_NULL: - if (unset_object) { - if (zend_hash_find(ht, "", sizeof(""), (void **)&object) == FAILURE) { - zend_error(E_ERROR, "Cannot delete non-existing object"); - } - if (Z_TYPE_PP(object) != IS_OBJECT) { - zend_error(E_ERROR, "Cannot call delete on non-object type"); - } - Z_OBJ_HT_PP(object)->delete_obj(*object TSRMLS_CC); - } - - zend_hash_del(ht, "", sizeof("")); - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - break; - } + if (zend_hash_index_find(ht, index, (void **) &value) == SUCCESS) { + isset = 1; } - } else { - /* overloaded element */ + break; } - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - } - NEXT_OPCODE(); - case ZEND_FE_RESET: { - zval *array_ptr, **array_ptr_ptr; - HashTable *fe_ht; + case IS_STRING: + if (zend_hash_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) { + isset = 1; + } + break; + case IS_NULL: + if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) { + isset = 1; + } + break; + default: + zend_error(E_WARNING, "Illegal offset type in unset"); - if (EX(opline)->extended_value) { - array_ptr_ptr = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_R); - if (array_ptr_ptr == NULL) { - MAKE_STD_ZVAL(array_ptr); - } else { - SEPARATE_ZVAL_IF_NOT_REF(array_ptr_ptr); - array_ptr = *array_ptr_ptr; - array_ptr->refcount++; - } + break; + } + + switch (EX(opline)->extended_value) { + case ZEND_ISSET: + if (isset && Z_TYPE_PP(value) == IS_NULL) { + result = 0; } else { - array_ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - if (EG(free_op1)) { /* IS_TMP_VAR */ - zval *tmp; - - ALLOC_ZVAL(tmp); - *tmp = *array_ptr; - INIT_PZVAL(tmp); - array_ptr = tmp; - } else { - array_ptr->refcount++; - } + result = isset; } - PZVAL_LOCK(array_ptr); - EX(Ts)[EX(opline)->result.u.var].var.ptr = array_ptr; - EX(Ts)[EX(opline)->result.u.var].var.ptr_ptr = &EX(Ts)[EX(opline)->result.u.var].var.ptr; - - if ((fe_ht = HASH_OF(array_ptr)) != NULL) { - /* probably redundant */ - zend_hash_internal_pointer_reset(fe_ht); + break; + case ZEND_ISEMPTY: + if (!isset || !zend_is_true(*value)) { + result = 0; } else { - /* JMP to the end of foreach - TBD */ + result = 1; } - } - NEXT_OPCODE(); - case ZEND_FE_FETCH: { - zval *array = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - zval *result = &EX(Ts)[EX(opline)->result.u.var].tmp_var; - zval **value, *key; - char *str_key; - ulong int_key; - HashTable *fe_ht; - - PZVAL_LOCK(array); - - fe_ht = HASH_OF(array); - if (!fe_ht) { - zend_error(E_WARNING, "Invalid argument supplied for foreach()"); - EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num; - continue; - } else if (zend_hash_get_current_data(fe_ht, (void **) &value)==FAILURE) { - EX(opline) = op_array->opcodes+EX(opline)->op2.u.opline_num; - continue; + break; + } + } else if ((*container)->type == IS_OBJECT) { + result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (EX(opline)->extended_value == ZEND_ISEMPTY) TSRMLS_CC); + } else if ((*container)->type == IS_STRING) { /* string offsets */ + switch (EX(opline)->extended_value) { + case ZEND_ISSET: + if (offset->value.lval <= Z_STRLEN_PP(container)) { + result = 1; + } + break; + case ZEND_ISEMPTY: + if (offset->value.lval <= Z_STRLEN_PP(container) && Z_STRVAL_PP(container)[offset->value.lval] != '0') { + result = 1; } - array_init(result); + break; + } + } + } + + EX_T(EX(opline)->result.u.var).tmp_var.type = IS_BOOL; + switch (EX(opline)->extended_value) { + case ZEND_ISSET: + EX_T(EX(opline)->result.u.var).tmp_var.value.lval = result; + break; + case ZEND_ISEMPTY: + EX_T(EX(opline)->result.u.var).tmp_var.value.lval = !result; + break; + } - (*value)->refcount++; - zend_hash_index_update(result->value.ht, 0, value, sizeof(zval *), NULL); + FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - ALLOC_ZVAL(key); - INIT_PZVAL(key); - switch (zend_hash_get_current_key(fe_ht, &str_key, &int_key, 1)) { - case HASH_KEY_IS_STRING: - key->value.str.val = str_key; - key->value.str.len = strlen(str_key); - key->type = IS_STRING; - break; - case HASH_KEY_IS_LONG: - key->value.lval = int_key; - key->type = IS_LONG; - break; - EMPTY_SWITCH_DEFAULT_CASE() - } - zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL); - zend_hash_move_forward(fe_ht); - } - NEXT_OPCODE(); - case ZEND_JMP_NO_CTOR: { - zval *object_zval; - zend_function *constructor; + NEXT_OPCODE(); +} - if (EX(opline)->op1.op_type == IS_VAR) { - PZVAL_LOCK(*EX(Ts)[EX(opline)->op1.u.var].var.ptr_ptr); - } - - object_zval = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - constructor = Z_OBJ_HT_P(object_zval)->get_constructor(object_zval TSRMLS_CC); - EX(fbc_constructor) = NULL; - if (constructor == NULL) { - EX(opline) = op_array->opcodes + EX(opline)->op2.u.opline_num; - continue; - } else { - EX(fbc_constructor) = constructor; - } - - } - NEXT_OPCODE(); - case ZEND_ISSET_ISEMPTY_VAR: - { - zval tmp, *variable = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - zval **value; - zend_bool isset = 1; - HashTable *target_symbol_table; - - target_symbol_table = zend_get_target_symbol_table(EX(opline), EX(Ts), BP_VAR_IS TSRMLS_CC); +int zend_exit_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if (EX(opline)->op1.op_type != IS_UNUSED) { + zval *ptr; - if (variable->type != IS_STRING) { - tmp = *variable; - zval_copy_ctor(&tmp); - convert_to_string(&tmp); - variable = &tmp; - } - - if (zend_hash_find(target_symbol_table, variable->value.str.val, variable->value.str.len+1, (void **) &value) == FAILURE) { - isset = 0; - } - - EX(Ts)[EX(opline)->result.u.var].tmp_var.type = IS_BOOL; + ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + if (Z_TYPE_P(ptr) == IS_LONG) { + EG(exit_status) = Z_LVAL_P(ptr); + } else { + zend_print_variable(ptr); + } + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + } + zend_bailout(); + NEXT_OPCODE(); +} - switch (EX(opline)->extended_value) { - case ZEND_ISSET: - if (isset && Z_TYPE_PP(value) == IS_NULL) { - EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = 0; - } else { - EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = isset; - } - break; - case ZEND_ISEMPTY: - if (!isset || !zend_is_true(*value)) { - EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = 1; - } else { - EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = 0; - } - break; - } - if (variable == &tmp) { - zval_dtor(&tmp); - } - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); - } - NEXT_OPCODE(); - case ZEND_ISSET_ISEMPTY_DIM_OBJ: - { - zval **container = get_zval_ptr_ptr(&EX(opline)->op1, EX(Ts), BP_VAR_R); - zval *offset = get_zval_ptr(&EX(opline)->op2, EX(Ts), &EG(free_op2), BP_VAR_R); - zval **value = NULL; - int result = 0; - - if (container) { - - if((*container)->type == IS_ARRAY) { - HashTable *ht; - int isset = 0; - - ht = (*container)->value.ht; - - switch (offset->type) { - case IS_DOUBLE: - case IS_RESOURCE: - case IS_BOOL: - case IS_LONG: - { - long index; - - if (offset->type == IS_DOUBLE) { - index = (long) offset->value.lval; - } else { - index = offset->value.lval; - } - if (zend_hash_index_find(ht, index, (void **) &value) == SUCCESS) { - isset = 1; - } - break; - } - case IS_STRING: - if (zend_hash_find(ht, offset->value.str.val, offset->value.str.len+1, (void **) &value) == SUCCESS) { - isset = 1; - } - break; - case IS_NULL: - if (zend_hash_find(ht, "", sizeof(""), (void **) &value) == SUCCESS) { - isset = 1; - } - break; - default: - zend_error(E_WARNING, "Illegal offset type in unset"); - - break; - } - - switch (EX(opline)->extended_value) { - case ZEND_ISSET: - if (isset && Z_TYPE_PP(value) == IS_NULL) { - result = 0; - } else { - result = isset; - } - break; - case ZEND_ISEMPTY: - if (!isset || !zend_is_true(*value)) { - result = 0; - } else { - result = 1; - } - break; - } - } else { - if((*container)->type == IS_OBJECT) { - result = Z_OBJ_HT_P(*container)->has_property(*container, offset, (EX(opline)->extended_value == ZEND_ISEMPTY) TSRMLS_CC); - } - } - } else { - /* string offsets */ - } - - EX(Ts)[EX(opline)->result.u.var].tmp_var.type = IS_BOOL; +int zend_begin_silence_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + EX_T(EX(opline)->result.u.var).tmp_var.value.lval = EG(error_reporting); + EX_T(EX(opline)->result.u.var).tmp_var.type = IS_LONG; /* shouldn't be necessary */ + zend_alter_ini_entry("error_reporting", sizeof("error_reporting"), "0", 1, ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME); + NEXT_OPCODE(); +} - switch (EX(opline)->extended_value) { - case ZEND_ISSET: - EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = result; - break; - case ZEND_ISEMPTY: - EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = !result; - break; - } - FREE_OP(EX(Ts), &EX(opline)->op2, EG(free_op2)); - } - NEXT_OPCODE(); - break; - case ZEND_EXIT: - if (EX(opline)->op1.op_type != IS_UNUSED) { - zval *ptr; - - ptr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); - if (Z_TYPE_P(ptr) == IS_LONG) { - EG(exit_status) = Z_LVAL_P(ptr); - } else { - zend_print_variable(ptr); - } - FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); - } - zend_bailout(); - NEXT_OPCODE(); - case ZEND_BEGIN_SILENCE: - EX(Ts)[EX(opline)->result.u.var].tmp_var.value.lval = EG(error_reporting); - EX(Ts)[EX(opline)->result.u.var].tmp_var.type = IS_LONG; /* shouldn't be necessary */ - EG(error_reporting) = 0; - NEXT_OPCODE(); - case ZEND_END_SILENCE: - EG(error_reporting) = EX(Ts)[EX(opline)->op1.u.var].tmp_var.value.lval; - NEXT_OPCODE(); - case ZEND_QM_ASSIGN: { - zval *value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); +int zend_raise_abstract_error_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zend_error(E_ERROR, "Cannot call abstract method %s::%s()", EG(scope)->name, op_array->function_name); + NEXT_OPCODE(); /* Never reached */ +} - EX(Ts)[EX(opline)->result.u.var].tmp_var = *value; - if (!EG(free_op1)) { - zval_copy_ctor(&EX(Ts)[EX(opline)->result.u.var].tmp_var); - } - } - NEXT_OPCODE(); - case ZEND_EXT_STMT: - if (!EG(no_extensions)) { - zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, op_array TSRMLS_CC); - } - NEXT_OPCODE(); - case ZEND_EXT_FCALL_BEGIN: - if (!EG(no_extensions)) { - zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, op_array TSRMLS_CC); - } - NEXT_OPCODE(); - case ZEND_EXT_FCALL_END: - if (!EG(no_extensions)) { - zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, op_array TSRMLS_CC); - } - NEXT_OPCODE(); - case ZEND_DECLARE_FUNCTION_OR_CLASS: - do_bind_function_or_class(EX(opline), EG(function_table), EG(class_table), 0); - NEXT_OPCODE(); - case ZEND_TICKS: - if (++EG(ticks_count)==EX(opline)->op1.u.constant.value.lval) { - EG(ticks_count)=0; - if (zend_ticks_function) { - zend_ticks_function(EX(opline)->op1.u.constant.value.lval); - } - } - NEXT_OPCODE(); - case ZEND_EXT_NOP: - case ZEND_NOP: - NEXT_OPCODE(); - EMPTY_SWITCH_DEFAULT_CASE() + +int zend_end_silence_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval restored_error_reporting; + + restored_error_reporting.type = IS_LONG; + restored_error_reporting.value.lval = EX_T(EX(opline)->op1.u.var).tmp_var.value.lval; + convert_to_string(&restored_error_reporting); + zend_alter_ini_entry("error_reporting", sizeof("error_reporting"), Z_STRVAL(restored_error_reporting), Z_STRLEN(restored_error_reporting), ZEND_INI_USER, ZEND_INI_STAGE_RUNTIME); + zendi_zval_dtor(restored_error_reporting); + NEXT_OPCODE(); +} + + +int zend_qm_assign_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *value = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + + EX_T(EX(opline)->result.u.var).tmp_var = *value; + if (!EG(free_op1)) { + zval_copy_ctor(&EX_T(EX(opline)->result.u.var).tmp_var); + } + NEXT_OPCODE(); +} + + +int zend_ext_stmt_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if (!EG(no_extensions)) { + zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_statement_handler, op_array TSRMLS_CC); + } + NEXT_OPCODE(); +} + + +int zend_ext_fcall_begin_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if (!EG(no_extensions)) { + zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_begin_handler, op_array TSRMLS_CC); + } + NEXT_OPCODE(); +} + + +int zend_ext_fcall_end_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if (!EG(no_extensions)) { + zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_fcall_end_handler, op_array TSRMLS_CC); + } + NEXT_OPCODE(); +} + + +int zend_declare_class_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + do_bind_class(EX(opline), EG(function_table), EG(class_table)); + NEXT_OPCODE(); +} + + +int zend_declare_inherited_class_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + do_bind_inherited_class(EX(opline), EG(function_table), EG(class_table), EX_T(EX(opline)->extended_value).EA.class_entry); + NEXT_OPCODE(); +} + + +int zend_declare_function_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + do_bind_function(EX(opline), EG(function_table), EG(class_table), 0); + NEXT_OPCODE(); +} + + +int zend_ticks_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + if (++EG(ticks_count)>=EX(opline)->op1.u.constant.value.lval) { + EG(ticks_count)=0; + if (zend_ticks_function) { + zend_ticks_function(EX(opline)->op1.u.constant.value.lval); } } - zend_error(E_ERROR, "Arrived at end of main loop which shouldn't happen"); + NEXT_OPCODE(); +} + + +int zend_instanceof_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + zval *expr = get_zval_ptr(&EX(opline)->op1, EX(Ts), &EG(free_op1), BP_VAR_R); + instanceof_function(&EX_T(EX(opline)->result.u.var).tmp_var, expr, + EX_T(EX(opline)->op2.u.var).EA.class_entry TSRMLS_CC); + FREE_OP(EX(Ts), &EX(opline)->op1, EG(free_op1)); + NEXT_OPCODE(); +} + + +int zend_ext_nop_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + NEXT_OPCODE(); +} + + +int zend_nop_handler(ZEND_OPCODE_HANDLER_ARGS) +{ + NEXT_OPCODE(); +} + + +void zend_init_opcodes_handlers() +{ + zend_opcode_handlers[ZEND_NOP] = zend_nop_handler; + zend_opcode_handlers[ZEND_ADD] = zend_add_handler; + zend_opcode_handlers[ZEND_SUB] = zend_sub_handler; + zend_opcode_handlers[ZEND_MUL] = zend_mul_handler; + zend_opcode_handlers[ZEND_DIV] = zend_div_handler; + zend_opcode_handlers[ZEND_MOD] = zend_mod_handler; + zend_opcode_handlers[ZEND_SL] = zend_sl_handler; + zend_opcode_handlers[ZEND_SR] = zend_sr_handler; + zend_opcode_handlers[ZEND_CONCAT] = zend_concat_handler; + zend_opcode_handlers[ZEND_BW_OR] = zend_bw_or_handler; + zend_opcode_handlers[ZEND_BW_AND] = zend_bw_and_handler; + zend_opcode_handlers[ZEND_BW_XOR] = zend_bw_xor_handler; + zend_opcode_handlers[ZEND_BW_NOT] = zend_bw_not_handler; + zend_opcode_handlers[ZEND_BOOL_NOT] = zend_bool_not_handler; + zend_opcode_handlers[ZEND_BOOL_XOR] = zend_bool_xor_handler; + zend_opcode_handlers[ZEND_IS_IDENTICAL] = zend_is_identical_handler; + zend_opcode_handlers[ZEND_IS_NOT_IDENTICAL] = zend_is_not_identical_handler; + zend_opcode_handlers[ZEND_IS_EQUAL] = zend_is_equal_handler; + zend_opcode_handlers[ZEND_IS_NOT_EQUAL] = zend_is_not_equal_handler; + zend_opcode_handlers[ZEND_IS_SMALLER] = zend_is_smaller_handler; + zend_opcode_handlers[ZEND_IS_SMALLER_OR_EQUAL] = zend_is_smaller_or_equal_handler; + zend_opcode_handlers[ZEND_CAST] = zend_cast_handler; + zend_opcode_handlers[ZEND_QM_ASSIGN] = zend_qm_assign_handler; + + zend_opcode_handlers[ZEND_ASSIGN_ADD] = zend_assign_add_handler; + zend_opcode_handlers[ZEND_ASSIGN_SUB] = zend_assign_sub_handler; + zend_opcode_handlers[ZEND_ASSIGN_MUL] = zend_assign_mul_handler; + zend_opcode_handlers[ZEND_ASSIGN_DIV] = zend_assign_div_handler; + zend_opcode_handlers[ZEND_ASSIGN_MOD] = zend_assign_mod_handler; + zend_opcode_handlers[ZEND_ASSIGN_SL] = zend_assign_sl_handler; + zend_opcode_handlers[ZEND_ASSIGN_SR] = zend_assign_sr_handler; + zend_opcode_handlers[ZEND_ASSIGN_CONCAT] = zend_assign_concat_handler; + zend_opcode_handlers[ZEND_ASSIGN_BW_OR] = zend_assign_bw_or_handler; + zend_opcode_handlers[ZEND_ASSIGN_BW_AND] = zend_assign_bw_and_handler; + zend_opcode_handlers[ZEND_ASSIGN_BW_XOR] = zend_assign_bw_xor_handler; + + zend_opcode_handlers[ZEND_PRE_INC] = zend_pre_inc_handler; + zend_opcode_handlers[ZEND_PRE_DEC] = zend_pre_dec_handler; + zend_opcode_handlers[ZEND_POST_INC] = zend_post_inc_handler; + zend_opcode_handlers[ZEND_POST_DEC] = zend_post_dec_handler; + + zend_opcode_handlers[ZEND_ASSIGN] = zend_assign_handler; + zend_opcode_handlers[ZEND_ASSIGN_REF] = zend_assign_ref_handler; + + zend_opcode_handlers[ZEND_ECHO] = zend_echo_handler; + zend_opcode_handlers[ZEND_PRINT] = zend_print_handler; + + zend_opcode_handlers[ZEND_JMP] = zend_jmp_handler; + zend_opcode_handlers[ZEND_JMPZ] = zend_jmpz_handler; + zend_opcode_handlers[ZEND_JMPNZ] = zend_jmpnz_handler; + zend_opcode_handlers[ZEND_JMPZNZ] = zend_jmpznz_handler; + zend_opcode_handlers[ZEND_JMPZ_EX] = zend_jmpz_ex_handler; + zend_opcode_handlers[ZEND_JMPNZ_EX] = zend_jmpnz_ex_handler; + zend_opcode_handlers[ZEND_CASE] = zend_case_handler; + zend_opcode_handlers[ZEND_SWITCH_FREE] = zend_switch_free_handler; + zend_opcode_handlers[ZEND_BRK] = zend_brk_handler; + zend_opcode_handlers[ZEND_CONT] = zend_cont_handler; + zend_opcode_handlers[ZEND_BOOL] = zend_bool_handler; + + zend_opcode_handlers[ZEND_INIT_STRING] = zend_init_string_handler; + zend_opcode_handlers[ZEND_ADD_CHAR] = zend_add_char_handler; + zend_opcode_handlers[ZEND_ADD_STRING] = zend_add_string_handler; + zend_opcode_handlers[ZEND_ADD_VAR] = zend_add_var_handler; + + zend_opcode_handlers[ZEND_BEGIN_SILENCE] = zend_begin_silence_handler; + zend_opcode_handlers[ZEND_END_SILENCE] = zend_end_silence_handler; + + zend_opcode_handlers[ZEND_INIT_FCALL_BY_NAME] = zend_init_fcall_by_name_handler; + zend_opcode_handlers[ZEND_DO_FCALL] = zend_do_fcall_handler; + zend_opcode_handlers[ZEND_DO_FCALL_BY_NAME] = zend_do_fcall_by_name_handler; + zend_opcode_handlers[ZEND_RETURN] = zend_return_handler; + + zend_opcode_handlers[ZEND_RECV] = zend_recv_handler; + zend_opcode_handlers[ZEND_RECV_INIT] = zend_recv_init_handler; + + zend_opcode_handlers[ZEND_SEND_VAL] = zend_send_val_handler; + zend_opcode_handlers[ZEND_SEND_VAR] = zend_send_var_handler; + zend_opcode_handlers[ZEND_SEND_REF] = zend_send_ref_handler; + + zend_opcode_handlers[ZEND_NEW] = zend_new_handler; + zend_opcode_handlers[ZEND_JMP_NO_CTOR] = zend_jmp_no_ctor_handler; + zend_opcode_handlers[ZEND_FREE] = zend_free_handler; + + zend_opcode_handlers[ZEND_INIT_ARRAY] = zend_init_array_handler; + zend_opcode_handlers[ZEND_ADD_ARRAY_ELEMENT] = zend_add_array_element_handler; + + zend_opcode_handlers[ZEND_INCLUDE_OR_EVAL] = zend_include_or_eval_handler; + + zend_opcode_handlers[ZEND_UNSET_VAR] = zend_unset_var_handler; + zend_opcode_handlers[ZEND_UNSET_DIM_OBJ] = zend_unset_dim_obj_handler; + + zend_opcode_handlers[ZEND_FE_RESET] = zend_fe_reset_handler; + zend_opcode_handlers[ZEND_FE_FETCH] = zend_fe_fetch_handler; + + zend_opcode_handlers[ZEND_EXIT] = zend_exit_handler; + + zend_opcode_handlers[ZEND_FETCH_R] = zend_fetch_r_handler; + zend_opcode_handlers[ZEND_FETCH_DIM_R] = zend_fetch_dim_r_handler; + zend_opcode_handlers[ZEND_FETCH_OBJ_R] = zend_fetch_obj_r_handler; + zend_opcode_handlers[ZEND_FETCH_W] = zend_fetch_w_handler; + zend_opcode_handlers[ZEND_FETCH_DIM_W] = zend_fetch_dim_w_handler; + zend_opcode_handlers[ZEND_FETCH_OBJ_W] = zend_fetch_obj_w_handler; + zend_opcode_handlers[ZEND_FETCH_RW] = zend_fetch_rw_handler; + zend_opcode_handlers[ZEND_FETCH_DIM_RW] = zend_fetch_dim_rw_handler; + zend_opcode_handlers[ZEND_FETCH_OBJ_RW] = zend_fetch_obj_rw_handler; + zend_opcode_handlers[ZEND_FETCH_IS] = zend_fetch_is_handler; + zend_opcode_handlers[ZEND_FETCH_DIM_IS] = zend_fetch_dim_is_handler; + zend_opcode_handlers[ZEND_FETCH_OBJ_IS] = zend_fetch_obj_is_handler; + zend_opcode_handlers[ZEND_FETCH_FUNC_ARG] = zend_fetch_func_arg_handler; + zend_opcode_handlers[ZEND_FETCH_DIM_FUNC_ARG] = zend_fetch_dim_func_arg_handler; + zend_opcode_handlers[ZEND_FETCH_OBJ_FUNC_ARG] = zend_fetch_obj_func_arg_handler; + zend_opcode_handlers[ZEND_FETCH_UNSET] = zend_fetch_unset_handler; + zend_opcode_handlers[ZEND_FETCH_DIM_UNSET] = zend_fetch_dim_unset_handler; + zend_opcode_handlers[ZEND_FETCH_OBJ_UNSET] = zend_fetch_obj_unset_handler; + + zend_opcode_handlers[ZEND_FETCH_DIM_TMP_VAR] = zend_fetch_dim_tmp_var_handler; + zend_opcode_handlers[ZEND_FETCH_CONSTANT] = zend_fetch_constant_handler; + + zend_opcode_handlers[ZEND_EXT_STMT] = zend_ext_stmt_handler; + zend_opcode_handlers[ZEND_EXT_FCALL_BEGIN] = zend_ext_fcall_begin_handler; + zend_opcode_handlers[ZEND_EXT_FCALL_END] = zend_ext_fcall_end_handler; + zend_opcode_handlers[ZEND_EXT_NOP] = zend_ext_nop_handler; + + zend_opcode_handlers[ZEND_TICKS] = zend_ticks_handler; + + zend_opcode_handlers[ZEND_SEND_VAR_NO_REF] = zend_send_var_no_ref_handler; + + zend_opcode_handlers[ZEND_CATCH] = zend_catch_handler; + zend_opcode_handlers[ZEND_THROW] = zend_throw_handler; + + zend_opcode_handlers[ZEND_FETCH_CLASS] = zend_fetch_class_handler; + + zend_opcode_handlers[ZEND_CLONE] = zend_clone_handler; + + zend_opcode_handlers[ZEND_INIT_CTOR_CALL] = zend_init_ctor_call_handler; + zend_opcode_handlers[ZEND_INIT_METHOD_CALL] = zend_init_method_call_handler; + zend_opcode_handlers[ZEND_INIT_STATIC_METHOD_CALL] = zend_init_static_method_call_handler; + + zend_opcode_handlers[ZEND_ISSET_ISEMPTY_VAR] = zend_isset_isempty_var_handler; + zend_opcode_handlers[ZEND_ISSET_ISEMPTY_DIM_OBJ] = zend_isset_isempty_dim_obj_handler; + + zend_opcode_handlers[ZEND_IMPORT_FUNCTION] = zend_import_function_handler; + zend_opcode_handlers[ZEND_IMPORT_CLASS] = zend_import_class_handler; + zend_opcode_handlers[ZEND_IMPORT_CONST] = zend_import_const_handler; + + zend_opcode_handlers[ZEND_ASSIGN_ADD_OBJ] = zend_assign_add_obj_handler; + zend_opcode_handlers[ZEND_ASSIGN_SUB_OBJ] = zend_assign_sub_obj_handler; + zend_opcode_handlers[ZEND_ASSIGN_MUL_OBJ] = zend_assign_mul_obj_handler; + zend_opcode_handlers[ZEND_ASSIGN_DIV_OBJ] = zend_assign_div_obj_handler; + zend_opcode_handlers[ZEND_ASSIGN_MOD_OBJ] = zend_assign_mod_obj_handler; + zend_opcode_handlers[ZEND_ASSIGN_SL_OBJ] = zend_assign_sl_obj_handler; + zend_opcode_handlers[ZEND_ASSIGN_SR_OBJ] = zend_assign_sr_obj_handler; + zend_opcode_handlers[ZEND_ASSIGN_CONCAT_OBJ] = zend_assign_concat_obj_handler; + zend_opcode_handlers[ZEND_ASSIGN_BW_OR_OBJ] = zend_assign_bw_or_obj_handler; + zend_opcode_handlers[ZEND_ASSIGN_BW_AND_OBJ] = zend_assign_bw_and_obj_handler; + zend_opcode_handlers[ZEND_ASSIGN_BW_XOR_OBJ] = zend_assign_bw_xor_obj_handler; + + zend_opcode_handlers[ZEND_PRE_INC_OBJ] = zend_pre_inc_obj_handler; + zend_opcode_handlers[ZEND_PRE_DEC_OBJ] = zend_pre_dec_obj_handler; + zend_opcode_handlers[ZEND_POST_INC_OBJ] = zend_post_inc_obj_handler; + zend_opcode_handlers[ZEND_POST_DEC_OBJ] = zend_post_dec_obj_handler; + + zend_opcode_handlers[ZEND_ASSIGN_OBJ] = zend_assign_obj_handler; + zend_opcode_handlers[ZEND_OP_DATA] = NULL; + + zend_opcode_handlers[ZEND_INSTANCEOF] = zend_instanceof_handler; + + zend_opcode_handlers[ZEND_DECLARE_CLASS] = zend_declare_class_handler; + zend_opcode_handlers[ZEND_DECLARE_INHERITED_CLASS] = zend_declare_inherited_class_handler; + zend_opcode_handlers[ZEND_DECLARE_FUNCTION] = zend_declare_function_handler; + + zend_opcode_handlers[ZEND_RAISE_ABSTRACT_ERROR] = zend_raise_abstract_error_handler; } + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.5 +21 -2 ZendEngine2/zend_execute.h Index: zend_execute.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_execute.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_execute.h 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_execute.h 11 Feb 2003 02:40:18 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_execute.h,v 1.51 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_EXECUTE_H #define ZEND_EXECUTE_H @@ -49,11 +50,14 @@ } temp_variable; +BEGIN_EXTERN_C() ZEND_API extern void (*zend_execute)(zend_op_array *op_array TSRMLS_DC); +ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); void init_executor(TSRMLS_D); void shutdown_executor(TSRMLS_D); ZEND_API void execute(zend_op_array *op_array TSRMLS_DC); +ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); ZEND_API int zend_is_true(zval *op); static inline void safe_free_zval_ptr(zval *p) { @@ -63,7 +67,7 @@ FREE_ZVAL(p); } } - +ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC); ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC); static inline int i_zend_is_true(zval *op) @@ -161,4 +165,19 @@ #define IS_OVERLOADED_OBJECT 1 #define IS_STRING_OFFSET 2 +/* The following tries to resolve the classname of a zval of type object. + * Since it is slow it should be only used in error messages. + */ +#define Z_OBJ_CLASS_NAME_P(zval) ((zval) && (zval)->type == IS_OBJECT && Z_OBJ_HT_P(zval)->get_class_entry != NULL && Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC) ? Z_OBJ_HT_P(zval)->get_class_entry(zval TSRMLS_CC)->name : "") + +END_EXTERN_C() + #endif /* ZEND_EXECUTE_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.6 +168 -37 ZendEngine2/zend_execute_API.c Index: zend_execute_API.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_execute_API.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- zend_execute_API.c 3 Aug 2002 08:56:16 -0000 1.5 +++ zend_execute_API.c 11 Feb 2003 02:40:18 -0000 1.6 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_execute_API.c,v 1.194 2003/02/10 09:45:27 zeev Exp $ */ #include <stdio.h> #include <signal.h> @@ -34,6 +35,7 @@ ZEND_API void (*zend_execute)(zend_op_array *op_array TSRMLS_DC); +ZEND_API void (*zend_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); #ifdef ZEND_WIN32 #include <process.h> @@ -113,6 +115,8 @@ void init_executor(TSRMLS_D) { INIT_ZVAL(EG(uninitialized_zval)); +/* trick to make uninitialized_zval never be modified, passed by ref, etc. */ + EG(uninitialized_zval).refcount++; INIT_ZVAL(EG(error_zval)); EG(uninitialized_zval_ptr)=&EG(uninitialized_zval); EG(error_zval_ptr)=&EG(error_zval); @@ -126,6 +130,7 @@ EG(symtable_cache_ptr) = EG(symtable_cache)-1; EG(symtable_cache_limit)=EG(symtable_cache)+SYMTABLE_CACHE_SIZE-1; EG(no_extensions)=0; + EG(implicit_clone)=0; EG(function_table) = CG(function_table); EG(class_table) = CG(class_table); @@ -158,9 +163,9 @@ EG(user_error_handler) = NULL; zend_ptr_stack_init(&EG(user_error_handlers)); + zend_ptr_stack_init(&EG(user_exception_handlers)); - EG(orig_error_reporting) = EG(error_reporting); - zend_objects_init(&EG(objects), 1024); + zend_objects_store_init(&EG(objects_store), 1024); EG(full_tables_cleanup) = 0; #ifdef ZEND_WIN32 @@ -177,21 +182,31 @@ EG(current_execute_data) = NULL; EG(This) = NULL; + + EG(float_separator)[0] = '.'; } void shutdown_executor(TSRMLS_D) { zend_try { - zend_objects_call_destructors(&EG(objects) TSRMLS_CC); - zend_ptr_stack_destroy(&EG(arg_types_stack)); - - while (EG(symtable_cache_ptr)>=EG(symtable_cache)) { + +/* Removed because this can not be safely done, e.g. in this situation: + Object 1 creates object 2 + Object 3 holds reference to object 2. + Now when 1 and 2 are destroyed, 3 can still access 2 in its destructor, with + very problematic results */ +/* zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); */ + +/* Moved after symbol table cleaners, because some of the cleaners can call + destructors, which would use EG(symtable_cache_ptr) and thus leave leaks */ +/* while (EG(symtable_cache_ptr)>=EG(symtable_cache)) { zend_hash_destroy(*EG(symtable_cache_ptr)); efree(*EG(symtable_cache_ptr)); EG(symtable_cache_ptr)--; } +*/ zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator TSRMLS_CC); zend_hash_destroy(&EG(symbol_table)); @@ -204,6 +219,17 @@ zend_ptr_stack_destroy(&EG(argument_stack)); + /* Cleanup static data for functions and arrays. + We need separate cleanup stage because of the following problem: + Suppose we destroy class X, which destroys function table, + and in function table we have function foo() that has static $bar. Now if + object of class X is assigned to $bar, its destructor will be called and will + fail since X's function table is in mid-destruction. + So we want first of all to clean up all data and then move to tables destruction. + Note that only run-time accessed data need to be cleaned up, pre-defined data can + not contain objects and thus are not probelmatic */ + zend_hash_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data TSRMLS_CC); + zend_hash_apply(EG(class_table), (apply_func_t) zend_cleanup_class_data TSRMLS_CC); /* Destroy all op arrays */ if (EG(full_tables_cleanup)) { zend_hash_apply(EG(function_table), (apply_func_t) is_not_internal_function TSRMLS_CC); @@ -212,15 +238,24 @@ zend_hash_reverse_apply(EG(function_table), (apply_func_t) is_not_internal_function TSRMLS_CC); zend_hash_reverse_apply(EG(class_table), (apply_func_t) is_not_internal_class TSRMLS_CC); } + + while (EG(symtable_cache_ptr)>=EG(symtable_cache)) { + zend_hash_destroy(*EG(symtable_cache_ptr)); + efree(*EG(symtable_cache_ptr)); + EG(symtable_cache_ptr)--; + } + } zend_end_try(); + + zend_try { + clean_non_persistent_constants(TSRMLS_C); } zend_end_try(); - /* The regular list must be destroyed after the main symbol table and - * op arrays are destroyed. + /* The regular list must be destroyed after the main symbol table, + * op arrays, and constants are destroyed. */ zend_destroy_rsrc_list(&EG(regular_list) TSRMLS_CC); zend_try { - clean_non_persistent_constants(TSRMLS_C); #if ZEND_DEBUG signal(SIGSEGV, original_sigsegv_handler); #endif @@ -232,11 +267,18 @@ FREE_ZVAL(EG(user_error_handler)); } + if (EG(user_exception_handler)) { + zval_dtor(EG(user_exception_handler)); + FREE_ZVAL(EG(user_exception_handler)); + } + zend_ptr_stack_clean(&EG(user_error_handlers), ZVAL_DESTRUCTOR, 1); zend_ptr_stack_destroy(&EG(user_error_handlers)); - EG(error_reporting) = EG(orig_error_reporting); - zend_objects_destroy(&EG(objects)); + zend_ptr_stack_clean(&EG(user_exception_handlers), ZVAL_DESTRUCTOR, 1); + zend_ptr_stack_destroy(&EG(user_exception_handlers)); + + zend_objects_store_destroy(&EG(objects_store)); } zend_end_try(); } @@ -246,7 +288,7 @@ if (!zend_is_executing(TSRMLS_C)) { return NULL; } - switch(EG(function_state_ptr)->function->type) { + switch (EG(function_state_ptr)->function->type) { case ZEND_USER_FUNCTION: { char *function_name = ((zend_op_array *) EG(function_state_ptr)->function)->function_name; @@ -331,13 +373,30 @@ if (strchr(p->value.str.val, ':')) { char *cur, *temp; char *last; - zend_class_entry *ce; + zend_class_entry **ce; zval **value; last = tsrm_strtok_r(p->value.str.val, ":", &temp); - if (zend_hash_find(EG(class_table), last, strlen(last)+1, (void **)&ce) == FAILURE) { - zend_error(E_ERROR, "Invalid class! Improve this error message"); + if (strcasecmp(last, "self")==0) { + if (EG(scope)) { + last = EG(scope)->name; + } else { + zend_error(E_ERROR, "Cannot access self:: when no class scope is active"); + } + } else if (strcasecmp(last, "parent")==0) { + if (!EG(scope)) { + zend_error(E_ERROR, "Cannot access parent:: when no class scope is active"); + } else if (!EG(scope)->parent) { + zend_error(E_ERROR, "Cannot access parent:: when current class scope has no parent"); + } else { + last = EG(scope)->parent->name; + } + } + + + if (zend_lookup_class(last, strlen(last), &ce TSRMLS_CC) == FAILURE) { + zend_error(E_ERROR, "Undefined class '%s'", last); } last = tsrm_strtok_r(NULL, ":", &temp); @@ -347,13 +406,13 @@ if (!cur) { break; } - if (zend_hash_find(&ce->class_table, last, strlen(last)+1, (void **)&ce) == FAILURE) { - zend_error(E_ERROR, "Invalid class! Improve this error message"); + if (zend_hash_find(&(*ce)->class_table, last, strlen(last)+1, (void **)&ce) == FAILURE) { + zend_error(E_ERROR, "Undefined sub-class '%s'", last); } last = cur; } - if (zend_hash_find(&ce->constants_table, last, strlen(last)+1, (void **) &value) == FAILURE) { - zend_error(E_ERROR, "Invalid class! Improve this error message"); + if (zend_hash_find(&(*ce)->constants_table, last, strlen(last)+1, (void **) &value) == FAILURE) { + zend_error(E_ERROR, "Undefined class constant '%s'", last); } const_value = **value; zval_copy_ctor(&const_value); @@ -406,6 +465,15 @@ zend_hash_move_forward(p->value.ht); continue; } + + if (const_value.type == IS_STRING && const_value.value.str.len == str_index_len-1 && + !strncmp(const_value.value.str.val, str_index, str_index_len)) { + /* constant value is the same as its name */ + zval_dtor(&const_value); + zend_hash_move_forward(p->value.ht); + continue; + } + switch (const_value.type) { case IS_STRING: zend_hash_update(p->value.ht, const_value.value.str.val, const_value.value.str.len+1, element, sizeof(zval *), NULL); @@ -417,6 +485,7 @@ break; } zend_hash_del(p->value.ht, str_index, str_index_len); + zval_dtor(&const_value); } zend_hash_apply_with_argument(p->value.ht, (apply_func_arg_t) zval_update_constant, (void *) 1 TSRMLS_CC); } @@ -450,11 +519,10 @@ int i; zval **original_return_value; HashTable *calling_symbol_table; - zend_function_state function_state; zend_function_state *original_function_state_ptr; zend_op_array *original_op_array; zend_op **original_opline_ptr; - int orig_free_op1, orig_free_op2; + zval *orig_free_op1, *orig_free_op2; int (*orig_unary_op)(zval *result, zval *op1); int (*orig_binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC); zval function_name_copy; @@ -462,6 +530,14 @@ zend_class_entry *calling_scope = NULL; zval *current_this; + zend_execute_data execute_data; + + /* Initialize execute_data */ + EX(fbc) = NULL; + EX(object) = NULL; + EX(Ts) = NULL; + EX(op_array) = NULL; + EX(opline) = NULL; *retval_ptr_ptr = NULL; if (function_name->type==IS_ARRAY) { /* assume array($obj, $name) couple */ @@ -486,12 +562,13 @@ if (object_pp) { /* TBI!! new object handlers */ if (Z_TYPE_PP(object_pp) == IS_OBJECT) { - if(!IS_ZEND_STD_OBJECT(**object_pp)) { - zend_error(E_WARNING, "Cannot use call_user_function on overloaded objects"); + if (!IS_ZEND_STD_OBJECT(**object_pp)) { + zend_error(E_WARNING, "Cannot use call_user_function on objects without a class entry"); return FAILURE; } function_table = &Z_OBJCE_PP(object_pp)->function_table; + EX(object) = *object_pp; calling_scope = Z_OBJCE_PP(object_pp); } else if (Z_TYPE_PP(object_pp) == IS_STRING) { zend_class_entry **ce; @@ -500,7 +577,7 @@ lc_class = estrndup(Z_STRVAL_PP(object_pp), Z_STRLEN_PP(object_pp)); zend_str_tolower(lc_class, Z_STRLEN_PP(object_pp)); - found = zend_hash_find(EG(class_table), lc_class, Z_STRLEN_PP(object_pp) + 1, (void **) &ce); + found = zend_lookup_class(lc_class, Z_STRLEN_PP(object_pp), &ce TSRMLS_CC); efree(lc_class); if (found == FAILURE) return FAILURE; @@ -521,7 +598,7 @@ zend_str_tolower(function_name_copy.value.str.val, function_name_copy.value.str.len); original_function_state_ptr = EG(function_state_ptr); - if (zend_hash_find(function_table, function_name_copy.value.str.val, function_name_copy.value.str.len+1, (void **) &function_state.function)==FAILURE) { + if (zend_hash_find(function_table, function_name_copy.value.str.val, function_name_copy.value.str.len+1, (void **) &EX(function_state).function)==FAILURE) { zval_dtor(&function_name_copy); return FAILURE; } @@ -530,9 +607,9 @@ for (i=0; i<param_count; i++) { zval *param; - if (function_state.function->common.arg_types - && i<function_state.function->common.arg_types[0] - && function_state.function->common.arg_types[i+1]==BYREF_FORCE + if (EX(function_state).function->common.arg_types + && i<EX(function_state).function->common.arg_types[0] + && EX(function_state).function->common.arg_types[i+1]==BYREF_FORCE && !PZVAL_IS_REF(*params[i])) { if ((*params[i])->refcount>1) { zval *new_zval; @@ -563,7 +640,7 @@ zend_ptr_stack_n_push(&EG(argument_stack), 2, (void *) (long) param_count, NULL); - EG(function_state_ptr) = &function_state; + EG(function_state_ptr) = &EX(function_state); current_scope = EG(scope); EG(scope) = calling_scope; @@ -588,8 +665,10 @@ EG(This) = NULL; } + EX(prev_execute_data) = EG(current_execute_data); + EG(current_execute_data) = &execute_data; - if (function_state.function->type == ZEND_USER_FUNCTION) { + if (EX(function_state).function->type == ZEND_USER_FUNCTION) { calling_symbol_table = EG(active_symbol_table); if (symbol_table) { EG(active_symbol_table) = symbol_table; @@ -601,7 +680,7 @@ original_return_value = EG(return_value_ptr_ptr); original_op_array = EG(active_op_array); EG(return_value_ptr_ptr) = retval_ptr_ptr; - EG(active_op_array) = (zend_op_array *) function_state.function; + EG(active_op_array) = (zend_op_array *) EX(function_state).function; original_opline_ptr = EG(opline_ptr); orig_free_op1 = EG(free_op1); orig_free_op2 = EG(free_op2); @@ -622,7 +701,7 @@ EG(binary_op) = orig_binary_op; } else { ALLOC_INIT_ZVAL(*retval_ptr_ptr); - ((zend_internal_function *) function_state.function)->handler(param_count, *retval_ptr_ptr, (object_pp?*object_pp:NULL), 1 TSRMLS_CC); + ((zend_internal_function *) EX(function_state).function)->handler(param_count, *retval_ptr_ptr, (object_pp?*object_pp:NULL), 1 TSRMLS_CC); INIT_PZVAL(*retval_ptr_ptr); } zend_ptr_stack_clear_multiple(TSRMLS_C); @@ -633,10 +712,53 @@ } EG(scope) = current_scope; EG(This) = current_this; - + EG(current_execute_data) = EX(prev_execute_data); \ + return SUCCESS; } +ZEND_API int zend_lookup_class(char *name, int name_length, zend_class_entry ***ce TSRMLS_DC) +{ + zval **args[1]; + zval *autoload_function; + zval *class_name; + zval *retval_ptr; + int retval; + + if (EG(scope)) { + if (zend_hash_find(&EG(scope)->class_table, name, name_length+1, (void **) ce) == SUCCESS) { + return SUCCESS; + } + } + if (zend_hash_find(EG(class_table), name, name_length+1, (void **) ce) == SUCCESS) { + return SUCCESS; + } + + MAKE_STD_ZVAL(autoload_function); + ZVAL_STRINGL(autoload_function, "__autoload", sizeof("__autoload")-1, 1); + + MAKE_STD_ZVAL(class_name); + ZVAL_STRINGL(class_name, name, name_length, 1); + args[0] = &class_name; + + retval = call_user_function_ex(EG(function_table), NULL, autoload_function, &retval_ptr, 1, args, 0, NULL TSRMLS_CC); + + zval_ptr_dtor(&autoload_function); + zval_ptr_dtor(&class_name); + + if (retval == FAILURE) { + return FAILURE; + } + + if (EG(exception)) { + zend_error(E_ERROR, "__autoload threw an exception"); + } + + /* If an exception is thrown retval_ptr will be NULL but we bailout before we reach this point */ + zval_ptr_dtor(&retval_ptr); + + return zend_hash_find(EG(class_table), name, name_length + 1, (void **) ce); +} ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSRMLS_DC) { @@ -759,9 +881,10 @@ { TSRMLS_FETCH(); - /* is there any point in this? we're terminating the request anyway... - PG(connection_status) |= PHP_CONNECTION_TIMEOUT; - */ + if (zend_on_timeout) { + zend_on_timeout(EG(timeout_seconds) TSRMLS_CC); + } + zend_error(E_ERROR, "Maximum execution time of %d second%s exceeded", EG(timeout_seconds), EG(timeout_seconds) == 1 ? "" : "s"); } @@ -911,3 +1034,11 @@ # endif #endif } + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +29 -0 ZendEngine2/zend_execute_locks.h Index: zend_execute_locks.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_execute_locks.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_execute_locks.h 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_execute_locks.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -1,3 +1,24 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | licen****@zend***** so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans <andi****@zend*****> | + | Zeev Suraski <zeev****@zend*****> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: zend_execute_locks.h,v 1.9 2003/02/01 01:49:14 sniper Exp $ */ + #ifndef ZEND_EXECUTE_LOCKS_H #define ZEND_EXECUTE_LOCKS_H @@ -30,3 +51,11 @@ #define SELECTIVE_PZVAL_LOCK(pzv, pzn) if (!((pzn)->u.EA.type & EXT_TYPE_UNUSED)) { PZVAL_LOCK(pzv); } #endif /* ZEND_EXECUTE_LOCKS_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +72 -2 ZendEngine2/zend_extensions.c Index: zend_extensions.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_extensions.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_extensions.c 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_extensions.c 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_extensions.c,v 1.43 2003/02/01 01:49:14 sniper Exp $ */ #include "zend_extensions.h" @@ -33,7 +34,7 @@ handle = DL_LOAD(path); if (!handle) { #ifndef ZEND_WIN32 - fprintf(stderr, "Failed loading %s: %s\n", path, dlerror()); + fprintf(stderr, "Failed loading %s: %s\n", path, DL_ERROR()); #else fprintf(stderr, "Failed loading %s\n", path); #endif @@ -216,3 +217,72 @@ } return NULL; } + +/* + * Support for dynamic loading of MH_BUNDLEs on Darwin / Mac OS X + * + */ + +#if HAVE_MACH_O_DYLD_H + +void *zend_mh_bundle_load(char* bundle_path) +{ + NSObjectFileImage bundle_image; + NSModule bundle_handle; + NSSymbol bundle_init_nssymbol; + void (*bundle_init)(void); + + if (NSCreateObjectFileImageFromFile(bundle_path, &bundle_image) != NSObjectFileImageSuccess) { + return NULL; + } + + bundle_handle = NSLinkModule(bundle_image, bundle_path, NSLINKMODULE_OPTION_PRIVATE); + NSDestroyObjectFileImage(bundle_image); + + /* call the init function of the bundle */ + bundle_init_nssymbol = NSLookupSymbolInModule(bundle_handle, "__init"); + if (bundle_init_nssymbol != NULL) { + bundle_init = NSAddressOfSymbol(bundle_init_nssymbol); + bundle_init(); + } + + return bundle_handle; +} + +int zend_mh_bundle_unload(void *bundle_handle) +{ + NSSymbol bundle_fini_nssymbol; + void (*bundle_fini)(void); + + /* call the fini function of the bundle */ + bundle_fini_nssymbol = NSLookupSymbolInModule(bundle_handle, "__fini"); + if (bundle_fini_nssymbol != NULL) { + bundle_fini = NSAddressOfSymbol(bundle_fini_nssymbol); + bundle_fini(); + } + + return (int) NSUnLinkModule(bundle_handle, NULL); +} + +void *zend_mh_bundle_symbol(void *bundle_handle, const char *symbol_name) +{ + NSSymbol symbol; + symbol = NSLookupSymbolInModule(bundle_handle, symbol_name); + return NSAddressOfSymbol(symbol); +} + +const char *zend_mh_bundle_error(void) +{ + /* Witness the state of the art error reporting */ + return NULL; +} + +#endif /* HAVE_MACH_O_DYLD_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +11 -2 ZendEngine2/zend_extensions.h Index: zend_extensions.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_extensions.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_extensions.h 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_extensions.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,13 +17,14 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_extensions.h,v 1.51 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_EXTENSIONS_H #define ZEND_EXTENSIONS_H #include "zend_compile.h" -#define ZEND_EXTENSION_API_NO 20010710 +#define ZEND_EXTENSION_API_NO 90021012 typedef struct _zend_extension_version_info { int zend_extension_api_no; @@ -114,3 +115,11 @@ ZEND_API zend_extension *zend_get_extension(char *extension_name); #endif /* ZEND_EXTENSIONS_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.5 +4 -2 ZendEngine2/zend_fast_cache.h Index: zend_fast_cache.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_fast_cache.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_fast_cache.h 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_fast_cache.h 11 Feb 2003 02:40:18 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_fast_cache.h,v 1.17 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_FAST_CACHE_H #define ZEND_FAST_CACHE_H @@ -25,7 +26,7 @@ # if ZEND_DEBUG # define ZEND_ENABLE_FAST_CACHE 0 # else -# define ZEND_ENABLE_FAST_CACHE 1 +# define ZEND_ENABLE_FAST_CACHE 0 # endif #endif @@ -136,5 +137,6 @@ * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.6 +34 -5 ZendEngine2/zend_globals.h Index: zend_globals.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_globals.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- zend_globals.h 3 Aug 2002 08:56:16 -0000 1.5 +++ zend_globals.h 11 Feb 2003 02:40:18 -0000 1.6 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_globals.h,v 1.117 2003/02/07 10:05:36 zeev Exp $ */ #ifndef ZEND_GLOBALS_H #define ZEND_GLOBALS_H @@ -32,6 +33,7 @@ #include "zend_llist.h" #include "zend_fast_cache.h" #include "zend_objects.h" +#include "zend_objects_API.h" /* Define ZTS if you want a thread-safe Zend */ /*#undef ZTS*/ @@ -118,9 +120,13 @@ int interactive; + zend_uint start_lineno; + zend_bool in_clone_method; zend_bool increment_lineno; zend_llist import_commands; + + zend_uint access_type; }; @@ -172,6 +178,7 @@ zend_bool in_execution; zend_bool bailout_set; zend_bool full_tables_cleanup; + zend_bool implicit_clone; /* for extended information support */ zend_bool no_extensions; @@ -184,7 +191,7 @@ HashTable persistent_list; zend_ptr_stack argument_stack; - int free_op1, free_op2; + zval *free_op1, *free_op2; int (*unary_op)(zval *result, zval *op1); int (*binary_op)(zval *result, zval *op1, zval *op2 TSRMLS_DC); @@ -192,26 +199,33 @@ int garbage_ptr; zval *user_error_handler; + zval *user_exception_handler; zend_ptr_stack user_error_handlers; + zend_ptr_stack user_exception_handlers; /* timeout support */ int timeout_seconds; int lambda_count; - HashTable ini_directives; - zend_objects objects; + HashTable *ini_directives; + zend_objects_store objects_store; zval *exception; struct _zend_execute_data *current_execute_data; + zend_property_info std_property_info; + + /* locale stuff */ + char float_separator[1]; + void *reserved[ZEND_MAX_RESERVED_RESOURCES]; }; +#include "zend_mm.h" struct _zend_alloc_globals { zend_mem_header *head; /* standard list */ - zend_mem_header *phead; /* persistent list */ void *cache[MAX_CACHED_MEMORY][MAX_CACHED_ENTRIES]; unsigned int cache_count[MAX_CACHED_MEMORY]; void *fast_cache_list_head[MAX_FAST_CACHE_TYPES]; @@ -231,6 +245,9 @@ unsigned int allocated_memory_peak; unsigned char memory_exhausted; #endif +#ifdef ZEND_MM + zend_mm_heap mm_heap; +#endif }; struct _zend_scanner_globals { @@ -242,6 +259,7 @@ char *c_buf_p; int init; int start; + int lineno; char _yy_hold_char; int yy_n_chars; int _yy_did_buffer_switch_on_eof; @@ -251,6 +269,17 @@ char *_yy_last_accepting_cpos; int _yy_more_flag; int _yy_more_len; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; }; #endif /* ZEND_GLOBALS_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +9 -1 ZendEngine2/zend_globals_macros.h Index: zend_globals_macros.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_globals_macros.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_globals_macros.h 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_globals_macros.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_globals_macros.h,v 1.19 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_GLOBALS_MACROS_H #define ZEND_GLOBALS_MACROS_H @@ -107,3 +108,10 @@ #endif /* ZEND_GLOBALS_MACROS_H */ +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +69 -41 ZendEngine2/zend_hash.c Index: zend_hash.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_hash.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_hash.c 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_hash.c 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,15 +17,10 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_hash.c,v 1.99 2003/02/06 00:14:49 zeev Exp $ */ #include "zend.h" -#include <stdio.h> - -#ifdef HAVE_STDLIB_H -# include <stdlib.h> -#endif - #define HANDLE_NUMERIC(key, length, func) { \ register char *tmp=key; \ \ @@ -84,7 +79,7 @@ if (ht->inconsistent==HT_OK) { return; } - switch (ht->inconsistent) { + switch (ht->inconsistent) { case HT_IS_DESTROYING: zend_output_debug_string(1, "%s(%d) : ht=0x%08x is being destroyed", file, line, ht); break; @@ -94,7 +89,7 @@ case HT_CLEANING: zend_output_debug_string(1, "%s(%d) : ht=0x%08x is being cleaned", file, line, ht); break; - } + } zend_bailout(); } #define IS_CONSISTENT(a) _zend_is_inconsistent(a, __FILE__, __LINE__); @@ -161,7 +156,7 @@ } -ZEND_API int zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent) +ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC) { uint i = 3; @@ -175,7 +170,11 @@ ht->nTableMask = ht->nTableSize - 1; /* Uses ecalloc() so that Bucket* == NULL */ - ht->arBuckets = (Bucket **) pecalloc(ht->nTableSize, sizeof(Bucket *), persistent); + if (persistent) { + ht->arBuckets = (Bucket **) calloc(ht->nTableSize, sizeof(Bucket *)); + } else { + ht->arBuckets = (Bucket **) ecalloc_rel(ht->nTableSize, sizeof(Bucket *)); + } if (!ht->arBuckets) { return FAILURE; @@ -194,9 +193,9 @@ } -ZEND_API int zend_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection) +ZEND_API int _zend_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC) { - int retval = zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent); + int retval = _zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent ZEND_FILE_LINE_CC); ht->bApplyProtection = bApplyProtection; return retval; @@ -289,11 +288,8 @@ IS_CONSISTENT(ht); - if (nKeyLength <= 0) { -#if ZEND_DEBUG - ZEND_PUTS("zend_hash_update: Can't put in empty key\n"); -#endif - return FAILURE; + if (nKeyLength == 0) { + return zend_hash_index_update(ht, h, pData, nDataSize, pDest); } nIndex = h & ht->nTableMask; @@ -393,7 +389,7 @@ } UPDATE_DATA(ht, p, pData, nDataSize); HANDLE_UNBLOCK_INTERRUPTIONS(); - if (h >= ht->nNextFreeElement) { + if ((long)h >= (long)ht->nNextFreeElement) { ht->nNextFreeElement = h + 1; } if (pDest) { @@ -421,7 +417,7 @@ CONNECT_TO_GLOBAL_DLLIST(p, ht); HANDLE_UNBLOCK_INTERRUPTIONS(); - if (h >= ht->nNextFreeElement) { + if ((long)h >= (long)ht->nNextFreeElement) { ht->nNextFreeElement = h + 1; } ht->nNumOfElements++; @@ -724,9 +720,9 @@ HASH_PROTECT_RECURSION(ht); - va_start(args, num_args); p = ht->pListHead; while (p != NULL) { + va_start(args, num_args); hash_key.arKey = p->arKey; hash_key.nKeyLength = p->nKeyLength; hash_key.h = p->h; @@ -735,8 +731,8 @@ } else { p = p->pListNext; } + va_end(args); } - va_end(args); HASH_UNPROTECT_RECURSION(ht); } @@ -820,30 +816,30 @@ } -ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, zend_bool (*pReplaceOrig)(void *orig, void *p_new)) +static zend_bool zend_hash_replace_checker_wrapper(HashTable *target, void *source_data, Bucket *p, void *pParam, merge_checker_func_t merge_checker_func) +{ + zend_hash_key hash_key; + + hash_key.arKey = p->arKey; + hash_key.nKeyLength = p->nKeyLength; + hash_key.h = p->h; + return merge_checker_func(target, source_data, &hash_key, pParam); +} + + +ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam) { Bucket *p; void *t; - void *pOrig; IS_CONSISTENT(source); IS_CONSISTENT(target); p = source->pListHead; while (p) { - if (p->nKeyLength>0) { - if (zend_hash_find(target, p->arKey, p->nKeyLength, &pOrig)==FAILURE - || pReplaceOrig(pOrig, p->pData)) { - if (zend_hash_update(target, p->arKey, p->nKeyLength, p->pData, size, &t)==SUCCESS && pCopyConstructor) { - pCopyConstructor(t); - } - } - } else { - if (zend_hash_index_find(target, p->h, &pOrig)==FAILURE - || pReplaceOrig(pOrig, p->pData)) { - if (zend_hash_index_update(target, p->h, p->pData, size, &t)==SUCCESS && pCopyConstructor) { - pCopyConstructor(t); - } + if (zend_hash_replace_checker_wrapper(target, p->pData, p, pParam, pMergeSource)) { + if (zend_hash_quick_update(target, p->arKey, p->nKeyLength, p->h, p->pData, size, &t)==SUCCESS && pCopyConstructor) { + pCopyConstructor(t); } } p = p->pListNext; @@ -852,10 +848,8 @@ } -ZEND_API ulong zend_get_hash_value(HashTable *ht, char *arKey, uint nKeyLength) +ZEND_API ulong zend_get_hash_value(char *arKey, uint nKeyLength) { - IS_CONSISTENT(ht); - return zend_inline_hash_func(arKey, nKeyLength); } @@ -896,6 +890,10 @@ uint nIndex; Bucket *p; + if (nKeyLength==0) { + return zend_hash_index_find(ht, h, pData); + } + IS_CONSISTENT(ht); nIndex = h & ht->nTableMask; @@ -940,6 +938,35 @@ } +ZEND_API int zend_hash_quick_exists(HashTable *ht, char *arKey, uint nKeyLength, ulong h) +{ + uint nIndex; + Bucket *p; + + if (nKeyLength==0) { + return zend_hash_index_exists(ht, h); + } + + IS_CONSISTENT(ht); + + HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_exists(ht, idx)); + + nIndex = h & ht->nTableMask; + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && (p->nKeyLength == nKeyLength)) { + if (!memcmp(p->arKey, arKey, nKeyLength)) { + return 1; + } + } + p = p->pNext; + } + return 0; + +} + + ZEND_API int zend_hash_index_find(HashTable *ht, ulong h, void **pData) { uint nIndex; @@ -1115,7 +1142,7 @@ IS_CONSISTENT(ht); - if (ht->nNumOfElements <= 1) { /* Doesn't require sorting */ + if (!(ht->nNumOfElements>1) && !(renumber && ht->nNumOfElements>0)) { /* Doesn't require sorting */ return SUCCESS; } arTmp = (Bucket **) pemalloc(ht->nNumOfElements * sizeof(Bucket *), ht->persistent); @@ -1322,5 +1349,6 @@ * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.5 +87 -17 ZendEngine2/zend_hash.h Index: zend_hash.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_hash.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_hash.h 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_hash.h 11 Feb 2003 02:40:18 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,10 +17,13 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_hash.h,v 1.66 2003/02/06 00:14:49 zeev Exp $ */ + #ifndef ZEND_HASH_H #define ZEND_HASH_H #include <sys/types.h> +#include "zend.h" #define HASH_KEY_IS_STRING 1 #define HASH_KEY_IS_LONG 2 @@ -38,6 +41,7 @@ typedef void (*sort_func_t)(void *, size_t, register size_t, compare_func_t TSRMLS_DC); typedef void (*dtor_func_t)(void *pDest); typedef void (*copy_ctor_func_t)(void *pElement); +typedef void (*copy_ctor_param_func_t)(void *pElement, void *pParam); struct _hashtable; @@ -71,15 +75,27 @@ #endif } HashTable; + +typedef struct _zend_hash_key { + char *arKey; + uint nKeyLength; + ulong h; +} zend_hash_key; + + +typedef zend_bool (*merge_checker_func_t)(HashTable *target_ht, void *source_data, zend_hash_key *hash_key, void *pParam); + typedef Bucket* HashPosition; BEGIN_EXTERN_C() /* startup/shutdown */ -ZEND_API int zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent); -ZEND_API int zend_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection); +ZEND_API int _zend_hash_init(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent ZEND_FILE_LINE_DC); +ZEND_API int _zend_hash_init_ex(HashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC); ZEND_API void zend_hash_destroy(HashTable *ht); ZEND_API void zend_hash_clean(HashTable *ht); +#define zend_hash_init(ht, nSize, pHashFunction, pDestructor, persistent) _zend_hash_init((ht), (nSize), (pHashFunction), (pDestructor), (persistent) ZEND_FILE_LINE_CC) +#define zend_hash_init_ex(ht, nSize, pHashFunction, pDestructor, persistent, bApplyProtection) _zend_hash_init_ex((ht), (nSize), (pHashFunction), (pDestructor), (persistent), (bApplyProtection) ZEND_FILE_LINE_CC) /* additions/updates/changes */ ZEND_API int zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag); @@ -107,12 +123,6 @@ #define ZEND_HASH_APPLY_REMOVE 1<<0 #define ZEND_HASH_APPLY_STOP 1<<1 -typedef struct _zend_hash_key { - char *arKey; - uint nKeyLength; - ulong h; -} zend_hash_key; - typedef int (*apply_func_t)(void *pDest TSRMLS_DC); typedef int (*apply_func_arg_t)(void *pDest, void *argument TSRMLS_DC); @@ -140,7 +150,7 @@ #define zend_hash_index_del(ht, h) \ zend_hash_del_key_or_index(ht, NULL, 0, h, HASH_DEL_INDEX) -ZEND_API ulong zend_get_hash_value(HashTable *ht, char *arKey, uint nKeyLength); +ZEND_API ulong zend_get_hash_value(char *arKey, uint nKeyLength); /* Data retreival */ ZEND_API int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData); @@ -149,6 +159,7 @@ /* Misc */ ZEND_API int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLength); +ZEND_API int zend_hash_quick_exists(HashTable *ht, char *arKey, uint nKeyLength, ulong h); ZEND_API int zend_hash_index_exists(HashTable *ht, ulong h); ZEND_API ulong zend_hash_next_free_element(HashTable *ht); @@ -179,7 +190,7 @@ /* Copying, merging and sorting */ ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size); ZEND_API void zend_hash_merge(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite); -ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, zend_bool (*pReplaceOrig)(void *orig, void *p_new)); +ZEND_API void zend_hash_merge_ex(HashTable *target, HashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam); ZEND_API int zend_hash_sort(HashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber TSRMLS_DC); ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC); ZEND_API int zend_hash_minmax(HashTable *ht, compare_func_t compar, int flag, void **pData TSRMLS_DC); @@ -188,18 +199,69 @@ ZEND_API int zend_hash_rehash(HashTable *ht); +/* + * DJBX33A (Daniel J. Bernstein, Times 33 with Addition) + * + * This is Daniel J. Bernstein's popular `times 33' hash function as + * posted by him years ago on comp.lang.c. It basically uses a function + * like ``hash(i) = hash(i-1) * 33 + str[i]''. This is one of the best + * known hash functions for strings. Because it is both computed very + * fast and distributes very well. + * + * The magic of number 33, i.e. why it works better than many other + * constants, prime or not, has never been adequately explained by + * anyone. So I try an explanation: if one experimentally tests all + * multipliers between 1 and 256 (as RSE did now) one detects that even + * numbers are not useable at all. The remaining 128 odd numbers + * (except for the number 1) work more or less all equally well. They + * all distribute in an acceptable way and this way fill a hash table + * with an average percent of approx. 86%. + * + * If one compares the Chi^2 values of the variants, the number 33 not + * even has the best value. But the number 33 and a few other equally + * good numbers like 17, 31, 63, 127 and 129 have nevertheless a great + * advantage to the remaining numbers in the large set of possible + * multipliers: their multiply operation can be replaced by a faster + * operation based on just one shift plus either a single addition + * or subtraction operation. And because a hash function has to both + * distribute good _and_ has to be very fast to compute, those few + * numbers should be preferred and seems to be the reason why Daniel J. + * Bernstein also preferred it. + * + * + * -- Ralf S. Engelschall <rse****@engel*****> + */ + static inline ulong zend_inline_hash_func(char *arKey, uint nKeyLength) { - ulong h = 5381; - char *arEnd = arKey + nKeyLength; + register ulong hash = 5381; - while (arKey < arEnd) { - h += (h << 5); - h ^= (ulong) *arKey++; + /* variant with the hash unrolled eight times */ + for (; nKeyLength >= 8; nKeyLength -= 8) { + hash = ((hash << 5) + hash) + *arKey++; + hash = ((hash << 5) + hash) + *arKey++; + hash = ((hash << 5) + hash) + *arKey++; + hash = ((hash << 5) + hash) + *arKey++; + hash = ((hash << 5) + hash) + *arKey++; + hash = ((hash << 5) + hash) + *arKey++; + hash = ((hash << 5) + hash) + *arKey++; + hash = ((hash << 5) + hash) + *arKey++; + } + switch (nKeyLength) { + case 7: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */ + case 6: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */ + case 5: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */ + case 4: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */ + case 3: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */ + case 2: hash = ((hash << 5) + hash) + *arKey++; /* fallthrough... */ + case 1: hash = ((hash << 5) + hash) + *arKey++; break; + case 0: break; +EMPTY_SWITCH_DEFAULT_CASE() } - return h; + return hash; } + ZEND_API ulong zend_hash_func(char *arKey, uint nKeyLength); #if ZEND_DEBUG @@ -218,3 +280,11 @@ #endif /* ZEND_HASH_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.4 +9 -6 ZendEngine2/zend_highlight.c Index: zend_highlight.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_highlight.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- zend_highlight.c 19 May 2002 23:06:12 -0000 1.3 +++ zend_highlight.c 11 Feb 2003 02:40:18 -0000 1.4 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_highlight.c,v 1.33 2003/02/01 01:49:14 sniper Exp $ */ #include "zend.h" #include "zend_language_parser.h" @@ -53,7 +54,7 @@ } -ZEND_API void zend_html_puts(const char *s, uint len) +ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC) { const char *ptr=s, *end=s+len; @@ -113,7 +114,7 @@ in_string = !in_string; break; case T_WHITESPACE: - zend_html_puts(LANG_SCNG(yy_text), LANG_SCNG(yy_leng)); /* no color needed */ + zend_html_puts(LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC); /* no color needed */ token.type = 0; continue; break; @@ -141,10 +142,10 @@ } switch (token_type) { case T_END_HEREDOC: - zend_html_puts(token.value.str.val, token.value.str.len); + zend_html_puts(token.value.str.val, token.value.str.len TSRMLS_CC); break; default: - zend_html_puts(LANG_SCNG(yy_text), LANG_SCNG(yy_leng)); + zend_html_puts(LANG_SCNG(yy_text), LANG_SCNG(yy_leng) TSRMLS_CC); break; } @@ -190,7 +191,7 @@ switch (token_type) { case T_COMMENT: token.type = 0; - break; + continue; case T_WHITESPACE: if (token.type) { @@ -239,9 +240,11 @@ token.type = 0; } } + /* * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.4 +11 -2 ZendEngine2/zend_highlight.h Index: zend_highlight.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_highlight.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- zend_highlight.h 19 May 2002 23:06:12 -0000 1.3 +++ zend_highlight.h 11 Feb 2003 02:40:18 -0000 1.4 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_highlight.h,v 1.22 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_HIGHLIGHT_H #define ZEND_HIGHLIGHT_H @@ -44,9 +45,17 @@ ZEND_API int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini TSRMLS_DC); ZEND_API int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini, char *str_name TSRMLS_DC); ZEND_API void zend_html_putc(char c); -ZEND_API void zend_html_puts(const char *s, uint len); +ZEND_API void zend_html_puts(const char *s, uint len TSRMLS_DC); END_EXTERN_C() extern zend_syntax_highlighter_ini syntax_highlighter_ini; #endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +11 -2 ZendEngine2/zend_indent.c Index: zend_indent.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_indent.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_indent.c 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_indent.c 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_indent.c,v 1.20 2003/02/01 01:49:14 sniper Exp $ */ /* This indenter doesn't really work, it's here for no particular reason. */ @@ -80,7 +81,7 @@ default: if (token.type==0) { /* keyword */ - switch(token_type) { + switch (token_type) { case ',': ZEND_PUTS(", "); goto dflt_printout; @@ -145,3 +146,11 @@ token.type = 0; } } + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +10 -1 ZendEngine2/zend_indent.h Index: zend_indent.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_indent.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_indent.h 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_indent.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_indent.h,v 1.13 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_INDENT_H #define ZEND_INDENT_H @@ -24,3 +25,11 @@ ZEND_API void zend_indent(void); #endif /* ZEND_INDENT_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +55 -22 ZendEngine2/zend_ini.c Index: zend_ini.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_ini.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_ini.c 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_ini.c 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,8 +16,7 @@ +----------------------------------------------------------------------+ */ - -#include <stdlib.h> +/* $Id: zend_ini.c,v 1.28 2003/02/01 01:49:14 sniper Exp $ */ #include "zend.h" #include "zend_qsort.h" @@ -28,6 +27,8 @@ static HashTable *registered_zend_ini_directives; +#define NO_VALUE_PLAINTEXT "no value" +#define NO_VALUE_HTML "<i>no value</i>" /* * hash_apply functions @@ -63,7 +64,9 @@ */ ZEND_API int zend_ini_startup(TSRMLS_D) { - registered_zend_ini_directives = &EG(ini_directives); + registered_zend_ini_directives = (HashTable *) malloc(sizeof(HashTable)); + + EG(ini_directives) = registered_zend_ini_directives; if (zend_hash_init_ex(registered_zend_ini_directives, 100, NULL, NULL, 1, 0)==FAILURE) { return FAILURE; } @@ -73,29 +76,41 @@ ZEND_API int zend_ini_shutdown(TSRMLS_D) { - zend_hash_destroy(&EG(ini_directives)); + zend_hash_destroy(EG(ini_directives)); + free(EG(ini_directives)); + return SUCCESS; +} + + +ZEND_API int zend_ini_global_shutdown(TSRMLS_D) +{ + zend_hash_destroy(registered_zend_ini_directives); + free(registered_zend_ini_directives); return SUCCESS; } ZEND_API int zend_ini_deactivate(TSRMLS_D) { - zend_hash_apply_with_argument(&EG(ini_directives), (apply_func_arg_t) zend_restore_ini_entry_cb, (void *) ZEND_INI_STAGE_DEACTIVATE TSRMLS_CC); + zend_hash_apply_with_argument(EG(ini_directives), (apply_func_arg_t) zend_restore_ini_entry_cb, (void *) ZEND_INI_STAGE_DEACTIVATE TSRMLS_CC); return SUCCESS; } +#ifdef ZTS ZEND_API int zend_copy_ini_directives(TSRMLS_D) { zend_ini_entry ini_entry; - if (zend_hash_init_ex(&EG(ini_directives), registered_zend_ini_directives->nNumOfElements, NULL, NULL, 1, 0)==FAILURE) { + EG(ini_directives) = (HashTable *) malloc(sizeof(HashTable)); + if (zend_hash_init_ex(EG(ini_directives), registered_zend_ini_directives->nNumOfElements, NULL, NULL, 1, 0)==FAILURE) { return FAILURE; } - zend_hash_copy(&EG(ini_directives), registered_zend_ini_directives, NULL, &ini_entry, sizeof(zend_ini_entry)); + zend_hash_copy(EG(ini_directives), registered_zend_ini_directives, NULL, &ini_entry, sizeof(zend_ini_entry)); zend_ini_refresh_caches(ZEND_INI_STAGE_STARTUP TSRMLS_CC); return SUCCESS; } +#endif static int ini_key_compare(const void *a, const void *b TSRMLS_DC) @@ -120,7 +135,7 @@ ZEND_API void zend_ini_sort_entries(TSRMLS_D) { - zend_hash_sort(&EG(ini_directives), zend_qsort, ini_key_compare, 0 TSRMLS_CC); + zend_hash_sort(EG(ini_directives), zend_qsort, ini_key_compare, 0 TSRMLS_CC); } /* @@ -173,7 +188,7 @@ ZEND_API void zend_ini_refresh_caches(int stage TSRMLS_DC) { - zend_hash_apply_with_argument(&EG(ini_directives), (apply_func_arg_t) zend_ini_refresh_cache, (void *)(long) stage TSRMLS_CC); + zend_hash_apply_with_argument(EG(ini_directives), (apply_func_arg_t) zend_ini_refresh_cache, (void *)(long) stage TSRMLS_CC); } @@ -183,7 +198,7 @@ char *duplicate; TSRMLS_FETCH(); - if (zend_hash_find(&EG(ini_directives), name, name_length, (void **) &ini_entry)==FAILURE) { + if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==FAILURE) { return FAILURE; } @@ -217,7 +232,7 @@ zend_ini_entry *ini_entry; TSRMLS_FETCH(); - if (zend_hash_find(&EG(ini_directives), name, name_length, (void **) &ini_entry)==FAILURE) { + if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==FAILURE) { return FAILURE; } @@ -249,7 +264,7 @@ zend_ini_entry *ini_entry; TSRMLS_FETCH(); - if (zend_hash_find(&EG(ini_directives), name, name_length, (void **) &ini_entry)==SUCCESS) { + if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==SUCCESS) { if (orig && ini_entry->modified) { return (ini_entry->orig_value ? strtol(ini_entry->orig_value, NULL, 0) : 0); } else if (ini_entry->value) { @@ -266,7 +281,7 @@ zend_ini_entry *ini_entry; TSRMLS_FETCH(); - if (zend_hash_find(&EG(ini_directives), name, name_length, (void **) &ini_entry)==SUCCESS) { + if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==SUCCESS) { if (orig && ini_entry->modified) { return (double) (ini_entry->orig_value ? strtod(ini_entry->orig_value, NULL) : 0.0); } else if (ini_entry->value) { @@ -283,7 +298,7 @@ zend_ini_entry *ini_entry; TSRMLS_FETCH(); - if (zend_hash_find(&EG(ini_directives), name, name_length, (void **) &ini_entry)==SUCCESS) { + if (zend_hash_find(EG(ini_directives), name, name_length, (void **) &ini_entry)==SUCCESS) { if (orig && ini_entry->modified) { return ini_entry->orig_value; } else { @@ -308,15 +323,25 @@ display_string = ini_entry->orig_value; display_string_length = ini_entry->orig_value_length; } else { - display_string = "<i>no value</i>"; - display_string_length = sizeof("<i>no value</i>")-1; + if (zend_uv.html_errors) { + display_string = NO_VALUE_HTML; + display_string_length = sizeof(NO_VALUE_HTML)-1; + } else { + display_string = NO_VALUE_PLAINTEXT; + display_string_length = sizeof(NO_VALUE_PLAINTEXT)-1; + } } } else if (ini_entry->value && ini_entry->value[0]) { display_string = ini_entry->value; display_string_length = ini_entry->value_length; } else { - display_string = "<i>no value</i>"; - display_string_length = sizeof("<i>no value</i>")-1; + if (zend_uv.html_errors) { + display_string = NO_VALUE_HTML; + display_string_length = sizeof(NO_VALUE_HTML)-1; + } else { + display_string = NO_VALUE_PLAINTEXT; + display_string_length = sizeof(NO_VALUE_PLAINTEXT)-1; + } } ZEND_WRITE(display_string, display_string_length); } @@ -354,9 +379,17 @@ value = NULL; } if (value) { - zend_printf("<font color=\"%s\">%s</font>", value, value); + if (zend_uv.html_errors) { + zend_printf("<font style=\"color: %s\">%s</font>", value, value); + } else { + ZEND_PUTS(value); + } } else { - ZEND_PUTS("<i>no value</i>;"); + if (zend_uv.html_errors) { + ZEND_PUTS(NO_VALUE_HTML); + } else { + ZEND_PUTS(NO_VALUE_PLAINTEXT); + } } } @@ -478,10 +511,10 @@ return SUCCESS; } - /* * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.3 +12 -1 ZendEngine2/zend_ini.h Index: zend_ini.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_ini.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_ini.h 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_ini.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,6 +16,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_ini.h,v 1.26 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_INI_H #define ZEND_INI_H @@ -84,6 +85,7 @@ ZEND_API int zend_ini_startup(TSRMLS_D); ZEND_API int zend_ini_shutdown(TSRMLS_D); +ZEND_API int zend_ini_global_shutdown(TSRMLS_D); ZEND_API int zend_ini_deactivate(TSRMLS_D); ZEND_API int zend_copy_ini_directives(TSRMLS_D); @@ -190,6 +192,7 @@ int zend_parse_ini_file(zend_file_handle *fh, zend_bool unbuffered_errors, zend_ini_parser_cb_t ini_parser_cb, void *arg); #define ZEND_INI_PARSER_ENTRY 1 #define ZEND_INI_PARSER_SECTION 2 +#define ZEND_INI_PARSER_POP_ENTRY 3 typedef struct _zend_ini_parser_param { zend_ini_parser_cb_t ini_parser_cb; @@ -197,3 +200,11 @@ } zend_ini_parser_param; #endif /* ZEND_INI_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +13 -4 ZendEngine2/zend_ini_parser.y Index: zend_ini_parser.y =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_ini_parser.y,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_ini_parser.y 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_ini_parser.y 11 Feb 2003 02:40:18 -0000 1.3 @@ -17,8 +17,7 @@ +----------------------------------------------------------------------+ */ - -/* $Id: zend_ini_parser.y,v 1.16 2002/01/06 15:21:36 sebastian Exp $ */ +/* $Id: zend_ini_parser.y,v 1.22 2003/02/01 01:49:14 sniper Exp $ */ #define DEBUG_CFG_PARSER 0 #include "zend.h" @@ -57,7 +56,6 @@ #ifndef ZTS extern int ini_lex(zval *ini_lval TSRMLS_DC); extern FILE *ini_in; -extern int ini_lineno; extern void init_cfg_scanner(void); #endif @@ -141,7 +139,7 @@ fprintf(stderr, "PHP: %s", error_buf); #endif } else { - zend_error(E_CORE_WARNING, error_buf); + zend_error(E_WARNING, error_buf); } efree(error_buf); } @@ -179,6 +177,7 @@ %pure_parser %token TC_STRING %token TC_ENCAPSULATED_STRING +%token BRACK %token SECTION %token CFG_TRUE %token CFG_FALSE @@ -201,6 +200,14 @@ free($1.value.str.val); free($3.value.str.val); } + | TC_STRING BRACK '=' string_or_value { +#if DEBUG_CFG_PARSER + printf("'%s'[ ] = '%s'\n", $1.value.str.val, $4.value.str.val); +#endif + ZEND_INI_PARSER_CB(&$1, &$4, ZEND_INI_PARSER_POP_ENTRY, ZEND_INI_PARSER_ARG); + free($1.value.str.val); + free($4.value.str.val); + } | TC_STRING { ZEND_INI_PARSER_CB(&$1, NULL, ZEND_INI_PARSER_ENTRY, ZEND_INI_PARSER_ARG); free($1.value.str.val); } | SECTION { ZEND_INI_PARSER_CB(&$1, NULL, ZEND_INI_PARSER_SECTION, ZEND_INI_PARSER_ARG); free($1.value.str.val); } | '\n' @@ -228,9 +235,11 @@ constant_string: TC_STRING { zend_ini_get_constant(&$$, &$1); } ; + /* * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.3 +29 -0 ZendEngine2/zend_ini_scanner.h Index: zend_ini_scanner.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_ini_scanner.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_ini_scanner.h 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_ini_scanner.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -1,3 +1,24 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | licen****@zend***** so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans <andi****@zend*****> | + | Zeev Suraski <zeev****@zend*****> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: zend_ini_scanner.h,v 1.11 2003/02/01 01:49:14 sniper Exp $ */ + #ifndef _ZEND_INI_SCANNER_H #define _ZEND_INI_SCANNER_H @@ -10,3 +31,11 @@ END_EXTERN_C() #endif /* _ZEND_INI_SCANNER_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.5 +21 -10 ZendEngine2/zend_ini_scanner.l Index: zend_ini_scanner.l =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_ini_scanner.l,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_ini_scanner.l 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_ini_scanner.l 11 Feb 2003 02:40:18 -0000 1.5 @@ -17,6 +17,8 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_ini_scanner.l,v 1.28 2003/02/01 07:32:09 sebastian Exp $ */ + #define yyleng SCNG(yy_leng) #define yytext SCNG(yy_text) #define yytext_ptr SCNG(yy_text) @@ -49,15 +51,15 @@ static char *ini_filename; -void init_ini_scanner() +void init_ini_scanner(TSRMLS_D) { - ini_lineno=1; + SCNG(lineno)=1; } int zend_ini_scanner_get_lineno(TSRMLS_D) { - return ini_lineno; + return SCNG(lineno); } @@ -83,7 +85,7 @@ return FAILURE; } - init_ini_scanner(); + init_ini_scanner(TSRMLS_C); yyin = fp; yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE TSRMLS_CC) TSRMLS_CC); ini_filename = fh->filename; @@ -105,10 +107,12 @@ NEWLINE ("\r"|"\n"|"\r\n") %option noyywrap -%option yylineno %% +<INITIAL>[ ]*[\[][ ]*[\]][ ]* { + return BRACK; +} <INITIAL>[ ]*("true"|"on"|"yes")[ ]* { ini_lval->value.str.val = zend_strndup("1", 1); @@ -125,15 +129,17 @@ return CFG_FALSE; } -<INITIAL>[[][^[]+[\]]{NEWLINE}? { +<INITIAL>[[][^[]+[\]][ ]*{NEWLINE}? { /* SECTION */ - /* eat trailng ] */ - while (yyleng>0 && (yytext[yyleng-1]=='\n' || yytext[yyleng-1]=='\r' || yytext[yyleng-1]==']')) { + /* eat trailng and spaces ] */ + while (yyleng>0 && (yytext[yyleng-1]=='\n' || yytext[yyleng-1]=='\r' || yytext[yyleng-1]==']' || yytext[yyleng-1]==' ')) { yyleng--; yytext[yyleng]=0; } + SCNG(lineno)++; + /* eat leading [ */ yytext++; yyleng--; @@ -150,7 +156,7 @@ /* eat trailing " */ yytext[yyleng-1]=0; - + /* eat leading " */ yytext++; @@ -165,7 +171,7 @@ } -<INITIAL>[^=\n\r\t;|&~()!"]+ { +<INITIAL>[^=\n\r\t;|&~()!"\[]+ { /* STRING */ register int i; @@ -200,15 +206,20 @@ <INITIAL>[=\n] { + if (yytext[0] == '\n') { + SCNG(lineno)++; + } return yytext[0]; } <INITIAL>{NEWLINE} { + SCNG(lineno)++; return '\n'; } <INITIAL>[;][^\r\n]*{NEWLINE}? { /* comment */ + SCNG(lineno)++; return '\n'; } 1.3 +29 -0 ZendEngine2/zend_istdiostream.h Index: zend_istdiostream.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_istdiostream.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_istdiostream.h 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_istdiostream.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -1,3 +1,24 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | licen****@zend***** so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans <andi****@zend*****> | + | Zeev Suraski <zeev****@zend*****> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: zend_istdiostream.h,v 1.3 2003/02/01 01:49:14 sniper Exp $ */ + #ifndef _ZEND_STDIOSTREAM #define _ZEND_STDIOSTREAM @@ -13,3 +34,11 @@ #endif #endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.5 +110 -72 ZendEngine2/zend_language_parser.y Index: zend_language_parser.y =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_language_parser.y,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_language_parser.y 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_language_parser.y 11 Feb 2003 02:40:18 -0000 1.5 @@ -18,6 +18,8 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_language_parser.y,v 1.87 2003/02/10 12:46:58 zeev Exp $ */ + /* * LALR shift/reduce conflicts and how they are resolved: * @@ -67,7 +69,7 @@ %left '*' '/' '%' %right '!' '~' T_INC T_DEC T_INT_CAST T_DOUBLE_CAST T_STRING_CAST T_ARRAY_CAST T_OBJECT_CAST T_BOOL_CAST T_UNSET_CAST '@' %right '[' -%nonassoc T_NEW T_DELETE +%nonassoc T_NEW T_INSTANCEOF %token T_EXIT %token T_IF %left T_ELSEIF @@ -94,6 +96,7 @@ %token T_ENDFOREACH %token T_DECLARE %token T_ENDDECLARE +%token T_INSTANCEOF %token T_AS %token T_SWITCH %token T_ENDSWITCH @@ -101,7 +104,6 @@ %token T_DEFAULT %token T_BREAK %token T_CONTINUE -%token T_OLD_FUNCTION %token T_FUNCTION %token T_CONST %token T_RETURN @@ -110,8 +112,7 @@ %token T_THROW %token T_USE %token T_GLOBAL -%token T_STATIC -%token T_PRIVATE +%right T_STATIC T_ABSTRACT T_PRIVATE T_PROTECTED T_PUBLIC %token T_VAR %token T_UNSET %token T_ISSET @@ -153,7 +154,8 @@ top_statement: statement - | declaration_statement { zend_do_early_binding(TSRMLS_C); } + | function_declaration_statement { zend_do_early_binding(TSRMLS_C); } + | class_declaration_statement ; @@ -165,7 +167,8 @@ inner_statement: statement - | declaration_statement + | function_declaration_statement + | class_declaration_statement ; @@ -173,7 +176,6 @@ unticked_statement { zend_do_ticks(TSRMLS_C); } ; - unticked_statement: '{' inner_statement_list '}' | T_IF '(' expr ')' { zend_do_if_cond(&$3, &$4 TSRMLS_CC); } statement { zend_do_if_after_statement(&$4, 1 TSRMLS_CC); } elseif_list else_single { zend_do_if_end(TSRMLS_C); } @@ -206,13 +208,12 @@ | T_UNSET '(' unset_variables ')' ';' | T_FOREACH '(' variable T_AS { zend_do_foreach_begin(&$1, &$3, &$2, &$4, 1 TSRMLS_CC); } w_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$6, &$7, &$4 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$2 TSRMLS_CC); } | T_FOREACH '(' expr_without_variable T_AS { zend_do_foreach_begin(&$1, &$3, &$2, &$4, 0 TSRMLS_CC); } w_variable foreach_optional_arg ')' { zend_do_foreach_cont(&$6, &$7, &$4 TSRMLS_CC); } foreach_statement { zend_do_foreach_end(&$1, &$2 TSRMLS_CC); } - | T_DECLARE { zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(TSRMLS_C); } + | T_DECLARE { $1.u.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end(&$1 TSRMLS_CC); } | ';' /* empty statement */ | T_TRY { zend_do_try(&$1 TSRMLS_CC); } '{' inner_statement_list '}' T_CATCH '(' catch_or_import_class_entry T_VARIABLE ')' { zend_do_begin_catch(&$1, &$8, &$9, 1 TSRMLS_CC); } '{' inner_statement_list '}' { zend_do_end_catch(&$1 TSRMLS_CC); } additional_catches | T_THROW expr ';' { zend_do_throw(&$2 TSRMLS_CC); } - | T_DELETE variable ';' { zend_do_end_variable_parse(BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$2, ZEND_UNSET_OBJ TSRMLS_CC); } | T_IMPORT { zend_do_begin_import(TSRMLS_C); } import_rule T_FROM catch_or_import_class_entry { zend_do_end_import(&$5 TSRMLS_CC); } ';' ; @@ -253,7 +254,7 @@ ; unset_variable: - variable { zend_do_end_variable_parse(BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1, ZEND_UNSET_REG TSRMLS_CC); } + variable { zend_do_end_variable_parse(BP_VAR_UNSET, 0 TSRMLS_CC); zend_do_unset(&$1 TSRMLS_CC); } ; use_filename: @@ -262,21 +263,36 @@ ; -declaration_statement: - unticked_declaration_statement { zend_do_ticks(TSRMLS_C); } +function_declaration_statement: + unticked_function_declaration_statement { zend_do_ticks(TSRMLS_C); } +; + +class_declaration_statement: + unticked_class_declaration_statement { zend_do_ticks(TSRMLS_C); } +; + + +is_reference: + /* empty */ { $$.op_type = ZEND_RETURN_VAL; } + | '&' { $$.op_type = ZEND_RETURN_REF; } ; -unticked_declaration_statement: - T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$4, 0, $3.op_type TSRMLS_CC); } +unticked_function_declaration_statement: + T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$4, 0, $3.op_type, 0 TSRMLS_CC); } '(' parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); } - | T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$4, 0, $3.op_type TSRMLS_CC); } - parameter_list '(' inner_statement_list ')' ';' { zend_do_end_function_declaration(&$1 TSRMLS_CC); } - | T_CLASS decleration_class_name { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); } - | T_CLASS T_STRING T_EXTENDS T_STRING { zend_do_begin_class_declaration(&$1, &$2, &$4 TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); } ; -decleration_class_name: +unticked_class_declaration_statement: + T_CLASS declaration_class_name extends_from '{' { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); } +; + +extends_from: + /* empty */ { $$.op_type = IS_UNUSED; } + | T_EXTENDS catch_or_import_class_entry { $$ = $2; } +; + +declaration_class_name: | parse_class_name_entry T_STRING { do_fetch_class_name(&$$, &$1, &$2, 0 TSRMLS_CC); } | T_STRING { $$ = $1; zend_str_tolower($$.u.constant.value.str.val, $$.u.constant.value.str.len); } ; @@ -286,7 +302,6 @@ | T_DOUBLE_ARROW w_variable { $$ = $2; } ; - for_statement: statement | ':' inner_statement_list T_ENDFOR ';' @@ -399,8 +414,8 @@ ; global_var_list: - global_var_list ',' global_var { zend_do_fetch_global_or_static_variable(&$3, NULL, ZEND_FETCH_GLOBAL TSRMLS_CC); } - | global_var { zend_do_fetch_global_or_static_variable(&$1, NULL, ZEND_FETCH_GLOBAL TSRMLS_CC); } + global_var_list ',' global_var { zend_do_fetch_global_variable(&$3, NULL, ZEND_FETCH_GLOBAL TSRMLS_CC); } + | global_var { zend_do_fetch_global_variable(&$1, NULL, ZEND_FETCH_GLOBAL TSRMLS_CC); } ; @@ -412,10 +427,10 @@ static_var_list: - static_var_list ',' T_VARIABLE { zend_do_fetch_global_or_static_variable(&$3, NULL, ZEND_FETCH_STATIC TSRMLS_CC); } - | static_var_list ',' T_VARIABLE '=' static_scalar { zend_do_fetch_global_or_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); } - | T_VARIABLE { zend_do_fetch_global_or_static_variable(&$1, NULL, ZEND_FETCH_STATIC TSRMLS_CC); } - | T_VARIABLE '=' static_scalar { zend_do_fetch_global_or_static_variable(&$1, &$3, ZEND_FETCH_STATIC TSRMLS_CC); } + static_var_list ',' T_VARIABLE { zend_do_fetch_static_variable(&$3, NULL, ZEND_FETCH_STATIC TSRMLS_CC); } + | static_var_list ',' T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$3, &$5, ZEND_FETCH_STATIC TSRMLS_CC); } + | T_VARIABLE { zend_do_fetch_static_variable(&$1, NULL, ZEND_FETCH_STATIC TSRMLS_CC); } + | T_VARIABLE '=' static_scalar { zend_do_fetch_static_variable(&$1, &$3, ZEND_FETCH_STATIC TSRMLS_CC); } ; @@ -427,40 +442,51 @@ class_statement: - class_variable_decleration ';' - | class_constant_decleration ';' - | T_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$4, 1, $3.op_type TSRMLS_CC); } '(' - parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$1 TSRMLS_CC); } - | T_OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$1, &$4, 1, $3.op_type TSRMLS_CC); } - parameter_list '(' inner_statement_list ')' ';' { zend_do_end_function_declaration(&$1 TSRMLS_CC); } - | T_CLASS T_STRING { zend_do_begin_class_declaration(&$1, &$2, NULL TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); } - | T_CLASS T_STRING T_EXTENDS T_STRING { zend_do_begin_class_declaration(&$1, &$2, &$4 TSRMLS_CC); } '{' class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); } + variable_modifiers { CG(access_type) = $1.u.constant.value.lval; } class_variable_declaration ';' + | class_constant_declaration ';' + | method_modifiers T_FUNCTION { $2.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$2, &$5, 1, $4.op_type, $1.u.constant.value.lval TSRMLS_CC); } '(' + parameter_list ')' '{' inner_statement_list '}' { zend_do_end_function_declaration(&$2 TSRMLS_CC); } + | T_ABSTRACT method_modifiers T_FUNCTION { $3.u.opline_num = CG(zend_lineno); } is_reference T_STRING { zend_do_begin_function_declaration(&$3, &$6, 1, $5.op_type, $2.u.constant.value.lval | ZEND_ACC_ABSTRACT TSRMLS_CC); } '(' + parameter_list ')' { zend_do_abstract_method(TSRMLS_C); zend_do_end_function_declaration(&$3 TSRMLS_CC); } ';' + | T_CLASS T_STRING extends_from '{' { zend_do_begin_class_declaration(&$1, &$2, &$3 TSRMLS_CC); } class_statement_list '}' { zend_do_end_class_declaration(&$1 TSRMLS_CC); } ; -is_reference: - /* empty */ { $$.op_type = ZEND_RETURN_VAL; } - | '&' { $$.op_type = ZEND_RETURN_REF; } +variable_modifiers: + non_empty_access_modifiers { $$ = $1; } + | T_VAR { $$.u.constant.value.lval = ZEND_ACC_PUBLIC; } +; + +method_modifiers: + /* empty */ { $$.u.constant.value.lval = ZEND_ACC_PUBLIC; } + | non_empty_access_modifiers { $$ = $1; if (!($$.u.constant.value.lval & ZEND_ACC_PPP_MASK)) { $$.u.constant.value.lval |= ZEND_ACC_PUBLIC; } } +; + +non_empty_access_modifiers: + access_modifier { $$ = $1; } + | non_empty_access_modifiers access_modifier { $$.u.constant.value.lval = zend_do_verify_access_types(&$1, &$2); } +; + +access_modifier: + T_PUBLIC { $$.u.constant.value.lval = ZEND_ACC_PUBLIC; } + | T_PROTECTED { $$.u.constant.value.lval = ZEND_ACC_PROTECTED; } + | T_PRIVATE { $$.u.constant.value.lval = ZEND_ACC_PRIVATE; } + | T_STATIC { $$.u.constant.value.lval = ZEND_ACC_STATIC; } +; + +class_variable_declaration: + class_variable_declaration ',' T_VARIABLE { zend_do_declare_property(&$3, NULL, CG(access_type) TSRMLS_CC); } + | class_variable_declaration ',' T_VARIABLE '=' static_scalar { zend_do_declare_property(&$3, &$5, CG(access_type) TSRMLS_CC); } + | T_VARIABLE { zend_do_declare_property(&$1, NULL, CG(access_type) TSRMLS_CC); } + | T_VARIABLE '=' static_scalar { zend_do_declare_property(&$1, &$3, CG(access_type) TSRMLS_CC); } +; -class_variable_decleration: - class_variable_decleration ',' T_VARIABLE { zend_do_declare_property(&$3, NULL, $1.op_type TSRMLS_CC); } - | class_variable_decleration ',' T_VARIABLE '=' static_scalar { zend_do_declare_property(&$3, &$5, $1.op_type TSRMLS_CC); } - | class_decleration_type T_VARIABLE { $$ = $1; zend_do_declare_property(&$2, NULL, $1.op_type TSRMLS_CC); } - | class_decleration_type T_VARIABLE '=' static_scalar { $$ = $1; zend_do_declare_property(&$2, &$4, $1.op_type TSRMLS_CC); } -; - -class_decleration_type: - T_VAR { $$.op_type = T_VAR; } - | T_STATIC { $$.op_type = T_STATIC; } - | T_PRIVATE { $$.op_type = T_PRIVATE; } -; - -class_constant_decleration: - | T_CONST ',' T_STRING '=' static_scalar { zend_do_declare_property(&$3, &$5, T_CONST TSRMLS_CC); } - | T_CONST T_STRING '=' static_scalar { zend_do_declare_property(&$2, &$4, T_CONST TSRMLS_CC); } +class_constant_declaration: + class_constant_declaration ',' T_STRING '=' static_scalar { zend_do_declare_class_constant(&$3, &$5 TSRMLS_CC); } + | T_CONST T_STRING '=' static_scalar { zend_do_declare_class_constant(&$2, &$4 TSRMLS_CC); } ; echo_expr_list: - | echo_expr_list ',' expr { zend_do_echo(&$3 TSRMLS_CC); } + echo_expr_list ',' expr { zend_do_echo(&$3 TSRMLS_CC); } | expr { zend_do_echo(&$1 TSRMLS_CC); } ; @@ -477,21 +503,21 @@ expr_without_variable: T_LIST '(' { zend_do_list_init(TSRMLS_C); } assignment_list ')' '=' expr { zend_do_list_end(&$$, &$7 TSRMLS_CC); } - | variable '=' expr { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); } - | variable '=' '&' w_variable { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); } - | variable '=' '&' T_NEW new_class_entry { zend_check_writable_variable(&$$); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); } + | variable '=' expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign(&$$, &$1, &$3 TSRMLS_CC); } + | variable '=' '&' variable { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$4 TSRMLS_CC); } + | variable '=' '&' T_NEW new_class_entry { zend_check_writable_variable(&$1); zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$4, &$5 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$3, &$4, &$7 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C); zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); zend_do_assign_ref(&$$, &$1, &$3 TSRMLS_CC); } | T_NEW new_class_entry { zend_do_extended_fcall_begin(TSRMLS_C); zend_do_begin_new_object(&$1, &$2 TSRMLS_CC); } ctor_arguments { zend_do_end_new_object(&$$, &$1, &$4 TSRMLS_CC); zend_do_extended_fcall_end(TSRMLS_C);} - | variable T_PLUS_EQUAL expr { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); } - | variable T_MINUS_EQUAL expr { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); } - | variable T_MUL_EQUAL expr { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); } - | variable T_DIV_EQUAL expr { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 TSRMLS_CC); } - | variable T_CONCAT_EQUAL expr { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 TSRMLS_CC); } - | variable T_MOD_EQUAL expr { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 TSRMLS_CC); } - | variable T_AND_EQUAL expr { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 TSRMLS_CC); } - | variable T_OR_EQUAL expr { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 TSRMLS_CC); } - | variable T_XOR_EQUAL expr { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); } - | variable T_SL_EQUAL expr { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 TSRMLS_CC); } - | variable T_SR_EQUAL expr { zend_check_writable_variable(&$$); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_PLUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_MINUS_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_MUL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_DIV_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_CONCAT_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_MOD_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_AND_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_OR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_XOR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_SL_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 TSRMLS_CC); } + | variable T_SR_EQUAL expr { zend_check_writable_variable(&$1); zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); zend_do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 TSRMLS_CC); } | rw_variable T_INC { zend_do_post_incdec(&$$, &$1, ZEND_POST_INC TSRMLS_CC); } | T_INC rw_variable { zend_do_pre_incdec(&$$, &$2, ZEND_PRE_INC TSRMLS_CC); } | rw_variable T_DEC { zend_do_post_incdec(&$$, &$1, ZEND_POST_DEC TSRMLS_CC); } @@ -524,6 +550,7 @@ | expr T_IS_SMALLER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$1, &$3 TSRMLS_CC); } | expr '>' expr { zend_do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 TSRMLS_CC); } | expr T_IS_GREATER_OR_EQUAL expr { zend_do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 TSRMLS_CC); } + | expr T_INSTANCEOF instanceof_expr { zend_do_instanceof(&$$, &$1, &$3, 0 TSRMLS_CC); } | '(' expr ')' { $$ = $2; } | expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); } expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); } @@ -572,7 +599,7 @@ ; new_class_entry: - parse_class_entry T_STRING { do_fetch_class(&$$, &$1, &$2 TSRMLS_CC); } + parse_class_entry static_or_variable_string { do_fetch_class(&$$, &$1, &$2 TSRMLS_CC); } | static_or_variable_string { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); } ; @@ -581,6 +608,10 @@ | r_variable_without_static_member { $$ = $1; } ; +instanceof_expr: + parse_class_entry T_STRING { do_fetch_class(&$$, &$1, &$2 TSRMLS_CC); } + | T_STRING { do_fetch_class(&$$, NULL, &$1 TSRMLS_CC); } +; exit_expr: /* empty */ { memset(&$$, 0, sizeof(znode)); $$.op_type = IS_UNUSED; } @@ -609,7 +640,7 @@ static_scalar: /* compile-time evaluated scalars */ common_scalar { $$ = $1; } | T_STRING { zend_do_fetch_constant(&$$, NULL, &$1, ZEND_CT TSRMLS_CC); } - | '+' static_scalar { $$ = $1; } + | '+' static_scalar { $$ = $2; } | '-' static_scalar { zval minus_one; minus_one.type = IS_LONG; minus_one.value.lval = -1; mul_function(&$2.u.constant, &$2.u.constant, &minus_one TSRMLS_CC); $$ = $2; } | T_ARRAY '(' static_array_pair_list ')' { $$ = $3; $$.u.constant.type = IS_CONSTANT_ARRAY; } | parse_class_name_entry T_STRING { zend_do_fetch_constant(&$$, &$1, &$2, ZEND_CT TSRMLS_CC); } @@ -657,12 +688,12 @@ w_variable: variable { zend_do_end_variable_parse(BP_VAR_W, 0 TSRMLS_CC); $$ = $1; } - { zend_check_writable_variable(&$$); } + { zend_check_writable_variable(&$1); } ; rw_variable: variable { zend_do_end_variable_parse(BP_VAR_RW, 0 TSRMLS_CC); $$ = $1; } - { zend_check_writable_variable(&$$); } + { zend_check_writable_variable(&$1); } ; r_variable_without_static_member: @@ -832,3 +863,10 @@ %% +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +10 -1 ZendEngine2/zend_language_scanner.h Index: zend_language_scanner.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_language_scanner.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_language_scanner.h 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_language_scanner.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_language_scanner.h,v 1.11 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_SCANNER_H #define ZEND_SCANNER_H @@ -39,3 +40,11 @@ END_EXTERN_C() #endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +75 -33 ZendEngine2/zend_language_scanner.l Index: zend_language_scanner.l =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_language_scanner.l,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_language_scanner.l 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_language_scanner.l 11 Feb 2003 02:40:18 -0000 1.3 @@ -7,7 +7,7 @@ | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | - | that is bundled with this package in the file LICENSE, and is | + | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.zend.com/license/2_00.txt. | | If you did not receive a copy of the Zend license and are unable to | @@ -19,6 +19,8 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_language_scanner.l,v 1.73 2003/02/01 07:32:09 sebastian Exp $ */ + #define yyleng SCNG(yy_leng) #define yytext SCNG(yy_text) #define yytext_ptr SCNG(yy_text) @@ -109,7 +111,7 @@ CG(zend_lineno)++; \ } \ } - + #define ZEND_IS_OCT(c) ((c)>='0' && (c)<='7') #define ZEND_IS_HEX(c) (((c)>='0' && (c)<='9') || ((c)>='a' && (c)<='f') || ((c)>='A' && (c)<='F')) @@ -125,6 +127,8 @@ { CG(heredoc) = NULL; CG(heredoc_len)=0; + SCNG(yy_start_stack_ptr) = 0; + SCNG(yy_start_stack_depth) = 0; } @@ -157,7 +161,7 @@ } else { YY_CURRENT_BUFFER = NULL; } - + yy_delete_buffer(original_buffer_state TSRMLS_CC); SCNG(yy_in) = lex_state->in; BEGIN(lex_state->state); @@ -229,7 +233,7 @@ return FAILURE; } - file_handle->type = ZEND_HANDLE_FP; + file_handle->type = ZEND_HANDLE_FP; if (file_handle->handle.fp != stdin) { zend_llist_add_element(&CG(open_files), file_handle); } @@ -239,13 +243,20 @@ BEGIN(INITIAL); if (file_handle->opened_path) { - file_path = file_handle->opened_path; + file_path = file_handle->opened_path; } else { file_path = file_handle->filename; } zend_set_compiled_filename(file_path TSRMLS_CC); - CG(zend_lineno) = 1; + + if (CG(start_lineno)) { + CG(zend_lineno) = CG(start_lineno); + CG(start_lineno) = 0; + } else { + CG(zend_lineno) = 1; + } + CG(increment_lineno) = 0; return SUCCESS; } @@ -276,7 +287,7 @@ if (open_file_for_scanning(file_handle TSRMLS_CC)==FAILURE) { if (type==ZEND_REQUIRE) { zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename); - zend_bailout(); + zend_bailout(); } else { zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename); } @@ -316,6 +327,7 @@ zend_file_handle file_handle; zval tmp; zend_op_array *retval; + char *opened_path = NULL; if (filename->type != IS_STRING) { tmp = *filename; @@ -330,9 +342,18 @@ retval = zend_compile_file(&file_handle, type TSRMLS_CC); - if (retval && file_handle.opened_path) { + if (retval && file_handle.handle.fp) { int dummy = 1; + + if (!file_handle.opened_path) { + file_handle.opened_path = opened_path = estrndup(filename->value.str.val, filename->value.str.len); + } + zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL); + + if (opened_path) { + efree(opened_path); + } } zend_destroy_file_handle(&file_handle TSRMLS_CC); @@ -390,7 +411,7 @@ CG(active_op_array) = op_array; BEGIN(ST_IN_SCRIPTING); compiler_result = zendparse(TSRMLS_C); - + if (compiler_result==1) { CG(active_op_array) = original_active_op_array; CG(unclean_shutdown)=1; @@ -455,6 +476,8 @@ EXPONENT_DNUM (({LNUM}|{DNUM})[eE][+-]?{LNUM}) HNUM "0x"[0-9a-fA-F]+ LABEL [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]* +ENCAPSED_STRING ([a-zA-Z0-9_\x7f-\xff \t #'.:;,()|^&+/*=%!~<>?@]|"-"[a-zA-Z0-9_\x7f-\xff \t #'.:;,()|^&+/*=%!~<?@])+ +ENCAPSED_STRING_WITH_NEWLINE ([a-zA-Z0-9_\x7f-\xff \t\n\r #'.:;,()|^&+/*=%!~<>?@]|"-"[a-zA-Z0-9_\x7f-\xff \t\n\r #'.:;,()|^&+/*=%!~<?@])+ WHITESPACE [ \n\r\t]+ TABS_AND_SPACES [ \t]* TOKENS [;:,.\[\]()|^&+-/*=%!~$<>?@] @@ -475,11 +498,7 @@ return T_EXIT; } -<ST_IN_SCRIPTING>"old_function" { - return T_OLD_FUNCTION; -} - -<ST_IN_SCRIPTING>"function"|"cfunction" { +<ST_IN_SCRIPTING>"function" { return T_FUNCTION; } @@ -555,6 +574,10 @@ return T_ENDDECLARE; } +<ST_IN_SCRIPTING>"instanceof" { + return T_INSTANCEOF; +} + <ST_IN_SCRIPTING>"as" { return T_AS; } @@ -625,10 +648,6 @@ return T_NEW; } -<ST_IN_SCRIPTING>"delete" { - return T_DELETE; -} - <ST_IN_SCRIPTING>"var" { return T_VAR; } @@ -709,10 +728,22 @@ return T_STATIC; } +<ST_IN_SCRIPTING>"abstract" { + return T_ABSTRACT; +} + <ST_IN_SCRIPTING>"private" { return T_PRIVATE; } +<ST_IN_SCRIPTING>"protected" { + return T_PROTECTED; +} + +<ST_IN_SCRIPTING>"public" { + return T_PUBLIC; +} + <ST_IN_SCRIPTING>"unset" { return T_UNSET; } @@ -923,8 +954,12 @@ } <ST_IN_SCRIPTING>"__CLASS__" { - char *class_name = CG(active_class_entry)->name; - + char *class_name = NULL; + + if (CG(active_class_entry)) { + class_name = CG(active_class_entry)->name; + } + if (!class_name) { class_name = ""; } @@ -936,7 +971,7 @@ <ST_IN_SCRIPTING>"__FUNCTION__" { char *func_name = CG(active_op_array)->function_name; - + if (!func_name) { func_name = ""; } @@ -954,7 +989,7 @@ <ST_IN_SCRIPTING>"__FILE__" { char *filename = zend_get_compiled_filename(TSRMLS_C); - + if (!filename) { filename = ""; } @@ -1048,6 +1083,13 @@ return T_VARIABLE; } +<ST_DOUBLE_QUOTES,ST_BACKQUOTE>{ENCAPSED_STRING_WITH_NEWLINE} { + HANDLE_NEWLINES(yytext, yyleng); + zendlval->value.str.val = (char *)estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return T_STRING; +} <ST_IN_SCRIPTING>{LABEL} { zendlval->value.str.val = (char *)estrndup(yytext, yyleng); @@ -1057,7 +1099,7 @@ } -<ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>{LABEL} { +<ST_HEREDOC>{ENCAPSED_STRING} { zendlval->value.str.val = (char *)estrndup(yytext, yyleng); zendlval->value.str.len = yyleng; zendlval->type = IS_STRING; @@ -1156,12 +1198,12 @@ <ST_IN_SCRIPTING>(["]([^$"\\]|("\\".))*["]) { register char *s, *t; char *end; - + zendlval->value.str.val = estrndup(yytext+1, yyleng-2); zendlval->value.str.len = yyleng-2; zendlval->type = IS_STRING; HANDLE_NEWLINES(yytext, yyleng); - + /* convert escape sequences */ s = t = zendlval->value.str.val; end = s+zendlval->value.str.len; @@ -1230,7 +1272,7 @@ } } *t = 0; - + return T_CONSTANT_ENCAPSED_STRING; } @@ -1238,12 +1280,12 @@ <ST_IN_SCRIPTING>([']([^'\\]|("\\".))*[']) { register char *s, *t; char *end; - + zendlval->value.str.val = estrndup(yytext+1, yyleng-2); zendlval->value.str.len = yyleng-2; zendlval->type = IS_STRING; HANDLE_NEWLINES(yytext, yyleng); - + /* convert escape sequences */ s = t = zendlval->value.str.val; end = s+zendlval->value.str.len; @@ -1270,7 +1312,7 @@ } } *t = 0; - + return T_CONSTANT_ENCAPSED_STRING; } @@ -1294,7 +1336,7 @@ BEGIN(ST_HEREDOC); return T_START_HEREDOC; } - + <ST_IN_SCRIPTING>[`] { BEGIN(ST_BACKQUOTE); @@ -1318,7 +1360,7 @@ } else { label_len = yyleng-1; } - + if (yytext[label_len-1]==';') { label_len--; unput_semicolon=1; @@ -1384,7 +1426,7 @@ if (yyleng == 2) { yyless(1); } - return T_CHARACTER; + return T_CHARACTER; } @@ -1496,7 +1538,7 @@ zend_error(E_COMPILE_WARNING,"Unterminated comment starting line %d", CG(comment_start_line)); return 0; } - + <ST_IN_SCRIPTING,INITIAL,ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_SINGLE_QUOTE,ST_HEREDOC>{ANY_CHAR} { 1.3 +5 -5 ZendEngine2/zend_list.c Index: zend_list.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_list.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_list.c 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_list.c 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_list.c,v 1.57 2003/02/01 01:49:14 sniper Exp $ */ /* resource lists */ @@ -233,7 +234,6 @@ zend_hash_graceful_reverse_destroy(ht); } - static int clean_module_resource(zend_rsrc_list_entry *le, int *resource_id TSRMLS_DC) { if (le->type == *resource_id) { @@ -314,8 +314,8 @@ HashPosition pos; zend_hash_internal_pointer_reset_ex(&list_destructors, &pos); - while(zend_hash_get_current_data_ex(&list_destructors, (void **)&lde, &pos) == SUCCESS) { - if(strcmp(type_name, lde->type_name) == 0) { + while (zend_hash_get_current_data_ex(&list_destructors, (void **)&lde, &pos) == SUCCESS) { + if (strcmp(type_name, lde->type_name) == 0) { #if 0 printf("Found resource id %d for resource type %s\n", (*lde).resource_id, type_name); #endif @@ -359,10 +359,10 @@ } } - /* * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.5 +12 -1 ZendEngine2/zend_list.h Index: zend_list.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_list.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_list.h 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_list.h 11 Feb 2003 02:40:18 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_list.h,v 1.42 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_LIST_H #define ZEND_LIST_H @@ -24,6 +25,7 @@ #include "zend_hash.h" #include "zend_globals.h" +BEGIN_EXTERN_C() #define ZEND_RESOURCE_LIST_TYPE_STD 1 #define ZEND_RESOURCE_LIST_TYPE_EX 2 @@ -105,5 +107,14 @@ if (le_id == 0) { \ le_id = zend_fetch_list_dtor_id(le_type_name); \ } +END_EXTERN_C() #endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.5 +14 -2 ZendEngine2/zend_llist.c Index: zend_llist.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_llist.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_llist.c 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_llist.c 11 Feb 2003 02:40:18 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_llist.c,v 1.32 2003/02/01 01:49:14 sniper Exp $ */ #include "zend.h" #include "zend_llist.h" @@ -82,8 +83,8 @@ }\ if ((l)->dtor) {\ (l)->dtor((current)->data);\ - pefree((current), (l)->persistent);\ }\ + pefree((current), (l)->persistent);\ --l->count; @@ -140,6 +141,9 @@ data = old_tail->data; l->tail = l->tail->prev; + if (l->dtor) { + l->dtor(data); + } pefree(old_tail, l->persistent); --l->count; @@ -303,3 +307,11 @@ } return NULL; } + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +11 -4 ZendEngine2/zend_llist.h Index: zend_llist.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_llist.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_llist.h 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_llist.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,12 +17,11 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_llist.h,v 1.30 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_LLIST_H #define ZEND_LLIST_H -#include <stdlib.h> - typedef struct _zend_llist_element { struct _zend_llist_element *next; struct _zend_llist_element *prev; @@ -30,7 +29,7 @@ } zend_llist_element; typedef void (*llist_dtor_func_t)(void *); -typedef int (*llist_compare_func_t)(const zend_llist_element *, const zend_llist_element * TSRMLS_DC); +typedef int (*llist_compare_func_t)(const zend_llist_element **, const zend_llist_element ** TSRMLS_DC); typedef void (*llist_apply_with_args_func_t)(void *data, int num_args, va_list args TSRMLS_DC); typedef void (*llist_apply_with_arg_func_t)(void *data, void *arg TSRMLS_DC); typedef void (*llist_apply_func_t)(void * TSRMLS_DC); @@ -77,3 +76,11 @@ END_EXTERN_C() #endif /* ZEND_LLIST_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.4 +58 -9 ZendEngine2/zend_mm.c Index: zend_mm.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_mm.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- zend_mm.c 3 Aug 2002 08:56:16 -0000 1.3 +++ zend_mm.c 11 Feb 2003 02:40:18 -0000 1.4 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,8 +17,8 @@ +----------------------------------------------------------------------+ */ -#include <stdlib.h> -#include <string.h> +/* $Id: zend_mm.c,v 1.20 2003/02/01 01:49:14 sniper Exp $ */ + #include "zend.h" #include "zend_mm.h" @@ -59,7 +59,6 @@ #define ZEND_MM_ALIGNED_FREE_HEADER_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_free_block)) #define ZEND_MM_ALIGNED_SEGMENT_SIZE ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_segment)) - /* Memory calculations */ #define ZEND_MM_BLOCK_AT(blk, offset) ((zend_mm_block *) (((char *) (blk))+(offset))) #define ZEND_MM_DATA_OF(p) ((void *) (((char *) (p))+ZEND_MM_ALIGNED_HEADER_SIZE)) @@ -154,14 +153,15 @@ block_size -= ZEND_MM_ALIGNED_SEGMENT_SIZE; mm_block = (zend_mm_free_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE); - mm_block->size = block_size - ZEND_MM_ALIGNED_FREE_HEADER_SIZE; /* keep one guard block in the end */ + mm_block->size = block_size - ZEND_MM_ALIGNED_HEADER_SIZE; /* keep one guard block in the end */ mm_block->type = ZEND_MM_FREE_BLOCK; mm_block->prev_size = 0; /* Size is always at least ZEND_MM_ALIGNED_HEADER_SIZE big (>0) so 0 is OK */ /* setup guard block */ guard_block = ZEND_MM_BLOCK_AT(mm_block, mm_block->size); guard_block->type = ZEND_MM_USED_BLOCK; - guard_block->size = ZEND_MM_ALIGNED_FREE_HEADER_SIZE; + guard_block->size = ZEND_MM_ALIGNED_HEADER_SIZE; + guard_block->guard_block = 1; guard_block->prev_size = mm_block->size; ZEND_MM_DEBUG(("Setup guard block at 0x%0.8X\n", guard_block)); @@ -233,9 +233,9 @@ zend_mm_finished_searching_for_block: if (!best_fit) { - if (true_size > (heap->block_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_FREE_HEADER_SIZE)) { + if (true_size > (heap->block_size - ZEND_MM_ALIGNED_SEGMENT_SIZE - ZEND_MM_ALIGNED_HEADER_SIZE)) { /* Make sure we add a memory block which is big enough */ - zend_mm_add_memory_block(heap, true_size + ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_FREE_HEADER_SIZE); + zend_mm_add_memory_block(heap, true_size + ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE); } else { zend_mm_add_memory_block(heap, heap->block_size); } @@ -244,6 +244,7 @@ /* mark as used */ best_fit->type = ZEND_MM_USED_BLOCK; + ((zend_mm_block *) best_fit)->guard_block = 0; /* remove from free list */ zend_mm_remove_from_free_list(heap, best_fit); @@ -259,7 +260,7 @@ zend_mm_block *mm_block = ZEND_MM_HEADER_OF(p); zend_mm_block *prev_block, *next_block; - if (mm_block->type!=ZEND_MM_USED_BLOCK) { + if (mm_block->type != ZEND_MM_USED_BLOCK) { /* error */ return; } @@ -302,6 +303,46 @@ next_block = ZEND_MM_BLOCK_AT(mm_block, mm_block->size); + if ((mm_block->prev_size == 0) && (next_block->type == ZEND_MM_USED_BLOCK) && + (next_block->guard_block)) { + zend_mm_segment *segment = (zend_mm_segment *) ((char *)mm_block - ZEND_MM_ALIGNED_SEGMENT_SIZE); + zend_mm_segment *segment_copy = segment; + zend_mm_block *guard_block; + size_t realloc_to_size; + + /* segment size, size of block and size of guard block */ + realloc_to_size = ZEND_MM_ALIGNED_SEGMENT_SIZE+true_size+ZEND_MM_ALIGNED_HEADER_SIZE; + segment = realloc(segment, realloc_to_size); + + if (segment != segment_copy) { + if (heap->segments_list == segment_copy) { + heap->segments_list = segment; + } else { + zend_mm_segment *seg = heap->segments_list; + + while (seg) { + if (seg->next_segment == segment_copy) { + seg->next_segment = segment; + break; + } + seg = seg->next_segment; + } + } + mm_block = (zend_mm_block *) ((char *) segment + ZEND_MM_ALIGNED_SEGMENT_SIZE); + } + + mm_block->size = true_size; + + /* setup guard block */ + guard_block = ZEND_MM_BLOCK_AT(mm_block, mm_block->size); + guard_block->type = ZEND_MM_USED_BLOCK; + guard_block->size = ZEND_MM_ALIGNED_HEADER_SIZE; + guard_block->guard_block = 1; + guard_block->prev_size = mm_block->size; + + return ZEND_MM_DATA_OF(mm_block); + } + if (next_block->type != ZEND_MM_FREE_BLOCK || (mm_block->size + next_block->size < true_size)) { void *ptr; @@ -320,3 +361,11 @@ return p; } + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +12 -1 ZendEngine2/zend_mm.h Index: zend_mm.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_mm.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_mm.h 2 Aug 2002 09:48:15 -0000 1.2 +++ zend_mm.h 11 Feb 2003 02:40:18 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,8 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_mm.h,v 1.11 2003/02/01 01:49:14 sniper Exp $ */ + #ifndef _ZEND_MM_H #define _ZEND_MM_H @@ -32,6 +34,7 @@ unsigned int size : 31; unsigned int type : 1; size_t prev_size; + unsigned int guard_block : 1; } zend_mm_block; typedef struct _zend_mm_free_block { @@ -61,3 +64,11 @@ void *zend_mm_realloc(zend_mm_heap *heap, void *p, size_t size); #endif /* _ZEND_MM_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.5 +15 -3 ZendEngine2/zend_modules.h Index: zend_modules.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_modules.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_modules.h 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_modules.h 11 Feb 2003 02:40:18 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_modules.h,v 1.51 2003/02/01 01:49:14 sniper Exp $ */ #ifndef MODULES_H #define MODULES_H @@ -34,14 +35,15 @@ ZEND_API extern unsigned char second_arg_force_ref[]; ZEND_API extern unsigned char third_arg_force_ref[]; -#define ZEND_MODULE_API_NO 20010927 +#define ZEND_MODULE_API_NO 20020429 #ifdef ZTS #define USING_ZTS 1 #else #define USING_ZTS 0 #endif -#define STANDARD_MODULE_HEADER sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS +#define STANDARD_MODULE_HEADER sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS, NULL +#define ZE2_STANDARD_MODULE_HEADER sizeof(zend_module_entry), ZEND_MODULE_API_NO, ZEND_DEBUG, USING_ZTS, ini_entries #define STANDARD_MODULE_PROPERTIES_EX 0, 0, 0, NULL, 0 @@ -53,6 +55,7 @@ #define MODULE_PERSISTENT 1 #define MODULE_TEMPORARY 2 +struct _zend_ini_entry; typedef struct _zend_module_entry zend_module_entry; struct _zend_module_entry { @@ -60,6 +63,7 @@ unsigned int zend_api; unsigned char zend_debug; unsigned char zts; + struct _zend_ini_entry *ini_entry; char *name; zend_function_entry *functions; int (*module_startup_func)(INIT_FUNC_ARGS); @@ -86,3 +90,11 @@ #define ZEND_MODULE_DTOR (void (*)(void *)) module_destructor #endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.2 +0 -677 ZendEngine2/zend_multibyte.c <<Binary file>> 1.6 +626 -56 ZendEngine2/zend_object_handlers.c Index: zend_object_handlers.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_object_handlers.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- zend_object_handlers.c 3 Aug 2002 08:56:16 -0000 1.5 +++ zend_object_handlers.c 11 Feb 2003 02:40:19 -0000 1.6 @@ -1,12 +1,53 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | licen****@zend***** so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans <andi****@zend*****> | + | Zeev Suraski <zeev****@zend*****> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: zend_object_handlers.c,v 1.39 2003/02/10 10:57:14 stas Exp $ */ + #include "zend.h" #include "zend_globals.h" #include "zend_variables.h" #include "zend_API.h" #include "zend_objects.h" +#include "zend_objects_API.h" #include "zend_object_handlers.h" #define DEBUG_OBJECT_HANDLERS 0 +#define Z_OBJ_P(zval_p) zend_objects_get_address(zval_p) + +/* + __X accessors explanation: + + if we have __get and property that is not part of the properties array is + requested, we call __get handler. If it fails, we return uninitialized. + + if we have __set and property that is not part of the properties array is + set, we call __set handler. If it fails, we do not change the array. + + for both handlers above, when we are inside __get/__set, no further calls for + __get/__set for these objects will be made, to prevent endless recursion and + enable accessors to change properties array. + + if we have __call and method which is not part of the class function table is + called, we cal __call handler. +*/ + static HashTable *zend_std_get_properties(zval *object TSRMLS_DC) { zend_object *zobj; @@ -14,11 +55,159 @@ return zobj->properties; } -zval *zend_std_read_property(zval *object, zval *member, int type TSRMLS_DC) +static zval *zend_std_call_getter(zval *object, zval *member TSRMLS_DC) +{ + zval **call_args[1]; + zval *retval = NULL; + zval __get_name; + int call_result; + + /* __get handler is called with two arguments: + property name + return value for the object (by reference) + + it should return whether the call was successfull or not + */ + INIT_PZVAL(&__get_name); + ZVAL_STRINGL(&__get_name, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1, 0); + + call_args[0] = &member; + + /* go call the __get handler */ + call_result = call_user_function_ex(NULL, + &object, + &__get_name, + &retval, + 1, call_args, + 0, NULL TSRMLS_CC); + + /* + call_result is if call_user_function gone OK. + retval returns the value that is received + */ + + + if (call_result == FAILURE) { + zend_error(E_ERROR, "Could not call __get handler for class %s", Z_OBJCE_P(object)->name); + return NULL; + } + + retval->refcount--; + + return retval; +} + +static int zend_std_call_setter(zval *object, zval *member, zval *value TSRMLS_DC) +{ + zval **call_args[2]; + zval *retval = NULL; + zval __set_name; + int call_result; + int ret; + + /* __set handler is called with two arguments: + property name + value to be set + + it should return whether the call was successfull or not + */ + INIT_PZVAL(&__set_name); + ZVAL_STRINGL(&__set_name, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1, 0); + + call_args[0] = &member; + value->refcount++; + call_args[1] = &value; + + /* go call the __set handler */ + call_result = call_user_function_ex(NULL, + &object, + &__set_name, + &retval, + 2, call_args, + 0, NULL TSRMLS_CC); + + /* + call_result is if call_user_function gone OK. + retval shows if __get method went OK. + */ + + + if (call_result == FAILURE) { + zend_error(E_ERROR, "Could not call __set handler for class %s", Z_OBJCE_P(object)->name); + return FAILURE; + } + + zval_ptr_dtor(&value); + + if (retval && zval_is_true(retval)) { + ret = SUCCESS; + } else { + ret = FAILURE; + } + + if (retval) { + zval_ptr_dtor(&retval); + } + + return ret; +} + + +inline int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce TSRMLS_DC) +{ + switch (property_info->flags & ZEND_ACC_PPP_MASK) { + case ZEND_ACC_PUBLIC: + return 1; + case ZEND_ACC_PROTECTED: + while (ce) { + if (ce==EG(scope)) { + return 1; + } + ce = ce->parent; + } + return 0; + case ZEND_ACC_PRIVATE: + if (ce==EG(scope)) { + return 1; + } else { + return 0; + } + break; + } + return 0; +} + +static inline zend_property_info *zend_get_property_info(zend_object *zobj, zval *member TSRMLS_DC) +{ + zend_property_info *property_info; + + ulong h = zend_get_hash_value(Z_STRVAL_P(member), Z_STRLEN_P(member)+1); + if (zend_hash_quick_find(&zobj->ce->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS) { + if (!zend_verify_property_access(property_info, zobj->ce TSRMLS_CC)) { + zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), zobj->ce->name, Z_STRVAL_P(member)); + } + } else if (EG(scope) + && zend_hash_quick_find(&EG(scope)->properties_info, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, h, (void **) &property_info)==SUCCESS + && property_info->flags & ZEND_ACC_PRIVATE) { + /* ok */ + } else { + EG(std_property_info).flags = ZEND_ACC_PUBLIC; + EG(std_property_info).name = Z_STRVAL_P(member); + EG(std_property_info).name_length = Z_STRLEN_P(member); + EG(std_property_info).h = zend_get_hash_value(EG(std_property_info).name, EG(std_property_info).name_length+1); + property_info = &EG(std_property_info); + } + return property_info; +} + + +zval *zend_std_read_property(zval *object, zval *member TSRMLS_DC) { zend_object *zobj; zval tmp_member; zval **retval; + zval *rv = NULL; + zend_property_info *property_info; zobj = Z_OBJ_P(object); @@ -32,27 +221,24 @@ #if DEBUG_OBJECT_HANDLERS fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member)); #endif - - if (zend_hash_find(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &retval) == FAILURE) { - switch (type) { - case BP_VAR_R: - zend_error(E_NOTICE,"Undefined property: %s", Z_STRVAL_P(member)); - /* break missing intentionally */ - case BP_VAR_IS: - retval = &EG(uninitialized_zval_ptr); - break; - case BP_VAR_RW: - zend_error(E_NOTICE,"Undefined property: %s", Z_STRVAL_P(member)); - /* break missing intentionally */ - case BP_VAR_W: { - zval *new_zval = &EG(uninitialized_zval); - - new_zval->refcount++; - zend_hash_update(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, &new_zval, sizeof(zval *), (void **) &retval); + + property_info = zend_get_property_info(zobj, member TSRMLS_CC); + + if (zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) { + if (zobj->ce->__get && !zobj->in_get) { + /* have getter - try with it! */ + zobj->in_get = 1; /* prevent circular getting */ + rv = zend_std_call_getter(object, member TSRMLS_CC); + zobj->in_get = 0; + + if (rv) { + retval = &rv; + } else { + retval = &EG(uninitialized_zval_ptr); } - break; - EMPTY_SWITCH_DEFAULT_CASE() - + } else { + zend_error(E_NOTICE,"Undefined property: %s::$%s", zobj->ce->name, Z_STRVAL_P(member)); + retval = &EG(uninitialized_zval_ptr); } } if (member == &tmp_member) { @@ -61,11 +247,14 @@ return *retval; } + static void zend_std_write_property(zval *object, zval *member, zval *value TSRMLS_DC) { zend_object *zobj; zval tmp_member; zval **variable_ptr; + int setter_done = 0; + zend_property_info *property_info; zobj = Z_OBJ_P(object); @@ -76,21 +265,47 @@ member = &tmp_member; } - if (zend_hash_find(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member), (void **) &variable_ptr) == SUCCESS) { - if (*variable_ptr == EG(error_zval_ptr) || member == EG(error_zval_ptr)) { - /* variable_ptr = EG(uninitialized_zval_ptr); */ -/* } else if (variable_ptr==&EG(uninitialized_zval) || variable_ptr!=value_ptr) { */ - } else if (*variable_ptr != value) { - (*variable_ptr)->refcount--; - if ((*variable_ptr)->refcount == 0) { - zendi_zval_dtor(**variable_ptr); - FREE_ZVAL(*variable_ptr); + property_info = zend_get_property_info(zobj, member TSRMLS_CC); + + if (zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &variable_ptr) == SUCCESS) { + if (*variable_ptr == value) { + /* if we already have this value there, we don't actually need to do anything */ + setter_done = 1; + } else { + /* if we are assigning reference, we shouldn't move it, but instead assign variable + to the same pointer */ + if (PZVAL_IS_REF(*variable_ptr)) { + zval_dtor(*variable_ptr); /* old value should be destroyed */ + /* To check: can't *variable_ptr be some system variable like error_zval here? */ + (*variable_ptr)->type = value->type; + (*variable_ptr)->value = value->value; + if (value->refcount>0) { + zval_copy_ctor(*variable_ptr); + } + setter_done = 1; + } + } + } else { + if (zobj->ce->__set && !zobj->in_set) { + zobj->in_set = 1; /* prevent circular setting */ + if (zend_std_call_setter(object, member, value TSRMLS_CC) != SUCCESS) { + /* for now, just ignore it - __set should take care of warnings, etc. */ } + setter_done = 1; + zobj->in_set = 0; } } - value->refcount++; - zend_hash_update(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, &value, sizeof(zval *), NULL); + if (!setter_done) { + zval **foo; + + /* if we assign referenced variable, we should separate it */ + value->refcount++; + if (PZVAL_IS_REF(value)) { + SEPARATE_ZVAL(&value); + } + zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &value, sizeof(zval *), (void **) &foo); + } if (member == &tmp_member) { zval_dtor(member); } @@ -101,6 +316,7 @@ zend_object *zobj; zval tmp_member; zval **retval; + zend_property_info *property_info; zobj = Z_OBJ_P(object); @@ -115,12 +331,22 @@ fprintf(stderr, "Ptr object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member)); #endif - if (zend_hash_find(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **) &retval) == FAILURE) { - zval *new_zval = &EG(uninitialized_zval); + property_info = zend_get_property_info(zobj, member TSRMLS_CC); - zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member)); - new_zval->refcount++; - zend_hash_update(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, &new_zval, sizeof(zval *), (void **) &retval); + if (zend_hash_quick_find(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval) == FAILURE) { + zval *new_zval; + + if (!zobj->ce->__get) { + /* we don't have getter - will just add it */ + new_zval = &EG(uninitialized_zval); + +/* zend_error(E_NOTICE, "Undefined property: %s", Z_STRVAL_P(member)); */ + new_zval->refcount++; + zend_hash_quick_update(zobj->properties, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval); + } else { + /* we do have getter - fail and let it try again with usual get/set */ + retval = NULL; + } } if (member == &tmp_member) { zval_dtor(member); @@ -132,6 +358,7 @@ { zend_object *zobj; zval tmp_member; + zend_property_info *property_info; zobj = Z_OBJ_P(object); @@ -141,35 +368,344 @@ convert_to_string(&tmp_member); member = &tmp_member; } - zend_hash_del(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1); + + property_info = zend_get_property_info(zobj, member TSRMLS_CC); + + zend_hash_del(zobj->properties, property_info->name, property_info->name_length+1); if (member == &tmp_member) { zval_dtor(member); } } -static union _zend_function *zend_std_get_method(zval *object, char *method_name, int method_len TSRMLS_DC) +static void zend_std_call_user_call(INTERNAL_FUNCTION_PARAMETERS) { - zend_object *zobj; - zend_function *func_method; + zval ***args; + zend_internal_function *func = (zend_internal_function *)EG(function_state_ptr)->function; + zval method_name, method_args, __call_name; + zval *method_name_ptr, *method_args_ptr; + zval **call_args[2]; + zval *method_result_ptr = NULL; + int i, call_result; - zobj = Z_OBJ_P(object); - if(zend_hash_find(&zobj->ce->function_table, method_name, method_len+1, (void **)&func_method) == FAILURE) { - zend_error(E_ERROR, "Call to undefined function %s()", method_name); + args = (zval ***)emalloc(ZEND_NUM_ARGS() * sizeof(zval **)); + + if (zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) { + efree(args); + zend_error(E_ERROR, "Cannot get arguments for __call"); + RETURN_FALSE; } + + method_name_ptr = &method_name; + INIT_PZVAL(method_name_ptr); + ZVAL_STRING(method_name_ptr, func->function_name, 0); /* no dup - it's a copy */ + + method_args_ptr = &method_args; + INIT_PZVAL(method_args_ptr); + array_init(method_args_ptr); + + for(i=0; i<ZEND_NUM_ARGS(); i++) { + zval_add_ref(args[i]); + add_next_index_zval(method_args_ptr, *args[i]); + } + + efree(args); + + INIT_PZVAL(&__call_name); + ZVAL_STRINGL(&__call_name, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1, 0); - return func_method; + /* __call handler is called with two arguments: + method name + array of method parameters + + */ + call_args[0] = &method_name_ptr; + call_args[1] = &method_args_ptr; + + /* go call the __call handler */ + call_result = call_user_function_ex(NULL, + &this_ptr, + &__call_name, + &method_result_ptr, + 2, call_args, + 0, NULL TSRMLS_CC); + + /* call_result is if call_user_function gone OK. + method_result_ptr is the true result of the called method + */ + + if (method_result_ptr) { + *return_value = *method_result_ptr; + zval_copy_ctor(return_value); + zval_ptr_dtor(&method_result_ptr); + } + + if (call_result == FAILURE) { + zend_error(E_ERROR, "Could not call __call handler for class %s", Z_OBJCE_P(this_ptr)->name); + } + + /* now destruct all auxiliaries */ + zval_dtor(method_args_ptr); + zval_dtor(method_name_ptr); + + /* destruct the function also, then - we have allocated it in get_method */ + efree(func); } -static union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC) +/* Ensures that we're allowed to call a private method. + * Returns the function address that should be called, or NULL + * if no such function exists. + */ +inline zend_function *zend_check_private(zend_function *fbc, zend_class_entry *ce, int fn_flags, char *function_name_strval, int function_name_strlen TSRMLS_DC) +{ + if (!ce) { + return 0; + } + + /* We may call a private function if: + * 1. The class of our object is the same as the scope, and the private + * function (EX(fbc)) has the same scope. + * 2. One of our parent classes are the same as the scope, and it contains + * a private function with the same name that has the same scope. + */ + if (fbc->common.scope == ce && EG(scope) == ce) { + /* rule #1 checks out ok, allow the function call */ + return fbc; + } + + + /* Check rule #2 */ + ce = ce->parent; + while (ce) { + if (ce == EG(scope)) { + if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &fbc)==SUCCESS + && fbc->op_array.fn_flags & ZEND_ACC_PRIVATE + && fbc->common.scope == EG(scope)) { + return fbc; + } + break; + } + ce = ce->parent; + } + return NULL; +} + + +/* Ensures that we're allowed to call a protected method. + */ +inline int zend_check_protected(zend_class_entry *ce, zend_class_entry *scope) +{ + zend_class_entry *fbc_scope = ce; + + /* Is the context that's calling the function, the same as one of + * the function's parents? + */ + while (fbc_scope) { + if (fbc_scope==scope) { + return 1; + } + fbc_scope = fbc_scope->parent; + } + + /* Is the function's scope the same as our current object context, + * or any of the parents of our context? + */ + while (scope) { + if (scope==ce) { + return 1; + } + scope = scope->parent; + } + return 0; +} + + +static union _zend_function *zend_std_get_method(zval *object, char *method_name, int method_len TSRMLS_DC) { zend_object *zobj; + zend_function *fbc; + char *lc_method_name; + lc_method_name = do_alloca(method_len+1); + /* Create a zend_copy_str_tolower(dest, src, src_length); */ + memcpy(lc_method_name, method_name, method_len+1); + zend_str_tolower(lc_method_name, method_len); + zobj = Z_OBJ_P(object); - return zobj->ce->constructor; + if (zend_hash_find(&zobj->ce->function_table, lc_method_name, method_len+1, (void **)&fbc) == FAILURE) { + if (zobj->ce->__call) { + zend_internal_function *call_user_call = emalloc(sizeof(zend_internal_function)); + call_user_call->type = ZEND_INTERNAL_FUNCTION; + call_user_call->handler = zend_std_call_user_call; + call_user_call->arg_types = NULL; + call_user_call->scope = zobj->ce; + call_user_call->fn_flags = 0; + call_user_call->function_name = estrndup(method_name, method_len); + + free_alloca(lc_method_name); + return (union _zend_function *)call_user_call; + } else { + return NULL; + } + } + + /* Check access level */ + if (fbc->op_array.fn_flags & ZEND_ACC_PUBLIC) { + /* Ensure that we haven't overridden a private function and end up calling + * the overriding public function... + */ + if (EG(scope) && fbc->op_array.fn_flags & ZEND_ACC_CHANGED) { + zend_function *priv_fbc; + + if (zend_hash_find(&EG(scope)->function_table, method_name, method_len+1, (void **) &priv_fbc)==SUCCESS + && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE) { + fbc = priv_fbc; + } + } + } else if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) { + zend_function *updated_fbc; + + /* Ensure that if we're calling a private function, we're allowed to do so. + */ + updated_fbc = zend_check_private(fbc, object->value.obj.handlers->get_class_entry(object TSRMLS_CC), fbc->common.fn_flags, method_name, method_len TSRMLS_CC); + if (!updated_fbc) { + zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : ""); + } + fbc = updated_fbc; + } else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) { + /* Ensure that if we're calling a protected function, we're allowed to do so. + */ + if (!zend_check_protected(fbc->common.scope, EG(scope))) { + zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), method_name, EG(scope) ? EG(scope)->name : ""); + } + } + + free_alloca(lc_method_name); + return fbc; } + +/* This is not (yet?) in the API, but it belongs in the built-in objects callbacks */ +zend_function *zend_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC) +{ + zend_function *fbc; + + if (zend_hash_find(&ce->function_table, function_name_strval, function_name_strlen+1, (void **) &fbc)==FAILURE) { + zend_error(E_ERROR, "Call to undefined method %s::%s()", ce->name, function_name_strval); + } + if (fbc->op_array.fn_flags & ZEND_ACC_PUBLIC) { + /* No further checks necessary, most common case */ + } else if (fbc->op_array.fn_flags & ZEND_ACC_PRIVATE) { + zend_function *updated_fbc; + + /* Ensure that if we're calling a private function, we're allowed to do so. + */ + updated_fbc = zend_check_private(fbc, EG(scope), fbc->common.fn_flags, function_name_strval, function_name_strlen TSRMLS_CC); + if (!updated_fbc) { + zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : ""); + } + fbc = updated_fbc; + } else if ((fbc->common.fn_flags & ZEND_ACC_PROTECTED)) { + /* Ensure that if we're calling a protected function, we're allowed to do so. + */ + if (!zend_check_protected(EG(scope), fbc->common.scope)) { + zend_error(E_ERROR, "Call to %s method %s::%s() from context '%s'", zend_visibility_string(fbc->common.fn_flags), ZEND_FN_SCOPE_NAME(fbc), function_name_strval, EG(scope) ? EG(scope)->name : ""); + } + } + + return fbc; +} + + +zval **zend_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, int type TSRMLS_DC) +{ + HashTable *statics_table; + zval **retval = NULL; + zend_class_entry *tmp_ce = ce; + zend_property_info *property_info; + zend_property_info std_property_info; + + if (zend_hash_find(&ce->properties_info, property_name, property_name_len+1, (void **) &property_info)==FAILURE) { + std_property_info.flags = ZEND_ACC_PUBLIC; + std_property_info.name = property_name; + std_property_info.name_length = property_name_len; + std_property_info.h = zend_get_hash_value(std_property_info.name, std_property_info.name_length+1); + property_info = &std_property_info; + } + +#if 1&&DEBUG_OBJECT_HANDLERS + zend_printf("Access type for %s::%s is %s\n", ce->name, property_name, zend_visibility_string(property_info->flags)); +#endif + + if (!zend_verify_property_access(property_info, ce TSRMLS_CC)) { + zend_error(E_ERROR, "Cannot access %s property %s::$%s", zend_visibility_string(property_info->flags), ce->name, property_name); + } + + while (tmp_ce) { + if (zend_hash_quick_find(tmp_ce->static_members, property_info->name, property_info->name_length+1, property_info->h, (void **) &retval)==SUCCESS) { + statics_table = tmp_ce->static_members; + break; + } + tmp_ce = tmp_ce->parent; + } + + if (!retval) { + switch (type) { + case BP_VAR_R: + zend_error(E_NOTICE,"Undefined variable: %s::$%s", ce->name, property_name); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval_ptr); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined variable: %s::$%s", ce->name, property_name); + /* break missing intentionally */ + case BP_VAR_W: { + zval *new_zval = &EG(uninitialized_zval); + + new_zval->refcount++; + zend_hash_quick_update(ce->static_members, property_info->name, property_info->name_length+1, property_info->h, &new_zval, sizeof(zval *), (void **) &retval); + } + break; + EMPTY_SWITCH_DEFAULT_CASE() + } + } else { + zval_update_constant(retval, (void *) 1 TSRMLS_CC); + } + + return retval; +} + + +static union _zend_function *zend_std_get_constructor(zval *object TSRMLS_DC) +{ + zend_object *zobj = Z_OBJ_P(object); + zend_function *constructor = zobj->ce->constructor; + + if (constructor) { + if (constructor->op_array.fn_flags & ZEND_ACC_PUBLIC) { + /* No further checks necessary */ + } else if (constructor->op_array.fn_flags & ZEND_ACC_PRIVATE) { + /* Ensure that if we're calling a private function, we're allowed to do so. + */ + if (object->value.obj.handlers->get_class_entry(object TSRMLS_CC) != EG(scope)) { + zend_error(E_ERROR, "Call to private constructor from context '%s'", EG(scope) ? EG(scope)->name : ""); + } + } else if ((constructor->common.fn_flags & ZEND_ACC_PROTECTED)) { + /* Ensure that if we're calling a protected function, we're allowed to do so. + */ + if (!zend_check_protected(constructor->common.scope, EG(scope))) { + zend_error(E_ERROR, "Call to protected constructor from context '%s'", EG(scope) ? EG(scope)->name : ""); + } + } + } + + return constructor; +} + + int zend_compare_symbol_tables_i(HashTable *ht1, HashTable *ht2 TSRMLS_DC); + static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) { zend_object *zobj1, *zobj2; @@ -177,30 +713,38 @@ zobj1 = Z_OBJ_P(o1); zobj2 = Z_OBJ_P(o2); - if(zobj1->ce != zobj2->ce) { + if (zobj1->ce != zobj2->ce) { return 1; /* different classes */ } return zend_compare_symbol_tables_i(zobj1->properties, zobj2->properties TSRMLS_CC); } + static int zend_std_has_property(zval *object, zval *member, int check_empty TSRMLS_DC) { zend_object *zobj; int result; zval **value; zval tmp_member; + zend_property_info *property_info; zobj = Z_OBJ_P(object); - + if (member->type != IS_STRING) { tmp_member = *member; zval_copy_ctor(&tmp_member); convert_to_string(&tmp_member); member = &tmp_member; } - - if(zend_hash_find(zobj->properties, Z_STRVAL_P(member), Z_STRLEN_P(member)+1, (void **)&value) == SUCCESS) { - if(check_empty) { + +#if DEBUG_OBJECT_HANDLERS + fprintf(stderr, "Read object #%d property: %s\n", Z_OBJ_HANDLE_P(object), Z_STRVAL_P(member)); +#endif + + property_info = zend_get_property_info(zobj, member TSRMLS_CC); + + if (zend_hash_find(zobj->properties, property_info->name, property_info->name_length+1, (void **) &value) == SUCCESS) { + if (check_empty) { result = zend_is_true(*value); } else { result = (Z_TYPE_PP(value) != IS_NULL); @@ -215,6 +759,7 @@ return result; } + zend_class_entry *zend_std_object_get_class(zval *object TSRMLS_DC) { zend_object *zobj; @@ -223,10 +768,28 @@ return zobj->ce; } +int zend_std_object_get_class_name(zval *object, char **class_name, zend_uint *class_name_len, int parent TSRMLS_DC) +{ + zend_object *zobj; + zobj = Z_OBJ_P(object); + + if (parent) { + if (!zobj->ce->parent) { + return FAILURE; + } + *class_name = zobj->ce->parent->name; + *class_name_len = zobj->ce->parent->name_length; + } else { + *class_name = zobj->ce->name; + *class_name_len = zobj->ce->name_length; + } + return SUCCESS; +} + zend_object_handlers std_object_handlers = { - zend_objects_add_ref, /* add_ref */ - zend_objects_del_ref, /* del_ref */ - zend_objects_delete_obj, /* delete_obj */ + zend_objects_store_add_ref, /* add_ref */ + zend_objects_store_del_ref, /* del_ref */ + zend_objects_store_delete_obj, /* delete_obj */ zend_objects_clone_obj, /* clone_obj */ zend_std_read_property, /* read_property */ @@ -242,7 +805,14 @@ NULL, /* call_method */ zend_std_get_constructor, /* get_constructor */ zend_std_object_get_class, /* get_class_entry */ - NULL, /* get_class_name */ + zend_std_object_get_class_name, /* get_class_name */ zend_std_compare_objects /* compare_objects */ }; +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.6 +35 -2 ZendEngine2/zend_object_handlers.h Index: zend_object_handlers.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_object_handlers.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- zend_object_handlers.h 3 Aug 2002 08:56:16 -0000 1.5 +++ zend_object_handlers.h 11 Feb 2003 02:40:19 -0000 1.6 @@ -1,9 +1,30 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | licen****@zend***** so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans <andi****@zend*****> | + | Zeev Suraski <zeev****@zend*****> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: zend_object_handlers.h,v 1.13 2003/02/05 14:27:30 zeev Exp $ */ + #ifndef ZEND_OBJECT_HANDLERS_H #define ZEND_OBJECT_HANDLERS_H union _zend_function; -typedef zval *(*zend_object_read_property_t)(zval *object, zval *member, int type TSRMLS_DC); +typedef zval *(*zend_object_read_property_t)(zval *object, zval *member TSRMLS_DC); /* Used to fetch property from the object, read-only */ typedef void (*zend_object_write_property_t)(zval *object, zval *member, zval *value TSRMLS_DC); /* Used to set property of the object */ @@ -72,7 +93,19 @@ } zend_object_handlers; extern zend_object_handlers std_object_handlers; +union _zend_function *zend_get_static_method(zend_class_entry *ce, char *function_name_strval, int function_name_strlen TSRMLS_DC); +zval **zend_get_static_property(zend_class_entry *ce, char *property_name, int property_name_len, int type TSRMLS_DC); -#define IS_ZEND_STD_OBJECT(z) ((z).type == IS_OBJECT && Z_OBJ_HT(z) == &std_object_handlers) + +#define IS_ZEND_STD_OBJECT(z) ((z).type == IS_OBJECT && (Z_OBJ_HT((z))->get_class_entry != NULL)) +#define HAS_CLASS_ENTRY(z) (Z_OBJ_HT(z)->get_class_entry != NULL) #endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.6 +43 -147 ZendEngine2/zend_objects.c Index: zend_objects.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_objects.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- zend_objects.c 3 Aug 2002 08:56:16 -0000 1.5 +++ zend_objects.c 11 Feb 2003 02:40:19 -0000 1.6 @@ -1,23 +1,29 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | licen****@zend***** so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans <andi****@zend*****> | + | Zeev Suraski <zeev****@zend*****> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: zend_objects.c,v 1.27 2003/02/01 01:49:14 sniper Exp $ */ + #include "zend.h" #include "zend_globals.h" #include "zend_variables.h" #include "zend_API.h" -#define ZEND_DEBUG_OBJECTS 0 - -void zend_objects_init(zend_objects *objects, zend_uint init_size) -{ - objects->object_buckets = (zend_object_bucket *) emalloc(init_size * sizeof(zend_object_bucket)); - objects->top = 1; /* Skip 0 so that handles are true */ - objects->size = init_size; - objects->free_list_head = -1; -} - -void zend_objects_destroy(zend_objects *objects) -{ - efree(objects->object_buckets); -} - static inline void zend_objects_call_destructor(zend_object *object, zend_object_handle handle TSRMLS_DC) { if (object->ce->destructor) { @@ -53,162 +59,44 @@ } -static inline void zend_objects_destroy_object(zend_object *object, zend_object_handle handle TSRMLS_DC) +ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handle handle TSRMLS_DC) { zend_objects_call_destructor(object, handle TSRMLS_CC); /* Nuke the object */ zend_hash_destroy(object->properties); - efree(object->properties); - + FREE_HASHTABLE(object->properties); + efree(object); } - -void zend_objects_call_destructors(zend_objects *objects TSRMLS_DC) -{ - zend_uint i = 1; - - for (i = 1; i < objects->top ; i++) { - if (EG(objects).object_buckets[i].valid) { - EG(objects).object_buckets[i].destructor_called = 1; - zend_objects_destroy_object(&EG(objects).object_buckets[i].bucket.obj.object, i TSRMLS_CC); - EG(objects).object_buckets[i].valid = 0; - } - } -} - - -zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type) -{ - zend_object_handle handle; +ZEND_API zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type) +{ zend_object_value retval; TSRMLS_FETCH(); - if (EG(objects).free_list_head != -1) { - handle = EG(objects).free_list_head; - EG(objects).free_list_head = EG(objects).object_buckets[handle].bucket.free_list.next; - } else { - if (EG(objects).top == EG(objects).size) { - EG(objects).size <<= 1; - EG(objects).object_buckets = (zend_object_bucket *) erealloc(EG(objects).object_buckets, EG(objects).size * sizeof(zend_object_bucket)); - } - handle = EG(objects).top++; - } - EG(objects).object_buckets[handle].valid = 1; - EG(objects).object_buckets[handle].destructor_called = 0; - EG(objects).object_buckets[handle].bucket.obj.refcount = 1; - - *object = &EG(objects).object_buckets[handle].bucket.obj.object; - + *object = emalloc(sizeof(zend_object)); (*object)->ce = class_type; - - retval.handle = handle; + retval.handle = zend_objects_store_put(*object, (zend_objects_store_dtor_t) zend_objects_destroy_object, NULL TSRMLS_CC); retval.handlers = &std_object_handlers; -#if ZEND_DEBUG_OBJECTS - fprintf(stderr, "Allocated object id #%d\n", handle); -#endif + (*object)->in_get = 0; + (*object)->in_set = 0; return retval; } -zend_object *zend_objects_get_address(zval *zobject) +ZEND_API zend_object *zend_objects_get_address(zval *zobject) { - zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); TSRMLS_FETCH(); - - if (!EG(objects).object_buckets[handle].valid) { - zend_error(E_ERROR, "Trying to access invalid object"); - } - return &EG(objects).object_buckets[handle].bucket.obj.object; -} - -void zend_objects_add_ref(zval *object TSRMLS_DC) -{ - zend_object_handle handle = Z_OBJ_HANDLE_P(object); - - if (!EG(objects).object_buckets[handle].valid) { - zend_error(E_ERROR, "Trying to add reference to invalid object"); - } - - EG(objects).object_buckets[handle].bucket.obj.refcount++; -#if ZEND_DEBUG_OBJECTS - fprintf(stderr, "Increased refcount of object id #%d\n", handle); -#endif + return (zend_object *)zend_object_store_get_object(zobject TSRMLS_CC); } -void zend_objects_delete_obj(zval *zobject TSRMLS_DC) -{ - zend_object *object; - zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); - - if (!EG(objects).object_buckets[handle].valid) { - zend_error(E_ERROR, "Trying to delete invalid object"); - } - - object = &EG(objects).object_buckets[handle].bucket.obj.object; - - if (!EG(objects).object_buckets[handle].destructor_called) { - EG(objects).object_buckets[handle].destructor_called = 1; - zend_objects_destroy_object(object, handle TSRMLS_CC); - } - - EG(objects).object_buckets[handle].valid = 0; - -#if ZEND_DEBUG_OBJECTS - fprintf(stderr, "Deleted object id #%d\n", handle); -#endif - -} - -#define ZEND_OBJECTS_ADD_TO_FREE_LIST() \ - EG(objects).object_buckets[handle].bucket.free_list.next = EG(objects).free_list_head; \ - EG(objects).free_list_head = handle; \ - EG(objects).object_buckets[handle].valid = 0; - -void zend_objects_del_ref(zval *zobject TSRMLS_DC) -{ - zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); - - if (--EG(objects).object_buckets[handle].bucket.obj.refcount == 0) { - zend_object *object; - do { - if (EG(objects).object_buckets[handle].valid) { - if (!EG(objects).object_buckets[handle].destructor_called) { - object = &EG(objects).object_buckets[handle].bucket.obj.object; - EG(objects).object_buckets[handle].destructor_called = 1; - zend_objects_destroy_object(object, handle TSRMLS_CC); - if (EG(objects).object_buckets[handle].bucket.obj.refcount == 0) { - ZEND_OBJECTS_ADD_TO_FREE_LIST(); - } - break; - } - } - ZEND_OBJECTS_ADD_TO_FREE_LIST(); - } while (0); - -#if ZEND_DEBUG_OBJECTS - fprintf(stderr, "Deallocated object id #%d\n", handle); -#endif - } -#if ZEND_DEBUG_OBJECTS - else { - fprintf(stderr, "Decreased refcount of object id #%d\n", handle); - } -#endif -} - -zend_object_value zend_objects_clone_obj(zval *zobject TSRMLS_DC) +ZEND_API zend_object_value zend_objects_clone_obj(zval *zobject TSRMLS_DC) { zend_object_value retval; zend_object *old_object; zend_object *new_object; zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); - - if (!EG(objects).object_buckets[handle].valid) { - zend_error(E_ERROR, "Trying to clone invalid object"); - } - - old_object = &EG(objects).object_buckets[handle].bucket.obj.object; + old_object = zend_objects_get_address(zobject); retval = zend_objects_new(&new_object, old_object->ce); if (old_object->ce->clone) { @@ -239,7 +127,7 @@ zend_hash_init(new_object->properties, 0, NULL, ZVAL_PTR_DTOR, 0); ZEND_INIT_SYMTABLE(&symbol_table); - ZEND_SET_SYMBOL(&symbol_table, "clone", old_obj); + ZEND_SET_SYMBOL(&symbol_table, "that", old_obj); call_user_function_ex(NULL, &new_obj, clone_func_name, &retval_ptr, 0, NULL, 0, &symbol_table TSRMLS_CC); @@ -255,3 +143,11 @@ return retval; } + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.6 +33 -32 ZendEngine2/zend_objects.h Index: zend_objects.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_objects.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- zend_objects.h 3 Aug 2002 08:56:16 -0000 1.5 +++ zend_objects.h 11 Feb 2003 02:40:19 -0000 1.6 @@ -1,39 +1,40 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | licen****@zend***** so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans <andi****@zend*****> | + | Zeev Suraski <zeev****@zend*****> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: zend_objects.h,v 1.16 2003/02/01 01:49:14 sniper Exp $ */ + #ifndef ZEND_OBJECTS_H #define ZEND_OBJECTS_H #include "zend.h" -typedef struct _zend_object_bucket { - zend_bool valid; - zend_bool destructor_called; - union _bucket { - struct { - zend_object object; - zend_uint refcount; - } obj; - struct { - int next; - } free_list; - } bucket; -} zend_object_bucket; - -typedef struct _zend_objects { - zend_object_bucket *object_buckets; - zend_uint top; - zend_uint size; - int free_list_head; -} zend_objects; - -void zend_objects_init(zend_objects *objects, zend_uint init_size); -void zend_objects_call_destructors(zend_objects *objects TSRMLS_DC); -void zend_objects_destroy(zend_objects *objects); -zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type); - -zend_object *zend_objects_get_address(zval *object); - -void zend_objects_add_ref(zval *object TSRMLS_DC); -void zend_objects_del_ref(zval *object TSRMLS_DC); -void zend_objects_delete_obj(zval *object TSRMLS_DC); -zend_object_value zend_objects_clone_obj(zval *object TSRMLS_DC); +ZEND_API zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type); +ZEND_API void zend_objects_destroy_object(zend_object *object, zend_object_handle handle TSRMLS_DC); +ZEND_API zend_object *zend_objects_get_address(zval *object); +ZEND_API zend_object_value zend_objects_clone_obj(zval *object TSRMLS_DC); #endif /* ZEND_OBJECTS_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.4 +56 -22 ZendEngine2/zend_objects_API.c Index: zend_objects_API.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_objects_API.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- zend_objects_API.c 3 Aug 2002 08:56:16 -0000 1.3 +++ zend_objects_API.c 11 Feb 2003 02:40:19 -0000 1.4 @@ -1,3 +1,24 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | licen****@zend***** so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans <andi****@zend*****> | + | Zeev Suraski <zeev****@zend*****> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: zend_objects_API.c,v 1.14 2003/02/05 14:27:30 zeev Exp $ */ + #include "zend.h" #include "zend_globals.h" #include "zend_variables.h" @@ -6,7 +27,7 @@ #define ZEND_DEBUG_OBJECTS 0 -void zend_objects_store_init(zend_objects_store *objects, zend_uint init_size) +ZEND_API void zend_objects_store_init(zend_objects_store *objects, zend_uint init_size) { objects->object_buckets = (zend_object_store_bucket *) emalloc(init_size * sizeof(zend_object_store_bucket)); objects->top = 1; /* Skip 0 so that handles are true */ @@ -14,19 +35,19 @@ objects->free_list_head = -1; } -void zend_objects_store_destroy(zend_objects_store *objects) +ZEND_API void zend_objects_store_destroy(zend_objects_store *objects) { efree(objects->object_buckets); } -void zend_objects_store_call_destructors(zend_objects_store *objects TSRMLS_DC) +ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TSRMLS_DC) { zend_uint i = 1; for (i = 1; i < objects->top ; i++) { if (objects->object_buckets[i].valid) { struct _store_object *obj = &objects->object_buckets[i].bucket.obj; - if(obj->dtor) { + if (obj->dtor && !objects->object_buckets[i].destructor_called) { objects->object_buckets[i].destructor_called = 1; obj->dtor(obj->object, i TSRMLS_CC); } @@ -37,7 +58,7 @@ /* Store objects API */ -zend_object_handle zend_objects_store_put(void *object, zend_objects_store_dtor_t dtor, zend_objects_store_clone_t clone TSRMLS_DC) +ZEND_API zend_object_handle zend_objects_store_put(void *object, zend_objects_store_dtor_t dtor, zend_objects_store_clone_t clone TSRMLS_DC) { zend_object_handle handle; struct _store_object *obj; @@ -67,7 +88,7 @@ return handle; } -void zend_objects_store_add_ref(zval *object TSRMLS_DC) +ZEND_API void zend_objects_store_add_ref(zval *object TSRMLS_DC) { zend_object_handle handle = Z_OBJ_HANDLE_P(object); @@ -81,7 +102,7 @@ #endif } -void zend_objects_store_delete_obj(zval *zobject TSRMLS_DC) +ZEND_API void zend_objects_store_delete_obj(zval *zobject TSRMLS_DC) { zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); struct _store_object *obj = &EG(objects_store).object_buckets[handle].bucket.obj; @@ -91,7 +112,7 @@ } - if(obj->dtor && !EG(objects_store).object_buckets[handle].destructor_called) { + if (obj->dtor && !EG(objects_store).object_buckets[handle].destructor_called) { EG(objects_store).object_buckets[handle].destructor_called = 1; obj->dtor(obj->object, handle TSRMLS_CC); } @@ -108,14 +129,14 @@ EG(objects_store).free_list_head = handle; \ EG(objects_store).object_buckets[handle].valid = 0; -void zend_objects_store_del_ref(zval *zobject TSRMLS_DC) +ZEND_API void zend_objects_store_del_ref(zval *zobject TSRMLS_DC) { zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); struct _store_object *obj = &EG(objects_store).object_buckets[handle].bucket.obj; if (--obj->refcount == 0) { if (EG(objects_store).object_buckets[handle].valid) { - if(!EG(objects_store).object_buckets[handle].destructor_called) { + if (!EG(objects_store).object_buckets[handle].destructor_called) { EG(objects_store).object_buckets[handle].destructor_called = 1; if (obj->dtor) { obj->dtor(obj->object, handle TSRMLS_CC); @@ -137,7 +158,7 @@ #endif } -zend_object_value zend_objects_store_clone_obj(zval *zobject TSRMLS_DC) +ZEND_API zend_object_value zend_objects_store_clone_obj(zval *zobject TSRMLS_DC) { zend_object_value retval; void *new_object; @@ -149,11 +170,11 @@ } obj = &EG(objects_store).object_buckets[handle].bucket.obj; - if(obj->clone == NULL) { + if (obj->clone == NULL) { zend_error(E_ERROR, "Trying to clone uncloneable object"); } - obj->clone(&obj->object, &new_object TSRMLS_CC); + obj->clone(obj->object, &new_object TSRMLS_CC); retval.handle = zend_objects_store_put(new_object, obj->dtor, obj->clone TSRMLS_CC); retval.handlers = Z_OBJ_HT_P(zobject); @@ -161,7 +182,7 @@ return retval; } -void *zend_object_store_get_object(zval *zobject TSRMLS_DC) +ZEND_API void *zend_object_store_get_object(zval *zobject TSRMLS_DC) { zend_object_handle handle = Z_OBJ_HANDLE_P(zobject); @@ -182,14 +203,14 @@ static zend_object_handlers zend_object_proxy_handlers; -void zend_objects_proxy_dtor(zend_proxy_object *object, zend_object_handle handle TSRMLS_DC) +ZEND_API void zend_objects_proxy_dtor(zend_proxy_object *object, zend_object_handle handle TSRMLS_DC) { zval_ptr_dtor(&object->object); zval_ptr_dtor(&object->property); efree(object); } -void zend_objects_proxy_clone(zend_proxy_object *object, zend_proxy_object **object_clone TSRMLS_DC) +ZEND_API void zend_objects_proxy_clone(zend_proxy_object *object, zend_proxy_object **object_clone TSRMLS_DC) { *object_clone = emalloc(sizeof(zend_proxy_object)); (*object_clone)->object = object->object; @@ -198,7 +219,7 @@ zval_add_ref(&(*object_clone)->object); } -zval **zend_object_create_proxy(zval *object, zval *member TSRMLS_DC) +ZEND_API zval **zend_object_create_proxy(zval *object, zval *member TSRMLS_DC) { zend_proxy_object *pobj = emalloc(sizeof(zend_proxy_object)); zval *retval, **pretval; @@ -218,23 +239,23 @@ return pretval; } -void zend_object_proxy_set(zval **property, zval *value TSRMLS_DC) +ZEND_API void zend_object_proxy_set(zval **property, zval *value TSRMLS_DC) { zend_proxy_object *probj = zend_object_store_get_object(*property TSRMLS_CC); - if(Z_OBJ_HT_P(probj->object) && Z_OBJ_HT_P(probj->object)->write_property) { + if (Z_OBJ_HT_P(probj->object) && Z_OBJ_HT_P(probj->object)->write_property) { Z_OBJ_HT_P(probj->object)->write_property(probj->object, probj->property, value TSRMLS_CC); } else { zend_error(E_WARNING, "Cannot write property of object - no write handler defined"); } } -zval* zend_object_proxy_get(zval *property TSRMLS_DC) +ZEND_API zval* zend_object_proxy_get(zval *property TSRMLS_DC) { zend_proxy_object *probj = zend_object_store_get_object(property TSRMLS_CC); - if(Z_OBJ_HT_P(probj->object) && Z_OBJ_HT_P(probj->object)->read_property) { - return Z_OBJ_HT_P(probj->object)->read_property(probj->object, probj->property, BP_VAR_R TSRMLS_CC); + if (Z_OBJ_HT_P(probj->object) && Z_OBJ_HT_P(probj->object)->read_property) { + return Z_OBJ_HT_P(probj->object)->read_property(probj->object, probj->property TSRMLS_CC); } else { zend_error(E_WARNING, "Cannot read property of object - no read handler defined"); } @@ -242,6 +263,11 @@ return NULL; } +ZEND_API zend_object_handlers *zend_get_std_object_handlers() +{ + return &std_object_handlers; +} + static zend_object_handlers zend_object_proxy_handlers = { ZEND_OBJECTS_STORE_HANDLERS, @@ -261,3 +287,11 @@ NULL, /* get_class_name */ NULL /* compare_objects */ }; + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +41 -10 ZendEngine2/zend_objects_API.h Index: zend_objects_API.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_objects_API.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_objects_API.h 2 Aug 2002 09:48:15 -0000 1.2 +++ zend_objects_API.h 11 Feb 2003 02:40:19 -0000 1.3 @@ -1,3 +1,24 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | + +----------------------------------------------------------------------+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is | + | available at through the world-wide-web at | + | http://www.zend.com/license/2_00.txt. | + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | licen****@zend***** so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans <andi****@zend*****> | + | Zeev Suraski <zeev****@zend*****> | + +----------------------------------------------------------------------+ +*/ + +/* $Id: zend_objects_API.h,v 1.4 2003/02/01 01:49:14 sniper Exp $ */ + #ifndef ZEND_OBJECTS_API_H #define ZEND_OBJECTS_API_H @@ -30,20 +51,30 @@ } zend_objects_store; /* Global store handling functions */ -void zend_objects_store_init(zend_objects_store *objects, zend_uint init_size); -void zend_objects_store_call_destructors(zend_objects_store *objects TSRMLS_DC); -void zend_objects_store_destroy(zend_objects_store *objects); +ZEND_API void zend_objects_store_init(zend_objects_store *objects, zend_uint init_size); +ZEND_API void zend_objects_store_call_destructors(zend_objects_store *objects TSRMLS_DC); +ZEND_API void zend_objects_store_destroy(zend_objects_store *objects); /* Store API functions */ -zend_object_handle zend_objects_store_put(void *object, zend_objects_store_dtor_t dtor, zend_objects_store_clone_t clone TSRMLS_DC); +ZEND_API zend_object_handle zend_objects_store_put(void *object, zend_objects_store_dtor_t dtor, zend_objects_store_clone_t clone TSRMLS_DC); -void zend_objects_store_add_ref(zval *object TSRMLS_DC); -void zend_objects_store_del_ref(zval *object TSRMLS_DC); -void zend_objects_store_delete_obj(zval *object TSRMLS_DC); -zend_object_value zend_objects_store_clone_obj(zval *object TSRMLS_DC); -void *zend_object_store_get_object(zval *object TSRMLS_DC); +ZEND_API void zend_objects_store_add_ref(zval *object TSRMLS_DC); +ZEND_API void zend_objects_store_del_ref(zval *object TSRMLS_DC); +ZEND_API void zend_objects_store_delete_obj(zval *object TSRMLS_DC); +ZEND_API zend_object_value zend_objects_store_clone_obj(zval *object TSRMLS_DC); +ZEND_API void *zend_object_store_get_object(zval *object TSRMLS_DC); #define ZEND_OBJECTS_STORE_HANDLERS zend_objects_store_add_ref, zend_objects_store_del_ref, zend_objects_store_delete_obj, zend_objects_store_clone_obj -zval **zend_object_create_proxy(zval *object, zval *member TSRMLS_DC); +ZEND_API zval **zend_object_create_proxy(zval *object, zval *member TSRMLS_DC); + +ZEND_API zend_object_handlers *zend_get_std_object_handlers(); #endif /* ZEND_OBJECTS_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +56 -6 ZendEngine2/zend_opcode.c Index: zend_opcode.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_opcode.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_opcode.c 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_opcode.c 11 Feb 2003 02:40:19 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_opcode.c,v 1.81 2003/02/05 13:35:52 zeev Exp $ */ #include <stdio.h> @@ -107,6 +108,33 @@ } } +static void zend_cleanup_op_array_data(zend_op_array *op_array) +{ + if (op_array->static_variables) { + zend_hash_clean(op_array->static_variables); + } +} + +ZEND_API int zend_cleanup_function_data(zend_function *function TSRMLS_DC) +{ + if(function->type == ZEND_USER_FUNCTION) { + zend_cleanup_op_array_data((zend_op_array *) function); + } + return 0; +} + +ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC) +{ + if((*pce)->type == ZEND_USER_CLASS) { + /* Clean all parts that can contain run-time data */ + /* Note that only run-time accessed data need to be cleaned up, pre-defined data can + not contain objects and thus are not probelmatic */ + zend_hash_clean((*pce)->static_members); + zend_hash_apply(&(*pce)->class_table, (apply_func_t) zend_cleanup_class_data TSRMLS_CC); + zend_hash_apply(&(*pce)->function_table, (apply_func_t) zend_cleanup_function_data TSRMLS_CC); + } + return 0; +} ZEND_API void destroy_zend_class(zend_class_entry **pce) { @@ -118,7 +146,7 @@ switch (ce->type) { case ZEND_USER_CLASS: zend_hash_destroy(&ce->default_properties); - zend_hash_destroy(&ce->private_properties); + zend_hash_destroy(&ce->properties_info); zend_hash_destroy(ce->static_members); efree(ce->name); zend_hash_destroy(&ce->function_table); @@ -129,7 +157,7 @@ break; case ZEND_INTERNAL_CLASS: zend_hash_destroy(&ce->default_properties); - zend_hash_destroy(&ce->private_properties); + zend_hash_destroy(&ce->properties_info); zend_hash_destroy(ce->static_members); free(ce->name); zend_hash_destroy(&ce->function_table); @@ -293,6 +321,9 @@ zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array TSRMLS_CC); } + op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last); + op_array->size = op_array->last; + opline = op_array->opcodes; end = opline + op_array->last; while (opline < end) { @@ -304,10 +335,21 @@ opline->op2.u.constant.is_ref = 1; opline->op2.u.constant.refcount = 2; } + switch (opline->opcode) { + case ZEND_JMP: + opline->op1.u.jmp_addr = &op_array->opcodes[opline->op1.u.opline_num]; + break; + case ZEND_JMPZ: + case ZEND_JMPNZ: + case ZEND_JMPZ_EX: + case ZEND_JMPNZ_EX: + opline->op2.u.jmp_addr = &op_array->opcodes[opline->op2.u.opline_num]; + break; + } + opline->handler = zend_opcode_handlers[opline->opcode]; opline++; } - op_array->opcodes = (zend_op *) erealloc(op_array->opcodes, sizeof(zend_op)*op_array->last); - op_array->size = op_array->last; + op_array->done_pass_two = 1; return 0; } @@ -323,7 +365,7 @@ ZEND_API unary_op_type get_unary_op(int opcode) { - switch(opcode) { + switch (opcode) { case ZEND_BW_NOT: return (unary_op_type) bitwise_not_function; break; @@ -407,3 +449,11 @@ break; } } + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.5 +83 -37 ZendEngine2/zend_operators.c Index: zend_operators.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_operators.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_operators.c 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_operators.c 11 Feb 2003 02:40:19 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,12 +17,9 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_operators.c,v 1.143 2003/02/01 01:49:14 sniper Exp $ */ -#include <stdio.h> -#include <errno.h> -#include <stdlib.h> #include <ctype.h> -#include <math.h> #include "zend.h" #include "zend_operators.h" @@ -43,7 +40,7 @@ if (!str_len) { str_len = strlen(str); } - retval = atoi(str); + retval = strtol(str, NULL, 0); if (str_len>0) { switch (str[str_len-1]) { case 'k': @@ -509,7 +506,7 @@ { TSRMLS_FETCH(); - switch(op->type) { + switch (op->type) { case IS_ARRAY: return; break; @@ -521,7 +518,7 @@ ALLOC_HASHTABLE(ht); zend_hash_init(ht, 0, NULL, ZVAL_PTR_DTOR, 0); - if(Z_OBJ_HT_P(op)->get_properties) { + if (Z_OBJ_HT_P(op)->get_properties) { zend_hash_copy(ht, Z_OBJ_HT_P(op)->get_properties(op TSRMLS_CC), (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *)); } zval_dtor(op); @@ -543,7 +540,7 @@ ZEND_API void convert_to_object(zval *op) { - switch(op->type) { + switch (op->type) { case IS_ARRAY: { /* OBJECTS_OPTIMIZE */ @@ -839,7 +836,7 @@ return SUCCESS; } if (op1->type == IS_STRING) { - zend_uint i; + int i; result->type = IS_STRING; result->value.str.val = estrndup(op1->value.str.val, op1->value.str.len); @@ -861,7 +858,7 @@ if (op1->type == IS_STRING && op2->type == IS_STRING) { zval *longer, *shorter; char *result_str; - zend_uint i, result_len; + int i, result_len; if (op1->value.str.len >= op2->value.str.len) { longer = op1; @@ -878,7 +875,7 @@ result_str[i] |= shorter->value.str.val[i]; } if (result==op1) { - efree(result->value.str.val); + STR_FREE(result->value.str.val); } result->value.str.val = result_str; result->value.str.len = result_len; @@ -900,7 +897,7 @@ if (op1->type == IS_STRING && op2->type == IS_STRING) { zval *longer, *shorter; char *result_str; - zend_uint i, result_len; + int i, result_len; if (op1->value.str.len >= op2->value.str.len) { longer = op1; @@ -917,7 +914,7 @@ result_str[i] &= longer->value.str.val[i]; } if (result==op1) { - efree(result->value.str.val); + STR_FREE(result->value.str.val); } result->value.str.val = result_str; result->value.str.len = result_len; @@ -941,7 +938,7 @@ if (op1->type == IS_STRING && op2->type == IS_STRING) { zval *longer, *shorter; char *result_str; - zend_uint i, result_len; + int i, result_len; if (op1->value.str.len >= op2->value.str.len) { longer = op1; @@ -958,7 +955,7 @@ result_str[i] ^= longer->value.str.val[i]; } if (result==op1) { - efree(result->value.str.val); + STR_FREE(result->value.str.val); } result->value.str.val = result_str; result->value.str.len = result_len; @@ -1254,7 +1251,7 @@ } break; case IS_OBJECT: - if(Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2) && Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) { + if (Z_OBJ_HT_P(op1) == Z_OBJ_HT_P(op2) && Z_OBJ_HANDLE_P(op1) == Z_OBJ_HANDLE_P(op2)) { result->value.lval = 1; } else { result->value.lval = 0; @@ -1365,6 +1362,21 @@ } +ZEND_API int instanceof_function(zval *result, zval *op1, zend_class_entry *class TSRMLS_DC) +{ + if (Z_TYPE_P(op1) == IS_OBJECT) { + zend_class_entry *ce; + for (ce = Z_OBJCE_P(op1); ce != NULL; ce = ce->parent) { + if (ce == class) { + ZVAL_BOOL(result, 1); + return SUCCESS; + } + } + } + ZVAL_BOOL(result, 0); + return SUCCESS; +} + #define LOWER_CASE 1 #define UPPER_CASE 2 #define NUMERIC 3 @@ -1451,7 +1463,7 @@ { switch (op1->type) { case IS_LONG: - if(op1->value.lval == LONG_MAX) { + if (op1->value.lval == LONG_MAX) { /* switch to double */ double d = (double)op1->value.lval; ZVAL_DOUBLE(op1, d+1); @@ -1473,7 +1485,7 @@ switch (is_numeric_string(strval, op1->value.str.len, &lval, &dval, 0)) { case IS_LONG: - if(lval == LONG_MAX) { + if (lval == LONG_MAX) { /* switch to double */ double d = (double)lval; ZVAL_DOUBLE(op1, d+1); @@ -1481,12 +1493,12 @@ op1->value.lval = lval+1; op1->type = IS_LONG; } - efree(strval); + efree(strval); /* should never be empty_string */ break; case IS_DOUBLE: op1->value.dval = dval+1; op1->type = IS_DOUBLE; - efree(strval); + efree(strval); /* should never be empty_string */ break; #if 0 case FLAG_IS_BC: @@ -1509,10 +1521,11 @@ ZEND_API int decrement_function(zval *op1) { long lval; + double dval; switch (op1->type) { case IS_LONG: - if(op1->value.lval == LONG_MIN) { + if (op1->value.lval == LONG_MIN) { double d = (double)op1->value.lval; ZVAL_DOUBLE(op1, d-1); } else { @@ -1528,16 +1541,23 @@ op1->value.lval = -1; op1->type = IS_LONG; break; - } else if (is_numeric_string(op1->value.str.val, op1->value.str.len, &lval, NULL, 0)==IS_LONG) { /* long */ - STR_FREE(op1->value.str.val); - if(lval == LONG_MIN) { - double d = (double)lval; - ZVAL_DOUBLE(op1, d-1); - } else { - op1->value.lval = lval-1; - op1->type = IS_LONG; - } - break; + } + switch (is_numeric_string(op1->value.str.val, op1->value.str.len, &lval, &dval, 0)) { + case IS_LONG: + STR_FREE(op1->value.str.val); + if (lval == LONG_MIN) { + double d = (double)lval; + ZVAL_DOUBLE(op1, d-1); + } else { + op1->value.lval = lval-1; + op1->type = IS_LONG; + } + break; + case IS_DOUBLE: + STR_FREE(op1->value.str.val); + op1->value.dval = dval - 1; + op1->type = IS_DOUBLE; + break; } break; default: @@ -1554,18 +1574,18 @@ return (op->value.lval ? 1 : 0); } - ZEND_API void zend_str_tolower(char *str, unsigned int length) { register char *p=str, *end=p+length; while (p<end) { - *p = tolower(*p); + if (*p >= 'A' && *p <= 'Z') { + *p = (*p)+32; + } p++; } } - ZEND_API int zend_binary_strcmp(char *s1, uint len1, char *s2, uint len2) { int retval; @@ -1737,8 +1757,8 @@ return; } - if(Z_OBJ_HT_P(o1)->compare_objects == NULL) { - if(Z_OBJ_HANDLE_P(o1) == Z_OBJ_HANDLE_P(o2)) { + if (Z_OBJ_HT_P(o1)->compare_objects == NULL) { + if (Z_OBJ_HANDLE_P(o1) == Z_OBJ_HANDLE_P(o2)) { result->value.lval = 0; } else { result->value.lval = 1; @@ -1748,3 +1768,29 @@ result->value.lval = Z_OBJ_HT_P(o1)->compare_objects(o1, o2 TSRMLS_CC); } } + +ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC) +{ + double dval = op->value.dval; + + TSRMLS_FETCH(); + + op->value.str.val = (char *) emalloc_rel(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1); + sprintf(op->value.str.val, "%.*G", (int) EG(precision), dval); + op->value.str.len = strlen(op->value.str.val); + + if (EG(float_separator)[0] != '.') { + char *p = op->value.str.val; + if ((p = strchr(p, '.'))) { + *p = EG(float_separator)[0]; + } + } +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.4 +29 -16 ZendEngine2/zend_operators.h Index: zend_operators.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_operators.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- zend_operators.h 2 May 2002 23:04:38 -0000 1.3 +++ zend_operators.h 11 Feb 2003 02:40:19 -0000 1.4 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_operators.h,v 1.69 2003/02/02 16:29:42 zeev Exp $ */ #ifndef ZEND_OPERATORS_H #define ZEND_OPERATORS_H @@ -58,6 +59,8 @@ ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2 TSRMLS_DC); +ZEND_API int instanceof_function(zval *result, zval *op1, zend_class_entry *ce TSRMLS_DC); + static inline zend_bool is_numeric_string(char *str, int length, long *lval, double *dval, zend_bool allow_errors) { long local_lval; @@ -107,7 +110,7 @@ register char *ptr=str, *end=str+length; while (ptr<end) { - switch(*ptr++) { + switch (*ptr++) { case 'e': case 'E': /* scientific notation, not handled by the BC library */ @@ -185,6 +188,8 @@ ZEND_API int zend_atoi(const char *str, int str_len); +ZEND_API void zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_DC); + #define convert_to_ex_master(ppzv, lower_type, upper_type) \ if ((*ppzv)->type!=IS_##upper_type) { \ if (!(*ppzv)->is_ref) { \ @@ -226,18 +231,18 @@ } -#define Z_LVAL(zval) (zval).value.lval -#define Z_BVAL(zval) ((zend_bool)(zval).value.lval) -#define Z_DVAL(zval) (zval).value.dval -#define Z_STRVAL(zval) (zval).value.str.val -#define Z_STRLEN(zval) (zval).value.str.len -#define Z_ARRVAL(zval) (zval).value.ht -#define Z_OBJ_HANDLE(zval) (zval).value.obj.handle -#define Z_OBJ_HT(zval) (zval).value.obj.handlers -#define Z_OBJ(zval) zend_objects_get_address(&(zval)) -#define Z_OBJCE(zval) zend_get_class_entry(&(zval)) -#define Z_OBJPROP(zval) Z_OBJ(zval)->properties -#define Z_RESVAL(zval) (zval).value.lval +#define Z_LVAL(zval) (zval).value.lval +#define Z_BVAL(zval) ((zend_bool)(zval).value.lval) +#define Z_DVAL(zval) (zval).value.dval +#define Z_STRVAL(zval) (zval).value.str.val +#define Z_STRLEN(zval) (zval).value.str.len +#define Z_ARRVAL(zval) (zval).value.ht +#define Z_OBJ_HANDLE(zval) (zval).value.obj.handle +#define Z_OBJ_HT(zval) (zval).value.obj.handlers +#define Z_OBJCE(zval) zend_get_class_entry(&(zval)) +#define Z_OBJPROP(zval) Z_OBJ_HT((zval))->get_properties(&(zval) TSRMLS_CC) +#define Z_OBJ_HANDLER(zval, hf) Z_OBJ_HT((zval))->hf +#define Z_RESVAL(zval) (zval).value.lval #define Z_LVAL_P(zval_p) Z_LVAL(*zval_p) #define Z_BVAL_P(zval_p) Z_BVAL(*zval_p) @@ -245,12 +250,12 @@ #define Z_STRVAL_P(zval_p) Z_STRVAL(*zval_p) #define Z_STRLEN_P(zval_p) Z_STRLEN(*zval_p) #define Z_ARRVAL_P(zval_p) Z_ARRVAL(*zval_p) -#define Z_OBJ_P(zval_p) Z_OBJ(*zval_p) #define Z_OBJPROP_P(zval_p) Z_OBJPROP(*zval_p) #define Z_OBJCE_P(zval_p) Z_OBJCE(*zval_p) #define Z_RESVAL_P(zval_p) Z_RESVAL(*zval_p) #define Z_OBJ_HANDLE_P(zval_p) Z_OBJ_HANDLE(*zval_p) #define Z_OBJ_HT_P(zval_p) Z_OBJ_HT(*zval_p) +#define Z_OBJ_HANDLER_P(zval_p, h) Z_OBJ_HANDLER(*zval_p, h) #define Z_LVAL_PP(zval_pp) Z_LVAL(**zval_pp) #define Z_BVAL_PP(zval_pp) Z_BVAL(**zval_pp) @@ -258,15 +263,23 @@ #define Z_STRVAL_PP(zval_pp) Z_STRVAL(**zval_pp) #define Z_STRLEN_PP(zval_pp) Z_STRLEN(**zval_pp) #define Z_ARRVAL_PP(zval_pp) Z_ARRVAL(**zval_pp) -#define Z_OBJ_PP(zval_pp) Z_OBJ(**zval_pp) #define Z_OBJPROP_PP(zval_pp) Z_OBJPROP(**zval_pp) #define Z_OBJCE_PP(zval_pp) Z_OBJCE(**zval_pp) #define Z_RESVAL_PP(zval_pp) Z_RESVAL(**zval_pp) #define Z_OBJ_HANDLE_PP(zval_p) Z_OBJ_HANDLE(**zval_p) #define Z_OBJ_HT_PP(zval_p) Z_OBJ_HT(**zval_p) +#define Z_OBJ_HANDLER_PP(zval_p, h) Z_OBJ_HANDLER(**zval_p, h) #define Z_TYPE(zval) (zval).type #define Z_TYPE_P(zval_p) Z_TYPE(*zval_p) #define Z_TYPE_PP(zval_pp) Z_TYPE(**zval_pp) #endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +10 -1 ZendEngine2/zend_ptr_stack.c Index: zend_ptr_stack.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_ptr_stack.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_ptr_stack.c 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_ptr_stack.c 11 Feb 2003 02:40:19 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_ptr_stack.c,v 1.19 2003/02/01 01:49:14 sniper Exp $ */ #include "zend.h" #include "zend_ptr_stack.h" @@ -108,3 +109,11 @@ { return stack->top; } + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +10 -2 ZendEngine2/zend_ptr_stack.h Index: zend_ptr_stack.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_ptr_stack.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_ptr_stack.h 29 Apr 2002 02:25:27 -0000 1.2 +++ zend_ptr_stack.h 11 Feb 2003 02:40:19 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_ptr_stack.h,v 1.16 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_PTR_STACK_H #define ZEND_PTR_STACK_H @@ -54,5 +55,12 @@ return *(--stack->top_element); } - #endif /* ZEND_PTR_STACK_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.4 +2 -2 ZendEngine2/zend_qsort.c Index: zend_qsort.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_qsort.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- zend_qsort.c 19 May 2002 23:06:12 -0000 1.3 +++ zend_qsort.c 11 Feb 2003 02:40:19 -0000 1.4 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: zend_qsort.c,v 1.4 2002/05/13 14:38:42 sterling Exp $ */ +/* $Id: zend_qsort.c,v 1.5 2002/12/31 15:54:08 sebastian Exp $ */ #include "zend.h" 1.3 +11 -1 ZendEngine2/zend_qsort.h Index: zend_qsort.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_qsort.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_qsort.h 29 Apr 2002 02:25:28 -0000 1.2 +++ zend_qsort.h 11 Feb 2003 02:40:19 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,6 +16,8 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_qsort.h,v 1.5 2003/02/01 01:49:14 sniper Exp $ */ + #ifndef ZEND_QSORT_H #define ZEND_QSORT_H @@ -24,3 +26,11 @@ END_EXTERN_C() #endif /* ZEND_QSORT_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +10 -1 ZendEngine2/zend_sprintf.c Index: zend_sprintf.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_sprintf.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_sprintf.c 29 Apr 2002 02:25:28 -0000 1.2 +++ zend_sprintf.c 11 Feb 2003 02:40:19 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_sprintf.c,v 1.13 2003/02/01 01:49:14 sniper Exp $ */ #include <stdio.h> @@ -38,3 +39,11 @@ return strlen(buffer); } #endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +10 -1 ZendEngine2/zend_stack.c Index: zend_stack.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_stack.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_stack.c 29 Apr 2002 02:25:28 -0000 1.2 +++ zend_stack.c 11 Feb 2003 02:40:19 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_stack.c,v 1.13 2003/02/01 01:49:14 sniper Exp $ */ #include "zend.h" #include "zend_stack.h" @@ -162,3 +163,11 @@ break; } } + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +10 -1 ZendEngine2/zend_stack.h Index: zend_stack.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_stack.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_stack.h 29 Apr 2002 02:25:28 -0000 1.2 +++ zend_stack.h 11 Feb 2003 02:40:19 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_stack.h,v 1.15 2003/02/01 01:49:14 sniper Exp $ */ #ifndef ZEND_STACK_H #define ZEND_STACK_H @@ -45,3 +46,11 @@ #define ZEND_STACK_APPLY_BOTTOMUP 2 #endif /* ZEND_STACK_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +10 -2 ZendEngine2/zend_static_allocator.c Index: zend_static_allocator.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_static_allocator.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_static_allocator.c 29 Apr 2002 02:25:28 -0000 1.2 +++ zend_static_allocator.c 11 Feb 2003 02:40:19 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,7 +16,7 @@ +----------------------------------------------------------------------+ */ -#include <stdlib.h> +/* $Id: zend_static_allocator.c,v 1.10 2003/02/01 01:49:14 sniper Exp $ */ #include "zend_static_allocator.h" @@ -74,3 +74,11 @@ } efree(sa->Blocks); } + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +11 -1 ZendEngine2/zend_static_allocator.h Index: zend_static_allocator.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_static_allocator.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_static_allocator.h 29 Apr 2002 02:25:28 -0000 1.2 +++ zend_static_allocator.h 11 Feb 2003 02:40:19 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,6 +16,8 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_static_allocator.h,v 1.10 2003/02/01 01:49:14 sniper Exp $ */ + #ifndef ZEND_STATIC_ALLOCATOR_H #define ZEND_STATIC_ALLOCATOR_H @@ -43,3 +45,11 @@ void static_allocator_destroy(StaticAllocator *sa); #endif /* ZEND_STATIC_ALLOCATOR_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.5 +57 -35 ZendEngine2/zend_ts_hash.c Index: zend_ts_hash.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_ts_hash.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_ts_hash.c 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_ts_hash.c 11 Feb 2003 02:40:19 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,67 +16,81 @@ +----------------------------------------------------------------------+ */ -#ifdef ZTS +/* $Id: zend_ts_hash.c,v 1.9 2003/02/04 12:12:34 zeev Exp $ */ #include "zend_ts_hash.h" /* ts management functions */ static void begin_read(TsHashTable *ht) { +#ifdef ZTS tsrm_mutex_lock(ht->mx_reader); if ((++(ht->reader)) == 1) { tsrm_mutex_lock(ht->mx_writer); } tsrm_mutex_unlock(ht->mx_reader); +#endif } static void end_read(TsHashTable *ht) { +#ifdef ZTS tsrm_mutex_lock(ht->mx_reader); if ((--(ht->reader)) == 0) { tsrm_mutex_unlock(ht->mx_writer); } tsrm_mutex_unlock(ht->mx_reader); +#endif } static void begin_write(TsHashTable *ht) { +#ifdef ZTS tsrm_mutex_lock(ht->mx_writer); +#endif } static void end_write(TsHashTable *ht) { +#ifdef ZTS tsrm_mutex_unlock(ht->mx_writer); +#endif } /* delegates */ ZEND_API int zend_ts_hash_init(TsHashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent) { +#ifdef ZTS ht->mx_reader = tsrm_mutex_alloc(); ht->mx_writer = tsrm_mutex_alloc(); ht->reader = 0; - return zend_hash_init(&(ht->hash), nSize, pHashFunction, pDestructor, persistent); +#endif + return zend_hash_init(TS_HASH(ht), nSize, pHashFunction, pDestructor, persistent); } ZEND_API int zend_ts_hash_init_ex(TsHashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection) { +#ifdef ZTS ht->mx_reader = tsrm_mutex_alloc(); ht->mx_writer = tsrm_mutex_alloc(); ht->reader = 0; - return zend_hash_init_ex(&(ht->hash), nSize, pHashFunction, pDestructor, persistent, bApplyProtection); +#endif + return zend_hash_init_ex(TS_HASH(ht), nSize, pHashFunction, pDestructor, persistent, bApplyProtection); } ZEND_API void zend_ts_hash_destroy(TsHashTable *ht) { +#ifdef ZTS tsrm_mutex_free(ht->mx_reader); - tsrm_mutex_free(ht->mx_reader); - zend_hash_destroy(&(ht->hash)); + tsrm_mutex_free(ht->mx_writer); +#endif + zend_hash_destroy(TS_HASH(ht)); } ZEND_API void zend_ts_hash_clean(TsHashTable *ht) { ht->reader = 0; - zend_hash_clean(&(ht->hash)); + zend_hash_clean(TS_HASH(ht)); } ZEND_API int zend_ts_hash_add_or_update(TsHashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag) @@ -84,7 +98,7 @@ int retval; begin_write(ht); - retval = zend_hash_add_or_update(&(ht->hash), arKey, nKeyLength, pData, nDataSize, pDest, flag); + retval = zend_hash_add_or_update(TS_HASH(ht), arKey, nKeyLength, pData, nDataSize, pDest, flag); end_write(ht); return retval; @@ -95,7 +109,7 @@ int retval; begin_write(ht); - retval = zend_hash_quick_add_or_update(&(ht->hash), arKey, nKeyLength, h, pData, nDataSize, pDest, flag); + retval = zend_hash_quick_add_or_update(TS_HASH(ht), arKey, nKeyLength, h, pData, nDataSize, pDest, flag); end_write(ht); return retval; @@ -106,7 +120,7 @@ int retval; begin_write(ht); - retval = zend_hash_index_update_or_next_insert(&(ht->hash), h, pData, nDataSize, pDest, flag); + retval = zend_hash_index_update_or_next_insert(TS_HASH(ht), h, pData, nDataSize, pDest, flag); end_write(ht); return retval; @@ -117,7 +131,7 @@ int retval; begin_write(ht); - retval = zend_hash_add_empty_element(&(ht->hash), arKey, nKeyLength); + retval = zend_hash_add_empty_element(TS_HASH(ht), arKey, nKeyLength); end_write(ht); return retval; @@ -125,22 +139,24 @@ ZEND_API void zend_ts_hash_graceful_destroy(TsHashTable *ht) { +#ifdef ZTS tsrm_mutex_free(ht->mx_reader); tsrm_mutex_free(ht->mx_reader); - zend_hash_graceful_destroy(&(ht->hash)); +#endif + zend_hash_graceful_destroy(TS_HASH(ht)); } ZEND_API void zend_ts_hash_apply(TsHashTable *ht, apply_func_t apply_func TSRMLS_DC) { begin_write(ht); - zend_hash_apply(&(ht->hash), apply_func TSRMLS_CC); + zend_hash_apply(TS_HASH(ht), apply_func TSRMLS_CC); end_write(ht); } ZEND_API void zend_ts_hash_apply_with_argument(TsHashTable *ht, apply_func_arg_t apply_func, void *argument TSRMLS_DC) { begin_write(ht); - zend_hash_apply_with_argument(&(ht->hash), apply_func, argument TSRMLS_CC); + zend_hash_apply_with_argument(TS_HASH(ht), apply_func, argument TSRMLS_CC); end_write(ht); } @@ -150,7 +166,7 @@ va_start(args, num_args); begin_write(ht); - zend_hash_apply_with_arguments(&(ht->hash), apply_func, num_args, args); + zend_hash_apply_with_arguments(TS_HASH(ht), apply_func, num_args, args); end_write(ht); va_end(args); } @@ -158,7 +174,7 @@ ZEND_API void zend_ts_hash_reverse_apply(TsHashTable *ht, apply_func_t apply_func TSRMLS_DC) { begin_write(ht); - zend_hash_reverse_apply(&(ht->hash), apply_func TSRMLS_CC); + zend_hash_reverse_apply(TS_HASH(ht), apply_func TSRMLS_CC); end_write(ht); } @@ -167,7 +183,7 @@ int retval; begin_write(ht); - retval = zend_hash_del_key_or_index(&(ht->hash), arKey, nKeyLength, h, flag); + retval = zend_hash_del_key_or_index(TS_HASH(ht), arKey, nKeyLength, h, flag); end_write(ht); return retval; @@ -178,7 +194,7 @@ ulong retval; begin_read(ht); - retval = zend_get_hash_value(&(ht->hash), arKey, nKeyLength); + retval = zend_get_hash_value(arKey, nKeyLength); end_read(ht); return retval; @@ -189,7 +205,7 @@ int retval; begin_read(ht); - retval = zend_hash_find(&(ht->hash), arKey, nKeyLength, pData); + retval = zend_hash_find(TS_HASH(ht), arKey, nKeyLength, pData); end_read(ht); return retval; @@ -200,7 +216,7 @@ int retval; begin_read(ht); - retval = zend_hash_quick_find(&(ht->hash), arKey, nKeyLength, h, pData); + retval = zend_hash_quick_find(TS_HASH(ht), arKey, nKeyLength, h, pData); end_read(ht); return retval; @@ -211,7 +227,7 @@ int retval; begin_read(ht); - retval = zend_hash_index_find(&(ht->hash), h, pData); + retval = zend_hash_index_find(TS_HASH(ht), h, pData); end_read(ht); return retval; @@ -222,7 +238,7 @@ int retval; begin_read(ht); - retval = zend_hash_exists(&(ht->hash), arKey, nKeyLength); + retval = zend_hash_exists(TS_HASH(ht), arKey, nKeyLength); end_read(ht); return retval; @@ -233,7 +249,7 @@ int retval; begin_read(ht); - retval = zend_hash_index_exists(&(ht->hash), h); + retval = zend_hash_index_exists(TS_HASH(ht), h); end_read(ht); return retval; @@ -243,7 +259,7 @@ { begin_read(source); begin_write(target); - zend_hash_copy(&(target->hash), &(source->hash), pCopyConstructor, tmp, size); + zend_hash_copy(TS_HASH(target), TS_HASH(source), pCopyConstructor, tmp, size); end_write(target); end_read(source); } @@ -252,16 +268,16 @@ { begin_read(source); begin_write(target); - zend_hash_merge(&(target->hash), &(source->hash), pCopyConstructor, tmp, size, overwrite); + zend_hash_merge(TS_HASH(target), TS_HASH(source), pCopyConstructor, tmp, size, overwrite); end_write(target); end_read(source); } -ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, uint size, zend_bool (*pReplaceOrig)(void *orig, void *p_new)) +ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam) { begin_read(source); begin_write(target); - zend_hash_merge_ex(&(target->hash), &(source->hash), pCopyConstructor, size, pReplaceOrig); + zend_hash_merge_ex(TS_HASH(target), TS_HASH(source), pCopyConstructor, size, pMergeSource, pParam); end_write(target); end_read(source); } @@ -271,7 +287,7 @@ int retval; begin_write(ht); - retval = zend_hash_sort(&(ht->hash), sort_func, compare_func, renumber TSRMLS_CC); + retval = zend_hash_sort(TS_HASH(ht), sort_func, compare_func, renumber TSRMLS_CC); end_write(ht); return retval; @@ -283,7 +299,7 @@ begin_read(ht1); begin_read(ht2); - retval = zend_hash_compare(&(ht1->hash), &(ht2->hash), compar, ordered TSRMLS_CC); + retval = zend_hash_compare(TS_HASH(ht1), TS_HASH(ht2), compar, ordered TSRMLS_CC); end_read(ht2); end_read(ht1); @@ -295,7 +311,7 @@ int retval; begin_read(ht); - retval = zend_hash_minmax(&(ht->hash), compar, flag, pData TSRMLS_CC); + retval = zend_hash_minmax(TS_HASH(ht), compar, flag, pData TSRMLS_CC); end_read(ht); return retval; @@ -306,7 +322,7 @@ int retval; begin_read(ht); - retval = zend_hash_num_elements(&(ht->hash)); + retval = zend_hash_num_elements(TS_HASH(ht)); end_read(ht); return retval; @@ -317,7 +333,7 @@ int retval; begin_write(ht); - retval = zend_hash_rehash(&(ht->hash)); + retval = zend_hash_rehash(TS_HASH(ht)); end_write(ht); return retval; @@ -327,16 +343,22 @@ void zend_ts_hash_display_pListTail(TsHashTable *ht) { begin_read(ht); - zend_hash_display_pListTail(&(ht->hash)); + zend_hash_display_pListTail(TS_HASH(ht)); end_read(ht); } void zend_ts_hash_display(TsHashTable *ht) { begin_read(ht); - zend_hash_display(&(ht->hash)); + zend_hash_display(TS_HASH(ht)); end_read(ht); } #endif -#endif /* ZTS */ +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.5 +16 -7 ZendEngine2/zend_ts_hash.h Index: zend_ts_hash.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_ts_hash.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_ts_hash.h 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_ts_hash.h 11 Feb 2003 02:40:19 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,22 +16,26 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_ts_hash.h,v 1.8 2003/02/04 12:12:34 zeev Exp $ */ + #ifndef ZEND_TS_HASH_H #define ZEND_TS_HASH_H -#ifdef ZTS - #include "zend.h" typedef struct _zend_ts_hashtable { HashTable hash; zend_uint reader; +#ifdef ZTS MUTEX_T mx_reader; MUTEX_T mx_writer; +#endif } TsHashTable; BEGIN_EXTERN_C() +#define TS_HASH(table) (&(table->hash)) + /* startup/shutdown */ ZEND_API int zend_ts_hash_init(TsHashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent); ZEND_API int zend_ts_hash_init_ex(TsHashTable *ht, uint nSize, hash_func_t pHashFunction, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection); @@ -88,7 +92,7 @@ /* Copying, merging and sorting */ ZEND_API void zend_ts_hash_copy(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size); ZEND_API void zend_ts_hash_merge(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, void *tmp, uint size, int overwrite); -ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, uint size, zend_bool (*pReplaceOrig)(void *orig, void *p_new)); +ZEND_API void zend_ts_hash_merge_ex(TsHashTable *target, TsHashTable *source, copy_ctor_func_t pCopyConstructor, uint size, merge_checker_func_t pMergeSource, void *pParam); ZEND_API int zend_ts_hash_sort(TsHashTable *ht, sort_func_t sort_func, compare_func_t compare_func, int renumber TSRMLS_DC); ZEND_API int zend_ts_hash_compare(TsHashTable *ht1, TsHashTable *ht2, compare_func_t compar, zend_bool ordered TSRMLS_DC); ZEND_API int zend_ts_hash_minmax(TsHashTable *ht, compare_func_t compar, int flag, void **pData TSRMLS_DC); @@ -113,7 +117,12 @@ #define ZEND_TS_INIT_SYMTABLE_EX(ht, n, persistent) \ zend_ts_hash_init(ht, n, NULL, ZVAL_PTR_DTOR, persistent) - -#endif /* ZTS */ - #endif /* ZEND_HASH_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.3 +11 -1 ZendEngine2/zend_types.h Index: zend_types.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_types.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- zend_types.h 2 Aug 2002 09:48:15 -0000 1.2 +++ zend_types.h 11 Feb 2003 02:40:19 -0000 1.3 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,8 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_types.h,v 1.3 2003/02/01 01:49:14 sniper Exp $ */ + #ifndef ZEND_TYPES_H #define ZEND_TYPES_H @@ -27,3 +29,11 @@ typedef unsigned short zend_ushort; #endif /* ZEND_TYPES_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ 1.5 +8 -37 ZendEngine2/zend_variables.c Index: zend_variables.c =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_variables.c,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_variables.c 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_variables.c 11 Feb 2003 02:40:19 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_variables.c,v 1.51 2003/02/01 01:49:14 sniper Exp $ */ #include <stdio.h> #include "zend.h" @@ -37,7 +38,7 @@ if (zvalue->type==IS_LONG) { return; } - switch(zvalue->type) { + switch (zvalue->type & ~IS_CONSTANT_INDEX) { case IS_STRING: case IS_CONSTANT: CHECK_ZVAL_STRING_REL(zvalue); @@ -126,43 +127,13 @@ case IS_OBJECT: { TSRMLS_FETCH(); -#if 0 - zvalue->value.obj = zvalue->value.obj.handlers->clone_obj(zvalue->value.obj.handle); -#else - Z_OBJ_HT_P(zvalue)->add_ref(zvalue TSRMLS_CC); -#endif - } - break; - } - return SUCCESS; -} - -ZEND_API int zval_persist(zval *zvalue TSRMLS_DC) -{ - switch (zvalue->type) { - case IS_OBJECT: - case IS_RESOURCE: - return FAILURE; /* resources and objects cannot be persisted */ - break; - case IS_BOOL: - case IS_LONG: - case IS_NULL: - break; - case IS_CONSTANT: - case IS_STRING: - if (zvalue->value.str.val) { - if (zvalue->value.str.len==0) { - zvalue->value.str.val = empty_string; - return SUCCESS; + if (EG(implicit_clone)) { + zvalue->value.obj = zvalue->value.obj.handlers->clone_obj(zvalue TSRMLS_CC); + } else { + Z_OBJ_HT_P(zvalue)->add_ref(zvalue TSRMLS_CC); } } - persist_alloc(zvalue->value.str.val); - break; - case IS_ARRAY: - case IS_CONSTANT_ARRAY: - persist_alloc(zvalue->value.ht); - zend_hash_apply(zvalue->value.ht, (apply_func_t) zval_persist TSRMLS_CC); break; } return SUCCESS; @@ -195,10 +166,10 @@ } #endif - /* * Local variables: * tab-width: 4 * c-basic-offset: 4 + * indent-tabs-mode: t * End: */ 1.5 +10 -3 ZendEngine2/zend_variables.h Index: zend_variables.h =================================================================== RCS file: /cvsroot/php-i18n/ZendEngine2/zend_variables.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- zend_variables.h 3 Aug 2002 08:56:16 -0000 1.4 +++ zend_variables.h 11 Feb 2003 02:40:19 -0000 1.5 @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | Zend Engine | +----------------------------------------------------------------------+ - | Copyright (c) 1998-2002 Zend Technologies Ltd. (http://www.zend.com) | + | Copyright (c) 1998-2003 Zend Technologies Ltd. (http://www.zend.com) | +----------------------------------------------------------------------+ | This source file is subject to version 2.00 of the Zend license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,6 +17,7 @@ +----------------------------------------------------------------------+ */ +/* $Id: zend_variables.h,v 1.25 2003/02/01 01:49:15 sniper Exp $ */ #ifndef ZEND_VARIABLES_H #define ZEND_VARIABLES_H @@ -32,8 +33,6 @@ #define zval_dtor(zvalue) _zval_dtor((zvalue) ZEND_FILE_LINE_CC) #define zval_ptr_dtor(zval_ptr) _zval_ptr_dtor((zval_ptr) ZEND_FILE_LINE_CC) -ZEND_API int zval_persist(zval *zvalue TSRMLS_DC); - #if ZEND_DEBUG ZEND_API int _zval_copy_ctor_wrapper(zval *zvalue); ZEND_API void _zval_dtor_wrapper(zval *zvalue); @@ -57,3 +56,11 @@ #define ZVAL_COPY_CTOR (void (*)(void *)) zval_copy_ctor_wrapper #endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */