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.
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: