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