source: asp3_tinet_ecnl_rx/trunk/asp3_dcre/tecsgen/tecslib/core/syntaxobj.rb@ 337

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

ASP3版ECNLを追加

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