source: EcnlProtoTool/trunk/asp3_dcre/cfg/cfg.rb@ 321

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

文字コードを設定

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 18.0 KB
Line 
1#!/usr/bin/env ruby
2# -*- coding: utf-8 -*-
3#
4# TOPPERS Configurator by Ruby
5#
6# Copyright (C) 2015 by FUJI SOFT INCORPORATED, JAPAN
7# Copyright (C) 2015,2016 by Embedded and Real-Time Systems Laboratory
8# Graduate School of Information Science, Nagoya Univ., JAPAN
9#
10# 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
11# ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
12# 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
13# (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
14# 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
15# スコード中に含まれていること.
16# (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
17# 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
18# 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
19# の無保証規定を掲載すること.
20# (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
21# 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
22# と.
23# (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
24# 作権表示,この利用条件および下記の無保証規定を掲載すること.
25# (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
26# 報告すること.
27# (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
28# 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
29# また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
30# 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
31# 免責すること.
32#
33# 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
34# よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
35# に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
36# アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
37# の責任を負わない.
38#
39# $Id$
40#
41
42if $0 == __FILE__
43 TOOL_ROOT = File.expand_path(File.dirname(__FILE__)) + "/"
44 $LOAD_PATH.unshift(TOOL_ROOT)
45end
46
47require "pp"
48require "csv"
49require "optparse"
50require "pstore"
51require "GenFile.rb"
52require "SRecord.rb"
53
54#
55# 定数定義
56#
57# 共通
58VERSION = "1.2.2"
59
60# cfg1_out関係
61CFG1_PREFIX = "TOPPERS_cfg_"
62CFG1_MAGIC_NUM = "TOPPERS_magic_number"
63CFG1_SIZEOF_SIGNED = "TOPPERS_sizeof_signed_t"
64CFG1_OUT_C = "cfg1_out.c"
65CFG1_OUT_DB = "cfg1_out.db"
66CFG1_OUT_SREC = "cfg1_out.srec"
67CFG1_OUT_SYMS = "cfg1_out.syms"
68CFG1_OUT_TIMESTAMP = "cfg1_out.timestamp"
69CFG1_OUT_TARGET_H = "target_cfg1_out.h"
70
71# cfg2_out関係
72CFG2_OUT_DB = "cfg2_out.db"
73
74# cfg3_out関係
75CFG3_OUT_DB = "cfg3_out.db"
76
77#
78# エラー発生有無フラグ
79#
80$errorFlag = false
81
82#
83# エラー/警告表示関数
84#
85# 一般的なエラー表示(処理を中断)
86def error_exit(message, location = "")
87 location += " " if location != ""
88 abort("#{location}error: #{message}")
89end
90
91# 一般的なエラー表示(処理を継続)
92def error(message, location = "")
93 location += " " if location != ""
94 STDERR.puts("#{location}error: #{message}")
95 $errorFlag = true
96end
97
98# 一般的な警告表示
99def warning(message, location = "")
100 location += " " if location != ""
101 STDERR.puts("#{location}warning: #{message}")
102end
103
104# システムコンフィギュレーションファイルの構文解析時のエラー
105$noParseError = 0
106def parse_error(cfgFile, message)
107 error(message, "#{cfgFile.getFileName()}:#{cfgFile.getLineNo}:")
108 if ($noParseError += 1) >= 10
109 abort("too many errors emitted, stopping now")
110 end
111end
112
113# システムコンフィギュレーションファイルの構文解析時の警告
114def parse_warning(cfgFile, message)
115 warning(message, "#{cfgFile.getFileName()}:#{cfgFile.getLineNo}:")
116end
117
118#
119# 静的API処理時のエラー/警告表示関数
120#
121# 静的API処理時のエラー/警告を短く記述できるように,メッセージ中の%ま
122# たは%%で始まる記述を以下のように展開する.
123# %label → #{params[:label]}
124# %%label → label `#{params[:label]}'
125#
126# エラー/警告メッセージの展開
127def expand_message(message, params)
128 result = message.dup
129 while /%%(\w+)\b/ =~ result
130 param = $1
131 paramVal = params[param.to_sym].to_s
132 result.sub!(/%%#{param}\b/, "#{param} `#{paramVal}'")
133 end
134 while /%(\w+)\b/ =~ result
135 param = $1
136 paramVal = params[param.to_sym].to_s
137 result.sub!(/%#{param}\b/, paramVal)
138 end
139 return(result)
140end
141
142# 静的API処理時のエラー
143def error_api(params, message)
144 error(expand_message(message, params), \
145 "#{params[:_file_]}:#{params[:_line_]}:")
146end
147
148# 静的API処理時の警告
149def warning_api(params, message)
150 warning(expand_message(message, params), \
151 "#{params[:_file_]}:#{params[:_line_]}:")
152end
153
154# 静的API処理時のエラー(エラーコード付き)
155def error_ercd(errorCode, params, message)
156 error_api(params, "#{errorCode}: #{message}")
157end
158
159# 静的API処理時の警告(エラーコード付き)
160def warning_ercd(errorCode, params, message)
161 warning_api(params, "#{errorCode}: #{message}")
162end
163
164# パラメータのエラー
165def error_wrong(errorCode, params, symbol, wrong)
166 error_ercd(errorCode, params, "%%#{symbol} is #{wrong} in %apiname")
167end
168
169def error_wrong_id(errorCode, params, symbol, objid, wrong)
170 error_ercd(errorCode, params, "%%#{symbol} is #{wrong} " \
171 "in %apiname of %#{objid}")
172end
173
174def error_wrong_sym(errorCode, params, symbol, symbol2, wrong)
175 error_ercd(errorCode, params, "%%#{symbol} is #{wrong} " \
176 "in %apiname of %%#{symbol2}")
177end
178
179# パラメータ不正のエラー
180def error_illegal(errorCode, params, symbol)
181 error_ercd(errorCode, params, "illegal %%#{symbol} in %apiname")
182end
183
184def error_illegal_id(errorCode, params, symbol, objid)
185 error_ercd(errorCode, params, "illegal %%#{symbol} " \
186 "in %apiname of %#{objid}")
187end
188
189def error_illegal_sym(errorCode, params, symbol, symbol2)
190 error_ercd(errorCode, params, "illegal %%#{symbol} " \
191 "in %apiname of %%#{symbol2}")
192end
193
194#
195# Stringクラスの拡張(二重引用符で囲まれた文字列の作成/展開)
196#
197class String
198 #
199 # 二重引用符で囲まれた文字列の作成
200 #
201 def quote
202 result = ""
203 self.chars do |c|
204 case c
205 when "'"
206 result += "\\\'"
207 when "\""
208 result += "\\\""
209 when "\0"
210 result += "\\0"
211 when "\a"
212 result += "\\a"
213 when "\b"
214 result += "\\b"
215 when "\f"
216 result += "\\f"
217 when "\n"
218 result += "\\n"
219 when "\r"
220 result += "\\r"
221 when "\t"
222 result += "\\t"
223 when "\v"
224 result += "\\v"
225 when "\\"
226 result += "\\\\"
227 else
228 result += c
229 end
230 end
231 return("\"" + result + "\"")
232 end
233
234 #
235 # 二重引用符で囲まれた文字列の展開
236 #
237 def unquote
238 if /^\"(.*)\"$/m =~ self
239 str = $1
240 result = ""
241 while (/^(.*)\\(.*)$/m =~ str)
242 result += $1
243 str = $2
244 case str
245 when /^[aA](.*)$/m
246 result += "\a"
247 str = $1
248 when /^[bB](.*)$/m
249 result += "\b"
250 str = $1
251 when /^[fF](.*)$/m
252 result += "\f"
253 str = $1
254 when /^[nN](.*)$/m
255 result += "\n"
256 str = $1
257 when /^[rR](.*)$/m
258 result += "\r"
259 str = $1
260 when /^[tT](.*)$/m
261 result += "\t"
262 str = $1
263 when /^[vV](.*)$/m
264 result += "\v"
265 str = $1
266 when /^[xX]([0-9a-fA-F][0-9a-fA-F]?)(.*)$/m
267 result += $1.hex
268 str = $2
269 when /^([0-7][0-7]?[0-7]?)(.*)$/m
270 result += $1.oct
271 str = $2
272 when /^\\(.*)$/m
273 result += "\\"
274 str = $1
275 end
276 end
277 return(result + str)
278 else
279 return(self.dup)
280 end
281 end
282end
283
284#
285# NumStrクラス(数値に文字列を付加したもの)の定義
286#
287class NumStr
288 def initialize(val, str = val.to_s)
289 @val = val
290 @str = str
291 end
292
293 # 数値情報を返す
294 def val
295 return @val
296 end
297 alias_method :to_i, :val
298
299 # 文字列情報を返す
300 def str
301 return @str
302 end
303 alias_method :to_s, :str
304
305 # 比較は数値情報で行う
306 def ==(other)
307 @val == other
308 end
309 def !=(other)
310 @val != other
311 end
312 def <=>(other)
313 @val <=> other
314 end
315
316 # ハッシュのキーとして使う時の比較も数値情報で行う
317 def eql?(other)
318 @val == other.val
319 end
320
321 # ハッシュ値の定義も上書きする
322 def hash
323 return @val.hash
324 end
325
326 # 数値クラスと演算できるようにする
327 def coerce(other)
328 if other.kind_of?(Numeric)
329 return other, @val
330 else
331 raise
332 end
333 end
334
335 # 二重引用符で囲まれた文字列の作成
336 def quote
337 str.quote
338 end
339
340 # 二重引用符で囲まれた文字列の展開
341 def unquote
342 str.unquote
343 end
344
345 # pp時の表示
346 def pretty_print(q)
347 q.text("[#{@val}(=0x#{@val.to_s(16)}),")
348 @str.pretty_print(q)
349 q.text("]")
350 end
351
352 # 未定義のメソッドは@valに送る
353 def method_missing(*method)
354 @val.send(*method)
355 end
356end
357
358#
359# シンボルファイルの読み込み
360#
361# 以下のメソッドは,GNUのnmが生成するシンボルファイルに対応している.
362# 別のツールに対応する場合には,このメソッドを書き換えればよい.
363#
364def ReadSymbolFile(symbolFileName)
365 begin
366 symbolFile = File.open(symbolFileName)
367 rescue Errno::ENOENT, Errno::EACCES => ex
368 abort(ex.message)
369 end
370
371 symbolAddress = {}
372 symbolFile.each do |line|
373 # スペース区切りで分解
374 fields = line.split(/\s+/)
375
376 # 3列になっていない行は除外
377 if fields.size == 3
378 symbolAddress[fields[2]] = fields[0].hex
379 end
380 end
381 symbolFile.close
382 return(symbolAddress)
383end
384
385#
386# 値取得シンボルをグローバル変数として定義する
387#
388def DefineSymbolValue
389 $symbolValueTable.each do |symbolName, symbolData|
390 if symbolData.has_key?(:VALUE)
391 eval("$#{symbolName} = #{symbolData[:VALUE]}")
392 end
393 end
394end
395
396#
397# インクルードパスからファイルを探す
398#
399def SearchFilePath(fileName)
400 if File.exist?(fileName)
401 # 指定したファイルパスに存在する
402 return fileName
403 elsif /^\./ =~ fileName
404 # 相対パスを指定していて見つからなかった場合,存在しないものとする
405 #(意図しないファイルが対象となることを防止)
406 return nil
407 else
408 # 各インクルードパスからファイル存在チェック
409 $includeDirectories.each do |includeDirectory|
410 path = includeDirectory + "/" + fileName
411 # 見つかったら相対パスを返す
412 if File.exist?(path)
413 return path
414 end
415 end
416 return nil
417 end
418end
419
420#
421# 指定した生成スクリプト(trbファイル)を検索してloadする
422#
423def IncludeTrb(fileName)
424 filePath = SearchFilePath(fileName)
425 if filePath.nil?
426 error_exit("`#{fileName}' not found")
427 else
428 load(filePath)
429 end
430end
431
432#
433# パス3の処理
434#
435def Pass3
436 #
437 # パス2から引き渡される情報をファイルから読み込む
438 #
439 db = PStore.new(CFG2_OUT_DB)
440 db.transaction(true) do
441 $apiDefinition = db[:apiDefinition]
442 $symbolValueTable = db[:symbolValueTable]
443 $cfgFileInfo = db[:cfgFileInfo]
444 $includeFiles = db[:includeFiles]
445 $cfgData = db[:cfgData]
446 $asmLabel = db[:asmLabel]
447 $endianLittle = db[:endianLittle]
448 $cfg2Data = db[:cfg2Data]
449 end
450 $cfg3Data = {}
451
452 #
453 # 値取得シンボルをグローバル変数として定義する
454 #
455 DefineSymbolValue()
456
457 #
458 # 生成スクリプト(trbファイル)を実行する
459 #
460 $trbFileNames.each do |trbFileName|
461 IncludeTrb(trbFileName)
462 end
463
464 #
465 # パス4に引き渡す情報をファイルに生成
466 #
467 if $omitOutputDb.nil?
468 db = PStore.new(CFG3_OUT_DB)
469 db.transaction do
470 db[:apiDefinition] = $apiDefinition
471 db[:symbolValueTable] = $symbolValueTable
472 db[:cfgFileInfo] = $cfgFileInfo
473 db[:includeFiles] = $includeFiles
474 db[:cfgData] = $cfgData
475 db[:asmLabel] = $asmLabel
476 db[:endianLittle] = $endianLittle
477 db[:cfg3Data] = $cfg3Data
478 end
479 end
480end
481
482#
483# パス4の処理
484#
485def Pass4
486 #
487 # パス3から引き渡される情報をファイルから読み込む
488 #
489 db = PStore.new(CFG3_OUT_DB)
490 db.transaction(true) do
491 $apiDefinition = db[:apiDefinition]
492 $symbolValueTable = db[:symbolValueTable]
493 $cfgFileInfo = db[:cfgFileInfo]
494 $includeFiles = db[:includeFiles]
495 $cfgData = db[:cfgData]
496 $asmLabel = db[:asmLabel]
497 $endianLittle = db[:endianLittle]
498 $cfg3Data = db[:cfg3Data] || db[:cfg2Data]
499 end
500
501 #
502 # 値取得シンボルをグローバル変数として定義する
503 #
504 DefineSymbolValue()
505
506 #
507 # 生成スクリプト(trbファイル)を実行する
508 #
509 $trbFileNames.each do |trbFileName|
510 IncludeTrb(trbFileName)
511 end
512end
513
514#
515# 生成スクリプト(trbファイル)向けの関数
516#
517def SYMBOL(symbol)
518 if !$romSymbol.nil? && $romSymbol.has_key?($asmLabel + symbol)
519 return $romSymbol[$asmLabel + symbol]
520 else
521 return nil
522 end
523end
524
525def BCOPY(fromAddress, toAddress, size)
526 if !$romImage.nil?
527 copyData = $romImage.get_data(fromAddress, size)
528 if !copyData.nil?
529 $romImage.set_data(toAddress, copyData)
530 end
531 end
532end
533
534def PEEK(address, size, signed=false)
535 if !$romImage.nil?
536 return $romImage.get_value(address, size, signed)
537 else
538 return nil
539 end
540end
541
542#
543# グローバル変数の初期化
544#
545$kernel = nil
546$pass = nil
547$includeDirectories = []
548$trbFileNames = []
549$apiTableFileNames = []
550$symvalTableFileNames = []
551$romImageFileName = nil
552$romSymbolFileName = nil
553$dependencyFileName = nil
554$idInputFileName = nil
555$idOutputFileName = nil
556
557#
558# オプションの処理
559#
560OptionParser.new(banner="Usage: cfg.rb [options] CONFIG-FILE", 40) do |opt|
561 opt.version = VERSION
562 opt.on("-k KERNEL", "--kernel KERNEL", "kernel profile name") do |val|
563 $kernel = val
564 end
565 opt.on("-p NUM", "--pass NUM", "processing pass number") do |val|
566 $pass = val
567 end
568 opt.on("-I DIRECTORY", "--include-directory DIRECTORY",
569 "include directory") do |val|
570 $includeDirectories.push(val)
571 end
572 opt.on("-T TRB-FILE", "--trb-file TRB-FILE",
573 "generation script (trb file)") do |val|
574 $trbFileNames.push(val)
575 end
576 opt.on("--api-table API-TABLE-FILE", "static API table file") do |val|
577 $apiTableFileNames.push(val)
578 end
579 opt.on("--symval-table SYMVAL-TABLE-FILE", "symbol-value table file") do |val|
580 $symvalTableFileNames.push(val)
581 end
582 opt.on("--rom-image SREC-FILE", "rom image file (s-record)") do |val|
583 $romImageFileName = val
584 end
585 opt.on("--rom-symbol SYMS-FILE", "rom symbol table file (nm)") do |val|
586 $romSymbolFileName = val
587 end
588 opt.on("--id-input-file ID-FILE", "ID input file") do |val|
589 $idInputFileName = val
590 end
591 opt.on("--id-output-file ID-FILE", "ID output file") do |val|
592 $idOutputFileName = val
593 end
594 opt.on("-M [DEPEND-FILE]", "--print-dependencies [DEPEND-FILE]",
595 "dependency file") do |val|
596 $dependencyFileName = val.nil? ? "" : val
597 end
598 opt.on("-O", "--omit-output-db", "omit DB file output") do
599 $omitOutputDb = true
600 end
601 opt.on("-v", "--version", "show version number") do
602 abort(opt.ver)
603 end
604 opt.on("-h", "--help", "show help (this)") do
605 abort(opt.help)
606 end
607 opt.parse!(ARGV)
608end
609$configFileNames = ARGV
610
611#
612# オプションのチェック
613#
614if $pass.nil?
615 # パスの指定は必須
616 abort("`--pass' option is mandatory")
617elsif /^[1234]$/ !~ $pass
618 abort("pass number `#{$pass}' is not valid")
619end
620
621# パス1では,静的APIテーブルは必須
622if ($pass == "1" && $apiTableFileNames.empty?)
623 abort("`--api-table' option must be specified in pass 1")
624end
625
626# パス1以外では,生成スクリプト(trbファイル)が必須
627if ($pass != "1" && $trbFileNames.empty?)
628 abort("`--trb-file' must be specified except in pass 1")
629end
630
631#
632# カーネルオプションの処理
633#
634case $kernel
635when /^hrp/
636 $supportDomain = true
637when /^fmp/
638 $supportClass = true
639end
640
641#
642# ID番号入力ファイルの取り込み
643#
644$inputObjid = {}
645if !$idInputFileName.nil?
646 begin
647 idInputFile = File.open($idInputFileName)
648 rescue Errno::ENOENT, Errno::EACCES => ex
649 abort(ex.message)
650 end
651
652 idInputFile.each do |line|
653 ( objName, objidNumber ) = line.split(/\s+/)
654 $inputObjid[objName] = objidNumber.to_i
655 end
656
657 idInputFile.close
658end
659
660#
661# 指定されたシンボルファイルの読み込み
662#
663if !$romSymbolFileName.nil?
664 if File.exist?($romSymbolFileName)
665 $romSymbol = ReadSymbolFile($romSymbolFileName)
666 else
667 error_exit("`#{$romSymbolFileName}' not found")
668 end
669end
670
671#
672# 指定されたSレコードファイルの読み込み
673#
674if !$romImageFileName.nil?
675 if File.exist?($romImageFileName)
676 $romImage = SRecord.new($romImageFileName)
677 else
678 error_exit("`#{$romImageFileName}' not found")
679 end
680end
681
682#
683# パスに従って各処理を実行
684#
685case $pass
686when "1"
687 load("pass1.rb")
688 Pass1()
689when "2"
690 load("pass2.rb")
691 Pass2()
692when "3"
693 Pass3()
694when "4"
695 Pass4()
696else
697 error_exit("invalid pass: #{$pass}")
698end
699
700# エラー発生時はabortする
701if $errorFlag
702 if ($0 == __FILE__)
703 abort()
704 else
705 # simplecov対応
706 raise()
707 end
708end
709
710#
711# 作成したすべてのファイルを出力する
712#
713GenFile.output
714
715#
716# タイムスタンプファイルの生成
717#
718if !$timeStampFileName.nil?
719 File.open($timeStampFileName, "w").close
720end
Note: See TracBrowser for help on using the repository browser.