File Coverage

blib/lib/CORBA/IDL/Symbtab.pm
Criterion Covered Total %
statement 12 517 2.3
branch 0 258 0.0
condition 0 111 0.0
subroutine 4 36 11.1
pod 0 21 0.0
total 16 943 1.7


line stmt bran cond sub pod time code
1             #
2             # Interface Definition Language (OMG IDL CORBA v3.0)
3             #
4            
5 1     1   8 use strict;
  1         1  
  1         41  
6 1     1   6 use warnings;
  1         1  
  1         6684  
7            
8             package CORBA::IDL::Scope;
9            
10             sub new {
11 0     0     my $proto = shift;
12 0   0       my $class = ref($proto) || $proto;
13 0           my $self = {};
14 0           bless $self, $class;
15 0           my($symbtab, $classname, $full, $name) = @_;
16 0           $self->{class} = $classname;
17 0           $self->{full} = $full;
18 0           $self->{entry} = {};
19 0           return $self;
20             }
21            
22             sub _Insert {
23 0     0     my $self = shift;
24 0           my($name, $defn) = @_;
25 0           $self->{entry}->{lc $name} = $defn;
26             }
27            
28             sub _Lookup {
29 0     0     my $self = shift;
30 0           return $self->{entry}->{lc shift};
31             }
32            
33             ##############################################################################
34            
35             package CORBA::IDL::Symbtab;
36            
37             our $VERSION = '2.63';
38            
39             sub new {
40 0     0 0   my $proto = shift;
41 0   0       my $class = ref($proto) || $proto;
42 0           my $self = {};
43 0           bless $self, $class;
44 0           my($parser) = @_;
45 0           $self->{current_root} = q{};
46 0           $self->{current_scope} = q{};
47 0           $self->{parser} = $parser;
48            
49 0           $self->{scopes} = {
50             q{} => new CORBA::IDL::Scope($self, 'CORBA::IDL::Module', q{}, q{})
51             };
52 0           $self->{prefix} = {};
53 0           $self->{typeprefix} = {};
54             # C Mapping
55 0           $self->{c_mapping} = {};
56             # $self->_Init();
57 0           return $self;
58             }
59            
60             #sub _Init {
61             # my $self = shift;
62             #}
63            
64             sub _CheckCMapping {
65 0     0     my $self = shift;
66 0           my($full) = @_;
67            
68 0           my $c_key = $full;
69 0           $c_key =~ s/^:://;
70 0           $c_key =~ s/::/_/g;
71 0 0         if (exists $self->{c_mapping}{$c_key}) {
72 0           $self->{parser}->Info(
73             "'$full' is ambiguous (C mapping) with '$self->{c_mapping}{$c_key}'.\n");
74             }
75             else {
76 0           $self->{c_mapping}{$c_key} = $full
77             }
78             }
79            
80             sub PushCurrentRoot {
81 0     0 0   my $self = shift;
82 0           my($node) = @_;
83 0           my $name = $node->{idf};
84 0           my $class = ref $node;
85 0           $class = substr $class, rindex($class, ':') + 1;
86             ## print "PushCurrentRoot '$name' $class\n";
87 0 0         $self->{parser}->Error("PushCurrentRoot: INTERNAL_ERROR ($class).\n")
88             unless ($class eq 'Module');
89             # OpenModule
90 0 0         $self->{parser}->Error("PushCurrentRoot: INTERNAL_ERROR current_scope not empty ($self->{current_scope}).\n")
91             if ($self->{current_scope});
92 0 0         delete $self->{msg} if (exists $self->{msg});
93 0           my $scope = $self->{current_root};
94 0           my $key_prefix = $self->{parser}->YYData->{filename} . $scope;
95 0           my $new_scope = $self->{current_root} . '::' . $name;
96 0           my $prev = $self->{scopes}->{$scope}->_Lookup($name);
97 0 0         if (defined $prev) {
98 0           while ($prev->isa('Entry')) {
99 0           $prev = $self->{scopes}->{$prev->{scope}}->_Lookup($name);
100             }
101 0 0         if ($prev->isa('Modules')) {
102             # reopen
103 0           push @{$prev->{list_decl}}, $node;
  0            
104 0 0         if ($prev->{prefix} ne $node->{prefix}) {
105 0           $self->{parser}->Error("Prefix redefinition for '$name'.\n");
106             }
107             }
108             else {
109 0   0       $self->{msg} ||= "Identifier '$name' already exists.\n";
110 0           $self->{parser}->Error($self->{msg});
111 0 0         unless (exists $self->{scopes}->{$new_scope}) {
112 0           $self->{scopes}->{$new_scope} = new CORBA::IDL::Scope($self, ref $node, $new_scope, $name);
113 0           my $modules = bless {
114             idf => $name,
115             full => $new_scope,
116             prefix => $node->{prefix},
117             _typeprefix => $node->{_typeprefix},
118             list_decl => [ $node ],
119             }, 'CORBA::IDL::Modules';
120 0 0         $modules->{typeprefix} = $node->{typeprefix}
121             if (exists $node->{typeprefix});
122 0 0         $modules->{declspec} = $node->{declspec}
123             if (exists $node->{declspec});
124 0           $self->{scopes}->{$new_scope}->_Insert($name, $modules);
125             }
126             }
127             }
128             else {
129 0           $self->{scopes}->{$scope}->_Insert($name, bless({'scope' => $new_scope}, 'Entry'));
130 0           $self->_CheckCMapping($new_scope);
131 0           $self->{scopes}->{$new_scope} = new CORBA::IDL::Scope($self, ref $node, $new_scope, $name);
132 0           my $modules = bless {
133             idf => $name,
134             full => $new_scope,
135             prefix => $node->{prefix},
136             _typeprefix => $node->{_typeprefix},
137             list_decl => [ $node ],
138             }, 'CORBA::IDL::Modules';
139 0 0         $modules->{typeprefix} = $node->{typeprefix}
140             if (exists $node->{typeprefix});
141 0 0         $modules->{declspec} = $node->{declspec}
142             if (exists $node->{declspec});
143 0           $self->{scopes}->{$new_scope}->_Insert($name, $modules);
144             }
145            
146 0           $self->{current_root} = $new_scope;
147 0           $node->{full} = $new_scope;
148 0 0         if (defined $node->{_typeprefix}) {
149 0           my $typeprefix = $node->{_typeprefix};
150 0 0         if ($typeprefix) {
151 0           $typeprefix .= '/' . $node->{idf};
152             }
153             else {
154 0           $typeprefix = $node->{idf};
155             }
156 0           $self->{typeprefix}->{$new_scope} = $typeprefix;
157             }
158             else {
159 0           $key_prefix .= '::' . $node->{idf};
160 0           my $prefix = $node->{prefix};
161 0 0         if ($prefix) {
162 0           $prefix .= '/' . $node->{idf};
163             }
164             else {
165 0           $prefix = $node->{idf};
166             }
167 0           $self->{prefix}->{$key_prefix} = $prefix;
168             }
169 0           return;
170             }
171            
172             sub PopCurrentRoot {
173 0     0 0   my $self = shift;
174 0           my($node) = @_;
175 0 0         return unless (defined $node);
176 0 0         return if ($self->{current_root} =~ s/::$node->{idf}$//);
177 0           $self->{parser}->Error(
178             "PopCurrentRoot: INTERNAL_ERROR $self->{current_root} $node->{idf}.\n");
179 0           return;
180             }
181            
182             sub PushCurrentScope {
183 0     0 0   my $self = shift;
184 0           my($node) = @_;
185 0           my $name = $node->{idf};
186 0           my $class = ref $node;
187 0           $class = substr $class, rindex($class, ':') + 1;
188             ## print "PushCurrentScope '$name' $class\n";
189             # Insert
190 0 0         delete $self->{msg} if (exists $self->{msg});
191 0           my $scope = $self->{current_root} . $self->{current_scope};
192 0           my $key_prefix = $self->{parser}->YYData->{filename} . $scope;
193 0           my $new_scope = $scope . '::' . $name;
194 0           my $prev = $self->{scopes}->{$scope}->_Lookup($name);
195 0 0         if (defined $prev) {
196 0           while ($prev->isa('Entry')) {
197 0           $prev = $self->{scopes}->{$prev->{scope}}->_Lookup($name);
198             }
199 0 0         if ($prev->isa('Forward' . $class)) {
200             # the previous must be the same
201 0           foreach (keys %{$prev}) {
  0            
202 0 0 0       if ( $_ eq 'full'
      0        
      0        
      0        
      0        
203             or $_ eq 'filename'
204             or $_ eq 'lineno'
205             or $_ eq 'typeprefix'
206             or $_ eq '_typeprefix'
207             or $_ eq 'hash_attribute_operation' ) {
208 0           next;
209             }
210 0 0 0       if ( $_ eq 'id'
211             or $_ eq 'version' ) {
212 0           $node->{$_} = $prev->{$_};
213 0           next;
214             }
215 0 0         if ($prev->{$_} ne $node->{$_}) {
216             ## print "$_ $prev->{$_} $node->{$_}\n";
217 0 0         if ($_ eq 'prefix') {
218 0 0         unless (defined $node->{_typeprefix}) {
219 0           $self->{parser}->Error(
220             "Prefix redefinition for '$name'.\n");
221             }
222 0           next;
223             }
224 0           $self->{parser}->Error(
225             "Definition of '$name' conflicts with previous declaration.\n");
226 0           return;
227             }
228             }
229 0 0         $node->{typeprefix} = $prev->{typeprefix}
230             if (exists $prev->{typeprefix});
231 0           $self->{scopes}->{$scope}->_Insert($name, bless({'scope' => $new_scope}, 'Entry'));
232 0           $self->{scopes}->{$new_scope} = new CORBA::IDL::Scope($self, ref $node, $new_scope, $name);
233 0           $self->{scopes}->{$new_scope}->_Insert($name, $node);
234             }
235             else {
236 0   0       $self->{msg} ||= "Identifier '$name' already exists.\n";
237 0           $self->{parser}->Error($self->{msg});
238 0 0         unless (exists $self->{scopes}->{$new_scope}) {
239 0           $self->{scopes}->{$new_scope} = new CORBA::IDL::Scope($self, ref $node, $new_scope, $name);
240 0           $self->{scopes}->{$new_scope}->_Insert($name, $node);
241             }
242             }
243             }
244             else {
245 0           $self->{scopes}->{$scope}->_Insert($name, bless({'scope' => $new_scope}, 'Entry'));
246 0           $self->_CheckCMapping($new_scope);
247 0           $self->{scopes}->{$new_scope} = new CORBA::IDL::Scope($self, ref $node, $new_scope, $name);
248 0           $self->{scopes}->{$new_scope}->_Insert($name, $node);
249             }
250            
251 0           $self->{current_scope} .= '::' . $name;
252 0           $node->{full} = $new_scope;
253 0 0         if (defined $node->{_typeprefix}) {
254 0           my $typeprefix = $node->{_typeprefix};
255 0 0         if ($typeprefix) {
256 0           $typeprefix .= '/' . $node->{idf};
257             }
258             else {
259 0           $typeprefix = $node->{idf};
260             }
261 0           $self->{typeprefix}->{$new_scope} = $typeprefix;
262             }
263             else {
264 0           $key_prefix .= '::' . $node->{idf};
265 0           my $prefix = $node->{prefix};
266 0 0         if ($prefix) {
267 0           $prefix .= '/' . $node->{idf};
268             }
269             else {
270 0           $prefix = $node->{idf};
271             }
272 0           $self->{prefix}->{$key_prefix} = $prefix;
273             }
274 0           return;
275             }
276            
277             sub PopCurrentScope {
278 0     0 0   my $self = shift;
279 0           my($node) = @_;
280 0 0         return unless (defined $node);
281 0 0         return if ($self->{current_scope} =~ s/::$node->{idf}$//);
282 0           $self->{parser}->Error(
283             "PopCurrentScope: INTERNAL_ERROR $self->{current_scope} $node->{idf}.\n");
284 0           return;
285             }
286            
287             sub Insert {
288 0     0 0   my $self = shift;
289 0           my($node) = @_;
290 0 0         if ($node->isa('Specification')) {
291 0           $node->{full} = q{};
292 0           $self->{scopes}->{''}->_Insert(q{}, $node);
293 0           return;
294             }
295 0           my $name = $node->{idf};
296 0 0         return unless ($name);
297 0 0         delete $self->{msg} if (exists $self->{msg});
298 0           my $scope = $self->{current_root} . $self->{current_scope};
299             ## print "Insert '$name' ",ref $node," => $scope\n";
300 0 0         unless (exists $self->{scopes}->{$scope}) {
301 0           warn "'$scope' not exist.\n";
302 0           return;
303             }
304 0           my $prev = $self->{scopes}->{$scope}->_Lookup($name);
305 0 0         if (defined $prev) {
306 0           while ($prev->isa('Entry')) {
307 0           $prev = $self->{scopes}->{$prev->{scope}}->_Lookup($name);
308             }
309 0           my $class = ref $prev;
310 0           $class = substr $class, rindex($class, ':') + 1;
311 0 0         if ($class =~ s/^Forward//) {
312 0 0         if (ref $node ne $class) {
313 0           $self->{parser}->Error(
314             "Definition of '$name' conflicts with previous declaration.\n");
315 0           return;
316             }
317             else {
318             # the previous must be the same
319 0           foreach (keys %{$prev}) {
  0            
320 0 0 0       if ( $_ eq 'full'
      0        
321             or $_ eq 'lineno'
322             or $_ eq 'hash_attribute_operation' ) {
323 0           next;
324             }
325 0 0 0       if ( $_ eq 'id'
326             or $_ eq 'version' ) {
327 0           $node->{$_} = $prev->{$_};
328 0           next;
329             }
330 0 0         if ($_ eq 'filename') {
331 0 0 0       if ( $prev->isa('ForwardStruct')
332             or $prev->isa('ForwardUnion') ) {
333 0 0         if ($prev->{$_} ne $node->{$_}) {
334 0           $self->{parser}->Error(
335             "Definition of '$name' is not in the same file.\n");
336             }
337             }
338 0           next;
339             }
340 0 0         if ($prev->{$_} ne $node->{$_}) {
341 0 0         if ($_ eq 'prefix') {
342 0 0         unless (defined $node->{_typeprefix}) {
343 0           $self->{parser}->Error(
344             "Prefix redefinition for '$name'.\n");
345             }
346 0           next;
347             }
348 0           $self->{parser}->Error(
349             "Definition of '$name' conflicts with previous declaration.\n");
350             }
351             }
352             }
353             }
354             else {
355 0 0         if ($prev->{idf} eq $name) {
356 0   0       $self->{msg} ||= "Identifier '$name' already exists.\n";
357             }
358             else {
359 0   0       $self->{msg} ||= "Identifier '$name' collides with '$prev->{idf}'.\n";
360             }
361 0           $self->{parser}->Error($self->{msg});
362 0           return;
363             }
364             }
365             # insert
366 0           $node->{full} = $scope . '::' . $name;
367 0           $self->{scopes}->{$scope}->_Insert($name, $node);
368 0           $self->_CheckCMapping($node->{full});
369 0           return;
370             }
371            
372             sub InsertForward {
373 0     0 0   my $self = shift;
374 0           my($node) = @_;
375 0           my $name = $node->{idf};
376 0 0         return unless ($name);
377 0           my $class = ref $node;
378 0           $class = substr $class, rindex($class, ':') + 1;
379             ## print "InsertForward '$name' '$node->{idf}'\n";
380 0 0         delete $self->{msg} if (exists $self->{msg});
381 0           my $scope = $self->{current_root} . $self->{current_scope};
382 0           my $prev = $self->{scopes}->{$scope}->_Lookup($name);
383 0 0         if (defined $prev) {
384 0           while ($prev->isa('Entry')) {
385 0           $prev = $self->{scopes}->{$prev->{scope}}->_Lookup($name);
386             }
387 0           my $class = ref $prev;
388 0           $class = substr $class, rindex($class, ':') + 1;
389 0 0         if ($class =~ /^Forward/) {
390             # redeclaration
391 0 0         if (ref $node ne ref $prev) {
392 0           $self->{parser}->Error(
393             "Definition of '$name' conflicts with previous declaration.\n");
394 0           return;
395             }
396             else {
397             # the previous must be the same
398 0           foreach (keys %{$prev}) {
  0            
399 0 0 0       if ( $_ eq 'full'
      0        
      0        
      0        
400             or $_ eq 'lineno'
401             or $_ eq 'filename'
402             or $_ eq 'typeprefix'
403             or $_ eq '_typeprefix' ) {
404 0           next;
405             }
406 0 0 0       if ( $_ eq 'id'
407             or $_ eq 'version' ) {
408 0           $node->{$_} = $prev->{$_};
409 0           next;
410             }
411 0 0         if ($prev->{$_} ne $node->{$_}) {
412 0 0         if ($_ eq 'prefix') {
413 0 0         unless (defined $node->{_typeprefix}) {
414 0           $self->{parser}->Error(
415             "Prefix redefinition for '$name'.\n");
416             }
417 0           next;
418             }
419 0           $self->{parser}->Error(
420             "Definition of '$name' conflicts with previous declaration.\n");
421 0           return;
422             }
423             }
424             }
425             }
426             else {
427 0   0       $self->{msg} ||= "Identifier '$name' already exists.\n";
428 0           $self->{parser}->Error($self->{msg});
429 0           return;
430             }
431             }
432             # insert
433 0           $node->{full} = $scope . '::' . $name;
434 0           $self->{scopes}->{$scope}->_Insert($name, $node);
435 0           return;
436             }
437            
438             sub InsertInherit {
439 0     0 0   my $self = shift;
440 0           my($node, $name, $full) = @_;
441             ## print "InsertInherit '$name' $full \n";
442            
443             # Insert
444 0 0         delete $self->{msg} if (exists $self->{msg});
445 0           my $scope = $self->{current_root} . $self->{current_scope};
446 0           my $prev = $self->{scopes}->{$scope}->_Lookup($name);
447 0 0         if (defined $prev) {
448 0           $self->{parser}->Error(__PACKAGE__ . "::InsertInherit: INTERNAL_ERROR ($full).\n");
449             }
450             else {
451 0           my $scope_base = $full;
452 0           $scope_base =~ s/::[0-9A-Z_a-z]+$//;
453 0           $self->{scopes}->{$scope}->_Insert($name, bless({'scope' => $scope_base}, 'Entry'));
454             }
455 0           return;
456             }
457            
458             sub InsertBogus {
459 0     0 0   my $self = shift;
460 0           my($node) = @_;
461 0           my $scope = $self->{current_root} . $self->{current_scope};
462 0           $node->{full} = $scope . '::_seq_';
463             }
464            
465             sub Lookup {
466 0     0 0   my $self = shift;
467 0           my($name) = @_;
468 0 0         delete $self->{msg} if (exists $self->{msg});
469 0 0         if (ref $name) {
470 0           warn __PACKAGE__,"::Lookup $name ",caller," PB\n";
471 0           return $name;
472             }
473 0           my $defn = $self->_Lookup($name);
474 0 0         if (defined $defn) {
475 0 0         $self->{parser}->Error($self->{msg}) if (exists $self->{msg});
476             }
477             else {
478             ## print __PACKAGE__,"::Lookup $name ",caller()," PB\n";
479 0           $self->{parser}->Error("Undefined symbol '$name'.\n");
480             }
481 0           return $defn;
482             }
483            
484             sub _Lookup {
485 0     0     my $self = shift;
486 0           my($name) = @_;
487 0           my $defn;
488             ## print "_Lookup: '$name'\n";
489 0 0         if (ref $name) {
490 0           warn __PACKAGE__,"::_Lookup $name ",caller," PB\n";
491 0           return $name;
492             }
493 0 0         return undef unless ($name);
494 0 0         if ($name =~ /^::/) {
    0          
495             # global name
496             ## print "_global name.\n";
497 0           return $self->___Lookup($name);
498             }
499             elsif ($name =~ /^[0-9A-Z_a-z]+$/) {
500             # identifier alone
501 0           my $scope_init = $self->{current_root} . $self->{current_scope};
502 0           my $scope = $scope_init;
503             ## print "_Lookup init : '$scope'\n";
504 0           while (1) {
505             # Section 3.15.3 Special Scoping Rules for Type Names
506 0           my $g_name = $scope . '::' . $name;
507 0           $defn = $self->__Lookup($scope, $g_name, $name);
508 0 0 0       last if (defined $defn || $scope eq '');
509 0           $scope =~ s/::[0-9A-Z_a-z]+$//;
510             ## print "_Lookup curr : '$scope'\n";
511             };
512 0 0         if (defined $defn) {
513             ## print "_found $name $scope_init $scope\n";
514 0           my $scope_real = $defn->{full};
515 0           $scope_real =~ s/::[0-9A-Z_a-z]+$//;
516 0           while ($scope_init ne $scope) {
517 0           my $node = $self->___Lookup($scope_init);
518 0 0 0       if ($defn->isa('Modules') or ! $node->isa('Modules')) {
519             ## print "_insert $name $scope_init $scope_real\n";
520 0           $self->{scopes}->{$scope_init}->_Insert($name, bless({'scope' => $scope_real}, 'Entry'));
521             }
522 0           $scope_init =~ s/::[0-9A-Z_a-z]+$//;
523             }
524             }
525 0           return $defn;
526             }
527             else {
528             # qualified name
529 0           my @list = split /::/, $name;
530 0           my $idf = pop @list;
531 0           my $scoped_name = $name;
532 0           $scoped_name =~ s/::[0-9A-Z_a-z]+$//;
533             ## print "_qualified name : '$scoped_name' '$idf'\n";
534 0           my $scope = $self->_Lookup($scoped_name); # recursive
535 0 0         if (defined $scope) {
536 0           $defn = $self->___Lookup($scope->{full} . '::' . $idf);
537             }
538 0           return $defn;
539             }
540             }
541            
542             sub __Lookup {
543 0     0     my $self = shift;
544 0           my ($scope, $g_name, $name) = @_;
545             ## print "__Lookup: '$scope' '$g_name' '$name'\n";
546 0           my $defn = $self->___Lookup($g_name);
547 0 0         return $defn if (defined $defn);
548 0 0         return undef unless($scope);
549 0           my $node = $self->___Lookup($scope);
550 0 0         if (defined $node) {
551             ## print "__inherit $node->{full}\n";
552 0           my @list;
553 0           foreach ($node->getInheritance()) {
554 0           my $base = $self->Lookup($_);
555 0 0         if (defined $base) {
556 0           $g_name = $base->{full} . '::' . $name;
557 0           $defn = $self->___Lookup($g_name);
558 0 0         if (defined $defn) {
559 0           my $found = 0;
560 0           foreach (@list) {
561 0 0         if ($defn == $_) {
562 0           $found = 1;
563 0           last;
564             }
565             }
566 0 0         push @list, $defn unless ($found);
567             }
568             }
569             }
570 0 0         if (@list) {
571 0 0         if (scalar @list > 1) {
572 0           $self->{parser}->Error("Ambiguous symbol '$name'.\n");
573             }
574 0           return pop @list;
575             }
576             }
577 0           return undef;
578             }
579            
580             sub ___Lookup {
581 0     0     my $self = shift;
582 0           my ($full) = @_;
583             ## print "___Lookup: '$full'\n";
584 0 0         if ($full =~ /^((?:::[0-9A-Z_a-z]+)*)::([0-9A-Z_a-z]+)$/) {
585 0 0         if (exists $self->{scopes}->{$1}) {
586 0           my $defn = $self->{scopes}->{$1}->_Lookup($2);
587 0 0         if (defined $defn) {
588 0           while ($defn->isa('Entry')) {
589 0           $defn = $self->{scopes}->{$defn->{scope}}->_Lookup($2);
590 0 0         last unless (defined $defn);
591             }
592 0 0         unless (defined $defn) {
593 0           $self->{parser}->Error(__PACKAGE__ . "::___Lookup: INTERNAL_ERROR ($full).\n");
594 0           return undef;
595             }
596 0 0         if ($defn->{idf} ne $2) {
597 0           $self->{msg} = "Identifier '$2' collides with '$defn->{idf}'.\n";
598             }
599             ## print "___found $defn->{full}\n";
600 0           return $defn;
601             }
602             else {
603             ## print "___not found '$2' in '$1'.\n";
604 0           return undef;
605             }
606             }
607             else {
608             ## print "___not found scope '$1'.\n";
609 0           return undef;
610             }
611             }
612             else {
613 0           $self->{parser}->Error(__PACKAGE__ . "::___Lookup: INTERNAL_ERROR not match ($full).\n");
614 0           return undef;
615             }
616             }
617            
618             sub PragmaID { # 10.7.5.1 The ID Pragma
619 0     0 0   my $self = shift;
620 0           my($name, $id) = @_;
621 0           my $node = $self->Lookup($name);
622 0 0         if (defined $node) {
623 0 0         if (exists $node->{typeid}) {
624 0           $self->{parser}->Warning("TypeId/pragma conflict for '$self->{idf}'.\n");
625             }
626 0 0         if (exists $node->{id}) {
627 0 0         $self->{parser}->Error("Repository ID redefinition for '$name'.\n")
628             unless ($id eq $node->{id});
629             }
630             else {
631 0           $node->{id} = $id;
632 0           $self->CheckID($node, $id);
633             }
634 0 0         if ($node->isa('Modules')) {
635 0           foreach (@{$node->{list_decl}}) {
  0            
636 0 0         if ($_->{filename} eq $self->{parser}->YYData->{filename}) {
637 0           $_->{id} = $id;
638             }
639             }
640             }
641             }
642             else {
643 0           $self->{parser}->Warning("Undefined symbol '$name' for '$id'.\n")
644             }
645             }
646            
647             sub CheckID {
648 0     0 0   my $self = shift;
649 0           my($node, $id) = @_;
650 0 0         if ($id =~ /^IDL:/) {
    0          
    0          
    0          
651             # 10.7.1 OMG IDL Format
652 0 0         if ($id =~ /^IDL:[0-9A-Za-z_:\.\/\-]+:([0-9]+)\.([0-9]+)/) {
653 0           my $version = $1 . '.' . $2;
654 0 0         if (exists $node->{version}) {
655 0 0         $self->{parser}->Error("Version redefinition for '$node->{idf}'.\n")
656             unless ($version eq $node->{version});
657             }
658             else {
659 0           $node->{version} = $version;
660             }
661             }
662             else {
663 0           $self->{parser}->Error("Bad IDL format for Repository ID '$id'.\n");
664             }
665             }
666             elsif ($id =~ /^RMI:/) {
667             # 10.7.2 RMI Hashed Format
668 0 0         $self->{parser}->Error("Bad RMI format for Repository ID '$id'.\n")
669             unless ($id =~ /^RMI:[0-9A-Za-z_\[\-\.\/\$\\]+:[0-9A-Fa-f]{16}(:[0-9A-Fa-f]{16})?/);
670             }
671             elsif ($id =~ /^DCE:/) {
672             # 10.7.3 DCE UUID Format
673 0 0         $self->{parser}->Error("Bad DCE format for Repository ID '$id'.\n")
674             unless ($id =~ /^DCE:[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}(:[0-9]+)?/);
675             }
676             elsif ($id =~ /^LOCAL:/) {
677             # 10.7.4 LOCAL Format
678             # followed by an arbitrary string.
679             }
680             }
681            
682             sub PragmaPrefix { # 10.7.5.2 The Prefix Pragma
683 0     0 0   my $self = shift;
684 0           my($prefix) = @_;
685 0           my $key_prefix = $self->{parser}->YYData->{filename} . $self->{current_root} . $self->{current_scope};
686 0           $self->{prefix}->{$key_prefix} = $prefix;
687             }
688            
689             sub GetPrefix {
690 0     0 0   my $self = shift;
691 0           my $scope = $self->{current_root} . $self->{current_scope};
692 0           my $key_prefix = $self->{parser}->YYData->{filename} . $scope;
693 0 0         if (exists $self->{prefix}->{$key_prefix}) {
694 0           return $self->{prefix}->{$key_prefix};
695             }
696             else {
697 0           return q{};
698             }
699             }
700            
701             sub GetTypePrefix {
702 0     0 0   my $self = shift;
703 0           my $scope = $self->{current_root} . $self->{current_scope};
704 0 0         if (exists $self->{typeprefix}->{$scope}) {
705 0           return $self->{typeprefix}->{$scope};
706             }
707             else {
708 0           return undef;
709             }
710             }
711            
712             sub PragmaVersion { # 10.7.5.3 The Version Pragma
713 0     0 0   my $self = shift;
714 0           my($name, $major, $minor) = @_;
715 0           my $version = $major . '.' . $minor;
716 0           my $node = $self->Lookup($name);
717 0 0         if (defined $node) {
718 0 0         if (exists $node->{version}) {
719 0 0         $self->{parser}->Error("Version redefinition for '$name'.\n")
720             unless ($version eq $node->{version});
721             }
722             else {
723 0           $node->{version} = $version;
724             }
725             }
726             }
727            
728             sub CheckForward {
729 0     0 0   my $self = shift;
730            
731 0           foreach my $scope (values %{$self->{scopes}}) {
  0            
732 0           foreach my $entry (values %{$scope->{entry}}) {
  0            
733 0 0         if ($entry->isa('_ForwardConstructedType')) {
734 0           $self->{parser}->Error("'$entry->{idf}' never defined.\n");
735             }
736             }
737             }
738             }
739            
740             sub CheckRepositoryID {
741 0     0 0   my $self = shift;
742            
743 0           foreach my $scope (values %{$self->{scopes}}) {
  0            
744 0           foreach my $entry (values %{$scope->{entry}}) {
  0            
745 0 0 0       if ($entry->isa('Modules') and exists $entry->{id}) {
746 0           foreach (@{$entry->{list_decl}}) {
  0            
747 0 0 0       if ( ! exists $_->{id}
748             or $_->{id} ne $entry->{id} ) {
749 0           $self->{parser}->Error("Repository ID inconsistent for '$entry->{idf}'.\n");
750             }
751             }
752             }
753             }
754             }
755             }
756            
757             sub Import {
758 0     0 0   my $self = shift;
759 0           my($node) = @_;
760            
761 0           my %imports = ($node->{value} => 1) ;
762 0           my $dirname = $self->{parser}->YYData->{opt_i};
763 0           my $fullname = $node->{value};
764 0           $fullname =~ s/::/_/g;
765 0           my $filename = $fullname . '.mod';
766 0 0         $filename = $dirname . '/' . $filename if ($dirname);
767 0           require $filename;
768 0           my $scope = eval('$main::' . $fullname);
769 0 0 0       if (defined $scope and $scope->isa('CORBA::IDL::Scope')) {
770 0           my $class = $scope->{class};
771 0 0 0       if ( $class eq 'CORBA::IDL::Module'
      0        
      0        
      0        
      0        
      0        
      0        
      0        
772             or $class eq 'CORBA::IDL::RegularInterface'
773             or $class eq 'CORBA::IDL::LocalInterface'
774             or $class eq 'CORBA::IDL::AbstractInterface'
775             or $class eq 'CORBA::IDL::RegularValue'
776             or $class eq 'CORBA::IDL::BoxedValue'
777             or $class eq 'CORBA::IDL::AbstractValue'
778             or $class eq 'CORBA::IDL::RegularEvent'
779             or $class eq 'CORBA::IDL::AbstractEvent' ) {
780 0           $self->{scopes}->{$node->{value}} = $scope;
781 0           my $root = $node->{value};
782 0           $root =~ s/::([0-9A-Z_a-z]+)$//;
783 0           my $name = lc $1;
784 0           $self->{scopes}->{$root}->_Insert($name, bless({'scope' => $node->{value}}, 'Entry'));
785 0           foreach (values %{$scope->{entry}}) {
  0            
786 0 0         next if (ref $_ ne 'Entry');
787 0 0         next if (exists $self->{scopes}->{$_->{scope}});
788 0           $self->_Import($_->{scope}, \%imports);
789             }
790 0           $node->{list_decl} = [ keys %imports ];
791             }
792             else {
793 0           $self->{parser}->Error("'$node->{value}' can't imported (bad type).\n");
794             }
795             }
796             else {
797 0           $self->{parser}->Error("Import: INTERNAL_ERROR ($node->{value}).\n");
798             }
799             }
800            
801             sub _Import {
802 0     0     my $self = shift;
803 0           my($full, $r_import) = @_;
804            
805 0           $r_import->{$full} = 1;
806 0           my $dirname = $self->{parser}->YYData->{opt_i};
807 0           my $fullname = $full;
808 0           $fullname =~ s/::/_/g;
809 0           my $filename = $fullname . '.mod';
810 0 0         $filename = $dirname . '/' . $filename if ($dirname);
811 0           require $filename;
812 0           my $scope = eval('$main::' . $fullname);
813 0 0 0       if (defined $scope and $scope->isa('CORBA::IDL::Scope')) {
814 0           $self->{scopes}->{$full} = $scope;
815 0           my $root = $full;
816 0           $root =~ s/::([0-9A-Z_a-z]+)$//;
817 0           my $name = lc $1;
818 0           $self->{scopes}->{$root}->_Insert($name, bless({'scope' => $full}, 'Entry'));
819 0           foreach (values %{$scope->{entry}}) {
  0            
820 0 0         next if (ref $_ ne 'Entry');
821 0 0         next if (exists $self->{scopes}->{$_->{scope}});
822 0           $self->_Import($_->{scope}, $r_import);
823             }
824             }
825             else {
826 0           $self->{parser}->Error("_Import: INTERNAL_ERROR ($full).\n");
827             }
828             }
829            
830             sub Export {
831 0     0 0   my $self = shift;
832 1     1   1298 use Data::Dumper;
  1         8532  
  1         372  
833            
834 0           my $dirname = $self->{parser}->YYData->{opt_i};
835 0 0         if ($dirname) {
836 0 0         unless (-d $dirname) {
837 0 0         mkdir $dirname
838             or die "can't create $dirname ($!).\n";
839             }
840             }
841 0           foreach my $scope (values %{$self->{scopes}}) {
  0            
842 0           my $fullname = $scope->{full};
843 0 0         next unless ($fullname);
844 0           $fullname =~ s/::/_/g;
845 0           my $filename = $fullname . '.mod';
846 0 0         $filename = $dirname . '/' . $filename if ($dirname);
847 0 0         open my $OUT, '>', $filename
848             or die "can't open $filename ($!).\n";
849 0           my $d = Data::Dumper->new([$scope], [$fullname]);
850 0           $d->Indent(1);
851             # $d->Indent(0);
852 0           $d->Purity(1);
853 0           print $OUT "package main;\n";
854 0           print $OUT $d->Dump();
855 0           close $OUT;
856             }
857             }
858            
859             sub Dump {
860 0     0 0   my $self = shift;
861 1     1   9 use Data::Dumper;
  1         2  
  1         437  
862            
863 0           my $d = Data::Dumper->new([$self->{scopes}], [qw(scopes)]);
864 0           $d->Indent(1);
865             # $d->Indent(0);
866 0           print $d->Dump();
867             }
868            
869             ##############################################################################
870            
871             package CORBA::IDL::UnnamedSymbtab;
872            
873             sub new {
874 0     0     my $proto = shift;
875 0   0       my $class = ref($proto) || $proto;
876 0           my($parser) = @_;
877 0           my $self = {};
878 0           bless $self, $class;
879 0           $self->{parser} = $parser;
880 0           $self->{entry} = {};
881 0           return $self;
882             }
883            
884             sub Insert {
885 0     0     my $self = shift;
886 0           my($name) = @_;
887             ## print "Insert '$name'\n";
888 0           my $key = lc $name;
889 0 0         if (exists $self->{entry}{$key}) {
890 0 0         if ($self->{entry}{$key} eq $name) {
891 0           $self->{parser}->Error(
892             "Identifier '$name' already exists.\n");
893             }
894             else {
895 0           $self->{parser}->Error(
896             "Identifier '$name' collides with '$self->{entry}{$key}'.\n");
897             }
898             }
899             else {
900 0           $self->{entry}{$key} = $name;
901             }
902 0           return;
903             }
904            
905             sub InsertUsed {
906 0     0     my $self = shift;
907 0 0         return if ($self->{parser}->YYData->{collision_allowed});
908 0           my($name) = @_;
909             ## print "InsertUsed '$name'\n";
910 0           my $key = lc $name;
911 0 0         $self->{entry}{$key} = $name unless (exists $self->{entry}{$key});
912 0           return;
913             }
914            
915             1;
916