View Javadoc
1   /*
2    * Copyright (c) 1999, 2009, 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  // -F46082.51<daz> Remove -stateful feature.
40  // -D52042<daz> Allow floating-point constants to be initialized with
41  //  integral as well as floating-point literals.  No other variations allowed.
42  // -D58058<daz> Set index array type to long rather than array element type.
43  // -D56351<daz> Update computation of RepositoryIDs to CORBA 2.3 (see spec.).
44  // -D57110<daz> Provide method() to set/clear ability for scoped names to
45  //  resolve to modules.  Allows rep. ids to be assigned to modules.
46  // -D46094<daz> Prohibit exceptions from appearing wihtin structs, unions, exceptions.
47  // -D46094<daz> Prohibit attributes from appearing as operation parameter types,
48  //  operation return types, attribute types.
49  // -D59067<daz> Prohibit nested value boxes.
50  // -D59166<daz> Prohibit collisions between keywords and non-escaped identifiers.
51  // -D59809<daz> At Pigeonhole(), add map short name of CORBA types to long name
52  //  (e.g., CORBA/StringValue --> org/omg/CORBA/StringValue), which allows fully-
53  //  qualified CORBA type names to resolve successfully.
54  // -F60858.1<daz> Support "-corba" option, level <= 2.2: issue warning for
55  //  keyowrd collisions;
56  // -D60942<daz> Prohibit operations from appearing within parameter types.
57  // -D61643<daz> Repair pigeonhole() to correctly filter bad RepIDs.
58  // -D62023<daz> Support -noWarn option; Issue warnings when tokens are
59  //  deprecated keywords or keywords in greater release version.
60  // -D61919<daz> Emit entries for modules originally opened in #include files
61  //  appearing at global scope and then reopened in the main IDL file.  Only
62  //  types appearing in the main IDL source will be emitted.
63  
64  import java.io.EOFException;
65  import java.io.IOException;
66  
67  import java.util.Enumeration;
68  import java.util.Hashtable;
69  import java.util.Stack;
70  import java.util.Vector;
71  import java.util.List ;
72  import java.util.ArrayList ;
73  import java.util.Iterator ;
74  
75  import java.math.BigInteger;
76  
77  import com.sun.tools.corba.se.idl.constExpr.*;
78  
79  /**
80   *
81   **/
82  class Parser
83  {
84    /**
85     *
86     **/
87    Parser (Preprocessor preprocessor, Arguments arguments, Hashtable overrides,
88        Hashtable symtab, SymtabFactory stFac, ExprFactory exprFac, String [] genKeywords)
89    {
90      this.arguments = arguments;
91      noWarn         = arguments.noWarn; // <d62023>
92      corbaLevel     = arguments.corbaLevel; // <f60858.1>
93      paths          = arguments.includePaths;
94      symbols        = arguments.definedSymbols;
95      verbose        = arguments.verbose;
96      emitAll        = arguments.emitAll;
97      // <f46082.46.01>
98      cppModule      = arguments.cppModule;
99      // <f46082.51> Remove -stateful feature.
100     //parseStateful  = arguments.parseStateful;
101     overrideNames  = (overrides == null) ? new Hashtable () : overrides;
102     symbolTable    = (symtab == null) ? new Hashtable () : symtab;
103     keywords       = (genKeywords == null) ? new String [0] : genKeywords;
104     stFactory      = stFac;
105     exprFactory    = exprFac;
106     currentModule  = topLevelModule = new ModuleEntry ();
107     prep           = preprocessor;
108     repIDStack.push (new IDLID ());
109     addPrimEntries ();
110   } // ctor
111 
112   /**
113    *
114    **/
115   void parse (String file) throws IOException
116   {
117     IncludeEntry fileEntry = stFactory.includeEntry ();
118     fileEntry.name ('"' + file + '"');
119     try
120     {
121       // Set absolute file path
122       fileEntry.absFilename (Util.getAbsolutePath (file, paths));
123     }
124     catch (IOException ioe)
125     {}
126 
127     // <f46082.51> Remove -stateful feature.
128     //scanner = new Scanner (fileEntry, keywords, verbose, parseStateful, emitAll);
129     // <f60585.1> Support "-corba [level]" option.
130     //scanner = new Scanner (fileEntry, keywords, verbose, emitAll);
131     scanner = new Scanner (fileEntry, keywords, verbose, emitAll, corbaLevel,
132         arguments.scannerDebugFlag );
133     topLevelModule.sourceFile (fileEntry);
134 
135     // Prime the pump...
136     // Match handles preprocessor directives, so use match to
137     // call scanner.getToken just in case the first token is
138     // such a directive.  But match depends on the token
139     // already having a value, so fudge something.
140     token = new Token (0);
141     tokenHistory.insert (token); // Initialize look back buffer <26jul1997daz>.
142     try
143     {
144       match (0);
145       if (token.equals (Token.EOF))
146         ParseException.nothing (file);
147       else
148         specification (topLevelModule);
149     }
150     catch (ParseException exception)  // Match MIGHT throw this
151     {
152       // It has already been reported, just end.
153     }
154     catch (EOFException exception)  // skipToSemicolon MIGHT throw this
155     {
156       // It has already been reported, just end.
157     }
158   } // parse
159 
160   /**
161    *
162    **/
163   private void addPrimEntries ()
164   {
165     symbolTable.put ("short", stFactory.primitiveEntry ("short"));
166     symbolTable.put ("long", stFactory.primitiveEntry ("long"));
167     symbolTable.put ("long long", stFactory.primitiveEntry ("long long"));
168     symbolTable.put ("unsigned short", stFactory.primitiveEntry ("unsigned short"));
169     symbolTable.put ("unsigned long", stFactory.primitiveEntry ("unsigned long"));
170     symbolTable.put ("unsigned long long", stFactory.primitiveEntry ("unsigned long long"));
171     symbolTable.put ("char", stFactory.primitiveEntry ("char"));
172     symbolTable.put ("wchar", stFactory.primitiveEntry ("wchar"));
173     symbolTable.put ("float", stFactory.primitiveEntry ("float"));
174     //Support fixed type: symbolTable.put ("fixed", stFactory.primitiveEntry ("fixed"));
175     symbolTable.put ("double", stFactory.primitiveEntry ("double"));
176     symbolTable.put ("boolean", stFactory.primitiveEntry ("boolean"));
177     symbolTable.put ("octet", stFactory.primitiveEntry ("octet"));
178     symbolTable.put ("any", stFactory.primitiveEntry ("any"));
179 
180     InterfaceEntry object = stFactory.interfaceEntry();
181     object.name ("Object");
182     symbolTable.put ("Object", object);
183 
184     ValueEntry valueBase = stFactory.valueEntry();
185     valueBase.name ("ValueBase");
186     symbolTable.put ("ValueBase", valueBase);
187 
188     // put these same entries in the lowercase symbol table
189     lcSymbolTable.put ("short", stFactory.primitiveEntry ("short"));
190     lcSymbolTable.put ("long", stFactory.primitiveEntry ("long"));
191     lcSymbolTable.put ("long long", stFactory.primitiveEntry ("long long"));
192     lcSymbolTable.put ("unsigned short", stFactory.primitiveEntry ("unsigned short"));
193     lcSymbolTable.put ("unsigned long", stFactory.primitiveEntry ("unsigned long"));
194     lcSymbolTable.put ("unsigned long long", stFactory.primitiveEntry ("unsigned long long"));
195     lcSymbolTable.put ("char", stFactory.primitiveEntry ("char"));
196     lcSymbolTable.put ("wchar", stFactory.primitiveEntry ("wchar"));
197     lcSymbolTable.put ("float", stFactory.primitiveEntry ("float"));
198     // Support fixed type: lcSymbolTable.put ("fixed", stFactory.primitiveEntry ("fixed"));
199     lcSymbolTable.put ("double", stFactory.primitiveEntry ("double"));
200     lcSymbolTable.put ("boolean", stFactory.primitiveEntry ("boolean"));
201     lcSymbolTable.put ("octet", stFactory.primitiveEntry ("octet"));
202     lcSymbolTable.put ("any", stFactory.primitiveEntry ("any"));
203     lcSymbolTable.put ("object", object);
204     lcSymbolTable.put ("valuebase", valueBase);
205   } // addPrimEntries
206 
207   /**
208    *
209    **/
210   private void specification (ModuleEntry entry) throws IOException
211   {
212     while (!token.equals (Token.EOF))
213     {
214       definition (entry);
215       addToEmitList (entry);
216     }
217   } // specification
218 
219   // ModuleEntry is the topLevelModule; add its contained types to the emit list.
220   /**
221    *
222    **/
223   private void addToEmitList (ModuleEntry entry)
224   {
225     for (Enumeration e = entry.contained ().elements (); e.hasMoreElements();)
226     {
227       SymtabEntry emitEntry = (SymtabEntry)e.nextElement ();
228       if (emitEntry.emit ())
229       {
230         emitList.addElement (emitEntry);
231 
232         // <d61919> I think the absence of the following statement was an
233         // oversight.  If module X.Y.Z first appears in an include file, then is
234         // reopened in the main IDL source, this statement guarantees that X.Y.Z
235         // definitions within the main IDL source are emitted.
236         ///---------------------------------------------------------------------
237         // If any of this module's elements should be emitted, add
238         // this module to the emit list.
239         if (emitEntry instanceof ModuleEntry)
240           checkContained ((ModuleEntry)emitEntry);
241         if (emitEntry instanceof IncludeEntry)
242         {
243           includes.addElement (emitEntry.name ());
244           includeEntries.addElement (emitEntry);
245         }
246       }
247       else
248         // If any of this module's elements should be emitted, add
249         // this module to the emit list.
250         if (emitEntry instanceof ModuleEntry)
251           checkContained ((ModuleEntry)emitEntry);
252     }
253     entry.contained ().removeAllElements ();
254   } // addToEmitList
255 
256   /**
257    *
258    **/
259   private void checkContained (ModuleEntry entry)
260   {
261     // If any of this module's elements is to be emitted,
262     // then add the module to the emit list.
263     for (Enumeration e = entry.contained ().elements (); e.hasMoreElements ();)
264     {
265       SymtabEntry contained = (SymtabEntry)e.nextElement ();
266       if (contained instanceof ModuleEntry)
267         checkContained ((ModuleEntry)contained);
268       if (contained.emit ())
269       {
270         if (!emitList.contains (entry))
271           emitList.addElement (entry);
272         entry.emit (true);
273         break;
274       }
275     }
276   } // checkContained
277 
278   /**
279    *
280    **/
281   private void definition (ModuleEntry entry) throws IOException
282   {
283     try
284     {
285       switch (token.type)
286       {
287         case Token.Typedef:
288         case Token.Struct:
289         case Token.Union:
290         case Token.Enum:
291           typeDcl (entry);
292           break;
293         case Token.Const:
294           constDcl (entry);
295           break;
296         case Token.Native:
297           nativeDcl (entry);
298           break;
299         case Token.Exception:
300           exceptDcl (entry);
301           break;
302         case Token.Interface:
303           interfaceProd (entry, InterfaceEntry.NORMAL);
304           break;
305         case Token.Local:
306           match( Token.Local ) ;
307           if (token.type ==  Token.Interface)
308               interfaceProd( entry, InterfaceEntry.LOCAL ) ;
309           else
310               throw ParseException.syntaxError( scanner, new int[] {
311                   Token.Interface }, token.type ) ;
312           break ;
313         case Token.Module:
314           module (entry);
315           break;
316         case Token.Abstract:
317           match (Token.Abstract);
318           if (token.type == Token.Interface)
319             interfaceProd (entry, InterfaceEntry.ABSTRACT);
320           else if (token.type == Token.Valuetype)
321             valueProd (entry, true);
322           else
323             throw ParseException.syntaxError (scanner, new int[] {
324                 Token.Interface, Token.Valuetype }, token.type);
325           break;
326         case Token.Custom:
327         case Token.Valuetype:
328           valueProd (entry, false);
329           break;
330         default:
331           throw ParseException.syntaxError (scanner, new int[] {
332               Token.Typedef, Token.Struct,    Token.Union,     Token.Enum,
333               Token.Const,   Token.Exception, Token.Interface, Token.Valuetype,
334               Token.Module }, token.type);
335       }
336       match (Token.Semicolon);
337     }
338     catch (ParseException e)
339     {
340       skipToSemicolon ();
341     }
342   } // definition
343 
344   /**
345    *
346    **/
347   private void module (ModuleEntry entry) throws IOException, ParseException
348   {
349     match (Token.Module);
350     repIDStack.push (((IDLID)repIDStack.peek ()).clone ());
351     ModuleEntry newEntry = newModule (entry);
352     ((IDLID)repIDStack.peek ()).appendToName (newEntry.name ());
353     // comment must immediately precede "module" keyword
354     newEntry.comment (tokenHistory.lookBack (1).comment);
355     currentModule = newEntry;
356     match (Token.Identifier);
357     prep.openScope (newEntry);
358     match (Token.LeftBrace);
359     definition (newEntry);
360     while (!token.equals (Token.EOF) && !token.equals (Token.RightBrace))
361       definition (newEntry);
362     prep.closeScope (newEntry);
363     match (Token.RightBrace);
364     currentModule = entry;
365     repIDStack.pop ();
366   } // module
367 
368   /**
369    *
370    **/
371   private void interfaceProd (ModuleEntry entry, int interfaceType)
372       throws IOException, ParseException
373   {
374     match (Token.Interface);
375     String name = token.name;
376     match (Token.Identifier);
377     interface2 (entry, name, interfaceType);
378   } // interfaceProd
379 
380   /**
381    *
382    **/
383   private void interface2 (ModuleEntry module, String name, int interfaceType)
384       throws IOException, ParseException
385   {
386     if (token.type == Token.Colon || token.type == Token.LeftBrace) {
387         repIDStack.push (((IDLID)repIDStack.peek ()).clone ());
388         InterfaceEntry entry = stFactory.interfaceEntry (module,
389             (IDLID)repIDStack.peek ());
390         entry.sourceFile (scanner.fileEntry ());
391         entry.name (name);
392         entry.setInterfaceType(interfaceType);
393         // Comment must immediately precede "[local | abstract] interface" keyword
394         entry.comment (tokenHistory.lookBack (
395             entry.getInterfaceType() == InterfaceEntry.NORMAL ? 2 : 3).comment);
396 
397         if (!ForwardEntry.replaceForwardDecl (entry))
398             ParseException.badAbstract (scanner, entry.fullName ());
399         pigeonhole (module, entry);
400         ((IDLID)repIDStack.peek ()).appendToName (name);
401         currentModule = entry;
402         interfaceDcl (entry);
403         currentModule = module;
404         repIDStack.pop ();
405     } else  { // This is a forward declaration
406         ForwardEntry entry = stFactory.forwardEntry (module, (IDLID)repIDStack.peek ());
407         entry.sourceFile (scanner.fileEntry ());
408         entry.name (name);
409         entry.setInterfaceType(interfaceType);
410         // comment must immediately precede "interface" keyword.
411         entry.comment (tokenHistory.lookBack (
412             entry.getInterfaceType() == InterfaceEntry.NORMAL ? 2 : 3).comment);
413         pigeonhole (module, entry);
414     }
415   } // interface2
416 
417   /**
418    *
419    **/
420   private void interfaceDcl (InterfaceEntry entry) throws IOException, ParseException
421   {
422     if (token.type != Token.LeftBrace)
423         inheritanceSpec (entry);
424     else if (!entry.isAbstract ()) {
425         SymtabEntry objectEntry = qualifiedEntry ("Object");
426         SymtabEntry realOEntry  = typeOf (objectEntry);
427         if (objectEntry == null)
428             ;  // qualifiedEntry already generated an error message
429         else if (!isInterface(realOEntry))
430             ParseException.wrongType (scanner, overrideName ("Object"),
431                 "interface", objectEntry.typeName ());
432         else
433             entry.derivedFromAddElement (realOEntry, scanner);
434     }
435 
436     prep.openScope (entry);
437     match (Token.LeftBrace);
438     while (token.type != Token.RightBrace)
439         export (entry);
440     prep.closeScope (entry);
441     match (Token.RightBrace);
442   } // interfaceDcl
443 
444   /**
445    *
446    **/
447   private void export (InterfaceEntry entry) throws IOException
448   {
449     try
450     {
451       switch (token.type)
452       {
453         case Token.Typedef:
454         case Token.Struct:
455         case Token.Union:
456         case Token.Enum:
457           typeDcl (entry);
458           break;
459         case Token.Const:
460           constDcl (entry);
461           break;
462         case Token.Native:
463           nativeDcl (entry);
464           break;
465         case Token.Exception:
466           exceptDcl (entry);
467           break;
468         case Token.Readonly:
469         case Token.Attribute:
470           attrDcl (entry);
471           break;
472         case Token.Oneway:
473         case Token.Float:
474         case Token.Double:
475         case Token.Long:
476         case Token.Short:
477         case Token.Unsigned:
478         case Token.Char:
479         case Token.Wchar:
480         case Token.Boolean:
481         case Token.Octet:
482         case Token.Any:
483         case Token.String:
484         case Token.Wstring:
485         case Token.Identifier:
486         case Token.Object:
487         // <f46082.40> Value base type.
488         case Token.ValueBase:
489         case Token.DoubleColon:
490         case Token.Void:
491           opDcl (entry);
492           break;
493         // <f46082.51> Remove -stateful feature.
494         //case Token.State:       if (parseStateful) {
495         //                          stateDef (entry);
496         //                          break; }
497         default:
498           throw ParseException.syntaxError(scanner, new int [] {
499               Token.Typedef,  Token.Struct,      Token.Union,        Token.Enum,
500               Token.Const,    Token.Exception,   Token.Readonly,     Token.Attribute,
501               Token.Oneway,   Token.Float,       Token.Double,       Token.Long,
502               Token.Short,    Token.Unsigned,    Token.Char,         Token.Wchar,
503               Token.Boolean,  Token.Octet,       Token.Any,          Token.String,
504               Token.Wstring,  Token.Identifier,  Token.DoubleColon,  Token.Void,
505               Token.ValueBase }, token.type);
506       }
507       match (Token.Semicolon);
508     }
509     catch (ParseException exception)
510     {
511       skipToSemicolon ();
512     }
513   } // export
514 
515   private void inheritanceSpec (InterfaceEntry entry) throws IOException, ParseException
516   {
517     for (match (Token.Colon); ; match (Token.Comma)) {
518         SymtabEntry parent = scopedName (entry.container (),
519             stFactory.interfaceEntry ());
520         SymtabEntry realParent = typeOf (parent);
521 
522         if (isInterfaceOnly (realParent)) {
523             boolean isInterface = (realParent instanceof InterfaceEntry);
524             if (entry.derivedFrom ().contains (realParent))
525                 ParseException.alreadyDerived (scanner, realParent.fullName (), entry.fullName ());
526             else if (!entry.isAbstract () ||
527                 (((InterfaceType)realParent).getInterfaceType() == InterfaceType.ABSTRACT))
528                 entry.derivedFromAddElement (realParent, scanner);
529             else
530                 ParseException.nonAbstractParent (scanner, entry.fullName (), parent.fullName ());
531         } else if (isForward( realParent )) {
532             ParseException.illegalForwardInheritance( scanner,
533                 entry.fullName(), parent.fullName() ) ;
534         } else
535             ParseException.wrongType (scanner, parent.fullName (), "interface", entryName (parent));
536 
537         if ((parent instanceof InterfaceEntry) && (((InterfaceEntry)parent).state () != null))
538             if (entry.state () == null)
539                 entry.initState ();
540             else
541                 throw ParseException.badState (scanner, entry.fullName ());
542 
543         if (token.type != Token.Comma)
544             break;
545     }
546   } // inheritanceSpec
547 
548   // <57110> Member _moduleIsLegalType may be set by any feature to allow
549   // method scopedName() and any of its helper methods -- qualifiedName(),
550   // partlyQualifiedName(), and unqualifiedName() -- to return a ModuleEntry
551   // rather than a parse error in the event a name resolves to a module.  The
552   // flag must be cleared (set to false) to resume normal parsing behavior.
553   //
554   // Currently, this is used only when preprocessing the ID pragma directive.
555 
556   private boolean _isModuleLegalType = false;
557 
558   /**
559    *
560    **/
561   public boolean isModuleLegalType ()
562   {
563     return _isModuleLegalType;
564   }; // moduleIsLegaType
565 
566   /**
567    *
568    **/
569   public void isModuleLegalType (boolean b)
570   {
571     _isModuleLegalType = b;
572   }; // moduleIsLegalType
573 
574   /**
575    *
576    **/
577   SymtabEntry scopedName (SymtabEntry container,
578     SymtabEntry expected) throws IOException, ParseException
579   {
580     return scopedName( container, expected, true ) ;
581   }
582 
583   SymtabEntry scopedName (SymtabEntry container, SymtabEntry expected,
584     boolean mustBeReferencable ) throws IOException, ParseException
585   {
586     boolean globalScope  = false;
587     boolean partialScope = false;
588     String  name         = null;
589     if (token.type == Token.DoubleColon)
590       globalScope = true;
591     else
592     {
593       if (token.type == Token.Object)
594       {
595         name = "Object";
596         match (Token.Object);
597       }
598       else if (token.type == Token.ValueBase) // <f46082.40>
599       {
600         name = "ValueBase";
601         match (Token.ValueBase);
602       }
603       else
604       {
605         name = token.name;
606         match (Token.Identifier);
607       }
608     }
609     while (token.type == Token.DoubleColon)
610     {
611       match (Token.DoubleColon);
612       partialScope = true;
613       if (name != null)
614         name += '/' + token.name;
615       else name = token.name;
616         match (Token.Identifier);
617     }
618     SymtabEntry entry = null;
619     if (globalScope)
620       entry = qualifiedEntry (name);
621     else if (partialScope)
622       entry = partlyQualifiedEntry (name, container);
623     else
624       entry = unqualifiedEntry (name, container);
625 
626     if (entry == null)
627       // Make the entry the expected entry.  The generators will
628       // not be called now, since a semantic exception ocurred, but
629       // the parse has to finish and something valid has to be
630       // returned.
631       (entry = expected).name (name);
632     else if (!entry.isReferencable() && mustBeReferencable)
633       throw ParseException.illegalIncompleteTypeReference( scanner, name ) ;
634 
635     return entry;
636   } // scopedName
637 
638   private void valueProd (ModuleEntry entry, boolean isAbstract) throws IOException, ParseException
639   {
640     boolean isCustom = (token.type == Token.Custom);
641     if (isCustom)
642       match (Token.Custom);
643     match (Token.Valuetype);
644     String name = token.name;
645     match (Token.Identifier);
646 
647     switch (token.type)
648     {
649       case Token.LeftBrace:
650       case Token.Colon:
651       case Token.Supports:
652         value2 (entry, name, isAbstract, isCustom);
653         return;
654       case Token.Semicolon:
655         if (isCustom)
656           break;
657         valueForwardDcl (entry, name, isAbstract);
658         return;
659     }
660     if (isCustom)
661       throw ParseException.badCustom (scanner);
662     if (isAbstract)
663       throw ParseException.abstractValueBox (scanner);
664     valueBox (entry, name);
665   }  // valueProd
666 
667   /**
668    *
669    **/
670   private void value2 (ModuleEntry module, String name, boolean isAbstract,
671       boolean isCustom) throws IOException, ParseException
672   {
673     repIDStack.push (((IDLID)repIDStack.peek ()).clone ());
674     // The 'actual' repository ID will be calculated at the end of the
675     // parsing phase, since it is based on the entire contents of the
676     // declaration, and needs to have all forward references resolved:
677     ValueEntry entry = stFactory.valueEntry (module, (IDLID)repIDStack.peek ());
678     entry.sourceFile (scanner.fileEntry ());
679     entry.name (name);
680     entry.setInterfaceType (isAbstract ? InterfaceType.ABSTRACT : InterfaceType.NORMAL);
681     entry.setCustom (isCustom);
682     // Comment must immediately precede "[abstract | custom] value" keyword
683     entry.comment (tokenHistory.lookBack ((isAbstract || isCustom) ? 3 : 2).comment);
684     // If this value has been forward declared, there are probably
685     // other values which derive from a ForwardValueEntry.  Replace
686     // those ForwardValueEntry's with this ValueEntry:
687     if (!ForwardEntry.replaceForwardDecl (entry))
688       ParseException.badAbstract (scanner, entry.fullName ());
689     pigeonhole (module, entry);
690     ((IDLID)repIDStack.peek ()).appendToName (name);
691     currentModule = entry;
692     valueDcl (entry);
693     entry.tagMethods ();
694     currentModule = module;
695     repIDStack.pop ();
696   } // value2
697 
698   /**
699    *
700    **/
701   private void valueDcl (ValueEntry entry) throws IOException, ParseException
702   {
703     if (token.type == Token.Colon)
704       valueInheritanceSpec (entry);
705     else if (!entry.isAbstract ())
706     {
707       SymtabEntry objectEntry = qualifiedEntry ("ValueBase");
708       SymtabEntry realOEntry  = typeOf (objectEntry);
709       if (objectEntry == null)
710         ; // qualifiedEntry already generated an error message
711       else if (!isValue (realOEntry))
712         ParseException.wrongType (scanner, overrideName ("ValueBase"), "value", objectEntry.typeName ());
713       else
714         entry.derivedFromAddElement (realOEntry, false, scanner);
715     }
716     if (token.type == Token.Supports)
717       valueSupportsSpec (entry);
718     prep.openScope (entry);
719     match (Token.LeftBrace);
720     while (token.type != Token.RightBrace)
721     {
722       valueElement (entry);
723     }
724     prep.closeScope (entry);
725     match (Token.RightBrace);
726   } // valueDcl
727 
728   /**
729    *
730    **/
731   private void valueInheritanceSpec (ValueEntry entry) throws IOException, ParseException
732   {
733     match (Token.Colon);
734     boolean isTruncatable = (token.type == Token.Truncatable);
735     if (isTruncatable)
736         match (Token.Truncatable);
737     for (; ; match (Token.Comma), isTruncatable = false) {
738         SymtabEntry parent = scopedName (entry.container (),
739             stFactory.valueEntry ());
740         SymtabEntry realParent = typeOf (parent);
741         if (isValue (realParent) && !(realParent instanceof ValueBoxEntry))
742             entry.derivedFromAddElement (realParent, isTruncatable,
743                 scanner);
744         else if (isForward(realParent))
745             ParseException.illegalForwardInheritance( scanner,
746                 entry.fullName(), parent.fullName() ) ;
747         else
748             ParseException.wrongType (scanner,
749                 parent.fullName (), "value", entryName (parent));
750         if (token.type != Token.Comma)
751             break;
752     }
753   } // valueInheritanceSpec
754 
755   /**
756    *
757    **/
758   private void valueSupportsSpec (ValueEntry entry) throws IOException, ParseException
759   {
760     match (Token.Supports) ;
761     for (; ; match( Token.Comma ) ) {
762         SymtabEntry parent = scopedName (entry.container (), stFactory.interfaceEntry ());
763         SymtabEntry realParent = typeOf (parent);
764         if (isInterface(realParent))
765             entry.derivedFromAddElement (realParent, scanner);
766         else
767             ParseException.wrongType (scanner, parent.fullName (), "interface",
768                 entryName (parent));
769 
770         if (token.type != Token.Comma)
771             break;
772     }
773   }  // valueSupportsSpec
774 
775   private void valueElement (ValueEntry entry) throws IOException, ParseException
776   {
777     if (entry.isAbstract ())
778       export (entry);
779     else
780       switch (token.type)
781       {
782         case Token.Private:
783         case Token.Public:
784           valueStateMember (entry);
785           break;
786         case Token.Init:
787         case Token.Factory:  // <d62023> "factory" supplants "init" in 2.4RTF
788           initDcl (entry);
789           break;
790         case Token.Typedef:
791         case Token.Struct:
792         case Token.Union:
793         case Token.Enum:
794         case Token.Const:
795         case Token.Native:
796         case Token.Exception:
797         case Token.Readonly:
798         case Token.Attribute:
799         case Token.Oneway:
800         case Token.Float:
801         case Token.Double:
802         case Token.Long:
803         case Token.Short:
804         case Token.Unsigned:
805         case Token.Char:
806         case Token.Wchar:
807         case Token.Boolean:
808         case Token.Octet:
809         case Token.Any:
810         case Token.String:
811         case Token.Wstring:
812         case Token.Identifier:
813         case Token.Object:
814         case Token.ValueBase:
815         case Token.DoubleColon:
816         case Token.Void:
817           export (entry);
818           break;
819         default:
820           throw ParseException.syntaxError(scanner, new int[] {
821               Token.Private,  Token.Public,      Token.Init,         Token.ValueBase,
822               Token.Typedef,  Token.Struct,      Token.Union,        Token.Enum,
823               Token.Const,    Token.Exception,   Token.Readonly,     Token.Attribute,
824               Token.Oneway,   Token.Float,       Token.Double,       Token.Long,
825               Token.Short,    Token.Unsigned,    Token.Char,         Token.Wchar,
826               Token.Boolean,  Token.Octet,       Token.Any,          Token.String,
827               Token.Wstring,  Token.Identifier,  Token.DoubleColon,  Token.Void },
828               token.type);
829       }  // switch
830   }  // valueElement
831 
832   // <f46082.40>
833   /**
834    *
835    **/
836   private void valueStateMember (ValueEntry entry) throws IOException, ParseException
837   {
838     TypedefEntry typedefEntry =
839         stFactory.typedefEntry (entry, (IDLID)repIDStack.peek ());
840     typedefEntry.sourceFile (scanner.fileEntry ());
841     // comment must immediately precede "public", "private" keywords
842     typedefEntry.comment (token.comment);
843     boolean isPublic = (token.type == Token.Public);
844     if (isPublic)
845       match (Token.Public);
846     else
847       match (Token.Private);
848     // <f46082.40> Add constructed types declared "inline" to the contained
849     // vector of this value entry.
850     boolean isConstTypeSpec =
851         (token.type == Token.Struct || token.type == Token.Union || token.type == Token.Enum);
852     // <f46082.40> Make typedefEntry anonymous.  If this line is removed,
853     // the entry will be named incorrectly.  See <d50618>.
854     typedefEntry.name ("");
855     typedefEntry.type (typeSpec (typedefEntry));
856     addDeclarators (entry, typedefEntry, isPublic);
857     // <f46082.40>
858     if (isConstTypeSpec)
859       entry.addContained (typedefEntry);
860     match (Token.Semicolon);
861   }  // valueStateMember
862 
863 
864   private void addDeclarators (ValueEntry entry, TypedefEntry typedefEntry,
865       boolean isPublic) throws IOException, ParseException
866   {
867     int modifier = isPublic ? InterfaceState.Public : InterfaceState.Private;
868     try
869     {
870       Vector typedefList = new Vector ();
871       declarators (typedefEntry, typedefList);
872       for (Enumeration e = typedefList.elements (); e.hasMoreElements ();)
873         entry.addStateElement (
874             new InterfaceState (modifier, (TypedefEntry)e.nextElement ()), scanner);
875     }
876     catch (ParseException exception)
877     {
878       skipToSemicolon ();
879     }
880   } // addDeclarators
881 
882   /**
883    *
884    **/
885   private void initDcl (ValueEntry entry) throws IOException, ParseException
886   {
887     MethodEntry method = stFactory.methodEntry (entry, (IDLID)repIDStack.peek ());
888     method.sourceFile (scanner.fileEntry ());
889     // Comment must immediately precede "init" keyword:
890     method.comment (token.comment);
891     repIDStack.push (((IDLID)repIDStack.peek ()).clone ());
892     ((IDLID)repIDStack.peek ()).appendToName (token.name);
893 
894     // <d62023> In 2.3 prelim, <init_dcl> ::= "init" "(" ...
895     if (token.type == Token.Init)
896     {
897       method.name ("init");
898       match (Token.Init);
899       match (Token.LeftParen);
900     }
901     else // <d62023> In 2.4rtf, <init_dcl> ::= "factory" <Indentifier> "(" ...
902     {
903       match (Token.Factory);
904       method.name (token.name);
905       if (token.type == Token.MacroIdentifier)
906         match (Token.MacroIdentifier);  // "(" already consumed.
907       else
908       {
909         match (Token.Identifier);
910         match (Token.LeftParen);
911       }
912     }
913 
914     if (token.type != Token.RightParen)
915       for (;;)
916       {
917         initParamDcl (method);
918         if (token.type == Token.RightParen)
919           break;
920         match (Token.Comma);
921       }
922     entry.initializersAddElement (method, scanner);
923     match (Token.RightParen);
924     match (Token.Semicolon);
925     repIDStack.pop ();
926   } // initDcl
927 
928   /**
929    *
930    **/
931   private void initParamDcl (MethodEntry entry) throws IOException, ParseException
932   {
933     ParameterEntry parmEntry = stFactory.parameterEntry (entry, (IDLID)repIDStack.peek ());
934     parmEntry.sourceFile (scanner.fileEntry());
935     // Comment must immediately precede parameter attribute
936     parmEntry.comment (token.comment);
937     match (Token.In);
938     parmEntry.passType (ParameterEntry.In);
939     parmEntry.type (paramTypeSpec (entry));
940     parmEntry.name (token.name);
941     match (Token.Identifier);
942     if (isntInList (entry.parameters (), parmEntry.name ()))
943       entry.addParameter (parmEntry);
944   } // initParamDcl
945 
946   /**
947    *
948    **/
949   private void valueBox (ModuleEntry module, String name) throws IOException, ParseException
950   {
951     repIDStack.push (((IDLID)repIDStack.peek ()).clone ());
952     // Note: The 'actual' repository ID will be calculated at the end of
953     // the parsing phase, since it is based on the entire contents of the
954     // declaration, and needs to have all forward references resolved:
955     ValueEntry entry = stFactory.valueBoxEntry (module, (IDLID)repIDStack.peek ());
956     entry.sourceFile (scanner.fileEntry ());
957     entry.name (name);
958     // comment must immediately precede "value" keyword
959     entry.comment (tokenHistory.lookBack (2).comment);
960     // <f46082.40> Value boxes may not be forwarded.
961     // If this value has been forward declared, there are probably
962     // other values which derive from a ForwardValueEntry.
963     // Replace those ForwardValueEntry's with this ValueEntry:
964     //if (!ForwardValueEntry.replaceForwardDecl (entry))
965     //   ParseException.badAbstract (scanner, entry.fullName());
966     SymtabEntry valueForward = (SymtabEntry)Parser.symbolTable.get (entry.fullName ());
967     if (valueForward != null && valueForward instanceof ForwardEntry)
968       ParseException.forwardedValueBox (scanner, entry.fullName ());
969     pigeonhole (module, entry);
970     ((IDLID)repIDStack.peek ()).appendToName (name);
971     currentModule = entry;
972     TypedefEntry typedefEntry = stFactory.typedefEntry (entry, (IDLID)repIDStack.peek ());
973     typedefEntry.sourceFile (scanner.fileEntry ());
974     typedefEntry.comment (token.comment);
975     // <d50237> Workaround to place typedefEntry in the _contained vector of
976     // this value box entry ONLY when <type_spec> is a constructed type declared
977     // at this point (i.e., not an identifier that resolves to a constructed
978     // type), so that emitters may generate bindings for it. <daz>
979     boolean isConstTypeSpec =
980         token.type == Token.Struct || token.type == Token.Union || token.type == Token.Enum;
981     // <d50618> Make typedefEntry anonymous.  If this line is removed, the
982     // entry will be named incorrectly.
983     typedefEntry.name ("");
984     typedefEntry.type (typeSpec (typedefEntry));
985     // <d59067> Value boxes cannot be nested.
986     if (typedefEntry.type () instanceof ValueBoxEntry)
987       ParseException.nestedValueBox (scanner);
988     //typedefEntry.name ("");
989     entry.addStateElement (new InterfaceState (InterfaceState.Public, typedefEntry), scanner);
990     if (isConstTypeSpec)
991       entry.addContained (typedefEntry);
992     currentModule = module;
993     repIDStack.pop ();
994   } // valueBox
995 
996   /**
997    *
998    **/
999   private void valueForwardDcl (ModuleEntry module, String name, boolean isAbstract)
1000       throws IOException, ParseException
1001   {
1002     ForwardValueEntry entry = stFactory.forwardValueEntry (module, (IDLID)repIDStack.peek ());
1003     entry.sourceFile (scanner.fileEntry ());
1004     entry.name (name);
1005     entry.setInterfaceType(isAbstract ? InterfaceType.ABSTRACT : InterfaceType.NORMAL );
1006     // Comment must immediately precede "[abstract] value" keyword[s]
1007     entry.comment (tokenHistory.lookBack (isAbstract? 3 : 2).comment);
1008     pigeonhole (module, entry);
1009   } // valueForwardDcl
1010 
1011   private void nativeDcl (SymtabEntry entry) throws IOException, ParseException
1012   {
1013     match (Token.Native);
1014     NativeEntry nativeEntry = stFactory.nativeEntry (entry, (IDLID)repIDStack.peek ());
1015     nativeEntry.sourceFile (scanner.fileEntry ());
1016     // Comment must immediately precede "native" keyword
1017     nativeEntry.comment (tokenHistory.lookBack (1).comment);
1018     nativeEntry.name (token.name);
1019     match (Token.Identifier);
1020     pigeonhole (entry, nativeEntry);
1021   } // nativeDcl
1022   /**
1023    *
1024    **/
1025   private void constDcl (SymtabEntry entry) throws IOException, ParseException
1026   {
1027     match (Token.Const);
1028     ConstEntry constEntry = stFactory.constEntry (entry, (IDLID)repIDStack.peek ());
1029     constEntry.sourceFile (scanner.fileEntry ());
1030     // Comment must immediately precede "const" keyword
1031     constEntry.comment (tokenHistory.lookBack (1).comment);
1032     constType (constEntry);
1033     constEntry.name (token.name);
1034     match (Token.Identifier);
1035     match (Token.Equal);
1036     constEntry.value (constExp (constEntry));
1037     verifyConstType (constEntry.value (), typeOf (constEntry.type ()));
1038     pigeonhole (entry, constEntry);
1039   } // constDcl
1040 
1041   /**
1042    *
1043    **/
1044   private void constType (SymtabEntry entry) throws IOException, ParseException
1045   {
1046     switch (token.type)
1047     {
1048       case Token.Octet:
1049         entry.type( octetType()) ;
1050         break ;
1051       case Token.Long:
1052       case Token.Short:
1053       case Token.Unsigned:
1054         entry.type (integerType (entry));
1055         break;
1056       case Token.Char:
1057       case Token.Wchar:
1058         entry.type (charType ());
1059         break;
1060       case Token.Boolean:
1061         entry.type (booleanType ());
1062         break;
1063       case Token.Float:
1064       case Token.Double:
1065         entry.type (floatingPtType ());
1066         break;
1067       case Token.String:
1068       case Token.Wstring:
1069         entry.type (stringType (entry));
1070         break;
1071       case Token.Identifier:
1072       case Token.DoubleColon:
1073         entry.type (scopedName (entry.container (), stFactory.primitiveEntry ()));
1074         if (hasArrayInfo (entry.type ()))
1075           ParseException.illegalArray (scanner, "const");
1076         SymtabEntry entryType = typeOf (entry.type ());
1077         if (!((entryType instanceof PrimitiveEntry) || (entryType instanceof StringEntry)))
1078         {
1079           ParseException.wrongType(scanner, entry.fullName (), "primitive or string", entryName (entry.type ()));
1080           entry.type (qualifiedEntry ("long"));
1081         }
1082         else if (entryType instanceof PrimitiveEntry)
1083         {
1084           String any = overrideName ("any");
1085           if (entryType.name().equals (any))
1086           {
1087             ParseException.wrongType (scanner, entry.fullName (), "primitive or string (except " + any + ')', any);
1088             entry.type (qualifiedEntry ("long"));
1089           }
1090         }
1091         break;
1092       default:
1093         throw ParseException.syntaxError (scanner, new int [] {
1094                       Token.Long,   Token.Short,   Token.Unsigned, Token.Char,
1095                       Token.Wchar,  Token.Boolean, Token.Float,    Token.Double,
1096                       Token.String, Token.Wstring, Token.Identifier,
1097                       Token.DoubleColon }, token.type);
1098     }
1099   } // constType
1100 
1101   /**
1102    *
1103    **/
1104   private boolean hasArrayInfo (SymtabEntry entry)
1105   {
1106     while (entry instanceof TypedefEntry)
1107     {
1108       if (((TypedefEntry)entry).arrayInfo ().size () != 0)
1109         return true;
1110       entry = entry.type ();
1111     }
1112   return false;
1113   } // hasArrayInfo
1114 
1115   /**
1116    *
1117    **/
1118   public static String overrideName (String string)
1119   {
1120     String name = (String)overrideNames.get (string);
1121     return (name == null) ? string : name;
1122   } // overrideName
1123 
1124   // If entry is boolean, expression value must be boolean
1125   // If entry is float/double, expression value must be float/double
1126   // If entry is integral, expression value must be integral
1127   // If entry is string, expression value must be string
1128 
1129   /**
1130    *
1131    **/
1132   private void verifyConstType (Expression e, SymtabEntry t)
1133   {
1134     Object value = e.value ();
1135     if (value instanceof BigInteger)
1136       verifyIntegral ((Number)value, t);
1137     else if (value instanceof String)
1138       verifyString (e, t);
1139     else if (value instanceof Boolean)
1140       verifyBoolean (t);
1141     else if (value instanceof Character)
1142       verifyCharacter (e, t);
1143     else if (value instanceof Float || value instanceof Double)
1144       verifyFloat((Number)value, t);
1145     else if (value instanceof ConstEntry)
1146       verifyConstType (((ConstEntry)value).value (), t);
1147     else
1148       ParseException.wrongExprType (scanner, t.fullName (),
1149           (value == null) ? "" : value.toString ());
1150   } // verifyConstType
1151 
1152   private static final int MAX_SHORT  = 32767;
1153   private static final int MIN_SHORT  = -32768;
1154   private static final int MAX_USHORT = 65535;
1155 
1156   /**
1157    *
1158    **/
1159   private void verifyIntegral (Number n, SymtabEntry t)
1160   {
1161     boolean outOfRange = false;
1162     //KEEP: Useful for debugging com.sun.tools.corba.se.idl.constExpr package
1163     //System.out.println ("verifyIntegral, n = " + n.toString ());
1164 
1165     if (t == qualifiedEntry( "octet" )) {
1166         if ((n.longValue() > 255) || (n.longValue() < 0))
1167             outOfRange = true ;
1168     } else if (t == qualifiedEntry ("long")) {
1169         if (n.longValue () > Integer.MAX_VALUE || n.longValue() < Integer.MIN_VALUE)
1170             outOfRange = true;
1171     } else if (t == qualifiedEntry ("short")) {
1172         if (n.intValue () > Short.MAX_VALUE || n.intValue () < Short.MIN_VALUE)
1173             outOfRange = true;
1174     } else if (t == qualifiedEntry ("unsigned long")) {
1175         if (n.longValue () > (long)Integer.MAX_VALUE*2+1 || n.longValue() < 0)
1176             outOfRange = true;
1177     } else if (t == qualifiedEntry ("unsigned short")) {
1178         if (n.intValue () > (int) Short.MAX_VALUE*2+1 || n.intValue () < 0)
1179             outOfRange = true;
1180     } else if (t == qualifiedEntry ("long long")) {
1181         // BigInteger required because value being compared may exceed
1182         // java.lang.Long.MAX_VALUE/MIN_VALUE:
1183         BigInteger llMax = BigInteger.valueOf (Long.MAX_VALUE);
1184         BigInteger llMin = BigInteger.valueOf (Long.MIN_VALUE);
1185         if (((BigInteger)n).compareTo (llMax) > 0 ||
1186             ((BigInteger)n).compareTo (llMin) < 0)
1187             outOfRange = true;
1188     } else if (t == qualifiedEntry ("unsigned long long")) {
1189         BigInteger ullMax = BigInteger.valueOf (Long.MAX_VALUE).
1190             multiply (BigInteger.valueOf (2)).
1191             add (BigInteger.valueOf (1));
1192         BigInteger ullMin = BigInteger.valueOf (0);
1193         if (((BigInteger)n).compareTo (ullMax) > 0 ||
1194             ((BigInteger)n).compareTo (ullMin) < 0)
1195             outOfRange = true;
1196     } else {
1197         String got = null;
1198         // THIS MUST BE CHANGED; BIGINTEGER IS ALWAYS THE CONTAINER
1199         /*
1200         if (n instanceof Short)
1201           got = "short";
1202         else if (n instanceof Integer)
1203           got = "long";
1204         else
1205           got = "long long";
1206         */
1207         got = "long";
1208         ParseException.wrongExprType (scanner, t.fullName (), got);
1209     }
1210 
1211     if (outOfRange)
1212         ParseException.outOfRange (scanner, n.toString (), t.fullName ());
1213   } // verifyIntegral
1214 
1215   /**
1216    *
1217    **/
1218   private void verifyString (Expression e, SymtabEntry t)
1219   {
1220     String string = (String)(e.value()) ;
1221     if (!(t instanceof StringEntry)) {
1222         ParseException.wrongExprType (scanner, t.fullName (), e.type() );
1223     } else if (((StringEntry)t).maxSize () != null) {
1224         Expression maxExp = ((StringEntry)t).maxSize ();
1225         try {
1226             Number max = (Number)maxExp.value ();
1227             if (string.length () > max.intValue ())
1228                 ParseException.stringTooLong (scanner, string, max.toString ());
1229         } catch (Exception exception) {
1230             // If the above statement is not valid and throws an
1231             // exception, then an error occurred and was reported
1232             // earlier.  Move on.
1233         }
1234     }
1235 
1236     if (!e.type().equals( t.name())) {
1237         // cannot mix strings and wide strings
1238         ParseException.wrongExprType (scanner, t.name(), e.type() ) ;
1239     }
1240   } // verifyString
1241 
1242   /**
1243    *
1244    **/
1245   private void verifyBoolean (SymtabEntry t)
1246   {
1247     if (!t.name ().equals (overrideName ("boolean")))
1248       ParseException.wrongExprType(scanner, t.name(), "boolean");
1249   } // verifyBoolean
1250 
1251   /**
1252    *
1253    **/
1254   private void verifyCharacter (Expression e, SymtabEntry t)
1255   {
1256     // Bug fix 4382578:  Can't compile a wchar literal.
1257     // Allow a Character to be either a char or a wchar.
1258     if (!t.name ().equals (overrideName ("char")) &&
1259         !t.name ().equals (overrideName ("wchar")) ||
1260         !t.name().equals(e.type()) )
1261         ParseException.wrongExprType (scanner, t.fullName(), e.type() ) ;
1262   } // verifyCharacter
1263 
1264   /**
1265    *
1266    **/
1267   private void verifyFloat (Number f, SymtabEntry t)
1268   {
1269     // <d52042> Added range checking for floats.
1270     //if (!(t.name ().equals (overrideName ("float")) ||
1271     //    t.name ().equals (overrideName ("double"))))
1272     //  ParseException.wrongExprType (scanner,
1273     //      t.fullName (), (f instanceof Float) ? "float" : "double");
1274     //KEEP: Useful for debugging com.sun.tools.corba.se.idl.constExpr package
1275     //System.out.println ("verifyFloat, f = " + f.toString ());
1276     boolean outOfRange = false;
1277     if (t.name ().equals (overrideName ("float")))
1278     {
1279       double absVal = (f.doubleValue () < 0.0) ?
1280           f.doubleValue () * -1.0 : f.doubleValue ();
1281       if ((absVal != 0.0) &&
1282           (absVal > Float.MAX_VALUE || absVal < Float.MIN_VALUE))
1283         outOfRange = true;
1284     }
1285     else if (t.name ().equals (overrideName ("double")))
1286     {
1287       // Cannot check range of double until BigDecimal is the basis
1288       // of all floating-point types.  Currently, it is Double.  The
1289       // parser will fail when instantiating a Double with an exception.
1290     }
1291     else
1292     {
1293       ParseException.wrongExprType (scanner, t.fullName (),
1294         (f instanceof Float) ? "float" : "double");
1295     }
1296     if (outOfRange)
1297       ParseException.outOfRange (scanner, f.toString (), t.fullName ());
1298   } // verifyFloat
1299 
1300   /**
1301    *
1302    **/
1303   Expression constExp (SymtabEntry entry) throws IOException, ParseException
1304   {
1305     // Parse the expression.
1306     Expression expr = orExpr (null, entry);
1307 
1308     // Set its target type.
1309     if (expr.type() == null)
1310       expr.type (entry.typeName ());
1311     // Compute its value and <d53042> coerce it to the target type.
1312     try
1313     {
1314       expr.evaluate ();
1315 
1316       // <d54042> Coerces integral value to Double if an integer literal
1317       // was used to initialize a floating-point constant expression.
1318       if (expr instanceof Terminal &&
1319           expr.value () instanceof BigInteger &&
1320           (overrideName (expr.type ()).equals ("float") ||
1321                overrideName (expr.type ()).indexOf ("double") >= 0))
1322       {
1323         expr.value (new Double (((BigInteger)expr.value ()).doubleValue ()));
1324       }
1325     }
1326     catch (EvaluationException exception)
1327     {
1328       ParseException.evaluationError (scanner, exception.toString ());
1329     }
1330     return expr;
1331   } // constExp
1332 
1333   /**
1334    *
1335    **/
1336   private Expression orExpr (Expression e, SymtabEntry entry) throws IOException, ParseException
1337   {
1338     if (e == null)
1339       e = xorExpr (null, entry);
1340     else
1341     {
1342       BinaryExpr b = (BinaryExpr)e;
1343       b.right (xorExpr (null, entry));
1344       e.rep (e.rep () + b.right ().rep ());
1345     }
1346     if (token.equals (Token.Bar))
1347     {
1348       match (token.type);
1349       Or or = exprFactory.or (e, null);
1350       or.type (entry.typeName ());
1351       or.rep (e.rep () + " | ");
1352       return orExpr (or, entry);
1353     }
1354     return e;
1355   } // orExpr
1356 
1357   /**
1358    *
1359    **/
1360   private Expression xorExpr (Expression e, SymtabEntry entry) throws IOException, ParseException
1361   {
1362     if (e == null)
1363       e = andExpr (null, entry);
1364     else
1365     {
1366       BinaryExpr b = (BinaryExpr)e;
1367       b.right (andExpr (null, entry));
1368       e.rep (e.rep () + b.right ().rep ());
1369     }
1370     if (token.equals (Token.Carat))
1371     {
1372       match (token.type);
1373       Xor xor = exprFactory.xor (e, null);
1374       xor.rep (e.rep () + " ^ ");
1375       xor.type (entry.typeName ());
1376       return xorExpr (xor, entry);
1377     }
1378     return e;
1379   } // xorExpr
1380 
1381   /**
1382    *
1383    **/
1384   private Expression andExpr (Expression e, SymtabEntry entry) throws IOException, ParseException
1385   {
1386     if (e == null)
1387       e = shiftExpr (null, entry);
1388     else
1389     {
1390       BinaryExpr b = (BinaryExpr)e;
1391       b.right (shiftExpr (null, entry));
1392       e.rep (e.rep () + b.right ().rep ());
1393     }
1394     if (token.equals (Token.Ampersand))
1395     {
1396       match (token.type);
1397       And and = exprFactory.and (e, null);
1398       and.rep(e.rep () + " & ");
1399       and.type (entry.typeName ());
1400       return andExpr (and, entry);
1401     }
1402     return e;
1403   } // andExpr
1404 
1405   /**
1406    *
1407    **/
1408   private Expression shiftExpr (Expression e, SymtabEntry entry) throws IOException, ParseException
1409   {
1410     if (e == null)
1411       e = addExpr (null, entry);
1412     else
1413     {
1414       BinaryExpr b = (BinaryExpr)e;
1415       b.right (addExpr (null, entry));
1416       e.rep (e.rep () + b.right ().rep ());
1417     }
1418     if (token.equals (Token.ShiftLeft))
1419     {
1420       match (token.type);
1421       ShiftLeft sl = exprFactory.shiftLeft (e, null);
1422       sl.type (entry.typeName ());
1423       sl.rep (e.rep () + " << ");
1424       return shiftExpr (sl, entry);
1425     }
1426     if (token.equals (Token.ShiftRight))
1427     {
1428       match (token.type);
1429       ShiftRight sr = exprFactory.shiftRight (e, null);
1430       sr.type (entry.typeName ());
1431       sr.rep (e.rep () + " >> ");
1432       return shiftExpr (sr, entry);
1433     }
1434     return e;
1435   } // shiftExpr
1436 
1437   /**
1438    *
1439    **/
1440   private Expression addExpr (Expression e, SymtabEntry entry) throws IOException, ParseException
1441   {
1442     if (e == null)
1443       e = multExpr (null, entry);
1444     else
1445     {
1446       BinaryExpr b = (BinaryExpr)e;
1447       b.right (multExpr (null, entry));
1448       e.rep (e.rep () + b.right ().rep ());
1449     }
1450     if (token.equals (Token.Plus))
1451     {
1452       match (token.type);
1453       Plus p = exprFactory.plus (e, null);
1454       p.type (entry.typeName ());
1455       p.rep (e.rep () + " + ");
1456       return addExpr (p, entry);
1457     }
1458     if (token.equals (Token.Minus))
1459     {
1460       match (token.type);
1461       Minus m = exprFactory.minus (e, null);
1462       m.type (entry.typeName ());
1463       m.rep (e.rep () + " - ");
1464       return addExpr (m, entry);
1465     }
1466     return e;
1467   } // addExpr
1468 
1469   /**
1470    *
1471    **/
1472   private Expression multExpr (Expression e, SymtabEntry entry) throws IOException, ParseException
1473   {
1474     if (e == null)
1475     e = unaryExpr (entry);
1476     else
1477     {
1478       BinaryExpr b = (BinaryExpr)e;
1479       b.right (unaryExpr (entry));
1480       e.rep (e.rep () + b.right ().rep ());
1481     }
1482     if (token.equals (Token.Star))
1483     {
1484       match (token.type);
1485       Times t = exprFactory.times (e, null);
1486       t.type (entry.typeName ());
1487       t.rep (e.rep () + " * ");
1488       return multExpr (t, entry);
1489     }
1490     if (token.equals (Token.Slash))
1491     {
1492       match (token.type);
1493       Divide d = exprFactory.divide (e, null);
1494       d.type (entry.typeName ());
1495       d.rep (e.rep () + " / ");
1496       return multExpr (d, entry);
1497     }
1498     if (token.equals (Token.Percent))
1499     {
1500       match (token.type);
1501       Modulo m = exprFactory.modulo (e, null);
1502       m.type (entry.typeName ());
1503       m.rep (e.rep () + " % ");
1504       return multExpr (m, entry);
1505     }
1506     return e;
1507   } // multExpr
1508 
1509   /**
1510    *
1511    **/
1512   private Expression unaryExpr (SymtabEntry entry) throws IOException, ParseException
1513   {
1514     if (token.equals (Token.Plus))
1515     {
1516       match (token.type);
1517       Expression e   = primaryExpr (entry);
1518       Positive   pos = exprFactory.positive (e);
1519       pos.type (entry.typeName());
1520       pos.rep ('+' + e.rep());
1521       return pos;
1522     }
1523     if (token.equals (Token.Minus))
1524     {
1525       match (token.type);
1526       Expression e   = primaryExpr (entry);
1527       Negative   neg = exprFactory.negative (e);
1528       neg.type (entry.typeName());
1529       neg.rep ('-' + e.rep());
1530       return neg;
1531     }
1532     if (token.equals (Token.Tilde))
1533     {
1534       match (token.type);
1535       Expression e   = primaryExpr (entry);
1536       Not        not = exprFactory.not (e);
1537       not.type (entry.typeName());
1538       not.rep ('~' + e.rep());
1539       return not;
1540     }
1541     return primaryExpr (entry);
1542   } // unaryExpr
1543 
1544   /**
1545    *
1546    **/
1547   private Expression primaryExpr (SymtabEntry entry)
1548       throws IOException, ParseException
1549   {
1550     Expression primary = null;
1551     if (parsingConditionalExpr)
1552     {
1553       prep.token = token; // Give current token to preprocessor
1554       primary    = prep.primaryExpr (entry);
1555       token      = prep.token; // Get the current token from preprocessor
1556     }
1557     else
1558       switch (token.type)
1559       {
1560         case Token.Identifier:
1561         case Token.DoubleColon:
1562           ConstEntry expectedC = stFactory.constEntry ();
1563           expectedC.value (exprFactory.terminal ("1", BigInteger.valueOf (1)));
1564           SymtabEntry ref = scopedName (entry.container (), expectedC);
1565           if (!(ref instanceof ConstEntry))
1566           {
1567             ParseException.invalidConst (scanner, ref.fullName ());
1568             // An error occurred.  Just give it some bogus value. <daz>
1569             //primary = exprFactory.terminal ("1", new Long (1));
1570             primary = exprFactory.terminal ("1", BigInteger.valueOf (1));
1571           }
1572           else
1573             primary = exprFactory.terminal ((ConstEntry)ref);
1574           break;
1575         case Token.BooleanLiteral:
1576         case Token.CharacterLiteral:
1577         case Token.IntegerLiteral:
1578         case Token.FloatingPointLiteral:
1579         case Token.StringLiteral:
1580           primary = literal (entry);
1581           break;
1582         case Token.LeftParen:
1583           match (Token.LeftParen);
1584           primary = constExp (entry);
1585           match (Token.RightParen);
1586           primary.rep ('(' + primary.rep () + ')');
1587           break;
1588         default:
1589           throw ParseException.syntaxError (scanner, new int [] {
1590               Token.Identifier, Token.DoubleColon, Token.Literal, Token.LeftParen},
1591               token.type);
1592       }
1593     return primary;
1594   } // primaryExpr
1595 
1596   /**
1597    *
1598    **/
1599   Expression literal (SymtabEntry entry) throws IOException, ParseException
1600   {
1601     String     string  = token.name;
1602     Expression literal = null;
1603     switch (token.type)
1604     {
1605       case Token.IntegerLiteral:
1606         match (Token.IntegerLiteral);
1607         try
1608         {
1609           literal = exprFactory.terminal (string, parseString (string));
1610           literal.type (entry.typeName ());
1611         }
1612         catch (NumberFormatException exception)
1613         {
1614           ParseException.notANumber (scanner, string);
1615           literal = exprFactory.terminal ("0", BigInteger.valueOf (0));
1616         }
1617         break;
1618       case Token.CharacterLiteral:
1619         boolean isWide = token.isWide();
1620         match (Token.CharacterLiteral);
1621         literal = exprFactory.terminal ("'" + string.substring (1) + "'",
1622             new Character (string.charAt (0)), isWide );
1623         break;
1624       case Token.FloatingPointLiteral:
1625         match (Token.FloatingPointLiteral);
1626         try
1627         {
1628           literal = exprFactory.terminal (string, new Double (string));
1629           literal.type (entry.typeName ());
1630         }
1631         catch (NumberFormatException e)
1632         {
1633           ParseException.notANumber (scanner, string);
1634         }
1635         break;
1636       case Token.BooleanLiteral:
1637         literal = booleanLiteral ();
1638         break;
1639       case Token.StringLiteral:
1640         literal = stringLiteral ();
1641         break;
1642       default:
1643         throw ParseException.syntaxError (scanner, Token.Literal,token.type);
1644     }
1645     return literal;
1646   } // literal
1647 
1648   /**
1649    *
1650    **/
1651   private BigInteger parseString (String string) throws NumberFormatException
1652   {
1653     int radix = 10;
1654     if (string.length() > 1)
1655       if (string.charAt (0) == '0')
1656         if (string.charAt (1) == 'x' || string.charAt (1) == 'X')
1657         {
1658           string = string.substring (2);
1659           radix = 16;
1660         }
1661         else
1662           radix = 8;
1663     return new BigInteger (string, radix);
1664   } // parseString
1665 
1666   /**
1667    *
1668    **/
1669   private Terminal booleanLiteral () throws IOException, ParseException
1670   {
1671     Boolean bool = null;
1672     if (token.name.equals ("TRUE"))
1673       bool = new Boolean (true);
1674     else if (token.name.equals ("FALSE"))
1675       bool = new Boolean (false);
1676     else
1677     {
1678       ParseException.invalidConst (scanner, token.name);
1679       bool = new Boolean (false);
1680     }
1681     String name = token.name;
1682     match (Token.BooleanLiteral);
1683     return exprFactory.terminal (name, bool);
1684   } // booleanLiteral
1685 
1686   /**
1687    *
1688    **/
1689   private Expression stringLiteral () throws IOException, ParseException
1690   {
1691     // If string literals appear together, concatenate them.  Ie:
1692     // "Twas " "brillig " "and " "the " "slithy " "toves"
1693     // becomes
1694     // "Twas brillig and the slithy toves"
1695     boolean isWide = token.isWide() ;
1696     String literal = "";
1697     do
1698     {
1699       literal += token.name;
1700       match (Token.StringLiteral);
1701     } while (token.equals (Token.StringLiteral));
1702     Expression stringExpr = exprFactory.terminal (literal, isWide );
1703     stringExpr.rep ('"' + literal + '"');
1704     return stringExpr;
1705   } // stringLiteral
1706 
1707   /**
1708    *
1709    **/
1710   private Expression positiveIntConst (SymtabEntry entry) throws IOException, ParseException
1711   {
1712     Expression e     = constExp (entry);
1713     Object     value = e.value ();
1714     while (value instanceof ConstEntry)
1715       value = ((ConstEntry)value).value ().value ();
1716     if (!(value instanceof Number) || value instanceof Float || value instanceof Double)
1717     {
1718       ParseException.notPositiveInt (scanner, e.rep ());
1719       //e = exprFactory.terminal ("1", new Long (1));
1720       e = exprFactory.terminal ("1", BigInteger.valueOf (1));
1721     }
1722     //else if (((Number)value).longValue () <= 0) {
1723     //   ParseException.notPositiveInt (scanner, value.toString ());
1724     //   e = exprFactory.terminal ("1", new Long (1)); }
1725     else if (((BigInteger)value).compareTo (BigInteger.valueOf (0)) <= 0)
1726     {
1727       ParseException.notPositiveInt (scanner, value.toString ());
1728       //e = exprFactory.terminal ("1", new Long (1)); <daz>
1729       e = exprFactory.terminal ("1", BigInteger.valueOf (1));
1730     }
1731     return e;
1732   } // positiveIntConst
1733 
1734   /**
1735    *
1736    **/
1737   private SymtabEntry typeDcl (SymtabEntry entry) throws IOException, ParseException
1738   {
1739     switch (token.type)
1740     {
1741       case Token.Typedef:
1742         match (Token.Typedef);
1743         return typeDeclarator (entry);
1744       case Token.Struct:
1745         return structType (entry);
1746       case Token.Union:
1747         return unionType (entry);
1748       case Token.Enum:
1749         return enumType (entry);
1750       default:
1751         throw ParseException.syntaxError (scanner, new int [] {
1752             Token.Typedef, Token.Struct, Token.Union, Token.Enum}, token.type);
1753     }
1754   } // typeDcl
1755 
1756   /**
1757    *
1758    **/
1759   private TypedefEntry typeDeclarator (SymtabEntry entry) throws IOException, ParseException
1760   {
1761     TypedefEntry typedefEntry = stFactory.typedefEntry (entry, (IDLID)repIDStack.peek ());
1762     typedefEntry.sourceFile (scanner.fileEntry ());
1763     // Comment must immediately precede "typedef" keyword
1764     typedefEntry.comment (tokenHistory.lookBack (1).comment);
1765     typedefEntry.type (typeSpec (entry));
1766     Vector typedefList = new Vector ();
1767     declarators (typedefEntry, typedefList);
1768     for (Enumeration e = typedefList.elements(); e.hasMoreElements();)
1769       pigeonhole (entry, (SymtabEntry)e.nextElement ());
1770     return typedefEntry;
1771   } // typeDeclarator
1772 
1773   /**
1774    *
1775    **/
1776   private SymtabEntry typeSpec (SymtabEntry entry) throws IOException, ParseException
1777   {
1778     return ((token.type == Token.Struct) ||
1779             (token.type == Token.Union)  ||
1780             (token.type == Token.Enum))
1781         ? constrTypeSpec (entry)
1782         : simpleTypeSpec (entry, true);
1783   } // typeSpec
1784 
1785   /**
1786    *
1787    **/
1788   private SymtabEntry simpleTypeSpec (SymtabEntry entry,
1789     boolean mustBeReferencable ) throws IOException, ParseException
1790   {
1791     // <f46082.40>
1792     //if ((token.type == Token.Identifier)  ||
1793     //    (token.type == Token.DoubleColon) ||
1794     //    (token.type == Token.Object)) {
1795     if ((token.type == Token.Identifier)  ||
1796         (token.type == Token.DoubleColon) ||
1797         (token.type == Token.Object)      ||
1798         (token.type == Token.ValueBase))
1799     {
1800       SymtabEntry container = ((entry instanceof InterfaceEntry) ||
1801                                (entry instanceof ModuleEntry)    ||
1802                                (entry instanceof StructEntry)    ||
1803                                (entry instanceof UnionEntry))
1804           ? entry
1805           : entry.container ();
1806       return scopedName (container, stFactory.primitiveEntry (),
1807         mustBeReferencable);
1808     }
1809     return ((token.type == Token.Sequence) ||
1810             (token.type == Token.String)   ||
1811             (token.type == Token.Wstring))
1812         ? templateTypeSpec (entry)
1813         : baseTypeSpec (entry);
1814   } // simpleTypeSpec
1815 
1816   /**
1817    *
1818    **/
1819   private SymtabEntry baseTypeSpec (SymtabEntry entry) throws IOException, ParseException
1820   {
1821     switch (token.type)
1822     {
1823       case Token.Float:
1824       case Token.Double:
1825         return floatingPtType ();
1826       case Token.Long:
1827       case Token.Short:
1828      case Token.Unsigned:
1829         return integerType (entry);
1830       case Token.Char:
1831       case Token.Wchar:
1832         return charType ();
1833       case Token.Boolean:
1834         return booleanType ();
1835      case Token.Octet:
1836         return octetType ();
1837       case Token.Any:
1838         return anyType ();
1839       // NOTE: Object and ValueBase are <base_type_spec>s, but both
1840       // are processed at simpleTypeSpec(), not here.  parmTypeSpec()
1841       // directly checks for these types.  Could make baseTypeSpec() do
1842       // the same
1843       default:
1844         throw ParseException.syntaxError (scanner, new int [] {
1845             Token.Float,    Token.Double, Token.Long,  Token.Short,
1846             Token.Unsigned, Token.Char,   Token.Wchar, Token.Boolean,
1847             Token.Octet,    Token.Any}, token.type);
1848     }
1849   } // baseTypeSpec
1850 
1851   /**
1852    *
1853    **/
1854   private SymtabEntry templateTypeSpec (SymtabEntry entry) throws IOException, ParseException
1855   {
1856     switch (token.type)
1857     {
1858       case Token.Sequence:
1859         return sequenceType (entry);
1860       case Token.String:
1861       case Token.Wstring:
1862         return stringType (entry);
1863     }
1864     throw ParseException.syntaxError (scanner, new int [] {Token.Sequence, Token.String, Token.Wstring}, token.type);
1865   } // templateTypeSpec
1866 
1867   /**
1868    *
1869    **/
1870   private SymtabEntry constrTypeSpec (SymtabEntry entry) throws IOException, ParseException
1871   {
1872     switch (token.type)
1873     {
1874       case Token.Struct:
1875         return structType (entry);
1876       case Token.Union:
1877         return unionType (entry);
1878       case Token.Enum:
1879         return enumType (entry);
1880     }
1881     throw ParseException.syntaxError (scanner, new int [] {Token.Struct, Token.Union, Token.Enum}, token.type);
1882   } // constrTypeSpec
1883 
1884   /**
1885    *
1886    **/
1887   private void declarators (TypedefEntry entry, Vector list) throws IOException, ParseException
1888   {
1889     for (; ; match (Token.Comma))
1890     {
1891       TypedefEntry newEntry = (TypedefEntry)entry.clone ();
1892       declarator (newEntry);
1893       if (isntInList (list, newEntry.name ()))
1894         list.addElement (newEntry);
1895       if (token.type != Token.Comma)
1896         break;
1897     }
1898   } // declarators
1899 
1900   /**
1901    *
1902    **/
1903   private void declarator (TypedefEntry entry) throws IOException, ParseException
1904   {
1905     entry.name (token.name);
1906     // If the declarator is commented then override the comment cloned from the parent
1907     // entry. <08aug1997daz>
1908     if (!token.comment.text ().equals (""))
1909       entry.comment (token.comment);
1910     match (Token.Identifier);
1911     while (token.type == Token.LeftBracket)
1912       fixedArraySize (entry);
1913   } // declarator
1914 
1915   /**
1916    *
1917    **/
1918   private PrimitiveEntry floatingPtType () throws IOException, ParseException
1919   {
1920     String name = "double";
1921     if (token.type == Token.Float)
1922     {
1923       match (Token.Float);
1924       name = "float";
1925     }
1926     else if (token.type == Token.Double)
1927       match (Token.Double);
1928     else
1929     {
1930       int [] expected = {Token.Float, Token.Double};
1931       ParseException.syntaxError (scanner, new int [] {Token.Float, Token.Double }, token.type);
1932     }
1933     PrimitiveEntry ret = null;
1934     try
1935     {
1936       ret = (PrimitiveEntry)qualifiedEntry (name);
1937     }
1938     catch (ClassCastException exception)
1939     {
1940       ParseException.undeclaredType (scanner, name);
1941     }
1942     return ret;
1943   } // floatingPtType
1944 
1945   /**
1946    *
1947    **/
1948   private PrimitiveEntry integerType (SymtabEntry entry) throws IOException, ParseException
1949   {
1950     String name = "";
1951     if (token.type == Token.Unsigned)
1952     {
1953       match (Token.Unsigned);
1954       name = "unsigned ";
1955     }
1956     name += signedInt();
1957     PrimitiveEntry ret = null;
1958     try
1959     {
1960       ret = (PrimitiveEntry) qualifiedEntry (name);
1961     }
1962     catch (ClassCastException exception)
1963     {
1964       ParseException.undeclaredType (scanner, name);
1965     }
1966     return ret;
1967   } // integerType
1968 
1969   /**
1970    *
1971    **/
1972   private String signedInt () throws IOException, ParseException
1973   {
1974     String ret = "long";
1975     if (token.type == Token.Long)
1976     {
1977       match (Token.Long);
1978       // <signedInt'> ::= "long" | e
1979       if (token.type == Token.Long)
1980       {
1981         ret = "long long";
1982         match (Token.Long);
1983       }
1984     }
1985     else if (token.type == Token.Short)
1986     {
1987       ret = "short";
1988       match (Token.Short);
1989     }
1990     else
1991       ParseException.syntaxError (scanner, new int [] {Token.Long, Token.Short}, token.type);
1992     return ret;
1993   } // signedInt
1994 
1995   /**
1996    *
1997    **/
1998   private PrimitiveEntry charType () throws IOException, ParseException
1999   {
2000     String tokenName;
2001     if (token.type == Token.Char)
2002     {
2003       match (Token.Char);
2004       tokenName = "char";
2005     }
2006     else
2007     {
2008       match (Token.Wchar);
2009       tokenName = "wchar";
2010     }
2011     PrimitiveEntry ret = null;
2012     try
2013     {
2014       ret = (PrimitiveEntry) qualifiedEntry (tokenName);
2015     }
2016     catch (ClassCastException exception)
2017     {
2018       ParseException.undeclaredType (scanner, overrideName (tokenName));
2019     }
2020     return ret;
2021   } // charType
2022 
2023   /**
2024    *
2025    **/
2026   private PrimitiveEntry booleanType () throws IOException, ParseException
2027   {
2028     PrimitiveEntry ret = null;
2029     match (Token.Boolean);
2030     try
2031     {
2032       ret = (PrimitiveEntry) qualifiedEntry ("boolean");
2033     }
2034     catch (ClassCastException exception)
2035     {
2036       ParseException.undeclaredType (scanner, overrideName ("boolean"));
2037     }
2038     return ret;
2039   } // booleanType
2040 
2041   /**
2042    *
2043    **/
2044   private PrimitiveEntry octetType () throws IOException, ParseException
2045   {
2046     PrimitiveEntry ret = null;
2047     match (Token.Octet);
2048     try
2049     {
2050       ret = (PrimitiveEntry) qualifiedEntry ("octet");
2051     }
2052     catch (ClassCastException exception)
2053     {
2054       ParseException.undeclaredType (scanner, overrideName ("octet"));
2055     }
2056     return ret;
2057   } // octetType
2058 
2059   /**
2060    *
2061    **/
2062   private SymtabEntry anyType () throws IOException, ParseException
2063   {
2064     match (Token.Any);
2065     try
2066     {
2067       return qualifiedEntry ("any");
2068     }
2069     catch (ClassCastException exception)
2070     {
2071       ParseException.undeclaredType (scanner, overrideName ("any"));
2072       return null;
2073     }
2074   } // anyType
2075 
2076   /**
2077    *
2078    **/
2079   private StructEntry structType (SymtabEntry entry) throws IOException,
2080     ParseException
2081   {
2082     match (Token.Struct);
2083     String name = token.name;
2084     match (Token.Identifier);
2085     StructEntry structEntry = null ;
2086 
2087     if (token.type == Token.LeftBrace) {
2088       repIDStack.push(((IDLID)repIDStack.peek ()).clone ()) ;
2089       structEntry = makeStructEntry( name, entry, false ) ;
2090       ((IDLID)repIDStack.peek ()).appendToName (name);
2091       prep.openScope (structEntry);
2092       match (Token.LeftBrace) ;
2093       member (structEntry) ;
2094       memberList2 (structEntry) ;
2095       prep.closeScope (structEntry);
2096       match (Token.RightBrace) ;
2097       repIDStack.pop() ;
2098     } else if (token.equals( Token.Semicolon )) {
2099       structEntry = makeStructEntry( name, entry, true ) ;
2100     } else {
2101       throw ParseException.syntaxError (scanner,
2102         new int[] { Token.Semicolon, Token.LeftBrace }, token.type);
2103     }
2104     return structEntry;
2105   } // structType
2106 
2107   private StructEntry makeStructEntry( String name, SymtabEntry entry,
2108     boolean isForward )
2109   {
2110     StructEntry structEntry = stFactory.structEntry (entry,
2111       (IDLID)repIDStack.peek () );
2112     structEntry.isReferencable( !isForward ) ;
2113     structEntry.sourceFile (scanner.fileEntry ());
2114     structEntry.name (name);
2115     // Comment must immediately preceed "struct" keyword
2116     structEntry.comment (tokenHistory.lookBack (1).comment);
2117     pigeonhole( entry, structEntry ) ;
2118     return structEntry ;
2119   }
2120 
2121   /**
2122    *
2123    **/
2124   private void memberList2 (StructEntry entry) throws IOException
2125   {
2126     while (token.type != Token.RightBrace)
2127       member (entry);
2128   } // memberList2
2129 
2130   /**
2131    *
2132    **/
2133   private void member (StructEntry entry) throws IOException
2134   {
2135     TypedefEntry newEntry = stFactory.typedefEntry(entry, (IDLID)repIDStack.peek());
2136     newEntry.sourceFile (scanner.fileEntry ());
2137     // comment must immediately precede <type_spec> lexeme
2138     newEntry.comment (token.comment);
2139     try
2140     {
2141       newEntry.type (typeSpec (entry));
2142       if (newEntry.type () == entry)
2143         throw ParseException.recursive (scanner, entry.fullName (),
2144             (token.name == null) ? "" : token.name);
2145       // <d46094> Exception cannot appear within a struct, union, or exception
2146       if (typeOf (newEntry) instanceof ExceptionEntry)
2147         throw ParseException.illegalException (scanner, entryName (entry));
2148       declarators (newEntry, entry.members ());
2149       match (Token.Semicolon);
2150     }
2151     catch (ParseException exception)
2152     {
2153       skipToSemicolon ();
2154     }
2155   } // member
2156 
2157   /**
2158    *
2159    **/
2160   private final boolean isConstTypeSpec (Token t)
2161   {
2162     return (t.type == Token.Struct || t.type == Token.Union || t.type == Token.Enum);
2163   } // isConstTypeSpec
2164 
2165   /**
2166    *
2167    **/
2168   private UnionEntry unionType (SymtabEntry entry) throws IOException, ParseException
2169   {
2170     match (Token.Union) ;
2171     String name = token.name ;
2172     match (Token.Identifier) ;
2173     UnionEntry unionEntry = null ;
2174 
2175     if (token.type == Token.Switch) {
2176       repIDStack.push (((IDLID)repIDStack.peek ()).clone ());
2177       unionEntry = makeUnionEntry( name, entry, false ) ;
2178       ((IDLID)repIDStack.peek ()).appendToName (name);
2179       match (Token.Switch);
2180       match (Token.LeftParen);
2181       unionEntry.type (switchTypeSpec (unionEntry));
2182       match (Token.RightParen);
2183       prep.openScope (unionEntry);
2184       match (Token.LeftBrace);
2185       switchBody (unionEntry);
2186       verifyUnion (unionEntry);
2187       prep.closeScope (unionEntry);
2188       match (Token.RightBrace);
2189       repIDStack.pop ();
2190     } else if (token.equals( Token.Semicolon )) {
2191       unionEntry = makeUnionEntry( name, entry, true ) ;
2192     } else {
2193       throw ParseException.syntaxError (scanner,
2194         new int[] { Token.Semicolon, Token.Switch }, token.type);
2195     }
2196 
2197     return unionEntry ;
2198   } // unionType
2199 
2200   private UnionEntry makeUnionEntry( String name, SymtabEntry entry,
2201     boolean isForward )
2202   {
2203     UnionEntry unionEntry = stFactory.unionEntry (entry,
2204       (IDLID)repIDStack.peek () );
2205     unionEntry.isReferencable( !isForward ) ;
2206     unionEntry.sourceFile (scanner.fileEntry ());
2207     unionEntry.name (name);
2208     // Comment must immediately preceed "union" keyword
2209     unionEntry.comment (tokenHistory.lookBack (1).comment);
2210     pigeonhole( entry, unionEntry ) ;
2211     return unionEntry ;
2212   }
2213 
2214   /**
2215    *
2216    **/
2217   private void verifyUnion (UnionEntry u)
2218   {
2219     if (u.typeName ().equals (overrideName ("boolean")))
2220     {
2221       if (caseCount (u) > 2)
2222         ParseException.noDefault (scanner);
2223     }
2224     else if (u.type () instanceof EnumEntry)
2225     {
2226       if (caseCount (u) > ((EnumEntry)u.type ()).elements ().size ())
2227         ParseException.noDefault (scanner);
2228     }
2229   } // verifyUnion
2230 
2231   /**
2232    *
2233    **/
2234   private long caseCount (UnionEntry u)
2235   {
2236     long cases = 0;
2237     Enumeration branches = u.branches ().elements ();
2238     while (branches.hasMoreElements ())
2239     {
2240       UnionBranch branch = (UnionBranch)branches.nextElement ();
2241       cases += branch.labels.size ();
2242       if (branch.isDefault)
2243         ++cases;
2244     }
2245     return cases;
2246   } // caseCount
2247 
2248   /**
2249    *
2250    **/
2251   private SymtabEntry switchTypeSpec (UnionEntry entry) throws IOException, ParseException
2252   {
2253     SymtabEntry ret = null;
2254     switch (token.type)
2255     {
2256        case Token.Long:
2257        case Token.Short:
2258        case Token.Unsigned:
2259          return integerType (entry);
2260        case Token.Char:
2261        case Token.Wchar:
2262          return charType();
2263        case Token.Boolean:
2264          return booleanType();
2265        case Token.Enum:
2266          return enumType (entry);
2267        case Token.Identifier:
2268        case Token.DoubleColon:
2269          ret = scopedName (entry, stFactory.primitiveEntry ());
2270          if (hasArrayInfo (entry.type ()))
2271            ParseException.illegalArray (scanner, "switch");
2272          SymtabEntry retType = typeOf (ret);
2273          if (!(retType instanceof EnumEntry || retType instanceof PrimitiveEntry))
2274            ParseException.wrongType (scanner, ret.fullName (),
2275                "long, unsigned long, short, unsigned short, char, boolean, enum",
2276                entryName (ret.type ()));
2277          else if (ret instanceof PrimitiveEntry)
2278          {
2279            SymtabEntry octet = qualifiedEntry ("octet");
2280            SymtabEntry flt   = qualifiedEntry ("float");
2281            SymtabEntry dbl   = qualifiedEntry ("double");
2282            if (retType == octet || retType == flt || retType == dbl)
2283              ParseException.wrongType (scanner, ret.fullName(),
2284                  "long, unsigned long, short, unsigned short, char, boolean, enum",
2285                  entryName(ret.type ()));
2286          }
2287          break;
2288        default:
2289          throw ParseException.syntaxError (scanner, new int [] {
2290              Token.Long,    Token.Short, Token.Unsigned, Token.Char,
2291              Token.Boolean, Token.Enum,  Token.Identifier,
2292              Token.DoubleColon }, token.type);
2293     }
2294     return ret;
2295   } // switchTypeSpec
2296 
2297   // This is only used by the union methods
2298   UnionBranch defaultBranch = null;
2299 
2300   /**
2301    *
2302    **/
2303   private void switchBody (UnionEntry entry) throws IOException, ParseException
2304   {
2305     caseProd (entry);
2306     while (!token.equals (Token.RightBrace))
2307       caseProd (entry);
2308     entry.defaultBranch ((defaultBranch == null) ? null : defaultBranch.typedef);
2309     defaultBranch = null;
2310   } // switchBody
2311 
2312   /**
2313    *
2314    **/
2315   private void caseProd (UnionEntry entry) throws IOException, ParseException
2316   {
2317     UnionBranch branch = new UnionBranch ();
2318     entry.addBranch (branch);
2319     caseLabel (entry, branch);
2320     while (token.equals (Token.Case) || token.equals (Token.Default))
2321       caseLabel (entry, branch);
2322     elementSpec (entry, branch);
2323     match (Token.Semicolon);
2324   } // caseProd
2325 
2326   /**
2327    *
2328    **/
2329   private void caseLabel (UnionEntry entry, UnionBranch branch) throws IOException, ParseException
2330   {
2331     if (token.type == Token.Case)
2332     {
2333       match (Token.Case);
2334       ConstEntry tmpEntry = stFactory.constEntry (entry, (IDLID)repIDStack.peek ());
2335       tmpEntry.sourceFile (scanner.fileEntry ());
2336       tmpEntry.type (entry);
2337 
2338       Expression  label;
2339       SymtabEntry type = typeOf (entry.type ());
2340       if (type instanceof EnumEntry)
2341         label = matchEnum ((EnumEntry)type);
2342       else
2343       {
2344         label = constExp (tmpEntry);
2345         verifyConstType (label, type);
2346       }
2347       if (entry.has (label))
2348         ParseException.branchLabel (scanner, label.rep ());
2349       branch.labels.addElement (label);
2350       match (Token.Colon);
2351     }
2352     else if (token.type == Token.Default)
2353     {
2354       match (Token.Default);
2355       match (Token.Colon);
2356       if (entry.defaultBranch () != null)
2357         ParseException.alreadyDefaulted (scanner);
2358       branch.isDefault = true;
2359       defaultBranch    = branch;
2360     }
2361     else
2362       throw ParseException.syntaxError (scanner, new int [] { Token.Case, Token.Default }, token.type);
2363   } // caselabel
2364 
2365   /**
2366    *
2367    **/
2368   private Expression matchEnum (EnumEntry entry) throws IOException, ParseException
2369   {
2370     // Get the symbol table entry for the case label based on the
2371     // scope of the EnumEntry, NOT the UnionEntry (the union could be
2372     // in a different scope than the enum).  Given
2373     // module M { enum E {A, B, C, D}; };
2374     // a case label for A could be one of the following:
2375     // case A:
2376     // case M::A:
2377     // case ::M::A:
2378     SymtabEntry label = scopedName (entry.container(), new SymtabEntry ());
2379     return exprFactory.terminal (label.name (), false);
2380   } // matchEnum
2381 
2382   /**
2383    *
2384    **/
2385   private void elementSpec (UnionEntry entry, UnionBranch branch) throws IOException, ParseException
2386   {
2387     TypedefEntry typedef = stFactory.typedefEntry (entry, (IDLID)repIDStack.peek ());
2388     typedef.sourceFile (scanner.fileEntry ());
2389     // Comment must immediately precede <type_spec> lexeme
2390     typedef.comment (token.comment);
2391     typedef.type (typeSpec (entry));
2392     if (typedef.type () == entry)
2393       throw ParseException.recursive (scanner, entry.fullName (), (token.name == null)? "" : token.name);
2394     // <d46094> Exception cannot appear within a struct, union, or exception
2395     if (typeOf (typedef) instanceof ExceptionEntry)
2396       throw ParseException.illegalException (scanner, entryName (entry));
2397     declarator (typedef);
2398     branch.typedef = typedef;
2399     // Ensure a branch with the same name doesn't already exist.
2400     if (entry.has (typedef))
2401       ParseException.branchName (scanner, typedef.name ());
2402   } // elementSpec
2403 
2404   /**
2405    *
2406    **/
2407   private EnumEntry enumType (SymtabEntry entry) throws IOException, ParseException
2408   {
2409     match (Token.Enum);
2410     EnumEntry enumEntry = newEnumEntry (entry);
2411     // comment must immediately precede "enum" keyword
2412     enumEntry.comment (tokenHistory.lookBack (1).comment);
2413     enumEntry.name (token.name);
2414     match (Token.Identifier);
2415     prep.openScope (enumEntry);
2416     match (Token.LeftBrace);
2417     if (isntInStringList (enumEntry.elements (), token.name))
2418     {
2419       enumEntry.addElement (token.name);
2420       SymtabEntry element = new SymtabEntry (entry, (IDLID)repIDStack.peek ());
2421       // if block taken from EnumEntry ctor
2422       if (element.module ().equals (""))
2423         element.module (element.name ());
2424       else if (!element.name ().equals (""))
2425         element.module (element.module () + "/" + element.name ());
2426       element.name (token.name);
2427       // <d50237> Place the SymtabEntry representing this enumeration
2428       // contant into the SymtabEntry defining its scope (e.g., InterfaceEntry,
2429       // ValueEntry, etc.) rather than the SymtabEntry passed in, which
2430       // may not define the contant's scope (e.g., TypedefEntry).
2431       //pigeonhole (entry, element); } <daz>
2432       pigeonhole (enumEntry.container (), element);
2433     }
2434     match (Token.Identifier);
2435     enumType2 (enumEntry);
2436     prep.closeScope (enumEntry);
2437     match (Token.RightBrace);
2438     return enumEntry;
2439   } // enumType
2440 
2441   /**
2442    *
2443    **/
2444   private void enumType2 (EnumEntry entry) throws IOException, ParseException
2445   {
2446     while (token.type == Token.Comma)
2447     {
2448       match (Token.Comma);
2449       String name = token.name;
2450       match (Token.Identifier);
2451       if (isntInStringList (entry.elements (), name))
2452       {
2453         entry.addElement (name);
2454         SymtabEntry element = new SymtabEntry (entry.container (), (IDLID)repIDStack.peek ());
2455         // if block taken from EnumEntry ctor:
2456         if (element.module ().equals (""))
2457           element.module (element.name ());
2458         else if (!element.name().equals (""))
2459           element.module (element.module () + "/" + element.name ());
2460         element.name (name);
2461         pigeonhole (entry.container  (), element);
2462       }
2463     }
2464   } // enumType2
2465 
2466   /**
2467    *
2468    **/
2469   private SequenceEntry sequenceType (SymtabEntry entry) throws IOException, ParseException
2470   {
2471     match (Token.Sequence);
2472     match (Token.LessThan);
2473 
2474     SequenceEntry newEntry = newSequenceEntry (entry);
2475     SymtabEntry tsentry = simpleTypeSpec (newEntry, false );
2476     newEntry.type (tsentry);
2477     if (!tsentry.isReferencable()) {
2478         // This is a sequence type that is referencing an
2479         // incomplete forward declaration of a struct or
2480         // union.  Save the sequence in a list for later
2481         // backpatching.
2482         try {
2483             List fwdTypes = (List)tsentry.dynamicVariable( ftlKey ) ;
2484             if (fwdTypes == null) {
2485                 fwdTypes = new ArrayList() ;
2486                 tsentry.dynamicVariable( ftlKey, fwdTypes ) ;
2487             }
2488             fwdTypes.add( newEntry ) ;
2489         } catch (NoSuchFieldException exc) {
2490             throw new IllegalStateException() ;
2491         }
2492     }
2493 
2494     if (token.type == Token.Comma)
2495     {
2496       match (Token.Comma);
2497       ConstEntry tmpEntry = stFactory.constEntry (newEntry, (IDLID)repIDStack.peek ());
2498       tmpEntry.sourceFile (scanner.fileEntry ());
2499       tmpEntry.type (qualifiedEntry ("long"));
2500       newEntry.maxSize (positiveIntConst (tmpEntry));
2501       verifyConstType (newEntry.maxSize(), qualifiedEntry ("long"));
2502     }
2503     match (Token.GreaterThan);
2504     return newEntry;
2505   } // sequenceType
2506 
2507   /**
2508    *
2509    **/
2510   private StringEntry stringType (SymtabEntry entry) throws IOException, ParseException
2511   {
2512     StringEntry string = stFactory.stringEntry ();
2513     if (token.type == Token.String)
2514     {
2515       string.name (overrideName ("string"));
2516       match (Token.String);
2517     }
2518     else
2519     {
2520       string.name (overrideName ("wstring"));
2521       match (Token.Wstring);
2522     }
2523     string.maxSize (stringType2 (entry));
2524     return string;
2525   } // stringType
2526 
2527   /**
2528    *
2529    **/
2530   private Expression stringType2 (SymtabEntry entry) throws IOException, ParseException
2531   {
2532     if (token.type == Token.LessThan)
2533     {
2534       match (Token.LessThan);
2535 
2536       // START IBM.11417 failure in the IDL compiler
2537       //Expression maxSize = positiveIntConst (entry);   IBM.11417
2538 
2539       ConstEntry tmpEntry = stFactory.constEntry (entry, (IDLID)repIDStack.peek
2540 ());
2541       tmpEntry.sourceFile (scanner.fileEntry ());
2542       tmpEntry.type (qualifiedEntry ("long"));
2543       Expression maxSize = positiveIntConst (tmpEntry);
2544 
2545       // END IBM.11417
2546 
2547       verifyConstType (maxSize, qualifiedEntry ("long"));
2548       match (Token.GreaterThan);
2549       return maxSize;
2550     }
2551     return null;
2552   } // stringType2
2553 
2554   /**
2555    *
2556    **/
2557   private void fixedArraySize (TypedefEntry entry) throws IOException, ParseException
2558   {
2559     match (Token.LeftBracket);
2560     ConstEntry tmpEntry = stFactory.constEntry (entry, (IDLID)repIDStack.peek ());
2561     tmpEntry.sourceFile (scanner.fileEntry ());
2562     // <d58058> Set type of tmpExpr to "long", which is the array index type.
2563     // Previously, this type was erroneously set to the array element type.
2564     //tmpEntry.type (entry.type ());
2565     tmpEntry.type (qualifiedEntry ("long"));
2566     Expression expr = positiveIntConst (tmpEntry);
2567     entry.addArrayInfo (expr);
2568     verifyConstType (expr, qualifiedEntry ("long"));
2569     match (Token.RightBracket);
2570   } // fixedArraySize
2571 
2572   /**
2573    *
2574    **/
2575   private void attrDcl (InterfaceEntry entry) throws IOException, ParseException
2576   {
2577     AttributeEntry attribute = stFactory.attributeEntry (entry, (IDLID)repIDStack.peek ());
2578     attribute.sourceFile (scanner.fileEntry ());
2579     // Comment must immediately precede the "attribute" keyword.  Save the
2580     // comment preceding the declaration for use below.
2581     attribute.comment (token.comment);
2582     Comment dclComment = attribute.comment ();
2583 
2584     if (token.type == Token.Readonly)
2585     {
2586       match (Token.Readonly);
2587       attribute.readOnly (true);
2588     }
2589     match (Token.Attribute);
2590     attribute.type (paramTypeSpec (attribute));
2591     attribute.name (token.name);
2592     // Override declaration comment if attribute identifier is commented
2593     if (!token.comment.text ().equals (""))
2594       attribute.comment (token.comment);
2595     entry.methodsAddElement (attribute, scanner);
2596     pigeonholeMethod (entry, attribute);
2597     // Declaration comment was overriden:
2598     if (!token.comment.text ().equals (""))
2599     {
2600       // Create a temporary attribute with declaration comment so cloning in
2601       // attrdcl2() can use declaration comment as default.
2602       AttributeEntry attributeClone = (AttributeEntry) attribute.clone ();
2603       attributeClone.comment (dclComment);
2604 
2605       match (Token.Identifier);
2606       attrDcl2 (entry, attributeClone);
2607     }
2608     else
2609     {
2610       match (Token.Identifier);
2611       attrDcl2 (entry, attribute);
2612     }
2613     //match (Token.Identifier);
2614     //attrDcl2 (entry, attribute);
2615   } // attrDcl
2616 
2617   /**
2618    *
2619    **/
2620   private void attrDcl2 (InterfaceEntry entry, AttributeEntry clone)
2621           throws IOException, ParseException
2622   {
2623     while (token.type == Token.Comma)
2624     {
2625       match (Token.Comma);
2626       AttributeEntry attribute = (AttributeEntry)clone.clone ();
2627       attribute.name (token.name);
2628       // Override the declaration comment (i.e., that preceding the
2629       // "attribute" keyword) if the attribute identifier is commented.
2630       if (!token.comment.text ().equals (""))
2631         attribute.comment (token.comment);
2632       entry.methodsAddElement (attribute, scanner);
2633       pigeonholeMethod (entry, attribute);
2634       match (Token.Identifier);
2635     }
2636   } // attrDcl2
2637 
2638   /**
2639    *
2640    **/
2641   private void exceptDcl (SymtabEntry entry) throws IOException, ParseException
2642   {
2643     match (Token.Exception);
2644     repIDStack.push (((IDLID)repIDStack.peek ()).clone ());
2645     ExceptionEntry exceptEntry = stFactory.exceptionEntry (entry, (IDLID)repIDStack.peek ());
2646     ((IDLID)repIDStack.peek ()).appendToName (token.name);
2647     exceptEntry.sourceFile (scanner.fileEntry ());
2648     // Comment must immediately precede "exception" keyword
2649     exceptEntry.comment (tokenHistory.lookBack (1).comment);
2650     exceptEntry.name (token.name);
2651     match (Token.Identifier);
2652     pigeonhole (entry, exceptEntry);
2653     if (token.equals (Token.LeftBrace))
2654     {
2655       prep.openScope (exceptEntry);
2656       match (Token.LeftBrace);
2657       memberList2 (exceptEntry);
2658       prep.closeScope (exceptEntry);
2659       match (Token.RightBrace);
2660       repIDStack.pop ();
2661     }
2662     else
2663       throw ParseException.syntaxError (scanner, Token.LeftBrace,token.type);
2664   } // exceptDcl
2665 
2666   /**
2667    *
2668    **/
2669   private void opDcl (InterfaceEntry entry) throws IOException, ParseException
2670   {
2671     MethodEntry method = stFactory.methodEntry (entry, (IDLID)repIDStack.peek ());
2672     method.sourceFile (scanner.fileEntry ());
2673     // Comment must immediately precede "oneway" keyword or <return_type_spec>
2674     method.comment (token.comment);
2675     if (token.type == Token.Oneway)
2676     {
2677       match (Token.Oneway);
2678       method.oneway (true);
2679     }
2680     method.type (opTypeSpec (method));
2681     repIDStack.push (((IDLID)repIDStack.peek ()).clone ());
2682     ((IDLID)repIDStack.peek ()).appendToName (token.name);
2683     method.name (token.name);
2684     entry.methodsAddElement (method, scanner);
2685     pigeonholeMethod (entry, method);
2686     opDcl2 (method);
2687     if (method.oneway ())
2688       checkIfOpLegalForOneway (method);
2689     repIDStack.pop ();
2690   } // opDcl
2691 
2692   /**
2693    *
2694    **/
2695   private void checkIfOpLegalForOneway (MethodEntry method)
2696   {
2697     boolean notLegal = false;
2698     if ((method.type() != null) ||
2699          (method.exceptions().size() != 0)) notLegal = true;
2700     else
2701     {
2702       for (Enumeration e = method.parameters().elements(); e.hasMoreElements();)
2703       {
2704         if (((ParameterEntry)e.nextElement ()).passType () != ParameterEntry.In)
2705         {
2706           notLegal = true;
2707           break;
2708         }
2709       }
2710     }
2711     if (notLegal)
2712       ParseException.oneway (scanner, method.name ());
2713   } // checkifOpLegalForOneway
2714 
2715   /**
2716    *
2717    **/
2718   private void opDcl2 (MethodEntry method) throws IOException, ParseException
2719   {
2720     if (token.equals (Token.MacroIdentifier))
2721     {
2722       match (Token.MacroIdentifier);
2723       parameterDcls2 (method);
2724     }
2725     else
2726     {
2727       match (Token.Identifier);
2728       parameterDcls (method);
2729      }
2730     opDcl3 (method);
2731   } // opDcl2
2732 
2733   /**
2734    *
2735    **/
2736   private void opDcl3 (MethodEntry entry) throws IOException, ParseException
2737   {
2738     if (token.type != Token.Semicolon)
2739     {
2740       if (!token.equals (Token.Raises) && !token.equals (Token.Context))
2741         throw ParseException.syntaxError (scanner, new int [] {
2742             Token.Raises, Token.Context, Token.Semicolon }, token.type);
2743       if (token.type == Token.Raises)
2744         raisesExpr (entry);
2745       if (token.type == Token.Context)
2746         contextExpr (entry);
2747     }
2748   } // opDcl3
2749 
2750   /**
2751    *
2752    **/
2753   private SymtabEntry opTypeSpec (SymtabEntry entry) throws IOException, ParseException
2754   {
2755     SymtabEntry ret = null;
2756     if (token.type == Token.Void)
2757       match (Token.Void);
2758     else
2759       ret = paramTypeSpec (entry);
2760     return ret;
2761   } // opTypeSpec
2762 
2763   /**
2764    *
2765    **/
2766   private void parameterDcls (MethodEntry entry) throws IOException, ParseException
2767   {
2768     match (Token.LeftParen);
2769     parameterDcls2 (entry);
2770   } // parameterDcls
2771 
2772   /**
2773    *
2774    **/
2775   private void parameterDcls2 (MethodEntry entry) throws IOException, ParseException
2776   {
2777     if (token.type == Token.RightParen)
2778       match (Token.RightParen);
2779     else
2780     {
2781       paramDcl (entry);
2782       while (token.type == Token.Comma)
2783       {
2784         match (Token.Comma);
2785         paramDcl (entry);
2786       }
2787       match (Token.RightParen);
2788     }
2789   } // paraneterDcls2
2790 
2791   /**
2792    *
2793    **/
2794   private void paramDcl (MethodEntry entry) throws IOException, ParseException
2795   {
2796     ParameterEntry parmEntry = stFactory.parameterEntry (entry, (IDLID)repIDStack.peek ());
2797     parmEntry.sourceFile (scanner.fileEntry ());
2798     // Comment must immeiately precede the parameter attribute
2799     parmEntry.comment (token.comment);
2800     paramAttribute (parmEntry);
2801     parmEntry.type (paramTypeSpec (entry));
2802     parmEntry.name (token.name);
2803     match (Token.Identifier);
2804     if (isntInList (entry.parameters (), parmEntry.name ()))
2805       entry.addParameter (parmEntry);
2806   } // paramDcl
2807 
2808   /**
2809    *
2810    **/
2811   private void paramAttribute (ParameterEntry entry) throws IOException, ParseException
2812   {
2813     if (token.type == Token.In)
2814     {
2815       entry.passType (ParameterEntry.In);
2816       match (Token.In);
2817     }
2818     else if (token.type == Token.Out)
2819     {
2820       entry.passType (ParameterEntry.Out);
2821       match (Token.Out);
2822     }
2823     else if (token.type == Token.Inout)
2824     {
2825       entry.passType (ParameterEntry.Inout);
2826       match (Token.Inout);
2827     }
2828     else
2829       throw ParseException.syntaxError (scanner, new int [] {
2830           Token.In, Token.Out, Token.Inout }, token.type);
2831   } // paramAttribute
2832 
2833   /**
2834    *
2835    **/
2836   private void raisesExpr (MethodEntry entry) throws IOException, ParseException
2837   {
2838     match (Token.Raises);
2839     match (Token.LeftParen);
2840     // Comment must immediately precede <scoped_name> for exception
2841     Comment tempComment = token.comment;
2842     SymtabEntry exception = scopedName(entry.container (), stFactory.exceptionEntry ());
2843     if (typeOf (exception) instanceof ExceptionEntry)
2844     {
2845       // Comment must immediately precede <scoped_name> for exception
2846       exception.comment (tempComment);
2847       if (isntInList (entry.exceptions (), exception))
2848         entry.exceptionsAddElement ((ExceptionEntry) exception);
2849     }
2850     else
2851       ParseException.wrongType (scanner, exception.fullName(),
2852           "exception", entryName (exception.type ()));
2853     raisesExpr2 (entry);
2854     match (Token.RightParen);
2855   } // raisesExpr
2856 
2857   /**
2858    *
2859    **/
2860   private void raisesExpr2 (MethodEntry entry) throws IOException, ParseException
2861   {
2862     while (token.type == Token.Comma)
2863     {
2864       match (Token.Comma);
2865       // Comment must immediately precede <scoped_name> of exception
2866       Comment tempComment = token.comment;
2867       SymtabEntry exception = scopedName (entry.container (), stFactory.exceptionEntry ());
2868       if (typeOf (exception) instanceof ExceptionEntry)
2869       {
2870         // Comment must immediately precede <scoped_name> of exception
2871         exception.comment (tempComment);
2872         if (isntInList (entry.exceptions (), exception))
2873           entry.addException ((ExceptionEntry)exception);
2874       }
2875       else
2876         ParseException.wrongType (scanner, exception.fullName (),
2877             "exception", entryName (exception.type ()));
2878     }
2879   } // raisesExpr2
2880 
2881   /**
2882    *
2883    **/
2884   private void contextExpr (MethodEntry entry) throws IOException, ParseException
2885   {
2886     match (Token.Context);
2887     match (Token.LeftParen);
2888     String stringLit = (String)stringLiteral ().value ();
2889     if (isntInStringList (entry.contexts (), stringLit))
2890       entry.addContext (stringLit);
2891     contextExpr2 (entry);
2892     match (Token.RightParen);
2893   } // contextExpr
2894 
2895 
2896   private void contextExpr2 (MethodEntry entry) throws IOException, ParseException
2897   {
2898     while (token.type == Token.Comma)
2899     {
2900       match (Token.Comma);
2901       String stringLit = (String)stringLiteral ().value ();
2902       if (isntInStringList (entry.contexts (), stringLit))
2903         entry.addContext (stringLit);
2904     }
2905   } // contextExpr2
2906 
2907   /**
2908    *
2909    **/
2910   private SymtabEntry paramTypeSpec (SymtabEntry entry) throws IOException, ParseException
2911   {
2912     SymtabEntry ret = null;
2913     switch (token.type)
2914     {
2915       case Token.Float:
2916       case Token.Double:
2917       case Token.Long:
2918       case Token.Short:
2919       case Token.Unsigned:
2920       case Token.Char:
2921       case Token.Wchar:
2922       case Token.Boolean:
2923       case Token.Octet:
2924       case Token.Any:
2925         return baseTypeSpec (entry);
2926       case Token.String:
2927       case Token.Wstring:
2928         return stringType (entry);
2929       case Token.Identifier:
2930       case Token.Object:
2931       // <f46082.40>
2932       case Token.ValueBase:
2933       case Token.DoubleColon:
2934         ret = scopedName (entry.container (), stFactory.primitiveEntry ());
2935         if (typeOf (ret) instanceof AttributeEntry)
2936           //ParseException.attributeParamType (scanner);
2937           ParseException.attributeNotType (scanner, ret.name ());
2938         else // <d60942>
2939           if (typeOf (ret) instanceof MethodEntry)
2940             ParseException.operationNotType (scanner, ret.name ());
2941 
2942         //if (!(returnType instanceof PrimitiveEntry ||
2943         //     returnType instanceof StringEntry))
2944         //ParseException.wrongType (scanner, ret.fullName(),
2945         //                          "primitive or string", entryName (ret.type()));
2946         break;
2947       default:
2948         throw ParseException.syntaxError (scanner, new int [] {
2949             Token.Float,      Token.Double,      Token.Long,    Token.Short,
2950             Token.Unsigned,   Token.Char,        Token.Wchar,   Token.Boolean,
2951             Token.Octet,      Token.Any,         Token.String,  Token.Wstring,
2952             Token.Identifier, Token.DoubleColon, Token.ValueBase }, token.type);
2953     }
2954     return ret;
2955   } // paramTypeSpec
2956 
2957   /**
2958    *
2959    **/
2960   private void match (int type) throws IOException, ParseException
2961   {
2962     ParseException exception = null;
2963     if (!token.equals (type))
2964     {
2965       exception = ParseException.syntaxError (scanner, type, token.type);
2966       // Missing a semicolon is a common error.  If a semicolon was expected,
2967       // assume it exists and keep the current token (don't get the next one).
2968       // BEWARE!!! THIS HAS THE POTENTIAL FOR AN INFINITE LOOP!
2969       if (type == Token.Semicolon)
2970         return;
2971     }
2972     // <f46082.40> Unecessary due to new valueElement() algorithm.
2973     //if (!tokenStack.empty())
2974     //{
2975     //  token = (Token)tokenStack.pop ();
2976     //  return;
2977     //}
2978 
2979     // Fetch the next token.
2980     token = scanner.getToken ();
2981 
2982     // <d62023> Issue warnings about tokens.
2983     issueTokenWarnings ();
2984 
2985     // Maintain history of most recent tokens.
2986     tokenHistory.insert (token);
2987 
2988     // <d59166> Identifiers that collide with keywords are illegal.  Note
2989     // that escaped identifers never collide!
2990     /*
2991     if (token.collidesWithKeyword ())
2992     {
2993       // <f60858.1> Issue a warning only
2994       if (corbaLevel <= 2.2f)
2995         ParseException.keywordCollisionWarning (scanner, token.name);
2996       else
2997         exception = ParseException.keywordCollision (scanner, token.name);
2998     }
2999     */
3000 
3001     while (token.isDirective ())
3002       token = prep.process (token);
3003 
3004     // If the token is a defined thingy, scan the defined string
3005     // instead of the input stream for a while.
3006     if (token.equals (Token.Identifier) || token.equals (Token.MacroIdentifier))
3007     {
3008       String string = (String)symbols.get (token.name);
3009       if (string != null && !string.equals (""))
3010       {
3011         // If this is a macro, parse the macro
3012         if (macros.contains (token.name))
3013         {
3014           scanner.scanString (prep.expandMacro (string, token));
3015           match (token.type);
3016         }
3017         else // This is just a normal define.
3018         {
3019           scanner.scanString (string);
3020           match (token.type);
3021         }
3022       }
3023     }
3024     if (exception != null)
3025       throw exception;
3026   } // match
3027 
3028   // <d62023>
3029   /**
3030    * Issue warnings according to attributes of current Token.
3031    **/
3032   private void issueTokenWarnings ()
3033   {
3034     if (noWarn)
3035       return;
3036 
3037     if ((token.equals (Token.Identifier) || token.equals (Token.MacroIdentifier))
3038         && !token.isEscaped ())
3039     {
3040       // Identifier collision with keyword in another release.
3041       // Identifier collision with keyword in letter, but not in case.
3042       if (token.collidesWithKeyword ())
3043         ParseException.warning (scanner, Util.getMessage ("Migration.keywordCollision", token.name));
3044     }
3045     // Deprecated keyword.
3046     if (token.isKeyword () && token.isDeprecated ())
3047       ParseException.warning (scanner, Util.getMessage ("Deprecated.keyword", token.toString ()));
3048   } // issueTokenWarnings
3049 
3050   /**
3051    *
3052    **/
3053   private ModuleEntry newModule (ModuleEntry oldEntry)
3054   {
3055     ModuleEntry entry = stFactory.moduleEntry (oldEntry, (IDLID)repIDStack.peek ());
3056     entry.sourceFile (scanner.fileEntry ());
3057     entry.name (token.name);
3058     // If this named module already exists, just reopen it.
3059     /* <46082.46.01> if cppModule, always create new module entry */
3060     SymtabEntry prevEntry = (SymtabEntry) symbolTable.get (entry.fullName ());
3061     if (!cppModule && prevEntry != null && prevEntry instanceof ModuleEntry)
3062     {
3063       // A module has been reopened, return that ModuleEntry.
3064       entry = (ModuleEntry) prevEntry;
3065       if (oldEntry == topLevelModule)
3066       {
3067         // Do a little checking:
3068         if (!entry.emit ())
3069           // The entry module is being reopened to put new stuff into it.
3070           // The module itself is not marked as "emit", but the new stuff
3071           // may be, so put the module on the emitList (add it to topLevelModule).
3072           addToContainer (oldEntry, entry);
3073         else if (!oldEntry.contained().contains (entry))
3074           // <d50767> The entry module being reopened is to be emitted, but
3075           // will not be placed on the emitList! I.E., it was not added to
3076           // topLevelModule.  Occurs when a generator manually inserts
3077           // ModuleEntrys into the symbol table (e.g., org; see preParse()
3078           // in ...idl.toJava.Compile). <daz>
3079           addToContainer (oldEntry, entry);
3080       }
3081     }
3082     else
3083       pigeonhole (oldEntry, entry);
3084     return entry;
3085   } // newModule
3086 
3087   /**
3088    *
3089    **/
3090   private EnumEntry newEnumEntry (SymtabEntry oldEntry)
3091   {
3092     EnumEntry entry = stFactory.enumEntry (oldEntry, (IDLID)repIDStack.peek ());
3093     entry.sourceFile (scanner.fileEntry ());
3094     entry.name (token.name);
3095     pigeonhole (oldEntry, entry);
3096     return entry;
3097   } // newEnumEntry
3098 
3099   /**
3100    *
3101    **/
3102   private SequenceEntry newSequenceEntry (SymtabEntry oldEntry)
3103   {
3104     SequenceEntry entry = stFactory.sequenceEntry (oldEntry, (IDLID)repIDStack.peek ());
3105      entry.sourceFile (scanner.fileEntry ());
3106      entry.name ("");
3107      pigeonhole (oldEntry, entry);
3108      return entry;
3109   } // newSequenceEntry
3110 
3111     private void updateSymbolTable( String fullName, SymtabEntry entry, boolean lcCheck )
3112     {
3113         // Check for case-insensitive collision (IDL error).
3114         String lcFullName = fullName.toLowerCase();
3115         if (lcCheck)
3116             if (lcSymbolTable.get (lcFullName) != null) {
3117                 ParseException.alreadyDeclared (scanner, fullName);
3118             }
3119         symbolTable.put (fullName, entry);
3120         lcSymbolTable.put (lcFullName, entry);
3121         // <d59809> Allow fully-qualified CORBA types to be resolved by mapping
3122         // short name (e.g., CORBA/StringValue) to long name, actual name.
3123         String omgPrefix = "org/omg/CORBA" ;
3124         if (fullName.startsWith (omgPrefix)) {
3125             overrideNames.put (
3126                 "CORBA" + fullName.substring (omgPrefix.length()), fullName);
3127         }
3128     }
3129 
3130     private void pigeonhole (SymtabEntry container, SymtabEntry entry)
3131     {
3132         if (entry.name().equals (""))
3133             entry.name (unknownNamePrefix + ++sequence);
3134 
3135         // If this object is not in the overrides list, then it is
3136         // ok to put it in the table (if it IS in the overrides list,
3137         // it is already in the table under a different name).
3138         String fullName = entry.fullName();
3139         if (overrideNames.get (fullName) == null) {
3140             addToContainer (container, entry);
3141 
3142             // It is an error is this name already exists in the symbol
3143             // table, unless this is a redefinition of a forward decl.
3144             // Re-opening a module is also legal, but not handled here.
3145             SymtabEntry oldEntry = (SymtabEntry) symbolTable.get (fullName);
3146 
3147             if (oldEntry == null) {
3148                 updateSymbolTable( fullName, entry, true ) ;
3149             } else if (oldEntry instanceof ForwardEntry &&
3150                 entry instanceof InterfaceEntry) {
3151 
3152                 String repIDPrefix = ((IDLID)entry.repositoryID ()).prefix ();
3153                 String oldRepIDPrefix = ((IDLID)oldEntry.repositoryID ()).prefix ();
3154                 if (repIDPrefix.equals (oldRepIDPrefix)) {
3155                     updateSymbolTable( fullName, entry, false ) ;
3156                 } else {
3157                     ParseException.badRepIDPrefix (scanner, fullName,
3158                         oldRepIDPrefix, repIDPrefix);
3159                 }
3160             } else if (entry instanceof ForwardEntry &&
3161                        (oldEntry instanceof InterfaceEntry ||
3162                         oldEntry instanceof ForwardEntry)) {
3163                 if (oldEntry instanceof ForwardEntry &&
3164                     entry.repositoryID () instanceof IDLID &&
3165                     oldEntry.repositoryID () instanceof IDLID) {
3166 
3167                     String repIDPrefix =
3168                         ((IDLID)entry.repositoryID ()).prefix ();
3169                     String oldRepIDPrefix =
3170                         ((IDLID)oldEntry.repositoryID ()).prefix ();
3171 
3172                     if (!(repIDPrefix.equals (oldRepIDPrefix))) {
3173                         // Disallow multiple ForwardEntry's having same Repository
3174                         // ID prefixes (CORBA 2.3).
3175                         ParseException.badRepIDPrefix (scanner, fullName,
3176                             oldRepIDPrefix, repIDPrefix);
3177                     }
3178                 }
3179             } else if (cppModule && entry instanceof ModuleEntry &&
3180                 oldEntry instanceof ModuleEntry) {
3181                 // Allow multiple ModuleEntrys when user submits
3182                 // the -cppModule flag.
3183             } else if (fullName.startsWith ("org/omg/CORBA") ||
3184                 fullName.startsWith ("CORBA")) {
3185                 // Ignore CORBA PIDL types entered at preParse() by generator.
3186             } else if (isForwardable( oldEntry, entry )) {
3187                 // Both oldEntry and entry are structs or unions.
3188                 // Legality depends on isReferencable on the two entries:
3189                 // oldEntry     Entry
3190                 //      T           T       ERROR alreadyDeclared
3191                 //      T           F       legal fwd decl
3192                 //      F           T       if defined in same file legal,
3193                 //                          otherwise ERROR
3194                 //      F           F       legal fwd decl
3195                 if (oldEntry.isReferencable() && entry.isReferencable())
3196                     ParseException.alreadyDeclared (scanner, fullName);
3197 
3198                 if (entry.isReferencable()) {
3199                     String firstFile =
3200                         oldEntry.sourceFile().absFilename() ;
3201                     String defFile =
3202                         entry.sourceFile().absFilename() ;
3203                     if (!firstFile.equals( defFile ))
3204                         ParseException.declNotInSameFile( scanner,
3205                             fullName, firstFile ) ;
3206                     else {
3207                         updateSymbolTable( fullName, entry, false ) ;
3208 
3209                         List oldRefList ;
3210 
3211                         try {
3212                             oldRefList = (List)oldEntry.dynamicVariable(
3213                                 ftlKey ) ;
3214                         } catch (NoSuchFieldException exc) {
3215                             throw new IllegalStateException() ;
3216                         }
3217 
3218                         if (oldRefList != null) {
3219                             // Update entries in backpatch list
3220                             Iterator iter = oldRefList.iterator() ;
3221                             while (iter.hasNext()) {
3222                                 SymtabEntry elem = (SymtabEntry)iter.next() ;
3223                                 elem.type( entry ) ;
3224                             }
3225                         }
3226                     }
3227                 }
3228             } else {
3229                 ParseException.alreadyDeclared (scanner, fullName);
3230             }
3231         }
3232     } // pigeonhole
3233 
3234     private boolean isForwardable( SymtabEntry oldEntry,
3235         SymtabEntry entry )
3236     {
3237         return ((oldEntry instanceof StructEntry) &&
3238             (entry instanceof StructEntry)) ||
3239            ((oldEntry instanceof UnionEntry) &&
3240             (entry instanceof UnionEntry)) ;
3241     }
3242 
3243   // pigeonhole checks to see if this entry is already in the symbol
3244   // table and generates an error if it is.  Methods must be checked
3245   // not only against the symbol table but also against their
3246   // interface's parent's methods.  This is done in InterfaceEntry.
3247   // verifyMethod, so no checking need be done here.
3248 
3249   /**
3250    *
3251    **/
3252   private void pigeonholeMethod (InterfaceEntry container, MethodEntry entry)
3253   {
3254     if (entry.name ().equals (""))
3255        entry.name (unknownNamePrefix + ++sequence);
3256 
3257     // If this object is not in the overrides list, then it is
3258     // ok to put it in the table (if it IS in the overrides list,
3259     // it is already in the table under a different name).
3260     String fullName = entry.fullName ();
3261     if (overrideNames.get (fullName) == null)
3262     {
3263       addToContainer (container, entry);
3264       String lcFullName = fullName.toLowerCase ();
3265       symbolTable.put (fullName, entry);
3266       lcSymbolTable.put (lcFullName, entry);
3267       // <d59809> Allow fully-qualified CORBA types to be resolved by mapping
3268       // short name (e.g., CORBA/StringValue) to long name, actual name.
3269       if (fullName.startsWith ("org/omg/CORBA"))
3270         overrideNames.put ("CORBA" + fullName.substring (13), fullName);
3271     }
3272   } // pigeonholeMethod
3273 
3274   /**
3275    *
3276    **/
3277   private void addToContainer (SymtabEntry container, SymtabEntry contained)
3278   {
3279     if (container instanceof ModuleEntry)
3280       ((ModuleEntry)container).addContained (contained);
3281     else if (container instanceof InterfaceEntry)
3282       ((InterfaceEntry)container).addContained (contained);
3283     else if (container instanceof StructEntry)
3284       ((StructEntry)container).addContained (contained);
3285     else if (container instanceof UnionEntry)
3286       ((UnionEntry)container).addContained (contained);
3287     else if (container instanceof SequenceEntry)
3288       ((SequenceEntry)container).addContained (contained);
3289   } // addToContainer
3290 
3291   // NOTE: qualifiedEntry/partlyQualifiedEntry/unqualifiedEntry and
3292   // their court could probably use some performance improvements,
3293   // but I'm scared to touch anything.  It's the most complex bit of
3294   // code in this parser.
3295 
3296   // The qualified named type is searched for in the following order:
3297   // 1.  OverrideNames
3298   // 2.  Global scope
3299   // 3.  Inheritance scope (if container is an interface)
3300   // A qualified name is one which begins with :: or is assumed to be
3301   // in the global scope (like long, short, etc).
3302 
3303   /**
3304    *
3305    **/
3306   SymtabEntry qualifiedEntry (String typeName)
3307   {
3308     SymtabEntry type = recursiveQualifiedEntry (typeName);
3309     if (type == null)
3310       // Then it's not anywhere, report the error.
3311       ParseException.undeclaredType (scanner, typeName);
3312 
3313     // <d57110> Relax this retriction when parsing ID pragma directive, e.g..
3314     //else if (type instanceof ModuleEntry) {
3315     else if (type instanceof ModuleEntry && !_isModuleLegalType)
3316     {
3317       // Module's are not valid types.
3318       ParseException.moduleNotType (scanner, typeName);
3319       type = null;
3320     }
3321     return type;
3322   } // qualifiedEntry
3323 
3324   /**
3325    *
3326    **/
3327   SymtabEntry recursiveQualifiedEntry (String typeName)
3328   {
3329     SymtabEntry type = null;
3330     if (typeName != null && !typeName.equals ("void"))
3331     {
3332       int index = typeName.lastIndexOf ('/');
3333       if (index >= 0)
3334       {
3335         // Figure out if the container of this thing exists, converting any typedefs to interfaces if necessary.
3336         type = recursiveQualifiedEntry (typeName.substring (0, index));
3337         if (type == null)
3338           return null;
3339         else if (type instanceof TypedefEntry)
3340           typeName = typeOf (type).fullName () + typeName.substring (index);
3341       }
3342 
3343       // If we got this far, a container exists, start over looking
3344       // for the thing itself (this is the meat of the method):
3345       type = searchOverrideNames (typeName);
3346       if (type == null)
3347         type = (SymtabEntry) symbolTable.get (typeName); // search global scope:
3348       if (type == null)
3349         type = searchGlobalInheritanceScope (typeName);
3350     }
3351     return type;
3352   } // recursiveQualifiedEntry
3353 
3354   // A partially qualified name is of the form <scope>::<name>.
3355   // First the scope is defined (meaning it is fully qualified);
3356   // Then the name is searched for in the scope.
3357 
3358   /**
3359    *
3360    **/
3361   SymtabEntry partlyQualifiedEntry (String typeName, SymtabEntry container)
3362   {
3363     // This is the simple logic of this method:
3364     // type = searchModuleScope (typeName.substring (0, typeName.lastIndexOf ('/')), container);
3365     // type = qualifiedEntry (type.fullName () + typeName.substring (typeName.lastIndexOf ('/')));
3366     // But searchModuleScope only finds the first module that fits.
3367     // The name might not be in that module but in one further out
3368     // in the module scope.  Should others be searched?
3369     SymtabEntry type = null;
3370     if (typeName != null)
3371     {
3372       int index = typeName.lastIndexOf ('/');
3373 
3374       // Figure out if the container of this thing exists, converting any
3375       // typedefs to interfaces if necessary:
3376       type = recursivePQEntry (typeName.substring (0, index), container);
3377       if (type instanceof TypedefEntry)
3378         typeName = typeOf (type).fullName () + typeName.substring (index);
3379 
3380       // If we got this far, a container exists, start over looking
3381       // for the thing itself.
3382 
3383       if (container != null)
3384         type = searchModuleScope (typeName.substring (0, typeName.lastIndexOf ('/')), container);
3385       if (type == null)
3386         type = qualifiedEntry (typeName);
3387       else
3388         type = qualifiedEntry (type.fullName () + typeName.substring (typeName.lastIndexOf ('/')));
3389     }
3390     return type;
3391   } // partlyQualifiedEntry
3392 
3393   // partlyQualifiedEntry and recursivePQEntry are almost identical.
3394   // They are different because when the recursive one is looking for
3395   // the existence of containers, the error check for a module type
3396   // must not occur (this check is done in qualifiedEntry).  Only
3397   // when the full partly qualified name is being processed must this
3398   // check be performed.
3399 
3400   /**
3401    *
3402    **/
3403   SymtabEntry recursivePQEntry (String typeName, SymtabEntry container)
3404   {
3405     SymtabEntry type = null;
3406     if (typeName != null)
3407     {
3408       int index = typeName.lastIndexOf ('/');
3409       if (index < 0)
3410         type = searchModuleScope (typeName, container);
3411       else
3412       {
3413         // Figure out if the container of this thing exists, converting any
3414         // typedefs to interfaces if necessary:
3415         type = recursivePQEntry (typeName.substring (0, index), container);
3416         if (type == null)
3417           return null;
3418         else if (type instanceof TypedefEntry)
3419           typeName = typeOf (type).fullName () + typeName.substring (index);
3420 
3421         // If we got this far, a container exists, start over, looking
3422         // for the thing itself (This is the meat of the method):
3423         if (container != null)
3424           type = searchModuleScope (typeName.substring (0, typeName.lastIndexOf ('/')), container);
3425           if (type == null)
3426             recursiveQualifiedEntry (typeName);
3427           else
3428             type = recursiveQualifiedEntry (type.fullName () + typeName.substring (typeName.lastIndexOf ('/')));
3429       }
3430     }
3431     return type;
3432   } // recursivePQEntry
3433 
3434   // The named type is searched for in the following order:
3435   // 1.  Local scope
3436   // 2.  Inheritance scope
3437   // 3.  OverrideNames
3438   // 4.  Module scope
3439 
3440   /**
3441    *
3442    **/
3443   SymtabEntry unqualifiedEntry (String typeName, SymtabEntry container)
3444   {
3445     SymtabEntry type = unqualifiedEntryWMod (typeName, container);
3446 
3447     // <d57110> Relax this retriction in special cases, e.g., when
3448     // parsing a ID pragma directive.
3449     //if (type instanceof ModuleEntry) {
3450     if (type instanceof ModuleEntry && !_isModuleLegalType)
3451     {
3452       // Module's are not valid types:
3453       ParseException.moduleNotType (scanner, typeName);
3454       type = null;
3455     }
3456     return type;
3457   } // unqualifiedEntry
3458 
3459   /**
3460    *
3461    **/
3462   SymtabEntry unqualifiedEntryWMod (String typeName, SymtabEntry container)
3463   {
3464     SymtabEntry type = null;
3465     if ((typeName != null) && !typeName.equals ("void"))
3466     {
3467       // Search local scope:
3468       type = (SymtabEntry)symbolTable.get (container.fullName () + '/' + typeName);
3469       if (type == null)
3470         type = searchLocalInheritanceScope (typeName, container);
3471       if (type == null)
3472         type = searchOverrideNames (typeName);
3473       if ((type == null) && (container != null))
3474         type = searchModuleScope (typeName, container);
3475       if (type == null)
3476         type = searchParentInheritanceScope (typeName, container);
3477     }
3478     if (type == null)
3479       // Then it's not anywhere, report the error:
3480       ParseException.undeclaredType (scanner, typeName);
3481     return type;
3482   } // unqualifiedEntryWMod
3483 
3484   /**
3485    * Walks up the enclosing scopes until it finds an interface type. Then,
3486    * searches up that interface inheritance tree for the type definition.
3487    *
3488    * @param name type name to be searched for.
3489    * @param ptype parent type entry.
3490    **/
3491   SymtabEntry searchParentInheritanceScope(String name, SymtabEntry ptype) {
3492 
3493     String cname = ptype.fullName();
3494 
3495     while ((ptype != null) && !(cname.equals ("")) &&
3496            !(ptype instanceof InterfaceEntry)) {
3497         int index = cname.lastIndexOf ('/');
3498         if (index < 0) {
3499             cname = "";
3500         } else {
3501             cname = cname.substring (0, index);
3502             ptype = (SymtabEntry) symbolTable.get(cname);
3503         }
3504     }
3505 
3506     if ((ptype == null) || !(ptype instanceof InterfaceEntry)) {
3507         return null; // could not find an enclosing interface type - give up.
3508     }
3509 
3510     // check if the enclosing interface supports the type definition.
3511     String fullName = ptype.fullName () + '/' + name;
3512     SymtabEntry type = (SymtabEntry) symbolTable.get (fullName);
3513     if (type != null) {
3514         return type; // found type definition.
3515     }
3516 
3517     // search up the interface inheritance tree.
3518     return searchLocalInheritanceScope(name, ptype);
3519   }
3520 
3521   /**
3522    *
3523    **/
3524   SymtabEntry searchGlobalInheritanceScope (String name)
3525   {
3526     // See if the container of this named object is an interface:
3527     int         index = name.lastIndexOf ('/');
3528     SymtabEntry entry = null;
3529     if (index >= 0)
3530     {
3531       String containerName = name.substring (0, index);
3532       entry = (SymtabEntry)symbolTable.get (containerName);
3533       entry = (entry instanceof InterfaceEntry)
3534           // It's an interface, now look in its inheritance scope:
3535           ? searchLocalInheritanceScope (name.substring (index + 1), entry)
3536           : null;
3537     }
3538     return entry;
3539   } // searchGlobalInheritanceScope
3540 
3541   /**
3542    *
3543    **/
3544   SymtabEntry searchLocalInheritanceScope (String name, SymtabEntry container)
3545   {
3546     return (container instanceof InterfaceEntry)
3547         ? searchDerivedFrom (name, (InterfaceEntry) container)
3548         : null;
3549   } // searchLocalInheritanceScope
3550 
3551   /**
3552    *
3553    **/
3554   SymtabEntry searchOverrideNames (String name)
3555   {
3556     String overrideName = (String)overrideNames.get (name);
3557     return (overrideName != null)
3558         ? (SymtabEntry)symbolTable.get (overrideName)
3559         : null;
3560   } // searchOverrideNames
3561 
3562   /**
3563    *
3564    **/
3565   SymtabEntry searchModuleScope (String name, SymtabEntry container)
3566   {
3567     String      module   = container.fullName ();
3568     String      fullName = module + '/' + name;
3569     SymtabEntry type     = (SymtabEntry)symbolTable.get (fullName);
3570     while ((type == null) && !module.equals (""))
3571     {
3572       int index = module.lastIndexOf ('/');
3573       if (index < 0)
3574         module = "";
3575       else
3576       {
3577         module   = module.substring (0, index);
3578         fullName = module + '/' + name;
3579         type     = (SymtabEntry)symbolTable.get (fullName);
3580       }
3581     }
3582     return (type == null) ? (SymtabEntry)symbolTable.get (name) : type;
3583   } // searchModuleScope
3584 
3585   /**
3586    *
3587    **/
3588   SymtabEntry searchDerivedFrom (String name, InterfaceEntry i)
3589   {
3590     for (Enumeration e = i.derivedFrom ().elements (); e.hasMoreElements ();)
3591     {
3592       SymtabEntry tmp = (SymtabEntry)e.nextElement ();
3593       if (tmp instanceof InterfaceEntry)
3594       {
3595         InterfaceEntry parent = (InterfaceEntry)tmp;
3596         String fullName = parent.fullName () + '/' + name;
3597         SymtabEntry type = (SymtabEntry)symbolTable.get (fullName);
3598         if (type != null)
3599           return type;
3600         type = searchDerivedFrom (name, parent);
3601         if (type != null)
3602           return type;
3603       }
3604       // else it is a ForwardEntry and nothing can be done at this point.
3605     }
3606     return null;
3607   } // searchDerivedFrom
3608 
3609   /**
3610    *
3611    **/
3612   String entryName (SymtabEntry entry)
3613   {
3614     if (entry instanceof AttributeEntry)
3615       return "attribute";
3616     if (entry instanceof ConstEntry)
3617       return "constant";
3618     if (entry instanceof EnumEntry)
3619       return "enumeration";
3620     if (entry instanceof ExceptionEntry)
3621       return "exception";
3622     if (entry instanceof ValueBoxEntry)
3623       return "value box";
3624     if (entry instanceof ForwardValueEntry || entry instanceof ValueEntry)
3625       return "value";
3626     if (entry instanceof ForwardEntry || entry instanceof InterfaceEntry)
3627       return "interface";
3628     if (entry instanceof MethodEntry)
3629       return "method";
3630     if (entry instanceof ModuleEntry)
3631       return "module";
3632     if (entry instanceof ParameterEntry)
3633       return "parameter";
3634     if (entry instanceof PrimitiveEntry)
3635       return "primitive";
3636     if (entry instanceof SequenceEntry)
3637       return "sequence";
3638     if (entry instanceof StringEntry)
3639       return "string";
3640     if (entry instanceof StructEntry)
3641       return "struct";
3642     if (entry instanceof TypedefEntry)
3643       return "typedef";
3644     if (entry instanceof UnionEntry)
3645       return "union";
3646     return "void";
3647   } // entryName
3648 
3649   /**
3650    *
3651    **/
3652   private boolean isInterface (SymtabEntry entry)
3653   {
3654     return entry instanceof InterfaceEntry || (entry instanceof ForwardEntry
3655         && !(entry instanceof ForwardValueEntry)) ;
3656   }
3657 
3658   private boolean isValue (SymtabEntry entry)
3659   {
3660     return entry instanceof ValueEntry ; // || entry instanceof ForwardValueEntry;
3661   }
3662 
3663   private boolean isInterfaceOnly (SymtabEntry entry)
3664   {
3665     return entry instanceof InterfaceEntry ;
3666   }
3667 
3668   private boolean isForward(SymtabEntry entry)
3669   {
3670       return entry instanceof ForwardEntry ;
3671   }
3672 
3673   // list must be a vector of Strings.
3674   /**
3675    *
3676    **/
3677   private boolean isntInStringList (Vector list, String name)
3678   {
3679     boolean isnt = true;
3680     Enumeration e = list.elements ();
3681     while (e.hasMoreElements ())
3682       if (name.equals ((String)e.nextElement ()))
3683       {
3684         ParseException.alreadyDeclared (scanner, name);
3685         isnt = false;
3686         break;
3687       }
3688     return isnt;
3689   } // isntInStringList
3690 
3691   // list must be a vector of SymtabEntry's.
3692   /**
3693    *
3694    **/
3695   private boolean isntInList (Vector list, String name)
3696   {
3697     boolean isnt = true;
3698     for (Enumeration e = list.elements (); e.hasMoreElements ();)
3699       if (name.equals (((SymtabEntry)e.nextElement ()).name ()))
3700       {
3701         ParseException.alreadyDeclared (scanner, name);
3702         isnt = false;
3703         break;
3704       }
3705     return isnt;
3706   } // isntInList
3707 
3708   // list must be a vector of SymtabEntry's.
3709   /**
3710    *
3711    **/
3712   private boolean isntInList (Vector list, SymtabEntry entry)
3713   {
3714     boolean isnt = true;
3715     for (Enumeration e = list.elements (); e.hasMoreElements ();)
3716     {
3717       SymtabEntry eEntry = (SymtabEntry)e.nextElement ();
3718       if (entry == eEntry)  // && entry.fullName().equals (eEntry.fullName()))
3719       {
3720         ParseException.alreadyDeclared (scanner, entry.fullName ());
3721         isnt = false;
3722         break;
3723       }
3724      }
3725      return isnt;
3726   } // isntInList
3727 
3728   /**
3729    *
3730    **/
3731   public static SymtabEntry typeOf (SymtabEntry entry)
3732   {
3733     while (entry instanceof TypedefEntry)
3734       entry = entry.type ();
3735     return entry;
3736   } // typeOf
3737 
3738   /**
3739    *
3740    **/
3741   void forwardEntryCheck ()
3742   {
3743     for (Enumeration e = symbolTable.elements (); e.hasMoreElements ();)
3744     {
3745       SymtabEntry entry = (SymtabEntry)e.nextElement ();
3746       if (entry instanceof ForwardEntry)
3747         ParseException.forwardEntry (scanner, entry.fullName ());
3748     }
3749   } // forwardEntryCheck
3750 
3751   // <46082.03> Revert to "IDL:"-style (i.e., regular) repository ID.
3752   /*
3753   void updateRepositoryIds () {
3754      for (Enumeration e = symbolTable.elements(); e.hasMoreElements();) {
3755          SymtabEntry entry = (SymtabEntry) e.nextElement();
3756          if (entry instanceof ValueEntry)
3757            ((ValueEntry) entry).calcRepId();
3758      }
3759   } // updateRepositoryIds
3760   */
3761 
3762   ////////////////////
3763   // Error Handling Methods
3764 
3765   // A syntax error occurred.  Skip until a semicolon is encountered.
3766   // Ignore semicolons within {...} blocks
3767   /**
3768    *
3769    **/
3770   private void skipToSemicolon () throws IOException
3771   {
3772     while (!token.equals (Token.EOF) && !token.equals (Token.Semicolon))
3773     {
3774       if (token.equals (Token.LeftBrace))
3775         skipToRightBrace();
3776       try
3777       {
3778         match (token.type);
3779       }
3780       catch (ParseException exception)
3781       {
3782         // The error has already been reported...
3783       }
3784     }
3785     if (token.equals (Token.EOF))
3786       throw new EOFException ();
3787     try
3788     {
3789       match (Token.Semicolon);
3790     }
3791     catch (Exception exception)
3792     {
3793     }
3794   } // skipToSemicolon
3795 
3796   /**
3797    *
3798    **/
3799   private void skipToRightBrace () throws IOException
3800   {
3801     boolean firstTime = true;
3802     while (!token.equals (Token.EOF) && !token.equals (Token.RightBrace))
3803     {
3804       if (firstTime)
3805         firstTime = false;
3806       else if (token.equals (Token.LeftBrace))
3807         skipToRightBrace ();
3808       try
3809       {
3810         match (token.type);
3811       }
3812       catch (ParseException exception)
3813       {
3814         // The error has already been reported...
3815       }
3816     }
3817     if (token.equals (Token.EOF))
3818       throw new EOFException();
3819   } // skipToRightBrace
3820 
3821   // Error Handling Methods
3822   ////////////////////
3823 
3824   // <d56351> In CORBA 2.3, an IDL file provides a new scope for Repository IDs.
3825   // The following methods provide a means for other classes in the framework
3826   // to manage this scoping (see Preprocessor and Scanner).
3827 
3828   // public static int nPush = 0;
3829   // public static int nPop = 0;
3830 
3831   /**
3832    *
3833    **/
3834   public static void enteringInclude ()
3835   {
3836     repIDStack.push (new IDLID ());
3837   } // enteringInclude
3838 
3839   /**
3840    *
3841    **/
3842   public static void exitingInclude ()
3843   {
3844     repIDStack.pop ();
3845   } // exitingInclude
3846 
3847 
3848   public static final String unknownNamePrefix = "uN__";
3849 
3850        static Hashtable   symbolTable;
3851               Hashtable   lcSymbolTable  = new Hashtable ();
3852        static Hashtable   overrideNames;
3853               Vector      emitList       = new Vector ();
3854               boolean     emitAll;
3855   // <f46082.46.01>
3856               boolean     cppModule;
3857   // <d62023>
3858               boolean     noWarn;
3859               Scanner     scanner;
3860   // <f46082.40> No longer necessary due to new valueElement() algorithm.
3861   //          Stack       tokenStack     = new Stack();
3862               Hashtable   symbols;
3863               Vector      macros         = new Vector ();
3864               Vector      paths;
3865 
3866   // Only needed for the pragma directive
3867               SymtabEntry currentModule  = null;
3868 
3869   // <d56351> Static field necessary to allow Scanner access to enterind/exiting
3870   // Include() methods. Must reset in Compile class, too!
3871   //          Stack       repIDStack     = new Stack ();
3872        static Stack       repIDStack     = new Stack ();
3873 
3874   // Dynamic variable key used for forward type lists.
3875   // A struct or union X entry may have this attached,
3876   // which always contains a List<SymtabEntry>.
3877   // The elements are entries E such that E.type() == X.
3878   // This list must be resolved in pigeonhole when the
3879   // type is finally defined.  This is similar to
3880   // ForwardEntry.replaceForwardDecl.
3881   private static int ftlKey = SymtabEntry.getVariableKey() ;
3882 
3883               int         sequence       = 0;
3884               Vector      includes;
3885               Vector      includeEntries;
3886 
3887   // Only needed in primaryExpr.  Set in Preprocessor.booleanConstExpr.
3888               boolean     parsingConditionalExpr = false;
3889 
3890               Token         token;
3891               ModuleEntry   topLevelModule;
3892   private     Preprocessor  prep;
3893   private     boolean       verbose;
3894               SymtabFactory stFactory;
3895               ExprFactory   exprFactory;
3896   private     String[]      keywords;
3897   // <f46082.51> Remove -stateful feature.
3898   //private     boolean       parseStateful = false;
3899 
3900   // Circular buffer containing most recent tokens, including the current token.
3901   private     TokenBuffer tokenHistory = new TokenBuffer ();
3902   protected   float       corbaLevel; // <f60858.1>
3903   private     Arguments   arguments;
3904 
3905 } // class Parser