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