From 573b46022c46ab41a879c23f4ea432dd4d0c102e Mon Sep 17 00:00:00 2001 From: Andi Gutmans Date: Wed, 7 Apr 1999 18:10:10 +0000 Subject: [PATCH] Zend Library --- Zend/LICENSE | 37 + Zend/Makefile.in | 145 +++ Zend/ZEND_CHANGES | 111 +++ Zend/ZendCore.dep | 258 ++++++ Zend/ZendCore.dsp | 358 ++++++++ Zend/ZendCore.dsw | 65 ++ Zend/ZendCore.mak | 628 +++++++++++++ Zend/acconfig.h | 247 +++++ Zend/aclocal.m4 | 52 ++ Zend/config.h.in | 274 ++++++ Zend/config.unix.h | 39 + Zend/config.w32.h | 41 + Zend/configure.in | 194 ++++ Zend/diffs | 8 + Zend/zend-parser.y | 632 +++++++++++++ Zend/zend-scanner.h | 29 + Zend/zend-scanner.l | 1195 +++++++++++++++++++++++++ Zend/zend.c | 255 ++++++ Zend/zend.h | 205 +++++ Zend/zend.ico | Bin 0 -> 1382 bytes Zend/zend_API.c | 701 +++++++++++++++ Zend/zend_API.h | 92 ++ Zend/zend_alloc.c | 498 +++++++++++ Zend/zend_alloc.h | 117 +++ Zend/zend_compile.c | 1822 +++++++++++++++++++++++++++++++++++++ Zend/zend_compile.h | 499 +++++++++++ Zend/zend_constants.c | 236 +++++ Zend/zend_constants.h | 53 ++ Zend/zend_errors.h | 33 + Zend/zend_execute.c | 1885 +++++++++++++++++++++++++++++++++++++++ Zend/zend_execute.h | 67 ++ Zend/zend_execute_API.c | 446 +++++++++ Zend/zend_extensions.c | 123 +++ Zend/zend_extensions.h | 90 ++ Zend/zend_globals.h | 209 +++++ Zend/zend_hash.c | 1163 ++++++++++++++++++++++++ Zend/zend_hash.h | 153 ++++ Zend/zend_highlight.c | 160 ++++ Zend/zend_highlight.h | 43 + Zend/zend_indent.c | 141 +++ Zend/zend_indent.h | 22 + Zend/zend_list.c | 238 +++++ Zend/zend_list.h | 61 ++ Zend/zend_llist.c | 189 ++++ Zend/zend_llist.h | 53 ++ Zend/zend_modules.h | 53 ++ Zend/zend_opcode.c | 375 ++++++++ Zend/zend_operators.c | 1329 +++++++++++++++++++++++++++ Zend/zend_operators.h | 66 ++ Zend/zend_ptr_stack.c | 71 ++ Zend/zend_ptr_stack.h | 37 + Zend/zend_sprintf.c | 34 + Zend/zend_stack.c | 114 +++ Zend/zend_stack.h | 39 + Zend/zend_variables.c | 167 ++++ Zend/zend_variables.h | 35 + 56 files changed, 16187 insertions(+) create mode 100644 Zend/LICENSE create mode 100644 Zend/Makefile.in create mode 100644 Zend/ZEND_CHANGES create mode 100644 Zend/ZendCore.dep create mode 100644 Zend/ZendCore.dsp create mode 100644 Zend/ZendCore.dsw create mode 100644 Zend/ZendCore.mak create mode 100644 Zend/acconfig.h create mode 100644 Zend/aclocal.m4 create mode 100644 Zend/config.h.in create mode 100644 Zend/config.unix.h create mode 100644 Zend/config.w32.h create mode 100644 Zend/configure.in create mode 100644 Zend/diffs create mode 100644 Zend/zend-parser.y create mode 100644 Zend/zend-scanner.h create mode 100644 Zend/zend-scanner.l create mode 100644 Zend/zend.c create mode 100644 Zend/zend.h create mode 100644 Zend/zend.ico create mode 100644 Zend/zend_API.c create mode 100644 Zend/zend_API.h create mode 100644 Zend/zend_alloc.c create mode 100644 Zend/zend_alloc.h create mode 100644 Zend/zend_compile.c create mode 100644 Zend/zend_compile.h create mode 100644 Zend/zend_constants.c create mode 100644 Zend/zend_constants.h create mode 100644 Zend/zend_errors.h create mode 100644 Zend/zend_execute.c create mode 100644 Zend/zend_execute.h create mode 100644 Zend/zend_execute_API.c create mode 100644 Zend/zend_extensions.c create mode 100644 Zend/zend_extensions.h create mode 100644 Zend/zend_globals.h create mode 100644 Zend/zend_hash.c create mode 100644 Zend/zend_hash.h create mode 100644 Zend/zend_highlight.c create mode 100644 Zend/zend_highlight.h create mode 100644 Zend/zend_indent.c create mode 100644 Zend/zend_indent.h create mode 100644 Zend/zend_list.c create mode 100644 Zend/zend_list.h create mode 100644 Zend/zend_llist.c create mode 100644 Zend/zend_llist.h create mode 100644 Zend/zend_modules.h create mode 100644 Zend/zend_opcode.c create mode 100644 Zend/zend_operators.c create mode 100644 Zend/zend_operators.h create mode 100644 Zend/zend_ptr_stack.c create mode 100644 Zend/zend_ptr_stack.h create mode 100644 Zend/zend_sprintf.c create mode 100644 Zend/zend_stack.c create mode 100644 Zend/zend_stack.h create mode 100644 Zend/zend_variables.c create mode 100644 Zend/zend_variables.h diff --git a/Zend/LICENSE b/Zend/LICENSE new file mode 100644 index 0000000000000..df4543ee103bc --- /dev/null +++ b/Zend/LICENSE @@ -0,0 +1,37 @@ +Zend Temporary License +====================== + +This is a temporary license, that is in effect until the final Zend license +is available. + +* The final license will include the ability to distribute Zend freely, + as a part of PHP (in both compiled and source code formats). It may + (and probably will) allow to redistribute Zend under other circumstances + as well, but at the very least, it'll be freely distributed as a part + of PHP. + +* The source code in the Zend engine is the property of Andi Gutmans and + Zeev Suraski. Parts of this code are based on source code taken from + PHP 3.0, which may include several patches and enhancements that weren't + made by us (Andi&Zeev). If you're the author of such a patch and you're + not willing to give up ownership over your patch to us, please contact + us as soon as possible, so we can remove it. We're doing this so that + we'd be eligible to sell the Zend engine for uses other than PHP, most + notably - as an embedded part of possible commercial products that we'd + have. + +* Patches submitted to the Zend CVS automatically fall under this license, + and by submitting them you're implicitly giving up your ownership over + this patch to us. + +* Until further notice, Zend is in a status of a closed beta test. That means + that only people that were explicitly given the right to access the Zend + CVS repository are allowed to use it. If you're reading this file and you + weren't explicitly given the right to access the Zend CVS repository from + either Andi Gutmans or Zeev Suraski - you're not supposed to have it - please + erase the Zend files from your system. When the closed beta period finishes, + the Zend CVS tree will be open for the public (in read-only mode, of course). + + +Any questions regarding Zend or this license should be addressed via Email to +zend@zend.com. diff --git a/Zend/Makefile.in b/Zend/Makefile.in new file mode 100644 index 0000000000000..929c8194c8e4d --- /dev/null +++ b/Zend/Makefile.in @@ -0,0 +1,145 @@ +CC = @CC@ +AR = ar rc +LIBNAME = libzend.a +PROF_CFLAGS = +CFLAGS_SHLIB = @CFLAGS_SHLIB@ +LDFLAGS_SHLIB = @LDFLAGS_SHLIB@ +LDFLAGS_SHLIB_EXPORT = @LDFLAGS_SHLIB_EXPORT@ +CPPFLAGS = @CPPFLAGS@ +CFLAGS = @CFLAGS@ $(CFLAGS_SHLIB) $(CPPFLAGS) $(INCLUDE) @DEBUG_CFLAGS@ $(PROF_CFLAGS) +LDFLAGS = @LDFLAGS@ $(LDFLAGS_SHLIB) $(LDFLAGS_SHLIB_EXPORT) +RANLIB = @RANLIB@ +YACC = @YACC@ + +SOURCE = zend_alloc.c zend_compile.c zend_constants.c zend_execute.c zend_execute_API.c \ + zend_highlight.c zend_llist.c zend_opcode.c zend_operators.c zend_ptr_stack.c \ + zend_stack.c zend_variables.c zend-parser.c zend-scanner.c zend.c zend_API.c zend_extensions.c \ + zend_hash.c zend_list.c zend_indent.c + +OBJS = zend_alloc.o zend_compile.o zend_constants.o zend_execute.o zend_execute_API.o \ + zend_highlight.o zend_llist.o zend_opcode.o zend_operators.o zend_ptr_stack.o \ + zend_stack.o zend_variables.o zend-parser.o zend-scanner.o zend.o zend_API.o zend_extensions.o \ + zend_hash.o zend_list.o zend_indent.o + +LIBS = @LIBS@ + +all: $(LIBNAME) + +libzend.a: $(OBJS) + -rm -f libzend.a + $(AR) libzend.a $(OBJS) + $(RANLIB) libzend.a + +zend-parser.h zend-parser.c: zend-parser.y + bison -p zend -v -d zend-parser.y -o zend-parser.c + +zend-scanner.o: + $(CC) $(CFLAGS) -w -c zend-scanner.c + +zend-scanner.c: zend-scanner.l + flex -Pzend -ozend-scanner.c -i zend-scanner.l + +clean: + -rm -f libzend.a *.o + +distclean: clean + -rm -f *-scanner.c *-parser.[ch] *.output + -rm -f config.status config.cache config.log + -rm -f Makefile Makefile.depend config.h + +.c.o: + @rm -f $@ + $(CC) $(CFLAGS) -c $< -o $@ + @bn=`echo $@ | sed -e 's#functions/##'`; test -f $@ || \ + (test "$@" != "$$bn" && test -f "$$bn" && mv $$bn $@) + +parser-scanner: zend-parser.c zend-parser.h zend-scanner.c + +depend: parser-scanner + $(CC) $(CFLAGS) -MM $(SOURCE) | perl -pe 's|regex/regex.h||;' > Makefile.depend + + +zend_alloc.o: zend_alloc.c zend.h config.h config.unix.h zend_errors.h \ + zend_alloc.h zend_hash.h zend_llist.h zend_globals.h zend_stack.h \ + zend_ptr_stack.h zend_compile.h zend-parser.h zend_execute.h +zend_compile.o: zend_compile.c zend.h config.h config.unix.h \ + zend_errors.h zend_alloc.h zend_hash.h zend_llist.h zend_compile.h \ + zend-parser.h zend_globals.h zend_stack.h zend_ptr_stack.h \ + zend_execute.h zend_API.h modules.h zend_list.h zend_variables.h \ + zend_operators.h +zend_constants.o: zend_constants.c zend.h config.h config.unix.h \ + zend_errors.h zend_alloc.h zend_hash.h zend_llist.h zend_constants.h \ + zend_variables.h zend_operators.h zend_globals.h zend_stack.h \ + zend_ptr_stack.h zend_compile.h zend-parser.h zend_execute.h +zend_execute.o: zend_execute.c zend.h config.h config.unix.h \ + zend_errors.h zend_alloc.h zend_hash.h zend_llist.h zend_compile.h \ + zend-parser.h zend_globals.h zend_stack.h zend_ptr_stack.h \ + zend_execute.h zend_API.h modules.h zend_list.h zend_variables.h \ + zend_operators.h zend_constants.h zend_extensions.h +zend_execute_API.o: zend_execute_API.c zend.h config.h config.unix.h \ + zend_errors.h zend_alloc.h zend_hash.h zend_llist.h zend_compile.h \ + zend-parser.h zend_globals.h zend_stack.h zend_ptr_stack.h \ + zend_execute.h zend_API.h modules.h zend_list.h zend_variables.h \ + zend_operators.h zend_constants.h zend_extensions.h +zend_highlight.o: zend_highlight.c zend.h config.h config.unix.h \ + zend_errors.h zend_alloc.h zend_hash.h zend_llist.h zend_compile.h \ + zend-parser.h zend_globals.h zend_stack.h zend_ptr_stack.h \ + zend_execute.h zend_highlight.h +zend_llist.o: zend_llist.c zend.h config.h config.unix.h zend_errors.h \ + zend_alloc.h zend_hash.h zend_llist.h +zend_opcode.o: zend_opcode.c zend.h config.h config.unix.h \ + zend_errors.h zend_alloc.h zend_hash.h zend_llist.h zend_compile.h \ + zend-parser.h zend_globals.h zend_stack.h zend_ptr_stack.h \ + zend_execute.h zend_variables.h zend_operators.h zend_extensions.h \ + zend_API.h modules.h zend_list.h +zend_operators.o: zend_operators.c zend.h config.h config.unix.h \ + zend_errors.h zend_alloc.h zend_hash.h zend_llist.h zend_operators.h \ + zend_variables.h zend_globals.h zend_stack.h zend_ptr_stack.h \ + zend_compile.h zend-parser.h zend_execute.h +zend_ptr_stack.o: zend_ptr_stack.c zend.h config.h config.unix.h \ + zend_errors.h zend_alloc.h zend_hash.h zend_llist.h zend_ptr_stack.h +zend_stack.o: zend_stack.c zend.h config.h config.unix.h zend_errors.h \ + zend_alloc.h zend_hash.h zend_llist.h zend_stack.h +zend_variables.o: zend_variables.c zend.h config.h config.unix.h \ + zend_errors.h zend_alloc.h zend_hash.h zend_llist.h zend_API.h \ + modules.h zend_list.h zend_globals.h zend_stack.h zend_ptr_stack.h \ + zend_compile.h zend-parser.h zend_execute.h zend_constants.h \ + zend_variables.h +zend-parser.o: zend-parser.c zend_compile.h zend.h config.h \ + config.unix.h zend_errors.h zend_alloc.h zend_hash.h zend_llist.h \ + zend-parser.h zend_globals.h zend_stack.h zend_ptr_stack.h \ + zend_execute.h zend_list.h zend_API.h modules.h zend_variables.h \ + zend_operators.h +zend-scanner.o: zend-scanner.c zend.h config.h config.unix.h \ + zend_errors.h zend_alloc.h zend_hash.h zend_llist.h zend_compile.h \ + zend-parser.h zend_globals.h zend_stack.h zend_ptr_stack.h \ + zend_execute.h zend-scanner.h zend_highlight.h zend_constants.h \ + zend_variables.h zend_operators.h +zend.o: zend.c zend.h config.h config.unix.h zend_errors.h \ + zend_alloc.h zend_hash.h zend_llist.h zend_operators.h \ + zend_variables.h zend_extensions.h zend_compile.h zend-parser.h \ + zend_globals.h zend_stack.h zend_ptr_stack.h zend_execute.h modules.h \ + zend_constants.h zend_list.h +zend_API.o: zend_API.c zend.h config.h config.unix.h zend_errors.h \ + zend_alloc.h zend_hash.h zend_llist.h zend_variables.h zend_execute.h \ + zend_compile.h zend-parser.h zend_globals.h zend_stack.h \ + zend_ptr_stack.h zend_API.h modules.h zend_list.h zend_constants.h \ + zend_operators.h +zend_extensions.o: zend_extensions.c zend_extensions.h zend_compile.h \ + zend.h config.h config.unix.h zend_errors.h zend_alloc.h zend_hash.h \ + zend_llist.h zend-parser.h zend_globals.h zend_stack.h \ + zend_ptr_stack.h zend_execute.h +zend_hash.o: zend_hash.c zend.h config.h config.unix.h zend_errors.h \ + zend_alloc.h zend_hash.h zend_llist.h +zend_list.o: zend_list.c zend.h config.h config.unix.h zend_errors.h \ + zend_alloc.h zend_hash.h zend_llist.h zend_list.h zend_API.h \ + modules.h zend_globals.h zend_stack.h zend_ptr_stack.h zend_compile.h \ + zend-parser.h zend_execute.h +zend_indent.o: zend_indent.c zend.h config.h config.unix.h \ + zend_errors.h zend_alloc.h zend_hash.h zend_llist.h zend_compile.h \ + zend-parser.h zend_globals.h zend_stack.h zend_ptr_stack.h \ + zend_execute.h zend_indent.h + +# Local Variables: +# tab-width: 4 +# End: diff --git a/Zend/ZEND_CHANGES b/Zend/ZEND_CHANGES new file mode 100644 index 0000000000000..7ebb7e4afec3f --- /dev/null +++ b/Zend/ZEND_CHANGES @@ -0,0 +1,111 @@ +Improvements +------------ + +Zend was designed from the ground up for increased speed, +reduced memory consumption and more reliable execution. We dare +say it meets all of these goals and does so pretty well. Beyond +that, there are several improvements in the language engine +features: + +* References support. $foo = &$a; would make $foo and $a be two + names to the same variable. This works with arrays as well, + on either side; e.g., $foo = &$a[7]; would make $foo and $a[7] + be two names to the same variable. Changing one would change + the other and vice versa. +* Object overloading support. This feature allows various OO + libraries to use the OO notation of PHP to access their + functionality. Right now, no use is made of that feature, + but we'd have a COM module ready by the time PHP 4.0 is released. + A CORBA module would probably follow. +* include() and eval() are now functions, and not statements. + That means they return a value. The default return value from + include() and eval() is 1, so that you can do if (include()) + without further coding. The return value may be changed by + returning a value from the global scope of the included file + or the evaluated string. For example, if 'return 7;' is executed + in the global scope of foo.inc, include("foo.inc") would evaluate + to 7. +* Automatic resource deallocation. Several people have been bitten + by the fact that PHP 3.0 had no concept of reference counting. + Zend adds full reference counting for every value in the system, + including resources. As soon as a resource is no longer referenced + from any variable, it is automatically destroyed to save memory + and resources. The most obvious example for the advantage in this + is a loop that has an SQL query inside it, something like + '$result = sql_query(...);'. In PHP 3.0, every iteration resulted + in another SQL result-set allocated in the memory, and all of the + result sets weren't destroyed until the end of the script's execution. + In Zend, as soon as we overwrite an old result set with a new one, + the old result set which is no longer referenced, is destroyed. +* Full support for nesting arrays and objects within each other, in + as many levels as you want. +* Boolean type. true and false are now constants of type boolean. + Comparing any other value to them would convert that value to a + boolean first, and conduct the comparison later. That means, for + example, that 5==true would evaluate to true (in PHP 3.0, true + was nothing but a constant for the integer value of 1, so 5==true + was identical to 5==1, which was false). +* Runtime binding of function names. This complex name has a simple + explanation - you can now call functions before they're declared! +* Added here-docs support. +* Added foreach. Two syntaxes supported: + foreach($val in array_expr) statement + foreach($key, $val in array_expr) statement +* A true unset() implementation. A variable or element that is unset(), is now + sent to oblivion in its entirely, no trace remains from it. +* Output buffering support! Use ob_start() to begin output buffering, ob_end_flush() + to end buffering and send out the buffered contents, ob_end_clean() to end buffering + without sending the buffered contents, and ob_get_contents() to retreive the current + contents of the output buffer. + Header information (header(), content type, cookies) are not buffered. By turning + on output buffering, you can effectively send header information all throughout your + file, regardless of whether you've emitted body output or not. +* Full variable reference within quoted strings: + ${expr} - full indirect reference support for scalar variables + {variable} - full variable support + For example: + $foo[5]["bar"] = "foobar"; + print "{$foo[5]["bar"]}"; // would print "foobar" +* Ability to call member functions of other classes from within member functions or from + the global scope. You can now, for example, override a parent function with a child function, + and call the parent function from it. +* Runtime information for classes (class name, parent, available functions, etc.). +* Much more efficient syntax highlighter - runs much quicker, performs more reliably, and + generates much tighter HTML. +* A full-featured debugger has been integrated with the language (supports breakpoints, + expression evaluation, step-in/over, function call backtrace, and more). + + +Incompatabilities +----------------- + +Zend claims 100% compatability with the engine of PHP 3.0, and is +shamelessly lying about it. Here's why: + +* static variable initializers only accept scalar values + (in PHP 3.0 they accepted any valid expression). The impact + should be somewhere in between void and non existant, since + initializing a static variable with anything but a simple + static value makes no sense at all. + +* The scope of break and continue is local to that of an + include()'d file or an eval()'d string. The impact should + be somewhat smaller of the one above. + +* return statement from a require()'d file no longer works. It + hardly worked in PHP 3.0, so the impact should be fairly small. + If you want this functionality - use include() instead. + +* unset() is no longer a function, but a statement. It was never + documented as a function so the impact should be no bigger than + nada. + +* The following letter combination is not supported within encapsulated + strings: "{$". If you have a string that includes this letter + combination, for example, print "{$somevar"; (which printed the + letter { and the contents of the variable $somevar in PHP 3.0), + it will result in a parse error under Zend. In this case, you + would have to change the code to print "\{$somevar"; + This incompatability is due to the full variable reference + within quoted strings feature added in Zend. + diff --git a/Zend/ZendCore.dep b/Zend/ZendCore.dep new file mode 100644 index 0000000000000..bc420a02f1db4 --- /dev/null +++ b/Zend/ZendCore.dep @@ -0,0 +1,258 @@ +# Microsoft Developer Studio Generated Dependency File, included by ZendCore.mak + +.\zend_alloc.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\zend_compile.h"\ + ".\config.w32.h"\ + ".\zend_execute.h"\ + ".\zend_llist.h"\ + ".\zend_ptr_stack.h"\ + ".\zend_stack.h"\ + ".\zend.h"\ + ".\zend_errors.h"\ + ".\zend_globals.h"\ + ".\zend_hash.h"\ + + +.\alloca.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\config.w32.h"\ + ".\zend.h"\ + ".\zend_errors.h"\ + ".\zend_hash.h"\ + + +.\zend_compile.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\zend_compile.h"\ + ".\config.w32.h"\ + ".\zend_execute.h"\ + ".\zend_llist.h"\ + ".\modules.h"\ + ".\zend_operators.h"\ + ".\zend_ptr_stack.h"\ + ".\zend_stack.h"\ + ".\zend_variables.h"\ + ".\zend.h"\ + ".\zend_API.h"\ + ".\zend_errors.h"\ + ".\zend_globals.h"\ + ".\zend_hash.h"\ + ".\zend_ini.h"\ + + +.\zend_constants.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\config.w32.h"\ + ".\zend_constants.h"\ + ".\zend_operators.h"\ + ".\zend_variables.h"\ + ".\zend.h"\ + ".\zend_errors.h"\ + ".\zend_hash.h"\ + + +.\zend_execute.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\zend_compile.h"\ + ".\config.w32.h"\ + ".\zend_constants.h"\ + ".\zend_execute.h"\ + ".\zend_llist.h"\ + ".\modules.h"\ + ".\zend_operators.h"\ + ".\zend_ptr_stack.h"\ + ".\zend_stack.h"\ + ".\zend_variables.h"\ + ".\zend.h"\ + ".\zend_API.h"\ + ".\zend_errors.h"\ + ".\zend_globals.h"\ + ".\zend_hash.h"\ + ".\zend_ini.h"\ + + +.\zend_highlight.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\zend_compile.h"\ + ".\config.w32.h"\ + ".\zend_execute.h"\ + ".\zend_highlight.h"\ + ".\zend_llist.h"\ + ".\zend_ptr_stack.h"\ + ".\zend_stack.h"\ + ".\zend-parser.tab.h"\ + ".\zend.h"\ + ".\zend_errors.h"\ + ".\zend_globals.h"\ + ".\zend_hash.h"\ + + +.\zend_llist.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\config.w32.h"\ + ".\zend_llist.h"\ + ".\zend.h"\ + ".\zend_errors.h"\ + ".\zend_hash.h"\ + + +.\zend_opcode.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\zend_compile.h"\ + ".\config.w32.h"\ + ".\zend_execute.h"\ + ".\zend_llist.h"\ + ".\modules.h"\ + ".\zend_operators.h"\ + ".\zend_ptr_stack.h"\ + ".\zend_stack.h"\ + ".\zend_variables.h"\ + ".\zend.h"\ + ".\zend_API.h"\ + ".\zend_errors.h"\ + ".\zend_globals.h"\ + ".\zend_hash.h"\ + ".\zend_ini.h"\ + + +.\zend_operators.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\zend_compile.h"\ + ".\config.w32.h"\ + ".\zend_execute.h"\ + ".\zend_llist.h"\ + ".\zend_operators.h"\ + ".\zend_ptr_stack.h"\ + ".\zend_stack.h"\ + ".\zend_variables.h"\ + ".\zend.h"\ + ".\zend_errors.h"\ + ".\zend_globals.h"\ + ".\zend_hash.h"\ + + +.\zend_ptr_stack.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\config.w32.h"\ + ".\zend_ptr_stack.h"\ + ".\zend.h"\ + ".\zend_errors.h"\ + ".\zend_hash.h"\ + + +.\zend_stack.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\config.w32.h"\ + ".\zend_stack.h"\ + ".\zend.h"\ + ".\zend_errors.h"\ + ".\zend_hash.h"\ + + +.\zend_variables.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\zend_compile.h"\ + ".\config.w32.h"\ + ".\zend_constants.h"\ + ".\zend_execute.h"\ + ".\zend_llist.h"\ + ".\modules.h"\ + ".\zend_ptr_stack.h"\ + ".\zend_stack.h"\ + ".\zend_variables.h"\ + ".\zend.h"\ + ".\zend_API.h"\ + ".\zend_errors.h"\ + ".\zend_globals.h"\ + ".\zend_hash.h"\ + ".\zend_ini.h"\ + ".\zend_list.h"\ + + +.\zend.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\config.w32.h"\ + ".\zend_operators.h"\ + ".\zend_variables.h"\ + ".\zend.h"\ + ".\zend_errors.h"\ + ".\zend_hash.h"\ + + +.\zend_API.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\zend_compile.h"\ + ".\config.w32.h"\ + ".\zend_constants.h"\ + ".\zend_execute.h"\ + ".\zend_llist.h"\ + ".\modules.h"\ + ".\zend_operators.h"\ + ".\zend_ptr_stack.h"\ + ".\zend_stack.h"\ + ".\zend_variables.h"\ + ".\zend.h"\ + ".\zend_API.h"\ + ".\zend_errors.h"\ + ".\zend_globals.h"\ + ".\zend_hash.h"\ + ".\zend_ini.h"\ + ".\zend_list.h"\ + + +.\zend_hash.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\config.w32.h"\ + ".\zend.h"\ + ".\zend_errors.h"\ + ".\zend_hash.h"\ + + +.\zend_ini.c : \ + "..\..\..\program files\microsoft visual studio\vc98\include\basetsd.h"\ + ".\zend_alloc.h"\ + ".\config.w32.h"\ + ".\zend.h"\ + ".\zend_errors.h"\ + ".\zend_hash.h"\ + ".\zend_ini.h"\ + + +!IF "$(CFG)" == "ZendCore - Win32 Release" + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + +!ENDIF + +!IF "$(CFG)" == "ZendCore - Win32 Release" + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + +!ENDIF + +!IF "$(CFG)" == "ZendCore - Win32 Release" + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + +!ENDIF + +!IF "$(CFG)" == "ZendCore - Win32 Release" + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + +!ENDIF + diff --git a/Zend/ZendCore.dsp b/Zend/ZendCore.dsp new file mode 100644 index 0000000000000..372cdf635019a --- /dev/null +++ b/Zend/ZendCore.dsp @@ -0,0 +1,358 @@ +# Microsoft Developer Studio Project File - Name="ZendCore" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=ZendCore - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "ZendCore.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ZendCore.mak" CFG="ZendCore - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ZendCore - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "ZendCore - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "ZendCore - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "COMPILE_LIBZEND" /YX /FD /c +# ADD BASE RSC /l 0x40d /d "NDEBUG" +# ADD RSC /l 0x40d /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "COMPILE_LIBZEND" /FR /YX /FD /GZ /c +# ADD BASE RSC /l 0x40d /d "_DEBUG" +# ADD RSC /l 0x40d /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo + +!ENDIF + +# Begin Target + +# Name "ZendCore - Win32 Release" +# Name "ZendCore - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\alloca.c +# End Source File +# Begin Source File + +SOURCE=.\sprintf.c +# End Source File +# Begin Source File + +SOURCE=".\zend-parser.c" +# End Source File +# Begin Source File + +SOURCE=".\zend-scanner.c" +# End Source File +# Begin Source File + +SOURCE=.\zend.c +# End Source File +# Begin Source File + +SOURCE=.\zend_alloc.c +# End Source File +# Begin Source File + +SOURCE=.\zend_API.c +# End Source File +# Begin Source File + +SOURCE=.\zend_compile.c +# End Source File +# Begin Source File + +SOURCE=.\zend_constants.c +# End Source File +# Begin Source File + +SOURCE=.\zend_execute.c +# End Source File +# Begin Source File + +SOURCE=.\zend_execute_API.c +# End Source File +# Begin Source File + +SOURCE=.\zend_extensions.c +# End Source File +# Begin Source File + +SOURCE=.\zend_hash.c +# End Source File +# Begin Source File + +SOURCE=.\zend_highlight.c +# End Source File +# Begin Source File + +SOURCE=.\zend_indent.c +# End Source File +# Begin Source File + +SOURCE=.\zend_list.c +# End Source File +# Begin Source File + +SOURCE=.\zend_llist.c +# End Source File +# Begin Source File + +SOURCE=.\zend_opcode.c +# End Source File +# Begin Source File + +SOURCE=.\zend_operators.c +# End Source File +# Begin Source File + +SOURCE=.\zend_ptr_stack.c +# End Source File +# Begin Source File + +SOURCE=.\zend_stack.c +# End Source File +# Begin Source File + +SOURCE=.\zend_variables.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\config.w32.h +# End Source File +# Begin Source File + +SOURCE=.\modules.h +# End Source File +# Begin Source File + +SOURCE=".\zend-parser.h" +# End Source File +# Begin Source File + +SOURCE=".\zend-scanner.h" +# End Source File +# Begin Source File + +SOURCE=.\zend.h +# End Source File +# Begin Source File + +SOURCE=.\zend_alloc.h +# End Source File +# Begin Source File + +SOURCE=.\zend_API.h +# End Source File +# Begin Source File + +SOURCE=.\zend_compile.h +# End Source File +# Begin Source File + +SOURCE=.\zend_constants.h +# End Source File +# Begin Source File + +SOURCE=.\zend_errors.h +# End Source File +# Begin Source File + +SOURCE=.\zend_execute.h +# End Source File +# Begin Source File + +SOURCE=.\zend_extensions.h +# End Source File +# Begin Source File + +SOURCE=.\zend_globals.h +# End Source File +# Begin Source File + +SOURCE=.\zend_hash.h +# End Source File +# Begin Source File + +SOURCE=.\zend_highlight.h +# End Source File +# Begin Source File + +SOURCE=.\zend_indent.h +# End Source File +# Begin Source File + +SOURCE=.\zend_list.h +# End Source File +# Begin Source File + +SOURCE=.\zend_llist.h +# End Source File +# Begin Source File + +SOURCE=.\zend_operators.h +# End Source File +# Begin Source File + +SOURCE=.\zend_ptr_stack.h +# End Source File +# Begin Source File + +SOURCE=.\zend_stack.h +# End Source File +# Begin Source File + +SOURCE=.\zend_variables.h +# End Source File +# End Group +# Begin Group "Parsers" + +# PROP Default_Filter "y" +# Begin Source File + +SOURCE=".\zend-parser.y" + +!IF "$(CFG)" == "ZendCore - Win32 Release" + +# Begin Custom Build +InputDir=. +InputPath=".\zend-parser.y" + +BuildCmds= \ + bison --output=zend-parser.c -v -d -S "C:\Program Files\Cygnus\share\bison.simple" -p zend zend-parser.y + +"$(InputDir)\zend-parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\zend-parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + +# Begin Custom Build +InputDir=. +InputPath=".\zend-parser.y" + +BuildCmds= \ + bison --output=zend-parser.c -v -d -S "C:\Program Files\Cygnus\share\bison.simple" -p zend zend-parser.y + +"$(InputDir)\zend-parser.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)\zend-parser.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# End Group +# Begin Group "Scanners" + +# PROP Default_Filter "l" +# Begin Source File + +SOURCE=".\zend-scanner.l" + +!IF "$(CFG)" == "ZendCore - Win32 Release" + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + +# Begin Custom Build +InputPath=".\zend-scanner.l" + +"zend-scanner.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + flex -i -Pzend -ozend-scanner.c zend-scanner.l + +# End Custom Build + +!ENDIF + +# End Source File +# End Group +# Begin Group "Text Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\ZEND_BUGS +# End Source File +# Begin Source File + +SOURCE=.\ZEND_CHANGES +# End Source File +# Begin Source File + +SOURCE=.\ZEND_TODO +# End Source File +# End Group +# Begin Group "Resources" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\zend.ico +# End Source File +# End Group +# End Target +# End Project diff --git a/Zend/ZendCore.dsw b/Zend/ZendCore.dsw new file mode 100644 index 0000000000000..299757e565feb --- /dev/null +++ b/Zend/ZendCore.dsw @@ -0,0 +1,65 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "ZendCore"=.\ZendCore.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "ZendDebugger"=..\ZendDebugger\ZendDebugger.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "ZendOpArrayViewer"=..\ZendOpArrayViewer\ZendOpArrayViewer.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "ZendOptimizer"=..\ZendOptimizer\ZendOptimizer.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/Zend/ZendCore.mak b/Zend/ZendCore.mak new file mode 100644 index 0000000000000..eb4499791d952 --- /dev/null +++ b/Zend/ZendCore.mak @@ -0,0 +1,628 @@ +# Microsoft Developer Studio Generated NMAKE File, Based on ZendCore.dsp +!IF "$(CFG)" == "" +CFG=ZendCore - Win32 Debug +!MESSAGE No configuration specified. Defaulting to ZendCore - Win32 Debug. +!ENDIF + +!IF "$(CFG)" != "ZendCore - Win32 Release" && "$(CFG)" != "ZendCore - Win32 Debug" +!MESSAGE Invalid configuration "$(CFG)" specified. +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "ZendCore.mak" CFG="ZendCore - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "ZendCore - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "ZendCore - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE +!ERROR An invalid configuration is specified. +!ENDIF + +!IF "$(OS)" == "Windows_NT" +NULL= +!ELSE +NULL=nul +!ENDIF + +!IF "$(CFG)" == "ZendCore - Win32 Release" + +OUTDIR=.\Release +INTDIR=.\Release +# Begin Custom Macros +OutDir=.\Release +# End Custom Macros + +ALL : "$(OUTDIR)\ZendCore.lib" + + +CLEAN : + -@erase "$(INTDIR)\alloc.obj" + -@erase "$(INTDIR)\alloca.obj" + -@erase "$(INTDIR)\compile.obj" + -@erase "$(INTDIR)\constants.obj" + -@erase "$(INTDIR)\execute.obj" + -@erase "$(INTDIR)\highlight.obj" + -@erase "$(INTDIR)\llist.obj" + -@erase "$(INTDIR)\opcode.obj" + -@erase "$(INTDIR)\operators.obj" + -@erase "$(INTDIR)\ptr_stack.obj" + -@erase "$(INTDIR)\sprintf.obj" + -@erase "$(INTDIR)\stack.obj" + -@erase "$(INTDIR)\variables.obj" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\zend.obj" + -@erase "$(INTDIR)\zend_API.obj" + -@erase "$(INTDIR)\zend_hash.obj" + -@erase "$(INTDIR)\zend_ini.obj" + -@erase "$(OUTDIR)\ZendCore.lib" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /Fp"$(INTDIR)\ZendCore.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ZendCore.bsc" +BSC32_SBRS= \ + +LIB32=link.exe -lib +LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ZendCore.lib" +LIB32_OBJS= \ + "$(INTDIR)\alloc.obj" \ + "$(INTDIR)\alloca.obj" \ + "$(INTDIR)\compile.obj" \ + "$(INTDIR)\constants.obj" \ + "$(INTDIR)\execute.obj" \ + "$(INTDIR)\highlight.obj" \ + "$(INTDIR)\llist.obj" \ + "$(INTDIR)\opcode.obj" \ + "$(INTDIR)\operators.obj" \ + "$(INTDIR)\ptr_stack.obj" \ + "$(INTDIR)\sprintf.obj" \ + "$(INTDIR)\stack.obj" \ + "$(INTDIR)\variables.obj" \ + "$(INTDIR)\zend.obj" \ + "$(INTDIR)\zend_hash.obj" \ + "$(INTDIR)\zend_ini.obj" \ + "$(INTDIR)\zend_API.obj" + +"$(OUTDIR)\ZendCore.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) + $(LIB32) @<< + $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) +<< + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + +OUTDIR=.\Debug +INTDIR=.\Debug +# Begin Custom Macros +OutDir=.\Debug +# End Custom Macros + +ALL : ".\zend-scanner.c" ".\zend-parser.tab.h" ".\zend-parser.tab.c" ".\configuration-scanner.c" ".\configuration-parser.tab.h" ".\configuration-parser.tab.c" "$(OUTDIR)\ZendCore.lib" "$(OUTDIR)\ZendCore.bsc" + + +CLEAN : + -@erase "$(INTDIR)\alloc.obj" + -@erase "$(INTDIR)\alloc.sbr" + -@erase "$(INTDIR)\alloca.obj" + -@erase "$(INTDIR)\alloca.sbr" + -@erase "$(INTDIR)\compile.obj" + -@erase "$(INTDIR)\compile.sbr" + -@erase "$(INTDIR)\constants.obj" + -@erase "$(INTDIR)\constants.sbr" + -@erase "$(INTDIR)\execute.obj" + -@erase "$(INTDIR)\execute.sbr" + -@erase "$(INTDIR)\highlight.obj" + -@erase "$(INTDIR)\highlight.sbr" + -@erase "$(INTDIR)\llist.obj" + -@erase "$(INTDIR)\llist.sbr" + -@erase "$(INTDIR)\opcode.obj" + -@erase "$(INTDIR)\opcode.sbr" + -@erase "$(INTDIR)\operators.obj" + -@erase "$(INTDIR)\operators.sbr" + -@erase "$(INTDIR)\ptr_stack.obj" + -@erase "$(INTDIR)\ptr_stack.sbr" + -@erase "$(INTDIR)\sprintf.obj" + -@erase "$(INTDIR)\sprintf.sbr" + -@erase "$(INTDIR)\stack.obj" + -@erase "$(INTDIR)\stack.sbr" + -@erase "$(INTDIR)\variables.obj" + -@erase "$(INTDIR)\variables.sbr" + -@erase "$(INTDIR)\vc60.idb" + -@erase "$(INTDIR)\vc60.pdb" + -@erase "$(INTDIR)\zend.obj" + -@erase "$(INTDIR)\zend.sbr" + -@erase "$(INTDIR)\zend_API.obj" + -@erase "$(INTDIR)\zend_API.sbr" + -@erase "$(INTDIR)\zend_hash.obj" + -@erase "$(INTDIR)\zend_hash.sbr" + -@erase "$(INTDIR)\zend_ini.obj" + -@erase "$(INTDIR)\zend_ini.sbr" + -@erase "$(OUTDIR)\ZendCore.bsc" + -@erase "$(OUTDIR)\ZendCore.lib" + -@erase "configuration-parser.tab.c" + -@erase "configuration-parser.tab.h" + -@erase "configuration-scanner.c" + -@erase "zend-parser.tab.c" + -@erase "zend-parser.tab.h" + -@erase "zend-scanner.c" + +"$(OUTDIR)" : + if not exist "$(OUTDIR)/$(NULL)" mkdir "$(OUTDIR)" + +CPP=cl.exe +CPP_PROJ=/nologo /MLd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR"$(INTDIR)\\" /Fp"$(INTDIR)\ZendCore.pch" /YX /Fo"$(INTDIR)\\" /Fd"$(INTDIR)\\" /FD /GZ /c + +.c{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.obj:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.c{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cpp{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +.cxx{$(INTDIR)}.sbr:: + $(CPP) @<< + $(CPP_PROJ) $< +<< + +RSC=rc.exe +BSC32=bscmake.exe +BSC32_FLAGS=/nologo /o"$(OUTDIR)\ZendCore.bsc" +BSC32_SBRS= \ + "$(INTDIR)\alloc.sbr" \ + "$(INTDIR)\alloca.sbr" \ + "$(INTDIR)\compile.sbr" \ + "$(INTDIR)\constants.sbr" \ + "$(INTDIR)\execute.sbr" \ + "$(INTDIR)\highlight.sbr" \ + "$(INTDIR)\llist.sbr" \ + "$(INTDIR)\opcode.sbr" \ + "$(INTDIR)\operators.sbr" \ + "$(INTDIR)\ptr_stack.sbr" \ + "$(INTDIR)\sprintf.sbr" \ + "$(INTDIR)\stack.sbr" \ + "$(INTDIR)\variables.sbr" \ + "$(INTDIR)\zend.sbr" \ + "$(INTDIR)\zend_hash.sbr" \ + "$(INTDIR)\zend_ini.sbr" \ + "$(INTDIR)\zend_API.sbr" + +"$(OUTDIR)\ZendCore.bsc" : "$(OUTDIR)" $(BSC32_SBRS) + $(BSC32) @<< + $(BSC32_FLAGS) $(BSC32_SBRS) +<< + +LIB32=link.exe -lib +LIB32_FLAGS=/nologo /out:"$(OUTDIR)\ZendCore.lib" +LIB32_OBJS= \ + "$(INTDIR)\alloc.obj" \ + "$(INTDIR)\alloca.obj" \ + "$(INTDIR)\compile.obj" \ + "$(INTDIR)\constants.obj" \ + "$(INTDIR)\execute.obj" \ + "$(INTDIR)\highlight.obj" \ + "$(INTDIR)\llist.obj" \ + "$(INTDIR)\opcode.obj" \ + "$(INTDIR)\operators.obj" \ + "$(INTDIR)\ptr_stack.obj" \ + "$(INTDIR)\sprintf.obj" \ + "$(INTDIR)\stack.obj" \ + "$(INTDIR)\variables.obj" \ + "$(INTDIR)\zend.obj" \ + "$(INTDIR)\zend_hash.obj" \ + "$(INTDIR)\zend_ini.obj" \ + "$(INTDIR)\zend_API.obj" + +"$(OUTDIR)\ZendCore.lib" : "$(OUTDIR)" $(DEF_FILE) $(LIB32_OBJS) + $(LIB32) @<< + $(LIB32_FLAGS) $(DEF_FLAGS) $(LIB32_OBJS) +<< + +!ENDIF + + +!IF "$(NO_EXTERNAL_DEPS)" != "1" +!IF EXISTS("ZendCore.dep") +!INCLUDE "ZendCore.dep" +!ELSE +!MESSAGE Warning: cannot find "ZendCore.dep" +!ENDIF +!ENDIF + + +!IF "$(CFG)" == "ZendCore - Win32 Release" || "$(CFG)" == "ZendCore - Win32 Debug" +SOURCE=.\zend_alloc.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\alloc.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\alloc.obj" "$(INTDIR)\alloc.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\alloca.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\alloca.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\alloca.obj" "$(INTDIR)\alloca.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend_compile.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\compile.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\compile.obj" "$(INTDIR)\compile.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend_constants.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\constants.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\constants.obj" "$(INTDIR)\constants.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend_execute.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\execute.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\execute.obj" "$(INTDIR)\execute.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend_highlight.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\highlight.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\highlight.obj" "$(INTDIR)\highlight.sbr" : $(SOURCE) "$(INTDIR)" ".\zend-parser.tab.h" + + +!ENDIF + +SOURCE=.\zend_llist.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\llist.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\llist.obj" "$(INTDIR)\llist.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend_opcode.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\opcode.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\opcode.obj" "$(INTDIR)\opcode.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend_operators.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\operators.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\operators.obj" "$(INTDIR)\operators.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend_ptr_stack.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\ptr_stack.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\ptr_stack.obj" "$(INTDIR)\ptr_stack.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\sprintf.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\sprintf.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\sprintf.obj" "$(INTDIR)\sprintf.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend_stack.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\stack.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\stack.obj" "$(INTDIR)\stack.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend_variables.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\variables.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\variables.obj" "$(INTDIR)\variables.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\zend.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\zend.obj" "$(INTDIR)\zend.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend_API.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\zend_API.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\zend_API.obj" "$(INTDIR)\zend_API.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend_hash.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\zend_hash.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\zend_hash.obj" "$(INTDIR)\zend_hash.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=.\zend_ini.c + +!IF "$(CFG)" == "ZendCore - Win32 Release" + + +"$(INTDIR)\zend_ini.obj" : $(SOURCE) "$(INTDIR)" + + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + + +"$(INTDIR)\zend_ini.obj" "$(INTDIR)\zend_ini.sbr" : $(SOURCE) "$(INTDIR)" + + +!ENDIF + +SOURCE=".\configuration-parser.y" + +!IF "$(CFG)" == "ZendCore - Win32 Release" + +!ELSEIF "$(CFG)" == "ZendCore - Win32 Debug" + +InputPath=".\configuration-parser.y" + +".\configuration-parser.tab.c" ".\configuration-parser.tab.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + <" by default) */ +#define DEFAULT_SHORT_OPEN_TAG 1 + +/* Define if you want the logging to go to ndbm/gdbm/flatfile */ +#define LOG_DBM 0 +#define LOG_DBM_DIR "." + +/* Define if you want the logging to go to a mysql database */ +#define LOG_MYSQL 0 + +/* Define if you want the logging to go to a mysql database */ +#define LOG_MSQL 0 + +/* Define these if you are using an SQL database for logging */ +#define LOG_SQL_HOST "" +#define LOG_SQL_DB "" + +/* Define if you an ndbm compatible library (-ldbm). */ +#define NDBM 0 + +/* Define if you have the gdbm library (-lgdbm). */ +#define GDBM 0 + +/* Define both of these if you want the bundled REGEX library */ +#define REGEX 0 +#define HSREGEX 0 + +/* Define if you want Solid database support */ +#define HAVE_SOLID 0 + +/* Define if you want to use the supplied dbase library */ +#define DBASE 0 + +/* Define if you want Hyperwave support */ +#define HYPERWAVE 0 + +/* Define if you have the crypt() function */ +#define HAVE_CRYPT 1 + +/* Define if you have the Oracle database client libraries */ +#define HAVE_ORACLE 0 + +/* Define if you have the Oracle version 8 database client libraries */ +#define HAVE_OCI8 0 + +/* Define if you want to use the iODBC database driver */ +#define HAVE_IODBC 0 + +/* Define if you want to use the OpenLink ODBC database driver */ +#define HAVE_OPENLINK 0 + +/* Define if you have the AdabasD client libraries */ +#define HAVE_ADABAS 0 + +/* Define if you want the LDAP directory interface */ +#define HAVE_LDAP 0 + +/* Define if you want the Cybercash MCK support */ +#define HAVE_MCK 0 + +/* Define if you want the SNMP interface */ +#define HAVE_SNMP 0 + +/* Define if you want the IMAP directory interface */ +#define HAVE_IMAP 0 + +/* Define if you want the ASPELL interface */ +#define HAVE_ASPELL 0 + +/* Define if you want to use a custom ODBC database driver */ +#define HAVE_CODBC 0 + +/* Define to use the unified ODBC interface */ +#define HAVE_UODBC 0 + +/* Define if you have libdl (used for dynamic linking) */ +#define HAVE_LIBDL 0 + +/* Define if you have libdnet_stub (used for Sybase support) */ +#define HAVE_LIBDNET_STUB 0 + +/* Define if you have and want to use libcrypt */ +#define HAVE_LIBCRYPT 0 + +/* Define if you have and want to use libnsl */ +#define HAVE_LIBNSL 0 + +/* Define if you have and want to use libsocket */ +#define HAVE_LIBSOCKET 0 + +/* Define if you have and want to use libpam */ +#define HAVE_LIBPAM 0 + +/* Define if you have the sendmail program available */ +#define HAVE_SENDMAIL 0 + +/* Define if your Apache creates an ap_config.h header file (only 1.3b6 and later) */ +#define HAVE_AP_CONFIG_H 0 + +/* Define if your Apache has src/include/compat.h */ +#define HAVE_OLD_COMPAT_H 0 + +/* Define if your Apache has src/include/ap_compat.h */ +#define HAVE_AP_COMPAT_H 0 + +#ifndef HAVE_EMPRESS +#define HAVE_EMPRESS 0 +#endif + +#define HAVE_SYBASE 0 +#define HAVE_SYBASE_CT 0 + +#ifndef HAVE_MYSQL +#define HAVE_MYSQL 0 +#endif + +#ifndef HAVE_MSQL +#define HAVE_MSQL 0 +#endif + +#ifndef HAVE_PGSQL +#define HAVE_PGSQL 0 +#endif + +#ifndef HAVE_VELOCIS +#define HAVE_VELOCIS 0 +#endif + +#ifndef HAVE_IFX +#define HAVE_IFX 0 +#endif +#ifndef HAVE_IFX_IUS +#define HAVE_IFX_IUS 0 +#endif +#ifndef IFX_VERSION +#define IFX_VERSION 0 +#endif + +#ifndef HAVE_IBASE +#define HAVE_IBASE 0 +#endif + +#ifndef HAVE_PQCMDTUPLES +#define HAVE_PQCMDTUPLES 0 +#endif + +#undef ZEND_DEBUG + +/* Define if your system has the gettimeofday() call */ +#define HAVE_GETTIMEOFDAY 0 + +/* Define if your system has the getrusage() call */ +#define HAVE_GETRUSAGE 0 + +/* Define if your system has the putenv() library call */ +#define HAVE_PUTENV 0 + +/* Define if you want to enable bc style precision math support */ +#define WITH_BCMATH 0 + +/* Define if you want to prevent the CGI from working unless REDIRECT_STATUS is defined in the environment */ +#define FORCE_CGI_REDIRECT 0 + +/* Define if you want to prevent the CGI from using path_info and path_translated */ +#define DISCARD_PATH 0 + +/* Define if you want to enable memory limit support */ +#define MEMORY_LIMIT 0 + +/* Define if you want System V semaphore support. + */ +#define HAVE_SYSVSEM 0 + +/* Define if you have union semun. + */ +#define HAVE_SEMUN 0 + +/* Define if you want System V shared memory support. */ +#define HAVE_SYSVSHM 0 + +/* Define if you want to enable displaying source support. */ +#define HAVE_DISPLAY_SOURCE 0 + +/* Define if you have broken header files like SunOS 4 */ +#define MISSING_FCLOSE_DECL 0 + +/* Define if you have broken sprintf function like SunOS 4 */ +#define BROKEN_SPRINTF 0 + +/* Define if you have the expat (XML Parser Toolkit) library */ +#define HAVE_LIBEXPAT 0 + +/* Define if you have the pdflib library */ +#define HAVE_PDFLIB 0 + +/* Define if you have the fdftk library */ +#define HAVE_FDFLIB 0 + +/* Define to compile with mod_dav support */ +#define HAVE_MOD_DAV 0 + +/* Define to enable yp/nis support */ +#define HAVE_YP 0 diff --git a/Zend/aclocal.m4 b/Zend/aclocal.m4 new file mode 100644 index 0000000000000..3bea7217f928c --- /dev/null +++ b/Zend/aclocal.m4 @@ -0,0 +1,52 @@ +dnl $Id$ +dnl +dnl This file contains local autoconf functions. + +dnl +dnl Check for broken sprintf() +dnl +AC_DEFUN(AC_BROKEN_SPRINTF,[ + AC_MSG_CHECKING([for broken sprintf]) + AC_TRY_RUN([main() { char buf[20]; exit (sprintf(buf,"testing 123")!=11); }],[ + AC_DEFINE(BROKEN_SPRINTF,0) + AC_MSG_RESULT(ok) + ],[ + AC_DEFINE(BROKEN_SPRINTF,1) + AC_MSG_RESULT(broken) + ],[ + AC_DEFINE(BROKEN_SPRINTF,0) + AC_MSG_RESULT(cannot check, guessing ok) + ]) +]) +# another one stolen from automake temporarily +# +# Check to make sure that the build environment is sane. +# + +AC_DEFUN(AM_SANITY_CHECK, +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftestfile +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftestfile 2> /dev/null` + if test "$@" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftestfile` + fi + test "[$]2" = conftestfile + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +rm -f conftest* +AC_MSG_RESULT(yes)]) diff --git a/Zend/config.h.in b/Zend/config.h.in new file mode 100644 index 0000000000000..9a8d7b7b89938 --- /dev/null +++ b/Zend/config.h.in @@ -0,0 +1,274 @@ +/* config.h.in. Generated automatically from configure.in by autoheader. */ + +/* Define if using alloca.c. */ +#undef C_ALLOCA + +/* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. + This function is required for alloca.c support on those systems. */ +#undef CRAY_STACKSEG_END + +/* Define if you have alloca, as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define if you have and it should be used (not on Ultrix). */ +#undef HAVE_ALLOCA_H + +/* Define if you don't have vprintf but do have _doprnt. */ +#undef HAVE_DOPRNT + +/* Define if utime(file, NULL) sets file's timestamp to the present. */ +#undef HAVE_UTIME_NULL + +/* Define if you have the vprintf function. */ +#undef HAVE_VPRINTF + +/* Define if your C compiler doesn't accept -c and -o together. */ +#undef NO_MINUS_C_MINUS_O + +/* Define to `unsigned' if doesn't define. */ +#undef size_t + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at run-time. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown + */ +#undef STACK_DIRECTION + +/* Define if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* define uint by configure if it is missed (QNX and BSD derived) */ +#undef uint + +/* define ulong by configure if it is missed (most probably is) */ +#undef ulong + +/* Define if you have the resolv library (-lresolv). */ +#define HAVE_LIBRESOLV 0 + +/* Define if you have libdl (used for dynamic linking) */ +#define HAVE_LIBDL 0 + +/* Define if you have and want to use libnsl */ +#define HAVE_LIBNSL 0 + +/* Define if you have and want to use libsocket */ +#define HAVE_LIBSOCKET 0 + +#undef ZEND_DEBUG + +/* Define if you want to enable memory limit support */ +#define MEMORY_LIMIT 0 + +/* Define if you have broken sprintf function like SunOS 4 */ +#define BROKEN_SPRINTF 0 + +/* Define if you have the crypt function. */ +#undef HAVE_CRYPT + +/* Define if you have the cuserid function. */ +#undef HAVE_CUSERID + +/* Define if you have the flock function. */ +#undef HAVE_FLOCK + +/* Define if you have the gcvt function. */ +#undef HAVE_GCVT + +/* Define if you have the getlogin function. */ +#undef HAVE_GETLOGIN + +/* Define if you have the getopt function. */ +#undef HAVE_GETOPT + +/* Define if you have the gettimeofday function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define if you have the inet_aton function. */ +#undef HAVE_INET_ATON + +/* Define if you have the link function. */ +#undef HAVE_LINK + +/* Define if you have the lockf function. */ +#undef HAVE_LOCKF + +/* Define if you have the lrand48 function. */ +#undef HAVE_LRAND48 + +/* Define if you have the memcpy function. */ +#undef HAVE_MEMCPY + +/* Define if you have the memmove function. */ +#undef HAVE_MEMMOVE + +/* Define if you have the putenv function. */ +#undef HAVE_PUTENV + +/* Define if you have the random function. */ +#undef HAVE_RANDOM + +/* Define if you have the regcomp function. */ +#undef HAVE_REGCOMP + +/* Define if you have the rint function. */ +#undef HAVE_RINT + +/* Define if you have the setitimer function. */ +#undef HAVE_SETITIMER + +/* Define if you have the setlocale function. */ +#undef HAVE_SETLOCALE + +/* Define if you have the setsockopt function. */ +#undef HAVE_SETSOCKOPT + +/* Define if you have the setvbuf function. */ +#undef HAVE_SETVBUF + +/* Define if you have the snprintf function. */ +#undef HAVE_SNPRINTF + +/* Define if you have the srand48 function. */ +#undef HAVE_SRAND48 + +/* Define if you have the srandom function. */ +#undef HAVE_SRANDOM + +/* Define if you have the statfs function. */ +#undef HAVE_STATFS + +/* Define if you have the statvfs function. */ +#undef HAVE_STATVFS + +/* Define if you have the strcasecmp function. */ +#undef HAVE_STRCASECMP + +/* Define if you have the strdup function. */ +#undef HAVE_STRDUP + +/* Define if you have the strerror function. */ +#undef HAVE_STRERROR + +/* Define if you have the strftime function. */ +#undef HAVE_STRFTIME + +/* Define if you have the strstr function. */ +#undef HAVE_STRSTR + +/* Define if you have the symlink function. */ +#undef HAVE_SYMLINK + +/* Define if you have the tempnam function. */ +#undef HAVE_TEMPNAM + +/* Define if you have the tzset function. */ +#undef HAVE_TZSET + +/* Define if you have the unsetenv function. */ +#undef HAVE_UNSETENV + +/* Define if you have the usleep function. */ +#undef HAVE_USLEEP + +/* Define if you have the utime function. */ +#undef HAVE_UTIME + +/* Define if you have the vsnprintf function. */ +#undef HAVE_VSNPRINTF + +/* Define if you have the header file. */ +#undef HAVE_CRYPT_H + +/* Define if you have the header file. */ +#undef HAVE_DB_H + +/* Define if you have the header file. */ +#undef HAVE_DIRENT_H + +/* Define if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define if you have the header file. */ +#undef HAVE_FCNTL_H + +/* Define if you have the header file. */ +#undef HAVE_GRP_H + +/* Define if you have the header file. */ +#undef HAVE_LIMITS_H + +/* Define if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define if you have the header file. */ +#undef HAVE_NDBM_H + +/* Define if you have the header file. */ +#undef HAVE_NDIR_H + +/* Define if you have the header file. */ +#undef HAVE_NETINET_IN_H + +/* Define if you have the header file. */ +#undef HAVE_PWD_H + +/* Define if you have the header file. */ +#undef HAVE_SIGNAL_H + +/* Define if you have the header file. */ +#undef HAVE_STDARG_H + +/* Define if you have the header file. */ +#undef HAVE_STRING_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_DIR_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_FILE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_NDIR_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_STATFS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_STATVFS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_VARARGS_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_WAIT_H + +/* Define if you have the header file. */ +#undef HAVE_SYSLOG_H + +/* Define if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define if you have the header file. */ +#undef HAVE_UNIX_H + +/* Define if you have the m library (-lm). */ +#undef HAVE_LIBM + +/* Define if you have the resolv library (-lresolv). */ +#undef HAVE_LIBRESOLV diff --git a/Zend/config.unix.h b/Zend/config.unix.h new file mode 100644 index 0000000000000..ecbfd70b3df9f --- /dev/null +++ b/Zend/config.unix.h @@ -0,0 +1,39 @@ +#ifndef _CONFIG_UNIX_H +#define _CONFIG_UNIX_H + +#define ZEND_API + +#include + +#if HAVE_SYS_TYPES_H +#include +#endif + +#if HAVE_STRING_H +#include +#else +#include +#endif + +#if HAVE_LIBDL +# include +# define DL_LOAD(libname) dlopen(libname, RTLD_NOW) +# define DL_UNLOAD dlclose +# define DL_FETCH_SYMBOL dlsym +# define DL_HANDLE void * +# define ZEND_EXTENSIONS_SUPPORT 1 +#else +# define ZEND_EXTENSIONS_SUPPORT 0 +#endif + +#if BROKEN_SPRINTF +int zend_sprintf(char *buffer, const char *format, ...); +#else +# define zend_sprintf sprintf +#endif + +#if ZEND_DEBUG +# define inline +#endif + +#endif /* _CONFIG_UNIX_H */ diff --git a/Zend/config.w32.h b/Zend/config.w32.h new file mode 100644 index 0000000000000..dac03e3b46e51 --- /dev/null +++ b/Zend/config.w32.h @@ -0,0 +1,41 @@ +#ifndef _ZEND_CONFIG_W32_H +#define _ZEND_CONFIG_W32_H + + +#include +#include + +typedef unsigned long ulong; +typedef unsigned int uint; + +#define HAVE_ALLOCA 1 +#include + +#define HAVE_DIRENT_H 0 + +#ifdef inline +#undef inline +#endif + +#define ZEND_DEBUG 1 + +#define zend_sprintf sprintf + +/* Visual C++ doesn't really work with inline for C */ +#define inline + + +#define DL_LOAD(libname) LoadLibrary(libname) +#define DL_FETCH_SYMBOL GetProcAddress +#define DL_UNLOAD FreeLibrary +#define DL_HANDLE HMODULE +#define ZEND_EXTENSIONS_SUPPORT 1 + +#ifdef COMPILE_LIBZEND +# define ZEND_API __declspec(dllexport) +#else +# define ZEND_API __declspec(dllimport) +#endif + + +#endif /* _ZEND_CONFIG_W32_H */ \ No newline at end of file diff --git a/Zend/configure.in b/Zend/configure.in new file mode 100644 index 0000000000000..201755a27257a --- /dev/null +++ b/Zend/configure.in @@ -0,0 +1,194 @@ +dnl $Id$ +dnl Process this file with autoconf to produce a configure script. + +AC_INIT(zend.c) + +AC_CONFIG_HEADER(config.h) +AM_SANITY_CHECK + +dnl We want this one before the checks, so the checks can modify CFLAGS. +test -z "$CFLAGS" && auto_cflags=1 + +dnl Checks for programs. +AC_PROG_YACC +if test "$YACC" != "bison -y"; then + AC_MSG_WARN(You will need bison if you'd want to regenerate the PHP 3.0 parsers.) +else + AC_MSG_CHECKING(bison version) + set `bison --version| sed -e 's/^GNU Bison version //' -e 's/\./ /'` + if test "$1" = "1" -a "$2" -lt "25"; then + AC_MSG_WARN(You will need bison 1.25 if you'd want to regenerate the PHP 3.0 parsers (found $1.$2).) + fi + AC_MSG_RESULT($1.$2 (ok)) +fi +AC_PROG_CC +AC_PROG_RANLIB +AC_PROG_CC_C_O +AC_PATH_PROG(PERL_PATH, perl) + +dnl Ugly hack to get around a problem with gcc on AIX. +if test "$CC" = "gcc" -a "$ac_cv_prog_cc_g" = "yes" -a \ + "`uname -sv`" = "AIX 4"; then + CFLAGS=`echo $CFLAGS | sed -e 's/-g//'` +fi + +dnl check for -R, etc. switch +AC_MSG_CHECKING(if compiler supports -R) +AC_CACHE_VAL(php_cv_cc_dashr,[ + SAVE_LIBS="${LIBS}" + LIBS="-R /usr/lib ${LIBS}" + AC_TRY_LINK([], [], php_cv_cc_dashr=yes, php_cv_cc_dashr=no) + LIBS="${SAVE_LIBS}"]) +AC_MSG_RESULT($php_cv_cc_dashr) +if test $php_cv_cc_dashr = "yes"; then + ld_runpath_switch="-R" + apxs_runpath_switch="-Wl,-R'" +else + AC_MSG_CHECKING([if compiler supports -Wl,-rpath,]) + AC_CACHE_VAL(php_cv_cc_rpath,[ + SAVE_LIBS="${LIBS}" + LIBS="-Wl,-rpath,/usr/lib ${LIBS}" + AC_TRY_LINK([], [], php_cv_cc_rpath=yes, php_cv_cc_rpath=no) + LIBS="${SAVE_LIBS}"]) + AC_MSG_RESULT($php_cv_cc_rpath) + if test $php_cv_cc_rpath = "yes"; then + ld_runpath_switch="-Wl,-rpath," + apxs_runpath_switch="-Wl,'-rpath " + else + dnl something innocuous + ld_runpath_switch="-L" + apxs_runpath_switch="-L'" + fi +fi + +dnl +dnl Check for /usr/pkg/{lib,include} which is where NetBSD puts binary +dnl and source packages. This should be harmless on other OSs. +dnl +if test -d /usr/pkg/include -a -d /usr/pkg/lib ; then + CFLAGS="$CFLAGS -I/usr/pkg/include" + LDFLAGS="$LDFLAGS -L/usr/pkg/lib" +fi + +AC_CHECK_LIB(nsl, gethostname, [ + LIBS="-lnsl $LIBS" + AC_DEFINE(HAVE_LIBNSL) ], []) + +AC_CHECK_LIB(c, socket, [:], [ + AC_CHECK_LIB(socket, socket, [ + LIBS="-lsocket $LIBS" + AC_DEFINE(HAVE_LIBSOCKET) ], []) ]) + +AC_CHECK_LIB(c, gethostbyaddr, [:], [ + AC_CHECK_LIB(nsl, gethostbyaddr, [ + LIBS="-lnsl $LIBS" + AC_DEFINE(HAVE_LIBNSL) ], []) ]) + +AC_CHECK_LIB(c, dlopen, [ + # fake it + AC_DEFINE(HAVE_LIBDL) ], [ + AC_CHECK_LIB(dl, dlopen, [ + LIBS="-ldl $LIBS" + AC_DEFINE(HAVE_LIBDL) ], []) ]) + +dnl The sin may be in a library which need not be specifed +dnl as well as res_search resides in libsocket +AC_CHECK_LIB(c, sin, [:], [ + AC_CHECK_LIB(m, sin) ]) + +dnl The res_search may be in libsocket as well, and if it is +dnl make sure to check for dn_skipname in libresolv, or if res_search +dnl is in neither of these libs, still check for dn_skipname in libresolv +AC_CHECK_LIB(socket, res_search, [ + AC_CHECK_LIB(resolv, dn_skipname) + AC_CHECK_LIB(resolv, __dn_skipname) + LIBS="$LIBS -lsocket" + AC_DEFINE(HAVE_LIBSOCKET) +], [ + AC_CHECK_LIB(resolv, res_search, [ + LIBS="$LIBS -lresolv" + AC_DEFINE(HAVE_LIBRESOLV) + ], [ + AC_CHECK_LIB(resolv, dn_skipname) + AC_CHECK_LIB(resolv, __dn_skipname) + ]) +]) + +dnl Checks for header files. +AC_HEADER_STDC + +dnl In QNX opendir resides in libc but dirent.h is still required +if test "`uname -s 2>/dev/null`" != "QNX"; then + AC_HEADER_DIRENT +else + AC_CHECK_HEADERS(dirent.h) +fi +dnl QNX requires unix.h to allow functions in libunix to work properly +AC_CHECK_HEADERS(fcntl.h unistd.h crypt.h sys/file.h memory.h pwd.h grp.h sys/socket.h sys/wait.h syslog.h string.h sys/varargs.h stdarg.h sys/resource.h sys/time.h signal.h netinet/in.h dlfcn.h limits.h sys/types.h sys/statvfs.h sys/statfs.h unix.h db.h ndbm.h) + +dnl Checks for types +AC_TYPE_SIZE_T + +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_CHECK_FUNCS(memcpy memmove strdup strerror strcasecmp strstr flock lockf putenv tempnam usleep setlocale gettimeofday setvbuf srand48 lrand48 srandom random link symlink regcomp getlogin cuserid vsnprintf snprintf gcvt utime crypt setitimer rint unsetenv strftime setsockopt tzset statvfs statfs inet_aton) +AC_FUNC_UTIME_NULL +AC_FUNC_ALLOCA +AC_BROKEN_SPRINTF +AC_REPLACE_FUNCS(getopt) + +AC_MSG_CHECKING(whether to include debugging symbols) +AC_ARG_ENABLE(debug, +[ --enable-debug Compile with debugging symbols], +[ + if test "$enableval" = "yes"; then + AC_MSG_RESULT(yes) + AC_DEFINE(ZEND_DEBUG,1) + DEBUG_CFLAGS="-g" + test -n "$GCC" && DEBUG_CFLAGS="$DEBUG_CFLAGS -Wall" + test -n "$GCC" && test "$USE_MAINTAINER_MODE" = "yes" && \ + DEBUG_CFLAGS="$DEBUG_CFLAGS -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations" + else + AC_MSG_RESULT(no) + AC_DEFINE(ZEND_DEBUG,0) + DEBUG_CFLAGS="" + fi +],[ + AC_MSG_RESULT(no) + AC_DEFINE(ZEND_DEBUG,0) + DEBUG_CFLAGS="" +]) +AC_SUBST(DEBUG_CFLAGS) + + +AC_MSG_CHECKING(whether to enable a memory limit) +AC_ARG_ENABLE(memory-limit, +[ --enable-memory-limit Compile with memory limit support. ], +[ + if test "$enableval" = "yes"; then + AC_DEFINE(MEMORY_LIMIT, 1) + AC_MSG_RESULT(yes) + else + AC_DEFINE(MEMORY_LIMIT, 0) + AC_MSG_RESULT(no) + fi +],[ + AC_DEFINE(MEMORY_LIMIT, 0) + AC_MSG_RESULT(no) +]) + + +AC_SUBST(CFLAGS_SHLIB) +AC_SUBST(LDFLAGS_SHLIB) +AC_SUBST(LDFLAGS_SHLIB_EXPORT) + +AC_OUTPUT(Makefile, [], []) + + +# Local Variables: +# tab-width: 4 +# End: diff --git a/Zend/diffs b/Zend/diffs new file mode 100644 index 0000000000000..5915889366b55 --- /dev/null +++ b/Zend/diffs @@ -0,0 +1,8 @@ +Index: zend_execute.c +=================================================================== +RCS file: /repository/Zend/ZendCore/zend_execute.c,v +retrieving revision 1.25 +retrieving revision 1.26 +diff -r1.25 -r1.26 +17d16 +< /* $Id$ */ diff --git a/Zend/zend-parser.y b/Zend/zend-parser.y new file mode 100644 index 0000000000000..f5c51ff408e2b --- /dev/null +++ b/Zend/zend-parser.y @@ -0,0 +1,632 @@ +%{ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +/* + * LALR shift/reduce conflicts and how they are resolved: + * + * - 2 shift/reduce conflicts due to the dangeling elseif/else ambiguity. Solved by shift. + * - 1 shift/reduce conflict due to arrays within encapsulated strings. Solved by shift. + * - 1 shift/reduce conflict due to objects within encapsulated strings. Solved by shift. + * + */ + +#include "zend_compile.h" +#include "zend.h" +#include "zend_list.h" +#include "zend_globals.h" +#include "zend_API.h" +#include "zend_variables.h" +#include "zend_operators.h" + + +#define YYERROR_VERBOSE + +%} + +%pure_parser +%expect 4 + +%left INCLUDE EVAL +%left ',' +%left LOGICAL_OR +%left LOGICAL_XOR +%left LOGICAL_AND +%right ZEND_PRINT +%left '=' PLUS_EQUAL MINUS_EQUAL MUL_EQUAL DIV_EQUAL CONCAT_EQUAL MOD_EQUAL AND_EQUAL OR_EQUAL XOR_EQUAL SHIFT_LEFT_EQUAL SHIFT_RIGHT_EQUAL +%left '?' ':' +%left BOOLEAN_OR +%left BOOLEAN_AND +%left '|' +%left '^' +%left '&' +%nonassoc IS_EQUAL IS_NOT_EQUAL +%nonassoc '<' IS_SMALLER_OR_EQUAL '>' IS_GREATER_OR_EQUAL +%left SHIFT_LEFT SHIFT_RIGHT +%left '+' '-' '.' +%left '*' '/' '%' +%right '!' '~' INCREMENT DECREMENT INT_CAST DOUBLE_CAST STRING_CAST ARRAY_CAST OBJECT_CAST '@' +%right '[' +%nonassoc NEW +%token T_EXIT +%token IF +%left ELSEIF +%left ELSE +%left ENDIF +%token LNUMBER +%token DNUMBER +%token STRING +%token VARIABLE +%token NUM_STRING +%token INLINE_HTML +%token CHARACTER +%token BAD_CHARACTER +%token ENCAPSED_AND_WHITESPACE +%token CONSTANT_ENCAPSED_STRING +%token ZEND_ECHO +%token DO +%token WHILE +%token ENDWHILE +%token FOR +%token ENDFOR +%token ZEND_FOREACH +%token T_ENDFOREACH +%token ZEND_AS +%token SWITCH +%token ENDSWITCH +%token CASE +%token DEFAULT +%token BREAK +%token CONTINUE +%token CONTINUED_WHILE +%token CONTINUED_DOWHILE +%token CONTINUED_FOR +%token OLD_FUNCTION +%token FUNCTION +%token ZEND_CONST +%token RETURN +%token REQUIRE +%token ZEND_GLOBAL +%token ZEND_STATIC +%token ZEND_UNSET +%token T_ISSET +%token T_EMPTY +%token CLASS +%token EXTENDS +%token ZEND_OBJECT_OPERATOR +%token ZEND_DOUBLE_ARROW +%token ZEND_LIST +%token ZEND_ARRAY +%token VAR +%token ZEND_LINE +%token ZEND_FILE +%token ZEND_COMMENT +%token ZEND_ML_COMMENT +%token PHP_OPEN_TAG +%token PHP_OPEN_TAG_WITH_ECHO +%token PHP_CLOSE_TAG +%token T_WHITESPACE +%token ZEND_HEREDOC +%token DOLLAR_OPEN_CURLY_BRACES +%token T_CURLY_OPEN +%token T_PAAMAYIM_NEKUDOTAYIM +%token T_PHP_TRACK_VARS + +%% /* Rules */ + +statement_list: + statement_list { do_extended_info(CLS_C); } statement { HANDLE_INTERACTIVE(); } + | /* empty */ +; + + +statement: + '{' statement_list '}' + | IF '(' expr ')' { do_if_cond(&$3, &$4 CLS_CC); } statement { do_if_after_statement(&$4, 1 CLS_CC); } elseif_list else_single { do_if_end(CLS_C); } + | IF '(' expr ')' ':' { do_if_cond(&$3, &$4 CLS_CC); } statement_list { do_if_after_statement(&$4, 1 CLS_CC); } new_elseif_list new_else_single ENDIF ';' { do_if_end(CLS_C); } + | WHILE '(' { $1.u.opline_num = get_next_op_number(CG(active_op_array)); } expr ')' { do_while_cond(&$4, &$5 CLS_CC); } while_statement { do_while_end(&$1, &$5 CLS_CC); } + | DO { $1.u.opline_num = get_next_op_number(CG(active_op_array)); do_do_while_begin(CLS_C); } statement WHILE '(' expr ')' ';' { do_do_while_end(&$1, &$6 CLS_CC); } + | FOR + '(' + for_expr + ';' { do_free(&$3 CLS_CC); $4.u.opline_num = get_next_op_number(CG(active_op_array)); } + for_expr + ';' { do_for_cond(&$6, &$7 CLS_CC); } + for_expr + ')' { do_free(&$9 CLS_CC); do_for_before_statement(&$4, &$7 CLS_CC); } + for_statement { do_for_end(&$7 CLS_CC); } + | SWITCH '(' expr ')' { do_switch_cond(&$3 CLS_CC); } switch_case_list { do_switch_end(&$6 CLS_CC); } + | BREAK ';' { do_brk_cont(ZEND_BRK, NULL CLS_CC); } + | BREAK expr ';' { do_brk_cont(ZEND_BRK, &$2 CLS_CC); } + | CONTINUE ';' { do_brk_cont(ZEND_CONT, NULL CLS_CC); } + | CONTINUE expr ';' { do_brk_cont(ZEND_CONT, &$2 CLS_CC); } + | FUNCTION { $1.u.opline_num = CG(zend_lineno); } STRING { do_begin_function_declaration(&$1, &$3, 0 CLS_CC); } + '(' parameter_list ')' '{' statement_list '}' { do_end_function_declaration(&$1 CLS_CC); } + | OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } STRING { do_begin_function_declaration(&$1, &$3, 0 CLS_CC); } + parameter_list '(' statement_list ')' ';' { do_end_function_declaration(&$1 CLS_CC); } + | RETURN ';' { do_return(NULL CLS_CC); } + | RETURN expr ';' { do_return(&$2 CLS_CC); } + | ZEND_GLOBAL global_var_list + | ZEND_STATIC static_var_list + | CLASS STRING { do_begin_class_declaration(&$2, NULL CLS_CC); } '{' class_statement_list '}' { do_end_class_declaration(CLS_C); } + | CLASS STRING EXTENDS STRING { do_begin_class_declaration(&$2, &$4 CLS_CC); } '{' class_statement_list '}' { do_end_class_declaration(CLS_C); } + | ZEND_ECHO echo_expr_list ';' + | INLINE_HTML { do_echo(&$1 CLS_CC); } + | expr ';' { do_free(&$1 CLS_CC); } + | REQUIRE CONSTANT_ENCAPSED_STRING ';' { require_filename($2.u.constant.value.str.val CLS_CC); zval_dtor(&$2.u.constant); } + | REQUIRE '(' CONSTANT_ENCAPSED_STRING ')' ';' { require_filename($3.u.constant.value.str.val CLS_CC); zval_dtor(&$3.u.constant); } + | ZEND_UNSET '(' r_cvar ')' ';' { do_unset(&$3 CLS_CC); } + | ZEND_FOREACH '(' expr ZEND_AS { do_foreach_begin(&$1, &$3, &$2, &$4); } w_cvar foreach_optional_arg ')' { do_foreach_cont(&$6, &$7, &$4 CLS_CC); } foreach_statement { do_foreach_end(&$1, &$2 CLS_CC); } + | ';' /* empty statement */ +; + + +foreach_optional_arg: + /* empty */ { $$.op_type = IS_UNUSED; } + | ZEND_DOUBLE_ARROW w_cvar { $$ = $2; } +; + + +for_statement: + statement + | ':' statement_list ENDFOR ';' +; + + +foreach_statement: + statement + | ':' statement_list T_ENDFOREACH ';' +; + + +switch_case_list: + '{' case_list '}' { $$ = $2; } + | '{' ';' case_list '}' { $$ = $3; } + | ':' case_list ENDSWITCH ';' { $$ = $2; } + | ':' ';' case_list ENDSWITCH ';' { $$ = $3; } +; + + +case_list: + /* empty */ { $$.u.opline_num = -1; } + | case_list CASE expr case_separator { do_case_before_statement(&$1, &$2, &$3 CLS_CC); } statement_list { do_case_after_statement(&$$, &$2 CLS_CC); } + | case_list DEFAULT case_separator { do_default_before_statement(&$1, &$2 CLS_CC); } statement_list { do_case_after_statement(&$$, &$2 CLS_CC); } +; + + +case_separator: + ':' + | ';' +; + + +while_statement: + statement + | ':' statement_list ENDWHILE ';' +; + + + +elseif_list: + /* empty */ + | elseif_list ELSEIF '(' expr ')' { do_if_cond(&$4, &$5 CLS_CC); } statement { do_if_after_statement(&$5, 0 CLS_CC); } +; + + +new_elseif_list: + /* empty */ + | new_elseif_list ELSEIF '(' expr ')' ':' { do_if_cond(&$4, &$5 CLS_CC); } statement_list { do_if_after_statement(&$5, 0 CLS_CC); } +; + + +else_single: + /* empty */ + | ELSE statement +; + + +new_else_single: + /* empty */ + | ELSE ':' statement_list +; + + + + +parameter_list: + non_empty_parameter_list + | /* empty */ +; + + +non_empty_parameter_list: + VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=0; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); } + | '&' VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$2, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=0; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_FORCE CLS_CC); } + | ZEND_CONST VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$2, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=0; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); } + | VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$1, 0 CLS_CC); $$.op_type = IS_CONST; $$.u.constant.value.lval=0; $$.u.constant.type=IS_LONG; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$3, BYREF_NONE CLS_CC); } + | non_empty_parameter_list ',' VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$3, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); } + | non_empty_parameter_list ',' '&' VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$4, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_FORCE CLS_CC); } + | non_empty_parameter_list ',' ZEND_CONST VARIABLE { znode tmp; fetch_simple_variable(&tmp, &$4, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV, &tmp, &$$, NULL, BYREF_NONE CLS_CC); } + | non_empty_parameter_list ',' VARIABLE '=' static_scalar { znode tmp; fetch_simple_variable(&tmp, &$3, 0 CLS_CC); $$=$1; $$.u.constant.value.lval++; do_receive_arg(ZEND_RECV_INIT, &tmp, &$$, &$5, BYREF_NONE CLS_CC); } +; + + +function_call_parameter_list: + non_empty_function_call_parameter_list + | /* empty */ +; + + +non_empty_function_call_parameter_list: + expr_without_variable { $$.u.constant.value.lval = 0; do_pass_param(&$1, ZEND_SEND_VAL, $$.u.constant.value.lval CLS_CC); } + | cvar { $$.u.constant.value.lval = 0; do_pass_param(&$1, ZEND_SEND_VAR, $$.u.constant.value.lval CLS_CC); } + | '&' w_cvar { $$.u.constant.value.lval = 0; do_pass_param(&$2, ZEND_SEND_REF, $$.u.constant.value.lval CLS_CC); } + | non_empty_function_call_parameter_list ',' expr_without_variable { $$.u.constant.value.lval=$1.u.constant.value.lval+1; do_pass_param(&$3, ZEND_SEND_VAL, $$.u.constant.value.lval CLS_CC); } + | non_empty_function_call_parameter_list ',' cvar { $$.u.constant.value.lval=$1.u.constant.value.lval+1; do_pass_param(&$3, ZEND_SEND_VAR, $$.u.constant.value.lval CLS_CC); } + | non_empty_function_call_parameter_list ',' '&' w_cvar { $$.u.constant.value.lval=$1.u.constant.value.lval+1; do_pass_param(&$4, ZEND_SEND_REF, $$.u.constant.value.lval CLS_CC); } +; + +global_var_list: + global_var_list ',' global_var { do_fetch_global_or_static_variable(&$3, NULL, ZEND_FETCH_GLOBAL CLS_CC); } + | global_var { do_fetch_global_or_static_variable(&$1, NULL, ZEND_FETCH_GLOBAL CLS_CC); } +; + + +global_var: + VARIABLE { $$ = $1; } + | '$' r_cvar { $$ = $2; } + | '$' '{' expr '}' { $$ = $3; } +; + + +static_var_list: + static_var_list ',' VARIABLE { do_fetch_global_or_static_variable(&$3, NULL, ZEND_FETCH_STATIC CLS_CC); } + | static_var_list ',' VARIABLE '=' static_scalar { do_fetch_global_or_static_variable(&$3, &$5, ZEND_FETCH_STATIC CLS_CC); } + | VARIABLE { do_fetch_global_or_static_variable(&$1, NULL, ZEND_FETCH_STATIC CLS_CC); } + | VARIABLE '=' static_scalar { do_fetch_global_or_static_variable(&$1, &$3, ZEND_FETCH_STATIC CLS_CC); } + +; + + +class_statement_list: + class_statement_list class_statement + | /* empty */ +; + + +class_statement: + VAR class_variable_decleration ';' + | FUNCTION { $1.u.opline_num = CG(zend_lineno); } STRING { do_begin_function_declaration(&$1, &$3, 1 CLS_CC); } '(' + parameter_list ')' '{' statement_list '}' { do_end_function_declaration(&$1 CLS_CC); } + | OLD_FUNCTION { $1.u.opline_num = CG(zend_lineno); } STRING { do_begin_function_declaration(&$1, &$3, 1 CLS_CC); } + parameter_list '(' statement_list ')' ';' { do_end_function_declaration(&$1 CLS_CC); } + +; + + +class_variable_decleration: + class_variable_decleration ',' VARIABLE { do_declare_property(&$3, NULL CLS_CC); } + | class_variable_decleration ',' VARIABLE '=' static_scalar { do_declare_property(&$3, &$5 CLS_CC); } + | VARIABLE { do_declare_property(&$1, NULL CLS_CC); } + | VARIABLE '=' static_scalar { do_declare_property(&$1, &$3 CLS_CC); } +; + + +echo_expr_list: + /* empty */ + | echo_expr_list ',' expr { do_echo(&$3 CLS_CC); } + | expr { do_echo(&$1 CLS_CC); } +; + + +for_expr: + /* empty */ { $$.op_type = IS_CONST; $$.u.constant.type = IS_BOOL; $$.u.constant.value.lval = 1; } + | for_expr ',' expr { $$ = $3; } + | expr { $$ = $1; } +; + + +expr_without_variable: + ZEND_LIST '(' { do_list_init(); } assignment_list ')' '=' expr { do_list_end(&$$, &$7 CLS_CC); } + | w_cvar '=' expr { do_assign(&$$, &$1, &$3 CLS_CC); } + | w_cvar '=' '&' w_cvar { do_assign_ref(&$$, &$1, &$4 CLS_CC); } + | w_cvar '=' NEW class_name { do_extended_fcall_begin(CLS_C); do_begin_new_object(&$2, &$1, &$3, &$4 CLS_CC); } ctor_arguments { do_end_new_object(&$4, &$3 CLS_CC); do_extended_fcall_end(CLS_C); $$ = $2;} + | rw_cvar PLUS_EQUAL expr { do_binary_assign_op(ZEND_ASSIGN_ADD, &$$, &$1, &$3 CLS_CC); } + | rw_cvar MINUS_EQUAL expr { do_binary_assign_op(ZEND_ASSIGN_SUB, &$$, &$1, &$3 CLS_CC); } + | rw_cvar MUL_EQUAL expr { do_binary_assign_op(ZEND_ASSIGN_MUL, &$$, &$1, &$3 CLS_CC); } + | rw_cvar DIV_EQUAL expr { do_binary_assign_op(ZEND_ASSIGN_DIV, &$$, &$1, &$3 CLS_CC); } + | rw_cvar CONCAT_EQUAL expr { do_binary_assign_op(ZEND_ASSIGN_CONCAT, &$$, &$1, &$3 CLS_CC); } + | rw_cvar MOD_EQUAL expr { do_binary_assign_op(ZEND_ASSIGN_MOD, &$$, &$1, &$3 CLS_CC); } + | rw_cvar AND_EQUAL expr { do_binary_assign_op(ZEND_ASSIGN_BW_AND, &$$, &$1, &$3 CLS_CC); } + | rw_cvar OR_EQUAL expr { do_binary_assign_op(ZEND_ASSIGN_BW_OR, &$$, &$1, &$3 CLS_CC); } + | rw_cvar XOR_EQUAL expr { do_binary_assign_op(ZEND_ASSIGN_BW_XOR, &$$, &$1, &$3 CLS_CC); } + | rw_cvar SHIFT_LEFT_EQUAL expr { do_binary_assign_op(ZEND_ASSIGN_SL, &$$, &$1, &$3 CLS_CC); } + | rw_cvar SHIFT_RIGHT_EQUAL expr { do_binary_assign_op(ZEND_ASSIGN_SR, &$$, &$1, &$3 CLS_CC); } + | rw_cvar INCREMENT { do_post_incdec(&$$, &$1, ZEND_POST_INC CLS_CC); } + | INCREMENT rw_cvar { do_pre_incdec(&$$, &$2, ZEND_PRE_INC CLS_CC); } + | rw_cvar DECREMENT { do_post_incdec(&$$, &$1, ZEND_POST_DEC CLS_CC); } + | DECREMENT rw_cvar { do_pre_incdec(&$$, &$2, ZEND_PRE_DEC CLS_CC); } + | expr BOOLEAN_OR { do_boolean_or_begin(&$1, &$2 CLS_CC); } expr { do_boolean_or_end(&$$, &$1, &$4, &$2 CLS_CC); } + | expr BOOLEAN_AND { do_boolean_and_begin(&$1, &$2 CLS_CC); } expr { do_boolean_and_end(&$$, &$1, &$4, &$2 CLS_CC); } + | expr LOGICAL_OR { do_boolean_or_begin(&$1, &$2 CLS_CC); } expr { do_boolean_or_end(&$$, &$1, &$4, &$2 CLS_CC); } + | expr LOGICAL_AND { do_boolean_and_begin(&$1, &$2 CLS_CC); } expr { do_boolean_and_end(&$$, &$1, &$4, &$2 CLS_CC); } + | expr LOGICAL_XOR expr { do_binary_op(ZEND_BOOL_XOR, &$$, &$1, &$3 CLS_CC); } + | expr '|' expr { do_binary_op(ZEND_BW_OR, &$$, &$1, &$3 CLS_CC); } + | expr '&' expr { do_binary_op(ZEND_BW_AND, &$$, &$1, &$3 CLS_CC); } + | expr '^' expr { do_binary_op(ZEND_BW_XOR, &$$, &$1, &$3 CLS_CC); } + | expr '.' expr { do_binary_op(ZEND_CONCAT,&$$,&$1,&$3 CLS_CC); } + | expr '+' expr { do_binary_op(ZEND_ADD,&$$,&$1,&$3 CLS_CC); } + | expr '-' expr { do_binary_op(ZEND_SUB,&$$,&$1,&$3 CLS_CC); } + | expr '*' expr { do_binary_op(ZEND_MUL,&$$,&$1,&$3 CLS_CC); } + | expr '/' expr { do_binary_op(ZEND_DIV,&$$,&$1,&$3 CLS_CC); } + | expr '%' expr { do_binary_op(ZEND_MOD,&$$,&$1,&$3 CLS_CC); } + | expr SHIFT_LEFT expr { do_binary_op(ZEND_SL, &$$, &$1, &$3 CLS_CC); } + | expr SHIFT_RIGHT expr { do_binary_op(ZEND_SR, &$$, &$1, &$3 CLS_CC); } + | '+' expr { $1.u.constant.value.lval=0; $1.u.constant.type=IS_LONG; $1.op_type = IS_CONST; $1.u.constant.refcount=1; do_binary_op(ZEND_ADD, &$$, &$1, &$2 CLS_CC); } + | '-' expr { $1.u.constant.value.lval=0; $1.u.constant.type=IS_LONG; $1.op_type = IS_CONST; $1.u.constant.refcount=1; do_binary_op(ZEND_SUB, &$$, &$1, &$2 CLS_CC); } + | '!' expr { do_unary_op(ZEND_BOOL_NOT, &$$, &$2 CLS_CC); } + | '~' expr { do_unary_op(ZEND_BW_NOT, &$$, &$2 CLS_CC); } + | expr IS_EQUAL expr { do_binary_op(ZEND_IS_EQUAL, &$$, &$1, &$3 CLS_CC); } + | expr IS_NOT_EQUAL expr { do_binary_op(ZEND_IS_NOT_EQUAL, &$$, &$1, &$3 CLS_CC); } + | expr '<' expr { do_binary_op(ZEND_IS_SMALLER, &$$, &$1, &$3 CLS_CC); } + | expr IS_SMALLER_OR_EQUAL expr { do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$1, &$3 CLS_CC); } + | expr '>' expr { do_binary_op(ZEND_IS_SMALLER, &$$, &$3, &$1 CLS_CC); } + | expr IS_GREATER_OR_EQUAL expr { do_binary_op(ZEND_IS_SMALLER_OR_EQUAL, &$$, &$3, &$1 CLS_CC); } + | '(' expr ')' { $$ = $2; } + | expr '?' { do_begin_qm_op(&$1, &$2 CLS_CC); } + expr ':' { do_qm_true(&$4, &$2, &$5 CLS_CC); } + expr { do_qm_false(&$$, &$7, &$2, &$5 CLS_CC); } + | STRING '(' { do_extended_fcall_begin(CLS_C); do_begin_function_call(&$1 CLS_CC); } + function_call_parameter_list + ')' { do_end_function_call(&$1, &$$, 0 CLS_CC); do_extended_fcall_end(CLS_C); } + | r_cvar '(' { do_extended_fcall_begin(CLS_C); do_begin_dynamic_function_call(&$1 CLS_CC); } + function_call_parameter_list + ')' { do_end_function_call(&$1, &$$, 0 CLS_CC); do_extended_fcall_end(CLS_C);} + | STRING T_PAAMAYIM_NEKUDOTAYIM STRING '(' { do_extended_fcall_begin(CLS_C); do_begin_class_member_function_call(&$1, &$3 CLS_CC); } + function_call_parameter_list + ')' { do_end_function_call(&$3, &$$, 1 CLS_CC); do_extended_fcall_end(CLS_C);} + | internal_functions_in_yacc { $$ = $1; } + | INT_CAST expr { do_cast(&$$, &$2, IS_LONG CLS_CC); } + | DOUBLE_CAST expr { do_cast(&$$, &$2, IS_DOUBLE CLS_CC); } + | STRING_CAST expr { do_cast(&$$, &$2, IS_STRING CLS_CC); } + | ARRAY_CAST expr { do_cast(&$$, &$2, IS_ARRAY CLS_CC); } + | OBJECT_CAST expr { do_cast(&$$, &$2, IS_OBJECT CLS_CC); } + | T_EXIT exit_expr { do_exit(&$$, &$2 CLS_CC); } + | '@' { do_begin_silence(&$1 CLS_CC); } expr { do_end_silence(&$1 CLS_CC); $$ = $3; } + | scalar { $$ = $1; } + | ZEND_ARRAY '(' array_pair_list ')' { $$ = $3; } + | '`' encaps_list '`' { do_shell_exec(&$$, &$2 CLS_CC); } + | ZEND_PRINT expr { do_print(&$$, &$2 CLS_CC); } +; + + +exit_expr: + /* empty */ { $$.op_type = IS_UNUSED; } + | '(' ')' { $$.op_type = IS_UNUSED; } + | '(' expr ')' { $$ = $2; } +; + + +ctor_arguments: + /* empty */ + | '(' function_call_parameter_list ')' +; + + +class_name: + STRING { $$ = $1; } + | r_cvar { $$ = $1; } +; + + + +common_scalar: + LNUMBER { $$=$1; } + | DNUMBER { $$=$1; } + | CONSTANT_ENCAPSED_STRING { $$ = $1; } + | ZEND_LINE + | ZEND_FILE +; + + +static_scalar: /* compile-time evaluated scalars */ + common_scalar { $$ = $1; } + | STRING { do_fetch_constant(&$$, &$1, ZEND_CT CLS_CC); } + | '+' static_scalar { $$ = $1; } + | '-' 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); $$ = $2; } + | ZEND_ARRAY '(' static_array_pair_list ')' { $$ = $3; } +; + + +scalar: + STRING { do_fetch_constant(&$$, &$1, ZEND_RT CLS_CC); } + | common_scalar { $$ = $1; } + | '"' encaps_list '"' { $$ = $2; } + | '\'' encaps_list '\'' { $$ = $2; } + | ZEND_HEREDOC encaps_list ZEND_HEREDOC { $$ = $2; do_end_heredoc(CLS_C); } +; + + +static_array_pair_list: + /* empty */ { $$.op_type = IS_CONST; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; array_init(&$$.u.constant); } + | non_empty_static_array_pair_list { $$ = $1; } +; + + +non_empty_static_array_pair_list: + non_empty_static_array_pair_list ',' static_scalar ZEND_DOUBLE_ARROW static_scalar { do_add_static_array_element(&$$, &$3, &$5); } + | non_empty_static_array_pair_list ',' static_scalar { do_add_static_array_element(&$$, &$3, NULL); } + | static_scalar ZEND_DOUBLE_ARROW static_scalar { $$.op_type = IS_CONST; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; array_init(&$$.u.constant); do_add_static_array_element(&$$, &$1, &$3); } + | static_scalar { $$.op_type = IS_CONST; $$.u.constant.refcount=1; $$.u.constant.is_ref=0; array_init(&$$.u.constant); do_add_static_array_element(&$$, &$1, NULL); } +; + +expr: + r_cvar { $$ = $1; } + | expr_without_variable { $$ = $1; } +; + + + +r_cvar: + cvar { do_end_variable_parse(BP_VAR_R CLS_CC); $$ = $1; } +; + + +w_cvar: + cvar { do_end_variable_parse(BP_VAR_W CLS_CC); $$ = $1; } +; + + +rw_cvar: + cvar { do_end_variable_parse(BP_VAR_RW CLS_CC); $$ = $1; } +; + + +cvar: + cvar_without_objects { $$ = $1; } + | cvar_without_objects ZEND_OBJECT_OPERATOR { do_push_object(&$1 CLS_CC); } ref_list { $$ = $4; } +; + + +cvar_without_objects: + reference_variable { $$ = $1; } + | simple_indirect_reference reference_variable { do_indirect_references(&$$, &$1, &$2 CLS_CC); } +; + + +reference_variable: + dim_list ']' { $$ = $1; } + | compound_variable { do_begin_variable_parse(CLS_C); fetch_simple_variable(&$$, &$1, 1 CLS_CC); } +; + + +compound_variable: + VARIABLE { $$ = $1; } + | '$' '{' expr '}' { $$ = $3; } +; + + +dim_list: + dim_list ']' '[' dim_offset { fetch_array_dim(&$$, &$1, &$4 CLS_CC); } + | compound_variable { do_begin_variable_parse(CLS_C); } '[' dim_offset { fetch_array_begin(&$$, &$1, &$4 CLS_CC); } +; + + +dim_offset: + /* empty */ { $$.op_type = IS_UNUSED; } + | expr { $$ = $1; } +; + + +ref_list: + object_property { $$ = $1; } + | ref_list ZEND_OBJECT_OPERATOR { do_push_object(&$1 CLS_CC); } object_property { $$ = $4; } +; + +object_property: + scalar_object_property { znode tmp_znode; do_pop_object(&tmp_znode CLS_CC); do_fetch_property(&$$, &tmp_znode, &$1 CLS_CC); } + | object_dim_list ']' { $$ = $1; } +; + +scalar_object_property: + STRING { $$ = $1; } + | '{' expr '}' { $$ = $2; } + | cvar_without_objects { do_end_variable_parse(BP_VAR_R CLS_CC); $$ = $1; } +; + + +object_dim_list: + object_dim_list ']' '[' expr { fetch_array_dim(&$$, &$1, &$4 CLS_CC); } + | STRING { znode tmp_znode, res; do_pop_object(&tmp_znode CLS_CC); do_fetch_property(&res, &tmp_znode, &$1 CLS_CC); $1 = res; } '[' expr { fetch_array_dim(&$$, &$1, &$4 CLS_CC); } +; + + +simple_indirect_reference: + '$' { $$.u.constant.value.lval = 1; } + | simple_indirect_reference '$' { $$.u.constant.value.lval++; } +; + +assignment_list: + assignment_list ',' assignment_list_element + | assignment_list_element +; + + +assignment_list_element: + w_cvar { do_add_list_element(&$1 CLS_CC); } + | ZEND_LIST '(' { do_new_list_begin(CLS_C); } assignment_list ')' { do_new_list_end(CLS_C); } + | /* empty */ { do_add_list_element(NULL CLS_CC); } +; + + +array_pair_list: + /* empty */ { do_init_array(&$$, NULL, NULL CLS_CC); } + | non_empty_array_pair_list { $$ = $1; } +; + +non_empty_array_pair_list: + non_empty_array_pair_list ',' expr ZEND_DOUBLE_ARROW expr { do_add_array_element(&$$, &$5, &$3 CLS_CC); } + | non_empty_array_pair_list ',' expr { do_add_array_element(&$$, &$3, NULL CLS_CC); } + | expr ZEND_DOUBLE_ARROW expr { do_init_array(&$$, &$3, &$1 CLS_CC); } + | expr { do_init_array(&$$, &$1, NULL CLS_CC); } +; + + +encaps_list: + encaps_list encaps_var { do_end_variable_parse(BP_VAR_R CLS_CC); do_add_variable(&$$, &$1, &$2 CLS_CC); } + | encaps_list STRING { do_add_string(&$$, &$1, &$2 CLS_CC); } + | encaps_list NUM_STRING { do_add_string(&$$, &$1, &$2 CLS_CC); } + | encaps_list ENCAPSED_AND_WHITESPACE { do_add_string(&$$, &$1, &$2 CLS_CC); } + | encaps_list CHARACTER { do_add_char(&$$, &$1, &$2 CLS_CC); } + | encaps_list BAD_CHARACTER { do_add_char(&$$, &$1, &$2 CLS_CC); } + | encaps_list '[' { $2.u.constant.value.chval = '['; do_add_char(&$$, &$1, &$2 CLS_CC); } + | encaps_list ']' { $2.u.constant.value.chval = ']'; do_add_char(&$$, &$1, &$2 CLS_CC); } + | encaps_list '{' { $2.u.constant.value.chval = '{'; do_add_char(&$$, &$1, &$2 CLS_CC); } + | encaps_list '}' { $2.u.constant.value.chval = '}'; do_add_char(&$$, &$1, &$2 CLS_CC); } + | encaps_list ZEND_OBJECT_OPERATOR { znode tmp; $2.u.constant.value.chval = '-'; do_add_char(&tmp, &$1, &$2 CLS_CC); $2.u.constant.value.chval = '>'; do_add_char(&$$, &tmp, &$2 CLS_CC); } + | /* empty */ { do_init_string(&$$); } + +; + + + +encaps_var: + VARIABLE { do_begin_variable_parse(CLS_C); fetch_simple_variable(&$$, &$1, 1 CLS_CC); } + | VARIABLE '[' encaps_var_offset ']' { do_begin_variable_parse(CLS_C); fetch_array_begin(&$$, &$1, &$3 CLS_CC); } + | VARIABLE ZEND_OBJECT_OPERATOR STRING { do_begin_variable_parse(CLS_C); fetch_simple_variable(&$2, &$1, 1 CLS_CC); do_fetch_property(&$$, &$2, &$3 CLS_CC); } + | DOLLAR_OPEN_CURLY_BRACES expr '}' { do_begin_variable_parse(CLS_C); fetch_simple_variable(&$$, &$2, 1 CLS_CC); } + | DOLLAR_OPEN_CURLY_BRACES STRING '[' expr ']' '}' { do_begin_variable_parse(CLS_C); fetch_array_begin(&$$, &$2, &$4 CLS_CC); } + | T_CURLY_OPEN cvar '}' { $$ = $2; } +; + + +encaps_var_offset: + STRING { $$ = $1; } + | NUM_STRING { $$ = $1; } + | { do_begin_variable_parse(CLS_C); } VARIABLE { fetch_simple_variable(&$$, &$2, 1 CLS_CC); } +; + + +internal_functions_in_yacc: + T_ISSET '(' cvar ')' { do_isset_or_isempty(ZEND_ISSET, &$$, &$3 CLS_CC); } + | T_EMPTY '(' cvar ')' { do_isset_or_isempty(ZEND_ISEMPTY, &$$, &$3 CLS_CC); } + | INCLUDE expr { do_include_or_eval(ZEND_INCLUDE, &$$, &$2 CLS_CC); } + | EVAL '(' expr ')' { do_include_or_eval(ZEND_EVAL, &$$, &$3 CLS_CC); } +; + + +%% + diff --git a/Zend/zend-scanner.h b/Zend/zend-scanner.h new file mode 100644 index 0000000000000..e28cf599bfd2e --- /dev/null +++ b/Zend/zend-scanner.h @@ -0,0 +1,29 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _LANGUAGE_SCANNER_H +#define _LANGUAGE_SCANNER_H + +typedef struct { + YY_BUFFER_STATE buffer_state; + int state; + uint return_offset; + uint lineno; + FILE *in; + char *filename; +} zend_lex_state; + +#endif diff --git a/Zend/zend-scanner.l b/Zend/zend-scanner.l new file mode 100644 index 0000000000000..03131240d993c --- /dev/null +++ b/Zend/zend-scanner.l @@ -0,0 +1,1195 @@ +%{ + +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +%} + +%x IN_SCRIPTING +%x DOUBLE_QUOTES +%x SINGLE_QUOTE +%x BACKQUOTE +%x HEREDOC +%x LOOKING_FOR_PROPERTY +%option stack + +%{ + +#if WIN32|WINNT +#include +#endif + +#include + +#include "zend.h" +#include "zend_alloc.h" +#include "zend_compile.h" +#include "zend-scanner.h" +#include "zend_highlight.h" +#include "zend_constants.h" +#include "zend_variables.h" +#include "zend_operators.h" + +#if HAVE_STDARG_H +#include +#endif + +#define YY_DECL int lex_scan(zval *zendlval CLS_DC) +#define ECHO { ZEND_WRITE( yytext, yyleng ); } + +#ifdef __cplusplus +# define MY_INPUT yyinput +#else +# define MY_INPUT input +#endif + + +#ifndef YY_TLS_VARS +/* NOTE, YY_TLS_VARS CANNOT have a semicolon after in + in the code or it will break compilation in msvc5 */ +#define YY_TLS_VARS +#endif + +#ifndef TLS_VARS /* just to make sure ;) */ +#define TLS_VARS +#endif + +#define HANDLE_NEWLINES(s,l) \ +do { \ + char *p = (s),*boundary = p+(l); \ +\ + while(pbuffer_state,&YY_CURRENT_BUFFER,sizeof(YY_BUFFER_STATE)); + lex_state->in = yyin; + lex_state->lineno = CG(zend_lineno); + lex_state->state = YYSTATE; + lex_state->filename = zend_get_compiled_filename(); +} + + +static inline void restore_lexical_state(zend_lex_state *lex_state CLS_DC) +{ + YY_BUFFER_STATE original_buffer_state = YY_CURRENT_BUFFER; + + if (lex_state->buffer_state) { + yy_switch_to_buffer(lex_state->buffer_state); + } else { + YY_CURRENT_BUFFER = NULL; + } + + yy_delete_buffer(original_buffer_state); + yyin = lex_state->in; + CG(zend_lineno) = lex_state->lineno; + BEGIN(lex_state->state); + zend_restore_compiled_filename(lex_state->filename); +} + + +inline int open_file_for_scanning(zend_file_handle *file_handle CLS_DC) +{ + FILE *tmp; + YY_BUFFER_STATE buffer_state = YY_CURRENT_BUFFER; + + switch (file_handle->type) { + case ZEND_HANDLE_FILENAME: + tmp = zend_fopen(file_handle->filename); + break; + case ZEND_HANDLE_FD: + tmp = fdopen(file_handle->handle.fd, "r"); + break; + case ZEND_HANDLE_FP: + tmp = file_handle->handle.fp; + break; + } + if (!tmp) { + return FAILURE; + } + + /* Reset the scanner for scanning the new file */ + yyin = tmp; + yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE)); + CG(zend_lineno) = 1; + BEGIN(INITIAL); + + zend_set_compiled_filename(file_handle->filename); + return SUCCESS; +} + + +zend_op_array *compile_files(int mark_as_ref CLS_DC, int file_count, ...) +{ + zend_lex_state original_lex_state; + zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); + zend_op_array *original_active_op_array = CG(active_op_array); + zend_op_array *retval=NULL; + zend_file_handle *file_handle; + va_list files; + int i; + + va_start(files, file_count); + + init_op_array(op_array, INITIAL_OP_ARRAY_SIZE); + save_lexical_state(&original_lex_state CLS_CC); + + for (i=0; ifilename); + destroy_op_array(op_array); + efree(op_array); + retval = NULL; + break; + } else { + CG(active_op_array) = op_array; + if (zendparse(CLS_C)==1) { + retval = NULL; + break; + } else { + fclose(yyin); + restore_lexical_state(&original_lex_state CLS_CC); + CG(active_op_array) = original_active_op_array; + retval = op_array; + } + } + } + if (retval) { + pass_two(op_array); + if (mark_as_ref) { + pass_include_eval(op_array); + } + } + va_end(files); + return retval; +} + + +zend_op_array *compile_filename(zval *filename CLS_DC) +{ + zend_file_handle file_handle; + zval tmp; + zend_op_array *retval; + + if (filename->type != IS_STRING) { + tmp = *filename; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + filename = &tmp; + } + file_handle.filename = filename->value.str.val; + file_handle.type = ZEND_HANDLE_FILENAME; + retval = compile_files(0 CLS_CC, 1, &file_handle); + if (filename==&tmp) { + zval_dtor(&tmp); + } + return retval; +} + + +static inline int prepare_string_for_scanning(zval *str) +{ + /* enforce two trailing NULLs for flex... */ + str->value.str.val = (char *) erealloc(str->value.str.val,str->value.str.len+2); + str->value.str.val[str->value.str.len+1]=0; + + yyin=NULL; + yy_scan_buffer(str->value.str.val, str->value.str.len+2); + return SUCCESS; +} + + +zend_op_array *compile_string(zval *source_string CLS_DC) +{ + zend_lex_state original_lex_state; + zend_op_array *op_array = (zend_op_array *) emalloc(sizeof(zend_op_array)); + zend_op_array *original_active_op_array = CG(active_op_array); + zend_op_array *retval; + zval tmp; + + tmp = *source_string; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + source_string = &tmp; + + init_op_array(op_array, INITIAL_OP_ARRAY_SIZE); + save_lexical_state(&original_lex_state CLS_CC); + if (prepare_string_for_scanning(source_string)==FAILURE) { + destroy_op_array(op_array); + efree(op_array); + retval = NULL; + } else { + CG(active_op_array) = op_array; + BEGIN(IN_SCRIPTING); + if (zendparse(CLS_C)==1) { + retval = NULL; + } else { + pass_two(op_array); + pass_include_eval(op_array); + restore_lexical_state(&original_lex_state CLS_CC); + CG(active_op_array) = original_active_op_array; + retval = op_array; + } + } + + zval_dtor(&tmp); + + return retval; +} + + +int require_filename(char *filename CLS_DC) +{ + zend_file_handle file_handle; + + file_handle.type = ZEND_HANDLE_FILENAME; + file_handle.filename = filename; + return require_file(&file_handle CLS_CC); +} + + +int require_file(zend_file_handle *file_handle CLS_DC) +{ + zend_lex_state original_lex_state; + + save_lexical_state(&original_lex_state CLS_CC); + if (open_file_for_scanning(file_handle CLS_CC)==FAILURE) { + zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename); + return FAILURE; + } + zendparse(CLS_C); + fclose(yyin); + restore_lexical_state(&original_lex_state CLS_CC); + return SUCCESS; +} + +int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini) +{ + zend_lex_state original_lex_state; + zend_file_handle file_handle; + CLS_FETCH(); + + file_handle.type = ZEND_HANDLE_FILENAME; + file_handle.filename = filename; + save_lexical_state(&original_lex_state CLS_CC); + if (open_file_for_scanning(&file_handle CLS_CC)==FAILURE) { + zend_message_dispatcher(ZMSG_FAILED_HIGHLIGHT_FOPEN, filename); + return FAILURE; + } + zend_highlight(syntax_highlighter_ini); + fclose(yyin); + restore_lexical_state(&original_lex_state CLS_CC); + return SUCCESS; +} + + +int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini) +{ + zend_lex_state original_lex_state; + zval tmp = *str; + CLS_FETCH(); + + str = &tmp; + zval_copy_ctor(str); + save_lexical_state(&original_lex_state CLS_CC); + if (prepare_string_for_scanning(str)==FAILURE) { + return FAILURE; + } + zend_highlight(syntax_highlighter_ini); + restore_lexical_state(&original_lex_state CLS_CC); + zval_dtor(str); + return SUCCESS; +} + + +/* redefine YY_INPUT to handle urls for win32*/ +#if 0 /*WIN32|WINNT*/ +#define YY_INPUT(buf,result,max_size) \ + if ( yyin->_tmpfname != "url" ){ \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + }else{ /* this is a url */ \ + int recv_char=0,socketd=0; \ + /*memset(buf,0,max_size);*/ \ + socketd=yyin->_file; \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + ( (recv_char=recv( socketd,(char *)&c,1,0 ))) >0 && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( recv_char == SOCKET_ERROR ) \ + YY_FATAL_ERROR( "input from url in flex scanner failed" ); \ + result = n; \ + } \ + else if ((result = recv( socketd, (char *)buf, max_size, 0)) == SOCKET_ERROR) \ + YY_FATAL_ERROR( "input from url read in flex scanner failed" ); \ + } +#endif + +%} + +LNUM [0-9]+ +DNUM ([0-9]*[\.][0-9]+)|([0-9]+[\.][0-9]*) +EXPONENT_DNUM (({LNUM}|{DNUM})[eE][+-]?{LNUM}) +HNUM "0x"[0-9a-fA-F]+ +LABEL [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]* +WHITESPACE [ \n\r\t]+ +TABS_AND_SPACES [ \t]* +TOKENS [;:,.\[\]()|^&+-/*=%!~$<>?@] +ENCAPSED_TOKENS [\[\]{}$] +ESCAPED_AND_WHITESPACE [\n\t\r #'.:;,()|^&+-/*=%!~<>?@]+ + +%option noyylineno +%option noyywrap +%% +%{ +TLS_VARS; +%} + +"exit" { + return T_EXIT; +} + +"die" { + return T_EXIT; +} + +"old_function" { + return OLD_FUNCTION; +} + +"function"|"cfunction" { + return FUNCTION; +} + +"const" { + return ZEND_CONST; +} + +"return" { + return RETURN; +} + +"if" { + return IF; +} + +"elseif" { + return ELSEIF; +} + +"endif" { + return ENDIF; +} + +"else" { + return ELSE; +} + +"while" { + return WHILE; +} + +"endwhile" { + return ENDWHILE; +} + +"do" { + return DO; +} + +"for" { + return FOR; +} + +"endfor" { + return ENDFOR; +} + +"foreach" { + return ZEND_FOREACH; +} + +"endforeach" { + return T_ENDFOREACH; +} + +"as" { + return ZEND_AS; +} + +"switch" { + return SWITCH; +} + +"endswitch" { + return ENDSWITCH; +} + +"case" { + return CASE; +} + +"default" { + return DEFAULT; +} + +"break" { + return BREAK; +} + +"continue" { + return CONTINUE; +} + +"echo" { + return ZEND_ECHO; +} + +"print" { + return ZEND_PRINT; +} + +"class" { + return CLASS; +} + +"extends" { + return EXTENDS; +} + +"->" { + yy_push_state(LOOKING_FOR_PROPERTY); + return ZEND_OBJECT_OPERATOR; +} + +{LABEL} { + yy_pop_state(); + zendlval->value.str.val = (char *)estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return STRING; +} + +. { + unput(yytext[0]); + yy_pop_state(); +} + +"::" { + return T_PAAMAYIM_NEKUDOTAYIM; +} + +"new" { + return NEW; +} + +"var" { + return VAR; +} + +"("{TABS_AND_SPACES}("int"|"integer"){TABS_AND_SPACES}")" { + return INT_CAST; +} + +"("{TABS_AND_SPACES}("real"|"double"|"float"){TABS_AND_SPACES}")" { + return DOUBLE_CAST; +} + +"("{TABS_AND_SPACES}"string"{TABS_AND_SPACES}")" { + return STRING_CAST; +} + +"("{TABS_AND_SPACES}"array"{TABS_AND_SPACES}")" { + return ARRAY_CAST; +} + +"("{TABS_AND_SPACES}"object"{TABS_AND_SPACES}")" { + return OBJECT_CAST; +} + +"eval" { + return EVAL; +} + +"include" { + return INCLUDE; +} + +"require" { + return REQUIRE; +} + +"global" { + return ZEND_GLOBAL; +} + +"isset" { + return T_ISSET; +} + +"empty" { + return T_EMPTY; +} + +"static" { + return ZEND_STATIC; +} + +"unset" { + return ZEND_UNSET; +} + +"=>" { + return ZEND_DOUBLE_ARROW; +} + +"list" { + return ZEND_LIST; +} + +"array" { + return ZEND_ARRAY; +} + +"++" { + return INCREMENT; +} + +"--" { + return DECREMENT; +} + +"==" { + return IS_EQUAL; +} + +"!="|"<>" { + return IS_NOT_EQUAL; +} + +"<=" { + return IS_SMALLER_OR_EQUAL; +} + +">=" { + return IS_GREATER_OR_EQUAL; +} + +"+=" { + return PLUS_EQUAL; +} + +"-=" { + return MINUS_EQUAL; +} + +"*=" { + return MUL_EQUAL; +} + +"/=" { + return DIV_EQUAL; +} + +".=" { + return CONCAT_EQUAL; +} + + +"%=" { + return MOD_EQUAL; +} + +"<<=" { + return SHIFT_LEFT_EQUAL; +} + +">>=" { + return SHIFT_RIGHT_EQUAL; +} + +"&=" { + return AND_EQUAL; +} + +"|=" { + return OR_EQUAL; +} + +"^=" { + return XOR_EQUAL; +} + +"||" { + return BOOLEAN_OR; +} + +"&&" { + return BOOLEAN_AND; +} + +"OR" { + return LOGICAL_OR; +} + +"AND" { + return LOGICAL_AND; +} + +"XOR" { + return LOGICAL_XOR; +} + +"<<" { + return SHIFT_LEFT; +} + +">>" { + return SHIFT_RIGHT; +} + +{TOKENS} { + return yytext[0]; +} + + +"{" { + yy_push_state(IN_SCRIPTING); + return '{'; +} + + +"${" { + yy_push_state(IN_SCRIPTING); + return DOLLAR_OPEN_CURLY_BRACES; +} + + +"}" { + yy_pop_state(); + return '}'; +} + + + +{LNUM}|{HNUM} { + errno = 0; + zendlval->value.lval = strtol(yytext, NULL, 0); + if (errno == ERANGE) { /* overflow */ + zendlval->value.dval = strtod(yytext,NULL); + zendlval->type = IS_DOUBLE; + return DNUMBER; + } else { + zendlval->type = IS_LONG; + return LNUMBER; + } +} + +{LNUM}|{HNUM} { /* treat numbers (almost) as strings inside encapsulated strings */ + zendlval->value.str.val = (char *)estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return NUM_STRING; +} + +{DNUM}|{EXPONENT_DNUM} { + zendlval->value.dval = strtod(yytext,NULL); + zendlval->type = IS_DOUBLE; + return DNUMBER; +} + +"__LINE__" { + zendlval->value.lval = CG(zend_lineno); + zendlval->type = IS_LONG; + return ZEND_LINE; +} + +"__FILE__" { + char *filename = zend_get_compiled_filename(); + + zendlval->value.str.len = strlen(filename); + zendlval->value.str.val = estrndup(filename,zendlval->value.str.len); + zendlval->type = IS_STRING; + return ZEND_FILE; +} + + +(([^<]|"<"[^?%s<]){1,400})|"value.str.val = (char *) estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + HANDLE_NEWLINES(yytext,yyleng); + return INLINE_HTML; +} + +"" { + HANDLE_NEWLINES(yytext,yyleng); + if (CG(short_tags) || yyleng>2) { /* yyleng>2 means it's not */ + zendlval->value.str.val = yytext; /* no copying - intentional */ + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + BEGIN(IN_SCRIPTING); + return PHP_OPEN_TAG; + } else { + zendlval->value.str.val = (char *) estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return INLINE_HTML; + } +} + + +"<%=" { + HANDLE_NEWLINES(yytext,yyleng); + if (CG(asp_tags)) { + zendlval->value.str.val = yytext; /* no copying - intentional */ + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + BEGIN(IN_SCRIPTING); + return PHP_OPEN_TAG_WITH_ECHO; + } else { + zendlval->value.str.val = (char *) estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return INLINE_HTML; + } +} + + +"<%" { + HANDLE_NEWLINES(yytext,yyleng); + if (CG(asp_tags)) { + zendlval->value.str.val = yytext; /* no copying - intentional */ + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + BEGIN(IN_SCRIPTING); + } else { + zendlval->value.str.val = (char *) estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return INLINE_HTML; + } +} + + +"value.str.val = yytext; /* no copying - intentional */ + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + HANDLE_NEWLINE(yytext[yyleng-1]); + BEGIN(IN_SCRIPTING); + return PHP_OPEN_TAG; +} + + +""([\n]|"\r\n")? { + zend_message_dispatcher(ZMSG_ENABLE_TRACK_VARS, NULL); + HANDLE_NEWLINE(yytext[yyleng-1]); + return T_PHP_TRACK_VARS; +} + +"$"{LABEL} { + zendlval->value.str.val = (char *)estrndup(yytext+1, yyleng-1); + zendlval->value.str.len = yyleng-1; + zendlval->type = IS_STRING; + return VARIABLE; +} + + +{LABEL} { + zendlval->value.str.val = (char *)estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return STRING; +} + + +{LABEL} { + zendlval->value.str.val = (char *)estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return STRING; +} + + +{WHITESPACE} { + zendlval->value.str.val = yytext; /* no copying - intentional */ + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + HANDLE_NEWLINES(yytext,yyleng); + return T_WHITESPACE; +} + + +([#]|"//")([^\n\r?]|"?"[^>\n\r])*("?\n"|"?\r\n")? { /* eat one line comments */ + HANDLE_NEWLINE(yytext[yyleng-1]); + return ZEND_COMMENT; +} + +"/*"([^*]|"*"[^/])*(("*/")?) { + HANDLE_NEWLINES(yytext, yyleng); + return ZEND_COMMENT; +} + + +("?>"|"")([\n]|"\r\n")? { + zendlval->value.str.val = yytext; /* no copying - intentional */ + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + HANDLE_NEWLINES(yytext, yyleng); + BEGIN(INITIAL); + return PHP_CLOSE_TAG; /* implicit ';' at php-end tag */ +} + + +"%>"([\n]|"\r\n")? { + zendlval->value.str.val = yytext; /* no copying - intentional */ + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + HANDLE_NEWLINES(yytext,yyleng); + if (CG(asp_tags)) { + BEGIN(INITIAL); + return PHP_CLOSE_TAG; /* implicit ';' at php-end tag */ + } else { + return INLINE_HTML; + } +} + + +(["]([^"$\\]|([\\]+[^\\$]))*["])|([']([^'\\]|([\\]+['\\]))*[']) { + 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; + while (s=end) { + continue; + } + switch(*s) { + case 'n': + *t++ = '\n'; + zendlval->value.str.len--; + break; + case 'r': + *t++ = '\r'; + zendlval->value.str.len--; + break; + case 't': + *t++ = '\t'; + zendlval->value.str.len--; + break; + case '\\': + *t++ = '\\'; + zendlval->value.str.len--; + break; + case '$': + case '"': + *t++ = *s; + zendlval->value.str.len--; + break; + default: + *t++ = '\\'; + *t++ = *s; + break; + } + s++; + } else { + *t++ = *s++; + } + } + *t = 0; + + return CONSTANT_ENCAPSED_STRING; +} + + +["] { + BEGIN(DOUBLE_QUOTES); + return '\"'; +} + + +"<<"{LABEL}("\r")?"\n" { + CG(heredoc_len) = yyleng-2-1-(yytext[yyleng-2]=='\r'?1:0); + CG(heredoc) = estrndup(yytext+2, CG(heredoc_len)); + BEGIN(HEREDOC); + return ZEND_HEREDOC; +} + + +[`] { + BEGIN(BACKQUOTE); + return '`'; +} + + +['] { + BEGIN(SINGLE_QUOTE); + return '\''; +} + + +^{LABEL}("\r")?"\n" { + int label_len; + + if (yytext[yyleng-2]=='\r') { + label_len = yyleng-2; + } else { + label_len = yyleng-1; + } + + if (label_len==CG(heredoc_len) && !memcmp(yytext, CG(heredoc), label_len)) { + efree(CG(heredoc)); + CG(heredoc)=NULL; + CG(heredoc_len)=0; + BEGIN(IN_SCRIPTING); + return ZEND_HEREDOC; + } else { + zendlval->value.str.val = (char *)estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return STRING; + } +} + + +{ESCAPED_AND_WHITESPACE} { + HANDLE_NEWLINES(yytext,yyleng); + zendlval->value.str.val = (char *) estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return ENCAPSED_AND_WHITESPACE; +} + +([^'\\]|\\[^'\\])+ { + HANDLE_NEWLINES(yytext,yyleng); + zendlval->value.str.val = (char *) estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return ENCAPSED_AND_WHITESPACE; +} + + +[`]+ { + zendlval->value.str.val = (char *) estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return ENCAPSED_AND_WHITESPACE; +} + + +["]+ { + zendlval->value.str.val = (char *) estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return ENCAPSED_AND_WHITESPACE; +} + + +"$"[^a-zA-Z_\x7f-\xff{] { + zendlval->value.chval = yytext[0]; + if (yyleng == 2) { + unput(yytext[1]); + yytext[1] = 0; + yyleng--; + } + return CHARACTER; +} + + +{ENCAPSED_TOKENS} { + zendlval->value.chval = yytext[0]; + return yytext[0]; +} + +"{$" { + zendlval->value.chval = yytext[0]; + yy_push_state(IN_SCRIPTING); + unput('$'); + return T_CURLY_OPEN; +} + +"\\'" { + zendlval->value.chval='\''; + return CHARACTER; +} + +"\\\\" { + zendlval->value.chval='\\'; + return CHARACTER; +} + +"\\\"" { + zendlval->value.chval='"'; + return CHARACTER; +} + +"\\`" { + zendlval->value.chval='`'; + return CHARACTER; +} + +"\\"[0-7]{1,3} { + zendlval->value.chval = (char) strtol (yytext+1, NULL, 8); + return CHARACTER; +} + +"\\x"[0-9A-Fa-f]{1,2} { + zendlval->value.chval = (char) strtol (yytext+2, NULL, 16); + return CHARACTER; +} + +"\\". { + switch (yytext[1]) { + case 'n': + zendlval->value.chval='\n'; + break; + case 't': + zendlval->value.chval='\t'; + break; + case 'r': + zendlval->value.chval='\r'; + break; + case '\\': + zendlval->value.chval='\\'; + break; + case '$': + zendlval->value.chval=yytext[1]; + break; + case '{': + zendlval->value.chval=yytext[1]; + break; + default: + zendlval->value.str.val = estrndup(yytext,yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return BAD_CHARACTER; + break; + } + return CHARACTER; +} + + +"\\$"|"\\{" { + zendlval->value.chval = yytext[1]; + return CHARACTER; +} + + +["'`]+ { + zendlval->value.str.val = (char *) estrndup(yytext, yyleng); + zendlval->value.str.len = yyleng; + zendlval->type = IS_STRING; + return ENCAPSED_AND_WHITESPACE; +} + + +["] { + BEGIN(IN_SCRIPTING); + return '\"'; +} + + +[`] { + BEGIN(IN_SCRIPTING); + return '`'; +} + + +['] { + BEGIN(IN_SCRIPTING); + return '\''; +} + + +<> { + return 0; +} + + + + +. { + zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d",yytext[0],yytext[0],YYSTATE); +} diff --git a/Zend/zend.c b/Zend/zend.c new file mode 100644 index 0000000000000..7fa2845df7a75 --- /dev/null +++ b/Zend/zend.c @@ -0,0 +1,255 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "zend_operators.h" +#include "zend_variables.h" +#include "zend_extensions.h" +#include "modules.h" +#include "zend_constants.h" +#include "zend_list.h" + +/* true multithread-shared globals */ +zend_class_entry standard_class; +ZEND_API int (*zend_printf)(const char *format, ...); +ZEND_API int (*zend_write)(const char *str, uint str_length); +ZEND_API void (*zend_error)(int type, const char *format, ...); +void (*zend_message_dispatcher)(long message, void *data); +FILE *(*zend_fopen)(const char *filename); +void (*zend_block_interruptions)(); +void (*zend_unblock_interruptions)(); + +zend_utility_values zend_uv; + +/* 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, 1999 Andi Gutmans, Zeev Suraski\n" + + +#define PRINT_PVAL_INDENT 4 + +static void print_hash(HashTable *ht, int indent) +{ + zval **tmp; + char *string_key; + unsigned long num_key; + int i; + + for (i=0; i "); + zend_print_zval_r(*tmp, indent+PRINT_PVAL_INDENT); + ZEND_PUTS("\n"); + zend_hash_move_forward(ht); + } + indent -= PRINT_PVAL_INDENT; + for (i=0; itype != IS_STRING) { + if (expr->type == IS_BOOL) { + if (expr->value.lval) { + expr_copy.value.str.val = estrndup("true",4); + expr_copy.value.str.len = 4; + } else { + expr_copy.value.str.val = estrndup("false",5); + expr_copy.value.str.len = 5; + } + expr_copy.type = IS_STRING; + } else if (expr->type == IS_RESOURCE) { + expr_copy.value.str.val = (char *) emalloc(sizeof("Resource id #")-1 + MAX_LENGTH_OF_LONG); + expr_copy.value.str.len = sprintf(expr_copy.value.str.val, "Resource id #%ld", expr->value.lval); + expr_copy.type = IS_STRING; + } else { + expr_copy = *expr; + zval_copy_ctor(&expr_copy); + convert_to_string(&expr_copy); + } + expr = &expr_copy; + destroy=1; + } + if (expr->value.str.len==0) { /* optimize away empty strings */ + return 0; + } + ZEND_WRITE(expr->value.str.val,expr->value.str.len); + if (destroy) { + zval_dtor(expr); + } + return expr->value.str.len; +} + + +ZEND_API void zend_print_zval_r(zval *expr, int indent) +{ + switch(expr->type) { + case IS_ARRAY: + ZEND_PUTS("Array\n"); + print_hash(expr->value.ht,indent); + break; + case IS_OBJECT: + zend_printf("%s Object\n", expr->value.obj.ce->name); + print_hash(expr->value.obj.properties, indent); + break; + default: + zend_print_variable(expr); + break; + } +} + + +static FILE *zend_fopen_wrapper(const char *filename) +{ + return fopen(filename, "r"); +} + + +static void register_standard_class() +{ + standard_class.type = ZEND_INTERNAL_CLASS; + standard_class.name_length = sizeof("stdClass") - 1; + standard_class.name = zend_strndup("stdClass", standard_class.name_length); + standard_class.parent = NULL; + zend_hash_init(&standard_class.default_properties, 0, NULL, PVAL_PTR_DTOR, 1); + zend_hash_init(&standard_class.function_table, 0, NULL, (void (*)(void *)) destroy_zend_function, 1); + standard_class.handle_function_call = NULL; + standard_class.handle_property_get = NULL; + standard_class.handle_property_set = NULL; + zend_hash_add(CG(class_table), "stdClass", sizeof("stdClass"), &standard_class, sizeof(zend_class_entry), NULL); +} + + +int zend_startup(zend_utility_functions *utility_functions, zend_utility_values *utility_values, char **extensions) +{ + start_memory_manager(); + + /* Set up utility functions and values */ + zend_error = utility_functions->error_function; + zend_printf = utility_functions->printf_function; + zend_write = utility_functions->write_function; + zend_fopen = utility_functions->fopen_function; + if (!zend_fopen) { + zend_fopen = zend_fopen_wrapper; + } + zend_message_dispatcher = utility_functions->message_handler; + zend_block_interruptions = utility_functions->block_interruptions; + zend_unblock_interruptions = utility_functions->unblock_interruptions; + zend_compile_files = compile_files; + zend_execute = execute; + + zend_uv = *utility_values; + zend_llist_init(&zend_extensions, sizeof(zend_extension), (void (*)(void *)) zend_extension_dtor, 1); + + /* set up version */ + zend_version_info = strdup(ZEND_CORE_VERSION_INFO); + zend_version_info_length = sizeof(ZEND_CORE_VERSION_INFO)-1; + + /* Prepare data structures */ + zend_startup_constants(); + CG(function_table) = (HashTable *) malloc(sizeof(HashTable)); + CG(class_table) = (HashTable *) malloc(sizeof(HashTable)); + zend_hash_init(CG(function_table), 100, NULL, (void (*)(void *)) destroy_zend_function, 1); + zend_hash_init(CG(class_table), 10, NULL, (void (*)(void *)) destroy_zend_class, 1); + register_standard_class(); + zend_hash_init(&module_registry, 50, NULL, (void (*)(void *)) module_destructor, 1); + init_resource_plist(); + zend_hash_init(&list_destructors, 50, NULL, NULL, 1); + + return SUCCESS; +} + + +void zend_shutdown() +{ + destroy_resource_plist(); + zend_hash_destroy(&list_destructors); + zend_hash_destroy(&module_registry); + zend_hash_destroy(CG(function_table)); + free(CG(function_table)); + zend_hash_destroy(CG(class_table)); + free(CG(class_table)); + zend_llist_destroy(&zend_extensions); + free(zend_version_info); + zend_shutdown_constants(); +} + + +/* this should be compatible with the standard zenderror */ +void zenderror(char *error) +{ + zend_error(E_PARSE, error); +} + + +ZEND_API void zend_bailout() +{ + ELS_FETCH(); + + longjmp(EG(bailout), FAILURE); +} + + +void zend_append_version_info(zend_extension *extension) +{ + char *new_info; + uint new_info_length; + + new_info_length = sizeof(" with v, by \n") + + strlen(extension->name) + + strlen(extension->version) + + strlen(extension->copyright) + + strlen(extension->author); + + new_info = (char *) malloc(new_info_length+1); + + sprintf(new_info, " with %s v%s, %s, by %s\n", extension->name, extension->version, extension->copyright, extension->author); + + zend_version_info = (char *) realloc(zend_version_info, zend_version_info_length+new_info_length+1); + strcat(zend_version_info, new_info); + zend_version_info_length += new_info_length; + free(new_info); +} + + +ZEND_API char *get_zend_version() +{ + return zend_version_info; +} diff --git a/Zend/zend.h b/Zend/zend.h new file mode 100644 index 0000000000000..a2395a9ec0e96 --- /dev/null +++ b/Zend/zend.h @@ -0,0 +1,205 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _ZEND_H +#define _ZEND_H + +#define ZEND_VERSION "0.80A" + +#include + +/* + * general definitions + */ + +#if WINNT||WIN32 +#include "config.w32.h" +#else +#include "config.h" +#include "config.unix.h" +#endif + +#include "zend_errors.h" +#include "zend_alloc.h" + + +#undef SUCCESS +#undef FAILURE +#define SUCCESS 0 +#define FAILURE -1 /* this MUST stay a negative number, or it may effect functions! */ + + +#include "zend_hash.h" +#include "zend_llist.h" + + +#define INTERNAL_FUNCTION_PARAMETERS HashTable *ht, zval *return_value, HashTable *list, HashTable *plist +#define INTERNAL_FUNCTION_PARAM_PASSTHRU ht, return_value, list, plist + +/* + * zval + */ +typedef struct _zval_struct zval; +typedef struct _zend_class_entry zend_class_entry; + +typedef union { + long lval; /* long value */ + double dval; /* double value */ + struct { + char *val; + int len; + } str; + char chval; /* char value */ + HashTable *ht; /* hash table value */ + struct { + zend_class_entry *ce; + HashTable *properties; + } obj; +} zvalue_value; + + +struct _zval_struct { + /* Variable information */ + zvalue_value value; /* value */ + unsigned char type; /* active type */ + unsigned char is_ref; + short refcount; +}; + + + +typedef struct { + char *fname; + void (*handler)(INTERNAL_FUNCTION_PARAMETERS); + unsigned char *func_arg_types; +} function_entry; + + +typedef struct { + int type; /* read, write or r/w */ + zval **object; + zend_llist elements_list; +} zend_property_reference; + + + +typedef struct { + int type; /* array offset or object proprety */ + zval element; +} zend_overloaded_element; + + +struct _zend_class_entry { + char type; + char *name; + uint name_length; + struct _zend_class_entry *parent; + + HashTable function_table; + HashTable default_properties; + + /* handlers */ + 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); +}; + + + +typedef struct { + void (*error_function)(int type, const char *format, ...); + int (*printf_function)(const char *format, ...); + int (*write_function)(const char *str, uint str_length); + FILE *(*fopen_function)(const char *filename); + void (*message_handler)(long message, void *data); + void (*block_interruptions)(); + void (*unblock_interruptions)(); +} zend_utility_functions; + + +typedef struct { + unsigned char short_tags; + unsigned char asp_tags; +} zend_utility_values; + + +#undef MIN +#undef MAX +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) + +/* data types */ +#define IS_LONG 1 +#define IS_DOUBLE 2 +#define IS_STRING 3 +#define IS_ARRAY 4 +#define IS_OBJECT 5 +#define IS_BC 6 /* for parser internal use only */ +#define IS_BOOL 7 +#define IS_RESOURCE 8 +#define IS_CONSTANT 9 +#define IS_METHOD 10 /* for overloaded function calls */ + +int zend_startup(zend_utility_functions *utility_functions, zend_utility_values *utility_values, char **extensions); +void zend_shutdown(); +ZEND_API void zend_bailout(); +ZEND_API char *get_zend_version(); + +ZEND_API int zend_print_zval(zval *expr, int indent); +ZEND_API void zend_print_zval_r(zval *expr, int indent); + +ZEND_API extern char *empty_string; +ZEND_API extern char *undefined_variable_string; + +#define STR_FREE(ptr) if (ptr && ptr!=empty_string && ptr!=undefined_variable_string) { efree(ptr); } + + +/* output support */ +#define ZEND_WRITE(str, str_len) zend_write((str), (str_len)) +#define ZEND_PUTS(str) zend_write((str), strlen((str))) +#define ZEND_PUTC(c) zend_write(&(c), 1), (c) + +extern ZEND_API int (*zend_printf)(const char *format, ...); +extern ZEND_API int (*zend_write)(const char *str, uint str_length); +extern ZEND_API void (*zend_error)(int type, const char *format, ...); +extern FILE *(*zend_fopen)(const char *filename); +extern void (*zend_message_dispatcher)(long message, void *data); +extern void (*zend_block_interruptions)(); +extern void (*zend_unblock_interruptions)(); + + +void zenderror(char *error); + +extern zend_class_entry standard_class; +extern zend_utility_values zend_uv; + +#define ZEND_UV(name) (zend_uv.name) + + +#define HANDLE_BLOCK_INTERRUPTIONS() if (zend_block_interruptions) { zend_block_interruptions(); } +#define HANDLE_UNBLOCK_INTERRUPTIONS() if (zend_unblock_interruptions) { zend_unblock_interruptions(); } + + + + +/* Messages for applications of Zend */ +#define ZMSG_ENABLE_TRACK_VARS 1L +#define ZMSG_FAILED_INCLUDE_FOPEN 2L +#define ZMSG_FAILED_REQUIRE_FOPEN 3L +#define ZMSG_FAILED_HIGHLIGHT_FOPEN 4L +#define ZMSG_MEMORY_LEAK_DETECTED 5L + +#endif /* _ZEND_H */ diff --git a/Zend/zend.ico b/Zend/zend.ico new file mode 100644 index 0000000000000000000000000000000000000000..80978a6c7eb9797674ed75679fced786ad6f47a3 GIT binary patch literal 1382 zcmbW$F>KmE7>41m6)kkj%9h1ZSG*H3pvo{Yl(2iMgoGk_h{X~QY0Lx?L&l6%WhR!0 zEEUQCQin`dhlmNJsH2sIE!X!p6bIZ zsmI*m;qLnPm(sV__S|aeb4mL0hWi*>aY)$pY?te^b8O$0!zL&1Xc^{tny=={zJ5}g8BNzl!_=s|F!E+bPC}k+j8{_sR`Rc;W+1sO zr5pSbKf#ai0ltH66AgS7U%@;0GM;s(Q~VI$#d~-Mt7if)yzs)Sr44?GpWsLM0N=s4 z*~13Dim%`ud>NnN*Z35_z|ZgrKEaRieY}rv;$6JK8@$0Ayulm%Gj&D1rCw13YAg2{ zevMD@3;YakS5MGmbRX@bn`oEyH~1xff*;`nd~3HXCHKN;WHG(;=H>e1>1+Q~Uxy!zcIzKgRd*KE8=}?N^C6 zc!M{1gEu@6+qGi5ZrQFYwku$}S}iHVukk5Vp7i+msE3CK-QVBq?(R-EH#bU>MAz5X8jr`iyu4Ju-&e2KlkfXFIXO|Y+0^mz Mv0T^H(b1890N*_06aWAK literal 0 HcmV?d00001 diff --git a/Zend/zend_API.c b/Zend/zend_API.c new file mode 100644 index 0000000000000..6ab30724579ea --- /dev/null +++ b/Zend/zend_API.c @@ -0,0 +1,701 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "zend_variables.h" +#include "zend_execute.h" +#include "zend_API.h" +#include "modules.h" +#include "zend_constants.h" +#include "zend_operators.h" + +#if HAVE_STDARG_H +#include +#endif + +/* these variables are true statics/globals, and have to be mutex'ed on every access */ +static int module_count=0; +HashTable list_destructors, module_registry; + +/* this function doesn't check for too many parameters */ +int getParameters(HashTable *ht, int param_count,...) +{ + va_list ptr; + zval **param, **tmp = NULL, *param_ptr; + int i; + + va_start(ptr, param_count); + + for (i = 0; i < param_count; i++) { + param = va_arg(ptr, zval **); + if (zend_hash_index_find(ht, i, (void **) &tmp) == FAILURE) { + va_end(ptr); + return FAILURE; + } + param_ptr = *tmp; + if (!param_ptr->is_ref && param_ptr->refcount>1) { + zval *new_tmp; + + new_tmp = (zval *) emalloc(sizeof(zval)); + *new_tmp = *param_ptr; + zval_copy_ctor(new_tmp); + new_tmp->refcount = 1; + new_tmp->is_ref = 0; + param_ptr = new_tmp; + zend_hash_index_update(ht, i, ¶m_ptr, sizeof(zval *), NULL); + } + *param = param_ptr; + } + va_end(ptr); + return SUCCESS; +} + + +int getParametersArray(HashTable *ht, int param_count, zval **argument_array) +{ + int i; + zval **tmp = NULL, *param_ptr; + + for (i = 0; i < param_count; i++) { + if (zend_hash_index_find(ht, i, (void **) &tmp) == FAILURE) { + return FAILURE; + } + param_ptr = *tmp; + if (!param_ptr->is_ref && param_ptr->refcount>1) { + zval *new_tmp; + + new_tmp = (zval *) emalloc(sizeof(zval)); + *new_tmp = *param_ptr; + zval_copy_ctor(new_tmp); + new_tmp->refcount = 1; + new_tmp->is_ref = 0; + param_ptr = new_tmp; + zend_hash_index_update(ht, i, ¶m_ptr, sizeof(zval *), NULL); + } + argument_array[i] = param_ptr; + } + return SUCCESS; +} + + +int getThis(zval **this) +{ + /* NEEDS TO BE IMPLEMENTED FOR ZEND */ + /* + zval *data; + + if (zend_hash_find(GLOBAL(function_state.calling_symbol_table), "this", sizeof("this"), (void **)&data) == FAILURE) { + return FAILURE; + } + + *this = data; + */ + return SUCCESS; +} + +int ParameterPassedByReference(HashTable *ht, uint n) +{ + zval **tmp; + + if (zend_hash_index_find(ht, n-1, (void **) &tmp) == FAILURE) { + return 0; + } + return (*tmp)->is_ref; +} + + +ZEND_API void wrong_param_count() +{ + zend_error(E_WARNING,"Wrong parameter count for %s()",get_active_function_name()); +} + + +ZEND_API inline int array_init(zval *arg) +{ + arg->value.ht = (HashTable *) emalloc(sizeof(HashTable)); + if (!arg->value.ht || zend_hash_init(arg->value.ht, 0, NULL, PVAL_PTR_DTOR, 0)) { + zend_error(E_CORE_ERROR, "Cannot allocate memory for array"); + return FAILURE; + } + arg->type = IS_ARRAY; + return SUCCESS; +} + + +static void zval_update_const_and_ref(zval **p) +{ + zval_update_constant(*p); + zval_add_ref(p); +} + + + +ZEND_API inline int object_init_ex(zval *arg, zend_class_entry *class_type) +{ + zval *tmp; + + arg->value.obj.properties = (HashTable *) emalloc(sizeof(HashTable)); + zend_hash_init(arg->value.obj.properties, 0, NULL, PVAL_PTR_DTOR, 0); + zend_hash_copy(arg->value.obj.properties, &class_type->default_properties, (void (*)(void *)) zval_update_const_and_ref, (void *) &tmp, sizeof(zval *)); + arg->type = IS_OBJECT; + arg->value.obj.ce = class_type; + return SUCCESS; +} + + +ZEND_API inline int object_init(zval *arg) +{ + return object_init_ex(arg, &standard_class); +} + + +ZEND_API inline int add_assoc_long(zval *arg, char *key, long n) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_LONG; + tmp->value.lval = n; + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL); +} + + +ZEND_API inline int add_assoc_double(zval *arg, char *key, double d) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_DOUBLE; + tmp->value.dval = d; + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL); +} + + +ZEND_API inline int add_assoc_string(zval *arg, char *key, char *str, int duplicate) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_STRING; + tmp->value.str.len = strlen(str); + if (duplicate) { + tmp->value.str.val = estrndup(str,tmp->value.str.len); + } else { + tmp->value.str.val = str; + } + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL); +} + + +ZEND_API inline int add_assoc_stringl(zval *arg, char *key, char *str, uint length, int duplicate) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_STRING; + tmp->value.str.len = length; + if (duplicate) { + tmp->value.str.val = estrndup(str,tmp->value.str.len); + } else { + tmp->value.str.val = str; + } + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL); +} + + +ZEND_API inline int add_assoc_function(zval *arg, char *key,void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)) +{ + zend_error(E_WARNING, "add_assoc_function() is no longer supported"); + return FAILURE; +} + + +ZEND_API inline int add_index_long(zval *arg, uint index, long n) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_LONG; + tmp->value.lval = n; + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),NULL); +} + + +ZEND_API inline int add_index_double(zval *arg, uint index, double d) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_DOUBLE; + tmp->value.dval = d; + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),NULL); +} + + +ZEND_API inline int add_index_string(zval *arg, uint index, char *str, int duplicate) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_STRING; + tmp->value.str.len = strlen(str); + if (duplicate) { + tmp->value.str.val = estrndup(str,tmp->value.str.len); + } else { + tmp->value.str.val = str; + } + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),NULL); +} + + +ZEND_API inline int add_index_stringl(zval *arg, uint index, char *str, uint length, int duplicate) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_STRING; + tmp->value.str.len = length; + if (duplicate) { + tmp->value.str.val = estrndup(str,tmp->value.str.len); + } else { + tmp->value.str.val = str; + } + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),NULL); +} + + +ZEND_API inline int add_next_index_long(zval *arg, long n) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_LONG; + tmp->value.lval = n; + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_next_index_insert(arg->value.ht, &tmp, sizeof(zval *), NULL); +} + + +ZEND_API inline int add_next_index_double(zval *arg, double d) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_DOUBLE; + tmp->value.dval = d; + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_next_index_insert(arg->value.ht, &tmp, sizeof(zval *), NULL); +} + + +ZEND_API inline int add_next_index_string(zval *arg, char *str, int duplicate) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_STRING; + tmp->value.str.len = strlen(str); + if (duplicate) { + tmp->value.str.val = estrndup(str,tmp->value.str.len); + } else { + tmp->value.str.val = str; + } + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_next_index_insert(arg->value.ht, &tmp, sizeof(zval *),NULL); +} + + +ZEND_API inline int add_next_index_stringl(zval *arg, char *str, uint length, int duplicate) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_STRING; + tmp->value.str.len = length; + if (duplicate) { + tmp->value.str.val = estrndup(str,tmp->value.str.len); + } else { + tmp->value.str.val = str; + } + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_next_index_insert(arg->value.ht, &tmp, sizeof(zval *),NULL); +} + + +ZEND_API inline int add_get_assoc_string(zval *arg, char *key, char *str, void **dest, int duplicate) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_STRING; + tmp->value.str.len = strlen(str); + if (duplicate) { + tmp->value.str.val = estrndup(str,tmp->value.str.len); + } else { + tmp->value.str.val = str; + } + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), dest); +} + + +ZEND_API inline int add_get_assoc_stringl(zval *arg, char *key, char *str, uint length, void **dest, int duplicate) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_STRING; + tmp->value.str.len = length; + if (duplicate) { + tmp->value.str.val = estrndup(str,tmp->value.str.len); + } else { + tmp->value.str.val = str; + } + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_update(arg->value.ht, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), dest); +} + + +ZEND_API inline int add_get_index_long(zval *arg, uint index, long l, void **dest) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_LONG; + tmp->value.lval= l; + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),dest); +} + + +ZEND_API inline int add_get_index_double(zval *arg, uint index, double d, void **dest) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_DOUBLE; + tmp->value.dval= d; + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),dest); +} + + +ZEND_API inline int add_get_index_string(zval *arg, uint index, char *str, void **dest, int duplicate) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_STRING; + tmp->value.str.len = strlen(str); + if (duplicate) { + tmp->value.str.val = estrndup(str,tmp->value.str.len); + } else { + tmp->value.str.val = str; + } + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),dest); +} + + +ZEND_API inline int add_get_index_stringl(zval *arg, uint index, char *str, uint length, void **dest, int duplicate) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_STRING; + tmp->value.str.len = length; + if (duplicate) { + tmp->value.str.val = estrndup(str,tmp->value.str.len); + } else { + tmp->value.str.val = str; + } + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_index_update(arg->value.ht, index, (void *) &tmp, sizeof(zval *),dest); +} + + +ZEND_API inline int add_property_long(zval *arg, char *key, long n) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_LONG; + tmp->value.lval = n; + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_update(arg->value.obj.properties, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL); +} + + +ZEND_API inline int add_property_double(zval *arg, char *key, double d) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_DOUBLE; + tmp->value.dval = d; + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_update(arg->value.obj.properties, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL); +} + + +ZEND_API inline int add_property_string(zval *arg, char *key, char *str, int duplicate) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_STRING; + tmp->value.str.len = strlen(str); + if (duplicate) { + tmp->value.str.val = estrndup(str,tmp->value.str.len); + } else { + tmp->value.str.val = str; + } + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_update(arg->value.obj.properties, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL); +} + + +ZEND_API inline int add_property_stringl(zval *arg, char *key, char *str, uint length, int duplicate) +{ + zval *tmp = (zval *) emalloc(sizeof(zval)); + + tmp->type = IS_STRING; + tmp->value.str.len = length; + if (duplicate) { + tmp->value.str.val = estrndup(str,tmp->value.str.len); + } else { + tmp->value.str.val = str; + } + tmp->refcount=1; + tmp->is_ref=0; + return zend_hash_update(arg->value.obj.properties, key, strlen(key)+1, (void *) &tmp, sizeof(zval *), NULL); +} + + +int zend_startup_module(zend_module_entry *module) +{ + if (module) { + module->module_number = zend_next_free_module(); + if (module->module_startup_func) { + if (module->module_startup_func(MODULE_PERSISTENT, module->module_number)==FAILURE) { + zend_error(E_CORE_ERROR,"Unable to start %s module",module->name); + return FAILURE; + } + } + module->type = MODULE_PERSISTENT; + register_module(module); + } + return SUCCESS; +} + + +ZEND_API int _register_list_destructors(void (*list_destructor)(void *), void (*plist_destructor)(void *), int module_number) +{ + list_destructors_entry ld; + +#if 0 + printf("Registering destructors %d for module %d\n", list_destructors.nNextFreeElement, module_number); +#endif + + ld.list_destructor=(void (*)(void *)) list_destructor; + ld.plist_destructor=(void (*)(void *)) plist_destructor; + ld.module_number = module_number; + ld.resource_id = list_destructors.nNextFreeElement; + + if (zend_hash_next_index_insert(&list_destructors,(void *) &ld,sizeof(list_destructors_entry),NULL)==FAILURE) { + return FAILURE; + } + return list_destructors.nNextFreeElement-1; +} + + +/* registers all functions in *library_functions in the function hash */ +int register_functions(function_entry *functions) +{ + function_entry *ptr = functions; + zend_internal_function internal_function; + int count=0,unload=0; + CLS_FETCH(); + + internal_function.type = ZEND_INTERNAL_FUNCTION; + + while (ptr->fname) { + internal_function.handler = ptr->handler; + internal_function.arg_types = ptr->func_arg_types; + internal_function.function_name = ptr->fname; + if (!internal_function.handler) { + zend_error(E_CORE_WARNING,"Null function defined as active function"); + unregister_functions(functions,count); + return FAILURE; + } + if (zend_hash_add(CG(function_table), ptr->fname, strlen(ptr->fname)+1, &internal_function, sizeof(zend_internal_function), NULL) == FAILURE) { + unload=1; + break; + } + ptr++; + count++; + } + if (unload) { /* before unloading, display all remaining bad function in the module */ + while (ptr->fname) { + if (zend_hash_exists(CG(function_table), ptr->fname, strlen(ptr->fname)+1)) { + zend_error(E_CORE_WARNING,"Module load failed - duplicate function name - %s",ptr->fname); + } + ptr++; + } + unregister_functions(functions,count); + return FAILURE; + } + return SUCCESS; +} + +/* count=-1 means erase all functions, otherwise, + * erase the first count functions + */ +void unregister_functions(function_entry *functions,int count) +{ + function_entry *ptr = functions; + int i=0; + CLS_FETCH(); + + while (ptr->fname) { + if (count!=-1 && i>=count) { + break; + } +#if 0 + zend_printf("Unregistering %s()\n",ptr->fname); +#endif + zend_hash_del(CG(function_table),ptr->fname,strlen(ptr->fname)+1); + ptr++; + i++; + } +} + + +int register_module(zend_module_entry *module) +{ +#if 0 + zend_printf("%s: Registering module %d\n",module->name, module->module_number); +#endif + if (register_functions(module->functions)==FAILURE) { + zend_error(E_CORE_WARNING,"%s: Unable to register functions, unable to load",module->name); + return FAILURE; + } + module->module_started=1; + return zend_hash_add(&module_registry, module->name,strlen(module->name)+1,(void *)module,sizeof(zend_module_entry),NULL); +} + + +void module_destructor(zend_module_entry *module) +{ + if (module->type == MODULE_TEMPORARY) { + zend_hash_apply_with_argument(&list_destructors, (int (*)(void *,void *)) clean_module_resource_destructors, (void *) &(module->module_number)); + clean_module_constants(module->module_number); + } + + if (module->request_started && module->request_shutdown_func) { +#if 0 + zend_printf("%s: Request shutdown\n",module->name); +#endif + module->request_shutdown_func(); + } + module->request_started=0; + if (module->module_started && module->module_shutdown_func) { +#if 0 + zend_printf("%s: Module shutdown\n",module->name); +#endif + module->module_shutdown_func(); + } + module->module_started=0; + unregister_functions(module->functions,-1); + +#if HAVE_LIBDL + if (module->handle) { + dlclose(module->handle); + } +#endif +} + + +/* call request startup for all modules */ +int module_registry_request_startup(zend_module_entry *module) +{ + if (!module->request_started && module->request_startup_func) { +#if 0 + zend_printf("%s: Request startup\n",module->name); +#endif + module->request_startup_func(module->type, module->module_number); + } + module->request_started=1; + return 0; +} + + +/* for persistent modules - call request shutdown and flag NOT to erase + * for temporary modules - do nothing, and flag to erase + */ +int module_registry_cleanup(zend_module_entry *module) +{ + switch(module->type) { + case MODULE_PERSISTENT: + if (module->request_started && module->request_shutdown_func) { +#if 0 + zend_printf("%s: Request shutdown\n",module->name); +#endif + module->request_shutdown_func(); + } + module->request_started=0; + return 0; + break; + case MODULE_TEMPORARY: + return 1; + break; + } + return 0; +} + + +/* return the next free module number */ +int zend_next_free_module(void) +{ + return ++module_count; +} + + +zend_class_entry *register_internal_class(zend_class_entry *class_entry) +{ + zend_class_entry *register_class; + char *lowercase_name = zend_strndup(class_entry->name, class_entry->name_length); + CLS_FETCH(); + + zend_str_tolower(lowercase_name, class_entry->name_length); + + class_entry->type = ZEND_INTERNAL_CLASS; + class_entry->parent = NULL; + zend_hash_init(&class_entry->default_properties, 0, NULL, PVAL_PTR_DTOR, 1); + zend_hash_init(&class_entry->function_table, 0, NULL, (void (*)(void *)) destroy_zend_function, 1); + + zend_hash_update(CG(class_table), lowercase_name, class_entry->name_length+1, class_entry, sizeof(zend_class_entry), (void **) ®ister_class); + free(lowercase_name); + return register_class; +} diff --git a/Zend/zend_API.h b/Zend/zend_API.h new file mode 100644 index 0000000000000..2c95d0a41b8cc --- /dev/null +++ b/Zend/zend_API.h @@ -0,0 +1,92 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _ZEND_API_H +#define _ZEND_API_H + +#include "modules.h" +#include "zend_list.h" + + +int zend_next_free_module(void); + +int getParameters(HashTable *ht, int param_count,...); +int getParametersArray(HashTable *ht, int param_count, zval **argument_array); +int getThis(zval **this); +int ParameterPassedByReference(HashTable *ht, uint n); +int register_functions(function_entry *functions); +void unregister_functions(function_entry *functions, int count); +int register_module(zend_module_entry *module_entry); +zend_class_entry *register_internal_class(zend_class_entry *class_entry); + +ZEND_API void wrong_param_count(void); + +#define WRONG_PARAM_COUNT { wrong_param_count(); return; } +#define WRONG_PARAM_COUNT_WITH_RETVAL(ret) { wrong_param_count(); return ret; } +#define ARG_COUNT(ht) (ht->nNextFreeElement) + +#define BYREF_NONE 0 +#define BYREF_FORCE 1 +#define BYREF_ALLOW 2 + +#if !MSVC5 +#define DLEXPORT +#endif + +int zend_startup_module(zend_module_entry *module); + +ZEND_API int array_init(zval *arg); +ZEND_API int object_init(zval *arg); +ZEND_API int object_init_ex(zval *arg, zend_class_entry *ce); +ZEND_API int add_assoc_long(zval *arg, char *key, long n); +ZEND_API int add_assoc_double(zval *arg, char *key, double d); +ZEND_API int add_assoc_string(zval *arg, char *key, char *str, int duplicate); +ZEND_API int add_assoc_stringl(zval *arg, char *key, char *str, uint length, int duplicate); +ZEND_API int add_assoc_function(zval *arg, char *key,void (*function_ptr)(INTERNAL_FUNCTION_PARAMETERS)); +ZEND_API int add_index_long(zval *arg, uint idx, long n); +ZEND_API int add_index_double(zval *arg, uint idx, double d); +ZEND_API int add_index_string(zval *arg, uint idx, char *str, int duplicate); +ZEND_API int add_index_stringl(zval *arg, uint idx, char *str, uint length, int duplicate); +ZEND_API int add_next_index_long(zval *arg, long n); +ZEND_API int add_next_index_double(zval *arg, double d); +ZEND_API int add_next_index_string(zval *arg, char *str, int duplicate); +ZEND_API int add_next_index_stringl(zval *arg, char *str, uint length, int duplicate); + +ZEND_API int add_get_assoc_string(zval *arg, char *key, char *str, void **dest, int duplicate); +ZEND_API int add_get_assoc_stringl(zval *arg, char *key, char *str, uint length, void **dest, int duplicate); +ZEND_API int add_get_index_long(zval *arg, uint idx, long l, void **dest); +ZEND_API int add_get_index_double(zval *arg, uint idx, double d, void **dest); +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 call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval, int param_count, zval *params[]); + + +ZEND_API int add_property_long(zval *arg, char *key, long l); +ZEND_API int add_property_double(zval *arg, char *key, double d); +ZEND_API int add_property_string(zval *arg, char *key, char *str, int duplicate); +ZEND_API int add_property_stringl(zval *arg, char *key, char *str, uint length, int duplicate); + +#define add_method(arg,key,method) add_assoc_function((arg),(key),(method)) + +#endif /* _ZEND_API_H */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c new file mode 100644 index 0000000000000..0336982a0717c --- /dev/null +++ b/Zend/zend_alloc.c @@ -0,0 +1,498 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include + +#include "zend.h" +#include "zend_alloc.h" +#include "zend_globals.h" + +#ifndef ZTS +static zend_alloc_globals alloc_globals; +#endif + + +#if ZEND_DEBUG +# define END_MAGIC_SIZE sizeof(long) +# define END_ALIGNMENT(size) (((size)%PLATFORM_ALIGNMENT)?(PLATFORM_ALIGNMENT-((size)%PLATFORM_ALIGNMENT)):0) +#else +# define END_MAGIC_SIZE 0 +# define END_ALIGNMENT(size) 0 +#endif + + +# if MEMORY_LIMIT +# if ZEND_DEBUG +#define CHECK_MEMORY_LIMIT(s) _CHECK_MEMORY_LIMIT(s,filename,lineno) +# else +#define CHECK_MEMORY_LIMIT(s) _CHECK_MEMORY_LIMIT(s,NULL,0) +# endif + +#define _CHECK_MEMORY_LIMIT(s,file,lineno) { AG(allocated_memory) += (s);\ + if (php3_ini.memory_limitpersistent && p==AG(head)) { \ + AG(head) = p->pNext; \ + } else if (p->persistent && p==AG(phead)) { \ + AG(phead) = p->pNext; \ + } else { \ + p->pLast->pNext = p->pNext; \ + } \ + if (p->pNext) { \ + p->pNext->pLast = p->pLast; \ + } + +#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->pLast = (mem_header *) NULL; + + +/* used by ISAPI and NSAPI */ + +#if ZEND_DEBUG +ZEND_API void *_emalloc(size_t size, char *filename, uint lineno) +#else +ZEND_API void *_emalloc(size_t size) +#endif +{ + mem_header *p; + + HANDLE_BLOCK_INTERRUPTIONS(); + + if ((size < MAX_CACHED_MEMORY) && (AG(cache_count)[size] > 0)) { + p = AG(cache)[size][--AG(cache_count)[size]]; +#if ZEND_DEBUG + p->filename = filename; + p->lineno = lineno; + p->magic = MEM_BLOCK_START_MAGIC; +#endif + HANDLE_UNBLOCK_INTERRUPTIONS(); + p->persistent = 0; + p->cached = 0; + return (void *)((char *)p + sizeof(mem_header) + PLATFORM_PADDING); + } else { + p = (mem_header *) malloc(sizeof(mem_header) + size + PLATFORM_PADDING + END_ALIGNMENT(size) + END_MAGIC_SIZE); + } + + if (!p) { + fprintf(stderr,"FATAL: emalloc(): Unable to allocate %d bytes\n", size); + exit(1); + HANDLE_UNBLOCK_INTERRUPTIONS(); + return (void *)p; + } + p->persistent = p->cached = 0; + ADD_POINTER_TO_LIST(p); + p->size = size; +#if ZEND_DEBUG + p->filename = filename; + p->lineno = lineno; + p->magic = MEM_BLOCK_START_MAGIC; + *((long *)(((char *) p) + sizeof(mem_header)+size+PLATFORM_PADDING+END_ALIGNMENT(size))) = MEM_BLOCK_END_MAGIC; +#endif +#if MEMORY_LIMIT + CHECK_MEMORY_LIMIT(size); +#endif + HANDLE_UNBLOCK_INTERRUPTIONS(); + return (void *)((char *)p + sizeof(mem_header) + PLATFORM_PADDING); +} + + +#if ZEND_DEBUG +ZEND_API void _efree(void *ptr, char *filename, uint lineno) +#else +ZEND_API void _efree(void *ptr) +#endif +{ + mem_header *p = (mem_header *) ((char *)ptr - sizeof(mem_header) - PLATFORM_PADDING); + +#if ZEND_DEBUG + _mem_block_check(ptr, 1, filename, lineno); + memset(ptr, 0x5a, p->size); +#endif + + if (!p->persistent && (p->size < MAX_CACHED_MEMORY) && (AG(cache_count)[p->size] < MAX_CACHED_ENTRIES)) { + AG(cache)[p->size][AG(cache_count)[p->size]++] = p; + p->cached = 1; +#if ZEND_DEBUG + p->magic = MEM_BLOCK_CACHED_MAGIC; +#endif + return; + } + HANDLE_BLOCK_INTERRUPTIONS(); + REMOVE_POINTER_FROM_LIST(p); + +#if MEMORY_LIMIT + AG(allocated_memory) -= p->size; +#endif + + free(p); + HANDLE_UNBLOCK_INTERRUPTIONS(); +} + + +#if ZEND_DEBUG +ZEND_API void *_ecalloc(size_t nmemb, size_t size, char *filename, uint lineno) +#else +ZEND_API void *_ecalloc(size_t nmemb, size_t size) +#endif +{ + void *p; + int final_size=size*nmemb; + + HANDLE_BLOCK_INTERRUPTIONS(); +#if ZEND_DEBUG + p = _emalloc(final_size,filename,lineno); +#else + p = emalloc(final_size); +#endif + if (!p) { + HANDLE_UNBLOCK_INTERRUPTIONS(); + return (void *) p; + } + memset(p,(int)NULL,final_size); + HANDLE_UNBLOCK_INTERRUPTIONS(); + return p; +} + + +#if ZEND_DEBUG +ZEND_API void *_erealloc(void *ptr, size_t size, char *filename, uint lineno) +#else +ZEND_API void *_erealloc(void *ptr, size_t size) +#endif +{ + mem_header *p = (mem_header *) ((char *)ptr-sizeof(mem_header)-PLATFORM_PADDING); + mem_header *orig = p; + + if (!ptr) { +#if ZEND_DEBUG + return _emalloc(size, filename, lineno); +#else + return emalloc(size); +#endif + } + HANDLE_BLOCK_INTERRUPTIONS(); + REMOVE_POINTER_FROM_LIST(p); + p = (mem_header *) realloc(p,sizeof(mem_header)+size+PLATFORM_PADDING+END_ALIGNMENT(size)+END_MAGIC_SIZE); + if (!p) { + fprintf(stderr,"FATAL: erealloc(): Unable to allocate %d bytes\n", size); + HANDLE_UNBLOCK_INTERRUPTIONS(); + zend_bailout(); + ADD_POINTER_TO_LIST(orig); + return (void *)NULL; + } + ADD_POINTER_TO_LIST(p); +#if ZEND_DEBUG + p->filename = filename; + p->lineno = lineno; + p->magic = MEM_BLOCK_START_MAGIC; + *((long *)(((char *) p) + sizeof(mem_header)+size+PLATFORM_PADDING+END_ALIGNMENT(size))) = MEM_BLOCK_END_MAGIC; +#endif +#if MEMORY_LIMIT + CHECK_MEMORY_LIMIT(size - p->size); +#endif + p->size = size; + + HANDLE_UNBLOCK_INTERRUPTIONS(); + return (void *)((char *)p+sizeof(mem_header)+PLATFORM_PADDING); +} + + +#if ZEND_DEBUG +ZEND_API char *_estrdup(const char *s, char *filename, uint lineno) +#else +ZEND_API char *_estrdup(const char *s) +#endif +{ + int length; + char *p; + + length = strlen(s)+1; + HANDLE_BLOCK_INTERRUPTIONS(); +#if ZEND_DEBUG + p = (char *) _emalloc(length,filename,lineno); +#else + p = (char *) emalloc(length); +#endif + if (!p) { + HANDLE_UNBLOCK_INTERRUPTIONS(); + return (char *)NULL; + } + HANDLE_UNBLOCK_INTERRUPTIONS(); + memcpy(p,s,length); + return p; +} + + +#if ZEND_DEBUG +ZEND_API char *_estrndup(const char *s, uint length, char *filename, uint lineno) +#else +ZEND_API char *_estrndup(const char *s, uint length) +#endif +{ + char *p; + + HANDLE_BLOCK_INTERRUPTIONS(); +#if ZEND_DEBUG + p = (char *) _emalloc(length+1,filename,lineno); +#else + p = (char *) emalloc(length+1); +#endif + if (!p) { + HANDLE_UNBLOCK_INTERRUPTIONS(); + return (char *)NULL; + } + HANDLE_UNBLOCK_INTERRUPTIONS(); + memcpy(p,s,length); + p[length]=0; + return p; +} + + +ZEND_API char *zend_strndup(const char *s, uint length) +{ + char *p; + + p = (char *) malloc(length+1); + if (!p) { + return (char *)NULL; + } + if (length) { + memcpy(p,s,length); + } + p[length]=0; + return p; +} + + +ZEND_API void start_memory_manager(void) +{ + AG(phead) = AG(head) = NULL; + +#if MEMORY_LIMIT + AG(allocated_memory)=0; + AG(memory_exhausted)=0; +#endif + + memset(AG(cache_count),0,MAX_CACHED_MEMORY*sizeof(unsigned char)); +} + + +ZEND_API void shutdown_memory_manager(int silent, int clean_cache) +{ + mem_header *p, *t; + + p=AG(head); + t=AG(head); + while (t) { + if (!t->cached || clean_cache) { +#if ZEND_DEBUG + if (!t->cached) { + /* does not use zend_error() *intentionally* */ + if (!silent) { + zend_message_dispatcher(ZMSG_MEMORY_LEAK_DETECTED, t); + } + } +#endif + p = t->pNext; + REMOVE_POINTER_FROM_LIST(t); + free(t); + t = p; + } else { + t = t->pNext; + } + } +} + + +#if ZEND_DEBUG +ZEND_API int _mem_block_check(void *ptr, int silent, char *filename, int lineno) +{ + mem_header *p = (mem_header *) ((char *)ptr - sizeof(mem_header) - PLATFORM_PADDING); + int no_cache_notice=0; + int valid_beginning=1; + int had_problems=0; + + if (silent==2) { + silent=1; + no_cache_notice=1; + } + if (silent==3) { + silent=0; + no_cache_notice=1; + } + if (!silent) { + fprintf(stderr,"---------------------------------------\n"); + fprintf(stderr,"Block 0x%0.8lX status at %s:%d:\n", (long) p, filename, lineno); + fprintf(stderr,"%10s\t","Beginning: "); + } + + switch (p->magic) { + case MEM_BLOCK_START_MAGIC: + if (!silent) { + fprintf(stderr, "OK (allocated on %s:%d, %d bytes)\n", p->filename, p->lineno, p->size); + } + break; /* ok */ + case MEM_BLOCK_FREED_MAGIC: + if (!silent) { + fprintf(stderr,"Freed\n"); + had_problems=1; + } else { + return _mem_block_check(ptr, 0, filename, lineno); + } + break; + case MEM_BLOCK_CACHED_MAGIC: + if (!silent) { + if (!no_cache_notice) { + fprintf(stderr,"Cached (allocated on %s:%d, %d bytes)\n", p->filename, p->lineno, p->size); + had_problems=1; + } + } else { + if (!no_cache_notice) { + return _mem_block_check(ptr, 0, filename, lineno); + } + } + break; + default: + if (!silent) { + fprintf(stderr,"Overrun (magic=0x%0.8lX, expected=0x%0.8lX)\n", p->magic, MEM_BLOCK_START_MAGIC); + } else { + return _mem_block_check(ptr, 0, filename, lineno); + } + had_problems=1; + valid_beginning=0; + break; + } + + + if (valid_beginning + && *((long *)(((char *) p)+sizeof(mem_header)+p->size+PLATFORM_PADDING+END_ALIGNMENT(p->size))) != MEM_BLOCK_END_MAGIC) { + long magic_num = MEM_BLOCK_END_MAGIC; + char *overflow_ptr, *magic_ptr=(char *) &magic_num; + int overflows=0; + int i; + + if (silent) { + return _mem_block_check(ptr, 0, filename, lineno); + } + had_problems=1; + overflow_ptr = ((char *) p)+sizeof(mem_header)+p->size+PLATFORM_PADDING; + + for (i=0; isize+PLATFORM_PADDING+END_ALIGNMENT(p->size))), MEM_BLOCK_END_MAGIC); + fprintf(stderr,"%10s\t",""); + if (overflows>=sizeof(long)) { + fprintf(stderr, "At least %d bytes overflown\n", sizeof(long)); + } else { + fprintf(stderr, "%d byte(s) overflown\n", overflows); + } + } else if (!silent) { + fprintf(stderr,"%10s\t", "End:"); + if (valid_beginning) { + fprintf(stderr,"OK\n"); + } else { + fprintf(stderr,"Unknown\n"); + } + } + + if (!silent) { + fprintf(stderr,"---------------------------------------\n"); + } + return ((!had_problems) ? 1 : 0); +} + + +ZEND_API void _full_mem_check(int silent, char *filename, uint lineno) +{ + mem_header *p = AG(head); + int errors=0; + + fprintf(stderr,"------------------------------------------------\n"); + fprintf(stderr,"Full Memory Check at %s:%d\n", filename, lineno); + + while (p) { + if (!_mem_block_check((void *)((char *)p + sizeof(mem_header) + PLATFORM_PADDING), (silent?2:3), filename, lineno)) { + errors++; + } + p = p->pNext; + } + fprintf(stderr,"End of full memory check %s:%d (%d errors)\n", filename, lineno, errors); + fprintf(stderr,"------------------------------------------------\n"); +} +#endif + + +#if ZEND_DEBUG +ZEND_API void _persist_alloc(void *ptr, char *filename, uint lineno) +#else +ZEND_API void _persist_alloc(void *ptr) +#endif +{ + mem_header *p = (mem_header *) ((char *)ptr-sizeof(mem_header)-PLATFORM_PADDING); + +#if ZEND_DEBUG + _mem_block_check(ptr, 1, filename, lineno); +#endif + + /* 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); +} + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h new file mode 100644 index 0000000000000..0caddae81fdf8 --- /dev/null +++ b/Zend/zend_alloc.h @@ -0,0 +1,117 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _ALLOC_H +#define _ALLOC_H + +#include + +#define MEM_BLOCK_START_MAGIC 0x7312F8DCL +#define MEM_BLOCK_END_MAGIC 0x2A8FCC84L +#define MEM_BLOCK_FREED_MAGIC 0x99954317L +#define MEM_BLOCK_CACHED_MAGIC 0xFB8277DCL + +typedef struct _mem_header { +#if ZEND_DEBUG + long magic; + char *filename; + uint lineno; +#endif + struct _mem_header *pNext; + struct _mem_header *pLast; + unsigned int size:30; + unsigned int persistent:1; + unsigned int cached:1; +} mem_header; + +typedef union { + void *ptr; + double dbl; + long lng; +} align_test; + +#define MAX_CACHED_MEMORY 64 +#define MAX_CACHED_ENTRIES 16 + +#define PLATFORM_ALIGNMENT (sizeof(align_test)) +#define PLATFORM_PADDING (((PLATFORM_ALIGNMENT-sizeof(mem_header))%PLATFORM_ALIGNMENT+PLATFORM_ALIGNMENT)%PLATFORM_ALIGNMENT) + +ZEND_API char *zend_strndup(const char *s, unsigned int length); + +#if ZEND_DEBUG +ZEND_API void *_emalloc(size_t size,char *filename,uint lineno); +ZEND_API void _efree(void *ptr,char *filename,uint lineno); +ZEND_API void *_ecalloc(size_t nmemb, size_t size,char *filename,uint lineno); +ZEND_API void *_erealloc(void *ptr, size_t size,char *filename,uint lineno); +ZEND_API char *_estrdup(const char *s,char *filename,uint lineno); +ZEND_API char *_estrndup(const char *s, unsigned int length,char *filename,uint lineno); +ZEND_API void _persist_alloc(void *ptr, char *filename, uint lineno); +#define emalloc(size) _emalloc((size),__FILE__,__LINE__) +#define efree(ptr) _efree((ptr),__FILE__,__LINE__) +#define ecalloc(nmemb,size) _ecalloc((nmemb),(size),__FILE__,__LINE__) +#define erealloc(ptr,size) _erealloc((ptr),(size),__FILE__,__LINE__) +#define estrdup(s) _estrdup((s),__FILE__,__LINE__) +#define estrndup(s,length) _estrndup((s),(length),__FILE__,__LINE__) +#define persist_alloc(p) _persist_alloc((p),__FILE__,__LINE__) +#else +ZEND_API void *_emalloc(size_t size); +ZEND_API void _efree(void *ptr); +ZEND_API void *_ecalloc(size_t nmemb, size_t size); +ZEND_API void *_erealloc(void *ptr, size_t size); +ZEND_API char *_estrdup(const char *s); +ZEND_API char *_estrndup(const char *s, unsigned int length); +ZEND_API void _persist_alloc(void *ptr); +#define emalloc(size) _emalloc((size)) +#define efree(ptr) _efree((ptr)) +#define ecalloc(nmemb,size) _ecalloc((nmemb),(size)) +#define erealloc(ptr,size) _erealloc((ptr),(size)) +#define estrdup(s) _estrdup((s)) +#define estrndup(s,length) _estrndup((s),(length)) +#define persist_alloc(p) _persist_alloc((p)) +#endif + +#define pemalloc(size,persistent) ((persistent)?malloc(size):emalloc(size)) +#define pefree(ptr,persistent) ((persistent)?free(ptr):efree(ptr)) +#define pecalloc(nmemb,size,persistent) ((persistent)?calloc((nmemb),(size)):ecalloc((nmemb),(size))) +#define perealloc(ptr,size,persistent) ((persistent)?realloc((ptr),(size)):erealloc((ptr),(size))) +#define pestrdup(s,persistent) ((persistent)?strdup(s):estrdup(s)) + +#define safe_estrdup(ptr) ((ptr)?(estrdup(ptr)):(empty_string)) +#define safe_estrndup(ptr,len) ((ptr)?(estrndup((ptr),(len))):(empty_string)) + +ZEND_API void start_memory_manager(void); +ZEND_API void shutdown_memory_manager(int silent, int clean_cache); + +#if ZEND_DEBUG +ZEND_API int _mem_block_check(void *ptr, int silent, char *filename, int lineno); +ZEND_API void _full_mem_check(int silent, char *filename, uint lineno); +#define mem_block_check(ptr, silent) _mem_block_check(ptr, silent, __FILE__, __LINE__) +#define mem_block_check(ptr, silent) _mem_block_check(ptr, silent, __FILE__, __LINE__) +#define full_mem_check(silent) _full_mem_check(silent, __FILE__, __LINE__) +#else +#define mem_block_check(type, ptr, silent) +#define full_mem_check(silent) +#endif + + +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c new file mode 100644 index 0000000000000..f666adeea7240 --- /dev/null +++ b/Zend/zend_compile.c @@ -0,0 +1,1822 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "zend_compile.h" +#include "zend_llist.h" +#include "zend_API.h" +#include "zend_variables.h" +#include "zend_operators.h" + + +zend_op_array *(*zend_compile_files)(int mark_as_ref CLS_DC, int file_count, ...); + + +#ifndef ZTS +ZEND_API zend_compiler_globals compiler_globals; +ZEND_API zend_executor_globals executor_globals; +#endif + + +#define SET_UNUSED(op) (op).op_type = IS_UNUSED + +static int is_not_internal_function(zend_function *function) +{ + return(function->type != ZEND_INTERNAL_FUNCTION); +} + + +static int is_not_internal_class(zend_class_entry *ce) +{ + return(ce->type != ZEND_INTERNAL_CLASS); +} + + +static void free_filename(void *p) +{ + efree(*((char **) p)); +} + + +void init_compiler(CLS_D ELS_DC) +{ + zend_stack_init(&CG(bp_stack)); + zend_stack_init(&CG(function_call_stack)); + zend_stack_init(&CG(switch_cond_stack)); + zend_stack_init(&CG(object_stack)); + CG(active_class_entry) = NULL; + zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0); + zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0); + zend_llist_init(&CG(filenames_list), sizeof(char *), free_filename, 0); + CG(short_tags) = ZEND_UV(short_tags); + CG(asp_tags) = ZEND_UV(asp_tags); + CG(handle_op_arrays) = 1; + zend_hash_apply(&module_registry, (int (*)(void *)) module_registry_request_startup); + init_resource_list(); +} + + +void shutdown_compiler(CLS_D) +{ + zend_stack_destroy(&CG(bp_stack)); + zend_stack_destroy(&CG(function_call_stack)); + zend_stack_destroy(&CG(switch_cond_stack)); + zend_stack_destroy(&CG(object_stack)); + zend_llist_destroy(&CG(filenames_list)); + zend_hash_apply(CG(function_table), (int (*)(void *)) is_not_internal_function); + zend_hash_apply(CG(class_table), (int (*)(void *)) is_not_internal_class); + destroy_resource_list(); + zend_hash_apply(&module_registry, (int (*)(void *)) module_registry_cleanup); +} + + +ZEND_API void zend_set_compiled_filename(char *new_compiled_filename) +{ + char *p = estrdup(new_compiled_filename); + CLS_FETCH(); + + zend_llist_add_element(&CG(filenames_list), &p); + CG(compiled_filename) = p; +} + + +ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename) +{ + CLS_FETCH(); + + CG(compiled_filename) = original_compiled_filename; +} + +ZEND_API char *zend_get_compiled_filename() +{ + CLS_FETCH(); + + return CG(compiled_filename); +} + + +static int get_temporary_variable(zend_op_array *op_array) +{ + return (op_array->T)++; +} + + +void do_binary_op(int op, znode *result, znode *op1, znode *op2 CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = op; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *op1; + opline->op2 = *op2; + *result = opline->result; +} + + +void do_unary_op(int op, znode *result, znode *op1 CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = op; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *op1; + *result = opline->result; + SET_UNUSED(opline->op2); +} + + +void do_binary_assign_op(int op, znode *result, znode *op1, znode *op2 CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = op; + 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 = *op1; + opline->op2 = *op2; + *result = opline->result; +} + + +void fetch_simple_variable(znode *result, znode *varname, int bp CLS_DC) +{ + int next_op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + zend_llist *fetch_list_ptr; + + 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; + *result = opline->result; + SET_UNUSED(opline->op2); + opline->op2.u.constant.value.lval = ZEND_FETCH_LOCAL; + + if (bp) { + zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); + zend_llist_add_element(fetch_list_ptr, &next_op_number); + } +} + + +void fetch_array_begin(znode *result, znode *varname, znode *first_dim CLS_DC) +{ + fetch_simple_variable(result, varname, 1 CLS_CC); + + fetch_array_dim(result, result, first_dim CLS_CC); +} + + +void fetch_array_dim(znode *result, znode *parent, znode *dim CLS_DC) +{ + int next_op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + zend_llist *fetch_list_ptr; + + opline->opcode = ZEND_FETCH_DIM_W; /* the backpatching routine assumes W */ + 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 = *parent; + opline->op2 = *dim; + *result = opline->result; + + zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); + zend_llist_add_element(fetch_list_ptr, &next_op_number); +} + + +void do_print(znode *result, znode *arg CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->opcode = ZEND_PRINT_OP; + opline->op1 = *arg; + SET_UNUSED(opline->op2); + *result = opline->result; +} + + +void do_echo(znode *arg CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_ECHO_OP; + opline->op1 = *arg; + SET_UNUSED(opline->op2); +} + + +void do_assign(znode *result, znode *variable, znode *value CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_ASSIGN; + 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 = *variable; + opline->op2 = *value; + *result = opline->result; +} + + +void do_assign_ref(znode *result, znode *lvar, znode *rvar CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_ASSIGN_REF; + if (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; + } else { + SET_UNUSED(opline->result); + } + opline->op1 = *lvar; + opline->op2 = *rvar; +} + + +static inline void do_begin_loop(CLS_D) +{ + zend_brk_cont_element *brk_cont_element; + int parent; + + parent = CG(active_op_array)->current_brk_cont; + CG(active_op_array)->current_brk_cont = CG(active_op_array)->last_brk_cont; + brk_cont_element = get_next_brk_cont_element(CG(active_op_array)); + brk_cont_element->parent = parent; +} + + +static inline void do_end_loop(int cont_addr CLS_DC) +{ + CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = cont_addr; + CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array)); + CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent; +} + + +void do_while_cond(znode *expr, znode *close_bracket_token CLS_DC) +{ + int while_cond_op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_JMPZ; + opline->op1 = *expr; + close_bracket_token->u.opline_num = while_cond_op_number; + SET_UNUSED(opline->op2); + + do_begin_loop(CLS_C); + INC_BPC(CG(active_op_array)); +} + + +void do_while_end(znode *while_token, znode *close_bracket_token CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + /* add unconditional jump */ + opline->opcode = ZEND_JMP; + opline->op1.u.opline_num = while_token->u.opline_num; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + + /* update while's conditional jmp */ + CG(active_op_array)->opcodes[close_bracket_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); + + do_end_loop(while_token->u.opline_num CLS_CC); + + DEC_BPC(CG(active_op_array)); +} + + +void do_for_cond(znode *expr, znode *second_semicolon_token CLS_DC) +{ + int for_cond_op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_JMPZNZ; + opline->result = *expr; /* the conditional expression */ + second_semicolon_token->u.opline_num = for_cond_op_number; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); +} + + +void do_for_before_statement(znode *cond_start, znode *second_semicolon_token CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_JMP; + opline->op1.u.opline_num = cond_start->u.opline_num; + CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].op1.u.opline_num = get_next_op_number(CG(active_op_array)); + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + + do_begin_loop(CLS_C); + + INC_BPC(CG(active_op_array)); +} + + +void do_for_end(znode *second_semicolon_token CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_JMP; + opline->op1.u.opline_num = second_semicolon_token->u.opline_num+1; + CG(active_op_array)->opcodes[second_semicolon_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + + do_end_loop(second_semicolon_token->u.opline_num+1 CLS_CC); + + DEC_BPC(CG(active_op_array)); +} + + +void do_pre_incdec(znode *result, znode *op1, int op CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = op; + 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 = *op1; + *result = opline->result; + SET_UNUSED(opline->op2); +} + + +void do_post_incdec(znode *result, znode *op1, int op CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = op; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *op1; + *result = opline->result; + SET_UNUSED(opline->op2); +} + + +void do_if_cond(znode *cond, znode *closing_bracket_token CLS_DC) +{ + int if_cond_op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_JMPZ; + opline->op1 = *cond; + closing_bracket_token->u.opline_num = if_cond_op_number; + SET_UNUSED(opline->op2); + INC_BPC(CG(active_op_array)); +} + + +void do_if_after_statement(znode *closing_bracket_token, unsigned char initialize CLS_DC) +{ + int if_end_op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + zend_llist *jmp_list_ptr; + + opline->opcode = ZEND_JMP; + /* save for backpatching */ + if (initialize) { + zend_llist jmp_list; + + zend_llist_init(&jmp_list, sizeof(int), NULL, 0); + zend_stack_push(&CG(bp_stack), (void *) &jmp_list, sizeof(zend_llist)); + } + zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr); + zend_llist_add_element(jmp_list_ptr, &if_end_op_number); + + CG(active_op_array)->opcodes[closing_bracket_token->u.opline_num].op2.u.opline_num = if_end_op_number+1; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); +} + + +void do_if_end(CLS_D) +{ + int next_op_number = get_next_op_number(CG(active_op_array)); + zend_llist *jmp_list_ptr; + zend_llist_element *le; + + zend_stack_top(&CG(bp_stack), (void **) &jmp_list_ptr); + for (le=jmp_list_ptr->head; le; le = le->next) { + CG(active_op_array)->opcodes[*((int *) le->data)].op1.u.opline_num = next_op_number; + } + zend_llist_destroy(jmp_list_ptr); + zend_stack_del_top(&CG(bp_stack)); + DEC_BPC(CG(active_op_array)); +} + + +void do_begin_variable_parse(CLS_D) +{ + zend_llist fetch_list; + + zend_llist_init(&fetch_list, sizeof(int), NULL, 0); + zend_stack_push(&CG(bp_stack), (void *) &fetch_list, sizeof(zend_llist)); +} + + +void do_end_variable_parse(int type CLS_DC) +{ + zend_llist *fetch_list_ptr; + zend_llist_element *le; + zend_op *opline; + + zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); + + le = fetch_list_ptr->head; + + while (le) { + opline = &CG(active_op_array)->opcodes[*((int *) le->data)]; + switch (type) { + case BP_VAR_R: + if (opline->opcode == ZEND_FETCH_DIM_W && opline->op2.op_type == IS_UNUSED) { + zend_error(E_COMPILE_ERROR, "Cannot use [] for reading"); + } + opline->opcode -= 3; + break; + case BP_VAR_W: + break; + case BP_VAR_RW: + opline->opcode += 3; + break; + case BP_VAR_IS: + opline->opcode += 6; /* 3+3 */ + } + le = le->next; + } + zend_llist_destroy(fetch_list_ptr); + zend_stack_del_top(&CG(bp_stack)); +} + + +void do_init_string(znode *result) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_INIT_STRING; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + *result = opline->result; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); +} + + +void do_add_char(znode *result, znode *op1, znode *op2 CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_ADD_CHAR; + opline->op1 = *op1; + opline->op2 = *op2; + opline->op2.op_type = IS_CONST; + opline->result = opline->op1; + *result = opline->result; +} + + +void do_add_string(znode *result, znode *op1, znode *op2 CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_ADD_STRING; + opline->op1 = *op1; + opline->op2 = *op2; + opline->op2.op_type = IS_CONST; + opline->result = opline->op1; + *result = opline->result; +} + + +void do_add_variable(znode *result, znode *op1, znode *op2 CLS_DC) +{ + zend_op *opline; + + if (op1->op_type == IS_CONST) { + opline = get_next_op(CG(active_op_array) CLS_CC); + opline->opcode = ZEND_INIT_STRING; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + *result = opline->result; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + + if (op1->u.constant.value.str.len>0) { + opline = get_next_op(CG(active_op_array) CLS_CC); + opline->opcode = ZEND_ADD_STRING; + opline->result = *result; + opline->op1 = *result; + opline->op2 = *op1; + opline->result = opline->op1; + } else { + zval_dtor(&op1->u.constant); + } + } else { + *result = *op1; + } + + opline = get_next_op(CG(active_op_array) CLS_CC); + opline->opcode = ZEND_ADD_VAR; + opline->result = *result; + opline->op1 = *result; + opline->op2 = *op2; + *result = opline->result; +} + + +void do_free(znode *op1 CLS_DC) +{ + if (op1->op_type==IS_TMP_VAR) { + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_FREE; + opline->op1 = *op1; + SET_UNUSED(opline->op2); + } else if (op1->op_type==IS_VAR) { + zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; + + if (opline->result.op_type == op1->op_type + && opline->result.u.var == op1->u.var) { + opline->result.u.EA.type |= EXT_TYPE_UNUSED; + } else { + + /* This should be an object instanciation + * Find JMP_NO_CTOR, mark the preceding ASSIGN and the + * proceeding INIT_FCALL_BY_NAME as unused + */ + while (opline>CG(active_op_array)->opcodes) { + if (opline->opcode == ZEND_JMP_NO_CTOR) { + (opline-1)->result.u.EA.type |= EXT_TYPE_UNUSED; + (opline+1)->op1.u.EA.type |= EXT_TYPE_UNUSED; + break; + } + opline--; + } + } + } +} + + +void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method CLS_DC) +{ + zend_op_array op_array; + char *name = function_name->u.constant.value.str.val; + int name_len = function_name->u.constant.value.str.len; + int function_begin_line = function_token->u.opline_num; + + function_token->u.op_array = CG(active_op_array); + zend_str_tolower(name, name_len); + + init_op_array(&op_array, INITIAL_OP_ARRAY_SIZE); + op_array.function_name = name; + op_array.arg_types = NULL; + + 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)); + } else { + zend_hash_add(CG(function_table), name, name_len+1, &op_array, sizeof(zend_op_array), (void **) &CG(active_op_array)); + } + + if (CG(extended_info)) { + zend_op *opline = get_next_op(CG(active_op_array)); + + opline->opcode = ZEND_EXT_NOP; + opline->lineno = function_begin_line; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + } +} + + +void do_end_function_declaration(znode *function_token CLS_DC) +{ + pass_two(CG(active_op_array)); + CG(active_op_array) = function_token->u.op_array; +} + + +void do_receive_arg(int op, znode *var, znode *offset, znode *initialization, unsigned char pass_type CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = op; + opline->result = *var; + opline->op1 = *offset; + if (initialization) { + opline->op2 = *initialization; + } else { + SET_UNUSED(opline->op2); + } + if (pass_type==BYREF_FORCE && !CG(active_op_array)->arg_types) { + int i; + + CG(active_op_array)->arg_types = (unsigned char *) emalloc(sizeof(unsigned char)*(offset->u.constant.value.lval+2)); + for (i=1; i<=offset->u.constant.value.lval; i++) { + CG(active_op_array)->arg_types[i] = BYREF_NONE; + } + CG(active_op_array)->arg_types[0]=(unsigned char) offset->u.constant.value.lval; + } + if (CG(active_op_array)->arg_types) { + CG(active_op_array)->arg_types = (unsigned char *) erealloc(CG(active_op_array)->arg_types, sizeof(unsigned char)*(offset->u.constant.value.lval+2)); + CG(active_op_array)->arg_types[offset->u.constant.value.lval+1] = pass_type; + CG(active_op_array)->arg_types[0]++; + } +} + + +void do_begin_function_call(znode *function_name CLS_DC) +{ + zend_op *opline ; + zend_function *function; + + zend_str_tolower(function_name->u.constant.value.str.val, function_name->u.constant.value.str.len); + if (zend_hash_find(CG(function_table), function_name->u.constant.value.str.val,function_name->u.constant.value.str.len+1, (void **) &function)==FAILURE) { + znode tmp = *function_name; + + zval_copy_ctor(&tmp.u.constant); + do_begin_dynamic_function_call(&tmp CLS_CC); + return; + } + + opline = get_next_op(CG(active_op_array) CLS_CC); + + switch (function->type) { + case ZEND_USER_FUNCTION: { + zend_op_array *op_array = (zend_op_array *) function; + + zend_stack_push(&CG(function_call_stack), (void *) &op_array->arg_types, sizeof(unsigned char *)); + } + break; + case ZEND_INTERNAL_FUNCTION: { + zend_internal_function *internal_function = (zend_internal_function *) function; + + zend_stack_push(&CG(function_call_stack), (void *) &internal_function->arg_types, sizeof(unsigned char *)); + } + break; + } + + opline->opcode = ZEND_INIT_FCALL; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); +} + + +void do_begin_dynamic_function_call(znode *function_name CLS_DC) +{ + unsigned char *ptr = NULL; + int last_op_number = get_next_op_number(CG(active_op_array))-1; + + if (CG(active_op_array)->opcodes[last_op_number].opcode == ZEND_FETCH_OBJ_R) { + CG(active_op_array)->opcodes[last_op_number].opcode = ZEND_INIT_FCALL_BY_NAME; + } else { + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_INIT_FCALL_BY_NAME; + opline->op2 = *function_name; + SET_UNUSED(opline->op1); + } + zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *)); +} + + +void do_begin_class_member_function_call(znode *class_name, znode *function_name CLS_DC) +{ + unsigned char *ptr = NULL; + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_INIT_FCALL_BY_NAME; + zend_str_tolower(class_name->u.constant.value.str.val, class_name->u.constant.value.str.len); + opline->op1 = *class_name; + opline->op2 = *function_name; + zval_copy_ctor(&opline->op2.u.constant); + zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *)); +} + + +void do_end_function_call(znode *function_name, znode *result, int is_method CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + ELS_FETCH(); + + opline->opcode = ZEND_DO_FCALL; + opline->op1 = *function_name; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->result.op_type = IS_TMP_VAR; + *result = opline->result; + SET_UNUSED(opline->op2); + opline->op2.u.constant.value.lval = is_method; + zend_stack_del_top(&CG(function_call_stack)); +} + + +void do_pass_param(znode *param, int op, int offset CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + unsigned char **arg_types_ptr, *arg_types; + int original_op=op; + + zend_stack_top(&CG(function_call_stack), (void **) &arg_types_ptr); + arg_types = *arg_types_ptr; + + if (op == ZEND_SEND_VAL) { + switch (param->op_type) { + case IS_CONST: /* constants behave like variables when passed to functions, + * as far as reference counting is concerned. Treat them + * as if they were variables here. + */ + case IS_VAR: + op = ZEND_SEND_VAR; + break; + } + } + if (arg_types && offsetop_type) { + case IS_VAR: + op = ZEND_SEND_REF; + break; + default: + zend_error(E_COMPILE_ERROR, "Only variables can be passed by reference"); + break; + } + } + + if (original_op==ZEND_SEND_VAR) { + switch(op) { + case ZEND_SEND_VAR: + do_end_variable_parse(BP_VAR_R CLS_CC); + break; + case ZEND_SEND_REF: + do_end_variable_parse(BP_VAR_W CLS_CC); + break; + } + } + + opline->opcode = op; + opline->op1 = *param; + opline->op2.u.opline_num = offset; + SET_UNUSED(opline->op2); +} + + +void do_return(znode *expr CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_RETURN; + if (expr) { + opline->op1 = *expr; + } else { + var_uninit(&opline->op1.u.constant); + opline->op1.op_type = IS_CONST; + opline->op1.u.constant.refcount=1; + opline->op1.u.constant.is_ref=0; + } + SET_UNUSED(opline->op2); +} + + +void do_boolean_or_begin(znode *expr1, znode *op_token CLS_DC) +{ + int next_op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_JMPNZ_EX; + if (expr1->op_type == IS_TMP_VAR) { + opline->result = *expr1; + } else { + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->result.op_type = IS_TMP_VAR; + } + opline->op1 = *expr1; + SET_UNUSED(opline->op2); + + op_token->u.opline_num = next_op_number; + + *expr1 = opline->result; +} + + +void do_boolean_or_end(znode *result, znode *expr1, znode *expr2, znode *op_token CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + *result = *expr1; /* we saved the original result in expr1 */ + opline->opcode = ZEND_BOOL; + opline->result = *result; + opline->op1 = *expr2; + SET_UNUSED(opline->op2); + + CG(active_op_array)->opcodes[op_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); +} + + +void do_boolean_and_begin(znode *expr1, znode *op_token CLS_DC) +{ + int next_op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_JMPZ_EX; + if (expr1->op_type == IS_TMP_VAR) { + opline->result = *expr1; + } else { + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->result.op_type = IS_TMP_VAR; + } + opline->op1 = *expr1; + SET_UNUSED(opline->op2); + + op_token->u.opline_num = next_op_number; + + *expr1 = opline->result; +} + + +void do_boolean_and_end(znode *result, znode *expr1, znode *expr2, znode *op_token CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + *result = *expr1; /* we saved the original result in expr1 */ + opline->opcode = ZEND_BOOL; + opline->result = *result; + opline->op1 = *expr2; + SET_UNUSED(opline->op2); + + CG(active_op_array)->opcodes[op_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); +} + + +void do_do_while_begin(CLS_D) +{ + do_begin_loop(CLS_C); + INC_BPC(CG(active_op_array)); +} + + +void do_do_while_end(znode *do_token, znode *expr CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_JMPNZ; + opline->op1 = *expr; + opline->op2.u.opline_num = do_token->u.opline_num; + + do_end_loop(do_token->u.opline_num CLS_CC); + + DEC_BPC(CG(active_op_array)); +} + + +void do_brk_cont(int op, znode *expr CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = op; + opline->op1.u.opline_num = CG(active_op_array)->current_brk_cont; + SET_UNUSED(opline->op1); + if (expr) { + opline->op2 = *expr; + } else { + opline->op2.u.constant.type = IS_LONG; + opline->op2.u.constant.value.lval = 1; + opline->op2.u.constant.refcount=1; + opline->op2.u.constant.is_ref=0; + opline->op2.op_type = IS_CONST; + } +} + + +void do_switch_cond(znode *cond CLS_DC) +{ + zend_switch_entry switch_entry; + + switch_entry.cond = *cond; + switch_entry.default_case = -1; + switch_entry.control_var = -1; + zend_stack_push(&CG(switch_cond_stack), (void *) &switch_entry, sizeof(switch_entry)); + + do_begin_loop(CLS_C); + + INC_BPC(CG(active_op_array)); +} + + + +void do_switch_end(znode *case_list CLS_DC) +{ + zend_op *opline; + zend_switch_entry *switch_entry_ptr; + + zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr); + + if (case_list->u.opline_num != -1) { /* empty switch */ + int next_op_number = get_next_op_number(CG(active_op_array)); + + CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number; + } + + /* add code to jmp to default case */ + if (switch_entry_ptr->default_case != -1) { + opline = get_next_op(CG(active_op_array) CLS_CC); + opline->opcode = ZEND_JMPZ; + opline->op1.op_type = IS_TMP_VAR; + opline->op1.u.var = switch_entry_ptr->control_var; + opline->op2.u.opline_num = switch_entry_ptr->default_case; + SET_UNUSED(opline->op2); + } + + + /* remember break/continue loop information */ + CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].brk = get_next_op_number(CG(active_op_array)); + CG(active_op_array)->current_brk_cont = CG(active_op_array)->brk_cont_array[CG(active_op_array)->current_brk_cont].parent; + + /* emit free for the switch condition*/ + do_free(&switch_entry_ptr->cond CLS_CC); + if (switch_entry_ptr->cond.op_type == IS_CONST) { + zval_dtor(&switch_entry_ptr->cond.u.constant); + } + + zend_stack_del_top(&CG(switch_cond_stack)); + + DEC_BPC(CG(active_op_array)); +} + + +void do_case_before_statement(znode *case_list, znode *case_token, znode *case_expr CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + int next_op_number; + zend_switch_entry *switch_entry_ptr; + znode result; + + zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr); + + opline->opcode = ZEND_CASE; + if (switch_entry_ptr->control_var==-1) { + switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array)); + } + opline->result.u.var = switch_entry_ptr->control_var; + opline->result.op_type = IS_TMP_VAR; + opline->op1 = switch_entry_ptr->cond; + opline->op2 = *case_expr; + if (opline->op1.op_type == IS_CONST) { + zval_copy_ctor(&opline->op1.u.constant); + } + result = opline->result; + + next_op_number = get_next_op_number(CG(active_op_array)); + opline = get_next_op(CG(active_op_array) CLS_CC); + opline->opcode = ZEND_JMPZ; + opline->op1 = result; + SET_UNUSED(opline->op2); + case_token->u.opline_num = next_op_number; + + if (case_list->u.opline_num==-1) { + return; + } + next_op_number = get_next_op_number(CG(active_op_array)); + CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number; +} + + +void do_case_after_statement(znode *result, znode *case_token CLS_DC) +{ + int next_op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_JMP; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + result->u.opline_num = next_op_number; + + switch (CG(active_op_array)->opcodes[case_token->u.opline_num].opcode) { + case ZEND_JMP: + CG(active_op_array)->opcodes[case_token->u.opline_num].op1.u.opline_num = get_next_op_number(CG(active_op_array)); + break; + case ZEND_JMPZ: + CG(active_op_array)->opcodes[case_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); + break; + } +} + + + +void do_default_before_statement(znode *case_list, znode *default_token CLS_DC) +{ + int next_op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + zend_switch_entry *switch_entry_ptr; + + zend_stack_top(&CG(switch_cond_stack), (void **) &switch_entry_ptr); + + opline->opcode = ZEND_JMP; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + default_token->u.opline_num = next_op_number; + + next_op_number = get_next_op_number(CG(active_op_array)); + opline = get_next_op(CG(active_op_array) CLS_CC); + opline->opcode = ZEND_BOOL; + if (switch_entry_ptr->control_var==-1) { + switch_entry_ptr->control_var = get_temporary_variable(CG(active_op_array)); + } + opline->result.u.var = switch_entry_ptr->control_var; + opline->result.op_type = IS_TMP_VAR; + opline->op1.op_type = IS_CONST; + opline->op1.u.constant.type = IS_LONG; + opline->op1.u.constant.value.lval = 1; + opline->op1.u.constant.refcount=1; + opline->op1.u.constant.is_ref=0; + SET_UNUSED(opline->op2); + switch_entry_ptr->default_case = next_op_number; + + next_op_number = get_next_op_number(CG(active_op_array)); + if (case_list->u.opline_num==-1) { + return; + } + CG(active_op_array)->opcodes[case_list->u.opline_num].op1.u.opline_num = next_op_number; +} + +static void function_add_ref(zend_function *function) +{ + if (function->type == ZEND_USER_FUNCTION) { + (*((zend_op_array *) function)->refcount)++; + } +} + + +void do_begin_class_declaration(znode *class_name, znode *parent_class_name CLS_DC) +{ + if (CG(active_class_entry)) { + zend_error(E_COMPILE_ERROR, "Class declarations may not be nested"); + return; + } + CG(class_entry).type = ZEND_USER_CLASS; + CG(class_entry).name = class_name->u.constant.value.str.val; + CG(class_entry).name_length = class_name->u.constant.value.str.len; + + zend_str_tolower(CG(class_entry).name, CG(class_entry).name_length); + + zend_hash_init(&CG(class_entry).function_table, 10, NULL, (void (*)(void *)) destroy_zend_function, 0); + zend_hash_init(&CG(class_entry).default_properties, 10, NULL, PVAL_PTR_DTOR, 0); + + /* code for inheritance from parent class */ + if (parent_class_name) { + zend_class_entry *parent_class; + zend_function tmp_zend_function; + zval *tmp; + + if (zend_hash_find(CG(class_table), parent_class_name->u.constant.value.str.val, parent_class_name->u.constant.value.str.len+1, (void **) &parent_class)==FAILURE) { + zend_error(E_ERROR, "Undefined parent class '%s'", parent_class_name->u.constant.value.str.val); + return; + } + /* copy functions */ + zend_hash_copy(&CG(class_entry).function_table, &parent_class->function_table, (void (*)(void *)) function_add_ref, &tmp_zend_function, sizeof(zend_function)); + + /* copy default properties */ + zend_hash_copy(&CG(class_entry).default_properties, &parent_class->default_properties, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *)); + + zval_dtor(&parent_class_name->u.constant); + } else { + CG(class_entry).parent = NULL; + } + + CG(class_entry).handle_function_call = NULL; + CG(class_entry).handle_property_set = NULL; + CG(class_entry).handle_property_get = NULL; + + zend_hash_add(CG(class_table), CG(class_entry).name, CG(class_entry).name_length+1, &CG(class_entry), sizeof(zend_class_entry), (void **) &CG(active_class_entry)); +} + + +void do_end_class_declaration(CLS_D) +{ + CG(active_class_entry) = NULL; +} + + +void do_declare_property(znode *var_name, znode *value CLS_DC) +{ + if (value) { + zval *property = (zval *) emalloc(sizeof(zval)); + + *property = value->u.constant; + 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); + } + FREE_PNODE(var_name); +} + + +void do_fetch_property(znode *result, znode *object, znode *property CLS_DC) +{ + int next_op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + zend_llist *fetch_list_ptr; + + opline->opcode = ZEND_FETCH_OBJ_W; /* the backpatching routine assumes W */ + 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 = *object; + opline->op2 = *property; + *result = opline->result; + + zend_stack_top(&CG(bp_stack), (void **) &fetch_list_ptr); + zend_llist_add_element(fetch_list_ptr, &next_op_number); +} + + +void do_push_object(znode *object CLS_DC) +{ + zend_stack_push(&CG(object_stack), object, sizeof(znode)); +} + + +void do_pop_object(znode *object CLS_DC) +{ + znode *tmp; + + zend_stack_top(&CG(object_stack), (void **) &tmp); + *object = *tmp; + zend_stack_del_top(&CG(object_stack)); +} + + +void do_begin_new_object(znode *result, znode *variable, znode *new_token, znode *class_name CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + unsigned char *ptr = NULL; + + opline->opcode = ZEND_NEW; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *class_name; + SET_UNUSED(opline->op2); + + do_assign(result, variable, &opline->result CLS_CC); + + new_token->u.opline_num = get_next_op_number(CG(active_op_array)); + opline = get_next_op(CG(active_op_array) CLS_CC); + opline->opcode = ZEND_JMP_NO_CTOR; + opline->op1 = *result; + SET_UNUSED(opline->op2); + + if (class_name->op_type == IS_CONST) { + zval_copy_ctor(&class_name->u.constant); + } + opline = get_next_op(CG(active_op_array) CLS_CC); + opline->opcode = ZEND_INIT_FCALL_BY_NAME; + opline->op1 = *result; + opline->op2 = *class_name; + zend_stack_push(&CG(function_call_stack), (void *) &ptr, sizeof(unsigned char *)); +} + + +void do_end_new_object(znode *class_name, znode *new_token CLS_DC) +{ + znode ctor_result; + + if (class_name->op_type == IS_CONST) { + zval_copy_ctor(&class_name->u.constant); + } + do_end_function_call(class_name, &ctor_result, 1 CLS_CC); + do_free(&ctor_result CLS_CC); + + CG(active_op_array)->opcodes[new_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); +} + + +void do_fetch_constant(znode *result, znode *constant_name, int mode CLS_DC) +{ + switch (mode) { + case ZEND_CT: + *result = *constant_name; + result->u.constant.type = IS_CONSTANT; + printf("Fetching compiletime constant: '%s'\n", result->u.constant.value.str.val); + break; + case ZEND_RT: { + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_FETCH_CONSTANT; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *constant_name; + *result = opline->result; + SET_UNUSED(opline->op2); + } + break; + } +} + + +void do_shell_exec(znode *result, znode *cmd CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_INIT_FCALL; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + + opline = get_next_op(CG(active_op_array) CLS_CC); + switch (cmd->op_type) { + case IS_TMP_VAR: + opline->opcode = ZEND_SEND_VAL; + break; + default: + opline->opcode = ZEND_SEND_VAR; + break; + } + opline->op1 = *cmd; + opline->op2.u.opline_num = 0; + SET_UNUSED(opline->op2); + + opline = get_next_op(CG(active_op_array) CLS_CC); + opline->opcode = ZEND_DO_FCALL; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->result.op_type = IS_TMP_VAR; + opline->op1.u.constant.value.str.val = estrndup("shell_exec",sizeof("shell_exec")-1); + opline->op1.u.constant.value.str.len = sizeof("shell_exec")-1; + opline->op1.u.constant.refcount = 1; + opline->op1.u.constant.is_ref = 0; + opline->op1.u.constant.type = IS_STRING; + opline->op1.op_type = IS_CONST; + SET_UNUSED(opline->op2); + *result = opline->result; +} + + + +void do_init_array(znode *result, znode *expr, znode *offset CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_INIT_ARRAY; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->result.op_type = IS_TMP_VAR; + *result = opline->result; + if (expr) { + opline->op1 = *expr; + if (offset) { + opline->op2 = *offset; + } else { + SET_UNUSED(opline->op2); + } + } else { + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + } +} + + +void do_add_array_element(znode *result, znode *expr, znode *offset CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_ADD_ARRAY_ELEMENT; + opline->result = *result; + opline->op1 = *expr; + if (offset) { + opline->op2 = *offset; + } else { + SET_UNUSED(opline->op2); + } +} + + + +void do_add_static_array_element(znode *result, znode *expr, znode *offset) +{ + zval *element = (zval *) emalloc(sizeof(zval)); + + *element = expr->u.constant; + if (offset) { + switch (offset->u.constant.type) { + case IS_STRING: + zend_hash_update(result->u.constant.value.ht, offset->u.constant.value.str.val, offset->u.constant.value.str.len+1, &element, sizeof(zval *), NULL); + break; + case IS_LONG: + zend_hash_index_update(result->u.constant.value.ht, offset->u.constant.value.lval, &element, sizeof(zval *), NULL); + break; + } + } else { + zend_hash_next_index_insert(result->u.constant.value.ht, &element, sizeof(zval *), NULL); + } +} + + +void do_add_list_element(znode *element CLS_DC) +{ + list_llist_element lle; + + if(element) { + lle.var = *element; + zend_llist_copy(&lle.dimensions, &CG(dimension_llist)); + zend_llist_add_element(&CG(list_llist), &lle); + } + (*((int *)CG(dimension_llist).tail->data))++; +} + + +void do_new_list_begin(CLS_D) +{ + int current_dimension = 0; + zend_llist_add_element(&CG(dimension_llist), ¤t_dimension); +} + + +void do_new_list_end(CLS_D) +{ + + zend_llist_remove_tail(&CG(dimension_llist)); + (*((int *)CG(dimension_llist).tail->data))++; +} + + +void do_list_init(CLS_D) +{ + zend_llist_init(&CG(list_llist), sizeof(list_llist_element), NULL, 0); + zend_llist_init(&CG(dimension_llist), sizeof(int), NULL, 0); + do_new_list_begin(CLS_C); +} + + +void do_list_end(znode *result, znode *expr CLS_DC) +{ + zend_llist_element *le; + zend_llist_element *dimension; + zend_op *opline; + znode last_container; + + le = CG(list_llist).head; + while (le) { + zend_llist *tmp_dimension_llist = &((list_llist_element *)le->data)->dimensions; + dimension = tmp_dimension_llist->head; + while (dimension) { + opline = get_next_op(CG(active_op_array) CLS_CC); + if (dimension == tmp_dimension_llist->head) { /* first */ + last_container = *expr; + switch(expr->op_type) { + case IS_VAR: + opline->opcode = ZEND_FETCH_DIM_R; + break; + case IS_TMP_VAR: + case IS_CONST: /* fetch_dim_tmp_var will handle this bogus fetch */ + opline->opcode = ZEND_FETCH_DIM_TMP_VAR; + break; + } + } else { + opline->opcode = ZEND_FETCH_DIM_R; + } + 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 = last_container; + opline->op2.op_type = IS_CONST; + opline->op2.u.constant.type = IS_LONG; + opline->op2.u.constant.value.lval = *((int *) dimension->data); + opline->op2.u.constant.refcount = 1; + opline->op2.u.constant.is_ref = 0; + last_container = opline->result; + dimension = dimension->next; + } + ((list_llist_element *) le->data)->value = last_container; + zend_llist_destroy(&((list_llist_element *) le->data)->dimensions); + le = le->next; + } + + le = CG(list_llist).head; + while (le) { + do_assign(result, &((list_llist_element *) le->data)->var, &((list_llist_element *) le->data)->value CLS_CC); + le = le->next; + } + zend_llist_destroy(&CG(dimension_llist)); + zend_llist_destroy(&CG(list_llist)); + *result = *expr; +} + + +void do_fetch_global_or_static_variable(znode *varname, znode *static_assignment, int fetch_type CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + znode lval; + + if (fetch_type==ZEND_FETCH_STATIC) { + zval *tmp = (zval *) emalloc(sizeof(zval)); + + convert_to_string(&varname->u.constant); + *tmp = static_assignment->u.constant; + if (!CG(active_op_array)->static_variables) { + CG(active_op_array)->static_variables = (HashTable *) emalloc(sizeof(HashTable)); + zend_hash_init(CG(active_op_array)->static_variables, 2, NULL, PVAL_PTR_DTOR, 0); + } + zend_hash_update_ptr(CG(active_op_array)->static_variables, varname->u.constant.value.str.val, varname->u.constant.value.str.len+1, tmp, sizeof(zval *), NULL); + } + + + 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.constant.value.lval = fetch_type; + + if (varname->op_type == IS_CONST) { + zval_copy_ctor(&varname->u.constant); + } + fetch_simple_variable(&lval, varname, 0 CLS_CC); /* Relies on the fact that the default fetch is BP_VAR_W */ + + + do_assign_ref(NULL, &lval, &opline->result CLS_CC); +} + + +void do_cast(znode *result, znode *expr, int type CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_CAST; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *expr; + SET_UNUSED(opline->op2); + opline->op2.u.constant.type = type; + *result = opline->result; +} + + +void do_include_or_eval(int type, znode *result, znode *op1 CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_INCLUDE_OR_EVAL; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *op1; + SET_UNUSED(opline->op2); + opline->op2.u.constant.value.lval = type; + *result = opline->result; +} + + +void do_indirect_references(znode *result, znode *num_references, znode *variable CLS_DC) +{ + int i; + + for (i=1; i<=num_references->u.constant.value.lval; i++) { + fetch_simple_variable(result, variable, 1 CLS_CC); + *variable = *result; + } +} + + +void do_unset(znode *variable CLS_DC) +{ + zend_op *last_op; + + last_op = &CG(active_op_array)->opcodes[get_next_op_number(CG(active_op_array))-1]; + + switch (last_op->opcode) { + case ZEND_FETCH_R: + last_op->opcode = ZEND_UNSET_VAR; + break; + case ZEND_FETCH_DIM_R: + case ZEND_FETCH_OBJ_R: + last_op->opcode = ZEND_UNSET_DIM_OBJ; + break; + + } +} + + +void do_isset_or_isempty(int type, znode *result, znode *variable CLS_DC) +{ + zend_op *opline; + + do_end_variable_parse(BP_VAR_IS CLS_CC); + opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_ISSET_ISEMPTY; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *variable; + opline->op2.u.constant.value.lval = type; + SET_UNUSED(opline->op2); + *result = opline->result; +} + + +void do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + /* Preform array reset */ + opline->opcode = ZEND_FE_RESET; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *array; + SET_UNUSED(opline->op2); + *open_brackets_token = opline->result; + + /* save the location of the beginning of the loop (array fetching) */ + foreach_token->u.opline_num = get_next_op_number(CG(active_op_array)); + + opline = get_next_op(CG(active_op_array) CLS_CC); + opline->opcode = ZEND_FE_FETCH; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *open_brackets_token; + SET_UNUSED(opline->op2); + *as_token = opline->result; +} + + +void do_foreach_cont(znode *value, znode *key, znode *as_token CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + znode result_value, result_key, dummy; + + if (key->op_type != IS_UNUSED) { + znode *tmp; + + /* switch between the key and value... */ + tmp = key; + key = value; + value = tmp; + } + + opline->opcode = ZEND_FETCH_DIM_TMP_VAR; + opline->result.op_type = IS_VAR; + opline->result.u.EA.type = 0; + opline->result.u.opline_num = get_temporary_variable(CG(active_op_array)); + opline->op1 = *as_token; + opline->op2.op_type = IS_CONST; + opline->op2.u.constant.type = IS_LONG; + opline->op2.u.constant.value.lval = 0; + result_value = opline->result; + + if (key->op_type != IS_UNUSED) { + opline = get_next_op(CG(active_op_array) CLS_CC); + opline->opcode = ZEND_FETCH_DIM_TMP_VAR; + opline->result.op_type = IS_VAR; + opline->result.u.EA.type = 0; + opline->result.u.opline_num = get_temporary_variable(CG(active_op_array)); + opline->op1 = *as_token; + opline->op2.op_type = IS_CONST; + opline->op2.u.constant.type = IS_LONG; + opline->op2.u.constant.value.lval = 1; + result_key = opline->result; + } + + do_assign(&dummy, value, &result_value CLS_CC); + CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED; + if (key->op_type != IS_UNUSED) { + do_assign(&dummy, key, &result_key CLS_CC); + CG(active_op_array)->opcodes[CG(active_op_array)->last-1].result.u.EA.type |= EXT_TYPE_UNUSED; + } + do_free(as_token CLS_CC); + + do_begin_loop(CLS_C); + INC_BPC(CG(active_op_array)); +} + + +void do_foreach_end(znode *foreach_token, znode *open_brackets_token CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_JMP; + opline->op1.u.opline_num = foreach_token->u.opline_num; + SET_UNUSED(opline->op2); + + CG(active_op_array)->opcodes[foreach_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array)); + + do_end_loop(foreach_token->u.opline_num CLS_CC); + + do_free(open_brackets_token CLS_CC); + + DEC_BPC(CG(active_op_array)); +} + + +void do_end_heredoc(CLS_D) +{ + int opline_num = get_next_op_number(CG(active_op_array))-1; + zend_op *opline = &CG(active_op_array)->opcodes[opline_num]; + + if (opline->opcode != ZEND_ADD_STRING) { + return; + } + + opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0; + if (opline->op2.u.constant.value.str.len>0) { + if (opline->op2.u.constant.value.str.val[opline->op2.u.constant.value.str.len-1]=='\r') { + opline->op2.u.constant.value.str.val[(opline->op2.u.constant.value.str.len--)-1] = 0; + } + } +} + + +void do_exit(znode *result, znode *message CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_EXIT; + opline->op1 = *message; + SET_UNUSED(opline->op2); + + result->op_type = IS_CONST; + result->u.constant.type = IS_BOOL; + result->u.constant.value.lval = 1; +} + + +void do_begin_silence(znode *strudel_token CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_BEGIN_SILENCE; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); + *strudel_token = opline->result; +} + + +void do_end_silence(znode *strudel_token CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_END_SILENCE; + opline->op1 = *strudel_token; + SET_UNUSED(opline->op2); +} + + +void do_begin_qm_op(znode *cond, znode *qm_token CLS_DC) +{ + int jmpz_op_number = get_next_op_number(CG(active_op_array)); + zend_op *opline; + + opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_JMPZ; + opline->op1 = *cond; + SET_UNUSED(opline->op2); + opline->op2.u.opline_num = jmpz_op_number; + *qm_token = opline->op2; + + INC_BPC(CG(active_op_array)); +} + + +void do_qm_true(znode *true_value, znode *qm_token, znode *colon_token CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + CG(active_op_array)->opcodes[qm_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array))+1; /* jmp over the ZEND_JMP */ + + opline->opcode = ZEND_QM_ASSIGN; + opline->result.op_type = IS_TMP_VAR; + opline->result.u.var = get_temporary_variable(CG(active_op_array)); + opline->op1 = *true_value; + SET_UNUSED(opline->op2); + + *qm_token = opline->result; + colon_token->u.opline_num = get_next_op_number(CG(active_op_array)); + + opline = get_next_op(CG(active_op_array) CLS_CC); + opline->opcode = ZEND_JMP; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); +} + + +void do_qm_false(znode *result, znode *false_value, znode *qm_token, znode *colon_token CLS_DC) +{ + zend_op *opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_QM_ASSIGN; + opline->result = *qm_token; + opline->op1 = *false_value; + SET_UNUSED(opline->op2); + + CG(active_op_array)->opcodes[colon_token->u.opline_num].op1.u.opline_num = get_next_op_number(CG(active_op_array)); + + *result = opline->result; + + DEC_BPC(CG(active_op_array)); +} + +void do_extended_info(CLS_D) +{ + zend_op *opline; + + if (!CG(extended_info)) { + return; + } + + opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_EXT_STMT; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); +} + +void do_extended_fcall_begin(CLS_D) +{ + zend_op *opline; + + if (!CG(extended_info)) { + return; + } + + opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_EXT_FCALL_BEGIN; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); +} + + +void do_extended_fcall_end(CLS_D) +{ + zend_op *opline; + + if (!CG(extended_info)) { + return; + } + + opline = get_next_op(CG(active_op_array) CLS_CC); + + opline->opcode = ZEND_EXT_FCALL_END; + SET_UNUSED(opline->op1); + SET_UNUSED(opline->op2); +} + + +int zendlex(znode *zendlval CLS_DC) +{ + int retval; + +#if 0 +#if (WIN32|WINNT) + if (GLOBAL(wintimer) && !(++GLOBAL(wintimer_counter) & 0xff) && (GLOBAL(wintimer) < (unsigned int) clock())) { + zend_error(E_WARNING, "PHP Timed out!
\n"); + } +#endif +#endif + + zendlval->u.constant.type = IS_LONG; + retval = lex_scan(&zendlval->u.constant CLS_CC); + switch(retval) { + case ZEND_COMMENT: + case PHP_OPEN_TAG: + case T_WHITESPACE: + retval = zendlex(zendlval CLS_CC); + break; + case PHP_CLOSE_TAG: + retval = ';'; /* implicit ; */ + break; + case PHP_OPEN_TAG_WITH_ECHO: + retval = ZEND_ECHO; + break; + } + + zendlval->u.constant.refcount = 1; + zendlval->u.constant.is_ref = 0; + zendlval->op_type = IS_CONST; + return retval; +} diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h new file mode 100644 index 0000000000000..0eace155657ff --- /dev/null +++ b/Zend/zend_compile.h @@ -0,0 +1,499 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _COMPILE_H +#define _COMPILE_H + +#include "zend.h" +#include "zend_llist.h" +#define YYSTYPE znode +#include "zend-parser.h" + +#define DEBUG_ZEND 0 +#define SUPPORT_INTERACTIVE 1 + +#define FREE_PNODE(znode) zval_dtor(&znode->u.constant); +#define FREE_OP(op, should_free) if (should_free) zval_dtor(&Ts[(op)->u.var].tmp_var); + + +#if SUPPORT_INTERACTIVE +#define INC_BPC(op_array) ((op_array)->backpatch_count++) +#define DEC_BPC(op_array) ((op_array)->backpatch_count--) +#define HANDLE_INTERACTIVE() if (EG(interactive)) { execute_new_code(CLS_C); } +#else +#define INC_BPC(op_array) +#define DEC_BPC(op_array) +#define HANDLE_INTERACTIVE() +#endif + +typedef struct _zend_op_array zend_op_array; + +typedef struct { + int op_type; + union { + zval constant; + + int var; + int opline_num; + zend_op_array *op_array; + struct { + int var; /* dummy */ + int type; + } EA; + } u; +} znode; + + +typedef struct _zend_op { + int opcode; + znode result; + znode op1; + znode op2; + char *filename; + uint lineno; +} zend_op; + + +typedef struct { + int cont; + int brk; + int parent; +} zend_brk_cont_element; + + +struct _zend_op_array { + int type; /* MUST be the first element of this struct! */ + + unsigned char *arg_types; /* MUST be the second element of this struct! */ + + int *refcount; + + zend_op *opcodes; + int last, size; + + int T; + + char *function_name; + + zend_brk_cont_element *brk_cont_array; + int last_brk_cont; + int current_brk_cont; + + /* static variables support */ + HashTable *static_variables; + +#if SUPPORT_INTERACTIVE + int start_op_number, end_op_number; + int last_executed_op_number; + int backpatch_count; +#endif + + void *reserved[4]; +}; + + +typedef struct { + int type; /* MUST be the first element of this struct! */ + + unsigned char *arg_types; /* MUST be the second element of this struct */ + + void (*handler)(INTERNAL_FUNCTION_PARAMETERS); + char *function_name; +} zend_internal_function; + + +typedef union { + int type; /* MUST be the first element of this struct! */ + struct { + int type; /* never used */ + unsigned char *arg_types; + } common; + + zend_op_array op_array; + zend_internal_function internal_function; +} zend_function; + + +typedef struct { + HashTable *function_symbol_table; + zend_function *function; + void *reserved[4]; +} zend_function_state; + + +typedef struct { + znode cond; + int default_case; + int control_var; +} zend_switch_entry; + + +typedef struct { + znode var; + zend_llist dimensions; + znode value; +} list_llist_element; + + +typedef struct { + int type; + char *filename; + union { + int fd; + FILE *fp; +#ifdef __cplusplus + istream *is; +#endif + } handle; +} zend_file_handle; + + +#include "zend_globals.h" + +#define IS_CONST (1<<0) +#define IS_TMP_VAR (1<<1) +#define IS_VAR (1<<2) +#define IS_UNUSED (1<<3) /* Unused variable */ + + +#define EXT_TYPE_UNUSED (1<<0) + +void init_compiler(CLS_D ELS_DC); +void shutdown_compiler(CLS_D); + +extern zend_op_array *(*zend_compile_files)(int mark_as_ref CLS_DC, int file_count, ...); + +int lex_scan(zval *zendlval CLS_DC); +void reset_scanner(CLS_D); +void startup_scanner(CLS_D); +void shutdown_scanner(CLS_D); + +ZEND_API void zend_set_compiled_filename(char *new_compiled_filename); +ZEND_API void zend_restore_compiled_filename(char *original_compiled_filename); +ZEND_API char *zend_get_compiled_filename(); + + +/* parser-driven code generators */ +void do_binary_op(int op, znode *result, znode *op1, znode *op2 CLS_DC); +void do_unary_op(int op, znode *result, znode *op1 CLS_DC); +void do_binary_assign_op(int op, znode *result, znode *op1, znode *op2 CLS_DC); +void do_assign(znode *result, znode *variable, znode *value CLS_DC); +void do_assign_ref(znode *result, znode *lvar, znode *rvar CLS_DC); +void fetch_simple_variable(znode *result, znode *varname, int bp CLS_DC); +void do_indirect_references(znode *result, znode *num_references, znode *variable CLS_DC); +void do_fetch_global_or_static_variable(znode *varname, znode *static_assignment, int fetch_type CLS_DC); + +void fetch_array_begin(znode *result, znode *varname, znode *first_dim CLS_DC); +void fetch_array_dim(znode *result, znode *parent, znode *dim CLS_DC); +void do_print(znode *result, znode *arg CLS_DC); +void do_echo(znode *arg CLS_DC); +ZEND_API void *get_unary_op(int opcode); +ZEND_API void *get_binary_op(int opcode); + +void do_while_cond(znode *expr, znode *close_bracket_token CLS_DC); +void do_while_end(znode *while_token, znode *close_bracket_token CLS_DC); +void do_do_while_begin(CLS_D); +void do_do_while_end(znode *do_token, znode *expr CLS_DC); + + +void do_if_cond(znode *cond, znode *closing_bracket_token CLS_DC); +void do_if_after_statement(znode *closing_bracket_token, unsigned char initialize CLS_DC); +void do_if_end(CLS_D); + +void do_for_cond(znode *expr, znode *second_semicolon_token CLS_DC); +void do_for_before_statement(znode *cond_start, znode *second_semicolon_token CLS_DC); +void do_for_end(znode *second_semicolon_token CLS_DC); + +void do_pre_incdec(znode *result, znode *op1, int op CLS_DC); +void do_post_incdec(znode *result, znode *op1, int op CLS_DC); + +void do_begin_variable_parse(CLS_D); +void do_end_variable_parse(int type CLS_DC); + +void do_free(znode *op1 CLS_DC); + +void do_init_string(znode *result); +void do_add_char(znode *result, znode *op1, znode *op2 CLS_DC); +void do_add_string(znode *result, znode *op1, znode *op2 CLS_DC); +void do_add_variable(znode *result, znode *op1, znode *op2 CLS_DC); + +void do_begin_function_declaration(znode *function_token, znode *function_name, int is_method CLS_DC); +void do_end_function_declaration(znode *function_token CLS_DC); +void do_receive_arg(int op, znode *var, znode *offset, znode *initialization, unsigned char pass_type CLS_DC); +void do_begin_function_call(znode *function_name CLS_DC); +void do_begin_dynamic_function_call(znode *function_name CLS_DC); +void do_begin_class_member_function_call(znode *class_name, znode *function_name CLS_DC); +void do_end_function_call(znode *function_name, znode *result, int is_method CLS_DC); +void do_return(znode *expr CLS_DC); + +void do_pass_param(znode *param, int op, int offset CLS_DC); + + +void do_boolean_or_begin(znode *expr1, znode *op_token CLS_DC); +void do_boolean_or_end(znode *result, znode *expr1, znode *expr2, znode *op_token CLS_DC); +void do_boolean_and_begin(znode *expr1, znode *op_token CLS_DC); +void do_boolean_and_end(znode *result, znode *expr1, znode *expr2, znode *op_token CLS_DC); + +void do_brk_cont(int op, znode *expr CLS_DC); + +void do_switch_cond(znode *cond CLS_DC); +void do_switch_end(znode *case_list CLS_DC); +void do_case_before_statement(znode *case_list, znode *case_token, znode *case_expr CLS_DC); +void do_case_after_statement(znode *result, znode *case_token CLS_DC); +void do_default_before_statement(znode *case_list, znode *default_token CLS_DC); + +void do_begin_class_declaration(znode *class_name, znode *parent_class_name CLS_DC); +void do_end_class_declaration(CLS_D); +void do_declare_property(znode *var_name, znode *value CLS_DC); + +void do_fetch_property(znode *result, znode *object, znode *property CLS_DC); + + +void do_push_object(znode *object CLS_DC); +void do_pop_object(znode *object CLS_DC); + + +void do_begin_new_object(znode *result, znode *variable, znode *new_token, znode *class_name CLS_DC); +void do_end_new_object(znode *class_name, znode *new_token CLS_DC); + +void do_fetch_constant(znode *result, znode *constant_name, int mode CLS_DC); + +void do_shell_exec(znode *result, znode *cmd CLS_DC); + +void do_init_array(znode *result, znode *expr, znode *offset CLS_DC); +void do_add_array_element(znode *result, znode *expr, znode *offset CLS_DC); +void do_add_static_array_element(znode *result, znode *expr, znode *offset); +void do_list_init(); +void do_list_end(znode *result, znode *expr CLS_DC); +void do_add_list_element(znode *element CLS_DC); +void do_new_list_begin(CLS_D); +void do_new_list_end(CLS_D); + +void do_cast(znode *result, znode *expr, int type CLS_DC); +void do_include_or_eval(int type, znode *result, znode *op1 CLS_DC); + +void do_unset(znode *variable CLS_DC); +void do_isset_or_isempty(int type, znode *result, znode *variable CLS_DC); + +void do_foreach_begin(znode *foreach_token, znode *array, znode *open_brackets_token, znode *as_token CLS_DC); +void do_foreach_cont(znode *value, znode *key, znode *as_token CLS_DC); +void do_foreach_end(znode *foreach_token, znode *open_brackets_token CLS_DC); + +void do_end_heredoc(CLS_D); + +void do_exit(znode *result, znode *message CLS_DC); + +void do_begin_silence(znode *strudel_token CLS_DC); +void do_end_silence(znode *strudel_token CLS_DC); + +void do_begin_qm_op(znode *cond, znode *qm_token CLS_DC); +void do_qm_true(znode *true_value, znode *qm_token, znode *colon_token CLS_DC); +void do_qm_false(znode *result, znode *false_value, znode *qm_token, znode *colon_token CLS_DC); + +void do_extended_info(CLS_D); +void do_extended_fcall_begin(CLS_D); +void do_extended_fcall_end(CLS_D); + + +/* helper functions in zend-scanner.l */ +ZEND_API int require_file(zend_file_handle *file_handle CLS_DC); +ZEND_API int require_filename(char *filename CLS_DC); +ZEND_API zend_op_array *compile_files(int mark_as_ref CLS_DC, int file_count, ...); +ZEND_API zend_op_array *compile_string(zval *source_string CLS_DC); +ZEND_API zend_op_array *compile_filename(zval *filename CLS_DC); +inline int open_file_for_scanning(zend_file_handle *file_handle CLS_DC); + +#define INITIAL_OP_ARRAY_SIZE 1024 + + +ZEND_API void init_op_array(zend_op_array *op_array, int initial_ops_size); +ZEND_API void destroy_op_array(zend_op_array *op_array); + +void destroy_zend_function(zend_function *function); +void destroy_zend_class(zend_class_entry *ce); +zend_op *get_next_op(zend_op_array *op_array CLS_DC); +int get_next_op_number(zend_op_array *op_array); +int print_class(zend_class_entry *class_entry); +void print_op_array(zend_op_array *op_array, int optimizations); +int pass_two(zend_op_array *op_array); +void pass_include_eval(zend_op_array *op_array); +zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array); + + +int zendlex(znode *zendlval CLS_DC); + + +#define ZEND_NOP 0 + +#define ZEND_ADD 1 +#define ZEND_SUB 2 +#define ZEND_MUL 3 +#define ZEND_DIV 4 +#define ZEND_MOD 5 +#define ZEND_SL 6 +#define ZEND_SR 7 +#define ZEND_CONCAT 8 +#define ZEND_BW_OR 9 +#define ZEND_BW_AND 10 +#define ZEND_BW_XOR 11 +#define ZEND_BW_NOT 12 +#define ZEND_BOOL_NOT 13 +#define ZEND_BOOL_XOR 14 +#define ZEND_IS_EQUAL 15 +#define ZEND_IS_NOT_EQUAL 16 +#define ZEND_IS_SMALLER 17 +#define ZEND_IS_SMALLER_OR_EQUAL 18 +#define ZEND_CAST 19 +#define ZEND_QM_ASSIGN 20 + +#define ZEND_ASSIGN_ADD 21 +#define ZEND_ASSIGN_SUB 22 +#define ZEND_ASSIGN_MUL 23 +#define ZEND_ASSIGN_DIV 24 +#define ZEND_ASSIGN_MOD 25 +#define ZEND_ASSIGN_SL 26 +#define ZEND_ASSIGN_SR 27 +#define ZEND_ASSIGN_CONCAT 28 +#define ZEND_ASSIGN_BW_OR 29 +#define ZEND_ASSIGN_BW_AND 30 +#define ZEND_ASSIGN_BW_XOR 31 + +#define ZEND_PRE_INC 32 +#define ZEND_PRE_DEC 33 +#define ZEND_POST_INC 34 +#define ZEND_POST_DEC 35 + +#define ZEND_ASSIGN 36 +#define ZEND_ASSIGN_REF 37 + +#define ZEND_ECHO_OP 38 +#define ZEND_PRINT_OP 39 + +#define ZEND_JMP 40 +#define ZEND_JMPZ 41 +#define ZEND_JMPNZ 42 +#define ZEND_JMPZNZ 43 +#define ZEND_JMPZ_EX 44 +#define ZEND_JMPNZ_EX 45 +#define ZEND_CASE 46 +#define ZEND_BRK 47 +#define ZEND_CONT 48 +#define ZEND_BOOL 49 + +#define ZEND_INIT_STRING 50 +#define ZEND_ADD_CHAR 51 +#define ZEND_ADD_STRING 52 +#define ZEND_ADD_VAR 53 + +#define ZEND_BEGIN_SILENCE 54 +#define ZEND_END_SILENCE 55 + +#define ZEND_INIT_FCALL 56 +#define ZEND_INIT_FCALL_BY_NAME 57 +#define ZEND_DO_FCALL 58 +#define ZEND_RETURN 59 + +#define ZEND_RECV 60 +#define ZEND_RECV_INIT 61 + +#define ZEND_SEND_VAL 62 +#define ZEND_SEND_VAR 63 +#define ZEND_SEND_REF 64 + +#define ZEND_NEW 65 +#define ZEND_JMP_NO_CTOR 66 +#define ZEND_FREE 67 + +#define ZEND_INIT_ARRAY 68 +#define ZEND_ADD_ARRAY_ELEMENT 69 + +#define ZEND_INCLUDE_OR_EVAL 70 + +#define ZEND_UNSET_VAR 71 +#define ZEND_UNSET_DIM_OBJ 72 +#define ZEND_ISSET_ISEMPTY 73 + +#define ZEND_FE_RESET 74 +#define ZEND_FE_FETCH 75 + +#define ZEND_EXIT 76 + + +/* the following 12 opcodes are 4 groups of 3 opcodes each, and must + * remain in that order! + */ +#define ZEND_FETCH_R 77 +#define ZEND_FETCH_DIM_R 78 +#define ZEND_FETCH_OBJ_R 79 +#define ZEND_FETCH_W 80 +#define ZEND_FETCH_DIM_W 81 +#define ZEND_FETCH_OBJ_W 82 +#define ZEND_FETCH_RW 83 +#define ZEND_FETCH_DIM_RW 84 +#define ZEND_FETCH_OBJ_RW 85 +#define ZEND_FETCH_IS 86 +#define ZEND_FETCH_DIM_IS 87 +#define ZEND_FETCH_OBJ_IS 88 + +#define ZEND_FETCH_DIM_TMP_VAR 89 +#define ZEND_FETCH_CONSTANT 90 + +#define ZEND_EXT_STMT 91 +#define ZEND_EXT_FCALL_BEGIN 92 +#define ZEND_EXT_FCALL_END 93 +#define ZEND_EXT_NOP 94 + +/* end of block */ + + + + +/* global/local fetches */ +#define ZEND_FETCH_GLOBAL 0 +#define ZEND_FETCH_LOCAL 1 +#define ZEND_FETCH_STATIC 2 + +/* var status for backpatching */ +#define BP_VAR_R 0 +#define BP_VAR_W 1 +#define BP_VAR_RW 2 +#define BP_VAR_IS 3 +#define BP_VAR_NA 4 /* if not applicable */ + + +#define ZEND_INTERNAL_FUNCTION 1 +#define ZEND_USER_FUNCTION 2 +#define ZEND_OVERLOADED_FUNCTION 3 + +#define ZEND_INTERNAL_CLASS 1 +#define ZEND_USER_CLASS 2 + +#define ZEND_EVAL (1<<0) +#define ZEND_INCLUDE (1<<1) + +#define ZEND_ISSET (1<<0) +#define ZEND_ISEMPTY (1<<1) + +#define ZEND_CT (1<<0) +#define ZEND_RT (1<<1) + + +#define ZEND_HANDLE_FILENAME 0 +#define ZEND_HANDLE_FD 1 +#define ZEND_HANDLE_FP 2 +#define ZEND_HANDLE_ISTREAM 3 + +#endif /* _COMPILE_H */ diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c new file mode 100644 index 0000000000000..6072227a82525 --- /dev/null +++ b/Zend/zend_constants.c @@ -0,0 +1,236 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + + +#include "zend.h" +#include "zend_constants.h" +#include "zend_variables.h" +#include "zend_operators.h" +#include "zend_globals.h" + + +void free_zend_constant(zend_constant *c) +{ + if (!(c->flags & CONST_PERSISTENT)) { + zval_dtor(&c->value); + } + free(c->name); +} + + +static int clean_non_persistent_constant(zend_constant *c) +{ + if (c->flags & CONST_PERSISTENT) { + return 0; + } else { + return 1; + } +} + + +static int clean_module_constant(zend_constant *c, int *module_number) +{ + if (c->module_number == *module_number) { + return 1; + } else { + return 0; + } +} + + +void clean_module_constants(int module_number) +{ + zend_hash_apply_with_argument(EG(zend_constants), (int (*)(void *,void *)) clean_module_constant, (void *) &module_number); +} + + +int zend_startup_constants(void) +{ +#if WIN32|WINNT + DWORD dwBuild=0; + DWORD dwVersion = GetVersion(); + DWORD dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); + DWORD dwWindowsMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion))); +#endif + + +/* ZEND_FIX: Move to PHP */ +#if 0 +#if WIN32|WINNT + // Get build numbers for Windows NT or Win95 + if (dwVersion < 0x80000000){ + php3_os="WINNT"; + } else { + php3_os="WIN32"; + } +#else + php3_os=PHP_OS; +#endif +#endif + + + EG(zend_constants) = (HashTable *) malloc(sizeof(HashTable)); + + if (zend_hash_init(EG(zend_constants), 20, NULL, (void(*)(void *)) free_zend_constant, 1)==FAILURE) { + return FAILURE; + } + +#if 0 + /* This should go back to PHP */ + REGISTER_MAIN_STRINGL_CONSTANT("PHP_VERSION", PHP_VERSION, sizeof(PHP_VERSION)-1, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_STRINGL_CONSTANT("PHP_OS", php3_os, strlen(php3_os), CONST_PERSISTENT | CONST_CS); +#endif + REGISTER_MAIN_LONG_CONSTANT("E_ERROR", E_ERROR, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("E_WARNING", E_WARNING, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("E_NOTICE", E_NOTICE, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("E_PARSE", E_PARSE, CONST_PERSISTENT | CONST_CS); + REGISTER_MAIN_LONG_CONSTANT("E_ALL", E_ALL, CONST_PERSISTENT | CONST_CS); + + /* true/false constants */ + { + zend_constant c; + + c.value.type = IS_BOOL; + c.flags = CONST_PERSISTENT; + c.module_number = 0; + + c.name = zend_strndup("TRUE",4); + c.name_len = 5; + c.value.value.lval = 1; + c.value.type = IS_BOOL; + zend_register_constant(&c); + + c.name = zend_strndup("FALSE",5); + c.name_len = 6; + c.value.value.lval = 0; + c.value.type = IS_BOOL; + zend_register_constant(&c); + } + + return SUCCESS; +} + + +int zend_shutdown_constants(void) +{ + zend_hash_destroy(EG(zend_constants)); + free(EG(zend_constants)); + return SUCCESS; +} + + +void clean_non_persistent_constants(void) +{ + zend_hash_apply(EG(zend_constants), (int (*)(void *)) clean_non_persistent_constant); +} + + +ZEND_API void zend_register_long_constant(char *name, uint name_len, long lval, int flags, int module_number) +{ + zend_constant c; + + c.value.type = IS_LONG; + c.value.value.lval = lval; + c.flags = flags; + c.name = zend_strndup(name,name_len); + c.name_len = name_len; + c.module_number = module_number; + zend_register_constant(&c); +} + + +ZEND_API void zend_register_double_constant(char *name, uint name_len, double dval, int flags, int module_number) +{ + zend_constant c; + + c.value.type = IS_DOUBLE; + c.value.value.dval = dval; + c.flags = flags; + c.name = zend_strndup(name,name_len); + c.name_len = name_len; + c.module_number = module_number; + zend_register_constant(&c); +} + + +ZEND_API void zend_register_stringl_constant(char *name, uint name_len, char *strval, uint strlen, int flags, int module_number) +{ + zend_constant c; + + c.value.type = IS_STRING; + c.value.value.str.val = strval; + c.value.value.str.len = strlen; + c.flags = flags; + c.name = zend_strndup(name,name_len); + c.name_len = name_len; + c.module_number = module_number; + zend_register_constant(&c); +} + + +ZEND_API void zend_register_string_constant(char *name, uint name_len, char *strval, int flags, int module_number) +{ + zend_register_stringl_constant(name, name_len, strval, strlen(strval), flags, module_number); +} + + +ZEND_API int zend_get_constant(char *name, uint name_len, zval *result) +{ + zend_constant *c; + char *lookup_name = estrndup(name,name_len); + int retval; + + 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); + } + } else { + retval=0; + } + + efree(lookup_name); + return retval; +} + + +ZEND_API void zend_register_constant(zend_constant *c) +{ + char *lowercase_name = zend_strndup(c->name, c->name_len); + +#if 0 + printf("Registering constant for module %d\n",c->module_number); +#endif + + 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) { + zval_dtor(&c->value); + } + free(lowercase_name); +} + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h new file mode 100644 index 0000000000000..b03ac9c766e24 --- /dev/null +++ b/Zend/zend_constants.h @@ -0,0 +1,53 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _CONSTANTS_H +#define _CONSTANTS_H + +#define CONST_CS 0x1 /* Case Sensitive */ +#define CONST_PERSISTENT 0x2 + +typedef struct { + zval value; + int flags; + char *name; + uint name_len; + int module_number; +} zend_constant; + +#define REGISTER_LONG_CONSTANT(name,lval,flags) zend_register_long_constant((name),sizeof(name),(lval),(flags),module_number) +#define REGISTER_DOUBLE_CONSTANT(name,dval,flags) zend_register_double_constant((name),sizeof(name),(dval),(flags),module_number) +#define REGISTER_STRING_CONSTANT(name,str,flags) zend_register_string_constant((name),sizeof(name),(str),(flags),module_number) +#define REGISTER_STRINGL_CONSTANT(name,str,len,flags) zend_register_stringl_constant((name),sizeof(name),(str),(len),(flags),module_number) + +#define REGISTER_MAIN_LONG_CONSTANT(name,lval,flags) zend_register_long_constant((name),sizeof(name),(lval),(flags),0) +#define REGISTER_MAIN_DOUBLE_CONSTANT(name,dval,flags) zend_register_double_constant((name),sizeof(name),(dval),(flags),0) +#define REGISTER_MAIN_STRING_CONSTANT(name,str,flags) zend_register_string_constant((name),sizeof(name),(str),(flags),0) +#define REGISTER_MAIN_STRINGL_CONSTANT(name,str,len,flags) zend_register_stringl_constant((name),sizeof(name),(str),(len),(flags),0) + +void clean_module_constants(int module_number); +void free_zend_constant(zend_constant *c); +int zend_startup_constants(void); +int zend_shutdown_constants(void); +void clean_non_persistent_constants(void); +ZEND_API int zend_get_constant(char *name, uint name_len, zval *result); +ZEND_API void zend_register_long_constant(char *name, uint name_len, long lval, int flags, int module_number); +ZEND_API void zend_register_double_constant(char *name, uint name_len, double dval, int flags, int module_number); +ZEND_API void zend_register_string_constant(char *name, uint name_len, char *strval, int flags, int module_number); +ZEND_API void zend_register_stringl_constant(char *name, uint name_len, char *strval, uint strlen, int flags, int module_number); +ZEND_API void zend_register_constant(zend_constant *c); + +#endif diff --git a/Zend/zend_errors.h b/Zend/zend_errors.h new file mode 100644 index 0000000000000..bfb0d4c908bc8 --- /dev/null +++ b/Zend/zend_errors.h @@ -0,0 +1,33 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _ZEND_ERRORS_H +#define _ZEND_ERRORS_H + +#define E_CORE_ERROR (1<<0L) +#define E_CORE_WARNING (1<<1L) +#define E_COMPILE_ERROR (1<<2L) +#define E_COMPILE_WARNING (1<<3L) +#define E_PARSE (1<<4L) +#define E_ERROR (1<<5L) +#define E_WARNING (1<<6L) +#define E_NOTICE (1<<7L) + +#define E_ALL (E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING) +#define E_CORE (E_CORE_ERROR | E_CORE_WARNING) + + +#endif /* _ZEND_ERRORS_H */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c new file mode 100644 index 0000000000000..346b217fe0697 --- /dev/null +++ b/Zend/zend_execute.c @@ -0,0 +1,1885 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include +#include + +#include "zend.h" +#include "zend_compile.h" +#include "zend_execute.h" +#include "zend_API.h" +#include "zend_ptr_stack.h" +#include "zend_variables.h" +#include "zend_operators.h" +#include "zend_constants.h" +#include "zend_extensions.h" + + +static void destroy_garbage(HashTable *ht) +{ + zend_hash_destroy(ht); + efree(ht); +} + + +#define INC_AI_COUNT(znode_ptr) if (!((znode_ptr)->u.EA.type & EXT_TYPE_UNUSED)) { EG(AiCount)++; } +#define DEC_AI_COUNT() if (--EG(AiCount)==0) { zend_ptr_stack_clean(&EG(garbage), (void (*)(void *)) destroy_garbage); } + +#define get_zval_ptr(node, Ts, should_free, type) _get_zval_ptr(node, Ts, should_free ELS_CC) +#define get_zval_ptr_ptr(node, Ts, type) _get_zval_ptr_ptr(node, Ts ELS_CC) + +#define get_incdec_op(op, opcode) \ + switch (opcode) { \ + case ZEND_PRE_INC: \ + case ZEND_POST_INC: \ + (op) = increment_function; \ + break; \ + case ZEND_PRE_DEC: \ + case ZEND_POST_DEC: \ + (op) = decrement_function; \ + break; \ + default: \ + (op) = NULL; \ + break; \ + } \ + +/* These globals don't have to be thread safe since they're never modified */ + + +/* Prototypes */ +static zval get_overloaded_property(ELS_D); +static void set_overloaded_property(zval *value ELS_DC); +static void call_overloaded_function(HashTable *ht, zval *return_value, HashTable *list, HashTable *plist ELS_DC); +static inline void zend_fetch_var_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type ELS_DC); +static inline void zend_fetch_dimension_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type ELS_DC); +static inline void zend_fetch_property_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type ELS_DC); +static inline void zend_fetch_dimension_address_from_tmp_var(znode *result, znode *op1, znode *op2, temp_variable *Ts ELS_DC); +static void zend_extension_statement_handler(zend_extension *extension, zend_op_array *op_array); +static void zend_extension_fcall_begin_handler(zend_extension *extension, zend_op_array *op_array); +static void zend_extension_fcall_end_handler(zend_extension *extension, zend_op_array *op_array); + + +static inline zval *_get_zval_ptr(znode *node, temp_variable *Ts, int *should_free ELS_DC) +{ + 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; + break; + case IS_VAR: + if (Ts[node->u.var].var) { + DEC_AI_COUNT(); + *should_free = 0; + return *Ts[node->u.var].var; + } else { + *should_free = 1; + + switch (Ts[node->u.var].EA.type) { + case IS_OVERLOADED_OBJECT: + Ts[node->u.var].tmp_var = get_overloaded_property(ELS_C); + Ts[node->u.var].tmp_var.refcount=1; + Ts[node->u.var].tmp_var.is_ref=1; + return &Ts[node->u.var].tmp_var; + break; + case IS_STRING_OFFSET: { + temp_variable *T = &Ts[node->u.var]; + zval *str = T->EA.str; + + if (T->EA.str->type != IS_STRING + || (T->EA.str->value.str.len <= T->EA.offset)) { + T->tmp_var.value.str.val = empty_string; + T->tmp_var.value.str.len = 0; + } else { + char c = str->value.str.val[T->EA.offset]; + + T->tmp_var.value.str.val = estrndup(&c, 1); + T->tmp_var.value.str.len = 1; + } + zval_ptr_dtor(&str); + T->tmp_var.refcount=1; + T->tmp_var.is_ref=1; + T->tmp_var.type = IS_STRING; + return &T->tmp_var; + } + break; + } + } + break; + case IS_UNUSED: + return NULL; + break; +#if DEBUG_ZEND + default: + zend_error(E_ERROR, "Unknown temporary variable type"); + break; +#endif + } + return NULL; +} + + +static inline zval **_get_zval_ptr_ptr(znode *node, temp_variable *Ts ELS_DC) +{ + switch(node->op_type) { + case IS_VAR: + if (Ts[node->u.var].var) { + DEC_AI_COUNT(); + } + return Ts[node->u.var].var; + break; + default: + return NULL; + break; + } +} + + +static inline zval **zend_fetch_property_address_inner(HashTable *ht, znode *op2, temp_variable *Ts, int type ELS_DC) +{ + int free_op2; + zval *prop_ptr = get_zval_ptr(op2, Ts, &free_op2, BP_VAR_R); + zval **retval; + zval tmp; + + + switch (op2->op_type) { + case IS_CONST: + /* already a constant string */ + break; + case IS_VAR: + tmp = *prop_ptr; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + prop_ptr = &tmp; + break; + case IS_TMP_VAR: + convert_to_string(prop_ptr); + break; + } + + if (zend_hash_find(ht, prop_ptr->value.str.val, prop_ptr->value.str.len+1, (void **) &retval) == FAILURE) { + switch (type) { + case BP_VAR_R: + zend_error(E_NOTICE,"Undefined property: %s", prop_ptr->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 property: %s", prop_ptr->value.str.val); + /* break missing intentionally */ + case BP_VAR_W: { + zval *new_zval = (zval *) emalloc(sizeof(zval)); + + var_uninit(new_zval); + new_zval->refcount=1; + new_zval->is_ref=0; + //zend_hash_update(ht, prop_ptr->value.str.val, prop_ptr->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval); + zend_hash_update_ptr(ht, prop_ptr->value.str.val, prop_ptr->value.str.len+1, new_zval, sizeof(zval *), (void **) &retval); + } + break; + } + } + + if (prop_ptr == &tmp) { + zval_dtor(prop_ptr); + } + FREE_OP(op2, free_op2); + return retval; +} + + +static inline void zend_assign_to_variable(znode *result, znode *op1, zval *value, int type, temp_variable *Ts ELS_DC) +{ + zval **variable_ptr_ptr = get_zval_ptr_ptr(op1, Ts, BP_VAR_W); + zval *variable_ptr; + + if (!variable_ptr_ptr) { + switch (Ts[op1->u.var].EA.type) { + case IS_OVERLOADED_OBJECT: + set_overloaded_property(value ELS_CC); + if (type == IS_TMP_VAR) { + zval_dtor(value); + } + break; + case IS_STRING_OFFSET: { + temp_variable *T = &Ts[op1->u.var]; + + if (T->EA.str->type == IS_STRING + && (T->EA.offset < T->EA.str->value.str.len)) { + zval tmp; + + if (value->type!=IS_STRING) { + tmp = *value; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + value = &tmp; + } + + T->EA.str->value.str.val[T->EA.offset] = value->value.str.val[0]; + if (value == &tmp) { + zval_dtor(value); + } + /* + * the value of an assignment to a string offset is undefined + Ts[result->u.var].var = &T->EA.str; + */ + } + zval_ptr_dtor(&T->EA.str); + T->tmp_var.type = IS_STRING; + } + break; + } + Ts[result->u.var].var = &EG(uninitialized_zval_ptr); + INC_AI_COUNT(result); + return; + } + + variable_ptr = *variable_ptr_ptr; + + if (variable_ptr == EG(error_zval_ptr)) { + if (result) { + Ts[result->u.var].var = &EG(uninitialized_zval_ptr); + INC_AI_COUNT(result); + } + return; + } + + if (variable_ptr->is_ref) { + if (variable_ptr!=value) { + short refcount=variable_ptr->refcount; + + zendi_zval_dtor(*variable_ptr); + *variable_ptr = *value; + variable_ptr->refcount = refcount; + variable_ptr->is_ref=1; + if (type!=IS_TMP_VAR) { + zendi_zval_copy_ctor(*variable_ptr); + } + } + } else { + variable_ptr->refcount--; + variable_ptr = *variable_ptr_ptr; + if (variable_ptr->refcount==0) { + switch (type) { + case IS_VAR: + case IS_CONST: + if (variable_ptr==value) { + variable_ptr->refcount++; + } else if (value->is_ref) { + *variable_ptr = *value; + zval_copy_ctor(variable_ptr); + variable_ptr->refcount=1; + } else { + zendi_zval_dtor(*variable_ptr); + safe_free_zval_ptr(variable_ptr); + *variable_ptr_ptr = value; + value->refcount++; + } + break; + case IS_TMP_VAR: + zendi_zval_dtor(*variable_ptr); + value->refcount=1; + *variable_ptr = *value; + break; + } + } else { /* we need to split */ + switch (type) { + case IS_VAR: + case IS_CONST: + if (value->is_ref) { + variable_ptr = *variable_ptr_ptr = (zval *) emalloc(sizeof(zval)); + *variable_ptr = *value; + zval_copy_ctor(variable_ptr); + variable_ptr->refcount=1; + break; + } + *variable_ptr_ptr = value; + value->refcount++; + break; + case IS_TMP_VAR: + (*variable_ptr_ptr) = (zval *) emalloc(sizeof(zval)); + value->refcount=1; + **variable_ptr_ptr = *value; + break; + } + } + (*variable_ptr_ptr)->is_ref=0; + } + if (result) { + Ts[result->u.var].var = variable_ptr_ptr; + INC_AI_COUNT(result); + } +} + + +/* Utility Functions for Extensions */ +static void zend_extension_statement_handler(zend_extension *extension, zend_op_array *op_array) +{ + if (extension->statement_handler) { + extension->statement_handler(op_array); + } +} + + +static void zend_extension_fcall_begin_handler(zend_extension *extension, zend_op_array *op_array) +{ + if (extension->fcall_begin_handler) { + extension->fcall_begin_handler(op_array); + } +} + + +static void zend_extension_fcall_end_handler(zend_extension *extension, zend_op_array *op_array) +{ + if (extension->fcall_end_handler) { + extension->fcall_end_handler(op_array); + } +} + + +static void print_refcount(zval *p, char *str) +{ + //printf("*** refcount for %x - '%s': %d\n", p, str, p->refcount); + print_refcount(NULL, NULL); +} + + +static inline void zend_fetch_var_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type ELS_DC) +{ + int free_op1; + zval *varname = get_zval_ptr(op1, Ts, &free_op1, BP_VAR_R); + zval **retval; + zval tmp_varname; + HashTable *target_symbol_table; + + switch (op2->u.constant.value.lval) { + case ZEND_FETCH_LOCAL: + default: /* just to shut gcc up */ + target_symbol_table = EG(active_symbol_table); + break; + case ZEND_FETCH_GLOBAL: + target_symbol_table = &EG(symbol_table); + break; + case ZEND_FETCH_STATIC: + target_symbol_table = EG(active_op_array)->static_variables; + break; + } + + if (varname->type != IS_STRING) { + tmp_varname = *varname; + zval_copy_ctor(&tmp_varname); + convert_to_string(&tmp_varname); + 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 = (zval *) emalloc(sizeof(zval)); + + var_uninit(new_zval); + new_zval->refcount=1; + new_zval->is_ref=0; + //zend_hash_update(target_symbol_table, varname->value.str.val, varname->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval); + zend_hash_update_ptr(target_symbol_table, varname->value.str.val, varname->value.str.len+1, new_zval, sizeof(zval *), (void **) &retval); + } + break; + } + } + if (op2->u.constant.value.lval == ZEND_FETCH_LOCAL) { + FREE_OP(op1, free_op1); + } else if (op2->u.constant.value.lval == ZEND_FETCH_STATIC) { + zval_update_constant(*retval); + } + + if (varname == &tmp_varname) { + zval_dtor(varname); + } + Ts[result->u.var].var = retval; + INC_AI_COUNT(result); +} + + +static inline zval **zend_fetch_dimension_address_inner(HashTable *ht, znode *op2, temp_variable *Ts, int type ELS_DC) +{ + int free_op2; + zval *dim = get_zval_ptr(op2, Ts, &free_op2, BP_VAR_R); + zval **retval; + + switch (dim->type) { + case IS_STRING: { + if (zend_hash_find(ht, dim->value.str.val, dim->value.str.len+1, (void **) &retval) == FAILURE) { + switch (type) { + case BP_VAR_R: + zend_error(E_NOTICE,"Undefined index: %s", dim->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 index: %s", dim->value.str.val); + /* break missing intentionally */ + case BP_VAR_W: { + zval *new_zval = (zval *) emalloc(sizeof(zval)); + + var_uninit(new_zval); + new_zval->refcount=1; + new_zval->is_ref=0; + //zend_hash_update(ht, dim->value.str.val, dim->value.str.len+1, &new_zval, sizeof(zval *), (void **) &retval); + zend_hash_update_ptr(ht, dim->value.str.val, dim->value.str.len+1, new_zval, sizeof(zval *), (void **) &retval); + } + break; + } + } + } + break; + case IS_LONG: { + if (zend_hash_index_find(ht, dim->value.lval, (void **) &retval) == FAILURE) { + switch (type) { + case BP_VAR_R: + zend_error(E_NOTICE,"Undefined offset: %d", dim->value.lval); + /* break missing intentionally */ + case BP_VAR_IS: + retval = &EG(uninitialized_zval_ptr); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,"Undefined offset: %d", dim->value.lval); + /* break missing intentionally */ + case BP_VAR_W: { + zval *new_zval = (zval *) emalloc(sizeof(zval)); + + var_uninit(new_zval); + new_zval->refcount=1; + new_zval->is_ref=0; + zend_hash_index_update(ht, dim->value.lval, &new_zval, sizeof(zval *), (void **) &retval); + } + break; + } + } + } + break; + /* we need to do implement this nicely somehow ZA + case IS_DOUBLE: + break; + */ + default: + zend_error(E_WARNING, "Illegal offset type"); + if (type == BP_VAR_R || type == BP_VAR_IS) { + retval = &EG(uninitialized_zval_ptr); + } else { + retval = &EG(error_zval_ptr); + } + break; + } + FREE_OP(op2, free_op2); + return retval; +} + + +static inline void zend_fetch_dimension_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type ELS_DC) +{ + int free_op2; + zval **container_ptr = get_zval_ptr_ptr(op1, Ts, type); + zval *container; + zval ***retval = &Ts[result->u.var].var; + + + if (container_ptr == NULL) { + zend_property_reference *property_reference; + zend_overloaded_element overloaded_element; + + if (Ts[op1->u.var].EA.type == IS_STRING_OFFSET) { + zval_ptr_dtor(&Ts[op1->u.var].EA.str); + switch (type) { + case BP_VAR_R: + case BP_VAR_IS: + *retval = &EG(uninitialized_zval_ptr); + return; + case BP_VAR_W: + case BP_VAR_RW: + *retval = &EG(error_zval_ptr); + return; + } + } + + /* prepare the new element */ + overloaded_element.element = *get_zval_ptr(op2, Ts, &free_op2, type); + overloaded_element.type = IS_ARRAY; + if (!free_op2) { + zval_copy_ctor(&overloaded_element.element); + } + + zend_stack_top(&EG(overloaded_objects_stack), (void **) &property_reference); + + zend_llist_add_element(&property_reference->elements_list, &overloaded_element); + + Ts[result->u.var].EA.type = IS_OVERLOADED_OBJECT; + *retval = NULL; + return; + } + container = *container_ptr; + + if (container == EG(error_zval_ptr)) { + INC_AI_COUNT(result); + *retval = &EG(error_zval_ptr); + return; + } + + if (container->type == IS_STRING && container->value.str.val == undefined_variable_string) { + switch (type) { + case BP_VAR_RW: + case BP_VAR_W: + if (!container->is_ref) { + container->refcount--; + if (container->refcount>0) { + container = *container_ptr = (zval *) emalloc(sizeof(zval)); + container->is_ref=0; + } + container->refcount=1; + } + array_init(container); + break; + } + } + + switch (container->type) { + case IS_ARRAY: + if ((type==BP_VAR_W || type==BP_VAR_RW) && container->refcount>1 && !container->is_ref) { + container->refcount--; + *container_ptr = (zval *) emalloc(sizeof(zval)); + **container_ptr = *container; + container = *container_ptr; + container->refcount=1; + container->is_ref=0; + zendi_zval_copy_ctor(*container); + } + if (op2->op_type == IS_UNUSED) { + zval *new_zval = (zval *) emalloc(sizeof(zval)); + + var_uninit(new_zval); + new_zval->refcount = 1; + new_zval->is_ref = 0; + zend_hash_next_index_insert_ptr(container->value.ht, new_zval, sizeof(zval *), (void **) retval); + } else { + *retval = zend_fetch_dimension_address_inner(container->value.ht, op2, Ts, type ELS_CC); + } + break; + case IS_STRING: { + zval *offset; + offset = get_zval_ptr(op2, Ts, &free_op2, BP_VAR_R); + + if (container->value.str.val == undefined_variable_string + || type==BP_VAR_IS) { + /* for read-mode only */ + *retval = &EG(uninitialized_zval_ptr); + FREE_OP(op2, free_op2); + } else { + zval tmp; + + if (offset->type != IS_LONG) { + tmp = *offset; + zval_copy_ctor(&tmp); + convert_to_long(&tmp); + offset = &tmp; + } + Ts[result->u.var].EA.str = container; + container->refcount++; + Ts[result->u.var].EA.offset = offset->value.lval; + Ts[result->u.var].EA.type = IS_STRING_OFFSET; + FREE_OP(op2, free_op2); + *retval = NULL; + return; + } + } + break; + default: { + zval *offset; + + offset = get_zval_ptr(op2, Ts, &free_op2, BP_VAR_R); + if (type==BP_VAR_R || type==BP_VAR_IS) { + *retval = &EG(uninitialized_zval_ptr); + } else { + *retval = &EG(error_zval_ptr); + } + FREE_OP(op2, free_op2); + } + break; + } + INC_AI_COUNT(result); +} + + +static inline void zend_fetch_dimension_address_from_tmp_var(znode *result, znode *op1, znode *op2, temp_variable *Ts ELS_DC) +{ + int free_op1; + zval *container = get_zval_ptr(op1, Ts, &free_op1, BP_VAR_R); + + if (container->type != IS_ARRAY) { + INC_AI_COUNT(result); + Ts[result->u.var].var = &EG(uninitialized_zval_ptr); + return; + } + + INC_AI_COUNT(result); + Ts[result->u.var].var = zend_fetch_dimension_address_inner(container->value.ht, op2, Ts, BP_VAR_R ELS_CC); +} + + +static inline void zend_fetch_property_address(znode *result, znode *op1, znode *op2, temp_variable *Ts, int type ELS_DC) +{ + int free_op2; + zval **container_ptr = get_zval_ptr_ptr(op1, Ts, type); + zval *container; + zval ***retval = &Ts[result->u.var].var; + + + if (container_ptr == NULL) { + zend_property_reference *property_reference; + zend_overloaded_element overloaded_element; + + if (Ts[op1->u.var].EA.type == IS_STRING_OFFSET) { + zval_ptr_dtor(&Ts[op1->u.var].EA.str); + switch (type) { + case BP_VAR_R: + case BP_VAR_IS: + *retval = &EG(uninitialized_zval_ptr); + return; + case BP_VAR_W: + case BP_VAR_RW: + *retval = &EG(error_zval_ptr); + return; + } + } + + overloaded_element.element = *get_zval_ptr(op2, Ts, &free_op2, type); + overloaded_element.type = IS_OBJECT; + if (!free_op2) { + zval_copy_ctor(&overloaded_element.element); + } + + zend_stack_top(&EG(overloaded_objects_stack), (void **) &property_reference); + + zend_llist_add_element(&property_reference->elements_list, &overloaded_element); + + Ts[result->u.var].EA.type = IS_OVERLOADED_OBJECT; + *retval = NULL; + return; + } + + container = *container_ptr; + if (container == EG(error_zval_ptr)) { + INC_AI_COUNT(result); + *retval = &EG(error_zval_ptr); + return; + } + + if (container->type == IS_OBJECT + && container->value.obj.ce->handle_property_get) { + zend_property_reference property_reference; + zend_overloaded_element overloaded_element; + + property_reference.object = container_ptr; + property_reference.type = type; + zend_llist_init(&property_reference.elements_list, sizeof(zend_overloaded_element), NULL, 0); + overloaded_element.element = *get_zval_ptr(op2, Ts, &free_op2, type); + overloaded_element.type = IS_OBJECT; + if (!free_op2) { + zval_copy_ctor(&overloaded_element.element); + } + zend_llist_add_element(&property_reference.elements_list, &overloaded_element); + zend_stack_push(&EG(overloaded_objects_stack), &property_reference, sizeof(zend_property_reference)); + Ts[result->u.var].EA.type = IS_OVERLOADED_OBJECT; + *retval = NULL; + return; + } + + + + if (container->type == IS_STRING && container->value.str.val == undefined_variable_string) { + switch (type) { + case BP_VAR_RW: + case BP_VAR_W: + if (!container->is_ref) { + container->refcount--; + if (container->refcount>0) { + container = *container_ptr = (zval *) emalloc(sizeof(zval)); + container->is_ref=0; + } + container->refcount=1; + } + object_init(container); + break; + } + } + + if (container->type != IS_OBJECT) { + zval *offset; + + offset = get_zval_ptr(op2, Ts, &free_op2, BP_VAR_R); + FREE_OP(op2, free_op2); + INC_AI_COUNT(result); + if (type==BP_VAR_R || type==BP_VAR_IS) { + *retval = &EG(uninitialized_zval_ptr); + return; + } else { + *retval = &EG(error_zval_ptr); + return; + } + } + + + if ((type==BP_VAR_W || type==BP_VAR_RW) && container->refcount>1 && !container->is_ref) { + container->refcount--; + *container_ptr = (zval *) emalloc(sizeof(zval)); + **container_ptr = *container; + container = *container_ptr; + container->refcount=1; + container->is_ref=0; + zendi_zval_copy_ctor(*container); + } + INC_AI_COUNT(result); + *retval = zend_fetch_property_address_inner(container->value.obj.properties, op2, Ts, type ELS_CC); +} + + +static zval get_overloaded_property(ELS_D) +{ + zend_property_reference *property_reference; + zval result; + + zend_stack_top(&EG(overloaded_objects_stack), (void **) &property_reference); + result = (*(property_reference->object))->value.obj.ce->handle_property_get(property_reference); + + zend_llist_destroy(&property_reference->elements_list); + + zend_stack_del_top(&EG(overloaded_objects_stack)); + return result; +} + + +static void set_overloaded_property(zval *value ELS_DC) +{ + zend_property_reference *property_reference; + + zend_stack_top(&EG(overloaded_objects_stack), (void **) &property_reference); + (*(property_reference->object))->value.obj.ce->handle_property_set(property_reference, value); + + zend_llist_destroy(&property_reference->elements_list); + + zend_stack_del_top(&EG(overloaded_objects_stack)); +} + + +static void call_overloaded_function(HashTable *ht, zval *return_value, HashTable *list, HashTable *plist ELS_DC) +{ + zend_property_reference *property_reference; + + zend_stack_top(&EG(overloaded_objects_stack), (void **) &property_reference); + (*(property_reference->object))->value.obj.ce->handle_function_call(ht, return_value, list, plist, property_reference); + //(*(property_reference->object))->value.obj.ce->handle_function_call(NULL, NULL, NULL, NULL, NULL); + zend_llist_destroy(&property_reference->elements_list); + + zend_stack_del_top(&EG(overloaded_objects_stack)); +} + + +#if HAVE_ALLOCA || (defined (__GNUC__) && __GNUC__ >= 2) +# define free_alloca(p) +#else +# define alloca(p) emalloc(p) +# define free_alloca(p) efree(p) +#endif + + +void execute(zend_op_array *op_array ELS_DC) +{ + zend_op *opline = op_array->opcodes; + int free_op1, free_op2; + int (*unary_op)(zval *result, zval *op1); + int (*binary_op)(zval *result, zval *op1, zval *op2); + zend_op *end = op_array->opcodes + op_array->last; + zend_function_state function_state; + HashTable *calling_symbol_table; + zend_function *function_being_called=NULL; + zval **object_ptr=NULL; +#if !defined (__GNUC__) || __GNUC__ < 2 + temp_variable *Ts = (temp_variable *) alloca(sizeof(temp_variable)*op_array->T); +#else + temp_variable Ts[op_array->T]; +#endif + +#if SUPPORT_INTERACTIVE + if (EG(interactive)) { + opline = op_array->opcodes + op_array->start_op_number; + end = op_array->opcodes + op_array->end_op_number; + } +#endif + + EG(opline_ptr) = &opline; + + function_state.function = (zend_function *) op_array; + EG(function_state_ptr) = &function_state; +#if ZEND_DEBUG + /* function_state.function_symbol_table is saved as-is to a stack, + * which is an intentional UMR. Shut it up if we're in DEBUG. + */ + function_state.function_symbol_table = NULL; +#endif + + while (oplineopcode) { + case ZEND_ADD: + binary_op = add_function; + goto binary_op_addr; + case ZEND_SUB: + binary_op = sub_function; + goto binary_op_addr; + case ZEND_MUL: + binary_op = mul_function; + goto binary_op_addr; + case ZEND_DIV: + binary_op = div_function; + goto binary_op_addr; + case ZEND_MOD: + binary_op = mod_function; + goto binary_op_addr; + case ZEND_SL: + binary_op = shift_left_function; + goto binary_op_addr; + case ZEND_SR: + binary_op = shift_right_function; + goto binary_op_addr; + case ZEND_CONCAT: + binary_op = concat_function; + goto binary_op_addr; + case ZEND_IS_EQUAL: + binary_op = is_equal_function; + goto binary_op_addr; + case ZEND_IS_NOT_EQUAL: + binary_op = is_not_equal_function; + goto binary_op_addr; + case ZEND_IS_SMALLER: + binary_op = is_smaller_function; + goto binary_op_addr; + case ZEND_IS_SMALLER_OR_EQUAL: + binary_op = is_smaller_or_equal_function; + goto binary_op_addr; + case ZEND_BW_OR: + binary_op = bitwise_or_function; + goto binary_op_addr; + case ZEND_BW_AND: + binary_op = bitwise_and_function; + goto binary_op_addr; + case ZEND_BW_XOR: + binary_op = bitwise_xor_function; + goto binary_op_addr; + case ZEND_BOOL_XOR: + binary_op = boolean_xor_function; + /* Fall through */ +binary_op_addr: + binary_op(&Ts[opline->result.u.var].tmp_var, + get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R), + get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R) ); + FREE_OP(&opline->op1, free_op1); + FREE_OP(&opline->op2, free_op2); + break; + case ZEND_BW_NOT: + case ZEND_BOOL_NOT: + unary_op = get_unary_op(opline->opcode); + unary_op(&Ts[opline->result.u.var].tmp_var, + get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R) ); + FREE_OP(&opline->op1, free_op1); + break; + + case ZEND_ASSIGN_ADD: + binary_op = add_function; + goto binary_assign_op_addr; + case ZEND_ASSIGN_SUB: + binary_op = sub_function; + goto binary_assign_op_addr; + case ZEND_ASSIGN_MUL: + binary_op = mul_function; + goto binary_assign_op_addr; + case ZEND_ASSIGN_DIV: + binary_op = div_function; + goto binary_assign_op_addr; + case ZEND_ASSIGN_MOD: + binary_op = mod_function; + goto binary_assign_op_addr; + case ZEND_ASSIGN_SL: + binary_op = shift_left_function; + goto binary_assign_op_addr; + case ZEND_ASSIGN_SR: + binary_op = shift_right_function; + goto binary_assign_op_addr; + case ZEND_ASSIGN_CONCAT: + binary_op = concat_function; + goto binary_assign_op_addr; + case ZEND_ASSIGN_BW_OR: + binary_op = bitwise_or_function; + goto binary_assign_op_addr; + case ZEND_ASSIGN_BW_AND: + binary_op = bitwise_and_function; + goto binary_assign_op_addr; + case ZEND_ASSIGN_BW_XOR: + binary_op = bitwise_xor_function; + /* Fall through */ +binary_assign_op_addr: { + zval **var_ptr = get_zval_ptr_ptr(&opline->op1, 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)) { + Ts[opline->result.u.var].var = &EG(uninitialized_zval_ptr); + INC_AI_COUNT(&opline->result); + opline++; + continue; + } + if (!(*var_ptr)->is_ref) { + if ((*var_ptr)->refcount>1) { + zval *orig_var=*var_ptr; + + (*var_ptr)->refcount--; + *var_ptr = (zval *) emalloc(sizeof(zval)); + **var_ptr = *orig_var; + zendi_zval_copy_ctor(**var_ptr); + (*var_ptr)->refcount=1; + } + } + binary_op(*var_ptr, *var_ptr, get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R)); + Ts[opline->result.u.var].var = var_ptr; + INC_AI_COUNT(&opline->result); + FREE_OP(&opline->op2, free_op2); + } + break; + 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(&opline->op1, Ts, BP_VAR_RW); + + if (!var_ptr) { + zend_error(E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets"); + } + if (*var_ptr == EG(error_zval_ptr)) { + Ts[opline->result.u.var].var = &EG(uninitialized_zval_ptr); + INC_AI_COUNT(&opline->result); + opline++; + continue; + } + + get_incdec_op(incdec_op, opline->opcode); + + switch (opline->opcode) { + case ZEND_POST_INC: + case ZEND_POST_DEC: + Ts[opline->result.u.var].tmp_var = **var_ptr; + zendi_zval_copy_ctor(Ts[opline->result.u.var].tmp_var); + break; + } + if (!(*var_ptr)->is_ref) { + if ((*var_ptr)->refcount>1) { + zval *orig_var = *var_ptr; + + (*var_ptr)->refcount--; + *var_ptr = (zval *) emalloc(sizeof(zval)); + **var_ptr = *orig_var; + zendi_zval_copy_ctor(**var_ptr); + (*var_ptr)->refcount=1; + } + } + incdec_op(*var_ptr); + switch (opline->opcode) { + case ZEND_PRE_INC: + case ZEND_PRE_DEC: + Ts[opline->result.u.var].var = var_ptr; + INC_AI_COUNT(&opline->result); + break; + } + } + break; + case ZEND_PRINT_OP: + zend_print_variable(get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R)); + Ts[opline->result.u.var].tmp_var.value.lval = 1; + Ts[opline->result.u.var].tmp_var.type = IS_LONG; + FREE_OP(&opline->op1, free_op1); + break; + case ZEND_ECHO_OP: + zend_print_variable(get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R)); + FREE_OP(&opline->op1, free_op1); + break; + case ZEND_FETCH_R: + zend_fetch_var_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_R ELS_CC); + break; + case ZEND_FETCH_W: + zend_fetch_var_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_W ELS_CC); + break; + case ZEND_FETCH_RW: + zend_fetch_var_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_RW ELS_CC); + break; + case ZEND_FETCH_IS: + zend_fetch_var_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_IS ELS_CC); + break; + case ZEND_FETCH_DIM_R: + zend_fetch_dimension_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_R ELS_CC); + break; + case ZEND_FETCH_DIM_W: + zend_fetch_dimension_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_W ELS_CC); + break; + case ZEND_FETCH_DIM_RW: + zend_fetch_dimension_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_RW ELS_CC); + break; + case ZEND_FETCH_DIM_IS: + zend_fetch_dimension_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_IS ELS_CC); + break; + case ZEND_FETCH_OBJ_R: + zend_fetch_property_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_R ELS_CC); + break; + case ZEND_FETCH_OBJ_W: + zend_fetch_property_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_W ELS_CC); + break; + case ZEND_FETCH_OBJ_RW: + zend_fetch_property_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_RW ELS_CC); + break; + case ZEND_FETCH_OBJ_IS: + zend_fetch_property_address(&opline->result, &opline->op1, &opline->op2, Ts, BP_VAR_IS ELS_CC); + break; + case ZEND_FETCH_DIM_TMP_VAR: + zend_fetch_dimension_address_from_tmp_var(&opline->result, &opline->op1, &opline->op2, Ts ELS_CC); + break; + case ZEND_ASSIGN: { + zval *value = get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R); + + zend_assign_to_variable(&opline->result, &opline->op1, value, (free_op2?IS_TMP_VAR:opline->op2.op_type), Ts ELS_CC); + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } + break; + case ZEND_ASSIGN_REF: + zend_assign_to_variable_reference(&opline->result, get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_W), get_zval_ptr_ptr(&opline->op2, Ts, BP_VAR_W), Ts ELS_CC); + INC_AI_COUNT(&opline->result); + break; + case ZEND_JMP: +#if DEBUG_ZEND>=2 + printf("Jumping to %d\n", opline->op1.u.opline_num); +#endif + opline = &op_array->opcodes[opline->op1.u.opline_num]; + continue; + break; + case ZEND_JMPZ: { + znode *op1 = &opline->op1; + + if (!i_zend_is_true(get_zval_ptr(op1, Ts, &free_op1, BP_VAR_R))) { +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.u.opline_num); +#endif + opline = &op_array->opcodes[opline->op2.u.opline_num]; + FREE_OP(op1, free_op1); + continue; + } + FREE_OP(op1, free_op1); + } + break; + case ZEND_JMPNZ: { + znode *op1 = &opline->op1; + + if (zend_is_true(get_zval_ptr(op1, Ts, &free_op1, BP_VAR_R))) { +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.u.opline_num); +#endif + opline = &op_array->opcodes[opline->op2.u.opline_num]; + FREE_OP(op1, free_op1); + continue; + } + FREE_OP(op1, free_op1); + } + break; + case ZEND_JMPZNZ: { + znode *res = &opline->result; + + if (!zend_is_true(get_zval_ptr(res, Ts, &free_op1, BP_VAR_R))) { +#if DEBUG_ZEND>=2 + printf("Conditional jmp on false to %d\n", opline->op2.u.opline_num); +#endif + opline = &op_array->opcodes[opline->op2.u.opline_num]; + } else { +#if DEBUG_ZEND>=2 + printf("Conditional jmp on true to %d\n", opline->op1.u.opline_num); +#endif + opline = &op_array->opcodes[opline->op1.u.opline_num]; + } + FREE_OP(res, free_op1); + } + continue; + break; + case ZEND_JMPZ_EX: { + zend_op *original_opline = opline; + int retval = zend_is_true(get_zval_ptr(&original_opline->op1, Ts, &free_op1, BP_VAR_R)); + + if (!retval) { +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.u.opline_num); +#endif + opline = &op_array->opcodes[opline->op2.u.opline_num]; + FREE_OP(&original_opline->op1, free_op1); + Ts[original_opline->result.u.var].tmp_var.value.lval = retval; + Ts[original_opline->result.u.var].tmp_var.type = IS_LONG; + continue; + } + FREE_OP(&original_opline->op1, free_op1); + Ts[original_opline->result.u.var].tmp_var.value.lval = retval; + Ts[original_opline->result.u.var].tmp_var.type = IS_LONG; + } + break; + case ZEND_JMPNZ_EX: { + zend_op *original_opline = opline; + int retval = zend_is_true(get_zval_ptr(&original_opline->op1, Ts, &free_op1, BP_VAR_R)); + + if (retval) { +#if DEBUG_ZEND>=2 + printf("Conditional jmp to %d\n", opline->op2.u.opline_num); +#endif + opline = &op_array->opcodes[opline->op2.u.opline_num]; + FREE_OP(&original_opline->op1, free_op1); + Ts[original_opline->result.u.var].tmp_var.value.lval = retval; + Ts[original_opline->result.u.var].tmp_var.type = IS_LONG; + continue; + } + FREE_OP(&original_opline->op1, free_op1); + Ts[original_opline->result.u.var].tmp_var.value.lval = retval; + Ts[original_opline->result.u.var].tmp_var.type = IS_LONG; + } + break; + case ZEND_FREE: + zendi_zval_dtor(Ts[opline->op1.u.var].tmp_var); + break; + case ZEND_INIT_STRING: + Ts[opline->result.u.var].tmp_var.value.str.val = emalloc(1); + Ts[opline->result.u.var].tmp_var.value.str.val[0] = 0; + Ts[opline->result.u.var].tmp_var.value.str.len = 0; + Ts[opline->result.u.var].tmp_var.refcount = 1; + break; + case ZEND_ADD_CHAR: + add_char_to_string( &Ts[opline->result.u.var].tmp_var, + get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_NA), + &opline->op2.u.constant); + /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */ + break; + case ZEND_ADD_STRING: + add_string_to_string( &Ts[opline->result.u.var].tmp_var, + get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_NA), + &opline->op2.u.constant); + /* FREE_OP is missing intentionally here - we're always working on the same temporary variable */ + break; + case ZEND_ADD_VAR: { + zval *var = get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R); + zval var_copy; + int destroy=0; + + if (var->type != IS_STRING) { + var_copy = *var; + zval_copy_ctor(&var_copy); + var = &var_copy; + convert_to_string(var); + destroy=1; + } + add_string_to_string( &Ts[opline->result.u.var].tmp_var, + get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_NA), + var); + if (destroy) { + 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()'s anyway, unless they're + * string offsets or overloaded objects + */ + FREE_OP(&opline->op2, free_op2); + } + break; + case ZEND_INIT_FCALL_BY_NAME: { + zval *function_name = get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R); + zend_function *function; + HashTable *active_function_table; + zval tmp; + + 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); + + if (opline->op1.op_type != IS_UNUSED) { + if (opline->op1.op_type==IS_CONST) { /* used for class_name::function() */ + zend_class_entry *ce; + + if (zend_hash_find(EG(class_table), opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len+1, (void **) &ce)==FAILURE) { + zend_error(E_ERROR, "Undefined class name '%s'", opline->op1.u.constant.value.str.val); + } + active_function_table = &ce->function_table; + if (zend_hash_find(EG(active_symbol_table), "this", sizeof("this"), (void **) &object_ptr)==FAILURE) { + object_ptr=NULL; + } + } else { /* used for member function calls */ + object_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_R); + + if (opline->op1.op_type==IS_VAR + && opline>EG(active_op_array)->opcodes + && (opline-1)->opcode == ZEND_JMP_NO_CTOR) { + /* constructor call */ + EG(AiCount)++; + } + + if (!object_ptr || (*object_ptr)->value.obj.ce->handle_function_call) { /* overloaded function call */ + zend_overloaded_element overloaded_element; + zend_property_reference *property_reference; + + overloaded_element.element = *function_name; + overloaded_element.type = IS_METHOD; + + if (object_ptr) { + zend_property_reference property_reference; + + if ((*object_ptr)->type != IS_OBJECT) { + zend_error(E_ERROR, "Call to a member function on a non-object"); + } + + property_reference.object = object_ptr; + property_reference.type = BP_VAR_NA; + zend_llist_init(&property_reference.elements_list, sizeof(zend_overloaded_element), NULL, 0); + zend_stack_push(&EG(overloaded_objects_stack), &property_reference, sizeof(zend_property_reference)); + } + zend_stack_top(&EG(overloaded_objects_stack), (void **) &property_reference); + zend_llist_add_element(&property_reference->elements_list, &overloaded_element); + function_being_called = (zend_function *) emalloc(sizeof(zend_function)); + function_being_called->type = ZEND_OVERLOADED_FUNCTION; + function_being_called->common.arg_types = NULL; + goto overloaded_function_call_cont; + } + + if ((*object_ptr)->type != IS_OBJECT) { + zend_error(E_ERROR, "Call to a member function on a non-object"); + } + active_function_table = &(*object_ptr)->value.obj.ce->function_table; + } + } else { /* function pointer */ + object_ptr = NULL; + active_function_table = EG(function_table); + } + if (zend_hash_find(active_function_table, function_name->value.str.val, function_name->value.str.len+1, (void **) &function)==FAILURE) { + zend_error(E_ERROR, "Call to undefined function: %s()\n", function_name->value.str.val); + } + zval_dtor(&tmp); + function_being_called = function; +overloaded_function_call_cont: + zend_ptr_stack_push(&EG(arg_types_stack), function_being_called); + FREE_OP(&opline->op2, free_op2); + } + goto init_by_name_cont; + break; + case ZEND_INIT_FCALL: + object_ptr=NULL; + function_being_called=NULL; +init_by_name_cont: + zend_ptr_stack_push(&EG(function_symbol_table_stack), function_state.function_symbol_table); + if (EG(symtable_cache_ptr)>=EG(symtable_cache)) { + //printf("Cache hit! Reusing %x\n", symtable_cache[symtable_cache_ptr]); + function_state.function_symbol_table = *(EG(symtable_cache_ptr)--); + } else { + function_state.function_symbol_table = (HashTable *) emalloc(sizeof(HashTable)); + zend_hash_init(function_state.function_symbol_table, 0, NULL, PVAL_PTR_DTOR, 0); + //printf("Cache miss! Initialized %x\n", function_state.function_symbol_table); + } + if (object_ptr && function_being_called && function_being_called->type!=ZEND_OVERLOADED_FUNCTION) { + zval *dummy = (zval *) emalloc(sizeof(zval)), **this_ptr; + + var_uninit(dummy); + dummy->refcount=1; + dummy->is_ref=0; + zend_hash_update_ptr(function_state.function_symbol_table, "this", sizeof("this"), dummy, sizeof(zval *), (void **) &this_ptr); + zend_assign_to_variable_reference(NULL, this_ptr, object_ptr, NULL ELS_CC); + object_ptr = NULL; + } + break; + case ZEND_DO_FCALL: + if (function_being_called) { + function_state.function = function_being_called; + } else { + zval *fname = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); + + if (zend_hash_find(EG(function_table), fname->value.str.val, fname->value.str.len+1, (void **) &function_state.function)==FAILURE) { + zend_error(E_ERROR, "Unknown function: %s()\n", fname->value.str.val); + } + FREE_OP(&opline->op1, free_op1); + } + { + zval *original_return_value; + + if (function_being_called) { + function_being_called = zend_ptr_stack_pop(&EG(arg_types_stack)); + } + calling_symbol_table = EG(active_symbol_table); + EG(active_symbol_table) = function_state.function_symbol_table; + if (function_state.function->type==ZEND_INTERNAL_FUNCTION) { + var_uninit(&Ts[opline->result.u.var].tmp_var); + ((zend_internal_function *) function_state.function)->handler(EG(active_symbol_table), &Ts[opline->result.u.var].tmp_var, &EG(regular_list), &EG(persistent_list)); + } else if (function_state.function->type==ZEND_USER_FUNCTION) { + original_return_value = EG(return_value); + EG(return_value) = &Ts[opline->result.u.var].tmp_var; + var_uninit(EG(return_value)); + EG(active_op_array) = (zend_op_array *) function_state.function; + zend_execute(EG(active_op_array) ELS_CC); + EG(opline_ptr) = &opline; + EG(active_op_array) = op_array; + EG(return_value)=original_return_value; + } else { /* ZEND_OVERLOADED_FUNCTION */ + call_overloaded_function(EG(active_symbol_table), &Ts[opline->result.u.var].tmp_var, &EG(regular_list), &EG(persistent_list)); + efree(function_being_called); + } + function_state.function = (zend_function *) op_array; + EG(active_symbol_table) = calling_symbol_table; + if (EG(symtable_cache_ptr)>=EG(symtable_cache_limit)) { + zend_hash_destroy(function_state.function_symbol_table); + efree(function_state.function_symbol_table); + } else { + *(++EG(symtable_cache_ptr)) = function_state.function_symbol_table; + zend_hash_clean(*EG(symtable_cache_ptr)); + } + EG(function_state_ptr) = &function_state; + function_state.function_symbol_table = zend_ptr_stack_pop(&EG(function_symbol_table_stack)); + } + break; + case ZEND_RETURN: { + zval *retval = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); + + *EG(return_value) = *retval; + if (!free_op1) { + zendi_zval_copy_ctor(*EG(return_value)); + } + //return_value->refcount=1; + //return_value->is_ref=0; +#if SUPPORT_INTERACTIVE + op_array->last_executed_op_number = opline-op_array->opcodes; +#endif + free_alloca(Ts); + return; + } + break; + case ZEND_SEND_VAL: + if (function_being_called + && function_being_called->common.arg_types + && opline->op2.u.opline_numcommon.arg_types[0] + && function_being_called->common.arg_types[1+opline->op2.u.opline_num]==BYREF_FORCE) { + zend_error(E_ERROR, "Cannot pass parameter %d by reference", opline->op2.u.opline_num); + } + { + zval *valptr = (zval *) emalloc(sizeof(zval)); + + *valptr = Ts[opline->op1.u.var].tmp_var; + valptr->refcount=1; + valptr->is_ref=0; + zend_hash_next_index_insert_ptr(function_state.function_symbol_table, valptr, sizeof(zval *), NULL); + } + break; + case ZEND_SEND_VAR: + if (function_being_called + && function_being_called->common.arg_types + && opline->op2.u.opline_numcommon.arg_types[0] + && function_being_called->common.arg_types[1+opline->op2.u.opline_num]==BYREF_FORCE) { + goto send_by_ref; + } + { + zval *varptr = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); + + if (varptr == &EG(uninitialized_zval)) { + varptr = (zval *) emalloc(sizeof(zval)); + var_uninit(varptr); + varptr->refcount=0; + varptr->is_ref=0; + } else if (varptr->is_ref) { + zval *original_var = varptr; + + varptr = (zval *) emalloc(sizeof(zval)); + *varptr = *original_var; + varptr->is_ref = 0; + varptr->refcount = 0; + zval_copy_ctor(varptr); + } + varptr->refcount++; + zend_hash_next_index_insert_ptr(function_state.function_symbol_table, varptr, sizeof(zval *), NULL); + } + break; +send_by_ref: + case ZEND_SEND_REF: { + zval **varptr_ptr = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_W); + zval *varptr = *varptr_ptr; + + if (!varptr->is_ref) { + /* code to break away this variable */ + if (varptr->refcount>1) { + *varptr_ptr = (zval *) emalloc(sizeof(zval)); + **varptr_ptr = *varptr; + varptr = *varptr_ptr; + varptr->refcount = 1; + } + varptr->is_ref = 1; + /* at the end of this code refcount is always 1 */ + } + varptr->refcount++; + zend_hash_next_index_insert_ptr(function_state.function_symbol_table, varptr, sizeof(zval *), NULL); + } + break; + case ZEND_RECV: { + zval **param; + + if (zend_hash_index_find(EG(active_symbol_table), opline->op1.u.constant.value.lval, (void **) ¶m)==FAILURE) { + zend_error(E_NOTICE, "Missing argument %d for %s()\n", opline->op1.u.constant.value.lval, get_active_function_name()); + } else if ((*param)->is_ref) { + zend_assign_to_variable_reference(NULL, get_zval_ptr_ptr(&opline->result, Ts, BP_VAR_W), param, NULL ELS_CC); + } else { + zend_assign_to_variable(NULL, &opline->result, *param, IS_VAR, Ts ELS_CC); + } + } + break; + case ZEND_RECV_INIT: { + zval **param, *assignment_value; + + if (zend_hash_index_find(EG(active_symbol_table), opline->op1.u.constant.value.lval, (void **) ¶m)==FAILURE) { + if (opline->op2.u.constant.type == IS_CONSTANT) { + zval *default_value = (zval *) emalloc(sizeof(zval)); + zval tmp; + + *default_value = opline->op2.u.constant; + if (!zend_get_constant(default_value->value.str.val, default_value->value.str.len, &tmp)) { + default_value->type = IS_STRING; + zval_copy_ctor(default_value); + } else { + *default_value = tmp; + } + default_value->refcount=0; + default_value->is_ref=0; + param = &default_value; + assignment_value = default_value; + } else { + param = NULL; + assignment_value = &opline->op2.u.constant; + } + } else { + assignment_value = *param; + } + + if (assignment_value->is_ref) { + zend_assign_to_variable_reference(NULL, get_zval_ptr_ptr(&opline->result, Ts, BP_VAR_W), param, NULL ELS_CC); + } else { + zend_assign_to_variable(NULL, &opline->result, assignment_value, IS_VAR, Ts ELS_CC); + } + } + break; + case ZEND_BOOL: + /* PHP 3.0 returned "" for false and 1 for true, here we use 0 and 1 for now */ + Ts[opline->result.u.var].tmp_var.value.lval = zend_is_true(get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R)); + Ts[opline->result.u.var].tmp_var.type = IS_LONG; + FREE_OP(&opline->op1, free_op1); + break; + case ZEND_BRK: + case ZEND_CONT: { + zval *nest_levels_zval = get_zval_ptr(&opline->op2, Ts, &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 = opline->op1.u.opline_num; + do { + if (array_offset==-1) { + zend_error(E_ERROR, "Cannot break/continue %d levels\n", original_nest_levels); + } + jmp_to = &op_array->brk_cont_array[array_offset]; + array_offset = jmp_to->parent; + } while (--nest_levels > 0); + + if (opline->opcode == ZEND_BRK) { + opline = op_array->opcodes+jmp_to->brk; + // printf("Jumping to %d\n", jmp_to->brk); + } else { + opline = op_array->opcodes+jmp_to->cont; + // printf("Jumping to %d\n", jmp_to->cont); + } + FREE_OP(&opline->op2, free_op2); + continue; + } + break; + case ZEND_CASE: + is_equal_function(&Ts[opline->result.u.var].tmp_var, + get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R), + get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R) ); + FREE_OP(&opline->op2, free_op2); + break; + case ZEND_NEW: { + zval *tmp = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); + zval class_name; + zend_class_entry *ce; + + class_name = *tmp; + zval_copy_ctor(&class_name); + convert_to_string(&class_name); + zend_str_tolower(class_name.value.str.val, class_name.value.str.len); + + if (zend_hash_find(EG(class_table), class_name.value.str.val, class_name.value.str.len+1, (void **) &ce)==FAILURE) { + zend_error(E_ERROR, "Cannot instanciate non-existant class: %s", class_name.value.str.val); + } + object_init_ex(&Ts[opline->result.u.var].tmp_var, ce); + + zval_dtor(&class_name); + FREE_OP(&opline->op1, free_op1); + } + break; + case ZEND_FETCH_CONSTANT: + if (!zend_get_constant(opline->op1.u.constant.value.str.val, opline->op1.u.constant.value.str.len, &Ts[opline->result.u.var].tmp_var)) { + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", + opline->op1.u.constant.value.str.val, + opline->op1.u.constant.value.str.val); + Ts[opline->result.u.var].tmp_var = opline->op1.u.constant; + zval_copy_ctor(&Ts[opline->result.u.var].tmp_var); + } + break; + case ZEND_INIT_ARRAY: + case ZEND_ADD_ARRAY_ELEMENT: { + zval *array_ptr = &Ts[opline->result.u.var].tmp_var; + zval *expr=get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); + zval *offset=get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R); + + if (opline->opcode==ZEND_INIT_ARRAY) { + array_init(array_ptr); + if (!expr) { + break; + } + } + if (free_op1) { /* temporary variable */ + zval *new_expr = (zval *) emalloc(sizeof(zval)); + + *new_expr = *expr; + expr = new_expr; + expr->refcount=1; + expr->is_ref=0; + } else { + if (expr->is_ref) { + zval *new_expr = (zval *) emalloc(sizeof(zval)); + + *new_expr = *expr; + expr = new_expr; + zendi_zval_copy_ctor(*expr); + expr->refcount=1; + expr->is_ref=0; + } else { + expr->refcount++; + } + } + if (offset) { + switch(offset->type) { + case IS_DOUBLE: + zend_hash_index_update(array_ptr->value.ht, (long) offset->value.lval, &expr, sizeof(zval *), NULL); + break; + case IS_LONG: + zend_hash_index_update(array_ptr->value.ht, offset->value.lval, &expr, sizeof(zval *), NULL); + break; + case IS_STRING: + zend_hash_update(array_ptr->value.ht, offset->value.str.val, offset->value.str.len+1, &expr, sizeof(zval *), NULL); + break; + default: + /* do nothing */ + break; + } + FREE_OP(&opline->op2, free_op2); + } else { + zend_hash_next_index_insert(array_ptr->value.ht, &expr, sizeof(zval *), NULL); + } + } + break; + case ZEND_CAST: { + zval *expr = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); + zval *result = &Ts[opline->result.u.var].tmp_var; + + *result = *expr; + if (!free_op1) { + zendi_zval_copy_ctor(*result); + } + switch (opline->op2.u.constant.type) { + 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; + } + } + break; + case ZEND_INCLUDE_OR_EVAL: { + zend_op_array *new_op_array=NULL; + zval *original_return_value = EG(return_value); + CLS_FETCH(); + + switch (opline->op2.u.constant.value.lval) { + case ZEND_INCLUDE: + new_op_array = compile_filename(get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R) CLS_CC); + break; + case ZEND_EVAL: + new_op_array = compile_string(get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R) CLS_CC); + break; + } + if (new_op_array) { + Ts[opline->result.u.var].tmp_var.value.lval = 1; + Ts[opline->result.u.var].tmp_var.type = IS_LONG; + EG(return_value) = &Ts[opline->result.u.var].tmp_var; + EG(active_op_array) = new_op_array; + zend_execute(new_op_array ELS_CC); + + EG(opline_ptr) = &opline; + EG(active_op_array) = op_array; + EG(function_state_ptr) = &function_state; + destroy_op_array(new_op_array); + efree(new_op_array); + } else { + var_uninit(&Ts[opline->result.u.var].tmp_var); + } + EG(return_value) = original_return_value; + FREE_OP(&opline->op1, free_op1); + } + break; + case ZEND_UNSET_VAR: { + zval tmp, *variable = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); + + if (variable->type != IS_STRING) { + tmp = *variable; + zval_copy_ctor(&tmp); + convert_to_string(&tmp); + variable = &tmp; + } + + zend_hash_del(EG(active_symbol_table), variable->value.str.val, variable->value.str.len+1); + + if (variable == &tmp) { + zval_dtor(&tmp); + } + FREE_OP(&opline->op1, free_op1); + } + break; + case ZEND_UNSET_DIM_OBJ: { + zval **container = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_R); + zval *offset = get_zval_ptr(&opline->op2, Ts, &free_op2, BP_VAR_R); + + if (container) { + HashTable *ht; + + switch ((*container)->type) { + case IS_ARRAY: + ht = (*container)->value.ht; + break; + case IS_OBJECT: + ht = (*container)->value.obj.properties; + break; + default: + ht = NULL; + break; + } + if (ht) { + switch (offset->type) { + case IS_LONG: + zend_hash_index_del(ht, offset->value.lval); + break; + case IS_STRING: + zend_hash_del(ht, offset->value.str.val, offset->value.str.len+1); + break; + } + } + } else { + /* overloaded element */ + } + FREE_OP(&opline->op2, free_op2); + } + break; + case ZEND_FE_RESET: { + zval *array = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); + + Ts[opline->result.u.var].tmp_var = *array; + array = &Ts[opline->result.u.var].tmp_var; + if (!free_op1) { + zval_copy_ctor(array); + } + if (array->type == IS_ARRAY) { + /* probably redundant */ + zend_hash_internal_pointer_reset(array->value.ht); + } else { + /* JMP to the end of foreach - TBD */ + } + } + break; + case ZEND_FE_FETCH: { + zval *array = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); + zval *result = &Ts[opline->result.u.var].tmp_var; + zval **value, *key; + char *str_key; + ulong int_key; + + if (zend_hash_get_current_data(array->value.ht, (void **) &value)==FAILURE) { + opline = op_array->opcodes+opline->op2.u.opline_num; + continue; + } + array_init(result); + + + (*value)->refcount++; + zend_hash_index_update(result->value.ht, 0, value, sizeof(zval *), NULL); + + key = (zval *) emalloc(sizeof(zval)); + key->refcount=1; + key->is_ref=0; + switch (zend_hash_get_current_key(array->value.ht, &str_key, &int_key)) { + 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; + } + zend_hash_index_update(result->value.ht, 1, &key, sizeof(zval *), NULL); + zend_hash_move_forward(array->value.ht); + } + break; + case ZEND_JMP_NO_CTOR: { + zval *object = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); + + EG(AiCount)++; + if (!object->value.obj.ce->handle_function_call + && !zend_hash_exists(&object->value.obj.ce->function_table, object->value.obj.ce->name, object->value.obj.ce->name_length+1)) { + opline = op_array->opcodes + opline->op2.u.opline_num; + continue; + } + } + break; + case ZEND_ISSET_ISEMPTY: { + zval **var = get_zval_ptr_ptr(&opline->op1, Ts, BP_VAR_IS); + int isset; + + if (var==&EG(uninitialized_zval_ptr) + || ((*var)->type == IS_STRING && (*var)->value.str.val == undefined_variable_string)) { + isset = 0; + } else { + isset = 1; + } + + switch (opline->op2.u.constant.value.lval) { + case ZEND_ISSET: + Ts[opline->result.u.var].tmp_var.value.lval = isset; + break; + case ZEND_ISEMPTY: + if (!isset || !zend_is_true(*var)) { + Ts[opline->result.u.var].tmp_var.value.lval = 1; + } else { + Ts[opline->result.u.var].tmp_var.value.lval = 0; + } + break; + } + Ts[opline->result.u.var].tmp_var.type = IS_BOOL; + } + break; + case ZEND_EXIT: + if (opline->op1.op_type != IS_UNUSED) { + zend_print_variable(get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R)); + FREE_OP(&opline->op1, free_op1); + } + zend_bailout(); + break; + case ZEND_BEGIN_SILENCE: + Ts[opline->result.u.var].tmp_var.value.lval = EG(error_reporting); + Ts[opline->result.u.var].tmp_var.type = IS_LONG; /* shouldn't be necessary */ + EG(error_reporting) = 0; + break; + case ZEND_END_SILENCE: + EG(error_reporting) = Ts[opline->op1.u.var].tmp_var.value.lval; + break; + case ZEND_QM_ASSIGN: { + zval *value = get_zval_ptr(&opline->op1, Ts, &free_op1, BP_VAR_R); + + Ts[opline->result.u.var].tmp_var = *value; + if (!free_op1) { + zval_copy_ctor(&Ts[opline->result.u.var].tmp_var); + } + } + break; + case ZEND_EXT_STMT: + if (!EG(no_extensions)) { + zend_llist_apply_with_argument(&zend_extensions, (void (*)(void *, void *)) zend_extension_statement_handler, op_array); + } + break; + case ZEND_EXT_FCALL_BEGIN: + if (!EG(no_extensions)) { + zend_llist_apply_with_argument(&zend_extensions, (void (*)(void *, void *)) zend_extension_fcall_begin_handler, op_array); + } + break; + case ZEND_EXT_FCALL_END: + if (!EG(no_extensions)) { + zend_llist_apply_with_argument(&zend_extensions, (void (*)(void *, void *)) zend_extension_fcall_end_handler, op_array); + } + break; + case ZEND_EXT_NOP: + case ZEND_NOP: + break; + default: + break; + } + opline++; + } +#if SUPPORT_INTERACTIVE + op_array->last_executed_op_number = opline-op_array->opcodes; +#endif + free_alloca(Ts); +} diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h new file mode 100644 index 0000000000000..d09d42caaa56b --- /dev/null +++ b/Zend/zend_execute.h @@ -0,0 +1,67 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _EXECUTE_H +#define _EXECUTE_H + +#include "zend_compile.h" +#include "zend_hash.h" + +typedef union { + zval tmp_var; + zval **var; + struct { + zval **var_dummy; /* a dummy */ + + zval *str; + int offset; + unsigned char type; + } EA; +} temp_variable; + + +ZEND_API extern void (*zend_execute)(zend_op_array *op_array ELS_DC); + +void init_executor(CLS_D ELS_DC); +void shutdown_executor(ELS_D); +void execute(zend_op_array *op_array ELS_DC); +ZEND_API int zend_is_true(zval *op); +ZEND_API inline void safe_free_zval_ptr(zval *p); +ZEND_API void zend_eval_string(char *str, zval *retval CLS_DC ELS_DC); +ZEND_API inline int i_zend_is_true(zval *op); +ZEND_API void zval_update_constant(zval *p); +ZEND_API inline void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, zval **value_ptr_ptr, temp_variable *Ts ELS_DC); + +#if SUPPORT_INTERACTIVE +void execute_new_code(CLS_D); +#endif + + +/* services */ +ZEND_API char *get_active_function_name(); +ZEND_API char *zend_get_executed_filename(ELS_D); +ZEND_API uint zend_get_executed_lineno(ELS_D); + +#define zendi_zval_copy_ctor(p) zval_copy_ctor(&(p)) +#define zendi_zval_dtor(p) zval_dtor(&(p)) + +#define active_opline (*EG(opline_ptr)) + + +#define IS_OVERLOADED_OBJECT 1 +#define IS_STRING_OFFSET 2 + +#endif /* _EXECUTE_H */ diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c new file mode 100644 index 0000000000000..dc16c62e07ff1 --- /dev/null +++ b/Zend/zend_execute_API.c @@ -0,0 +1,446 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include +#include + +#include "zend.h" +#include "zend_compile.h" +#include "zend_execute.h" +#include "zend_API.h" +#include "zend_ptr_stack.h" +#include "zend_variables.h" +#include "zend_operators.h" +#include "zend_constants.h" +#include "zend_extensions.h" + + +ZEND_API void (*zend_execute)(zend_op_array *op_array ELS_DC); + + +static void (*original_sigsegv_handler)(int); +static void zend_handle_sigsegv(int dummy) +{ + fflush(stdout); + signal(SIGSEGV, original_sigsegv_handler); +/* + printf("SIGSEGV caught on opcode %d on opline %d of %s() at %s:%d\n\n", + active_opline->opcode, + active_opline-EG(active_op_array)->opcodes, + get_active_function_name(), + zend_get_executed_filename(), + zend_get_executed_lineno()); + original_sigsegv_handler(dummy); +*/ +} + + +static void zend_extension_activator(zend_extension *extension) +{ + if (extension->activate) { + extension->activate(); + } +} + + +static void zend_extension_deactivator(zend_extension *extension) +{ + if (extension->deactivate) { + extension->deactivate(); + } +} + + +void init_executor(CLS_D ELS_DC) +{ + var_uninit(&EG(uninitialized_zval)); + var_uninit(&EG(error_zval)); + EG(uninitialized_zval).refcount = 1; + EG(uninitialized_zval).is_ref=0; + EG(uninitialized_zval_ptr)=&EG(uninitialized_zval); + EG(error_zval).refcount = 1; + EG(error_zval).is_ref=0; + EG(error_zval_ptr)=&EG(error_zval); + zend_ptr_stack_init(&EG(function_symbol_table_stack)); + zend_ptr_stack_init(&EG(arg_types_stack)); + zend_stack_init(&EG(overloaded_objects_stack)); + original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv); + EG(return_value) = &EG(global_return_value); + EG(symtable_cache_ptr) = EG(symtable_cache)-1; + EG(symtable_cache_limit)=EG(symtable_cache)+SYMTABLE_CACHE_SIZE-1; + EG(no_extensions)=0; + + EG(function_table) = CG(function_table); + EG(class_table) = CG(class_table); + + EG(AiCount) = 0; + zend_ptr_stack_init(&EG(garbage)); + + EG(main_op_array) = NULL; + zend_hash_init(&EG(symbol_table), 50, NULL, PVAL_PTR_DTOR, 0); + EG(active_symbol_table) = &EG(symbol_table); + + zend_llist_apply(&zend_extensions, (void (*)(void *)) zend_extension_activator); + + /* $GLOBALS array */ + { + zval *globals = (zval *) emalloc(sizeof(zval)); + + globals->value.ht = &EG(symbol_table); + globals->type = IS_ARRAY; + globals->refcount = 1; + globals->is_ref = 0; + zend_hash_update(&EG(symbol_table), "GLOBALS", sizeof("GLOBALS"), &globals, sizeof(zval *), NULL); + } +} + + +void shutdown_executor(ELS_D) +{ + zend_ptr_stack_destroy(&EG(function_symbol_table_stack)); + zend_ptr_stack_destroy(&EG(arg_types_stack)); + zend_stack_destroy(&EG(overloaded_objects_stack)); + + 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, (void (*)(void *)) zend_extension_deactivator); + zend_ptr_stack_destroy(&EG(garbage)); + + zend_hash_destroy(&EG(symbol_table)); + + if (EG(main_op_array)) { + destroy_op_array(EG(main_op_array)); + efree(EG(main_op_array)); + } + clean_non_persistent_constants(); +} + + +ZEND_API char *get_active_function_name(ELS_D) +{ + switch(EG(function_state_ptr)->function->type) { + case ZEND_USER_FUNCTION: { + char *function_name = ((zend_op_array *) EG(function_state_ptr)->function)->function_name; + + if (function_name) { + return function_name; + } else { + return "main"; + } + } + break; + case ZEND_INTERNAL_FUNCTION: + return ((zend_internal_function *) EG(function_state_ptr)->function)->function_name; + break; + default: + return NULL; + } +} + + +ZEND_API char *zend_get_executed_filename(ELS_D) +{ + return active_opline->filename; +} + + +ZEND_API uint zend_get_executed_lineno(ELS_D) +{ + return active_opline->lineno; +} + + +ZEND_API inline void safe_free_zval_ptr(zval *p) +{ + ELS_FETCH(); + + if (p!=EG(uninitialized_zval_ptr)) { + efree(p); + } +} + + +ZEND_API void zval_ptr_dtor(zval **zval_ptr) +{ +#if DEBUG_ZEND>=2 + printf("Reducing refcount for %x (%x): %d->%d\n", *zval_ptr, zval_ptr, (*zval_ptr)->refcount, (*zval_ptr)->refcount-1); +#endif + (*zval_ptr)->refcount--; + if ((*zval_ptr)->refcount==0) { + zval_dtor(*zval_ptr); + safe_free_zval_ptr(*zval_ptr); + } +} + + +ZEND_API inline int i_zend_is_true(zval *op) +{ + int result; + + switch (op->type) { + case IS_LONG: + case IS_BOOL: + case IS_RESOURCE: + result = (op->value.lval?1:0); + break; + case IS_DOUBLE: + result = (op->value.dval ? 1 : 0); + break; + case IS_STRING: + if (op->value.str.len == 0 + || (op->value.str.len==1 && op->value.str.val[0]=='0')) { + result = 0; + } else { + result = 1; + } + break; + case IS_ARRAY: + result = (zend_hash_num_elements(op->value.ht)?1:0); + break; + case IS_OBJECT: + result = (zend_hash_num_elements(op->value.obj.properties)?1:0); + break; + default: + result = 0; + break; + } + return result; +} + + +ZEND_API int zend_is_true(zval *op) +{ + return i_zend_is_true(op); +} + + +ZEND_API void zval_update_constant(zval *p) +{ + if (p->type == IS_CONSTANT) { + zval c; + + if (!zend_get_constant(p->value.str.val, p->value.str.len, &c)) { + zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'", + p->value.str.val, + p->value.str.val); + p->type = IS_STRING; + } else { + STR_FREE(p->value.str.val); + *p = c; + } + p->refcount = 1; + p->is_ref = 0; + } +} + +int call_user_function(HashTable *function_table, zval *object, zval *function_name, zval *retval, int param_count, zval *params[]) +{ + 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; + zval *this=NULL; + CLS_FETCH(); + ELS_FETCH(); + + if (object) { + if (object->type != IS_OBJECT) { + return FAILURE; + } + function_table = &object->value.obj.ce->function_table; + /* unimplemented */ + } + original_function_state_ptr = EG(function_state_ptr); + zend_str_tolower(function_name->value.str.val, function_name->value.str.len); + if (zend_hash_find(function_table, function_name->value.str.val, function_name->value.str.len+1, (void **) &function_state.function)==FAILURE) { + zend_error(E_ERROR, "Unknown function: %s()\n", function_name->value.str.val); + return FAILURE; + } + + zend_ptr_stack_push(&EG(function_symbol_table_stack), function_state.function_symbol_table); + function_state.function_symbol_table = (HashTable *) emalloc(sizeof(HashTable)); + zend_hash_init(function_state.function_symbol_table, 0, NULL, PVAL_PTR_DTOR, 0); + + for (i=0; irefcount=1; + param->is_ref=0; + zval_copy_ctor(param); + zend_hash_next_index_insert_ptr(function_state.function_symbol_table, param, sizeof(zval *), NULL); + } + + if (object) { + zval *dummy = (zval *) emalloc(sizeof(zval)), **this_ptr; + + var_uninit(dummy); + dummy->refcount=1; + dummy->is_ref=0; + zend_hash_update_ptr(function_state.function_symbol_table, "this", sizeof("this"), dummy, sizeof(zval *), (void **) &this_ptr); + zend_assign_to_variable_reference(NULL, this_ptr, &object, NULL ELS_CC); + } + + calling_symbol_table = EG(active_symbol_table); + EG(active_symbol_table) = function_state.function_symbol_table; + var_uninit(retval); + if (function_state.function->type == ZEND_USER_FUNCTION) { + original_return_value = EG(return_value); + original_op_array = EG(active_op_array); + EG(return_value) = retval; + EG(active_op_array) = (zend_op_array *) function_state.function; + original_opline_ptr = EG(opline_ptr); + zend_execute(EG(active_op_array) ELS_CC); + EG(active_op_array) = original_op_array; + EG(return_value)=original_return_value; + EG(opline_ptr) = original_opline_ptr; + } else { + ((zend_internal_function *) function_state.function)->handler(EG(active_symbol_table), retval, &EG(regular_list), &EG(persistent_list)); + } + zend_hash_destroy(EG(active_symbol_table)); + efree(EG(active_symbol_table)); + EG(active_symbol_table) = calling_symbol_table; + EG(function_state_ptr) = original_function_state_ptr; + function_state.function_symbol_table = zend_ptr_stack_pop(&EG(function_symbol_table_stack)); + + return SUCCESS; +} + + +ZEND_API void zend_eval_string(char *str, zval *retval CLS_DC ELS_DC) +{ + zval pv; + zend_op_array *new_op_array; + zend_op_array *original_active_op_array = EG(active_op_array); + zend_function_state *original_function_state_ptr = EG(function_state_ptr); + int original_handle_op_arrays; + + if (retval) { + pv.value.str.len = strlen(str)+sizeof("return ;")-1; + pv.value.str.val = emalloc(pv.value.str.len+1); + strcpy(pv.value.str.val, "return "); + strcat(pv.value.str.val, str); + strcat(pv.value.str.val, " ;"); + } else { + pv.value.str.len = strlen(str); + pv.value.str.val = estrndup(str, pv.value.str.len); + } + pv.type = IS_STRING; + + /*printf("Evaluating '%s'\n", pv.value.str.val);*/ + + original_handle_op_arrays = CG(handle_op_arrays); + CG(handle_op_arrays) = 0; + new_op_array = compile_string(&pv CLS_CC); + CG(handle_op_arrays) = original_handle_op_arrays; + + if (new_op_array) { + zval dummy_retval; + zval *original_return_value = EG(return_value); + zend_op **original_opline_ptr = EG(opline_ptr); + + EG(return_value) = (retval?retval:&dummy_retval); + var_reset(EG(return_value)); + EG(active_op_array) = new_op_array; + EG(no_extensions)=1; + zend_execute(new_op_array ELS_CC); + EG(no_extensions)=0; + EG(opline_ptr) = original_opline_ptr; + EG(active_op_array) = original_active_op_array; + EG(function_state_ptr) = original_function_state_ptr; + destroy_op_array(new_op_array); + efree(new_op_array); + EG(return_value) = original_return_value; + if (!retval) { + zval_dtor(&dummy_retval); + } + } else { + printf("Failed executing:\n%s\n", str); + } + zval_dtor(&pv); +} + + +ZEND_API inline void zend_assign_to_variable_reference(znode *result, zval **variable_ptr_ptr, zval **value_ptr_ptr, temp_variable *Ts ELS_DC) +{ + zval *variable_ptr = *variable_ptr_ptr; + zval *value_ptr; + + + if (!value_ptr_ptr) { + zend_error(E_ERROR, "Cannot create references to string offsets nor overloaded objects"); + return; + } + + value_ptr = *value_ptr_ptr; + if (variable_ptr == EG(error_zval_ptr) || value_ptr==EG(error_zval_ptr)) { + variable_ptr_ptr = &EG(uninitialized_zval_ptr); + } else if (variable_ptr!=value_ptr) { + variable_ptr->refcount--; + if (variable_ptr->refcount==0) { + zendi_zval_dtor(*variable_ptr); + efree(variable_ptr); + } + + if (!value_ptr->is_ref) { + /* break it away */ + value_ptr->refcount--; + if (value_ptr->refcount>0) { + *value_ptr_ptr = (zval *) emalloc(sizeof(zval)); + **value_ptr_ptr = *value_ptr; + value_ptr = *value_ptr_ptr; + zendi_zval_copy_ctor(*value_ptr); + } + value_ptr->refcount=1; + value_ptr->is_ref=1; + } + + *variable_ptr_ptr = value_ptr; + value_ptr->refcount++; + } else { + /* nothing to do */ + } + + if (result && (result->op_type != IS_UNUSED)) { + Ts[result->u.var].var = variable_ptr_ptr; + } +} + + +#if SUPPORT_INTERACTIVE +void execute_new_code(CLS_D) +{ + ELS_FETCH(); + + if (!EG(interactive) + || CG(active_op_array)->backpatch_count>0) { + + return; + } + CG(active_op_array)->start_op_number = CG(active_op_array)->last_executed_op_number; + CG(active_op_array)->end_op_number = CG(active_op_array)->last; + EG(active_op_array) = CG(active_op_array); + zend_execute(CG(active_op_array) ELS_CC); + CG(active_op_array)->start_op_number = CG(active_op_array)->last_executed_op_number; +} +#endif diff --git a/Zend/zend_extensions.c b/Zend/zend_extensions.c new file mode 100644 index 0000000000000..fe63768dba9ec --- /dev/null +++ b/Zend/zend_extensions.c @@ -0,0 +1,123 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include "zend_extensions.h" + +ZEND_API zend_llist zend_extensions; +static int last_resource_number; + +int zend_load_extensions(char **extension_paths) +{ + char **p = extension_paths; + + if (!p) { + return SUCCESS; + } + while (*p) { + if (zend_load_extension(*p)==FAILURE) { + return FAILURE; + } + p++; + } + return SUCCESS; +} + + +int zend_load_extension(char *path) +{ +#if ZEND_EXTENSIONS_SUPPORT + DL_HANDLE handle; + zend_extension extension, *new_extension; + zend_extension_version_info *extension_version_info; + + handle = DL_LOAD(path); + if (!handle) { + zend_printf("Failed loading %s\n", path); + return FAILURE; + } + + extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "extension_version_info"); + new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "zend_extension_entry"); + if (!extension_version_info || !new_extension) { + zend_printf("%s doesn't appear to be a valid Zend extension\n", path); + return FAILURE; + } + + if (extension_version_info->zend_extension_api_no > ZEND_EXTENSION_API_NO) { + zend_printf("%s requires Zend version %s or later\n" + "Current version %s, API version %d\n", + new_extension->name, + extension_version_info->required_zend_version, + ZEND_VERSION, + ZEND_EXTENSION_API_NO); + return FAILURE; + } else if (extension_version_info->zend_extension_api_no < ZEND_EXTENSION_API_NO) { + /* we may be able to allow for downwards compatability in some harmless cases. */ + zend_printf("%s is outdated (API version %d, current version %d)\n" + "Contact %s at %s for a later version of this module.\n", + new_extension->name, + extension_version_info->zend_extension_api_no, + ZEND_EXTENSION_API_NO, + new_extension->author, + new_extension->URL); + return FAILURE; + } else if (ZTS_V!=extension_version_info->thread_safe) { + zend_printf("Cannot load %s - it %s thread safe, whereas Zend %s\n", + new_extension->name, + (extension_version_info->thread_safe?"is":"isn't"), + (ZTS_V?"is":"isn't")); + return FAILURE; + } + + if (new_extension->startup) { + new_extension->startup(new_extension); + } + extension = *new_extension; + extension.handle = handle; + + zend_llist_add_element(&zend_extensions, &extension); + + /*zend_printf("Loaded %s, version %s\n", extension.name, extension.version);*/ + + zend_append_version_info(&extension); + return SUCCESS; +#else + zend_printf("Extensions are not supported on this platform.\n"); + return FAILURE +#endif +} + + +void zend_extension_dtor(zend_extension *extension) +{ +#if ZEND_EXTENSIONS_SUPPORT + if (extension->shutdown) { + extension->shutdown(extension); + } + DL_UNLOAD(extension->handle); +#endif +} + + +ZEND_API int zend_get_resource_handle(zend_extension *extension) +{ + if (last_resource_number<4) { + extension->resource_number = last_resource_number; + return last_resource_number; + } else { + return -1; + } +} diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h new file mode 100644 index 0000000000000..97c2243e1a0f1 --- /dev/null +++ b/Zend/zend_extensions.h @@ -0,0 +1,90 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _ZEND_EXTENSIONS_H +#define _ZEND_EXTENSIONS_H + +#include "zend_compile.h" + +#define ZEND_EXTENSION_API_NO 2 + +typedef struct { + int zend_extension_api_no; + char *required_zend_version; + unsigned char thread_safe; +} zend_extension_version_info; + + +typedef struct _zend_extension zend_extension; + +struct _zend_extension { + char *name; + char *version; + char *author; + char *URL; + char *copyright; + + void (*startup)(zend_extension *extension); + void (*shutdown)(zend_extension *extension); + void (*activate)(); + void (*deactivate)(); + + void (*op_array_handler)(zend_op_array *op_array); + + void (*statement_handler)(zend_op_array *op_array); + void (*fcall_begin_handler)(zend_op_array *op_array); + void (*fcall_end_handler)(zend_op_array *op_array); + + void (*op_array_ctor)(void **resource); + void (*op_array_dtor)(void **resource); + + void *reserved1; + void *reserved2; + void *reserved3; + void *reserved4; + void *reserved5; + void *reserved6; + void *reserved7; + void *reserved8; + + DL_HANDLE handle; + int resource_number; +}; + + +ZEND_API int zend_get_resource_handle(); + +#ifdef ZTS +#define ZTS_V 1 +#else +#define ZTS_V 0 +#endif + + +#define ZEND_EXTENSION() \ + ZEND_EXT_API zend_extension_version_info extension_version_info = { ZEND_EXTENSION_API_NO, "0.80A", ZTS_V } + +#define STANDARD_ZEND_EXTENSION_PROPERTIES NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, -1 + + +ZEND_API extern zend_llist zend_extensions; + +void zend_extension_dtor(zend_extension *extension); +int zend_load_extension(char *path); +int zend_load_extensions(char **extension_paths); +void zend_append_version_info(zend_extension *extension); + +#endif /* _ZEND_EXTENSIONS_H */ diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h new file mode 100644 index 0000000000000..7be0ce9c034e3 --- /dev/null +++ b/Zend/zend_globals.h @@ -0,0 +1,209 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _ZEND_GLOBALS_H +#define _ZEND_GLOBALS_H + +#include + +#include "zend_stack.h" +#include "zend_ptr_stack.h" +#include "zend_hash.h" +#include "zend_llist.h" + +#undef ZTS + +#ifdef ZTS +#include "SAPI.h" + +extern int compiler_globals_id; +extern int executor_globals_id; +#endif + +typedef struct _zend_compiler_globals zend_compiler_globals; +typedef struct _zend_executor_globals zend_executor_globals; +typedef struct _zend_alloc_globals zend_alloc_globals; + +#define SYMTABLE_CACHE_SIZE 32 + + +/* Compiler */ +#ifdef ZTS +# define CLS_D zend_compiler_globals *compiler_globals +# define CLS_DC , CLS_D +# define CLS_C compiler_globals +# define CLS_CC , CLS_C +# define CG(v) (((zend_compiler_globals *) compiler_globals)->v) +# define CLS_FETCH() zend_compiler_globals *compiler_globals = ts_resource(compiler_globals_id) +# define YYPARSE_PARAM compiler_globals +# define YYLEX_PARAM compiler_globals +int zendparse(void *compiler_globals); +#else +# define CLS_D +# define CLS_DC +# define CLS_C +# define CLS_CC +# define CG(v) (compiler_globals.v) +# define CLS_FETCH() +extern ZEND_API zend_compiler_globals compiler_globals; +int zendparse(); +#endif + + +/* Executor */ +#ifdef ZTS +# define ELS_D zend_executor_globals *executor_globals +# define ELS_DC , ELS_D +# define ELS_C executor_globals +# define ELS_CC , ELS_C +# define EG(v) (executor_globals->v) +# define ELS_FETCH() zend_executor_globals *executor_globals = ts_resource(executor_globals_id) +#else +# define ELS_D +# define ELS_DC +# define ELS_C +# define ELS_CC +# define EG(v) (executor_globals.v) +# define ELS_FETCH() +extern ZEND_API zend_executor_globals executor_globals; +#endif + + +/* Memory Manager */ +#ifdef ZTS +# define ALS_D zend_alloc_globals *alloc_globals +# define ALS_DC , ALS_D +# define ALS_C alloc_globals +# define ALS_CC , ALS_C +# define AG(v) (((zend_alloc_globals *) alloc_globals)->v) +# define ALS_FETCH() zend_alloc_globals *alloc_globals = ts_resource(alloc_globals_id) +#else +# define ALS_D +# define ALS_DC +# define ALS_C +# define ALS_CC +# define AG(v) (alloc_globals.v) +# define ALS_FETCH() +#endif + + +#include "zend_compile.h" +#include "zend_execute.h" + +struct _zend_compiler_globals { + zend_stack bp_stack; + zend_stack switch_cond_stack; + zend_stack object_stack; + + zend_class_entry class_entry, *active_class_entry; + + /* variables for list() compilation */ + zend_llist list_llist; + zend_llist dimension_llist; + + zend_stack function_call_stack; + + char *compiled_filename; + + int zend_lineno; + char *heredoc; + int heredoc_len; + + zend_op_array *active_op_array; + + HashTable *function_table; /* function symbol table */ + HashTable *class_table; /* class table */ + + zend_llist filenames_list; + + unsigned char short_tags; + unsigned char asp_tags; + + /* For extensions support */ + unsigned char extended_info; /* generate extension information for debugger/profiler */ + unsigned char handle_op_arrays; /* run op_arrays through op_array handlers */ +}; + + +struct _zend_executor_globals { + zval *return_value; + + zval uninitialized_zval; + zval *uninitialized_zval_ptr; + + zval error_zval; + zval *error_zval_ptr; + + zend_function_state *function_state_ptr; + zend_ptr_stack function_symbol_table_stack; + zend_ptr_stack arg_types_stack; + zend_stack overloaded_objects_stack; + zval global_return_value; + + /* symbol table cache */ + HashTable *symtable_cache[SYMTABLE_CACHE_SIZE]; + HashTable **symtable_cache_limit; + HashTable **symtable_cache_ptr; + + zend_op **opline_ptr; + + HashTable *active_symbol_table; + HashTable symbol_table; /* main symbol table */ + + jmp_buf bailout; + + int error_reporting; + + zend_op_array *active_op_array; + zend_op_array *main_op_array; + + HashTable *function_table; /* function symbol table */ + HashTable *class_table; /* class table */ + HashTable *zend_constants; /* constants table */ + + long precision; + + unsigned int AiCount; + + zend_ptr_stack garbage; + + /* for extended information support */ + unsigned char no_extensions; + + HashTable regular_list; + HashTable persistent_list; + +#if SUPPORT_INTERACTIVE + int interactive; +#endif +}; + + + +struct _zend_alloc_globals { + mem_header *head; /* standard list */ + mem_header *phead; /* persistent list */ + void *cache[MAX_CACHED_MEMORY][MAX_CACHED_ENTRIES]; + unsigned char cache_count[MAX_CACHED_MEMORY]; + +# if MEMORY_LIMIT + unsigned int allocated_memory; + unsigned char memory_exhausted; +#endif +}; + + +#endif /* _ZEND_GLOBALS_H */ diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c new file mode 100644 index 0000000000000..4cb93c9c69062 --- /dev/null +++ b/Zend/zend_hash.c @@ -0,0 +1,1163 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include + +#include "zend.h" + + +#define HANDLE_NUMERIC(key,length,func) { \ + register char *tmp=key; \ +\ + if ((*tmp>='0' && *tmp<='9')) do { /* possibly a numeric index */ \ + char *end=tmp+length-1; \ + ulong idx; \ + \ + if (*tmp++=='0' && length>2) { /* don't accept numbers with leading zeros */ \ + break; \ + } \ + while (tmp='0' && *tmp<='9')) { \ + break; \ + } \ + tmp++; \ + } \ + if (tmp==end && *tmp=='\0') { /* a numeric index */ \ + idx = strtol(key,NULL,10); \ + if (idx!=LONG_MAX) { \ + return func; \ + } \ + } \ + } while(0); \ +} + +/* Generated on an Octa-ALPHA 300MHz CPU & 2.5GB RAM monster */ +static uint PrimeNumbers[] = +{5, 11, 19, 53, 107, 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987, 262237, 524521, 1048793, 2097397, 4194103, 8388857, 16777447, 33554201, 67108961, 134217487, 268435697, 536870683, 1073741621, 2147483399}; + +static int if_full_do_resize(HashTable *ht); +static int zend_hash_rehash(HashTable *ht); + +static uint nNumPrimeNumbers = sizeof(PrimeNumbers) / sizeof(ulong); + +ZEND_API ulong hashpjw(char *arKey, uint nKeyLength) +{ + ulong h = 0, g; + char *arEnd=arKey+nKeyLength; + + while (arKey < arEnd) { + h = (h << 4) + *arKey++; + if ((g = (h & 0xF0000000))) { + h = h ^ (g >> 24); + h = h ^ g; + } + } + return h; +} + + +ZEND_API int zend_hash_init(HashTable *ht, uint nSize, ulong(*pHashFunction) (char *arKey, uint nKeyLength), void (*pDestructor) (void *pData),int persistent) +{ + uint i; + + for (i = 0; i < nNumPrimeNumbers; i++) { + if (nSize <= PrimeNumbers[i]) { + nSize = PrimeNumbers[i]; + ht->nHashSizeIndex = i; + break; + } + } + if (i == nNumPrimeNumbers) { /* This shouldn't really happen unless the ask for a ridiculous size */ + nSize = PrimeNumbers[i - 1]; + ht->nHashSizeIndex = i - 1; + } + + /* Uses ecalloc() so that Bucket* == NULL */ + ht->arBuckets = (Bucket **) pecalloc(nSize, sizeof(Bucket *), persistent); + + if (!ht->arBuckets) { + return FAILURE; + } + if (pHashFunction == NULL) { + ht->pHashFunction = hashpjw; + } else { + ht->pHashFunction = pHashFunction; + } + ht->pDestructor = pDestructor; + ht->nTableSize = nSize; + ht->pListHead = NULL; + ht->pListTail = NULL; + ht->nNumOfElements = 0; + ht->nNextFreeElement = 0; + ht->pInternalPointer = NULL; + ht->persistent = persistent; + return SUCCESS; +} + +ZEND_API int zend_hash_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData, uint nDataSize, void **pDest, int flag) +{ + ulong h; + uint nIndex; + Bucket *p; + + if (nKeyLength <= 0) { +#if ZEND_DEBUG + ZEND_PUTS("zend_hash_update: Can't put in empty key\n"); +#endif + return FAILURE; + } + + HANDLE_NUMERIC(arKey,nKeyLength,zend_hash_index_update_or_next_insert(ht,idx,pData,nDataSize,pDest,flag)); + + h = ht->pHashFunction(arKey, nKeyLength); + nIndex = h % ht->nTableSize; + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && (p->nKeyLength == nKeyLength)) { + if (!memcmp(p->arKey, arKey, nKeyLength)) { + if (flag & HASH_ADD) { + return FAILURE; + } + HANDLE_BLOCK_INTERRUPTIONS(); +#if ZEND_DEBUG + if (p->pData == pData) { + ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n"); + HANDLE_UNBLOCK_INTERRUPTIONS(); + return FAILURE; + } +#endif + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } + if (flag & HASH_ADD_PTR) { + if (!p->pDataPtr) { + efree(p->pData); + } + p->pDataPtr = pData; + p->pData = &p->pDataPtr; + } else { + if (p->pDataPtr) { + p->pData = (void *) emalloc(nDataSize); + p->pDataPtr=NULL; + } + memcpy(p->pData, pData, nDataSize); + } + if (pDest) { + *pDest = p->pData; + } + HANDLE_UNBLOCK_INTERRUPTIONS(); + return SUCCESS; + } + } + p = p->pNext; + } + + p = (Bucket *) pemalloc(sizeof(Bucket)-1+nKeyLength,ht->persistent); + if (!p) { + return FAILURE; + } + memcpy(p->arKey, arKey, nKeyLength); + p->nKeyLength = nKeyLength; + if (flag & HASH_ADD_PTR) { + p->pDataPtr = pData; + p->pData = &p->pDataPtr; + } else { + p->pData = (void *) pemalloc(nDataSize,ht->persistent); + if (!p->pData) { + pefree(p,ht->persistent); + pefree(p->arKey,ht->persistent); + return FAILURE; + } + memcpy(p->pData, pData, nDataSize); + p->pDataPtr=NULL; + } + p->h = h; + p->bIsPointer = 0; + p->pNext = ht->arBuckets[nIndex]; + if (pDest) { + *pDest = p->pData; + } + + HANDLE_BLOCK_INTERRUPTIONS(); + if (ht->pInternalPointer == NULL) { + ht->pInternalPointer = p; + } + ht->arBuckets[nIndex] = p; + + /* Setup the double linked list */ + p->pListLast = ht->pListTail; + ht->pListTail = p; + p->pListNext = NULL; + if (p->pListLast != NULL) { + p->pListLast->pListNext = p; + } + if (!ht->pListHead) { + ht->pListHead = p; + } + HANDLE_UNBLOCK_INTERRUPTIONS(); + ht->nNumOfElements++; + if_full_do_resize(ht); /* If the Hash table is full, resize it */ + return SUCCESS; +} + +ZEND_API int zend_hash_quick_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest, int flag) +{ + uint nIndex; + Bucket *p; + + if (nKeyLength <= 0) { +#if ZEND_DEBUG + ZEND_PUTS("zend_hash_update: Can't put in empty key\n"); +#endif + return FAILURE; + } + + nIndex = h % ht->nTableSize; + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && (p->nKeyLength == nKeyLength)) { + if (!memcmp(p->arKey, arKey, nKeyLength)) { + if (flag & HASH_ADD) { + return FAILURE; + } + HANDLE_BLOCK_INTERRUPTIONS(); +#if ZEND_DEBUG + if (p->pData == pData) { + ZEND_PUTS("Fatal error in zend_hash_update: p->pData == pData\n"); + HANDLE_UNBLOCK_INTERRUPTIONS(); + return FAILURE; + } +#endif + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } + if (flag & HASH_ADD_PTR) { + if (!p->pDataPtr) { + efree(p->pData); + } + p->pDataPtr = pData; + p->pData = &p->pDataPtr; + } else { + if (p->pDataPtr) { + p->pData = (void *) emalloc(nDataSize); + p->pDataPtr=NULL; + } + memcpy(p->pData, pData, nDataSize); + } + if (pDest) { + *pDest = p->pData; + } + HANDLE_UNBLOCK_INTERRUPTIONS(); + return SUCCESS; + } + } + p = p->pNext; + } + + p = (Bucket *) pemalloc(sizeof(Bucket)-1+nKeyLength,ht->persistent); + if (!p) { + return FAILURE; + } + + memcpy(p->arKey, arKey, nKeyLength); + p->nKeyLength = nKeyLength; + if (flag & HASH_ADD_PTR) { + p->pDataPtr = pData; + p->pData = &p->pDataPtr; + } else { + p->pData = (void *) pemalloc(nDataSize,ht->persistent); + if (!p->pData) { + pefree(p,ht->persistent); + pefree(p->arKey,ht->persistent); + return FAILURE; + } + + memcpy(p->pData, pData, nDataSize); + p->pDataPtr=NULL; + } + p->h = h; + p->bIsPointer = 0; + p->pNext = ht->arBuckets[nIndex]; + if (pDest) { + *pDest = p->pData; + } + + HANDLE_BLOCK_INTERRUPTIONS(); + if (ht->pInternalPointer == NULL) { + ht->pInternalPointer = p; + } + ht->arBuckets[nIndex] = p; + + /* Setup the double linked list */ + p->pListLast = ht->pListTail; + ht->pListTail = p; + p->pListNext = NULL; + if (p->pListLast != NULL) { + p->pListLast->pListNext = p; + } + if (!ht->pListHead) { + ht->pListHead = p; + } + HANDLE_UNBLOCK_INTERRUPTIONS(); + ht->nNumOfElements++; + if_full_do_resize(ht); /* If the Hash table is full, resize it */ + return SUCCESS; +} + + +ZEND_API int zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag) +{ + uint nIndex; + Bucket *p; + + if (flag & HASH_NEXT_INSERT) { + h = ht->nNextFreeElement; + } + nIndex = h % ht->nTableSize; + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->nKeyLength == 0) && (p->h == h)) { + if (flag & HASH_NEXT_INSERT || flag & HASH_ADD) { + return FAILURE; + } + HANDLE_BLOCK_INTERRUPTIONS(); +#if ZEND_DEBUG + if (p->pData == pData) { + ZEND_PUTS("Fatal error in zend_hash_index_update: p->pData == pData\n"); + HANDLE_UNBLOCK_INTERRUPTIONS(); + return FAILURE; + } +#endif + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } + if (flag & HASH_ADD_PTR) { + if (!p->pDataPtr) { + efree(p->pData); + } + p->pDataPtr = pData; + p->pData = &p->pDataPtr; + } else { + if (p->pDataPtr) { + p->pData = (void *) emalloc(nDataSize); + p->pDataPtr=NULL; + } + memcpy(p->pData, pData, nDataSize); + } + HANDLE_UNBLOCK_INTERRUPTIONS(); + if (h >= ht->nNextFreeElement) { + ht->nNextFreeElement = h + 1; + } + if (pDest) { + *pDest = p->pData; + } + return SUCCESS; + } + p = p->pNext; + } + p = (Bucket *) pemalloc(sizeof(Bucket)-1,ht->persistent); + if (!p) { + return FAILURE; + } + p->nKeyLength = 0; /* Numeric indices are marked by making the nKeyLength == 0 */ + p->h = h; + + if (flag & HASH_ADD_PTR) { + p->pDataPtr = pData; + p->pData = &p->pDataPtr; + } else { + p->pData = (void *) pemalloc(nDataSize,ht->persistent); + if (!p->pData) { + pefree(p,ht->persistent); + return FAILURE; + } + memcpy(p->pData, pData, nDataSize); + p->pDataPtr=NULL; + } + p->bIsPointer = 0; + if (pDest) { + *pDest = p->pData; + } + + p->pNext = ht->arBuckets[nIndex]; + HANDLE_BLOCK_INTERRUPTIONS(); + if (ht->pInternalPointer == NULL) { + ht->pInternalPointer = p; + } + ht->arBuckets[nIndex] = p; + + /* Setup the double linked list */ + p->pListLast = ht->pListTail; + ht->pListTail = p; + p->pListNext = NULL; + if (p->pListLast != NULL) { + p->pListLast->pListNext = p; + } + if (!ht->pListHead) { + ht->pListHead = p; + } + HANDLE_UNBLOCK_INTERRUPTIONS(); + if (h >= ht->nNextFreeElement) { + ht->nNextFreeElement = h + 1; + } + ht->nNumOfElements++; + if_full_do_resize(ht); + return SUCCESS; +} + +ZEND_API int zend_hash_pointer_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData) +{ + ulong h; + uint nIndex; + Bucket *p; + + + if (nKeyLength <= 0) { +#if ZEND_DEBUG + ZEND_PUTS("zend_hash_update: Can't put in empty key\n"); +#endif + return FAILURE; + } + + HANDLE_NUMERIC(arKey,nKeyLength,zend_hash_pointer_index_update_or_next_insert(ht,idx,pData,HASH_UPDATE)); + + h = ht->pHashFunction(arKey, nKeyLength); + nIndex = h % ht->nTableSize; + + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && (p->nKeyLength == nKeyLength)) { + if (!memcmp(p->arKey, arKey, nKeyLength)) { +#if ZEND_DEBUG + if (p->pData == pData) { + ZEND_PUTS("Fatal error in zend_hash_pointer_update: p->pData == pData\n"); + return FAILURE; + } +#endif + HANDLE_BLOCK_INTERRUPTIONS(); + if (!p->bIsPointer && ht->pDestructor) { + ht->pDestructor(p->pData); + pefree(p->pData,ht->persistent); + } + p->pData = pData; + p->bIsPointer = 1; + HANDLE_UNBLOCK_INTERRUPTIONS(); + return SUCCESS; + } + } + p = p->pNext; + } + p = (Bucket *) pemalloc(sizeof(Bucket)-1+nKeyLength,ht->persistent); + if (!p) { + return FAILURE; + } + p->nKeyLength = nKeyLength; + p->pData = pData; + p->h = h; + p->bIsPointer = 1; + memcpy(p->arKey, arKey, nKeyLength); + + p->pNext = ht->arBuckets[nIndex]; + + HANDLE_BLOCK_INTERRUPTIONS(); + if (ht->pInternalPointer == NULL) { + ht->pInternalPointer = p; + } + ht->arBuckets[nIndex] = p; + + /* Setup the double linked list */ + p->pListLast = ht->pListTail; + ht->pListTail = p; + p->pListNext = NULL; + if (p->pListLast != NULL) { + p->pListLast->pListNext = p; + } + if (!ht->pListHead) { + ht->pListHead = p; + } + HANDLE_UNBLOCK_INTERRUPTIONS(); + + ht->nNumOfElements++; + if_full_do_resize(ht); /* If the Hash table is full, resize it */ + return SUCCESS; +} + + +ZEND_API int zend_hash_pointer_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, int flag) +{ + uint nIndex; + Bucket *p; + + if (flag & HASH_NEXT_INSERT) { + h = ht->nNextFreeElement; + } + nIndex = h % ht->nTableSize; + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->nKeyLength == 0) && (p->h == h)) { + if (flag & HASH_NEXT_INSERT) { + return FAILURE; + } +#if ZEND_DEBUG + if (p->pData == pData) { + ZEND_PUTS("Fatal error in zend_hash_pointer_update: p->pData == pData\n"); + return FAILURE; + } +#endif + HANDLE_BLOCK_INTERRUPTIONS(); + if (!p->bIsPointer && ht->pDestructor) { + ht->pDestructor(p->pData); + pefree(p->pData,ht->persistent); + } + p->pData = pData; + p->bIsPointer = 1; + if (h >= ht->nNextFreeElement) { + ht->nNextFreeElement = h + 1; + } + HANDLE_UNBLOCK_INTERRUPTIONS(); + return SUCCESS; + } + p = p->pNext; + } + p = (Bucket *) pemalloc(sizeof(Bucket)-1,ht->persistent); + if (!p) { + return FAILURE; + } + p->nKeyLength = 0; + p->pData = pData; + p->h = h; + p->bIsPointer = 1; + + p->pNext = ht->arBuckets[nIndex]; + + HANDLE_BLOCK_INTERRUPTIONS(); + if (ht->pInternalPointer == NULL) { + ht->pInternalPointer = p; + } + ht->arBuckets[nIndex] = p; + + /* Setup the double linked list */ + p->pListLast = ht->pListTail; + ht->pListTail = p; + p->pListNext = NULL; + if (p->pListLast != NULL) { + p->pListLast->pListNext = p; + } + if (!ht->pListHead) { + ht->pListHead = p; + } + HANDLE_UNBLOCK_INTERRUPTIONS(); + + ht->nNumOfElements++; + if (h >= ht->nNextFreeElement) { + ht->nNextFreeElement = h + 1; + } + if_full_do_resize(ht); /* If the Hash table is full, resize it */ + return SUCCESS; +} + + +ZEND_API int zend_hash_is_pointer(HashTable *ht, char *arKey, uint nKeyLength) +{ + ulong h; + uint nIndex; + Bucket *p; + + if (nKeyLength <= 0) { +#if ZEND_DEBUG + ZEND_PUTS("zend_hash_update: Can't check for empty key\n"); +#endif + return FAILURE; + } + + HANDLE_NUMERIC(arKey,nKeyLength,zend_hash_index_is_pointer(ht, idx)); + + h = ht->pHashFunction(arKey, nKeyLength); + nIndex = h % ht->nTableSize; + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && (p->nKeyLength == nKeyLength)) { + if (!memcmp(p->arKey, arKey, nKeyLength)) { + return (p->bIsPointer); + } + } + p = p->pNext; + } + return 0; +} + +ZEND_API int zend_hash_index_is_pointer(HashTable *ht, ulong h) +{ + uint nIndex; + Bucket *p; + + nIndex = h % ht->nTableSize; + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->nKeyLength == 0) && (p->h == h)) { + return (p->bIsPointer); + } + p = p->pNext; + } + return 0; +} + + +static int if_full_do_resize(HashTable *ht) +{ + Bucket **t; + + if ((ht->nNumOfElements > ht->nTableSize) && (ht->nHashSizeIndex < nNumPrimeNumbers - 1)) { /* Let's double the table + size */ + t = (Bucket **) perealloc(ht->arBuckets, PrimeNumbers[ht->nHashSizeIndex + 1] * sizeof(Bucket *),ht->persistent); + if (t) { + HANDLE_BLOCK_INTERRUPTIONS(); + ht->arBuckets = t; + ht->nTableSize = PrimeNumbers[ht->nHashSizeIndex + 1]; + ht->nHashSizeIndex++; + zend_hash_rehash(ht); + HANDLE_UNBLOCK_INTERRUPTIONS(); + return SUCCESS; + } + return FAILURE; + } + return SUCCESS; +} + +static int zend_hash_rehash(HashTable *ht) +{ + Bucket *p; + uint nIndex; + + memset(ht->arBuckets, 0, PrimeNumbers[ht->nHashSizeIndex] * sizeof(Bucket *)); + p = ht->pListHead; + while (p != NULL) { + nIndex = p->h % ht->nTableSize; + p->pNext = ht->arBuckets[nIndex]; + ht->arBuckets[nIndex] = p; + p = p->pListNext; + } + return SUCCESS; +} + +ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLength, ulong h, int flag) +{ + uint nIndex; + Bucket *p, *t = NULL; /* initialize just to shut gcc up with -Wall */ + + if (flag == HASH_DEL_KEY) { + HANDLE_NUMERIC(arKey,nKeyLength,zend_hash_del_key_or_index(ht,arKey,nKeyLength,idx,HASH_DEL_INDEX)); + h = ht->pHashFunction(arKey, nKeyLength); + } + nIndex = h % ht->nTableSize; + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && ((p->nKeyLength == 0) || /* Numeric index */ + ((p->nKeyLength == nKeyLength) && (!memcmp(p->arKey, arKey, nKeyLength))))) { + HANDLE_BLOCK_INTERRUPTIONS(); + if (p == ht->arBuckets[nIndex]) { + ht->arBuckets[nIndex] = p->pNext; + } else { + t->pNext = p->pNext; + } + if (p->pListLast != NULL) { + p->pListLast->pListNext = p->pListNext; + } else { + /* Deleting the head of the list */ + ht->pListHead = p->pListNext; + } + if (p->pListNext != NULL) { + p->pListNext->pListLast = p->pListLast; + } else { + ht->pListTail = p->pListLast; + } + if (!p->bIsPointer) { + if (ht->pDestructor) { + ht->pDestructor(p->pData); + } + if (!p->pDataPtr) { + pefree(p->pData,ht->persistent); + } + } + if (ht->pInternalPointer == p) { + ht->pInternalPointer = p->pListNext; + } + pefree(p,ht->persistent); + HANDLE_UNBLOCK_INTERRUPTIONS(); + ht->nNumOfElements--; + return SUCCESS; + } + t = p; + p = p->pNext; + } + return FAILURE; +} + + +ZEND_API void zend_hash_destroy(HashTable *ht) +{ + Bucket *p, *q; + + p = ht->pListHead; + while (p != NULL) { + q = p; + p = p->pListNext; + if (!q->bIsPointer) { + if (ht->pDestructor) { + ht->pDestructor(q->pData); + } + if (!q->pDataPtr && q->pData) { + pefree(q->pData,ht->persistent); + } + } + pefree(q,ht->persistent); + } + pefree(ht->arBuckets,ht->persistent); +} + + +ZEND_API void zend_hash_clean(HashTable *ht) +{ + Bucket *p, *q; + + p = ht->pListHead; + while (p != NULL) { + q = p; + p = p->pListNext; + if (!q->bIsPointer) { + if (ht->pDestructor) { + ht->pDestructor(q->pData); + } + if (!q->pDataPtr && q->pData) { + pefree(q->pData,ht->persistent); + } + } + pefree(q,ht->persistent); + } + memset(ht->arBuckets, 0, ht->nTableSize*sizeof(Bucket *)); + ht->pListHead = NULL; + ht->pListTail = NULL; + ht->nNumOfElements = 0; + ht->nNextFreeElement = 0; + ht->pInternalPointer = NULL; +} + + +/* This is used to selectively delete certain entries from a hashtable. + * destruct() receives the data and decides if the entry should be deleted + * or not + */ +ZEND_API void zend_hash_apply(HashTable *ht,int (*destruct) (void *)) +{ + Bucket *p, *q; + + p = ht->pListHead; + while (p != NULL) { + q = p; + p = p->pListNext; + if (destruct(q->pData)) { + if (q->arKey == NULL) { + zend_hash_index_del(ht, q->h); + } else { + zend_hash_del(ht,q->arKey,q->nKeyLength); + } + } + } +} + + +ZEND_API void zend_hash_apply_with_argument(HashTable *ht,int (*destruct) (void *, void *), void *argument) +{ + Bucket *p, *q; + + p = ht->pListHead; + while (p != NULL) { + q = p; + p = p->pListNext; + if (destruct(q->pData, argument)) { + if (q->arKey == NULL) { + zend_hash_index_del(ht, q->h); + } else { + zend_hash_del(ht,q->arKey,q->nKeyLength); + } + } + } +} + + +ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, void (*pCopyConstructor) (void *pData), void *tmp, uint size) +{ + Bucket *p; + + p = source->pListHead; + while (p) { + memcpy(tmp, p->pData, size); + if (pCopyConstructor) { + pCopyConstructor(tmp); + } + if (p->nKeyLength) { + zend_hash_update(target, p->arKey, p->nKeyLength, tmp, size, NULL); + } else { + zend_hash_index_update(target, p->h, tmp, size, NULL); + } + p = p->pListNext; + } + target->pInternalPointer = target->pListHead; +} + + +ZEND_API void zend_hash_merge(HashTable *target, HashTable *source, void (*pCopyConstructor) (void *pData), void *tmp, uint size) +{ + Bucket *p; + void *t; + + p = source->pListHead; + while (p) { + memcpy(tmp, p->pData, size); + if (p->arKey) { + if (zend_hash_add(target, p->arKey, p->nKeyLength, tmp, size, &t)==SUCCESS && pCopyConstructor) { + pCopyConstructor(t); + } + } else { + if (!zend_hash_index_exists(target, p->h) && zend_hash_index_update(target, p->h, tmp, size, &t)==SUCCESS && pCopyConstructor) { + pCopyConstructor(t); + } + } + p = p->pListNext; + } + target->pInternalPointer = target->pListHead; +} + + +ZEND_API ulong zend_get_hash_value(HashTable *ht, char *arKey, uint nKeyLength) +{ + return ht->pHashFunction(arKey, nKeyLength); +} + + +/* Returns SUCCESS if found and FAILURE if not. The pointer to the + * data is returned in pData. The reason is that there's no reason + * someone using the hash table might not want to have NULL data + */ +ZEND_API int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData) +{ + ulong h; + uint nIndex; + Bucket *p; + + HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_find(ht,idx,pData)); + + h = ht->pHashFunction(arKey, nKeyLength); + nIndex = h % ht->nTableSize; + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && (p->nKeyLength == nKeyLength)) { + if (!memcmp(p->arKey, arKey, nKeyLength)) { + *pData = p->pData; + return SUCCESS; + } + } + p = p->pNext; + } + return FAILURE; +} + + +ZEND_API int zend_hash_quick_find(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void **pData) +{ + uint nIndex; + Bucket *p; + + nIndex = h % ht->nTableSize; + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && (p->nKeyLength == nKeyLength)) { + if (!memcmp(p->arKey, arKey, nKeyLength)) { + *pData = p->pData; + return SUCCESS; + } + } + p = p->pNext; + } + return FAILURE; +} + + +ZEND_API int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLength) +{ + ulong h; + uint nIndex; + Bucket *p; + + HANDLE_NUMERIC(arKey, nKeyLength, zend_hash_index_exists(ht,idx)); + + h = ht->pHashFunction(arKey, nKeyLength); + nIndex = h % ht->nTableSize; + + 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; + Bucket *p; + + nIndex = h % ht->nTableSize; + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && (p->nKeyLength == 0)) { + *pData = p->pData; + return SUCCESS; + } + p = p->pNext; + } + return FAILURE; +} + + +ZEND_API int zend_hash_index_exists(HashTable *ht, ulong h) +{ + uint nIndex; + Bucket *p; + + nIndex = h % ht->nTableSize; + + p = ht->arBuckets[nIndex]; + while (p != NULL) { + if ((p->h == h) && (p->nKeyLength == 0)) { + return 1; + } + p = p->pNext; + } + return 0; +} + + +ZEND_API int zend_hash_num_elements(HashTable *ht) +{ + return ht->nNumOfElements; +} + + +ZEND_API void zend_hash_internal_pointer_reset(HashTable *ht) +{ + ht->pInternalPointer = ht->pListHead; +} + + +/* This function will be extremely optimized by remembering + * the end of the list + */ +ZEND_API void zend_hash_internal_pointer_end(HashTable *ht) +{ + ht->pInternalPointer = ht->pListTail; +} + + +ZEND_API void zend_hash_move_forward(HashTable *ht) +{ + if (ht->pInternalPointer) { + ht->pInternalPointer = ht->pInternalPointer->pListNext; + } +} + +ZEND_API void zend_hash_move_backwards(HashTable *ht) +{ + if (ht->pInternalPointer) { + ht->pInternalPointer = ht->pInternalPointer->pListLast; + } +} + + +/* This function should be made binary safe */ +ZEND_API int zend_hash_get_current_key(HashTable *ht, char **str_index, ulong *num_index) +{ + Bucket *p = ht->pInternalPointer; + + if (p) { + if (p->nKeyLength) { + *str_index = (char *) pemalloc(p->nKeyLength,ht->persistent); + memcpy(*str_index, p->arKey, p->nKeyLength); + return HASH_KEY_IS_STRING; + } else { + *num_index = p->h; + return HASH_KEY_IS_LONG; + } + } + return HASH_KEY_NON_EXISTANT; +} + + +ZEND_API int zend_hash_get_current_data(HashTable *ht, void **pData) +{ + Bucket *p = ht->pInternalPointer; + + if (p) { + *pData = p->pData; + return SUCCESS; + } else { + return FAILURE; + } +} + + +ZEND_API int zend_hash_sort(HashTable *ht, int (*compar) (const void *, const void *), int renumber) +{ + Bucket **arTmp; + Bucket *p; + int i, j; + + if (ht->nNumOfElements <= 1) { /* Doesn't require sorting */ + return SUCCESS; + } + arTmp = (Bucket **) pemalloc(ht->nNumOfElements * sizeof(Bucket *),ht->persistent); + if (!arTmp) { + return FAILURE; + } + p = ht->pListHead; + i = 0; + while (p) { + arTmp[i] = p; + p = p->pListNext; + i++; + } + + qsort((void *) arTmp, i, sizeof(Bucket *), compar); + + HANDLE_BLOCK_INTERRUPTIONS(); + ht->pListHead = arTmp[0]; + ht->pListTail = NULL; + ht->pInternalPointer = ht->pListHead; + + for (j = 0; j < i; j++) { + if (ht->pListTail) { + ht->pListTail->pListNext = arTmp[j]; + } + arTmp[j]->pListLast = ht->pListTail; + arTmp[j]->pListNext = NULL; + ht->pListTail = arTmp[j]; + } + pefree(arTmp,ht->persistent); + HANDLE_UNBLOCK_INTERRUPTIONS(); + + if (renumber) { + p = ht->pListHead; + i=0; + while (p != NULL) { + p->nKeyLength = 0; + p->h = i++; + p = p->pListNext; + } + ht->nNextFreeElement = i; + zend_hash_rehash(ht); + } + return SUCCESS; +} + + +ZEND_API int zend_hash_minmax(HashTable *ht, int (*compar) (const void *, const void *), int flag, void **pData) +{ + Bucket *p,*res; + + if (ht->nNumOfElements == 0 ) { + *pData=NULL; + return FAILURE; + } + + res = p = ht->pListHead; + while ((p = p->pListNext)) { + if (flag) { + if (compar(&res,&p) < 0) { /* max */ + res = p; + } + } else { + if (compar(&res,&p) > 0) { /* min */ + res = p; + } + } + } + *pData = res->pData; + return SUCCESS; +} + +ZEND_API ulong zend_hash_next_free_element(HashTable *ht) +{ + return ht->nNextFreeElement; + +} + +#if ZEND_DEBUG +void zend_hash_display_pListTail(HashTable *ht) +{ + Bucket *p; + + p = ht->pListTail; + while (p != NULL) { + zend_printf("pListTail has key %s\n", p->arKey); + p = p->pListLast; + } +} + +void zend_hash_display(HashTable *ht) +{ + Bucket *p; + uint i; + + for (i = 0; i < ht->nTableSize; i++) { + p = ht->arBuckets[i]; + while (p != NULL) { + zend_printf("%s <==> 0x%X\n", p->arKey, p->h); + p = p->pNext; + } + } + + p = ht->pListTail; + while (p != NULL) { + zend_printf("%s <==> 0x%X\n", p->arKey, p->h); + p = p->pListLast; + } +} +#endif + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h new file mode 100644 index 0000000000000..2699b53978fd1 --- /dev/null +++ b/Zend/zend_hash.h @@ -0,0 +1,153 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + + +#ifndef _HASH_ +#define _HASH_ + +#include + +#define HASH_KEY_IS_STRING 1 +#define HASH_KEY_IS_LONG 2 +#define HASH_KEY_NON_EXISTANT 3 + +#define HASH_UPDATE (1<<0) +#define HASH_ADD (1<<1) +#define HASH_NEXT_INSERT (1<<2) +#define HASH_ADD_PTR (1<<3) + +#define HASH_DEL_KEY 0 +#define HASH_DEL_INDEX 1 + +struct hashtable; + +typedef struct bucket { + ulong h; /* Used for numeric indexing */ + uint nKeyLength; + void *pData; + void *pDataPtr; + char bIsPointer; + struct bucket *pListNext; + struct bucket *pListLast; + struct bucket *pNext; + char arKey[1]; /* Must be last element */ +} Bucket; + +typedef struct hashtable { + uint nTableSize; + uint nHashSizeIndex; + uint nNumOfElements; + ulong nNextFreeElement; + ulong(*pHashFunction) (char *arKey, uint nKeyLength); + Bucket *pInternalPointer; /* Used for element traversal */ + Bucket *pListHead; + Bucket *pListTail; + Bucket **arBuckets; + void (*pDestructor) (void *pData); + unsigned char persistent; +} HashTable; + + +/* startup/shutdown */ +ZEND_API int zend_hash_init(HashTable *ht, uint nSize, ulong(*pHashFunction) (char *arKey, uint nKeyLength), void (*pDestructor) (void *pData), int persistent); +ZEND_API void zend_hash_destroy(HashTable *ht); + +ZEND_API void zend_hash_clean(HashTable *ht); + +/* 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); +#define zend_hash_update(ht,arKey,nKeyLength,pData,nDataSize,pDest) \ + zend_hash_add_or_update(ht,arKey,nKeyLength,pData,nDataSize,pDest,HASH_UPDATE) +#define zend_hash_add(ht,arKey,nKeyLength,pData,nDataSize,pDest) \ + zend_hash_add_or_update(ht,arKey,nKeyLength,pData,nDataSize,pDest,HASH_ADD) +#define zend_hash_update_ptr(ht,arKey,nKeyLength,pData,nDataSize,pDest) \ + zend_hash_add_or_update(ht,arKey,nKeyLength,pData,0,pDest,(HASH_UPDATE|HASH_ADD_PTR)) + +ZEND_API int zend_hash_quick_add_or_update(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void *pData, uint nDataSize, void **pDest,int flag); +#define zend_hash_quick_update(ht,arKey,nKeyLength,h,pData,nDataSize,pDest) \ + zend_hash_quick_add_or_update(ht,arKey,nKeyLength,h,pData,nDataSize,pDest,HASH_UPDATE) +#define zend_hash_quick_add(ht,arKey,nKeyLength,h,pData,nDataSize,pDest) \ + zend_hash_quick_add_or_update(ht,arKey,nKeyLength,h,pData,nDataSize,pDest,HASH_ADD) +#define zend_hash_quick_update_ptr(ht,arKey,nKeyLength,h,pData,nDataSize,pDest) \ + zend_hash_quick_add_or_update(ht,arKey,nKeyLength,h,pData,0,pDest,HASH_UPDATE|HASH_ADD_PTR) + +ZEND_API int zend_hash_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, uint nDataSize, void **pDest, int flag); +#define zend_hash_index_update(ht,h,pData,nDataSize,pDest) \ + zend_hash_index_update_or_next_insert(ht,h,pData,nDataSize,pDest,HASH_UPDATE) +#define zend_hash_next_index_insert(ht,pData,nDataSize,pDest) \ + zend_hash_index_update_or_next_insert(ht,0,pData,nDataSize,pDest,HASH_NEXT_INSERT) +#define zend_hash_next_index_insert_ptr(ht,pData,nDataSize,pDest) \ + zend_hash_index_update_or_next_insert(ht,0,pData,nDataSize,pDest,HASH_NEXT_INSERT|HASH_ADD_PTR) + +ZEND_API int zend_hash_pointer_update(HashTable *ht, char *arKey, uint nKeyLength, void *pData); + +ZEND_API int zend_hash_pointer_index_update_or_next_insert(HashTable *ht, ulong h, void *pData, int flag); +#define zend_hash_pointer_index_update(ht,h,pData) \ + zend_hash_pointer_index_update_or_next_insert(ht,h,pData,HASH_UPDATE) +#define zend_hash_next_index_pointer_insert(ht,pData) \ + zend_hash_pointer_index_update_or_next_insert(ht,0,pData,HASH_NEXT_INSERT) +ZEND_API void zend_hash_apply(HashTable *ht,int (*destruct) (void *)); +ZEND_API void zend_hash_apply_with_argument(HashTable *ht,int (*destruct) (void *, void *), void *); + + + +/* Deletes */ +ZEND_API int zend_hash_del_key_or_index(HashTable *ht, char *arKey, uint nKeyLength, ulong h, int flag); +#define zend_hash_del(ht,arKey,nKeyLength) \ + zend_hash_del_key_or_index(ht,arKey,nKeyLength,0,HASH_DEL_KEY) +#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); + +/* Data retreival */ +ZEND_API int zend_hash_find(HashTable *ht, char *arKey, uint nKeyLength, void **pData); +ZEND_API int zend_hash_quick_find(HashTable *ht, char *arKey, uint nKeyLength, ulong h, void **pData); +ZEND_API int zend_hash_index_find(HashTable *ht, ulong h, void **pData); + +/* Misc */ +ZEND_API int zend_hash_exists(HashTable *ht, char *arKey, uint nKeyLength); +ZEND_API int zend_hash_index_exists(HashTable *ht, ulong h); +ZEND_API int zend_hash_is_pointer(HashTable *ht, char *arKey, uint nKeyLength); +ZEND_API int zend_hash_index_is_pointer(HashTable *ht, ulong h); +ZEND_API ulong zend_hash_next_free_element(HashTable *ht); + +/* traversing */ +ZEND_API void zend_hash_move_forward(HashTable *ht); +ZEND_API void zend_hash_move_backwards(HashTable *ht); +ZEND_API int zend_hash_get_current_key(HashTable *ht, char **str_index, ulong *num_index); +ZEND_API int zend_hash_get_current_data(HashTable *ht, void **pData); +ZEND_API void zend_hash_internal_pointer_reset(HashTable *ht); +ZEND_API void zend_hash_internal_pointer_end(HashTable *ht); + +/* Copying, merging and sorting */ +ZEND_API void zend_hash_copy(HashTable *target, HashTable *source, void (*pCopyConstructor) (void *pData), void *tmp, uint size); +ZEND_API void zend_hash_merge(HashTable *target, HashTable *source, void (*pCopyConstructor) (void *pData), void *tmp, uint size); +ZEND_API int zend_hash_sort(HashTable *ht, int (*compar) (const void *, const void *), int renumber); +ZEND_API int zend_hash_minmax(HashTable *ht, int (*compar) (const void *, const void *), int flag, void **pData); + +ZEND_API int zend_hash_num_elements(HashTable *ht); + + +ZEND_API ulong hashpjw(char *arKey, uint nKeyLength); + +#if DEBUG +/* debug */ +void zend_hash_display_pListTail(HashTable *ht); +void zend_hash_display(HashTable *ht); +#endif + +#endif /* _HASH_ */ diff --git a/Zend/zend_highlight.c b/Zend/zend_highlight.c new file mode 100644 index 0000000000000..542d1989f0bea --- /dev/null +++ b/Zend/zend_highlight.c @@ -0,0 +1,160 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "zend_compile.h" +#include "zend_highlight.h" +#include "zend_ptr_stack.h" +#include "zend_globals.h" + +extern char *zendtext; +extern int zendleng; + + +static void html_putc(char c) +{ + switch (c) { + case '\n': + ZEND_PUTS("
"); + break; + case '<': + ZEND_PUTS("<"); + break; + case '>': + ZEND_PUTS(">"); + break; + case '&': + ZEND_PUTS("&"); + break; + case ' ': + ZEND_PUTS(" "); + break; + case '\t': + ZEND_PUTS("    "); + break; + default: + ZEND_PUTC(c); + break; + } +} + + +static void html_puts(char *s, uint len) +{ + register char *ptr=s, *end=s+len; + + while (ptrhighlight_html; + char *next_color; + int in_string=0; + CLS_FETCH(); + + zend_printf("\n", last_color); + /* highlight stuff coming back from zendlex() */ + token.type = 0; + while ((token_type=lex_scan(&token CLS_CC))) { + switch (token_type) { + case INLINE_HTML: + next_color = syntax_highlighter_ini->highlight_html; + break; + case ZEND_COMMENT: + next_color = syntax_highlighter_ini->highlight_comment; + break; + case PHP_OPEN_TAG: + next_color = syntax_highlighter_ini->highlight_default; + break; + case PHP_CLOSE_TAG: + next_color = syntax_highlighter_ini->highlight_default; + break; + case CONSTANT_ENCAPSED_STRING: + next_color = syntax_highlighter_ini->highlight_string; + break; + case '"': + next_color = syntax_highlighter_ini->highlight_string; + in_string = !in_string; + break; + case T_WHITESPACE: + html_puts(zendtext, zendleng); /* no color needed */ + token.type = 0; + continue; + break; + default: + if (token.type==0) { + next_color = syntax_highlighter_ini->highlight_keyword; + } else { + if (in_string) { + next_color = syntax_highlighter_ini->highlight_string; + } else { + next_color = syntax_highlighter_ini->highlight_default; + } + } + break; + } + + if (last_color != next_color) { + if (last_color != syntax_highlighter_ini->highlight_html) { + zend_printf(""); + } + last_color = next_color; + if (last_color != syntax_highlighter_ini->highlight_html) { + zend_printf("", last_color); + } + } + switch (token_type) { + case DOLLAR_OPEN_CURLY_BRACES: + html_puts("{", 1); + break; + default: + html_puts(zendtext, zendleng); + break; + } + + if (token.type == IS_STRING) { + switch (token_type) { + case PHP_OPEN_TAG: + case PHP_CLOSE_TAG: + case T_WHITESPACE: + break; + default: + efree(token.value.str.val); + break; + } + } + token.type = 0; + } + if (last_color != syntax_highlighter_ini->highlight_html) { + zend_printf("\n"); + } + zend_printf("\n"); +} + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/Zend/zend_highlight.h b/Zend/zend_highlight.h new file mode 100644 index 0000000000000..77e7bc418cca7 --- /dev/null +++ b/Zend/zend_highlight.h @@ -0,0 +1,43 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _HIGHLIGHT_H +#define _HIGHLIGHT_H + +#define HL_COMMENT_COLOR "#FF8000" /* orange */ +#define HL_DEFAULT_COLOR "#0000BB" /* blue */ +#define HL_HTML_COLOR "#000000" /* black */ +#define HL_STRING_COLOR "#DD0000" /* red */ +#define HL_BG_COLOR "#FFFFFF" /* white */ +#define HL_KEYWORD_COLOR "#007700" /* green */ + + +typedef struct { + char *highlight_html; + char *highlight_comment; + char *highlight_default; + char *highlight_string; + char *highlight_keyword; +} zend_syntax_highlighter_ini; + +void zend_highlight(zend_syntax_highlighter_ini *syntax_highlighter_ini); + +int highlight_file(char *filename, zend_syntax_highlighter_ini *syntax_highlighter_ini); +int highlight_string(zval *str, zend_syntax_highlighter_ini *syntax_highlighter_ini); + +extern zend_syntax_highlighter_ini syntax_highlighter_ini; + +#endif diff --git a/Zend/zend_indent.c b/Zend/zend_indent.c new file mode 100644 index 0000000000000..223cbea791a20 --- /dev/null +++ b/Zend/zend_indent.c @@ -0,0 +1,141 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +/* This indenter doesn't really work, it's here for no particular reason. */ + + +#include "zend.h" +#include "zend_compile.h" +#include "zend_indent.h" + +extern char *zendtext; +extern int zendleng; + +static void handle_whitespace(int *emit_whitespace) +{ + unsigned char c; + int i; + + for (c=0; c<128; c++) { + if (emit_whitespace[c]>0) { + for (i=0; i0) { + ZEND_PUTS(" {\n"); + memset(emit_whitespace, 0, sizeof(int)*256); + } else { + ZEND_PUTS("{"); + } + break; + case '}': + nest_level--; + if (emit_whitespace['\n']==0) { + ZEND_PUTS("\n"); + } + for (i=0; i0) { + for (i=0; i | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _ZEND_INDENT_H +#define _ZEND_INDENT_H + +void zend_indent(); + +#endif /* _ZEND_INDENT_H */ diff --git a/Zend/zend_list.c b/Zend/zend_list.c new file mode 100644 index 0000000000000..9c5c6caf8001f --- /dev/null +++ b/Zend/zend_list.c @@ -0,0 +1,238 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "zend_list.h" +#include "zend_API.h" +#include "zend_globals.h" + +#if 0 +#if HAVE_DIRENT_H +#include +#endif + +#if MSVC5 +#if !(APACHE) +#define NEEDRDH 1 +#endif +#include "win32/readdir.h" +#endif +#endif + + +int le_index_ptr; + +static inline int zend_list_do_insert(HashTable *list,void *ptr, int type) +{ + int index; + list_entry le; + + index = zend_hash_next_free_element(list); + + if (index==0) index++; + + le.ptr=ptr; + le.type=type; + le.refcount=1; + zend_hash_index_update(list, index, (void *) &le, sizeof(list_entry), NULL); + return index; +} + +static inline int zend_list_do_delete(HashTable *list,int id) +{ + list_entry *le; + ELS_FETCH(); + + if (zend_hash_index_find(&EG(regular_list), id, (void **) &le)==SUCCESS) { +// printf("del(%d): %d->%d\n", id, le->refcount, le->refcount-1); + if (--le->refcount<=0) { + return zend_hash_index_del(&EG(regular_list), id); + } else { + return SUCCESS; + } + } else { + return FAILURE; + } +} + + +static inline void *zend_list_do_find(HashTable *list,int id, int *type) +{ + list_entry *le; + + if (zend_hash_index_find(list, id, (void **) &le)==SUCCESS) { + *type = le->type; + return le->ptr; + } else { + *type = -1; + return NULL; + } +} + + +int zend_list_insert(void *ptr, int type) +{ + ELS_FETCH(); + + return zend_list_do_insert(&EG(regular_list), ptr, type); +} + + +int zend_plist_insert(void *ptr, int type) +{ + ELS_FETCH(); + + return zend_list_do_insert(&EG(persistent_list), ptr, type); +} + + +int zend_list_delete(int id) +{ + ELS_FETCH(); + + return zend_list_do_delete(&EG(regular_list), id); +} + + +int zend_list_addref(int id) +{ + list_entry *le; + ELS_FETCH(); + + if (zend_hash_index_find(&EG(regular_list), id, (void **) &le)==SUCCESS) { +// printf("add(%d): %d->%d\n", id, le->refcount, le->refcount+1); + le->refcount++; + return SUCCESS; + } else { + return FAILURE; + } +} + +int zend_plist_delete(int id) +{ + ELS_FETCH(); + + return zend_list_do_delete(&EG(persistent_list), id); +} + + +void *zend_list_find(int id, int *type) +{ + ELS_FETCH(); + + return zend_list_do_find(&EG(regular_list), id, type); +} + + +void *zend_plist_find(int id, int *type) +{ + ELS_FETCH(); + + return zend_list_do_find(&EG(persistent_list), id, type); +} + + +void list_entry_destructor(void *ptr) +{ + list_entry *le = (list_entry *) ptr; + list_destructors_entry *ld; + + if (zend_hash_index_find(&list_destructors,le->type,(void **) &ld)==SUCCESS) { + if (ld->list_destructor) { + (ld->list_destructor)(le->ptr); + } + } else { + zend_error(E_WARNING,"Unknown list entry type in request shutdown (%d)",le->type); + } +} + + +void plist_entry_destructor(void *ptr) +{ + list_entry *le = (list_entry *) ptr; + list_destructors_entry *ld; + + if (zend_hash_index_find(&list_destructors,le->type,(void **) &ld)==SUCCESS) { + if (ld->plist_destructor) { + (ld->plist_destructor)(le->ptr); + } + } else { + zend_error(E_WARNING,"Unknown persistent list entry type in module shutdown (%d)",le->type); + } +} + + +int init_resource_list(void) +{ + ELS_FETCH(); + + return zend_hash_init(&EG(regular_list), 0, NULL, list_entry_destructor, 0); +} + + +int init_resource_plist(void) +{ + ELS_FETCH(); + + return zend_hash_init(&EG(persistent_list), 0, NULL, plist_entry_destructor, 1); +} + + +void destroy_resource_list(void) +{ + ELS_FETCH(); + + zend_hash_destroy(&EG(regular_list)); +} + + +void destroy_resource_plist(void) +{ + ELS_FETCH(); + + zend_hash_destroy(&EG(persistent_list)); +} + + +static int clean_module_resource(list_entry *le, int *resource_id) +{ + if (le->type == *resource_id) { + return 1; + } else { + return 0; + } +} + + +int clean_module_resource_destructors(list_destructors_entry *ld, int *module_number) +{ + if (ld->module_number == *module_number) { + ELS_FETCH(); + + zend_hash_apply_with_argument(&EG(persistent_list), (int (*)(void *,void *)) clean_module_resource, (void *) &(ld->resource_id)); + return 1; + } else { + return 0; + } +} + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/Zend/zend_list.h b/Zend/zend_list.h new file mode 100644 index 0000000000000..b3e11a0c69674 --- /dev/null +++ b/Zend/zend_list.h @@ -0,0 +1,61 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _LIST_H +#define _LIST_H + +#include "zend_hash.h" + +extern HashTable list_destructors; + +typedef struct { + void *ptr; + int type; + int refcount; +} list_entry; + +typedef struct { + void (*list_destructor)(void *); + void (*plist_destructor)(void *); + int module_number; + int resource_id; +} list_destructors_entry; + +#define register_list_destructors(ld,pld) _register_list_destructors((void (*)(void *))ld, (void (*)(void *))pld, module_number); +ZEND_API int _register_list_destructors(void (*ld)(void *), void (*pld)(void *), int module_number); + +enum list_entry_type { + LE_DB=1000 +}; + +void list_entry_destructor(void *ptr); +void plist_entry_destructor(void *ptr); + +int clean_module_resource_destructors(list_destructors_entry *ld, int *module_number); +int init_resource_list(void); +int init_resource_plist(void); +void destroy_resource_list(void); +void destroy_resource_plist(void); + +int zend_list_insert(void *ptr, int type); +int zend_plist_insert(void *ptr, int type); +int zend_list_addref(int id); +int zend_list_delete(int id); +int zend_plist_delete(int id); +void *zend_list_find(int id, int *type); +void *zend_plist_find(int id, int *type); + +#endif diff --git a/Zend/zend_llist.c b/Zend/zend_llist.c new file mode 100644 index 0000000000000..ec19038dd0701 --- /dev/null +++ b/Zend/zend_llist.c @@ -0,0 +1,189 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "zend_llist.h" + +ZEND_API void zend_llist_init(zend_llist *l, size_t size, void (*dtor)(void *data), unsigned char persistent) +{ + l->head = NULL; + l->tail = NULL; + l->size = size; + l->dtor = dtor; + l->persistent = persistent; +} + + +ZEND_API void zend_llist_add_element(zend_llist *l, void *element) +{ + zend_llist_element *tmp = pemalloc(sizeof(zend_llist_element)+l->size-1, l->persistent); + + tmp->prev = l->tail; + tmp->next = NULL; + if (l->tail) { + l->tail->next = tmp; + } else { + l->head = tmp; + } + l->tail = tmp; + memcpy(tmp->data, element, l->size); +} + + +ZEND_API void zend_llist_del_element(zend_llist *l, void *element) +{ + zend_llist_element *current=l->head; + + while (current) { + if (current->data == element) { + if (current->prev) { + current->prev->next = current->next; + } else { + l->head = current->next; + } + if (current->next) { + current->next->prev = current->prev; + } else { + l->tail = current->prev; + } + if (l->dtor) { + l->dtor(current->data); + efree(current); + } + break; + } + current = current->next; + } +} + + +ZEND_API void zend_llist_destroy(zend_llist *l) +{ + zend_llist_element *current=l->head, *next; + + while (current) { + next = current->next; + if (l->dtor) { + l->dtor(current->data); + } + pefree(current, l->persistent); + current = next; + } +} + +ZEND_API void zend_llist_remove_tail(zend_llist *l) +{ + zend_llist_element *old_tail; + + if ((old_tail = l->tail)) { + if (l->tail->prev) { + l->tail->prev->next = NULL; + } + l->tail = l->tail->prev; + efree(old_tail); + } +} + + +ZEND_API void zend_llist_copy(zend_llist *dst, zend_llist *src) +{ + zend_llist_element *ptr; + + zend_llist_init(dst, src->size, src->dtor, src->persistent); + ptr = src->head; + while (ptr) { + zend_llist_add_element(dst, ptr->data); + ptr = ptr->next; + } +} + + +ZEND_API void zend_llist_apply(zend_llist *l, void (*func)(void *data)) +{ + zend_llist_element *element; + + for (element=l->head; element; element=element->next) { + func(element->data); + } +} + + +ZEND_API void zend_llist_apply_with_argument(zend_llist *l, void (*func)(void *data, void *arg), void *arg) +{ + zend_llist_element *element; + + for (element=l->head; element; element=element->next) { + func(element->data, arg); + } +} + + +ZEND_API int zend_llist_count(zend_llist *l) +{ + zend_llist_element *element; + int element_count=0; + + for (element=l->head; element; element=element->next) { + element_count++; + } + return element_count; +} + + +ZEND_API void *zend_llist_get_first(zend_llist *l) +{ + l->traverse_ptr = l->head; + if (l->traverse_ptr) { + return l->traverse_ptr->data; + } else { + return NULL; + } +} + + +ZEND_API void *zend_llist_get_last(zend_llist *l) +{ + l->traverse_ptr = l->tail; + if (l->traverse_ptr) { + return l->traverse_ptr->data; + } else { + return NULL; + } +} + + +ZEND_API void *zend_llist_get_next(zend_llist *l) +{ + if (l->traverse_ptr) { + l->traverse_ptr = l->traverse_ptr->next; + if (l->traverse_ptr) { + return l->traverse_ptr->data; + } + } + return NULL; +} + + +ZEND_API void *zend_llist_get_prev(zend_llist *l) +{ + if (l->traverse_ptr) { + l->traverse_ptr = l->traverse_ptr->prev; + if (l->traverse_ptr) { + return l->traverse_ptr->data; + } + } + return NULL; +} diff --git a/Zend/zend_llist.h b/Zend/zend_llist.h new file mode 100644 index 0000000000000..0c591f55d9f22 --- /dev/null +++ b/Zend/zend_llist.h @@ -0,0 +1,53 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _ZEND_LLIST_H +#define _ZEND_LLIST_H + +#include + +typedef struct _zend_llist_element { + struct _zend_llist_element *next; + struct _zend_llist_element *prev; + char data[1]; /* Needs to always be last in the struct */ +} zend_llist_element; + +typedef struct { + zend_llist_element *head; + zend_llist_element *tail; + size_t size; + void (*dtor)(void *data); + unsigned char persistent; + zend_llist_element *traverse_ptr; +} zend_llist; + +ZEND_API void zend_llist_init(zend_llist *l, size_t size, void (*dtor)(void *data), unsigned char persistent); +ZEND_API void zend_llist_add_element(zend_llist *l, void *element); +ZEND_API void zend_llist_del_element(zend_llist *l, void *element); +ZEND_API void zend_llist_destroy(zend_llist *l); +ZEND_API void zend_llist_remove_tail(zend_llist *l); +ZEND_API void zend_llist_copy(zend_llist *dst, zend_llist *src); +ZEND_API void zend_llist_apply(zend_llist *l, void (*func)(void *data)); +ZEND_API void zend_llist_apply_with_argument(zend_llist *l, void (*func)(void *data, void *arg), void *arg); +ZEND_API int zend_llist_count(zend_llist *l); + +/* traversal */ +ZEND_API void *zend_llist_get_first(zend_llist *l); +ZEND_API void *zend_llist_get_last(zend_llist *l); +ZEND_API void *zend_llist_get_next(zend_llist *l); +ZEND_API void *zend_llist_get_prev(zend_llist *l); + +#endif /* _ZEND_LLIST_H */ diff --git a/Zend/zend_modules.h b/Zend/zend_modules.h new file mode 100644 index 0000000000000..2aafdd3b0dc51 --- /dev/null +++ b/Zend/zend_modules.h @@ -0,0 +1,53 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _MODULES_H +#define _MODULES_H + +#define INIT_FUNC_ARGS int type, int module_number + +#ifdef HAS_ZEND_INI_ENTRIES +#define STANDARD_MODULE_PROPERTIES 0, 0, 0, NULL, 0 +#else +#define STANDARD_MODULE_PROPERTIES 0, 0, 0, NULL, 0 +#endif + + +#define MODULE_PERSISTENT 1 +#define MODULE_TEMPORARY 2 + +typedef struct { + char *name; + function_entry *functions; + int (*module_startup_func)(INIT_FUNC_ARGS); + int (*module_shutdown_func)(void); + int (*request_startup_func)(INIT_FUNC_ARGS); + int (*request_shutdown_func)(void); + void (*info_func)(void); + int request_started,module_started; + unsigned char type; + void *handle; + int module_number; +} zend_module_entry; + + +extern HashTable module_registry; + +extern void module_destructor(zend_module_entry *module); +extern int module_registry_cleanup(zend_module_entry *module); +extern int module_registry_request_startup(zend_module_entry *module); + +#endif diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c new file mode 100644 index 0000000000000..83f5bdf908541 --- /dev/null +++ b/Zend/zend_opcode.c @@ -0,0 +1,375 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include + +#include "zend.h" +#include "zend_alloc.h" +#include "zend_compile.h" +#include "zend_variables.h" +#include "zend_operators.h" +#include "zend_extensions.h" +#include "zend_API.h" + +static void zend_extension_op_array_ctor_handler(zend_extension *extension, zend_op_array *op_array) +{ + if (extension->op_array_ctor) { + if (extension->resource_number>=0) { + extension->op_array_ctor(&op_array->reserved[extension->resource_number]); + } else { + extension->op_array_ctor(NULL); + } + } +} + + +static void zend_extension_op_array_dtor_handler(zend_extension *extension, zend_op_array *op_array) +{ + if (extension->op_array_dtor) { + if (extension->resource_number>=0) { + extension->op_array_dtor(&op_array->reserved[extension->resource_number]); + } else { + extension->op_array_dtor(NULL); + } + } +} + + +static void op_array_alloc_ops(zend_op_array *op_array) +{ + op_array->opcodes = erealloc(op_array->opcodes, (op_array->size)*sizeof(zend_op)); +} + + + +void init_op_array(zend_op_array *op_array, int initial_ops_size) +{ + op_array->type = ZEND_USER_FUNCTION; +#if SUPPORT_INTERACTIVE + CLS_FETCH(); + + op_array->start_op_number = op_array->end_op_number = op_array->last_executed_op_number = 0; + op_array->backpatch_count = 0; + if (EG(interactive)) { + /* We must avoid a realloc() on the op_array in interactive mode, since pointers to constants + * will become invalid + */ + initial_ops_size = 8192; + } +#endif + + op_array->refcount = (int *) emalloc(sizeof(int)); + *op_array->refcount = 1; + op_array->size = initial_ops_size; + op_array->last = 0; + op_array->opcodes = NULL; + op_array_alloc_ops(op_array); + + op_array->T = 0; + + op_array->function_name = NULL; + + op_array->arg_types = NULL; + + op_array->brk_cont_array = NULL; + op_array->last_brk_cont = 0; + op_array->current_brk_cont = -1; + + op_array->static_variables = NULL; + + zend_llist_apply_with_argument(&zend_extensions, (void (*)(void *, void *)) zend_extension_op_array_ctor_handler, op_array); +} + + +void destroy_zend_function(zend_function *function) +{ + switch (function->type) { + case ZEND_USER_FUNCTION: + destroy_op_array((zend_op_array *) function); + break; + case ZEND_INTERNAL_FUNCTION: + /* do nothing */ + break; + } +} + +void destroy_zend_class(zend_class_entry *ce) +{ + switch (ce->type) { + case ZEND_USER_CLASS: + efree(ce->name); + zend_hash_destroy(&ce->function_table); + zend_hash_destroy(&ce->default_properties); + break; + case ZEND_INTERNAL_CLASS: + free(ce->name); + zend_hash_destroy(&ce->function_table); + zend_hash_destroy(&ce->default_properties); + break; + } +} + + +ZEND_API void destroy_op_array(zend_op_array *op_array) +{ + zend_op *opline = op_array->opcodes; + zend_op *end = op_array->opcodes+op_array->last; + + if (--(*op_array->refcount)>0) { + return; + } + + efree(op_array->refcount); + + while (oplineop1.op_type==IS_CONST) { +#if DEBUG_ZEND>2 + printf("Reducing refcount for %x 1=>0 (destroying)\n", &opline->op1.u.constant); +#endif + zval_dtor(&opline->op1.u.constant); + } + if (opline->op2.op_type==IS_CONST) { +#if DEBUG_ZEND>2 + printf("Reducing refcount for %x 1=>0 (destroying)\n", &opline->op2.u.constant); +#endif + zval_dtor(&opline->op2.u.constant); + } + opline++; + } + efree(op_array->opcodes); + if (op_array->function_name) { + efree(op_array->function_name); + } + if (op_array->arg_types) { + efree(op_array->arg_types); + } + if (op_array->brk_cont_array) { + efree(op_array->brk_cont_array); + } + if (op_array->static_variables) { + zend_hash_destroy(op_array->static_variables); + efree(op_array->static_variables); + } + zend_llist_apply_with_argument(&zend_extensions, (void (*)(void *, void *)) zend_extension_op_array_dtor_handler, op_array); +} + + +zend_op *get_next_op(zend_op_array *op_array CLS_DC) +{ + int next_op_num = op_array->last++; + zend_op *next_op; + + if (next_op_num >= op_array->size) { +#if SUPPORT_INTERACTIVE + ELS_FETCH(); + + if (EG(interactive)) { + /* we messed up */ + zend_printf("Ran out of opcode space!\n" + "You should probably consider writing this huge script into a file!\n"); + zend_bailout(); + } +#endif + op_array->size *= 2; + op_array_alloc_ops(op_array); + } + + next_op = &(op_array->opcodes[next_op_num]); + next_op->lineno = CG(zend_lineno); + next_op->filename = zend_get_compiled_filename(); + next_op->result.op_type = IS_UNUSED; + + return next_op; +} + + +int get_next_op_number(zend_op_array *op_array) +{ + return op_array->last; +} + + + + +zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array) +{ + op_array->last_brk_cont++; + op_array->brk_cont_array = erealloc(op_array->brk_cont_array, sizeof(zend_brk_cont_element)*op_array->last_brk_cont); + return &op_array->brk_cont_array[op_array->last_brk_cont-1]; +} + + +static void zend_update_extended_info(zend_op_array *op_array) +{ + zend_op *opline = op_array->opcodes, *end=opline+op_array->last; + + while (oplineopcode == ZEND_EXT_STMT) { + if (opline+1opcode == ZEND_EXT_STMT) { + opline->opcode = ZEND_NOP; + opline++; + continue; + } + opline->lineno = (opline+1)->lineno; + opline->filename = (opline+1)->filename; + } else { + opline->opcode = ZEND_NOP; + } + } + opline++; + } + opline = get_next_op(op_array); + opline->opcode = ZEND_EXT_STMT; + opline->op1.op_type = IS_UNUSED; + opline->op2.op_type = IS_UNUSED; + if (op_array->last>0) { + opline->filename = op_array->opcodes[op_array->last-2].filename; + opline->lineno= op_array->opcodes[op_array->last-2].lineno; + } +} + + + +static void zend_extension_op_array_handler(zend_extension *extension, zend_op_array *op_array) +{ + if (extension->op_array_handler) { + extension->op_array_handler(op_array); + } +} + + +int pass_two(zend_op_array *op_array) +{ + CLS_FETCH(); + + if (op_array->type != ZEND_USER_FUNCTION) { + return 0; + } + if (CG(extended_info)) { + zend_update_extended_info(op_array); + } + if (CG(handle_op_arrays)) { + zend_llist_apply_with_argument(&zend_extensions, (void (*)(void *, void *)) zend_extension_op_array_handler, op_array); + } + return 0; +} + + +void pass_include_eval(zend_op_array *op_array) +{ + zend_op *opline=op_array->opcodes, *end=opline+op_array->last; + + while (oplineop1.op_type==IS_CONST) { + opline->op1.u.constant.is_ref = 1; + } + if (opline->op2.op_type==IS_CONST) { + opline->op2.u.constant.is_ref = 1; + } + opline++; + } +} + + +int print_class(zend_class_entry *class_entry) +{ + printf("Class %s:\n", class_entry->name); + zend_hash_apply(&class_entry->function_table, (int (*)(void *)) pass_two); + printf("End of class %s.\n\n", class_entry->name); + return 0; +} + +ZEND_API void *get_unary_op(int opcode) +{ + switch(opcode) { + case ZEND_BW_NOT: + return (void *) bitwise_not_function; + break; + case ZEND_BOOL_NOT: + return (void *) boolean_not_function; + break; + default: + return (void *) NULL; + break; + } +} + + +ZEND_API void *get_binary_op(int opcode) +{ + switch (opcode) { + case ZEND_ADD: + case ZEND_ASSIGN_ADD: + return (void *) add_function; + break; + case ZEND_SUB: + case ZEND_ASSIGN_SUB: + return (void *) sub_function; + break; + case ZEND_MUL: + case ZEND_ASSIGN_MUL: + return (void *) mul_function; + break; + case ZEND_DIV: + case ZEND_ASSIGN_DIV: + return (void *) div_function; + break; + case ZEND_MOD: + case ZEND_ASSIGN_MOD: + return (void *) mod_function; + break; + case ZEND_SL: + case ZEND_ASSIGN_SL: + return (void *) shift_left_function; + break; + case ZEND_SR: + case ZEND_ASSIGN_SR: + return (void *) shift_right_function; + break; + case ZEND_CONCAT: + case ZEND_ASSIGN_CONCAT: + return (void *) concat_function; + break; + case ZEND_IS_EQUAL: + return (void *) is_equal_function; + break; + case ZEND_IS_NOT_EQUAL: + return (void *) is_not_equal_function; + break; + case ZEND_IS_SMALLER: + return (void *) is_smaller_function; + break; + case ZEND_IS_SMALLER_OR_EQUAL: + return (void *) is_smaller_or_equal_function; + break; + case ZEND_BW_OR: + case ZEND_ASSIGN_BW_OR: + return (void *) bitwise_or_function; + break; + case ZEND_BW_AND: + case ZEND_ASSIGN_BW_AND: + return (void *) bitwise_and_function; + break; + case ZEND_BW_XOR: + case ZEND_ASSIGN_BW_XOR: + return (void *) bitwise_xor_function; + break; + default: + return (void *) NULL; + break; + } +} diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c new file mode 100644 index 0000000000000..242afc85b6cdb --- /dev/null +++ b/Zend/zend_operators.c @@ -0,0 +1,1329 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include +#include +#include +#include +#include + +#include "zend.h" +#include "zend_operators.h" +#include "zend_variables.h" +#include "zend_globals.h" + +#if WITH_BCMATH +#include "functions/number.h" +#endif + +static inline int is_numeric_string(char *str, int length, long *lval, double *dval); + +ZEND_API void convert_scalar_to_number(zval *op) +{ + char *strval; + + if (op->type == IS_STRING) { + strval = op->value.str.val; + switch ((op->type=is_numeric_string(strval, op->value.str.len, &op->value.lval, &op->value.dval))) { + case IS_DOUBLE: + case IS_LONG: + break; +#if WITH_BCMATH + case IS_BC: + op->type = IS_DOUBLE; /* may have lost significant digits */ + break; +#endif + default: + op->value.lval = strtol(op->value.str.val, NULL, 10); + op->type = IS_LONG; + break; + } + STR_FREE(strval); + } else if (op->type == IS_BOOL || op->type==IS_RESOURCE) { + op->type = IS_LONG; + } +} + +#define zendi_convert_scalar_to_number(op, holder) \ + if ((op)->type == IS_STRING) { \ + switch (((holder).type=is_numeric_string((op)->value.str.val, (op)->value.str.len, &(holder).value.lval, &(holder).value.dval))) { \ + case IS_DOUBLE: \ + case IS_LONG: \ + break; \ + case IS_BC: \ + (holder).type = IS_DOUBLE; /* may have lost significant digits */ \ + break; \ + default: \ + (holder).value.lval = strtol((op)->value.str.val, NULL, 10); \ + (holder).type = IS_LONG; \ + break; \ + } \ + (op) = &(holder); \ + } + + +#define zendi_convert_to_long(op, holder) \ + if ((op)->type != IS_LONG) { \ + switch ((op)->type) { \ + case IS_BOOL: \ + case IS_RESOURCE: \ + break; \ + case IS_DOUBLE: \ + (holder).value.lval = (long) (op)->value.dval; \ + break; \ + case IS_STRING: \ + (holder).value.lval = strtol((op)->value.str.val, NULL, 10); \ + break; \ + case IS_ARRAY: \ + case IS_OBJECT: \ + (holder).value.lval = (zend_hash_num_elements((op)->value.ht)?1:0); \ + break; \ + default: \ + zend_error(E_WARNING, "Cannot convert to ordinal value"); \ + (holder).value.lval = 0; \ + break; \ + } \ + (holder).type = IS_LONG; \ + (op) = &(holder); \ + } + + +#define zendi_convert_to_boolean(op, holder) \ + if ((op)->type != IS_BOOL) { \ + switch ((op)->type) { \ + case IS_LONG: \ + case IS_RESOURCE: \ + (holder).value.lval = ((op)->value.lval ? 1 : 0); \ + break; \ + case IS_DOUBLE: \ + (holder).value.lval = ((op)->value.dval ? 1 : 0); \ + break; \ + case IS_STRING: \ + if ((op)->value.str.len == 0 \ + || ((op)->value.str.len==1 && (op)->value.str.val[0]=='0')) { \ + (holder).value.lval = 0; \ + } else { \ + (holder).value.lval = 1; \ + } \ + break; \ + case IS_ARRAY: \ + case IS_OBJECT: \ + (holder).value.lval = (zend_hash_num_elements((op)->value.ht)?1:0); \ + break; \ + default: \ + (holder).value.lval = 0; \ + break; \ + } \ + (holder).type = IS_BOOL; \ + (op) = &(holder); \ + } \ + + +static inline void zendi_convert_to_string(zval **op_ptr, zval *holder) +{ + zval *op = *op_ptr; + ELS_FETCH(); + + if (op->type != IS_STRING) { + switch (op->type) { + case IS_BOOL: + holder->value.str.val = (op->value.lval?estrndup("1",1):estrndup("0",1)); + holder->value.str.len = 1; + break; + case IS_RESOURCE: + case IS_LONG: + holder->value.str.val = (char *) emalloc(MAX_LENGTH_OF_LONG + 1); + holder->value.str.len = zend_sprintf(holder->value.str.val, "%ld", op->value.lval); /* SAFE */ + break; + case IS_DOUBLE: { + holder->value.str.val = (char *) emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1); + holder->value.str.len = zend_sprintf(holder->value.str.val, "%.*G", (int) EG(precision), op->value.dval); /* SAFE */ + /* %G already handles removing trailing zeros from the fractional part, yay */ + break; + } + case IS_ARRAY: + holder->value.str.val = estrndup("Array",sizeof("Array")-1); + holder->value.str.len = sizeof("Array")-1; + break; + case IS_OBJECT: + holder->value.str.val = estrndup("Object",sizeof("Object")-1); + holder->value.str.len = sizeof("Object")-1; + break; + default: + var_reset(holder); + break; + } + holder->type = IS_STRING; + *op_ptr = holder; + } +} + +ZEND_API void convert_to_long(zval *op) +{ + convert_to_long_base(op, 10); +} + + +ZEND_API void convert_to_long_base(zval *op, int base) +{ + char *strval; + long tmp; + + switch (op->type) { + case IS_BOOL: + case IS_RESOURCE: + case IS_LONG: + return; + case IS_DOUBLE: + op->value.lval = (long) op->value.dval; + op->type = IS_LONG; + break; + case IS_STRING: + strval = op->value.str.val; + op->value.lval = strtol(strval, NULL, base); + op->type = IS_LONG; + STR_FREE(strval); + break; + case IS_ARRAY: + tmp = (zend_hash_num_elements(op->value.ht)?1:0); + zval_dtor(op); + op->value.lval = tmp; + op->type = IS_LONG; + break; + case IS_OBJECT: + tmp = (zend_hash_num_elements(op->value.obj.properties)?1:0); + zval_dtor(op); + op->value.lval = tmp; + op->type = IS_LONG; + break; + default: + zend_error(E_WARNING, "Cannot convert to ordinal value"); + zval_dtor(op); + op->value.lval = 0; + op->type = IS_LONG; + break; + } + + op->type = IS_LONG; +} + + +ZEND_API void convert_to_double(zval *op) +{ + char *strval; + double tmp; + + switch (op->type) { + case IS_BOOL: + case IS_RESOURCE: + case IS_LONG: + op->value.dval = (double) op->value.lval; + op->type = IS_DOUBLE; + break; + case IS_DOUBLE: + break; + case IS_STRING: + strval = op->value.str.val; + + op->value.dval = strtod(strval, NULL); + op->type = IS_DOUBLE; + STR_FREE(strval); + break; + case IS_ARRAY: + case IS_OBJECT: + tmp = (zend_hash_num_elements(op->value.ht)?1:0); + zval_dtor(op); + op->value.dval = tmp; + op->type = IS_DOUBLE; + break; + default: + zend_error(E_WARNING, "Cannot convert to real value (type=%d)", op->type); + zval_dtor(op); + op->value.dval = 0; + op->type = IS_DOUBLE; + break; + } +} + + +ZEND_API void convert_to_boolean(zval *op) +{ + char *strval; + int tmp; + + switch (op->type) { + case IS_BOOL: + break; + case IS_LONG: + case IS_RESOURCE: + op->value.lval = (op->value.lval ? 1 : 0); + break; + case IS_DOUBLE: + op->value.lval = (op->value.dval ? 1 : 0); + break; + case IS_STRING: + strval = op->value.str.val; + + if (op->value.str.len == 0 + || (op->value.str.len==1 && op->value.str.val[0]=='0')) { + op->value.lval = 0; + } else { + op->value.lval = 1; + } + STR_FREE(strval); + break; + case IS_ARRAY: + case IS_OBJECT: + tmp = (zend_hash_num_elements(op->value.ht)?1:0); + zval_dtor(op); + op->value.lval = tmp; + break; + default: + zval_dtor(op); + op->value.lval = 0; + break; + } + op->type = IS_BOOL; +} + + +ZEND_API void convert_to_string(zval *op) +{ + long lval; + double dval; + ELS_FETCH(); + + switch (op->type) { + case IS_STRING: + break; + case IS_BOOL: + op->value.str.val = (op->value.lval?estrndup("1",1):estrndup("0",0)); + op->value.str.len = 1; + break; + case IS_LONG: + lval = op->value.lval; + + op->value.str.val = (char *) emalloc(MAX_LENGTH_OF_LONG + 1); + op->value.str.len = zend_sprintf(op->value.str.val, "%ld", lval); /* SAFE */ + break; + case IS_DOUBLE: { + dval = op->value.dval; + op->value.str.val = (char *) emalloc(MAX_LENGTH_OF_DOUBLE + EG(precision) + 1); + op->value.str.len = zend_sprintf(op->value.str.val, "%.*G", (int) EG(precision), dval); /* SAFE */ + /* %G already handles removing trailing zeros from the fractional part, yay */ + break; + } + case IS_ARRAY: + zval_dtor(op); + op->value.str.val = estrndup("Array",sizeof("Array")-1); + op->value.str.len = sizeof("Array")-1; + break; + case IS_OBJECT: + zval_dtor(op); + op->value.str.val = estrndup("Object",sizeof("Object")-1); + op->value.str.len = sizeof("Object")-1; + break; + default: + zval_dtor(op); + var_reset(op); + break; + } + op->type = IS_STRING; +} + + +static void convert_scalar_to_array(zval *op, int type) +{ + zval *entry = (zval *) emalloc(sizeof(zval)); + + *entry = *op; + entry->refcount = 1; + entry->is_ref = 0; + + switch (type) { + case IS_ARRAY: + op->value.ht = (HashTable *) emalloc(sizeof(HashTable)); + zend_hash_init(op->value.ht, 0, NULL, PVAL_PTR_DTOR, 0); + zend_hash_index_update(op->value.ht, 0, (void *) &entry, sizeof(zval *), NULL); + op->type = IS_ARRAY; + break; + case IS_OBJECT: + op->value.obj.properties = (HashTable *) emalloc(sizeof(HashTable)); + zend_hash_init(op->value.obj.properties, 0, NULL, PVAL_PTR_DTOR, 0); + zend_hash_update(op->value.obj.properties, "scalar", sizeof("scalar"), (void *) &entry, sizeof(zval *), NULL); + op->value.obj.ce = &standard_class; + op->type = IS_OBJECT; + break; + } +} + + +ZEND_API void convert_to_array(zval *op) +{ + switch(op->type) { + case IS_ARRAY: + return; + break; + case IS_OBJECT: + op->type = IS_ARRAY; + op->value.ht = op->value.obj.properties; + return; + break; + default: + convert_scalar_to_array(op, IS_ARRAY); + break; + } +} + + +ZEND_API void convert_to_object(zval *op) +{ + switch(op->type) { + case IS_ARRAY: + op->type = IS_OBJECT; + op->value.obj.properties = op->value.ht; + op->value.obj.ce = &standard_class; + return; + break; + case IS_OBJECT: + return; + break; + default: + convert_scalar_to_array(op, IS_OBJECT); + break; + } +} + + +ZEND_API int add_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + if (op1->type == IS_ARRAY && op2->type == IS_ARRAY) { + zval tmp; + + zend_hash_merge(op1->value.ht,op2->value.ht,(void (*)(void *pData)) zval_copy_ctor, (void *) &tmp, sizeof(zval)); + *result = *op1; + zval_dtor(op2); + return SUCCESS; + } + zendi_convert_scalar_to_number(op1, op1_copy); + zendi_convert_scalar_to_number(op2, op2_copy); + + if (op1->type == IS_LONG && op2->type == IS_LONG) { + double dval = (double) op1->value.lval + (double) op2->value.lval; + + if (dval > (double) LONG_MAX) { + result->value.dval = dval; + result->type = IS_DOUBLE; + } else { + result->value.lval = op1->value.lval + op2->value.lval; + result->type = IS_LONG; + } + return SUCCESS; + } + if ((op1->type == IS_DOUBLE && op2->type == IS_LONG) + || (op1->type == IS_LONG && op2->type == IS_DOUBLE)) { + result->type = IS_DOUBLE; + result->value.dval = (op1->type == IS_LONG ? + (((double) op1->value.lval) + op2->value.dval) : + (op1->value.dval + ((double) op2->value.lval))); + return SUCCESS; + } + if (op1->type == IS_DOUBLE && op2->type == IS_DOUBLE) { + result->type = IS_DOUBLE; + result->value.dval = op1->value.dval + op2->value.dval; + return SUCCESS; + } + zend_error(E_ERROR, "Unsupported operand types"); + return FAILURE; /* unknown datatype */ +} + + +ZEND_API int sub_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + zendi_convert_scalar_to_number(op1, op1_copy); + zendi_convert_scalar_to_number(op2, op2_copy); + + if (op1->type == IS_LONG && op2->type == IS_LONG) { + double dval = (double) op1->value.lval - (double) op2->value.lval; + + if (dval < (double) LONG_MIN) { + result->value.dval = dval; + result->type = IS_DOUBLE; + } else { + result->value.lval = op1->value.lval - op2->value.lval; + result->type = IS_LONG; + } + return SUCCESS; + } + if ((op1->type == IS_DOUBLE && op2->type == IS_LONG) + || (op1->type == IS_LONG && op2->type == IS_DOUBLE)) { + result->type = IS_DOUBLE; + result->value.dval = (op1->type == IS_LONG ? + (((double) op1->value.lval) - op2->value.dval) : + (op1->value.dval - ((double) op2->value.lval))); + return SUCCESS; + } + if (op1->type == IS_DOUBLE && op2->type == IS_DOUBLE) { + result->type = IS_DOUBLE; + result->value.dval = op1->value.dval - op2->value.dval; + return SUCCESS; + } + zend_error(E_ERROR, "Unsupported operand types"); + return FAILURE; /* unknown datatype */ +} + + +ZEND_API int mul_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + zendi_convert_scalar_to_number(op1, op1_copy); + zendi_convert_scalar_to_number(op2, op2_copy); + + if (op1->type == IS_LONG && op2->type == IS_LONG) { + double dval = (double) op1->value.lval * (double) op2->value.lval; + + if (dval > (double) LONG_MAX) { + result->value.dval = dval; + result->type = IS_DOUBLE; + } else { + result->value.lval = op1->value.lval * op2->value.lval; + result->type = IS_LONG; + } + return SUCCESS; + } + if ((op1->type == IS_DOUBLE && op2->type == IS_LONG) + || (op1->type == IS_LONG && op2->type == IS_DOUBLE)) { + result->type = IS_DOUBLE; + result->value.dval = (op1->type == IS_LONG ? + (((double) op1->value.lval) * op2->value.dval) : + (op1->value.dval * ((double) op2->value.lval))); + return SUCCESS; + } + if (op1->type == IS_DOUBLE && op2->type == IS_DOUBLE) { + result->type = IS_DOUBLE; + result->value.dval = op1->value.dval * op2->value.dval; + return SUCCESS; + } + zend_error(E_ERROR, "Unsupported operand types"); + return FAILURE; /* unknown datatype */ +} + +ZEND_API int div_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + zendi_convert_scalar_to_number(op1, op1_copy); + zendi_convert_scalar_to_number(op2, op2_copy); + + if ((op2->type == IS_LONG && op2->value.lval == 0) || (op2->type == IS_DOUBLE && op2->value.dval == 0.0)) { + zend_error(E_WARNING, "Division by zero"); + var_reset(result); + return FAILURE; /* division by zero */ + } + if (op1->type == IS_LONG && op2->type == IS_LONG) { + if (op1->value.lval % op2->value.lval == 0) { /* integer */ + result->type = IS_LONG; + result->value.lval = op1->value.lval / op2->value.lval; + } else { + result->type = IS_DOUBLE; + result->value.dval = ((double) op1->value.lval) / op2->value.lval; + } + return SUCCESS; + } + if ((op1->type == IS_DOUBLE && op2->type == IS_LONG) + || (op1->type == IS_LONG && op2->type == IS_DOUBLE)) { + result->type = IS_DOUBLE; + result->value.dval = (op1->type == IS_LONG ? + (((double) op1->value.lval) / op2->value.dval) : + (op1->value.dval / ((double) op2->value.lval))); + return SUCCESS; + } + if (op1->type == IS_DOUBLE && op2->type == IS_DOUBLE) { + result->type = IS_DOUBLE; + result->value.dval = op1->value.dval / op2->value.dval; + return SUCCESS; + } + zend_error(E_ERROR, "Unsupported operand types"); + return FAILURE; /* unknown datatype */ +} + + +ZEND_API int mod_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + zendi_convert_to_long(op1, op1_copy); + zendi_convert_to_long(op2, op2_copy); + + if (op2->value.lval == 0) { + var_reset(result); + return FAILURE; /* modulus by zero */ + } + + result->type = IS_LONG; + result->value.lval = op1->value.lval % op2->value.lval; + return SUCCESS; +} + + +ZEND_API int boolean_or_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + result->type = IS_BOOL; + + zendi_convert_to_boolean(op1, op1_copy); + if (op1->value.lval) { + result->value.lval = 1; + return SUCCESS; + } + zendi_convert_to_boolean(op2, op2_copy); + if (op2->value.lval) { + result->value.lval = 1; + return SUCCESS; + } + result->value.lval = 0; + return SUCCESS; +} + + +ZEND_API int boolean_and_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + result->type = IS_BOOL; + + zendi_convert_to_boolean(op1, op1_copy); + if (!op1->value.lval) { + result->value.lval = 0; + return SUCCESS; + } + zendi_convert_to_boolean(op2, op2_copy); + if (!op2->value.lval) { + result->value.lval = 0; + return SUCCESS; + } + result->value.lval = 1; + return SUCCESS; +} + + +ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + result->type = IS_BOOL; + + zendi_convert_to_boolean(op1, op1_copy); + zendi_convert_to_boolean(op2, op2_copy); + result->value.lval = op1->value.lval ^ op2->value.lval; + return SUCCESS; +} + + +ZEND_API int boolean_not_function(zval *result, zval *op1) +{ + zval op1_copy; + + zendi_convert_to_boolean(op1, op1_copy); + + result->type = IS_BOOL; + result->value.lval = !op1->value.lval; + return SUCCESS; +} + + +ZEND_API int bitwise_not_function(zval *result, zval *op1) +{ + zval op1_copy = *op1; + + op1 = &op1_copy; + + if (op1->type == IS_DOUBLE) { + op1->value.lval = (long) op1->value.dval; + op1->type = IS_LONG; + } + if (op1->type == IS_LONG) { + result->value.lval = ~op1->value.lval; + result->type = IS_LONG; + return SUCCESS; + } + if (op1->type == IS_STRING) { + int i; + + result->type = IS_STRING; + result->value.str.val = estrndup(op1->value.str.val, op1->value.str.len); + result->value.str.len = op1->value.str.len; + for (i = 0; i < op1->value.str.len; i++) { + result->value.str.val[i] = ~op1->value.str.val[i]; + } + return SUCCESS; + } + zend_error(E_ERROR, "Unsupported operand types"); + return FAILURE; /* unknown datatype */ +} + + +ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + if (op1->type == IS_STRING && op2->type == IS_STRING) { + zval *longer, *shorter; + int i; + + if (op1->value.str.len >= op2->value.str.len) { + longer = op1; + shorter = op2; + } else { + longer = op2; + shorter = op1; + } + + result->value.str.len = longer->value.str.len; + result->value.str.val = estrndup(longer->value.str.val, longer->value.str.len); + for (i = 0; i < shorter->value.str.len; i++) { + result->value.str.val[i] |= shorter->value.str.val[i]; + } + return SUCCESS; + } + zendi_convert_to_long(op1, op1_copy); + zendi_convert_to_long(op2, op2_copy); + + result->type = IS_LONG; + result->value.lval = op1->value.lval | op2->value.lval; + return SUCCESS; +} + + +ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + if (op1->type == IS_STRING && op2->type == IS_STRING) { + zval *longer, *shorter; + int i; + + if (op1->value.str.len >= op2->value.str.len) { + longer = op1; + shorter = op2; + } else { + longer = op2; + shorter = op1; + } + + result->value.str.len = shorter->value.str.len; + result->value.str.val = estrndup(shorter->value.str.val, shorter->value.str.len); + for (i = 0; i < shorter->value.str.len; i++) { + result->value.str.val[i] &= longer->value.str.val[i]; + } + return SUCCESS; + } + + + zendi_convert_to_long(op1, op1_copy); + zendi_convert_to_long(op2, op2_copy); + + result->type = IS_LONG; + result->value.lval = op1->value.lval & op2->value.lval; + return SUCCESS; +} + + +ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + if (op1->type == IS_STRING && op2->type == IS_STRING) { + zval *longer, *shorter; + int i; + + if (op1->value.str.len >= op2->value.str.len) { + longer = op1; + shorter = op2; + } else { + longer = op2; + shorter = op1; + } + + result->value.str.len = shorter->value.str.len; + result->value.str.val = estrndup(shorter->value.str.val, shorter->value.str.len); + for (i = 0; i < shorter->value.str.len; i++) { + result->value.str.val[i] ^= longer->value.str.val[i]; + } + return SUCCESS; + } + + zendi_convert_to_long(op1, op1_copy); + zendi_convert_to_long(op2, op2_copy); + + result->type = IS_LONG; + result->value.lval = op1->value.lval ^ op2->value.lval; + return SUCCESS; +} + + +ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + zendi_convert_to_long(op1, op1_copy); + zendi_convert_to_long(op2, op2_copy); + result->value.lval = op1->value.lval << op2->value.lval; + result->type = IS_LONG; + return SUCCESS; +} + + +ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + zendi_convert_to_long(op1, op1_copy); + zendi_convert_to_long(op2, op2_copy); + result->value.lval = op1->value.lval >> op2->value.lval; + result->type = IS_LONG; + return SUCCESS; +} + + + +/* must support result==op1 */ +ZEND_API int add_char_to_string(zval *result, zval *op1, zval *op2) +{ + result->value.str.len = op1->value.str.len + 1; + result->value.str.val = (char *) erealloc(op1->value.str.val, result->value.str.len+1); + result->value.str.val[result->value.str.len - 1] = op2->value.chval; + result->value.str.val[result->value.str.len] = 0; + result->type = IS_STRING; + return SUCCESS; +} + + +/* must support result==op1 */ +ZEND_API int add_string_to_string(zval *result, zval *op1, zval *op2) +{ + int length = op1->value.str.len + op2->value.str.len; + result->value.str.val = (char *) erealloc(op1->value.str.val, length+1); + memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val, op2->value.str.len); + result->value.str.val[length] = 0; + result->value.str.len = length; + result->type = IS_STRING; + return SUCCESS; +} + + +ZEND_API int concat_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + zval *orig_op1=op1, *orig_op2=op2; + + zendi_convert_to_string(&op1, &op1_copy); + zendi_convert_to_string(&op2, &op2_copy); + + if (result==op1) { /* special case, perform operations on result */ + uint res_len = op1->value.str.len + op2->value.str.len; + + if (result->value.str.len == 0) { /* handle empty_string */ + STR_FREE(result->value.str.val); + result->value.str.val = emalloc(res_len+1); + } else { + result->value.str.val = erealloc(result->value.str.val, res_len+1); + } + memcpy(result->value.str.val+result->value.str.len, op2->value.str.val, op2->value.str.len); + result->value.str.val[res_len]=0; + result->value.str.len = res_len; + } else { + result->value.str.len = op1->value.str.len + op2->value.str.len; + result->value.str.val = (char *) emalloc(result->value.str.len + 1); + memcpy(result->value.str.val, op1->value.str.val, op1->value.str.len); + memcpy(result->value.str.val+op1->value.str.len, op2->value.str.val,op2->value.str.len); + result->value.str.val[result->value.str.len] = 0; + result->type = IS_STRING; + } + if (orig_op1 != op1) { + zval_dtor(op1); + } + if (orig_op2 != op2) { + zval_dtor(op2); + } + return SUCCESS; +} + + +ZEND_API int compare_function(zval *result, zval *op1, zval *op2) +{ + zval op1_copy, op2_copy; + + if (op1->type == IS_STRING && op2->type == IS_STRING) { + zendi_smart_strcmp(result,op1,op2); + return SUCCESS; + } + + if (op1->type == IS_BOOL || op2->type == IS_BOOL) { + convert_to_boolean(op1); + convert_to_boolean(op2); + result->type = IS_LONG; + result->value.lval = (op1->value.lval!=op2->value.lval); + return SUCCESS; + } + zendi_convert_scalar_to_number(op1, op1_copy); + zendi_convert_scalar_to_number(op2, op2_copy); + + if (op1->type == IS_LONG && op2->type == IS_LONG) { + result->type = IS_LONG; + result->value.lval = op1->value.lval - op2->value.lval; + return SUCCESS; + } + if ((op1->type == IS_DOUBLE || op1->type == IS_LONG) + && (op2->type == IS_DOUBLE || op2->type == IS_LONG)) { + result->type = IS_DOUBLE; + result->value.dval = (op1->type == IS_LONG ? (double) op1->value.lval : op1->value.dval) - (op2->type == IS_LONG ? (double) op2->value.lval : op2->value.dval); + return SUCCESS; + } + if ((op1->type==IS_ARRAY || op1->type==IS_OBJECT) + && (op2->type==IS_ARRAY || op2->type==IS_OBJECT)) { + zend_error(E_WARNING,"Cannot compare arrays or objects"); + } + var_reset(result); + return FAILURE; +} + + +ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2) +{ + if (compare_function(result, op1, op2) == FAILURE) { + return FAILURE; + } + convert_to_boolean(result); + if (result->value.lval == 0) { + result->value.lval = 1; + } else { + result->value.lval = 0; + } + return SUCCESS; +} + + +ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2) +{ + if (compare_function(result, op1, op2) == FAILURE) { + return FAILURE; + } + convert_to_boolean(result); + if (result->value.lval) { + result->value.lval = 1; + } else { + result->value.lval = 0; + } + return SUCCESS; +} + + +ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2) +{ + //printf("Comparing %d and %d\n", op1->value.lval, op2->value.lval); + if (compare_function(result, op1, op2) == FAILURE) { + return FAILURE; + } + if (result->type == IS_LONG) { + if (result->value.lval < 0) { + result->value.lval = 1; + } else { + result->value.lval = 0; + } + return SUCCESS; + } + if (result->type == IS_DOUBLE) { + result->type = IS_LONG; + if (result->value.dval < 0) { + result->value.lval = 1; + } else { + result->value.lval = 0; + } + return SUCCESS; + } + zend_error(E_ERROR, "Unsupported operand types"); + return FAILURE; +} + + +ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2) +{ + if (compare_function(result, op1, op2) == FAILURE) { + return FAILURE; + } + if (result->type == IS_LONG) { + if (result->value.lval <= 0) { + result->value.lval = 1; + } else { + result->value.lval = 0; + } + return SUCCESS; + } + if (result->type == IS_DOUBLE) { + result->type = IS_LONG; + if (result->value.dval <= 0) { + result->value.lval = 1; + } else { + result->value.lval = 0; + } + return SUCCESS; + } + zend_error(E_ERROR, "Unsupported operand types"); + return FAILURE; +} + + +#define LOWER_CASE 1 +#define UPPER_CASE 2 +#define NUMERIC 3 + + +static void increment_string(zval *str) +{ + int carry=0; + int pos=str->value.str.len-1; + char *s=str->value.str.val; + char *t; + int last=0; /* Shut up the compiler warning */ + int ch; + + while(pos >= 0) { + ch = s[pos]; + if (ch >= 'a' && ch <= 'z') { + if (ch == 'z') { + s[pos] = 'a'; + carry=1; + } else { + s[pos]++; + carry=0; + } + last=LOWER_CASE; + } else if (ch >= 'A' && ch <= 'Z') { + if (ch == 'Z') { + s[pos] = 'A'; + carry=1; + } else { + s[pos]++; + carry=0; + } + last=UPPER_CASE; + } else if (ch >= '0' && ch <= '9') { + if (ch == '9') { + s[pos] = '0'; + carry=1; + } else { + s[pos]++; + carry=0; + } + last = NUMERIC; + } else { + carry=0; + break; + } + if (carry == 0) { + break; + } + pos--; + } + + if (carry) { + t = (char *) emalloc(str->value.str.len+1+1); + memcpy(t+1,str->value.str.val, str->value.str.len); + str->value.str.len++; + t[str->value.str.len] = '\0'; + switch (last) { + case NUMERIC: + t[0] = '1'; + break; + case UPPER_CASE: + t[0] = 'A'; + break; + case LOWER_CASE: + t[0] = 'a'; + break; + } + STR_FREE(str->value.str.val); + str->value.str.val = t; + } +} + + +ZEND_API int increment_function(zval *op1) +{ + switch (op1->type) { + case IS_LONG: + op1->value.lval++; + break; + case IS_DOUBLE: + op1->value.dval = op1->value.dval + 1; + break; + case IS_STRING: /* Perl style string increment */ + if (op1->value.str.len==0) { /* consider as 0 */ + STR_FREE(op1->value.str.val); + op1->value.lval = 1; + op1->type = IS_LONG; + } else { + increment_string(op1); + } + break; + default: + return FAILURE; + } + return SUCCESS; +} + + +ZEND_API int decrement_function(zval *op1) +{ + long lval; + + switch (op1->type) { + case IS_LONG: + op1->value.lval--; + break; + case IS_DOUBLE: + op1->value.dval = op1->value.dval - 1; + break; + case IS_STRING: /* Like perl we only support string increment */ + if (op1->value.str.len==0) { /* consider as 0 */ + STR_FREE(op1->value.str.val); + op1->value.lval = -1; + op1->type = IS_LONG; + break; + } else if (is_numeric_string(op1->value.str.val, op1->value.str.len, &lval, NULL)==IS_LONG) { /* long */ + op1->value.lval = lval-1; + op1->type = IS_LONG; + break; + } + break; + default: + return FAILURE; + } + + return SUCCESS; +} + + +ZEND_API int zval_is_true(zval *op) +{ + convert_to_boolean(op); + 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 (pvalue.str.val, s2->value.str.val, MIN(s1->value.str.len,s2->value.str.len)); + if (!retval) { + return (s1->value.str.len - s2->value.str.len); + } else { + return retval; + } +} + + +ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2) +{ + int ret1,ret2; + long lval1, lval2; + double dval1, dval2; + + if ((ret1=is_numeric_string(s1->value.str.val, s1->value.str.len, &lval1, &dval1)) && + (ret2=is_numeric_string(s2->value.str.val, s2->value.str.len, &lval2, &dval2))) { +#if WITH_BCMATH + if ((ret1==IS_BC) || (ret2==IS_BC)) { + bc_num first, second; + + /* use the BC math library to compare the numbers */ + init_num(&first); + init_num(&second); + str2num(&first,s1->value.str.val,100); /* this scale should do */ + str2num(&second,s2->value.str.val,100); /* ditto */ + result->value.lval = bc_compare(first,second); + result->type = IS_LONG; + free_num(&first); + free_num(&second); + } else +#endif + if ((ret1==IS_DOUBLE) || (ret2==IS_DOUBLE)) { + if (ret1!=IS_DOUBLE) { + dval1 = strtod(s1->value.str.val, NULL); + } else if (ret2!=IS_DOUBLE) { + dval2 = strtod(s2->value.str.val, NULL); + } + result->value.dval = dval1 - dval2; + result->type = IS_DOUBLE; + } else { /* they both have to be long's */ + result->value.lval = lval1 - lval2; + result->type = IS_LONG; + } + } else { + result->value.lval = zend_binary_strcmp(s1,s2); + result->type = IS_LONG; + } + return; +} + + +/* returns 0 for non-numeric string + * returns IS_DOUBLE for floating point string, and assigns the value to *dval (if it's not NULL) + * returns IS_LONG for integer strings, and assigns the value to *lval (if it's not NULL) + * returns IS_BC if the number might lose accuracy when converted to a double + */ + +#if 1 +static inline int is_numeric_string(char *str, int length, long *lval, double *dval) +{ + long local_lval; + double local_dval; + char *end_ptr; + + if (!length) { + return 0; + } + + errno=0; + local_lval = strtol(str, &end_ptr, 10); + if (errno!=ERANGE && end_ptr == str+length) { /* integer string */ + if (lval) { + *lval = local_lval; + } + return IS_LONG; + } + + errno=0; + local_dval = strtod(str, &end_ptr); + if (errno!=ERANGE && end_ptr == str+length) { /* floating point string */ + if (dval) { + *dval = local_dval; + } +#if WITH_BCMATH + if (length>16) { + register char *ptr=str, *end=str+length; + + while(ptr | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _OPERATORS_H +#define _OPERATORS_H + +#define MAX_LENGTH_OF_LONG 18 +#define MAX_LENGTH_OF_DOUBLE 32 + +ZEND_API int add_function(zval *result, zval *op1, zval *op2); +ZEND_API int sub_function(zval *result, zval *op1, zval *op2); +ZEND_API int mul_function(zval *result, zval *op1, zval *op2); +ZEND_API int div_function(zval *result, zval *op1, zval *op2); +ZEND_API int mod_function(zval *result, zval *op1, zval *op2); +ZEND_API int boolean_or_function(zval *result, zval *op1, zval *op2); +ZEND_API int boolean_xor_function(zval *result, zval *op1, zval *op2); +ZEND_API int boolean_and_function(zval *result, zval *op1, zval *op2); +ZEND_API int boolean_not_function(zval *result, zval *op1); +ZEND_API int bitwise_not_function(zval *result, zval *op1); +ZEND_API int bitwise_or_function(zval *result, zval *op1, zval *op2); +ZEND_API int bitwise_and_function(zval *result, zval *op1, zval *op2); +ZEND_API int bitwise_xor_function(zval *result, zval *op1, zval *op2); +ZEND_API int shift_left_function(zval *result, zval *op1, zval *op2); +ZEND_API int shift_right_function(zval *result, zval *op1, zval *op2); +ZEND_API int concat_function(zval *result, zval *op1, zval *op2); + +ZEND_API int is_equal_function(zval *result, zval *op1, zval *op2); +ZEND_API int is_not_equal_function(zval *result, zval *op1, zval *op2); +ZEND_API int is_smaller_function(zval *result, zval *op1, zval *op2); +ZEND_API int is_smaller_or_equal_function(zval *result, zval *op1, zval *op2); + +ZEND_API int increment_function(zval *op1); +ZEND_API int decrement_function(zval *op2); + +ZEND_API void convert_scalar_to_number(zval *op); +ZEND_API void convert_to_string(zval *op); +ZEND_API void convert_to_long(zval *op); +ZEND_API void convert_to_long_base(zval *op, int base); +ZEND_API void convert_to_boolean(zval *op); +ZEND_API void convert_to_array(zval *op); +ZEND_API void convert_to_object(zval *op); +ZEND_API int add_char_to_string(zval *result, zval *op1, zval *op2); +ZEND_API int add_string_to_string(zval *result, zval *op1, zval *op2); +ZEND_API void convert_to_double(zval *op); + +ZEND_API int zval_is_true(zval *op); +ZEND_API int compare_function(zval *result, zval *op1, zval *op2); + +ZEND_API void zend_str_tolower(char *str, unsigned int length); +ZEND_API int zend_binary_strcmp(zval *s1, zval *s2); +ZEND_API void zendi_smart_strcmp(zval *result, zval *s1, zval *s2); + +#endif diff --git a/Zend/zend_ptr_stack.c b/Zend/zend_ptr_stack.c new file mode 100644 index 0000000000000..3eeec0576ca5a --- /dev/null +++ b/Zend/zend_ptr_stack.c @@ -0,0 +1,71 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "zend_ptr_stack.h" + + +ZEND_API void zend_ptr_stack_init(zend_ptr_stack *stack) +{ + stack->top_element = stack->elements = (void **) emalloc(sizeof(void *)*STACK_BLOCK_SIZE); + stack->max = STACK_BLOCK_SIZE; + stack->top = 0; +} + + +ZEND_API inline void zend_ptr_stack_push(zend_ptr_stack *stack, void *ptr) +{ + if (stack->top >= stack->max) { /* we need to allocate more memory */ + short diff = stack->top_element-stack->elements; + + stack->elements = (void **) erealloc(stack->elements, (sizeof(void *) * (stack->max *= 2 ))); + stack->top_element = stack->elements+diff; + } + stack->top++; + *(stack->top_element++) = ptr; +} + + +ZEND_API inline void *zend_ptr_stack_pop(zend_ptr_stack *stack) +{ + stack->top--; + return *(--stack->top_element); +} + + +ZEND_API void zend_ptr_stack_destroy(zend_ptr_stack *stack) +{ + if (stack->elements) { + efree(stack->elements); + } +} + + +ZEND_API void zend_ptr_stack_apply(zend_ptr_stack *stack, void (*func)(void *)) +{ + int i = stack->top; + + while (--i >= 0) { + func(stack->elements[i]); + } +} + + +ZEND_API void zend_ptr_stack_clean(zend_ptr_stack *stack, void (*func)(void *)) +{ + zend_ptr_stack_apply(stack, func); + stack->top = 0; +} diff --git a/Zend/zend_ptr_stack.h b/Zend/zend_ptr_stack.h new file mode 100644 index 0000000000000..15f59de293c4b --- /dev/null +++ b/Zend/zend_ptr_stack.h @@ -0,0 +1,37 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + + +#ifndef _ZEND_PTR_STACK_H +#define _ZEND_PTR_STACK_H + +typedef struct { + short top, max; + void **elements; + void **top_element; +} zend_ptr_stack; + + +#define STACK_BLOCK_SIZE 64 + +ZEND_API void zend_ptr_stack_init(zend_ptr_stack *stack); +ZEND_API void zend_ptr_stack_push(zend_ptr_stack *stack, void *ptr); +ZEND_API void *zend_ptr_stack_pop(zend_ptr_stack *stack); +ZEND_API void zend_ptr_stack_destroy(zend_ptr_stack *stack); +ZEND_API void zend_ptr_stack_apply(zend_ptr_stack *stack, void (*func)(void *)); +ZEND_API void zend_ptr_stack_clean(zend_ptr_stack *stack, void (*func)(void *)); + +#endif /* _ZEND_PTR_STACK_H */ diff --git a/Zend/zend_sprintf.c b/Zend/zend_sprintf.c new file mode 100644 index 0000000000000..bebfd2ae8f875 --- /dev/null +++ b/Zend/zend_sprintf.c @@ -0,0 +1,34 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include + +#include "zend.h" + +#if HAVE_STDARG_H +#include +#endif + +int zend_sprintf(char *buffer, const char *format, ...) +{ + va_list args; + + va_start(args, format); + vsprintf(buffer, format, args); + va_end(args); + + return strlen(buffer); +} diff --git a/Zend/zend_stack.c b/Zend/zend_stack.c new file mode 100644 index 0000000000000..4744fed0b68a0 --- /dev/null +++ b/Zend/zend_stack.c @@ -0,0 +1,114 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include "zend.h" +#include "zend_stack.h" + +ZEND_API int zend_stack_init(zend_stack *stack) +{ + stack->top = 0; + stack->elements = (void **) emalloc(sizeof(void **) * STACK_BLOCK_SIZE); + if (!stack->elements) { + return FAILURE; + } else { + stack->max = STACK_BLOCK_SIZE; + return SUCCESS; + } +} + +ZEND_API int zend_stack_push(zend_stack *stack, void *element, int size) +{ + if (stack->top >= stack->max) { /* we need to allocate more memory */ + stack->elements = (void **) erealloc(stack->elements, + (sizeof(void **) * (stack->max += STACK_BLOCK_SIZE))); + if (!stack->elements) { + return FAILURE; + } + } + stack->elements[stack->top] = (void *) emalloc(size); + memcpy(stack->elements[stack->top], element, size); + return stack->top++; +} + + +ZEND_API int zend_stack_top(zend_stack *stack, void **element) +{ + if (stack->top > 0) { + *element = stack->elements[stack->top - 1]; + return SUCCESS; + } else { + *element = NULL; + return FAILURE; + } +} + + +ZEND_API int zend_stack_del_top(zend_stack *stack) +{ + if (stack->top > 0) { + efree(stack->elements[--stack->top]); + } + return SUCCESS; +} + + +ZEND_API int zend_stack_int_top(zend_stack *stack) +{ + int *e; + + if (zend_stack_top(stack, (void **) &e) == FAILURE) { + return FAILURE; /* this must be a negative number, since negative numbers can't be address numbers */ + } else { + return *e; + } +} + + +ZEND_API int zend_stack_is_empty(zend_stack *stack) +{ + if (stack->top == 0) { + return 1; + } else { + return 0; + } +} + + +ZEND_API int zend_stack_destroy(zend_stack *stack) +{ + register int i; + + for (i = 0; i < stack->top; i++) { + efree(stack->elements[i]); + } + + if (stack->elements) { + efree(stack->elements); + } + return SUCCESS; +} + + +ZEND_API void **zend_stack_base(zend_stack *stack) +{ + return stack->elements; +} + + +ZEND_API int zend_stack_count(zend_stack *stack) +{ + return stack->top; +} diff --git a/Zend/zend_stack.h b/Zend/zend_stack.h new file mode 100644 index 0000000000000..abd3652529aaa --- /dev/null +++ b/Zend/zend_stack.h @@ -0,0 +1,39 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _ZEND_STACK_H +#define _ZEND_STACK_H + +typedef struct { + int top, max; + void **elements; +} zend_stack; + + +#define STACK_BLOCK_SIZE 64 + +ZEND_API int zend_stack_init(zend_stack *stack); +ZEND_API int zend_stack_push(zend_stack *stack, void *element, int size); +ZEND_API int zend_stack_top(zend_stack *stack, void **element); +ZEND_API int zend_stack_del_top(zend_stack *stack); +ZEND_API int zend_stack_int_top(zend_stack *stack); +ZEND_API int zend_stack_is_empty(zend_stack *stack); +ZEND_API int zend_stack_destroy(zend_stack *stack); +ZEND_API void **zend_stack_base(zend_stack *stack); +ZEND_API int zend_stack_count(zend_stack *stack); + + +#endif /* _ZEND_STACK_H */ diff --git a/Zend/zend_variables.c b/Zend/zend_variables.c new file mode 100644 index 0000000000000..a4365435d7207 --- /dev/null +++ b/Zend/zend_variables.c @@ -0,0 +1,167 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#include +#include "zend.h" +#include "zend_API.h" +#include "zend_globals.h" +#include "zend_constants.h" +#include "zend_variables.h" +#include "zend_list.h" + +ZEND_API char *empty_string = ""; /* in order to save emalloc() and efree() time for + * empty strings (usually used to denote empty + * return values in failed functions). + * The macro STR_FREE() will not efree() it. + */ + +ZEND_API char *undefined_variable_string = "\0"; + +/* this function MUST set the value for the variable to an empty string */ +/* and empty strings must be evaluated as FALSE */ +ZEND_API inline void var_reset(zval *var) +{ + var->type = IS_STRING; + var->value.str.val = empty_string; + var->value.str.len = 0; +} + +ZEND_API inline void var_uninit(zval *var) +{ + var->type = IS_STRING; + var->value.str.val = undefined_variable_string; + var->value.str.len = 0; +} + + +ZEND_API void zval_dtor(zval *zvalue) +{ + if (zvalue->type==IS_LONG) { + return; + } + switch(zvalue->type) { + case IS_STRING: + case IS_CONSTANT: + STR_FREE(zvalue->value.str.val); + break; + case IS_ARRAY: { + ELS_FETCH(); + + if (zvalue->value.ht && (zvalue->value.ht != &EG(symbol_table))) { + if (EG(AiCount)==0) { + zend_hash_destroy(zvalue->value.ht); + efree(zvalue->value.ht); + } else { + zend_ptr_stack_push(&EG(garbage), zvalue->value.ht); + } + } + } + break; + case IS_OBJECT: { + ELS_FETCH(); + + if (EG(AiCount)==0) { + zend_hash_destroy(zvalue->value.obj.properties); + efree(zvalue->value.obj.properties); + } else { + zend_ptr_stack_push(&EG(garbage), zvalue->value.obj.properties); + } + } + break; + case IS_RESOURCE: + /* destroy resource */ + zend_list_delete(zvalue->value.lval); + break; + case IS_LONG: + case IS_DOUBLE: + case IS_BOOL: + default: + return; + break; + } +} + + +void zval_add_ref(zval **p) +{ + (*p)->refcount++; +} + + + + +ZEND_API int zval_copy_ctor(zval *zvalue) +{ + switch (zvalue->type) { + case IS_RESOURCE: + zend_list_addref(zvalue->value.lval); + break; + case IS_BOOL: + case IS_LONG: + break; + case IS_STRING: + if (zvalue->value.str.val) { + if (zvalue->value.str.len==0) { + if (zvalue->value.str.val==undefined_variable_string) { + zvalue->value.str.val = undefined_variable_string; + } else { + zvalue->value.str.val = empty_string; + } + return SUCCESS; + } + } + zvalue->value.str.val = (char *) estrndup(zvalue->value.str.val, zvalue->value.str.len); + break; + case IS_ARRAY: { + zval *tmp; + HashTable *original_ht = zvalue->value.ht; + ELS_FETCH(); + + if (!zvalue->value.ht || zvalue->value.ht==&EG(symbol_table)) { + var_reset(zvalue); + return FAILURE; + } + zvalue->value.ht = (HashTable *) emalloc(sizeof(HashTable)); + zend_hash_init(zvalue->value.ht, 0, NULL, PVAL_PTR_DTOR, 0); + zend_hash_copy(zvalue->value.ht, original_ht, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *)); + } + break; + case IS_OBJECT: { + zval *tmp; + HashTable *original_ht = zvalue->value.obj.properties; + + zvalue->value.obj.properties = (HashTable *) emalloc(sizeof(HashTable)); + zend_hash_init(zvalue->value.obj.properties, 0, NULL, PVAL_PTR_DTOR, 0); + zend_hash_copy(zvalue->value.obj.properties, original_ht, (void (*)(void *)) zval_add_ref, (void *) &tmp, sizeof(zval *)); + } + break; + } + return SUCCESS; +} + + +ZEND_API int zend_print_variable(zval *var) +{ + return zend_print_zval(var, 0); +} + + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * End: + */ diff --git a/Zend/zend_variables.h b/Zend/zend_variables.h new file mode 100644 index 0000000000000..a4525dae96b13 --- /dev/null +++ b/Zend/zend_variables.h @@ -0,0 +1,35 @@ +/* + +----------------------------------------------------------------------+ + | Zend Engine | + +----------------------------------------------------------------------+ + | Copyright (c) 1998, 1999 Andi Gutmans, Zeev Suraski | + +----------------------------------------------------------------------+ + | This source file is subject to the Zend license, that is bundled | + | with this package in the file LICENSE. If you did not receive a | + | copy of the Zend license, please mail us at zend@zend.com so we can | + | send you a copy immediately. | + +----------------------------------------------------------------------+ + | Authors: Andi Gutmans | + | Zeev Suraski | + +----------------------------------------------------------------------+ +*/ + +#ifndef _VARIABLES_H +#define _VARIABLES_H + + +ZEND_API int zend_print_variable(zval *var); + +ZEND_API int zval_copy_ctor(zval *zvalue); +ZEND_API void zval_dtor(zval *zvalue); +ZEND_API void zval_ptr_dtor(zval **zval_ptr); +void zval_add_ref(zval **p); + +#define PVAL_DESTRUCTOR (void (*)(void *)) zval_dtor +#define PVAL_PTR_DTOR (void (*)(void *)) zval_ptr_dtor +#define PVAL_COPY_CTOR (void (*)(void *)) zval_copy_ctor + +ZEND_API void var_reset(zval *var); +ZEND_API void var_uninit(zval *var); + +#endif