source: EcnlProtoTool/trunk/asp3_dcre/cfg/pass1.rb@ 270

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

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby
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# 上記著作権者
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 1011 2016-07-11 02:20:01Z coas-nagasima $
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 symvalCsv.each do |record|
188 # 変数名
189 if record[0].nil?
190 error_exit("invalid variable name in `#{fileName}'")
191 end
192
193 symbol = {}
194 variable = record[0]
195
196 # 式
197 if record[1].nil? || record[1].empty?
198 symbol[:EXPR] = variable
199 else
200 symbol[:EXPR] = record[1]
201 end
202
203 # 式の型
204 if !record[2].nil? && !record[2].empty?
205 case record[2]
206 when /^[bB]/ # 真偽値
207 symbol[:BOOL] = true
208 when /^[uU]/ # 符号無し整数値
209 # 何も設定しない
210 else # 符号付き整数値
211 symbol[:SIGNED] = true
212 end
213 end
214
215 # コンパイル条件
216 if !record[3].nil? && !record[3].empty?
217 symbol[:CONDITION] = record[3]
218 end
219
220 # 条件が成立しない時の式
221 if !record[4].nil? && !record[4].empty?
222 symbol[:ELSE_EXPR] = record[4]
223 end
224
225 $symbolValueTable[variable] = symbol
226 end
227 symvalCsv.close
228 end
229end
230
231#
232# システムコンフィギュレーションファイルからの読み込みクラス
233#
234class ConfigFile
235 def initialize(fileName)
236 @cfgFileName = fileName
237 begin
238 @cfgFile = File.open(@cfgFileName)
239 rescue Errno::ENOENT, Errno::EACCES => ex
240 abort(ex.message)
241 end
242 @lineNo = 0
243 @withinComment = false
244 end
245
246 def close
247 @cfgFile.close
248 end
249
250 def getNextLine(withinApi)
251 line = @cfgFile.gets
252 return(nil) if line.nil?
253 @lineNo += 1
254
255 line.chomp!
256 if @withinComment
257 case line
258 when /\*\// # C言語スタイルのコメント終了
259 line.sub!(/^.*?\*\//, "") # 最初の*/にマッチさせる */
260 @withinComment = false
261 else
262 line = ""
263 end
264 end
265 if !@withinComment
266 line.gsub!(/\/\*.*?\*\//, "") # C言語スタイルのコメントの除去
267 # 最初の*/にマッチさせる */
268 case line
269 when /^\s*#/ # プリプロセッサディレクティブ
270 if withinApi
271 parse_error(self, \
272 "preprocessor directive must not be within static API")
273 line = ""
274 end
275 when /\/\*/ # C言語スタイルのコメント開始
276 line.sub!(/\/\*.*$/, "")
277 @withinComment = true
278 when /\/\// # C++言語スタイルのコメント
279 line.sub!(/\/\/.*$/, "")
280 end
281 end
282 return(line)
283 end
284
285 def getFileName
286 return(@cfgFileName)
287 end
288
289 def getLineNo
290 return(@lineNo)
291 end
292end
293
294#
295# システムコンフィギュレーションファイルのパーサークラス
296#
297class CfgParser
298 @@lastApiIndex = 0
299 @@currentDomain = nil
300 @@currentClass = nil
301 @@nestDC = []
302
303 def initialize
304 @line = ""
305 @skipComma = false # 次が,であれば読み飛ばす
306 end
307
308 #
309 # 文字列末まで読む
310 #
311 def parseString(cfgFile)
312 string = ""
313 begin
314 case @line
315 when /^([^"]*\\\\)(.*)$/ # \\まで読む
316 string += $1
317 @line = $2
318 when /^([^"]*\\\")(.*)$/ # \"まで読む
319 string += $1
320 @line = $2
321 when /^([^"]*\")(.*)$/ # "まで読む
322 string += $1
323 @line = $2
324 return(string)
325 else # 行末まで読む
326 string += @line + "\n"
327 @line = cfgFile.getNextLine(true)
328 end
329 end while (@line)
330 error_exit("unterminated string meets end-of-file")
331 return(string)
332 end
333
334 #
335 # 文字末まで読む
336 #
337 def parseChar(cfgFile)
338 string = ""
339 begin
340 case @line
341 when /^([^']*\\\\)(.*)$/ # \\まで読む
342 string += $1
343 @line = $2
344 when /^([^']*\\\')(.*)$/ # \'まで読む
345 string += $1
346 @line = $2
347 when /^([^']*\')(.*)$/ # 'まで読む
348 string += $1
349 @line = $2
350 return(string)
351 else # 行末まで読む
352 string += @line + "\n"
353 @line = cfgFile.getNextLine(true)
354 end
355 end while (@line)
356 error_exit("unterminated string meets end-of-file")
357 return(string)
358 end
359
360 #
361 # 改行と空白文字を読み飛ばす
362 #
363 def skipSpace(cfgFile, withinApi)
364 loop do
365 return if @line.nil? # ファイル末であればリターン
366 @line.lstrip! # å…
367ˆé ­ã®ç©ºç™½ã‚’削除
368 return if @line != "" # 空行でなければリターン
369 @line = cfgFile.getNextLine(withinApi) # 次の行を読む
370 end
371 end
372
373 #
374 # 次の文字まで読み飛ばす
375 #
376 def skipToToken(cfgFile, withinApi=true)
377 skipSpace(cfgFile, withinApi)
378 if @line.nil? # ファイル末であればエラー終了
379 error_exit("unexpexced end-of-file")
380 end
381 end
382
383 #
384 # パラメータを1つ読む
385 #
386 # @lineのå…
387ˆé ­ã‹ã‚‰ãƒ‘ラメータを1つ読んで,それを文字列で返す.読んだパ
388 # ラメータは,@lineからは削除する.パラメータの途中で行末に達した時は,
389 # cfgFileから次の行を取り出す.ファイル末に達した時は,nilを返す.
390 #
391 def parseParam(cfgFile)
392 param = "" # 読んだ文字列
393 parenLevel = 0 # 括弧のネストレベル
394 skipComma = @skipComma
395 @skipComma = false
396
397 skipToToken(cfgFile) # 次の文字まで読み飛ばす
398 begin
399 if parenLevel == 0
400 case @line
401 when /^(\s*,)(.*)$/ # ,
402 @line = $2
403 if param == "" && skipComma
404 skipComma = false
405 return(parseParam(cfgFile)) # 再帰呼び出し
406 else
407 return(param.strip)
408 end
409 when /^(\s*{)(.*)$/ # {
410 if param != ""
411 return(param.strip)
412 else
413 @line = $2
414 return("{")
415 end
416 when /^(\s*\()(.*)$/ # (
417 param += $1
418 @line = $2
419 parenLevel += 1
420 when /^(\s*([)}]))(.*)$/ # }か)
421 if param != ""
422 return(param.strip)
423 else
424 @line = $3
425 @skipComma = true if $2 == "}"
426 return($2)
427 end
428 when /^(\s*\")(.*)$/ # "
429 @line = $2
430 param += $1 + parseString(cfgFile)
431 when /^(\s*\')(.*)$/ # '
432 @line = $2
433 param += $1 + parseChar(cfgFile)
434 when /^(\s*[^,{}()"'\s]+)(.*)$/ # その他の文字列
435 param += $1
436 @line = $2
437 else # 行末
438 param += " "
439 @line = cfgFile.getNextLine(true)
440 end
441 else
442 # 括弧内
443の処理
444 case @line
445 when /^(\s*\()(.*)$/ # "("
446 param += $1
447 @line = $2
448 parenLevel += 1
449 when /^(\s*\))(.*)$/ # ")"
450 param += $1
451 @line = $2
452 parenLevel -= 1
453 when /^(\s*\")(.*)$/ # "
454 @line = $2
455 param += $1 + parseString(cfgFile)
456 when /^(\s*\')(.*)$/ # '
457 @line = $2
458 param += $1 + parseChar(cfgFile)
459 when /^(\s*[^()"'\s]+)(.*)$/ # その他の文字列
460 param += $1
461 @line = $2
462 else # 行末
463 param += " "
464 @line = cfgFile.getNextLine(true)
465 end
466 end
467 end while (@line)
468 return(param.strip)
469 end
470
471 def getParam(apiParam, param, cfgFile)
472 if param == ""
473 if !apiParam.has_key?(:OPTIONAL)
474 parse_error(cfgFile, "unexpected `,'")
475 end
476 return(param)
477 end
478
479 if apiParam.has_key?(:ID_DEF) || apiParam.has_key?(:ID_REF)
480 if (/^[A-Za-z_]\w*$/ !~ param)
481 parse_error(cfgFile, "`#{param}' is illegal object ID")
482 end
483 return(param)
484 end
485
486 if apiParam.has_key?(:STRING)
487 return(param.unquote)
488 else
489 return(param)
490 end
491 end
492
493 def parseApi(cfgFile, apiName)
494 # 静的APIの読み込み
495 staticApi = {}
496 tooFewParams = false
497 skipUntilBrace = 0
498
499 skipToToken(cfgFile) # 次の文字まで読み飛ばす
500 if (/^\((.*)$/ =~ @line)
501 @line = $1
502
503 staticApi[:APINAME] = apiName
504 staticApi[:_FILE_] = cfgFile.getFileName
505 staticApi[:_LINE_] = cfgFile.getLineNo
506 apiDef = $apiDefinition[apiName]
507 param = parseParam(cfgFile)
508
509 apiDef[:PARAM].each do |apiParam|
510 return(staticApi) if param.nil? # ファイル末であればリターン
511
512 if skipUntilBrace > 0
513 # API定義を}までスキップ中
514 if apiParam.has_key?(:BRACE)
515 case apiParam[:BRACE]
516 when "{"
517 skipUntilBrace += 1
518 when "}"
519 skipUntilBrace -= 1
520 end
521 end
522 elsif apiParam.has_key?(:OPTIONAL)
523 if /^([{})])$/ !~ param
524 store_param = getParam(apiParam, param, cfgFile)
525 if store_param != ""
526 staticApi[apiParam[:NAME]] = store_param
527 end
528 param = parseParam(cfgFile)
529 end
530 elsif apiParam.has_key?(:LIST)
531 staticApi[apiParam[:NAME]] = []
532 while /^([{})])$/ !~ param
533 staticApi[apiParam[:NAME]].push(getParam(apiParam, param, cfgFile))
534 param = parseParam(cfgFile)
535 break if param.nil? # ファイル末の場合
536 end
537 elsif apiParam.has_key?(:OPTBRACE)
538 if param == apiParam[:BRACE]
539 param = parseParam(cfgFile)
540 break if param.nil? # ファイル末の場合
541 else
542 if param == ""
543 param = parseParam(cfgFile)
544 break if param.nil? # ファイル末の場合
545 elsif /^([})])$/ !~ param
546 parse_error(cfgFile, "`{...}' expected before #{param}")
547 end
548 skipUntilBrace += 1 # API定義を}までスキップ
549 end
550 elsif !apiParam.has_key?(:BRACE)
551 if /^([{})])$/ !~ param
552 staticApi[apiParam[:NAME]] = getParam(apiParam, param, cfgFile)
553 param = parseParam(cfgFile)
554 elsif !tooFewParams
555 parse_error(cfgFile, "too few parameters before `#{$1}'")
556 tooFewParams = true
557 end
558 elsif param == apiParam[:BRACE]
559 param = parseParam(cfgFile)
560 tooFewParams = false
561 else
562 parse_error(cfgFile, "`#{apiParam[:BRACE]}' expected before #{param}")
563 # )かファイル末まで読み飛ばす
564 loop do
565 param = parseParam(cfgFile)
566 break if (param.nil? || param == ")")
567 end
568 break
569 end
570 end
571
572 # 期待
573されるパラメータをすべて読んだ後の処理
574 if param != ")"
575 begin
576 param = parseParam(cfgFile)
577 return(staticApi) if param.nil? # ファイル末であればリターン
578 end while param != ")"
579 parse_error(cfgFile, "too many parameters before `)'")
580 end
581 else
582 parse_error(cfgFile, "syntax error: #{@line}")
583 @line = ""
584 end
585 return(staticApi)
586 end
587
588 def parseOpenBrace(cfgFile)
589 # {の読み込み
590 skipToToken(cfgFile) # 次の文字まで読み飛ばす
591 if (/^\{(.*)$/ =~ @line)
592 @line = $1
593 else
594 parse_error(cfgFile, "`{' expected before #{@line}")
595 end
596 end
597
598 def parseFile(cfgFileName)
599 cfgFiles = [ ConfigFile.new(cfgFileName) ]
600 @line = ""
601 loop do
602 cfgFile = cfgFiles.last
603
604 skipSpace(cfgFile, false) # 改行と空白文字を読み飛ばす
605 if @line.nil?
606 # ファイル末の処理
607 cfgFiles.pop.close
608 if cfgFiles.empty?
609 break # パース処理終了
610 else
611 @line = "" # å…
612ƒã®ãƒ•ã‚¡ã‚¤ãƒ«ã«æˆ»ã£ã¦ç¶šã‘ã‚‹
613 end
614 elsif /^;(.*)$/ =~ @line
615 # ;は読み飛ばす
616 @line = $1
617 elsif /^#/ =~ @line
618 # プリプロセッサディレクティブを読む
619 case @line
620 when /^#include\b(.*)$/
621 $includeFiles.push($1.strip)
622 when /^#(ifdef|ifndef|if|endif|else|elif)\b/
623 directive = { :DIRECTIVE => @line.strip }
624 $cfgFileInfo.push(directive)
625 else
626 parse_error(cfgFile, "unknown preprocessor directive: #{@line}")
627 end
628 @line = ""
629 elsif (/^([A-Z_][A-Z0-9_]*)\b(.*)$/ =~ @line)
630 apiName = $1
631 @line = $2
632
633 case apiName
634 when "KERNEL_DOMAIN"
635 if $supportDomain.nil?
636 parse_warning(cfgFile, "`KERNEL_DOMAIN' is not supported")
637 end
638 if !@@currentDomain.nil?
639 parse_error(cfgFile, "`DOMAIN' must not be nested")
640 end
641 @@currentDomain = "TDOM_KERNEL"
642 parseOpenBrace(cfgFile)
643 @@nestDC.push("domain")
644 when "DOMAIN"
645 if $supportDomain.nil?
646 parse_warning(cfgFile, "`DOMAIN' is not supported")
647 end
648 if !@@currentDomain.nil?
649 parse_error(cfgFile, "`DOMAIN' must not be nested")
650 end
651 domid = parseParam(cfgFile).sub(/^\((.+)\)$/m, "\\1").strip
652 if (/^[A-Za-z_]\w*$/ !~ domid)
653 parse_error(cfgFile, "`#{domid}' is illegal domain ID")
654 else
655 if !$domainId.has_key?(domid)
656 if $inputObjid.has_key?(domid)
657 # ID番号å…
658¥åŠ›ãƒ•ã‚¡ã‚¤ãƒ«ã«å®šç¾©ã•ã‚Œã¦ã„た場合
659 $domainId[domid] = $inputObjid[domid]
660 if $domainId[domid] > 32
661 error_exit("domain ID for `#{domid}' is too large")
662 end
663 else
664 $domainId[domid] = nil
665 end
666 end
667 @@currentDomain = domid
668 end
669 parseOpenBrace(cfgFile)
670 @@nestDC.push("domain")
671 when "CLASS"
672 if $supportClass.nil?
673 parse_warning(cfgFile, "`CLASS' is not supported")
674 end
675 if !@@currentClass.nil?
676 parse_error(cfgFile, "`CLASS' must not be nested")
677 end
678 @@currentClass = parseParam(cfgFile).sub(/^\((.+)\)$/m, "\\1").strip
679 @@classFile = cfgFile.getFileName
680 @@classLine = cfgFile.getLineNo
681 parseOpenBrace(cfgFile)
682 @@nestDC.push("class")
683 else
684 if $apiDefinition.has_key?(apiName)
685 # 静的APIを1つ読む
686 staticApi = parseApi(cfgFile, apiName)
687 if staticApi.empty?
688 # ファイル末か文法エラー
689 elsif (staticApi[:APINAME] == "INCLUDE")
690 # INCLUDEの処理
691 includeFilePath = SearchFilePath(staticApi[:file])
692 if includeFilePath.nil?
693 parse_error(cfgFile, "`#{staticApi[:file]}' not found")
694 else
695 $dependencyFiles.push(includeFilePath)
696 cfgFiles.push(ConfigFile.new(includeFilePath))
697 end
698 else
699 # 静的APIの処理
700 if !@@currentDomain.nil?
701 staticApi[:DOMAIN] = @@currentDomain
702 end
703 if !@@currentClass.nil?
704 staticApi[:CLASS] = @@currentClass
705 staticApi[:CLASS_FILE_] = @@classFile
706 staticApi[:CLASS_LINE_] = @@classLine
707 end
708 staticApi[:INDEX] = (@@lastApiIndex += 1)
709 $cfgFileInfo.push(staticApi)
710 end
711 else
712 parse_error(cfgFile, "unknown static API: #{apiName}")
713 end
714 end
715 elsif (/^\}(.*)$/ =~ @line)
716 # }の処理
717 if @@nestDC.size > 0
718 case @@nestDC.pop
719 when "domain"
720 @@currentDomain = nil
721 when "class"
722 @@currentClass = nil
723 end
724 else
725 error_exit("unexpected `}'")
726 end
727 @line = $1
728 else
729 parse_error(cfgFile, "syntax error: #{@line}")
730 @line = ""
731 end
732 end
733 end
734end
735
736#
737# cfg1_out.cの生成
738#
739module Cfg1OutC
740 #
741 # 静的APIのファイル名と行番号の出力
742 #
743 def self.OutLineNumber(cfgInfo)
744 @cfg1Out.add("#line #{cfgInfo[:_LINE_]} \"#{cfgInfo[:_FILE_]}\"")
745 end
746
747 #
748 # クラス記述のファイル名と行番号の出力
749 #
750 def self.OutClassLineNumber(cfgInfo)
751 @cfg1Out.add("#line #{cfgInfo[:CLASS_LINE_]} \"#{cfgInfo[:CLASS_FILE_]}\"")
752 end
753
754 #
755 # パラメータに関する定義の出力
756 #
757 def self.OutParamDef(param, index, apiParam, cfgInfo)
758 if apiParam.has_key?(:ID_DEF)
759 @cfg1Out.add("#define #{param}\t(<>)")
760 elsif apiParam.has_key?(:EXPTYPE)
761 OutLineNumber(cfgInfo)
762 @cfg1Out.add("const #{apiParam[:EXPTYPE]} #{CFG1_PREFIX}valueof_" \
763 "#{apiParam[:NAME]}_#{index} = " \
764 "(#{apiParam[:EXPTYPE]})(#{param});")
765 end
766 end
767
768 #
769 # cfg1_out.cの生成(メインの処理)
770 #
771 def self.Generate
772 @cfg1Out = GenFile.new(CFG1_OUT_C)
773
774 @cfg1Out.append(<<EOS)
775/* #{CFG1_OUT_C} */
776#define TOPPERS_CFG1_OUT
777#include "kernel/kernel_int.h"
778EOS
779
780 # インクルードヘッダファイル
781 $includeFiles.each do |file|
782 @cfg1Out.add("#include #{file}")
783 end
784
785 @cfg1Out.add(<<EOS)
786
787#ifdef INT64_MAX
788 typedef int64_t signed_t;
789 typedef uint64_t unsigned_t;
790#else
791 typedef int32_t signed_t;
792 typedef uint32_t unsigned_t;
793#endif
794
795#include "#{CFG1_OUT_TARGET_H}"
796#include <limits.h>
797
798const uint32_t #{CFG1_MAGIC_NUM} = 0x12345678;
799const uint32_t #{CFG1_SIZEOF_SIGNED} = sizeof(signed_t);
800EOS
801
802 # 値取得シンボルの処理
803 $symbolValueTable.each do |symbolName, symbolData|
804 if symbolData.has_key?(:BOOL) || symbolData.has_key?(:SIGNED)
805 type = "signed_t"
806 else
807 type = "unsigned_t"
808 end
809 if symbolData.has_key?(:CONDITION)
810 @cfg1Out.add("#if #{symbolData[:CONDITION]}")
811 end
812 @cfg1Out.add("const #{type} #{CFG1_PREFIX}#{symbolName} = " \
813 "(#{type})(#{symbolData[:EXPR]});")
814 if symbolData.has_key?(:ELSE_EXPR)
815 @cfg1Out.add("#else")
816 @cfg1Out.add("const #{type} #{CFG1_PREFIX}#{symbolName} = " \
817 "(#{type})(#{symbolData[:ELSE_EXPR]});")
818 end
819 if symbolData.has_key?(:CONDITION)
820 @cfg1Out.add("#endif")
821 end
822 end
823 @cfg1Out.add
824
825 # ドメインIDの定義の生成
826 $domainId.each do |domainName, domainVal|
827 if domainVal > 0
828 @cfg1Out.add("#define #{domainName} #{domainVal}")
829 end
830 end
831 @cfg1Out.add
832
833 # 静的API/プリプロセッサディレクティブの処理
834 $cfgFileInfo.each do |cfgInfo|
835 if cfgInfo.has_key?(:DIRECTIVE)
836 @cfg1Out.add2(cfgInfo[:DIRECTIVE])
837 else
838 apiDef = $apiDefinition[cfgInfo[:APINAME]]
839 apiIndex = cfgInfo[:INDEX]
840 OutLineNumber(cfgInfo)
841 @cfg1Out.add("const unsigned_t #{CFG1_PREFIX}static_api_" \
842 "#{apiIndex} = #{apiIndex};")
843 apiDef[:PARAM].each do |apiParam|
844 next unless apiParam.has_key?(:NAME)
845 paramName = apiParam[:NAME]
846 next unless cfgInfo.has_key?(paramName) # パラメータがない場合
847 paramData = cfgInfo[paramName]
848
849 if apiParam.has_key?(:LIST)
850 paramData.each.with_index(1) do |param, index|
851 OutParamDef(param, "#{apiIndex}_#{index}", apiParam, cfgInfo)
852 end
853 else
854 OutParamDef(paramData, "#{apiIndex}", apiParam, cfgInfo)
855 end
856 end
857 if cfgInfo.has_key?(:CLASS)
858 # クラスIDの取得のための処理
859 OutClassLineNumber(cfgInfo)
860 @cfg1Out.add("const signed_t #{CFG1_PREFIX}valueof_CLASS_" \
861 "#{apiIndex} = (signed_t)(#{cfgInfo[:CLASS]});")
862 end
863 @cfg1Out.add
864 end
865 end
866 end
867end
868
869#
870# パス1の処理
871#
872def Pass1
873 #
874 # タイムスタンプファイルの指定
875 #
876 $timeStampFileName = CFG1_OUT_TIMESTAMP
877
878 #
879 # 静的APIテーブルの読み込み
880 #
881 ReadApiTableFile()
882
883 #
884 # 値取得シンボルテーブルの読み込み
885 #
886 ReadSymvalTable()
887
888 #
889 # システムコンフィギュレーションファイルの読み込み
890 #
891 $cfgFileInfo = []
892 $dependencyFiles = $configFileNames.dup
893 $includeFiles = []
894 $domainId = { "TDOM_KERNEL" => -1, "TDOM_NONE" => -2 }
895 $configFileNames.each do |configFileName|
896 CfgParser.new.parseFile(configFileName)
897 end
898 abort if $errorFlag # エラー発生時はabortする
899
900 #
901 # ドメインIDの割当て処理
902 #
903 nextDomainId = 1
904 $domainId.each do |domainName, domainVal|
905 if domainVal.nil?
906 while $domainId.has_value?(nextDomainId)
907 nextDomainId += 1
908 end
909 $domainId[domainName] = nextDomainId
910 if nextDomainId > 32
911 error_exit("too large number of user domains")
912 end
913 nextDomainId += 1
914 end
915 end
916
917 #
918 # cfg1_out.cの生成
919 #
920 Cfg1OutC::Generate()
921
922 #
923 # 依存関係の出力
924 #
925 if !$dependencyFileName.nil?
926 if $dependencyFileName == ""
927 depFile = STDOUT
928 else
929 begin
930 depFile = File.open($dependencyFileName, "w")
931 rescue Errno::ENOENT, Errno::EACCES => ex
932 abort(ex.message)
933 end
934 end
935
936 depFile.print("#{CFG1_OUT_TIMESTAMP}:")
937 $dependencyFiles.each do |fileName|
938 depFile.print(" #{fileName}")
939 end
940 depFile.puts("")
941
942 if $dependencyFileName != ""
943 depFile.close
944 end
945 end
946
947 #
948 # パス2に引き渡す情
949報をファイルに生成
950 #
951 if $omitOutputDb.nil?
952 db = PStore.new(CFG1_OUT_DB)
953 db.transaction do
954 db[:apiDefinition] = $apiDefinition
955 db[:symbolValueTable] = $symbolValueTable
956 db[:cfgFileInfo] = $cfgFileInfo
957 db[:includeFiles] = $includeFiles
958 db[:domainId] = $domainId
959 end
960 end
961end
Note: See TracBrowser for help on using the repository browser.