[337] | 1 | # -*- coding: utf-8 -*-
|
---|
| 2 | #
|
---|
| 3 | # TECS Generator
|
---|
| 4 | # Generator for TOPPERS Embedded Component System
|
---|
| 5 | #
|
---|
[374] | 6 | # Copyright (C) 2008-2017 by TOPPERS Project
|
---|
[337] | 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 | #
|
---|
[359] | 37 | # $Id$
|
---|
[337] | 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 |
|
---|
| 51 | class 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
|
---|
| 108 | end
|
---|
| 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 | #
|
---|
| 140 | class 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
|
---|
| 168 | end
|
---|
| 169 |
|
---|
| 170 | #== Namespace 名を持つ BDNode
|
---|
| 171 | # Namespace(Region), Signature, Celltype, CompositeCelltype, Cell
|
---|
| 172 | class 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
|
---|
| 215 | end
|
---|
| 216 |
|
---|
| 217 | class 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 |
|
---|
| 328 | end
|
---|
| 329 |
|
---|
| 330 | class 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
|
---|
| 361 | end
|
---|
| 362 |
|
---|
| 363 | #== 関数頭部
|
---|
| 364 | # signature に登録される関数
|
---|
| 365 | class 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
|
---|
| 437 | end
|
---|
| 438 |
|
---|
| 439 | #=== 宣言
|
---|
| 440 | # @kind で示される各種の宣言
|
---|
| 441 | class 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 |
|
---|
[374] | 687 | #=== Decl# print_flowinfo
|
---|
| 688 | def print_flowinfo file
|
---|
| 689 | if @kind == :VAR then
|
---|
| 690 | file.write "#{@identifier} "
|
---|
| 691 | end
|
---|
| 692 | end
|
---|
| 693 |
|
---|
[337] | 694 | def show_tree( indent )
|
---|
| 695 | indent.times { print " " }
|
---|
| 696 | puts "Declarator: name: #{@identifier} kind: #{@kind} global_name: #{@global_name} #{locale_str}"
|
---|
| 697 | (indent+1).times { print " " }
|
---|
| 698 | puts "type:"
|
---|
| 699 | @type.show_tree( indent + 2 )
|
---|
| 700 | if @initializer then
|
---|
| 701 | (indent+1).times { print " " }
|
---|
| 702 | puts "initializer:"
|
---|
| 703 | @initializer.show_tree( indent + 2 )
|
---|
| 704 | else
|
---|
| 705 | (indent+1).times { print " " }
|
---|
| 706 | puts "initializer: no"
|
---|
| 707 | end
|
---|
| 708 | (indent+1).times { print " " }
|
---|
| 709 | puts "size_is: #{@size_is.to_s}, count_is: #{@count_is.to_s}, string: #{@string.to_s} referenced: #{@b_referenced} "
|
---|
| 710 |
|
---|
| 711 | end
|
---|
| 712 |
|
---|
| 713 | end
|
---|
| 714 |
|
---|
| 715 | # 関数パラメータの宣言
|
---|
| 716 | class ParamDecl < BDNode
|
---|
| 717 |
|
---|
| 718 | # @declarator:: Decl: Token, ArrayType, FuncType, PtrType
|
---|
| 719 | # @direction:: :IN, :OUT, :INOUT, :SEND, :RECEIVE
|
---|
| 720 | # @size:: Expr (size_is 引数)
|
---|
| 721 | # @count:: Expr (count_is 引数)
|
---|
| 722 | # @max:: Expr (size_is の第二引数)
|
---|
| 723 | # @b_nullable:: Bool : nullable
|
---|
| 724 | # @string:: Expr or -1(if size not specified) (string 引数)
|
---|
| 725 | # @allocator:: Signature of allocator
|
---|
| 726 | # @b_ref:: bool : size_is, count_is, string_is 引数として参照されている
|
---|
| 727 | #
|
---|
| 728 | # 1. 関数型でないこと
|
---|
| 729 | # 2. 2次元以上の配列であって最も内側以外の添数があること
|
---|
| 730 | # 3. in, out, ..., size_is, count_is, ... の重複指定がないこと
|
---|
| 731 | # 4. ポインタレベルが適切なこと
|
---|
| 732 |
|
---|
| 733 | def initialize( declarator, specifier, param_specifier )
|
---|
| 734 | super()
|
---|
| 735 | @declarator = declarator
|
---|
| 736 | @declarator.set_owner self # Decl (ParamDecl)
|
---|
| 737 | @declarator.set_type( specifier )
|
---|
| 738 | @param_specifier = param_specifier
|
---|
| 739 | @b_ref = false
|
---|
| 740 | @b_nullable = false
|
---|
| 741 |
|
---|
| 742 | if @declarator.is_function? then # (1)
|
---|
| 743 | cdl_error( "S2006 \'$1\' function" , get_name )
|
---|
| 744 | return
|
---|
| 745 | end
|
---|
| 746 |
|
---|
| 747 | res = @declarator.check
|
---|
| 748 | if res then # (2)
|
---|
| 749 | cdl_error( "S2007 \'$1\' $2" , get_name, res )
|
---|
| 750 | return
|
---|
| 751 | end
|
---|
| 752 |
|
---|
| 753 | @param_specifier.each { |i|
|
---|
| 754 | case i[0] # (3)
|
---|
| 755 | when :IN, :OUT, :INOUT, :SEND, :RECEIVE
|
---|
| 756 | if @direction == nil then
|
---|
| 757 | @direction = i[0]
|
---|
| 758 | elsif i[0] == @direction then
|
---|
| 759 | cdl_warning( "W3001 $1: duplicate" , i[0] )
|
---|
| 760 | next
|
---|
| 761 | else
|
---|
| 762 | cdl_error( "S2008 $1: inconsitent with previous one" , i[0] )
|
---|
| 763 | next
|
---|
| 764 | end
|
---|
| 765 |
|
---|
| 766 | case i[0]
|
---|
| 767 | when :SEND, :RECEIVE
|
---|
| 768 | @allocator = Namespace.find( i[1] ) #1
|
---|
| 769 | if ! @allocator.instance_of?( Signature ) then
|
---|
| 770 | cdl_error( "S2009 $1: not found or not signature" , i[1] )
|
---|
| 771 | next
|
---|
| 772 | elsif ! @allocator.is_allocator? then
|
---|
| 773 | # cdl_error( "S2010 $1: not allocator signature" , i[1] )
|
---|
| 774 | end
|
---|
| 775 | end
|
---|
| 776 |
|
---|
| 777 | when :SIZE_IS
|
---|
| 778 | if @size then
|
---|
| 779 | cdl_error( "S2011 size_is duplicate" )
|
---|
| 780 | else
|
---|
| 781 | @size = i[1]
|
---|
| 782 | end
|
---|
| 783 | when :COUNT_IS
|
---|
| 784 | if @count then
|
---|
| 785 | cdl_error( "S2012 count_is duplicate" )
|
---|
| 786 | else
|
---|
| 787 | @count = i[1]
|
---|
| 788 | end
|
---|
| 789 | when :STRING
|
---|
| 790 | if @string then
|
---|
| 791 | cdl_error( "S2013 string duplicate" )
|
---|
| 792 | elsif i[1] then
|
---|
| 793 | @string = i[1]
|
---|
| 794 | else
|
---|
| 795 | @string = -1
|
---|
| 796 | end
|
---|
| 797 | when :MAX_IS
|
---|
| 798 | # max_is は、内部的なもの bnf.y.rb 参照
|
---|
| 799 | # size_is で重複チェックされる
|
---|
| 800 | @max = i[1]
|
---|
| 801 | when :NULLABLE
|
---|
| 802 | # if ! @declarator.get_type.kind_of?( PtrType ) then
|
---|
| 803 | # cdl_error( "S2026 '$1' nullable specified for non-pointer type", @declarator.get_name )
|
---|
| 804 | # else
|
---|
| 805 | @b_nullable = true
|
---|
| 806 | # end
|
---|
| 807 | end
|
---|
| 808 |
|
---|
| 809 | }
|
---|
| 810 |
|
---|
| 811 | if @direction == nil then
|
---|
| 812 | cdl_error( "S2014 No direction specified. [in/out/inout/send/receive]" )
|
---|
| 813 | end
|
---|
| 814 |
|
---|
| 815 | if ( @direction == :OUT || @direction == :INOUT ) && @string == -1 then
|
---|
| 816 | cdl_warning( "W3002 $1: this string might cause buffer over run" , get_name )
|
---|
| 817 | end
|
---|
| 818 |
|
---|
| 819 | # mikan ポインタの配列(添数有)のレベルが0
|
---|
| 820 | ptr_level = @declarator.get_ptr_level
|
---|
| 821 |
|
---|
| 822 | # p "ptr_level: #{@declarator.get_identifier} #{ptr_level}"
|
---|
| 823 | # p @declarator
|
---|
| 824 |
|
---|
| 825 | #---- set req_level, min_level & max_level ----#
|
---|
| 826 | if !(@size||@count||@string) then # (4)
|
---|
| 827 | req_level = 1
|
---|
| 828 | elsif (@size||@count)&&@string then
|
---|
| 829 | req_level = 2
|
---|
| 830 | else
|
---|
| 831 | req_level = 1
|
---|
| 832 | end
|
---|
| 833 |
|
---|
| 834 | if @direction == :RECEIVE then
|
---|
| 835 | req_level += 1
|
---|
| 836 | end
|
---|
| 837 | min_level = req_level
|
---|
| 838 | max_level = req_level
|
---|
| 839 |
|
---|
| 840 | # IN without pointer specifier can be non-pointer type
|
---|
| 841 | if @direction == :IN && !(@size||@count||@string) then
|
---|
| 842 | min_level = 0
|
---|
| 843 | end
|
---|
| 844 |
|
---|
| 845 | # if size_is specified and pointer refer to struct, max_level increase
|
---|
| 846 | if @size then
|
---|
| 847 | type = @declarator.get_type.get_original_type
|
---|
| 848 | while type.kind_of? PtrType
|
---|
| 849 | type = type.get_referto.get_original_type
|
---|
| 850 | end
|
---|
| 851 | if type.kind_of? StructType then
|
---|
| 852 | max_level += 1
|
---|
| 853 | end
|
---|
| 854 | end
|
---|
| 855 | #---- end req_level & max_level ----#
|
---|
| 856 |
|
---|
| 857 | # p "req_level: #{req_level} ptr_level: #{ptr_level}"
|
---|
| 858 | #if ptr_level < req_level && ! ( @direction == :IN && req_level == 1 && ptr_level == 0) then
|
---|
| 859 | if ptr_level < min_level then
|
---|
| 860 | cdl_error( "S2014 $1 need pointer or more pointer" , @declarator.get_identifier )
|
---|
| 861 | elsif ptr_level > max_level then
|
---|
| 862 | # note: 構文解析段階で実行のため get_current 可
|
---|
| 863 | if Signature.get_current == nil || Signature.get_current.is_deviate? == false then
|
---|
| 864 | cdl_warning( "W3003 $1 pointer level mismatch" , @declarator.get_identifier )
|
---|
| 865 | end
|
---|
| 866 | end
|
---|
| 867 |
|
---|
| 868 | type = @declarator.get_type
|
---|
| 869 | while type.kind_of?( DefinedType )
|
---|
| 870 | type = type.get_original_type
|
---|
| 871 | end
|
---|
| 872 |
|
---|
| 873 | if ptr_level > 0 then
|
---|
| 874 | # size_is, count_is, string をセット
|
---|
| 875 | if @direction == :RECEIVE && ptr_level > 1 then
|
---|
| 876 | type.get_type.set_scs( @size, @count, @string, @max, @b_nullable )
|
---|
| 877 | else
|
---|
| 878 | type.set_scs( @size, @count, @string, @max, @b_nullable )
|
---|
| 879 | end
|
---|
| 880 |
|
---|
| 881 | #p ptr_level
|
---|
| 882 | #type.show_tree 1
|
---|
| 883 |
|
---|
| 884 | # ポインタが指している先のデータ型を得る
|
---|
| 885 | i = 0
|
---|
| 886 | t2 = type
|
---|
| 887 | while i < ptr_level
|
---|
| 888 | t2 = t2.get_referto
|
---|
| 889 | while t2.kind_of?( DefinedType )
|
---|
| 890 | t2 = t2.get_original_type
|
---|
| 891 | end
|
---|
| 892 | i += 1
|
---|
| 893 | end
|
---|
| 894 |
|
---|
| 895 | # p @declarator.get_name
|
---|
| 896 | # t2.show_tree 1
|
---|
| 897 | # p t2.is_const?
|
---|
| 898 |
|
---|
| 899 | # const 修飾が適切かチェック
|
---|
| 900 | if @direction == :IN then
|
---|
| 901 | if ! t2.is_const? then
|
---|
| 902 | cdl_error( "S2015 '$1' must be const for \'in\' parameter $2" , get_name, type.class )
|
---|
| 903 | end
|
---|
| 904 | else
|
---|
| 905 | if t2.is_const? then
|
---|
| 906 | cdl_error( "S2016 '$1' can not be const for $2 parameter" , get_name, @direction )
|
---|
| 907 | end
|
---|
| 908 | end
|
---|
| 909 | else
|
---|
| 910 | # 非ポインタタイプ
|
---|
| 911 | if @size != nil || @count != nil || @string != nil || @max != nil || @b_nullable then
|
---|
| 912 | type.set_scs( @size, @count, @string, @max, @b_nullable )
|
---|
| 913 | end
|
---|
| 914 | end
|
---|
| 915 |
|
---|
| 916 | # if ptr_level > 0 && @direction == :IN then
|
---|
| 917 | # if type.is_const != :CONST
|
---|
| 918 | # end
|
---|
| 919 |
|
---|
| 920 | # p self
|
---|
| 921 |
|
---|
| 922 | end
|
---|
| 923 |
|
---|
| 924 | def check_struct_tag kind
|
---|
| 925 | @declarator.get_type.check_struct_tag :PARAMETER
|
---|
| 926 | end
|
---|
| 927 |
|
---|
| 928 | def get_name
|
---|
| 929 | @declarator.get_name
|
---|
| 930 | end
|
---|
| 931 |
|
---|
| 932 | def get_size
|
---|
| 933 | @size
|
---|
| 934 | end
|
---|
| 935 |
|
---|
| 936 | def get_count
|
---|
| 937 | @count
|
---|
| 938 | end
|
---|
| 939 |
|
---|
| 940 | def get_string
|
---|
| 941 | @string
|
---|
| 942 | end
|
---|
| 943 |
|
---|
| 944 | def get_max
|
---|
| 945 | @max
|
---|
| 946 | end
|
---|
| 947 |
|
---|
| 948 | def clear_max
|
---|
| 949 | # p "clear_max: #{@declarator.get_name} #{@max.to_s}"
|
---|
| 950 | @max = nil
|
---|
| 951 | @declarator.get_type.clear_max
|
---|
| 952 | end
|
---|
| 953 |
|
---|
| 954 | def is_nullable?
|
---|
| 955 | @b_nullable
|
---|
| 956 | end
|
---|
| 957 |
|
---|
| 958 | def get_type
|
---|
| 959 | @declarator.get_type
|
---|
| 960 | end
|
---|
| 961 |
|
---|
| 962 | def get_direction
|
---|
| 963 | @direction
|
---|
| 964 | end
|
---|
| 965 |
|
---|
| 966 | def get_declarator
|
---|
| 967 | @declarator
|
---|
| 968 | end
|
---|
| 969 |
|
---|
| 970 | def get_allocator
|
---|
| 971 | @allocator
|
---|
| 972 | end
|
---|
| 973 |
|
---|
| 974 | def referenced
|
---|
| 975 | @b_ref = true
|
---|
| 976 | end
|
---|
| 977 |
|
---|
| 978 | def is_referenced?
|
---|
| 979 | @b_ref
|
---|
| 980 | end
|
---|
| 981 |
|
---|
| 982 | #=== PPAllocator が必要か
|
---|
| 983 | # Transparent RPC の場合 in で size_is, count_is, string のいずれかが指定されている場合 oneway では PPAllocator が必要
|
---|
| 984 | # Transparent PC で oneway かどうかは、ここでは判断しないので別途判断が必要
|
---|
| 985 | # Opaque RPC の場合 size_is, count_is, string のいずれかが指定されている場合、PPAllocator が必要
|
---|
| 986 | def need_PPAllocator?( b_opaque = false )
|
---|
| 987 | if ! b_opaque then
|
---|
| 988 | # if @direction == :IN && ( @size || @count || @string ) then
|
---|
| 989 | if @direction == :IN && @declarator.get_type.get_original_type.kind_of?( PtrType ) then
|
---|
| 990 | return true
|
---|
| 991 | end
|
---|
| 992 | else
|
---|
| 993 | if (@direction == :IN || @direction == :OUT || @direction == :INOUT ) &&
|
---|
| 994 | @declarator.get_type.get_original_type.kind_of?( PtrType ) then
|
---|
| 995 | return true
|
---|
| 996 | end
|
---|
| 997 | end
|
---|
| 998 | return false
|
---|
| 999 | end
|
---|
| 1000 |
|
---|
| 1001 | def show_tree( indent )
|
---|
| 1002 | indent.times { print " " }
|
---|
| 1003 | puts "ParamDecl: direction: #{@direction} #{locale_str}"
|
---|
| 1004 | @declarator.show_tree( indent + 1 )
|
---|
| 1005 | if @size then
|
---|
| 1006 | (indent+1).times { print " " }
|
---|
| 1007 | puts "size:"
|
---|
| 1008 | @size.show_tree( indent + 2 )
|
---|
| 1009 | end
|
---|
| 1010 | if @count then
|
---|
| 1011 | (indent+1).times { print " " }
|
---|
| 1012 | puts "count:"
|
---|
| 1013 | @count.show_tree( indent + 2 )
|
---|
| 1014 | end
|
---|
| 1015 | if @string then
|
---|
| 1016 | (indent+1).times { print " " }
|
---|
| 1017 | puts "string:"
|
---|
| 1018 | if @string == -1 then
|
---|
| 1019 | (indent+2).times { print " " }
|
---|
| 1020 | puts "size is not specified"
|
---|
| 1021 | else
|
---|
| 1022 | @string.show_tree( indent + 2 )
|
---|
| 1023 | end
|
---|
| 1024 | end
|
---|
| 1025 | if @allocator then
|
---|
| 1026 | (indent+1).times { print " " }
|
---|
| 1027 | puts "allocator: signature: #{@allocator.get_name}"
|
---|
| 1028 | end
|
---|
| 1029 | end
|
---|
| 1030 | end
|
---|
| 1031 |
|
---|
| 1032 | # 関数パラメータリスト
|
---|
| 1033 | class ParamList < BDNode
|
---|
| 1034 | # @param_list:: NamedList : item: ParamDecl
|
---|
| 1035 |
|
---|
| 1036 | def initialize( paramdecl )
|
---|
| 1037 | super()
|
---|
| 1038 | @param_list = NamedList.new( paramdecl, "parameter" )
|
---|
| 1039 | @param_list.get_items.each { |paramdecl|
|
---|
| 1040 | paramdecl.set_owner self # ParamDecl
|
---|
| 1041 | }
|
---|
| 1042 | end
|
---|
| 1043 |
|
---|
| 1044 | def add_param( paramdecl )
|
---|
| 1045 | return if paramdecl == nil # 既にエラー
|
---|
| 1046 |
|
---|
| 1047 | @param_list.add_item( paramdecl )
|
---|
| 1048 | paramdecl.set_owner self # ParamDecl
|
---|
| 1049 | end
|
---|
| 1050 |
|
---|
| 1051 | def get_items
|
---|
| 1052 | @param_list.get_items
|
---|
| 1053 | end
|
---|
| 1054 |
|
---|
| 1055 | #=== size_is, count_is, string の引数の式をチェック
|
---|
| 1056 | # 変数は前方参照可能なため、関数頭部の構文解釈が終わった後にチェックする
|
---|
| 1057 | def check_param
|
---|
| 1058 | @param_list.get_items.each { |i|
|
---|
| 1059 | next if i == nil # i == nil : エラー時
|
---|
| 1060 |
|
---|
| 1061 | if i.get_type.class == VoidType then
|
---|
| 1062 | # 単一の void 型はここにはこない
|
---|
| 1063 | cdl_error( "S2027 '$1' parameter cannot be void type", i.get_name )
|
---|
| 1064 | end
|
---|
| 1065 |
|
---|
| 1066 | size = i.get_size # Expression
|
---|
| 1067 | if size then
|
---|
| 1068 | val = size.eval_const( @param_list )
|
---|
| 1069 | if val == nil then # 定数式でないか?
|
---|
| 1070 | # mikan 変数を含む式:単一の変数のみ OK
|
---|
| 1071 | type = size.get_type( @param_list )
|
---|
| 1072 | unless type.kind_of?( IntType ) then
|
---|
| 1073 | cdl_error( "S2017 size_is argument is not integer type" )
|
---|
| 1074 | else
|
---|
| 1075 | size.check_dir_for_param( @param_list, i.get_direction, "size_is" )
|
---|
| 1076 | end
|
---|
| 1077 | else
|
---|
| 1078 | if val != Integer( val ) then
|
---|
| 1079 | cdl_error( "S2018 \'$1\' size_is parameter not integer" , i.get_declarator.get_identifier )
|
---|
| 1080 | elsif val <= 0 then
|
---|
| 1081 | cdl_error( "S2019 \'$1\' size_is parameter negative or zero" , i.get_declarator.get_identifier )
|
---|
| 1082 | end
|
---|
| 1083 | end
|
---|
| 1084 | end
|
---|
| 1085 |
|
---|
| 1086 | max = i.get_max
|
---|
| 1087 | if max then
|
---|
| 1088 | val2 = max.eval_const( @param_list )
|
---|
| 1089 | if val2 == nil then
|
---|
| 1090 | cdl_error( "S2028 '$1' max (size_is 2nd parameter) not constant", i.get_name )
|
---|
| 1091 | elsif val2 != Integer( val2 ) || val2 <= 0 then
|
---|
| 1092 | cdl_error( "S2029 '$1' max (size_is 2nd parameter) negative or zero, or not integer", i.get_name )
|
---|
| 1093 | end
|
---|
| 1094 | end
|
---|
| 1095 |
|
---|
| 1096 | if val != nil && val2 != nil then
|
---|
| 1097 | if val < val2 then
|
---|
| 1098 | cdl_warning( "W3005 '$1' size_is always lower than max. max is ignored", i.get_name )
|
---|
| 1099 | i.clear_max
|
---|
| 1100 | else
|
---|
| 1101 | cdl_error( "S2030 '$1' both size_is and max are const. size_is larger than max", i.get_name )
|
---|
| 1102 | end
|
---|
| 1103 | end
|
---|
| 1104 |
|
---|
| 1105 | count = i.get_count # Expression
|
---|
| 1106 | if count then
|
---|
| 1107 | val = count.eval_const( @param_list )
|
---|
| 1108 | if val == nil then # 定数式でないか?
|
---|
| 1109 | # mikan 変数を含む式:単一の変数のみ OK
|
---|
| 1110 | type = count.get_type( @param_list )
|
---|
| 1111 | unless type.kind_of?( IntType ) then
|
---|
| 1112 | cdl_error( "S2020 count_is argument is not integer type" )
|
---|
| 1113 | else
|
---|
| 1114 | count.check_dir_for_param( @param_list, i.get_direction, "count_is" )
|
---|
| 1115 | end
|
---|
| 1116 | else
|
---|
| 1117 | if val != Integer( val ) then
|
---|
| 1118 | cdl_error( "S2021 \'$1\' count_is parameter not integer" , i.get_declarator.get_identifier )
|
---|
| 1119 | elsif val <= 0 then
|
---|
| 1120 | cdl_error( "S2022 \'$1\' count_is parameter negative or zero" , i.get_declarator.get_identifier )
|
---|
| 1121 | end
|
---|
| 1122 | end
|
---|
| 1123 | end
|
---|
| 1124 |
|
---|
| 1125 | string = i.get_string # Expression
|
---|
| 1126 | if string != -1 && string then
|
---|
| 1127 | val = string.eval_const( @param_list )
|
---|
| 1128 | if val == nil then # 定数式でないか?
|
---|
| 1129 | # mikan 変数を含む式:単一の変数のみ OK
|
---|
| 1130 | type = string.get_type( @param_list )
|
---|
| 1131 | unless type.kind_of?( IntType ) then
|
---|
| 1132 | cdl_error( "S2023 string argument is not integer type" )
|
---|
| 1133 | else
|
---|
| 1134 | string.check_dir_for_param( @param_list, i.get_direction, "string" )
|
---|
| 1135 | end
|
---|
| 1136 | else
|
---|
| 1137 | if val != Integer( val ) then
|
---|
| 1138 | cdl_error( "S2024 \'$1\' string parameter not integer" , i.get_declarator.get_identifier )
|
---|
| 1139 | elsif val <= 0 then
|
---|
| 1140 | cdl_error( "S2025 \'$1\' string parameter negative or zero" , i.get_declarator.get_identifier )
|
---|
| 1141 | end
|
---|
| 1142 | end
|
---|
| 1143 | end
|
---|
| 1144 | }
|
---|
| 1145 | end
|
---|
| 1146 |
|
---|
| 1147 | def check_struct_tag kind
|
---|
| 1148 | @param_list.get_items.each{ |p|
|
---|
| 1149 | p.check_struct_tag kind
|
---|
| 1150 | }
|
---|
| 1151 | end
|
---|
| 1152 |
|
---|
| 1153 | #=== Push Pop Allocator が必要か?
|
---|
| 1154 | # Transparent RPC の場合 (oneway かつ) in の配列(size_is, count_is, string のいずれかで修飾)がある
|
---|
| 1155 | def need_PPAllocator?( b_opaque = false )
|
---|
| 1156 | @param_list.get_items.each { |i|
|
---|
| 1157 | if i.need_PPAllocator?( b_opaque ) then
|
---|
| 1158 | return true
|
---|
| 1159 | end
|
---|
| 1160 | }
|
---|
| 1161 | false
|
---|
| 1162 | end
|
---|
| 1163 |
|
---|
| 1164 | def find( name )
|
---|
| 1165 | @param_list.get_item( name )
|
---|
| 1166 | end
|
---|
| 1167 |
|
---|
| 1168 | #== ParamList# 文字列化
|
---|
| 1169 | #b_name:: Bool: パラメータ名を含める
|
---|
| 1170 | def to_str( b_name )
|
---|
| 1171 | str = "("
|
---|
| 1172 | delim = ""
|
---|
| 1173 | @param_list.get_items.each{ |paramdecl|
|
---|
| 1174 | decl = paramdecl.get_declarator
|
---|
| 1175 | str += delim + decl.get_type
|
---|
| 1176 | if b_name then
|
---|
| 1177 | str += " " + decl.get_name
|
---|
| 1178 | end
|
---|
| 1179 | str += decl.get_type_post
|
---|
| 1180 | delim = ", "
|
---|
| 1181 | }
|
---|
| 1182 | str += ")"
|
---|
| 1183 | end
|
---|
| 1184 |
|
---|
| 1185 | def show_tree( indent )
|
---|
| 1186 | indent.times { print " " }
|
---|
| 1187 | puts "ParamList: #{locale_str}"
|
---|
| 1188 | @param_list.show_tree( indent + 1 )
|
---|
| 1189 | end
|
---|
| 1190 | end
|
---|
| 1191 |
|
---|
| 1192 | #== CDL の文字列リテラルを扱うためのクラス
|
---|
| 1193 | # CDL の文字列リテラルそのものではない
|
---|
| 1194 | class CDLString
|
---|
| 1195 | # エスケープ文字を変換
|
---|
| 1196 | def self.escape str
|
---|
| 1197 | str = str.dup
|
---|
| 1198 | str.gsub!( /\\a/, "\x07" )
|
---|
| 1199 | str.gsub!( /\\b/, "\x08" )
|
---|
| 1200 | str.gsub!( /\\f/, "\x0c" )
|
---|
| 1201 | str.gsub!( /\\n/, "\x0a" )
|
---|
| 1202 | str.gsub!( /\\r/, "\x0d" )
|
---|
| 1203 | str.gsub!( /\\t/, "\x08" )
|
---|
| 1204 | str.gsub!( /\\v/, "\x0b" )
|
---|
| 1205 | str.gsub!( /(\\[Xx][0-9A-Fa-f]{1,2})/, '{printf \"\\1\"}' )
|
---|
| 1206 | str.gsub!( /(\\[0-7]{1,3})/, '{printf \"\\1\"}' )
|
---|
| 1207 | str.gsub!( /\\(.)/, "\\1" ) # mikan 未定義のエスケープシーケンスを変換してしまう (gcc V3.4.4 では警告が出される)
|
---|
| 1208 | return str
|
---|
| 1209 | end
|
---|
| 1210 |
|
---|
| 1211 | #=== CDLString#前後の " を取り除く
|
---|
| 1212 | def self.remove_dquote str
|
---|
| 1213 | s = str.sub( /\A"/, "" )
|
---|
| 1214 | s.sub!( /"\z/, "" )
|
---|
| 1215 | return s
|
---|
| 1216 | end
|
---|
| 1217 | end
|
---|
| 1218 |
|
---|
| 1219 | #== CDL の初期化子を扱うためのクラス
|
---|
| 1220 | # CDL の初期化子そのものではない
|
---|
| 1221 | class CDLInitializer
|
---|
| 1222 | #=== 初期化子のクローン
|
---|
| 1223 | # 初期化子は Expression, C_EXP, Array のいずれか
|
---|
| 1224 | def self.clone_for_composite( rhs, ct_name, cell_name, locale )
|
---|
| 1225 | if rhs.instance_of? C_EXP then
|
---|
| 1226 | # C_EXP の clone を作るとともに置換
|
---|
| 1227 | rhs = rhs.clone_for_composite( ct_name, cell_name, locale )
|
---|
| 1228 | elsif rhs.instance_of? Expression then
|
---|
| 1229 | rhs = rhs.clone_for_composite
|
---|
| 1230 | elsif rhs.instance_of? Array then
|
---|
| 1231 | rhs = clone_for_compoiste_array( rhs, ct_name, cell_name, locale )
|
---|
| 1232 | else
|
---|
| 1233 | raise "unknown rhs for join"
|
---|
| 1234 | end
|
---|
| 1235 | return rhs
|
---|
| 1236 | end
|
---|
| 1237 |
|
---|
| 1238 | #=== 初期化子(配列)のクローン
|
---|
| 1239 | # 要素は clone_for_composite を持つものだけ
|
---|
| 1240 | def self.clone_for_compoiste_array( array, ct_name, cell_name, locale )
|
---|
| 1241 | # "compoiste.identifier" の場合 (CDL としては誤り)
|
---|
| 1242 | if array[0] == :COMPOSITE then
|
---|
| 1243 | return array.clone
|
---|
| 1244 | end
|
---|
| 1245 |
|
---|
| 1246 | new_array = array.map{ |m|
|
---|
| 1247 | clone_for_composite( m, ct_name, cell_name, locale )
|
---|
| 1248 | }
|
---|
| 1249 | return new_array
|
---|
| 1250 | end
|
---|
| 1251 | end
|
---|