summaryrefslogtreecommitdiff
path: root/zend/script.cpp
blob: 9e1d8f642c76eacd747bd35b280b32970600e7d9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/**
 *  Script.cpp
 *
 *  Implementation file for the script class
 *
 *  @author Emiel Bruijntjes <emiel.bruijntjes@copernica.com>
 *  @copyright 2014 Copernica BV
 */

/**
 *  Dependencies
 */
#include "includes.h"

/**
 *  Open PHP namespace
 */
namespace Php {

/**
 *  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
 */
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
    // the zend_eval_stringl() function into this file here. However, the code
    // found there is full of zval manipulation, for which we can use the much
    // simpler Php::Value object
    Php::Value source(phpcode, size);

    // we need the tsrm_ls variable
    // @todo it would be better if this was passed as param to the compile() method
    TSRMLS_FETCH();
    
    // remember the old compiler options, and set new compiler options
    CompilerOptions options(ZEND_COMPILE_DEFAULT_FOR_EVAL TSRMLS_CC);
    
    // compile the string
    return zend_compile_string(source._val, (char *)name TSRMLS_CC);
}

/**
 *  Constructor
 *  @param  name        name of the script
 *  @param  script      actual PHP code
 *  @param  size        length of the string
 */
Script::Script(const char *name, const char *phpcode, size_t size) _NOEXCEPT
{
    // we need the tsrm_ls variable
    TSRMLS_FETCH();

    // construct opcodes
    _opcodes = new Opcodes(compile(name, phpcode, size) TSRMLS_CC);
}

/**
 *  Destructor
 */
Script::~Script()
{
    // remove opcodes
    delete _opcodes;
}

/**
 *  Is the script a valid PHP script without syntax errors?
 *  @return bool
 */
bool Script::valid() const
{
    // check opcodes
    return _opcodes && _opcodes->valid();
}

/**
 *  Execute the script
 *  The return value of the script is returned
 *  @return Value
 */
Value Script::execute() const
{
    // pass on to opcodes
    if (!_opcodes) return nullptr;
    
    // execute opcodes
    return _opcodes->execute();
}

/**
 *  End of namespace
 */
}