php_vm 1.3.2 → 1.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/php_vm/php_vm.c +110 -24
- data/ext/php_vm/php_vm.h +2 -0
- metadata +2 -2
data/ext/php_vm/php_vm.c
CHANGED
@@ -48,7 +48,7 @@ static void php_embed_error_handler(char *message)
|
|
48
48
|
}
|
49
49
|
}
|
50
50
|
|
51
|
-
static void
|
51
|
+
static void php_vm_exception_hook(zval *ex TSRMLS_DC)
|
52
52
|
{
|
53
53
|
VALUE exception = zval_to_value(ex);
|
54
54
|
rb_exc_raise(exception);
|
@@ -154,6 +154,13 @@ void find_zend_function(zend_class_entry *ce, char *name, int name_len, zend_fun
|
|
154
154
|
free(lcname);
|
155
155
|
}
|
156
156
|
|
157
|
+
int has_zend_function(zend_class_entry *ce, VALUE method_name)
|
158
|
+
{
|
159
|
+
zend_function *mptr;
|
160
|
+
find_zend_function(ce, RSTRING_PTR(method_name), RSTRING_LEN(method_name), &mptr);
|
161
|
+
return mptr!=NULL;
|
162
|
+
}
|
163
|
+
|
157
164
|
int new_php_object(zend_class_entry *ce, VALUE v_args, zval *retval)
|
158
165
|
{
|
159
166
|
int result = FAILURE;
|
@@ -240,10 +247,6 @@ void define_php_methods(VALUE v_obj, zend_class_entry *ce, int is_static)
|
|
240
247
|
// TODO: access scope
|
241
248
|
// TODO: __toString
|
242
249
|
// TODO: __clone
|
243
|
-
// TODO: __call
|
244
|
-
// TODO: __callStatic
|
245
|
-
// TODO: __get
|
246
|
-
// TODO: __set
|
247
250
|
// TODO: __isset
|
248
251
|
|
249
252
|
HashPosition pos;
|
@@ -254,24 +257,49 @@ void define_php_methods(VALUE v_obj, zend_class_entry *ce, int is_static)
|
|
254
257
|
while (zend_hash_get_current_data_ex(&ce->function_table, (void **)&mptr, &pos) == SUCCESS) {
|
255
258
|
int flag = mptr->common.fn_flags;
|
256
259
|
const char *fname = mptr->common.function_name;
|
260
|
+
int is_pass_define = 0;
|
257
261
|
|
258
262
|
if (is_static) {
|
259
263
|
// class method
|
260
|
-
if (
|
261
|
-
|
264
|
+
if (0<(flag & ZEND_ACC_STATIC)) {
|
265
|
+
if (strcmp("new", fname)==0) {
|
266
|
+
// new => no define
|
267
|
+
is_pass_define = 1;
|
262
268
|
|
263
|
-
|
264
|
-
|
265
|
-
|
269
|
+
} else if (strcmp("__callStatic", fname)==0) {
|
270
|
+
// __callStatic => method_missing
|
271
|
+
rb_define_singleton_method(v_obj, "method_missing", rb_php_class_call_method_missing, -1);
|
272
|
+
}
|
273
|
+
|
274
|
+
// define
|
275
|
+
if (!is_pass_define) {
|
276
|
+
rb_define_singleton_method(v_obj, fname, rb_php_class_call, -1);
|
277
|
+
}
|
266
278
|
}
|
267
279
|
} else {
|
268
280
|
// instance method
|
269
|
-
if (
|
270
|
-
|
281
|
+
if (0==(flag & ZEND_ACC_STATIC)) {
|
282
|
+
if (strcmp("__construct", fname)==0 || strcmp(ce->name, fname)==0) {
|
283
|
+
// __construct => no define
|
284
|
+
is_pass_define = 1;
|
285
|
+
|
286
|
+
} else if (strcmp("__call", fname)==0) {
|
287
|
+
// __call => method_missing
|
288
|
+
rb_define_singleton_method(v_obj, "method_missing", rb_php_object_call_method_missing, -1);
|
289
|
+
|
290
|
+
} else if (strcmp("__get", fname)==0) {
|
291
|
+
// __get => method_missing
|
292
|
+
rb_define_singleton_method(v_obj, "method_missing", rb_php_object_call_method_missing, -1);
|
293
|
+
|
294
|
+
} else if (strcmp("__set", fname)==0) {
|
295
|
+
// __set => method_missing
|
296
|
+
rb_define_singleton_method(v_obj, "method_missing", rb_php_object_call_method_missing, -1);
|
297
|
+
}
|
271
298
|
|
272
|
-
} else if (0==(flag & ZEND_ACC_STATIC)) {
|
273
299
|
// other method
|
274
|
-
|
300
|
+
if (!is_pass_define) {
|
301
|
+
rb_define_singleton_method(v_obj, fname, rb_php_object_call, -1);
|
302
|
+
}
|
275
303
|
}
|
276
304
|
}
|
277
305
|
|
@@ -619,7 +647,8 @@ VALUE define_global_constants()
|
|
619
647
|
case HASH_KEY_IS_STRING:{
|
620
648
|
if (0x61<=string_key[0] && string_key[0]<=0x7a) {
|
621
649
|
// lower case
|
622
|
-
char *string_key2 = malloc(strlen(string_key));
|
650
|
+
char *string_key2 = malloc(strlen(string_key)+1);
|
651
|
+
memcpy(string_key2, string_key, strlen(string_key));
|
623
652
|
string_key2[0] = string_key2[0]-32;
|
624
653
|
if (!rb_const_defined(rb_mPHPGlobal, rb_intern(string_key2))) {
|
625
654
|
rb_define_const(rb_mPHPGlobal, string_key2, zval_to_value(*data));
|
@@ -699,11 +728,22 @@ VALUE define_global_classes()
|
|
699
728
|
|
700
729
|
HashTable* ht = Z_ARRVAL_P(z_val);
|
701
730
|
HashPosition pos;
|
702
|
-
zval**
|
731
|
+
zval** z_classname;
|
703
732
|
|
704
733
|
zend_hash_internal_pointer_reset_ex(ht, &pos);
|
705
|
-
while (SUCCESS == zend_hash_get_current_data_ex(ht, (void **)&
|
706
|
-
|
734
|
+
while (SUCCESS == zend_hash_get_current_data_ex(ht, (void **)&z_classname, &pos)) {
|
735
|
+
char *classname = Z_STRVAL_P(*z_classname);
|
736
|
+
int classname_len = Z_STRLEN_P(*z_classname);
|
737
|
+
if (0x41<=classname[0] && classname[0]<=0x5a) {
|
738
|
+
// define class as const if class name is uppercase
|
739
|
+
if (!rb_const_defined(rb_mPHPGlobal, rb_intern(classname))) {
|
740
|
+
VALUE class = rb_php_class_get(rb_cPHPClass, rb_str_new(classname, classname_len));
|
741
|
+
rb_define_const(rb_mPHPGlobal, classname, class);
|
742
|
+
}
|
743
|
+
} else {
|
744
|
+
// define class as module function if class name is lowercase
|
745
|
+
rb_define_module_function(rb_mPHPGlobal, classname, rb_php_global_class_call, 0);
|
746
|
+
}
|
707
747
|
zend_hash_move_forward_ex(ht, &pos);
|
708
748
|
}
|
709
749
|
return Qtrue;
|
@@ -914,6 +954,17 @@ VALUE rb_php_class_call(int argc, VALUE *argv, VALUE self)
|
|
914
954
|
return call_php_method_bridge(ce, NULL, callee, argc, argv);
|
915
955
|
}
|
916
956
|
|
957
|
+
VALUE rb_php_class_call_method_missing(int argc, VALUE *argv, VALUE self)
|
958
|
+
{
|
959
|
+
zend_class_entry *ce = get_zend_class_entry(self);
|
960
|
+
|
961
|
+
VALUE name, args;
|
962
|
+
rb_scan_args(argc, argv, "1*", &name, &args);
|
963
|
+
VALUE argv2[2] = {name, args};
|
964
|
+
|
965
|
+
return call_php_method_bridge(ce, NULL, rb_str_new2("__callStatic"), 2, argv2);
|
966
|
+
}
|
967
|
+
|
917
968
|
|
918
969
|
// class PHPVM::PHPObject
|
919
970
|
|
@@ -967,6 +1018,40 @@ VALUE rb_php_object_call(int argc, VALUE *argv, VALUE self)
|
|
967
1018
|
return call_php_method_bridge(ce, zobj, callee, argc, argv);
|
968
1019
|
}
|
969
1020
|
|
1021
|
+
VALUE rb_php_object_call_method_missing(int argc, VALUE *argv, VALUE self)
|
1022
|
+
{
|
1023
|
+
zend_class_entry *ce = get_zend_class_entry(self);
|
1024
|
+
zval *zobj = get_zval(self);
|
1025
|
+
|
1026
|
+
VALUE call_method = rb_str_new2("__call");
|
1027
|
+
if (has_zend_function(ce, call_method)) {
|
1028
|
+
// __call
|
1029
|
+
VALUE name, args;
|
1030
|
+
rb_scan_args(argc, argv, "1*", &name, &args);
|
1031
|
+
name = rb_str_new2(rb_id2name(SYM2ID(name)));
|
1032
|
+
VALUE argv2[2] = {name, args};
|
1033
|
+
|
1034
|
+
return call_php_method_bridge(ce, zobj, call_method, 2, argv2);
|
1035
|
+
} else {
|
1036
|
+
// accessor
|
1037
|
+
VALUE name, val;
|
1038
|
+
rb_scan_args(argc, argv, "11", &name, &val);
|
1039
|
+
name = rb_str_new2(rb_id2name(SYM2ID(name)));
|
1040
|
+
VALUE argv2[2] = {name, val};
|
1041
|
+
|
1042
|
+
VALUE is_setter = rb_funcall(name, rb_intern("end_with?"), 1, rb_str_new2("="));
|
1043
|
+
if (is_setter) {
|
1044
|
+
// __set
|
1045
|
+
rb_funcall(name, rb_intern("gsub!"), 2, rb_str_new2("="), rb_str_new2(""));
|
1046
|
+
return call_php_method_bridge(ce, zobj, rb_str_new2("__set"), 2, argv2);
|
1047
|
+
} else {
|
1048
|
+
// __get
|
1049
|
+
return call_php_method_bridge(ce, zobj, rb_str_new2("__get"), 1, argv2);
|
1050
|
+
}
|
1051
|
+
}
|
1052
|
+
return Qnil;
|
1053
|
+
}
|
1054
|
+
|
970
1055
|
|
971
1056
|
// class PHPVM::PHPExceptionObject
|
972
1057
|
|
@@ -976,6 +1061,7 @@ VALUE rb_php_exception_object_initialize(int argc, VALUE *argv, VALUE self)
|
|
976
1061
|
return self;
|
977
1062
|
}
|
978
1063
|
|
1064
|
+
|
979
1065
|
// class PHPVM::PHPErrorReporting
|
980
1066
|
|
981
1067
|
VALUE rb_php_error_reporting_initialize(int argc, VALUE *argv, VALUE self)
|
@@ -988,7 +1074,7 @@ VALUE rb_php_error_reporting_initialize(int argc, VALUE *argv, VALUE self)
|
|
988
1074
|
|
989
1075
|
if (argc==1 &&TYPE( argv[0])==T_STRING) {
|
990
1076
|
log_message = argv[0];
|
991
|
-
VALUE re_str = rb_str_new2("^
|
1077
|
+
VALUE re_str = rb_str_new2("^PHP ([^:]+?)(?: error)?: {0,2}(.+) in (.+) on line (\\d+)$");
|
992
1078
|
VALUE re_option = rb_const_get(rb_cRegexp, rb_intern("MULTILINE"));
|
993
1079
|
VALUE report_re = rb_funcall(rb_cRegexp, rb_intern("new"), 2, re_str, re_option);
|
994
1080
|
VALUE m = rb_funcall(argv[0], rb_intern("match"), 1, report_re);
|
@@ -1059,11 +1145,11 @@ void Init_php_vm()
|
|
1059
1145
|
php_vm_module_init();
|
1060
1146
|
atexit(php_vm_module_exit);
|
1061
1147
|
|
1062
|
-
zend_throw_exception_hook =
|
1148
|
+
zend_throw_exception_hook = php_vm_exception_hook;
|
1063
1149
|
|
1064
1150
|
// ini
|
1065
1151
|
zend_try {
|
1066
|
-
zend_alter_ini_entry("display_errors", sizeof("display_errors"), "
|
1152
|
+
zend_alter_ini_entry("display_errors", sizeof("display_errors"), "1", sizeof("0")-1, PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME);
|
1067
1153
|
zend_alter_ini_entry("log_errors", sizeof("log_errors"), "1", sizeof("1")-1, PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME);
|
1068
1154
|
} zend_catch {
|
1069
1155
|
} zend_end_try();
|
@@ -1085,7 +1171,7 @@ void Init_php_vm()
|
|
1085
1171
|
rb_define_singleton_method(rb_mPHPVM, "get_class", rb_php_vm_get_class, 1);
|
1086
1172
|
rb_define_singleton_method(rb_mPHPVM, "define_global", rb_php_vm_define_global, 0);
|
1087
1173
|
|
1088
|
-
rb_define_const(rb_mPHPVM, "VERSION", rb_str_new2("1.3.
|
1174
|
+
rb_define_const(rb_mPHPVM, "VERSION", rb_str_new2("1.3.3"));
|
1089
1175
|
|
1090
1176
|
rb_cv_set(rb_mPHPVM, "@@output_handler", Qnil);
|
1091
1177
|
rb_cv_set(rb_mPHPVM, "@@error_handler", Qnil);
|
@@ -1099,8 +1185,6 @@ void Init_php_vm()
|
|
1099
1185
|
rb_define_module_function(rb_mPHPGlobal, "print", rb_php_global_print, 1);
|
1100
1186
|
rb_define_module_function(rb_mPHPGlobal, "array", rb_php_global_array, -1);
|
1101
1187
|
|
1102
|
-
rb_php_vm_define_global(rb_mPHPVM);
|
1103
|
-
|
1104
1188
|
// class PHPVM::PHPClass
|
1105
1189
|
rb_cPHPClass = rb_define_class_under(rb_mPHPVM, "PHPClass", rb_cObject);
|
1106
1190
|
rb_define_class_variable(rb_cPHPClass, "@@classes", rb_obj_alloc(rb_cHash));
|
@@ -1135,4 +1219,6 @@ void Init_php_vm()
|
|
1135
1219
|
rb_define_method(rb_ePHPErrorReporting, "error_level", rb_php_error_reporting_error_level, 0);
|
1136
1220
|
rb_define_method(rb_ePHPErrorReporting, "file", rb_php_error_reporting_file, 0);
|
1137
1221
|
rb_define_method(rb_ePHPErrorReporting, "line", rb_php_error_reporting_line, 0);
|
1222
|
+
|
1223
|
+
rb_php_vm_define_global(rb_mPHPVM);
|
1138
1224
|
}
|
data/ext/php_vm/php_vm.h
CHANGED
@@ -77,6 +77,7 @@ extern VALUE rb_php_class_new(int argc, VALUE *argv, VALUE self);
|
|
77
77
|
extern VALUE rb_php_class_getter(VALUE self);
|
78
78
|
extern VALUE rb_php_class_setter(VALUE self, VALUE value);
|
79
79
|
extern VALUE rb_php_class_call(int argc, VALUE *argv, VALUE self);
|
80
|
+
extern VALUE rb_php_class_call_method_missing(int argc, VALUE *argv, VALUE self);
|
80
81
|
|
81
82
|
// class PHPVM::PHPObject
|
82
83
|
extern VALUE rb_php_object_initialize(VALUE self, VALUE class, VALUE arg_arr);
|
@@ -84,6 +85,7 @@ extern VALUE rb_php_object_php_class(VALUE self);
|
|
84
85
|
extern VALUE rb_php_object_getter(VALUE self);
|
85
86
|
extern VALUE rb_php_object_setter(VALUE self, VALUE value);
|
86
87
|
extern VALUE rb_php_object_call(int argc, VALUE *argv, VALUE self);
|
88
|
+
extern VALUE rb_php_object_call_method_missing(int argc, VALUE *argv, VALUE self);
|
87
89
|
|
88
90
|
// module
|
89
91
|
extern void php_vm_module_init();
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: php_vm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-12-
|
12
|
+
date: 2012-12-31 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: php_vm is a native bridge between Ruby and PHP.
|
15
15
|
email:
|