php_vm 1.3.2 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. data/ext/php_vm/php_vm.c +110 -24
  2. data/ext/php_vm/php_vm.h +2 -0
  3. 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 php_vm_catch_exception(zval *ex TSRMLS_DC)
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 (strcmp("new", fname)==0) {
261
- // new => no define
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
- } else if (0<(flag & ZEND_ACC_STATIC)) {
264
- // other method
265
- rb_define_singleton_method(v_obj, fname, rb_php_class_call, -1);
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 (strcmp("__construct", fname)==0 || strcmp(ce->name, fname)==0) {
270
- // __construct => no define
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
- rb_define_singleton_method(v_obj, fname, rb_php_object_call, -1);
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** data;
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 **)&data, &pos)) {
706
- rb_define_module_function(rb_mPHPGlobal, Z_STRVAL_P(*data), rb_php_global_class_call, 0);
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("^(?:(?:PHP )?([^:]+?)(?: error)?: {0,2})?(.+) in (.+) on line (\\d+)$");
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 = php_vm_catch_exception;
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"), "0", sizeof("0")-1, PHP_INI_SYSTEM, PHP_INI_STAGE_RUNTIME);
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.2"));
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.2
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-30 00:00:00.000000000 Z
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: