source: azure_iot_hub/trunk/asp3_dcre/tecsgen/tecslib/core/tecsgen.rb@ 388

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

Azure IoT Hub Device C SDK を使ったサンプルの追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
File size: 19.0 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# 上記著作権者
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$
53#++
54
55
56class TECSGEN
57
58 @@b_post_coded = false # ポストコード生成開始後 true
59
60 #=== import パス (-I) を末尾に追加
61 # 既に登録済みであれば、追加しない
62 def self.add_import_path path
63 if $import_path.index( path ) == nil then
64 dbgPrint "add_import_path: '#{path}'\n"
65 $import_path << path
66 end
67 end
68
69 #=== EXEB 版のパスの調整
70 # 環境変数 TECSPATH が cygwin スタイルだと、exerb 版では扱えない
71 # $import_path と $TECSPATH を調整する
72 def self.adjust_exerb_path
73 if $IN_EXERB then
74 new_tecspath = cygpath( $tecspath, $tecspath )
75 pattern = /\A#{$tecspath}/
76 paths = []
77 $import_path.each{ |path|
78 # cygpath は '..' を簡約してしまうので、new_tecspath で置換する
79 # paths << cygpath( path, path )
80 paths << path.sub( pattern, new_tecspath )
81 }
82 $import_path = paths
83 $tecspath = new_tecspath
84 else
85 return
86 end
87 end
88
89 #=== $(TECSPATH) への置換
90 #path::String : ENV[ 'TECSPATH' ] に一致する部分があれば、 "$(TECSPATH)" に置換
91 #b_global::Bool : true なら gsub で置換。false なら sub で置換
92 def self.subst_tecspath( path, b_global = false )
93 tp = $tecspath.dup
94 tp.gsub!( /\\/, "\\\\\\\\" )
95 pattern = /#{tp}/
96 substr = "$(TECSPATH)"
97 if b_global then
98 str = path.gsub( pattern, substr )
99 else
100 str = path.sub( pattern, substr )
101 end
102 dbgPrint "subst_tecspath #{path}, #{str}\n"
103 return str
104 end
105
106 #=== path は絶対パスか?
107 #path:: String :
108 # '/' または '$' で始まる場合、絶対パスと判定する
109 def self.is_absolute_path?( path )
110 pa = path[0..0]; pa2 = path[0..1]
111 if pa == '/' || pa == '$' || pa2 =~ /[A-Za-z]:/ then
112 res = true
113 else
114 res = false
115 end
116 dbgPrint "is_absolute( #{path} ) = #{res} #{path[0]}\n"
117 return res
118 end
119
120 #=== tecsgen のデフォルトを設定
121 def self.set_default_config
122 Makefile::set_default_config
123 end
124
125 ###
126 #== Makefile.templ の出力内
127容を追加、変更するための操作
128 module Makefile
129 # 固定されている変数(add_var で変更できない)
130 @@fixed_vars = { :INCLUDES => nil, :DEFINES => nil, :TARGET_BASE => nil, :BASE_DIR => nil }
131 @@config_mode = false
132
133 @@vars = { }
134 @@vars_default = { }
135 @@var_comments = { }
136
137 @@objs = []
138 @@ldflags = ""
139 @@search_path = []
140 @@pre_tecsgen_target = []
141 @@post_tecsgen_target = []
142 @@lines = []
143
144 #=== OTHER_OBJS に追加する
145 def self.add_obj obj
146 @@objs << obj
147 end
148 #=== 追加する変数
149 # プラグインからは、デフォルト値を変更できる
150 # config により
151 def self.add_var( var, val, comment = nil )
152 if @@fixed_vars[ var ]
153 raise "fixed var '#{var}' cannot be changed"
154 end
155 if @@config_mode then
156 @@vars_default[ var.to_sym ] = val
157 @@var_comments_default[ var.to_sym ] = comment
158 else
159 @@vars[ var.to_sym ] = val
160 @@var_comments[ var.to_sym ] = comment
161 end
162 end
163 #=== LDFLAGS に追加する
164 def self.add_ldflag ldflag
165 @@ldflags += " " + ldflag
166 end
167 #=== サーチパスを追加する
168 # CFLAGS, vpath に追加する
169 def self.add_search_path path
170 @@search_path << path
171 end
172 #=== PRE_TECSGEN_TARGET に追加する
173 # PRE_TECSGEN_TARGET に target を追加する
174 def self.add_pre_tecsgen_target target
175 @@pre_tecsgen_target << pre_tecsgen_target
176 end
177 #=== POST_TECSGEN_TARGET に追加する
178 # POST_TECSGEN_TARGET に target を追加する
179 def self.add_post_tecsgen_target target
180 @@post_tecsgen_target << pre_tecsgen_target
181 end
182 #=== 追加する変数
183 def self.add_line( line )
184 @@lines << line.to_s + "\n"
185 end
186
187 def self.get_objs # Array を返す
188 return @@objs.uniq
189 end
190 def self.get_vars # Array を返す
191 if RUBY_VERSION >= '1.9' then
192 return (@@vars.keys + @@vars_default.keys).sort.uniq
193 else
194 # V1.8 では、Symbol の sort ができないので、一旦 String に置換する
195 return (@@vars.keys + @@vars_default.keys).map{|s| s.to_s }.sort.uniq.map!{|s| s.to_sym }
196 end
197 end
198 def self.get_var_val( var )
199 return @@vars[ var ] ? @@vars[ var ] : @@vars_default[ var ]
200 end
201 def self.get_var_comment( var )
202 return @@var_comments[ var ]
203 end
204 def self.get_ldflags # String を返す
205 return @@ldflags
206 end
207 def self.get_search_path # Array を返す
208 return @@search_path.uniq
209 end
210 def self.get_pre_tecsgen_target # Array を返す
211 return @@pre_tecsgen_target.uniq
212 end
213 def self.get_post_tecsgen_target # Array を返す
214 return @@post_tecsgen_target.uniq
215 end
216 def self.get_lines # 付加する行を得る
217 return @@lines.uniq
218 end
219
220 #=== TECSGEN のデフォルト設定を行う
221 # Makefile
222 # @@fixed_vars で定義されている変数は、変更できず、定数定義されている
223 def self.set_default_config
224 add_var( "TARGET", "$(TARGET_BASE).exe", "default target name" )
225 add_var( "TECSGEN", "tecsgen", "default TECS generator" )
226 add_var( "TIMESTAMP", "$(GEN_DIR)/tecsgen.timestamp", "Time Stamp" )
227 add_var( "CC", "gcc", "default C Compiler" )
228 add_var( "CFLAGS", '$(INCLUDES) $(DEFINES) -D "Inline=static inline"', "default C Compiler options" )
229 add_var( "LD", "gcc", "default Liknker" )
230 add_var( "LDFLAGS", @@ldflags, "default Liknker Options" )
231 add_var( "SRC_DIR", "$(BASE_DIR)/src", "default source directory" )
232 add_var( "_TECS_OBJ_DIR", "$(GEN_DIR)/", "default relocatable object (.o) directory" )
233 end
234 end
235
236 def self.get_argv
237 ARGV
238 end
239
240 #------ TECSGEN CDL analyze and generate ------#
241
242 def syntax_analisys argv
243 # ルート namespace (region) を生成
244 @root_namespace = Region.new("::")
245
246 #### 構文解析 (post コードを除く) ####
247 # すべての cdl を import する
248 argv.each{ |f|
249 dbgPrint( "## Import: #{f}\n")
250 Import.new( f, false, false )
251 }
252
253 # すべての構文解釈が完了したことの報告
254 # 実際には、後からプラグインの生成する CDL のパースが行われる
255 # エラー行数の決定方法の変更のために行う
256 Generator.end_all_parse
257 dbgPrint( "## End all parse (except Post Code)\n")
258 end # syntax_analisys
259
260 #=== TECSGEN#semantics_analisys_1
261 # semantics check. only cells here
262 # other objects (signature, celltype, typedef, etc ) are checked while syntax analisys
263 def semantics_analisys_1
264 #### 意味解析1 (post コードを除く) ####
265 dbgPrint( "## Creating reverse join \n")
266 Cell.create_reverse_join
267
268 DescriptorType.check_signature
269 Signature.set_descriptor_list
270 Celltype.check_dynamic_join
271
272 #0 set_definition_join は2回呼び出される(1回目)
273 dbgPrint( "## Checking all join\n")
274 @root_namespace.set_definition_join
275 # @root_namespace.set_require_join ### いったん見合わせ。重複エラーを見逃す
276 # through プラグインで生成されたセルにも require も生成できる (set_definition_join の後ろで実施)
277
278 #### post コードの生成と構文解析 ####
279 @@b_post_coded = true # ポストコード生成開始後 true
280 # 引数がなければ、プラグインのポストコードを出力しない
281 if ARGV.length > 0 then
282 dbgPrint( "## Generating Post Code\n")
283 # プラグインのポストコードの出力と import
284 tmp_file_name = "#{$gen}/tmp_plugin_post_code.cdl"
285 file = nil
286 begin
287 file = CFile.open( tmp_file_name, "w" )
288 rescue
289 Generator.error( "G9999 fail to create #{tmp_file_name}" )
290 end
291
292 if file then
293 # through プラグインのポストコード生成
294 PluginModule.gen_plugin_post_code file
295
296 begin
297 file.close
298 rescue
299 Generator.error( "G9999 fail to close #{tmp_file_name}" )
300 end
301 dbgPrint( "## Import Post Code\n")
302 Import.new( "#{tmp_file_name}" )
303 end
304 end
305
306 #### 意味解析1 (post コード) ####
307 dbgPrint( "## Creating reverse join (for post code) \n")
308 Cell.create_reverse_join
309
310 # Join の定義の設定とチェック
311 #0 # 前方参ç…
312§å¯¾å¿œ
313 #0 set_definition_join は2回呼び出される(2回目) post_code で生成された
314 dbgPrint( "## Checking all join (for cells generated by Post Code\n")
315 @root_namespace.set_definition_join
316 @root_namespace.set_max_entry_port_inner_cell
317
318 dbgPrint( "## Set require join\n")
319 @root_namespace.set_require_join # mikan post の前にも
320 # ポストコードで生成されたセルの require のjoin を生成
321 # mikan require で through が適用されて、ポストコードが必
322要となっても出力されない
323 end # semantics_analisys_1
324
325 def semantics_analisys_2
326 #### 意味解析2 ####
327 Cell.make_cell_list2
328 dbgPrint( "## Set fixed join\n")
329 Cell.create_reverse_require_join
330 # create_reverse_require_join は set_detinition_join に埋め込むことができない
331 # namespace に依存しない出現順で行う
332 # mikan through プラグインが適用されポストコードに影響を与える場合が考æ…
333®ã§ãã¦ã„ない
334 # mikan post code に影響のあるものであれば、早くに reverse_require_join の結合が必
335要
336 dbgPrint( "## Setting port reference count\n")
337 @root_namespace.set_port_reference_count
338
339 dbgPrint( "## Checking all join\n")
340 @root_namespace.check_join
341
342 # mikan プラグインで生成されたコンポーネントの set_def_and_check_join
343
344 dbgPrint( "## Checking referenced but undefined cell\n")
345 @root_namespace.check_ref_but_undef
346 end # semantics_analisys_2
347
348 def optimize_and_generate
349 #### Region link root ごとにオプティマイズおよび生成 ####
350 Region.get_link_roots.each { |region|
351
352 n_cells = region.get_n_cells
353
354 dbgPrint "#{region.get_name} has #{n_cells} cells\n"
355 if $verbose
356 print "=====================================\n"
357 print "=== Region.path_str: #{region.get_namespace_path.get_path_str}\n"
358 print "=====================================\n"
359 else
360 dbgPrint "Region.path_str: #{region.get_namespace_path.get_path_str}\n"
361 end
362
363 if $region_list.length > 0 then
364 if $region_list[ region.get_namespace_path.get_path_str ] then
365 $region_list[ region.get_namespace_path.get_path_str ] = false
366 else
367 next
368 end
369 end
370
371 # セルが一つもなければ生成しない
372 # セルの生成がない場合
373 if region.get_n_cells == 0 then
374 if $region_list.length > 0 then
375 Generator.warning( "W9999 $1: specified to generate but has no cell", region.get_name )
376 end
377 if region != @root_namespace then
378 next
379 end
380 end
381
382 $generating_region = region
383 if Region.get_link_roots.length > 1 then
384 if region.get_name == "::" then
385 $gen = $gen_base
386 else
387 $gen = $gen_base + "/" + region.get_global_name.to_s
388 begin
389 if ! File.directory?( $gen ) then
390 Dir.mkdir( $gen )
391 end
392 rescue
393 print( "Cannot mkdir #{$gen}\n" )
394 exit 1
395 end
396 end
397 else
398 $gen = $gen_base
399 end
400
401 dbgPrint( "## Unset optimize variables\n")
402 @root_namespace.reset_optimize # 最適化をリセットする
403
404 if Generator.get_n_error == 0 then
405 # エラーが発生していたら、設定しない
406 dbgPrint( "## Set cell id\n")
407 @root_namespace.set_cell_id_and_domain # セルの ID とドメイン情
408報を設定(linkunit 毎に0からつける)
409
410 # エラーが発生していたら、最適化は実施しない
411 if ! $unopt then
412 dbgPrint( "## Optimizing: Link Region=#{@root_namespace.get_name}\n")
413 @root_namespace.optimize
414 end
415 end
416
417 if $show_tree then
418 # エラーが発生していても表示(エラー発生時は最適化されていないので注意)
419 print "##### show_tree LinkRegion=#{region.get_name} #####\n"
420 @root_namespace.show_tree(0)
421 print "##### END LinkRegion=#{region.get_name} #####\n\n"
422 end
423
424 # 構文解釈、意味解析でエラー発生していたら、コード生成をしない
425 if Generator.get_n_error != 0 then
426 print_report
427 exit 1
428 end
429
430 #### コード生成 ####
431 begin
432 dbgPrint( "## Generating: Link Region=#{@root_namespace.get_name}\n")
433 @root_namespace.generate
434 dbgPrint( "## Generating Post: Link Region=#{@root_namespace.get_name}\n")
435 @root_namespace.generate_post
436 rescue
437 # 通常ここへは来ない (generate, generate_post で処置される)
438 Generator.error( "G9999 fail to generate" )
439 end
440 }
441 end # optimize_and_generate
442
443 def finalize
444 dbgPrint( "## Generating XML\n")
445 # Region.gen_xml @root_namespace
446 ##
447 # Namespace.gen_XML @root_namespace
448
449 $region_list.each{ |region_path_str, val|
450 if val == true then
451 Generator.warning( "W9999 $1: not link root, -G ignored", region_path_str )
452 end
453 }
454
455 # update する
456 # APPFile で生成されたファイルは、もし変化があれば、ここで更新する
457 # コード生成段階でエラーが発生すれば、更新しない
458 # CFile で生成されたものは、更新されている
459 if Generator.get_n_error == 0 then
460 begin
461 AppFile.update
462 rescue => evar
463 Generator.error( "G9999 Fail to update. (error occurred while renaming generated files)" )
464 print_exception( evar )
465 end
466 end
467
468 print_report
469 if Generator.get_n_error != 0 then
470 STDERR.print "error occurred while generating. some file can be corrupt in #{$gen_base}\n"
471 exit 1
472 end
473
474 open( "#{$gen_base}/tecsgen.timestamp", "w" ){|io|}
475 end # finalize
476
477 def dump_tecsgen_rbdmp
478 dbgPrint "dump_tecsgen_rbdmp 0:\n"
479 #### unjoin_plugin 後に行う必
480要があるため、コード生成後にダンプを行う
481 #### Region link root ごとにオプティマイズしてダンプ ####
482 Namespace.get_root.unjoin_plugin
483 Namespace.get_root.find_plugin 0, []
484
485 Region.get_link_roots.each { |region|
486 dbgPrint "dump_tecsgen_rbdmp 1: Region.path_str: #{region.get_namespace_path.get_path_str}\n"
487
488 n_cells = region.get_n_cells
489
490 if $region_list.length > 0 then
491 if $region_list[ region.get_namespace_path.get_path_str ] == false then
492 $region_list[ region.get_namespace_path.get_path_str ] = true
493 else
494 next
495 end
496 end
497
498 dbgPrint "dump_tecsgen_rbdmp 2: Region.path_str: #{region.get_namespace_path.get_path_str}\n"
499 # セルが一つもなければ生成しない
500 # セルの生成がない場合
501 if region.get_n_cells == 0 then
502 # if $region_list.length > 0 then
503 # Generator.warning( "W9999 $1: specified to generate but has no cell", region.get_name )
504 # end
505 if region != @root_namespace then
506 next
507 end
508 end
509
510 dbgPrint "dump_tecsgen_rbdmp 3: Region.path_str: #{region.get_namespace_path.get_path_str}\n"
511 $generating_region = region
512 if Region.get_link_roots.length > 1 then
513 if region.get_name == "::" then
514 $gen = $gen_base
515 else
516 $gen = $gen_base + "/" + region.get_global_name.to_s
517 end
518 else
519 $gen = $gen_base
520 end
521
522 dbgPrint "dump_tecsgen_rbdmp 4: Region.path_str: #{region.get_namespace_path.get_path_str}\n"
523 dbgPrint( "## Unset optimize variables\n")
524 @root_namespace.reset_optimize # 最適化をリセットする
525
526 # if Generator.get_n_error == 0 then
527 # # エラーが発生していたら、ここへは来ない
528 dbgPrint( "## Set cell id\n")
529 @root_namespace.set_cell_id_and_domain # セルの ID とドメイン情
530報を設定(linkunit 毎に0からつける)
531
532 # エラーが発生していたら、最適化は実施しない
533 if ! $unopt then
534 dbgPrint( "## Optimizing: Link Region=#{@root_namespace.get_name}\n")
535 @root_namespace.optimize
536 end
537 # end
538 dbgPrint "dump_tecsgen_rbdmp final: Region.path_str: #{region.get_namespace_path.get_path_str}\n"
539 File.write( "#{$gen}/tecsgen.rbdmp", Marshal.dump(Namespace.get_root) )
540 }
541 end
542
543 def self.post_coded?
544 @@b_post_coded
545 end
546end # class TECSGEN
Note: See TracBrowser for help on using the repository browser.