source: azure_iot_hub/trunk/asp3_dcre/tecsgen/tecslib/core/types.rb@ 389

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

ビルドが通るよう更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-ruby;charset=UTF-8
File size: 43.3 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# TECS Generator
4# Generator for TOPPERS Embedded Component System
5#
6# Copyright (C) 2008-2017 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#= HasType: @type を内部に持つ型のためのモジュール
41# @b_cloned::Bool : true if @type is cloned
42#
43# このモジュールは DefinedType, PtrType, ArrayType に include される
44# 本当は typedef された時の Decl の要素のみ clone すればよいのだが、get_type, get_original_type で
45# 取り出されたとき、set_scs, set_qualifier されたときに無条件で clone する (無駄にメモリを使用する)
46# ただし、clone するのは一回のみである (二回 clone すると別の型を参照してしまう)
47#
48# initialize で clone しても、共有されているときに clone されない
49#
50module HasType
51 def initHasType
52 @b_cloned = false
53 end
54
55 #=== HasType# @type をクローンする
56 def clone_type
57# if @b_cloned == false then
58 @type = @type.clone
59 @b_cloned = true
60# end
61 end
62end
63
64class Type < Node
65# @b_const : bool
66# @b_volatile : bool
67
68 def initialize
69 super
70 end
71
72 def set_qualifier( qualifier )
73 case qualifier
74 when :CONST
75# if @b_const then
76# cdl_error( "T1001 const duplicate" )
77# end
78 @b_const = true
79 when :VOLATILE
80# if @b_volatile then
81# cdl_error( "T1002 volatile duplicate" )
82# end
83 @b_volatile = true
84 else
85 raise "Unknown qualifier #{qualifier}"
86 end
87 end
88
89 def is_const?
90 if @b_const then
91 return true
92 else
93 return false
94 end
95 end
96
97 def is_volatile?
98 if @b_volatile then
99 return true
100 else
101 return false
102 end
103 end
104
105 def is_void?
106 if self.kind_of? DefinedType then
107 return @type.is_void?
108 elsif self.kind_of? VoidType then
109 return true
110 else
111 return false
112 end
113 end
114
115 #=== size_is, count_is, string を設定
116 # 派生クラスでオーバーライドする(デフォルトではエラー)
117 def set_scs( size, count, string, max = nil, b_nullable = false )
118 str = ""
119 delim = ""
120 if size then
121 str = "size_is"
122 delim = ", "
123 end
124 if count then
125 str = "#{str}#{delim}count_is"
126 delim = ", "
127 end
128 if string then
129 str = "#{str}#{delim}string"
130 delim = ", "
131 end
132 if b_nullable then
133 str = "#{str}#{delim}nullable"
134 delim = ", "
135 end
136 cdl_error( "T1003 $1: unsuitable specifier for $2" , str, self.class )
137 end
138
139 def clear_max
140 raise "clear_max called: #{self.class}"
141 end
142
143 def get_type_str
144 str = ""
145 if @b_const then
146 str = "#{str}const "
147 end
148 if @b_volatile then
149 str = "#{str}volatile "
150 end
151 return str
152 end
153
154 #=== 型をチェック
155 # 正当な型定義かどうか、チェックする
156 def check
157 # 型に誤りがあれば、エラー文字列を返す
158 end
159
160 #=== struct の tag をチェック
161 # 正当な型定義かどうか、チェックする
162 #kind:: Decl の @kind を参照
163 def check_struct_tag kind
164 # tag が存在しなければエラーを出力する
165 # 配列型では、要素の型を再帰的にチェック
166 # ポインタ型では、指す先の tag チェックはしない
167 # 関数型ではパラメータリストのすべてについて行う
168 end
169
170 #=== 初期化可能かチェック
171 # attribute など初期化可能かチェックする(型に対し正当な初期化子が与えられているか)
172 #ident:: string 被代入変数命
173 #initialize:: Expression, Array of initializer or C_EXP
174 # 代入値、C_EXP が与えられるのは IntType の場合のみ
175 #kind:: symbol (:ATTRIBUTE, :VAR, :CONSTNAT )
176 #attribute:: NameList kind == :VAR のとき参照できる attribute
177 #
178 # locale を第一引数として取るのは、以下の理由による。
179 # このメソッドは、変数への代入が行われる「行」に対して呼び出されるが、
180 # Type クラスのインスタンスは、変数が定義された「行」を記憶している。
181 #
182 # STAGE: S
183 def check_init( locale, ident, initializer, kind, attribute = nil )
184 #
185 end
186
187 #=== const_val を指定の型にキャストする
188 # 派生クラスでオーバーライドしていないとエラー
189 def cast( const_val )
190 cdl_error( "T1004 cannot cast to $1" , self.class )
191 end
192
193 #=== 型が一致するかのチェック
194 # 型名の字面でチェック.
195 # typedef された型も字面で一致を見るため、元の型が同じでも型名が異なれば不一致となる
196 def equal? type2
197 return ( get_type_str == type2.get_type_str ) && ( get_type_str_post == type2.get_type_str_post )
198 end
199
200 #=== bit size を得る
201 # IntType, FloatType 以外は0
202 def get_bit_size
203 return 0
204 end
205
206 #=== 元の型を得る
207 # typedef された型の場合、その元の型を返す.
208 # それ以外は、自分自身を返す.
209 # (DefinedType では本メソッドがオーバーライドされる)
210 def get_original_type
211 return self
212 end
213
214 #=== 内部にポインタ型を持つ
215 # ポインタ型、またはポインタ型メンバを持つ構造体、または要素がポインタ型を持つ配列
216 def has_pointer?
217 false
218 end
219
220 #=== size_is, count_is, string 指定されたポインタを持つか
221 # size_is, count_is, string 指定されたポインタ型、またはそれをメンバに持つ構造体、またはそれをを要素に持つ配列
222 def has_sized_pointer?
223 false
224 end
225
226 #=== 長さ指定のない string を持つ
227 # なさ指定のない string 指定されたポインタ型、またはそれをメンバに持つ構造体、またはそれを要素に持つ配列
228 def has_unsized_string?
229 false
230 end
231
232 def show_tree indent
233 indent.times { print " " }
234 puts "const=#{@b_const} volatile=#{@b_volatile} #{locale_str}"
235 indent.times { print " " }
236 puts "has_pointer=#{has_pointer?} has_sized_pointer=#{has_sized_pointer?} has_unsized_string=#{has_unsized_string?}"
237 end
238end
239
240class DefinedType < Type
241# @type_name::string
242# @typedef::Typedef
243# @type:: kind_of Type
244
245 include HasType
246
247 def initialize( type_name )
248 super()
249 @type_name = type_name
250
251 # mikan type_name が path になっていないため暫定
252 @typedef = Namespace.find( [ type_name ] ) #1
253
254# if @type.class != Typedef then
255# raise NotTypedef
256 # end
257 if @typedef == nil then
258 cdl_error( "T1005 \'$1\' not defined" , type_name )
259 elsif @typedef.class != Typedef then
260 cdl_error( "T1006 \'$1\' not type name. expecting type name here" , type_name )
261 end
262 @type = @typedef.get_declarator.get_type
263 initHasType
264 end
265
266 def get_type
267 clone_type
268 return @type
269 end
270
271 def get_type_str
272 "#{super}#{@type_name}"
273 end
274
275 def get_type_str_post
276 ""
277 end
278
279 def get_size
280 return @type.get_size
281 end
282
283 def is_nullable?
284 return @type.is_nullable?
285 end
286
287 #=== qualifier(const, volatile) の設定
288 def set_qualifier( qualifier )
289 clone_type
290 @type.set_qualifier( qualifier )
291 super
292 end
293
294 def set_scs( size, count, string, max = nil, b_nullable = false )
295 clone_type
296 @type.set_scs( size, count, string, max, b_nullable )
297 end
298
299 def clear_max
300 @type.clear_max
301 end
302
303 def get_original_type
304 clone_type
305 return @type.get_original_type
306 end
307
308 def check # 意味的誤りがあれば、文字列を返す
309 nil # typedef の段階で意味チェックされている
310 end
311
312 def check_init( locale, ident, initializer, kind, attribute = nil )
313 get_type.check_init( locale, ident, initializer, kind, attribute )
314 end
315
316 #=== 内部にポインタ型を持つ
317 # ポインタ型、またはポインタ型メンバを持つ構造体、または要素がポインタ型を持つ配列
318 def has_pointer?
319 @type.has_pointer?
320 end
321
322 #=== size_is, count_is, string 指定されたポインタを持つか
323 # size_is, count_is, string 指定されたポインタ型、またはそれをメンバに持つ構造体、またはそれをを要素に持つ配列
324 def has_sized_pointer?
325 @type.has_sized_pointer?
326 end
327
328 #=== 長さ指定のない string を持つ
329 # なさ指定のない string 指定されたポインタ型、またはそれをメンバに持つ構造体、またはそれを要素に持つ配列
330 def has_unsized_string?
331 @type.has_unsized_string?
332 end
333
334 def show_tree( indent )
335 indent.times { print " " }
336 if @typedef == nil then
337 puts "DefinedType: #{@type_name} is missing, const=#{@b_const} volatile=#{@b_volatile} #{locale_str}"
338 else
339 puts "DefinedType: #{@type_name}, const=#{@b_const} volatile=#{@b_volatile}"
340 end
341 super( indent + 1 )
342 @typedef.show_tree( indent + 1 )
343 @type.show_tree( indent + 1 )
344 end
345end
346
347class VoidType < Type
348
349 def check # 意味的誤りがあれば、文字列を返す
350 nil
351 end
352
353 def check_init( locale, ident, initializer, kind, attribute = nil )
354 cdl_error2( locale, "T1007 $1: void type variable cannot have initializer" , ident )
355 end
356
357 def get_type_str
358 "#{super}void"
359 end
360
361 def get_type_str_post
362 ""
363 end
364
365 def show_tree( indent )
366 indent.times { print " " }
367 puts "VoidType #{locale_str}"
368 super( indent + 1 )
369 end
370end
371
372class BoolType < Type
373
374 def check # 意味的誤りがあれば、文字列を返す
375 nil
376 end
377
378 def get_type_str
379 "#{super}bool_t"
380 end
381
382 def get_type_str_post
383 ""
384 end
385
386 def show_tree( indent )
387 indent.times { print " " }
388 puts "BoolType #{locale_str}"
389 super( indent + 1 )
390 end
391end
392
393class IntType < Type
394# @bit_size:: -11: char, -1: char_t, -2: short, -3: int, -4: long, -5: long long
395# 8, 16, 32, 64, 128
396# @sign:: :SIGNED, :UNSIGNED, nil
397
398 def initialize( bit_size )
399 super()
400 @bit_size = bit_size
401 @sign = nil
402 end
403
404 def set_sign( sign, b_uint = false )
405 if @sign then
406 if @sign != sign then
407 cdl_error( "T1008 ambigous signed or unsigned" )
408 end
409 elsif b_uint == false && @bit_size > 0 then
410 if sign == :SIGNED then
411 cdl_warning( "W2001 signed int$1_t: obsolete. use int$2_t" , @bit_size, @bit_size )
412 else
413 cdl_warning( "W2002 unsinged int$1_t: obsolete. use uint$2_t" , @bit_size, @bit_size )
414 end
415 end
416
417 @sign = sign
418
419 if @sign != :SIGNED && @sign != :UNSIGNED then
420 raise "set_sign: unknown sign: #{@sign}"
421 end
422 end
423
424 def check # 意味的誤りがあれば、文字列を返す
425 nil
426 end
427
428 def check_init( locale, ident, initializer, kind, attribute = nil )
429 val = initializer # C_EXP, Array
430 if val.instance_of?( Expression ) then
431 val = val.eval_const2( nil, attribute )
432 # 評価の結果 C_EXP や Array となる可能性がある
433 end
434
435 if val.instance_of? Token then # StringVal 導入により、もはや Token は来ないはず
436 # val が Token の場合 == の右辺が String だとエラーを起こす (#198)
437 cdl_error2( locale, "T1009 $1: $2: not integer" , ident, val )
438 return
439 elsif val.is_a? C_EXP then
440 # #192 var が attribute を参照し、attribute の右辺が C_EXP の場合
441 # const の右辺が C_EXP の場合も
442 return
443 elsif val.kind_of? FloatVal then
444 cdl_error2( locale, "T1011 $1: need cast to assign float to integer" , ident )
445 return
446 elsif val.instance_of? Array then
447 cdl_error2( locale, "T1017 $1: unsuitable initializer for scalar type" , ident )
448 return
449 elsif val == nil then
450 cdl_error2( locale, "T1010 $1: initializer is not constant" , ident )
451 return
452 end
453
454 if ! val.kind_of? IntegerVal then
455 cdl_error2( locale, "T1012 $1: $2: not integer" , ident, val )
456 return
457 end
458
459 val = val.to_i
460 max = get_max
461 min = get_min
462 dbgPrint "sign=#{@sign} ident=#{ident} val=#{val} max=#{max} min=#{min}\n"
463
464 if max != nil then
465 if val > max then
466 if @sign == :SIGNED || @sign == nil then
467 cdl_error2( locale, "T1013 $1: too large (max=$2)" , ident, max )
468 else
469 cdl_error2( locale, "T1016 $1: too large (max=$2)" , ident, max )
470 end
471 end
472 end
473
474 if min != nil then
475 if val < min
476 if @sign == :SIGNED || @sign == nil then
477 cdl_error2( locale, "T1014 $1: too large negative value (min=$2)" , ident, min )
478 else
479 cdl_error2( locale, "T1015 $1: negative value for unsigned" , ident )
480 end
481 end
482 end
483 end
484
485 #=== IntType# 最大値、最小値をチェックしてクリップする
486 # キャスト演算を行う
487 #in_val:: IntegerVal, FloatVal: この型にキャストする値
488 #from_type:: Symbol: :IntType, :FloatType IntType の場合はビット数でクリップ、FloatType の場合は最大値でクリップ
489 def check_and_clip( in_val, from_type = :IntType )
490 bit_size = get_bit_size
491 if bit_size == -1 then
492 bit_size = 8
493 end
494 val = in_val.to_i
495 if get_max && val > get_max then
496 if from_type == :IntType then
497 rval = ((1 << bit_size)-1) & val # bit 数でクリップ
498 else
499 rval = get_max # 最大値でクリップ (FloatType)
500 end
501 cdl_warning( "W2003 $1: too large to cast to $2, clipped($3)" , in_val, get_type_str, rval )
502 elsif get_min && val < get_min then
503 if from_type == :IntType then
504 rval = ((1 << bit_size)-1) & val
505 else
506 rval = get_min
507 end
508 if @sign == :SIGNED || @sign == nil then
509 cdl_warning( "W2004 $1: too small to cast to $2, clipped($3)" , in_val, get_type_str, rval )
510 else # @sign == :UNSIGNED || @sign == nil (char の場合)
511 cdl_warning( "W2005 $1: negative value for unsigned: convert to $2" , in_val, rval )
512 end
513 else
514 rval = val
515 end
516 return rval
517 end
518
519 def get_min
520 if @sign == :SIGNED || @sign == nil then
521 if @bit_size == -1 then
522 bit_sz = 8 # char_t は、有符号に扱う
523 else
524 bit_sz = @bit_size
525 end
526 case bit_sz
527 when 8, 16, 32, 64, 128
528 return - ( 1 << ( bit_sz - 1 ))
529 else # -1, -2, -3, -4, -5, -11
530 return nil
531 end
532 else # @sign == :UNSIGNED
533 return 0
534 end
535 end
536
537 def get_max
538 if @bit_size == -1 then
539 if @sign == nil then
540 return 255 # char_t は、無符号に扱う
541 else
542 bit_sz = 8
543 end
544 else
545 bit_sz = @bit_size
546 end
547 if @sign == :SIGNED || @sign == nil then
548 case bit_sz
549 when 8, 16, 32, 64, 128
550 return ( 1 << ( bit_sz - 1 )) -1
551 else # -1, -2, -3, -4, -5, -11
552 return nil
553 end
554 else # @sign == :UNSIGNED
555 case bit_sz
556 when 8, 16, 32, 64, 128
557 return ( 1 << bit_sz ) - 1
558 else # -2, -3, -4, -5, -11
559 return nil
560 end
561 end
562 end
563
564 #=== IntType# C 言語における型名(修飾子付き)
565 def get_type_str
566 str = super
567
568 # NEW_MODE
569 case @sign
570 when :SIGNED
571 sign = ""
572 signL = "signed "
573 when :UNSIGNED
574 sign = "u"
575 signL = "unsigned "
576 else
577 sign = ""
578 signL = ""
579 end
580
581 # p "get_type_str: sign:#{@sign} signL=#{signL}"
582
583 case @bit_size
584 when -1 # char_t 型
585 if @sign == :SIGNED then
586 sign = "s"
587 end
588 str = "#{str}#{sign}char_t"
589 when -11 # char 型(obsolete)
590 str = "#{str}#{signL}char"
591 when -2 # short 型
592 str = "#{str}#{signL}short"
593 when -3 # int 型
594 str = "#{str}#{signL}int"
595 when -4 # long 型
596 str = "#{str}#{signL}long"
597 when -5 # long long 型
598 str = "#{str}#{signL}long long"
599 when 8, 16, 32, 64, 128 # int16, int32, int64, int128 型
600 str = "#{str}#{sign}int#{@bit_size}_t"
601 end
602
603 return str
604 end
605
606 #=== IntType# C 言語における型名(後置文字列)
607 def get_type_str_post
608 ""
609 end
610
611 #=== IntType#bit_size を得る
612 # 返される値は @bit_size の仕様を参照
613 def get_bit_size
614 return @bit_size
615 end
616
617 #=== IntType# sign を得る
618 # @sign の説明を参照
619 def get_sign
620 @sign
621 end
622
623 def show_tree( indent )
624 indent.times { print " " }
625 puts "IntType bit_size=#{@bit_size} sign=#{@sign} const=#{@b_const} volatile=#{@b_volatile} #{locale_str}"
626 super( indent + 1 )
627 end
628end
629
630class FloatType < Type
631# @bit_size:: 32, 64, (80), -32, -64, -128
632
633 def initialize( bit_size )
634 super()
635 @bit_size = bit_size
636 end
637
638 def check # 意味的誤りがあれば、文字列を返す
639 nil
640 end
641
642 # mikan Float 型の C_EXP 対応 (generate.rb にも変更必要)
643 def check_init( locale, ident, initializer, kind, attribute = nil )
644 # 型に対する初期値に誤りがあれば、エラー文字列を返す
645 val = initializer
646 if val.instance_of?( Expression ) then
647 val = val.eval_const2( nil, attribute )
648 # 評価の結果 C_EXP や Array となる可能性がある
649 end
650
651 if val.instance_of? Token then
652 # val が Token の場合 == の右辺が String だとエラーを起こす
653 cdl_error2( locale, "T1018 $1: $2: not number" , ident, val )
654 return
655 elsif val.instance_of? Array then
656 cdl_error2( locale, "T1020 $1: unsuitable initializer for scalar type" , ident )
657 return
658 elsif val.instance_of? C_EXP then
659 return
660 elsif val == nil then
661 cdl_error2( locale, "T1019 $1: initializer is not constant" , ident )
662 return
663 elsif ! val.kind_of?( IntegerVal ) && ! val.kind_of?( FloatVal ) then
664 cdl_error2( locale, "T1037 $1: not number" , ident )
665 return
666 end
667 # else
668 # cdl_error2( locale, "T1020 $1: unsuitable initializer for scalar type" , ident )
669 # return
670 # end
671 return
672 end
673
674 def get_type_str
675 str = super
676
677 case @bit_size
678 when 32
679 str = "#{str}float32_t"
680 when 64
681 str = "#{str}double64_t"
682 when -32
683 str = "#{str}float"
684 when -64
685 str = "#{str}double"
686 when -128
687 str = "#{str}long double"
688 end
689 return str
690 end
691
692 def get_type_str_post
693 ""
694 end
695
696 def get_bit_size
697 @bit_size
698 end
699
700 def show_tree( indent )
701 indent.times { print " " }
702 puts "FloatType bit_size=#{@bit_size} qualifier=#{@qualifier} #{locale_str}"
703 super( indent + 1 )
704 end
705end
706
707class EnumType < Type # mikan
708# @bit_size:: -1: enum
709# 8, 16, 32, 64, 128
710# @element:: []
711# @element_val:: []
712
713 def initialize( bit_size )
714 super()
715 @bit_size = bit_size
716 end
717
718 def check
719 # mikan enum check
720 end
721
722 def show_tree( indent )
723 indent.times { print " " }
724 puts "EnumType bit_size=#{@bit_size} qualifier=#{@qualifier} #{locale_str}"
725 super( indent + 1 )
726 # mikan element
727 end
728end
729
730class StructType < Type
731# @tag::
732# @b_define:: true if define, false if refer
733# @members_decl:: NamedList
734# @definition:: StructType
735# @b_has_pointer_member:: bool : メンバにポインタ型がある
736# @b_has_sized_pointer_member:: bool : メンバにポインタ型がある
737# @b_has_unsized_string_member:: bool : メンバにポインタ型がある
738# @b_hasTag:: bool : タグがある
739# @member_types_symbol:: Symbol : tag が無い時のみ設定 (それ以外では nil)
740
741 @@structtype_current_stack = []
742 @@structtype_current_sp = -1
743
744 # tag なし struct
745 @@no_struct_tag_num = 0
746 @@no_tag_struct_list = {}
747
748 def initialize( tag = nil )
749 super()
750 @tag = tag
751 if tag then
752 @b_hasTag = true
753 else
754 @b_hasTag = false
755 end
756 @@structtype_current_sp += 1
757 @@structtype_current_stack[@@structtype_current_sp] = self
758 @b_has_pointer_member = false
759 @b_has_sized_pointer_member = false
760 @b_has_unsized_string_member = false
761 @member_types_symbol = nil
762 end
763
764 def self.set_define( b_define )
765 @@structtype_current_stack[@@structtype_current_sp].set_define( b_define )
766 end
767
768 def set_define( b_define )
769 @b_define = b_define
770 if @b_define then
771 @members_decl = NamedList.new( nil, "in struct #{@tag}" )
772 # if @tag then 登録タイミングを終わりに変更 V1.0.2.19
773 # Namespace.new_structtype( self )
774 # end
775 else
776 @definition = Namespace.find_tag( @tag )
777 # check_struct_tag に移す V1.0.2.19
778 # if @definition == nil then
779 # cdl_error( "T1021 \'$1\': struct not defined" , @tag )
780 # end
781 end
782 end
783
784 def self.new_member( member_decl )
785 @@structtype_current_stack[@@structtype_current_sp].new_member( member_decl )
786 end
787
788 def new_member( member_decl )
789 member_decl.set_owner self # Decl (StructType)
790 @members_decl.add_item( member_decl )
791 if member_decl.get_type.has_pointer?
792 @b_has_pointer_member = true
793 end
794 if member_decl.get_type.has_sized_pointer?
795 @b_has_sized_pointer_member = true
796 end
797 if member_decl.get_type.has_unsized_string?
798 @b_has_unsized_string_member = true
799 end
800 end
801
802 def check # 意味的誤りがあれば、文字列を返す
803 nil
804 end
805
806 #=== 構造体のタグをチェック
807 # declarator の時点でチェックする
808 #kind:: Decl の @kind を参照
809 def check_struct_tag kind
810 if @tag == nil
811 return
812 end
813
814 st = Namespace.find_tag( @tag )
815 if st == nil then
816 cdl_error( "T1022 struct $1: not defined" , @tag )
817 end
818 end
819
820 # mikan Float 型の C_EXP 対応 (generate.rb にも変更必要)
821 def check_init( locale, ident, initializer, kind, attribute = nil )
822
823 st = Namespace.find_tag( @tag )
824 if st == nil then
825 cdl_error2( locale, "T1023 struct $1: not defined" , @tag )
826 return
827 end
828
829 # 初期化子が式の場合、型(タグ)が一致するかチェック
830 if initializer.instance_of?( Expression ) then
831 t = initializer.get_type( attribute )
832 # print "Check init #{t.class} #{t.get_name}\n"
833 if ! t.kind_of?( StructType ) then
834 if t then
835 str = t.get_type_str
836 else
837 str = "unknown"
838 end
839 cdl_error2( locale, "T1038 $1: initializer type mismatch. '$2' & '$3'" , ident, get_type_str, str )
840 elsif @tag != t.get_name then
841 cdl_error2( locale, "T1039 $1: struct tag mismatch $2 and $3" , ident, @tag, t.get_name )
842 end
843 initializer = initializer.eval_const( attribute )
844 end
845
846 if initializer.instance_of?( Array ) then
847 i = 0
848 st.get_members_decl.get_items.each { |d|
849 if initializer[i] then
850 d.get_type.check_init( locale, "#{ident}.#{d.get_identifier}", initializer[i], kind )
851 end
852 i += 1
853 }
854 else
855 cdl_error2( locale, "T1024 $1: unsuitable initializer for struct" , ident )
856 end
857 end
858
859 def self.end_of_parse()
860 @@structtype_current_stack[@@structtype_current_sp].end_of_parse
861 @@structtype_current_sp -= 1
862 end
863
864 def end_of_parse()
865 if @members_decl == nil # @b_define = false またはメンバーのない構造体(エラー)
866 return
867 end
868 @members_decl.get_items.each{ |md|
869 size = md.get_size_is
870 if size then
871 val = size.eval_const( @members_decl )
872 if val == nil then
873 type = size.get_type( @members_decl )
874 if ! type.kind_of?( IntType ) then
875 cdl_error( "T1025 size_is argument is not integer type" )
876 end
877 end
878 end
879 count = md.get_count_is
880 if count then
881 val = count.eval_const( @members_decl )
882 if val == nil then
883 type = count.get_type( @members_decl )
884 if ! type.kind_of?( IntType ) then
885 cdl_error( "T1026 count_is argument is not integer type" )
886 end
887 end
888 end
889 string = md.get_string
890 if string == -1 then
891 # 長さ指定なし
892 elsif string then
893 val = string.eval_const( @members_decl )
894 if val == nil then
895 type = string.get_type( @members_decl )
896 if ! type.kind_of?( IntType ) then
897 cdl_error( "T1027 string argument is not integer type" )
898 end
899 end
900 end
901 }
902
903 if @tag == nil then
904 @member_types_symbol = get_member_types_symbol
905 # print "member_types_symbol = #{get_member_types_symbol}\n"
906 if @@no_tag_struct_list[ @member_types_symbol ] then
907 @tag = @@no_tag_struct_list[ @member_types_symbol ]
908 else
909 @tag = :"TAG_#{@@no_struct_tag_num}_TECS_internal__"
910 @@no_struct_tag_num += 1
911 @@no_tag_struct_list[ @member_types_symbol ] = @tag
912 Namespace.new_structtype( self )
913 end
914 else
915 if @b_define then
916 Namespace.new_structtype( self )
917 end
918 end
919 end
920
921 def get_name
922 @tag
923 end
924
925 def get_type_str # mikan struct get_type_str
926 str = super
927
928 if @b_hasTag then
929 # typedef struct tag StructType; の形式の場合
930 # struct の本体は、別に生成される
931 return "#{str}struct #{@tag}"
932
933 else
934 # typedef struct { int a; } StructType; の形式の場合
935 str += "struct {"
936 @members_decl.get_items.each{ |i|
937 str += sprintf( "%s %s%s;", "#{i.get_type.get_type_str}", "#{i.get_name}", "#{i.get_type.get_type_str_post}" )
938 }
939 str += "} "
940
941 return str
942
943 end
944 end
945
946 def get_type_str_post
947 ""
948 end
949
950 def get_members_decl
951 return @members_decl if @members_decl
952
953 st = Namespace.find_tag( @tag )
954 if st then
955 return st.get_members_decl
956 end
957
958 return nil
959 end
960
961 def has_pointer?
962 if @definition
963 return @definition.has_pointer?
964 else
965 return @b_has_pointer_member
966 end
967 end
968
969 def has_sized_pointer?
970 if @definition
971 return @definition.has_sized_pointer?
972 else
973 return @b_has_sized_pointer_member
974 end
975 end
976
977 def has_unsized_string?
978 if @definition
979 return @definition.has_unsized_string?
980 else
981 return @b_has_unsized_string_member
982 end
983 end
984
985 #=== 同じ構造体かどうかチェックする
986 # tag のチェックは行わない
987 # すべてのメンバの名前と型が一致することを確認する
988 def same? another
989 md = another.get_members_decl
990 if @members_decl == nil || md == nil
991 return false
992 end
993
994 md1 = @members_decl.get_items
995 md2 = md.get_items
996 if( md1.length != md2.length )
997 return false
998 end
999
1000 i = 0
1001 while i < md1.length
1002 if md1[i].get_name != md2[i].get_name ||
1003 md1[i].get_type.get_type_str != md2[i].get_type.get_type_str ||
1004 md1[i].get_type.get_type_str_post != md2[i].get_type.get_type_str_post
1005 return false
1006 end
1007 i += 1
1008 end
1009
1010 return true
1011 end
1012
1013 def get_member_types_symbol
1014 mts = ''
1015 @members_decl.get_items.each { |member|
1016 mts += member.get_type.get_type_str + member.get_type.get_type_str_post + ';'
1017 }
1018 return mts.to_sym
1019 end
1020
1021 def show_tree( indent )
1022 indent.times { print " " }
1023 puts "StructType tag: #{@tag} qualifier=#{@qualifier} has_pointer=#{@b_has_pointer_member} #{locale_str}"
1024 super( indent + 1 )
1025 if @b_define then
1026 @members_decl.show_tree( indent + 1 )
1027 end
1028 end
1029end
1030
1031class FuncType < Type
1032# @paramlist:: ParamList
1033# @type:: return type : PtrType, ArrayType, FuncType, IntType, FloatType, ...
1034# @b_oneway:: bool: true, false
1035# @has_in:: bool : has [in] parameter
1036# @has_inout:: bool : has [inout] parameter
1037# @has_out:: bool : has [out] parameter
1038# @has_send:: bool : has [send] parameter
1039# @has_receive:: bool : has [receive] parameter
1040
1041 def initialize( paramlist = nil )
1042 super()
1043
1044 @has_in = false
1045 @has_inout = false
1046 @has_out = false
1047 @has_send = false
1048 @has_receive = false
1049
1050 @paramlist = paramlist
1051 @b_oneway = false
1052 if paramlist then
1053 paramlist.check_param
1054 else
1055 @paramlist = ParamList.new( nil )
1056 end
1057 @paramlist.set_owner self # ParamList
1058 @paramlist.get_items.each{ |p|
1059 case p.get_direction
1060 when :IN
1061 @has_in = true
1062 when :INOUT
1063 @has_inout = true
1064 when :OUT
1065 @has_out = true
1066 when :SEND
1067 @has_send = true
1068 when :RECEIVE
1069 @has_receive = true
1070 else
1071 raise "unkown direction"
1072 end
1073 }
1074
1075 end
1076
1077 def check # 意味的誤りがあれば、文字列を返す
1078 if @type.class == ArrayType then # 配列を返す関数
1079 return "function returning array"
1080 elsif @type.class == FuncType then # 関数を返す関数
1081 return "function returning function"
1082 end
1083 return @type.check # 関数の return する型のチェック
1084
1085 # パラメータの型のチェックは ParamList#check_param で行う
1086 end
1087
1088 def check_struct_tag kind
1089 @type.check_struct_tag kind
1090 # ParamDecl でもチェックされるので、ここではチェックしない
1091 # @paramlist.check_struct_tag kind
1092 end
1093
1094 def check_init( locale, ident, initializer, kind, attribute = nil )
1095 cdl_error2( locale, "T1028 $1: cannot initialize function pointer" , ident )
1096 return
1097 end
1098
1099 def set_type( type )
1100 unless @type then
1101 @type = type
1102 else
1103 @type.set_type( type )
1104 end
1105 end
1106
1107 #=== return type を返す
1108 #
1109 # return type を返す
1110 # get_return_type とすべきだった
1111 def get_type
1112 @type
1113 end
1114
1115 def get_type_str
1116 return @type.get_type_str
1117 end
1118
1119 def get_type_str_post
1120 # 型だけを返す (仮引数の名前を含めない)
1121 @paramlist.to_str( false )
1122 end
1123
1124 def get_paramlist
1125 @paramlist
1126 end
1127
1128 def set_oneway( b_oneway )
1129 @b_oneway = b_oneway
1130
1131 if ( ( @type.get_type_str != "ER" && @type.get_type_str != "void" ) || @type.get_type_str_post != "" ) then
1132 cdl_error( "T1029 oneway function cannot return type \'$1$2\', \'void\' or \'ER\' is permitted" , @type.get_type_str, @type.get_type_str_post )
1133 end
1134
1135 if @paramlist then
1136 @paramlist.get_items.each{ |p|
1137 if p.get_direction != :IN && p.get_direction != :SEND then
1138 cdl_error( "T1030 oneway function cannot have $1 parameter for \'$2\'" , p.get_direction, p.get_name )
1139 end
1140 }
1141 end
1142 end
1143
1144 def is_oneway?
1145 @b_oneway
1146 end
1147
1148 #=== Push Pop Allocator が必要か?
1149 # Transparent RPC の場合 oneway かつ in の配列(size_is, count_is, string のいずれかで修飾)がある
1150 def need_PPAllocator?( b_opaque = false )
1151 if @b_oneway || b_opaque then
1152 return @paramlist.need_PPAllocator?( b_opaque )
1153 else
1154 return false
1155 end
1156 end
1157
1158 #=== パラメータが in, inout, out, send, receive を持つか
1159 def has_in?
1160 @has_in
1161 end
1162 def has_inout?
1163 @has_inout
1164 end
1165 def has_out?
1166 @has_out
1167 end
1168 def has_send?
1169 @has_send
1170 end
1171 def has_receive?
1172 @has_receive
1173 end
1174
1175 #=== 入力方向のパラメータを持つか
1176 def has_inward?
1177 @has_in || @has_inout || @has_send
1178 end
1179 #=== 出力方向のパラメータを持つか
1180 def has_outward?
1181 @has_inout || @has_out || @has_receive
1182 end
1183
1184 def show_tree( indent )
1185 indent.times { print " " }
1186 if @b_oneway then
1187 puts "FunctType: oneway=true #{locale_str}"
1188 else
1189 puts "FunctType: oneway=false #{locale_str}"
1190 end
1191 super( indent + 1 )
1192 if @paramlist then
1193 @paramlist.show_tree( indent + 1 )
1194 end
1195 (indent+1).times { print " " }
1196 puts "return type:"
1197 @type.show_tree( indent + 2 )
1198 end
1199end
1200
1201class ArrayType < Type
1202# @type:: element type : ArrayType, FuncType, IntType, FloatType, ...
1203# @subscript:: Expression, nil if '[]'
1204
1205 include HasType
1206
1207 def initialize( subscript = nil )
1208 super()
1209 @subscript = subscript
1210 initHasType
1211 end
1212
1213 def set_type( type )
1214 unless @type then
1215 @type = type
1216 else
1217 @type.set_type( type )
1218 end
1219 end
1220
1221 #=== Array#qualifier(const, volatile) の設定
1222 def set_qualifier( qualifier )
1223 clone_type
1224 @type.set_qualifier( qualifier )
1225 super
1226 end
1227
1228 # 配列要素が const なら const
1229 def is_const?
1230 @type.is_const?
1231 end
1232
1233 # 配列要素が volatile なら volatile
1234 def is_volatile?
1235 @type.is_volatile?
1236 end
1237
1238 def get_type
1239 @type
1240 end
1241
1242 def get_subscript
1243 @subscript
1244 end
1245
1246 def get_type_str
1247 return "#{@type.get_type_str}"
1248 end
1249
1250 def get_type_str_post
1251 if @subscript
1252 "[#{@subscript.eval_const(nil)}]#{@type.get_type_str_post}"
1253 else
1254 "[]#{@type.get_type_str_post}"
1255 end
1256 # "[#{@subscript.to_s}]#{@type.get_type_str_post}"
1257 end
1258
1259 def check # 意味的誤りがあれば、文字列を返す
1260 if @type.class == FuncType then # 関数の配列
1261 return "array of function"
1262 elsif @type.class == ArrayType then # 添数なし配列の配列
1263 unless @type.get_subscript then
1264 return "subscript not specified"
1265 end
1266 end
1267
1268 return @type.check # 配列要素の型をチェック
1269 end
1270
1271 def check_struct_tag kind
1272 @type.check_struct_tag kind
1273 end
1274
1275 def check_init( locale, ident, initializer, kind, attribute = nil )
1276 if ( initializer.instance_of?( Array ) ) then
1277 # 要素数が指定されている場合、初期化要素数をチェック
1278 if @subscript then
1279 n_sub = @subscript.eval_const( nil )
1280 if n_sub then
1281 if initializer.length > n_sub then
1282 cdl_error2( locale, "T9999 $1: too many initializer, $2 for $3" , ident, initializer.length, n_sub )
1283 end
1284 end
1285 end
1286 index = 0
1287 initializer.each{ |i|
1288 @type.check_init( locale, "#{ident}[#{index}]", i, kind, attribute = nil )
1289 index += 1
1290 }
1291 else
1292 cdl_error2( locale, "T1031 $1: unsuitable initializer for array" , ident )
1293 end
1294 end
1295
1296 def has_pointer?
1297 @type.has_pointer?
1298 end
1299
1300 def has_sized_pointer?
1301 @type.has_sized_pointer?
1302 end
1303
1304 def has_unsized_string?
1305 @type.has_unsized_string?
1306 end
1307
1308 def show_tree( indent )
1309 indent.times { print " " }
1310 puts "ArrayType: #{locale_str}"
1311 super( indent + 1 )
1312 (indent+1).times { print " " }
1313 puts "type:"
1314 @type.show_tree( indent + 2 )
1315 (indent+1).times { print " " }
1316 puts "subscript:"
1317 if @subscript then
1318 @subscript.show_tree( indent + 2 )
1319 else
1320 (indent+2).times { print " " }
1321 puts "no subscript"
1322 end
1323 end
1324end
1325
1326class PtrType < Type
1327# @type:: refer to : PtrType, FuncType, ArrayType, IntType, FloatType, ...
1328# @size:: Expr, or nil if not specified
1329# @count:: Expr, or nil if not specified
1330# @string:: Expr or -1(if size not specified) (string 引数), or nil if not specified
1331
1332 include HasType
1333
1334 def initialize( referto = nil )
1335 super()
1336 @type = referto
1337 @size = nil
1338 @count = nil
1339 @string = nil
1340 initHasType
1341 end
1342
1343 def set_type( type )
1344 unless @type then
1345 @type = type
1346 else
1347 @type.set_type( type ) # 枝先の type を設定
1348 end
1349 end
1350
1351 def get_type_str
1352 if @type.kind_of?( ArrayType ) || @type.kind_of?( FuncType ) then
1353 parenthes = "("
1354 else
1355 parenthes = ""
1356 end
1357 return "#{@type.get_type_str}#{parenthes}*"
1358 end
1359
1360 def get_type_str_post
1361 if @type.kind_of?( ArrayType ) || @type.kind_of?( FuncType ) then
1362 parenthes = ")"
1363 else
1364 parenthes = ""
1365 end
1366 "#{parenthes}#{@type.get_type_str_post}"
1367 end
1368
1369 def check # 意味的誤りがあれば、文字列を返す
1370 return nil if @type == nil
1371 @type.check
1372 end
1373
1374 def check_struct_tag kind
1375 if kind != :MEMBER # 構造体メンバーの場合、ポインタの先の構造体タグをチェックしない
1376 @type.check_struct_tag kind
1377 end
1378 end
1379
1380 def check_init( locale, ident, initializer, kind, attribute = nil )
1381 if ( initializer.instance_of?( Expression ) ) then
1382 val = initializer.eval_const2( nil, attribute )
1383 if val.kind_of? PointerVal then
1384 type = val.get_type # PtrType
1385 t1 = self
1386 t2 = type
1387 while( t1.kind_of?( PtrType ) && t2.kind_of?( PtrType ) )
1388 t1 = t1.get_type
1389 t2 = t2.get_type
1390 if ( t1.class == t2.class ) && ( t1.get_bit_size == t2.get_bit_size ) then
1391 elsif ( t1.kind_of?( CDefinedType) || t2.kind_of?( CDefinedType ) )&& t1.get_type_str == t2.get_type_str && t1.get_type_str_post && t2.get_type_str_post then
1392 # int8_t などが、一方は .h に定義されているケース
1393 else
1394 cdl_error2( locale, "T1032 $1: incompatible pointer type" , ident )
1395 break
1396 end
1397 end
1398 elsif val.kind_of? IntegerVal then
1399 if val.to_i != 0 then
1400 cdl_error2( locale, "T1033 $1: need cast to assign integer to pointer" , ident )
1401 end
1402 elsif val.kind_of? StringVal then
1403 # 文字列定数
1404 # mikan L"wide string"
1405 if @type.get_bit_size != -1 && @type.get_bit_size != -11 then # -1: char_t
1406 cdl_error2( locale, "T1034 $1: unsuitable string constant" , ident )
1407 end
1408 elsif ( val.instance_of?( Array ) ) then
1409 i = 0
1410 val.each { |ini|
1411 @type.check_init( locale, "#{ident}[#{i}]", ini, kind, attribute = nil )
1412 i += 1
1413 }
1414 elsif val.instance_of?( C_EXP ) then
1415
1416 else
1417 cdl_error2( locale, "T1035 $1: unsuitable initializer for pointer" , ident )
1418 end
1419 elsif ( initializer.instance_of?( Array ) ) then
1420 if @size == nil && @count == nil then
1421 cdl_error2( locale, "T9999 $1: non-size_is pointer cannot have array initializer", ident )
1422 end
1423
1424 i = 0
1425 initializer.each { |ini|
1426 @type.check_init( locale, "#{ident}[#{i}]", ini, kind, attribute = nil )
1427 i += 1
1428 }
1429 elsif( initializer.instance_of?( C_EXP ) ) then
1430
1431 else
1432 cdl_error2( locale, "T1036 $1: unsuitable initializer for pointer" , ident )
1433 end
1434 end
1435
1436 def get_referto
1437 clone_type
1438 @type
1439 end
1440
1441 def set_scs( size, count, string, max, b_nullable )
1442 @size = size
1443 @count = count
1444 @max = max
1445 @b_nullable = b_nullable
1446
1447 # string は最も左側の ptr に作用する
1448 if @type.kind_of?( PtrType ) then
1449 # ptr_level が 2 以上であることは ParamDecl#initializer でチェックされる
1450 clone_type
1451 @type.set_scs( nil, nil, string, nil, false )
1452 elsif @type.kind_of?( VoidType ) && ( size || count || string ) then
1453 str = ""
1454 if size then
1455 str = "size_is"
1456 end
1457 if count then
1458 if str then
1459 str += ", "
1460 end
1461 str += "count_is"
1462 end
1463 if string then
1464 if str then
1465 str += ", "
1466 end
1467 str += "string"
1468 end
1469
1470 cdl_error( "T1040 $1 specified for void pointer type", str )
1471 else
1472 @string = string
1473 end
1474
1475 if (@size != nil) && (@b_nullable != false) then
1476 cdl_error( "T9999 size_is & nullable cannot be specified simultaneously. If size is zero, pointer must be null")
1477 end
1478 end
1479
1480 def clear_max
1481 @max = nil
1482 end
1483
1484 def get_size
1485 @size
1486 end
1487
1488 def get_count
1489 @count
1490 end
1491
1492 def get_string
1493 @string
1494 end
1495
1496 #=== PtrType# size_is の最大値
1497 def get_max
1498 @max
1499 end
1500
1501 def is_nullable?
1502 return @b_nullable
1503 end
1504
1505 def get_type
1506 clone_type
1507 @type
1508 end
1509
1510 def has_pointer?
1511 true
1512 end
1513
1514 def has_sized_pointer?
1515 @size != nil || @count != nil || @string.instance_of?( Expression ) || @type.has_sized_pointer?
1516 end
1517
1518 def has_unsized_string?
1519 @string == -1 || @type.has_unsized_string?
1520 end
1521
1522 def show_tree( indent )
1523 indent.times { print " " }
1524 puts "PtrType: qualifier=#{@qualifier}, nullable=#{@b_nullable} #{locale_str}"
1525 super( indent + 1 )
1526 (indent+1).times { print " " }
1527 if @size then
1528 print "size=#{@size.to_s}, "
1529 else
1530 print "size=nil, "
1531 end
1532 if @max then
1533 print "max=#{@size.to_s}, "
1534 else
1535 print "max=nil, "
1536 end
1537 if @count then
1538 print "count=#{@count.to_s}, "
1539 else
1540 print "count=nil, "
1541 end
1542 if @string then
1543 if @string.instance_of?( Expression ) then
1544 print "string=#{@string.to_s}\n"
1545 else
1546 print "string=yes\n"
1547 end
1548 else
1549 print "string=nil\n"
1550 end
1551
1552 (indent+1).times { print " " }
1553 puts "type:"
1554 @type.show_tree( indent + 2 )
1555 end
1556
1557end
1558
1559#== DescriptorType クラス
1560# 動的結合で渡すデスクリプタ型
1561class DescriptorType < Type
1562 # @sinagure_nsp::NamespacePath
1563
1564 @@descriptors = {}
1565
1566 def initialize( signature_nsp )
1567 @signature_nsp = signature_nsp
1568 # check_signature ##
1569 @@descriptors[ self ] = false
1570 end
1571
1572 def get_type_str
1573 "Descriptor( #{@signature_nsp.get_global_name} )"
1574 end
1575
1576 def get_type_str_post
1577 ""
1578 end
1579
1580 def set_qualifier( qualifier )
1581 cdl_error( "T9999 '$1' cannot be specified for Descriptor", qualfier.to_s )
1582 end
1583
1584 def check
1585 end
1586
1587 def check_init( locale, ident, initializer, kind, attribute = nil )
1588 case kind
1589 when :PARAMETER
1590 # 引数は初期化できない
1591 else
1592 cdl_error2( locale, "T9999 Descriptor cannot be used for $1", kind)
1593 end
1594 end
1595
1596 def self.check_signature
1597 @@descriptors.each{ |desc, val|
1598 if val != true then
1599 desc.check_signature
1600 @@descriptors[ desc ] = true
1601 end
1602 }
1603 end
1604
1605 def check_signature
1606 # p "Desc #{@signature_nsp.to_s}"
1607 obj = Namespace.find @signature_nsp
1608 if ! obj.kind_of? Signature then
1609 cdl_error( "T9999 '$1': not signature or not found", @signature_nsp.to_s )
1610 else
1611 if obj.has_descriptor? then
1612 # cdl_error( "T9999 '$1': has Descriptor in function parameter", @signature_nsp.to_s )
1613 end
1614 # @signature_nsp = obj.get_namespace_path
1615 end
1616 end
1617
1618 #== DescriptorType#
1619 def get_signature
1620 Namespace.find @signature_nsp
1621 end
1622end
1623
1624# 以下単体テストコード
1625if $unit_test then
1626 puts( "===== Unit Test: IntType ===== (types.rb)")
1627 sizes = [ 8, 16, 32, 64 ]
1628 sizes.each{ |n|
1629 int = IntType.new n
1630 printf( "%8s max: %d min:%d\n", "int#{n}_t", int.get_max, int.get_min )
1631 }
1632 puts ""
1633end
Note: See TracBrowser for help on using the repository browser.