source: asp3_gr_sakura/trunk/tecsgen/tecslib/plugin/lib/GenOpaqueMarshaler.rb@ 317

Last change on this file since 317 was 317, checked in by coas-nagasima, 7 years ago

GR-SAKURA向けASP3を追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
File size: 40.4 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TECS Generator
4# Generator for TOPPERS Embedded Component System
5#
6# Copyright (C) 2008-2014 by TOPPERS Project
7#--
8# 上記著作権者
9は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
10# ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
11# 変・再é…
12å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
13# (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
14# 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15# スコード中に含まれていること.
16# (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
17# 用できる形で再é…
18å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
19å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
20# 者
21マニュアルなど)に,上記の著作権表示,この利用条件および下記
22# の無保証規定を掲載すること.
23# (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
24# 用できない形で再é…
25å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
26# と.
27# (a) 再é…
28å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
29マニュアルなど)に,上記の著
30# 作権表示,この利用条件および下記の無保証規定を掲載すること.
31# (b) 再é…
32å¸ƒã®å½¢æ…
33‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
34# 報告すること.
35# (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
36# 害からも,上記著作権者
37およびTOPPERSプロジェクトをå…
38è²¬ã™ã‚‹ã“と.
39# また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
40# 由に基づく請求からも,上記著作権者
41およびTOPPERSプロジェクトを
42# å…
43è²¬ã™ã‚‹ã“と.
44#
45# 本ソフトウェアは,無保証で提供されているものである.上記著作権者
46お
47# よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
48# に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
49# アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
50# の責任を負わない.
51#
52# $Id: GenOpaqueMarshaler.rb 2061 2014-05-31 22:15:33Z okuma-top $
53#++
54
55#== GenOpaqueMarshaler
56# OpaqueRPCPlugin, sharedOpaqueRPCPlugin å…
57±é€šã®è¦ç´ ã‚’集めたモジュール
58module GenOpaqueMarshaler
59
60 # プラグイン引数名と Proc
61 RPCPluginArgProc = {
62 "clientChannelCelltype" => Proc.new { |obj,rhs| obj.set_clientChannelCelltype rhs },
63 "serverChannelCelltype" => Proc.new { |obj,rhs| obj.set_serverChannelCelltype rhs },
64 "clientChannelCell" => Proc.new { |obj,rhs| obj.set_clientChannelCell rhs },
65 "serverChannelCell" => Proc.new { |obj,rhs| obj.set_serverChannelCell rhs },
66 "clientChannelInitializer" => Proc.new { |obj,rhs| obj.set_clientChannelInitializer rhs },
67 "serverChannelInitializer" => Proc.new { |obj,rhs| obj.set_serverChannelInitializer rhs },
68 "clientSemaphoreCelltype" => Proc.new { |obj,rhs| obj.set_clientSemaphoreCelltype rhs },
69 "clientSemaphoreInitializer" => Proc.new { |obj,rhs| obj.set_clientSemaphoreInitializer rhs },
70 "clientErrorHandler" => Proc.new { |obj,rhs| obj.set_clientErrorHandler rhs },
71 "serverErrorHandler" => Proc.new { |obj,rhs| obj.set_serverErrorHandler rhs },
72 "TDRCelltype" => Proc.new { |obj,rhs| obj.set_TDRCelltype rhs },
73 "PPAllocatorSize" => Proc.new { |obj,rhs| obj.set_PPAllocatorSize rhs },
74 "substituteAllocator" => Proc.new { |obj,rhs| obj.set_substituteAllocator rhs },
75 "noServerChannelOpenerCode" => Proc.new { |obj,rhs| obj.set_noServerChannelOpenerCode rhs },
76 "taskCelltype" => Proc.new { |obj,rhs| obj.set_taskCelltype rhs },
77 "taskPriority" => Proc.new { |obj,rhs| obj.set_taskPriority rhs },
78 "stackSize" => Proc.new { |obj,rhs| obj.set_stackSize rhs },
79 }
80
81 ##### プラグイン引数チェック関数
82
83 #=== プラグイン引数 taskPriority のチェック
84 def set_taskPriority( rhs )
85 @taskPriority = rhs
86 end
87
88 #=== プラグイン引数 serverChannelCelltype のチェック
89 def set_serverChannelCelltype( rhs )
90 @serverChannelCelltype = rhs.to_sym
91 # path = [ "::", @serverChannelCelltype ]
92 # obj = Namespace.find( path )
93 nsp = NamespacePath.analyze( @serverChannelCelltype.to_s )
94 obj = Namespace.find( nsp )
95 if ! obj.instance_of?( Celltype ) && ! obj.instance_of?( CompositeCelltype ) then
96 cdl_error( "RPCPlugin: serverChannelCelltype '#{rhs}' not celltype or not defined" )
97 end
98 end
99
100 #=== プラグイン引数 clientChannelCelltype のチェック
101 def set_clientChannelCelltype( rhs )
102 @clientChannelCelltype = rhs.to_sym
103 # path = [ "::", @clientChannelCelltype ]
104 # obj = Namespace.find( path )
105 nsp = NamespacePath.analyze( @clientChannelCelltype.to_s )
106 obj = Namespace.find( nsp )
107 if ! obj.instance_of?( Celltype ) && ! obj.instance_of?( CompositeCelltype ) then
108 cdl_error( "RPCPlugin: clientChanneclCelltype '#{rhs}' not celltype or not defined" )
109 end
110 end
111
112 #=== プラグイン引数 serverChannelCell のチェック
113 def set_serverChannelCell( rhs )
114 @serverChannelCell = rhs.to_sym
115 # ChannelCell はプラグインで生成されるため、ここではチェックできない
116 # path = [ "::", @serverChannelCell ]
117 # obj = Namespace.find( path )
118 # if ! obj.instance_of?( Cell ) then
119 # cdl_error( "RPCPlugin: serverChanneclCell '#{rhs}' not cell or not defined" )
120 # end
121 end
122
123 #=== プラグイン引数 clientChannelCell のチェック
124 def set_clientChannelCell( rhs )
125 @clientChannelCell = rhs.to_sym
126 # ChannelCell はプラグインで生成されるため、ここではチェックできない
127 # path = [ "::", @clientChannelCell ]
128 # obj = Namespace.find( path )
129 # if ! obj.instance_of?( Cell ) then
130 # cdl_error( "RPCPlugin: clientChanneclCell '#{rhs}' not cell or not defined" )
131 # end
132 end
133
134 #=== プラグイン引数 serverChannelInitializer のチェック
135 def set_serverChannelInitializer( rhs )
136 @serverChannelInitializer = rhs.to_sym
137 end
138
139 #=== プラグイン引数 clientChannelInitializer のチェック
140 def set_clientChannelInitializer( rhs )
141 @clientChannelInitializer = rhs.to_sym
142 end
143
144 #=== タスクタイプ taskCellype のチェック
145 def set_taskCelltype( rhs )
146 @taskCelltype = rhs.to_sym
147 # path = [ "::", @taskCelltype ]
148 # obj = Namespace.find( path )
149 nsp = NamespacePath.analyze( @taskCelltype.to_s )
150 obj = Namespace.find( nsp )
151 if ! obj.instance_of?( Celltype ) && ! obj.instance_of?( CompositeCelltype ) then
152 cdl_error( "RPCPlugin: taskCelltype '#{rhs}' not celltype or not defined" )
153 end
154 end
155
156 #=== タスクタイプ stack\size のチェック
157 def set_stackSize( rhs )
158 @stackSize = rhs
159 end
160
161 #=== プラグイン引数 PPAllocatorSize のチェック
162 def set_PPAllocatorSize( rhs )
163 @PPAllocatorSize = rhs
164 end
165
166 #=== プラグイン引数 TDRCelltype のチェック
167 def set_TDRCelltype( rhs )
168 @TDRCelltype = rhs.to_sym
169 # path = [ "::", @TDRCelltype ]
170 # obj = Namespace.find( path )
171 nsp = NamespacePath.analyze( @TDRCelltype.to_s )
172 obj = Namespace.find( nsp )
173 if ! obj.instance_of?( Celltype ) && ! obj.instance_of?( CompositeCelltype ) then
174 cdl_error( "RPCPlugin: TDRCelltype '#{rhs}' not celltype or not found" )
175 end
176 end
177
178 #=== プラグイン引数 substituteAllocator のチェック
179 # オプション引数が、以下の形式であることをチェック
180 # substituteAllocator(Alloc.eAlloc=>Subst.eAlloc,Alloc2.eAlloc=>Subst2.eAlloc)
181 def set_substituteAllocator( rhs )
182 #str::String : 破壊される(マッチした残りになる)。str.empty? で空になったことをチェックできる
183 #regexp::Regexp : 期待
184するトークンにマッチする正規表現。 "\A" 出始める
185 #expected::String: 期待
186するトークン、regexp が出現しなかった場合にエラーメッセージとして表示
187 def optparse (str,regexp,expected)
188 str.strip!
189 token = nil
190 res = str.sub!( regexp ){ |matched| token = matched; "" }
191 if ! token then
192 cdl_error( "syntax error in substituteAllocator option near '#{str}', expected '#{expected}'" )
193 end
194 return token
195 end
196
197 opt = rhs.dup
198 ident_rexpr = /\A(\w[\w\d]*)/
199
200 # "Alloc.eAlloc=>CAlloc.eAlloc" の形式になっていることをチェック
201 while true
202 lhs_alloc_cell = optparse( opt, ident_rexpr, "allocator cell name" )
203 break if ! lhs_alloc_cell
204
205 res = optparse( opt, /\A\./, "." )
206 break if ! res
207
208 lhs_alloc_ent = optparse( opt, ident_rexpr, "allocator cell entry name" )
209 break if ! lhs_alloc_ent
210
211 res = optparse( opt, /\A\=\>/, "=>" )
212 break if ! res
213
214 rhs_alloc_cell = optparse( opt, ident_rexpr, "allocator cell name" )
215 break if ! rhs_alloc_cell
216
217 res = optparse( opt, /\A\./, "." )
218 break if ! res
219
220 rhs_alloc_ent = optparse( opt, ident_rexpr, "allocator cell entry name" )
221 break if ! rhs_alloc_ent
222
223# ここでは、右辺のチェックはできない。右辺のセルは前方参ç…
224§ã¨ãªã‚‹
225# path = [ "::", rhs_alloc_cell.to_sym ] # mikan namespace
226# obj = Namespace.find( path )
227# if ! obj.instance_of?( Cell ) || obj.get_region.get_path_string != @clientRegion then
228# cdl_error( "RPCPlugin: substituteAllocator: '#{rhs_alloc_cell}' not cell or not found in client region" )
229# else
230# ct = obj.get_celltype
231# if ct # nil なら既にエラー
232# ent = ct.find rhs_alloc_ent
233# if ! ent.instance_of? Port || ent.get_port_type != :ENTRY || ent.get_signature == nil || ! ent.get_signature.is_allocator?
234# cdl_error( "RPCPlugin: substituteAllocator: '#{rhs_alloc_cell}.#{rhs_alloc_ent}' not entry port or not have alllocator signature" )
235# end
236# end
237# end
238
239 @substituteAllocator[ "#{lhs_alloc_cell}.#{lhs_alloc_ent}".to_sym ] =
240 [ lhs_alloc_cell, lhs_alloc_ent, rhs_alloc_cell, rhs_alloc_ent ]
241
242# p "substituteAllocator: #{lhs_alloc_cell}.#{lhs_alloc_ent}=>#{rhs_alloc_cell}.#{rhs_alloc_ent}"
243
244 break if opt.empty?
245
246 res = optparse( opt, /\A\,/, "," )
247 break if ! res
248 end
249
250 end
251
252 #=== プラグイン引数 noServerChannelOpenerCode のチェック
253 def set_noServerChannelOpenerCode( rhs )
254 rhs = rhs.to_sym
255 if rhs == :true
256 @noServerChannelOpenerCode = true
257 elsif rhs == :false then
258 @noServerChannelOpenerCode = false
259 else
260 cdl_error( "RPCPlugin: specify true or false for noServerChannelOpenerCode" )
261 end
262 end
263
264 #=== プラグイン引数 clientSemaphoreCelltype のチェック
265 def set_clientSemaphoreCelltype rhs
266 @semaphoreCelltype = rhs.to_sym
267 nsp = NamespacePath.analyze( @semaphoreCelltype.to_s )
268 obj = Namespace.find( nsp )
269 if ! obj.instance_of?( Celltype ) && ! obj.instance_of?( CompositeCelltype ) then
270 cdl_error( "RPCPlugin: clientSemaphoreCelltype '#{rhs}' not celltype or not defined" )
271 end
272 end
273
274 #=== プラグイン引数 clientSemaphoreInitializer のチェック
275 def set_clientSemaphoreInitializer rhs
276 @semaphoreInitializer = rhs.to_sym
277 end
278
279 #=== プラグイン引数 clientErrorHandler のチェック
280 def set_clientErrorHandler rhs
281 @clientErrorHandler = rhs.to_sym
282 end
283
284 #=== プラグイン引数 serverErrorHandler のチェック
285 def set_serverErrorHandler rhs
286 @serverErrorHandler = rhs.to_sym
287 end
288
289
290 #=== セルの名前を得る
291 # ThroughPlugin::get_cell_name plugin.rb をオーバーライド
292 def get_cell_name
293 @cell_name
294 # @clientChannelCell
295 end
296
297 #=== marshaler のセルタイプ名を設定する
298 def initialize_opaque_marshaler
299
300 # オプション設定される変数のデフォルトを設定
301 @taskPriority = 11
302 @stackSize = 4096
303 @serverChannelCelltype = :"tSocketServer"
304 @clientChannelCelltype = :"tSocketClient"
305 @serverChannelCell = :"#{@cell_name}Server"
306 @clientChannelCell = :"#{@cell_name}Client"
307 @serverChannelInitializer = subst_name( "portNo=8931+$count$;" ).to_sym
308 @clientChannelInitializer = subst_name( "portNo=8931+$count$; serverAddr=\"127.0.0.1\"; " ).to_sym
309 @taskCelltype = :"tTask"
310 @PPAllocatorSize = nil
311 # @TDRCelltype = :"tTDR" # "tNBOTDR" に変更の予定
312 @TDRCelltype = :"tNBOTDR"
313 @substituteAllocator = {}
314 @noServerChannelOpenerCode = false
315 @semaphoreCelltype = :"tSemaphore"
316 @semaphoreInitializer = :"count = 1; attribute = C_EXP( \"TA_NULL\" ); ";
317 @clientErrorHandler = nil
318 @serverErrorHandler = nil
319 @b_genOpener = false
320 @taskMainCelltype = :"tRPCDedicatedTaskMain"
321
322 @marshaler_celltype_name = :"tOpaqueMarshaler_#{@signature.get_global_name}"
323 @unmarshaler_celltype_name = :"tOpaqueUnmarshaler_#{@signature.get_global_name}"
324 @marshaler_celltype_file_name = "#{$gen}/#{@marshaler_celltype_name}.cdl"
325
326 # signature で対応できないものをチェック
327 @signature.each_param{ |func_decl, param_decl|
328 if param_decl.get_direction == :OUT then
329 if param_decl.get_count && ! param_decl.get_size then
330 cdl_error( "#{@signature.get_namespace_path}.#{func_decl.get_name}.#{param_decl.get_name}: size_is must be specified for out parameter of Opaque RPC" )
331 end
332 if param_decl.get_string == -1 then
333 cdl_error( "#{@signature.get_namespace_path}.#{func_decl.get_name}.#{param_decl.get_name}: string length must be specified for out parameter of Opaque RPC" )
334 end
335 end
336 }
337 end
338
339 #=== GenOpaqueMarshaler# Opener Code の生成時のチェック
340 def check_opener_code
341 # サーバーチャンネルセルタイプが entry sServerChannelOpener eOpener を持つかどうかをチェック
342 # mikan entry か (call でないか) をチェックしていない
343 # scct = Namespace.find ["::", @serverChannelCelltype] # mikan namespace
344 nsp = NamespacePath.analyze( @serverChannelCelltype.to_s )
345 scct = Namespace.find nsp
346 if scct then
347 obj = scct.find( :"eOpener" )
348 if obj.instance_of? Port then
349 if obj.get_signature.get_name.to_sym == :sServerChannelOpener then
350 if @noServerChannelOpenerCode == false then
351 @b_genOpener = true
352 @taskMainCelltype = :"tRPCDedicatedTaskMainWithOpener"
353 end
354 end
355 end
356 end
357 if @noServerChannelOpenerCode == false && @taskMainCelltype != :"tRPCDedicatedTaskMainWithOpener" then
358 cdl_warning( "O9999 ServerChannelOpener code not generated, not found 'entry sServerChannelOpener eOpener'")
359 end
360 end
361
362 #=== GenOpaqueMarshaler# PPAllocator の必
363要性をチェックする
364 def check_PPAllocator
365 if @signature.need_PPAllocator?(true) then
366 if @PPAllocatorSize == nil then
367 cdl_error( "PPAllocatorSize must be speicified for size_is array" )
368 end
369 end
370 end
371
372 #####
373
374 def gen_marshaler_celltype
375 f = CFile.open( @marshaler_celltype_file_name, "w" )
376 # 同じ内
377容を二度書く可能性あり (AppFile は不可)
378
379 if @PPAllocatorSize then
380 alloc_call_port = " call sPPAllocator cPPAllocator;\n"
381 else
382 alloc_call_port = ""
383 end
384
385 f.print <<EOT
386
387celltype #{@marshaler_celltype_name} {
388 entry #{@signature.get_namespace_path} eClientEntry;
389 call sTDR cTDR;
390 [optional]
391 call sSemaphore cLockChannel;
392 [optional]
393 call sRPCErrorHandler cErrorHandler;
394};
395celltype #{@unmarshaler_celltype_name} {
396 call #{@signature.get_namespace_path} cServerCall;
397 call sTDR cTDR;
398 [optional]
399 call sRPCErrorHandler cErrorHandler;
400 entry sUnmarshalerMain eService;
401#{alloc_call_port}};
402EOT
403 f.close
404 end
405
406 #=== 受け口関数の本体コードを生成(頭部と末尾は別途出力)
407 #ct_name:: Symbol (through プラグインで生成された) セルタイプ名 .Symbol として送られてくる(らしい)
408 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 )
409
410 # unmarshaler クラスか?
411 if ct_name == @unmarshaler_celltype_name.to_sym then
412 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 )
413 else
414 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 )
415 end
416 end
417
418 #=== marshal コードの生成
419 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 )
420
421 b_void = false
422 b_ret_er = false
423
424 # 関数の戻り値のå…
425ƒã®åž‹ã‚’å¾—ã‚‹(typedef されている場合)
426 type = func_type.get_type.get_original_type
427
428 # 戻り値記憶用の変数を出力(void 型の関数では出力しない)
429 if ! type.is_void? then
430 file.print( "\t#{func_type.get_type.get_type_str}\t\tretval_;\n" )
431 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
432 b_ret_er = true
433 end
434 else
435 b_void = true
436 end
437
438 file.print( "\tER\t\tercd_;\n" )
439 file.print( "\tint16_t\tstate_;\n" )
440
441 # 関数 ID (整数値)
442 func_id = "FUNCID_#{@signature.get_global_name}_#{func_name}".upcase
443 fid = @signature.get_id_from_func_name( func_name )
444 file.print( "\tint16_t\tfunc_id_ = #{func_id}; /* (id of '#{func_name}') = #{fid}*/\n" )
445
446 # シングルトンでないか?
447 if ! b_singleton then
448
449 # singleton でなければ p_cellcb 取得コードを出力
450 file.print <<EOT
451 #{ct_name}_CB *p_cellcb;
452
453 if( VALID_IDX( idx ) ){
454 p_cellcb = GET_CELLCB(idx);
455EOT
456
457 # エラーを返すか?
458 if b_ret_er then
459 file.print <<EOT
460 }else{
461 return ERCD( E_RPC, E_ID );
462 }
463EOT
464 else
465 file.print <<EOT
466 }else{
467 /* エラー処理コードをここに記述 */
468 }
469
470EOT
471 end
472 end
473
474 if func_type.has_receive? then
475 file.print " /* initialize receive parameters */\n"
476 params.each{ |param|
477 if param.get_direction == :RECEIVE then
478 file.print " *#{param.get_name} = 0;\n"
479 end
480 }
481 end
482
483 # channel lock コード
484 file.print <<EOT
485
486 /* Channel Lock */
487 SET_RPC_STATE( state_, RPCSTATE_CLIENT_GET_SEM );
488 if( is_cLockChannel_joined() )
489 cLockChannel_wait();
490EOT
491
492 # SOP を送信
493 file.print " /* SOPの送出 */\n"
494 file.print " SET_RPC_STATE( state_, RPCSTATE_CLIENT_SEND_SOP );\n"
495 file.print " if( ( ercd_ = cTDR_sendSOP( true ) ) != E_OK )\n"
496 file.print " goto error_reset;\n"
497
498 # func_id を送信
499 file.print " /* 関数 id の送出 */\n"
500 file.print " if( ( ercd_ = cTDR_putInt16( func_id_ ) ) != E_OK )\n"
501 file.print " goto error_reset;\n"
502
503 # p "celltype_name, sig_name, func_name, func_global_name"
504 # p "#{ct_name}, #{sig_name}, #{func_name}, #{func_global_name}"
505
506 b_get = false # marshal なら put
507 b_marshal = true # marshal
508
509 # in 方向のå…
510¥å‡ºåŠ›ã‚’出力
511 if func_type.has_inward? then
512 file.print " /* å…
513¥åŠ›å¼•æ•°é€å‡º */\n"
514 file.print " SET_RPC_STATE( state_, RPCSTATE_CLIENT_SEND_BODY );\n"
515 print_params( params, file, 1, b_marshal, b_get, true, "eClientEntry", func_name )
516 print_params( params, file, 1, b_marshal, b_get, false, "eClientEntry", func_name )
517 end
518 print_out_nullable( params, file, 1, b_marshal );
519
520 if ! func_type.is_oneway? then
521 b_continue = "true"
522 else
523 b_continue = "false"
524 end
525 file.print " /* EOPの送出(パケットの掃きだし) */\n"
526 file.print " SET_RPC_STATE( state_, RPCSTATE_CLIENT_SEND_EOP );\n"
527 file.print " if( (ercd_=cTDR_sendEOP(#{b_continue})) != E_OK )\n"
528 file.print " goto error_reset;\n\n"
529
530 # send のメモリをデアロケート
531 if func_type.has_send? then
532 file.print " /* dealloc send parameter while executing */\n"
533 file.print " SET_RPC_STATE( state_, RPCSTATE_CLIENT_EXEC );\n"
534 dir = :SEND; nest = 1; dealloc_cp = "eClientEntry_#{func_name}"
535 dealloc_for_params( params, file, nest, dir, dealloc_cp )
536 file.print "\n"
537 end
538
539 if ! func_type.is_oneway? then
540
541 file.print " /* パケットの始まりをチェック */\n"
542 file.print " SET_RPC_STATE( state_, RPCSTATE_CLIENT_RECV_SOP );\n"
543 file.print " if( (ercd_=cTDR_receiveSOP( true )) != E_OK )\n"
544 file.print " goto error_reset;\n"
545
546 b_get = true # marshaler は get
547 file.print " /* 戻り値の受け取り */\n"
548 print_param( "retval_", func_type.get_type, file, 1, :RETURN, nil, nil, b_marshal, b_get )
549
550 if func_type.has_outward? then
551 if b_ret_er then
552 indent_level = 2
553 file.print " if( MERCD( retval_ ) != E_RPC ){\n"
554 else
555 indent_level = 1
556 end
557 indent = " " * indent_level
558
559 file.print "#{indent}/* 出力値の受け取り */\n"
560 file.print "#{indent}SET_RPC_STATE( state_, RPCSTATE_CLIENT_RECV_BODY );\n"
561 print_params( params, file, indent_level, b_marshal, b_get, true, "eClientEntry", func_name )
562 print_params( params, file, indent_level, b_marshal, b_get, false, "eClientEntry", func_name )
563
564 if b_ret_er then
565 file.print " }\n"
566 end
567 end
568
569 file.print "\n /* パケットの終わりをチェック */\n"
570 file.print " SET_RPC_STATE( state_, RPCSTATE_CLIENT_RECV_EOP );\n"
571 file.print " if( (ercd_=cTDR_receiveEOP(false)) != E_OK )\n" # b_continue = false
572 file.print " goto error_reset;\n"
573
574 end # ! func_type.is_oneway?
575
576 # channel lock コード
577 file.print <<EOT
578 /* Channel Unlock */
579 SET_RPC_STATE( state_, RPCSTATE_CLIENT_RELEASE_SEM );
580 if( is_cLockChannel_joined() )
581 cLockChannel_signal();
582EOT
583
584 if( b_void == false )then
585 # 呼びå…
586ƒã«æˆ»ã‚Šå€¤ã‚’リターン
587 file.print( " return retval_;\n" )
588 else
589 file.print( " return;\n" )
590 end
591
592 file.print <<EOT
593
594error_reset:
595EOT
596 # send のメモリをデアロケート
597 if func_type.has_send? then
598 file.print " /* dealloc send parameter */\n"
599 file.print " if( state_ < RPCSTATE_CLIENT_EXEC ){\n"
600 dir = :SEND; nest = 2; dealloc_cp = "eClientEntry_#{func_name}"
601 dealloc_for_params( params, file, nest, dir, dealloc_cp )
602 file.print " }\n"
603 end
604
605 # receive のメモリをデアロケート
606 if func_type.has_receive? then
607 file.print( " /* receive parameter */\n" )
608 dir = :RECEIVE; nest = 1; dealloc_cp = "eClientEntry_#{func_name}"
609 dealloc_for_params( params, file, nest, dir, dealloc_cp, true )
610 end
611
612 file.print <<EOT
613 if( MERCD( ercd_ ) != E_RESET )
614 (void)cTDR_reset();
615EOT
616
617 # channel lock コード
618 file.print <<EOT
619 /* Channel Unlock */
620 if( is_cLockChannel_joined() )
621 cLockChannel_signal();
622
623 if( ercd_ != E_OK && is_cErrorHandler_joined() )
624 cErrorHandler_errorOccured( func_id_, ercd_, state_ );
625EOT
626
627 if( b_ret_er != false )then
628 # 呼びå…
629ƒã«æˆ»ã‚Šå€¤ã‚’リターン
630 file.print( " return ERCD( E_RPC, MERCD( ercd_ ) );\n" )
631 else
632 file.print( " return;\n" )
633 end
634
635 end
636
637 #=== unmarshal コードの生成
638 def 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 )
639
640 b_ret_er = true
641
642 # func_id を得るコードを生成
643 file.print <<EOT
644
645 int16_t func_id_;
646 ER ercd_ = E_OK;
647 int16_t state_;
648
649 #{ct_name}_CB *p_cellcb;
650
651 if( VALID_IDX( idx ) ){
652 p_cellcb = GET_CELLCB(idx);
653EOT
654
655 if b_ret_er then
656 file.print <<EOT
657 }else{
658 return;
659 }
660EOT
661 else
662 file.print <<EOT
663 }else{
664 /* エラー処理コードをここに記述 */
665 }
666EOT
667 end
668
669 file.print <<EOT
670
671#ifdef RPC_DEBUG
672 syslog(LOG_INFO, "Entering RPC service loop" );
673#endif
674
675 /* SOPのチェック */
676 SET_RPC_STATE( state_, RPCSTATE_SERVER_RECV_SOP );
677 if( (ercd_=cTDR_receiveSOP( false )) != E_OK )
678 goto error_reset;
679 /* func_id の取得 */
680 if( (ercd_=cTDR_getInt16( &func_id_ )) != E_OK )
681 goto error_reset;
682
683#ifdef RPC_DEBUG
684 syslog(LOG_INFO, "unmarshaler task: func_id: %d", func_id_ );
685#endif
686 switch( func_id_ ){
687EOT
688
689 # signature に含まれる すべての関数について
690 @signature.get_function_head_array.each { |f|
691 f_name = f.get_name
692 f_type = f.get_declarator.get_type
693 func_id = "FUNCID_#{@signature.get_global_name}_#{f_name}".upcase
694 fid = @signature.get_id_from_func_name( f_name )
695
696 file.print " case #{func_id}: /* (id of '#{f_name}') = #{fid} */ \n"
697 file.print " ercd_ = tOpaqueUnmarshaler_#{@signature.get_global_name}_#{f_name}( p_cellcb, &state_ );\n"
698 file.print " break;\n"
699
700 } #
701
702 if @PPAllocatorSize then
703 ppallocator_dealloc_str = " /* PPAllocator のすべてを解放 */\n cPPAllocator_dealloc_all();"
704 else
705 ppallocator_dealloc_str = ""
706 end
707
708 file.print <<EOT
709 default:
710 syslog(LOG_INFO, "unmarshaler task: ERROR: unknown func_id: %d", func_id_ );
711 ercd_ = E_ID;
712 };
713error_reset: /* OK cases also come here */
714#{ppallocator_dealloc_str}
715 if( ercd_ == E_OK )
716 return ercd_;
717 if( is_cErrorHandler_joined() )
718 ercd_ = cErrorHandler_errorOccured( func_id_, ercd_, state_ );
719 if( MERCD( ercd_ ) != E_RESET )
720 (void)cTDR_reset();
721 return ercd_;
722EOT
723
724 end
725
726 #=== PREAMBLE 部のコード生成
727 # アンマーシャラセルタイプの場合、アンマーシャラ関数のプロトタイプ宣言を生成
728 def gen_preamble file, b_singleton, ct_name, global_name
729 if ct_name != @unmarshaler_celltype_name.to_sym then
730 return
731 end
732
733 # string.h の include (memset, strlen のため)
734 file.print "/* header file (strlen, memset) */\n"
735 file.print "#include\t<string.h>\n\n"
736
737 file.print "/* アンマーシャラ関数のプロトタイプ宣言 */\n"
738 # signature に含まれる すべての関数について
739 @signature.get_function_head_array.each { |f|
740 f_name = f.get_name
741 f_type = f.get_declarator.get_type
742 id = @signature.get_id_from_func_name( f_name )
743 file.print "static ER tOpaqueUnmarshaler_#{@signature.get_global_name}_#{f_name}(CELLCB *p_cellcb, int16_t *state);\t/* func_id: #{id} */\n"
744 }
745 file.print "\n"
746 end
747
748 #=== POSTAMBLE 部のコード生成
749 # アンマーシャラセルタイプの場合、個々
750のアンマーシャラ関数の生成
751 def gen_postamble file, b_singleton, ct_name, global_name
752 if ct_name != @unmarshaler_celltype_name.to_sym then
753 return
754 end
755
756 file.print "\n/*** アンマーシャラ関数 ***/\n\n"
757 @signature.get_function_head_array.each { |f|
758 f_name = f.get_name
759 f_type = f.get_declarator.get_type
760 id = @signature.get_id_from_func_name( f_name )
761
762 # 関数は返り値を持つか?
763 b_ret_er = false
764 init_retval = ""
765 if f_type.get_type.is_void? then
766 b_void = true
767 else
768 b_void = false
769 if f_type.get_type.get_type_str == "ER" || f_type.get_type.get_type_str == "ER_INT" then
770 b_ret_er = true
771 init_retval = " = E_OK"
772 end
773 end
774
775 file.print <<EOT
776/*
777 * name: #{f_name}
778 * func_id: #{id}
779 */
780EOT
781 file.print "static ER\n"
782 file.print "tOpaqueUnmarshaler_#{@signature.get_global_name}_#{f_name}(CELLCB *p_cellcb, int16_t *state_)\t\t\n"
783 file.print "{\n"
784 file.print " ER ercd_;\n"
785
786 # 引数を受取る変数の定義
787 params = f.get_declarator.get_type.get_paramlist.get_items
788 # FuncHead-> Decl-> FuncType->ParamList
789 params.each{ |par|
790 name = par.get_name
791 type = par.get_type.get_original_type
792
793 dir = par.get_direction
794 if( dir == :RECEIVE )then
795 # type は PtrType で、それを取り除いた型
796 type = type.get_type
797 end
798 if( dir == :SEND || dir == :RECEIVE )then
799 init = " = 0"
800 else
801 init = ""
802 end
803
804 if type.kind_of? ArrayType then
805 type = type.get_type
806 aster = "(*"
807 aster2 = ")"
808 else
809 aster = ""
810 aster2 = ""
811 end
812
813 type_str = type.get_type_str.gsub( /\bconst\b */, "" ) # "const" を外す
814 file.printf( " %-12s %s%s%s%s%s;\n", type_str, aster, name, aster2, type.get_type_str_post, init )
815
816 if dir == :OUT && type.is_nullable? then
817 file.print( " int8_t\tb_#{name}_null_;\n" )
818 end
819 }
820
821 if ! b_void then
822 file.printf( " %-12s retval_%s%s;\n", f_type.get_type.get_type_str, f_type.get_type.get_type_str_post, init_retval )
823 end
824
825 # in 方向のå…
826¥å‡ºåŠ›ã‚’å…
827¥åŠ›
828 file.print "\n /* å…
829¥åŠ›å¼•æ•°å—取 */\n"
830 file.print " SET_RPC_STATE( *state_, RPCSTATE_SERVER_RECV_BODY );\n"
831 b_get = true # unmarshal では get
832 b_marshal = false
833 print_params( params, file, 1, b_marshal, b_get, true, "cServerCall", f_name )
834 print_params( params, file, 1, b_marshal, b_get, false, "cServerCall", f_name )
835 print_out_nullable( params, file, 1, b_marshal );
836
837
838 # パケットの受信完了
839 file.print " /* パケット終わりをチェック */\n"
840 file.print " SET_RPC_STATE( *state_, RPCSTATE_SERVER_RECV_EOP );\n"
841 if ! f_type.is_oneway? then
842 b_continue = "true"
843 else
844 b_continue = "false"
845 end
846 file.print " if( (ercd_=cTDR_receiveEOP(#{b_continue})) != E_OK )\n"
847 file.print " goto error_reset;\n\n"
848
849 # out のメモリをアロケート
850 dir = :OUT; alloc_cp = "cPPAllocator_alloc"; alloc_cp_extra = nil; nest = 1
851 alloc_for_out_params( params, file, nest, dir, alloc_cp, alloc_cp_extra )
852
853 # 対象関数を呼出す
854 file.print " /* 対象関数の呼出し */\n"
855 file.print " SET_RPC_STATE( *state_, RPCSTATE_SERVER_EXEC );\n"
856 if b_void then
857 file.print( " cServerCall_#{f_name}(" )
858 else
859 file.print( " retval_ = cServerCall_#{f_name}(" )
860 end
861
862 delim = " "
863 params.each{ |par|
864 file.print delim
865 delim = ", "
866 if par.get_direction == :RECEIVE then
867 file.print "&"
868 end
869 file.print par.get_name
870 }
871 file.print( " );\n" )
872
873 # 戻り値、出力引数の受取コードの生成
874
875 # oneway の場合出力、戻り値が無く、受取を待
876たない(非同期な呼出し)
877 if ! f.is_oneway? then
878
879 file.print "\n /* SOPの送出 */\n"
880 file.print " SET_RPC_STATE( *state_, RPCSTATE_SERVER_SEND_SOP );\n"
881
882 file.print " if( ( ercd_ = cTDR_sendSOP( false ) ) != E_OK )\n"
883 file.print " goto error_reset;\n"
884
885 b_get = false # unmarshaler は put
886 if( ! b_void )then
887 file.print " /* 戻り値の送出 */\n"
888 print_param( "retval_", f_type.get_type, file, 1, :RETURN, nil, nil, b_marshal, b_get )
889 end
890
891 if f_type.has_outward? then
892 if b_ret_er then
893 indent_level = 2
894 file.print " if( MERCD( retval_ ) != E_RPC ){\n"
895 else
896 indent_level = 1
897 end
898 indent = " " * indent_level
899
900 file.print "#{indent}/* 出力値の送出 */\n"
901 file.print "#{indent}SET_RPC_STATE( *state_, RPCSTATE_SERVER_SEND_BODY );\n"
902 print_params( params, file, indent_level, b_marshal, b_get, true, "cServerCall", f_name )
903 print_params( params, file, indent_level, b_marshal, b_get, false, "cServerCall", f_name )
904
905 # receive のメモリをデアロケート
906 if f_type.has_receive? then
907 file.print "#{indent}/* dealloc receive parameter */\n"
908 dir = :RECEIVE; dealloc_cp = "cServerCall_#{f_name}"
909 dealloc_for_params( params, file, indent_level, dir, dealloc_cp )
910 end
911
912 if b_ret_er then
913 file.print " }\n"
914 end
915 end
916
917 file.print " /* パケットの終わり(掃きだし) */\n"
918 file.print " SET_RPC_STATE( *state_, RPCSTATE_SERVER_SEND_EOP );\n"
919 file.print " if( (ercd_=cTDR_sendEOP(false)) != E_OK )\n" # b_continue = false
920 file.print " goto error_reset;\n"
921 end # ! f.is_oneway?
922
923 file.print " return E_OK;\n"
924 file.print <<EOT
925
926error_reset:
927EOT
928 # send のリセット用デアロケート
929 if f_type.has_send? then
930 file.print " /* dealloc send parameter */\n"
931 file.print " if( *state_ < RPCSTATE_SERVER_EXEC ){\n"
932 dir = :SEND; indent_level = 2; dealloc_cp = "cServerCall_#{f_name}"
933 dealloc_for_params( params, file, indent_level, dir, dealloc_cp, true )
934 file.print " }\n"
935 end
936
937 # receive のメモリをデアロケート
938 if f_type.has_receive? && b_ret_er then
939 file.print " /* dealloc receive parameter */\n"
940 file.print " if( MERCD( retval_ ) != E_RPC ){\n"
941 dir = :RECEIVE; indent_level = 2; dealloc_cp = "cServerCall_#{f_name}"
942 dealloc_for_params( params, file, indent_level, dir, dealloc_cp )
943 file.print " }\n"
944 end
945
946 file.print " return ERCD( E_RPC, MERCD( ercd_ ) );\n"
947 file.print "}\n\n"
948
949 # ここ(個々
950の関数)ではエラーハンドラーは呼び出さない。呼びå…
951ƒï¼ˆã‚µãƒ¼ãƒãƒ¼ã®ãƒ¡ã‚¤ãƒ³é–¢æ•°ï¼‰ã§å‘¼ã³å‡ºã™ã€‚
952 }
953 end
954
955
956 #b_marshal:: bool
957 #b_get:: bool
958 # b_marshal = true && b_get == false : マーシャラでå…
959¥åŠ›å¼•æ•°é€å‡º
960 # b_marshal = true && b_get == true : マーシャラで出力引数受取
961 # b_marshal = false && b_get == false : アンマーシャラでå…
962¥åŠ›å¼•æ•°å—取
963 # b_marshal = false && b_get == true : アンマーシャラで出力引数送出
964 #b_referenced:: size_is, count_is, string で参ç…
965§ã•ã‚Œã¦ã„るものを出力
966 def print_params( params, file, nest, b_marshal, b_get, b_referenced, port_name, func_name )
967 params.each{ |param|
968# p "#{param.get_name}: b_marshal: #{b_marshal} b_get: #{b_get}"
969 if ! ( b_referenced == param.is_referenced? ) then
970 next
971 end
972
973 dir = param.get_direction
974 if( b_get == false && b_marshal == true || b_get == true && b_marshal == false )then
975 case dir
976 when :IN, :INOUT
977 alloc_cp = "cPPAllocator_alloc"
978 alloc_cp_extra = nil
979 print_param( param.get_name, param.get_type, file, nest, dir, nil, nil, b_marshal, b_get, alloc_cp, alloc_cp_extra )
980 when :SEND
981 alloc_cp = "#{port_name}_#{func_name}_#{param.get_name}_alloc"
982 alloc_cp_extra = nil
983 print_param( param.get_name, param.get_type, file, nest, dir, nil, nil, b_marshal, b_get, alloc_cp, alloc_cp_extra )
984 end
985 else
986 case dir
987 when :OUT, :INOUT
988 alloc_cp = nil # inout の b_get==true&&b_marsha==true のときアロケータコードは不用
989 alloc_cp_extra = nil
990 print_param( param.get_name, param.get_type, file, nest, dir, nil, nil, b_marshal, b_get, alloc_cp, alloc_cp_extra )
991 when :RECEIVE
992 alloc_cp = "#{port_name}_#{func_name}_#{param.get_name}_alloc"
993 alloc_cp_extra = nil
994 if b_get then
995 outer = "(*" # マーシャラ側では、ポインタが (send と比べ) 一つ多い
996 outer2 = ")"
997 else
998 outer = nil # アンマーシャラ側では、ポインタが一つ外されている
999 outer2 = nil
1000 end
1001 type = param.get_type.get_referto
1002 print_param( param.get_name, type, file, nest, dir, outer, outer2, b_marshal, b_get, alloc_cp, alloc_cp_extra )
1003 end
1004 end
1005 }
1006 end
1007
1008 #=== アロケータコードを生成 (out のアンマーシャラ用)
1009 def alloc_for_out_params( params, file, nest, dir, alloc_cp, alloc_cp_extra )
1010 params.each{ |param|
1011 dir = param.get_direction
1012 if dir == :OUT then
1013 alloc_for_out_param( param.get_name, param.get_type, file, nest, nil, nil, alloc_cp, alloc_cp_extra )
1014 end
1015 }
1016 end
1017
1018 #=== アロケータコードを生成 (out のアンマーシャラ用個別パラメータの生成)
1019 def alloc_for_out_param( name, type, file, nest, outer, outer2, alloc_cp, alloc_cp_extra )
1020 org_type = type.get_original_type
1021 if org_type.is_nullable? then
1022 indent = "\t" * nest
1023 file.print "#{indent}if( ! b_#{name}_null_ ){\n"
1024 nest += 1
1025 end
1026 case org_type
1027 when PtrType
1028 indent = "\t" * nest
1029 count = type.get_count; size = type.get_size; string = type.get_string
1030 if count || size || string then
1031 loop_counter_type = IntType.new(16) # mikan 方を size_is, count_is の引数の型とする
1032 if count then
1033 len = type.get_count.to_s
1034 elsif size then
1035 len = type.get_size.to_s
1036 elsif string then
1037 if type.get_string.instance_of? Expression then
1038 len = type.get_string.to_s
1039 else
1040 raise "unsuscripted string used for out parameter #{name}"
1041 end
1042 end
1043
1044 # size_is に max 指定がある場合、length が max を超
1045えているかチェックするコードを生成
1046 if org_type.get_max != nil && string == nil then
1047 file.print "#{indent}if( #{len} > #{type.get_max} ){\t/* GenOpaqueMarshaler max check 2 */\n"
1048 file.print "#{indent} ercd_ = E_PAR;\n"
1049 file.print "#{indent} goto error_reset;\n"
1050 file.print "#{indent}}\n"
1051 end
1052
1053 file.print <<EOT
1054#{indent}if((ercd_=#{alloc_cp}(sizeof(#{type.get_type.get_type_str}#{type.get_type.get_type_str_post})*#{len},(void **)&#{outer}#{name}#{outer2}#{alloc_cp_extra}))!=E_OK)\t/* GenOpaqueMarshaler 1 */
1055#{indent} goto error_reset;
1056EOT
1057
1058 if type.get_type.kind_of? PtrType then
1059 file.print "#{indent}{\n"
1060 file.print "#{indent} #{loop_counter_type.get_type_str} i__#{nest}, length__#{nest} = #{len};\n"
1061 file.print "#{indent} for( i__#{nest} = 0; i__#{nest} < length__#{nest}; i__#{nest}++ ){\n"
1062 alloc_for_out_param( name, type.get_type, file, nest + 2, outer, "#{outer2}[i__#{nest}]", alloc_cp, alloc_cp_extra )
1063 file.print "#{indent} }\n"
1064 file.print "#{indent}}\n"
1065 end
1066
1067 else
1068 file.print <<EOT
1069#{indent}if((ercd_=#{alloc_cp}(sizeof(#{type.get_type.get_type_str}#{type.get_type.get_type_str_post}),(void **)&#{outer}#{name}#{outer2}#{alloc_cp_extra}))!=E_OK)\t/* GenOpaqueMarshaler 2 */
1070#{indent} goto error_reset;
1071EOT
1072 end
1073 end
1074 if org_type.is_nullable? then
1075 nest -= 1
1076 indent = "\t" * nest
1077 file.print "#{indent}} else {\n"
1078 file.print "#{indent} #{name} = NULL;\n"
1079 file.print "#{indent}}\n"
1080 nest += 1
1081 end
1082 end
1083
1084 #=== 引数の一括デアロケートコードの生成
1085 # send:マーシャラの最後、receive:アンマーシャラの最後で一括して引数をデアロケートする
1086 def dealloc_for_params( params, file, nest, dir, dealloc_cp, b_reset = false )
1087 if b_reset then
1088 reset_str = "_reset"
1089 else
1090 reset_str = ""
1091 end
1092
1093 params.each{ |param|
1094 if dir == param.get_direction then
1095 indent = "\t" * nest
1096 type = param.get_type.get_original_type
1097 aster = ""
1098 if dir == :RECEIVE then
1099 type = type.get_type.get_original_type # ポインタを一つ外す
1100 if b_reset then
1101 aster = "*"
1102 end
1103 end
1104 count = type.get_count; size = type.get_size
1105 if (size || count) && type.get_type.has_pointer? then
1106 if count then
1107 len = ", #{type.get_count.to_s}"
1108 elsif size then
1109 len = ", #{type.get_size.to_s}"
1110 end
1111 else
1112 len = ""
1113 end
1114 cp = "#{dealloc_cp}_#{param.get_name}_dealloc#{reset_str}".upcase
1115 file.print "#{indent}#{cp}(#{aster}#{param.get_name}#{len});\n"
1116 end
1117 }
1118 end
1119
1120 #== out で nullable な引数の情
1121報を渡す
1122 # out nullable の場合、in, send, receive のように、値を渡す直前ではなく、呼出し時に渡す
1123 def print_out_nullable( params, file, nest, b_marshal );
1124 indent = "\t" * nest
1125 params.each{ |param|
1126 next if param.get_direction != :OUT
1127 next if ! param.is_nullable?
1128 if b_marshal then
1129 file.print "#{indent}if( (ercd_=cTDR_putInt8( (int8_t)(#{param.get_name} == NULL) )) != E_OK )\n"
1130 file.print "#{indent}\tgoto error_reset;\n"
1131 else
1132 # 呼びå…
1133ˆã¯ alloc_for_out_param で nullable の対応する
1134 file.print "#{indent}if( (ercd_=cTDR_getInt8( &b_#{param.get_name}_null_)) != E_OK )\n"
1135 file.print "#{indent}\tgoto error_reset;\n"
1136 end
1137 }
1138 end
1139end
Note: See TracBrowser for help on using the repository browser.