summaryrefslogtreecommitdiff
path: root/zend/script.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'zend/script.cpp')
-rw-r--r--zend/script.cpp164
1 files changed, 9 insertions, 155 deletions
diff --git a/zend/script.cpp b/zend/script.cpp
index 46a9ddd..58ee376 100644
--- a/zend/script.cpp
+++ b/zend/script.cpp
@@ -11,7 +11,6 @@
* Dependencies
*/
#include "includes.h"
-#include <mutex>
/**
* Open PHP namespace
@@ -19,95 +18,13 @@
namespace Php {
/**
- * Helper class to temporarily set compiler options
- *
- * When an object is destructed, it automatically restored the previous compiler settings
- */
-class CompilerOptions
-{
-private:
- /**
- * The original compiler options
- * @var int
- */
- zend_uint _original;
-
-public:
- /**
- * Constructor
- * @param options
- */
- CompilerOptions(zend_uint options)
- {
- // remember the old compiler options before we set temporary compile options
- _original = CG(compiler_options);
-
- // we're going to evaluate only once
- CG(compiler_options) = options;
- }
-
- /**
- * Destructor
- */
- virtual ~CompilerOptions()
- {
- // restore original options
- CG(compiler_options) = _original;
- }
-};
-
-/**
- * Helper class to store and restore the current opcode state
- *
- * When we're going to execute a set of instructions, we need to store the
- * current state of the Zend engine. After the instructions have been processed,
- * we can switch back to the original instructions
- */
-class ExecuteState
-{
-private:
- /**
- * All the original settings
- */
- zend_op_array *_active_op_array;
- zval **_return_value_ptr_ptr;
- zend_op **_opline_ptr;
- int _interactive;
-
-public:
- /**
- * Constructor
- */
- ExecuteState()
- {
- // store all the original stuff
- _active_op_array = EG(active_op_array);
- _return_value_ptr_ptr = EG(return_value_ptr_ptr);
- _opline_ptr = EG(opline_ptr);
- _interactive = CG(interactive);
- }
-
- /**
- * Destructor
- */
- virtual ~ExecuteState()
- {
- // restore all settings
- CG(interactive) = _interactive;
- EG(no_extensions) = 0;
- EG(opline_ptr) = _opline_ptr;
- EG(active_op_array) = _active_op_array;
- EG(return_value_ptr_ptr) = _return_value_ptr_ptr;
- }
-};
-
-/**
- * Constructor
+ * Helper function to compile the source code
* @param name name of the script
* @param script actual PHP code
* @param size length of the string
+ * @return opcodes
*/
-Script::Script(const char *name, const char *phpcode, size_t size)
+zend_op_array *Script::compile(const char *name, const char *phpcode, size_t size)
{
// Sadly, there is not a simple Zend function to compile a string into opcodes,
// so we basically copy the code that we found in zend_execute_API.c inside
@@ -123,80 +40,17 @@ Script::Script(const char *name, const char *phpcode, size_t size)
TSRMLS_FETCH();
// compile the string
- _opcodes = zend_compile_string(source._val, (char *)name TSRMLS_CC);
-}
-
-/**
- * Destructor
- */
-Script::~Script()
-{
- // do nothing if there are no opcodes
- if (!_opcodes) return;
-
- // clean up opcodes
- destroy_op_array(_opcodes TSRMLS_CC);
- efree(_opcodes);
+ return zend_compile_string(source._val, (char *)name TSRMLS_CC);
}
/**
- * Execute a script
- * @return Value
+ * Constructor
+ * @param name name of the script
+ * @param script actual PHP code
+ * @param size length of the string
*/
-Value Script::execute() const
+Script::Script(const char *name, const char *phpcode, size_t size) : _opcodes(compile(name, phpcode, size))
{
- // if the script could not be compiled, we return null
- if (!_opcodes) return nullptr;
-
- // pointer that is going to hold the return value of the script
- zval *retval_ptr = nullptr;
-
- // the zend engine is probably already busy processing opcodes, so we store
- // the current execute state before we're going to switch the runtime to
- // our own set of opcodes
- ExecuteState oldstate;
-
- // old execute state has been saved (and will automatically be restured when
- // the oldstate is destructed), so we can now safely overwrite all the settings
- EG(return_value_ptr_ptr) = &retval_ptr;
- EG(active_op_array) = _opcodes;
- EG(no_extensions) = 1;
- if (!EG(active_symbol_table)) zend_rebuild_symbol_table(TSRMLS_C);
- CG(interactive) = 0;
-
- // this code was copied from zend_execute_API.c. this is what I think it does:
- // the zend_execute() call could result in all sort of disastrous things, one
- // of them is a full crash of the executing script. if that happens, the zend
- // engine does a long jump right up to some other point in the code. the
- // 'zend_try' and 'zend_catch' macros prevent this: they install a new
- // destination for the long jump, so that we can catch a failure
- zend_try
- {
- // the current exception
- zval* oldException = EG(exception);
-
- // execute the code
- zend_execute(_opcodes TSRMLS_CC);
-
- // was an exception thrown inside the eval()'ed code? In that case we
- // throw a C++ new exception to give the C++ code the chance to catch it
- if (oldException != EG(exception) && EG(exception)) throw OrigException(EG(exception) TSRMLS_CC);
- }
- zend_catch
- {
- // the code could not be executed, and the zend engine is in big
- // trouble now, in the original code the _opcodes are efree'd, but here
- // we can just as well continue with the real bailout (the zend_try/
- // zend_catch pair was maybe not even necessary???)
- zend_bailout();
- }
- zend_end_try();
-
- // we're ready if there is no return value
- if (!retval_ptr) return nullptr;
-
- // copy the pointer into a value object, and return that
- return retval_ptr;
}
/**