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