/* * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * COMPONENT_NAME: idl.toJava * * ORIGINS: 27 * * Licensed Materials - Property of IBM * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999 * RMI-IIOP v1.0 * */ package com.sun.tools.corba.se.idl.toJavaPortable; // Notes: // -F46838.4 Ported -td option from toJava. // -10/17/98 KLR Ported fix for d48911 from toJava // -10/18/98 KLR Ported fix from toJava for "unsigned long" constants // -F46082.51 Removed code to collect makefile list generation inforamtion // from getStream(); see f46830. // -F46082.51 Removed -stateful feature: methods javaStatefulName(String) // and javaStatefulName(SymtabEntry) are obsolete, supplanted by javaName(). // -D54640 Represent unsigned long long expressions with their computed // value rather than their actual representation (see notes in method // parseTerminal(), parseBinary(), and parseUnary().) // -D58319 Add getVersion() method. // -D48034 Import Helper classes for typedef struct members when generating // helper. See method addImportLines(). // -D59851 Modify to enable QuickTest build. (pending) // -D42256 Determine import lines for template types, which may specify any // positive int., constant expression for a boundary. Such expression containing // non-literal contansts previously caused problems when appearing in constructs // structs, unions, exceptions, typedefs, operation types and parameters, // attributes; and of course, sequences, strings. // -D59063 Add helper for global exception to stub import list. // -D58951 Publicise members for QuickTest. // -D59421 Change ValueBaseHolder to SerializableHolder // -D59596 Prevent accesses to elements of empty Vectors. // -D59771 Add import stmt for Helper of global type in stubs. // -D59355 Remove target dir. from filename when writing to prolog. // -D59437 Fill typename information for value boxes. // -D62023 Don't import ValueBase* // -D62023 Add corbaLevel import java.io.File; import java.io.PrintWriter; import java.math.BigInteger; import java.text.DateFormat; import java.util.Date; import java.util.Enumeration; import java.util.Hashtable; import java.util.Locale; import java.util.Vector; import com.sun.tools.corba.se.idl.ConstEntry; import com.sun.tools.corba.se.idl.EnumEntry; import com.sun.tools.corba.se.idl.ExceptionEntry; import com.sun.tools.corba.se.idl.GenFileStream; import com.sun.tools.corba.se.idl.InterfaceEntry; import com.sun.tools.corba.se.idl.MethodEntry; import com.sun.tools.corba.se.idl.NativeEntry; import com.sun.tools.corba.se.idl.ParameterEntry; import com.sun.tools.corba.se.idl.PrimitiveEntry; import com.sun.tools.corba.se.idl.SequenceEntry; import com.sun.tools.corba.se.idl.StringEntry; import com.sun.tools.corba.se.idl.StructEntry; import com.sun.tools.corba.se.idl.SymtabEntry; import com.sun.tools.corba.se.idl.TypedefEntry; import com.sun.tools.corba.se.idl.UnionBranch; import com.sun.tools.corba.se.idl.UnionEntry; import com.sun.tools.corba.se.idl.ValueEntry; import com.sun.tools.corba.se.idl.ValueBoxEntry; import com.sun.tools.corba.se.idl.InterfaceState; import com.sun.tools.corba.se.idl.constExpr.*; /** * Class Util is a repository of static members available for general * use by the IDL parser framework and any generator extensions. **/ public class Util extends com.sun.tools.corba.se.idl.Util { // /** * Fetch the version number of this build of the IDL-to-Java (portable) * compiler from the appropriate properties file. * @return the version number of this compiler build. **/ public static String getVersion () { return com.sun.tools.corba.se.idl.Util.getVersion ("com/sun/tools/corba/se/idl/toJavaPortable/toJavaPortable.prp"); } // getVersion /** * This method is called by Setup.preEmit, so * symbolTable is available for all Util methods. **/ static void setSymbolTable (Hashtable symtab) { symbolTable = symtab; } // setSymbolTable public static void setPackageTranslation( Hashtable pkgtrans ) { packageTranslation = pkgtrans ; } public static boolean isInterface (String name) { return isInterface (name, symbolTable); } // isInterface static String arrayInfo (Vector arrayInfo) { int arrays = arrayInfo.size (); String info = ""; Enumeration e = arrayInfo.elements (); while (e.hasMoreElements ()) info = info + '[' + parseExpression ((Expression)e.nextElement ()) + ']'; return info; } // arrayInfo // static String sansArrayInfo (Vector arrayInfo) public static String sansArrayInfo (Vector arrayInfo) { int arrays = arrayInfo.size (); String brackets = ""; for (int i = 0; i < arrays; ++i) brackets = brackets + "[]"; return brackets; } // sansArrayInfo // static String sansArrayInfo (String name) static public String sansArrayInfo (String name) { int index = name.indexOf ('['); if (index >= 0) { String array = name.substring (index); name = name.substring (0, index); while (!array.equals ("")) { name = name + "[]"; array = array.substring (array.indexOf (']') + 1); } } return name; } // sansArrayInfo /** * Given a symbol table entry, return the name of * the file which should be created. **/ public static String fileName (SymtabEntry entry, String extension ) { NameModifier nm = new NameModifierImpl() ; return fileName( entry, nm, extension ) ; } // fileName public static String fileName (SymtabEntry entry, NameModifier modifier, String extension ) { // This may not be the most appropriate place for // the mkdir calls, but it's common to everything: String pkg = containerFullName (entry.container ()); if (pkg != null && !pkg.equals ("")) mkdir (pkg); String name = entry.name (); name = modifier.makeName( name ) + extension ; if (pkg != null && !pkg.equals ("")) name = pkg + '/' + name; return name.replace ('/', File.separatorChar); } // fileName public static GenFileStream stream (SymtabEntry entry, String extension) { NameModifier nm = new NameModifierImpl() ; return stream(entry, nm, extension); } // stream public static GenFileStream stream (SymtabEntry entry, NameModifier modifier, String extension ) { return getStream ( fileName (entry,modifier,extension), entry ) ; } public static GenFileStream getStream (String name, SymtabEntry entry) { // String absPathName = ((Arguments)Compile.compiler.arguments).targetDir + name; if (Compile.compiler.arguments.keepOldFiles && new File (absPathName).exists ()) return null; else // Write the data to the file stream return new GenFileStream (absPathName); } // getStream public static String containerFullName( SymtabEntry container) { String name = doContainerFullName( container ) ; if (packageTranslation.size() > 0) name = translate( name ) ; return name ; } public static String translate( String name ) { String head = name ; String tail = "" ; int index ; String trname ; // Check for package name translations, starting with the // most specific match. do { trname = (String)(packageTranslation.get( head )) ; if (trname != null) return trname + tail ; index = head.lastIndexOf( '/' ) ; if (index >= 0) { tail = head.substring( index ) + tail ; head = head.substring( 0, index ) ; } } while (index >= 0) ; return name ; } private static String doContainerFullName (SymtabEntry container) { String name = ""; if (container == null) name = ""; else { if (container instanceof InterfaceEntry || container instanceof StructEntry || container instanceof UnionEntry) name = container.name () + "Package"; else name = container.name (); if (container.container () != null && !container.container ().name ().equals ("")) name = doContainerFullName (container.container ()) + '/' + name; } return name; } // doContainerFullName /** * Given a SymtabEntry, return the string which should be used * for this entry. Enums are converted to ints, typedefs and * sequences are converted to their info types. javaQualifiedName * does not do any of these conversions. **/ public static String javaName (SymtabEntry entry) { // First get the real name of this type String name = ""; if (entry instanceof TypedefEntry || entry instanceof SequenceEntry) try { name = sansArrayInfo ((String)entry.dynamicVariable (Compile.typedefInfo)); } catch (NoSuchFieldException e) { name = entry.name (); } else if (entry instanceof PrimitiveEntry) name = javaPrimName (entry.name ()); else if (entry instanceof StringEntry) name = "String"; else if (entry instanceof NativeEntry) name = javaNativeName (entry.name()); else if (entry instanceof ValueEntry && entry.name ().equals ("ValueBase")) name = "java.io.Serializable"; else if (entry instanceof ValueBoxEntry) { ValueBoxEntry v = (ValueBoxEntry) entry; TypedefEntry member = ((InterfaceState) v.state ().elementAt (0)).entry; SymtabEntry mType = member.type (); if (mType instanceof PrimitiveEntry) { name = containerFullName (entry.container ()); if (!name.equals ("")) name = name + '.'; name = name + entry.name (); } else name = javaName (mType); } else { name = containerFullName (entry.container ()); if (name.equals ("")) name = entry.name (); else name = name + '.' + entry.name (); } // Make it a fully package-qualified name return name.replace ('/', '.'); } // javaName public static String javaPrimName (String name) { if (name.equals ("long") || name.equals ("unsigned long")) name = "int"; else if (name.equals ("octet")) name = "byte"; // "unisigned long long" exceeds Java long. else if (name.equals ("long long") || name.equals ("unsigned long long")) name = "long"; else if (name.equals ("wchar")) name = "char"; else if (name.equals ("unsigned short")) name = "short"; else if (name.equals ("any")) name = "org.omg.CORBA.Any"; else if (name.equals ("TypeCode")) name = "org.omg.CORBA.TypeCode"; else if (name.equals ("Principal")) // name = "org.omg.CORBA.Principal"; return name; } // javaPrimName public static String javaNativeName (String name) { // translations for Native declarations according to CORBA 2.3 spec if (name.equals ("AbstractBase") || name.equals ("Cookie")) name = "java.lang.Object"; else if (name.equals ("Servant")) name = "org.omg.PortableServer.Servant"; else if (name.equals ("ValueFactory")) name = "org.omg.CORBA.portable.ValueFactory"; return name; } /** * Given a symtabEntry, return the name of this entry. This * method does not do any conversions like javaName does. **/ public static String javaQualifiedName (SymtabEntry entry) { String name = ""; if (entry instanceof PrimitiveEntry) name = javaPrimName (entry.name ()); else if (entry instanceof StringEntry) name = "String"; else if (entry instanceof ValueEntry && entry.name ().equals ("ValueBase")) name = "java.io.Serializable"; else { SymtabEntry container = entry.container (); if (container != null) name = container.name (); if (name.equals ("")) name = entry.name (); else name = containerFullName (entry.container ()) + '.' + entry.name (); } return name.replace ('/', '.'); } // javaQualifiedName // Publicize for extensions. //static String collapseName (String name) /** * Collapse primitive type names. **/ public static String collapseName (String name) { if (name.equals ("unsigned short")) name = "ushort"; else if (name.equals ("unsigned long")) name = "ulong"; else if (name.equals ("unsigned long long")) name = "ulonglong"; else if (name.equals ("long long")) name = "longlong"; return name; } // collapseName /** * **/ public static SymtabEntry typeOf (SymtabEntry entry) { while (entry instanceof TypedefEntry && ((TypedefEntry)entry).arrayInfo ().isEmpty () && !(entry.type () instanceof SequenceEntry)) entry = entry.type (); return entry; } // typeOf /** * Fill the info field with the full name (with array info) of the type. **/ static void fillInfo (SymtabEntry infoEntry) { String arrayInfo = ""; SymtabEntry entry = infoEntry; boolean alreadyHave = false; do { try { alreadyHave = entry.dynamicVariable (Compile.typedefInfo) != null; } catch (NoSuchFieldException e) {} // If this entry's info has already been processed // don't bother processing it again, just take it. if (!alreadyHave) { if (entry instanceof TypedefEntry) arrayInfo = arrayInfo + arrayInfo (((TypedefEntry)entry).arrayInfo ()); else if (entry instanceof SequenceEntry) { Expression maxSize = ((SequenceEntry)entry).maxSize (); if (maxSize == null) arrayInfo = arrayInfo + "[]"; else arrayInfo = arrayInfo + '[' + parseExpression (maxSize) + ']'; } if (entry.type () == null) { // Suppress this message. It tells the developer nothing, and // this path does not cause the algorithm to fail. Value boxes may // contain anonymous types, like a struct or enum. //System.err.println (getMessage ("PreEmit.indeterminateTypeInfo", entry.typeName ())); } else entry = entry.type (); } } while (!alreadyHave && entry != null && (entry instanceof TypedefEntry || entry instanceof SequenceEntry)); // Value boxes may contain types lacking typename info., which // causes the 2nd case, below, to fail with exception when retrieving the // javaName(). if (entry instanceof ValueBoxEntry) fillValueBoxInfo ((ValueBoxEntry)entry); try { if (alreadyHave) infoEntry.dynamicVariable (Compile.typedefInfo, (String)entry.dynamicVariable (Compile.typedefInfo) + arrayInfo); else infoEntry.dynamicVariable (Compile.typedefInfo, javaName (entry) + arrayInfo); } catch (NoSuchFieldException e) {} } // fillInfo // /** * **/ static void fillValueBoxInfo (ValueBoxEntry vb) { SymtabEntry stateMember = (((InterfaceState) vb.state ().elementAt (0)).entry); if (stateMember.type() != null) Util.fillInfo (stateMember.type ()); Util.fillInfo (stateMember); } // fillValueBoxInfo /** * **/ public static String holderName (SymtabEntry entry) { String name; if (entry instanceof PrimitiveEntry) if (entry.name ().equals ("any")) name = "org.omg.CORBA.AnyHolder"; else if (entry.name ().equals ("TypeCode")) name = "org.omg.CORBA.TypeCodeHolder"; else if (entry.name ().equals ("Principal")) // name = "org.omg.CORBA.PrincipalHolder"; else name = "org.omg.CORBA." + capitalize (javaQualifiedName (entry)) + "Holder"; else if (entry instanceof TypedefEntry) { TypedefEntry td = (TypedefEntry)entry; if (!td.arrayInfo ().isEmpty () || td.type () instanceof SequenceEntry) name = javaQualifiedName (entry) + "Holder"; else name = holderName (entry.type ()); } else if (entry instanceof StringEntry) name = "org.omg.CORBA.StringHolder"; else if (entry instanceof ValueEntry) { if (entry.name ().equals ("ValueBase")) name = "org.omg.CORBA.ValueBaseHolder"; // , else name = javaName (entry) + "Holder"; } else if (entry instanceof NativeEntry) { // do not attach holder to the translation for Native Entries, e.g. // for Cookie it should be CookieHolder instead of java.lang.ObjectHolder // returns the complete name for the package, etc. name = javaQualifiedName(entry) + "Holder"; } else name = javaName (entry) + "Holder"; return name; } // holderName /** * d61056 **/ public static String helperName (SymtabEntry entry, boolean qualifiedName) { if (entry instanceof ValueEntry) if (entry.name ().equals ("ValueBase")) return "org.omg.CORBA.ValueBaseHelper"; if (qualifiedName) return javaQualifiedName (entry) + "Helper"; else return javaName (entry) + "Helper"; } // helperName public static final short TypeFile = 0, StubFile = 1, HelperFile = 2, HolderFile = 3, StateFile = 4; /** * **/ public static void writePackage (PrintWriter stream, SymtabEntry entry) { writePackage (stream, entry, TypeFile); } // writePackage /** * **/ public static void writePackage (PrintWriter stream, SymtabEntry entry, String name, short type) { if (name != null && !name.equals ("")) { stream.println ("package " + name.replace ('/', '.') + ';'); // This type is in a module. Just in case it refers to types // in the unnamed module, add an import statement for each of // those types. if (!Compile.compiler.importTypes.isEmpty ()) { stream.println (); Vector v = addImportLines (entry, Compile.compiler.importTypes, type); printImports (v, stream); } } } // writePackage /** * **/ public static void writePackage (PrintWriter stream, SymtabEntry entry, short type) { String fullName = containerFullName (entry.container ()); if (fullName != null && !fullName.equals ("")) { stream.println ("package " + fullName.replace ('/', '.') + ';'); // This type is in a module. Just in case it refers to types // in the unnamed module, add an import statement for each of // those types. if ((type != HolderFile || entry instanceof TypedefEntry) && !Compile.compiler.importTypes.isEmpty ()) { stream.println (); Vector v = addImportLines (entry, Compile.compiler.importTypes, type); printImports (v, stream); } /* Enumeration e = Compile.compiler.importTypes.elements (); while (e.hasMoreElements ()) { SymtabEntry i = (SymtabEntry)e.nextElement (); // Write import for type if (!(i instanceof TypedefEntry)) stream.println ("import " + i.name () + ';'); // Write import for Helper if (!(i instanceof ConstEntry)) stream.println ("import " + i.name () + "Helper;"); // Write import for Holder if (!(i instanceof ConstEntry)) if (!(i instanceof TypedefEntry) || (i.type () instanceof SequenceEntry || !((TypedefEntry)i).arrayInfo ().isEmpty ())) stream.println ("import " + i.name () + "Holder;"); } */ } } // writePackage /** * **/ static private void printImports (Vector importList, PrintWriter stream) { Enumeration e = importList.elements (); while (e.hasMoreElements ()) stream.println ("import " + (String)e.nextElement () + ';'); } // printImport /** * **/ static private void addTo (Vector importList, String name) { // REVISIT - was also importing ValueBaseHolder and Helper if (name.startsWith ("ValueBase")) // don't import ValueBase* if ((name.compareTo ("ValueBase") == 0) || (name.compareTo ("ValueBaseHolder") == 0) || (name.compareTo ("ValueBaseHelper") == 0)) return; if (!importList.contains (name)) importList.addElement (name); } // addTo /** * **/ static private Vector addImportLines (SymtabEntry entry, Vector importTypes, short type) { Vector importList = new Vector (); if (entry instanceof ConstEntry) { ConstEntry c = (ConstEntry)entry; Object cvalue = c.value ().value (); if (cvalue instanceof ConstEntry && importTypes.contains (cvalue)) addTo (importList, ((ConstEntry)cvalue).name ()); } else if (entry instanceof ValueEntry && type == HelperFile) // { // This code inspired by ValueGen.getConcreteBaseTypeCode(). Helper method // type() could be invoked against a global valuetype. if (((ValueEntry)entry).derivedFrom ().size () > 0) // <59596> KLR HACK { ValueEntry base = (ValueEntry)((ValueEntry)entry).derivedFrom ().elementAt (0); String baseName = base.name (); if (!"ValueBase".equals (baseName)) if (importTypes.contains (base)) addTo (importList, baseName + "Helper"); } } else if (entry instanceof InterfaceEntry && (type == TypeFile || type == StubFile)) { InterfaceEntry i = (InterfaceEntry)entry; if (i instanceof ValueEntry) // { // Examine interface parents in supports vector. Enumeration e = ((ValueEntry)i).supports ().elements (); while (e.hasMoreElements ()) { SymtabEntry parent = (SymtabEntry)e.nextElement (); if (importTypes.contains (parent)) { addTo (importList, parent.name () + "Operations"); } // If this is a stub, then recurse to the parents if (type == StubFile) { if (importTypes.contains (parent)) addTo (importList, parent.name ()); Vector subImportList = addImportLines (parent, importTypes, StubFile); Enumeration en = subImportList.elements (); while (en.hasMoreElements ()) { addTo (importList, (String)en.nextElement ()); } } } } // Interface or valuetype -- Examine interface and valuetype parents, // Look through derivedFrom vector Enumeration e = i.derivedFrom ().elements (); while (e.hasMoreElements ()) { SymtabEntry parent = (SymtabEntry)e.nextElement (); if (importTypes.contains (parent)) { addTo (importList, parent.name ()); // Always add both imports, even though superfluous. Cannot // tell when writing Operations or Signature interface! if (!(parent instanceof ValueEntry)) // && parent.name ().equals ("ValueBase"))) addTo (importList, parent.name () + "Operations"); } // If this is a stub, then recurse to the parents if (type == StubFile) { Vector subImportList = addImportLines (parent, importTypes, StubFile); Enumeration en = subImportList.elements (); while (en.hasMoreElements ()) { addTo (importList, (String)en.nextElement ()); } } } // Look through methods vector e = i.methods ().elements (); while (e.hasMoreElements ()) { MethodEntry m = (MethodEntry)e.nextElement (); // Look at method type SymtabEntry mtype = typeOf (m.type ()); if (mtype != null && importTypes.contains (mtype)) if (type == TypeFile || type == StubFile) { addTo (importList, mtype.name ()); addTo (importList, mtype.name () + "Holder"); if (type == StubFile) addTo (importList, mtype.name () + "Helper"); } checkForArrays (mtype, importTypes, importList); // Print import lines for globals constants and constants // within global interfaces. if (type == StubFile) checkForBounds (mtype, importTypes, importList); // Look through exceptions Enumeration exEnum = m.exceptions ().elements (); while (exEnum.hasMoreElements ()) { ExceptionEntry ex = (ExceptionEntry)exEnum.nextElement (); if (importTypes.contains (ex)) { addTo (importList, ex.name ()); addTo (importList, ex.name () + "Helper"); // } } // Look through parameters Enumeration parms = m.parameters ().elements (); while (parms.hasMoreElements ()) { ParameterEntry parm = (ParameterEntry)parms.nextElement (); SymtabEntry parmType = typeOf (parm.type ()); if (importTypes.contains (parmType)) { // Helper needed in stubs. if (type == StubFile) addTo (importList, parmType.name () + "Helper"); if (parm.passType () == ParameterEntry.In) addTo (importList, parmType.name ()); else addTo (importList, parmType.name () + "Holder"); } checkForArrays (parmType, importTypes, importList); // if (type == StubFile) checkForBounds (parmType, importTypes, importList); } } } else if (entry instanceof StructEntry) { StructEntry s = (StructEntry)entry; // Look through the members Enumeration members = s.members ().elements (); while (members.hasMoreElements ()) { SymtabEntry member = (TypedefEntry)members.nextElement (); // Need to add helper name for typedef members. This name // is referenced at typecode generation in Helper class. SymtabEntry memberType = member.type (); member = typeOf (member); if (importTypes.contains (member)) { // If this IS a typedef, then there are only Helper/Holder classes. //if (!(member instanceof TypedefEntry)) // Valueboxes if (!(member instanceof TypedefEntry) && !(member instanceof ValueBoxEntry)) addTo (importList, member.name ()); // Add helper name of alias, too, if member is a typedef. //if (type == HelperFile) // addTo (importList, member.name () + "Helper"); if (type == HelperFile) { addTo (importList, member.name () + "Helper"); if (memberType instanceof TypedefEntry) addTo (importList, memberType.name () + "Helper"); } } checkForArrays (member, importTypes, importList); checkForBounds (member, importTypes, importList); } } else if (entry instanceof TypedefEntry) { TypedefEntry t = (TypedefEntry)entry; String arrays = checkForArrayBase (t, importTypes, importList); if (type == HelperFile) { checkForArrayDimensions (arrays, importTypes, importList); try { String name = (String)t.dynamicVariable (Compile.typedefInfo); int index = name.indexOf ('['); if (index >= 0) name = name.substring (0, index); // See if the base type should be added to the list. SymtabEntry typeEntry = (SymtabEntry)symbolTable.get (name); if (typeEntry != null && importTypes.contains (typeEntry)) addTo (importList, typeEntry.name () + "Helper"); } catch (NoSuchFieldException e) {} // Typedefs for global bounded strings need import // statement when bound expression contains non-literal constants. checkForBounds (typeOf (t), importTypes, importList); } Vector subImportList = addImportLines (t.type (), importTypes, type); Enumeration e = subImportList.elements (); while (e.hasMoreElements ()) addTo (importList, (String)e.nextElement ()); } else if (entry instanceof UnionEntry) { UnionEntry u = (UnionEntry)entry; // Look at the discriminant type SymtabEntry utype = typeOf (u.type ()); if (utype instanceof EnumEntry && importTypes.contains (utype)) addTo (importList, utype.name ()); // Look through the branches Enumeration branches = u.branches ().elements (); while (branches.hasMoreElements ()) { UnionBranch branch = (UnionBranch)branches.nextElement (); SymtabEntry branchEntry = typeOf (branch.typedef); if (importTypes.contains (branchEntry)) { addTo (importList, branchEntry.name ()); if (type == HelperFile) addTo (importList, branchEntry.name () + "Helper"); } checkForArrays (branchEntry, importTypes, importList); // checkForBounds (branchEntry, importTypes, importList); } } // If a typedef is not a sequence or an array, only holders and // helpers are generated for it. Remove references to such // class names. Enumeration en = importList.elements (); while (en.hasMoreElements ()) { String name = (String)en.nextElement (); SymtabEntry e = (SymtabEntry)symbolTable.get (name); if (e != null && e instanceof TypedefEntry) { TypedefEntry t = (TypedefEntry)e; if (t.arrayInfo ().size () == 0 || !(t.type () instanceof SequenceEntry)) importList.removeElement (name); } } return importList; } // addImportLines /** * **/ static private void checkForArrays (SymtabEntry entry, Vector importTypes, Vector importList) { if (entry instanceof TypedefEntry) { TypedefEntry t = (TypedefEntry)entry; String arrays = checkForArrayBase (t, importTypes, importList); checkForArrayDimensions (arrays, importTypes, importList); } } // checkForArrays /** * **/ static private String checkForArrayBase (TypedefEntry t, Vector importTypes, Vector importList) { String arrays = ""; try { String name = (String)t.dynamicVariable (Compile.typedefInfo); int index = name.indexOf ('['); if (index >= 0) { arrays = name.substring (index); name = name.substring (0, index); } // See if the base type should be added to the list. SymtabEntry typeEntry = (SymtabEntry)symbolTable.get (name); if (typeEntry != null && importTypes.contains (typeEntry)) addTo (importList, typeEntry.name ()); } catch (NoSuchFieldException e) {} return arrays; } // checkForArrayBase /** * **/ static private void checkForArrayDimensions (String arrays, Vector importTypes, Vector importList) { // See if any of the arrays contain a constentry. // If so, see if it should be added to the list. while (!arrays.equals ("")) { int index = arrays.indexOf (']'); String dim = arrays.substring (1, index); arrays = arrays.substring (index + 1); SymtabEntry constant = (SymtabEntry)symbolTable.get (dim); if (constant == null) { // A constant expr could be of the form OR // .. This if branch checks for that case. int i = dim.lastIndexOf ('.'); if (i >= 0) constant = (SymtabEntry)symbolTable.get (dim.substring (0, i)); } if (constant != null && importTypes.contains (constant)) addTo (importList, constant.name ()); } } // checkForArrayDimensions // Call the following method when its necessary to determine the // the import types for IDL constructs containing arbitrary positive int. // expressions, which may specify non-literal constants. /** * Determine the import lines for template types. **/ static private void checkForBounds (SymtabEntry entry, Vector importTypes, Vector importList) { // Obtain actual type, just to be complete. SymtabEntry entryType = entry; while (entryType instanceof TypedefEntry) entryType = entryType.type (); if (entryType instanceof StringEntry && ((StringEntry)entryType).maxSize () != null) checkForGlobalConstants (((StringEntry)entryType).maxSize ().rep (), importTypes, importList); else if (entryType instanceof SequenceEntry && ((SequenceEntry)entryType).maxSize () != null) checkForGlobalConstants (((SequenceEntry)entryType).maxSize ().rep (), importTypes, importList); } // checkForBounds /** * Extract the global constants from the supplied integer expression * representation (string) and add them to the supplied import list. **/ static private void checkForGlobalConstants (String exprRep, Vector importTypes, Vector importList) { // NOTE: Do not use '/' as a delimiter. Symbol table names use '/' as a // delimiter and would not be otherwise properly collected. Blanks and // arithmetic symbols do not appear in tokens, except for '/'. java.util.StringTokenizer st = new java.util.StringTokenizer (exprRep, " +-*()~&|^%<>"); while (st.hasMoreTokens ()) { String token = st.nextToken (); // When token contains '/', it represents the division symbol or // a nested type (e.g., I/x). Ignore the division symbol, and don't // forget constants declared within global interfaces! if (!token.equals ("/")) { SymtabEntry typeEntry = (SymtabEntry)symbolTable.get (token); if (typeEntry instanceof ConstEntry) { int slashIdx = token.indexOf ('/'); if (slashIdx < 0) // Possible global constant { if (importTypes.contains (typeEntry)) addTo (importList, typeEntry.name ()); } else // Possible constant in global interface { SymtabEntry constContainer = (SymtabEntry)symbolTable.get (token.substring (0, slashIdx)); if (constContainer instanceof InterfaceEntry && importTypes.contains (constContainer)) addTo (importList, constContainer.name ()); } } } } } // checkForGlobalConstants /** * **/ public static void writeInitializer (String indent, String name, String arrayDcl, SymtabEntry entry, PrintWriter stream) { if (entry instanceof TypedefEntry) { TypedefEntry td = (TypedefEntry)entry; writeInitializer (indent, name, arrayDcl + sansArrayInfo (td.arrayInfo ()), td.type (), stream); } else if (entry instanceof SequenceEntry) writeInitializer (indent, name, arrayDcl + "[]", entry.type (), stream); else if (entry instanceof EnumEntry) if (arrayDcl.length () > 0) stream.println (indent + javaName (entry) + ' ' + name + arrayDcl + " = null;"); else stream.println (indent + javaName (entry) + ' ' + name + " = null;"); else if (entry instanceof PrimitiveEntry) { boolean array = arrayDcl.length () > 0; String tname = javaPrimName (entry.name ()); if (tname.equals ("boolean")) stream.println (indent + "boolean " + name + arrayDcl + " = " + (array ? "null;" : "false;")); else if (tname.equals ("org.omg.CORBA.TypeCode")) stream.println (indent + "org.omg.CORBA.TypeCode " + name + arrayDcl + " = null;"); else if (tname.equals ("org.omg.CORBA.Any")) stream.println (indent + "org.omg.CORBA.Any " + name + arrayDcl + " = null;"); else if (tname.equals ("org.omg.CORBA.Principal")) // stream.println (indent + "org.omg.CORBA.Principal " + name + arrayDcl + " = null;"); else stream.println (indent + tname + ' ' + name + arrayDcl + " = " + (array ? "null;" : '(' + tname + ")0;")); } // Remove -stateful feature. This case is identical to next one // because javaName() supplants javaStatefulName(). //else if (entry instanceof InterfaceEntry && ((InterfaceEntry)entry).state () != null) // stream.println (indent + javaStatefulName ((InterfaceEntry)entry) + ' ' + name + arrayDcl + " = null;"); else stream.println (indent + javaName (entry) + ' ' + name + arrayDcl + " = null;"); } // writeInitializer /** * **/ public static void writeInitializer (String indent, String name, String arrayDcl, SymtabEntry entry, String initializer, PrintWriter stream) { if (entry instanceof TypedefEntry) { TypedefEntry td = (TypedefEntry)entry; writeInitializer (indent, name, arrayDcl + sansArrayInfo (td.arrayInfo ()), td.type (), initializer, stream); } else if (entry instanceof SequenceEntry) writeInitializer (indent, name, arrayDcl + "[]", entry.type (), initializer, stream); else if (entry instanceof EnumEntry) if (arrayDcl.length () > 0) stream.println (indent + javaName (entry) + ' ' + name + arrayDcl + " = " + initializer + ';'); else stream.println (indent + javaName (entry) + ' ' + name + " = " + initializer + ';'); else if (entry instanceof PrimitiveEntry) { boolean array = arrayDcl.length () > 0; String tname = javaPrimName (entry.name ()); if (tname.equals ("boolean")) stream.println (indent + "boolean " + name + arrayDcl + " = " + initializer + ';'); else if (tname.equals ("org.omg.CORBA.TypeCode")) stream.println (indent + "org.omg.CORBA.TypeCode " + name + arrayDcl + " = " + initializer + ';'); else if (tname.equals ("org.omg.CORBA.Any")) stream.println (indent + "org.omg.CORBA.Any " + name + arrayDcl + " = " + initializer + ';'); else if (tname.equals ("org.omg.CORBA.Principal")) // stream.println (indent + "org.omg.CORBA.Principal " + name + arrayDcl + " = " + initializer + ';'); else stream.println (indent + tname + ' ' + name + arrayDcl + " = " + initializer + ';'); } // Remove -stateful feature. This case is identical to next one // because javaName() supplants javaStatefulName(). //else if (entry instanceof InterfaceEntry && ((InterfaceEntry)entry).state () != null) // stream.println (indent + javaStatefulName ((InterfaceEntry)entry) + ' ' + name + arrayDcl + " = " + initializer + ';'); else stream.println (indent + javaName (entry) + ' ' + name + arrayDcl + " = " + initializer + ';'); } // writeInitializer /** * **/ public static void mkdir (String name) { String targetDir = ((Arguments)Compile.compiler.arguments).targetDir; // F46838.4 name = (targetDir + name).replace ('/', File.separatorChar); // F46838.4 File pkg = new File (name); if (!pkg.exists ()) if (!pkg.mkdirs ()) System.err.println (getMessage ("Util.cantCreatePkg", name)); } // mkdir /** * **/ public static void writeProlog (PrintWriter stream, String filename) { // Remove target directory String targetDir = ((Arguments)Compile.compiler.arguments).targetDir; if (targetDir != null) filename = filename.substring (targetDir.length ()); stream.println (); stream.println ("/**"); stream.println ("* " + filename.replace (File.separatorChar, '/') + " ."); stream.println ("* " + Util.getMessage ("toJavaProlog1", Util.getMessage ("Version.product", Util.getMessage ("Version.number")))); // Do not introduce invalid escape characters into comment! //stream.println ("* " + Util.getMessage ("toJavaProlog2", Compile.compiler.arguments.file)); stream.println ("* " + Util.getMessage ("toJavaProlog2", Compile.compiler.arguments.file.replace (File.separatorChar, '/'))); /////////////// // This SHOULD work, but there's a bug in the JDK. // stream.println ("* " + DateFormat.getDateTimeInstance (DateFormat.FULL, DateFormat.FULL, Locale.getDefault ()).format (new Date ())); // This gets around the bug: DateFormat formatter = DateFormat.getDateTimeInstance (DateFormat.FULL, DateFormat.FULL, Locale.getDefault ()); // Japanese-specific workaround. JDK bug 4069784 being repaired by JavaSoft. // Keep this transient solution until bug fix is reported.cd . if (Locale.getDefault () == Locale.JAPAN) formatter.setTimeZone (java.util.TimeZone.getTimeZone ("JST")); else formatter.setTimeZone (java.util.TimeZone.getDefault ()); stream.println ("* " + formatter.format (new Date ())); // /////////////// stream.println ("*/"); stream.println (); } // writeProlog // keywords ending in Holder or Helper or Package have '_' prepended. // These prepended underscores must not be part of anything sent // across the wire, so these two methods are provided to strip them // off. /** * **/ public static String stripLeadingUnderscores (String string) { while (string.startsWith ("_")) string = string.substring (1); return string; } // stripLeadingUnderscores /** * **/ public static String stripLeadingUnderscoresFromID (String string) { String stringPrefix = ""; int slashIndex = string.indexOf (':'); if (slashIndex >= 0) do { stringPrefix = stringPrefix + string.substring (0, slashIndex + 1); string = string.substring (slashIndex + 1); while (string.startsWith ("_")) string = string.substring (1); slashIndex = string.indexOf ('/'); } while (slashIndex >= 0); return stringPrefix + string; } // stripLeadingUnderscoresFromID /** * **/ public static String parseExpression (Expression e) { if (e instanceof Terminal) return parseTerminal ((Terminal)e); else if (e instanceof BinaryExpr) return parseBinary ((BinaryExpr)e); else if (e instanceof UnaryExpr) return parseUnary ((UnaryExpr)e); else return "(UNKNOWN_VALUE)"; // This shouldn't happen unless someone slips // in another type of expression. } // parseExpression /** * **/ static String parseTerminal (Terminal e) { if (e.value () instanceof ConstEntry) { ConstEntry c = (ConstEntry)e.value (); if (c.container () instanceof InterfaceEntry) return javaQualifiedName (c.container ()) + '.' + c.name (); else return javaQualifiedName (c) + ".value"; } else if (e.value () instanceof Expression) return '(' + parseExpression ((Expression)e.value ()) + ')'; else if (e.value () instanceof Character) { if (((Character)e.value ()).charValue () == '\013') // e.rep is \v. \v for vertical tab is meaningless in Java. return "'\\013'"; else if (((Character)e.value ()).charValue () == '\007') // e.rep is \a. \a for alert is meaningless in Java. return "'\\007'"; else if (e.rep ().startsWith ("'\\x")) return hexToOctal (e.rep ()); else if (e.rep ().equals ("'\\?'")) return "'?'"; else return e.rep (); } else if (e.value () instanceof Boolean) return e.value ().toString (); // If value is type "unsigned long long" (ull) and its magnitude // is greater than the maximal Java long (i.e., IDL long long) value, then // return its signed representation rather than its actual representation. /* // Support long long //else if (e.value () instanceof Long) else if (e.value () instanceof BigInteger && (e.type ().indexOf ("long long") >= 0 || e.type ().equals ("unsigned long"))) // { String rep = e.rep (); int index = rep.indexOf (')'); if (index < 0) return rep + 'L'; else return rep.substring (0, index) + 'L' + rep.substring (index); } */ else if (e.value () instanceof BigInteger) { // Get the correct primitive type. Since integer types (octet, short, // long, long long, unsigned short, unsigned long, unsigned long long) // could be aliased (typedef'ed) to any arbitrary levels, the code // below walks up the alias chain to get to the primitive type. // Get the symbol table entry corresponding to the 'type'. SymtabEntry typeEntry = (SymtabEntry) symbolTable.get(e.type()); // Get to the primitive type. while (typeEntry.type() != null) { typeEntry = typeEntry.type(); } String type = typeEntry.name(); if (type.equals("unsigned long long") && ((BigInteger)e.value ()).compareTo (Expression.llMax) > 0) // value > long long Max? { // Convert to signed value, which will always be negative. BigInteger v = (BigInteger)e.value (); v = v.subtract (Expression.twoPow64); int index = e.rep ().indexOf (')'); if (index < 0) return v.toString () + 'L'; else return '(' + v.toString () + 'L' + ')'; } else if ( type.indexOf("long long") >= 0 || type.equals("unsigned long") ) { String rep = e.rep (); int index = rep.indexOf (')'); if (index < 0) return rep + 'L'; else return rep.substring (0, index) + 'L' + rep.substring (index); } else return e.rep (); } // end else return e.rep (); } // parseTerminal /** * **/ static String hexToOctal (String hex) { // The format of hex is '/xXX' where XX is one or two hex digits. // This statement pulls off XX. hex = hex.substring (3, hex.length () - 1); return "'\\" + Integer.toString (Integer.parseInt (hex, 16), 8) + "'"; } // hexToOctal /** * **/ static String parseBinary (BinaryExpr e) { String castString = ""; if (e.value () instanceof Float || e.value () instanceof Double) { castString = "(double)"; if (!(e instanceof Plus || e instanceof Minus || e instanceof Times || e instanceof Divide)) System.err.println ("Operator " + e.op () + " is invalid on floating point numbers"); } else if (e.value () instanceof Number) { if (e.type (). indexOf ("long long") >= 0) castString = "(long)"; else castString = "(int)"; } else { castString = ""; System.err.println ("Unknown type in constant expression"); } // Must emit value rather than representation when type "unsigned // long long" (ull) because emitted binary arithmetic expressions containing // ull's converted to long (i.e., IDL long long) do not always compute to // the correct result. //return castString + '(' + parseExpression (e.left ()) + ' ' + e.op () + ' ' + parseExpression (e.right ()) + ')'; if (e.type ().equals ("unsigned long long")) { BigInteger value = (BigInteger)e.value (); if (value.compareTo (Expression.llMax) > 0) // value > long long max? value = value.subtract (Expression.twoPow64); // Convert to Java long (signed) return castString + '(' + value.toString () + 'L' + ')'; } else return castString + '(' + parseExpression (e.left ()) + ' ' + e.op () + ' ' + parseExpression (e.right ()) + ')'; // end } // parseBinary /** * **/ static String parseUnary (UnaryExpr e) { if (!(e.value () instanceof Number)) return "(UNKNOWN_VALUE)"; // This shouldn't happen if the parser checked the expression types correctly. else if ((e.value () instanceof Float || e.value () instanceof Double) && e instanceof Not) return "(UNKNOWN_VALUE)"; // This shouldn't happen if the parser checked the expression types correctly. else { String castString = ""; if (e.operand ().value () instanceof Float || e.operand ().value () instanceof Double) castString = "(double)"; // Support long long. //else // castString = "(long)"; else if (e.type (). indexOf ("long long") >= 0) castString = "(long)"; else castString = "(int)"; // Must emit value rather than representation when type is // "unsigned long long" (ull) because emitted unary arithmetic expressions // containing a ull converted to long (i.e., IDL long long) do not always // compute to the correct result. //return castString + e.op () + parseExpression (e.operand ()); if (e.type ().equals ("unsigned long long")) { BigInteger value = (BigInteger)e.value (); if (value.compareTo (Expression.llMax) > 0) // value > long long max? value = value.subtract (Expression.twoPow64); // Convert to Java long (signed) return castString + '(' + value.toString () + 'L' + ')'; } else return castString + e.op () + parseExpression (e.operand ()); // end } } // parseUnary /** * **/ public static boolean IDLEntity (SymtabEntry entry) { boolean rc = true; if (entry instanceof PrimitiveEntry || entry instanceof StringEntry) rc = false; else if (entry instanceof TypedefEntry) rc = IDLEntity (entry.type ()); return rc; } // IDLEntity // /** * @return true if the current setting of corbaLevel is within delta of * the range {@code min <= corbaLevel <= max} **/ public static boolean corbaLevel (float min, float max) { float level = Compile.compiler.arguments.corbaLevel; float delta = 0.001f; if ((level - min + delta >= 0.0f) && (max - level + delta >= 0.0f)) return true; else return false; } // corbaLevel static Hashtable symbolTable = new Hashtable (); static Hashtable packageTranslation = new Hashtable() ; } // class Util