source: EcnlProtoTool/trunk/asp3_dcre/tecsgen/tecslib/core/syntaxobj.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: 34.2 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TECS Generator
4# Generator for TOPPERS Embedded Component System
5#
6# Copyright (C) 2008-2016 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: syntaxobj.rb 1011 2016-07-11 02:20:01Z coas-nagasima $
53#++
54
55# mikan ruby の symbol と文字列の使い分けがどうしてもうまくいかないことが時々
56あるので name.to_sym をå…
57¥ã‚Œã‚‹ã“とにした
58
59#== Node
60#
61# Node の直接の子クラス: C_EXP, Type, BaseVal, BDNode(ほとんどのものは BDNode の子クラス)
62# Node に (BDNodeにも) å…
63¥ã‚‰ãªã„もの: Token, Import, Import_C, Generate
64#
65# owner を持たないものが Node となる
66# エラーは、cdl_error を通じて報告する (意味解析が構文解析後に行われる場合には、行番号が正しく出力できる
67#
68
69class Node
70#@locale:: [@file, @lineno, @col]
71
72 def initialize
73 @locale = Generator.current_locale
74 end
75
76 #=== エラーを出力する
77 def cdl_error( message, *arg )
78 Generator.error2( @locale, message, *arg )
79 end
80
81 #=== エラーを出力する
82 #locale:: Array(locale info) : 構文解析中は無視される
83 def cdl_error2( locale, message, *arg )
84 Generator.error2( locale, message, *arg )
85 end
86
87 #=== エラーを出力する
88 #locale:: Array(locale info)
89 # 構文解析中 cdl_error2 では locale が無視されるため、別に locale を出力する
90 def cdl_error3( locale, message, *arg )
91 Generator.error( message, *arg )
92 Console.puts "check: #{locale[0]}: line #{locale[1]} for above error"
93 end
94
95 #=== ウォーニング出力する
96 def cdl_warning( message, *arg )
97 Generator.warning2( @locale, message, *arg )
98 end
99
100 #=== ウォーニング出力する
101 def cdl_warning2( locale, message, *arg )
102 Generator.warning2( locale, message, *arg )
103 end
104
105 #=== 情
106報を表示する
107 def cdl_info( message )
108 Console.puts "info: #{message}"
109 end
110
111 def get_locale
112 @locale
113 end
114
115 def set_locale locale
116 @locale = locale
117 end
118
119 def locale_str
120 "locale=( #{@locale[0]}, #{@locale[1]} )"
121 end
122end
123
124#== 双方向 Node (Bi Direction Node)
125#
126# Node の子クラス
127# owner Node から参ç…
128§ã•ã‚Œã¦ã„るもの (owner へのリンクも取り出せる)
129#
130# get_owner で得られるもの
131# FuncHead => Signature
132# Decl => Namespace(const), Typedef(typedef),
133# Celltype, CompositeCelltype(attr,var)
134# Struct(member), ParamDecl(parameter), FuncHead(funchead)
135# Signature, Celltype, CompositeCelltype, Typedef => Namespace
136#, Namespace => Namespace, Generator.class (root Namespace の場合)
137# Cell => Region, CompositeCelltype(in_composite)
138# Port => Celltype, Composite
139# Factory => Celltype
140# Join => Cell
141# CompositeCelltypeJoin => CompositeCelltype
142# Region => Region,
143# ParamDecl => ParamList
144# ParamList => FuncHead
145# Expression => Namespace
146# 大半のものは new_* メソッドで owner Node に伝達される
147# そのメソッドが呼び出されたときに owner Node が記録される
148# new_* がないもの:
149# Decl(parameter), ParamDecl, ParamList, FuncHead, Expression
150#
151# Expression は、owner Node となるものが多くあるが、改造が困難であるため
152# Expression が定義されたときの Namespace を owner Node とする
153# StructType は Type の一種なので owner を持たない
154#
155class BDNode < Node
156#@owner::Node
157#@NamespacePath:: NamespacePath
158#@Generator::
159#@import::Import :
160
161 def initialize
162 super
163 @owner = nil
164 @NamespacePath = nil
165 @import = Import.get_current
166
167 end
168
169 #=== owner を設定する
170 def set_owner owner
171 dbgPrint "set_owner: #{owner.class.name}\n"
172 @owner = owner
173 end
174
175 #=== owner を得る
176 # class の説明を参ç…
177§
178 def get_owner
179 if @owner == nil
180 raise "Node have no owner #{self.class.name} #{get_name}"
181 end
182 @owner
183 end
184end
185
186#== Namespace 名を持つ BDNode
187# Namespace(Region), Signature, Celltype, CompositeCelltype, Cell
188class NSBDNode < BDNode
189
190 def initialize
191 super
192 end
193
194 #=== 属する namespace を得る
195 # owner を namespace にたどり着くまで上にたどる
196 def get_namespace
197 if @owner.kind_of? Namespace
198 return @owner
199 elsif @owner != nil then
200 return @owner.get_namespace
201 else
202 # @owner == nil なら "::"
203 if @name != "::" then
204 raise "non-root namespace has no owner #{self.class.name}##{@name} #{self}"
205 end
206 return nil
207 end
208 end
209
210 def set_namespace_path
211 ns = get_namespace
212 if ns then
213 @NamespacePath = ns.get_namespace_path.append( get_name )
214 else
215 raise "get_namespace_path: no namespace found"
216 end
217 end
218
219 #=== NamespacePath を得る
220 def get_namespace_path
221 return @NamespacePath
222 end
223
224 def is_imported?
225 if @import then
226 return @import.is_imported?
227 else
228 return false # mikan: 仮 @import が nil になるケースが追求できていない
229 end
230 end
231end
232
233class NamedList
234# @names:: {} of items
235# @items:: [] of items : item の CLASS は get_name メソッドを持つこと get_name の戻り値は Symbol でなくてはならない
236# NamedList を clone_for_composite する場合は、item にもメソッドが必
237要
238# @type:: string エラーメッセージ
239
240 def initialize( item, type )
241 @names = {}
242 @items = []
243 @type = type
244 add_item( item )
245 end
246
247 #=== 要素を加える
248 # parse した時点で加えること(場所を記憶する)
249 def add_item( item )
250
251 if item then
252 assert_name item
253 name = item.get_name
254 prev = @names[name]
255 if prev then
256 Generator.error( "S2001 \'$1\' duplicate $2" , name, @type )
257 prev_locale = prev.get_locale
258 puts "previous: #{prev_locale[0]}: line #{prev_locale[1]} \'#{name}\' defined here"
259 return self
260 end
261
262 @names[name]=item
263 @items << item
264 end
265
266 return self
267 end
268
269 def change_item( item )
270 assert_name item
271 name = item.get_name
272
273 prev_one = @names[name]
274 @names[name]=item
275
276 @items = @items - [ prev_one ]
277 @items << item
278 end
279
280 def del_item( item )
281 assert_name item
282 name = item.get_name
283 @names.delete name
284
285 @items = @items - [ item ]
286 end
287
288 def get_item( name )
289 if ! name.kind_of? Symbol
290 print "get_item: '#{name}', items are below\n"
291 @names.each{ |nm,item|
292 p nm
293 }
294 raise "get_item: #{name}: not Symbol"
295 end
296 if name then
297 return @names[name.to_sym]
298 else
299 return nil
300 end
301 end
302
303 def get_items
304 return @items
305 end
306
307 #=== composite cell を clone した時に要素(JOIN) の clone する
308 #
309 # mikan このメソッドは Join に特化されているので NamedList から分離すべき
310 def clone_for_composite( ct_name, cell_name, locale )
311 cl = self.clone
312 cl.set_cloned( ct_name, cell_name, locale )
313 return cl
314 end
315
316 #=== clone された NamedList インスタンスの参ç…
317§ã™ã‚‹ã‚‚の(item)を clone
318 #
319 # mikan このメソッドは Join に特化されているので NamedList から分離すべき
320 def set_cloned( ct_name, cell_name, locale )
321 items = []
322 names = {}
323 @items.each { |i|
324 dbgPrint "NamedList clone #{ct_name}, #{cell_name}, #{i.get_name}\n"
325
326 cl = i.clone_for_composite( ct_name, cell_name, locale )
327 names[cl.get_name] = cl
328 items << cl
329 }
330 @items = items
331 @names = names
332 end
333
334 def assert_name item
335 if ! item.get_name.kind_of? Symbol
336 raise "Not symbol for NamedList item"
337 end
338 end
339
340 def show_tree( indent )
341 @items.each { |i|
342 i.show_tree( indent )
343 }
344 end
345
346end
347
348class Typedef < BDNode
349# @declarator:: Decl
350
351 def self.new_decl_list( type_spec_qual_list, decl_list )
352 decl_list.each { |decl|
353 Typedef.new( type_spec_qual_list, decl )
354 }
355 end
356
357 def initialize( type_spec_qual_list, decl )
358 super()
359 decl.set_type( type_spec_qual_list )
360 @declarator = decl
361 decl.set_owner self # Decl(Typedef)
362
363 Namespace.new_typedef( self )
364 end
365
366 def get_name
367 @declarator.get_name
368 end
369
370 def get_declarator
371 @declarator
372 end
373
374 def show_tree( indent )
375 indent.times { print " " }
376 puts "Typedef: #{locale_str}"
377 @declarator.show_tree( indent + 1 )
378 end
379end
380
381#== 関数頭部
382# signature に登録される関数
383class FuncHead <BDNode
384# @declarator:: Decl
385
386 def initialize( declarator, type, b_oneway )
387 super()
388 declarator.set_type( type )
389 @declarator = declarator
390 @declarator.set_owner self # Decl (FuncHead)
391
392 if @declarator.get_type.kind_of?( FuncType ) then
393 if b_oneway then
394 @declarator.get_type.set_oneway( b_oneway )
395 end
396 end
397 @declarator.get_type.check_struct_tag :FUNCHEAD
398
399 # check if return type is pointer
400 if declarator.get_type.kind_of? FuncType then
401 if declarator.get_type.get_type.get_original_type.kind_of?( PtrType ) &&
402 Signature.get_current.is_deviate? == false then
403 cdl_warning( "W3004 $1 pointer type has returned. specify deviate or stop return pointer" , @declarator.get_identifier )
404 end
405 end
406 end
407
408 def get_name
409 @declarator.get_name
410 end
411
412 def get_declarator
413 @declarator
414 end
415
416 def is_oneway?
417 if @declarator.is_function? then
418 return @declarator.get_type.is_oneway?
419 end
420 return false
421 end
422
423 def is_function?
424 @declarator.is_function?
425 end
426
427 #=== FuncHead# 関数の名前を返す
428 def get_name
429 return @declarator.get_name
430 end
431
432 #=== FuncHead# 関数の戻り値の型を返す
433 # types.rb に定義されている型
434 # 関数ヘッダの定義として不完å…
435¨ãªå ´åˆ nil を返す
436 def get_return_type
437 if is_function? then
438 return @declarator.get_type.get_type
439 end
440 end
441
442 #=== FuncHead# 関数の引数のリストを返す
443 # ParamList を返す
444 # 関数ヘッダの定義として不完å…
445¨ãªå ´åˆ nil を返す
446 def get_paramlist
447 if is_function? then
448 return @declarator.get_type.get_paramlist
449 end
450 end
451
452 def show_tree( indent )
453 indent.times { print " " }
454 puts "FuncHead: #{locale_str}"
455 @declarator.show_tree( indent + 1 )
456 end
457end
458
459#=== 宣言
460# @kind で示される各種の宣言
461class Decl < BDNode
462
463# @identifer:: String
464# @global_name:: String | nil : String(@kind=TYPEDEF||:CONSTANT), nil(@kind=その他)
465# set_kind にて設定される
466# @type:: ArrayType, FuncType, PtrType, IntType, StructType
467# VoidType, FloatType, DefinedType, BoolType
468# @initializer:: constant_expression, mikan { initlist }
469# @kind:: :VAR, :ATTRIBUTE, :PARAMETER, :TYPEDEF, :CONSTANT, :MEMBER, :FUNCHEAD(signatureの関数定義)
470# @b_referenced:: bool
471#
472# 以下は、@kind が :VAR, :ATTRIBUTE のときに有効
473# @rw:: bool # 古い文法では attr に指定可能だった(消すには generate の修正も必
474要)
475# @omit:: bool
476# @choice_list:: [String] attr 初期値の選択肢
477# 以下は、@kind が :VAR, :ATTRIBUTE, :MEMBER のときに有効
478# @size_is:: Expression or nil unless specified
479# 以下は、@kind が :MEMBER のときに有効
480# @count_is:: Expression or nil unless specified
481# attr, var の場合、count_is は指定できない
482# @string:: Expression, -1 (length not specified) or nil (not specified)
483#
484# mikan ParamDecl だけ別に設けたが、MemberDecl, AttrDecl なども分けるべきか(?)
485
486 def initialize( identifier )
487 super()
488 @identifier = identifier
489 @rw = false
490 @omit = false
491 @size_is = nil
492 @count_is = nil
493 @string = nil
494 @choice_list = nil
495 @b_referenced = false
496 end
497
498 def set_initializer( initializer )
499 @initializer = initializer
500 end
501
502 def get_initializer
503 @initializer
504 end
505
506 def is_function?
507 if @type.class == FuncType then
508 return true
509 else
510 return false
511 end
512 end
513
514 #== Decl の意味的誤りをチェックする
515 def check
516 # return nil if @type == nil
517
518 # 構造体タグチェック(ポインタ型から構造体が参ç…
519§ã•ã‚Œã¦ã„る場合は、タグの存在をチェックしない)
520 @type.check_struct_tag @kind
521
522 # 型のチェックを行う
523 res = @type.check
524 if res then
525 cdl_error( "S2002 $1: $2" , @identifier, res )
526 end
527
528 # 不要の初期化子をチェックする
529 if @initializer then
530 case @kind
531 when :PARAMETER, :TYPEDEF, :MEMBER, :FUNCHEAD
532 cdl_error( "S2003 $1: $2 cannot have initializer" , @identifier, @kind.to_s.downcase )
533 when :VAR, :ATTRIBUTE, :CONSTANT
534 # p @initializer ここでは代å…
535¥å¯èƒ½ã‹ã©ã†ã‹ã€ãƒã‚§ãƒƒã‚¯ã—ない
536 # :VAR, :ATTRIBUTE, :CONSTANT はそれぞれでチェックする
537 # return @type.check_init( @identifier, @initializer, @kind )
538 else
539 raise "unknown kind in Delc::check"
540 end
541 end
542
543 if( @type.kind_of? ArrayType ) && ( @type.get_subscript == nil ) && ( @omit == false ) then
544 if @kind == :ATTRIBUTE then
545 cdl_error( "S2004 $1: array subscript must be specified or omit" , @identifier )
546 elsif @kind == :VAR || @kind == :MEMBER then
547 cdl_error( "S2005 $1: array subscript must be specified" , @identifier )
548 end
549 end
550
551 return nil
552 end
553
554 #== ポインタレベルを得る
555 # 戻り値:
556 # 非ポインタ変数 = 0
557 # ポインタ変数 = 1
558 # 二重ポインタ変数 = 2
559 def get_ptr_level
560 level = 0
561 type = @type
562 while 1
563 if type.kind_of?( PtrType ) then
564 level += 1
565 type = type.get_referto
566# elsif type.kind_of?( ArrayType ) then # 添数なしé…
567åˆ—はポインタとみなす
568# if type.get_subscript == nil then
569# level += 1
570# type = type.get_type
571# else
572# break
573# end
574 # mikan ポインタの添数ありé…
575åˆ—のポインタレベルは0でよい?
576 elsif type.kind_of?( DefinedType ) then
577 type = type.get_type
578 # p "DefinedType: #{type} #{type.class}"
579 else
580 break
581 end
582 end
583 return level
584 end
585
586 def get_name
587 @identifier
588 end
589
590 def get_global_name
591 @global_name
592 end
593
594 def set_type( type )
595 unless @type then
596 @type = type
597 else
598 @type.set_type( type ) # 葉に設定
599 end
600 end
601
602 def get_type
603 @type
604 end
605
606 def get_identifier
607 @identifier
608 end
609
610 # STAGE: B
611 def set_kind( kind )
612 @kind = kind
613 case kind
614 when :TYPEDEF, :CONSTANT
615 if Namespace.get_global_name.to_s == "" then
616 @global_name = @identifier
617 else
618 @global_name = :"#{Namespace.get_global_name}_#{@identifier}"
619 end
620 else
621 @global_name = nil
622 end
623 end
624
625 def get_kind
626 @kind
627 end
628
629 def set_specifier_list( spec_list )
630 spec_list.each{ |spec|
631 case spec[0]
632 when :RW
633 @rw = true
634 when :OMIT
635 @omit = true
636 when :SIZE_IS
637 @size_is = spec[1]
638 when :COUNT_IS
639 @count_is = spec[1]
640 when :STRING
641 @string = spec[1]
642 when :CHOICE
643 @choice_list = spec[1]
644 else
645 raise "Unknown specifier #{spec[0]}"
646 end
647 }
648
649 if @size_is || @count_is || @string
650 @type.set_scs( @size_is, @count_is, @string, nil, false )
651 end
652 end
653
654 def is_rw?
655 @rw
656 end
657
658 def is_omit?
659 @omit
660 end
661
662 def get_size_is
663 @size_is
664 end
665
666 def get_count_is
667 @count_is
668 end
669
670 def get_string
671 @string
672 end
673
674 def get_choice_list
675 @choice_list
676 end
677
678 def referenced
679 @b_referenced = true
680 end
681
682 def is_referenced?
683 @b_referenced
684 end
685
686 def is_type?( type )
687 t = @type
688 while 1
689 if t.kind_of?( type ) then
690 return true
691 elsif t.kind_of?( DefinedType ) then
692 t = t.get_type
693 else
694 return false
695 end
696 end
697 end
698
699 def is_const?
700 type = @type
701 while 1
702 if type.is_const? then
703 return true
704 elsif type.kind_of?( DefinedType ) then
705 type = type.get_type
706 else
707 return false
708 end
709 end
710 end
711
712 def show_tree( indent )
713 indent.times { print " " }
714 puts "Declarator: name: #{@identifier} kind: #{@kind} global_name: #{@global_name} #{locale_str}"
715 (indent+1).times { print " " }
716 puts "type:"
717 @type.show_tree( indent + 2 )
718 if @initializer then
719 (indent+1).times { print " " }
720 puts "initializer:"
721 @initializer.show_tree( indent + 2 )
722 else
723 (indent+1).times { print " " }
724 puts "initializer: no"
725 end
726 (indent+1).times { print " " }
727 puts "size_is: #{@size_is.to_s}, count_is: #{@count_is.to_s}, string: #{@string.to_s} referenced: #{@b_referenced} "
728
729 end
730
731end
732
733# 関数パラメータの宣言
734class ParamDecl < BDNode
735
736# @declarator:: Decl: Token, ArrayType, FuncType, PtrType
737# @direction:: :IN, :OUT, :INOUT, :SEND, :RECEIVE
738# @size:: Expr (size_is 引数)
739# @count:: Expr (count_is 引数)
740# @max:: Expr (size_is の第二引数)
741# @b_nullable:: Bool : nullable
742# @string:: Expr or -1(if size not specified) (string 引数)
743# @allocator:: Signature of allocator
744# @b_ref:: bool : size_is, count_is, string_is 引数として参ç…
745§ã•ã‚Œã¦ã„ã‚‹
746#
747# 1. 関数型でないこと
748# 2. 2次å…
749ƒä»¥ä¸Šã®é…
750åˆ—であって最も内
751側以外の添数があること
752# 3. in, out, ..., size_is, count_is, ... の重複指定がないこと
753# 4. ポインタレベルが適切なこと
754
755 def initialize( declarator, specifier, param_specifier )
756 super()
757 @declarator = declarator
758 @declarator.set_owner self # Decl (ParamDecl)
759 @declarator.set_type( specifier )
760 @param_specifier = param_specifier
761 @b_ref = false
762 @b_nullable = false
763
764 if @declarator.is_function? then # (1)
765 cdl_error( "S2006 \'$1\' function" , get_name )
766 return
767 end
768
769 res = @declarator.check
770 if res then # (2)
771 cdl_error( "S2007 \'$1\' $2" , get_name, res )
772 return
773 end
774
775 @param_specifier.each { |i|
776 case i[0] # (3)
777 when :IN, :OUT, :INOUT, :SEND, :RECEIVE
778 if @direction == nil then
779 @direction = i[0]
780 elsif i[0] == @direction then
781 cdl_warning( "W3001 $1: duplicate" , i[0] )
782 next
783 else
784 cdl_error( "S2008 $1: inconsitent with previous one" , i[0] )
785 next
786 end
787
788 case i[0]
789 when :SEND, :RECEIVE
790 @allocator = Namespace.find( i[1] ) #1
791 if ! @allocator.instance_of?( Signature ) then
792 cdl_error( "S2009 $1: not found or not signature" , i[1] )
793 next
794 elsif ! @allocator.is_allocator? then
795 # cdl_error( "S2010 $1: not allocator signature" , i[1] )
796 end
797 end
798
799 when :SIZE_IS
800 if @size then
801 cdl_error( "S2011 size_is duplicate" )
802 else
803 @size = i[1]
804 end
805 when :COUNT_IS
806 if @count then
807 cdl_error( "S2012 count_is duplicate" )
808 else
809 @count = i[1]
810 end
811 when :STRING
812 if @string then
813 cdl_error( "S2013 string duplicate" )
814 elsif i[1] then
815 @string = i[1]
816 else
817 @string = -1
818 end
819 when :MAX_IS
820 # max_is は、内
821部的なもの bnf.y.rb 参ç…
822§
823 # size_is で重複チェックされる
824 @max = i[1]
825 when :NULLABLE
826 # if ! @declarator.get_type.kind_of?( PtrType ) then
827 # cdl_error( "S2026 '$1' nullable specified for non-pointer type", @declarator.get_name )
828 # else
829 @b_nullable = true
830 # end
831 end
832
833 }
834
835 if @direction == nil then
836 cdl_error( "S2014 No direction specified. [in/out/inout/send/receive]" )
837 end
838
839 if ( @direction == :OUT || @direction == :INOUT ) && @string == -1 then
840 cdl_warning( "W3002 $1: this string might cause buffer over run" , get_name )
841 end
842
843 # mikan ポインタのé…
844åˆ—(添数有)のレベルが0
845 ptr_level = @declarator.get_ptr_level
846
847 # p "ptr_level: #{@declarator.get_identifier} #{ptr_level}"
848 # p @declarator
849
850 #---- set req_level, min_level & max_level ----#
851 if !(@size||@count||@string) then # (4)
852 req_level = 1
853 elsif (@size||@count)&&@string then
854 req_level = 2
855 else
856 req_level = 1
857 end
858
859 if @direction == :RECEIVE then
860 req_level += 1
861 end
862 min_level = req_level
863 max_level = req_level
864
865 # IN without pointer specifier can be non-pointer type
866 if @direction == :IN && !(@size||@count||@string) then
867 min_level = 0
868 end
869
870 # if size_is specified and pointer refer to struct, max_level increase
871 if @size then
872 type = @declarator.get_type.get_original_type
873 while type.kind_of? PtrType
874 type = type.get_referto.get_original_type
875 end
876 if type.kind_of? StructType then
877 max_level += 1
878 end
879 end
880 #---- end req_level & max_level ----#
881
882 # p "req_level: #{req_level} ptr_level: #{ptr_level}"
883 #if ptr_level < req_level && ! ( @direction == :IN && req_level == 1 && ptr_level == 0) then
884 if ptr_level < min_level then
885 cdl_error( "S2014 $1 need pointer or more pointer" , @declarator.get_identifier )
886 elsif ptr_level > max_level then
887 # note: 構文解析段階で実行のため get_current 可
888 if Signature.get_current == nil || Signature.get_current.is_deviate? == false then
889 cdl_warning( "W3003 $1 pointer level mismatch" , @declarator.get_identifier )
890 end
891 end
892
893 type = @declarator.get_type
894 while type.kind_of?( DefinedType )
895 type = type.get_original_type
896 end
897
898 if ptr_level > 0 then
899 # size_is, count_is, string をセット
900 if @direction == :RECEIVE && ptr_level > 1 then
901 type.get_type.set_scs( @size, @count, @string, @max, @b_nullable )
902 else
903 type.set_scs( @size, @count, @string, @max, @b_nullable )
904 end
905
906#p ptr_level
907#type.show_tree 1
908
909 # ポインタが指しているå…
910ˆã®ãƒ‡ãƒ¼ã‚¿åž‹ã‚’å¾—ã‚‹
911 i = 0
912 t2 = type
913 while i < ptr_level
914 t2 = t2.get_referto
915 while t2.kind_of?( DefinedType )
916 t2 = t2.get_original_type
917 end
918 i += 1
919 end
920
921# p @declarator.get_name
922# t2.show_tree 1
923# p t2.is_const?
924
925 # const 修飾が適切かチェック
926 if @direction == :IN then
927 if ! t2.is_const? then
928 cdl_error( "S2015 '$1' must be const for \'in\' parameter $2" , get_name, type.class )
929 end
930 else
931 if t2.is_const? then
932 cdl_error( "S2016 '$1' can not be const for $2 parameter" , get_name, @direction )
933 end
934 end
935 else
936 # 非ポインタタイプ
937 if @size != nil || @count != nil || @string != nil || @max != nil || @b_nullable then
938 type.set_scs( @size, @count, @string, @max, @b_nullable )
939 end
940 end
941
942# if ptr_level > 0 && @direction == :IN then
943# if type.is_const != :CONST
944# end
945
946 # p self
947
948 end
949
950 def check_struct_tag kind
951 @declarator.get_type.check_struct_tag :PARAMETER
952 end
953
954 def get_name
955 @declarator.get_name
956 end
957
958 def get_size
959 @size
960 end
961
962 def get_count
963 @count
964 end
965
966 def get_string
967 @string
968 end
969
970 def get_max
971 @max
972 end
973
974 def clear_max
975 # p "clear_max: #{@declarator.get_name} #{@max.to_s}"
976 @max = nil
977 @declarator.get_type.clear_max
978 end
979
980 def is_nullable?
981 @b_nullable
982 end
983
984 def get_type
985 @declarator.get_type
986 end
987
988 def get_direction
989 @direction
990 end
991
992 def get_declarator
993 @declarator
994 end
995
996 def get_allocator
997 @allocator
998 end
999
1000 def referenced
1001 @b_ref = true
1002 end
1003
1004 def is_referenced?
1005 @b_ref
1006 end
1007
1008 #=== PPAllocator が必
1009要か
1010 # Transparent RPC の場合 in で size_is, count_is, string のいずれかが指定されている場合 oneway では PPAllocator が必
1011要
1012 # Transparent PC で oneway かどうかは、ここでは判断しないので別途判断が必
1013要
1014 # Opaque RPC の場合 size_is, count_is, string のいずれかが指定されている場合、PPAllocator が必
1015要
1016 def need_PPAllocator?( b_opaque = false )
1017 if ! b_opaque then
1018# if @direction == :IN && ( @size || @count || @string ) then
1019 if @direction == :IN && @declarator.get_type.get_original_type.kind_of?( PtrType ) then
1020 return true
1021 end
1022 else
1023 if (@direction == :IN || @direction == :OUT || @direction == :INOUT ) &&
1024 @declarator.get_type.get_original_type.kind_of?( PtrType ) then
1025 return true
1026 end
1027 end
1028 return false
1029 end
1030
1031 def show_tree( indent )
1032 indent.times { print " " }
1033 puts "ParamDecl: direction: #{@direction} #{locale_str}"
1034 @declarator.show_tree( indent + 1 )
1035 if @size then
1036 (indent+1).times { print " " }
1037 puts "size:"
1038 @size.show_tree( indent + 2 )
1039 end
1040 if @count then
1041 (indent+1).times { print " " }
1042 puts "count:"
1043 @count.show_tree( indent + 2 )
1044 end
1045 if @string then
1046 (indent+1).times { print " " }
1047 puts "string:"
1048 if @string == -1 then
1049 (indent+2).times { print " " }
1050 puts "size is not specified"
1051 else
1052 @string.show_tree( indent + 2 )
1053 end
1054 end
1055 if @allocator then
1056 (indent+1).times { print " " }
1057 puts "allocator: signature: #{@allocator.get_name}"
1058 end
1059 end
1060end
1061
1062# 関数パラメータリスト
1063class ParamList < BDNode
1064# @param_list:: NamedList : item: ParamDecl
1065
1066 def initialize( paramdecl )
1067 super()
1068 @param_list = NamedList.new( paramdecl, "parameter" )
1069 @param_list.get_items.each { |paramdecl|
1070 paramdecl.set_owner self # ParamDecl
1071 }
1072 end
1073
1074 def add_param( paramdecl )
1075 return if paramdecl == nil # 既にエラー
1076
1077 @param_list.add_item( paramdecl )
1078 paramdecl.set_owner self # ParamDecl
1079 end
1080
1081 def get_items
1082 @param_list.get_items
1083 end
1084
1085 #=== size_is, count_is, string の引数の式をチェック
1086 # 変数は前方参ç…
1087§å¯èƒ½ãªãŸã‚ã€é–¢æ•°é ­éƒ¨ã®æ§‹æ–‡è§£é‡ˆãŒçµ‚わった後にチェックする
1088 def check_param
1089 @param_list.get_items.each { |i|
1090 next if i == nil # i == nil : エラー時
1091
1092 if i.get_type.class == VoidType then
1093 # 単一の void 型はここにはこない
1094 cdl_error( "S2027 '$1' parameter cannot be void type", i.get_name )
1095 end
1096
1097 size = i.get_size # Expression
1098 if size then
1099 val = size.eval_const( @param_list )
1100 if val == nil then # 定数式でないか?
1101 # mikan 変数を含む式:単一の変数のみ OK
1102 type = size.get_type( @param_list )
1103 unless type.kind_of?( IntType ) then
1104 cdl_error( "S2017 size_is argument is not integer type" )
1105 else
1106 size.check_dir_for_param( @param_list, i.get_direction, "size_is" )
1107 end
1108 else
1109 if val != Integer( val ) then
1110 cdl_error( "S2018 \'$1\' size_is parameter not integer" , i.get_declarator.get_identifier )
1111 elsif val <= 0 then
1112 cdl_error( "S2019 \'$1\' size_is parameter negative or zero" , i.get_declarator.get_identifier )
1113 end
1114 end
1115 end
1116
1117 max = i.get_max
1118 if max then
1119 val2 = max.eval_const( @param_list )
1120 if val2 == nil then
1121 cdl_error( "S2028 '$1' max (size_is 2nd parameter) not constant", i.get_name )
1122 elsif val2 != Integer( val2 ) || val2 <= 0 then
1123 cdl_error( "S2029 '$1' max (size_is 2nd parameter) negative or zero, or not integer", i.get_name )
1124 end
1125 end
1126
1127 if val != nil && val2 != nil then
1128 if val < val2 then
1129 cdl_warning( "W3005 '$1' size_is always lower than max. max is ignored", i.get_name )
1130 i.clear_max
1131 else
1132 cdl_error( "S2030 '$1' both size_is and max are const. size_is larger than max", i.get_name )
1133 end
1134 end
1135
1136 count = i.get_count # Expression
1137 if count then
1138 val = count.eval_const( @param_list )
1139 if val == nil then # 定数式でないか?
1140 # mikan 変数を含む式:単一の変数のみ OK
1141 type = count.get_type( @param_list )
1142 unless type.kind_of?( IntType ) then
1143 cdl_error( "S2020 count_is argument is not integer type" )
1144 else
1145 count.check_dir_for_param( @param_list, i.get_direction, "count_is" )
1146 end
1147 else
1148 if val != Integer( val ) then
1149 cdl_error( "S2021 \'$1\' count_is parameter not integer" , i.get_declarator.get_identifier )
1150 elsif val <= 0 then
1151 cdl_error( "S2022 \'$1\' count_is parameter negative or zero" , i.get_declarator.get_identifier )
1152 end
1153 end
1154 end
1155
1156 string = i.get_string # Expression
1157 if string != -1 && string then
1158 val = string.eval_const( @param_list )
1159 if val == nil then # 定数式でないか?
1160 # mikan 変数を含む式:単一の変数のみ OK
1161 type = string.get_type( @param_list )
1162 unless type.kind_of?( IntType ) then
1163 cdl_error( "S2023 string argument is not integer type" )
1164 else
1165 string.check_dir_for_param( @param_list, i.get_direction, "string" )
1166 end
1167 else
1168 if val != Integer( val ) then
1169 cdl_error( "S2024 \'$1\' string parameter not integer" , i.get_declarator.get_identifier )
1170 elsif val <= 0 then
1171 cdl_error( "S2025 \'$1\' string parameter negative or zero" , i.get_declarator.get_identifier )
1172 end
1173 end
1174 end
1175 }
1176 end
1177
1178 def check_struct_tag kind
1179 @param_list.get_items.each{ |p|
1180 p.check_struct_tag kind
1181 }
1182 end
1183
1184 #=== Push Pop Allocator が必
1185要か?
1186 # Transparent RPC の場合 (oneway かつ) in のé…
1187åˆ—(size_is, count_is, string のいずれかで修飾)がある
1188 def need_PPAllocator?( b_opaque = false )
1189 @param_list.get_items.each { |i|
1190 if i.need_PPAllocator?( b_opaque ) then
1191 return true
1192 end
1193 }
1194 false
1195 end
1196
1197 def find( name )
1198 @param_list.get_item( name )
1199 end
1200
1201 #== ParamList# 文字列化
1202 #b_name:: Bool: パラメータ名を含める
1203 def to_str( b_name )
1204 str = "("
1205 delim = ""
1206 @param_list.get_items.each{ |paramdecl|
1207 decl = paramdecl.get_declarator
1208 str += delim + decl.get_type
1209 if b_name then
1210 str += " " + decl.get_name
1211 end
1212 str += decl.get_type_post
1213 delim = ", "
1214 }
1215 str += ")"
1216 end
1217
1218 def show_tree( indent )
1219 indent.times { print " " }
1220 puts "ParamList: #{locale_str}"
1221 @param_list.show_tree( indent + 1 )
1222 end
1223end
1224
1225#== CDL の文字列リテラルを扱うためのクラス
1226# CDL の文字列リテラルそのものではない
1227class CDLString
1228 # エスケープ文字を変換
1229 def self.escape str
1230 str = str.dup
1231 str.gsub!( /\\a/, "\x07" )
1232 str.gsub!( /\\b/, "\x08" )
1233 str.gsub!( /\\f/, "\x0c" )
1234 str.gsub!( /\\n/, "\x0a" )
1235 str.gsub!( /\\r/, "\x0d" )
1236 str.gsub!( /\\t/, "\x08" )
1237 str.gsub!( /\\v/, "\x0b" )
1238 str.gsub!( /(\\[Xx][0-9A-Fa-f]{1,2})/, '{printf \"\\1\"}' )
1239 str.gsub!( /(\\[0-7]{1,3})/, '{printf \"\\1\"}' )
1240 str.gsub!( /\\(.)/, "\\1" ) # mikan 未定義のエスケープシーケンスを変換してしまう (gcc V3.4.4 では警告が出される)
1241 return str
1242 end
1243
1244 #=== CDLString#前後の " を取り除く
1245 def self.remove_dquote str
1246 s = str.sub( /\A"/, "" )
1247 s.sub!( /"\z/, "" )
1248 return s
1249 end
1250end
1251
1252#== CDL の初期化子を扱うためのクラス
1253# CDL の初期化子そのものではない
1254class CDLInitializer
1255 #=== 初期化子のクローン
1256 # 初期化子は Expression, C_EXP, Array のいずれか
1257 def self.clone_for_composite( rhs, ct_name, cell_name, locale )
1258 if rhs.instance_of? C_EXP then
1259 # C_EXP の clone を作るとともに置換
1260 rhs = rhs.clone_for_composite( ct_name, cell_name, locale )
1261 elsif rhs.instance_of? Expression then
1262 rhs = rhs.clone_for_composite
1263 elsif rhs.instance_of? Array then
1264 rhs = clone_for_compoiste_array( rhs, ct_name, cell_name, locale )
1265 else
1266 raise "unknown rhs for join"
1267 end
1268 return rhs
1269 end
1270
1271 #=== 初期化子(é…
1272åˆ—)のクローン
1273 # 要素は clone_for_composite を持つものだけ
1274 def self.clone_for_compoiste_array( array, ct_name, cell_name, locale )
1275 # "compoiste.identifier" の場合 (CDL としては誤り)
1276 if array[0] == :COMPOSITE then
1277 return array.clone
1278 end
1279
1280 new_array = array.map{ |m|
1281 clone_for_composite( m, ct_name, cell_name, locale )
1282 }
1283 return new_array
1284 end
1285end
Note: See TracBrowser for help on using the repository browser.