- Timestamp:
- Jul 3, 2020, 7:19:17 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
EcnlProtoTool/trunk/asp3_dcre/tecsgen/tecslib/plugin/MrubyBridgePlugin.rb
r321 r429 3 3 # mruby => TECS bridge 4 4 # 5 # Copyright (C) 2008-201 5by TOPPERS Project5 # Copyright (C) 2008-2017 by TOPPERS Project 6 6 # 7 7 # 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ … … 37 37 # 38 38 39 # Todo: 40 # 生成するもの 41 # gen_cdl_file 42 # ブリッジ初期化セルタイプ (シグニチャごと) 43 # @@init_celltypes に記録 44 # ブリッジセルタイプ (シグニチャごと) 45 # @@celltypes に記録 46 # 構造体セルタイプ 47 # @@struct_list に記録 48 # new_cell 49 # TECS 初期化セル(プロトタイプ宣言) 50 # @@VM_init_cells に記録 51 # @@VM_struct_list に記録 52 # @@VM_ptr_list に記録 53 # gen_post_code 54 # 構造体初期化セル 55 # ポインタ初期化セル 56 # TECS 初期化セル 57 # 58 # ep_func の作成 59 # signature, ポインタ、構造体 … 初期化受け口=mruby VM への登録 60 # ポインタ 61 # preamble の作成 62 # ポインタ、構造体 … アクセス用コードの生成 63 # signature … ブリッジ関数のプロトタイプ宣言 64 # postamble の作成 65 # signature … ブリッジ関数の定義 66 67 class MrubyBridgePlugin < SignaturePlugin 68 69 # プラグイン引数名 => Proc 70 MrubyBridgePluginArgProc = { 71 "ignoreUnsigned" => Proc.new { |obj,rhs| obj.set_ignoreUnsigned rhs }, 72 "include" => Proc.new { |obj,rhs| obj.set_include rhs }, 73 "exclude" => Proc.new { |obj,rhs| obj.set_exclude rhs }, 74 } 75 76 @@celltypes = { } # {celltype_name => [ BridgePlugin のインスタンスの配列 } 77 @@init_celltypes = { } # {celltype_name => [ BridgePlugin のインスタンスの配列 } 78 @@struct_list = { } # {struct_name=>StructType} 79 @@ptr_list = { } # {ptr_celltype_name=> @@TYPE_MAP の対応するもの} 80 @@VM_list = { } # VM_name => true 81 @@VM_celltypes = { } # VM_name => { @celltype_name => セルの配列 } 82 @@VM_struct_list = { } # {name=>StructType} 83 @@VM_ptr_list = { } # { VM_name => {name=> @@TYPE_MAP の対応するもの} } 84 @@TYPE_MAP = { # type_str class GET_SET 85 :char_t => [:char_t, "Char", :Char, :INT ], 86 :uchar_t => [:uchar_t, "UChar", :Char, :INT ], 87 :schar_t => [:schar_t, "SChar", :Char, :INT ], 88 89 :bool_t => [:bool_t, "Bool", :Bool, :BOOL ], 90 :int8_t => [:int8_t, "Int8", :Int, :INT ], 91 :int16_t => [:int16_t, "Int16", :Int, :INT ], 92 :int32_t => [:int32_t, "Int32", :Int, :INT ], 93 :int64_t => [:int64_t, "Int64", :Int, :INT ], 94 :uint8_t => [:uint8_t, "UInt8", :Int, :INT ], 95 :uint16_t => [:uint16_t, "UInt16", :Int, :INT ], 96 :uint32_t => [:uint32_t, "UInt32", :Int, :INT ], 97 :uint64_t => [:uint64_t, "UInt64", :Int, :INT ], 98 99 :int => [:int, "Int", :Int, :INT ], 100 :char => [:char, "Char", :Char, :INT ], # char は char_t として扱う 101 :short => [:short, "Short", :Int, :INT ], 102 :long => [:long, "Long", :Int, :INT ], 103 104 :"unsigned char" => [:uchar_t, "UChar", :Char, :INT ], 105 :"unsigned int" => [:"unsigned int", "UInt", :Int, :INT ], 106 :"unsigned short" => [:"unsigned short", "UShort", :Int, :INT ], 107 :"unsigned long" => [:"unsigned long", "ULong", :Int, :INT ], 108 :"signed char" => [:schar_t, "SChar", :Char, :INT ], 109 :"signed int" => [:int, "Int", :Int, :INT ], 110 :"signed short" => [:short, "Short", :Int, :INT ], 111 :"signed long" => [:long, "Long", :Int, :INT ], 112 113 :float32_t => [:float32_t, "Float32", :Float, :FLOAT ], 114 :double64_t => [:double64_t,"Double64", :Float, :FLOAT ], 115 116 :float => [:float, "Float32", :Float, :FLOAT ], 117 :double => [:double, "Double64", :Float, :FLOAT ] 118 } 119 120 # included or excluded functions 121 122 ### ロードされた時点で実行される ### 123 124 # -I に $(TECSPATH)/mruby を追加 125 # TECSGEN::Makefile.add_obj "$(MRUBY_MAIN_OBJ)" 126 TECSGEN::Makefile.add_ldflag "-lmruby -L$(MRUBYPATH)/lib -lm" 127 TECSGEN::Makefile.add_search_path "$(MRUBYPATH)/include" 128 TECSGEN::Makefile.add_var "MRUBYPATH", "..", "CHANGE this to suitable path" 129 # TECSGEN::Makefile.add_var "MRUBY_MAIN_OBJ", "$(_TECS_OBJ_DIR)tecs_mruby.o", "CHANGE this if your have your main" 130 131 132 #=== プラグインインスタンスの初期化 133 # 戻り値、引数の型が使用可能なものかチェックする 134 # 135 def initialize( signature, option ) 136 super 137 138 if ! $no_banner 139 STDERR << "MrubyBridgePlugin: version 1.2.0 (Suitable for mruby ver 1.2.0. Has backward compatibility with ver 1.1.0)\n" 140 end 141 142 @b_ignoreUnsigned = false 143 @includes = [] 144 @excludes = [] 145 @struct_list = { } 146 @ptr_list = { } 147 148 @plugin_arg_check_proc_tab = MrubyBridgePluginArgProc 149 parse_plugin_arg 150 151 @celltype_name = :"t#{@signature.get_global_name}" 152 @init_celltype_name = :"#{@celltype_name}_Initializer" 153 # this variable is sometimes not used. rhs coded directry. 154 @class_name = :"T#{@signature.get_global_name}" 155 156 @func_head_array = [] 157 if @includes.length > 0 && @excludes.length > 0 then 158 cdl_error( "MRB1011 both include && exclude are specified" ) 159 end 160 161 if signature.get_function_head_array == nil then 162 return # 以前に文法エラー発生 163 end 164 165 signature.get_function_head_array.each{ |func_head| 166 if @includes.length > 0 then 167 if @includes.index func_head.get_name then 168 dbgPrint "MrubyBridgePlugin: #{func_head.get_name} INCLUDED\n" 169 @func_head_array << func_head 170 else 171 dbgPrint "MrubyBridgePlugin: #{func_head.get_name} NOT included\n" 172 end 173 elsif @excludes.length > 0 then 174 if @excludes.index( func_head.get_name ) == nil then 175 dbgPrint "MrubyBridgePlugin: #{func_head.get_name} NOT excluded\n" 176 @func_head_array << func_head 177 else 178 dbgPrint "MrubyBridgePlugin: #{func_head.get_name} EXCLUDED\n" 179 end 180 else 181 @func_head_array << func_head 182 end 183 } 184 185 if @func_head_array.length == 0 then 186 cdl_error( "MRB1012 '$1' no function remained by exclude", @signature.get_name ) 187 end 188 189 check_name_and_return_type @func_head_array 190 check_parameter_type @func_head_array 191 192 end 193 194 #=== check function name & return type 195 def check_name_and_return_type func_head_array 196 b_init = false; b_init_cell = false 197 func_head_array.each{ |func_head| 198 if( func_head.get_name == :initialize )then 199 cdl_warning( "MRW2001 initialize: internally defined. change to initialize_cell in ruby" ) 200 b_init = true 201 elsif( func_head.get_name == :initialize_cell )then 202 b_init_cell = true 203 end 204 rtype = func_head.get_return_type.get_original_type 205 case rtype 206 when BoolType, IntType, FloatType, VoidType 207 else 208 cdl_error( "MRB1001 cannot return type $1", rtype.get_type_str ) 209 end 210 } 211 if( b_init && b_init_cell )then 212 cdl_warning( "MRB1002 initialize: internally defined. change to initialize_cell in ruby" ) 39 #== MrubyBridgePlugin クラス 40 class MrubyBridgePlugin < MultiPlugin 41 def self.get_plugin superClass 42 # case when (つまりは ===) では、期待したように一致しない模様 43 if superClass == SignaturePlugin then 44 dbgPrint "MrubyBridgePlugin: SignaturePlugin" 45 require_tecsgen_lib 'tecslib/plugin/MrubyBridgeSignaturePlugin.rb' 46 return MrubyBridgeSignaturePlugin 47 elsif superClass == CelltypePlugin 48 dbgPrint "MrubyBridgePlugin: CelltypePlugin" 49 require_tecsgen_lib 'tecslib/plugin/MrubyBridgeCelltypePlugin.rb' 50 return MrubyBridgeCelltypePlugin 51 elsif superClass == CompositePlugin 52 dbgPrint "MrubyBridgePlugin: CompositePlugin" 53 require_tecsgen_lib 'tecslib/plugin/MrubyBridgeCompositePlugin.rb' 54 return MrubyBridgeCompositePlugin 55 elsif superClass == CellPlugin 56 dbgPrint "MrubyBridgePlugin: CellPlugin" 57 require_tecsgen_lib 'tecslib/plugin/MrubyBridgeCellPlugin.rb' 58 return MrubyBridgeCellPlugin 59 #elsif superClass == ThroughPlugin 60 # return ThroughPlugin 61 #elsif superClass == DomainPlugin 62 # return DomainPlugin 63 else 64 dbgPrint "MrubyBridgePlugin: unsupported" 65 return nil 213 66 end 214 67 end 215 216 #=== check paramter type217 def check_parameter_type func_head_array218 # check type of parameters219 func_head_array.each{ |fh|220 fh.get_paramlist.get_items.each{ |param_decl|221 case param_decl.get_direction222 when :SEND, :RECEIVE223 cdl_error( "MRB1003 $1: $2 parameter cannot be used in mruby Bridge", param_decl.get_name, param_decl.get_direction.to_s.downcase )224 end225 type = param_decl.get_type226 type_org = type.get_original_type227 type_str = type.get_type_str + type.get_type_str_post228 229 b_ng = false230 case type_org231 when IntType232 case type_org.get_bit_size233 when 8, 16, 32, 64234 when -1, -2, -3, -4, -11235 else236 b_ng = true237 end238 when BoolType239 when FloatType240 when PtrType241 ttype_org = type_org.get_type # ポインタの指している先の型242 ttype = ttype_org.get_original_type # 上記の typedef されている場合、元の型243 register_ptr_type ttype_org244 245 if( type_org.get_string.to_s == "-1" ) then246 case param_decl.get_direction247 when :OUT, :INOUT248 cdl_error( "MRB9999 string specifier without length cannot be used for out & inout parameter")249 end250 end251 252 case ttype253 when IntType254 bit_size = ttype.get_bit_size255 # if bit_size < 0 && bit_size != -1 then256 # b_ng = true257 # end258 when FloatType259 when BoolType260 when StructType261 if( type_org.get_size || type_org.get_string || type_org.get_count ) then262 cdl_error( "MRB1004 $1: size_is, count_is, string cannot be specified for struct pointer", param_decl.get_name )263 end264 check_struct_member ttype_org265 else266 b_ng = true267 end268 when StructType269 check_struct_member type_org270 else # ArrayType, FuncType, EnumType, VoidType271 b_ng = true272 end273 if b_ng then274 cdl_error( "MRB1005 $1: type $2 cannot be used in mruby Bridge", param_decl.get_name, type_str )275 end276 }277 }278 end279 280 #=== 構造体のメンバーの型のチェック281 def check_struct_member struct_type282 #p "tag name:#{struct_type.get_name}"283 # sttype = Namespace.find_tag( struct_type.get_name )284 sttype = struct_type.get_original_type285 if sttype.get_name == nil then286 cdl_error( "MRB10007 tagless-struct cannot be handled")287 end288 sttype.get_members_decl.get_items.each { |d|289 t = d.get_type.get_original_type290 case t291 when IntType, FloatType, BoolType292 else293 cdl_error( "MRB1006 $1: type $2 not allowed for struct member", d.get_name, d.get_type.get_type_str + d.get_type.get_type_str_post )294 end295 }296 st_name = :"t{}"297 if @struct_list[ sttype.get_name ] == nil then298 # print_msg " MrubyBridgePlugin: [struct] #{struct_type.get_type_str} => class TECS::Struct#{sttype.get_name}\n"299 print " MrubyBridgePlugin: [struct] #{struct_type.get_type_str} => class TECS::Struct#{sttype.get_name}\n"300 @struct_list[ sttype.get_name ] = sttype301 end302 end303 304 def register_ptr_type ttype305 t_org = ttype.get_original_type306 tment = get_type_map_ent t_org307 if tment == nil then308 return309 cdl_error( "MRB1008 unknown pointer type '$1'", ttype.get_type_str )310 end311 ptr_celltype_name = :"t#{tment[1]}Pointer"312 if @@ptr_list[ ptr_celltype_name ] == nil then313 # print_msg " MrubyBridgePlugin: [pointer] #{ttype.get_type_str}* => class TECS::#{tment[1]}Pointer\n"314 print " MrubyBridgePlugin: [pointer] #{ttype.get_type_str}* => class TECS::#{tment[1]}Pointer\n"315 @@ptr_list[ ptr_celltype_name ] = tment316 end317 if @ptr_list[ ptr_celltype_name ] == nil then318 @ptr_list[ ptr_celltype_name ] = tment319 end320 end321 322 def get_type_map_ent ttype323 # structure type is registerd in check_struct_member324 if ttype.kind_of? StructType325 return326 end327 tstr = ttype.get_type_str.sub( /const /, "" ) # const は無視328 tstr = tstr.sub( /volatile /, "" ) # volatile も無視329 if @b_ignoreUnsigned then330 tstr = tstr.sub( /unsigned /, "" ) # volatile も無視331 tstr = tstr.sub( /uint/, "int" ) # volatile も無視332 tstr = tstr.sub( /[cs]char/, "char" ) # volatile も無視333 end334 return @@TYPE_MAP[ tstr.to_sym ]335 end336 337 #=== CDL ファイルの生成338 # typedef, signature, celltype, cell コードを生成339 #file:: FILE 生成するファイル340 def gen_cdl_file(file)341 342 # ブリッジセルタイプの生成343 if @@celltypes[ @celltype_name ] == nil then344 @@celltypes[ @celltype_name ] = [ self ]345 @@init_celltypes[ @init_celltype_name ] = true346 print_msg <<EOT347 MrubyBridgePlugin: [signature] #{@signature.get_namespace_path} => [celltype] nMruby::#{@celltype_name} => [class] TECS::#{@class_name}348 EOT349 350 file.print <<EOT351 import( <mruby.cdl> );352 353 /**** Ruby => TECS Bridge Celltype (MBP500) ****/354 namespace nMruby{355 // bridge celltype356 [idx_is_id,active] // not actually active, to avoid warning W1002, W1007357 celltype #{@celltype_name} {358 call #{@signature.get_namespace_path.to_s} cTECS;359 attr {360 [omit]361 char_t *VMname = "VM";362 };363 };364 // bridge initializer celltype365 celltype #{@init_celltype_name} {366 entry sInitializeTECSBridge eInitialize;367 };368 };369 EOT370 371 # 構造体セルタイプの生成372 @struct_list.each{ |name, sttype|373 if @@struct_list[ name ] == nil then374 file.print <<EOT375 namespace nMruby{376 [singleton]377 celltype #{name} {378 entry sInitializeTECSBridge eInitialize;379 };380 };381 EOT382 @@struct_list[ name ] = sttype383 end384 }385 386 else387 cdl_warning( "MRBW001 MrubyBridgePlugin: signature '$1' duplicate. ignored current one", @signature.get_namespace_path )388 @@celltypes[ @celltype_name ] << self389 end390 end391 392 #=== gen_cdl_file で定義したセルタイプに 新しいセルが定義された393 # cell のセルタイプの名前は @celltype_name394 def new_cell cell395 if cell.get_celltype.get_name != @celltype_name then396 return397 end398 399 join = cell.get_join_list.get_item :VMname400 if join then401 vm_name = CDLString.remove_dquote(join.get_rhs.to_s).to_sym402 else403 vm_name = :"VM"404 end405 406 if @@VM_list[ vm_name ] == nil then407 @@VM_list[ vm_name ] = true408 409 initializer_celltype_cdl = "#{$gen}/#{cell.get_name}Initializer.cdl"410 file = CFile.open( initializer_celltype_cdl, "w" )411 412 # TECS 初期化セル(プロトタイプ宣言)413 print_msg " MrubyBridgePlugin: join your VM's cInitialize to #{vm_name}_TECSInitializer.eInitialize\n"414 415 file.print <<EOT416 417 // prototype of TECSInitializer (MBP510)418 cell nMruby::tTECSInitializer #{vm_name}_TECSInitializer;419 EOT420 file.close421 422 Generator.parse( initializer_celltype_cdl, self )423 end424 425 if @@VM_celltypes[ vm_name ] then426 vma = @@VM_celltypes[ vm_name ]427 428 if vma[ @celltype_name ] then429 vma[ @celltype_name ] << cell430 else431 vma[ @celltype_name ] = [cell]432 @@VM_celltypes[ vm_name ] = vma433 end434 else435 vma = { }436 vma[ @celltype_name ] = [cell]437 @@VM_celltypes[ vm_name ] = vma438 end439 440 @struct_list.each{ |stname, sttype|441 if @@VM_struct_list[ vm_name ] then442 @@VM_struct_list[ vm_name ][ sttype.get_name ] = sttype443 else444 @@VM_struct_list[ vm_name ] = { sttype.get_name => sttype }445 end446 }447 @ptr_list.each{ |ptr_celltype_name, tment|448 if @@VM_ptr_list[ vm_name ] then449 @@VM_ptr_list[ vm_name ][ ptr_celltype_name ] = tment450 else451 @@VM_ptr_list[ vm_name ] = { ptr_celltype_name => tment }452 end453 }454 455 end456 457 #=== プラグインが CDL の POST コードを生成458 # tmp_plugin_post_code.cdl への出力459 def self.gen_post_code file460 461 # file.print <<EOT462 # namespace nMruby {463 # EOT464 #465 # @@ptr_list.each{ |name,tment|466 # file.print <<EOT467 #468 # // MBP600469 # [singleton]470 # celltype #{name} {471 # entry sInitializeTECSBridge eInitialize;472 # };473 # EOT474 # }475 #476 # file.print <<EOT477 # };478 # EOT479 480 # gen_post_code で生成した celltype は gen_ep_func が呼び出されない #847481 # @@struct_list.each{ |name,sttype|482 # file.print <<EOT483 #484 # [singleton]485 # celltype #{name} {486 # entry sInitializeTECSBridge eInitialize;487 # };488 #EOT489 # }490 491 file.print " // MBP601\n"492 @@VM_celltypes.each{ |vm_name, instance_list|493 instance_list.each { |celltype_name, array|494 cell = array[0]495 if cell.get_celltype then496 ct_name = cell.get_celltype.get_name497 file.print <<EOT498 cell nMruby::#{ct_name}_Initializer #{vm_name}_#{ct_name}_Initializer{ };499 EOT500 end501 }502 }503 504 file.print " // MBP602\n"505 @@ptr_list.each{ |name,tment|506 file.print <<EOT507 cell nMruby::#{name} C#{name} { };508 EOT509 }510 511 file.print " // MBP603\n"512 @@struct_list.each{ |name,sttype|513 file.print <<EOT514 cell nMruby::#{name} C#{name} { };515 EOT516 }517 518 if @@VM_celltypes == nil519 raise "are0"520 end521 @@VM_celltypes.each{ |vm_name, instance_list|522 file.print " /* === VM #{vm_name} === (MBP610) */\n"523 init_cell_name = "#{vm_name}_TECSInitializer"524 525 file.print " cell nMruby::tTECSInitializer #{init_cell_name} {\n"526 527 instance_list.each { |celltype_name, array|528 array.each{ |cell|529 ct_name = cell.get_celltype.get_name530 file.print " cInitialize[] = #{vm_name}_#{ct_name}_Initializer.eInitialize;\n"531 }532 }533 if @@VM_ptr_list[vm_name] then534 @@VM_ptr_list[vm_name].each{ |name, tment|535 file.print " cInitialize[] = C#{name}.eInitialize;\n"536 }537 end538 if @@VM_struct_list[vm_name] then539 @@VM_struct_list[vm_name].each{ |name, sttype|540 file.print " cInitialize[] = C#{name}.eInitialize;\n"541 }542 end543 file.print " };"544 }545 546 end547 548 ####### 以下コード生成段階 ######549 550 #=== 受け口関数の本体コードを生成(頭部と末尾は別途出力)551 #ct_name:: Symbol (プラグインで生成された) セルタイプ名 .Symbol として送られてくる552 def gen_ep_func_body( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )553 if @@celltypes[ ct_name ] then554 gen_ep_func_body_bridge( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )555 elsif @@init_celltypes[ ct_name ] then556 gen_ep_func_body_bridge_init( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )557 elsif @@ptr_list[ ct_name ] then558 gen_ep_func_body_ptr( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )559 elsif @@struct_list[ ct_name ] then560 gen_ep_func_body_struct( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )561 else562 raise "Unknown #{ct_name}"563 end564 end565 566 def gen_ep_func_body_bridge( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )567 raise "unexpected "568 end569 570 def gen_ep_func_body_bridge_init( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )571 file.print <<EOT572 CELLCB *p_cellcb = GET_CELLCB( idx ); /* no error check */ /* MBP700 */573 struct RClass *rc;574 575 rc = mrb_define_class_under( mrb, TECS, \"#{@class_name}\", mrb->object_class );576 mrb_define_method( mrb, rc, "initialize", MrubyBridge_#{@celltype_name}_initialize, MRB_ARGS_REQ(1) );577 MRB_SET_INSTANCE_TT(rc, MRB_TT_DATA);578 EOT579 580 @func_head_array.each{ |f|581 if ! f.is_function? then582 next583 end584 if f.get_name != :initialize then585 func_name = f.get_name586 else587 func_name = :initialize_cell588 end589 590 ret_type = f.get_return_type591 n_param = 0592 f.get_paramlist.get_items.each{ |param|593 case param.get_direction594 when :IN, :INOUT, :OUT595 n_param += 1596 when :SEND, :RECEIVE597 raise "send, receive"598 end599 }600 if n_param > 0 then601 p_str = "MRB_ARGS_REQ( #{n_param} )"602 else603 p_str = "MRB_ARGS_NONE()"604 end605 file.print <<EOT606 mrb_define_method( mrb, rc, "#{func_name}", MrubyBridge_#{@celltype_name}_#{func_name}, #{p_str} );607 EOT608 }609 end610 611 def gen_ep_func_body_ptr( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )612 613 t = @@ptr_list[ct_name]614 type = t[1]615 file.print <<EOT616 struct RClass *a; /* MBP710 */617 618 a = mrb_define_class_under(mrb, TECS, "#{type}Pointer", mrb->object_class);619 MRB_SET_INSTANCE_TT(a, MRB_TT_DATA);620 621 mrb_define_method(mrb, a, "initialize", #{type}Pointer_initialize, MRB_ARGS_REQ(1));622 mrb_define_method(mrb, a, "[]", #{type}Pointer_aget, MRB_ARGS_REQ(1));623 mrb_define_method(mrb, a, "value", #{type}Pointer_get_val, MRB_ARGS_NONE());624 mrb_define_method(mrb, a, "[]=", #{type}Pointer_aset, MRB_ARGS_REQ(2));625 mrb_define_method(mrb, a, "value=", #{type}Pointer_set_val, MRB_ARGS_REQ(1));626 mrb_define_method(mrb, a, "size", #{type}Pointer_size, MRB_ARGS_NONE());627 mrb_define_method(mrb, a, "length", #{type}Pointer_size, MRB_ARGS_NONE());628 EOT629 630 if t[2] == :Char then631 file.print <<EOT632 mrb_define_method(mrb, a, "to_s", CharPointer_to_s, MRB_ARGS_NONE());633 mrb_define_method(mrb, a, "from_s", CharPointer_from_s, MRB_ARGS_REQ(1));634 EOT635 end636 end637 638 def gen_ep_func_body_struct( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params )639 tag = ct_name640 structType = @@struct_list[ tag ]641 file.print <<EOT642 struct RClass *a; /* MBP720 */643 644 a = mrb_define_class_under(mrb, TECS, "Struct#{tag}", mrb->object_class);645 MRB_SET_INSTANCE_TT(a, MRB_TT_DATA);646 647 mrb_define_method(mrb, a, "initialize", Struct_#{tag}_initialize, MRB_ARGS_NONE());648 EOT649 650 structType.get_members_decl.get_items.each{ |d|651 file.print " STRUCT_INIT_MEMBER( #{tag}, #{d.get_name} )\n"652 }653 end654 655 #=== 受け口関数の preamble (C言語)を生成する656 # 必要なら preamble 部に出力する657 #file:: FILE 出力先ファイル658 #b_singleton:: bool true if singleton659 #ct_name:: Symbol660 #global_ct_name:: string661 def gen_preamble( file, b_singleton, ct_name, global_ct_name )662 if @@celltypes[ ct_name ] then663 gen_preamble_mruby( file, b_singleton, ct_name, global_ct_name )664 gen_preamble_instance( file, b_singleton, ct_name, global_ct_name )665 gen_preamble_instance_initialize( file, b_singleton, ct_name, global_ct_name )666 gen_preamble_bridge_func( file, b_singleton, ct_name, global_ct_name )667 elsif @@init_celltypes[ ct_name ] then668 gen_preamble_mruby( file, b_singleton, ct_name, global_ct_name )669 gen_preamble_instance_proto( file, b_singleton, ct_name, global_ct_name )670 elsif @@ptr_list[ ct_name ] then671 gen_preamble_ptr( file, b_singleton, ct_name, global_ct_name )672 elsif @@struct_list[ ct_name ] then673 gen_preamble_struct( file, b_singleton, ct_name, global_ct_name )674 else675 raise "Unknown #{ct_name}"676 end677 end678 679 def gen_preamble_mruby( file, b_singleton, ct_name, global_ct_name )680 file.print <<EOT681 /* MBP: MrubyBridgePlugin: MBP000 */682 #include "mruby.h"683 #include "mruby/class.h"684 #include "mruby/data.h"685 #include "mruby/string.h"686 #include "TECSPointer.h"687 #include "TECSStruct.h"688 689 #if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)690 #define DLLEXPORT __declspec(dllexport)691 #else692 #define DLLEXPORT693 #endif694 695 #ifndef NULL696 #define NULL 0697 #endif698 EOT699 end700 701 def gen_preamble_instance( file, b_singleton, ct_name, global_ct_name )702 file.print <<EOT703 704 /* RData MBP001 */705 static void706 #{@celltype_name}_free( mrb_state *mrb, void *p )707 {708 if( p )709 (void)mrb_free( mrb, p );710 }711 712 /* RData MBP002 */713 struct mrb_data_type data_type_#{@celltype_name} =714 {715 "#{@celltype_name}",716 #{@celltype_name}_free717 };718 719 /* RData MBP003 */720 struct tecs_#{@celltype_name} {721 CELLCB *cbp;722 };723 724 /* name_to_cbp MBP010 */725 const struct name_to_cbp_#{@celltype_name} {726 char *name; /* Cell Name */727 CELLCB *cbp;728 } Name_to_cbp_#{@celltype_name}[] = {729 EOT730 731 # mikan namespace732 nsp = NamespacePath.new( :nMruby, true )733 nsp.append! ct_name734 ct = Namespace.find nsp735 736 ct.get_cell_list.each{ |cell|737 if cell.is_generate? then738 name_array = ct.get_name_array( cell )739 file.print "\t{ \"#{cell.get_name}\", #{name_array[8]} },\n"740 end741 }742 743 file.print <<EOT744 \t{ 0, 0 },745 };746 747 EOT748 749 end750 751 def gen_preamble_ptr( file, b_singleton, ct_name, global_ct_name )752 tment = @@ptr_list[ ct_name ]753 file.print <<EOT754 755 GET_SET_#{tment[3]}( #{tment[1]}, #{tment[0]} )756 POINTER_CLASS( #{tment[1]}, #{tment[0]} )757 EOT758 end759 760 def gen_preamble_struct( file, b_singleton, ct_name, global_ct_name )761 tag = ct_name762 structType = @@struct_list[ tag ]763 file.print <<EOT764 /* struct #{tag} */765 STRUCT_CLASS( #{tag} )766 EOT767 768 structType.get_members_decl.get_items.each{ |d|769 type = d.get_type.get_original_type770 case type771 when IntType, CIntType772 bit_size = type.get_bit_size773 case bit_size774 when -11, -1775 tType = "Char"776 ttype = "char"777 when -2778 tType = "Short"779 ttype = "short"780 when -3781 tType = "Int"782 ttype = "int"783 when -4784 tType = "Long"785 ttype = "long"786 when -5787 tType = "IntPtr"788 ttype = "intptr"789 when 8, 16, 32, 64790 tType = "Int#{bit_size}"791 ttype = "int#{bit_size}"792 else793 raise "cannot handle bit_size #{bit_size}"794 end795 file.print "MEMBER_GET_SET_INT( #{tag}, #{d.get_name}, #{tType}, #{ttype} )\n"796 when FloatType, CFloatType797 file.print "MEMBER_GET_SET_FLOAT( #{tag}, #{d.get_name} )\n"798 else799 raise "cannot handle type"800 end801 }802 803 end804 805 def gen_preamble_instance_proto( file, b_singleton, ct_name, global_ct_name )806 file.print <<EOT807 // Prototype MBP400808 mrb_value MrubyBridge_#{@celltype_name}_initialize( mrb_state *mrb, mrb_value self);809 EOT810 811 @func_head_array.each{ |f|812 if ! f.is_function? then813 next814 end815 if f.get_name != :initialize then816 func_name = f.get_name817 else818 func_name = :initialize_cell819 end820 821 ret_type = f.get_return_type822 ret_type0 = f.get_return_type.get_original_type823 b_void = ret_type0.is_void?824 plist = f.get_paramlist.get_items825 826 file.print <<EOT827 mrb_value MrubyBridge_#{@celltype_name}_#{func_name}( mrb_state *mrb, mrb_value self );828 EOT829 }830 end831 832 def gen_preamble_instance_initialize( file, b_singleton, ct_name, global_ct_name )833 file.print <<EOT834 835 /* MBP100 */836 mrb_value837 MrubyBridge_#{@celltype_name}_initialize( mrb_state *mrb, mrb_value self)838 {839 mrb_value name;840 struct tecs_#{@celltype_name} *tecs_cb;841 const struct name_to_cbp_#{@celltype_name} *ntc;842 843 /* set DATA_TYPE earlier to avoid SEGV */844 DATA_TYPE( self ) = &data_type_#{@celltype_name};845 846 mrb_get_args(mrb, "o", &name );847 if( mrb_type( name ) != MRB_TT_STRING ){848 mrb_raise(mrb, E_NAME_ERROR, "cell name not string");849 }850 for( ntc = &Name_to_cbp_#{@celltype_name}[0]; ntc->name != NULL; ntc++ ){851 if( strcmp( ntc->name, RSTRING_PTR( name ) ) == 0 )852 break;853 }854 if( ntc->name == 0 ){855 mrb_raise(mrb, E_ARGUMENT_ERROR, "cell not found");856 }857 tecs_cb = (struct tecs_#{@celltype_name} *)mrb_malloc(mrb, sizeof(struct tecs_#{@celltype_name}) );858 tecs_cb->cbp = ntc->cbp;859 DATA_PTR( self ) = (void *)tecs_cb;860 861 return self;862 }863 EOT864 end865 866 def gen_preamble_bridge_func( file, b_singleton, ct_name, global_ct_name )867 868 @func_head_array.each{ |f|869 if ! f.is_function? then870 next871 end872 if f.get_name != :initialize then873 func_name = f.get_name874 else875 func_name = :initialize_cell876 end877 878 ret_type = f.get_return_type879 ret_type0 = f.get_return_type.get_original_type880 b_void = ret_type0.is_void?881 plist = f.get_paramlist.get_items882 883 file.print <<EOT884 885 /* bridge function (MBP101) */886 mrb_value887 MrubyBridge_#{ct_name}_#{func_name}( mrb_state *mrb, mrb_value self )888 {889 /* cellcbp (MBP105) */890 CELLCB *p_cellcb = ((struct tecs_#{@celltype_name} *)DATA_PTR(self))->cbp;891 EOT892 893 file.print " /* variables for return & parameter (MBP110) */\n"894 if ! b_void then895 file.print " ", ret_type.get_type_str, "\tret_val", ret_type.get_type_str_post, ";\n"896 end897 arg_str = ""898 n_param = 0899 n_scalar = 0900 n_ptr = 0901 n_struct = 0902 plist.each{ |param|903 case param.get_direction904 when :IN, :INOUT, :OUT905 type = param.get_type.get_original_type906 case type907 when IntType908 file.print " mrb_int mrb_", param.get_name, ";\n"909 file.print " #{param.get_type.get_type_str} #{param.get_name}#{param.get_type.get_type_str_post};\n"910 arg_str += "i"911 n_param += 1912 n_scalar += 1913 when FloatType914 file.print " mrb_float mrb_", param.get_name, ";\n"915 file.print " #{param.get_type.get_type_str} #{param.get_name}#{param.get_type.get_type_str_post};\n"916 arg_str += "f"917 n_param += 1918 n_scalar += 1919 when BoolType920 file.print " mrb_value mrb_", param.get_name, ";\n"921 file.print " #{param.get_type.get_type_str} #{param.get_name}#{param.get_type.get_type_str_post};\n"922 arg_str += "o"923 n_param += 1924 n_scalar += 1925 when PtrType926 file.print " mrb_value mrb_", param.get_name, ";\n"927 file.print " #{param.get_type.get_type_str} #{param.get_name}#{param.get_type.get_type_str_post};\n"928 arg_str += "o"929 n_param += 1930 n_ptr += 1931 when StructType932 file.print " mrb_value mrb_", param.get_name, ";\n"933 file.print " #{param.get_type.get_type_str} *#{param.get_name}#{param.get_type.get_type_str_post};\n"934 arg_str += "o"935 n_param += 1936 n_struct += 1937 else938 raise "Unkown type"939 end940 end941 }942 943 if n_param > 0 then944 file.print " /* retrieve arguments (MBP111) */\n"945 file.print " mrb_get_args(mrb, \"#{arg_str}\""946 plist.each{ |param|947 case param.get_direction948 when :IN, :INOUT, :OUT949 type = param.get_type.get_original_type950 case type951 when IntType952 file.print ", &mrb_", param.get_name953 when FloatType954 file.print ", &mrb_", param.get_name955 when BoolType956 file.print ", &mrb_", param.get_name957 when PtrType958 file.print ", &mrb_", param.get_name959 when StructType960 file.print ", &mrb_", param.get_name961 else962 raise "Unkown type"963 end964 end965 }966 file.print " );\n"967 968 if n_scalar > 0 || n_struct > 0 then969 file.print " /* convert mrb to C (MBP112) */\n"970 end971 plist.each{ |param|972 case param.get_direction973 when :IN, :INOUT, :OUT974 type = param.get_type.get_original_type975 case type976 when IntType977 ttype = type.get_original_type978 tment = get_type_map_ent ttype979 file.print " VALCHECK_#{tment[1]}( mrb, mrb_#{param.get_name} );\n"980 file.print " #{param.get_name} = (#{param.get_type.get_type_str})mrb_#{param.get_name};\n"981 when FloatType982 file.print " #{param.get_name} = (#{param.get_type.get_type_str})mrb_#{param.get_name};\n"983 when BoolType984 file.print " #{param.get_name} = mrb_test( mrb_#{param.get_name} );\n"985 when PtrType986 ttype = type.get_type.get_original_type987 case ttype988 when StructType989 file.print " CHECK_STRUCT( #{ttype.get_name}, mrb_#{param.get_name} );\n"990 file.print " #{param.get_name} = (struct #{ttype.get_name}*)DATA_PTR(mrb_#{param.get_name});\n"991 when IntType992 when FloatType993 when BoolType994 else995 raise "cannot handle type"996 end997 when StructType998 file.print " CHECK_STRUCT( #{type.get_name}, mrb_#{param.get_name} );\n"999 file.print " #{param.get_name} = (struct #{type.get_name}*)DATA_PTR(mrb_#{param.get_name});\n"1000 else1001 raise( "canot treat class" )1002 end1003 end1004 }1005 1006 if n_ptr > 0 then1007 file.print " /* convert mrb to C for pointer types (MBP113) */\n"1008 end1009 plist.each{ |param|1010 case param.get_direction1011 when :IN, :INOUT, :OUT1012 type = param.get_type.get_original_type1013 case type1014 when IntType1015 when FloatType1016 when BoolType1017 when PtrType1018 case type.get_type.get_original_type1019 when StructType1020 when IntType1021 ptrMrb2C file, type, param1022 when FloatType1023 ptrMrb2C file, type, param1024 when BoolType1025 ptrMrb2C file, type, param1026 else1027 raise "cannot handle type"1028 end1029 when StructType1030 else1031 raise( "canot treat class" )1032 end1033 end1034 }1035 1036 end1037 1038 file.print " /* calling target (MBP120) */\n"1039 if ! b_void then1040 file.print " ret_val = "1041 else1042 file.print " "1043 end1044 delim = ""1045 file.print "cTECS_", f.get_name, "( "1046 plist.each{ |param|1047 if param.get_type.get_original_type.kind_of? StructType then1048 aster = "*"1049 else1050 aster = ""1051 end1052 file.print delim, aster, param.get_name1053 delim = ", "1054 }1055 file.print " );\n"1056 1057 file.print " /* return (MBP130) */\n"1058 case ret_type01059 when BoolType1060 file.print " return ret_val ? mrb_true_value() : mrb_false_value();\n"1061 when IntType1062 file.print " return mrb_fixnum_value( ret_val );\n"1063 when FloatType1064 file.print " return mrb_float_value( mrb, ret_val );\n"1065 when VoidType1066 file.print " return mrb_nil_value();\n"1067 else1068 raise "unknown type"1069 end1070 1071 file.print "}\n"1072 }1073 end1074 1075 def ptrMrb2C file, type, param1076 ttype = type.get_type.get_original_type1077 tment = get_type_map_ent ttype1078 tstr = tment[1]1079 =begin1080 case ttype1081 when IntType1082 bit_size = ttype.get_bit_size1083 case bit_size1084 when -1, -111085 tstr = "Char"1086 when 8, 16, 32, 641087 tstr = "Int#{bit_size}"1088 when -21089 tstr = "Short"1090 when -31091 tstr = "Int"1092 when -41093 tstr = "Long"1094 when -51095 tstr = "IntPtr"1096 else1097 raise "not handle type"1098 end1099 when FloatType1100 if ttype.get_bit_size == 32 then1101 tstr = "Float32"1102 else1103 tstr = "Double64"1104 end1105 when BoolType1106 tstr = "Bool"1107 when StructType1108 raise "not handle type 2 #{ttype}"1109 else1110 raise "not handle type 2 #{ttype}"1111 end1112 =end1113 if( param.get_size ) then1114 sz_str = param.get_size.to_s1115 elsif param.get_string then # mikan とりあえず size_is と string の同時指定 (二重ポインタ) はなし1116 sz_str = param.get_string.to_s1117 else1118 sz_str = "1"1119 end1120 # unsigned 型の場合には cast が必要1121 if ttype.get_original_type.get_type_str != param.get_type.get_type.get_type_str then1122 cast_str = "(#{param.get_type.get_type_str})"1123 else1124 cast_str = ""1125 end1126 1127 modify = ""1128 case param.get_direction1129 when :OUT, :INOUT1130 case tstr1131 when "Char", "SChar", "UChar"1132 modify = "Mod"1133 end1134 end1135 if param.is_nullable? then1136 nullable = "Nullable"1137 else1138 nullable = ""1139 end1140 1141 # file.print " CHECK_POINTER( #{tstr}, mrb_#{param.get_name}, #{sz_str} );\n"1142 # file.print " #{param.get_name} = #{cast_str}((struct #{tstr}PointerBody*)(DATA_PTR(mrb_#{param.get_name})))->buf;\n"1143 file.print " #{param.get_name} = CheckAndGet#{tstr}Pointer#{modify}#{nullable}( mrb, mrb_#{param.get_name}, #{sz_str} );\n"1144 end1145 1146 def get_celltype_name1147 @celltype_name1148 end1149 1150 #=== プラグイン引数 ignoreUnsigned1151 def set_ignoreUnsigned rhs1152 if rhs == "true" || rhs == nil then1153 @b_ignoreUnsigned = true1154 end1155 end1156 #=== プラグイン引数 include1157 def set_include rhs1158 funcs = rhs.split ','1159 funcs.each{ |rhs_func|1160 found = false1161 rhs_func.gsub!( /\s/, "" )1162 @signature.get_function_head_array.each{ |a|1163 if rhs_func.to_sym == a.get_name then1164 found = true1165 end1166 }1167 if found == false then1168 cdl_error( "MRB1009 include function '$1' not found in signagture '$2'", rhs, @signature.get_name )1169 else1170 @includes << rhs_func.to_sym1171 end1172 }1173 end1174 #=== プラグイン引数 exclude1175 def set_exclude rhs1176 funcs = rhs.split ','1177 funcs.each{ |rhs_func|1178 found = false1179 rhs_func.gsub!( /\s/, "" )1180 @signature.get_function_head_array.each{ |a|1181 if rhs_func.to_sym == a.get_name then1182 found = true1183 end1184 }1185 if found == false then1186 cdl_error( "MRB1010 exclude function '$1' not found in signagture '$2", rhs, @signature.get_name )1187 else1188 @excludes << rhs_func.to_sym1189 end1190 }1191 end1192 68 end 1193
Note:
See TracChangeset
for help on using the changeset viewer.