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