1 /*
   2  * Copyright (c) 1999, 2000, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 /*
  26  * COMPONENT_NAME: idl.parser
  27  *
  28  * ORIGINS: 27
  29  *
  30  * Licensed Materials - Property of IBM
  31  * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999
  32  * RMI-IIOP v1.0
  33  *
  34  */
  35 
  36 package com.sun.tools.corba.se.idl;
  37 
  38 // NOTES:
  39 // -D57110<daz> Allow ID pragma directive to be applied to modules and update
  40 //  feature in accordance to CORBA 2.3.
  41 // -D59165<daz> Enable escaped identifiers when processing pragmas.
  42 // -f60858.1<daz> Support -corba option, level = 2.2: Accept identifiers that
  43 //  collide with keywords, in letter but not case, and issue a warning.
  44 // -d62023 <daz> support -noWarn option; suppress inappropriate warnings when
  45 //  parsing IBM-specific pragmas (#meta <interface_name> abstract).
  46 
  47 import java.io.File;
  48 import java.io.FileNotFoundException;
  49 import java.io.IOException;
  50 import java.math.BigInteger;
  51 import java.util.Enumeration;
  52 import java.util.Hashtable;
  53 import java.util.Stack;
  54 import java.util.Vector;
  55 
  56 import com.sun.tools.corba.se.idl.RepositoryID;
  57 
  58 import com.sun.tools.corba.se.idl.constExpr.*;
  59 
  60 /**
  61  * This class should be extended if new pragmas are desired.  If the
  62  * preprocessor encounters a pragma name which it doesn't recognize
  63  * (anything other than ID, prefix, or version), it calls the method
  64  * otherPragmas.  This is the only method which need be overridden.
  65  * The Preprocessor base class has a number of utility-like methods
  66  * which can be used by the overridden otherPragmas method.
  67  **/
  68 public class Preprocessor
  69 {
  70   /**
  71    * Public zero-argument constructor.
  72    **/
  73   Preprocessor ()
  74   {
  75   } // ctor
  76 
  77   /**
  78    *
  79    **/
  80   void init (Parser p)
  81   {
  82     parser  = p;
  83     symbols = p.symbols;
  84     macros  = p.macros;
  85   } // init
  86 
  87   /**
  88    *
  89    **/
  90   protected Object clone ()
  91   {
  92     return new Preprocessor ();
  93   } // clone
  94 
  95   /**
  96    *
  97    **/
  98   Token process (Token t) throws IOException, ParseException
  99   {
 100     token   = t;
 101     scanner = parser.scanner;
 102     // <f46082.40> Deactivate escaped identifier processing in Scanner while
 103     // preprocessing.
 104     //scanner.underscoreOK = true;
 105     scanner.escapedOK = false;
 106     try
 107     {
 108       switch (token.type)
 109       {
 110         case Token.Include:
 111           include ();
 112           break;
 113         case Token.If:
 114           ifClause ();
 115           break;
 116         case Token.Ifdef:
 117           ifdef (false);
 118           break;
 119         case Token.Ifndef:
 120           ifdef (true);
 121           break;
 122         case Token.Else:
 123           if (alreadyProcessedABranch.empty ())
 124             throw ParseException.elseNoIf (scanner);
 125           else if (((Boolean)alreadyProcessedABranch.peek ()).booleanValue ())
 126             skipToEndif ();
 127           else
 128           {
 129             alreadyProcessedABranch.pop ();
 130             alreadyProcessedABranch.push (new Boolean (true));
 131             token = scanner.getToken ();
 132           }
 133           break;
 134         case Token.Elif:
 135           elif ();
 136           break;
 137         case Token.Endif:
 138           if (alreadyProcessedABranch.empty ())
 139             throw ParseException.endNoIf (scanner);
 140           else
 141           {
 142             alreadyProcessedABranch.pop ();
 143             token = scanner.getToken ();
 144             break;
 145           }
 146         case Token.Define:
 147           define ();
 148           break;
 149         case Token.Undef:
 150           undefine ();
 151           break;
 152         case Token.Pragma:
 153           pragma ();
 154           break;
 155         case Token.Unknown:
 156           if (!parser.noWarn)
 157             ParseException.warning (scanner, Util.getMessage ("Preprocessor.unknown", token.name));
 158         case Token.Error:
 159         case Token.Line:
 160         case Token.Null:
 161           // ignore
 162         default:
 163           scanner.skipLineComment ();
 164           token = scanner.getToken ();
 165       }
 166     }
 167     catch (IOException e)
 168     {
 169       // <f46082.40> Underscore may now precede any identifier, so underscoreOK
 170       // is vestigal.  The Preprocessor must reset escapedOK so that Scanner
 171       // will process escaped identifiers according to specification.
 172       //scanner.underscoreOK = false;
 173       scanner.escapedOK = true;
 174       throw e;
 175     }
 176     catch (ParseException e)
 177     {
 178       // <f46082.40> See above.
 179       //scanner.underscoreOK = false;
 180       scanner.escapedOK = true;
 181       throw e;
 182     }
 183     // <f46082.40> See above.
 184     //scanner.underscoreOK = false;
 185     scanner.escapedOK = true;
 186     return token;
 187   } // process
 188 
 189   /**
 190    *
 191    **/
 192   private void include () throws IOException, ParseException
 193   {
 194     match (Token.Include);
 195     IncludeEntry include = parser.stFactory.includeEntry (parser.currentModule);
 196     include.sourceFile (scanner.fileEntry ());
 197     scanner.fileEntry ().addInclude (include);
 198     if (token.type == Token.StringLiteral)
 199       include2 (include);
 200     else if (token.type == Token.LessThan)
 201       include3 (include);
 202     else
 203     {
 204       int[] expected = {Token.StringLiteral, Token.LessThan};
 205       throw ParseException.syntaxError (scanner, expected, token.type);
 206     }
 207     if (parser.currentModule instanceof ModuleEntry)
 208       ((ModuleEntry)parser.currentModule).addContained (include);
 209     else if (parser.currentModule instanceof InterfaceEntry)
 210       ((InterfaceEntry)parser.currentModule).addContained (include);
 211   } // include
 212 
 213   /**
 214    *
 215    **/
 216   private void include2 (IncludeEntry include) throws IOException, ParseException
 217   {
 218     include.name ('"' + token.name + '"');
 219     include4 (include, token.name);
 220     match (Token.StringLiteral);
 221   } // include2
 222 
 223   /**
 224    *
 225    **/
 226   private void include3 (IncludeEntry include) throws IOException, ParseException
 227   {
 228     if (token.type != Token.LessThan)
 229       // match will throw an exception
 230       match (Token.LessThan);
 231     else
 232     {
 233       try
 234       {
 235         String includeFile = getUntil ('>');
 236         token = scanner.getToken ();
 237         include.name ('<' + includeFile + '>');
 238         include4 (include, includeFile);
 239         match (Token.GreaterThan);
 240       }
 241       catch (IOException e)
 242       {
 243         throw ParseException.syntaxError (scanner, ">", "EOF");
 244       }
 245     }
 246   } // include3
 247 
 248   /**
 249    *
 250    **/
 251   private void include4 (IncludeEntry include, String filename) throws IOException, ParseException
 252   {
 253     try
 254     {
 255       // If the #include is at the global scope, it is treated as
 256       // an import statement.  If it is within some other scope, it
 257       // is treated as a normal #include.
 258       boolean includeIsImport = parser.currentModule == parser.topLevelModule;
 259       //daz
 260       include.absFilename (Util.getAbsolutePath (filename, parser.paths));
 261       scanner.scanIncludedFile (include, getFilename (filename), includeIsImport);
 262     }
 263     catch (IOException e)
 264     {
 265       ParseException.generic (scanner, e.toString ());
 266     }
 267   } // include4
 268 
 269   /**
 270    *
 271    **/
 272   private void define () throws IOException, ParseException
 273   {
 274     match (Token.Define);
 275     if (token.equals (Token.Identifier))
 276     {
 277       String symbol = scanner.getStringToEOL ();
 278       symbols.put (token.name, symbol.trim ());
 279       match (Token.Identifier);
 280     }
 281     else if (token.equals (Token.MacroIdentifier))
 282     {
 283       symbols.put (token.name, '(' + scanner.getStringToEOL () . trim ());
 284       macros.addElement (token.name);
 285       match (Token.MacroIdentifier);
 286     }
 287     else
 288       throw ParseException.syntaxError (scanner, Token.Identifier, token.type);
 289   } // define
 290 
 291   /**
 292    *
 293    **/
 294   private void undefine () throws IOException, ParseException
 295   {
 296     match (Token.Undef);
 297     if (token.equals (Token.Identifier))
 298     {
 299       symbols.remove (token.name);
 300       macros.removeElement (token.name);
 301       match (Token.Identifier);
 302     }
 303     else
 304       throw ParseException.syntaxError (scanner, Token.Identifier, token.type);
 305   } // undefine
 306 
 307   /**
 308    *
 309    **/
 310   private void ifClause () throws IOException, ParseException
 311   {
 312     match (Token.If);
 313     constExpr ();
 314   } // ifClause
 315 
 316   /**
 317    *
 318    **/
 319   private void constExpr () throws IOException, ParseException
 320   {
 321     SymtabEntry dummyEntry = new SymtabEntry (parser.currentModule);
 322     dummyEntry.container (parser.currentModule);
 323     parser.parsingConditionalExpr = true;
 324     Expression boolExpr = booleanConstExpr (dummyEntry);
 325     parser.parsingConditionalExpr = false;
 326     boolean expr;
 327     if (boolExpr.value () instanceof Boolean)
 328       expr = ((Boolean)boolExpr.value ()).booleanValue ();
 329     else
 330       expr = ((Number)boolExpr.value ()).longValue () != 0;
 331     alreadyProcessedABranch.push (new Boolean (expr));
 332     if (!expr)
 333       skipToEndiforElse ();
 334   } // constExpr
 335 
 336   /**
 337    *
 338    **/
 339   Expression booleanConstExpr (SymtabEntry entry) throws IOException, ParseException
 340   {
 341     Expression expr = orExpr (null, entry);
 342     try
 343     {
 344       expr.evaluate ();
 345     }
 346     catch (EvaluationException e)
 347     {
 348       ParseException.evaluationError (scanner, e.toString ());
 349     }
 350     return expr;
 351   } // booleanConstExpr
 352 
 353   /**
 354    *
 355    **/
 356   private Expression orExpr (Expression e, SymtabEntry entry) throws IOException, ParseException
 357   {
 358     if (e == null)
 359       e = andExpr (null, entry);
 360     else
 361     {
 362       BinaryExpr b = (BinaryExpr)e;
 363       b.right (andExpr (null, entry));
 364       e.rep (e.rep () + b.right ().rep ());
 365     }
 366     if (token.equals (Token.DoubleBar))
 367     {
 368       match (token.type);
 369       BooleanOr or = parser.exprFactory.booleanOr (e, null);
 370       or.rep (e.rep () + " || ");
 371       return orExpr (or, entry);
 372     }
 373     else
 374       return e;
 375   } // orExpr
 376 
 377   /**
 378    *
 379    **/
 380   private Expression andExpr (Expression e, SymtabEntry entry) throws IOException, ParseException
 381   {
 382     if (e == null)
 383       e = notExpr (entry);
 384     else
 385     {
 386       BinaryExpr b = (BinaryExpr)e;
 387       b.right (notExpr (entry));
 388       e.rep (e.rep () + b.right ().rep ());
 389     }
 390     if (token.equals (Token.DoubleAmpersand))
 391     {
 392       match (token.type);
 393       BooleanAnd and = parser.exprFactory.booleanAnd (e, null);
 394       and.rep (e.rep () + " && ");
 395       return andExpr (and, entry);
 396     }
 397     else
 398       return e;
 399   } // andExpr
 400 
 401   /**
 402    *
 403    **/
 404   private Expression notExpr (/*boolean alreadySawExclamation, */SymtabEntry entry) throws IOException, ParseException
 405   {
 406     Expression e;
 407     if (token.equals (Token.Exclamation))
 408     {
 409       match (Token.Exclamation);
 410       e = parser.exprFactory.booleanNot (definedExpr (entry));
 411       e.rep ("!" + ((BooleanNot)e).operand ().rep ());
 412     }
 413     else
 414       e = definedExpr (entry);
 415     return e;
 416   } // notExpr
 417 
 418   /**
 419    *
 420    **/
 421   private Expression definedExpr (SymtabEntry entry) throws IOException, ParseException
 422   {
 423     if (token.equals (Token.Identifier) && token.name.equals ("defined"))
 424       match (Token.Identifier);
 425     return equalityExpr (null, entry);
 426   } // definedExpr
 427 
 428   /**
 429    *
 430    **/
 431   private Expression equalityExpr (Expression e, SymtabEntry entry) throws IOException, ParseException
 432   {
 433     if (e == null)
 434     {
 435       parser.token = token; // Since parser to parse, give it this token
 436       e = parser.constExp (entry);
 437       token = parser.token; // Since parser last parsed, get its token
 438     }
 439     else
 440     {
 441       BinaryExpr b = (BinaryExpr)e;
 442       parser.token = token; // Since parser to parse, give it this token
 443       Expression constExpr = parser.constExp (entry);
 444       token = parser.token; // Since parser last parsed, get its token
 445       b.right (constExpr);
 446       e.rep (e.rep () + b.right ().rep ());
 447     }
 448     if (token.equals (Token.DoubleEqual))
 449     {
 450       match (token.type);
 451       Equal eq = parser.exprFactory.equal (e, null);
 452       eq.rep (e.rep () + " == ");
 453       return equalityExpr (eq, entry);
 454     }
 455     else if (token.equals (Token.NotEqual))
 456     {
 457       match (token.type);
 458       NotEqual n = parser.exprFactory.notEqual (e, null);
 459       n.rep (e.rep () + " != ");
 460       return equalityExpr (n, entry);
 461     }
 462     else if (token.equals (Token.GreaterThan))
 463     {
 464       match (token.type);
 465       GreaterThan g = parser.exprFactory.greaterThan (e, null);
 466       g.rep (e.rep () + " > ");
 467       return equalityExpr (g, entry);
 468     }
 469     else if (token.equals (Token.GreaterEqual))
 470     {
 471       match (token.type);
 472       GreaterEqual g = parser.exprFactory.greaterEqual (e, null);
 473       g.rep (e.rep () + " >= ");
 474       return equalityExpr (g, entry);
 475     }
 476     else if (token.equals (Token.LessThan))
 477     {
 478       match (token.type);
 479       LessThan l = parser.exprFactory.lessThan (e, null);
 480       l.rep (e.rep () + " < ");
 481       return equalityExpr (l, entry);
 482     }
 483     else if (token.equals (Token.LessEqual))
 484     {
 485       match (token.type);
 486       LessEqual l = parser.exprFactory.lessEqual (e, null);
 487       l.rep (e.rep () + " <= ");
 488       return equalityExpr (l, entry);
 489     }
 490     else
 491       return e;
 492   } // equalityExpr
 493 
 494   /**
 495    *
 496    **/
 497   Expression primaryExpr (SymtabEntry entry) throws IOException, ParseException
 498   {
 499     Expression primary = null;
 500     switch (token.type)
 501     {
 502       case Token.Identifier:
 503         // If an identifier gets this far, it means that no
 504         // preprocessor variable was defined with that name.
 505         // Generate a FALSE boolean expr.
 506         //daz        primary = parser.exprFactory.terminal ("0", new Long (0));
 507         primary = parser.exprFactory.terminal ("0", BigInteger.valueOf (0));
 508         token = scanner.getToken ();
 509         break;
 510       case Token.BooleanLiteral:
 511       case Token.CharacterLiteral:
 512       case Token.IntegerLiteral:
 513       case Token.FloatingPointLiteral:
 514       case Token.StringLiteral:
 515         //daz        primary = parser.literal ();
 516         primary = parser.literal (entry);
 517         token = parser.token;
 518         break;
 519       case Token.LeftParen:
 520         match (Token.LeftParen);
 521         primary = booleanConstExpr (entry);
 522         match (Token.RightParen);
 523         primary.rep ('(' + primary.rep () + ')');
 524         break;
 525       default:
 526         int[] expected = {Token.Literal, Token.LeftParen};
 527         throw ParseException.syntaxError (scanner, expected, token.type);
 528     }
 529     return primary;
 530   } // primaryExpr
 531 
 532   /**
 533    *
 534    **/
 535   private void ifDefine (boolean inParens, boolean not) throws IOException, ParseException
 536   {
 537     if (token.equals (Token.Identifier))
 538       if ((not && symbols.containsKey (token.name)) || (!not && !symbols.containsKey (token.name)))
 539       {
 540         alreadyProcessedABranch.push (new Boolean (false));
 541         skipToEndiforElse ();
 542       }
 543       else
 544       {
 545         alreadyProcessedABranch.push (new Boolean (true));
 546         match (Token.Identifier);
 547         if (inParens)
 548           match (Token.RightParen);
 549       }
 550     else
 551       throw ParseException.syntaxError (scanner, Token.Identifier, token.type);
 552   } // ifDefine
 553 
 554   /**
 555    *
 556    **/
 557   private void ifdef (boolean not) throws IOException, ParseException
 558   {
 559     if (not)
 560       match (Token.Ifndef);
 561     else
 562       match (Token.Ifdef);
 563     if (token.equals (Token.Identifier))
 564       if ((not && symbols.containsKey (token.name)) || (!not && !symbols.containsKey (token.name)))
 565       {
 566         alreadyProcessedABranch.push (new Boolean (false));
 567         skipToEndiforElse ();
 568       }
 569       else
 570       {
 571         alreadyProcessedABranch.push (new Boolean (true));
 572         match (Token.Identifier);
 573       }
 574     else
 575       throw ParseException.syntaxError (scanner, Token.Identifier, token.type);
 576   } // ifdef
 577 
 578   /**
 579    *
 580    **/
 581   private void elif () throws IOException, ParseException
 582   {
 583     if (alreadyProcessedABranch.empty ())
 584       throw ParseException.elseNoIf (scanner);
 585     else if (((Boolean)alreadyProcessedABranch.peek ()).booleanValue ())
 586       skipToEndif ();
 587     else
 588     {
 589       match (Token.Elif);
 590       constExpr ();
 591     }
 592   } // elif
 593 
 594   /**
 595    *
 596    **/
 597   private void skipToEndiforElse () throws IOException, ParseException
 598   {
 599     while (!token.equals (Token.Endif) && !token.equals (Token.Else) && !token.equals (Token.Elif))
 600     {
 601       if (token.equals (Token.Ifdef) || token.equals (Token.Ifndef))
 602       {
 603         alreadyProcessedABranch.push (new Boolean (true));
 604         skipToEndif ();
 605       }
 606       else
 607         token = scanner.skipUntil ('#');
 608     }
 609     process (token);
 610   } // skipToEndiforElse
 611 
 612   /**
 613    *
 614    **/
 615   private void skipToEndif () throws IOException, ParseException
 616   {
 617     while (!token.equals (Token.Endif))
 618     {
 619       token = scanner.skipUntil ('#');
 620       if (token.equals (Token.Ifdef) || token.equals (Token.Ifndef))
 621       {
 622         alreadyProcessedABranch.push (new Boolean (true));
 623         skipToEndif ();
 624       }
 625     }
 626     alreadyProcessedABranch.pop ();
 627     match (Token.Endif);
 628   } // skipToEndif
 629 
 630   ///////////////
 631   // For Pragma
 632 
 633   /**
 634    *
 635    **/
 636   private void pragma () throws IOException, ParseException
 637   {
 638     match (Token.Pragma);
 639     String pragmaType = token.name;
 640 
 641     // <d59165> Enable escaped identifiers while processing pragma internals.
 642     // Don't enable until scanning pragma name!
 643     scanner.escapedOK = true;
 644     match (Token.Identifier);
 645 
 646     // Add pragma entry to container
 647     PragmaEntry pragmaEntry = parser.stFactory.pragmaEntry (parser.currentModule);
 648     pragmaEntry.name (pragmaType);
 649     pragmaEntry.sourceFile (scanner.fileEntry ());
 650     pragmaEntry.data (scanner.currentLine ());
 651     if (parser.currentModule instanceof ModuleEntry)
 652       ((ModuleEntry)parser.currentModule).addContained (pragmaEntry);
 653     else if (parser.currentModule instanceof InterfaceEntry)
 654       ((InterfaceEntry)parser.currentModule).addContained (pragmaEntry);
 655 
 656     // If the token was an identifier, then pragmaType WILL be non-null.
 657     if (pragmaType.equals ("ID"))
 658       idPragma ();
 659     else if (pragmaType.equals ("prefix"))
 660       prefixPragma ();
 661     else if (pragmaType.equals ("version"))
 662       versionPragma ();
 663 
 664     // we are adding extensions to the Sun's idlj compiler to
 665     // handle correct code generation for local Objects, where
 666     // the OMG is taking a long time to formalize stuff.  Good
 667     // example of this is poa.idl.  Two proprietory pragmas
 668     // sun_local and sun_localservant are defined.  sun_local
 669     // generates only Holder and Helper classes, where read
 670     // and write methods throw marshal exceptions.  sun_localservant
 671     // is to generate Helper, Holder, and only Skel with _invoke
 672     // throwing an exception, since it does not make sense for
 673     // local objects.
 674 
 675     else if (pragmaType.equals ("sun_local"))
 676       localPragma();
 677     else if (pragmaType.equals ("sun_localservant"))
 678       localServantPragma();
 679     else
 680     {
 681       otherPragmas (pragmaType, tokenToString ());
 682       token = scanner.getToken ();
 683     }
 684 
 685     scanner.escapedOK = false; // <d59165> Disable escaped identifiers.
 686   } // pragma
 687 
 688   // <d57110> Pragma ID can be appiled to modules and it is an error to
 689   // name a type in more than one ID pragma directive.
 690 
 691   private Vector PragmaIDs = new Vector ();
 692 
 693   private void localPragma () throws IOException, ParseException
 694   {
 695     // Before I can use a parser method, I must make sure it has the current token.
 696     parser.token = token;
 697     // this makes sense only for interfaces, if specified for modules,
 698     // parser should throw an error
 699     SymtabEntry anErrorOccurred = new SymtabEntry ();
 700     SymtabEntry entry = parser.scopedName (parser.currentModule, anErrorOccurred);
 701     // Was the indicated type found in the symbol table?
 702     if (entry == anErrorOccurred)
 703     {
 704         System.out.println("Error occured ");
 705       // Don't have to generate an error, scopedName already has.
 706       scanner.skipLineComment ();
 707       token = scanner.getToken ();
 708     }
 709     else
 710     {
 711       // by this time we have already parsed the ModuleName and the
 712       // pragma type, therefore setInterfaceType
 713       if (entry instanceof InterfaceEntry) {
 714           InterfaceEntry ent = (InterfaceEntry) entry;
 715           ent.setInterfaceType (InterfaceEntry.LOCAL_SIGNATURE_ONLY);
 716       }
 717       token = parser.token;
 718       String string = token.name;
 719       match (Token.StringLiteral);
 720       // for non-interfaces it doesn't make sense, so just ignore it
 721     }
 722   } // localPragma
 723 
 724   private void localServantPragma () throws IOException, ParseException
 725   {
 726     // Before I can use a parser method, I must make sure it has the current token.
 727     parser.token = token;
 728     // this makes sense only for interfaces, if specified for modules,
 729     // parser should throw an error
 730     SymtabEntry anErrorOccurred = new SymtabEntry ();
 731     SymtabEntry entry = parser.scopedName (parser.currentModule, anErrorOccurred);
 732 
 733     // Was the indicated type found in the symbol table?
 734     if (entry == anErrorOccurred)
 735     {
 736       // Don't have to generate an error, scopedName already has.
 737       scanner.skipLineComment ();
 738       token = scanner.getToken ();
 739         System.out.println("Error occured ");
 740     }
 741     else
 742     {
 743       // by this time we have already parsed the ModuleName and the
 744       // pragma type, therefore setInterfaceType
 745       if (entry instanceof InterfaceEntry) {
 746           InterfaceEntry ent = (InterfaceEntry) entry;
 747           ent.setInterfaceType (InterfaceEntry.LOCALSERVANT);
 748       }
 749       token = parser.token;
 750       String string = token.name;
 751       match (Token.StringLiteral);
 752       // for non-interfaces it doesn't make sense, so just ignore it
 753     }
 754   } // localServantPragma
 755 
 756 
 757   /**
 758    *
 759    **/
 760   private void idPragma () throws IOException, ParseException
 761   {
 762     // Before I can use a parser method, I must make sure it has the current token.
 763     parser.token = token;
 764 
 765     // <d57110> This flag will relax the restriction that the scopedNamed
 766     // in this ID pragma directive cannot resolve to a module.
 767     parser.isModuleLegalType (true);
 768     SymtabEntry anErrorOccurred = new SymtabEntry ();
 769     SymtabEntry entry = parser.scopedName (parser.currentModule, anErrorOccurred);
 770     parser.isModuleLegalType (false);  // <57110>
 771 
 772     // Was the indicated type found in the symbol table?
 773     if (entry == anErrorOccurred)
 774     {
 775       // Don't have to generate an error, scopedName already has.
 776       scanner.skipLineComment ();
 777       token = scanner.getToken ();
 778     }
 779     // <d57110>
 780     //else if (PragmaIDs.contains (entry))
 781     //{
 782     //  ParseException.badRepIDAlreadyAssigned (scanner, entry.name ());
 783     //  scanner.skipLineComment ();
 784     //  token = scanner.getToken ();
 785     //}
 786     else
 787     {
 788       token = parser.token;
 789       String string = token.name;
 790       // Do not match token until after raise exceptions, otherwise
 791       // incorrect messages will be emitted!
 792       if (PragmaIDs.contains (entry)) // <d57110>
 793       {
 794         ParseException.badRepIDAlreadyAssigned (scanner, entry.name ());
 795       }
 796       else if (!RepositoryID.hasValidForm (string)) // <d57110>
 797       {
 798         ParseException.badRepIDForm (scanner, string);
 799       }
 800       else
 801       {
 802         entry.repositoryID (new RepositoryID (string));
 803         PragmaIDs.addElement (entry); // <d57110>
 804       }
 805       match (Token.StringLiteral);
 806     }
 807   } // idPragma
 808 
 809   /**
 810    *
 811    **/
 812   private void prefixPragma () throws IOException, ParseException
 813   {
 814     String string = token.name;
 815     match (Token.StringLiteral);
 816     ((IDLID)parser.repIDStack.peek ()).prefix (string);
 817     ((IDLID)parser.repIDStack.peek ()).name ("");
 818   } // prefixPragma
 819 
 820   /**
 821    *
 822    **/
 823   private void versionPragma () throws IOException, ParseException
 824   {
 825     // Before I can use a parser method, I must make sure it has the current token.
 826     parser.token = token;
 827     // This flag will relax the restriction that the scopedNamed
 828     // in this Version pragma directive cannot resolve to a module.
 829     parser.isModuleLegalType (true);
 830     SymtabEntry anErrorOccurred = new SymtabEntry ();
 831     SymtabEntry entry = parser.scopedName (parser.currentModule, anErrorOccurred);
 832     // reset the flag to original value
 833     parser.isModuleLegalType (false);
 834     if (entry == anErrorOccurred)
 835     {
 836       // Don't have to generate an error, scopedName already has.
 837       scanner.skipLineComment ();
 838       token = scanner.getToken ();
 839     }
 840     else
 841     {
 842       token = parser.token;
 843       String string = token.name;
 844       match (Token.FloatingPointLiteral);
 845       if (entry.repositoryID () instanceof IDLID)
 846         ((IDLID)entry.repositoryID ()).version (string);
 847     }
 848   } // versionPragma
 849 
 850   private Vector pragmaHandlers = new Vector ();
 851 
 852   /**
 853    *
 854    **/
 855   void registerPragma (PragmaHandler handler)
 856   {
 857     pragmaHandlers.addElement (handler);
 858   } // registerPragma
 859 
 860   /**
 861    *
 862    **/
 863   private void otherPragmas (String pragmaType, String currentToken) throws IOException
 864   {
 865     for (int i = pragmaHandlers.size () - 1; i >= 0; --i)
 866     {
 867       PragmaHandler handler = (PragmaHandler)pragmaHandlers.elementAt (i);
 868       if (handler.process (pragmaType, currentToken))
 869                 break;
 870     }
 871   } // otherPragmas
 872 
 873   /*
 874    * These protected methods are used by extenders, by the code
 875    * which implements otherPragma.
 876    */
 877 
 878   /**
 879    * Get the current token.
 880    **/
 881   String currentToken ()
 882   {
 883     return tokenToString ();
 884   } // currentToken
 885 
 886   /**
 887    * This method, given an entry name, returns the entry with that name.
 888    * It can take fully or partially qualified names and returns the
 889    * appropriate entry defined within the current scope.  If no entry
 890    * exists, null is returned.
 891    **/
 892   SymtabEntry getEntryForName (String string)
 893   {
 894     boolean partialScope = false;
 895     boolean globalScope  = false;
 896 
 897     // Change all ::'s to /'s
 898     if (string.startsWith ("::"))
 899     {
 900       globalScope = true;
 901       string = string.substring (2);
 902     }
 903     int index = string.indexOf ("::");
 904     while (index >= 0)
 905     {
 906       partialScope = true;
 907       string = string.substring (0, index) + '/' + string.substring (index + 2);
 908       index = string.indexOf ("::");
 909     }
 910 
 911     // Get the entry for that string
 912     SymtabEntry entry = null;
 913     if (globalScope)
 914       entry = parser.recursiveQualifiedEntry (string);
 915     else if (partialScope)
 916       entry = parser.recursivePQEntry (string, parser.currentModule);
 917     else
 918       entry = parser.unqualifiedEntryWMod (string, parser.currentModule);
 919     return entry;
 920   } // getEntryForName
 921 
 922   /**
 923    * This method returns a string of all of the characters from the
 924    * input file from the current position up to, but not including,
 925    * the end-of-line character(s).
 926    **/
 927   String getStringToEOL () throws IOException
 928   {
 929     return scanner.getStringToEOL ();
 930   } // getStringToEOL
 931 
 932   /**
 933    * This method returns a string of all of the characters from the
 934    * input file from the current position up to, but not including,
 935    * the given character.  It encapsulates parenthesis and quoted strings,
 936    * meaning it does not stop if the given character is found within
 937    * parentheses or quotes.  For instance, given the input of
 938    * `start(inside)end', getUntil ('n') will return "start(inside)e"
 939    **/
 940   String getUntil (char c) throws IOException
 941   {
 942     return scanner.getUntil (c);
 943   } // getUntil
 944 
 945   private boolean lastWasMacroID = false;
 946 
 947   /**
 948    *
 949    **/
 950   private String tokenToString ()
 951   {
 952     if (token.equals (Token.MacroIdentifier))
 953     {
 954       lastWasMacroID = true;
 955       return token.name;
 956     }
 957     else if (token.equals (Token.Identifier))
 958       return token.name;
 959     else
 960       return token.toString ();
 961   } // tokenToString
 962 
 963   /**
 964    * This method returns the next token String from the input file.
 965    **/
 966   String nextToken () throws IOException
 967   {
 968     if (lastWasMacroID)
 969     {
 970       lastWasMacroID = false;
 971       return "(";
 972     }
 973     else
 974     {
 975       token = scanner.getToken ();
 976       return tokenToString ();
 977     }
 978   } // nextToken
 979 
 980   /**
 981    * This method assumes that the current token marks the beginning
 982    * of a scoped name.  It then parses the subsequent identifier and
 983    * double colon tokens, builds the scoped name, and finds the symbol
 984    * table entry with that name.
 985    **/
 986   SymtabEntry scopedName () throws IOException
 987   {
 988     boolean     globalScope  = false;
 989     boolean     partialScope = false;
 990     String      name         = null;
 991     SymtabEntry entry        = null;
 992     try
 993     {
 994       if (token.equals (Token.DoubleColon))
 995         globalScope = true;
 996       else
 997       {
 998         if (token.equals (Token.Object))
 999         {
1000           name = "Object";
1001           match (Token.Object);
1002         }
1003         else if (token.type == Token.ValueBase)
1004         {
1005           name = "ValueBase";
1006           match (Token.ValueBase);
1007         }
1008         else
1009         {
1010           name = token.name;
1011           match (Token.Identifier);
1012         }
1013       }
1014       while (token.equals (Token.DoubleColon))
1015       {
1016         match (Token.DoubleColon);
1017         partialScope = true;
1018         if (name != null)
1019           name = name + '/' + token.name;
1020         else
1021           name = token.name;
1022         match (Token.Identifier);
1023       }
1024       if (globalScope)
1025         entry = parser.recursiveQualifiedEntry (name);
1026       else if (partialScope)
1027         entry = parser.recursivePQEntry (name, parser.currentModule);
1028       else
1029         entry = parser.unqualifiedEntryWMod (name, parser.currentModule);
1030     }
1031     catch (ParseException e)
1032     {
1033       entry = null;
1034     }
1035     return entry;
1036   } // scopedName
1037 
1038   /**
1039    * Skip to the end of the line.
1040    **/
1041   void skipToEOL () throws IOException
1042   {
1043     scanner.skipLineComment ();
1044   } // skipToEOL
1045 
1046   /**
1047    * This method skips the data in the input file until the specified
1048    * character is encountered, then it returns the next token.
1049    **/
1050   String skipUntil (char c) throws IOException
1051   {
1052     if (!(lastWasMacroID && c == '('))
1053       token = scanner.skipUntil (c);
1054     return tokenToString ();
1055   } // skipUntil
1056 
1057   /**
1058    * This method displays a Parser Exception complete with line number
1059    * and position information with the given message string.
1060    **/
1061   void parseException (String message)
1062   {
1063     // <d62023> Suppress warnings
1064     if (!parser.noWarn)
1065       ParseException.warning (scanner, message);
1066   } // parseException
1067 
1068   // For Pragma
1069   ///////////////
1070   // For macro expansion
1071 
1072   /**
1073    *
1074    **/
1075   String expandMacro (String macroDef, Token t) throws IOException, ParseException
1076   {
1077     token = t;
1078     // Get the parameter values from the macro 'call'
1079     Vector parmValues = getParmValues ();
1080 
1081     // Get the parameter names from the macro definition
1082     // NOTE:  a newline character is appended here so that when
1083     // getStringToEOL is called, it stops scanning at the end
1084     // of this string.
1085     scanner.scanString (macroDef + '\n');
1086     Vector parmNames = new Vector ();
1087     macro (parmNames);
1088 
1089     if (parmValues.size () < parmNames.size ())
1090       throw ParseException.syntaxError (scanner, Token.Comma, Token.RightParen);
1091     else if (parmValues.size () > parmNames.size ())
1092       throw ParseException.syntaxError (scanner, Token.RightParen, Token.Comma);
1093 
1094     macroDef = scanner.getStringToEOL ();
1095     for (int i = 0; i < parmNames.size (); ++i)
1096       macroDef = replaceAll (macroDef, (String)parmNames.elementAt (i), (String)parmValues.elementAt (i));
1097     return removeDoublePound (macroDef);
1098   } // expandMacro
1099 
1100   // This method is only used by the macro expansion methods.
1101   /**
1102    *
1103    **/
1104   private void miniMatch (int type) throws ParseException
1105   {
1106     // A normal production would now execute:
1107     // match (type);
1108     // But match reads the next token.  I don't want to do that now.
1109     // Just make sure the current token is a 'type'.
1110     if (!token.equals (type))
1111       throw ParseException.syntaxError (scanner, type, token.type);
1112   } // miniMatch
1113 
1114   /**
1115    *
1116    **/
1117   private Vector getParmValues () throws IOException, ParseException
1118   {
1119     Vector values = new Vector ();
1120     if (token.equals (Token.Identifier))
1121     {
1122       match (Token.Identifier);
1123       miniMatch (Token.LeftParen);
1124     }
1125     else if (!token.equals (Token.MacroIdentifier))
1126       throw ParseException.syntaxError (scanner, Token.Identifier, token.type);
1127 
1128     if (!token.equals (Token.RightParen))
1129     {
1130       values.addElement (scanner.getUntil (',', ')').trim ());
1131       token = scanner.getToken ();
1132       macroParmValues (values);
1133     }
1134     return values;
1135   } // getParmValues
1136 
1137   /**
1138    *
1139    **/
1140   private void macroParmValues (Vector values) throws IOException, ParseException
1141   {
1142     while (!token.equals (Token.RightParen))
1143     {
1144       miniMatch (Token.Comma);
1145       values.addElement (scanner.getUntil (',', ')').trim ());
1146       token = scanner.getToken ();
1147     }
1148   } // macroParmValues
1149 
1150   /**
1151    *
1152    **/
1153   private void macro (Vector parmNames) throws IOException, ParseException
1154   {
1155     match (token.type);
1156     match (Token.LeftParen);
1157     macroParms (parmNames);
1158     miniMatch (Token.RightParen);
1159   } // macro
1160 
1161   /**
1162    *
1163    **/
1164   private void macroParms (Vector parmNames) throws IOException, ParseException
1165   {
1166     if (!token.equals (Token.RightParen))
1167     {
1168       parmNames.addElement (token.name);
1169       match (Token.Identifier);
1170       macroParms2 (parmNames);
1171     }
1172   } // macroParms
1173 
1174   /**
1175    *
1176    **/
1177   private void macroParms2 (Vector parmNames) throws IOException, ParseException
1178   {
1179     while (!token.equals (Token.RightParen))
1180     {
1181       match (Token.Comma);
1182       parmNames.addElement (token.name);
1183       match (Token.Identifier);
1184     }
1185   } // macroParms2
1186 
1187   /**
1188    *
1189    **/
1190   private String replaceAll (String string, String from, String to)
1191   {
1192     int index = 0;
1193     while (index != -1)
1194     {
1195       index = string.indexOf (from, index);
1196       if (index != -1)
1197       {
1198         if (!embedded (string, index, index + from.length ()))
1199           if (index > 0 && string.charAt(index) == '#')
1200             string = string.substring (0, index) + '"' + to + '"' + string.substring (index + from.length ());
1201           else
1202             string = string.substring (0, index) + to + string.substring (index + from.length ());
1203         index += to.length ();
1204       }
1205     }
1206     return string;
1207   } // replaceAll
1208 
1209   /**
1210    *
1211    **/
1212   private boolean embedded (String string, int index, int endIndex)
1213   {
1214     // Don't replace if found substring is not an independent id.
1215     // For example, don't replace "thither".indexOf ("it", 0)
1216     boolean ret    = false;
1217     char    preCh  = index == 0 ? ' ' : string.charAt (index - 1);
1218     char    postCh = endIndex >= string.length () - 1 ? ' ' : string.charAt (endIndex);
1219     if ((preCh >= 'a' && preCh <= 'z') || (preCh >= 'A' && preCh <= 'Z'))
1220       ret = true;
1221     else if ((postCh >= 'a' && postCh <= 'z') || (postCh >= 'A' && postCh <= 'Z') || (postCh >= '0' && postCh <= '9') || postCh == '_')
1222       ret = true;
1223     else
1224       ret = inQuotes (string, index);
1225     return ret;
1226   } // embedded
1227 
1228   /**
1229    *
1230    **/
1231   private boolean inQuotes (String string, int index)
1232   {
1233     int quoteCount = 0;
1234     for (int i = 0; i < index; ++i)
1235       if (string.charAt (i) == '"') ++quoteCount;
1236     // If there are an odd number of quotes before this region,
1237     // then this region is within quotes
1238     return quoteCount % 2 != 0;
1239   } // inQuotes
1240 
1241   /**
1242    * Remove any occurrences of ##.
1243    **/
1244   private String removeDoublePound (String string)
1245   {
1246     int index = 0;
1247     while (index != -1)
1248     {
1249       index = string.indexOf ("##", index);
1250       if (index != -1)
1251       {
1252         int startSkip = index - 1;
1253         int stopSkip  = index + 2;
1254         if (startSkip < 0)
1255           startSkip = 0;
1256         if (stopSkip >= string.length ())
1257           stopSkip = string.length () - 1;
1258         while (startSkip > 0 &&
1259                (string.charAt (startSkip) == ' ' ||
1260                string.charAt (startSkip) == '\t'))
1261           --startSkip;
1262         while (stopSkip < string.length () - 1 &&
1263                (string.charAt (stopSkip) == ' ' ||
1264                string.charAt (stopSkip) == '\t'))
1265           ++stopSkip;
1266         string = string.substring (0, startSkip + 1) + string.substring (stopSkip);
1267       }
1268     }
1269     return string;
1270   } // removeDoublePound
1271 
1272   // For macro expansion
1273   ///////////////
1274 
1275   /**
1276    *
1277    **/
1278   private String getFilename (String name) throws FileNotFoundException
1279   {
1280     String fullName = null;
1281     File file = new File (name);
1282     if (file.canRead ())
1283       fullName = name;
1284     else
1285     {
1286       Enumeration pathList = parser.paths.elements ();
1287       while (!file.canRead () && pathList.hasMoreElements ())
1288       {
1289         fullName = (String)pathList.nextElement () + File.separatorChar + name;
1290         file = new File (fullName);
1291       }
1292       if (!file.canRead ())
1293         throw new FileNotFoundException (name);
1294     }
1295     return fullName;
1296   } // getFilename
1297 
1298   /**
1299    *
1300    **/
1301   private void match (int type) throws IOException, ParseException
1302   {
1303     if (!token.equals (type))
1304       throw ParseException.syntaxError (scanner, type, token.type);
1305     token = scanner.getToken ();
1306 
1307     // <d62023> Added for convenience, but commented-out because there is
1308     // no reason to issue warnings for tokens scanned during preprocessing.
1309     // See issueTokenWarnings().
1310     //issueTokenWarnings ();
1311 
1312     //System.out.println ("Preprocessor.match token = " + token.type);
1313     //if (token.equals (Token.Identifier) || token.equals (Token.MacroIdentifier))
1314     //  System.out.println ("Preprocessor.match token name = " + token.name);
1315 
1316     // If the token is a defined thingy, scan the defined string
1317     // instead of the input stream for a while.
1318     if (token.equals (Token.Identifier) || token.equals (Token.MacroIdentifier))
1319     {
1320       String string = (String)symbols.get (token.name);
1321       if (string != null && !string.equals (""))
1322         // If this is a macro, parse the macro
1323         if (macros.contains (token.name))
1324         {
1325           scanner.scanString (expandMacro (string, token));
1326           token = scanner.getToken ();
1327         }
1328         // else this is just a normal define
1329         else
1330         {
1331           scanner.scanString (string);
1332           token = scanner.getToken ();
1333         }
1334     }
1335   } // match
1336 
1337   // <d62023>
1338   /**
1339    * Issue warnings about tokens scanned during preprocessing.
1340    **/
1341   private void issueTokenWarnings ()
1342   {
1343     if (parser.noWarn)
1344       return;
1345 
1346     // There are no keywords defined for preprocessing (only directives), so:
1347     //
1348     // 1.) Do not issue warnings for identifiers known to be keywords in
1349     //     another level of IDL.
1350     // 2.) Do not issue warnings for identifiers that collide with keywords
1351     //     in letter, but not case.
1352     // 3.) Do not issue warnings for deprecated keywords.
1353     //
1354     // Should we warn when a macro identifier replaces a keyword?  Hmmm.
1355 
1356     // Deprecated directives?  None to date.
1357     //if (token.isDirective () && token.isDeprecated ())
1358     //  ParseException.warning (scanner, Util.getMesage ("Deprecated.directive", token.name));
1359   } // issueTokenWarnings
1360 
1361   /**
1362    * This method is called when the parser encounters a left curly brace.
1363    * An extender of PragmaHandler may find scope information useful.
1364    * For example, the prefix pragma takes effect as soon as it is
1365    * encountered and stays in effect until the current scope is closed.
1366    * If a similar pragma extension is desired, then the openScope and
1367    * closeScope methods are available for overriding.
1368    * @param entry the symbol table entry whose scope has just been opened.
1369    *  Be aware that, since the scope has just been entered, this entry is
1370    *  incomplete at this point.
1371    **/
1372   void openScope (SymtabEntry entry)
1373   {
1374     for (int i = pragmaHandlers.size () - 1; i >= 0; --i)
1375     {
1376       PragmaHandler handler = (PragmaHandler)pragmaHandlers.elementAt (i);
1377       handler.openScope (entry);
1378     }
1379   } // openScope
1380 
1381   /**
1382    * This method is called when the parser encounters a right curly brace.
1383    * An extender of PragmaHandler may find scope information useful.
1384    * For example, the prefix pragma takes effect as soon as it is
1385    * encountered and stays in effect until the current scope is closed.
1386    * If a similar pragma extension is desired, then the openScope and
1387    * closeScope methods are available for overriding.
1388    * @param entry the symbol table entry whose scope has just been closed.
1389    **/
1390   void closeScope (SymtabEntry entry)
1391   {
1392     for (int i = pragmaHandlers.size () - 1; i >= 0; --i)
1393     {
1394       PragmaHandler handler = (PragmaHandler)pragmaHandlers.elementAt (i);
1395       handler.closeScope (entry);
1396     }
1397   } // closeScope
1398 
1399   private Parser    parser;
1400   private Scanner   scanner;
1401   private Hashtable symbols;
1402   private Vector    macros;
1403 
1404   // The logic associated with this stack is scattered above.
1405   // A concise map of the logic is:
1406   // case #if false, #ifdef false, #ifndef true
1407   //   push (false);
1408   //   skipToEndifOrElse ();
1409   // case #if true, #ifdef true, #ifndef false
1410   //   push (true);
1411   // case #elif <conditional>
1412   //   if (top == true)
1413   //     skipToEndif ();
1414   //   else if (conditional == true)
1415   //     pop ();
1416   //     push (true);
1417   //   else if (conditional == false)
1418   //     skipToEndifOrElse ();
1419   // case #else
1420   //   if (top == true)
1421   //     skipToEndif ();
1422   //   else
1423   //     pop ();
1424   //     push (true);
1425   // case #endif
1426   //   pop ();
1427   private        Stack  alreadyProcessedABranch = new Stack ();
1428                  Token  token;
1429 
1430   private static String indent = "";
1431 }