Synopsis - Cross-Reference

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