# -*- coding: utf-8 -*- # # TECS Generator # Generator for TOPPERS Embedded Component System # # Copyright (C) 2008-2014 by TOPPERS Project #-- # 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ # ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 # 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. # (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 # 権表示,この利用条件および下記の無保証規定が,そのままの形でソー # スコード中に含まれていること. # (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 # 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 # 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 # の無保証規定を掲載すること. # (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 # 用できない形で再配布する場合には,次のいずれかの条件を満たすこ # と. # (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 # 作権表示,この利用条件および下記の無保証規定を掲載すること. # (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに # 報告すること. # (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 # 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. # また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 # 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを # 免責すること. # # 本ソフトウェアは,無保証で提供されているものである.上記著作権者お # よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 # に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ # アの利用により直接的または間接的に生じたいかなる損害に関しても,そ # の責任を負わない. # #++ #プラグインオプション用変数 #@task_priority:: Integer #@channelCelltype:: String #@channelCellName:: String #@PPAllocatorSize:: Integer module GenTransparentMarshaler # プラグイン引数名と Proc RPCPluginArgProc = { "taskPriority" => Proc.new { |obj,rhs| obj.set_taskPriority rhs }, "channelCelltype" => Proc.new { |obj,rhs| obj.set_channelCelltype rhs }, "TDRCelltype" => Proc.new { |obj,rhs| obj.set_TDRCelltype rhs }, "channelCell" => Proc.new { |obj,rhs| obj.set_channelCellName rhs }, "PPAllocatorSize" => Proc.new { |obj,rhs| obj.set_PPAllocatorSize rhs }, } #=== プラグイン引数 taskPriority のチェック def set_taskPriority( rhs ) @task_priority = rhs end #=== プラグイン引数 channelCelltype のチェック def set_channelCelltype( rhs ) @channelCelltype = rhs.to_sym # path = [ "::", @channelCelltype ] # obj = Namespace.find( path ) nsp = NamespacePath.analyze( @channelCelltype.to_s ) obj = Namespace.find( nsp ) if ! obj.instance_of?( Celltype ) && ! obj.instance_of?( CompositeCelltype ) then cdl_error( "RPCPlugin: channeclCelltype '#{rhs}' not celltype or not found" ) end end #=== プラグイン引数 TDRCelltype のチェック def set_TDRCelltype( rhs ) @TDRCelltype = rhs.to_sym # path = [ "::", @TDRCelltype ] # obj = Namespace.find( path ) nsp = NamespacePath.analyze( @TDRCelltype.to_s ) obj = Namespace.find( nsp ) if ! obj.instance_of?( Celltype ) && ! obj.instance_of?( CompositeCelltype ) then cdl_error( "RPCPlugin: TDRCelltype '#{rhs}' not celltype or not found" ) end end #=== プラグイン引数 channelCellName のチェック def set_channelCellName( rhs ) @channelCellName = rhs if @channelCellName =~ /\A[a-zA-Z_]\w*/ then # OK else cdl_error( "RPCPlugin: channeclCellName '#{rhs}' unsuitable for identifier" ) end end #=== プラグイン引数 PPAllocatorSize のチェック def set_PPAllocatorSize( rhs ) @PPAllocatorSize = rhs end #=== marshaler のセルタイプ名を設定する def initialize_transparent_marshaler cell_name @task_priority = 8 @channelCelltype = "tDataqueueOWChannel" @TDRCelltype = "tTDR" @channelCellName = "#{cell_name}_Channel" @PPAllocatorSize = nil @marshaler_celltype_name = "tMarshaler_#{@signature.get_name}" @unmarshaler_celltype_name = "tUnmarshaler_#{@signature.get_name}" @marshaler_celltype_file_name = "#{$gen}/#{@marshaler_celltype_name}.cdl" end def gen_marshaler_celltype if @PPAllocatorSize then alloc_call_port = " call sPPAllocator cPPAllocator;\n" else alloc_call_port = "" end f = CFile.open( @marshaler_celltype_file_name, "w" ) # 同じ内容を二度書く可能性あり (AppFile は不可) # modified by ishikawa f.print <"); }; }; EOT f.close end #=== 受け口関数の本体コードを生成(頭部と末尾は別途出力) #ct_name:: Symbol (through プラグインで生成された) セルタイプ名 .Symbol として送られてくる(らしい) 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 ) # unmarshaler クラスか? if ct_name == @unmarshaler_celltype_name.to_sym then gen_ep_func_body_unmarshal( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params ) else gen_ep_func_body_marshal( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params ) end end #=== marshal コードの生成 def gen_ep_func_body_marshal( file, b_singleton, ct_name, global_ct_name, sig_name, ep_name, func_name, func_global_name, func_type, params ) b_void = false b_ret_er = false # 関数の戻り値の元の型を得る(typedef されている場合) type = func_type.get_type.get_original_type # 戻り値記憶用の変数を出力(void 型の関数では出力しない) if ! type.kind_of?( VoidType ) then if func_type.get_type.kind_of?( DefinedType ) && ( func_type.get_type.get_type_str == "ER" || func_type.get_type.get_type_str == "ER_INT" ) then file.print( " #{func_type.get_type.get_type_str} retval_ = E_OK;\n" ) b_ret_er = true else file.print( " #{func_type.get_type.get_type_str} retval_;\n" ) end else b_void = true end file.print( " ER ercd_;\n" ) file.print( " FLGPTN flgptn;\n" ) # 呼び先の signature を取り出す signature = @signature # 関数 ID (整数値) func_id = signature.get_id_from_func_name( func_name ) file.print( " int16_t func_id_ = #{func_id}; /* id of #{func_name}: #{func_id} */\n" ) file.print( " uint8_t msg[256];\n" ) # シングルトンでないか? if ! b_singleton then # singleton でなければ p_cellcb 取得コードを出力 file.print < Decl-> FuncType->ParamList param_list.each{ |par| name = par.get_name type = par.get_type if type.kind_of? ArrayType then type = type.get_type aster = "(*" aster2 = ")" else aster = "" aster2 = "" end type_str = type.get_type_str.gsub( /\bconst\b */, "" ) # "const" を外す file.printf( " %-12s %s%s%s%s;\n", type_str, aster, name, aster2, type.get_type_str_post ) } # 戻り値を受け取る変数の定義 if ! b_void then if f.is_oneway? then retval_ptr = "" # oneway の場合、受け取るが捨てられる else # =begin ishikawa modified # retval_ptr = "*" retval_ptr = "" # =end ishikawa modified end file.printf( " %-12s #{retval_ptr}retval_%s;\n", f_type.get_type.get_type_str, f_type.get_type.get_type_str_post ) end # in 方向の入出力を入力 file.print "\n /* 入力引数受取 */\n" b_get = true # unmarshal では get b_marshal = false @index = 2 print_params( param_list, file, 1, b_marshal, b_get, true, f.is_oneway? ) print_params( param_list, file, 1, b_marshal, b_get, false, f.is_oneway? ) =begin if ! b_void && ! f.is_oneway? then ret_ptr_type = PtrType.new( f_type.get_type ) print_param_nc( "retval_", ret_ptr_type, file, 2, :RETURN, nil, nil, b_get ) end =end # パケットの受信完了 # mikan 本当は、対象関数を呼出す後に実施したい.呼出しパケットの使用終わりを宣言する目的として file.print " /* パケット終わりをチェック */\n" if ! f.is_oneway? then b_continue = "true" else b_continue = "false" end =begin file.print " if( (ercd_=cTDR_receiveEOP(#{b_continue})) != E_OK )\n" file.print " goto error_reset;\n\n" =end # 対象関数を呼出す file.print " /* 対象関数の呼出し */\n" if b_void then file.print( " cServerCall_#{f_name}(" ) else file.print( " #{retval_ptr}retval_ = cServerCall_#{f_name}(" ) end delim = " " param_list.each{ |par| file.print delim delim = ", " file.print "#{par.get_name}" } file.print( " );\n" ) # 戻り値、出力引数の受取コードの生成 if ! b_void && ! f.is_oneway? then file.print " if( (ercd_ = cMessageBuffer_send(&retval_, sizeof(#{f_type.get_type.get_type_str})) != E_OK ) )\n" file.print " goto error_reset;\n" end # oneway の場合出力、戻り値が無く、受取を待たない(非同期な呼出し) if ! f.is_oneway? then file.print <