mirror of https://github.com/deuill/go-php.git
Merge pull request #23 from deuill/feature/c-preprocessor-cleanup
Clean up C pre-processor mess
This commit is contained in:
commit
daf6987b14
|
@ -64,16 +64,17 @@ void context_exec(engine_context *context, char *filename) {
|
|||
}
|
||||
|
||||
void *context_eval(engine_context *context, char *script) {
|
||||
zval str;
|
||||
VALUE_SET_STRING(&str, script);
|
||||
zval *str = _value_init();
|
||||
_value_set_string(&str, script);
|
||||
|
||||
// Compile script value.
|
||||
uint32_t compiler_options = CG(compiler_options);
|
||||
|
||||
CG(compiler_options) = ZEND_COMPILE_DEFAULT_FOR_EVAL;
|
||||
zend_op_array *op = zend_compile_string(&str, "gophp-engine");
|
||||
zend_op_array *op = zend_compile_string(str, "gophp-engine");
|
||||
CG(compiler_options) = compiler_options;
|
||||
|
||||
zval_dtor(&str);
|
||||
zval_dtor(str);
|
||||
|
||||
// Return error if script failed to compile.
|
||||
if (!op) {
|
||||
|
@ -83,7 +84,7 @@ void *context_eval(engine_context *context, char *script) {
|
|||
|
||||
// Attempt to execute compiled string.
|
||||
zval tmp;
|
||||
CONTEXT_EXECUTE(op, &tmp);
|
||||
_context_eval(op, &tmp);
|
||||
|
||||
// Allocate result value and copy temporary execution result in.
|
||||
zval *result = malloc(sizeof(zval));
|
||||
|
@ -95,7 +96,7 @@ void *context_eval(engine_context *context, char *script) {
|
|||
|
||||
void context_bind(engine_context *context, char *name, void *value) {
|
||||
engine_value *v = (engine_value *) value;
|
||||
CONTEXT_VALUE_BIND(name, v->internal);
|
||||
_context_bind(name, v->internal);
|
||||
}
|
||||
|
||||
void context_destroy(engine_context *context) {
|
||||
|
@ -103,4 +104,6 @@ void context_destroy(engine_context *context) {
|
|||
|
||||
SG(server_context) = NULL;
|
||||
free(context);
|
||||
}
|
||||
}
|
||||
|
||||
#include "_context.c"
|
||||
|
|
|
@ -26,11 +26,7 @@ const char engine_ini_defaults[] = {
|
|||
"max_input_time = -1\n\0"
|
||||
};
|
||||
|
||||
// Unbuffered write to engine context.
|
||||
//
|
||||
// The function definition for this depends on the PHP version used, and is
|
||||
// defined in the "_engine.h" file for the respective PHP version used.
|
||||
static ENGINE_UB_WRITE(str, len) {
|
||||
static int engine_ub_write(const char *str, uint len) {
|
||||
engine_context *context = SG(server_context);
|
||||
|
||||
int written = engineWriteOut(context, (void *) str, len);
|
||||
|
@ -83,7 +79,7 @@ static sapi_module_struct engine_module = {
|
|||
NULL, // Activate
|
||||
NULL, // Deactivate
|
||||
|
||||
engine_ub_write, // Unbuffered Write
|
||||
_engine_ub_write, // Unbuffered Write
|
||||
NULL, // Flush
|
||||
NULL, // Get UID
|
||||
NULL, // Getenv
|
||||
|
@ -139,3 +135,5 @@ void engine_shutdown(php_engine *engine) {
|
|||
free(engine_module.ini_entries);
|
||||
free(engine);
|
||||
}
|
||||
|
||||
#include "_engine.c"
|
||||
|
|
|
@ -191,7 +191,7 @@ func engineSetHeader(ctx *C.struct__engine_context, operation C.uint, buffer uns
|
|||
|
||||
//export engineReceiverNew
|
||||
func engineReceiverNew(rcvr *C.struct__engine_receiver, args unsafe.Pointer) C.int {
|
||||
n := C.GoString(C.receiver_get_name(rcvr))
|
||||
n := C.GoString(C._receiver_get_name(rcvr))
|
||||
if engine == nil || engine.receivers[n] == nil {
|
||||
return 1
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ func engineReceiverNew(rcvr *C.struct__engine_receiver, args unsafe.Pointer) C.i
|
|||
|
||||
//export engineReceiverGet
|
||||
func engineReceiverGet(rcvr *C.struct__engine_receiver, name *C.char) unsafe.Pointer {
|
||||
n := C.GoString(C.receiver_get_name(rcvr))
|
||||
n := C.GoString(C._receiver_get_name(rcvr))
|
||||
if engine == nil || engine.receivers[n].objects[rcvr] == nil {
|
||||
return nil
|
||||
}
|
||||
|
@ -230,7 +230,7 @@ func engineReceiverGet(rcvr *C.struct__engine_receiver, name *C.char) unsafe.Poi
|
|||
|
||||
//export engineReceiverSet
|
||||
func engineReceiverSet(rcvr *C.struct__engine_receiver, name *C.char, val unsafe.Pointer) {
|
||||
n := C.GoString(C.receiver_get_name(rcvr))
|
||||
n := C.GoString(C._receiver_get_name(rcvr))
|
||||
if engine == nil || engine.receivers[n].objects[rcvr] == nil {
|
||||
return
|
||||
}
|
||||
|
@ -245,7 +245,7 @@ func engineReceiverSet(rcvr *C.struct__engine_receiver, name *C.char, val unsafe
|
|||
|
||||
//export engineReceiverExists
|
||||
func engineReceiverExists(rcvr *C.struct__engine_receiver, name *C.char) C.int {
|
||||
n := C.GoString(C.receiver_get_name(rcvr))
|
||||
n := C.GoString(C._receiver_get_name(rcvr))
|
||||
if engine == nil || engine.receivers[n].objects[rcvr] == nil {
|
||||
return 0
|
||||
}
|
||||
|
@ -259,7 +259,7 @@ func engineReceiverExists(rcvr *C.struct__engine_receiver, name *C.char) C.int {
|
|||
|
||||
//export engineReceiverCall
|
||||
func engineReceiverCall(rcvr *C.struct__engine_receiver, name *C.char, args unsafe.Pointer) unsafe.Pointer {
|
||||
n := C.GoString(C.receiver_get_name(rcvr))
|
||||
n := C.GoString(C._receiver_get_name(rcvr))
|
||||
if engine == nil || engine.receivers[n].objects[rcvr] == nil {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -5,43 +5,7 @@
|
|||
#ifndef ___CONTEXT_H___
|
||||
#define ___CONTEXT_H___
|
||||
|
||||
#define CONTEXT_VALUE_BIND(n, v) do { \
|
||||
ZEND_SET_SYMBOL(EG(active_symbol_table), n, v); \
|
||||
} while (0)
|
||||
static void _context_bind(char *name, zval *value);
|
||||
static void _context_eval(zend_op_array *op, zval *ret);
|
||||
|
||||
#define CONTEXT_EXECUTE(o, v) do { \
|
||||
zend_op_array *oparr = EG(active_op_array); \
|
||||
zval *retval=NULL; \
|
||||
zval **retvalptr = EG(return_value_ptr_ptr); \
|
||||
zend_op **opline = EG(opline_ptr); \
|
||||
int interact = CG(interactive); \
|
||||
EG(return_value_ptr_ptr) = &retval; \
|
||||
EG(active_op_array) = o; \
|
||||
EG(no_extensions) = 1; \
|
||||
if (!EG(active_symbol_table)) { \
|
||||
zend_rebuild_symbol_table(); \
|
||||
} \
|
||||
CG(interactive) = 0; \
|
||||
zend_try { \
|
||||
zend_execute(o); \
|
||||
} zend_catch { \
|
||||
destroy_op_array(o); \
|
||||
efree(o); \
|
||||
zend_bailout(); \
|
||||
} zend_end_try(); \
|
||||
destroy_op_array(o); \
|
||||
efree(o); \
|
||||
CG(interactive) = interact; \
|
||||
if (retval) { \
|
||||
ZVAL_COPY_VALUE(v, retval); \
|
||||
zval_copy_ctor(v); \
|
||||
} else { \
|
||||
ZVAL_NULL(v); \
|
||||
} \
|
||||
EG(no_extensions)=0; \
|
||||
EG(opline_ptr) = opline; \
|
||||
EG(active_op_array) = oparr; \
|
||||
EG(return_value_ptr_ptr) = retvalptr; \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
#ifndef ___ENGINE_H___
|
||||
#define ___ENGINE_H___
|
||||
|
||||
#define ENGINE_UB_WRITE(s, l) int engine_ub_write(const char *s, uint l)
|
||||
static int _engine_ub_write(const char *str, uint len);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -5,63 +5,20 @@
|
|||
#ifndef ___RECEIVER_H___
|
||||
#define ___RECEIVER_H___
|
||||
|
||||
#define RECEIVER_GET(o, m) receiver_get(o, m, int t, const zend_literal *k)
|
||||
#define RECEIVER_SET(o, m, v) receiver_set(o, m, v, const zend_literal *k)
|
||||
#define RECEIVER_EXISTS(o, m, c) receiver_exists(o, m, c, const zend_literal *k)
|
||||
#define RECEIVER_METHOD_GET(o, n, l) receiver_method_get(zval **o, char *n, int l, const zend_literal *k)
|
||||
#define RECEIVER_METHOD_CALL(m) receiver_method_call(const char *m, INTERNAL_FUNCTION_PARAMETERS)
|
||||
#define RECEIVER_CONSTRUCTOR_GET(o) receiver_constructor_get(zval *o)
|
||||
#define RECEIVER_FREE(o) receiver_free(void *o)
|
||||
#define RECEIVER_INIT(c) zend_object_value receiver_init(c)
|
||||
static zval *_receiver_get(zval *object, zval *member, int type, const zend_literal *key);
|
||||
static void _receiver_set(zval *object, zval *member, zval *value, const zend_literal *key);
|
||||
static int _receiver_exists(zval *object, zval *member, int check, const zend_literal *key);
|
||||
|
||||
#define RECEIVER_DESTROY(n) do { \
|
||||
zend_class_entry **c; \
|
||||
if (zend_hash_find(CG(class_table), n, strlen(n), (void **) &c) == SUCCESS) { \
|
||||
destroy_zend_class(c); \
|
||||
zend_hash_del_key_or_index(CG(class_table), n, strlen(n), 0, HASH_DEL_KEY); \
|
||||
} \
|
||||
} while (0)
|
||||
static int _receiver_method_call(const char *method, INTERNAL_FUNCTION_PARAMETERS);
|
||||
static zend_function *_receiver_method_get(zval **object, char *name, int len, const zend_literal *key);
|
||||
static zend_function *_receiver_constructor_get(zval *object);
|
||||
|
||||
static inline zval *RECEIVER_RETVAL() {
|
||||
zval *val = NULL;
|
||||
MAKE_STD_ZVAL(val);
|
||||
return val;
|
||||
}
|
||||
static void _receiver_free(void *object);
|
||||
static zend_object_value _receiver_init(zend_class_entry *class_type);
|
||||
static void _receiver_destroy(char *name);
|
||||
|
||||
#define RECEIVER_THIS(o) ((engine_receiver *) zend_object_store_get_object(o))
|
||||
#define RECEIVER_STRING_COPY(n) estrndup(n, len)
|
||||
static engine_receiver *_receiver_this(zval *object);
|
||||
static void _receiver_handlers_set(zend_object_handlers *handlers);
|
||||
char *_receiver_get_name(engine_receiver *rcvr);
|
||||
|
||||
#define RECEIVER_FUNC() (zend_internal_function *) EG(current_execute_data)->function_state.function
|
||||
#define RECEIVER_FUNC_NAME(m) (char *) (m)
|
||||
#define RECEIVER_FUNC_SET_ARGFLAGS(f)
|
||||
|
||||
#define RECEIVER_OBJECT(o) ((zend_object *) (&(RECEIVER_THIS(o)->obj)))
|
||||
#define RECEIVER_OBJECT_CREATE(r, t) do { \
|
||||
r = emalloc(sizeof(engine_receiver)); \
|
||||
memset(r, 0, sizeof(engine_receiver)); \
|
||||
zend_object_std_init(&this->obj, t); \
|
||||
zend_object_value object; \
|
||||
object.handle = zend_objects_store_put(r, \
|
||||
(zend_objects_store_dtor_t) zend_objects_destroy_object, \
|
||||
(zend_objects_free_object_storage_t) receiver_free, NULL); \
|
||||
object.handlers = &receiver_handlers; \
|
||||
return object; \
|
||||
} while (0)
|
||||
|
||||
#define RECEIVER_OBJECT_DESTROY(r) do { \
|
||||
zend_object_std_dtor(&r->obj); \
|
||||
efree(r); \
|
||||
} while (0)
|
||||
|
||||
#define RECEIVER_HANDLERS_SET(h) do { \
|
||||
zend_object_handlers *std = zend_get_std_object_handlers(); \
|
||||
h.get_class_name = std->get_class_name; \
|
||||
h.get_class_entry = std->get_class_entry; \
|
||||
} while (0)
|
||||
|
||||
// Return class name for method receiver.
|
||||
static inline char *receiver_get_name(engine_receiver *rcvr) {
|
||||
return (char *) rcvr->obj.ce->name;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -5,53 +5,17 @@
|
|||
#ifndef ___VALUE_H___
|
||||
#define ___VALUE_H___
|
||||
|
||||
#define CASE_BOOL IS_BOOL
|
||||
#define VALUE_TRUTH(v) (Z_BVAL_P(v))
|
||||
zval *_value_init();
|
||||
void _value_destroy(engine_value *val);
|
||||
|
||||
#define VALUE_SET_STRING(z, s) ZVAL_STRING(z, s, 1);
|
||||
int _value_truth(zval *val);
|
||||
void _value_set_string(zval **val, char *str);
|
||||
|
||||
#define VALUE_INIT(v) do { \
|
||||
MAKE_STD_ZVAL(v); \
|
||||
ZVAL_NULL(v); \
|
||||
} while (0)
|
||||
static int _value_current_key_get(HashTable *ht, char **str_index, ulong *num_index);
|
||||
static void _value_current_key_set(HashTable *ht, engine_value *val);
|
||||
|
||||
#define HASH_GET_CURRENT_KEY(h, k, i) zend_hash_get_current_key(h, k, i, 0)
|
||||
#define HASH_SET_CURRENT_KEY(h, v) do { \
|
||||
zval *t; \
|
||||
MAKE_STD_ZVAL(t); \
|
||||
zend_hash_get_current_key_zval(h, t); \
|
||||
add_next_index_zval(v, t); \
|
||||
} while (0)
|
||||
static void _value_array_next_get(HashTable *ht, engine_value *val);
|
||||
static void _value_array_index_get(HashTable *ht, unsigned long index, engine_value *val);
|
||||
static void _value_array_key_get(HashTable *ht, char *key, engine_value *val);
|
||||
|
||||
#define VALUE_ARRAY_NEXT_GET(h, v) do { \
|
||||
zval **t = NULL; \
|
||||
if (zend_hash_get_current_data(h, (void **) &t) == SUCCESS) { \
|
||||
value_set_zval(v, *t); \
|
||||
zend_hash_move_forward(h); \
|
||||
} \
|
||||
return v; \
|
||||
} while (0)
|
||||
|
||||
#define VALUE_ARRAY_INDEX_GET(h, i, v) do { \
|
||||
zval **t = NULL; \
|
||||
if (zend_hash_index_find(h, i, (void **) &t) == SUCCESS) { \
|
||||
value_set_zval(v, *t); \
|
||||
} \
|
||||
return v; \
|
||||
} while (0)
|
||||
|
||||
#define VALUE_ARRAY_KEY_GET(h, k, v) do { \
|
||||
zval **t = NULL; \
|
||||
if (zend_hash_find(h, k, strlen(k) + 1, (void **) &t) == SUCCESS) { \
|
||||
value_set_zval(v, *t); \
|
||||
} \
|
||||
return v; \
|
||||
} while (0)
|
||||
|
||||
// Destroy and free engine value.
|
||||
static inline void value_destroy(engine_value *val) {
|
||||
zval_dtor(val->internal);
|
||||
free(val);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -5,23 +5,7 @@
|
|||
#ifndef ___CONTEXT_H___
|
||||
#define ___CONTEXT_H___
|
||||
|
||||
#define CONTEXT_VALUE_BIND(n, v) do { \
|
||||
zend_hash_str_update(&EG(symbol_table), n, strlen(n), v); \
|
||||
} while (0)
|
||||
static void _context_bind(char *name, zval *value);
|
||||
static void _context_eval(zend_op_array *op, zval *ret);
|
||||
|
||||
#define CONTEXT_EXECUTE(o, v) do { \
|
||||
EG(no_extensions) = 1; \
|
||||
zend_try { \
|
||||
ZVAL_NULL(v); \
|
||||
zend_execute(o, v); \
|
||||
} zend_catch { \
|
||||
destroy_op_array(o); \
|
||||
efree_size(o, sizeof(zend_op_array)); \
|
||||
zend_bailout(); \
|
||||
} zend_end_try(); \
|
||||
destroy_op_array(o); \
|
||||
efree_size(o, sizeof(zend_op_array)); \
|
||||
EG(no_extensions) = 0; \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -5,6 +5,6 @@
|
|||
#ifndef ___ENGINE_H___
|
||||
#define ___ENGINE_H___
|
||||
|
||||
#define ENGINE_UB_WRITE(s, l) size_t engine_ub_write(const char *s, size_t l)
|
||||
static size_t _engine_ub_write(const char *str, size_t len);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -5,54 +5,20 @@
|
|||
#ifndef ___RECEIVER_H___
|
||||
#define ___RECEIVER_H___
|
||||
|
||||
#define RECEIVER_GET(o, m) receiver_get(o, m, int t, void **c, zval *r)
|
||||
#define RECEIVER_SET(o, m, v) receiver_set(o, m, v, void **c)
|
||||
#define RECEIVER_EXISTS(o, m, h) receiver_exists(o, m, h, void **c)
|
||||
#define RECEIVER_METHOD_GET(o, n, l) receiver_method_get(zend_object **o, zend_string *n, const zval *k)
|
||||
#define RECEIVER_METHOD_CALL(m) receiver_method_call(zend_string *m, zend_object *o, INTERNAL_FUNCTION_PARAMETERS)
|
||||
#define RECEIVER_CONSTRUCTOR_GET(o) receiver_constructor_get(zend_object *o)
|
||||
#define RECEIVER_FREE(o) receiver_free(zend_object *o)
|
||||
#define RECEIVER_INIT(c) zend_object *receiver_init(c)
|
||||
static zval *_receiver_get(zval *object, zval *member, int type, void **cache_slot, zval *retval);
|
||||
static void _receiver_set(zval *object, zval *member, zval *value, void **cache_slot);
|
||||
static int _receiver_exists(zval *object, zval *member, int check, void **cache_slot);
|
||||
|
||||
#define RECEIVER_DESTROY(n) do { \
|
||||
zval *c = zend_hash_str_find(CG(class_table), n, strlen(n)); \
|
||||
if (c != NULL) { \
|
||||
destroy_zend_class(c); \
|
||||
zend_hash_str_del(CG(class_table), n, strlen(n)); \
|
||||
} \
|
||||
} while (0)
|
||||
static int _receiver_method_call(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS);
|
||||
static zend_function *_receiver_method_get(zend_object **object, zend_string *name, const zval *key);
|
||||
static zend_function *_receiver_constructor_get(zend_object *object);
|
||||
|
||||
#define RECEIVER_RETVAL() (r)
|
||||
#define RECEIVER_THIS(o) ((engine_receiver *) Z_OBJ_P(o))
|
||||
#define RECEIVER_STRING_COPY(n) zend_string_copy(name)
|
||||
static void _receiver_free(zend_object *object);
|
||||
static zend_object *_receiver_init(zend_class_entry *class_type);
|
||||
static void _receiver_destroy(char *name);
|
||||
|
||||
#define RECEIVER_FUNC() (zend_internal_function *) EX(func)
|
||||
#define RECEIVER_FUNC_NAME(m) (m)->val
|
||||
#define RECEIVER_FUNC_SET_ARGFLAGS(f) zend_set_function_arg_flags((zend_function *) f);
|
||||
static engine_receiver *_receiver_this(zval *object);
|
||||
static void _receiver_handlers_set(zend_object_handlers *handlers);
|
||||
char *_receiver_get_name(engine_receiver *rcvr);
|
||||
|
||||
#define RECEIVER_OBJECT(o) (o)
|
||||
#define RECEIVER_OBJECT_CREATE(r, t) do { \
|
||||
r = emalloc(sizeof(engine_receiver)); \
|
||||
memset(r, 0, sizeof(engine_receiver)); \
|
||||
zend_object_std_init(&r->obj, t); \
|
||||
object_properties_init(&r->obj, t); \
|
||||
r->obj.handlers = &receiver_handlers; \
|
||||
return &r->obj; \
|
||||
} while (0)
|
||||
|
||||
#define RECEIVER_OBJECT_DESTROY(r) do { \
|
||||
zend_object_std_dtor(&r->obj); \
|
||||
} while (0)
|
||||
|
||||
#define RECEIVER_HANDLERS_SET(h) do { \
|
||||
zend_object_handlers *std = zend_get_std_object_handlers(); \
|
||||
h.get_class_name = std->get_class_name; \
|
||||
h.free_obj = receiver_free; \
|
||||
} while (0)
|
||||
|
||||
// Return class name for method receiver.
|
||||
static inline char *receiver_get_name(engine_receiver *rcvr) {
|
||||
return rcvr->obj.ce->name->val;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -5,55 +5,17 @@
|
|||
#ifndef ___VALUE_H___
|
||||
#define ___VALUE_H___
|
||||
|
||||
#define CASE_BOOL IS_TRUE: case IS_FALSE
|
||||
#define VALUE_TRUTH(v) (Z_TYPE_P(v) == IS_TRUE)
|
||||
zval *_value_init();
|
||||
void _value_destroy(engine_value *val);
|
||||
|
||||
#define VALUE_SET_STRING(z, s) ZVAL_STRING(z, s);
|
||||
int _value_truth(zval *val);
|
||||
void _value_set_string(zval **val, char *str);
|
||||
|
||||
#define VALUE_INIT(v) do { \
|
||||
(v) = malloc(sizeof(zval)); \
|
||||
ZVAL_NULL(v); \
|
||||
} while (0)
|
||||
static int _value_current_key_get(HashTable *ht, zend_string **str_index, zend_ulong *num_index);
|
||||
static void _value_current_key_set(HashTable *ht, engine_value *val);
|
||||
|
||||
#define HASH_GET_CURRENT_KEY(h, k, i) zend_hash_get_current_key(h, k, i)
|
||||
#define HASH_SET_CURRENT_KEY(h, v) do { \
|
||||
zval t; \
|
||||
zend_hash_get_current_key_zval(h, &t); \
|
||||
add_next_index_zval(v, &t); \
|
||||
} while (0)
|
||||
static void _value_array_next_get(HashTable *ht, engine_value *val);
|
||||
static void _value_array_index_get(HashTable *ht, unsigned long index, engine_value *val);
|
||||
static void _value_array_key_get(HashTable *ht, char *key, engine_value *val);
|
||||
|
||||
#define VALUE_ARRAY_NEXT_GET(h, v) do { \
|
||||
zval *t = NULL; \
|
||||
if ((t = zend_hash_get_current_data(h)) != NULL) { \
|
||||
value_set_zval(v, t); \
|
||||
zend_hash_move_forward(h); \
|
||||
} \
|
||||
return v; \
|
||||
} while (0)
|
||||
|
||||
#define VALUE_ARRAY_INDEX_GET(h, i, v) do { \
|
||||
zval *t = NULL; \
|
||||
if ((t = zend_hash_index_find(h, i)) != NULL) { \
|
||||
value_set_zval(v, t); \
|
||||
} \
|
||||
return v; \
|
||||
} while (0)
|
||||
|
||||
#define VALUE_ARRAY_KEY_GET(h, k, v) do { \
|
||||
zval *t = NULL; \
|
||||
zend_string *s = zend_string_init(k, strlen(k), 0); \
|
||||
if ((t = zend_hash_find(h, s)) != NULL) { \
|
||||
value_set_zval(v, t); \
|
||||
} \
|
||||
zend_string_release(s); \
|
||||
return v; \
|
||||
} while (0)
|
||||
|
||||
// Destroy and free engine value.
|
||||
static inline void value_destroy(engine_value *val) {
|
||||
zval_dtor(val->internal);
|
||||
free(val->internal);
|
||||
free(val);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -21,12 +21,8 @@ enum {
|
|||
KIND_OBJECT
|
||||
};
|
||||
|
||||
static inline void value_copy(zval *dst, zval *src) {
|
||||
ZVAL_COPY_VALUE(dst, src);
|
||||
zval_copy_ctor(dst);
|
||||
}
|
||||
|
||||
engine_value *value_new();
|
||||
void value_copy(zval *dst, zval *src);
|
||||
int value_kind(engine_value *val);
|
||||
|
||||
void value_set_null(engine_value *val);
|
||||
|
@ -57,4 +53,4 @@ engine_value *value_array_key_get(engine_value *arr, char *key);
|
|||
|
||||
#include "_value.h"
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
package engine
|
||||
|
||||
// #cgo CFLAGS: -I/usr/include/php5 -I/usr/include/php5/main -I/usr/include/php5/TSRM
|
||||
// #cgo CFLAGS: -I/usr/include/php5/Zend -Iinclude/php5
|
||||
// #cgo CFLAGS: -I/usr/include/php5/Zend -Iinclude/php5 -Isrc/php5
|
||||
// #cgo LDFLAGS: -lphp5
|
||||
import "C"
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
package engine
|
||||
|
||||
// #cgo CFLAGS: -Iinclude/php7
|
||||
// #cgo CFLAGS: -Iinclude/php7 -Isrc/php7
|
||||
// #cgo LDFLAGS: -lphp7
|
||||
import "C"
|
||||
|
|
|
@ -14,31 +14,20 @@
|
|||
#include "_cgo_export.h"
|
||||
|
||||
// Fetch and return field for method receiver.
|
||||
static zval *RECEIVER_GET(zval *object, zval *member) {
|
||||
engine_receiver *this = RECEIVER_THIS(object);
|
||||
zval *val = RECEIVER_RETVAL();
|
||||
|
||||
engine_value *result = engineReceiverGet(this, Z_STRVAL_P(member));
|
||||
if (result == NULL) {
|
||||
ZVAL_NULL(val);
|
||||
return val;
|
||||
}
|
||||
|
||||
value_copy(val, result->internal);
|
||||
value_destroy(result);
|
||||
|
||||
return val;
|
||||
static engine_value *receiver_get(zval *object, zval *member) {
|
||||
engine_receiver *this = _receiver_this(object);
|
||||
return engineReceiverGet(this, Z_STRVAL_P(member));
|
||||
}
|
||||
|
||||
// Set field for method receiver.
|
||||
static void RECEIVER_SET(zval *object, zval *member, zval *value) {
|
||||
engine_receiver *this = RECEIVER_THIS(object);
|
||||
static void receiver_set(zval *object, zval *member, zval *value) {
|
||||
engine_receiver *this = _receiver_this(object);
|
||||
engineReceiverSet(this, Z_STRVAL_P(member), (void *) value);
|
||||
}
|
||||
|
||||
// Check if field exists for method receiver.
|
||||
static int RECEIVER_EXISTS(zval *object, zval *member, int check) {
|
||||
engine_receiver *this = RECEIVER_THIS(object);
|
||||
static int receiver_exists(zval *object, zval *member, int check) {
|
||||
engine_receiver *this = _receiver_this(object);
|
||||
|
||||
if (!engineReceiverExists(this, Z_STRVAL_P(member))) {
|
||||
// Value does not exist.
|
||||
|
@ -54,7 +43,7 @@ static int RECEIVER_EXISTS(zval *object, zval *member, int check) {
|
|||
if (check == 1) {
|
||||
// Value exists and is "truthy".
|
||||
convert_to_boolean(val->internal);
|
||||
result = VALUE_TRUTH(val->internal) ? 1 : 0;
|
||||
result = _value_truth(val->internal);
|
||||
} else if (check == 0) {
|
||||
// Value exists and is not null.
|
||||
result = (val->kind != KIND_NULL) ? 1 : 0;
|
||||
|
@ -63,15 +52,14 @@ static int RECEIVER_EXISTS(zval *object, zval *member, int check) {
|
|||
result = 0;
|
||||
}
|
||||
|
||||
value_destroy(val);
|
||||
_value_destroy(val);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Call function with arguments passed and return value (if any).
|
||||
static int RECEIVER_METHOD_CALL(method) {
|
||||
engine_receiver *this = RECEIVER_THIS(getThis());
|
||||
char *name = RECEIVER_FUNC_NAME(method);
|
||||
static int receiver_method_call(char *name, INTERNAL_FUNCTION_PARAMETERS) {
|
||||
zval args;
|
||||
engine_receiver *this = _receiver_this(getThis());
|
||||
|
||||
array_init_size(&args, ZEND_NUM_ARGS());
|
||||
|
||||
|
@ -83,7 +71,7 @@ static int RECEIVER_METHOD_CALL(method) {
|
|||
RETVAL_NULL();
|
||||
} else {
|
||||
value_copy(return_value, result->internal);
|
||||
value_destroy(result);
|
||||
_value_destroy(result);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,8 +81,8 @@ static int RECEIVER_METHOD_CALL(method) {
|
|||
// Create new method receiver instance and attach to instantiated PHP object.
|
||||
// Returns an exception if method receiver failed to initialize for any reason.
|
||||
static void receiver_new(INTERNAL_FUNCTION_PARAMETERS) {
|
||||
engine_receiver *this = RECEIVER_THIS(getThis());
|
||||
zval args;
|
||||
engine_receiver *this = _receiver_this(getThis());
|
||||
|
||||
array_init_size(&args, ZEND_NUM_ARGS());
|
||||
|
||||
|
@ -113,49 +101,42 @@ static void receiver_new(INTERNAL_FUNCTION_PARAMETERS) {
|
|||
|
||||
// Fetch and return function definition for method receiver. The method call
|
||||
// happens in the method handler, as returned by this function.
|
||||
static zend_function *RECEIVER_METHOD_GET(object_ptr, name, len) {
|
||||
zend_object *obj = RECEIVER_OBJECT(*object_ptr);
|
||||
static zend_internal_function *receiver_method_get(zend_object *object) {
|
||||
zend_internal_function *func = emalloc(sizeof(zend_internal_function));
|
||||
|
||||
func->type = ZEND_OVERLOADED_FUNCTION;
|
||||
func->handler = NULL;
|
||||
func->arg_info = NULL;
|
||||
func->num_args = 0;
|
||||
func->scope = obj->ce;
|
||||
func->scope = object->ce;
|
||||
func->fn_flags = ZEND_ACC_CALL_VIA_HANDLER;
|
||||
func->function_name = RECEIVER_STRING_COPY(name);
|
||||
|
||||
RECEIVER_FUNC_SET_ARGFLAGS(func);
|
||||
|
||||
return (zend_function *) func;
|
||||
return func;
|
||||
}
|
||||
|
||||
// Fetch and return constructor function definition for method receiver. The
|
||||
// construct call happens in the constructor handler, as returned by this
|
||||
// function.
|
||||
static zend_function *RECEIVER_CONSTRUCTOR_GET(object) {
|
||||
zend_object *obj = RECEIVER_OBJECT(object);
|
||||
static zend_internal_function *receiver_constructor_get(zend_object *object) {
|
||||
static zend_internal_function func;
|
||||
|
||||
func.type = ZEND_INTERNAL_FUNCTION;
|
||||
func.handler = receiver_new;
|
||||
func.arg_info = NULL;
|
||||
func.num_args = 0;
|
||||
func.scope = obj->ce;
|
||||
func.scope = object->ce;
|
||||
func.fn_flags = 0;
|
||||
func.function_name = obj->ce->name;
|
||||
func.function_name = object->ce->name;
|
||||
|
||||
RECEIVER_FUNC_SET_ARGFLAGS(&func);
|
||||
|
||||
return (zend_function *) &func;
|
||||
return &func;
|
||||
}
|
||||
|
||||
// Table of handler functions for method receivers.
|
||||
static zend_object_handlers receiver_handlers = {
|
||||
ZEND_OBJECTS_STORE_HANDLERS,
|
||||
|
||||
receiver_get, // read_property
|
||||
receiver_set, // write_property
|
||||
_receiver_get, // read_property
|
||||
_receiver_set, // write_property
|
||||
NULL, // read_dimension
|
||||
NULL, // write_dimension
|
||||
|
||||
|
@ -163,32 +144,19 @@ static zend_object_handlers receiver_handlers = {
|
|||
NULL, // get
|
||||
NULL, // set
|
||||
|
||||
receiver_exists, // has_property
|
||||
_receiver_exists, // has_property
|
||||
NULL, // unset_property
|
||||
NULL, // has_dimension
|
||||
NULL, // unset_dimension
|
||||
|
||||
NULL, // get_properties
|
||||
|
||||
receiver_method_get, // get_method
|
||||
receiver_method_call, // call_method
|
||||
_receiver_method_get, // get_method
|
||||
_receiver_method_call, // call_method
|
||||
|
||||
receiver_constructor_get // get_constructor
|
||||
_receiver_constructor_get // get_constructor
|
||||
};
|
||||
|
||||
// Free storage for allocated method receiver instance.
|
||||
static void RECEIVER_FREE(object) {
|
||||
engine_receiver *this = (engine_receiver *) object;
|
||||
RECEIVER_OBJECT_DESTROY(this);
|
||||
}
|
||||
|
||||
// Initialize instance of method receiver object. The method receiver itself is
|
||||
// attached in the constructor function call.
|
||||
static RECEIVER_INIT(zend_class_entry *class_type) {
|
||||
engine_receiver *this;
|
||||
RECEIVER_OBJECT_CREATE(this, class_type);
|
||||
}
|
||||
|
||||
// Define class with unique name.
|
||||
void receiver_define(char *name) {
|
||||
zend_class_entry tmp;
|
||||
|
@ -196,14 +164,16 @@ void receiver_define(char *name) {
|
|||
|
||||
zend_class_entry *this = zend_register_internal_class(&tmp);
|
||||
|
||||
this->create_object = receiver_init;
|
||||
this->create_object = _receiver_init;
|
||||
this->ce_flags |= ZEND_ACC_FINAL;
|
||||
|
||||
// Set standard handlers for receiver.
|
||||
RECEIVER_HANDLERS_SET(receiver_handlers);
|
||||
_receiver_handlers_set(&receiver_handlers);
|
||||
}
|
||||
|
||||
void receiver_destroy(char *name) {
|
||||
name = php_strtolower(name, strlen(name));
|
||||
RECEIVER_DESTROY(name);
|
||||
_receiver_destroy(name);
|
||||
}
|
||||
|
||||
#include "_receiver.c"
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2016 Alexander Palaistras. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
static void _context_bind(char *name, zval *value) {
|
||||
ZEND_SET_SYMBOL(EG(active_symbol_table), name, value);
|
||||
}
|
||||
|
||||
static void _context_eval(zend_op_array *op, zval *ret) {
|
||||
zend_op_array *oparr = EG(active_op_array);
|
||||
zval *retval = NULL;
|
||||
zval **retvalptr = EG(return_value_ptr_ptr);
|
||||
zend_op **opline = EG(opline_ptr);
|
||||
int interact = CG(interactive);
|
||||
|
||||
EG(return_value_ptr_ptr) = &retval;
|
||||
EG(active_op_array) = op;
|
||||
EG(no_extensions) = 1;
|
||||
|
||||
if (!EG(active_symbol_table)) {
|
||||
zend_rebuild_symbol_table();
|
||||
}
|
||||
|
||||
CG(interactive) = 0;
|
||||
|
||||
zend_try {
|
||||
zend_execute(op);
|
||||
} zend_catch {
|
||||
destroy_op_array(op);
|
||||
efree(op);
|
||||
zend_bailout();
|
||||
} zend_end_try();
|
||||
|
||||
destroy_op_array(op);
|
||||
efree(op);
|
||||
|
||||
CG(interactive) = interact;
|
||||
|
||||
if (retval) {
|
||||
ZVAL_COPY_VALUE(ret, retval);
|
||||
zval_copy_ctor(ret);
|
||||
} else {
|
||||
ZVAL_NULL(ret);
|
||||
}
|
||||
|
||||
EG(no_extensions) = 0;
|
||||
EG(opline_ptr) = opline;
|
||||
EG(active_op_array) = oparr;
|
||||
EG(return_value_ptr_ptr) = retvalptr;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// Copyright 2016 Alexander Palaistras. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
static int _engine_ub_write(const char *str, uint len) {
|
||||
return engine_ub_write(str, len);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright 2016 Alexander Palaistras. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
static zval *_receiver_get(zval *object, zval *member, int type, const zend_literal *key) {
|
||||
zval *retval = NULL;
|
||||
MAKE_STD_ZVAL(retval);
|
||||
|
||||
engine_value *result = receiver_get(object, member);
|
||||
if (result == NULL) {
|
||||
ZVAL_NULL(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
value_copy(retval, result->internal);
|
||||
_value_destroy(result);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void _receiver_set(zval *object, zval *member, zval *value, const zend_literal *key) {
|
||||
receiver_set(object, member, value);
|
||||
}
|
||||
|
||||
static int _receiver_exists(zval *object, zval *member, int check, const zend_literal *key) {
|
||||
return receiver_exists(object, member, check);
|
||||
}
|
||||
|
||||
static int _receiver_method_call(const char *method, INTERNAL_FUNCTION_PARAMETERS) {
|
||||
return receiver_method_call((char *) method, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
||||
}
|
||||
|
||||
static zend_function *_receiver_method_get(zval **object, char *name, int len, const zend_literal *key) {
|
||||
zend_object *obj = &(_receiver_this(*object)->obj);
|
||||
zend_internal_function *func = receiver_method_get(obj);
|
||||
|
||||
func->function_name = estrndup(name, len);
|
||||
|
||||
return (zend_function *) func;
|
||||
}
|
||||
|
||||
static zend_function *_receiver_constructor_get(zval *object) {
|
||||
zend_object *obj = &(_receiver_this(object)->obj);
|
||||
zend_internal_function *func = receiver_constructor_get(obj);
|
||||
|
||||
return (zend_function *) func;
|
||||
}
|
||||
|
||||
// Free storage for allocated method receiver instance.
|
||||
static void _receiver_free(void *object) {
|
||||
engine_receiver *this = (engine_receiver *) object;
|
||||
zend_object_std_dtor(&(this->obj));
|
||||
}
|
||||
|
||||
// Initialize instance of method receiver object. The method receiver itself is
|
||||
// attached in the constructor function call.
|
||||
static zend_object_value _receiver_init(zend_class_entry *class_type) {
|
||||
engine_receiver *this = emalloc(sizeof(engine_receiver));
|
||||
memset(this, 0, sizeof(engine_receiver));
|
||||
|
||||
zend_object_std_init(&this->obj, class_type);
|
||||
|
||||
zend_object_value object;
|
||||
object.handle = zend_objects_store_put(this, (zend_objects_store_dtor_t) zend_objects_destroy_object, (zend_objects_free_object_storage_t) _receiver_free, NULL);
|
||||
object.handlers = &receiver_handlers;
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static void _receiver_destroy(char *name) {
|
||||
zend_class_entry **class;
|
||||
|
||||
if (zend_hash_find(CG(class_table), name, strlen(name), (void **) &class) == SUCCESS) {
|
||||
destroy_zend_class(class);
|
||||
zend_hash_del_key_or_index(CG(class_table), name, strlen(name), 0, HASH_DEL_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
static engine_receiver *_receiver_this(zval *object) {
|
||||
return (engine_receiver *) zend_object_store_get_object(object);
|
||||
}
|
||||
|
||||
static void _receiver_handlers_set(zend_object_handlers *handlers) {
|
||||
zend_object_handlers *std = zend_get_std_object_handlers();
|
||||
|
||||
handlers->get_class_name = std->get_class_name;
|
||||
handlers->get_class_entry = std->get_class_entry;
|
||||
}
|
||||
|
||||
// Return class name for method receiver.
|
||||
char *_receiver_get_name(engine_receiver *rcvr) {
|
||||
return (char *) rcvr->obj.ce->name;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright 2016 Alexander Palaistras. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
zval *_value_init() {
|
||||
zval *tmp = NULL;
|
||||
|
||||
MAKE_STD_ZVAL(tmp);
|
||||
ZVAL_NULL(tmp);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Destroy and free engine value.
|
||||
void _value_destroy(engine_value *val) {
|
||||
zval_dtor(val->internal);
|
||||
free(val);
|
||||
}
|
||||
|
||||
int _value_truth(zval *val) {
|
||||
return (Z_TYPE_P(val) != IS_BOOL) ? -1 : ((Z_BVAL_P(val)) ? 1 : 0);
|
||||
}
|
||||
|
||||
void _value_set_string(zval **val, char *str) {
|
||||
ZVAL_STRING(*val, str, 1);
|
||||
}
|
||||
|
||||
static int _value_current_key_get(HashTable *ht, char **str_index, ulong *num_index) {
|
||||
return zend_hash_get_current_key(ht, str_index, num_index, 0);
|
||||
}
|
||||
|
||||
static void _value_current_key_set(HashTable *ht, engine_value *val) {
|
||||
zval *tmp;
|
||||
|
||||
MAKE_STD_ZVAL(tmp);
|
||||
zend_hash_get_current_key_zval(ht, tmp);
|
||||
add_next_index_zval(val->internal, tmp);
|
||||
}
|
||||
|
||||
static void _value_array_next_get(HashTable *ht, engine_value *val) {
|
||||
zval **tmp = NULL;
|
||||
|
||||
if (zend_hash_get_current_data(ht, (void **) &tmp) == SUCCESS) {
|
||||
value_set_zval(val, *tmp);
|
||||
zend_hash_move_forward(ht);
|
||||
}
|
||||
}
|
||||
|
||||
static void _value_array_index_get(HashTable *ht, unsigned long index, engine_value *val) {
|
||||
zval **tmp = NULL;
|
||||
|
||||
if (zend_hash_index_find(ht, index, (void **) &tmp) == SUCCESS) {
|
||||
value_set_zval(val, *tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static void _value_array_key_get(HashTable *ht, char *key, engine_value *val) {
|
||||
zval **tmp = NULL;
|
||||
|
||||
if (zend_hash_find(ht, key, strlen(key) + 1, (void **) &tmp) == SUCCESS) {
|
||||
value_set_zval(val, *tmp);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
// Copyright 2016 Alexander Palaistras. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
static void _context_bind(char *name, zval *value) {
|
||||
zend_hash_str_update(&EG(symbol_table), name, strlen(name), value);
|
||||
}
|
||||
|
||||
static void _context_eval(zend_op_array *op, zval *ret) {
|
||||
EG(no_extensions) = 1;
|
||||
|
||||
zend_try {
|
||||
ZVAL_NULL(ret);
|
||||
zend_execute(op, ret);
|
||||
} zend_catch {
|
||||
destroy_op_array(op);
|
||||
efree_size(op, sizeof(zend_op_array));
|
||||
zend_bailout();
|
||||
} zend_end_try();
|
||||
|
||||
destroy_op_array(op);
|
||||
efree_size(op, sizeof(zend_op_array));
|
||||
|
||||
EG(no_extensions) = 0;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// Copyright 2016 Alexander Palaistras. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
static size_t _engine_ub_write(const char *str, size_t len) {
|
||||
return engine_ub_write(str, len);
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
// Copyright 2016 Alexander Palaistras. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
static zval *_receiver_get(zval *object, zval *member, int type, void **cache_slot, zval *retval) {
|
||||
engine_value *result = receiver_get(object, member);
|
||||
if (result == NULL) {
|
||||
ZVAL_NULL(retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
value_copy(retval, result->internal);
|
||||
_value_destroy(result);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void _receiver_set(zval *object, zval *member, zval *value, void **cache_slot) {
|
||||
receiver_set(object, member, value);
|
||||
}
|
||||
|
||||
static int _receiver_exists(zval *object, zval *member, int check, void **cache_slot) {
|
||||
return receiver_exists(object, member, check);
|
||||
}
|
||||
|
||||
static int _receiver_method_call(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS) {
|
||||
return receiver_method_call(method->val, INTERNAL_FUNCTION_PARAM_PASSTHRU);
|
||||
}
|
||||
|
||||
static zend_function *_receiver_method_get(zend_object **object, zend_string *name, const zval *key) {
|
||||
zend_internal_function *func = receiver_method_get(*object);
|
||||
|
||||
func->function_name = zend_string_copy(name);
|
||||
zend_set_function_arg_flags((zend_function *) func);
|
||||
|
||||
return (zend_function *) func;
|
||||
}
|
||||
|
||||
static zend_function *_receiver_constructor_get(zend_object *object) {
|
||||
zend_internal_function *func = receiver_constructor_get(object);
|
||||
zend_set_function_arg_flags((zend_function *) func);
|
||||
|
||||
return (zend_function *) func;
|
||||
}
|
||||
|
||||
// Free storage for allocated method receiver instance.
|
||||
static void _receiver_free(zend_object *object) {
|
||||
engine_receiver *this = (engine_receiver *) object;
|
||||
zend_object_std_dtor(&(this->obj));
|
||||
}
|
||||
|
||||
// Initialize instance of method receiver object. The method receiver itself is
|
||||
// attached in the constructor function call.
|
||||
static zend_object *_receiver_init(zend_class_entry *class_type) {
|
||||
engine_receiver *this = emalloc(sizeof(engine_receiver));
|
||||
memset(this, 0, sizeof(engine_receiver));
|
||||
|
||||
zend_object_std_init(&(this->obj), class_type);
|
||||
object_properties_init(&(this->obj), class_type);
|
||||
this->obj.handlers = &receiver_handlers;
|
||||
|
||||
return &(this->obj);
|
||||
}
|
||||
|
||||
static void _receiver_destroy(char *name) {
|
||||
zval *class = zend_hash_str_find(CG(class_table), name, strlen(name));
|
||||
|
||||
if (class != NULL) {
|
||||
destroy_zend_class(class);
|
||||
zend_hash_str_del(CG(class_table), name, strlen(name));
|
||||
}
|
||||
}
|
||||
|
||||
static engine_receiver *_receiver_this(zval *object) {
|
||||
return (engine_receiver *) Z_OBJ_P(object);
|
||||
}
|
||||
|
||||
static void _receiver_handlers_set(zend_object_handlers *handlers) {
|
||||
zend_object_handlers *std = zend_get_std_object_handlers();
|
||||
|
||||
handlers->get_class_name = std->get_class_name;
|
||||
handlers->free_obj = _receiver_free;
|
||||
}
|
||||
|
||||
// Return class name for method receiver.
|
||||
char *_receiver_get_name(engine_receiver *rcvr) {
|
||||
return rcvr->obj.ce->name->val;
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
// Copyright 2016 Alexander Palaistras. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
||||
|
||||
zval *_value_init() {
|
||||
zval *tmp = malloc(sizeof(zval));
|
||||
ZVAL_NULL(tmp);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Destroy and free engine value.
|
||||
void _value_destroy(engine_value *val) {
|
||||
zval_dtor(val->internal);
|
||||
free(val->internal);
|
||||
free(val);
|
||||
}
|
||||
|
||||
int _value_truth(zval *val) {
|
||||
return (Z_TYPE_P(val) == IS_TRUE) ? 1 : ((Z_TYPE_P(val) == IS_FALSE) ? 0 : -1);
|
||||
}
|
||||
|
||||
void _value_set_string(zval **val, char *str) {
|
||||
ZVAL_STRING(*val, str);
|
||||
}
|
||||
|
||||
static int _value_current_key_get(HashTable *ht, zend_string **str_index, zend_ulong *num_index) {
|
||||
return zend_hash_get_current_key(ht, str_index, num_index);
|
||||
}
|
||||
|
||||
static void _value_current_key_set(HashTable *ht, engine_value *val) {
|
||||
zval tmp;
|
||||
|
||||
zend_hash_get_current_key_zval(ht, &tmp);
|
||||
add_next_index_zval(val->internal, &tmp);
|
||||
}
|
||||
|
||||
static void _value_array_next_get(HashTable *ht, engine_value *val) {
|
||||
zval *tmp = NULL;
|
||||
|
||||
if ((tmp = zend_hash_get_current_data(ht)) != NULL) {
|
||||
value_set_zval(val, tmp);
|
||||
zend_hash_move_forward(ht);
|
||||
}
|
||||
}
|
||||
|
||||
static void _value_array_index_get(HashTable *ht, unsigned long index, engine_value *val) {
|
||||
zval *tmp = NULL;
|
||||
|
||||
if ((tmp = zend_hash_index_find(ht, index)) != NULL) {
|
||||
value_set_zval(val, tmp);
|
||||
}
|
||||
}
|
||||
|
||||
static void _value_array_key_get(HashTable *ht, char *key, engine_value *val) {
|
||||
zval *tmp = NULL;
|
||||
zend_string *str = zend_string_init(key, strlen(key), 0);
|
||||
|
||||
if ((tmp = zend_hash_find(ht, str)) != NULL) {
|
||||
value_set_zval(val, tmp);
|
||||
}
|
||||
|
||||
zend_string_release(str);
|
||||
}
|
|
@ -16,13 +16,20 @@ engine_value *value_new() {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
VALUE_INIT(val->internal);
|
||||
val->internal = _value_init();
|
||||
val->kind = KIND_NULL;
|
||||
|
||||
errno = 0;
|
||||
return val;
|
||||
}
|
||||
|
||||
// Creates a complete copy of a zval.
|
||||
// The destination zval needs to be correctly initialized before use.
|
||||
void value_copy(zval *dst, zval *src) {
|
||||
ZVAL_COPY_VALUE(dst, src);
|
||||
zval_copy_ctor(dst);
|
||||
}
|
||||
|
||||
// Returns engine value type. Usually compared against KIND_* constants, defined
|
||||
// in the `value.h` header file.
|
||||
int value_kind(engine_value *val) {
|
||||
|
@ -55,7 +62,7 @@ void value_set_bool(engine_value *val, bool status) {
|
|||
|
||||
// Set type and value to string.
|
||||
void value_set_string(engine_value *val, char *str) {
|
||||
VALUE_SET_STRING(val->internal, str);
|
||||
_value_set_string(&val->internal, str);
|
||||
val->kind = KIND_STRING;
|
||||
}
|
||||
|
||||
|
@ -78,12 +85,21 @@ void value_set_zval(engine_value *val, zval *src) {
|
|||
|
||||
// Determine concrete type from source zval.
|
||||
switch (Z_TYPE_P(src)) {
|
||||
case IS_NULL: kind = KIND_NULL; break;
|
||||
case IS_LONG: kind = KIND_LONG; break;
|
||||
case IS_DOUBLE: kind = KIND_DOUBLE; break;
|
||||
case CASE_BOOL: kind = KIND_BOOL; break;
|
||||
case IS_STRING: kind = KIND_STRING; break;
|
||||
case IS_OBJECT: kind = KIND_OBJECT; break;
|
||||
case IS_NULL:
|
||||
kind = KIND_NULL;
|
||||
break;
|
||||
case IS_LONG:
|
||||
kind = KIND_LONG;
|
||||
break;
|
||||
case IS_DOUBLE:
|
||||
kind = KIND_DOUBLE;
|
||||
break;
|
||||
case IS_STRING:
|
||||
kind = KIND_STRING;
|
||||
break;
|
||||
case IS_OBJECT:
|
||||
kind = KIND_OBJECT;
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
kind = KIND_ARRAY;
|
||||
HashTable *h = (Z_ARRVAL_P(src));
|
||||
|
@ -102,7 +118,7 @@ void value_set_zval(engine_value *val, zval *src) {
|
|||
|
||||
for (zend_hash_internal_pointer_reset(h); i < h->nNumOfElements; i++) {
|
||||
unsigned long index;
|
||||
int type = HASH_GET_CURRENT_KEY(h, NULL, &index);
|
||||
int type = _value_current_key_get(h, NULL, &index);
|
||||
|
||||
if (type == HASH_KEY_IS_STRING || index != i) {
|
||||
kind = KIND_MAP;
|
||||
|
@ -114,6 +130,12 @@ void value_set_zval(engine_value *val, zval *src) {
|
|||
|
||||
break;
|
||||
default:
|
||||
// Booleans need special handling for different PHP versions.
|
||||
if (_value_truth(src) != -1) {
|
||||
kind = KIND_BOOL;
|
||||
break;
|
||||
}
|
||||
|
||||
errno = 1;
|
||||
return;
|
||||
}
|
||||
|
@ -176,13 +198,13 @@ bool value_get_bool(engine_value *val) {
|
|||
|
||||
// Return value directly if already in correct type.
|
||||
if (val->kind == KIND_BOOL) {
|
||||
return VALUE_TRUTH(val->internal);
|
||||
return _value_truth(val->internal);
|
||||
}
|
||||
|
||||
value_copy(&tmp, val->internal);
|
||||
convert_to_boolean(&tmp);
|
||||
|
||||
return VALUE_TRUTH(&tmp);
|
||||
return _value_truth(&tmp);
|
||||
}
|
||||
|
||||
char *value_get_string(engine_value *val) {
|
||||
|
@ -251,7 +273,7 @@ engine_value *value_array_keys(engine_value *arr) {
|
|||
unsigned long i = 0;
|
||||
|
||||
for (zend_hash_internal_pointer_reset(h); i < h->nNumOfElements; i++) {
|
||||
HASH_SET_CURRENT_KEY(h, keys->internal);
|
||||
_value_current_key_set(h, keys);
|
||||
zend_hash_move_forward(h);
|
||||
}
|
||||
|
||||
|
@ -286,16 +308,16 @@ void value_array_reset(engine_value *arr) {
|
|||
}
|
||||
|
||||
engine_value *value_array_next_get(engine_value *arr) {
|
||||
HashTable *h = NULL;
|
||||
HashTable *ht = NULL;
|
||||
engine_value *val = value_new();
|
||||
|
||||
switch (arr->kind) {
|
||||
case KIND_ARRAY:
|
||||
case KIND_MAP:
|
||||
h = Z_ARRVAL_P(arr->internal);
|
||||
ht = Z_ARRVAL_P(arr->internal);
|
||||
break;
|
||||
case KIND_OBJECT:
|
||||
h = Z_OBJPROP_P(arr->internal);
|
||||
ht = Z_OBJPROP_P(arr->internal);
|
||||
break;
|
||||
default:
|
||||
// Attempting to return the next index of a non-array value will return
|
||||
|
@ -305,20 +327,21 @@ engine_value *value_array_next_get(engine_value *arr) {
|
|||
return val;
|
||||
}
|
||||
|
||||
VALUE_ARRAY_NEXT_GET(h, val);
|
||||
_value_array_next_get(ht, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
engine_value *value_array_index_get(engine_value *arr, unsigned long idx) {
|
||||
HashTable *h = NULL;
|
||||
HashTable *ht = NULL;
|
||||
engine_value *val = value_new();
|
||||
|
||||
switch (arr->kind) {
|
||||
case KIND_ARRAY:
|
||||
case KIND_MAP:
|
||||
h = Z_ARRVAL_P(arr->internal);
|
||||
ht = Z_ARRVAL_P(arr->internal);
|
||||
break;
|
||||
case KIND_OBJECT:
|
||||
h = Z_OBJPROP_P(arr->internal);
|
||||
ht = Z_OBJPROP_P(arr->internal);
|
||||
break;
|
||||
default:
|
||||
// Attempting to return the first index of a non-array value will return
|
||||
|
@ -332,24 +355,28 @@ engine_value *value_array_index_get(engine_value *arr, unsigned long idx) {
|
|||
return val;
|
||||
}
|
||||
|
||||
VALUE_ARRAY_INDEX_GET(h, idx, val);
|
||||
_value_array_index_get(ht, idx, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
engine_value *value_array_key_get(engine_value *arr, char *key) {
|
||||
HashTable *h = NULL;
|
||||
HashTable *ht = NULL;
|
||||
engine_value *val = value_new();
|
||||
|
||||
switch (arr->kind) {
|
||||
case KIND_ARRAY:
|
||||
case KIND_MAP:
|
||||
h = Z_ARRVAL_P(arr->internal);
|
||||
ht = Z_ARRVAL_P(arr->internal);
|
||||
break;
|
||||
case KIND_OBJECT:
|
||||
h = Z_OBJPROP_P(arr->internal);
|
||||
ht = Z_OBJPROP_P(arr->internal);
|
||||
break;
|
||||
default:
|
||||
return val;
|
||||
}
|
||||
|
||||
VALUE_ARRAY_KEY_GET(h, key, val);
|
||||
}
|
||||
_value_array_key_get(ht, key, val);
|
||||
return val;
|
||||
}
|
||||
|
||||
#include "_value.c"
|
||||
|
|
|
@ -87,7 +87,7 @@ func NewValue(val interface{}) (*Value, error) {
|
|||
for i := 0; i < v.Len(); i++ {
|
||||
vs, err := NewValue(v.Index(i).Interface())
|
||||
if err != nil {
|
||||
C.value_destroy(ptr)
|
||||
C._value_destroy(ptr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ func NewValue(val interface{}) (*Value, error) {
|
|||
for _, key := range v.MapKeys() {
|
||||
kv, err := NewValue(v.MapIndex(key).Interface())
|
||||
if err != nil {
|
||||
C.value_destroy(ptr)
|
||||
C._value_destroy(ptr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -132,7 +132,7 @@ func NewValue(val interface{}) (*Value, error) {
|
|||
|
||||
fv, err := NewValue(v.Field(i).Interface())
|
||||
if err != nil {
|
||||
C.value_destroy(ptr)
|
||||
C._value_destroy(ptr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ func NewValue(val interface{}) (*Value, error) {
|
|||
case reflect.Invalid:
|
||||
C.value_set_null(ptr)
|
||||
default:
|
||||
C.value_destroy(ptr)
|
||||
C._value_destroy(ptr)
|
||||
return nil, fmt.Errorf("Unable to create value of unknown type '%T'", val)
|
||||
}
|
||||
|
||||
|
@ -278,6 +278,6 @@ func (v *Value) Destroy() {
|
|||
return
|
||||
}
|
||||
|
||||
C.value_destroy(v.value)
|
||||
C._value_destroy(v.value)
|
||||
v.value = nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue