source: EcnlProtoTool/trunk/asp3_dcre/cfg/pass1.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: 27.4 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TOPPERS Configurator by Ruby
4#
5# Copyright (C) 2015 by FUJI SOFT INCORPORATED, JAPAN
6# Copyright (C) 2015,2016 by Embedded and Real-Time Systems Laboratory
7# Graduate School of Information Science, Nagoya Univ., JAPAN
8#
9# 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
10# ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
11# 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
12# (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
13# 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
14# スコード中に含まれていること.
15# (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
16# 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
17# 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
18# の無保証規定を掲載すること.
19# (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
20# 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
21# と.
22# (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
23# 作権表示,この利用条件および下記の無保証規定を掲載すること.
24# (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
25# 報告すること.
26# (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
27# 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
28# また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
29# 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
30# 免責すること.
31#
32# 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
33# よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
34# に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
35# アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
36# の責任を負わない.
37#
38# $Id$
39#
40
41#
42# パス1の処理
43#
44
45#
46# 値取得シンボルテーブルへの固定登録
47#
48$symbolValueTable = {
49 "CHAR_BIT" => { EXPR: "CHAR_BIT" },
50 "SCHAR_MAX" => { EXPR: "SCHAR_MAX", SIGNED: true },
51 "SCHAR_MIN" => { EXPR: "SCHAR_MIN", SIGNED: true },
52 "UCHAR_MAX" => { EXPR: "UCHAR_MAX" },
53 "CHAR_MAX" => { EXPR: "CHAR_MAX", SIGNED: true },
54 "CHAR_MIN" => { EXPR: "CHAR_MIN", SIGNED: true },
55 "SHRT_MAX" => { EXPR: "SHRT_MAX", SIGNED: true },
56 "SHRT_MIN" => { EXPR: "SHRT_MIN", SIGNED: true },
57 "USHRT_MAX" => { EXPR: "USHRT_MAX" },
58 "INT_MAX" => { EXPR: "INT_MAX", SIGNED: true },
59 "INT_MIN" => { EXPR: "INT_MIN", SIGNED: true },
60 "UINT_MAX" => { EXPR: "UINT_MAX" },
61 "LONG_MAX" => { EXPR: "LONG_MAX", SIGNED: true },
62 "LONG_MIN" => { EXPR: "LONG_MIN", SIGNED: true },
63 "ULONG_MAX" => { EXPR: "ULONG_MAX" }
64}
65
66#
67# 静的APIテーブルへの固定登録
68#
69$apiDefinition = { "INCLUDE" =>
70 { :PARAM => [ { :NAME => :file, :STRING => true }]}}
71
72#
73# 静的APIテーブルの読み込み
74#
75def ReadApiTableFile
76 $apiTableFileNames.each do |apiTableFileName|
77 if /^(.+):(\w+)$/ =~ apiTableFileName
78 apiTableFileName = $1
79 apiPhase = $2.to_sym
80 end
81
82 if !File.exist?(apiTableFileName)
83 error_exit("`#{apiTableFileName}' not found")
84 next
85 end
86
87 apiFile = File.open(apiTableFileName)
88 apiFile.each do |line|
89 next if /^#/ =~ line # コメントをスキップ
90
91 fields = line.split(/\s+/) # フィールドに分解
92
93 apiName = fields.shift # API名の取り出し
94 if /^(.+)\[(.+)\]$/ =~ apiName
95 apiName = $1
96 apiDef = { APINAME: apiName, API: $2 }
97 else
98 apiDef = { APINAME: apiName, API: apiName }
99 end
100 if !apiPhase.nil?
101 apiDef[:PHASE] = apiPhase
102 end
103
104 apiParams = []
105 fields.each do |param|
106 case param
107 when /^(\W*)(\w+)(\W*)$/
108 prefix = $1
109 name = $2
110 postfix = $3
111 apiParam = { :NAME => name }
112
113 case prefix
114 when "#" # オブジェクト識別名(定義)
115 apiParam[:ID_DEF] = true
116 when "%" # オブジェクト識別名(参照)
117 apiParam[:ID_REF] = true
118 when "." # 符号無し整数定数式パラメータ
119 apiParam[:EXPTYPE] = "unsigned_t"
120 when "+" # 符号付き整数定数式パラメータ
121 apiParam[:EXPTYPE] = "signed_t"
122 apiParam[:SIGNED] = true
123 when "&" # 一般整数定数式パラメータ
124 # do nothing
125 when "$" # 文字列定数式パラメータ
126 apiParam[:STRING] = true
127 else
128 error_exit("`#{param}' is invalid")
129 end
130
131 case postfix
132 when "*" # キーを決めるパラメータ
133 apiDef[:KEYPAR] = name
134 when "?" # オプションパラメータ
135 apiParam[:OPTIONAL] = true
136 when "\.\.\." # リストパラメータ
137 apiParam[:LIST] = true
138 end
139
140 when "{" # {
141 apiParam = { :BRACE => "{" }
142 when "{?" # {?
143 apiParam = { :BRACE => "{", :OPTBRACE => true }
144
145 when "}" # }
146 apiParam = { :BRACE => "}" }
147
148 else
149 error_exit("`#{param}' is invalid")
150 end
151 apiParams.push(apiParam)
152 end
153 apiDef[:PARAM] = apiParams
154 $apiDefinition[apiName] = apiDef
155 end
156 apiFile.close
157 end
158end
159
160#
161# 値取得シンボルテーブルの読み込み
162#
163def ReadSymvalTable
164 $symvalTableFileNames.each do |symvalTableFileName|
165 if !File.exist?(symvalTableFileName)
166 error_exit("`#{symvalTableFileName}' not found")
167 next
168 end
169
170 symvalCsv = CSV.open(symvalTableFileName)
171 symvalCsv.each do |record|
172 # 変数名
173 if record[0].nil?
174 error_exit("invalid variable name in `#{fileName}'")
175 end
176
177 symbol = {}
178 variable = record[0]
179
180 # 式
181 if record[1].nil? || record[1].empty?
182 symbol[:EXPR] = variable
183 else
184 symbol[:EXPR] = record[1]
185 end
186
187 # 式の型
188 if !record[2].nil? && !record[2].empty?
189 case record[2]
190 when /^[bB]/ # 真偽値
191 symbol[:BOOL] = true
192 when /^[uU]/ # 符号無し整数値
193 # 何も設定しない
194 else # 符号付き整数値
195 symbol[:SIGNED] = true
196 end
197 end
198
199 # コンパイル条件
200 if !record[3].nil? && !record[3].empty?
201 symbol[:CONDITION] = record[3]
202 end
203
204 # 条件が成立しない時の式
205 if !record[4].nil? && !record[4].empty?
206 symbol[:ELSE_EXPR] = record[4]
207 end
208
209 $symbolValueTable[variable] = symbol
210 end
211 symvalCsv.close
212 end
213end
214
215#
216# システムコンフィギュレーションファイルからの読み込みクラス
217#
218class ConfigFile
219 def initialize(fileName)
220 @cfgFileName = fileName
221 begin
222 @cfgFile = File.open(@cfgFileName)
223 rescue Errno::ENOENT, Errno::EACCES => ex
224 abort(ex.message)
225 end
226 @lineNo = 0
227 @withinComment = false
228 end
229
230 def close
231 @cfgFile.close
232 end
233
234 def getNextLine(withinApi)
235 line = @cfgFile.gets
236 return(nil) if line.nil?
237 @lineNo += 1
238
239 line.chomp!
240 if @withinComment
241 case line
242 when /\*\// # C言語スタイルのコメント終了
243 line.sub!(/^.*?\*\//, "") # 最初の*/にマッチさせる */
244 @withinComment = false
245 else
246 line = ""
247 end
248 end
249 if !@withinComment
250 line.gsub!(/\/\*.*?\*\//, "") # C言語スタイルのコメントの除去
251 # 最初の*/にマッチさせる */
252 case line
253 when /^\s*#/ # プリプロセッサディレクティブ
254 if withinApi
255 parse_error(self, \
256 "preprocessor directive must not be within static API")
257 line = ""
258 end
259 when /\/\*/ # C言語スタイルのコメント開始
260 line.sub!(/\/\*.*$/, "")
261 @withinComment = true
262 when /\/\// # C++言語スタイルのコメント
263 line.sub!(/\/\/.*$/, "")
264 end
265 end
266 return(line)
267 end
268
269 def getFileName
270 return(@cfgFileName)
271 end
272
273 def getLineNo
274 return(@lineNo)
275 end
276end
277
278#
279# システムコンフィギュレーションファイルのパーサークラス
280#
281class CfgParser
282 @@lastApiIndex = 0
283 @@currentDomain = nil
284 @@currentClass = nil
285 @@nestDC = []
286
287 def initialize
288 @line = ""
289 @skipComma = false # 次が,であれば読み飛ばす
290 end
291
292 #
293 # 文字列末まで読む
294 #
295 def parseString(cfgFile)
296 string = ""
297 begin
298 case @line
299 when /^([^"]*\\\\)(.*)$/ # \\まで読む
300 string += $1
301 @line = $2
302 when /^([^"]*\\\")(.*)$/ # \"まで読む
303 string += $1
304 @line = $2
305 when /^([^"]*\")(.*)$/ # "まで読む
306 string += $1
307 @line = $2
308 return(string)
309 else # 行末まで読む
310 string += @line + "\n"
311 @line = cfgFile.getNextLine(true)
312 end
313 end while (@line)
314 error_exit("unterminated string meets end-of-file")
315 return(string)
316 end
317
318 #
319 # 文字末まで読む
320 #
321 def parseChar(cfgFile)
322 string = ""
323 begin
324 case @line
325 when /^([^']*\\\\)(.*)$/ # \\まで読む
326 string += $1
327 @line = $2
328 when /^([^']*\\\')(.*)$/ # \'まで読む
329 string += $1
330 @line = $2
331 when /^([^']*\')(.*)$/ # 'まで読む
332 string += $1
333 @line = $2
334 return(string)
335 else # 行末まで読む
336 string += @line + "\n"
337 @line = cfgFile.getNextLine(true)
338 end
339 end while (@line)
340 error_exit("unterminated string meets end-of-file")
341 return(string)
342 end
343
344 #
345 # 改行と空白文字を読み飛ばす
346 #
347 def skipSpace(cfgFile, withinApi)
348 loop do
349 return if @line.nil? # ファイル末であればリターン
350 @line.lstrip! # 先頭の空白を削除
351 return if @line != "" # 空行でなければリターン
352 @line = cfgFile.getNextLine(withinApi) # 次の行を読む
353 end
354 end
355
356 #
357 # 次の文字まで読み飛ばす
358 #
359 def skipToToken(cfgFile, withinApi=true)
360 skipSpace(cfgFile, withinApi)
361 if @line.nil? # ファイル末であればエラー終了
362 error_exit("unexpexced end-of-file")
363 end
364 end
365
366 #
367 # パラメータを1つ読む
368 #
369 # @lineの先頭からパラメータを1つ読んで,それを文字列で返す.読んだパ
370 # ラメータは,@lineからは削除する.パラメータの途中で行末に達した時は,
371 # cfgFileから次の行を取り出す.ファイル末に達した時は,nilを返す.
372 #
373 def parseParam(cfgFile)
374 param = "" # 読んだ文字列
375 parenLevel = 0 # 括弧のネストレベル
376 skipComma = @skipComma
377 @skipComma = false
378
379 skipToToken(cfgFile) # 次の文字まで読み飛ばす
380 begin
381 if parenLevel == 0
382 case @line
383 when /^(\s*,)(.*)$/ # ,
384 @line = $2
385 if param == "" && skipComma
386 skipComma = false
387 return(parseParam(cfgFile)) # 再帰呼び出し
388 else
389 return(param.strip)
390 end
391 when /^(\s*{)(.*)$/ # {
392 if param != ""
393 return(param.strip)
394 else
395 @line = $2
396 return("{")
397 end
398 when /^(\s*\()(.*)$/ # (
399 param += $1
400 @line = $2
401 parenLevel += 1
402 when /^(\s*([)}]))(.*)$/ # }か)
403 if param != ""
404 return(param.strip)
405 else
406 @line = $3
407 @skipComma = true if $2 == "}"
408 return($2)
409 end
410 when /^(\s*\")(.*)$/ # "
411 @line = $2
412 param += $1 + parseString(cfgFile)
413 when /^(\s*\')(.*)$/ # '
414 @line = $2
415 param += $1 + parseChar(cfgFile)
416 when /^(\s*[^,{}()"'\s]+)(.*)$/ # その他の文字列
417 param += $1
418 @line = $2
419 else # 行末
420 param += " "
421 @line = cfgFile.getNextLine(true)
422 end
423 else
424 # 括弧内の処理
425 case @line
426 when /^(\s*\()(.*)$/ # "("
427 param += $1
428 @line = $2
429 parenLevel += 1
430 when /^(\s*\))(.*)$/ # ")"
431 param += $1
432 @line = $2
433 parenLevel -= 1
434 when /^(\s*\")(.*)$/ # "
435 @line = $2
436 param += $1 + parseString(cfgFile)
437 when /^(\s*\')(.*)$/ # '
438 @line = $2
439 param += $1 + parseChar(cfgFile)
440 when /^(\s*[^()"'\s]+)(.*)$/ # その他の文字列
441 param += $1
442 @line = $2
443 else # 行末
444 param += " "
445 @line = cfgFile.getNextLine(true)
446 end
447 end
448 end while (@line)
449 return(param.strip)
450 end
451
452 def getParam(apiParam, param, cfgFile)
453 if param == ""
454 if !apiParam.has_key?(:OPTIONAL)
455 parse_error(cfgFile, "unexpected `,'")
456 end
457 return(param)
458 end
459
460 if apiParam.has_key?(:ID_DEF) || apiParam.has_key?(:ID_REF)
461 if (/^[A-Za-z_]\w*$/ !~ param)
462 parse_error(cfgFile, "`#{param}' is illegal object ID")
463 end
464 return(param)
465 end
466
467 if apiParam.has_key?(:STRING)
468 return(param.unquote)
469 else
470 return(param)
471 end
472 end
473
474 def parseApi(cfgFile, apiName)
475 # 静的APIの読み込み
476 staticApi = {}
477 tooFewParams = false
478 skipUntilBrace = 0
479
480 skipToToken(cfgFile) # 次の文字まで読み飛ばす
481 if (/^\((.*)$/ =~ @line)
482 @line = $1
483
484 staticApi[:APINAME] = apiName
485 staticApi[:_FILE_] = cfgFile.getFileName
486 staticApi[:_LINE_] = cfgFile.getLineNo
487 apiDef = $apiDefinition[apiName]
488 param = parseParam(cfgFile)
489
490 apiDef[:PARAM].each do |apiParam|
491 return(staticApi) if param.nil? # ファイル末であればリターン
492
493 if skipUntilBrace > 0
494 # API定義を}までスキップ中
495 if apiParam.has_key?(:BRACE)
496 case apiParam[:BRACE]
497 when "{"
498 skipUntilBrace += 1
499 when "}"
500 skipUntilBrace -= 1
501 end
502 end
503 elsif apiParam.has_key?(:OPTIONAL)
504 if /^([{})])$/ !~ param
505 store_param = getParam(apiParam, param, cfgFile)
506 if store_param != ""
507 staticApi[apiParam[:NAME]] = store_param
508 end
509 param = parseParam(cfgFile)
510 end
511 elsif apiParam.has_key?(:LIST)
512 staticApi[apiParam[:NAME]] = []
513 while /^([{})])$/ !~ param
514 staticApi[apiParam[:NAME]].push(getParam(apiParam, param, cfgFile))
515 param = parseParam(cfgFile)
516 break if param.nil? # ファイル末の場合
517 end
518 elsif apiParam.has_key?(:OPTBRACE)
519 if param == apiParam[:BRACE]
520 param = parseParam(cfgFile)
521 break if param.nil? # ファイル末の場合
522 else
523 if param == ""
524 param = parseParam(cfgFile)
525 break if param.nil? # ファイル末の場合
526 elsif /^([})])$/ !~ param
527 parse_error(cfgFile, "`{...}' expected before #{param}")
528 end
529 skipUntilBrace += 1 # API定義を}までスキップ
530 end
531 elsif !apiParam.has_key?(:BRACE)
532 if /^([{})])$/ !~ param
533 staticApi[apiParam[:NAME]] = getParam(apiParam, param, cfgFile)
534 param = parseParam(cfgFile)
535 elsif !tooFewParams
536 parse_error(cfgFile, "too few parameters before `#{$1}'")
537 tooFewParams = true
538 end
539 elsif param == apiParam[:BRACE]
540 param = parseParam(cfgFile)
541 tooFewParams = false
542 else
543 parse_error(cfgFile, "`#{apiParam[:BRACE]}' expected before #{param}")
544 # )かファイル末まで読み飛ばす
545 loop do
546 param = parseParam(cfgFile)
547 break if (param.nil? || param == ")")
548 end
549 break
550 end
551 end
552
553 # 期待されるパラメータをすべて読んだ後の処理
554 if param != ")"
555 begin
556 param = parseParam(cfgFile)
557 return(staticApi) if param.nil? # ファイル末であればリターン
558 end while param != ")"
559 parse_error(cfgFile, "too many parameters before `)'")
560 end
561 else
562 parse_error(cfgFile, "syntax error: #{@line}")
563 @line = ""
564 end
565 return(staticApi)
566 end
567
568 def parseOpenBrace(cfgFile)
569 # {の読み込み
570 skipToToken(cfgFile) # 次の文字まで読み飛ばす
571 if (/^\{(.*)$/ =~ @line)
572 @line = $1
573 else
574 parse_error(cfgFile, "`{' expected before #{@line}")
575 end
576 end
577
578 def parseFile(cfgFileName)
579 cfgFiles = [ ConfigFile.new(cfgFileName) ]
580 @line = ""
581 loop do
582 cfgFile = cfgFiles.last
583
584 skipSpace(cfgFile, false) # 改行と空白文字を読み飛ばす
585 if @line.nil?
586 # ファイル末の処理
587 cfgFiles.pop.close
588 if cfgFiles.empty?
589 break # パース処理終了
590 else
591 @line = "" # 元のファイルに戻って続ける
592 end
593 elsif /^;(.*)$/ =~ @line
594 # ;は読み飛ばす
595 @line = $1
596 elsif /^#/ =~ @line
597 # プリプロセッサディレクティブを読む
598 case @line
599 when /^#include\b(.*)$/
600 $includeFiles.push($1.strip)
601 when /^#(ifdef|ifndef|if|endif|else|elif)\b/
602 directive = { :DIRECTIVE => @line.strip }
603 $cfgFileInfo.push(directive)
604 else
605 parse_error(cfgFile, "unknown preprocessor directive: #{@line}")
606 end
607 @line = ""
608 elsif (/^([A-Z_][A-Z0-9_]*)\b(.*)$/ =~ @line)
609 apiName = $1
610 @line = $2
611
612 case apiName
613 when "KERNEL_DOMAIN"
614 if $supportDomain.nil?
615 parse_warning(cfgFile, "`KERNEL_DOMAIN' is not supported")
616 end
617 if !@@currentDomain.nil?
618 parse_error(cfgFile, "`DOMAIN' must not be nested")
619 end
620 @@currentDomain = "TDOM_KERNEL"
621 parseOpenBrace(cfgFile)
622 @@nestDC.push("domain")
623 when "DOMAIN"
624 if $supportDomain.nil?
625 parse_warning(cfgFile, "`DOMAIN' is not supported")
626 end
627 if !@@currentDomain.nil?
628 parse_error(cfgFile, "`DOMAIN' must not be nested")
629 end
630 domid = parseParam(cfgFile).sub(/^\((.+)\)$/m, "\\1").strip
631 if (/^[A-Za-z_]\w*$/ !~ domid)
632 parse_error(cfgFile, "`#{domid}' is illegal domain ID")
633 else
634 if !$domainId.has_key?(domid)
635 if $inputObjid.has_key?(domid)
636 # ID番号入力ファイルに定義されていた場合
637 $domainId[domid] = $inputObjid[domid]
638 if $domainId[domid] > 32
639 error_exit("domain ID for `#{domid}' is too large")
640 end
641 else
642 $domainId[domid] = nil
643 end
644 end
645 @@currentDomain = domid
646 end
647 parseOpenBrace(cfgFile)
648 @@nestDC.push("domain")
649 when "CLASS"
650 if $supportClass.nil?
651 parse_warning(cfgFile, "`CLASS' is not supported")
652 end
653 if !@@currentClass.nil?
654 parse_error(cfgFile, "`CLASS' must not be nested")
655 end
656 @@currentClass = parseParam(cfgFile).sub(/^\((.+)\)$/m, "\\1").strip
657 @@classFile = cfgFile.getFileName
658 @@classLine = cfgFile.getLineNo
659 parseOpenBrace(cfgFile)
660 @@nestDC.push("class")
661 else
662 if $apiDefinition.has_key?(apiName)
663 # 静的APIを1つ読む
664 staticApi = parseApi(cfgFile, apiName)
665 if staticApi.empty?
666 # ファイル末か文法エラー
667 elsif (staticApi[:APINAME] == "INCLUDE")
668 # INCLUDEの処理
669 includeFilePath = SearchFilePath(staticApi[:file])
670 if includeFilePath.nil?
671 parse_error(cfgFile, "`#{staticApi[:file]}' not found")
672 else
673 $dependencyFiles.push(includeFilePath)
674 cfgFiles.push(ConfigFile.new(includeFilePath))
675 end
676 else
677 # 静的APIの処理
678 if !@@currentDomain.nil?
679 staticApi[:DOMAIN] = @@currentDomain
680 end
681 if !@@currentClass.nil?
682 staticApi[:CLASS] = @@currentClass
683 staticApi[:CLASS_FILE_] = @@classFile
684 staticApi[:CLASS_LINE_] = @@classLine
685 end
686 staticApi[:INDEX] = (@@lastApiIndex += 1)
687 $cfgFileInfo.push(staticApi)
688 end
689 else
690 parse_error(cfgFile, "unknown static API: #{apiName}")
691 end
692 end
693 elsif (/^\}(.*)$/ =~ @line)
694 # }の処理
695 if @@nestDC.size > 0
696 case @@nestDC.pop
697 when "domain"
698 @@currentDomain = nil
699 when "class"
700 @@currentClass = nil
701 end
702 else
703 error_exit("unexpected `}'")
704 end
705 @line = $1
706 else
707 parse_error(cfgFile, "syntax error: #{@line}")
708 @line = ""
709 end
710 end
711 end
712end
713
714#
715# cfg1_out.cの生成
716#
717module Cfg1OutC
718 #
719 # 静的APIのファイル名と行番号の出力
720 #
721 def self.OutLineNumber(cfgInfo)
722 @cfg1Out.add("#line #{cfgInfo[:_LINE_]} \"#{cfgInfo[:_FILE_]}\"")
723 end
724
725 #
726 # クラス記述のファイル名と行番号の出力
727 #
728 def self.OutClassLineNumber(cfgInfo)
729 @cfg1Out.add("#line #{cfgInfo[:CLASS_LINE_]} \"#{cfgInfo[:CLASS_FILE_]}\"")
730 end
731
732 #
733 # パラメータに関する定義の出力
734 #
735 def self.OutParamDef(param, index, apiParam, cfgInfo)
736 if apiParam.has_key?(:ID_DEF)
737 @cfg1Out.add("#define #{param}\t(<>)")
738 elsif apiParam.has_key?(:EXPTYPE)
739 OutLineNumber(cfgInfo)
740 @cfg1Out.add("const #{apiParam[:EXPTYPE]} #{CFG1_PREFIX}valueof_" \
741 "#{apiParam[:NAME]}_#{index} = " \
742 "(#{apiParam[:EXPTYPE]})(#{param});")
743 end
744 end
745
746 #
747 # cfg1_out.cの生成(メインの処理)
748 #
749 def self.Generate
750 @cfg1Out = GenFile.new(CFG1_OUT_C)
751
752 @cfg1Out.append(<<EOS)
753/* #{CFG1_OUT_C} */
754#define TOPPERS_CFG1_OUT
755#include "kernel/kernel_int.h"
756EOS
757
758 # インクルードヘッダファイル
759 $includeFiles.each do |file|
760 @cfg1Out.add("#include #{file}")
761 end
762
763 @cfg1Out.add(<<EOS)
764
765#ifdef INT64_MAX
766 typedef int64_t signed_t;
767 typedef uint64_t unsigned_t;
768#else
769 typedef int32_t signed_t;
770 typedef uint32_t unsigned_t;
771#endif
772
773#include "#{CFG1_OUT_TARGET_H}"
774#include <limits.h>
775
776const uint32_t #{CFG1_MAGIC_NUM} = 0x12345678;
777const uint32_t #{CFG1_SIZEOF_SIGNED} = sizeof(signed_t);
778EOS
779
780 # 値取得シンボルの処理
781 $symbolValueTable.each do |symbolName, symbolData|
782 if symbolData.has_key?(:BOOL) || symbolData.has_key?(:SIGNED)
783 type = "signed_t"
784 else
785 type = "unsigned_t"
786 end
787 if symbolData.has_key?(:CONDITION)
788 @cfg1Out.add("#if #{symbolData[:CONDITION]}")
789 end
790 @cfg1Out.add("const #{type} #{CFG1_PREFIX}#{symbolName} = " \
791 "(#{type})(#{symbolData[:EXPR]});")
792 if symbolData.has_key?(:ELSE_EXPR)
793 @cfg1Out.add("#else")
794 @cfg1Out.add("const #{type} #{CFG1_PREFIX}#{symbolName} = " \
795 "(#{type})(#{symbolData[:ELSE_EXPR]});")
796 end
797 if symbolData.has_key?(:CONDITION)
798 @cfg1Out.add("#endif")
799 end
800 end
801 @cfg1Out.add
802
803 # ドメインIDの定義の生成
804 $domainId.each do |domainName, domainVal|
805 if domainVal > 0
806 @cfg1Out.add("#define #{domainName} #{domainVal}")
807 end
808 end
809 @cfg1Out.add
810
811 # 静的API/プリプロセッサディレクティブの処理
812 $cfgFileInfo.each do |cfgInfo|
813 if cfgInfo.has_key?(:DIRECTIVE)
814 @cfg1Out.add2(cfgInfo[:DIRECTIVE])
815 else
816 apiDef = $apiDefinition[cfgInfo[:APINAME]]
817 apiIndex = cfgInfo[:INDEX]
818 OutLineNumber(cfgInfo)
819 @cfg1Out.add("const unsigned_t #{CFG1_PREFIX}static_api_" \
820 "#{apiIndex} = #{apiIndex};")
821 apiDef[:PARAM].each do |apiParam|
822 next unless apiParam.has_key?(:NAME)
823 paramName = apiParam[:NAME]
824 next unless cfgInfo.has_key?(paramName) # パラメータがない場合
825 paramData = cfgInfo[paramName]
826
827 if apiParam.has_key?(:LIST)
828 paramData.each.with_index(1) do |param, index|
829 OutParamDef(param, "#{apiIndex}_#{index}", apiParam, cfgInfo)
830 end
831 else
832 OutParamDef(paramData, "#{apiIndex}", apiParam, cfgInfo)
833 end
834 end
835 if cfgInfo.has_key?(:CLASS)
836 # クラスIDの取得のための処理
837 OutClassLineNumber(cfgInfo)
838 @cfg1Out.add("const signed_t #{CFG1_PREFIX}valueof_CLASS_" \
839 "#{apiIndex} = (signed_t)(#{cfgInfo[:CLASS]});")
840 end
841 @cfg1Out.add
842 end
843 end
844 end
845end
846
847#
848# パス1の処理
849#
850def Pass1
851 #
852 # タイムスタンプファイルの指定
853 #
854 $timeStampFileName = CFG1_OUT_TIMESTAMP
855
856 #
857 # 静的APIテーブルの読み込み
858 #
859 ReadApiTableFile()
860
861 #
862 # 値取得シンボルテーブルの読み込み
863 #
864 ReadSymvalTable()
865
866 #
867 # システムコンフィギュレーションファイルの読み込み
868 #
869 $cfgFileInfo = []
870 $dependencyFiles = $configFileNames.dup
871 $includeFiles = []
872 $domainId = { "TDOM_KERNEL" => -1, "TDOM_NONE" => -2 }
873 $configFileNames.each do |configFileName|
874 CfgParser.new.parseFile(configFileName)
875 end
876 abort if $errorFlag # エラー発生時はabortする
877
878 #
879 # ドメインIDの割当て処理
880 #
881 nextDomainId = 1
882 $domainId.each do |domainName, domainVal|
883 if domainVal.nil?
884 while $domainId.has_value?(nextDomainId)
885 nextDomainId += 1
886 end
887 $domainId[domainName] = nextDomainId
888 if nextDomainId > 32
889 error_exit("too large number of user domains")
890 end
891 nextDomainId += 1
892 end
893 end
894
895 #
896 # cfg1_out.cの生成
897 #
898 Cfg1OutC::Generate()
899
900 #
901 # 依存関係の出力
902 #
903 if !$dependencyFileName.nil?
904 if $dependencyFileName == ""
905 depFile = STDOUT
906 else
907 begin
908 depFile = File.open($dependencyFileName, "w")
909 rescue Errno::ENOENT, Errno::EACCES => ex
910 abort(ex.message)
911 end
912 end
913
914 depFile.print("#{CFG1_OUT_TIMESTAMP}:")
915 $dependencyFiles.each do |fileName|
916 depFile.print(" #{fileName}")
917 end
918 depFile.puts("")
919
920 if $dependencyFileName != ""
921 depFile.close
922 end
923 end
924
925 #
926 # パス2に引き渡す情報をファイルに生成
927 #
928 if $omitOutputDb.nil?
929 db = PStore.new(CFG1_OUT_DB)
930 db.transaction do
931 db[:apiDefinition] = $apiDefinition
932 db[:symbolValueTable] = $symbolValueTable
933 db[:cfgFileInfo] = $cfgFileInfo
934 db[:includeFiles] = $includeFiles
935 db[:domainId] = $domainId
936 end
937 end
938end
Note: See TracBrowser for help on using the repository browser.