1 // -*- c++ -*-
2 // Package : omniidl
3 // idlscope.cc Created on: 1999/10/11
4 // Author : Duncan Grisby (dpg1)
5 //
6 // Copyright (C) 2004-2008 Apasphere Ltd
7 // Copyright (C) 1999 AT&T Laboratories Cambridge
8 //
9 // This file is part of omniidl.
10 //
11 // omniidl is free software; you can redistribute it and/or modify it
12 // under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program. If not, see http://www.gnu.org/licenses/
23 //
24 // Description:
25 //
26 // Scope manipulation
27
28 #include <idlscope.h>
29 #include <idlast.h>
30 #include <idlerr.h>
31 #include <idlutil.h>
32 #include <idlconfig.h>
33 #include <idlrepoId.h>
34
35 #include <string.h>
36
37 // Global Scope pointers
38 Scope* Scope::global_ = 0;
39 Scope* Scope::current_ = 0;
40
41 int n_builtins = 0;
42 static Decl** builtins = 0;
43
44
45 // ScopedName implementation
46 ScopedName::
ScopedName(const char * identifier,IDL_Boolean absolute)47 ScopedName(const char* identifier, IDL_Boolean absolute) :
48 absolute_(absolute)
49 {
50 Fragment* f = new Fragment(identifier);
51 scopeList_ = f;
52 last_ = f;
53 }
54
55 ScopedName::
ScopedName(const ScopedName * sn)56 ScopedName(const ScopedName* sn) :
57 scopeList_(0), last_(0), absolute_(sn->absolute())
58 {
59 const Fragment *f;
60
61 for (f = sn->scopeList(); f; f = f->next())
62 append(f->identifier());
63 }
64
65 ScopedName::
ScopedName(const ScopedName::Fragment * frags,IDL_Boolean absolute)66 ScopedName(const ScopedName::Fragment* frags, IDL_Boolean absolute) :
67 scopeList_(0), last_(0), absolute_(absolute)
68 {
69 const Fragment *f;
70
71 for (f = frags; f; f = f->next())
72 append(f->identifier());
73 }
74
75
76 ScopedName::
~ScopedName()77 ~ScopedName()
78 {
79 Fragment* f;
80 Fragment* g;
81
82 for (f = scopeList_; f; f = g) {
83 g = f->next_;
84 delete f;
85 }
86 }
87
88 char*
89 ScopedName::
toString(IDL_Boolean qualify) const90 toString(IDL_Boolean qualify) const
91 {
92 int i;
93 Fragment* f;
94
95 i = (qualify && absolute_) ? 2 : 0;
96
97 for (f = scopeList_; f; f = f->next())
98 i += strlen(f->identifier()) + 2;
99
100 char* str = new char [i-1];
101
102 if (qualify && absolute_) {
103 str[0] = ':'; str[1] = ':';
104 i = 2;
105 }
106 else
107 i = 0;
108
109 const char* fi;
110 for (f = scopeList_; f; f = f->next()) {
111
112 for (fi = f->identifier(); *fi; fi++, i++)
113 str[i] = *fi;
114
115 if (f->next()) {
116 str[i++] = ':'; str[i++] = ':';
117 }
118 }
119 str[i] = '\0';
120 return str;
121 }
122
123 IDL_Boolean
124 ScopedName::
equal(const ScopedName * sn) const125 equal(const ScopedName* sn) const
126 {
127 if (sn->absolute() != absolute()) return 0;
128
129 Fragment *ourf, *theirf;
130
131 // Compare fragments
132 for (ourf = scopeList(), theirf = sn->scopeList();
133 ourf && theirf;
134 ourf = ourf->next(), theirf = theirf->next()) {
135
136 if (strcmp(ourf->identifier(), theirf->identifier()) != 0)
137 return 0;
138 }
139
140 // If either name has fragments left, names aren't equal
141 if (ourf || theirf) return 0;
142
143 return 1;
144 }
145
146 void
147 ScopedName::
append(const char * identifier)148 append(const char* identifier)
149 {
150 Fragment* f = new Fragment(identifier);
151
152 if (last_)
153 last_->next_ = f;
154 else
155 scopeList_ = f;
156
157 last_ = f;
158 }
159
160
161 // Scope implementation
162
163 Scope::
164 Entry::
Entry(const Scope * container,EntryKind k,const char * identifier,Scope * scope,Decl * decl,IdlType * idltype,Scope::Entry * inh_from,const char * file,int line)165 Entry(const Scope* container, EntryKind k, const char* identifier,
166 Scope* scope, Decl* decl, IdlType* idltype,
167 Scope::Entry* inh_from, const char* file, int line)
168
169 : container_(container), kind_(k), identifier_(idl_strdup(identifier)),
170 scope_(scope), decl_(decl), idltype_(idltype), inh_from_(inh_from),
171 file_(idl_strdup(file)), line_(line), next_(0)
172 {
173 const ScopedName* sn = container->scopedName();
174
175 if (identifier) {
176 if (sn) {
177 scopedName_ = new ScopedName(sn);
178 scopedName_->append(identifier);
179 }
180 else
181 scopedName_ = new ScopedName(identifier, 1);
182 }
183 else
184 scopedName_ = 0;
185 }
186
187 Scope::
188 Entry::
~Entry()189 ~Entry()
190 {
191 if (scopedName_) delete scopedName_;
192 if (identifier_) delete [] identifier_;
193 if (file_) delete [] file_;
194 }
195
196 void
197 Scope::
198 EntryList::
merge(Scope::EntryList * ml)199 merge(Scope::EntryList* ml)
200 {
201 EntryList* l;
202 IDL_Boolean add;
203
204 for (; ml; ml = ml->tail()) {
205 add = 1;
206 for (l=this; l; l = l->tail()) {
207
208 if (ml->head() == l->head()) {
209 add = 0;
210 break;
211 }
212 }
213 if (add) append(new EntryList(ml->head()));
214 }
215 delete ml;
216 }
217
218
219 Scope::
Scope(Scope * parent,Scope::Kind k,IDL_Boolean nestedUse,const char * file,int line)220 Scope(Scope* parent, Scope::Kind k, IDL_Boolean nestedUse,
221 const char* file, int line)
222
223 : parent_(parent), kind_(k), identifier_(0), scopedName_(0),
224 nestedUse_(nestedUse), entries_(0), last_(0),
225 inherited_(0), valueInherited_(0)
226 {
227 if (parent)
228 nestedUse_ |= parent->nestedUse();
229 }
230
231 Scope::
Scope(Scope * parent,const char * identifier,Scope::Kind k,IDL_Boolean nestedUse,const char * file,int line)232 Scope(Scope* parent, const char* identifier, Scope::Kind k,
233 IDL_Boolean nestedUse,
234 const char* file, int line)
235
236 : parent_(parent), kind_(k), nestedUse_(nestedUse),
237 inherited_(0), valueInherited_(0)
238 {
239 const ScopedName* psn = 0;
240
241 if (identifier && identifier[0] == '_') ++identifier;
242 identifier_ = idl_strdup(identifier);
243
244 if (parent) {
245 psn = parent->scopedName();
246 nestedUse_ |= parent->nestedUse();
247 }
248
249 if (psn) {
250 scopedName_ = new ScopedName(psn);
251 scopedName_->append(identifier);
252 }
253 else
254 scopedName_ = new ScopedName(identifier, 1);
255
256 // Add PARENT entry
257 entries_ = new Entry(this, Entry::E_PARENT, identifier, 0, 0, 0, 0,
258 file, line);
259 last_ = entries_;
260 }
261
262 Scope::
~Scope()263 ~Scope()
264 {
265 Entry *e, *f;
266 for (e=entries_; e; e=f) {
267 f = e->next();
268 delete e;
269 }
270 if (identifier_) delete [] identifier_;
271 if (scopedName_) delete scopedName_;
272 }
273
274 void
275 Scope::
init()276 init()
277 {
278 const char* file = "<built in>";
279
280 assert(global_ == 0);
281
282 Prefix::newFile();
283
284 global_ = new Scope(0, Scope::S_GLOBAL, 0, file, 0);
285 current_ = global_;
286
287 Scope* s = global_->newModuleScope("CORBA", file, 1);
288 global_->addModule("CORBA", s, 0, file, 1);
289 startScope(s);
290 Prefix::newScope("CORBA");
291
292 n_builtins = 2;
293 assert (builtins == 0);
294 builtins = new Decl*[n_builtins];
295 builtins[0] = new Native(file, 2, 0, "TypeCode", BaseType::TypeCodeType);
296 builtins[1] = new Native(file, 3, 0, "Principal", BaseType::PrincipalType);
297
298 //s->addDecl("TypeCode", 0, builtins[0], BaseType::TypeCodeType, file, 2);
299 //s->addDecl("Principal", 0, builtins[1], BaseType::PrincipalType, file, 3);
300
301 Prefix::endScope();
302 endScope();
303
304 // Creating the Decls sets the most recent decl pointer; clear it here.
305 Decl::clear();
306
307 Prefix::endOuterFile();
308 }
309
310 void
311 Scope::
clear()312 clear()
313 {
314 assert(global_ != 0);
315 delete global_;
316 global_ = 0;
317
318 for (int i=0; i < n_builtins; i++)
319 delete builtins[i];
320
321 delete [] builtins;
322 builtins = 0;
323 }
324
325 void
326 Scope::
setInherited(InheritSpec * inherited,const char * file,int line)327 setInherited(InheritSpec* inherited, const char* file, int line)
328 {
329 inherited_ = inherited;
330
331 InheritSpec* is;
332 Entry* e;
333
334 for (is = inherited; is; is = is->next()) {
335 if (!is->scope()) continue; // Skip bad entries from earlier errors
336
337 for (e = is->scope()->entries(); e; e = e->next()) {
338
339 switch (e->kind()) {
340 case Entry::E_CALLABLE:
341 addInherited(e->identifier(), e->scope(), e->decl(), e, file, line);
342 break;
343 case Entry::E_INHERITED:
344 addInherited(e->identifier(), e->scope(), e->decl(), e->inh_from(),
345 file, line);
346 break;
347 default:
348 break;
349 }
350 }
351 }
352 }
353
354 void
355 Scope::
setInherited(ValueInheritSpec * inherited,const char * file,int line)356 setInherited(ValueInheritSpec* inherited, const char* file, int line)
357 {
358 valueInherited_ = inherited;
359
360 ValueInheritSpec* is;
361 Entry* e;
362
363 for (is = inherited; is; is = is->next()) {
364 if (!is->scope()) continue; // Skip bad entries from earlier errors
365
366 for (e = is->scope()->entries(); e; e = e->next()) {
367
368 switch (e->kind()) {
369 case Entry::E_CALLABLE:
370 addInherited(e->identifier(), e->scope(), e->decl(), e, file, line);
371 break;
372 case Entry::E_INHERITED:
373 addInherited(e->identifier(), e->scope(), e->decl(), e->inh_from(),
374 file, line);
375 break;
376 default:
377 break;
378 }
379 }
380 }
381 }
382
383 void
384 Scope::
appendEntry(Entry * e)385 appendEntry(Entry* e)
386 {
387 if (entries_) last_->next_ = e;
388 else entries_ = e;
389 last_ = e;
390 }
391
392 void
393 Scope::
startScope(Scope * s)394 startScope(Scope* s)
395 {
396 assert(s->parent() == current_);
397 current_ = s;
398 }
399
400 void
401 Scope::
endScope()402 endScope()
403 {
404 assert(current_ != 0);
405 current_ = current_->parent();
406 assert(current_ != 0);
407 }
408
409 // Scope creation functions
410
411 Scope*
412 Scope::
newModuleScope(const char * identifier,const char * file,int line)413 newModuleScope(const char* identifier, const char* file, int line)
414 {
415 // Only the global scope and modules can contain modules. The
416 // grammar enforces this
417 assert(kind() == S_GLOBAL || kind() == S_MODULE);
418
419 // If there is already a module entry for this name, return it
420 Entry* e = find(identifier);
421 if (e && e->kind() == Entry::E_MODULE)
422 return e->scope();
423
424 // If there was an entry but it wasn't a module, carry on anyway,
425 // since addModule() will report the error
426
427 return new Scope(this, identifier, S_MODULE, 0, file, line);
428 }
429
430 Scope*
431 Scope::
newInterfaceScope(const char * identifier,const char * file,int line)432 newInterfaceScope(const char* identifier, const char* file, int line)
433 {
434 assert(kind() == S_GLOBAL || kind() == S_MODULE);
435 return new Scope(this, identifier, S_INTERFACE, 1, file, line);
436 }
437
438 Scope*
439 Scope::
newStructScope(const char * identifier,const char * file,int line)440 newStructScope(const char* identifier, const char* file, int line)
441 {
442 assert(kind() != S_OPERATION);
443 return new Scope(this, identifier, S_STRUCT, 0, file, line);
444 }
445
446 Scope*
447 Scope::
newExceptionScope(const char * identifier,const char * file,int line)448 newExceptionScope(const char* identifier, const char* file, int line)
449 {
450 assert(kind() != S_OPERATION);
451 return new Scope(this, identifier, S_EXCEPTION, 0, file, line);
452 }
453
454 Scope*
455 Scope::
newUnionScope(const char * identifier,const char * file,int line)456 newUnionScope(const char* identifier, const char* file, int line)
457 {
458 assert(kind() != S_OPERATION);
459 return new Scope(this, identifier, S_UNION, 0, file, line);
460 }
461
462 Scope*
463 Scope::
newOperationScope(const char * file,int line)464 newOperationScope(const char* file, int line)
465 {
466 assert(kind() == S_INTERFACE || kind() == S_VALUE);
467 return new Scope(this, S_OPERATION, 0, file, line);
468 }
469
470 Scope*
471 Scope::
newValueScope(const char * identifier,const char * file,int line)472 newValueScope(const char* identifier, const char* file, int line)
473 {
474 assert(kind() == S_GLOBAL || kind() == S_MODULE);
475 return new Scope(this, identifier, S_VALUE, 1, file, line);
476 }
477
478
479 // Searching functions
480
481 Scope::Entry*
482 Scope::
find(const char * identifier) const483 find(const char* identifier) const
484 {
485 Entry* e;
486 if (identifier[0] == '_') ++identifier;
487 for (e = entries_; e; e = e->next()) {
488 if (!(strcmp(identifier, e->identifier())))
489 return e;
490 }
491 return 0;
492 }
493
494 Scope::Entry*
495 Scope::
iFind(const char * identifier) const496 iFind(const char* identifier) const
497 {
498 Entry* e;
499 if (identifier[0] == '_') ++identifier;
500 for (e = entries_; e; e = e->next()) {
501 if (Config::caseSensitive) {
502 if (!(strcmp(identifier, e->identifier())))
503 return e;
504 }
505 else {
506 if (!(strcasecmp(identifier, e->identifier())))
507 return e;
508 }
509 }
510 return 0;
511 }
512
513
514 Scope::EntryList*
515 Scope::
findWithInheritance(const char * identifier) const516 findWithInheritance(const char* identifier) const
517 {
518 const Entry* e;
519 EntryList* el = 0;
520 EntryList* in_el;
521
522 if (identifier[0] == '_') ++identifier;
523 if ((e = find(identifier))) {
524 switch (e->kind()) {
525 case Entry::E_MODULE:
526 case Entry::E_DECL:
527 case Entry::E_CALLABLE:
528 case Entry::E_INHERITED:
529 case Entry::E_INSTANCE:
530 el = new EntryList(e);
531 return el;
532 case Entry::E_USE:
533 case Entry::E_PARENT:
534 break;
535 }
536 }
537 // Not found locally -- try inherited scopes
538 for (InheritSpec* is = inherited_; is; is = is->next()) {
539 if (!is->scope()) continue; // Skip broken entries from earlier errors
540
541 in_el = is->scope()->findWithInheritance(identifier);
542
543 if (el)
544 el->merge(in_el);
545 else
546 el = in_el;
547 }
548 for (ValueInheritSpec* vis = valueInherited_; vis; vis = vis->next()) {
549 if (!vis->scope()) continue; // Skip broken entries from earlier errors
550
551 in_el = vis->scope()->findWithInheritance(identifier);
552
553 if (el)
554 el->merge(in_el);
555 else
556 el = in_el;
557 }
558 return el;
559 }
560
561 Scope::EntryList*
562 Scope::
iFindWithInheritance(const char * identifier) const563 iFindWithInheritance(const char* identifier) const
564 {
565 const Entry* e;
566 EntryList* el = 0;
567 EntryList* in_el;
568
569 if (identifier[0] == '_') ++identifier;
570 if ((e = iFind(identifier))) {
571 switch (e->kind()) {
572 case Entry::E_MODULE:
573 case Entry::E_DECL:
574 case Entry::E_CALLABLE:
575 case Entry::E_INHERITED:
576 case Entry::E_INSTANCE:
577 el = new EntryList(e);
578 return el;
579 case Entry::E_USE:
580 case Entry::E_PARENT:
581 break;
582 }
583 }
584 // Not found locally -- try inherited scopes
585 for (InheritSpec* is = inherited_; is; is = is->next()) {
586 if (!is->scope()) continue; // Skip broken entries from earlier errors
587
588 in_el = is->scope()->iFindWithInheritance(identifier);
589
590 if (el)
591 el->merge(in_el);
592 else
593 el = in_el;
594 }
595 for (ValueInheritSpec* vis = valueInherited_; vis; vis = vis->next()) {
596 if (!vis->scope()) continue; // Skip broken entries from earlier errors
597
598 in_el = vis->scope()->iFindWithInheritance(identifier);
599
600 if (el)
601 el->merge(in_el);
602 else
603 el = in_el;
604 }
605 return el;
606 }
607
608 const Scope::Entry*
609 Scope::
findScopedName(const ScopedName * sn,const char * file,int line) const610 findScopedName(const ScopedName* sn, const char* file, int line) const
611 {
612 const Scope* s;
613
614 // Start at relevant Scope
615 if (sn->absolute())
616 s = global();
617 else
618 s = this;
619
620 // Find entry for each name component
621 const Entry* e = 0;
622 EntryList* el;
623 ScopedName::Fragment* f = sn->scopeList();
624 const char* fid;
625
626 IDL_Boolean top_component = 1;
627
628 while (f) {
629 fid = f->identifier();
630 if (fid[0] == '_') fid++;
631
632 do {
633 el = s->iFindWithInheritance(fid);
634
635 e = 0;
636 if (el) {
637 e = el->head();
638
639 if (el->tail()) {
640 // Error -- ambiguous
641 if (file) {
642 char* ssn = sn->toString();
643 IdlError(file, line, "Ambiguous name '%s':", ssn);
644 delete [] ssn;
645
646 for (; el; el = el->tail()) {
647 char* ssn = el->head()->container()->scopedName()->toString();
648 IdlErrorCont(el->head()->file(), el->head()->line(),
649 "('%s' defined in '%s')",
650 el->head()->identifier(), ssn);
651 delete [] ssn;
652 }
653 }
654 delete el;
655 return 0;
656 }
657 delete el;
658 break;
659 }
660 } while (top_component && (s = s->parent()));
661 top_component = 0;
662
663 if (!e) {
664 if (file) {
665 char* ssn = sn->toString();
666 IdlError(file, line, "Error in look-up of '%s': '%s' not found",
667 ssn, fid);
668 delete [] ssn;
669 }
670 return 0;
671 }
672
673 if (strcmp(fid, e->identifier())) {
674 // Case clash
675 if (file) {
676 char* ssn = sn->toString();
677 IdlError(file, line, "Error in look-up of '%s': '%s' differs in case",
678 ssn, fid);
679 delete [] ssn;
680 ssn = e->scopedName()->toString();
681 IdlErrorCont(e->file(), e->line(), "from '%s' declared here", ssn);
682 delete [] ssn;
683 }
684 return 0;
685 }
686
687 f = f->next();
688 if (f) { // More name fragments: check that current entry forms a scope
689 s = e->scope();
690
691 if (!s) {
692 if (file) {
693 char* ssn = sn->toString();
694 IdlError(file, line,
695 "Error in look-up of '%s': '%s' does not form a scope",
696 ssn, e->identifier());
697 IdlErrorCont(e->file(), e->line(), "('%s' defined here)",
698 e->identifier());
699 delete [] ssn;
700 }
701 return 0;
702 }
703 }
704 }
705 return e;
706 }
707
708
709 const Scope::Entry*
710 Scope::
findForUse(const ScopedName * sn,const char * file,int line)711 findForUse(const ScopedName* sn, const char* file, int line)
712 {
713 const Entry* e = findScopedName(sn, file, line);
714 addUse(sn, file, line);
715 return e;
716 }
717
718
719 static ScopedName*
findRelativeScope(const ScopedName::Fragment * from,const ScopedName::Fragment * to,const Scope * fromScope,const Scope::Entry * target)720 findRelativeScope(const ScopedName::Fragment* from,
721 const ScopedName::Fragment* to,
722 const Scope* fromScope,
723 const Scope::Entry* target)
724 {
725 ScopedName* result = 0;
726
727 if (!to)
728 return 0;
729
730 if (from && !strcmp(from->identifier(), to->identifier())) {
731 // Top name components match -- recursively try next components
732 result = findRelativeScope(from->next(), to->next(), fromScope, target);
733 }
734
735 if (!result && fromScope) {
736 ScopedName* test = new ScopedName(to, 0);
737 const Scope::Entry* find = fromScope->findScopedName(test);
738
739 if (find == target)
740 result = test;
741 else
742 delete test;
743 }
744 return result;
745 }
746
747 ScopedName*
relativeScopedName(const ScopedName * from,const ScopedName * to)748 Scope::relativeScopedName(const ScopedName* from, const ScopedName* to)
749 {
750 if (!global_) {
751 // Haven't parsed any IDL yet!
752 return 0;
753 }
754
755 if ((from && !from->absolute()) || !to->absolute())
756 return 0;
757
758 const Scope* fromScope;
759
760 if (from) {
761 const Entry* fromEntry = global_->findScopedName(from);
762 if (!fromEntry) return 0;
763 fromScope = fromEntry->scope();
764 }
765 else
766 fromScope = global_;
767
768 const Entry* toEntry = global_->findScopedName(to);
769 if (!toEntry) return 0;
770
771 ScopedName* result = findRelativeScope(from ? from->scopeList() : 0,
772 to->scopeList(), fromScope, toEntry);
773
774 if (!result)
775 result = new ScopedName(to);
776
777 return result;
778 }
779
780
781 // Entry adding functions
782
783 void
784 Scope::
addUse(const ScopedName * sn,const char * file,int line)785 addUse(const ScopedName* sn, const char* file, int line)
786 {
787 if (!sn->absolute()) {
788 const char* id = sn->scopeList()->identifier();
789 if (id[0] == '_') ++id;
790
791 const Entry* clash = iFind(id);
792
793 if (clash) {
794 if (strcmp(id, clash->identifier())) {
795 char* ssn = sn->toString();
796 IdlError(file, line, "Use of '%s' clashes with identifier '%s'",
797 ssn, clash->identifier());
798 IdlErrorCont(clash->file(), clash->line(), "('%s' declared here)",
799 clash->identifier());
800 delete [] ssn;
801 }
802 // Else the identifier is being used in the same scope that it was
803 // declared, so don't mark it as used.
804 }
805 else {
806 Entry* ue = new Entry(this, Entry::E_USE, id, 0, 0, 0, 0, file, line);
807 appendEntry(ue);
808 if (parent_ && parent_->nestedUse()) parent_->addUse(sn, file, line);
809 }
810 }
811 }
812
813
814 void
815 Scope::
addModule(const char * identifier,Scope * scope,Decl * decl,const char * file,int line)816 addModule(const char* identifier, Scope* scope, Decl* decl,
817 const char* file, int line)
818 {
819 if (*identifier == '_')
820 ++identifier;
821 else
822 keywordClash(identifier, file, line);
823
824 Entry* clash = iFind(identifier);
825
826 if (clash) {
827 switch (clash->kind()) {
828 case Entry::E_MODULE:
829 {
830 if (!strcmp(identifier, clash->identifier())) {
831 return; // Reopening the module
832 }
833 IdlError(file, line,
834 "Declaration of module '%s' clashes with declaration "
835 "of module '%s'", identifier, clash->identifier());
836 IdlErrorCont(clash->file(), clash->line(),
837 "(module '%s' declared here)", clash->identifier());
838 break;
839 }
840 case Entry::E_DECL:
841 {
842 IdlError(file, line,
843 "Declaration of module '%s' clashes with declaration "
844 "of %s '%s'", identifier, clash->decl()->kindAsString(),
845 clash->identifier());
846 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)",
847 clash->decl()->kindAsString(), clash->identifier());
848 break;
849 }
850 case Entry::E_CALLABLE:
851 case Entry::E_INHERITED:
852 case Entry::E_INSTANCE:
853 case Entry::E_USE:
854 {
855 assert(0); // Should never reach here
856 }
857 case Entry::E_PARENT:
858 {
859 IdlError(file, line,
860 "Declaration of module '%s' clashes with name of "
861 "enclosing module '%s'", identifier, clash->identifier());
862 IdlErrorCont(clash->file(), clash->line(),
863 "(module '%s' declared here)", clash->identifier());
864 break;
865 }
866 }
867 }
868 Entry* e = new Entry(this, Entry::E_MODULE, identifier, scope,
869 decl, 0, 0, file, line);
870 appendEntry(e);
871 }
872
873
874 void
875 Scope::
addDecl(const char * identifier,Scope * scope,Decl * decl,IdlType * idltype,const char * file,int line)876 addDecl(const char* identifier, Scope* scope, Decl* decl, IdlType* idltype,
877 const char* file, int line)
878 {
879 if (*identifier == '_')
880 ++identifier;
881 else
882 keywordClash(identifier, file, line);
883
884 Entry* clash = iFind(identifier);
885
886 if (clash) {
887 switch (clash->kind()) {
888 case Entry::E_MODULE:
889 {
890 IdlError(file, line,
891 "Declaration of %s '%s' clashes with declaration "
892 "of module '%s'", decl->kindAsString(),
893 identifier, clash->identifier());
894 IdlErrorCont(clash->file(), clash->line(),
895 "(module '%s' declared here)", clash->identifier());
896 break;
897 }
898 case Entry::E_DECL:
899 {
900 IdlError(file, line,
901 "Declaration of %s '%s' clashes with earlier declaration "
902 "of %s '%s'", decl->kindAsString(), identifier,
903 clash->decl()->kindAsString(), clash->identifier());
904 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)",
905 clash->decl()->kindAsString(), clash->identifier());
906 break;
907 }
908 case Entry::E_CALLABLE:
909 {
910 IdlError(file, line,
911 "Declaration of %s '%s' clashes with %s '%s'",
912 decl->kindAsString(), identifier,
913 clash->decl()->kindAsString(), clash->identifier());
914 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)",
915 clash->decl()->kindAsString(), clash->identifier());
916 break;
917 }
918 case Entry::E_INHERITED:
919 {
920 IdlError(file, line,
921 "Declaration of %s '%s' clashes with inherited %s '%s'",
922 decl->kindAsString(), identifier,
923 clash->decl()->kindAsString(), clash->identifier());
924 char* inhfrom =
925 clash->inh_from()->container()->scopedName()->toString();
926 IdlErrorCont(clash->inh_from()->file(), clash->inh_from()->line(),
927 "('%s' declared in %s here)",
928 clash->identifier(), inhfrom);
929 delete [] inhfrom;
930 break;
931 }
932 case Entry::E_INSTANCE:
933 {
934 IdlError(file, line,
935 "Declaration of %s '%s' clashes with instance '%s'",
936 decl->kindAsString(), identifier, clash->identifier());
937 IdlErrorCont(clash->file(), clash->line(),
938 "('%s' declared here)", clash->identifier());
939 break;
940 }
941 case Entry::E_USE:
942 {
943 IdlError(file, line,
944 "Declaration of %s '%s' clashes with use of "
945 "identifier '%s'", decl->kindAsString(),
946 identifier, clash->identifier());
947 IdlErrorCont(clash->file(), clash->line(),
948 "('%s' used here)", clash->identifier());
949 break;
950 }
951 case Entry::E_PARENT:
952 {
953 IdlError(file, line,
954 "Declaration of %s '%s' clashes with name of "
955 "enclosing scope '%s'", decl->kindAsString(),
956 identifier, clash->identifier());
957 IdlErrorCont(clash->file(), clash->line(), "('%s' declared here)",
958 clash->identifier());
959 break;
960 }
961 }
962 }
963 Entry* e = new Entry(this, Entry::E_DECL, identifier, scope,
964 decl, idltype, 0, file, line);
965 appendEntry(e);
966 }
967
968
969 void
970 Scope::
addCallable(const char * identifier,Scope * scope,Decl * decl,const char * file,int line)971 addCallable(const char* identifier, Scope* scope, Decl* decl,
972 const char* file, int line)
973 {
974 if (*identifier == '_')
975 ++identifier;
976 else
977 keywordClash(identifier, file, line);
978
979 Entry* clash = iFind(identifier);
980
981 if (clash) {
982 switch (clash->kind()) {
983 case Entry::E_MODULE:
984 {
985 IdlError(file, line,
986 "Declaration of %s '%s' clashes with declaration "
987 "of module '%s'", decl->kindAsString(),
988 identifier, clash->identifier());
989 IdlErrorCont(clash->file(), clash->line(),
990 "(module '%s' declared here)", clash->identifier());
991 break;
992 }
993 case Entry::E_DECL:
994 {
995 IdlError(file, line,
996 "Declaration of %s '%s' clashes with earlier declaration "
997 "of %s '%s'", decl->kindAsString(), identifier,
998 clash->decl()->kindAsString(), clash->identifier());
999 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)",
1000 clash->decl()->kindAsString(), clash->identifier());
1001 break;
1002 }
1003 case Entry::E_CALLABLE:
1004 {
1005 IdlError(file, line,
1006 "Declaration of %s '%s' clashes with %s '%s'",
1007 decl->kindAsString(), identifier,
1008 clash->decl()->kindAsString(), clash->identifier());
1009 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)",
1010 clash->decl()->kindAsString(), clash->identifier());
1011 break;
1012 }
1013 case Entry::E_INHERITED:
1014 {
1015 IdlError(file, line,
1016 "Declaration of %s '%s' clashes with inherited %s '%s'",
1017 decl->kindAsString(), identifier,
1018 clash->decl()->kindAsString(), clash->identifier());
1019 char* inhfrom =
1020 clash->inh_from()->container()->scopedName()->toString();
1021 IdlErrorCont(clash->inh_from()->file(), clash->inh_from()->line(),
1022 "('%s' declared in %s here)",
1023 clash->identifier(), inhfrom);
1024 delete [] inhfrom;
1025 break;
1026 }
1027 case Entry::E_INSTANCE:
1028 {
1029 IdlError(file, line,
1030 "Declaration of %s '%s' clashes with instance '%s'",
1031 decl->kindAsString(), identifier, clash->identifier());
1032 IdlErrorCont(clash->file(), clash->line(),
1033 "('%s' declared here)", clash->identifier());
1034 break;
1035 }
1036 case Entry::E_USE:
1037 {
1038 IdlError(file, line,
1039 "Declaration of %s '%s' clashes with use of "
1040 "identifier '%s'", decl->kindAsString(),
1041 identifier, clash->identifier());
1042 IdlErrorCont(clash->file(), clash->line(),
1043 "('%s' used here)", clash->identifier());
1044 break;
1045 }
1046 case Entry::E_PARENT:
1047 {
1048 IdlError(file, line,
1049 "Declaration of %s '%s' clashes with name of "
1050 "enclosing scope '%s'", decl->kindAsString(),
1051 identifier, clash->identifier());
1052 IdlErrorCont(clash->file(), clash->line(), "('%s' declared here)",
1053 clash->identifier());
1054 break;
1055 }
1056 }
1057 }
1058 Entry* e = new Entry(this, Entry::E_CALLABLE, identifier, scope,
1059 decl, 0, 0, file, line);
1060 appendEntry(e);
1061 }
1062
1063
1064 void
1065 Scope::
addInherited(const char * id,Scope * scope,Decl * decl,Scope::Entry * inh_from,const char * file,int line)1066 addInherited(const char* id, Scope* scope, Decl* decl,
1067 Scope::Entry* inh_from, const char* file, int line)
1068 {
1069 if (*id == '_') ++id;
1070
1071 Entry* clash = iFind(id);
1072
1073 if (clash) {
1074 switch (clash->kind()) {
1075 case Entry::E_MODULE:
1076 case Entry::E_DECL:
1077 case Entry::E_CALLABLE:
1078 case Entry::E_INSTANCE:
1079 case Entry::E_USE:
1080 {
1081 assert(0); // Should never reach here
1082 }
1083 case Entry::E_INHERITED:
1084 {
1085 if (inh_from != clash->inh_from()) {
1086 IdlError(file, line, "In definition of '%s': clash between "
1087 "inherited identifiers '%s' and '%s'",
1088 identifier(), id, clash->identifier());
1089 char* inhfrom =
1090 inh_from->container()->scopedName()->toString();
1091 IdlErrorCont(inh_from->file(), inh_from->line(),
1092 "(%s '%s' declared in %s here)",
1093 decl->kindAsString(), id, inhfrom);
1094 delete [] inhfrom;
1095 inhfrom = clash->inh_from()->container()->scopedName()->toString();
1096 IdlErrorCont(clash->inh_from()->file(), clash->inh_from()->line(),
1097 "(%s '%s' declared in %s here)",
1098 clash->decl()->kindAsString(),
1099 clash->identifier(), inhfrom);
1100 delete [] inhfrom;
1101 }
1102 break;
1103 }
1104 case Entry::E_PARENT:
1105 {
1106 // It's not clear whether this is OK, but the spec doesn't say
1107 // it's definitely illegal
1108
1109 IdlWarning(file, line,
1110 "Inherited %s '%s' clashes with interface name '%s'",
1111 decl->kindAsString(), id, clash->identifier());
1112 IdlWarningCont(decl->file(), decl->line(),
1113 "(%s '%s' declared here)", decl->kindAsString(), id);
1114 break;
1115 }
1116 }
1117 }
1118 Entry* e = new Entry(this, Entry::E_INHERITED, id, scope,
1119 decl, 0, inh_from, file, line);
1120 appendEntry(e);
1121 }
1122
1123
1124 void
1125 Scope::
addInstance(const char * identifier,Decl * decl,IdlType * idltype,const char * file,int line)1126 addInstance(const char* identifier, Decl* decl, IdlType* idltype,
1127 const char* file, int line)
1128 {
1129 if (*identifier == '_')
1130 ++identifier;
1131 else
1132 keywordClash(identifier, file, line);
1133
1134 Entry* clash = iFind(identifier);
1135
1136 if (clash) {
1137 switch (clash->kind()) {
1138 case Entry::E_MODULE:
1139 {
1140 IdlError(file, line,
1141 "Instance identifier '%s' clashes with declaration "
1142 "of module '%s'", identifier, clash->identifier());
1143 IdlErrorCont(clash->file(), clash->line(),
1144 "(module '%s' declared here)", clash->identifier());
1145 break;
1146 }
1147 case Entry::E_DECL:
1148 {
1149 IdlError(file, line,
1150 "Instance identifier '%s' clashes with declaration "
1151 "of %s '%s'", identifier, clash->decl()->kindAsString(),
1152 clash->identifier());
1153 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)",
1154 clash->decl()->kindAsString(), clash->identifier());
1155 break;
1156 }
1157 case Entry::E_CALLABLE:
1158 {
1159 IdlError(file, line,
1160 "Instance identifier '%s' clashes with %s '%s'",
1161 identifier, clash->decl()->kindAsString(),
1162 clash->identifier());
1163 IdlErrorCont(clash->file(), clash->line(), "(%s '%s' declared here)",
1164 clash->decl()->kindAsString(), clash->identifier());
1165 break;
1166 }
1167 case Entry::E_INHERITED:
1168 {
1169 IdlError(file, line,
1170 "Instance identifier '%s' clashes with inherited %s '%s'",
1171 identifier, clash->decl()->kindAsString(),
1172 clash->identifier());
1173 char* inhfrom =
1174 clash->inh_from()->container()->scopedName()->toString();
1175 IdlErrorCont(clash->inh_from()->file(), clash->inh_from()->line(),
1176 "('%s' declared in %s here)",
1177 clash->identifier(), inhfrom);
1178 delete [] inhfrom;
1179 break;
1180 }
1181 case Entry::E_INSTANCE:
1182 {
1183 IdlError(file, line,
1184 "Instance identifier '%s' clashes with instance '%s'",
1185 identifier, clash->identifier());
1186 IdlErrorCont(clash->file(), clash->line(),
1187 "('%s' declared here)", clash->identifier());
1188 break;
1189 }
1190 case Entry::E_USE:
1191 {
1192 IdlError(file, line,
1193 "Instance identifier '%s' clashes with use of "
1194 "identifier '%s'", identifier, clash->identifier());
1195 IdlErrorCont(clash->file(), clash->line(),
1196 "('%s' used here)", clash->identifier());
1197 break;
1198 }
1199 case Entry::E_PARENT:
1200 {
1201 IdlError(file, line,
1202 "Instance identifier '%s' clashes with name of "
1203 "enclosing scope '%s'", identifier, clash->identifier());
1204 IdlErrorCont(clash->file(), clash->line(), "('%s' declared here)",
1205 clash->identifier());
1206 break;
1207 }
1208 }
1209 }
1210 Entry* e = new Entry(this, Entry::E_INSTANCE, identifier, 0,
1211 decl, idltype, 0, file, line);
1212 appendEntry(e);
1213 }
1214
1215
1216 void
1217 Scope::
remEntry(Scope::Entry * re)1218 remEntry(Scope::Entry* re)
1219 {
1220 if (entries_ == re) {
1221 entries_ = re->next();
1222 if (!entries_) last_ = 0;
1223 }
1224 else {
1225 Entry *e;
1226 for (e = entries_; e && (e->next() != re); e = e->next());
1227 assert(e != 0);
1228 e->next_ = re->next();
1229 if (!e->next_) last_ = e;
1230 }
1231 re->next_ = 0;
1232 delete re;
1233 }
1234
1235
1236 IDL_Boolean
1237 Scope::
keywordClash(const char * identifier,const char * file,int line)1238 keywordClash(const char* identifier, const char* file, int line)
1239 {
1240 static const char* keywords[] = {
1241 "abstract", "any", "attribute", "boolean", "case", "char", "const",
1242 "context", "custom", "default", "double", "enum", "exception",
1243 "factory", "FALSE", "fixed", "float", "in", "inout", "interface",
1244 "local", "long", "module", "native", "Object", "octet", "oneway",
1245 "out", "private", "public", "raises", "readonly", "sequence",
1246 "short", "string", "struct", "supports", "switch", "TRUE",
1247 "truncatable", "typedef", "union", "unsigned", "ValueBase",
1248 "valuetype", "void", "wchar", "wstring", 0
1249 };
1250
1251 static const char* new_keywords[] = {
1252 "component", "consumes", "emits", "eventtype", "finder", "getraises",
1253 "home", "import", "multiple", "primarykey", "provides", "publishes",
1254 "setraises", "typeid", "typeprefix", "uses", 0
1255 };
1256
1257 const char** k;
1258
1259 for (k = keywords; *k; k++) {
1260 if (Config::caseSensitive) {
1261 if (!strcmp(*k, identifier)) {
1262 IdlError(file, line, "Identifier '%s' is identical to keyword '%s'",
1263 identifier, *k);
1264 return 1;
1265 }
1266 }
1267 else {
1268 if (!strcasecmp(*k, identifier)) {
1269 IdlError(file, line, "Identifier '%s' clashes with keyword '%s'",
1270 identifier, *k);
1271 return 1;
1272 }
1273 }
1274 }
1275 for (k = new_keywords; *k; k++) {
1276 if (Config::caseSensitive) {
1277 if (!strcmp(*k, identifier)) {
1278 IdlWarning(file, line, "Identifier '%s' is identical to "
1279 "CORBA 3 keyword '%s'.", identifier, *k);
1280 return 1;
1281 }
1282 }
1283 else {
1284 if (!strcasecmp(*k, identifier)) {
1285 IdlWarning(file, line, "Identifier '%s' clashes with "
1286 "CORBA 3 keyword '%s'", identifier, *k);
1287 return 1;
1288 }
1289 }
1290 }
1291 return 0;
1292 }
1293