source: EcnlProtoTool/trunk/asp3_dcre/tecsgen/tecslib/core/tecsgen.rb@ 270

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

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
File size: 16.1 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TECS Generator
4# Generator for TOPPERS Embedded Component System
5#
6# Copyright (C) 2008-2014 by TOPPERS Project
7#--
8# 上記著作権者
9は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
10# ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
11# 変・再é…
12å¸ƒï¼ˆä»¥ä¸‹ï¼Œåˆ©ç”¨ã¨å‘¼ã¶ï¼‰ã™ã‚‹ã“とを無償で許諾する.
13# (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
14# 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15# スコード中に含まれていること.
16# (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
17# 用できる形で再é…
18å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œå†é…
19å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨
20# 者
21マニュアルなど)に,上記の著作権表示,この利用条件および下記
22# の無保証規定を掲載すること.
23# (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
24# 用できない形で再é…
25å¸ƒã™ã‚‹å ´åˆã«ã¯ï¼Œæ¬¡ã®ã„ずれかの条件を満たすこ
26# と.
27# (a) 再é…
28å¸ƒã«ä¼´ã†ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆï¼ˆåˆ©ç”¨è€…
29マニュアルなど)に,上記の著
30# 作権表示,この利用条件および下記の無保証規定を掲載すること.
31# (b) 再é…
32å¸ƒã®å½¢æ…
33‹ã‚’,別に定める方法によって,TOPPERSプロジェクトに
34# 報告すること.
35# (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
36# 害からも,上記著作権者
37およびTOPPERSプロジェクトをå…
38è²¬ã™ã‚‹ã“と.
39# また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
40# 由に基づく請求からも,上記著作権者
41およびTOPPERSプロジェクトを
42# å…
43è²¬ã™ã‚‹ã“と.
44#
45# 本ソフトウェアは,無保証で提供されているものである.上記著作権者
46お
47# よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
48# に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
49# アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
50# の責任を負わない.
51#
52# $Id: tecsgen.rb 1011 2016-07-11 02:20:01Z coas-nagasima $
53#++
54
55
56class TECSGEN
57
58 #=== import パス (-I) を末尾に追加
59 # 既に登録済みであれば、追加しない
60 def self.add_import_path path
61 if $import_path.index( path ) == nil then
62 dbgPrint "add_import_path: '#{path}'\n"
63 $import_path << path
64 end
65 end
66
67 #=== EXEB 版のパスの調整
68 # 環境変数 TECSPATH が cygwin スタイルだと、exerb 版では扱えない
69 # $import_path と $TECSPATH を調整する
70 def self.adjust_exerb_path
71 if $IN_EXERB then
72 new_tecspath = cygpath( $tecspath, $tecspath )
73 pattern = /\A#{$tecspath}/
74 paths = []
75 $import_path.each{ |path|
76 # cygpath は '..' を簡約してしまうので、new_tecspath で置換する
77 # paths << cygpath( path, path )
78 paths << path.sub( pattern, new_tecspath )
79 }
80 $import_path = paths
81 $tecspath = new_tecspath
82 else
83 return
84 end
85 end
86
87 #=== $(TECSPATH) への置換
88 #path::String : ENV[ 'TECSPATH' ] に一致する部分があれば、 "$(TECSPATH)" に置換
89 #b_global::Bool : true なら gsub で置換。false なら sub で置換
90 def self.subst_tecspath( path, b_global = false )
91 tp = $tecspath.dup
92 tp.gsub!( /\\/, "\\\\\\\\" )
93 pattern = /#{tp}/
94 substr = "$(TECSPATH)"
95 if b_global then
96 str = path.gsub( pattern, substr )
97 else
98 str = path.sub( pattern, substr )
99 end
100 dbgPrint "subst_tecspath #{path}, #{str}\n"
101 return str
102 end
103
104 #=== path は絶対パスか?
105 #path:: String :
106 # '/' または '$' で始まる場合、絶対パスと判定する
107 def self.is_absolute_path?( path )
108 pa = path[0..0]; pa2 = path[0..1]
109 if pa == '/' || pa == '$' || pa2 =~ /[A-Za-z]:/ then
110 res = true
111 else
112 res = false
113 end
114 dbgPrint "is_absolute( #{path} ) = #{res} #{path[0]}\n"
115 return res
116 end
117
118 #=== tecsgen のデフォルトを設定
119 def self.set_default_config
120 Makefile::set_default_config
121 end
122
123 ###
124 #== Makefile.templ の出力内
125容を追加、変更するための操作
126 module Makefile
127 # 固定されている変数(add_var で変更できない)
128 @@fixed_vars = { :INCLUDES => nil, :DEFINES => nil, :TARGET_BASE => nil, :BASE_DIR => nil }
129 @@config_mode = false
130
131 @@vars = { }
132 @@vars_default = { }
133 @@var_comments = { }
134
135 @@objs = []
136 @@ldflags = ""
137 @@search_path = []
138 @@pre_tecsgen_target = []
139 @@post_tecsgen_target = []
140 @@lines = []
141
142 #=== OTHER_OBJS に追加する
143 def self.add_obj obj
144 @@objs << obj
145 end
146 #=== 追加する変数
147 # プラグインからは、デフォルト値を変更できる
148 # config により
149 def self.add_var( var, val, comment = nil )
150 if @@fixed_vars[ var ]
151 raise "fixed var '#{var}' cannot be changed"
152 end
153 if @@config_mode then
154 @@vars_default[ var.to_sym ] = val
155 @@var_comments_default[ var.to_sym ] = comment
156 else
157 @@vars[ var.to_sym ] = val
158 @@var_comments[ var.to_sym ] = comment
159 end
160 end
161 #=== LDFLAGS に追加する
162 def self.add_ldflag ldflag
163 @@ldflags += " " + ldflag
164 end
165 #=== サーチパスを追加する
166 # CFLAGS, vpath に追加する
167 def self.add_search_path path
168 @@search_path << path
169 end
170 #=== PRE_TECSGEN_TARGET に追加する
171 # PRE_TECSGEN_TARGET に target を追加する
172 def self.add_pre_tecsgen_target target
173 @@pre_tecsgen_target << pre_tecsgen_target
174 end
175 #=== POST_TECSGEN_TARGET に追加する
176 # POST_TECSGEN_TARGET に target を追加する
177 def self.add_post_tecsgen_target target
178 @@post_tecsgen_target << pre_tecsgen_target
179 end
180 #=== 追加する変数
181 def self.add_line( line )
182 @@lines << line.to_s + "\n"
183 end
184
185 def self.get_objs # Array を返す
186 return @@objs.uniq
187 end
188 def self.get_vars # Array を返す
189 if RUBY_VERSION >= '1.9' then
190 return (@@vars.keys + @@vars_default.keys).sort.uniq
191 else
192 # V1.8 では、Symbol の sort ができないので、一旦 String に置換する
193 return (@@vars.keys + @@vars_default.keys).map{|s| s.to_s }.sort.uniq.map!{|s| s.to_sym }
194 end
195 end
196 def self.get_var_val( var )
197 return @@vars[ var ] ? @@vars[ var ] : @@vars_default[ var ]
198 end
199 def self.get_var_comment( var )
200 return @@var_comments[ var ]
201 end
202 def self.get_ldflags # String を返す
203 return @@ldflags
204 end
205 def self.get_search_path # Array を返す
206 return @@search_path.uniq
207 end
208 def self.get_pre_tecsgen_target # Array を返す
209 return @@pre_tecsgen_target.uniq
210 end
211 def self.get_post_tecsgen_target # Array を返す
212 return @@post_tecsgen_target.uniq
213 end
214 def self.get_lines # 付加する行を得る
215 return @@lines.uniq
216 end
217
218 #=== TECSGEN のデフォルト設定を行う
219 # Makefile
220 # @@fixed_vars で定義されている変数は、変更できず、定数定義されている
221 def self.set_default_config
222 add_var( "TARGET", "$(TARGET_BASE).exe", "default target name" )
223 add_var( "TECSGEN", "tecsgen", "default TECS generator" )
224 add_var( "TIMESTAMP", "$(GEN_DIR)/tecsgen.timestamp", "Time Stamp" )
225 add_var( "CC", "gcc", "default C Compiler" )
226 add_var( "CFLAGS", '$(INCLUDES) $(DEFINES) -D "Inline=static inline"', "default C Compiler options" )
227 add_var( "LD", "gcc", "default Liknker" )
228 add_var( "LDFLAGS", @@ldflags, "default Liknker Options" )
229 add_var( "SRC_DIR", "$(BASE_DIR)/src", "default source directory" )
230 add_var( "_TECS_OBJ_DIR", "$(GEN_DIR)/", "default relocatable object (.o) directory" )
231 end
232 end
233
234 #------ TECSGEN CDL analyze and generate ------#
235
236 def syntax_analisys argv
237 # ルート namespace (region) を生成
238 @root_namespace = Region.new("::")
239
240 #### 構文解析 (post コードを除く) ####
241 # すべての cdl を import する
242 argv.each{ |f|
243 dbgPrint( "## Import: #{f}\n")
244 Import.new( f, false, false )
245 }
246
247 # すべての構文解釈が完了したことの報告
248 # 実際には、後からプラグインの生成する CDL のパースが行われる
249 # エラー行数の決定方法の変更のために行う
250 Generator.end_all_parse
251 dbgPrint( "## End all parse (except Post Code)\n")
252 end # syntax_analisys
253
254 def semantics_analisys_1
255 #### 意味解析1 (post コードを除く) ####
256 dbgPrint( "## Creating reverse join \n")
257 Cell.create_reverse_join
258
259 #0 set_definition_join は2回呼び出される(1回目)
260 dbgPrint( "## Checking all join\n")
261 @root_namespace.set_definition_join
262 # @root_namespace.set_require_join ### いったん見合わせ。重複エラーを見逃す
263 # through プラグインで生成されたセルにも require も生成できる (set_definition_join の後ろで実施)
264
265 #### post コードの生成と構文解析 ####
266 # 引数がなければ、プラグインのポストコードを出力しない
267 if ARGV.length > 0 then
268 dbgPrint( "## Generating Post Code\n")
269 # プラグインのポストコードの出力と import
270 tmp_file_name = "#{$gen}/tmp_plugin_post_code.cdl"
271 file = nil
272 begin
273 file = CFile.open( tmp_file_name, "w" )
274 rescue
275 Generator.error( "G9999 fail to create #{tmp_file_name}" )
276 end
277
278 if file then
279 # through プラグインのポストコード生成
280 PluginModule.gen_plugin_post_code file
281
282 begin
283 file.close
284 rescue
285 Generator.error( "G9999 fail to close #{tmp_file_name}" )
286 end
287 dbgPrint( "## Import Post Code\n")
288 Import.new( "#{tmp_file_name}" )
289 end
290 end
291
292 #### 意味解析1 (post コード) ####
293 dbgPrint( "## Creating reverse join (for post code) \n")
294 Cell.create_reverse_join
295
296 # Join の定義の設定とチェック
297 #0 # 前方参ç…
298§å¯¾å¿œ
299 #0 set_definition_join は2回呼び出される(2回目) post_code で生成された
300 dbgPrint( "## Checking all join (for cells generated by Post Code\n")
301 @root_namespace.set_definition_join
302
303 dbgPrint( "## Set require join\n")
304 @root_namespace.set_require_join # mikan post の前にも
305 # ポストコードで生成されたセルの require のjoin を生成
306 # mikan require で through が適用されて、ポストコードが必
307要となっても出力されない
308 end # semantics_analisys_1
309
310 def semantics_analisys_2
311 #### 意味解析2 ####
312 Cell.make_cell_list2
313 dbgPrint( "## Set fixed join\n")
314 Cell.create_reverse_require_join
315 # create_reverse_require_join は set_detinition_join に埋め込むことができない
316 # namespace に依存しない出現順で行う
317 # mikan through プラグインが適用されポストコードに影響を与える場合が考æ…
318®ã§ãã¦ã„ない
319 # mikan post code に影響のあるものであれば、早くに reverse_require_join の結合が必
320要
321 dbgPrint( "## Setting port reference count\n")
322 @root_namespace.set_port_reference_count
323
324 dbgPrint( "## Checking all join\n")
325 @root_namespace.check_join
326
327 # mikan プラグインで生成されたコンポーネントの set_def_and_check_join
328
329 dbgPrint( "## Checking referenced but undefined cell\n")
330 @root_namespace.check_ref_but_undef
331 end # semantics_analisys_2
332
333 def optimize_and_generate
334 #### Region link root ごとにオプティマイズおよび生成 ####
335 Region.get_link_roots.each { |region|
336
337 n_cells = region.get_n_cells
338
339 dbgPrint "#{region.get_name} has #{n_cells} cells\n"
340 if $verbose
341 print "=====================================\n"
342 print "=== Region.path_str: #{region.get_namespace_path.get_path_str}\n"
343 print "=====================================\n"
344 else
345 dbgPrint "Region.path_str: #{region.get_namespace_path.get_path_str}\n"
346 end
347
348 if $region_list.length > 0 then
349 if $region_list[ region.get_namespace_path.get_path_str ] then
350 $region_list[ region.get_namespace_path.get_path_str ] = false
351 else
352 next
353 end
354 end
355
356 # セルが一つもなければ生成しない
357 # セルの生成がない場合
358 if region.get_n_cells == 0 then
359 if $region_list.length > 0 then
360 Generator.warning( "W9999 $1: specified to generate but has no cell", region.get_name )
361 end
362 if region != @root_namespace then
363 next
364 end
365 end
366
367 $generating_region = region
368 if Region.get_link_roots.length > 1 then
369 if region.get_name == "::" then
370 $gen = $gen_base
371 else
372 $gen = $gen_base + "/" + region.get_global_name.to_s
373 begin
374 if ! File.directory?( $gen ) then
375 Dir.mkdir( $gen )
376 end
377 rescue
378 print( "Cannot mkdir #{$gen}\n" )
379 exit 1
380 end
381 end
382 else
383 $gen = $gen_base
384 end
385
386 dbgPrint( "## Unset optimize variables\n")
387 @root_namespace.reset_optimize # 最適化をリセットする
388
389 if Generator.get_n_error == 0 then
390 # エラーが発生していたら、設定しない
391 dbgPrint( "## Set cell id\n")
392 @root_namespace.set_cell_id_and_domain # セルの ID とドメイン情
393報を設定(linkunit 毎に0からつける)
394
395 # エラーが発生していたら、最適化は実施しない
396 if ! $unopt then
397 dbgPrint( "## Optimizing: Link Region=#{@root_namespace.get_name}\n")
398 @root_namespace.optimize
399 end
400 end
401
402 if $show_tree then
403 # エラーが発生していても表示(エラー発生時は最適化されていないので注意)
404 print "##### show_tree LinkRegion=#{region.get_name} #####\n"
405 @root_namespace.show_tree(0)
406 print "##### END LinkRegion=#{region.get_name} #####\n\n"
407 end
408
409 # 構文解釈、意味解析でエラー発生していたら、コード生成をしない
410 if Generator.get_n_error != 0 then
411 print_report
412 exit 1
413 end
414
415 #### コード生成 ####
416 begin
417 dbgPrint( "## Generating: Link Region=#{@root_namespace.get_name}\n")
418 @root_namespace.generate
419 dbgPrint( "## Generating Post: Link Region=#{@root_namespace.get_name}\n")
420 @root_namespace.generate_post
421 rescue
422 # 通常ここへは来ない (generate, generate_post で処置される)
423 Generator.error( "G9999 fail to generate" )
424 end
425 }
426 end # optimize_and_generate
427
428 def finalize
429 dbgPrint( "## Generating XML\n")
430 # Region.gen_xml @root_namespace
431 ##
432 # Namespace.gen_XML @root_namespace
433
434 $region_list.each{ |region_path_str, val|
435 if val == true then
436 Generator.warning( "W9999 $1: not link root, -G ignored", region_path_str )
437 end
438 }
439
440 # update する
441 # APPFile で生成されたファイルは、もし変化があれば、ここで更新する
442 # コード生成段階でエラーが発生すれば、更新しない
443 # CFile で生成されたものは、更新されている
444 if Generator.get_n_error == 0 then
445 begin
446 AppFile.update
447 rescue => evar
448 Generator.error( "G9999 Fail to update. (error occurred while renaming generated files)" )
449 print_exception( evar )
450 end
451 end
452
453 print_report
454 if Generator.get_n_error != 0 then
455 STDERR.print "error occurred while generating. some file can be corrupt in #{$gen_base}\n"
456 exit 1
457 end
458
459 open( "#{$gen_base}/tecsgen.timestamp", "w" ){|io|}
460 end # finalize
461end # class TECSGEN
Note: See TracBrowser for help on using the repository browser.