Util.java revision 673:6b017d166ac2
1/*
2 * Copyright (c) 1999, 2004, 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.toJava
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
36package com.sun.tools.corba.se.idl.toJavaPortable;
37
38// Notes:
39// -F46838.4<klr> Ported -td option from toJava.
40// -10/17/98  KLR Ported fix for d48911 from toJava
41// -10/18/98  KLR Ported fix from toJava for "unsigned long" constants
42// -F46082.51<daz> Removed code to collect makefile list generation inforamtion
43//  from getStream(); see f46830.
44// -F46082.51<daz> Removed -stateful feature: methods javaStatefulName(String)
45//  and javaStatefulName(SymtabEntry) are obsolete, supplanted by javaName().
46// -D54640<daz> Represent unsigned long long expressions with their computed
47//  value rather than their actual representation (see notes in method
48//  parseTerminal(), parseBinary(), and parseUnary().)
49// -D58319<daz> Add getVersion() method.
50// -D48034<daz> Import Helper classes for typedef struct members when generating
51//  helper.  See method addImportLines().
52// -D59851<daz> Modify to enable QuickTest build. (pending)
53// -D42256<daz> Determine import lines for template types, which may specify any
54//  positive int., constant expression for a boundary. Such expression containing
55//  non-literal contansts previously caused problems when appearing in constructs
56//  structs, unions, exceptions, typedefs, operation types and parameters,
57//  attributes; and of course, sequences, strings.
58// -D59063<daz> Add helper for global exception to stub import list.
59// -D58951<daz> Publicise members for QuickTest.
60// -D59421<klr> Change ValueBaseHolder to SerializableHolder
61// -D59596<klr> Prevent accesses to elements of empty Vectors.
62// -D59771<daz> Add import stmt for Helper of global type in stubs.
63// -D59355<daz> Remove target dir. from filename when writing to prolog.
64// -D59437<daz> Fill typename information for value boxes.
65// -D62023<klr> Don't import ValueBase*
66// -D62023<klr> Add corbaLevel
67
68import java.io.File;
69import java.io.PrintWriter;
70import java.math.BigInteger;
71import java.text.DateFormat;
72import java.util.Date;
73import java.util.Enumeration;
74import java.util.Hashtable;
75import java.util.Locale;
76import java.util.Vector;
77
78import com.sun.tools.corba.se.idl.ConstEntry;
79import com.sun.tools.corba.se.idl.EnumEntry;
80import com.sun.tools.corba.se.idl.ExceptionEntry;
81import com.sun.tools.corba.se.idl.GenFileStream;
82import com.sun.tools.corba.se.idl.InterfaceEntry;
83import com.sun.tools.corba.se.idl.MethodEntry;
84import com.sun.tools.corba.se.idl.NativeEntry;
85import com.sun.tools.corba.se.idl.ParameterEntry;
86import com.sun.tools.corba.se.idl.PrimitiveEntry;
87import com.sun.tools.corba.se.idl.SequenceEntry;
88import com.sun.tools.corba.se.idl.StringEntry;
89import com.sun.tools.corba.se.idl.StructEntry;
90import com.sun.tools.corba.se.idl.SymtabEntry;
91import com.sun.tools.corba.se.idl.TypedefEntry;
92import com.sun.tools.corba.se.idl.UnionBranch;
93import com.sun.tools.corba.se.idl.UnionEntry;
94import com.sun.tools.corba.se.idl.ValueEntry;
95import com.sun.tools.corba.se.idl.ValueBoxEntry;
96import com.sun.tools.corba.se.idl.InterfaceState;
97
98import com.sun.tools.corba.se.idl.constExpr.*;
99
100/**
101 * Class Util is a repository of static members available for general
102 * use by the IDL parser framework and any generator extensions.
103 **/
104public class Util extends com.sun.tools.corba.se.idl.Util
105{
106  // <d58319>
107  /**
108   * Fetch the version number of this build of the IDL-to-Java (portable)
109   * compiler from the appropriate properties file.
110   * @return the version number of this compiler build.
111   **/
112  public static String getVersion ()
113  {
114    return com.sun.tools.corba.se.idl.Util.getVersion ("com/sun/tools/corba/se/idl/toJavaPortable/toJavaPortable.prp");
115  } // getVersion
116
117  /**
118   * This method is called by Setup.preEmit, so
119   * symbolTable is available for all Util methods.
120   **/
121  static void setSymbolTable (Hashtable symtab)
122  {
123    symbolTable = symtab;
124  } // setSymbolTable
125
126  public static void setPackageTranslation( Hashtable pkgtrans )
127  {
128    packageTranslation = pkgtrans ;
129  }
130
131  public static boolean isInterface (String name)
132  {
133    return isInterface (name, symbolTable);
134  } // isInterface
135
136  static String arrayInfo (Vector arrayInfo)
137  {
138    int         arrays = arrayInfo.size ();
139    String      info   = "";
140    Enumeration e      = arrayInfo.elements ();
141    while (e.hasMoreElements ())
142      info = info + '[' + parseExpression ((Expression)e.nextElement ()) + ']';
143    return info;
144  } // arrayInfo
145
146  // <d58951> static String sansArrayInfo (Vector arrayInfo)
147  public static String sansArrayInfo (Vector arrayInfo)
148  {
149    int    arrays   = arrayInfo.size ();
150    String brackets = "";
151    for (int i = 0; i < arrays; ++i)
152      brackets = brackets + "[]";
153    return brackets;
154  } // sansArrayInfo
155
156  // <d58951> static String sansArrayInfo (String name)
157  static public String sansArrayInfo (String name)
158  {
159    int index = name.indexOf ('[');
160    if (index >= 0)
161    {
162      String array = name.substring (index);
163      name = name.substring (0, index);
164      while (!array.equals (""))
165      {
166        name = name + "[]";
167        array = array.substring (array.indexOf (']') + 1);
168      }
169    }
170    return name;
171  } // sansArrayInfo
172
173  /**
174   * Given a symbol table entry, return the name of
175   * the file which should be created.
176   **/
177  public static String fileName (SymtabEntry entry, String extension )
178  {
179    NameModifier nm = new NameModifierImpl() ;
180    return fileName( entry, nm, extension ) ;
181  } // fileName
182
183  public static String fileName (SymtabEntry entry, NameModifier modifier, String extension )
184  {
185    // This may not be the most appropriate place for
186    // the mkdir calls, but it's common to everything:
187    String pkg = containerFullName (entry.container ());
188    if (pkg != null && !pkg.equals (""))
189      mkdir (pkg);
190
191    String name = entry.name ();
192    name = modifier.makeName( name ) + extension ;
193    if (pkg != null && !pkg.equals (""))
194      name = pkg + '/' + name;
195
196    return name.replace ('/', File.separatorChar);
197  } // fileName
198
199  public static GenFileStream stream (SymtabEntry entry, String extension)
200  {
201    NameModifier nm = new NameModifierImpl() ;
202    return stream(entry, nm, extension);
203  } // stream
204
205  public static GenFileStream stream (SymtabEntry entry, NameModifier modifier, String extension )
206  {
207    return getStream ( fileName (entry,modifier,extension), entry ) ;
208  }
209
210  public static GenFileStream getStream (String name, SymtabEntry entry)
211  {
212    // <f46838.4>
213    String absPathName = ((Arguments)Compile.compiler.arguments).targetDir + name;
214    if (Compile.compiler.arguments.keepOldFiles && new File (absPathName).exists ())
215      return null;
216    else
217      // Write the data to the file stream
218      return new GenFileStream (absPathName);
219  } // getStream
220
221  public static String containerFullName( SymtabEntry container)
222  {
223      String name = doContainerFullName( container ) ;
224      if (packageTranslation.size() > 0)
225          name = translate( name ) ;
226      return name ;
227  }
228
229  public static String translate( String name )
230  {
231      String head = name ;
232      String tail = "" ;
233      int index ;
234      String trname ;
235
236      // Check for package name translations, starting with the
237      // most specific match.
238      do {
239          trname = (String)(packageTranslation.get( head )) ;
240          if (trname != null)
241              return trname + tail ;
242
243          index = head.lastIndexOf( '/' ) ;
244          if (index >= 0) {
245              tail = head.substring( index ) + tail ;
246              head = head.substring( 0, index ) ;
247          }
248      } while (index >= 0) ;
249
250      return name ;
251  }
252
253  private static String doContainerFullName (SymtabEntry container)
254  {
255    String name = "";
256
257    if (container == null)
258      name = "";
259    else
260    {
261      if (container instanceof InterfaceEntry ||
262          container instanceof StructEntry ||
263          container instanceof UnionEntry)
264        name = container.name () + "Package";
265      else
266        name = container.name ();
267
268      if (container.container () != null &&
269        !container.container ().name ().equals (""))
270        name = doContainerFullName (container.container ()) + '/' + name;
271    }
272
273    return name;
274  } // doContainerFullName
275
276  /**
277   * Given a SymtabEntry, return the string which should be used
278   * for this entry. Enums are converted to ints, typedefs and
279   * sequences are converted to their info types. javaQualifiedName
280   * does not do any of these conversions.
281   **/
282  public static String javaName (SymtabEntry entry)
283  {
284    // First get the real name of this type
285    String name = "";
286    if (entry instanceof TypedefEntry || entry instanceof SequenceEntry)
287      try
288      {
289        name = sansArrayInfo ((String)entry.dynamicVariable (Compile.typedefInfo));
290      }
291      catch (NoSuchFieldException e)
292      {
293        name = entry.name ();
294      }
295    else if (entry instanceof PrimitiveEntry)
296      name = javaPrimName (entry.name ());
297    else if (entry instanceof StringEntry)
298      name = "String";
299    else if (entry instanceof NativeEntry)
300      name = javaNativeName (entry.name());
301    else if (entry instanceof ValueEntry && entry.name ().equals ("ValueBase"))
302        name = "java.io.Serializable";
303    else if (entry instanceof ValueBoxEntry)
304    {
305      ValueBoxEntry v = (ValueBoxEntry) entry;
306      TypedefEntry member = ((InterfaceState) v.state ().elementAt (0)).entry;
307      SymtabEntry mType = member.type ();
308      if (mType instanceof PrimitiveEntry)
309      {
310         name = containerFullName (entry.container ());
311         if (!name.equals (""))
312           name = name + '.';
313         name = name + entry.name ();
314      }
315      else
316         name = javaName (mType);
317    }
318    else
319    {
320      name = containerFullName (entry.container ());
321      if (name.equals (""))
322        name = entry.name ();
323      else
324        name = name + '.' + entry.name ();
325    }
326
327    // Make it a fully package-qualified name
328    return name.replace ('/', '.');
329  } // javaName
330
331  public static String javaPrimName (String name)
332  {
333    if (name.equals ("long") || name.equals ("unsigned long"))
334      name = "int";
335    else if (name.equals ("octet"))
336      name = "byte";
337    // "unisigned long long" exceeds Java long.
338    else if (name.equals ("long long") || name.equals ("unsigned long long"))
339      name = "long";
340    else if (name.equals ("wchar"))
341      name = "char";
342    else if (name.equals ("unsigned short"))
343      name = "short";
344    else if (name.equals ("any"))
345      name = "org.omg.CORBA.Any";
346    else if (name.equals ("TypeCode"))
347      name = "org.omg.CORBA.TypeCode";
348    else if (name.equals ("Principal")) // <d61961>
349      name = "org.omg.CORBA.Principal";
350    return name;
351  } // javaPrimName
352
353  public static String javaNativeName (String name)
354  {
355
356    // translations for Native declarations according to CORBA 2.3 spec
357
358    if (name.equals ("AbstractBase") || name.equals ("Cookie"))
359      name = "java.lang.Object";
360    else if (name.equals ("Servant"))
361      name = "org.omg.PortableServer.Servant";
362    else if (name.equals ("ValueFactory"))
363      name = "org.omg.CORBA.portable.ValueFactory";
364    return name;
365  }
366
367
368  /**
369   * Given a symtabEntry, return the name of this entry. This
370   * method does not do any conversions like javaName does.
371   **/
372  public static String javaQualifiedName (SymtabEntry entry)
373  {
374    String name = "";
375    if (entry instanceof PrimitiveEntry)
376      name = javaPrimName (entry.name ());
377    else if (entry instanceof StringEntry)
378      name = "String";
379    else if (entry instanceof ValueEntry && entry.name ().equals ("ValueBase"))
380      name = "java.io.Serializable";
381    else
382    {
383      SymtabEntry container = entry.container ();
384      if (container != null)
385        name = container.name ();
386      if (name.equals (""))
387        name = entry.name ();
388      else
389        name = containerFullName (entry.container ()) + '.' + entry.name ();
390    }
391    return name.replace ('/', '.');
392  } // javaQualifiedName
393
394  // <f46082.03> Publicize for extensions.
395  //static String collapseName (String name)
396
397  /**
398   * Collapse primitive type names.
399   **/
400  public static String collapseName (String name)
401  {
402    if (name.equals ("unsigned short"))
403      name = "ushort";
404    else if (name.equals ("unsigned long"))
405      name = "ulong";
406    else if (name.equals ("unsigned long long"))
407      name = "ulonglong";
408    else if (name.equals ("long long"))
409      name = "longlong";
410    return name;
411  } // collapseName
412
413  /**
414   *
415   **/
416  public static SymtabEntry typeOf (SymtabEntry entry)
417  {
418    while (entry instanceof TypedefEntry && ((TypedefEntry)entry).arrayInfo ().isEmpty () && !(entry.type () instanceof SequenceEntry))
419      entry = entry.type ();
420    return entry;
421  } // typeOf
422
423  /**
424   * Fill the info field with the full name (with array info) of the type.
425   **/
426  static void fillInfo (SymtabEntry infoEntry)
427  {
428    String      arrayInfo   = "";
429    SymtabEntry entry       = infoEntry;
430    boolean     alreadyHave = false;
431
432    do
433    {
434      try
435      {
436        alreadyHave = entry.dynamicVariable (Compile.typedefInfo) != null;
437      }
438      catch (NoSuchFieldException e)
439      {}
440      // If this entry's info has already been processed
441      // don't bother processing it again, just take it.
442      if (!alreadyHave)
443      {
444        if (entry instanceof TypedefEntry)
445          arrayInfo = arrayInfo + arrayInfo (((TypedefEntry)entry).arrayInfo ());
446        else if (entry instanceof SequenceEntry)
447        {
448          Expression maxSize = ((SequenceEntry)entry).maxSize ();
449          if (maxSize == null)
450            arrayInfo = arrayInfo + "[]";
451          else
452            arrayInfo = arrayInfo + '[' + parseExpression (maxSize) + ']';
453        }
454        if (entry.type () == null)
455        {
456          // <d59437> Suppress this message.  It tells the developer nothing, and
457          // this path does not cause the algorithm to fail.  Value boxes may
458          // contain anonymous types, like a struct or enum.
459          //System.err.println (getMessage ("PreEmit.indeterminateTypeInfo", entry.typeName ()));
460        }
461        else
462          entry = entry.type ();
463      }
464    } while (!alreadyHave && entry != null &&
465        (entry instanceof TypedefEntry || entry instanceof SequenceEntry));
466    // <d59437> Value boxes may contain types lacking typename info., which
467    // causes the 2nd case, below, to fail with exception when retrieving the
468    // javaName().
469    if (entry instanceof ValueBoxEntry)
470      fillValueBoxInfo ((ValueBoxEntry)entry);
471    try
472    {
473      if (alreadyHave)
474        infoEntry.dynamicVariable (Compile.typedefInfo, (String)entry.dynamicVariable (Compile.typedefInfo) + arrayInfo);
475      else
476        infoEntry.dynamicVariable (Compile.typedefInfo, javaName (entry) + arrayInfo);
477    }
478    catch (NoSuchFieldException e)
479    {}
480  } // fillInfo
481
482  // <d59437>
483  /**
484   *
485   **/
486  static void fillValueBoxInfo (ValueBoxEntry vb)
487  {
488    SymtabEntry stateMember = (((InterfaceState) vb.state ().elementAt (0)).entry);
489    if (stateMember.type() != null)
490      Util.fillInfo (stateMember.type ());
491    Util.fillInfo (stateMember);
492  } // fillValueBoxInfo
493
494  /**
495   *
496   **/
497  public static String holderName (SymtabEntry entry)
498  {
499    String name;
500    if (entry instanceof PrimitiveEntry)
501      if (entry.name ().equals ("any"))
502        name = "org.omg.CORBA.AnyHolder";
503      else if (entry.name ().equals ("TypeCode"))
504        name = "org.omg.CORBA.TypeCodeHolder";
505      else if (entry.name ().equals ("Principal")) // <d61961>
506        name = "org.omg.CORBA.PrincipalHolder";
507      else
508        name = "org.omg.CORBA." + capitalize (javaQualifiedName (entry)) + "Holder";
509    else if (entry instanceof TypedefEntry)
510    {
511      TypedefEntry td = (TypedefEntry)entry;
512      if (!td.arrayInfo ().isEmpty () || td.type () instanceof SequenceEntry)
513        name = javaQualifiedName (entry) + "Holder";
514      else
515        name = holderName (entry.type ());
516    }
517    else if (entry instanceof StringEntry)
518      name = "org.omg.CORBA.StringHolder";
519    else if (entry instanceof ValueEntry)
520    {
521      if (entry.name ().equals ("ValueBase"))
522          name = "org.omg.CORBA.ValueBaseHolder"; // <d59421>, <d60929>
523      else
524          name = javaName (entry) + "Holder";
525    } else if (entry instanceof NativeEntry) {
526      // do not attach holder to the translation for Native Entries, e.g.
527      // for Cookie it should be CookieHolder instead of java.lang.ObjectHolder
528      // returns the complete name for the package, etc.
529      name = javaQualifiedName(entry) + "Holder";
530    }
531    else
532      name = javaName (entry) + "Holder";
533    return name;
534  } // holderName
535
536  /**
537   * d61056
538   **/
539  public static String helperName (SymtabEntry entry, boolean qualifiedName)
540  {
541    if (entry instanceof ValueEntry)
542      if (entry.name ().equals ("ValueBase"))
543          return "org.omg.CORBA.ValueBaseHelper";
544
545    if (qualifiedName)
546      return javaQualifiedName (entry) + "Helper";
547    else
548      return javaName (entry) + "Helper";
549  } // helperName
550
551  public static final short
552      TypeFile   = 0,
553      StubFile   = 1,
554      HelperFile = 2,
555      HolderFile = 3,
556      StateFile  = 4;
557
558  /**
559   *
560   **/
561  public static void writePackage (PrintWriter stream, SymtabEntry entry)
562  {
563    writePackage (stream, entry, TypeFile);
564  } // writePackage
565
566  /**
567   *
568   **/
569  public static void writePackage (PrintWriter stream, SymtabEntry entry, String name, short type)
570  {
571    if (name != null && !name.equals (""))
572    {
573      stream.println ("package " + name.replace ('/', '.') + ';');
574
575      // This type is in a module.  Just in case it refers to types
576      // in the unnamed module, add an import statement for each of
577      // those types.
578      if (!Compile.compiler.importTypes.isEmpty ())
579      {
580        stream.println ();
581        Vector v = addImportLines (entry, Compile.compiler.importTypes, type);
582        printImports (v, stream);
583      }
584    }
585  } // writePackage
586
587  /**
588   *
589   **/
590  public static void writePackage (PrintWriter stream, SymtabEntry entry, short type)
591  {
592    String fullName = containerFullName (entry.container ());
593    if (fullName != null && !fullName.equals (""))
594    {
595      stream.println ("package " + fullName.replace ('/', '.') + ';');
596       // This type is in a module.  Just in case it refers to types
597      // in the unnamed module, add an import statement for each of
598      // those types.
599      if ((type != HolderFile || entry instanceof TypedefEntry) && !Compile.compiler.importTypes.isEmpty ())
600      {
601        stream.println ();
602        Vector v = addImportLines (entry, Compile.compiler.importTypes, type);
603        printImports (v, stream);
604      }
605      /*
606      Enumeration e = Compile.compiler.importTypes.elements ();
607      while (e.hasMoreElements ())
608      {
609        SymtabEntry i = (SymtabEntry)e.nextElement ();
610        // Write import for type
611        if (!(i instanceof TypedefEntry))
612          stream.println ("import " + i.name () + ';');
613
614        // Write import for Helper
615        if (!(i instanceof ConstEntry))
616          stream.println ("import " + i.name () + "Helper;");
617
618        // Write import for Holder
619        if (!(i instanceof ConstEntry))
620          if (!(i instanceof TypedefEntry) || (i.type () instanceof SequenceEntry || !((TypedefEntry)i).arrayInfo ().isEmpty ()))
621            stream.println ("import " + i.name () + "Holder;");
622      }
623      */
624    }
625  } // writePackage
626
627  /**
628   *
629   **/
630  static private void printImports (Vector importList, PrintWriter stream)
631  {
632    Enumeration e = importList.elements ();
633    while (e.hasMoreElements ())
634      stream.println ("import " + (String)e.nextElement () + ';');
635  } // printImport
636
637  /**
638   *
639   **/
640  static private void addTo (Vector importList, String name)
641  {
642    // REVISIT - <d62023-klr> was also importing ValueBaseHolder and Helper
643    if (name.startsWith ("ValueBase"))  // don't import ValueBase*
644      if ((name.compareTo ("ValueBase") == 0) ||
645          (name.compareTo ("ValueBaseHolder") == 0) ||
646              (name.compareTo ("ValueBaseHelper") == 0))
647        return;
648    if (!importList.contains (name))
649      importList.addElement (name);
650  } // addTo
651
652  /**
653   *
654   **/
655  static private Vector addImportLines (SymtabEntry entry, Vector importTypes, short type)
656  {
657    Vector importList = new Vector ();
658    if (entry instanceof ConstEntry)
659    {
660      ConstEntry c      = (ConstEntry)entry;
661      Object     cvalue = c.value ().value ();
662      if (cvalue instanceof ConstEntry && importTypes.contains (cvalue))
663        addTo (importList, ((ConstEntry)cvalue).name ());
664    }
665    else if (entry instanceof ValueEntry && type == HelperFile) // <d59512>
666    {
667      // This code inspired by ValueGen.getConcreteBaseTypeCode().  Helper method
668      // type() could be invoked against a global valuetype.
669      if (((ValueEntry)entry).derivedFrom ().size () > 0) // <59596> KLR HACK
670      {
671        ValueEntry base = (ValueEntry)((ValueEntry)entry).derivedFrom ().elementAt (0);
672        String baseName = base.name ();
673        if (!"ValueBase".equals (baseName))
674          if (importTypes.contains (base))
675            addTo (importList, baseName + "Helper");
676      }
677    }
678    else if (entry instanceof InterfaceEntry && (type == TypeFile || type == StubFile))
679    {
680      InterfaceEntry i = (InterfaceEntry)entry;
681
682      if (i instanceof ValueEntry) // <d59512>
683      {
684        // Examine interface parents in supports vector.
685        Enumeration e = ((ValueEntry)i).supports ().elements ();
686        while (e.hasMoreElements ())
687        {
688          SymtabEntry parent = (SymtabEntry)e.nextElement ();
689          if (importTypes.contains (parent))
690          {
691            addTo (importList, parent.name () + "Operations");
692          }
693          // If this is a stub, then recurse to the parents
694          if (type == StubFile)
695          {
696            if (importTypes.contains (parent))
697              addTo (importList, parent.name ());
698            Vector subImportList = addImportLines (parent, importTypes, StubFile);
699            Enumeration en = subImportList.elements ();
700            while (en.hasMoreElements ())
701            {
702              addTo (importList, (String)en.nextElement ());
703            }
704          }
705        }
706      }
707      // Interface or valuetype -- Examine interface and valuetype parents,
708      // Look through derivedFrom vector
709      Enumeration e = i.derivedFrom ().elements ();
710      while (e.hasMoreElements ())
711      {
712        SymtabEntry parent = (SymtabEntry)e.nextElement ();
713        if (importTypes.contains (parent))
714        {
715          addTo (importList, parent.name ());
716          // <d59512> Always add both imports, even though superfluous.  Cannot
717          // tell when writing Operations or Signature interface!
718          if (!(parent instanceof ValueEntry)) // && parent.name ().equals ("ValueBase")))
719            addTo (importList, parent.name () + "Operations");
720        }
721        // If this is a stub, then recurse to the parents
722        if (type == StubFile)
723        {
724          Vector subImportList = addImportLines (parent, importTypes, StubFile);
725          Enumeration en = subImportList.elements ();
726          while (en.hasMoreElements ())
727          {
728            addTo (importList, (String)en.nextElement ());
729          }
730        }
731      }
732      // Look through methods vector
733      e = i.methods ().elements ();
734      while (e.hasMoreElements ())
735      {
736        MethodEntry m = (MethodEntry)e.nextElement ();
737
738        // Look at method type
739        SymtabEntry mtype = typeOf (m.type ());
740        if (mtype != null && importTypes.contains (mtype))
741          if (type == TypeFile || type == StubFile)
742          {
743            addTo (importList, mtype.name ());
744            addTo (importList, mtype.name () + "Holder");
745            if (type == StubFile)
746              addTo (importList, mtype.name () + "Helper");
747          }
748        checkForArrays (mtype, importTypes, importList);
749        // <d42256> Print import lines for globals constants and constants
750        // within global interfaces.
751        if (type == StubFile)
752          checkForBounds (mtype, importTypes, importList);
753
754        // Look through exceptions
755        Enumeration exEnum = m.exceptions ().elements ();
756        while (exEnum.hasMoreElements ())
757        {
758          ExceptionEntry ex = (ExceptionEntry)exEnum.nextElement ();
759          if (importTypes.contains (ex))
760          {
761            addTo (importList, ex.name ());
762            addTo (importList, ex.name () + "Helper"); // <d59063>
763          }
764        }
765
766        // Look through parameters
767        Enumeration parms = m.parameters ().elements ();
768        while (parms.hasMoreElements ())
769        {
770          ParameterEntry parm = (ParameterEntry)parms.nextElement ();
771          SymtabEntry parmType = typeOf (parm.type ());
772          if (importTypes.contains (parmType))
773          {
774            // <d59771> Helper needed in stubs.
775            if (type == StubFile)
776              addTo (importList, parmType.name () + "Helper");
777            if (parm.passType () == ParameterEntry.In)
778              addTo (importList, parmType.name ());
779            else
780              addTo (importList, parmType.name () + "Holder");
781          }
782          checkForArrays (parmType, importTypes, importList);
783          // <d42256>
784          if (type == StubFile)
785            checkForBounds (parmType, importTypes, importList);
786        }
787      }
788    }
789    else if (entry instanceof StructEntry)
790    {
791      StructEntry s = (StructEntry)entry;
792
793      // Look through the members
794      Enumeration members = s.members ().elements ();
795      while (members.hasMoreElements ())
796      {
797        SymtabEntry member = (TypedefEntry)members.nextElement ();
798        // <d48034> Need to add helper name for typedef members.  This name
799        // is referenced at typecode generation in Helper class.
800        SymtabEntry memberType = member.type ();
801        member = typeOf (member);
802        if (importTypes.contains (member))
803        {
804          // If this IS a typedef, then there are only Helper/Holder classes.
805          //if (!(member instanceof TypedefEntry))
806          // <d59437>  Valueboxes
807          if (!(member instanceof TypedefEntry) && !(member instanceof ValueBoxEntry))
808            addTo (importList, member.name ());
809          // <d48034> Add helper name of alias, too, if member is a typedef.
810          //if (type == HelperFile)
811          //  addTo (importList, member.name () + "Helper");
812          if (type == HelperFile)
813          {
814            addTo (importList, member.name () + "Helper");
815            if (memberType instanceof TypedefEntry)
816              addTo (importList, memberType.name () + "Helper");
817          }
818        }
819        checkForArrays (member, importTypes, importList);
820        checkForBounds (member, importTypes, importList);
821      }
822    }
823    else if (entry instanceof TypedefEntry)
824    {
825      TypedefEntry t = (TypedefEntry)entry;
826      String arrays = checkForArrayBase (t, importTypes, importList);
827      if (type == HelperFile)
828      {
829        checkForArrayDimensions (arrays, importTypes, importList);
830        try
831        {
832          String name = (String)t.dynamicVariable (Compile.typedefInfo);
833          int index = name.indexOf ('[');
834          if (index >= 0)
835            name = name.substring (0, index);
836          // See if the base type should be added to the list.
837          SymtabEntry typeEntry = (SymtabEntry)symbolTable.get (name);
838          if (typeEntry != null && importTypes.contains (typeEntry))
839            addTo (importList, typeEntry.name () + "Helper");
840        }
841        catch (NoSuchFieldException e)
842        {}
843
844        // <d42256> Typedefs for global bounded strings need import
845        // statement when bound expression contains non-literal constants.
846        checkForBounds (typeOf (t), importTypes, importList);
847      }
848      Vector subImportList = addImportLines (t.type (), importTypes, type);
849      Enumeration e = subImportList.elements ();
850      while (e.hasMoreElements ())
851        addTo (importList, (String)e.nextElement ());
852    }
853    else if (entry instanceof UnionEntry)
854    {
855      UnionEntry u = (UnionEntry)entry;
856
857      // Look at the discriminant type
858      SymtabEntry utype = typeOf (u.type ());
859      if (utype instanceof EnumEntry && importTypes.contains (utype))
860        addTo (importList, utype.name ());
861
862      // Look through the branches
863      Enumeration branches = u.branches ().elements ();
864      while (branches.hasMoreElements ())
865      {
866        UnionBranch branch = (UnionBranch)branches.nextElement ();
867        SymtabEntry branchEntry = typeOf (branch.typedef);
868        if (importTypes.contains (branchEntry))
869        {
870          addTo (importList, branchEntry.name ());
871          if (type == HelperFile)
872            addTo (importList, branchEntry.name () + "Helper");
873        }
874        checkForArrays (branchEntry, importTypes, importList);
875        // <d42256>
876        checkForBounds (branchEntry, importTypes, importList);
877      }
878    }
879
880    // If a typedef is not a sequence or an array, only holders and
881    // helpers are generated for it.  Remove references to such
882    // class names.
883    Enumeration en = importList.elements ();
884    while (en.hasMoreElements ())
885    {
886      String name = (String)en.nextElement ();
887      SymtabEntry e = (SymtabEntry)symbolTable.get (name);
888      if (e != null && e instanceof TypedefEntry)
889      {
890        TypedefEntry t = (TypedefEntry)e;
891        if (t.arrayInfo ().size () == 0 || !(t.type () instanceof SequenceEntry))
892          importList.removeElement (name);
893      }
894    }
895    return importList;
896  } // addImportLines
897
898  /**
899   *
900   **/
901  static private void checkForArrays (SymtabEntry entry, Vector importTypes, Vector importList)
902  {
903    if (entry instanceof TypedefEntry)
904    {
905      TypedefEntry t = (TypedefEntry)entry;
906      String arrays = checkForArrayBase (t, importTypes, importList);
907      checkForArrayDimensions (arrays, importTypes, importList);
908    }
909  } // checkForArrays
910
911  /**
912   *
913   **/
914  static private String checkForArrayBase (TypedefEntry t, Vector importTypes, Vector importList)
915  {
916    String arrays = "";
917    try
918    {
919      String name = (String)t.dynamicVariable (Compile.typedefInfo);
920      int index = name.indexOf ('[');
921      if (index >= 0)
922      {
923        arrays = name.substring (index);
924        name = name.substring (0, index);
925      }
926
927      // See if the base type should be added to the list.
928      SymtabEntry typeEntry = (SymtabEntry)symbolTable.get (name);
929      if (typeEntry != null && importTypes.contains (typeEntry))
930        addTo (importList, typeEntry.name ());
931    }
932    catch (NoSuchFieldException e)
933    {}
934    return arrays;
935  } // checkForArrayBase
936
937  /**
938   *
939   **/
940  static private void checkForArrayDimensions (String arrays, Vector importTypes, Vector importList)
941  {
942    // See if any of the arrays contain a constentry.
943    // If so, see if it should be added to the list.
944    while (!arrays.equals (""))
945    {
946      int index = arrays.indexOf (']');
947      String dim = arrays.substring (1, index);
948      arrays = arrays.substring (index + 1);
949      SymtabEntry constant = (SymtabEntry)symbolTable.get (dim);
950      if (constant == null)
951      {
952        // A constant expr could be of the form <const> OR
953        // <interface>.<const>.  This if branch checks for that case.
954        int i = dim.lastIndexOf ('.');
955        if (i >= 0)
956          constant = (SymtabEntry)symbolTable.get (dim.substring (0, i));
957      }
958      if (constant != null && importTypes.contains (constant))
959        addTo (importList, constant.name ());
960    }
961  } // checkForArrayDimensions
962
963  // <d42256> Call the following method when its necessary to determine the
964  // the import types for IDL constructs containing arbitrary positive int.
965  // expressions, which may specify non-literal constants.
966
967  /**
968   * Determine the import lines for template types.
969   **/
970  static private void checkForBounds (SymtabEntry entry, Vector importTypes, Vector importList)
971  {
972    // Obtain actual type, just to be complete.
973    SymtabEntry entryType = entry;
974    while (entryType instanceof TypedefEntry)
975      entryType = entryType.type ();
976
977    if (entryType instanceof StringEntry && ((StringEntry)entryType).maxSize () != null)
978      checkForGlobalConstants (((StringEntry)entryType).maxSize ().rep (), importTypes, importList);
979    else
980      if (entryType instanceof SequenceEntry && ((SequenceEntry)entryType).maxSize () != null)
981        checkForGlobalConstants (((SequenceEntry)entryType).maxSize ().rep (), importTypes, importList);
982  } // checkForBounds
983
984  /**
985   * Extract the global constants from the supplied integer expression
986   * representation (string) and add them to the supplied import list.
987   **/
988  static private void checkForGlobalConstants (String exprRep, Vector importTypes, Vector importList)
989  {
990    // NOTE: Do not use '/' as a delimiter. Symbol table names use '/' as a
991    // delimiter and would not be otherwise properly collected. Blanks and
992    // arithmetic symbols do not appear in tokens, except for '/'.
993    java.util.StringTokenizer st = new java.util.StringTokenizer (exprRep, " +-*()~&|^%<>");
994    while (st.hasMoreTokens ())
995    {
996      String token = st.nextToken ();
997      // When token contains '/', it represents the division symbol or
998      // a nested type (e.g., I/x). Ignore the division symbol, and don't
999      // forget constants declared within global interfaces!
1000      if (!token.equals ("/"))
1001      {
1002        SymtabEntry typeEntry = (SymtabEntry)symbolTable.get (token);
1003        if (typeEntry instanceof ConstEntry)
1004        {
1005          int slashIdx = token.indexOf ('/');
1006          if (slashIdx < 0)  // Possible global constant
1007          {
1008            if (importTypes.contains (typeEntry))
1009              addTo (importList, typeEntry.name ());
1010          }
1011          else  // Possible constant in global interface
1012          {
1013            SymtabEntry constContainer = (SymtabEntry)symbolTable.get (token.substring (0, slashIdx));
1014            if (constContainer instanceof InterfaceEntry && importTypes.contains (constContainer))
1015              addTo (importList, constContainer.name ());
1016          }
1017        }
1018      }
1019    }
1020  } // checkForGlobalConstants
1021
1022  /**
1023   *
1024   **/
1025  public static void writeInitializer (String indent, String name, String arrayDcl, SymtabEntry entry, PrintWriter stream)
1026  {
1027    if (entry instanceof TypedefEntry)
1028    {
1029      TypedefEntry td = (TypedefEntry)entry;
1030      writeInitializer (indent, name, arrayDcl + sansArrayInfo (td.arrayInfo ()), td.type (), stream);
1031    }
1032    else if (entry instanceof SequenceEntry)
1033      writeInitializer (indent, name, arrayDcl + "[]", entry.type (), stream);
1034    else if (entry instanceof EnumEntry)
1035      if (arrayDcl.length () > 0)
1036        stream.println (indent + javaName (entry) + ' ' + name + arrayDcl + " = null;");
1037      else
1038        stream.println (indent + javaName (entry) + ' ' + name + " = null;");
1039    else if (entry instanceof PrimitiveEntry)
1040    {
1041      boolean array = arrayDcl.length () > 0;
1042      String tname = javaPrimName (entry.name ());
1043      if (tname.equals ("boolean"))
1044        stream.println (indent + "boolean " + name + arrayDcl + " = " + (array ? "null;" : "false;"));
1045      else if (tname.equals ("org.omg.CORBA.TypeCode"))
1046        stream.println (indent + "org.omg.CORBA.TypeCode " + name + arrayDcl + " = null;");
1047      else if (tname.equals ("org.omg.CORBA.Any"))
1048        stream.println (indent + "org.omg.CORBA.Any " + name + arrayDcl + " = null;");
1049      else if (tname.equals ("org.omg.CORBA.Principal")) // <d61961>
1050        stream.println (indent + "org.omg.CORBA.Principal " + name + arrayDcl + " = null;");
1051      else
1052        stream.println (indent + tname + ' ' + name + arrayDcl + " = " + (array ? "null;" : '(' + tname + ")0;"));
1053    }
1054    // <f46082.51> Remove -stateful feature. This case is identical to next one
1055    // because javaName() supplants javaStatefulName().
1056    //else if (entry instanceof InterfaceEntry && ((InterfaceEntry)entry).state () != null)
1057    //  stream.println (indent + javaStatefulName ((InterfaceEntry)entry) + ' ' + name + arrayDcl + " = null;");
1058    else
1059      stream.println (indent + javaName (entry) + ' ' + name + arrayDcl + " = null;");
1060  } // writeInitializer
1061
1062  /**
1063   *
1064   **/
1065  public static void writeInitializer (String indent, String name, String arrayDcl, SymtabEntry entry, String initializer, PrintWriter stream)
1066  {
1067    if (entry instanceof TypedefEntry)
1068    {
1069      TypedefEntry td = (TypedefEntry)entry;
1070      writeInitializer (indent, name, arrayDcl + sansArrayInfo (td.arrayInfo ()), td.type (), initializer, stream);
1071    }
1072    else if (entry instanceof SequenceEntry)
1073      writeInitializer (indent, name, arrayDcl + "[]", entry.type (), initializer, stream);
1074    else if (entry instanceof EnumEntry)
1075      if (arrayDcl.length () > 0)
1076        stream.println (indent + javaName (entry) + ' ' + name + arrayDcl + " = " + initializer + ';');
1077      else
1078        stream.println (indent + javaName (entry) + ' ' + name + " = " + initializer + ';');
1079    else if (entry instanceof PrimitiveEntry)
1080    {
1081      boolean array = arrayDcl.length () > 0;
1082      String tname = javaPrimName (entry.name ());
1083      if (tname.equals ("boolean"))
1084        stream.println (indent + "boolean " + name + arrayDcl + " = " + initializer + ';');
1085      else if (tname.equals ("org.omg.CORBA.TypeCode"))
1086        stream.println (indent + "org.omg.CORBA.TypeCode " + name + arrayDcl + " = " + initializer + ';');
1087      else if (tname.equals ("org.omg.CORBA.Any"))
1088        stream.println (indent + "org.omg.CORBA.Any " + name + arrayDcl + " = " + initializer + ';');
1089      else if (tname.equals ("org.omg.CORBA.Principal")) // <d61961>
1090        stream.println (indent + "org.omg.CORBA.Principal " + name + arrayDcl + " = " + initializer + ';');
1091      else
1092        stream.println (indent + tname + ' ' + name + arrayDcl + " = " + initializer + ';');
1093    }
1094    // <f46082.51> Remove -stateful feature. This case is identical to next one
1095    // because javaName() supplants javaStatefulName().
1096    //else if (entry instanceof InterfaceEntry && ((InterfaceEntry)entry).state () != null)
1097    //  stream.println (indent + javaStatefulName ((InterfaceEntry)entry) + ' ' + name + arrayDcl + " = " + initializer + ';');
1098    else
1099      stream.println (indent + javaName (entry) + ' ' + name + arrayDcl + " = " + initializer + ';');
1100  } // writeInitializer
1101
1102  /**
1103   *
1104   **/
1105  public static void mkdir (String name)
1106  {
1107    String targetDir = ((Arguments)Compile.compiler.arguments).targetDir; // F46838.4
1108    name = (targetDir + name).replace ('/', File.separatorChar); // F46838.4
1109    File pkg = new File (name);
1110    if (!pkg.exists ())
1111      if (!pkg.mkdirs ())
1112        System.err.println (getMessage ("Util.cantCreatePkg", name));
1113  } // mkdir
1114
1115  /**
1116   *
1117   **/
1118  public static void writeProlog (PrintWriter stream, String filename)
1119  {
1120    // <d59355> Remove target directory
1121    String targetDir = ((Arguments)Compile.compiler.arguments).targetDir;
1122    if (targetDir != null)
1123      filename = filename.substring (targetDir.length ());
1124    stream.println ();
1125    stream.println ("/**");
1126    stream.println ("* " + filename.replace (File.separatorChar, '/') +
1127        " .");
1128    stream.println ("* " + Util.getMessage ("toJavaProlog1",
1129        Util.getMessage ("Version.product", Util.getMessage ("Version.number"))));
1130    // <d48911> Do not introduce invalid escape characters into comment! <daz>
1131    //stream.println ("* " + Util.getMessage ("toJavaProlog2", Compile.compiler.arguments.file));
1132    stream.println ("* " + Util.getMessage ("toJavaProlog2", Compile.compiler.arguments.file.replace (File.separatorChar, '/')));
1133
1134    ///////////////
1135    // This SHOULD work, but there's a bug in the JDK.
1136    //    stream.println ("* " + DateFormat.getDateTimeInstance (DateFormat.FULL, DateFormat.FULL, Locale.getDefault ()).format (new Date ()));
1137    // This gets around the bug:
1138
1139    DateFormat formatter = DateFormat.getDateTimeInstance (DateFormat.FULL, DateFormat.FULL, Locale.getDefault ());
1140
1141    // Japanese-specific workaround.  JDK bug 4069784 being repaired by JavaSoft.
1142    // Keep this transient solution until bug fix is reported.cd .
1143
1144    if (Locale.getDefault () == Locale.JAPAN)
1145      formatter.setTimeZone (java.util.TimeZone.getTimeZone ("JST"));
1146    else
1147      formatter.setTimeZone (java.util.TimeZone.getDefault ());
1148
1149    stream.println ("* " + formatter.format (new Date ()));
1150
1151    // <daz>
1152    ///////////////
1153
1154    stream.println ("*/");
1155    stream.println ();
1156  } // writeProlog
1157
1158  // keywords ending in Holder or Helper or Package have '_' prepended.
1159  // These prepended underscores must not be part of anything sent
1160  // across the wire, so these two methods are provided to strip them
1161  // off.
1162
1163  /**
1164   *
1165   **/
1166  public static String stripLeadingUnderscores (String string)
1167  {
1168    while (string.startsWith ("_"))
1169      string = string.substring (1);
1170    return string;
1171  } // stripLeadingUnderscores
1172
1173  /**
1174   *
1175   **/
1176  public static String stripLeadingUnderscoresFromID (String string)
1177  {
1178    String stringPrefix = "";
1179    int slashIndex = string.indexOf (':');
1180    if (slashIndex >= 0)
1181      do
1182      {
1183        stringPrefix = stringPrefix + string.substring (0, slashIndex + 1);
1184        string = string.substring (slashIndex + 1);
1185        while (string.startsWith ("_"))
1186          string = string.substring (1);
1187        slashIndex = string.indexOf ('/');
1188      } while (slashIndex >= 0);
1189    return stringPrefix + string;
1190  } // stripLeadingUnderscoresFromID
1191
1192  /**
1193   *
1194   **/
1195  public static String parseExpression (Expression e)
1196  {
1197    if (e instanceof Terminal)
1198      return parseTerminal ((Terminal)e);
1199    else if (e instanceof BinaryExpr)
1200      return parseBinary ((BinaryExpr)e);
1201    else if (e instanceof UnaryExpr)
1202      return parseUnary ((UnaryExpr)e);
1203    else
1204      return "(UNKNOWN_VALUE)"; // This shouldn't happen unless someone slips
1205                                // in another type of expression.
1206  } // parseExpression
1207
1208  /**
1209   *
1210   **/
1211  static String parseTerminal (Terminal e)
1212  {
1213    if (e.value () instanceof ConstEntry)
1214    {
1215      ConstEntry c = (ConstEntry)e.value ();
1216      if (c.container () instanceof InterfaceEntry)
1217        return javaQualifiedName (c.container ()) + '.' + c.name ();
1218      else
1219        return javaQualifiedName (c) + ".value";
1220    }
1221    else if (e.value () instanceof Expression)
1222      return '(' + parseExpression ((Expression)e.value ()) + ')';
1223    else if (e.value () instanceof Character)
1224    {
1225      if (((Character)e.value ()).charValue () == '\013')
1226        // e.rep is \v.  \v for vertical tab is meaningless in Java.
1227        return "'\\013'";
1228      else if (((Character)e.value ()).charValue () == '\007')
1229        // e.rep is \a.  \a for alert is meaningless in Java.
1230        return "'\\007'";
1231      else if (e.rep ().startsWith ("'\\x"))
1232        return hexToOctal (e.rep ());
1233      else if (e.rep ().equals ("'\\?'"))
1234        return "'?'";
1235      else
1236        return e.rep ();
1237    }
1238    else if (e.value () instanceof Boolean)
1239      return e.value ().toString ();
1240
1241    // <d54640> If value is type "unsigned long long" (ull) and its magnitude
1242    // is greater than the maximal Java long (i.e., IDL long long) value, then
1243    // return its signed representation rather than its actual representation.
1244    /*
1245    // Support long long
1246    //else if (e.value () instanceof Long)
1247    else if (e.value () instanceof BigInteger &&
1248             (e.type ().indexOf ("long long") >= 0 || e.type ().equals ("unsigned long"))) // <klr>
1249    {
1250      String rep   = e.rep ();
1251      int    index = rep.indexOf (')');
1252      if (index < 0)
1253        return rep + 'L';
1254      else
1255        return rep.substring (0, index) + 'L' + rep.substring (index);
1256    }
1257    */
1258    else if (e.value () instanceof BigInteger)
1259    {
1260      // Get the correct primitive type. Since integer types (octet, short,
1261      // long, long long, unsigned short, unsigned long, unsigned long long)
1262      // could be aliased (typedef'ed) to any arbitrary levels, the code
1263      // below walks up the alias chain to get to the primitive type.
1264
1265      // Get the symbol table entry corresponding to the 'type'.
1266      SymtabEntry typeEntry = (SymtabEntry) symbolTable.get(e.type());
1267
1268      // Get to the primitive type.
1269      while (typeEntry.type() != null) {
1270          typeEntry = typeEntry.type();
1271      }
1272      String type = typeEntry.name();
1273
1274      if (type.equals("unsigned long long") &&
1275          ((BigInteger)e.value ()).compareTo (Expression.llMax) > 0) // value > long long Max?
1276      {
1277        // Convert to signed value, which will always be negative.
1278        BigInteger v = (BigInteger)e.value ();
1279        v = v.subtract (Expression.twoPow64);
1280        int index = e.rep ().indexOf (')');
1281        if (index < 0)
1282          return v.toString () + 'L';
1283        else
1284          return '(' + v.toString () + 'L' + ')';
1285      }
1286      else if ( type.indexOf("long long") >= 0 || type.equals("unsigned long") )
1287      {
1288        String rep   = e.rep ();
1289        int    index = rep.indexOf (')');
1290        if (index < 0)
1291          return rep + 'L';
1292        else
1293          return rep.substring (0, index) + 'L' + rep.substring (index);
1294      }
1295      else
1296        return e.rep ();
1297    } // end <d54640>
1298    else
1299      return e.rep ();
1300  } // parseTerminal
1301
1302  /**
1303   *
1304   **/
1305  static String hexToOctal (String hex)
1306  {
1307    // The format of hex is '/xXX' where XX is one or two hex digits.
1308    // This statement pulls off XX.
1309    hex = hex.substring (3, hex.length () - 1);
1310    return "'\\" + Integer.toString (Integer.parseInt (hex, 16), 8) + "'";
1311  } // hexToOctal
1312
1313  /**
1314   *
1315   **/
1316  static String parseBinary (BinaryExpr e)
1317  {
1318    String castString = "";
1319    if (e.value () instanceof Float || e.value () instanceof Double)
1320    {
1321      castString = "(double)";
1322      if (!(e instanceof Plus || e instanceof Minus ||
1323            e instanceof Times || e instanceof Divide))
1324        System.err.println ("Operator " + e.op () + " is invalid on floating point numbers");
1325    }
1326    else if (e.value () instanceof Number)
1327    {
1328      if (e.type (). indexOf ("long long") >= 0)
1329        castString = "(long)";
1330      else
1331        castString = "(int)";
1332    }
1333    else
1334    {
1335      castString = "";
1336      System.err.println ("Unknown type in constant expression");
1337    }
1338
1339    // <d54640> Must emit value rather than representation when type "unsigned
1340    // long long" (ull) because emitted binary arithmetic expressions containing
1341    // ull's converted to long (i.e., IDL long long) do not always compute to
1342    // the correct result.
1343
1344    //return castString + '(' + parseExpression (e.left ()) + ' ' + e.op () + ' ' + parseExpression (e.right ()) + ')';
1345    if (e.type ().equals ("unsigned long long"))
1346    {
1347      BigInteger value = (BigInteger)e.value ();
1348      if (value.compareTo (Expression.llMax) > 0) // value > long long max?
1349        value = value.subtract (Expression.twoPow64); // Convert to Java long (signed)
1350      return castString + '(' + value.toString () + 'L' + ')';
1351    }
1352    else
1353      return castString + '(' + parseExpression (e.left ()) + ' ' + e.op () + ' ' + parseExpression (e.right ()) + ')';
1354    // <d54640> end
1355  } // parseBinary
1356
1357  /**
1358   *
1359   **/
1360  static String parseUnary (UnaryExpr e)
1361  {
1362    if (!(e.value () instanceof Number))
1363      return "(UNKNOWN_VALUE)"; // This shouldn't happen if the parser checked the expression types correctly.
1364    else if ((e.value () instanceof Float || e.value () instanceof Double) && e instanceof Not)
1365      return "(UNKNOWN_VALUE)"; // This shouldn't happen if the parser checked the expression types correctly.
1366    else
1367    {
1368      String castString = "";
1369      if (e.operand ().value () instanceof Float ||
1370          e.operand ().value () instanceof Double)
1371        castString = "(double)";
1372      // Support long long.
1373      //else
1374      //  castString = "(long)";
1375      else if (e.type (). indexOf ("long long") >= 0)
1376        castString = "(long)";
1377      else
1378        castString = "(int)";
1379
1380      // <d54640> Must emit value rather than representation when type is
1381      // "unsigned long long" (ull) because emitted unary arithmetic expressions
1382      // containing a ull converted to long (i.e., IDL long long) do not always
1383      // compute to the correct result.
1384
1385      //return castString + e.op () + parseExpression (e.operand ());
1386      if (e.type ().equals ("unsigned long long"))
1387      {
1388        BigInteger value = (BigInteger)e.value ();
1389        if (value.compareTo (Expression.llMax) > 0) // value > long long max?
1390          value = value.subtract (Expression.twoPow64); // Convert to Java long (signed)
1391        return castString + '(' + value.toString () + 'L' + ')';
1392      }
1393      else
1394        return castString + e.op () + parseExpression (e.operand ());
1395      // end <d54640>
1396    }
1397  } // parseUnary
1398
1399  /**
1400   *
1401   **/
1402  public static boolean IDLEntity (SymtabEntry entry)
1403  {
1404    boolean rc = true;
1405    if (entry instanceof PrimitiveEntry || entry instanceof StringEntry)
1406       rc = false;
1407    else if (entry instanceof TypedefEntry)
1408       rc = IDLEntity (entry.type ());
1409    return rc;
1410  } // IDLEntity
1411
1412  // <d62023>
1413  /**
1414   * @return true if the current setting of corbaLevel is within delta of
1415   *    the range {@code min <= corbaLevel <= max}
1416   **/
1417  public static boolean corbaLevel (float min, float max)
1418  {
1419    float level = Compile.compiler.arguments.corbaLevel;
1420    float delta = 0.001f;
1421    if ((level - min + delta >= 0.0f) && (max - level + delta >= 0.0f))
1422        return true;
1423    else
1424        return false;
1425  } // corbaLevel
1426
1427  static Hashtable symbolTable = new Hashtable ();
1428  static Hashtable packageTranslation = new Hashtable() ;
1429} // class Util
1430