source: rubycfg_asp/trunk/asp_dcre/cfg/pass1.rb@ 313

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

ソースを追加

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