source: asp3_tinet_ecnl_rx/trunk/asp3_dcre/tecsgen/tecslib/core/generate.rb@ 359

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

SDカードの挿抜を検知するよう更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 159.6 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TECS Generator
4# Generator for TOPPERS Embedded Component System
5#
6# Copyright (C) 2008-2017 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
40def ifdef_macro_only f
41 f.print <<EOT
42#ifndef TOPPERS_MACRO_ONLY
43
44EOT
45end
46
47def ifndef_macro_only f
48 f.print <<EOT
49#ifndef TOPPERS_MACRO_ONLY
50
51EOT
52end
53
54def endif_macro_only f
55 f.print <<EOT
56#endif /* TOPPERS_MACRO_ONLY */
57
58EOT
59end
60
61def ifndef_cb_type_only f
62 f.print <<EOT
63#ifndef TOPPERS_CB_TYPE_ONLY
64
65EOT
66end
67
68def ifdef_cb_type_only f
69 f.print <<EOT
70#ifdef TOPPERS_CB_TYPE_ONLY
71
72EOT
73end
74
75def endif_cb_type_only f
76 f.print <<EOT
77#endif /* TOPPERS_CB_TYPE_ONLY */
78
79EOT
80end
81
82def begin_extern_C f
83 f.print <<EOT
84#ifdef __cplusplus
85extern "C" {
86#endif /* __cplusplus */
87EOT
88end
89
90def end_extern_C f
91 f.print <<EOT
92#ifdef __cplusplus
93}
94#endif /* __cplusplus */
95EOT
96end
97
98def print_note( f, b_complete = true )
99 if b_complete
100 f.print "/*\n"
101 else
102 f.print " *\n"
103 end
104 f.print TECSMsg.get( :note )
105 if b_complete
106 f.print " */\n"
107 else
108 f.print " *\n"
109 end
110end
111
112def print_Makefile_note f
113 f.print TECSMsg.get( :Makefile_note )
114end
115
116
117def print_indent( f, n )
118 f.print " " * n
119end
120
121# celltype_private.h を生成
122
123class Namespace
124 def generate
125
126 begin
127 # root namespace ならば makefile を出力する(全セルタイプに関わるものだけ)
128 # 先に出力する
129 if @name == "::" then
130
131 gen_makefile_template
132 gen_makefile_tecsgen
133 if $generating_region.get_n_cells == 0 then
134 dbgPrint "only makefile_template #{@name}\n"
135 return
136 end
137 end
138
139 dbgPrint "generating region: #{$generating_region.get_name} namespace=#{@name} gen_dir=#{$gen}\n"
140 # global_tecsgen.h (typedef, struct, const) の生成
141 gen_global_header
142
143 # signature のコードを生成
144 @signature_list.each { |s|
145 s.generate
146 }
147
148 # celltype のコードを生成
149 @celltype_list.each { |t|
150 t.generate
151 }
152
153 # サブネームスペースのコードを生成
154 @namespace_list.each { |n|
155 n.generate
156 }
157
158 rescue => evar
159 # もしスタックトレースが出るまでい時間がかかるようならば、次をコメントアウトしてみるべし
160 cdl_error( "H1001 tecsgen: fatal internal error during code generation" )
161 print_exception( evar )
162 end
163 end
164
165 def generate_post
166
167 if $generating_region.get_n_cells == 0 then
168 return
169 end
170
171 begin
172 # global_tecsgen.h (typedef, struct, const) の終わりのガードコード生成
173 gen_global_header_post
174
175 # signature のコードを生成
176 @signature_list.each { |s|
177 s.generate_post
178 }
179
180 # celltype のコードを生成
181 @celltype_list.each { |t|
182 t.generate_post
183 }
184
185 # サブネームスペースのコードを生成
186 @namespace_list.each { |n|
187 n.generate_post
188 }
189
190 rescue => evar
191 cdl_error( "H1002 tecsgen: fatal internal error during post code generation" )
192 print_exception( evar )
193 end
194 end
195
196###
197 def gen_global_header
198
199 # global_tecs.h の生成
200 f = AppFile.open( "#{$gen}/global_tecsgen.#{$h_suffix}" )
201
202 if @name == "::" then
203 print_note f
204
205 # ガードコードを出力
206 f.print <<EOT
207#ifndef GLOBAL_TECSGEN_H
208#define GLOBAL_TECSGEN_H
209
210EOT
211
212 # import_C で指定されたヘッダファイルの #include を出力
213 if Import_C.get_header_list2.length > 0 then
214 # ヘッダ include の出力
215 f.printf TECSMsg.get( :IMP_comment ), "#_IMP_#"
216 Import_C.get_header_list2.each{ |h|
217 f.printf( "#include \"#{h}\"\n" )
218 }
219 f.printf( "/**/\n\n" )
220 end
221
222 ifndef_macro_only f
223 end
224
225 # typedef, struct, enum を生成
226 @decl_list.each { |d|
227
228 # d は Typedef, StructType, EnumType のいずれか
229 if d.instance_of?( Typedef ) then
230
231 # Typedef の場合、declarator の @type が CType でないか
232 if ! d.get_declarator.get_type.kind_of?( CType ) then
233 d.gen_gh f
234 end
235 elsif ! d.kind_of?( CType ) then
236
237 # CType ではない (StructType または EnumType)
238 d.gen_gh f
239# else
240# ここに該当するのは CStructType, CEnumType
241 end
242 }
243
244 if @name == "::" then
245
246 if $ram_initializer then
247 # Proc to judge the necessity of CB initializer
248 b_inline_only_or_proc = Proc.new{ |ct|
249 # print ct.get_name, ": ", ct.need_CB_initializer?, "\n"
250 ct.need_CB_initializer?
251 }
252 gen_celltype_names( f, "extern void ", "_CB_initialize();\n", true, b_inline_only_or_proc )
253 gen_celltype_names( f, "extern void ", "_CB_initialize();\n", false, b_inline_only_or_proc )
254 f.print "\n#define INITIALIZE_TECS() \\\n"
255 gen_celltype_names( f, "\t", "_CB_initialize();\\\n", true, b_inline_only_or_proc )
256 gen_celltype_names( f, "\t", "_CB_initialize();\\\n", false, b_inline_only_or_proc )
257 f.print( "/* INITIALIZE_TECS terminator */\n\n" )
258 else
259 f.print "\n#define INITIALIZE_TECS() \n"
260 end
261 f.print "#define INITIALZE_TECSGEN() INITIALIZE_TECS() /* for backward compatibility */\n\n"
262
263 f.print( "/* Descriptor for dynamic join */\n" )
264 f.print( "#define Descriptor( signature_global_name ) DynDesc__ ## signature_global_name\n" )
265 f.print( "#define is_descriptor_unjoined( desc ) ((desc).vdes==NULL)\n\n" )
266 endif_macro_only f
267 end
268
269 # const を生成 mikan
270 @const_decl_list.each { |d|
271 f.printf( "#define %-14s ((%s%s)%s)\n", d.get_global_name,
272 d.get_type.get_type_str, d.get_type.get_type_str_post,
273 d.get_initializer.eval_const2(nil) )
274 }
275
276 f.close
277
278 end
279
280 def gen_global_header_post
281
282 # global_tecs.h を開く
283 f = AppFile.open( "#{$gen}/global_tecsgen.#{$h_suffix}" )
284
285 if @name == "::" then
286 f.print <<EOT
287
288#endif /* GLOBAL_TECSGEN_H */
289EOT
290 end
291
292 f.close
293
294 end
295
296 #=== Makefile.tecsgen, Makefile.templ の出力
297 # 全セルタイプ名を出力する部分を出力
298 # (本メソッドは root namespace に対して呼出す)
299 # 個々のセルタイプのメークルールは Celltype クラスで出力
300 def gen_makefile
301 gen_makefile_template
302 gen_makefile_tecsgen
303 end
304
305 def gen_makefile_template
306
307 return if $generate_no_template
308
309 ### Makefile.templ の生成
310 f = AppFile.open( "#{$gen}/Makefile.templ" )
311
312 print_Makefile_note f
313
314 # Makefile の変数の出力
315 f.printf TECSMsg.get( :MVAR_comment ), "#_MVAR_#"
316 f.printf "# fixed variable (unchangeable by config or plugin)\n"
317
318 # TARGET の出力 (第一引数 $target に region 名および .exe を付加)
319 target = $target
320 if $generating_region != @@root_namespace then
321 # 子 region のリンクターゲットの場合
322 target += "-#{$generating_region.get_global_name}"
323 end
324 f.print "TARGET_BASE = #{target}\n"
325
326 if $generating_region == @@root_namespace then
327 f.print "BASE_DIR = .\n"
328 vpath_lead = ""
329 else
330 f.print "BASE_DIR = ..\n"
331 vpath_lead = "../"
332 end
333
334 f.print "GEN_DIR = $(BASE_DIR)/#{$gen}\n"
335
336 f.print "INCLUDES ="
337 search_path = $import_path + TECSGEN::Makefile.get_search_path
338 search_path.each{ |path|
339 if TECSGEN.is_absolute_path? path then
340 f.print( TECSGEN.subst_tecspath " -I #{path}" )
341 else
342 f.print " -I $(BASE_DIR)/#{path}"
343 end
344 }
345 f.print " -I $(GEN_DIR)\n"
346 f.print "DEFINES ="
347 $define.each{ |define| f.print " -D #{define}" }
348 f.print "\n\n"
349 f.printf "# end of fixed variable (unchangeable by config or plugin)\n"
350
351
352 vpath_add = ""
353 search_path.each{ |path|
354 if path != "." then
355 if TECSGEN.is_absolute_path? path then
356 vpath_add += " " + TECSGEN.subst_tecspath( path )
357 else
358 vpath_add += " " + vpath_lead + path
359 end
360 end
361 }
362 objs_add = ""
363 TECSGEN::Makefile.get_objs.each{ |obj| objs_add += " " + obj }
364 ld_flag_add = TECSGEN::Makefile.get_ldflags
365 var_add = ""
366 TECSGEN::Makefile.get_vars.each{ |var|
367 var_add += "#" + TECSGEN::Makefile.get_var_comment( var ) + "\n"
368 a = TECSGEN::Makefile.get_var_val( var ).to_s
369 b = var.to_s
370 c = var_add.to_s
371 var_add += var.to_s + " =" + " " + TECSGEN::Makefile.get_var_val( var ).to_s + "\n\n"
372 }
373 pre_tecsgen_target = ""
374 TECSGEN::Makefile.get_pre_tecsgen_target{ |target| pre_tecsgen_target += " " + target }
375 post_tecsgen_target = ""
376 TECSGEN::Makefile.get_post_tecsgen_target{ |target| post_tecsgen_target += " " + target }
377
378#
379# LD = gcc
380# LDFLAGS =#{ld_flag_add}
381# SRC_DIR = $(BASE_DIR)/src
382# _TECS_OBJ_DIR = $(GEN_DIR)/
383# # _TECS_OBJ_DIR # should end with '/'
384
385 f.print <<EOT
386#{var_add}
387
388# Pre-tecsgen target
389PRE_TECSGEN_TARGET =#{pre_tecsgen_target}
390
391# Post-tecsgen target
392POST_TECSGEN_TARGET =#{post_tecsgen_target}
393
394# vpath for C sources and headers
395vpath %.#{$c_suffix} $(SRC_DIR) $(GEN_DIR) #{vpath_add}
396vpath %.#{$h_suffix} $(SRC_DIR) $(GEN_DIR) #{vpath_add}
397
398# Other objects (out of tecsgen)
399OTHER_OBJS =#{objs_add} # Add objects out of tecs care.
400# OTHER_OBJS = $(_TECS_OBJ_DIR)vasyslog.o
401EOT
402
403 # make ルールの出力
404 f.printf( TECSMsg.get( :MRUL_comment), "#_MRUL_#" )
405
406 f.print <<EOT
407allall: tecs
408\tmake all # in order to include generated Makefile.tecsgen & Makefile.depend
409
410EOT
411
412 if $generating_region.get_n_cells != 0 then
413 all_target = "$(TARGET)"
414 else
415 all_target = ""
416 end
417
418 if $generating_region == @@root_namespace then
419 if Region.get_link_roots.length > 1 then
420 all_target += " sub_regions"
421 end
422 timestamp = " $(TIMESTAMP)"
423 else
424 timestamp = ""
425 end
426
427 f.print "all : #{all_target}\n\n"
428 f.printf TECSMsg.get( :MDEP_comment ), "#_MDEP_#"
429 f.print "-include $(GEN_DIR)/Makefile.tecsgen\n"
430 if $generating_region.get_n_cells != 0 then
431 # Makefile.depend の include
432 f.print "-include $(GEN_DIR)/Makefile.depend\n\n"
433
434 f.print "$(TARGET) :#{timestamp} $(CELLTYPE_COBJS) $(TECSGEN_COBJS) $(PLUGIN_COBJS) $(OTHER_OBJS)\n"
435 f.print " $(LD) -o $(TARGET) $(TECSGEN_COBJS) $(CELLTYPE_COBJS) $(PLUGIN_COBJS) $(OTHER_OBJS) $(LDFLAGS)\n\n"
436 end
437
438 if Region.get_link_roots.length > 1 && $generating_region == @@root_namespace then
439 f.print "\nsub_regions:$(TIMESTAMP)\n"
440 Region.get_link_roots.each {|region|
441 if region.get_global_name != "" then # Root region: この Makefile 自身
442 f.print "\tcd #{region.get_global_name}; make all\n"
443 end
444 }
445 f.print "\n"
446 end
447
448 # clean: ターゲット
449 f.print "clean :\n"
450 if $generating_region == @@root_namespace then
451 Region.get_link_roots.each {|region|
452 if region.get_global_name != "" then # Root region: この Makefile 自身
453 f.print "\tcd #{region.get_global_name}; make clean\n"
454 end
455 }
456 end
457 f.print " rm -f $(CELLTYPE_COBJS) $(TECSGEN_COBJS) $(PLUGIN_COBJS) $(OTHER_OBJS) $(TARGET) #{timestamp}\n"
458 if $generating_region == @@root_namespace then
459 f.print " rm -rf $(GEN_DIR)\n"
460 end
461 f.print "\n"
462
463 # tecs: ターゲット
464 if $generating_region == @@root_namespace then
465 f.print "tecs : $(PRE_TECSGEN_TARGET) $(TIMESTAMP) $(POST_TECSGEN_TARGET)\n\n"
466 f.print "$(TIMESTAMP) : $(TECS_IMPORTS)\n"
467 f.print " $(TECSGEN) #{TECSGEN.subst_tecspath( $arguments, true )}\n"
468 # f.print " touch $(TIMESTAMP)\n\n"
469
470 else
471 f.print "tecs:\n"
472 f.print "\t@echo \"run 'make tecs' in root region\"\n\n"
473 end
474
475 f.print "# generic target for objs\n"
476 f.print "$(_TECS_OBJ_DIR)%.o : %.#{$c_suffix}\n"
477 f.print " $(CC) -c $(CFLAGS) -o $@ $<\n\n"
478
479 lines = TECSGEN::Makefile.get_lines
480 if lines.length > 0 then
481 f.print( "# additional lines\n" )
482 lines.each{ |line|
483 f.print line, "\n"
484 }
485 f.print( "# end additional lines\n\n" )
486 end
487
488 f.close
489 end
490
491 def gen_makefile_tecsgen
492 ### Makefile.tecsgen の生成
493 f = AppFile.open( "#{$gen}/Makefile.tecsgen" )
494
495 f.print( "TECS_IMPORT_CDLS =" )
496 Import.get_list.each{ |cdl_expand_path, import|
497 path = import.get_cdl_path
498 if TECSGEN.is_absolute_path? path then
499 path = TECSGEN.subst_tecspath path
500 end
501 f.print " "
502 f.print( path )
503 }
504 f.print( "\n" )
505 f.print( "TECS_IMPORT_HEADERS =" )
506 Import_C.get_header_list.each{ |header,path|
507 if TECSGEN.is_absolute_path? path then
508 path = TECSGEN.subst_tecspath path
509 end
510 f.print " "
511 f.print path
512 }
513 f.print "\n"
514 f.print "TECS_IMPORTS = $(TECS_IMPORT_CDLS) $(TECS_IMPORT_HEADERS)\n\n"
515
516 f.print "SIGNATURE_HEADERS = \\\n"
517 if $generating_region.get_n_cells != 0 then
518 @signature_list.each{ |s|
519 f.print "\t$(GEN_DIR)/#{s.get_global_name}_tecsgen.#{$h_suffix} \\\n"
520 }
521 end
522 f.print "# SIGNATURE_HEADERS terminator\n\n"
523
524 b_inline_only_or_proc = Proc.new { |ct| true }
525 f.print "CELLTYPE_TECSGEN_HEADERS = \\\n"
526 gen_celltype_names( f, "\t$(GEN_DIR)/", "_tecsgen.h \\\n", true, b_inline_only_or_proc )
527 gen_celltype_names( f, "\t$(GEN_DIR)/", "_tecsgen.h \\\n", false, b_inline_only_or_proc )
528 f.print "# CELLTYPE_TECSGEN_HEADERS terminator\n\n"
529 f.print "CELLTYPE_FACTORY_HEADERS = \\\n"
530 gen_celltype_names( f, "\t$(GEN_DIR)/", "_factory.h \\\n", true, b_inline_only_or_proc )
531 gen_celltype_names( f, "\t$(GEN_DIR)/", "_factory.h \\\n", false, b_inline_only_or_proc )
532 f.print "# CELLTYPE_FACTORY_HEADERS terminator\n\n"
533 f.print "# TECS_HEADERS: headers generated by tecsgen\n"
534 f.print "TECS_HEADERS = $(SIGNATURE_HEADERS) $(CELLTYPE_TECSGEN_HEADERS) $(CELLTYPE_FACTORY_HEADERS)\n\n"
535 b_inline_only_or_proc = true
536 f.print "TECS_INLINE_HEADERS = \\\n"
537 gen_celltype_names( f, "\t", "_tecsgen.h \\\n", false, b_inline_only_or_proc )
538 f.print "# TECS_INLINE_HEADERS terminator\n\n"
539 f.print "PLUGIN_INLINE_HEADERS = \\\n"
540 gen_celltype_names( f, "\t", "_tecsgen.h \\\n", true, b_inline_only_or_proc )
541 f.print "# PLUGIN_INLINE_HEADERS terminator\n\n"
542
543 ### set domain variables ###
544 domain_type = nil
545 domain_regions = nil
546 DomainType.get_domain_regions.each{ |dt, regions|
547 # domain_type は一つのノードには、一つしかないので、このループは、必ず一回しか回らない
548 domain_regions = regions
549 domain_type = dt
550 }
551 if domain_regions == nil then
552 # in case no 'domain' specified at region
553 domain_regions = [ Region.get_root ]
554 end
555
556 hasDomainProc = Proc.new{
557 if domain_regions.length > 1 || domain_regions[0] != Region.get_root then
558 true
559 else
560 false
561 end
562 }
563 decideDomainNameProc = Proc.new { |region|
564 if region.is_root? then
565 if hasDomainProc.call then
566 dn = "_Root_"
567 else
568 dn = ""
569 end
570 else
571 dn = "_#{region.get_namespace_path.get_global_name}"
572 end
573 }
574
575 f.print( "# TECS_COBJS: all objects of TECS, include both user written code and tecsgen automatically generated code\n" )
576 f.print( "TECS_COBJS = $(TECSGEN_COBJS) $(PLUGIN_COBJS) $(CELLTYPE_COBJS)\n\n" )
577
578 ### in case domain is used ###
579 if hasDomainProc.call then
580
581 f.print( "# TECS_DOMAINS: list of domain names (names of 'domain' spacified region)\n" )
582 f.print( "TECS_DOMAINS = " )
583 domain_regions.each{ |r|
584 if r.get_domain_type.get_option != "OutOfDomain" then
585 f.print( " #{r.get_namespace_path.get_global_name}" )
586 end
587 }
588 f.print( "\n\n" )
589
590 f.print( "# TECS_COBJS: objects from sources which are automatically generated by tecsgen\n" )
591 f.print( "TECSGEN_COBJS = \\\n" )
592 domain_regions.each{ |r|
593 f.print( " $(TECSGEN#{decideDomainNameProc.call r}_COBJS) \\\n" )
594 }
595 f.print( "# TECSGEN_COBJS terminator\n\n" )
596
597 f.print( "# PLUGIN_COBJS: objects from sources which are automatically generated by plugin(s)\n" )
598 f.print( "PLUGIN_COBJS = \\\n" )
599 domain_regions.each{ |r|
600 f.print( " $(PLUGIN#{decideDomainNameProc.call r}_COBJS) \\\n" )
601 }
602 f.print( "# PLUGIN_COBJS terminator\n\n" )
603
604 f.print( "CELLTYPE_COBJS = \\\n" )
605 domain_regions.each{ |r|
606 f.print( " $(CELLTYPE#{decideDomainNameProc.call r}_COBJS) \\\n" )
607 }
608 f.print( "# CELLTYPE_COBJS terminator\n\n" )
609
610 f.print( "TECSGEN_SRCS = \\\n" )
611 domain_regions.each{ |r|
612 f.print( " $(TECSGEN#{decideDomainNameProc.call r}_SRCS) \\\n" )
613 }
614 f.print( "# TECSGEN_SRCS terminator\n\n" )
615
616 f.print( "PLUGIN_SRCS = \\\n" )
617 domain_regions.each{ |r|
618 f.print( " $(PLUGIN#{decideDomainNameProc.call r}_SRCS) \\\n" )
619 }
620 f.print( "# PLUGIN#_SRCS terminator\n\n" )
621 end
622
623 ###
624 f.print( "# TECS_COBJS: objects from sources which are automatically generated by tecsgen\n" )
625 domain_regions.each{ |r|
626 nsp = decideDomainNameProc.call( r )
627 f.print( "TECSGEN#{nsp}_COBJS = \\\n" )
628 gen_celltype_names_domain( f, " $(_TECS_OBJ_DIR)", "_tecsgen.o \\\n", domain_type, r, false )
629 f.print( "# TECSGEN#{nsp}_COBJS terminator\n\n" )
630 }
631
632 f.print( "# PLUGIN_COBJS: objects from sources which are automatically generated by plugin(s)\n" )
633 domain_regions.each{ |r|
634 nsp = decideDomainNameProc.call( r )
635 f.print( "PLUGIN#{nsp}_COBJS = \\\n" )
636 gen_celltype_names_domain( f, " $(_TECS_OBJ_DIR)", "_tecsgen.o \\\n", domain_type, r, true )
637 gen_celltype_names_domain2( f, " $(_TECS_OBJ_DIR)", ".o \\\n", domain_type, r, true, false )
638 f.print( "# PLUGIN#{nsp}_COBJS terminator\n\n" )
639 }
640
641 f.print( "# CELLTYPE_COBJS: objects of celltype code written by user\n" )
642 domain_regions.each{ |r|
643 nsp = decideDomainNameProc.call( r )
644 f.print( "CELLTYPE#{nsp}_COBJS = \\\n" )
645 gen_celltype_names_domain2( f, " $(_TECS_OBJ_DIR)", ".o \\\n", domain_type, r, false, false )
646 f.print( "# CELLTYPE#{nsp}_COBJS terminator\n\n" )
647 }
648
649 f.print( "# TECSGEN_SRCS: sources automatically generated by tecsgen\n" )
650 domain_regions.each{ |r|
651 nsp = decideDomainNameProc.call( r )
652 f.print( "TECSGEN#{nsp}_SRCS = \\\n" )
653 gen_celltype_names_domain( f, " $(GEN_DIR)/", "_tecsgen.#{$c_suffix} \\\n", domain_type, r, false )
654 f.print( "# TECSGEN#{nsp}_SRCS terminator\n\n" )
655 }
656
657 f.print( "# PLUGIN_SRCS: sources automatically generated by plugin\n" )
658 domain_regions.each{ |r|
659 nsp = decideDomainNameProc.call( r )
660 f.print( "PLUGIN#{nsp}_SRCS = \\\n" )
661 gen_celltype_names_domain( f, " $(GEN_DIR)/", "_tecsgen.#{$c_suffix} \\\n", domain_type, r, true )
662 gen_celltype_names_domain2( f, " $(GEN_DIR)/", ".#{$c_suffix} \\\n", domain_type, r, true, false )
663 f.print( "# PLUGIN#{nsp}_SRCS terminator\n\n" )
664 }
665
666 f.close
667
668 end
669
670 #=== すべてのセルタイプの名前を出力
671 #f:: FILE: 出力先ファイル
672 #prepend:: string: 前置文字列
673 #append:: string: 後置文字列
674 #b_plguin:: bool: plugin により生成されたセルタイプを出力
675 ##b_inline_only:: bool: true ならば inline の entry port のみのセルタイプを含める
676 #b_inline_only_or_proc:: bool|Proc: true ならば inline の entry port のみ、かつインアクティブなセルタイプを含める
677 # Proc ならば Proc を実行した結果 true ならば含める
678 # namespace "::" から呼出される
679 def gen_celltype_names( f, prepend, append, b_plugin, b_inline_only_or_proc = true )
680 dbgPrint "gen_celltype_names #{@name}\n"
681
682 @celltype_list.each { |ct|
683 next if ! ct.need_generate?
684# next if b_inline_only == false && ct.is_all_entry_inline?
685 next if b_inline_only_or_proc == false && ct.is_all_entry_inline? && ! ct.is_active?
686 # print "Proc:", b_inline_only_or_proc.kind_of?( Proc ), b_inline_only_or_proc.class, "\n"
687 next if b_inline_only_or_proc.kind_of?( Proc ) && ( b_inline_only_or_proc.call( ct ) == false )
688 if ( b_plugin && ct.get_plugin ) || ( ! b_plugin && ! ct.get_plugin ) then
689 f.print " #{prepend}#{ct.get_global_name}#{append}"
690 end
691 }
692 @namespace_list.each { |ns|
693 ns.gen_celltype_names( f, prepend, append, b_plugin, b_inline_only_or_proc )
694 }
695
696 end
697
698 #=== すべてのセルタイプの名前を出力
699 #region:: Region:
700 # gen_celltype_names とgen_celltype_names_domain の相違:
701 # region を domain_roots に含む場合、出力する.
702 # または、region を含まないが、domain_roots が複数かつルートリージョンの場合、出力する.
703 # それ以外は、gen_celltype_names の説明を参照
704 def gen_celltype_names_domain( f, prepend, append, domain_type, region, b_plugin, b_inline_only = true )
705 dbgPrint "gen_celltype_names #{@name}\n"
706
707 @celltype_list.each { |ct|
708 next if ! ct.need_generate?
709# next if b_inline_only == false && ct.is_all_entry_inline?
710 next if b_inline_only == false && ct.is_all_entry_inline? && ! ct.is_active?
711 if ( b_plugin && ct.get_plugin ) || ( ! b_plugin && ! ct.get_plugin ) then
712 regions = ct.get_domain_roots[ domain_type ]
713 if regions.include?( region ) then
714 # p "BBB celltype:#{ct.get_name} domain:#{domain_type} append:#{append}"
715 if region.is_root? then
716 nsp = ""
717 else
718 nsp = "_#{region.get_namespace_path.get_global_name}"
719 end
720 f.print " #{prepend}#{ct.get_global_name}#{nsp}#{append}"
721 elsif region.is_root? then
722 # the case of domain_roots >= 2 && no cell in root region
723 if regions.length > 1 then
724 f.print " #{prepend}#{ct.get_global_name}#{append}"
725 end
726 end
727 end
728 }
729 @namespace_list.each { |ns|
730 ns.gen_celltype_names_domain( f, prepend, append, domain_type, region, b_plugin, b_inline_only )
731 }
732 end
733 #== Namespace#すべてのセルタイプの名前を出力
734 # セルタイプコードのための名前出力
735 # gen_celltype_names_domain と gen_celltype_names_domain2 の相違
736 # ・どれか一つのリージョンにしか出さない
737 # domain_roots が1つだけで、指定リージョンを含む
738 # domain_roots が2つ以上で、指定リージョンがルートリージョン
739 # ・ドメイン名を付加しない
740 def gen_celltype_names_domain2( f, prepend, append, domain_type, region, b_plugin, b_inline_only = true )
741 dbgPrint "gen_celltype_names #{@name}\n"
742
743 @celltype_list.each { |ct|
744 next if ! ct.need_generate?
745# next if b_inline_only == false && ct.is_all_entry_inline?
746 next if b_inline_only == false && ct.is_all_entry_inline? && ! ct.is_active?
747 if ( b_plugin && ct.get_plugin ) || ( ! b_plugin && ! ct.get_plugin ) then
748 # p "BBB celltype:#{ct.get_name} domain:#{domain_type} append:#{append}"
749 regions = ct.get_domain_roots[ domain_type ]
750 if regions.include?( region ) && regions.length == 1 then
751 f.print " #{prepend}#{ct.get_global_name}#{append}"
752 elsif region.is_root? then
753 # the case of domain_roots >= 2 && no cell in root region
754 if regions.length > 1 then
755 f.print " #{prepend}#{ct.get_global_name}#{append}"
756 end
757 end
758 end
759 }
760 @namespace_list.each { |ns|
761 ns.gen_celltype_names_domain2( f, prepend, append, domain_type, region, b_plugin, b_inline_only )
762 }
763 end
764
765 #=== Namespace#すべてのシグニチャをたどる
766 def travers_all_signature # ブロック引数 { |signature| }
767 proc = Proc.new # このメソッドのブロック引数
768 @signature_list.each{ |sig|
769 proc.call sig
770 }
771 @namespace_list.each{ |ns|
772 ns.travers_all_signature_proc proc
773 }
774 end
775 def travers_all_signature_proc proc
776 @signature_list.each{ |sig|
777 proc.call sig
778 }
779 @namespace_list.each{ |ns|
780 ns.travers_all_signature_proc proc
781 }
782 end
783end
784
785class Typedef
786 def gen_gh f
787
788# print "Typedef.gen_gh\n"
789# show_tree 1
790
791 f.printf( "typedef %-14s %s%s;\n",
792 "#{@declarator.get_type.get_type_str}",
793 "#{@declarator.get_name}",
794 "#{@declarator.get_type.get_type_str_post}")
795 end
796end
797
798class StructType < Type
799 def gen_gh f
800
801# print "StructType.gen_gh\n"
802# show_tree 1
803
804 if ! @b_define then
805 return
806 end
807
808 f.print "struct #{@tag} {\n"
809
810 @members_decl.get_items.each{ |i|
811 f.printf( " %-14s %s%s;\n", "#{i.get_type.get_type_str}", "#{i.get_name}", "#{i.get_type.get_type_str_post}" )
812 }
813
814 f.print "};\n"
815
816 end
817end
818
819class Signature
820
821 def generate
822 generate_signature_header
823 end
824
825 def generate_post
826 generate_signature_header_post
827 end
828
829 def generate_signature_header
830 f = AppFile.open("#{$gen}/#{@global_name}_tecsgen.#{$h_suffix}")
831
832 print_note f
833 gen_sh_guard f
834 gen_sh_info f
835 gen_sh_include f
836
837 ifndef_macro_only f
838 gen_sh_func_tab f
839 endif_macro_only f
840 gen_sh_func_id f
841
842 f.close
843 end
844
845 def generate_signature_header_post
846 f = AppFile.open("#{$gen}/#{@global_name}_tecsgen.#{$h_suffix}")
847 gen_sh_endif f
848 f.close
849 end
850
851
852##### signature header
853
854 def gen_sh_guard f
855 f.print("#ifndef #{@global_name}_TECSGEN_H\n")
856 f.print("#define #{@global_name}_TECSGEN_H\n\n")
857 end
858
859 def gen_sh_info f
860 f.print <<EOT
861/*
862 * signature : #{@name}
863 * global name : #{@global_name}
864 * context : #{get_context}
865 */
866
867EOT
868 end
869
870 def gen_sh_include f
871 dl = get_descriptor_list
872 if dl.length > 0 then
873 f.printf TECSMsg.get(:SDI_comment), "#_SDI_#"
874 dl.each{ |dt,param|
875 f.print <<EOT
876/* pre-typedef incomplete-type to avoid error in case of mutual or cyclic reference */
877#ifndef Descriptor_of_#{dt.get_global_name}_Defined
878#define Descriptor_of_#{dt.get_global_name}_Defined
879typedef struct { struct tag_#{dt.get_global_name}_VDES *vdes; } Descriptor( #{dt.get_global_name} );
880#endif
881EOT
882# f.print "#include \"#{dt.get_global_name}_tecsgen.#{$h_suffix}\"\n"
883 }
884 f.print "\n"
885 end
886
887 end
888
889 def gen_sh_func_tab f
890
891 # シグニチャディスクリプタの出力
892 f.printf TECSMsg.get(:SD_comment), "#_SD_#"
893 f.print "struct tag_#{@global_name}_VDES {\n"
894 f.print " struct tag_#{@global_name}_VMT *VMT;\n"
895 f.print "};\n\n"
896
897 # シグニチャ関数テーブルの出力
898 f.printf TECSMsg.get(:SFT_comment), "#_SFT_#"
899 f.print( "struct tag_#{@global_name}_VMT {\n" )
900 get_function_head_array.each{ |fun|
901 f.print " "
902 functype = fun.get_declarator.get_type
903 f.printf( "%-14s", functype.get_type_str )
904
905 f.print( " (*#{fun.get_name}__T)(" )
906 f.print( " const struct tag_#{@global_name}_VDES *edp" ) unless @singleton
907
908 if functype.get_paramlist then
909 items = functype.get_paramlist.get_items
910 len = items.length
911 else
912 # ここで nil になるのは、引数なしの時に void がなかった場合
913 items = []
914 len = 0
915 end
916
917 i = 0
918 items.each{ |param|
919 f.print ", "
920 f.print( param.get_type.get_type_str )
921 f.print( " " )
922 f.print( param.get_name )
923 f.print( param.get_type.get_type_str_post )
924 i += 1
925 }
926 f.print " );\n"
927 }
928 if get_function_head_array.length == 0 then
929 f.print( " void (*dummy__)(void);\n" )
930 end
931
932 f.print "};\n\n"
933 f.printf TECSMsg.get(:SDES_comment), "#_SDES_#"
934 f.print <<EOT
935#ifndef Descriptor_of_#{@global_name}_Defined
936#define Descriptor_of_#{@global_name}_Defined
937typedef struct { struct tag_#{@global_name}_VDES *vdes; } Descriptor( #{@global_name} );
938#endif
939EOT
940 end
941
942 #=== Signature# 関数の ID の define を出力
943 def gen_sh_func_id f
944 f.print "/* function id */\n"
945 get_function_head_array.each{ |fun|
946 f.printf( "#define\tFUNCID_%-31s (%d)\n", "#{@global_name}_#{fun.get_name}".upcase, get_id_from_func_name( fun.get_name ) )
947 }
948 f.print "\n"
949 end
950
951 def gen_sh_endif f
952 f.print("#endif /* #{@global_name}_TECSGEN_H */\n")
953 end
954
955end
956
957class Celltype
958
959 def generate
960
961 if need_generate? # セルのないセルタイプは生成しない
962
963 generate_private_header
964 generate_factory_header
965 generate_cell_code
966 generate_template_code
967 generate_inline_template_code
968 generate_celltype_factory_code
969 generate_cell_factory_code
970 generate_makefile
971
972 elsif $generate_all_template # テンプレートコード生成オプション
973
974 generate_template_code
975 generate_inline_template_code
976
977 # generate_makefile_template は Makefile に追記するものだから、呼び出さない
978
979 end
980
981 end
982
983 def generate_post
984 return if ! need_generate? # セルのないセルタイプは生成しない
985
986 generate_private_header_post
987 generate_factory_header_post
988 end
989
990 def generate_private_header
991
992 f = AppFile.open("#{$gen}/#{@global_name}_tecsgen.#{$h_suffix}")
993
994 print_note f
995
996 gen_ph_guard f
997 gen_ph_info f
998 gen_ph_include f
999 #
1000 ifndef_macro_only f
1001 begin_extern_C f
1002 gen_ph_cell_cb_type f
1003 gen_ph_INIB_as_CB f
1004 gen_ph_extern_cell f # セルタイプグルコード以外は参照しない
1005 gen_ph_typedef_idx f # mikan 参照するものができていない
1006 gen_ph_ep_fun_prototype f
1007 end_extern_C f
1008 endif_macro_only f
1009 #
1010 gen_ph_include_cb_type f
1011
1012 if @n_entry_port_inline == 0 then
1013 # inline がなければ CB_TYPE_ONLY とする
1014 # inline ありの場合、いったん define しておいて、後ですべて undef する
1015 ifndef_cb_type_only f
1016 end
1017
1018 gen_ph_base f
1019 gen_ph_valid_idx f
1020 gen_ph_n_cp f if @n_call_port_array > 0
1021 gen_ph_n_ep f if @n_entry_port_array > 0
1022 gen_ph_test_optional_call_port f
1023 gen_ph_get_cellcb f
1024 gen_ph_attr_access f if @n_attribute_rw > 0 || @n_attribute_ro > 0 || @n_var > 0
1025 gen_ph_cp_fun_macro f if @n_call_port > 0
1026# gen_ph_abstract_ep_des_type f
1027
1028 if @n_entry_port_inline == 0 then
1029 endif_cb_type_only f
1030 end
1031
1032 ifndef_macro_only f
1033 begin_extern_C f
1034# gen_ph_cell_cb_type f
1035# gen_ph_INIB_as_CB f
1036# gen_ph_extern_cell f # セルタイプグルコード以外は参照しない
1037 # gen_ph_typedef_idx f # mikan 参照するものができていない
1038# gen_ph_ep_fun_prototype f
1039 gen_ph_ep_skel_prototype f
1040
1041 #--- CB_TYPE_ONLY の場合、ref_desc, set_desc 関数は含めない (マクロ参照するため)
1042 if @n_entry_port_inline == 0 then
1043 ifndef_cb_type_only f
1044 end
1045 gen_ph_ref_desc_func f
1046 gen_ph_set_desc_func f
1047 if @n_entry_port_inline == 0 then
1048 endif_cb_type_only f
1049 end
1050 end_extern_C f
1051 endif_macro_only f
1052
1053 # 短縮形などのマクロ出力
1054 if @n_entry_port_inline == 0 then
1055 ifndef_cb_type_only f
1056 end
1057 gen_ph_valid_idx_abbrev f
1058 gen_ph_get_cellcb_abbrev f
1059 gen_ph_attr_access_abbrev f if @n_attribute_rw > 0 || @n_attribute_ro > 0 || @n_var > 0
1060 gen_ph_cp_fun_macro_abbrev f if @n_call_port > 0
1061 gen_ph_ref_desc_macro_abbrev f
1062 gen_ph_set_desc_macro_abbrev f
1063 gen_ph_test_optional_call_port_abbrev f
1064 gen_ph_ep_fun_macro f if @n_entry_port > 0
1065 gen_ph_foreach_cell f # FOREACH マクロの出力
1066 gen_ph_cb_initialize_macro f # CB 初期化マクロの出力.消費しないので ram_initializer フラグに関わらず出力
1067 gen_ph_dealloc_code f, ""
1068 gen_ph_dealloc_code f, "_RESET"
1069 if @n_entry_port_inline == 0 then
1070 endif_cb_type_only f
1071 end
1072
1073 f.close
1074 end
1075
1076 def generate_private_header_post
1077
1078 f = AppFile.open("#{$gen}/#{@global_name}_tecsgen.#{$h_suffix}")
1079
1080 ifndef_macro_only f
1081 gen_ph_inline f
1082 endif_macro_only f
1083
1084 if @n_entry_port_inline > 0 then
1085 ifdef_cb_type_only f
1086 f.printf TECSMsg.get( :UDF_comment ), "#_UDF_#"
1087 f.print "#undef VALID_IDX\n"
1088 f.print "#undef GET_CELLCB\n"
1089 f.print "#undef CELLCB\n"
1090 f.print "#undef CELLIDX\n"
1091 f.print "#undef #{@name}_IDX\n"
1092
1093 f.print "#undef FOREACH_CELL\n"
1094 f.print "#undef END_FOREACH_CELL\n"
1095 f.print "#undef INITIALIZE_CB\n"
1096 f.print "#undef SET_CB_INIB_POINTER\n"
1097
1098 @attribute.each { |a|
1099 f.print( "#undef ATTR_#{a.get_name}\n" )
1100 f.print( "#undef #{@global_name}_ATTR_#{a.get_name}\n" )
1101 f.print( "#undef #{@global_name}_GET_#{a.get_name}\n" )
1102 }
1103 @var.each { |v|
1104 f.print( "#undef VAR_#{v.get_name}\n" )
1105 f.print( "#undef VAR_#{v.get_name}\n" )
1106 f.print( "#undef #{@global_name}_VAR_#{v.get_name}\n" )
1107 f.print( "#undef #{@global_name}_GET_#{v.get_name}\n" )
1108 f.print( "#undef #{@global_name}_SET_#{v.get_name}\n" )
1109 }
1110 @port.each { |p|
1111 next if p.get_port_type != :CALL
1112
1113 # is_...joined は omit するケースでも出力されるため、omit を検査する前に出力
1114 if p.is_optional? then
1115 f.print( "#undef is_#{p.get_name}_joined\n" )
1116 end
1117
1118 next if p.is_omit?
1119
1120 p.get_signature.get_function_head_array.each{ |fun|
1121 f.print( "#undef #{@global_name}_#{p.get_name}_#{fun.get_name}\n" )
1122 if ! p.is_require? || p.has_name? then
1123 f.print( "#undef #{p.get_name}_#{fun.get_name}\n" )
1124 else
1125 f.print( "#undef #{fun.get_name}\n" )
1126 end
1127 }
1128 if p.is_dynamic? then
1129 f.print( "#undef #{p.get_name}_set_descriptor\n" )
1130 if p.is_optional? then
1131 f.print( "#undef #{p.get_name}_unjoin\n" )
1132 end
1133 elsif p.is_ref_desc? then
1134 f.print( "#undef #{p.get_name}_refer_to_descriptor\n" )
1135 f.print( "#undef #{p.get_name}_ref_desc\n" )
1136 end
1137 }
1138 @port.each { |p|
1139 next if p.get_port_type != :ENTRY
1140 next if p.is_omit?
1141 p.get_signature.get_function_head_array.each{ |fun|
1142 f.print( "#undef #{p.get_name}_#{fun.get_name}\n" )
1143 }
1144 }
1145
1146 gen_ph_dealloc_code( f, "", true )
1147 gen_ph_dealloc_code( f, "_RESET", true )
1148
1149 endif_cb_type_only f
1150 end
1151
1152 gen_ph_endif f
1153
1154 f.close
1155 end
1156
1157 #=== CELLTYPE_tecsgen.c を生成
1158 def generate_cell_code
1159 fs = { }
1160 f = nil
1161 @domain_roots.each{ |domain_type_name, regions|
1162 regions.each{ |r|
1163 if r.is_root? then
1164 nsp = ""
1165 else
1166 nsp = "_#{r.get_namespace_path.get_global_name}"
1167 end
1168 # p "celltype:#{@name} dn:#{domain_type_name} nsp:#{nsp}"
1169 fs[r] = AppFile.open("#{$gen}/#{@global_name}#{nsp}_tecsgen.#{$c_suffix}")
1170 if r.is_root? then
1171 f = fs[r]
1172 end
1173 }
1174 }
1175
1176 # in case that domain_roots does not include root region
1177 if f == nil then
1178 regions = nil
1179 @domain_roots.each{ |domain_type_name, regions_|
1180 regions = regions_ # domain_type_name is unique
1181 }
1182 if regions.length > 1 then
1183 # if domain_roots.length >= 2 && no cell in root region
1184 # shared code are placed in root region
1185 f = AppFile.open("#{$gen}/#{@global_name}_tecsgen.#{$c_suffix}")
1186 else
1187 # shared code are placed in unique region
1188 f = fs[ regions[0] ]
1189 end
1190 end
1191
1192 # すべての _tecsgen.c に出力
1193 print_note f
1194 gen_cell_private_header f
1195 gen_cell_factory_header f
1196 gen_cell_ep_des_type f
1197
1198 # すべての _tecsgen.c に出力
1199 fs.each{ |r,f2|
1200 if f == f2 then
1201 next
1202 end
1203 print_note f2
1204 gen_cell_private_header f2
1205 gen_cell_factory_header f2
1206 gen_cell_ep_des_type f2
1207 }
1208
1209 # 一つの _tecsgen.c に出力
1210 gen_cell_skel_fun f
1211 gen_cell_fun_table f
1212 gen_cell_var_init f
1213
1214 # セルごとに _tecsgen.c に出力
1215 gen_cell_ep_vdes fs
1216 gen_cell_ep_vdes_array fs
1217 gen_cell_cb_out_init fs # INITIALIZE_CB で参照されるため ram_initializer=false でも消せない
1218 gen_cell_cb fs
1219 gen_cell_extern_mt fs
1220 gen_cell_ep_des fs
1221
1222 # 一つの _tecsgen.c に出力
1223 gen_cell_cb_tab f
1224 if $ram_initializer then
1225 gen_cell_cb_initialize_code f
1226 end
1227
1228 fs.each{ |r,f2|
1229 f2.close
1230 if f == f2 then
1231 f = nil
1232 end
1233 }
1234 if f then
1235 f.close
1236 end
1237
1238 end
1239
1240##### celltype header
1241
1242 def gen_ph_guard( f, post = "TECSGEN" )
1243 f.print("#ifndef #{@global_name}_#{post}_H\n")
1244 f.print("#define #{@global_name}_#{post}_H\n\n")
1245 end
1246
1247 def gen_ph_info f
1248
1249 yn_idx_is_id = "no"
1250 yn_idx_is_id = "yes" if @idx_is_id
1251 yn_idx_is_id_act = "no"
1252 yn_idx_is_id_act = "yes" if @idx_is_id_act
1253 yn_singleton = "no"
1254 yn_singleton = "yes" if @singleton
1255 yn_rom = "no"
1256 yn_rom = "yes" if $rom
1257 yn_cb_init = "no"
1258 yn_cb_init = "yes" if need_CB_initializer?
1259 # @singleton = false # mikan singleton 060827
1260
1261 f.print <<EOT
1262/*
1263 * celltype : #{@name}
1264 * global name : #{@global_name}
1265 * idx_is_id(actual) : #{yn_idx_is_id}(#{yn_idx_is_id_act})
1266 * singleton : #{yn_singleton}
1267 * has_CB : #{has_CB?}
1268 * has_INIB : #{has_INIB?}
1269 * rom : #{yn_rom}
1270 * CB initializer : #{yn_cb_init}
1271 */
1272
1273EOT
1274 end
1275
1276 def gen_ph_include f
1277 # ランタイムヘッダの include
1278# f.printf TECSMsg.get( :IRTH_comment), "#_IRTH_#"
1279# f.print "#include \"tecs.#{$h_suffix}\"\n\n"
1280
1281 # グローバルヘッダの include
1282 f.printf TECSMsg.get( :IGH_comment ), "#_IGH_#"
1283 f.print "#include \"global_tecsgen.#{$h_suffix}\"\n\n"
1284
1285 # シグニチャヘッダの include
1286 f.printf TECSMsg.get( :ISH_comment ), "#_ISH_#"
1287 @port.each { |p|
1288 next if p.is_omit?
1289 hname = "#{p.get_signature.get_global_name}_tecsgen.#{$h_suffix}".to_sym
1290 if header_included?( hname ) == false then
1291 f.print "#include \"#{hname}\"\n"
1292 end
1293 }
1294 f.print "\n"
1295 end
1296
1297 def gen_ph_include_cb_type f
1298
1299 if ! @b_cp_optimized then
1300 return
1301 end
1302
1303 # 最適化のため参照するセルタイプの CB 型の定義を取込む
1304 # _CB_TYPE_ONLY を定義した上で include する
1305 f.printf( TECSMsg.get( :ICT_comment ), "#_ICT_#" )
1306
1307 f.print( "#ifndef TOPPERS_CB_TYPE_ONLY\n" )
1308 f.print( "#define #{@global_name}_CB_TYPE_ONLY\n" )
1309 f.print( "#define TOPPERS_CB_TYPE_ONLY\n" )
1310 f.print( "#endif /* TOPPERS_CB_TYPE_ONLY */\n" )
1311
1312 @port.each { |p|
1313 next if p.get_port_type != :CALL
1314 next if p.is_omit?
1315
1316 if p.is_skelton_useless? || p.is_cell_unique? || p.is_VMT_useless? then
1317 # 最適化コード (optimize) # スケルトン不要など
1318 p2 = p.get_real_callee_port
1319 if p2 then
1320 ct = p2.get_celltype
1321 hname = "#{ct.get_global_name}_tecsgen.#{$h_suffix}".to_sym
1322 if header_included?( hname ) == false then
1323 f.print( "#include \"#{hname}\"\n" )
1324 end
1325 # else
1326 # optional で未結合
1327 end
1328 end
1329
1330 }
1331 f.print( "#ifdef #{@global_name}_CB_TYPE_ONLY\n" )
1332 f.print( "#undef TOPPERS_CB_TYPE_ONLY\n" )
1333 f.print( "#endif /* #{@global_name}_CB_TYPE_ONLY */\n" )
1334
1335# @port.each { |p|
1336# next if p.get_port_type != :CALL
1337# if p.is_skelton_useless? || p.is_cell_unique? || p.is_VMT_useless? then
1338# # 最適化コード (optimize) # スケルトン不要など
1339# p2 = p.get_real_callee_port
1340# ct = p2.get_celltype
1341# ct.gen_ph_typedef_idx f
1342# ct.gen_ph_INIB_as_CB f
1343# ct.gen_ph_extern_cell f
1344# f.print "\n"
1345# end
1346# }
1347
1348 end
1349
1350
1351 def gen_ph_base f
1352 return if @singleton
1353
1354 # ID の基数および個数の define を出力
1355 f.printf("#define %-20s %10s /* %s #_NIDB_# */\n", "#{@global_name}_ID_BASE", "(#{@id_base})", TECSMsg.get(:NIDB_comment))
1356 f.printf("#define %-20s %10s /* %s #_NCEL_# */\n\n", "#{@global_name}_N_CELL", "(#{@n_cell_gen})", TECSMsg.get(:NCEL_comment))
1357 end
1358
1359 def gen_ph_valid_idx f
1360 return if @singleton
1361
1362 # mikan 最適化
1363 # IDX 正当性チェックマクロの出力
1364 f.printf( TECSMsg.get( :CVI_comment ), "#_CVI_#" )
1365 if @idx_is_id_act then
1366 f.print("#define #{@global_name}_VALID_IDX(IDX) (#{@global_name}_ID_BASE <= (IDX) && (IDX) < #{@global_name}_ID_BASE+#{@global_name}_N_CELL)\n\n")
1367 else
1368 f.print("#define #{@global_name}_VALID_IDX(IDX) (1)\n\n")
1369 end
1370
1371 end
1372
1373 def gen_ph_valid_idx_abbrev f
1374 return if @singleton
1375
1376 # IDX 正当性チェックマクロ(短縮形)の出力
1377 f.printf( TECSMsg.get( :CVIA_comment ), "#_CVIA_#")
1378 f.print("#define VALID_IDX(IDX) #{@global_name}_VALID_IDX(IDX)\n\n")
1379
1380 end
1381
1382 #=== 呼び口配列の大きさを得るマクロの出力
1383 #
1384 #セルタイプヘッダへ呼び口の個数を出力
1385 def gen_ph_n_cp f
1386
1387 b_comment = false
1388 @port.each { |p|
1389 next if p.get_port_type != :CALL
1390 next if p.is_omit?
1391 next if p.get_array_size == nil
1392
1393 if ! b_comment then
1394 f.printf( TECSMsg.get( :NCPA_comment ), "#_NCPA_#" )
1395 b_comment = true
1396 end
1397
1398 if p.get_array_size != "[]" then # 固定長配列
1399 f.print( "#define N_CP_#{p.get_name} (#{p.get_array_size})\n" )
1400 f.print( "#define NCP_#{p.get_name} (#{p.get_array_size})\n" )
1401 else # 可変長配列
1402 if @singleton then
1403 if has_INIB? then
1404 inib = "INIB"
1405 else
1406 inib = "CB"
1407 end
1408 f.print( "#define N_CP_#{p.get_name} (#{@global_name}_SINGLE_CELL_#{inib}.n_#{p.get_name})\n" )
1409 f.print( "#define NCP_#{p.get_name} (#{@global_name}_SINGLE_CELL_#{inib}.n_#{p.get_name})\n" )
1410 # mikan singleton ならば、固定長化できる
1411 else
1412 if has_CB? && has_INIB? then
1413 inib = "->_inib"
1414 else
1415 inib = ""
1416 end
1417 f.print( "#define N_CP_#{p.get_name}(p_that) ((p_that)#{inib}->n_#{p.get_name})\n" )
1418 f.print( "#define NCP_#{p.get_name} (N_CP_#{p.get_name}(p_cellcb))\n" )
1419 end
1420 end
1421 }
1422 end
1423
1424 #=== 受け口配列の大きさを得るマクロの出力
1425 #
1426 #セルタイプヘッダへ受け口の個数を出力
1427 def gen_ph_n_ep f
1428
1429 b_comment = false
1430 @port.each { |p|
1431 next if p.get_port_type != :ENTRY
1432 # next if p.is_omit? # 受け口配列の個数は省略しない
1433 next if p.get_array_size == nil
1434
1435 if ! b_comment then
1436 f.printf( TECSMsg.get( :NEPA_comment ), "#_NEPA_#" )
1437 b_comment = true
1438 end
1439
1440 if p.get_array_size != "[]" then # 固定長配列
1441 f.print( "#define NEP_#{p.get_name} (#{p.get_array_size})\n" )
1442 else # 可変長配列
1443 if @singleton then
1444 if has_INIB? then
1445 inib = "INIB"
1446 else
1447 inib = "CB"
1448 end
1449 f.print( "#define NEP_#{p.get_name} (#{@global_name}_SINGLE_CELL_#{inib}.n_#{p.get_name})\n" )
1450 # mikan singleton ならば、固定長化できる
1451 else
1452 if has_CB? && has_INIB? then
1453 inib = "->_inib"
1454 else
1455 inib = ""
1456 end
1457 f.print( "#define NEP_#{p.get_name} ((p_cellcb)#{inib}->n_#{p.get_name})\n" )
1458 end
1459 end
1460 }
1461 end
1462
1463 #=== optional な呼び口が結合されているかテストするコードの生成
1464 def gen_ph_test_optional_call_port f
1465 b_comment = false
1466
1467 if @singleton then
1468 if has_INIB? then
1469 inib = "INIB"
1470 else
1471 inib = "CB"
1472 end
1473 else
1474 if has_CB? && has_INIB? then
1475 inib = "->_inib"
1476 else
1477 inib = ""
1478 end
1479 end
1480
1481 @port.each { |p|
1482 next if p.get_port_type != :CALL
1483 next if ! p.is_optional?
1484 # next if p.is_omit? # omit でも test コードは生成する
1485
1486 if b_comment == false then
1487 f.printf( TECSMsg.get( :TOCP_comment ), "#_TOCP_#" )
1488 b_comment = true
1489 end
1490
1491 if @singleton then
1492 param = ""
1493 delim = ""
1494 else
1495 param = "p_that"
1496 delim = ","
1497 end
1498 if p.get_array_size != nil then
1499 param = param + delim + "subscript"
1500 end
1501 f.print( "#define #{@global_name}_is_#{p.get_name}_joined(#{param}) \\\n" )
1502
1503 if p.is_omit? then
1504 f.print( " omit is_#{p.get_name}_joined\n" )
1505 next
1506 end
1507
1508 # 関数名の出力(標準:受け口ディスクリプタから VMT の関数名、最適化:受け口関数 or 受け口ディスクリプタ)
1509 # mikan 全部つながっているかどうかで (1) を判定する
1510 if ! p.is_VMT_useless? then
1511 if p.is_dynamic? then
1512 if @singleton then
1513 inib_tmp = "CB"
1514 else
1515 inib_tmp = ""
1516 end
1517 else
1518 inib_tmp = inib
1519 end
1520
1521 # 標準コード
1522 if p.get_array_size == nil then
1523 if @singleton then
1524 f.print( "\t (#{@global_name}_SINGLE_CELL_#{inib_tmp}.#{p.get_name}!=0)\n" )
1525 else
1526 f.print( "\t ((p_that)#{inib_tmp}->#{p.get_name}!=0)\n" )
1527 end
1528 else
1529 # 配列の場合
1530 if @singleton then
1531 f.print( "\t ((#{@global_name}_SINGLE_CELL_#{inib_tmp}.#{p.get_name}!=0) \\\n" )
1532 f.print( "\t &&(#{@global_name}_SINGLE_CELL_#{inib_tmp}.#{p.get_name}[subscript]!=0))\n" )
1533 else
1534 f.print( "\t (((p_that)#{inib_tmp}->#{p.get_name}!=0)\\\n" )
1535 f.print( "\t &&((p_that)#{inib_tmp}->#{p.get_name}[subscript]!=0))\n" )
1536 end
1537 end
1538 else
1539 # 最適化コード (optimize) # VMT 不要(配列要素すべて同じ)
1540 p2 = p.get_real_callee_port
1541 if p2 then
1542 ct = p2.get_celltype
1543 if p.is_skelton_useless? then
1544 # 受け口関数を直接呼出す
1545 f.print( "\t (1)\n" )
1546 else
1547 # 受け口スケルトン関数を直接呼出す
1548 f.print( "\t (1)\n" )
1549 end
1550 else
1551 # optional で未結合
1552 f.print( "\t (0) /* not joined */\n" )
1553 end
1554 end
1555 }
1556 end
1557
1558 #=== optional な呼び口が結合されているかテストするコードの生成(短縮形)
1559 def gen_ph_test_optional_call_port_abbrev f
1560 b_comment = false
1561
1562 @port.each { |p|
1563 next if p.get_port_type != :CALL
1564 next if ! p.is_optional?
1565 # next if p.is_omit? # omit でも test コードは生成する
1566
1567 if b_comment == false then
1568 f.printf( TECSMsg.get( :TOCPA_comment ), "#_TOCPA_#" )
1569 b_comment = true
1570 end
1571
1572 if @singleton then
1573 param = ""
1574 delim = ""
1575 else
1576 param = "p_cellcb"
1577 delim = ","
1578 end
1579
1580 if p.get_array_size == nil then
1581 subscript = ""
1582 else
1583 subscript = "subscript"
1584 param = param + delim + subscript
1585 end
1586 f.print( "#define is_#{p.get_name}_joined(#{subscript})\\\n\t\t#{@global_name}_is_#{p.get_name}_joined(#{param})\n" )
1587 }
1588 end
1589
1590 #=== CELLCB へのポインタを得るマクロを出力
1591 # セルタイプヘッダへ出力
1592 def gen_ph_get_cellcb f
1593 f.printf( TECSMsg.get( :GCB_comment ), "#_GCB_#" )
1594 if ( ! has_CB? && ! has_INIB? ) || @singleton then
1595 f.print( "#define #{@global_name}_GET_CELLCB(idx) ((void *)0)\n" )
1596 elsif @idx_is_id_act then # mikan 単一のセルの場合の最適化, idx_is_id でない場合
1597 f.print( "#define #{@global_name}_GET_CELLCB(idx) (#{@global_name}_CB_tab[(idx) - #{@global_name}_ID_BASE])\n" )
1598 else
1599 f.print( "#define #{@global_name}_GET_CELLCB(idx) (idx)\n" )
1600 end
1601 end
1602
1603 #=== CELLCB へのポインタを得るマクロ(短縮形)を出力
1604 # セルタイプヘッダへ出力
1605 def gen_ph_get_cellcb_abbrev f
1606 f.printf( TECSMsg.get( :GCBA_comment ), "#_GCBA_#" )
1607 f.print("#define GET_CELLCB(idx) #{@global_name}_GET_CELLCB(idx)\n\n")
1608
1609 f.printf( TECSMsg.get( :CCT_comment ), "#_CCT_#" )
1610 f.print( "#define CELLCB\t#{@global_name}_CB\n\n" )
1611
1612 f.printf( TECSMsg.get( :CTIXA_comment ), "#_CTIXA_#" )
1613 f.print( "#define CELLIDX\t#{@global_name}_IDX\n\n" )
1614
1615 if @name != @global_name then
1616 f.print( "#define #{@name}_IDX #{@global_name}_IDX\n" )
1617 end
1618 end
1619
1620 #=== attribute, var をアクセスするマクロを出力
1621 # セルタイプヘッダへ出力
1622 def gen_ph_attr_access f
1623 if @n_attribute_rw > 0 || @n_attribute_ro > 0 then
1624 f.printf( TECSMsg.get( :AAM_comment ), "#_AAM_#" )
1625 end
1626
1627 @attribute.each { |a|
1628
1629 next if a.is_omit?
1630
1631 # mikan const_value の場合
1632 f.print( "#define " )
1633 if @singleton then
1634 if has_INIB? then
1635 inib = "INIB"
1636 else
1637 inib = "CB"
1638 end
1639 f.printf( "%-20s", "#{@global_name}_ATTR_#{a.get_name}" )
1640 f.print( "\t(#{@global_name}_SINGLE_CELL_#{inib}.#{a.get_name})\n" )
1641 # mikan ここでは cell ではなく celltype の名前
1642 else
1643 if ! a.is_rw? && has_CB? && has_INIB? then
1644 inib = "->_inib"
1645 else
1646 inib = ""
1647 end
1648 f.printf( "%-20s", "#{@global_name}_ATTR_#{a.get_name}( p_that )" )
1649 f.print( "\t((p_that)#{inib}->#{a.get_name})\n" )
1650 end
1651 }
1652 f.print( "\n" )
1653
1654 @attribute.each { |a|
1655
1656 next if a.is_omit?
1657
1658 if @singleton then
1659 if has_INIB? then
1660 inib = "INIB"
1661 else
1662 inib = "CB"
1663 end
1664 else
1665 if ! a.is_rw? && has_CB? && has_INIB? then
1666 inib = "->_inib"
1667 else
1668 inib = ""
1669 end
1670 end
1671
1672 # mikan const_value の場合
1673 f.print( "#define " )
1674 if @singleton then
1675 f.printf( "%-20s", "#{@global_name}_GET_#{a.get_name}()" )
1676 f.print( "\t(#{@global_name}_SINGLE_CELL_#{inib}.#{a.get_name})\n" )
1677 # mikan ここでは cell ではなく celltype の名前
1678 else
1679 f.printf( "%-20s", "#{@global_name}_GET_#{a.get_name}(p_that)" )
1680 f.print( "\t((p_that)#{inib}->#{a.get_name})\n" )
1681 end
1682
1683 if a.is_rw? then
1684 f.print( "#define " )
1685 if @singleton then
1686 f.printf( "%-20s", "#{@global_name}_SET_#{a.get_name}(val)" )
1687 f.print( "\t(#{@global_name}_SINGLE_CELL_#{inib}.#{a.get_name} = (val))\n" )
1688 # mikan ここでは cell ではなく celltype の名前
1689 else
1690 f.printf( "%-20s", "#{@global_name}_SET_#{a.get_name}(p_that,val)" )
1691 f.print( "\t((p_that)#{inib}->#{a.get_name}=(val))\n" )
1692 end
1693 end
1694
1695 }
1696 f.print( "\n" )
1697
1698 if @n_var > 0 then
1699 f.printf( TECSMsg.get( :VAM_comment ), "#_VAM_#" )
1700 end
1701
1702 @var.each { |v|
1703
1704 next if v.is_omit?
1705
1706 if @singleton then
1707 if v.get_size_is && has_INIB? then
1708 inib = "INIB"
1709 else
1710 inib = "CB"
1711 end
1712 else
1713 if v.get_size_is && has_CB? && has_INIB? then
1714 inib = "->_inib"
1715 else
1716 inib = ""
1717 end
1718 end
1719
1720 # mikan const_value の場合
1721 f.print( "#define " )
1722 if @singleton then
1723 f.printf( "%-20s", "#{@global_name}_VAR_#{v.get_name}" )
1724 f.print( "\t(#{@global_name}_SINGLE_CELL_#{inib}.#{v.get_name})\n" )
1725 # mikan ここでは cell ではなく celltype の名前
1726 else
1727 f.printf( "%-20s", "#{@global_name}_VAR_#{v.get_name}(p_that)" )
1728 f.print( "\t((p_that)#{inib}->#{v.get_name})\n" )
1729 end
1730 }
1731 f.print( "\n" )
1732 @var.each { |v|
1733
1734 next if v.is_omit?
1735
1736 # mikan const_value の場合
1737 f.print( "#define " )
1738 if @singleton then
1739 f.printf( "%-20s", "#{@global_name}_GET_#{v.get_name}()" )
1740 f.print( "\t(#{@global_name}_SINGLE_CELL_CB.#{v.get_name})\n" )
1741 # mikan ここでは cell ではなく celltype の名前
1742 else
1743 f.printf( "%-20s", "#{@global_name}_GET_#{v.get_name}(p_that)" )
1744 f.print( "\t((p_that)->#{v.get_name})\n" )
1745 end
1746
1747 f.print( "#define " )
1748 if @singleton then
1749 f.printf( "%-20s", "#{@global_name}_SET_#{v.get_name}(val)" )
1750 f.print( "\t(#{@global_name}_SINGLE_CELL_CB.#{v.get_name}=(val))\n" )
1751 # mikan ここでは cell ではなく celltype の名前
1752 else
1753 f.printf( "%-20s", "#{@global_name}_SET_#{v.get_name}(p_that,val)" )
1754 f.print( "\t((p_that)->#{v.get_name}=(val))\n" )
1755 end
1756 }
1757 f.print( "\n" )
1758
1759 end
1760
1761 #=== attribute/var アクセスマクロ(短縮形)コードの生成
1762 def gen_ph_attr_access_abbrev f
1763 if @n_attribute_rw > 0 || @n_attribute_ro > 0 then
1764 f.printf( TECSMsg.get( :AAMA_comment ), "#_AAMA_#" )
1765 end
1766
1767 @attribute.each { |a|
1768 next if a.is_omit?
1769
1770 # mikan const_value の場合
1771 f.print( "#define " )
1772 f.printf( "%-20s", "ATTR_#{a.get_name}" )
1773 f.print( " #{@global_name}_ATTR_#{a.get_name}" )
1774 if ! @singleton then
1775 f.print( "( p_cellcb )" )
1776 end
1777 f.print "\n"
1778 }
1779 f.print( "\n" )
1780
1781 if @n_var > 0 then
1782 f.printf( TECSMsg.get( :VAMA_comment ), "#_VAMA_#" )
1783 end
1784
1785 @var.each { |v|
1786 next if v.is_omit?
1787
1788 # mikan const_value の場合
1789 f.print( "#define " )
1790 f.printf( "%-20s", "VAR_#{v.get_name}" )
1791 f.print( " #{@global_name}_VAR_#{v.get_name}" )
1792 if ! @singleton then
1793 f.print( "( p_cellcb )" )
1794 end
1795 f.print( "\n" )
1796 }
1797 f.print( "\n" )
1798
1799 end
1800
1801 def gen_ph_cp_fun_macro f
1802 if @n_call_port >0 then
1803 f.printf( TECSMsg.get( :CPM_comment ) , "#_CPM_#" )
1804 end
1805
1806 @port.each { |p|
1807 next if p.get_port_type != :CALL
1808 next if p.is_omit?
1809
1810 p.get_signature.get_function_head_array.each{ |fun|
1811 if @singleton then
1812 if has_INIB? then
1813 inib = "INIB"
1814 else
1815 inib = "CB"
1816 end
1817 if p.is_dynamic? && p.get_array_size == nil then
1818 # dynamic call port (not array)
1819 inib = "CB"
1820 end
1821 else
1822 if has_CB? && has_INIB? then
1823 inib = "->_inib"
1824 else
1825 inib = ""
1826 end
1827 if p.is_dynamic? && p.get_array_size == nil then
1828 # dynamic call port (not array)
1829 inib = ""
1830 end
1831 end
1832
1833 f.print( "#define #{@global_name}_#{p.get_name}_#{fun.get_name}(" )
1834 ft = fun.get_declarator.get_type
1835 delim = ""
1836
1837 if ! @singleton then
1838 f.print( "#{delim} p_that" )
1839 delim = ","
1840 end
1841
1842 if p.get_array_size then
1843 f.print( "#{delim} subscript" )
1844 delim = ","
1845 end
1846
1847 ft.get_paramlist.get_items.each{ |param|
1848 f.print( "#{delim} #{param.get_name}" )
1849 delim = ","
1850 }
1851 f.print( " ) \\\n" )
1852
1853 subsc = ""
1854 subsc = "[subscript]" if p.get_array_size
1855 delim = ""
1856
1857 # 関数名の出力(標準:受け口ディスクリプタから VMT の関数名、最適化:受け口関数 or 受け口ディスクリプタ)
1858 if ! p.is_VMT_useless? then
1859 # 標準コード
1860 if @singleton then
1861 f.print( "\t #{@global_name}_SINGLE_CELL_#{inib}.#{p.get_name}" )
1862 else
1863 f.print( "\t (p_that)#{inib}->#{p.get_name}" )
1864 end
1865 f.print( "#{subsc}->VMT->#{fun.get_name}__T( \\\n" )
1866 else
1867 # 最適化コード (optimize) # VMT 不要
1868 p2 = p.get_real_callee_port
1869 if p2 then
1870 ct = p2.get_celltype
1871 if p.is_skelton_useless? then
1872 # 受け口関数を直接呼出す
1873 f.print( "\t #{ct.get_global_name}_#{p2.get_name}_#{fun.get_name}( \\\n" )
1874 else
1875 # 受け口スケルトン関数を直接呼出す
1876 f.print( "\t #{ct.get_global_name}_#{p2.get_name}_#{fun.get_name}_skel( \\\n" )
1877 # print "skelton: #{@name} #{ct.get_global_name}_#{p2.get_name}\n"
1878 end
1879 else
1880 # optional で未結合
1881 f.print( "\t ((#{fun.get_declarator.get_type.get_type.get_type_str} (*)()" )
1882 f.print( "#{fun.get_declarator.get_type.get_type.get_type_str_post})0)()\n" )
1883 f.print( "\t /* optional no entry port joined */\n" )
1884 if ! p.is_optional? then
1885 raise "unjoined but not optional celltype: #{@name} #{p.get_name}"
1886 end
1887 end
1888 end
1889
1890 b_join = true # optional で結合していない場合 false
1891
1892 # 受け口情報の出力(標準:受け口ディスクリプタ、最適化:IDX など)
1893 if ! p.is_skelton_useless? && ! p.is_cell_unique? then
1894 # 標準コード
1895 if @singleton then
1896 f.print( "\t #{@global_name}_SINGLE_CELL_#{inib}.#{p.get_name}#{subsc}" )
1897 delim = ","
1898 else
1899 f.print( "\t (p_that)#{inib}->#{p.get_name}#{subsc}" )
1900 delim = ","
1901 end
1902 else
1903 # 最適化コード (optimize) # スケルトン不要
1904 c2 = p.get_real_callee_cell # 唯一のセル(でない場合もある、複数セルがある場合)
1905 p2 = p.get_real_callee_port # 唯一のポート(でない場合は、ない)
1906 if p2 then
1907 ct = p2.get_celltype # 呼び先のセルタイプ
1908 if ! ct.is_singleton? then
1909 if ct.has_CB? || ct.has_INIB? then
1910 if p.is_cell_unique? then
1911 name_array = ct.get_name_array( c2 )
1912 f.print( "\t #{name_array[7]}" )
1913 else
1914 # CELLCB IDX を渡す (標準コードと同じだが、扱う型は異なる)
1915 # p.is_skelton_useless? == true/false ともに同じ
1916 f.print( "\t (p_that)#{inib}->#{p.get_name}#{subsc}" )
1917 end
1918 else
1919 f.print( "\t (#{ct.get_global_name}_IDX)0" )
1920 end
1921 delim = ","
1922 else
1923 f.print( "\t " )
1924 end
1925 else
1926 # optional で未結合
1927 b_join = false
1928 end
1929 end
1930
1931 if b_join then
1932 ft.get_paramlist.get_items.each{ |param|
1933 f.print( "#{delim} (#{param.get_name})" )
1934 delim = ","
1935 }
1936 f.print( " )\n" )
1937 end
1938 }
1939 }
1940 f.print( "\n" )
1941 end
1942
1943 #=== ref_desc 指定された呼び口に対するディスクリプタ参照関数の生成
1944 def gen_ph_ref_desc_func f
1945 if @n_call_port_ref_desc >0 then
1946 f.printf( TECSMsg.get( :CRD_comment ), "#_CRD_#" )
1947 end
1948
1949 if has_CB? && has_INIB? then
1950 inib = "->_inib"
1951 else
1952 inib = ""
1953 end
1954 @port.each { |p|
1955 next if p.get_port_type != :CALL
1956 next if ! p.is_ref_desc?
1957
1958 if @singleton then
1959 p_that = ""
1960 p_cellcb = ""
1961 delim = ""
1962 if has_INIB? then
1963 cb = "#{@global_name}_SINGLE_CELL_INIB."
1964 else
1965 cb = "#{@global_name}_SINGLE_CELL_CB."
1966 end
1967 else
1968 p_that = "#{@global_name}_CB *p_that"
1969 p_cellcb = " #{@global_name}_CB *p_cellcb = p_that;\n"
1970 delim = ", "
1971 cb = "p_that#{inib}->"
1972 end
1973
1974 if p.get_array_size
1975 array = "#{delim}int_t i "
1976 array2 = "[ i ]"
1977 assert = " assert( 0 <= i && i < NCP_#{p.get_name} );\n"
1978 else
1979 array = ""
1980 array2 = ""
1981 assert = ""
1982 end
1983 f.print <<EOT
1984/* [ref_desc] #{p.get_name} */
1985Inline Descriptor( #{p.get_signature.get_global_name} )
1986#{@global_name}_#{p.get_name}_refer_to_descriptor( #{p_that}#{array} )
1987{
1988 Descriptor( #{p.get_signature.get_global_name} ) des;
1989#{p_cellcb} /* cast is ncecessary for removing 'const' */
1990#{assert} des.vdes = (struct tag_#{p.get_signature.get_global_name}_VDES *)#{cb}#{p.get_name}#{array2};
1991 return des;
1992}
1993
1994EOT
1995 }
1996 end
1997
1998 #=== dynamic 指定された呼び口に対するディスクリプタ設定関数の生成
1999 def gen_ph_set_desc_func f
2000 if @n_call_port_dynamic >0 then
2001 f.printf( TECSMsg.get( :SDF_comment ), "#_SDF_#" )
2002 end
2003
2004 @port.each { |p|
2005 next if p.get_port_type != :CALL
2006 next if ! p.is_dynamic?
2007 if has_CB? && has_INIB? && p.get_array_size then
2008 inib = "->_inib"
2009 else
2010 inib = ""
2011 end
2012 if @singleton then
2013 # p "main== #{@global_name} #{p.get_name} #{p.get_array_size}"
2014 p_that = ""
2015 p_that2 = ""
2016 p_cellcb = ""
2017 if p.get_array_size && $rom then
2018 cb = "#{@global_name}_SINGLE_CELL_INIB."
2019 else
2020 cb = "#{@global_name}_SINGLE_CELL_CB."
2021 end
2022 else
2023 p_that = "#{@global_name}_CB *p_that, "
2024 p_that2 = "#{@global_name}_CB *p_that "
2025 p_cellcb = " #{@global_name}_CB *p_cellcb = p_that;\n"
2026 cb = "(p_cellcb)->#{inib}"
2027 end
2028
2029 if p.get_array_size then
2030 array = "int_t i, "
2031 array2 = "[ i ]"
2032 array3 = " int_t i "
2033 assert2 = " assert( 0 <= i && i < NCP_#{p.get_name} );\n"
2034 else
2035 array = ""
2036 array2 = ""
2037 array3 = ""
2038 assert2 = ""
2039 end
2040 f.print <<EOT
2041/* [dynamic] #{p.get_name} */
2042Inline void
2043#{@global_name}_#{p.get_name}_set_descriptor( #{p_that}#{array}Descriptor( #{p.get_signature.get_global_name} ) des )
2044{
2045#{p_cellcb} assert( des.vdes != NULL );
2046#{assert2} #{cb}#{p.get_name}#{array2} = des.vdes;
2047}
2048
2049EOT
2050
2051 if p.is_optional? then
2052 if p_that2 != "" && array3 != "" then
2053 delim = ", "
2054 else
2055 delim = ""
2056 end
2057 f.print <<EOT
2058/* [dynamic,optional] #{p.get_name} */
2059Inline void
2060#{@global_name}_#{p.get_name}_unjoin( #{p_that2}#{delim}#{array3} )
2061{
2062#{p_cellcb} #{cb}#{p.get_name}#{array2} = NULL;
2063}
2064
2065EOT
2066 end
2067 }
2068 end
2069
2070 #=== send/receive で受け取ったメモリ領域を dealloc するマクロコード
2071 #f:: File
2072 #b_undef:: bool : true = #undef コードの生成, false = #define コードの生成
2073 def gen_ph_dealloc_code( f, append_name, b_undef = false )
2074 b_msg = false
2075 @port.each{ |p|
2076 next if p.is_omit?
2077
2078 p.each_param{ |port, fd, par|
2079 case par.get_direction # 引数の方向指定子 (in, out, inout, send, receive )
2080 when :SEND
2081 # next if port.get_port_type == :CALL
2082 type = par.get_declarator.get_type
2083 pre = "("
2084 post = ")"
2085 when :RECEIVE
2086 # next if port.get_port_type == :ENTRY
2087 type = par.get_declarator.get_type.get_type
2088# pre = "(*"
2089# post = ")"
2090 pre = "("
2091 post = ")"
2092 else
2093 next
2094 end
2095
2096 # ポート名 関数名 パラメータ名
2097 dealloc_func_name = "#{port.get_name}_#{fd.get_name}_#{par.get_name}_dealloc"
2098 dealloc_macro_name = dealloc_func_name.upcase
2099 name = par.get_name
2100
2101 if b_undef == false
2102 if (type.get_size || type.get_count) && type.get_type.has_pointer?
2103 count_str = "count__"
2104 count_str2 = ", count__"
2105 else
2106 count_str = nil
2107 count_str2 = nil
2108 end
2109 if ! b_msg
2110 f.print "\n"
2111 f.printf TECSMsg.get( :DAL_comment ), "#_DAL_# #{append_name}"
2112 b_msg = true
2113 end
2114 f.print "#define #{dealloc_macro_name}#{append_name}(#{name}#{count_str2})"
2115 if append_name == "_RESET" then
2116 gen_dealloc_code_for_type( f, type, dealloc_func_name, pre, name, post, 0, true, count_str )
2117 else
2118 gen_dealloc_code_for_type( f, type, dealloc_func_name, pre, name, post, 0, false, count_str )
2119 end
2120 f.print "\n"
2121 else
2122 f.print "#undef #{dealloc_macro_name}#{append_name}\n"
2123 end
2124 }
2125 }
2126 end
2127
2128 def gen_ph_cp_fun_macro_abbrev f
2129 if @n_call_port >0 then
2130 f.printf( TECSMsg.get( :CPMA_comment ), "#_CPMA_#" )
2131 end
2132
2133 @port.each { |p|
2134 next if p.get_port_type != :CALL
2135 # next if p.is_omit? 呼び出すとエラーを起こすコードを生成
2136
2137 p.get_signature.get_function_head_array.each{ |fun|
2138 if p.is_VMT_useless? && ! @singleton then
2139 dummy_p_cell_access_pre = "((void)p_cellcb, "
2140 dummy_p_cell_access_post = ")"
2141 else
2142 dummy_p_cell_access_pre = ""
2143 dummy_p_cell_access_post = ""
2144 end
2145
2146 if ! p.is_require? || p.has_name? then
2147 f.print( "#define #{p.get_name}_#{fun.get_name}(" )
2148 else
2149 f.print( "#define #{fun.get_name}(" )
2150 end
2151 ft = fun.get_declarator.get_type
2152 delim = ""
2153
2154# if ! @singleton then
2155# f.print( "#{delim} p_that" )
2156# delim = ","
2157# end
2158
2159 if p.get_array_size then
2160 f.print( "#{delim} subscript" )
2161 delim = ","
2162 end
2163
2164 ft.get_paramlist.get_items.each{ |param|
2165 f.print( "#{delim} #{param.get_name}" )
2166 delim = ","
2167 }
2168 f.print( " ) \\\n" )
2169
2170 if p.is_omit? then
2171 f.print( " #{dummy_p_cell_access_pre}omitted #{p.get_name}_#{fun.get_name}(" )
2172 else
2173 f.print( " #{dummy_p_cell_access_pre}#{@global_name}_#{p.get_name}_#{fun.get_name}(" )
2174 end
2175 ft = fun.get_declarator.get_type
2176 delim = ""
2177
2178 if ! @singleton then
2179 f.print( "#{delim} p_cellcb" )
2180 delim = ","
2181 end
2182
2183 if p.get_array_size then
2184 f.print( "#{delim} subscript" )
2185 delim = ","
2186 end
2187
2188 ft.get_paramlist.get_items.each{ |param|
2189 f.print( "#{delim} #{param.get_name}" )
2190 delim = ","
2191 }
2192 f.print( " )#{dummy_p_cell_access_post}\n" )
2193 }
2194 }
2195 f.print( "\n" )
2196 end
2197
2198 def gen_ph_ref_desc_macro_abbrev f
2199 if @n_call_port_ref_desc >0 then
2200 f.printf( TECSMsg.get( :CRDA_comment ), "#_CRDA_#" )
2201 end
2202
2203 @port.each { |p|
2204 next if p.get_port_type != :CALL
2205 next if ! p.is_ref_desc?
2206
2207 if @singleton then
2208 p_cellcb = ""
2209 delim = ""
2210 else
2211 p_cellcb = "p_cellcb"
2212 delim = ", "
2213 end
2214
2215 if p.get_array_size then
2216 array = " i "
2217 array2 = "#{delim}i"
2218 else
2219 array = ""
2220 array2 = ""
2221 end
2222
2223 f.printf( "#define %s_refer_to_descriptor(#{array})\\\n %s_refer_to_descriptor( #{p_cellcb}#{array2} )\n",
2224 "#{p.get_name}",
2225 "#{@global_name}_#{p.get_name}" )
2226 f.printf( "#define %s_ref_desc(#{array})\\\n %s_refer_to_descriptor(#{array})\n",
2227 "#{p.get_name}",
2228 "#{p.get_name}" )
2229 }
2230 f.print( "\n" )
2231 end
2232
2233 def gen_ph_set_desc_macro_abbrev f
2234 if @n_call_port_dynamic >0 then
2235 f.printf( TECSMsg.get( :SDMA_comment ), "#_SDMA_#" )
2236 end
2237
2238 if @singleton then
2239 p_cellcb = ""
2240 delim = ""
2241 else
2242 p_cellcb = "p_cellcb"
2243 delim = ", "
2244 end
2245 @port.each { |p|
2246 next if p.get_port_type != :CALL
2247 next if ! p.is_dynamic?
2248
2249 if p.get_array_size then
2250 subsc = "i, "
2251 subsc2 = "i"
2252 subsc3 = delim + subsc2
2253 else
2254 subsc = ""
2255 subsc2 = ""
2256 subsc3 = ""
2257 end
2258 f.printf( "#define %s_set_descriptor( #{subsc}desc )\\\n %s_set_descriptor( #{p_cellcb}#{delim}#{subsc}desc )\n",
2259 "#{p.get_name}",
2260 "#{@global_name}_#{p.get_name}" )
2261 f.printf( "#define %s_unjoin( #{subsc2} )\\\n %s_unjoin( #{p_cellcb}#{subsc3} )\n",
2262 "#{p.get_name}",
2263 "#{@global_name}_#{p.get_name}" )
2264 }
2265 f.print( "\n" )
2266 end
2267
2268 def gen_ph_ep_fun_macro f
2269 if @n_entry_port >0 then
2270 f.printf( TECSMsg.get( :EPM_comment ), "#_EPM_#" )
2271 end
2272
2273 @port.each { |p|
2274 next if p.get_port_type != :ENTRY
2275 next if p.is_omit?
2276
2277 p.get_signature.get_function_head_array.each{ |fun|
2278 f.printf( "#define %-16s %s\n",
2279 "#{p.get_name}_#{fun.get_name}",
2280 "#{@global_name}_#{p.get_name}_#{fun.get_name}" )
2281 }
2282 }
2283 f.print( "\n" )
2284
2285 end
2286
2287 def gen_ph_typedef_idx f
2288 f.printf( TECSMsg.get( :CTIX_comment ), "#_CTIX_#" )
2289 if @idx_is_id_act then
2290 f.print( "typedef ID #{@global_name}_IDX;\n" )
2291 else
2292 if has_CB? then
2293 f.print( "typedef struct tag_#{@global_name}_CB *#{@global_name}_IDX;\n" )
2294 elsif has_INIB? then
2295 f.print( "typedef const struct tag_#{@global_name}_INIB *#{@global_name}_IDX;\n" )
2296 else
2297 f.print( "typedef int #{@global_name}_IDX;\n" )
2298 end
2299 end
2300
2301 end
2302
2303 def gen_ph_idx_type f
2304 if @idx_is_id_act then
2305 f.print( "ID" )
2306 else
2307 if has_CB? then
2308 f.print( "struct tag_#{@global_name}_CB *" )
2309 elsif has_INIB? then
2310 # f.print( "struct tag_#{@global_name}_INIB *" ) # const を出力していない
2311 f.print( "const struct tag_#{@global_name}_INIB *" )
2312 else
2313 f.print( "int" )
2314 end
2315 end
2316
2317 end
2318
2319 def gen_ph_ep_fun_prototype f
2320 if @n_entry_port >0 then
2321 f.printf( TECSMsg.get( :EPP_comment ), "#_EPP_#" )
2322 end
2323
2324 @port.each { |p|
2325 next if p.get_port_type != :ENTRY
2326 next if p.is_omit?
2327
2328 f.print( "/* #{p.get_signature.get_global_name} */\n" )
2329
2330 p.get_signature.get_function_head_array.each{ |fun|
2331 if p.is_inline? then
2332 f.print( "Inline " )
2333 end
2334 functype = fun.get_declarator.get_type
2335 f.printf( "%-12s", functype.get_type_str )
2336
2337 f.print( " #{@global_name}_#{p.get_name}_#{fun.get_name}(" )
2338 if @singleton then
2339 delim = ""
2340 else
2341 f.print( "#{@global_name}_IDX idx" )
2342 delim = ","
2343 end
2344
2345 if p.get_array_size then
2346 f.print( "#{delim} int_t subscript" ) # mikan singleton 時の ',' の始末
2347 delim = ","
2348 end
2349
2350 if functype.get_paramlist then
2351 items = functype.get_paramlist.get_items
2352 len = items.length
2353 else
2354 # ここで nil になるのは、引数なしの時に void がなかった場合
2355 items = []
2356 len = 0
2357 end
2358 i = 0
2359 items.each{ |param|
2360 f.print "#{delim} "
2361 delim = ","
2362 f.print( param.get_type.get_type_str )
2363 f.print( " " )
2364 f.print( param.get_name )
2365 f.print( param.get_type.get_type_str_post )
2366 i += 1
2367 }
2368 f.print( ");\n" )
2369
2370 }
2371 }
2372 end
2373
2374 def gen_ph_ep_skel_prototype f
2375 # 受け口スケルトン関数のプロトタイプ宣言を出力
2376 if @n_entry_port >0 then
2377 f.printf( TECSMsg.get( :EPSP_comment ), "#_EPSP_#" )
2378 end
2379 @port.each { |p|
2380 next if p.get_port_type != :ENTRY
2381 next if p.is_omit?
2382# if p.is_skelton_useless? || ! p.is_VMT_useless? then # 受け口最適化
2383 if p.is_skelton_useless? then # 受け口最適化
2384# f.print( "/* #{p.get_name} : omitted by entry port optimize */\n" )
2385 next
2386 end
2387
2388 f.print( "/* #{p.get_name} */\n" )
2389
2390 p.get_signature.get_function_head_array.each{ |fun|
2391 functype = fun.get_declarator.get_type
2392 f.printf "%-14s", functype.get_type_str
2393
2394 f.print " #{@global_name}_#{p.get_name}_#{fun.get_name}_skel("
2395 f.print " const struct tag_#{p.get_signature.get_global_name}_VDES *epd"
2396 delim = ","
2397
2398 if functype.get_paramlist then
2399 items = functype.get_paramlist.get_items
2400 len = items.length
2401 else
2402 # ここで nil になるのは、引数なしの時に void がなかった場合
2403 items = []
2404 len = 0
2405 end
2406 i = 0
2407 items.each{ |param|
2408 f.print "#{delim} "
2409 delim = ","
2410 f.print param.get_type.get_type_str
2411 f.print " "
2412 f.print param.get_name
2413 f.print param.get_type.get_type_str_post
2414 i += 1
2415 }
2416 f.print ");\n"
2417 }
2418 }
2419 f.print( "\n" )
2420 end
2421
2422 def gen_ph_cell_cb_type f
2423
2424 if ( $rom )then
2425 # 定数部は ROM, 変数部は RAM
2426
2427 if has_INIB? then
2428
2429 f.printf( TECSMsg.get( :CIP_comment ), "#_CIP_#" )
2430 f.print( "typedef const struct tag_#{@global_name}_INIB {\n" )
2431
2432 gen_cell_cb_type_port( f, :INIB )
2433 gen_cell_cb_type_attribute( f, :INIB )
2434
2435 f.print( "} #{@global_name}_INIB;\n" )
2436
2437 end
2438
2439 if has_CB? then
2440 f.printf( TECSMsg.get( :CCTPA_comment ), "#_CCTPA_#" )
2441 f.print( "typedef struct tag_#{@global_name}_CB {\n" )
2442 if has_INIB? then
2443 f.print " #{@global_name}_INIB *_inib;\n"
2444 end
2445 gen_cell_cb_type_port( f, :CB_DYNAMIC )
2446 gen_cell_cb_type_attribute( f, :CB )
2447 gen_cell_cb_type_var f
2448 f.print( "} #{@global_name}_CB;\n" )
2449 end
2450
2451 if ! has_CB? && ! has_INIB? then
2452 f.printf( TECSMsg.get( :CCDP_comment ), "#_CCDP_#" )
2453 f.print( "typedef struct tag_#{@global_name}_CB {\n" )
2454 f.print( " int dummy;\n" )
2455 f.print( "} #{@global_name}_CB;\n" )
2456 end
2457
2458 else
2459 # 全て RAM
2460 f.printf( TECSMsg.get( :CCTPO_comment ), "#_CCTPO_#" )
2461
2462 f.print( "typedef struct tag_#{@global_name}_CB {\n" )
2463
2464 gen_cell_cb_type_port( f, :CB )
2465 gen_cell_cb_type_attribute( f, :CB )
2466 gen_cell_cb_type_var f
2467
2468 f.print( "} #{@global_name}_CB;\n" )
2469 end
2470 end
2471
2472
2473 #=== attribute の型宣言出力
2474 #inib_cb:: :INIB または :CB
2475 def gen_cell_cb_type_attribute( f, inib_cb )
2476 if inib_cb == :INIB && @n_attribute_ro > 0 then
2477 f.print " /* attribute(RO) #_ATO_# */ \n"
2478 elsif inib_cb == :CB then
2479 if $rom then
2480 if @n_attribute_rw > 0 then
2481 f.print " /* attribute(RW) #_ATW_# */ \n"
2482 end
2483 else
2484 if @n_attribute_rw > 0 || @n_attribute_ro > 0 then
2485 f.print " /* attribute #_AT_# */ \n"
2486 end
2487 end
2488 end
2489
2490 @attribute.each{ |a|
2491 next if a.is_omit?
2492 next if inib_cb == :INIB && a.is_rw?
2493 next if has_INIB? && inib_cb == :CB && ! a.is_rw?
2494
2495 if a.get_type.kind_of?( PtrType ) && ! a.get_type.is_const? && a.get_size_is then
2496 const_str = "const "
2497 else
2498 const_str = ""
2499 end
2500 f.print " "
2501 f.printf( "#{const_str}%-14s", a.get_type.get_type_str )
2502 f.print " #{a.get_name}#{a.get_type.get_type_str_post};\n"
2503 }
2504 @var.each { |v|
2505 next if v.is_omit?
2506 next if v.get_size_is == nil
2507 next if $rom && inib_cb == :CB # size_is 指定されたものは INIB にのみ出力する
2508
2509 f.print " "
2510 f.printf( "%-14s", v.get_type.get_type_str )
2511 f.print " #{v.get_name}#{v.get_type.get_type_str_post};\n"
2512 }
2513 end
2514
2515 def gen_cell_cb_type_var f
2516 # 変数の出力
2517 if @n_var > 0 then
2518 f.print " /* var #_VA_# */ \n"
2519 end
2520
2521 @var.each{ |v|
2522
2523 next if v.is_omit?
2524 next if v.get_size_is != nil # size_is 指定された var は attribute へ出力する
2525
2526 f.print " "
2527 f.printf( "%-14s", v.get_type.get_type_str )
2528 f.print " #{v.get_name}#{v.get_type.get_type_str_post};\n"
2529 }
2530 end
2531
2532 def gen_cell_cb_type_port( f, inib_cb )
2533 gen_cell_cb_type_call_port( f, inib_cb )
2534 gen_cell_cb_type_entry_port( f, inib_cb )
2535 end
2536
2537 def gen_cell_cb_type_call_port( f, inib_cb )
2538 # 呼び口
2539 if @n_call_port >0 then
2540 f.print " /* call port #_TCP_# */\n"
2541 end
2542
2543 @port.each{ |p|
2544 next if p.get_port_type != :CALL
2545 next if p.is_omit?
2546 next if inib_cb == :INIB && p.is_dynamic? && p.get_array_size == nil && ! $ram_initializer
2547 next if inib_cb == :CB_DYNAMIC && ( ! p.is_dynamic? || p.get_array_size != nil )
2548 # bprint "cb_type #{inib_cb} #{p.get_name} dynamic=#{p.is_dynamic?}\n"
2549
2550 ptr = p.get_array_size ? '*' : ''
2551
2552 if ! p.is_cell_unique? then
2553 const = p.is_dynamic? ? '' : 'const'
2554 if inib_cb == :INIB && p.is_dynamic? && p.get_array_size == nil && $ram_initializer then
2555 init = '_init_'
2556 const2 = 'const'
2557 else
2558 init = ''
2559 const2 = 'const'
2560 end
2561
2562 if ! p.is_skelton_useless? then
2563 # 標準形
2564 if inib_cb == :INIB && p.is_dynamic? && p.get_array_size != nil && $ram_initializer then
2565 f.print( " struct tag_#{p.get_signature.get_global_name}_VDES #{ptr}#{const2}*#{p.get_name;}_init_;\n" )
2566 end
2567 f.print( " struct tag_#{p.get_signature.get_global_name}_VDES #{ptr}#{const}*#{p.get_name;}#{init};\n" )
2568# f.print( " struct tag_#{p.get_signature.get_global_name}_VDES #{ptr}*#{p.get_name;};\n" )
2569 if p.get_array_size == "[]" then
2570 f.print( " int_t n_#{p.get_name};\n" )
2571 end
2572 else
2573 # 最適化 skelton 関数を呼出さない(受け口関数を直接呼出す)
2574 # 呼び先セルタイプの CB の IDX 型
2575 if p.get_real_callee_cell then
2576 f.print( " " )
2577 p.get_real_callee_cell.get_celltype.gen_ph_idx_type f
2578 f.print( " #{ptr}#{p.get_name;};\n" )
2579 # 相互参照に備えて、typedef した型を使わない
2580 # f.print( " #{p.get_real_callee_cell.get_celltype.get_global_name}_IDX #{ptr}#{p.get_name;};\n" )
2581 if p.get_array_size == "[]" then
2582 f.print( " int_t n_#{p.get_name};\n" )
2583 end
2584 #else
2585 # optional で未結合
2586 end
2587 end
2588 # else
2589 # 最適化 一つしかセルがない場合、受け口ディスクリプタまたは受け側の IDX は呼び口関数マクロに埋め込まれる
2590 end
2591 }
2592 end
2593
2594 #=== Celltype#受け口配列添数を記憶する変数の定義
2595 def gen_cell_cb_type_entry_port( f, inib_cb )
2596 # 呼び口
2597 if @n_entry_port >0 then
2598 f.print " /* call port #_NEP_# */ \n"
2599 end
2600
2601 @port.each{ |p|
2602 # next if p.is_omit? # 受け口配列の個数は省略しない
2603 if p.get_port_type == :ENTRY && p.get_array_size == "[]"
2604 f.print( " int_t n_#{p.get_name};\n" )
2605 end
2606 }
2607 end
2608
2609 def gen_ph_extern_cell f
2610 if @singleton then
2611 f.printf( TECSMsg.get( :SCP_comment ), "#_SCP_#" )
2612 if has_CB? then
2613 f.print "extern #{@global_name}_CB #{@global_name}_SINGLE_CELL_CB;\n"
2614 end
2615 if has_INIB? then
2616 f.print "extern #{@global_name}_INIB #{@global_name}_SINGLE_CELL_INIB;\n"
2617 end
2618
2619# @ordered_cell_list.each{ |c|
2620# f.print "extern #{@global_name}_CB #{@global_name}_#{c.get_name}_CB;\n"
2621# }
2622
2623 f.print "\n"
2624 elsif @idx_is_id_act then
2625 f.print "extern #{@global_name}_CB *#{@global_name}_CB_tab[];\n"
2626 else
2627 f.print "extern #{@global_name}_CB #{@global_name}_CB_tab[];\n"
2628 end
2629 end
2630
2631 def gen_ph_INIB_as_CB f
2632
2633 if ! has_CB? && has_INIB? then
2634 f.printf( TECSMsg.get( :DCI_comment ), "#_DCI_#" )
2635 f.print "#define #{@global_name}_CB_tab #{@global_name}_INIB_tab\n"
2636 f.print "#define #{@global_name}_SINGLE_CELL_CB #{@global_name}_SINGLE_CELL_INIB\n"
2637 f.print "#define #{@global_name}_CB #{@global_name}_INIB\n"
2638 f.print "#define tag_#{@global_name}_CB tag_#{@global_name}_INIB\n"
2639 f.print "\n"
2640 end
2641
2642 end
2643
2644 #=== イテレータコード (FOREACH_CELL)の生成
2645 # singleton では出力しない
2646 def gen_ph_foreach_cell f
2647
2648 return if @singleton
2649
2650 if has_CB? || has_INIB? then
2651
2652 if need_CB_initializer?
2653 necessity = ""
2654 else
2655 necessity = "//"
2656 end
2657
2658 f.printf( TECSMsg.get( :FEC_comment ), "#_FEC_#" )
2659
2660 if @idx_is_id_act then
2661 amp = ''
2662 else
2663 amp = '&'
2664 end
2665 f.print <<EOT
2666#define FOREACH_CELL(i,p_cb) \\
2667 for( (i) = 0; (i) < #{@global_name}_N_CELL; (i)++ ){ \\
2668 #{necessity}(p_cb) = #{amp}#{@global_name}_CB_tab[i];
2669
2670#define END_FOREACH_CELL }
2671
2672EOT
2673 else
2674 f.printf( TECSMsg.get( :NFEC_comment ), "#_NFEC_#" )
2675 f.print <<EOT
2676#define FOREACH_CELL(i,p_cb) \\
2677 for((i)=0;(i)<0;(i)++){
2678
2679#define END_FOREACH_CELL }
2680
2681EOT
2682 end
2683 end
2684
2685
2686 #=== 変数var初期化コード
2687 #
2688 def gen_ph_cb_initialize_macro f
2689
2690 f.printf( TECSMsg.get( :CIM_comment ), "#_CIM_#" )
2691
2692 @var.each { |v|
2693 init = v.get_initializer
2694 if init.instance_of? Array then
2695 type = v.get_type
2696 if( type.kind_of? PtrType )then
2697 # PtrType は ArrayType にすり替える
2698
2699 # 初期化子の要素数とする (後は 0 である)
2700 t2 = ArrayType.new( Expression.create_integer_constant( init.length, nil ) )
2701 t2.set_type( type.get_type )
2702 type = t2
2703 end
2704 f.print "extern const #{type.get_type_str} #{@global_name}_#{v.get_name}_VAR_INIT#{type.get_type_str_post};\n"
2705 end
2706 }
2707 if @singleton then
2708 arg = "()"
2709 p_that = ""
2710 that = "#{@global_name}_SINGLE_CELL_CB."
2711 else
2712 arg = "(p_that)"
2713 p_that = "(p_that)"
2714 that = "(p_that)->"
2715 end
2716
2717 if @n_cell_gen > 0 && need_CB_initializer? then
2718 b_var_init = false
2719 f.print "#define INITIALIZE_CB#{arg}"
2720 @var.each { |v|
2721 init = v.get_initializer
2722 next if init == nil
2723
2724 b_var_init = true
2725 type = v.get_type.get_original_type
2726 f.print "\\\n"
2727# print v.get_name, type.class, "\n"
2728# if init.instance_of? Array || type.kind_of?( StructType ) then
2729 if init.instance_of? Array then
2730 if(type.kind_of?( ArrayType ) || type.kind_of?( PtrType ))then
2731 pre = "&"
2732 post = "[0]"
2733 elsif type.kind_of? StructType then
2734 pre = "&"
2735 post = ""
2736# elsif type.kind_of? PtrType then
2737# pre = ""
2738# post = ""
2739 end
2740 f.print "\tmemcpy((void*)#{pre}#{@global_name}_VAR_#{v.get_name}#{p_that}#{post}, "
2741 f.print "(void*)#{pre}#{@global_name}_#{v.get_name}_VAR_INIT#{post}, sizeof(#{@global_name}_#{v.get_name}_VAR_INIT));"
2742 elsif init.instance_of? C_EXP then
2743 f.print "\t#{that}#{v.get_name} = #{init.get_c_exp_string};"
2744 else
2745 pre = "#{get_global_name}_ATTR_"
2746 if @singleton then
2747 post = ""
2748 else
2749 post = "#{p_that}"
2750 end
2751 f.print "\t#{that}#{v.get_name} = #{init.to_str( @name_list, pre, post )};"
2752 end
2753 }
2754
2755 # dynamic call port の初期化コード
2756 b_dyn_port = false
2757 @port.each{ |p|
2758 next if p.get_port_type != :CALL
2759 if p.is_dynamic? && $ram_initializer then
2760 if p.get_array_size == nil then
2761 f.print "\\\n\t#{that}#{p.get_name} = #{that}_inib->#{p.get_name}_init_;"
2762 else
2763 if @singleton || p.get_array_size != "[]" then
2764 p_that = ""
2765 else
2766 p_that = "(p_that)"
2767 end
2768 if @singleton then
2769 that = "#{@global_name}_SINGLE_CELL_INIB."
2770 else
2771 that = "(p_that)->"
2772 end
2773 if has_CB? then
2774 init = '_init->'
2775 else
2776 init = ''
2777 end
2778 f.printf( "\\\n%-80s\\\n", ' {' )
2779 f.printf( "%-80s\\\n", ' int_t j;' )
2780 f.printf( "%-80s\\\n", " for( j = 0; j < N_CP_#{p.get_name}#{p_that}; j++ ){" )
2781 f.printf( "%-80s\\\n", " #{that}#{p.get_name}[j] = #{that}#{init}#{p.get_name}_init_[j];" )
2782 f.printf( "%-80s\\\n", ' }' )
2783 f.printf( "%-80s", ' }' )
2784 end
2785 b_dyn_port = true
2786 end
2787 }
2788 if b_dyn_port then
2789 f.print( "\n" )
2790 end
2791
2792 if b_var_init == false && b_dyn_port == false && ! @singleton then
2793 f.print "\t(void)(p_that);"
2794 end
2795 f.print "\n"
2796
2797 f.print "#define SET_CB_INIB_POINTER(i,p_that)\\\n"
2798 if has_CB? && has_INIB? then
2799 if @singleton then
2800 f.print "\t#{that}_inib = &#{@global_name}_SINGLE_CELL_INIB;\n\n"
2801 elsif @idx_is_id_act
2802 f.print "\t#{that}_inib = #{@global_name}_INIB_tab[(i)];\n\n"
2803 else
2804 f.print "\t#{that}_inib = &#{@global_name}_INIB_tab[(i)];\n\n"
2805 end
2806 else
2807 f.print "\t/* empty */\n"
2808 end
2809
2810 # else
2811 # セルが一つもなければ出力しない
2812 end
2813
2814 end
2815
2816
2817 def gen_ph_inline f
2818 # inline ポートが一つでもあれば、inline.h の include
2819 if @n_entry_port_inline > 0 then
2820 f.printf( TECSMsg.get( :INL_comment ), "#_INL_#" )
2821 f.print( "#include \"#{@global_name}_inline.#{$h_suffix}\"\n\n" )
2822 end
2823 end
2824
2825 def gen_ph_endif( f, post = "TECSGEN" )
2826 f.print("#endif /* #{@global_name}_#{post}H */\n")
2827 end
2828
2829
2830##### celltype factory header
2831 def generate_factory_header
2832
2833 f = AppFile.open("#{$gen}/#{@global_name}_factory.#{$h_suffix}")
2834 f.print("#ifndef #{@name}_FACTORY_H\n")
2835 f.print("#define #{@name}_FACTORY_H\n")
2836 f.close
2837 end
2838
2839 def generate_factory_header_post
2840
2841 f = AppFile.open("#{$gen}/#{@global_name}_factory.#{$h_suffix}")
2842
2843 plugin_obj = get_celltype_plugin
2844 if plugin_obj
2845 plugin_obj.gen_factory f
2846 end
2847
2848 f.print("#endif /* #{@name}_FACTORY_H */\n")
2849 f.close
2850 end
2851
2852
2853##### celltype glue code
2854 def gen_cell_private_header f
2855 f.print "#include \"#{@global_name}_tecsgen.#{$h_suffix}\"\n"
2856 end
2857
2858 def gen_cell_factory_header f
2859 f.print "#include \"#{@global_name}_factory.#{$h_suffix}\"\n\n"
2860 end
2861
2862 def gen_cell_ep_des_type f
2863 if @n_entry_port > 0 then
2864 f.printf( TECSMsg.get( :EDT_comment ), "#_EDT_#" )
2865 end
2866
2867 @port.each { |p|
2868 next if p.get_port_type != :ENTRY
2869 next if p.is_omit?
2870 if p.is_skelton_useless? # 受け口最適化
2871 f.print( "/* #{p.get_name} : omitted by entry port optimize */\n\n" )
2872 next
2873 end
2874
2875 f.print( "/* #{p.get_name} */\n" )
2876 f.print( "struct tag_#{@global_name}_#{p.get_name}_DES {\n" )
2877 f.print( " const struct tag_#{p.get_signature.get_global_name}_VMT *vmt;\n" )
2878 if has_CB? || has_INIB? then
2879 f.print( " #{@name}_IDX idx;\n" )
2880 else
2881 # CB も INIB も存在しない (ので、idx として整数で初期化しておく)
2882 f.print( " int idx;\n" )
2883 end
2884 if p.get_array_size then
2885 f.print( " int_t subscript;\n" )
2886 end
2887 f.print( "};\n\n" )
2888 }
2889 end
2890
2891 def gen_cell_skel_fun f
2892 if @n_entry_port >0 then
2893 f.printf( TECSMsg.get( :EPSF_comment ), "#_EPSF_#" )
2894 end
2895
2896 @port.each { |p|
2897 next if p.get_port_type != :ENTRY
2898 next if p.is_omit?
2899 if p.is_skelton_useless? then # 受け口最適化
2900 f.print( "/* #{p.get_name} : omitted by entry port optimize */\n" )
2901 next
2902 end
2903
2904 f.print( "/* #{p.get_name} */\n" )
2905
2906 p.get_signature.get_function_head_array.each{ |fun|
2907 functype = fun.get_declarator.get_type
2908 f.printf "%-14s", functype.get_type_str
2909
2910 f.print " #{@global_name}_#{p.get_name}_#{fun.get_name}_skel("
2911 f.print " const struct tag_#{p.get_signature.get_global_name}_VDES *epd"
2912 delim = ","
2913
2914 if functype.get_paramlist then
2915 items = functype.get_paramlist.get_items
2916 len = items.length
2917 else
2918 # ここで nil になるのは、引数なしの時に void がなかった場合
2919 items = []
2920 len = 0
2921 end
2922 i = 0
2923 items.each{ |param|
2924 f.print "#{delim} "
2925 delim = ","
2926 f.print param.get_type.get_type_str
2927 f.print " "
2928 f.print param.get_name
2929 f.print param.get_type.get_type_str_post
2930 i += 1
2931 }
2932 f.print ")\n"
2933
2934 f.print "{\n"
2935 if ( ! @singleton || p.get_array_size != nil ) then
2936 f.print " struct tag_#{@global_name}_#{p.get_name}_DES *lepd\n"
2937 f.print " = (struct tag_#{@global_name}_#{p.get_name}_DES *)epd;\n"
2938 end
2939
2940 if functype.get_type_str == "void" then # mikan "void" の typedef に未対応
2941 f.print " "
2942 else
2943 f.print " return "
2944 end
2945
2946 f.print "#{@global_name}_#{p.get_name}_#{fun.get_name}("
2947 if @singleton then
2948 delim = ""
2949 else
2950 f.print " lepd->idx"
2951 delim = ","
2952 end
2953
2954 if p.get_array_size then
2955 f.print "#{delim} lepd->subscript"
2956 delim = ","
2957 end
2958
2959 items.each{ |param|
2960 f.print "#{delim} "
2961 delim = ","
2962 f.print param.get_name
2963 i += 1
2964 }
2965 f.print " );\n"
2966
2967 f.print "}\n"
2968 }
2969 }
2970 if @n_entry_port >0 then
2971 f.print( "\n" )
2972 end
2973 end
2974
2975 def gen_cell_fun_table f
2976 if @n_entry_port >0 then
2977 f.printf( TECSMsg.get( :EPSFT_comment ), "#_EPSFT_#" )
2978 end
2979
2980 @port.each { |p|
2981 next if p.get_port_type != :ENTRY
2982 next if p.is_omit?
2983 if p.is_VMT_useless? then # 受け口最適化
2984 f.print "/* #{p.get_name} : omitted by entry port optimize */\n"
2985 next
2986 end
2987
2988 f.print "/* #{p.get_name} */\n"
2989
2990 # f.print "static const struct tag_#{p.get_signature.get_global_name}_VMT"
2991 f.print "const struct tag_#{p.get_signature.get_global_name}_VMT"
2992 f.print " #{@global_name}_#{p.get_name}_MT_ = {\n"
2993
2994 p.get_signature.get_function_head_array.each{ |fun|
2995 f.print " #{@global_name}_#{p.get_name}_#{fun.get_name}_skel,\n"
2996 }
2997
2998 f.print "};\n"
2999 }
3000 f.print "\n"
3001
3002 end
3003
3004 def gen_cell_ep_vdes fs
3005 if @n_cell_gen >0 then
3006 fs.each{ |r,f| f.printf( TECSMsg.get( :CPEPD_comment ), "#_CPEPD_#" ) }
3007 end
3008
3009 # このセルタイプのすべてのセルについて
3010 @ordered_cell_list.each{ |c|
3011 if c.is_generate? then # 生成対象か?
3012
3013 f = fs[ c.get_region.get_domain_root ]
3014
3015 # 結合のリスト (NamedList)
3016 jl = c.get_join_list
3017
3018 # 全ての結合リストについて
3019 jl.get_items.each{ |j|
3020
3021 # 左辺の定義を得る
3022 definition = j.get_definition
3023
3024 # 呼び口ではない? (属性)
3025 next unless definition.instance_of? Port
3026
3027 port = find j.get_name # celltype の Port (こちらに最適化情報がある)
3028 # port = definition # definition は composite の Port が得られることがある
3029 next if port.is_cell_unique?
3030 next if port.is_omit?
3031
3032 # 配列要素を得る(受け口配列でなければ nil が返る)
3033 am = j.get_array_member2
3034
3035 # 呼び口配列か?
3036 if am then
3037 i = 0
3038 while( i < am.length )
3039 j = am[i]
3040 if j then
3041 if am[i].get_rhs_cell.get_celltype == self then
3042 # 同じセルタイプへ結合している場合(VDES では type conflict になる)
3043 p = am[i].get_rhs_port
3044 des_type = "const struct tag_#{@global_name}_#{p.get_name}_DES"
3045 else
3046 des_type = "struct tag_#{definition.get_signature.get_global_name}_VDES"
3047 end
3048
3049 # 右辺は受け口配列か?
3050 if j.get_rhs_subscript then
3051
3052 # 受け口の配列添数
3053 subscript = j.get_rhs_subscript
3054
3055 f.printf( "extern %s %s%d;\n",
3056 des_type,
3057 "#{j.get_port_global_name(i)}_des",
3058 subscript)
3059 else
3060 f.printf( "extern %s %s;\n",
3061 des_type,
3062 "#{j.get_port_global_name(i)}_des")
3063 end
3064 #else if j == nil
3065 # optioanl で配列要素が初期化されていない
3066 end
3067 i += 1
3068 end
3069 else
3070 dbgPrint "me=#{@name} callee=#{j.get_rhs_cell.get_celltype.get_name} #{j.get_cell.get_celltype.get_name} \n"
3071 if j.get_rhs_cell.get_celltype == self then
3072 # 同じセルタイプへ結合している場合(VDES では type conflict になる)
3073 p = j.get_rhs_port
3074 des_type = "const struct tag_#{@global_name}_#{p.get_name}_DES"
3075 else
3076 des_type = "struct tag_#{definition.get_signature.get_global_name}_VDES"
3077 end
3078
3079 if j.get_rhs_subscript then
3080 # 受け口配列
3081 subscript = j.get_rhs_subscript
3082 f.printf( "extern %s %s%d;\n",
3083 des_type,
3084 "#{j.get_port_global_name}_des",
3085 subscript)
3086 else
3087 f.printf( "extern %s %s;\n",
3088 des_type,
3089 "#{j.get_port_global_name}_des" )
3090 end
3091 end
3092 # mikan cell の namespace 未対応、Join で Cell オブジェクトを引当ておく必要あり
3093 }
3094
3095 f.print "\n"
3096 end
3097 }
3098 end
3099
3100 def gen_cell_ep_vdes_array fs
3101 if @n_cell_gen >0 then
3102 fs.each{ |r, f| f.printf( TECSMsg.get( :CPA_comment ), "#_CPA_#" ) } # mikan 呼び口配列が無い場合も出てしまう
3103 end
3104
3105 @ordered_cell_list.each{ |c|
3106 if c.is_generate? then
3107 f = fs[ c.get_region.get_domain_root ]
3108
3109 jl = c.get_join_list
3110 # ループを回す変数を jl から @port に変更
3111 # dynamic, optional
3112# jl.get_items.each{ |j|
3113 @port.each { |port|
3114 next if port.get_port_type != :CALL
3115 dbgPrint( "gen_cell_ep_vdes_array: #{c.get_name}.#{port.get_name}\n" )
3116
3117# definition = j.get_definition
3118# next unless definition.instance_of? Port
3119 j = jl.get_item( port.get_name )
3120
3121 # port = definition # definition は composite の Port が得られることがある
3122 # port = find j.get_name # celltype の Port (こちらに最適化情報がある)
3123 next if port.is_cell_unique?
3124 next if port.is_omit?
3125
3126 b_array = false
3127 am = nil
3128 if j then
3129 am = j.get_array_member2
3130 if am then
3131 b_array = true
3132 end
3133 else
3134 if port.get_array_size == "[]" then
3135 # this case is dynamic optional and nothing joined
3136 next
3137 elsif port.get_array_size then
3138 b_array = true
3139 end
3140 end
3141 if b_array then
3142# if am then
3143 # 左辺は配列
3144 const = ( port.is_dynamic? && ! $ram_initializer ) ? '' : 'const '
3145 init = ( port.is_dynamic? && $ram_initializer ) ? '_init_' : ''
3146
3147 if ! port.is_skelton_useless? then
3148 f.printf( "struct %s * #{const}%s_%s[] = {\n",
3149 "tag_#{port.get_signature.get_global_name}_VDES",
3150 "#{c.get_global_name}",
3151 "#{port.get_name}" + init )
3152 else
3153
3154# スケルトン関数不要最適化の場合、この配列は参照されない
3155 # mikan このケースがテストされていない
3156 f.printf( "#{const}%s_IDX %s_%s[] = {\n",
3157# "#{j.get_celltype.get_global_name}", # 右辺 composite に対応できない
3158 "#{j.get_rhs_cell.get_celltype.get_global_name}",
3159 "#{c.get_global_name}",
3160 "#{j.get_name}" )
3161 end
3162 if port.get_array_size == "[]" then
3163 length = am.length
3164 else
3165 length = port.get_array_size
3166 end
3167 # am.each { |j|
3168 i = 0
3169 while i < length
3170 if am == nil then
3171 f.print( " 0,\n" )
3172 i += 1
3173 next
3174 end
3175 j = am[i]
3176 i += 1
3177
3178 if j then
3179 # 同一セルタイプの結合の場合、VDES 型へのキャストが必要
3180 if j.get_rhs_cell.get_celltype == self then
3181 definition = j.get_definition
3182 des_type_cast = "(struct tag_#{definition.get_signature.get_global_name}_VDES *)"
3183 else
3184 des_type_cast = ""
3185 end
3186
3187
3188 if j.get_rhs_subscript then
3189 # 右辺配列の場合(最適化はない)
3190 subscript = j.get_rhs_subscript
3191 f.printf( " %s%d,\n",
3192 "#{des_type_cast}&#{j.get_port_global_name}_des",
3193 subscript)
3194 # p "1: #{j.get_port_global_name}_des"
3195 # p "2: #{j.get_cell_global_name}_#{j.get_port_name}_des"
3196
3197 else
3198 # 右辺非配列の場合 */
3199 if ! port.is_skelton_useless? then
3200 f.printf( " %s,\n",
3201 "#{des_type_cast}&#{j.get_port_global_name}_des" )
3202 else
3203 cell = j.get_rhs_cell
3204 name_array = cell.get_celltype.get_name_array( cell )
3205 f.printf( " #{name_array[7]},\n" )
3206 end
3207 end
3208 else
3209 # optional で呼び口配列要素が初期化されていない
3210 f.printf( " 0,\n" )
3211 end
3212 # }
3213 end
3214 # mikan cell の namespace 未対応、Join で Cell オブジェクトを引当ておく必要あり
3215 f.print "};\n"
3216 # dynamic の呼び口配列
3217 if port.is_dynamic? && $ram_initializer then
3218 f.printf( "struct %s * %s_%s[ #{length} ];\n",
3219 "tag_#{port.get_signature.get_global_name}_VDES",
3220 "#{c.get_global_name}",
3221 "#{port.get_name}" )
3222 end
3223 end
3224 }
3225
3226 f.print "\n"
3227 end
3228 }
3229 end
3230
3231 #=== CB を初期化するプログラムの生成
3232 def gen_cell_cb_initialize_code f
3233 if ! need_CB_initializer?
3234 return
3235 end
3236 f.printf( TECSMsg.get( :CIC_comment ), "#_CIC_#" )
3237 f.print <<EOT
3238void
3239#{@global_name}_CB_initialize()
3240{
3241EOT
3242 if @singleton then
3243 f.print <<EOT
3244 SET_CB_INIB_POINTER(i,p_cb)
3245 INITIALIZE_CB()
3246EOT
3247 else
3248 f.print <<EOT
3249 #{@global_name}_CB *p_cb;
3250 int i;
3251 FOREACH_CELL(i,p_cb)
3252 SET_CB_INIB_POINTER(i,p_cb)
3253 INITIALIZE_CB(p_cb)
3254 END_FOREACH_CELL
3255EOT
3256 end
3257
3258 f.print <<EOT
3259}
3260EOT
3261 end
3262
3263 # === CB/INIB の外で初期化される変数の出力
3264 def gen_cell_cb_out_init fs
3265
3266 # セルがなければ、出力しない
3267 if @n_cell_gen == 0 then
3268 return
3269 end
3270
3271 fs.each{ |r, f| f.printf( TECSMsg.get( :AVAI_comment ), "#_AVAI_#" ) }
3272
3273 # attribute, var のポインタ型の参照する配列を生成
3274 @ordered_cell_list.each{ |c|
3275 next if ! c.is_generate?
3276
3277 f = fs[ c.get_region.get_domain_root ]
3278 name_array = get_name_array( c )
3279
3280 ct = c.get_celltype
3281 jl = c.get_join_list
3282
3283 # attribute, var のポインタ変数が配列により初期化される場合の、配列を出力
3284 av_list = ct.get_attribute_list + ct.get_var_list
3285 if av_list.length != 0 then
3286 av_list.each{ |a| # a: Decl
3287 j = jl.get_item( a.get_identifier )
3288 if j then
3289 init = j.get_rhs
3290 else
3291 init = a.get_initializer
3292 end
3293
3294 if( a.is_type?( PtrType ) && ( (init && init.instance_of?( Array )) || init == nil ) )then
3295 ptr_type = a.get_type
3296 size = ptr_type.get_size
3297
3298 if size then
3299 # 式を評価する(attribute, var に含まれる変数を参照可能)
3300 sz = size.eval_const( c.get_join_list, c.get_celltype.get_name_list )
3301 # 式を生成しなおす (変数を含まない形にする) 不完全な形で Token を生成 (エラー発生しないから)
3302 size = Expression.new( [:INTEGER_CONSTANT, Token.new(sz, nil, 0, 0)] )
3303 array_type = ArrayType.new( size )
3304 type = a.get_type.get_referto
3305 if ! type.is_const? && a.get_kind == :ATTRIBUTE then
3306 type.set_qualifier :CONST
3307 end
3308 array_type.set_type( type )
3309 if a.get_kind == :ATTRIBUTE then
3310 f.print "const "
3311 end
3312 f.printf( "#{a.get_type.get_referto.get_type_str} #{name_array[3]}_#{a.get_identifier}_INIT[%d]#{a.get_type.get_referto.get_type_str_post}", sz )
3313 # name_array[3]: cell_CB_INIT
3314 if !( $ram_initializer && a.get_kind == :VAR ) then
3315 # -R (ram initializer 使用) の場合 var は初期化コードを出力しない
3316 if( init )then
3317 str = " = #{gen_cell_cb_init( f, c, name_array, array_type, init, a.get_identifier, 1, true )}"
3318 str = str.sub( /\}$/, "};\n" )
3319 else
3320 str = ";\n"
3321 end
3322 f.print( str )
3323 else
3324 f.print( ";\n" )
3325 end
3326 end
3327 end
3328 }
3329 end
3330 }
3331 end
3332
3333 #=== var の初期値の ROM 部への
3334 def gen_cell_var_init f
3335 # var の{ }で囲まれた初期値指定があるか調べる
3336 n_init = 0
3337 @var.each { |v|
3338 init = v.get_initializer
3339 if init && init.instance_of?( Array ) then
3340 n_init += 1
3341 end
3342 }
3343
3344 if n_init > 0 then
3345 f.printf( TECSMsg.get( :AVI_comment ), "#_AVI_#" )
3346 @var.each { |v|
3347 init = v.get_initializer
3348 if init && init.instance_of?( Array ) then
3349 type = v.get_type
3350 org_type = v.get_type.get_original_type
3351
3352 if( org_type.kind_of? PtrType )then
3353 # PtrType は ArrayType にすり替える
3354
3355 # 初期化子の要素数だけとする(後は 0)
3356 t2 = ArrayType.new( Expression.create_integer_constant( init.length, nil ) )
3357 t2.set_type( type.get_type )
3358 type = t2
3359 org_type = t2
3360 end
3361
3362 c = @ordered_cell_list[0] # 仮の cell (実際には使われない)
3363 name_array = get_name_array( c )
3364 # f.print "const #{type0.get_type_str}\t#{@global_name}_#{v.get_name}_VAR_INIT#{type0.get_type_str_post} = "
3365 f.print "const #{type.get_type_str}\t#{@global_name}_#{v.get_name}_VAR_INIT#{type.get_type_str_post} = "
3366 if org_type.kind_of? StructType then
3367 # celltype の default の初期値あり
3368 str = gen_cell_cb_init( f, c, name_array, type, init, v.get_identifier, 1, true )
3369 elsif( org_type.kind_of?( PtrType ) || org_type.kind_of?( ArrayType ) ) then
3370 str = "{ "
3371 type = org_type.get_type
3372 # mikan ポインタではなく、配列型としないと、ポインタ変数の領域の分、損する
3373 init.each { |i|
3374 str += gen_cell_cb_init( f, c, name_array, type, i, v.get_identifier, 1, true )
3375 str += ", "
3376 }
3377 str += "}"
3378 else
3379 p type.class
3380 raise "Unknown Type"
3381 end
3382 f.print str
3383 f.print ";\n"
3384 end
3385 }
3386 f.print "\n"
3387 end
3388
3389 end
3390
3391 def gen_cell_cb fs
3392 if has_INIB? then
3393 if @n_cell_gen > 0 then
3394 fs.each{ |r, f| f.printf( TECSMsg.get( :INIB_comment ), "#_INIB_#" ) }
3395 end
3396 if @singleton then
3397 fs.each{ |r, f| f.print "#{@global_name}_INIB #{@global_name}_SINGLE_CELL_INIB = \n" }
3398 indent = 0
3399 elsif ! @idx_is_id_act then
3400 fs.each{ |r, f| f.print "#{@global_name}_INIB #{@global_name}_INIB_tab[] = {\n" }
3401 indent = 1
3402 else
3403 indent = 0
3404 end
3405
3406 @ordered_cell_list.each{ |c|
3407 next if ! c.is_generate?
3408
3409 f = fs[ c.get_region.get_domain_root ]
3410
3411 name_array = get_name_array( c )
3412
3413 unless @singleton then
3414 print_indent( f, indent )
3415 f.print "/* cell: #{name_array[2]}: #{name_array[1]} id=#{c.get_id} */\n"
3416 # name_array[2]: cell_CB_name
3417 end
3418
3419 print_indent( f, indent )
3420 if @idx_is_id_act then
3421 f.print "const #{@global_name}_INIB #{name_array[5]} = "
3422 end
3423 f.print "{\n"
3424
3425 gen_cell_cb_port( c, indent, f, name_array, :INIB )
3426 gen_cell_cb_attribute( c, indent, f, name_array, :INIB )
3427
3428 unless @singleton then
3429 # 1 つの cell INIB の終わり
3430 if @idx_is_id_act then
3431 f.print( "};\n\n" )
3432 else
3433 f.print( " },\n" )
3434 end
3435 end
3436 }
3437 if ! @idx_is_id_act then
3438 fs.each{ |r, f| f.print( "};\n\n" ) }
3439 end
3440 end # has_INIB?
3441
3442 if has_CB? then
3443 if @n_cell_gen >0 then
3444 fs.each{ |r, f| f.printf( TECSMsg.get( :CB_comment ), "#_CB_#" ) }
3445 end
3446
3447 # RAM initializer を使用しない、または ROM 化しない
3448 if $ram_initializer == false || $rom == false then
3449 if @singleton then
3450 fs.each{ |r, f| f.print "struct tag_#{@global_name}_CB #{@global_name}_SINGLE_CELL_CB = \n" }
3451 indent = 0
3452 elsif ! @idx_is_id_act then
3453 fs.each{ |r, f| f.print "struct tag_#{@global_name}_CB #{@global_name}_CB_tab[] = {\n" }
3454 indent = 1
3455 else
3456 indent = 0
3457 end
3458
3459 @ordered_cell_list.each{ |c|
3460 next if ! c.is_generate?
3461
3462 f = fs[ c.get_region.get_domain_root ]
3463
3464 name_array = get_name_array( c )
3465
3466 unless @singleton then
3467 print_indent( f, indent )
3468 f.print "/* cell: #{name_array[2]}: #{name_array[1]} id=#{c.get_id} */\n"
3469 # name_array[2]: cell_CB_name
3470 end
3471
3472 print_indent( f, indent )
3473 if @idx_is_id_act then
3474 f.print "#{@global_name}_CB #{name_array[2]} = "
3475 end
3476 f.print "{\n"
3477
3478 if has_INIB? then
3479 print_indent( f, indent + 1 )
3480 f.printf( "&%-39s /* _inib */\n", "#{name_array[5]}," )
3481 end
3482
3483 #if ! has_INIB? then
3484 if $rom == false then
3485 gen_cell_cb_port( c, indent, f, name_array, :CB_ALL )
3486 else
3487 gen_cell_cb_port( c, indent, f, name_array, :CB_DYNAMIC )
3488 end
3489
3490 gen_cell_cb_attribute( c, indent, f, name_array, :CB )
3491 gen_cell_cb_var( c, indent, f, name_array )
3492
3493 unless @singleton then
3494 # 1 つの cell CB の終わり
3495 if @idx_is_id_act then
3496 f.print( "};\n\n" )
3497 else
3498 f.print( " },\n" )
3499 end
3500 end
3501 }
3502 if ! @idx_is_id_act then
3503 fs.each{ |r, f| f.print( "};\n\n" ) }
3504 end
3505 else
3506 if @singleton then
3507 fs.each{ |r, f| f.print "struct tag_#{@global_name}_CB #{@global_name}_SINGLE_CELL_CB;\n" }
3508 indent = 0
3509 elsif @idx_is_id_act then
3510 @ordered_cell_list.each{ |c|
3511 next if ! c.is_generate?
3512
3513 f = fs[ c.get_region.get_domain_root ]
3514
3515 name_array = get_name_array( c )
3516 f.print "/* cell: #{name_array[2]}: #{name_array[1]} id=#{c.get_id} */\n"
3517 f.print "#{@global_name}_CB #{name_array[2]} = {};\n"
3518 }
3519 else
3520 fs.each{ |r, f| f.print "struct tag_#{@global_name}_CB #{@global_name}_CB_tab[#{@n_cell_gen}];\n" }
3521 end
3522 end
3523 end # has_CB?
3524 end
3525
3526 def gen_cell_cb_tab f
3527 indent = 0
3528 if @idx_is_id_act then
3529 if has_INIB? && ( $ram_initializer || ! has_CB? ) then
3530 f.print "/* ID to INIB table #_INTAB_# */\n"
3531 @ordered_cell_list.each{ |c|
3532 if c.is_generate? && ( c.get_region.get_domain_root != Region.get_root ) then # 生成対象かつ、ルート以外か
3533 name_array = get_name_array( c )
3534 print_indent( f, indent + 1 )
3535 f.print "extern #{@global_name}_INIB #{name_array[5]};\n"
3536 end
3537 }
3538
3539 f.print "#{@global_name}_INIB *#{@global_name}_INIB_tab[] ={\n"
3540 @ordered_cell_list.each{ |c|
3541 if c.is_generate? then # 生成対象か?
3542 name_array = get_name_array( c )
3543 print_indent( f, indent + 1 )
3544 f.print "&#{name_array[5]},\n"
3545 end
3546 }
3547 f.print "};\n"
3548 end
3549 if has_CB? then
3550 f.print "/* ID to CB table #_CBTAB_# */\n"
3551 @ordered_cell_list.each{ |c|
3552 if c.is_generate? && ( c.get_region.get_domain_root != Region.get_root ) then # 生成対象かつ、ルート以外か
3553 name_array = get_name_array( c )
3554 print_indent( f, indent + 1 )
3555 f.print "extern #{@global_name}_CB #{name_array[2]};\n"
3556 end
3557 }
3558
3559 f.print "#{@global_name}_CB *#{@global_name}_CB_tab[] ={\n"
3560 @ordered_cell_list.each{ |c|
3561 if c.is_generate? then # 生成対象か?
3562 name_array = get_name_array( c )
3563 print_indent( f, indent + 1 )
3564 f.print "&#{name_array[2]},\n"
3565 end
3566 }
3567 f.print "};\n"
3568 end
3569 end
3570 end
3571
3572
3573 #=== name_array を生成
3574 # IN: cell : Cell
3575 # index : CB, INIB 配列の添数
3576 # RETURN: name_array
3577 # name_array[0] = @name # celltype name
3578 # name_array[1] = cell.get_name # cell name
3579 # name_array[2] = cell_CB_name # cell_CB_name
3580 # name_array[3] = cell_CB_INIT # cell_CB_INIT # CB の外側で初期化が必要な配列の名前
3581 # name_array[4] = cell_CB_proto # CB name for prototype
3582 # name_array[5] = cell_INIB # INIB name
3583 # name_array[6] = cell_ID # ID
3584 # name_array[7] = cell_IDX # IDX
3585 # name_array[8] = cell_CBP # CB pointer
3586 # name_array[9] = @global_name # celltype global name
3587 # name_array[10] = cell.get_global_name # cell global name
3588
3589 def get_name_array( cell )
3590
3591 if @singleton then
3592 cell_CB_name = "#{@global_name}_SINGLE_CELL_CB"
3593 cell_CB_INIT = cell_CB_name
3594 cell_CB_proto = "#{@global_name}_SINGLE_CELL_CB"
3595 cell_INIB_name = "#{@global_name}_SINGLE_CELL_INIB"
3596 cell_ID = 0
3597 else
3598 if ! @idx_is_id_act then
3599 index = cell.get_id - cell.get_celltype.get_id_base
3600 cell_CB_name = "#{@global_name}_CB_tab[#{index}]"
3601 cell_CB_INIT = "#{@global_name}_#{cell.get_name}_CB"
3602 cell_CB_proto = "#{@global_name}_CB_tab[]"
3603 cell_INIB_name = "#{@global_name}_INIB_tab[#{index}]"
3604 else
3605 cell_CB_name = "#{cell.get_global_name}_CB"
3606 cell_CB_INIT = cell_CB_name
3607 cell_CB_proto = cell_CB_name
3608 cell_INIB_name = "#{cell.get_global_name}_INIB"
3609 end
3610 cell_ID = cell.get_id
3611 end
3612 if @idx_is_id_act then
3613 cell_IDX = cell_ID
3614 else
3615 cell_IDX = "&#{cell_CB_name}"
3616 end
3617
3618 if has_CB? then
3619 cell_CBP = "&#{cell_CB_name}"
3620 elsif has_INIB? then
3621 cell_CBP = "&#{cell_INIB_name}"
3622 else
3623 cell_CBP = "NULL" # CB も INIB もなければ NULL に置換
3624 end
3625
3626 name_array = []
3627 name_array[0] = @name # celltype name
3628 name_array[1] = cell.get_name # cell name
3629 name_array[2] = cell_CB_name # cell_CB_name
3630 name_array[3] = cell_CB_INIT # cell_CB_INIT
3631 name_array[4] = cell_CB_proto # CB name for prototype
3632 name_array[5] = cell_INIB_name # cell INIB name
3633 name_array[6] = cell_ID # cell ID
3634 name_array[7] = cell_IDX # cell IDX
3635 name_array[8] = cell_CBP # cell CBP
3636 name_array[9] = @global_name # celltype global name
3637 name_array[10] = cell.get_global_name # cell global name
3638
3639 return name_array
3640 end
3641
3642 #=== attribute と size_is 指定された var (ポインタ)の初期化データを出力
3643 #
3644 # ROM 化サポートの有無、および出力対象が CB か INIB かにより出力される内容が異なる
3645 def gen_cell_cb_attribute( cell, indent, f, name_array, cb_inib )
3646 ct = self
3647 jl = cell.get_join_list
3648
3649 if cb_inib == :INIB then
3650 return if @n_attribute_ro == 0 && @n_var_size_is == 0
3651 print_indent( f, indent + 1 )
3652 f.print "/* attribute(RO) */ \n"
3653 elsif $rom then # && cb_inib == CB
3654 # CB で rw と var
3655 return if @n_attribute_rw == 0
3656 print_indent( f, indent + 1 )
3657 f.print "/* attribute(RW) */ \n"
3658 else # cb_inib == CB && $rom == false
3659 # CB に全部
3660 return if @n_attribute_rw == 0 && @n_attribute_ro == 0 && @n_var_size_is == 0
3661 print_indent( f, indent + 1 )
3662 f.print "/* attribute */ \n"
3663 end
3664
3665 attribute = ct.get_attribute_list
3666 attribute.each{ |a| # a: Decl
3667 next if a.is_omit?
3668 if cb_inib == :INIB && a.is_rw? == true then
3669 # $rom == true でしか、ここへ来ない
3670 next
3671 elsif cb_inib == :CB && $rom && ! a.is_rw? then
3672 next
3673 end
3674
3675 j = jl.get_item( a.get_identifier )
3676 if j then
3677 # cell の初期値指定あり
3678 gen_cell_cb_init( f, cell, name_array, a.get_type, j.get_rhs, a.get_identifier, indent + 1 )
3679 elsif a.get_initializer then
3680 # celltype の default の初期値あり
3681 gen_cell_cb_init( f, cell, name_array, a.get_type, a.get_initializer, a.get_identifier, indent + 1 )
3682 else
3683 # 初期値未指定
3684 gen_cell_cb_init( f, cell, name_array, a.get_type, nil, a.get_identifier, indent + 1 )
3685 end
3686 }
3687 @var.each{ |v|
3688 next if v.is_omit?
3689 next if v.get_size_is == nil # size_is 指定がある場合 attribute の一部として出力
3690
3691 if v.get_initializer && $ram_initializer == false then
3692 gen_cell_cb_init( f, cell, name_array, v.get_type, v.get_initializer, v.get_identifier, indent + 1 )
3693 else
3694 # 初期値未指定 または RAM initializer 使用
3695 gen_cell_cb_init( f, cell, name_array, v.get_type, nil, v.get_identifier, indent + 1 )
3696 end
3697 }
3698 end
3699
3700 #=== var の初期化データを出力
3701 def gen_cell_cb_var( cell, indent, f, name_array )
3702 jl = cell.get_join_list
3703 var = get_var_list
3704 if @n_var - @n_var_size_is > 0 then
3705 print_indent( f, indent + 1 )
3706 f.print "/* var */ \n"
3707 var.each{ |v|
3708
3709 next if v.is_omit?
3710 next if v.get_size_is # size_is 指定がある場合 attribute の一部として出力
3711
3712 if v.get_initializer && $ram_initializer == false then
3713 gen_cell_cb_init( f, cell, name_array, v.get_type, v.get_initializer, v.get_identifier, indent + 1 )
3714 else
3715 # 初期値未指定 または RAM initializer 使用
3716 gen_cell_cb_init( f, cell, name_array, v.get_type, nil, v.get_identifier, indent + 1 )
3717 end
3718 }
3719 end
3720 end
3721
3722 #inib_cb::Symbol: :INIB, :CB_ALL, :CB_DYNAMIC
3723 def gen_cell_cb_port( cell, indent, f, name_array, inib_cb = :INIB )
3724 gen_cell_cb_call_port( cell, indent, f, name_array, inib_cb )
3725 gen_cell_cb_entry_port( cell, indent, f, name_array )
3726 end
3727
3728 #=== 呼び口の初期化コードの生成
3729 def gen_cell_cb_call_port( cell, indent, f, name_array, inib_cb )
3730 jl = cell.get_join_list
3731
3732 port = get_port_list
3733 if inib_cb == :INIB && ( @n_call_port - @n_call_port_omitted_in_CB -
3734 ( $ram_initializer ? 0 : (@n_call_port_dynamic-@n_call_port_array_dynamic) ) > 0 ) ||
3735 inib_cb == :CB_ALL && @n_call_port > 0 ||
3736 inib_cb == :CB_DYNAMIC && (@n_call_port_dynamic - @n_call_port_array_dynamic) > 0 then
3737 print_indent( f, indent + 1 )
3738 f.print "/* call port (#{inib_cb}) #_CP_# */ \n"
3739 port.each{ |p|
3740 next if p.get_port_type != :CALL
3741 next if p.is_omit?
3742 next if p.is_cell_unique? # 最適化(単一セルで呼び口マクロに埋め込まれる)
3743 next if inib_cb == :INIB && p.is_dynamic? && p.get_array_size == nil && ! $ram_initializer
3744 next if inib_cb == :CB_DYNAMIC && ( ! p.is_dynamic? || p.get_array_size != nil )
3745
3746 j = jl.get_item( p.get_name )
3747 print_indent( f, indent + 1 )
3748
3749 # debug
3750 if j == nil then
3751 dbgPrint "cell_cb_call_port: #{p.get_name} array size=#{p.get_array_size}\n"
3752 # optional 呼び口
3753 # cdl_error( "H1003 internal error: cell \'$1\' port \'$2\': initializer not found\n" , cell.get_name, p.get_name )
3754 # exit( 1 )
3755 if p.get_array_size then
3756 if p.is_dynamic? then
3757 if inib_cb == :INIB then
3758 if $ram_initializer then
3759 f.printf( "%-40s /* #_CCP7_# _init_ */\n", "#{cell.get_global_name}_#{p.get_name}_init_," )
3760 print_indent( f, indent + 1 )
3761 end
3762 f.printf( "%-40s /* #_CCP7B_# */\n", "#{cell.get_global_name}_#{p.get_name}," )
3763 elsif $rom == false then
3764 f.printf( "%-40s /* #_CCP8_# */\n", "#{cell.get_global_name}_#{p.get_name}," )
3765 end
3766 else
3767 f.printf( "%-40s /* #_CCP9_# */\n", "0," )
3768 end
3769 if p.get_array_size == "[]" then
3770 # 添数省略の呼び口配列
3771 print_indent( f, indent + 1 )
3772 f.printf( "%-40s /* %s #_CCP6_# */\n", "0,", "length of #{p.get_name} (n_#{p.get_name})" )
3773 end
3774 else
3775 f.printf( "%-40s /* #_CCP5_# */\n", "0," )
3776 end
3777 next
3778 end
3779
3780 am = j.get_array_member2
3781 if am then
3782 # 呼び口配列の場合
3783 if inib_cb == :INIB && p.is_dynamic? && p.get_array_size != nil && $ram_initializer then
3784 f.printf( "%-40s /* #_CCP3_# _init_ */\n", "#{cell.get_global_name}_#{j.get_name}_init_," )
3785 print_indent( f, indent + 1 )
3786 end
3787 f.printf( "%-40s /* #_CCP3B_# */\n", "#{cell.get_global_name}_#{j.get_name}," )
3788 if p.get_array_size == "[]" then
3789 # 添数省略の呼び口配列
3790 print_indent( f, indent + 1 )
3791 f.printf( "%-40s /* %s #_CCP4_# */\n", "#{am.length},", "length of #{p.get_name} (n_#{p.get_name})" )
3792 end
3793 else
3794 # 同一セルタイプの結合の場合、VDES 型へのキャストが必要
3795 #print "CCP0/CCP1 #{p.get_name}, #{j.get_rhs_cell.get_celltype.get_name}, #{@name}\n"
3796 if j.get_rhs_cell.get_celltype == self then
3797 definition = j.get_definition
3798 des_type_cast = "(struct tag_#{definition.get_signature.get_global_name}_VDES *)"
3799 else
3800 des_type_cast = ""
3801 end
3802
3803 init = ( p.is_dynamic? && inib_cb == :INIB ) ? "_init_" : ""
3804
3805 if j.get_rhs_subscript then
3806 # 受け口配列の場合
3807 subscript = j.get_rhs_subscript
3808 f.printf( "%-40s /* %s #_CCP0_# */\n",
3809 # "&#{j.get_cell_global_name}_#{j.get_port_name}_des#{subscript},",
3810 "#{des_type_cast}&#{j.get_port_global_name}_des#{subscript},",
3811 p.get_name.to_s + init )
3812 else
3813 # 呼び口配列でも、受け口配列でもない
3814 if ! p.is_skelton_useless? then
3815 f.printf( "%-40s /* %s #_CCP1_# */\n",
3816 "#{des_type_cast}&#{j.get_port_global_name}_des,",
3817 p.get_name.to_s + init )
3818 else
3819 # スケルトン不要最適化(CB (INIB) へのポインタを埋め込む)
3820 c = j.get_rhs_cell # 呼び先セル
3821 ct = c.get_celltype # 呼び先セルタイプ
3822 if ct.has_INIB? || ct.has_CB? then
3823 name_array = ct.get_name_array( c ) # 呼び先セルタイプで name_array を得る
3824 f.printf( "%-40s /* %s #_CCP2_# */\n", "#{name_array[7]},", p.get_name )
3825 else
3826 # 呼び先は CB も INIB も持たない(NULL に初期化)
3827 f.printf( "%-40s /* %s #_CCP2B_# */\n", "0,", p.get_name )
3828 end
3829 end
3830 end
3831 end
3832
3833 }
3834 end
3835 end
3836
3837 #=== 受け口の初期化コードの生成
3838 def gen_cell_cb_entry_port( cell, indent, f, name_array )
3839 jl = cell.get_join_list
3840
3841 port = get_port_list
3842 if @n_entry_port != 0 then
3843 print_indent( f, indent + 1 )
3844 f.print "/* entry port #_EP_# */ \n"
3845 @port.each{ |p|
3846 # next if p.is_omit? # 受け口配列の個数は省略しない
3847 if p.get_port_type == :ENTRY && p.get_array_size == "[]"
3848 print_indent( f, indent + 1 )
3849 f.printf( "%-40s /* #_EEP_# */\n", "#{cell.get_entry_port_max_subscript( p )+1}," )
3850 end
3851 }
3852 end
3853 end
3854
3855 #=== セルの attribute の初期値を出力
3856 #
3857 #f_get_str:: true の場合、文字列を返す、false の場合、ファイル f に出力する.
3858 # 文字列を返すとき、末尾に ',' は含まれない.
3859 # ファイルへ出力するとき、末尾に ',' が出力される.構造体要素、配列要素の初期値を出力すると ',' が二重に出力される.
3860 # ただし現状では、ファイルへ出力することはない
3861 #
3862 def gen_cell_cb_init( f, cell, name_array, type, init, identifier, indent, f_get_str = false )
3863
3864 cell_CB_name = name_array[2]
3865 cell_CB_INIT = name_array[3]
3866
3867 while type.kind_of?( DefinedType )
3868 type = type.get_type
3869 end
3870
3871 if ( init == nil ) then
3872
3873 if f_get_str then
3874 # 初期値未指定
3875 if type.kind_of?( BoolType ) then
3876 str = "false" # formerly tecs_false
3877 elsif type.kind_of?( IntType ) then
3878 str = "0"
3879 elsif type.kind_of?( FloatType ) then
3880 str = "0.0"
3881 elsif type.kind_of?( EnumType ) then
3882 str = "0"
3883 elsif type.kind_of?( ArrayType ) then
3884 str = "{}"
3885 elsif type.kind_of?( StructType ) then
3886 str = "{}"
3887 elsif type.kind_of?( PtrType ) then
3888 if type.get_size then
3889 str = "#{cell_CB_INIT}_#{identifier}_INIT"
3890 else
3891 str = "0"
3892 end
3893 else
3894 raise "UnknownType"
3895 end
3896 return str
3897 else
3898 # 初期値未指定
3899 if type.kind_of?( BoolType ) then
3900 f.print " " * indent
3901 f.printf( "%-40s /* %s */\n", "false,", identifier ) # formerly tecs_false
3902 elsif type.kind_of?( IntType ) then
3903 f.print " " * indent
3904 f.printf( "%-40s /* %s */\n", "0,", identifier )
3905 elsif type.kind_of?( FloatType ) then
3906 f.print " " * indent
3907 f.printf( "%-40s /* %s */\n", "0.0,", identifier )
3908 elsif type.kind_of?( EnumType ) then
3909 f.print " " * indent
3910 f.printf( "%-40s /* %s */\n", "0,", identifier )
3911 elsif type.kind_of?( ArrayType ) then
3912 f.print " " * indent
3913 f.printf( "%-40s /* %s */\n", "{},", identifier )
3914 elsif type.kind_of?( StructType ) then
3915 f.print " " * indent
3916 f.printf( "%-40s /* %s */\n", "{},", identifier )
3917 elsif type.kind_of?( PtrType ) then
3918 if type.get_size then
3919 f.print " " * indent
3920 f.printf( "%-40s /* %s */\n", "#{cell_CB_INIT}_#{identifier}_INIT,", identifier )
3921 else
3922 f.print " " * indent
3923 f.printf( "%-40s /* %s */\n", "0,", identifier )
3924 end
3925 else
3926 raise "UnknownType"
3927 end
3928 end
3929 return
3930 end
3931
3932 # このメソッドは Celltype のものである必要は無い(上に続くのでここに置く)
3933 # 初期値指定あり
3934 if type.kind_of?( BoolType ) then
3935 if init.instance_of?( C_EXP ) then
3936 init_str = subst_name( init.get_c_exp_string, name_array )
3937 else
3938 init_str = init.eval_const2(cell.get_join_list,@name_list)
3939 end
3940
3941 if f_get_str then
3942 return "#{init_str}"
3943 else
3944 f.print " " * indent
3945 f.printf( "%-40s /* %s */\n", "#{init_str},", identifier )
3946 end
3947# if f_get_str then
3948# return "#{init.eval_const2(nil)}"
3949# else
3950# f.print " " * indent
3951# f.printf( "%-40s /* %s */\n", "#{init.eval_const2(nil)},", identifier )
3952# end
3953 elsif type.kind_of?( IntType ) then
3954 if init.instance_of?( C_EXP ) then
3955 init_str = subst_name( init.get_c_exp_string, name_array )
3956 else
3957 init_str = init.eval_const2(cell.get_join_list,@name_list)
3958 end
3959
3960 if f_get_str then
3961 return "#{init_str}"
3962 else
3963 f.print " " * indent
3964 f.printf( "%-40s /* %s */\n", "#{init_str},", identifier )
3965 end
3966 elsif type.kind_of?( FloatType ) then
3967 # mikan C_EXP for FloatType
3968 if f_get_str then
3969 return "#{init.eval_const2(cell.get_join_list,@name_list)}"
3970 else
3971 f.print " " * indent
3972 f.printf( "%-40s /* %s */\n", "#{init.eval_const2(cell.get_join_list,@name_list)},", identifier )
3973 end
3974 elsif type.kind_of?( EnumType ) then
3975 # mikan C_EXP for EnumType
3976 if f_get_str then
3977 return "#{init.eval_const2(cell.get_join_list,@name_list)}"
3978 else
3979 f.print " " * indent
3980 f.printf( "%-40s /* %s */\n", "#{init.eval_const2(cell.get_join_list,@name_list)},", identifier )
3981 end
3982 elsif type.kind_of?( ArrayType ) then
3983 if type.get_subscript
3984 len = type.get_subscript.eval_const(cell.get_join_list,@name_list)
3985 else
3986 len = init.length
3987 end
3988
3989 at = type.get_type
3990 i = 0
3991 if f_get_str then
3992 str = "{ "
3993 else
3994 f.print " " * indent
3995 f.print( "{\n" )
3996 end
3997
3998 len.times {
3999 next if ! init[i] # mikan この処置は適切?
4000 if f_get_str then
4001 str += gen_cell_cb_init( f, cell, name_array, at, init[i], "#{identifier}[#{i}]", indent + 1, f_get_str )
4002 str += ', '
4003 else
4004 gen_cell_cb_init( f, cell, name_array, at, init[i], "#{identifier}[#{i}]", indent + 1, f_get_str )
4005 end
4006 i += 1
4007 }
4008
4009 if f_get_str then
4010 str += "}"
4011 else
4012 f.print " " * indent
4013 f.print( "},\n" )
4014 end
4015
4016 elsif type.kind_of?( StructType ) then
4017 i = 0
4018 decls = type.get_members_decl.get_items
4019 if f_get_str then
4020 str = "{ "
4021 else
4022 f.print " " * indent
4023 f.print( "{ /* #{identifier} */\n" )
4024 end
4025
4026 decls.each{ |d|
4027 # p "#{d.get_identifier}: #{init}"
4028 next if ! init[i]
4029
4030 if f_get_str then
4031 str += gen_cell_cb_init( f, cell, name_array, d.get_type, init[i], d.get_identifier, indent + 1, f_get_str )
4032 str += ', '
4033 else
4034 gen_cell_cb_init( f, cell, name_array, d.get_type, init[i], d.get_identifier, indent + 1, f_get_str )
4035 end
4036 i += 1
4037 }
4038 if f_get_str then
4039 str += "}"
4040 else
4041 f.print " " * indent
4042 f.print( "},\n" )
4043 end
4044
4045 elsif type.kind_of?( PtrType ) then
4046
4047 if init.instance_of?( Array ) then
4048 if f_get_str then
4049 return "#{cell_CB_INIT}_#{identifier}_INIT"
4050 else
4051 f.print " " * indent
4052 f.printf( "%-40s /* %s */\n", "#{cell_CB_INIT}_#{identifier}_INIT,", identifier )
4053 end
4054 elsif init.instance_of?( C_EXP ) then
4055 init_str = subst_name( init.get_c_exp_string, name_array )
4056
4057 if f_get_str then
4058 return "#{init_str}"
4059 else
4060 f.print " " * indent
4061 f.printf( "%-40s /* %s */\n", "#{init_str},", identifier )
4062 end
4063
4064 else
4065 if f_get_str then
4066 return "#{init.eval_const2(cell.get_join_list,@name_list)}"
4067 else
4068 f.print " " * indent
4069# p init.eval_const2(cell.get_join_list,@name_list).class
4070# p init.eval_const2(cell.get_join_list,@name_list)
4071# p identifier
4072 f.printf( "%-40s /* %s */\n", "#{init.eval_const2(cell.get_join_list,@name_list)},", identifier )
4073
4074 end
4075 end
4076 else
4077 raise "UnknownType"
4078 end
4079 end
4080
4081 #== 関数テーブルの外部参照
4082 def gen_cell_extern_mt fs
4083 fs.each{ |r, f|
4084 if ! r.is_root? then
4085 @port.each{ |p|
4086 next if p.is_omit?
4087 if p.get_port_type == :ENTRY && ! p.is_VMT_useless? then
4088 f.print "extern const struct tag_#{p.get_signature.get_global_name}_VMT"
4089 f.print " #{@global_name}_#{p.get_name}_MT_;\n"
4090 end
4091 }
4092 end
4093 }
4094 end
4095
4096 #=== 受け口ディスクリプタの定義を生成
4097 def gen_cell_ep_des fs
4098 if @n_cell_gen >0 then
4099 fs.each{ |r, f| f.printf( TECSMsg.get( :EPD_comment ), "#_EPD_#" ) }
4100 end
4101
4102 index = 0
4103 @ordered_cell_list.each{ |c|
4104
4105 next if ! c.is_generate?
4106
4107 f = fs[ c.get_region.get_domain_root ]
4108
4109 ct = c.get_celltype
4110 jl = c.get_join_list
4111
4112 port = ct.get_port_list
4113 if port.length != 0 then
4114 port.each{ |p|
4115 next if p.get_port_type != :ENTRY
4116 next if p.is_omit?
4117 if p.is_skelton_useless? # 受け口最適化n ep_opt
4118 f.print( "/* #{p.get_name} : omitted by entry port optimize */\n" )
4119 next
4120 end
4121
4122 len = p.get_array_size
4123 if len == "[]" then
4124 len = c.get_entry_port_max_subscript(p) + 1
4125 end
4126
4127 if len != nil then
4128 # 受け口配列の場合
4129 i = 0
4130 while i < len
4131 f.print "extern const struct tag_#{@global_name}_#{p.get_name}_DES"
4132 f.print " #{c.get_global_name}_#{p.get_name}_des#{i};\n"
4133 f.print "const struct tag_#{@global_name}_#{p.get_name}_DES"
4134 # f.print " #{c.get_name}_#{p.get_name}_des#{i} = {\n"
4135 f.print " #{c.get_global_name}_#{p.get_name}_des#{i} = {\n"
4136 if p.is_VMT_useless? then
4137 f.print " 0,\n"
4138 else
4139 f.print " &#{@global_name}_#{p.get_name}_MT_,\n"
4140 end
4141 if( @idx_is_id_act )then
4142 f.print " #{c.get_id}, /* ID */\n"
4143 else
4144 if has_CB? then
4145 if @singleton then
4146 f.print " &#{@global_name}_SINGLE_CELL_CB, /* CB */\n"
4147 else
4148 # f.print " &#{@global_name}_#{c.get_name}_CB,\n"
4149 f.print " &#{@global_name}_CB_tab[#{index}], /* CB */\n"
4150 end
4151 elsif has_INIB? then
4152 if @singleton then
4153 f.print " &#{@global_name}_SINGLE_CELL_INIB, /* INIB */\n"
4154 else
4155 f.print " &#{@global_name}_INIB_tab[#{index}], /* INIB */\n"
4156 end
4157 else
4158 f.print " 0,\n"
4159 end
4160 end
4161 f.print " #{i}\n"
4162 f.print "};\n"
4163 i += 1
4164 end
4165 else
4166 f.print "extern const struct tag_#{@global_name}_#{p.get_name}_DES"
4167 f.print " #{c.get_global_name}_#{p.get_name}_des;\n"
4168 f.print "const struct tag_#{@global_name}_#{p.get_name}_DES"
4169 # f.print " #{c.get_name}_#{p.get_name}_des = {\n"
4170 f.print " #{c.get_global_name}_#{p.get_name}_des = {\n"
4171 if p.is_VMT_useless? then
4172 f.print " 0,\n"
4173 else
4174 f.print " &#{@global_name}_#{p.get_name}_MT_,\n"
4175 end
4176 if @idx_is_id_act then
4177 f.print " #{c.get_id}, /* ID */\n"
4178 else
4179 if has_CB? then
4180 if @singleton then
4181 f.print " &#{@global_name}_SINGLE_CELL_CB, /* CB */\n"
4182 else
4183 f.print " &#{@global_name}_CB_tab[#{index}], /* CB */\n"
4184 # f.print " &#{@global_name}_#{c.get_name}_CB,\n"
4185 end
4186 elsif has_INIB? then
4187 if @singleton then
4188 f.print " &#{@global_name}_SINGLE_CELL_INIB, /* INIB */\n"
4189 else
4190 f.print " &#{@global_name}_INIB_tab[#{index}], /* INIB */\n"
4191 end
4192 else
4193 f.print " 0,\n"
4194 end
4195 end
4196 f.print "};\n"
4197 end
4198 }
4199 end
4200 index += 1
4201 }
4202 end
4203
4204 def generate_template_code
4205
4206 return if is_all_entry_inline?
4207 return if @b_reuse && ! $generate_all_template
4208 if ! ( @plugin && @plugin.gen_ep_func? ) then
4209 return if $generate_no_template # $generate_all_template より優先される
4210
4211 # 参考として出力するテンプレートファイルであることを示すために "_templ" を付加する
4212 fname = "#{$gen}/#{@global_name}_templ.#{$c_suffix}"
4213 else
4214 # Plugin により生成されたセルタイプについては、原則的にテンプレートではなく、
4215 # 修正不要なセルタイプの実装コードを生成する.
4216 # このため、ファイル名に _temp を付加しない
4217 fname = "#{$gen}/#{@global_name}.#{$c_suffix}"
4218 end
4219
4220 f = AppFile.open(fname)
4221
4222 unless ( @plugin && @plugin.gen_ep_func? ) then
4223 f.printf( TECSMsg.get( :template_note ), @name, @name )
4224 else
4225 print_note( f, true )
4226 end
4227
4228 f.print TECSMsg.get( :preamble_note )
4229 gen_template_attr_access f
4230 gen_template_cp_fun f
4231 # gen_template_types f # 0805503 追加してみたが、やっぱりやめる
4232 f.print( " *\n * #[</PREAMBLE>]# */\n\n" )
4233 f.printf TECSMsg.get( :PAC_comment ), "#_PAC_#"
4234
4235 gen_template_private_header f
4236 if ( @plugin ) then
4237 # このメソッドの引数は plugin.rb の説明を見よ
4238 @plugin.gen_preamble( f, @singleton, @name, @global_name )
4239 end
4240
4241 gen_template_ep_fun f
4242
4243 f.print TECSMsg.get( :postamble_note )
4244
4245 if ( @plugin ) then
4246 # このメソッドの引数は plugin.rb の説明を見よ
4247 @plugin.gen_postamble( f, @singleton, @name, @global_name )
4248 end
4249
4250 f.close
4251 end
4252
4253##### celltype template
4254
4255 def gen_template_private_header f
4256 f.print "#include \"#{@global_name}_tecsgen.#{$h_suffix}\"\n\n"
4257 f.print <<EOT
4258#ifndef E_OK
4259#define E_OK 0 /* success */
4260#define E_ID (-18) /* illegal ID */
4261#endif
4262
4263EOT
4264 end
4265
4266 def gen_template_attr_access f
4267
4268 if @n_attribute_rw > 0 || @n_attribute_ro > 0 || @n_var > 0 then
4269 f.printf( TECSMsg.get( :CAAM_comment ), "#_CAAM_#" )
4270 end
4271
4272 @attribute.each { |a|
4273
4274 next if a.is_omit?
4275
4276 f.printf( " * %-16s %-16s %-16s\n", a.get_name, "#{a.get_type.get_type_str} #{a.get_type.get_type_str_post}", "ATTR_#{a.get_name}" )
4277
4278 }
4279
4280 @var.each { |v|
4281
4282 next if v.is_omit?
4283
4284 f.printf( " * %-16s %-16s %-16s\n", v.get_name, "#{v.get_type.get_type_str} #{v.get_type.get_type_str_post}", "VAR_#{v.get_name}" )
4285 }
4286
4287 end
4288
4289 def gen_template_types f
4290 f.printf( TECSMsg.get( :TYP_comment ), "#_TYP_#", "#{@global_name}_CB", "#{@name}_IDX" )
4291 end
4292
4293 def gen_template_cp_fun f
4294 if @n_call_port >0 then
4295 f.print " *\n"
4296 f.printf( TECSMsg.get( :TCPF_comment ), "#_TCPF_#" )
4297 end
4298
4299 @port.each { |p|
4300 next if p.get_port_type != :CALL
4301 # next if p.is_omit?
4302
4303 sig_name = p.get_signature.get_global_name
4304 con_tmp = p.get_signature.get_context
4305 if con_tmp then
4306 context = " context:#{con_tmp}"
4307 else
4308 context = ""
4309 end
4310
4311 if p.is_optional? then
4312 optional = " optional:true"
4313 if p.get_array_size
4314 is_join = " * bool_t is_#{p.get_name}_joined(int subscript) check if joined\n"
4315 else
4316 is_join = " * bool_t is_#{p.get_name}_joined() check if joined\n"
4317 end
4318 else
4319 optional = ""
4320 is_join = ""
4321 end
4322
4323 if p.is_omit? then
4324 omit = " omit:true"
4325 else
4326 omit = ""
4327 end
4328
4329 if p.is_allocator_port? then
4330 f.print " * allocator port for #{p.get_port_type.to_s.downcase} port:#{p.get_allocator_port.get_name} func:#{p.get_allocator_func_decl.get_name} param: #{p.get_allocator_param_decl.get_name}\n"
4331 elsif ! p.is_require? then
4332 f.print " * call port: #{p.get_name} signature: #{sig_name}#{context}#{optional}#{omit}\n#{is_join}"
4333 else
4334 f.print " * require port: signature:#{sig_name}#{context}\n"
4335 end
4336
4337 p.get_signature.get_function_head_array.each{ |fun|
4338
4339 ft = fun.get_declarator.get_type
4340
4341 f.printf( " * %-14s ", ft.get_type.get_type_str )
4342 if ! p.is_require? || p.has_name? then
4343 f.print( "#{p.get_name}_#{fun.get_name}(" )
4344 else
4345 f.print( "#{fun.get_name}(" )
4346 end
4347 delim = ""
4348
4349# if ! @singleton then
4350# f.print( "#{delim} p_that" )
4351# delim = ","
4352# end
4353
4354 if p.get_array_size then
4355 f.print( "#{delim} subscript" )
4356 delim = ","
4357 end
4358
4359 ft.get_paramlist.get_items.each{ |param|
4360 # p "type_str: #{param.get_type.get_type_str}"
4361 f.print( "#{delim} #{param.get_type.get_type_str}" )
4362 f.print( " #{param.get_name}#{param.get_type.get_type_str_post}" )
4363 delim = ","
4364 }
4365 f.print( " );\n" )
4366
4367# subsc = ""
4368# subsc = "[subscript]" if p.get_array_size
4369#
4370# if @singleton then
4371# f.print( " * #{@global_name}_#{p.get_name}" )
4372# else
4373# f.print( " * (p_that)->#{p.get_name}" )
4374# end
4375# f.print( "#{subsc}->VMT->#{fun.get_name}(" )
4376# f.print( " (p_that)->#{p.get_name}#{subsc}" )
4377# ft.get_paramlist.get_items.each{ |param|
4378# f.print( ", (#{param.get_name})" )
4379# }
4380# f.print( " )\n" )
4381
4382 }
4383
4384 if p.get_array_size then
4385 f.print " * subscript: 0...(NCP_#{p.get_name}-1)\n"
4386 end
4387
4388 if p.is_ref_desc? then
4389 subsc = p.get_array_size ? ' int_t subscript ' : ''
4390 f.print " * [ref_desc]\n"
4391 f.printf( " * %-14s %s;\n",
4392 "Descriptor( #{p.get_signature.get_global_name} )",
4393 "#{p.get_name}_refer_to_descriptor(#{subsc})" )
4394 f.printf( " * %-14s %s;\n",
4395 "Descriptor( #{p.get_signature.get_global_name} )",
4396 "#{p.get_name}_ref_desc(#{subsc}) (same as above; abbreviated version)" )
4397 end
4398 if p.is_dynamic? then
4399 subsc = p.get_array_size ? 'int_t subscript, ' : ''
4400 subsc2 = p.get_array_size ? ' int_t subscript' : ''
4401 if p.is_optional? then
4402 f.print " * [dynamic, optional]\n"
4403 else
4404 f.print " * [dynamic]\n"
4405 end
4406 f.printf( " * %-14s %s;\n",
4407 "void",
4408 "#{p.get_name}_set_descriptor( #{subsc}Descriptor( #{p.get_signature.get_global_name} ) desc )" )
4409 if p.is_optional? then
4410 f.printf( " * %-14s %s;\n",
4411 "void",
4412 "#{p.get_name}_unjoin( #{subsc2} )" )
4413 end
4414 end
4415 }
4416
4417 end
4418
4419 def gen_template_ep_fun( f, b_inline = false )
4420
4421 if @n_entry_port >0 then
4422 f.printf( TECSMsg.get( :TEPF_comment ), "#_TEPF_#" )
4423 end
4424
4425 @port.each { |p|
4426 next if p.get_port_type != :ENTRY
4427 next if p.is_omit?
4428 next if b_inline && ! p.is_inline? # inline ポート
4429 next if ! b_inline && p.is_inline? # 非 inline ポート
4430
4431 inline_prefix = ""
4432 nCELLIDX = "CELLIDX"
4433 nCELLCB = "CELLCB"
4434 nVALID_IDX = "VALID_IDX"
4435 nGET_CELLCB = "GET_CELLCB"
4436
4437 f.print <<EOT
4438/* #[<ENTRY_PORT>]# #{p.get_name}
4439 * entry port: #{p.get_name}
4440 * signature: #{p.get_signature.get_global_name}
4441 * context: #{p.get_signature.get_context}
4442EOT
4443
4444 if p.get_array_size != nil then
4445 f.print <<EOT
4446 * entry port array size: NEP_#{p.get_name}
4447EOT
4448 end
4449
4450 f.print <<EOT
4451 * #[</ENTRY_PORT>]# */
4452
4453EOT
4454
4455 p.get_signature.get_function_head_array.each{ |fun|
4456 f.print <<EOT
4457/* #[<ENTRY_FUNC>]# #{p.get_name}_#{fun.get_name}
4458 * name: #{p.get_name}_#{fun.get_name}
4459 * global_name: #{@global_name}_#{p.get_name}_#{fun.get_name}
4460 * oneway: #{fun.is_oneway?}
4461 * #[</ENTRY_FUNC>]# */
4462EOT
4463
4464 if b_inline then
4465 f.print "Inline "
4466 end
4467 functype = fun.get_declarator.get_type
4468 f.printf "%s\n", functype.get_type_str
4469 f.print "#{inline_prefix}#{p.get_name}_#{fun.get_name}("
4470 if @singleton then
4471 delim = ""
4472 else
4473 f.print "#{nCELLIDX} idx"
4474 delim = ", "
4475 end
4476
4477 if p.get_array_size then
4478 f.print "#{delim}int_t subscript"
4479 delim = ", "
4480 end
4481
4482 if functype.get_paramlist then
4483 items = functype.get_paramlist.get_items
4484 len = items.length
4485 else
4486 # ここで nil になるのは、引数なしの時に void がなかった場合
4487 items = []
4488 len = 0
4489 end
4490
4491 i = 0
4492 items.each{ |param|
4493 f.print "#{delim}"
4494 delim = ", "
4495 f.print param.get_type.get_type_str
4496 # p "type_str2: #{param.get_type.get_type_str}"
4497 f.print " "
4498 f.print param.get_name
4499 f.print param.get_type.get_type_str_post
4500 i += 1
4501 }
4502 f.print ")\n"
4503
4504 f.print "{\n"
4505
4506 if ( @plugin && @plugin.gen_ep_func? ) then
4507 # このメソッドの引数は plugin.rb の説明を見よ
4508 @plugin.gen_ep_func_body( f, @singleton, @name, @global_name, p.get_signature.get_global_name, p.get_name, fun.get_name, "#{@global_name}_#{p.get_name}_#{fun.get_name}", functype, items )
4509
4510 else
4511 if ! @singleton then
4512 if functype.get_type.kind_of?( DefinedType ) && ( functype.get_type.get_type_str == "ER" || functype.get_type.get_type_str == "ER_UINT" ) then
4513 if ! fun.is_oneway? then
4514 f.print " ER\t\tercd = E_OK;\n"
4515 er_cd = "return(E_ID);"
4516 ret_cd = "return(ercd);"
4517 else
4518 er_cd = "#{TECSMsg.get(:oneway_ercd_note)}\n return(E_OK);"
4519 ret_cd = "#{TECSMsg.get(:oneway_ercd_note)}\n return(E_OK);"
4520 end
4521 else
4522 er_cd = "#{TECSMsg.get(:ercd_note)}"
4523 ret_cd = nil
4524 end
4525 f.print <<EOT
4526 #{nCELLCB} *p_cellcb;
4527 if (#{nVALID_IDX}(idx)) {
4528 p_cellcb = #{nGET_CELLCB}(idx);
4529 }
4530 else {
4531 #{er_cd}
4532 } /* end if #{nVALID_IDX}(idx) */
4533
4534EOT
4535 f.printf( TECSMsg.get( :TEFB_comment ), "#_TEFB_#" )
4536 f.printf( "\n" )
4537
4538 if ret_cd then
4539 f.print " #{ret_cd}\n"
4540 end
4541 else
4542 end # ! @singleton
4543 end # @plugin
4544
4545 f.print "}\n\n"
4546 }
4547 }
4548 end
4549
4550 def generate_inline_template_code
4551 return if @n_entry_port_inline == 0
4552 if ! ( @plugin && @plugin.gen_ep_func? ) then
4553 return if @b_reuse && ! $generate_all_template
4554 return if $generate_no_template # $generate_all_template より優先される
4555
4556 # 参考として出力するテンプレートファイルであることを示すために "_templ" を付加する
4557 fname = "#{$gen}/#{@global_name}_inline_templ.#{$h_suffix}"
4558 else
4559 # Plugin により生成されたセルタイプについては、原則的にテンプレートではなく、
4560 # 修正不要なセルタイプの実装コードを生成する.
4561 # このため、ファイル名に _temp を付加しない
4562 fname = "#{$gen}/#{@global_name}_inline.#{$h_suffix}"
4563 end
4564 f = AppFile.open(fname)
4565
4566 gen_ph_guard f, "_INLINE"
4567
4568 unless ( @plugin && @plugin.gen_ep_func? ) then
4569 f.printf( TECSMsg.get( :inline_template_note ), @name, @name )
4570 else
4571 print_note( f, true )
4572 end
4573
4574 f.print TECSMsg.get( :preamble_note )
4575 gen_template_attr_access f
4576 gen_template_cp_fun f
4577 f.print( " *\n * #[</PREAMBLE>]# */\n\n" )
4578
4579 gen_template_ep_fun( f, true )
4580
4581 f.print TECSMsg.get( :postamble_note )
4582
4583 if ( @plugin ) then
4584 # このメソッドの引数は plugin.rb の説明を見よ
4585 @plugin.gen_postamble( f, @singleton, @name, @global_name )
4586 end
4587
4588 f.print "\n"
4589 gen_ph_endif f, "INLINE"
4590 f.close
4591 end
4592
4593
4594##### generate tecsgen.cfg
4595
4596 def generate_celltype_factory_code
4597
4598 @ct_factory_list.each { |fa|
4599 if fa.get_name == :write then
4600
4601 # 前後の " を取り除く
4602 # file_name = fa.get_file_name.sub( /^\"(.*)\"$/, "\\1" )
4603 file_name = CDLString.remove_dquote fa.get_file_name
4604 format = CDLString.remove_dquote fa.get_format
4605 # format = fa.get_format.sub( /^\"(.*)/, "\\1" ) # 前の " を取り除く
4606 # format = format.sub( /(.*)\"\z/, "\\1" ) # 後の " を取り除く
4607 format = format.gsub( /\\\n/, "\n" ) # \\\n => \n
4608
4609
4610 # mikan 以下は subst_name で置換するように変更すべき
4611 file_name = file_name.gsub( /(^|[^\$])\$ct\$/, "\\1#{@name}" ) # $ct$ をセルタイプ名に置換
4612 file_name = file_name.gsub( /(^|[^\$])\$ct_global\$/, "\\1#{@global_name}" ) # $ct$ をセルタイプ名に置換
4613 format = format.gsub( /(^|[^\$])\$ct\$/, "\\1#{@name}" ) # $ct$ をセルタイプ名に置換
4614 format = format.gsub( /(^|[^\$])\$ct_global\$/, "\\1#{@global_name}" ) # $ct$ をセルタイプ名に置換
4615 format = format.gsub( /\$\$/, "\$" ) # $$ を $ に置換
4616
4617 if file_name[0] != ?/ then
4618 file_name = "#{$gen}/#{file_name}"
4619 end
4620
4621 begin
4622 cfg_file = AppFile.open( file_name )
4623 if $debug then
4624 print "'#{@name}' : celltype factory format: "
4625 puts( format )
4626 end
4627 # format 中の \n, \r, \t, \f と \" などを置換
4628 fmt = CDLString.escape format
4629 cfg_file.print( fmt )
4630 cfg_file.puts( "\n" )
4631 cfg_file.close()
4632 rescue => evar
4633 cdl_error( "H1004 \'$1\' : write error while writing factory (specify -t to get more info)" , file_name )
4634 print_exception( evar )
4635 end
4636 end
4637 }
4638 end
4639
4640 def generate_cell_factory_code
4641
4642 @ordered_cell_list.each{ |c|
4643
4644 # cell のプロトタイプ宣言なら無視
4645 next if ! c.is_generate?
4646
4647 name_array = get_name_array( c )
4648
4649 @factory_list.each { |fa|
4650
4651 if fa.get_name == :write then
4652
4653 # 前後の " を取り除く
4654 # file_name = fa.get_file_name.sub( /^\"(.*)\"$/, "\\1" )
4655 file_name = CDLString.remove_dquote fa.get_file_name
4656 file_name = subst_name( file_name, name_array )
4657 # format = fa.get_format.sub( /^\"(.*)\"$/, "\\1" ) # 前後の "" を取り除く
4658 format = CDLString.remove_dquote fa.get_format
4659 # format = fa.get_format.sub( /^\"(.*)/, "\\1" ) # 前の " を取り除く
4660 # format = format.sub( /(.*)\"\z/, "\\1" ) # 後の " を取り除く
4661 format = format.gsub( /\\\n/, "\n" ) # \\\n => \n
4662
4663 format = subst_name( format, name_array )
4664
4665 arg_list = fa.get_arg_list
4666
4667 if file_name[0] != ?/ then
4668 file_name = "#{$gen}/#{file_name}"
4669 end
4670
4671 na = [] # シンボルを attribute の値に置き換えた後の引数
4672 if arg_list then
4673 arg_list.each { |a|
4674 case a[0]
4675 when :STRING_LITERAL # 文字列定数
4676 # s = a[1].sub( /^\"(.*)\"$/, "\\1" ) # 前後の "" を取り除く
4677 s = CDLString.remove_dquote a[1]
4678 s = subst_name( s, name_array )
4679 # s = subst_name( a[1], name_array )
4680
4681 na << s
4682 when :IDENTIFIER
4683 param_name = a[1] # 識別子(属性の名前)
4684 attr = self.find( param_name )
4685 init = attr.get_initializer # celltype で指定された初期値
4686
4687 # cell の join のリストから名前を探す
4688 j = c.get_join_list.get_item( param_name )
4689 if j then # param_name の cell のジョインがあるか
4690 init = j.get_rhs # cell で指定された初期値を優先
4691 end
4692
4693 str = gen_cell_cb_init( nil, c, name_array, attr.get_type, init, attr.get_identifier, 0, true )
4694 # file,cell, name_array, type, init, identifier, indent, f_get_str
4695
4696 # str = str.sub( /^\"(.*)\"$/, "\\1" ) # 前後の "" を取り除く mikan ここで置換でよい?
4697 str = CDLString.remove_dquote str
4698 na << str
4699 end
4700 }
4701 end
4702
4703 begin
4704 cfg_file = AppFile.open( file_name )
4705
4706 if $debug then
4707 print "'#{c.get_name}' : factory format: "
4708 print( format )
4709 print( " arg: " )
4710 na.each { |n| print "'#{n}' " }
4711 print( "\n" )
4712 end
4713
4714 # format 中の \n, \r, \t, \f と \" などを置換
4715 fmt = CDLString.escape format
4716 cfg_file.printf( fmt, *na )
4717 cfg_file.puts( "\n" )
4718 cfg_file.close()
4719 rescue => evar
4720 cdl_error( "H1005 \'$1\' : write error while writing factory (specify -t to get more info)" , file_name )
4721 print_exception( evar )
4722 end
4723 end
4724 }
4725 }
4726
4727 end
4728
4729 def generate_makefile
4730 generate_makefile_template
4731 generate_makefile_depend
4732 end
4733
4734 def generate_makefile_template
4735
4736 return if $generate_no_template
4737
4738 # Makefile.templ の生成(追記)
4739
4740 f = AppFile.open( "#{$gen}/Makefile.templ" )
4741 f.print <<EOT
4742$(_TECS_OBJ_DIR)#{@global_name}.o : #{@global_name}.#{$c_suffix}
4743 $(CC) -c $(CFLAGS) -o $@ $<
4744
4745EOT
4746# この生成規則は2点で意味がない
4747# ・$(GEN_DIR) に .o を生成するルールがない
4748# ・テンプレートコードをそのままビルドするのは紛らわしい
4749# # Celltype: #{@name}
4750# $(GEN_DIR)/#{@global_name}_tecsgen.o : $(GEN_DIR)/#{@global_name}_tecsgen.#{$c_suffix}
4751# $(CC) -c $(CFLAGS) -o $@ $<
4752#
4753# $(GEN_DIR)/#{@global_name}_templ.o : $(GEN_DIR)/#{@global_name}_templ.#{$c_suffix}
4754# $(CC) -c $(CFLAGS) -o $@ $<
4755#
4756
4757 f.close
4758
4759 end
4760
4761 def generate_makefile_depend
4762
4763 headers = [ "$(GEN_DIR)/#{@global_name}_tecsgen.#{$h_suffix}", "$(GEN_DIR)/#{@global_name}_factory.#{$h_suffix}", "$(GEN_DIR)/global_tecsgen.#{$h_suffix}" ]
4764
4765 # inline 受け口を持つか?
4766 if @n_entry_port_inline > 0 then
4767 headers << "#{@global_name}_inline.#{$h_suffix}"
4768 end
4769
4770 # 呼び口または受け口のシグニチャのヘッダ
4771 @port.each { |p|
4772 next if p.is_omit?
4773 headers << "$(GEN_DIR)/#{p.get_signature.get_global_name}_tecsgen.#{$h_suffix}"
4774 }
4775
4776 headers += get_depend_header_list
4777 headers.sort!
4778 headers.uniq!
4779 headers = headers.join " "
4780
4781 f = AppFile.open( "#{$gen}/Makefile.depend" )
4782
4783# print_Makefile_note f
4784
4785 f.print <<EOT
4786# Celltype: #{@name} #_MDEP_#
4787$(_TECS_OBJ_DIR)#{@global_name}_tecsgen.o : #{@global_name}_tecsgen.#{$c_suffix} #{headers}
4788$(_TECS_OBJ_DIR)#{@global_name}_templ.o : #{@global_name}_templ.#{$c_suffix} #{headers}
4789$(_TECS_OBJ_DIR)#{@global_name}.o : #{@global_name}.#{$c_suffix} #{headers}
4790
4791EOT
4792 f.close
4793 end
4794
4795 #=== decl 用の dealloc コードを生成
4796 #b_reset:: Bool: リセット用の dealloc コードの生成 (NULL ポインタの場合 dealloc しない)
4797 # mikan string 修飾されたポインタの先にポインタが来ないと仮定。ポインタ型を持つ構造体の可能性を排除していない
4798 # このメソッドでは、行を出力する直前に " \\\n" を出力し、行末で改行文字を出力しない
4799 def gen_dealloc_code_for_type( f, type, dealloc_func_name, pre, name, post, level, b_reset, count_str = nil )
4800 type = type.get_original_type
4801 indent = " " + " " * (level+1)
4802 if ! type.has_pointer?
4803 return
4804 elsif type.kind_of?( ArrayType ) then
4805 if type.get_type.has_pointer?
4806 loop_str = "i#{level}__"
4807 count_str = "#{type.get_subscript.eval_const(nil)}"
4808 f.print " \\\n"
4809 f.print "#{indent}{ int_t #{loop_str};"
4810 f.print " \\\n"
4811 f.print "#{indent} for( #{loop_str} = 0; #{loop_str} < #{count_str}; #{loop_str}++ ){ "
4812
4813 gen_dealloc_code_for_type( f, type.get_type, dealloc_func_name, pre, name, "#{post}[#{loop_str}]", level+2, b_reset )
4814
4815 f.print " \\\n"
4816 f.print "#{indent} }"
4817 f.print " \\\n"
4818 f.print "#{indent}}"
4819 end
4820 elsif type.kind_of?( StructType ) then
4821 members_decl = type.get_members_decl
4822 members_decl.get_items.each { |md|
4823 pre2 = pre + name.to_s + post + "."
4824 name2 = md.get_name
4825 post2 = ""
4826 type2 = md.get_type.get_original_type
4827 if type2.kind_of? PtrType then # mikan typedef された型
4828 if type2.get_count then
4829 count_str = type2.get_count.to_str( members_decl, pre2, post2 )
4830 elsif type2.get_size then
4831 count_str = type2.get_size.to_str( members_decl, pre2, post2 )
4832 else
4833 count_str = nil
4834 end
4835 else
4836 count_str = nil
4837 end
4838 gen_dealloc_code_for_type( f, md.get_type, dealloc_func_name, pre2, name2, post2, level, b_reset, count_str )
4839 }
4840
4841 elsif type.kind_of?( PtrType ) then
4842
4843 if b_reset || type.is_nullable? then
4844 nullable = ""
4845 if( !b_reset && type.is_nullable? )then
4846 nullable = "\t/* nullable */"
4847 end
4848 level2 = level + 1
4849 indent2 = indent + " "
4850 f.print " \\\n"
4851 f.print "#{indent}if( #{pre}#{name}#{post} ){#{nullable}"
4852 else
4853 level2 = level
4854 indent2 = indent
4855 end
4856
4857 if type.get_type.has_pointer?
4858 if count_str then
4859 loop_str = "i#{level}__"
4860 f.print " \\\n"
4861 f.print "#{indent2}{ int_t #{loop_str};"
4862 f.print " \\\n"
4863 f.print "#{indent2} for( #{loop_str} = 0; #{loop_str} < #{count_str}; #{loop_str}++ ){ "
4864
4865 gen_dealloc_code_for_type( f, type.get_type, dealloc_func_name, pre, name, "#{post}[#{loop_str}]", level2+2, b_reset )
4866
4867 f.print " \\\n"
4868 f.print "#{indent2} }"
4869 f.print " \\\n"
4870 f.print "#{indent2}}"
4871 else
4872 gen_dealloc_code_for_type( f, type.get_type, dealloc_func_name, "(*#{pre}", name, "#{post})", level2, b_reset )
4873 end
4874 end
4875 f.print " \\\n"
4876 f.print "#{indent2}#{dealloc_func_name}( #{pre}#{name}#{post} ); "
4877
4878 if b_reset || type.is_nullable? then
4879 f.print " \\\n"
4880 f.print "#{indent}}"
4881 end
4882 else
4883 raise "UnknownType"
4884 end
4885 end
4886
4887 def get_depend_header_list
4888 get_depend_header_list_( [] )
4889 end
4890
4891 def get_depend_header_list_( celltype_list )
4892 headers = []
4893
4894 if celltype_list.include? self then
4895 return headers
4896 else
4897 celltype_list << self
4898 end
4899
4900 # 呼び口の結合先のセルタイプのヘッダ(最適化の場合のみ)
4901 # 結合先の受け口が inline の場合、inline ヘッダも
4902 @port.each { |p|
4903 next if p.get_port_type != :CALL
4904 next if p.is_omit?
4905
4906 if p.is_skelton_useless? || p.is_cell_unique? || p.is_VMT_useless? then
4907 # 最適化コード (optimize) # スケルトン不要など
4908 p2 = p.get_real_callee_port
4909 if p2 then
4910 ct = p2.get_celltype
4911 headers << " $(GEN_DIR)/#{ct.get_global_name}_tecsgen.#{$h_suffix}"
4912 if p2.is_inline? then
4913 headers << " #{ct.get_global_name}_inline.#{$h_suffix}"
4914 end
4915 headers += ct.get_depend_header_list_( celltype_list )
4916 #else
4917 # optional で未結合
4918 end
4919 end
4920 }
4921 return headers
4922 end
4923
4924
4925 #=== $id$, $ct$, $cb$, $idx$ 置換
4926 #
4927 # str に以下の置換を行う
4928 #- $ct$ ⇒ セルタイプ名(ct)
4929 #- $cell$ ⇒ セル名(cell) cell が nil ならば3つの置換は行われない
4930 #- $cb$ ⇒ CB の C 言語名(cb)
4931 #- $cbp$ ⇒ CB へのポインタ(cbp)
4932 #- $cb_proto$ ⇒ CB の C 言語名プロトタイプ宣言用(cb_proto)
4933 #- $id$ ⇒ ct_cell
4934 #- $idx$ ⇒ idx
4935 #- $ID$ ⇒ id (整数の番号)
4936 #- $ct_global$ ⇒ セルタイプ名(ct)
4937 #- $cell_global$ ⇒ セル名(cell) cell が nil ならば3つの置換は行われない
4938 #- $$ ⇒ $
4939 def subst_name( str, name_array )
4940 ct = name_array[0] # celltype name
4941 cell = name_array[1] # cell name
4942 cb = name_array[2] # cell CB name
4943 cb_init = name_array[3] # cell CB INIT, これは置換に使われない
4944 cb_proto = name_array[4] # cell CB name for prototype
4945 id = name_array[6] # cell ID
4946 idx = name_array[7] # cell CB name for prototype
4947 cbp = name_array[8] # cell CB pointer
4948 ct_global = name_array[9] # cell CB pointer
4949 cell_global = name_array[10] # cell CB pointer
4950
4951 str = str.gsub( /(^|[^\$])\$ct\$/, "\\1#{ct}" )
4952 if cell then
4953 str = str.gsub( /(^|[^\$])\$cell\$/, "\\1#{cell}" )
4954 str = str.gsub( /(^|[^\$])\$cb\$/, "\\1#{cb}" )
4955 str = str.gsub( /(^|[^\$])\$id\$/, "\\1#{ct}_#{cell}" )
4956 str = str.gsub( /(^|[^\$])\$cb_proto\$/, "\\1#{cb_proto}" )
4957 str = str.gsub( /(^|[^\$])\$ID\$/, "\\1#{id}" )
4958 str = str.gsub( /(^|[^\$])\$idx\$/, "\\1#{idx}" )
4959 str = str.gsub( /(^|[^\$])\$cbp\$/, "\\1#{cbp}" )
4960 str = str.gsub( /(^|[^\$])\$ct_global\$/, "\\1#{ct_global}" )
4961 str = str.gsub( /(^|[^\$])\$cell_global\$/, "\\1#{cell_global}" )
4962 end
4963 str = str.gsub( /\$\$/, "\$" ) # $$ を $ に置換
4964
4965 return str
4966 end
4967
4968end
4969
4970# Appendable File(追記可能ファイル)
4971class AppFile
4972 # 開いたファイルのリスト
4973 @@file_name_list = {}
4974
4975 def self.open( name )
4976 if $force_overwrite
4977 real_name = name
4978 else
4979 real_name = name+".tmp"
4980 end
4981
4982#2.0
4983 if $b_no_kcode then
4984 mode = ":" + $Ruby19_File_Encode
4985 else
4986 mode = ""
4987 end
4988
4989 # 既に開いているか?
4990 if @@file_name_list[ name ] then
4991#2.0
4992 mode = "a" + mode
4993 # 追記モードで開く
4994 file = File.open( real_name, mode )
4995 else
4996#2.0
4997 mode = "w" + mode
4998 # 新規モードで開く(既にあれば、サイズを0にする)
4999 file = File.open( real_name, mode )
5000 @@file_name_list[ name ] = true
5001 end
5002 # File クラスのオブジェクトを返す
5003 return file
5004 end
5005
5006 def self.update
5007 if $force_overwrite
5008 return
5009 end
5010
5011 @@file_name_list.each{ |name,boo|
5012 b_identical = false
5013 if File.readable? name
5014 old_lines = File.readlines name
5015 new_lines = File.readlines name + ".tmp"
5016 if old_lines.length == new_lines.length then
5017 i = 0
5018 len = old_lines.length
5019 while i < len
5020 if old_lines[i] != new_lines[i]
5021 break
5022 end
5023 i += 1
5024 end
5025 if i == len
5026 b_identical = true
5027 end
5028 end
5029 end
5030 if b_identical == false then
5031 if $verbose then
5032 print "#{name} updated\n"
5033 print "renaming '#{name}.tmp' => '#{name}'\n"
5034 end
5035 File.rename name+".tmp", name
5036 else
5037 if $verbose then
5038 print "#{name} not updated\n"
5039 end
5040 File.delete name+".tmp"
5041 end
5042 }
5043 end
5044end
5045
5046class MemFile
5047 def initialize
5048 @string = ""
5049 end
5050 def print str
5051 @string += str
5052 end
5053 def get_string
5054 @string
5055 end
5056end
5057
5058class Region
5059
5060 def gen_region_str_pre f
5061 nest = 1
5062 while nest < @family_line.length
5063 f.print " " * ( nest-1 )
5064 f.print "region #{@family_line[ nest ].get_name}{\n"
5065 nest += 1
5066 end
5067 return nest - 1
5068 end
5069
5070 def gen_region_str_post f
5071 nest = @family_line.length - 1
5072 while nest >= 1
5073 f.print " " * ( nest-1 )
5074 f.print "};\n"
5075 nest -= 1
5076 end
5077 return nest - 1
5078 end
5079end
Note: See TracBrowser for help on using the repository browser.