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 
  36 package 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 
  68 import java.io.File;
  69 import java.io.PrintWriter;
  70 import java.math.BigInteger;
  71 import java.text.DateFormat;
  72 import java.util.Date;
  73 import java.util.Enumeration;
  74 import java.util.Hashtable;
  75 import java.util.Locale;
  76 import java.util.Vector;
  77 
  78 import com.sun.tools.corba.se.idl.ConstEntry;
  79 import com.sun.tools.corba.se.idl.EnumEntry;
  80 import com.sun.tools.corba.se.idl.ExceptionEntry;
  81 import com.sun.tools.corba.se.idl.GenFileStream;
  82 import com.sun.tools.corba.se.idl.InterfaceEntry;
  83 import com.sun.tools.corba.se.idl.MethodEntry;
  84 import com.sun.tools.corba.se.idl.NativeEntry;
  85 import com.sun.tools.corba.se.idl.ParameterEntry;
  86 import com.sun.tools.corba.se.idl.PrimitiveEntry;
  87 import com.sun.tools.corba.se.idl.SequenceEntry;
  88 import com.sun.tools.corba.se.idl.StringEntry;
  89 import com.sun.tools.corba.se.idl.StructEntry;
  90 import com.sun.tools.corba.se.idl.SymtabEntry;
  91 import com.sun.tools.corba.se.idl.TypedefEntry;
  92 import com.sun.tools.corba.se.idl.UnionBranch;
  93 import com.sun.tools.corba.se.idl.UnionEntry;
  94 import com.sun.tools.corba.se.idl.ValueEntry;
  95 import com.sun.tools.corba.se.idl.ValueBoxEntry;
  96 import com.sun.tools.corba.se.idl.InterfaceState;
  97 
  98 import 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  **/
 104 public 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