| /* |
| * 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.parser |
| * |
| * 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; |
| |
| // NOTES: |
| // -D56351<daz> Update computation of RepositoryIDs to CORBA 2.3 (see spec.). |
| // -D58319<daz> Display version info. for -version option. |
| |
| import java.io.FileNotFoundException; |
| import java.io.IOException; |
| import java.util.Enumeration; |
| import java.util.Hashtable; |
| import java.util.Vector; |
| |
| import com.sun.tools.corba.se.idl.constExpr.ExprFactory; |
| import com.sun.tools.corba.se.idl.constExpr.DefaultExprFactory; |
| |
| /** |
| * Compiler usage: |
| * <br><br> |
| * |
| * java com.sun.tools.corba.se.idl.toJava.compile [options] <idl file> |
| * <br><br> |
| * |
| * where <idl file> is the name of a file containing IDL definitions, |
| * and [options] is any combination of the options listed below. The options |
| * and the idl file name can appear in any order. |
| * <br><br> |
| * |
| * Options: |
| * <dl> |
| * <dt>-i <include path> |
| * <dd>By default, the current directory is scanned for included files. |
| * This option adds another directory. See also Note 1 below. |
| * |
| * <dt>-d <symbol> |
| * <dd>This is equivalent to the following line in an IDL file: #define <symbol> |
| * |
| * <dt>-emitAll |
| * <dd>Emit all types, including those found in #included files. |
| * |
| * <dt>-v |
| * <dd>Verbose mode. |
| * </dl> |
| * |
| * Note 1: If you have an include path or paths that you will always be using, |
| * it can get tedious putting these on the command with the -i option all the |
| * time. Instead, these can be placed into a config file called idl.config. |
| * This file must be in the CLASSPATH. The format of the includes line is: |
| * |
| * <pre> |
| * includes=<path1>;<path2>;...;<pathN> |
| * </pre> |
| * |
| * Note that the path separator character, here shown as a semicolon, is |
| * machine dependent. For instance, on Windows 95 this character is a |
| * semicolon, on UNIX it is a colon. |
| * |
| * <p> |
| * Note 2: If you are directly invoking the main method on this class (not |
| * a subclass), then it will only check that the IDL file is syntactically |
| * correct. It does not generate any files. Only extensions to this |
| * framework generate files, therefore an extension must be invoked if you |
| * want files to be generated. |
| * <br><br> |
| * |
| * To Extend the compiler: |
| * <br><br> |
| * |
| * You only need to extend the compiler if you want it to generate something |
| * other than what it currently generates. |
| * <br><br> |
| * |
| * Step 1 - Implement the generator interfaces: |
| * <br><br> |
| * |
| * Each generator interface defines one method: generate (Hashtable, XXXEntry, PrintWriter); |
| * <br> |
| * - The Hashtable is the symbol table; each element is a SymtabEntry (or a |
| * subclass of SymtabEntry) and is keyed by its fully qualified name; |
| * <br> |
| * - XXXEntry is the appropriate entry for the type to be generated. For |
| * example: AttributeGen defines generate (Hashtable, AttributeEntry, PrintWriter); |
| * ConstGen defines generate (Hashtable, ConstEntry, PrintWriter); etc. |
| * <br> |
| * - The PrintWriter is a stream to the file being generated. For the |
| * generators called by the compiler framework, this will be null. The |
| * generator is responsible for creating and opening files. But for |
| * generators that are called by other generators - for instance, |
| * MethodGen.generate will most likely be called by InterfaceGen.generate - |
| * this parameter is provided so that the proper file can be written to. |
| * <br><br> |
| * |
| * Step 2 - Implement the GenFactory interface: |
| * <br><br> |
| * |
| * All of the generators implemented in Step 1 must be created somehow. There |
| * is an interface for a factory, GenFactory, which must be implemented. The |
| * name of this factory must be set in the extension to the Compile class (see |
| * Step 3, below). |
| * <br><br> |
| * |
| * Step 3 - Extend com.sun.tools.corba.se.idl.Factories: |
| * <br><br> |
| * |
| * Extend com.sun.tools.corba.se.idl.Factories and override the method genFactory. This |
| * method must return an instance of the factory which you implemented in |
| * step 2. Your extension of this class may also do more, this is only the |
| * minimum. See com.sun.tools.corba.se.idl.Factories for more information. |
| * <br><br> |
| * |
| * Step 4 - Extend com.sun.tools.corba.se.idl.Compile: |
| * <br><br> |
| * |
| * Your extension of com.sun.tools.corba.se.idl.Compile should contain a minimum of |
| * two methods: |
| * <dl> |
| * <dt>protected com.sun.tools.corba.se.idl.Factories () |
| * <dd>This method overrides com.sun.tools.corba.se.idl.Compile.factories and returns your |
| * extension from Step 3. |
| * |
| * <dt>public static void main (String[] args) |
| * <dd>This main method must instantiate this class and call its start method. |
| * </dl> |
| * |
| * Given that the extension of Factories is MyFactories, the extension of |
| * Compile could be: |
| * |
| * <pre> |
| * public class MyCompile extends com.sun.tools.corba.se.idl.Compile |
| * { |
| * protected com.sun.tools.corba.se.idl.Factories factories () |
| * { |
| * return new MyFactories (); |
| * } |
| * public static void main (String[] args) |
| * { |
| * MyCompile compile = new MyCompile (); |
| * compile.start (args); |
| * } |
| * } |
| * </pre> |
| * |
| * If you would like a bit more control over the processing of the framework, |
| * you can replace compile.start with what it calls. But then you also have |
| * to handle the exceptions which start handles for you: |
| * <pre> |
| * public class MyCompile extends com.sun.tools.corba.se.idl.Compile |
| * { |
| * ... |
| * |
| * public static void main (String[] args) |
| * { |
| * MyCompile compile = new MyCompile (); |
| * try |
| * { |
| * compile.init (args); |
| * java.util.Enumeration emitList = compile.parse (); |
| * compile.generate (); |
| * } |
| * catch (com.sun.tools.corba.se.idl.InvalidArgument e) |
| * { |
| * System.err.println (e); |
| * } |
| * catch (java.io.IOException e) |
| * { |
| * System.err.println (e); |
| * } |
| * } |
| * } |
| * </pre> |
| * |
| * Note that compile.parse returns an enumeration. This enumerates the |
| * SymtabEntry's which should be generated. If the parse method detects |
| * errors, it returns null. Note that you do not have to check that |
| * `emitList' is valid before calling generate (that's done internally), but |
| * if you do any processing between parse and generate, emitList should be |
| * checked before executing that code. |
| * <br><br> |
| **/ |
| public class Compile |
| { |
| public Compile () |
| { |
| noPragma.init (preprocessor); |
| preprocessor.registerPragma (noPragma); |
| |
| // <d41197> Reset static variables to allow parsing multiple sources. |
| // DO NOT reset SymtabEntry.maxKey because it crashes IDLC. |
| ParseException.detected = false; |
| SymtabEntry.includeStack = new java.util.Stack (); |
| SymtabEntry.setEmit = true; |
| //SymtabEntry.maxKey = -1; |
| Parser.repIDStack = new java.util.Stack (); // <d56351> |
| } // ctor |
| |
| public static void main (String[] args) |
| { |
| (new Compile ()).start (args); |
| } // main |
| |
| protected Factories factories () |
| { |
| return new Factories (); |
| } // genFactoryName |
| |
| protected void registerPragma (PragmaHandler handler) |
| { |
| handler.init (preprocessor); |
| preprocessor.registerPragma (handler); |
| } // registerPragma |
| |
| /** |
| * Initialize the framework. |
| **/ |
| protected void init (String[] args) throws InvalidArgument |
| { |
| initFactories (); |
| arguments.parseArgs (args); |
| initGenerators (); |
| parser = new Parser (preprocessor, arguments, overrideNames, symbolTable, symtabFactory, exprFactory, keywords); |
| preprocessor.init (parser); |
| parser.includes = includes; |
| parser.includeEntries = includeEntries; |
| } // init |
| |
| /** |
| * Parse the IDL file and return an enumeration of the symbols to be |
| * generated. All elements of the Enumeration will be extensions of |
| * SymtabEntry. If any errors were encountered during parsing, null |
| * will be returned. |
| **/ |
| protected Enumeration parse () throws IOException |
| { |
| if (arguments.verbose) |
| System.out.println (Util.getMessage ("Compile.parsing", arguments.file)); |
| parser.parse (arguments.file); |
| if ( !ParseException.detected ) |
| { |
| parser.forwardEntryCheck(); |
| |
| // <46082.03> Revert to "IDL:"-style (i.e., regular) repository ID. |
| //parser.updateRepositoryIds(); |
| } |
| if (arguments.verbose) |
| System.out.println (Util.getMessage ("Compile.parseDone", arguments.file)); |
| if (ParseException.detected) |
| { |
| symbolTable = null; |
| emitList = null; |
| } |
| else |
| { |
| symbolTable = parser.symbolTable; |
| emitList = parser.emitList.elements (); |
| } |
| return emitList; |
| } // parse |
| |
| /** |
| * Invoke the generators. |
| **/ |
| protected void generate () throws IOException |
| { |
| /* |
| // print the symbol table |
| Enumeration v = parser.symbolTable.elements (); |
| Enumeration k = parser.symbolTable.keys (); |
| while (k.hasMoreElements ()) |
| System.out.println (k.nextElement () + ": " + v.nextElement ()); |
| */ |
| if (ParseException.detected) |
| emitList = null; |
| else |
| emitList = parser.emitList.elements (); |
| if (emitList != null) |
| { |
| // Emit the output files for all of the types in the IDL file |
| if (arguments.verbose) |
| System.out.println (); |
| while (emitList.hasMoreElements ()) |
| { |
| SymtabEntry entry = (SymtabEntry)emitList.nextElement (); |
| if (arguments.verbose) |
| if (entry.generator () instanceof Noop) |
| ; // Nothing will be generated, so don't say so. |
| else if (entry.module () . equals ("")) |
| System.out.println (Util.getMessage ("Compile.generating", entry.name ())); |
| else |
| System.out.println (Util.getMessage ("Compile.generating", entry.module () + '/' + entry.name ())); |
| entry.generate (symbolTable, null); |
| if (arguments.verbose) |
| if (entry.generator () instanceof Noop) |
| ; // Nothing will be generated, so don't say so. |
| else if (entry.module () . equals ("")) |
| System.out.println (Util.getMessage ("Compile.genDone", entry.name ())); |
| else |
| System.out.println (Util.getMessage ("Compile.genDone", entry.module () + '/' + entry.name ())); |
| } |
| } |
| } // generate |
| |
| /** |
| * Start the parse/code generation process. This method calls init, |
| * parse, generate. If more control is desired, rather than call start, |
| * those three methods could be called explicitly. |
| **/ |
| public void start (String[] args) |
| { |
| try |
| { |
| init (args); |
| if (arguments.versionRequest) // <d59319> |
| displayVersion (); |
| else |
| { |
| parse (); |
| generate (); |
| } |
| } |
| catch (InvalidArgument e) |
| { |
| System.err.println (e); |
| } |
| catch (IOException e) |
| { |
| System.err.println (e); |
| } |
| } // start |
| |
| private void initFactories () |
| { |
| // Get the factories. |
| Factories factories = factories (); |
| if (factories == null) factories = new Factories (); |
| |
| // Get the argument processor from the factories. |
| Arguments tmpArgs = factories.arguments (); |
| if (tmpArgs == null) |
| arguments = new Arguments (); |
| else |
| arguments = tmpArgs; |
| |
| // Get the symbol table entry factory from the factories. |
| SymtabFactory tmpSTF = factories.symtabFactory (); |
| if (tmpSTF == null) |
| symtabFactory = new DefaultSymtabFactory (); |
| else |
| symtabFactory = tmpSTF; |
| |
| // Get the expression factory from the factories. |
| ExprFactory tmpExpF = factories.exprFactory (); |
| if (tmpExpF == null) |
| exprFactory = new DefaultExprFactory (); |
| else |
| exprFactory = tmpExpF; |
| |
| // Get the generator factory from the factories. |
| GenFactory tmpGenF = factories.genFactory (); |
| if (tmpGenF == null) |
| genFactory = noop; |
| else |
| genFactory = tmpGenF; |
| |
| // Get the language keywords. |
| keywords = factories.languageKeywords (); |
| if (keywords == null) |
| keywords = new String[0]; |
| } // initFactories |
| |
| private void initGenerators () |
| { |
| AttributeGen agen = genFactory.createAttributeGen (); |
| AttributeEntry.attributeGen = agen == null ? noop : agen; |
| |
| ConstGen cgen = genFactory.createConstGen (); |
| ConstEntry.constGen = cgen == null ? noop : cgen; |
| |
| EnumGen egen = genFactory.createEnumGen (); |
| EnumEntry.enumGen = egen == null ? noop : egen; |
| |
| ExceptionGen exgen = genFactory.createExceptionGen (); |
| ExceptionEntry.exceptionGen = exgen == null ? noop : exgen; |
| |
| ForwardGen fgen = genFactory.createForwardGen (); |
| ForwardEntry.forwardGen = fgen == null ? noop : fgen; |
| |
| ForwardValueGen fvgen = genFactory.createForwardValueGen (); |
| ForwardValueEntry.forwardValueGen = fvgen == null ? noop : fvgen; |
| |
| IncludeGen ingen = genFactory.createIncludeGen (); |
| IncludeEntry.includeGen = ingen == null ? noop : ingen; |
| |
| InterfaceGen igen = genFactory.createInterfaceGen (); |
| InterfaceEntry.interfaceGen = igen == null ? noop : igen; |
| |
| ValueGen vgen = genFactory.createValueGen (); |
| ValueEntry.valueGen = vgen == null ? noop : vgen; |
| |
| ValueBoxGen vbgen = genFactory.createValueBoxGen (); |
| ValueBoxEntry.valueBoxGen = vbgen == null ? noop : vbgen; |
| |
| MethodGen mgen = genFactory.createMethodGen (); |
| MethodEntry.methodGen = mgen == null ? noop : mgen; |
| |
| ModuleGen modgen = genFactory.createModuleGen (); |
| ModuleEntry.moduleGen = modgen == null ? noop : modgen; |
| |
| NativeGen ngen = genFactory.createNativeGen (); |
| NativeEntry.nativeGen = ngen == null ? noop : ngen; |
| |
| ParameterGen pgen = genFactory.createParameterGen (); |
| ParameterEntry.parameterGen = pgen == null ? noop : pgen; |
| |
| PragmaGen prgen = genFactory.createPragmaGen (); |
| PragmaEntry.pragmaGen = prgen == null ? noop : prgen; |
| |
| PrimitiveGen primgen = genFactory.createPrimitiveGen (); |
| PrimitiveEntry.primitiveGen = primgen == null ? noop : primgen; |
| |
| SequenceGen seqgen = genFactory.createSequenceGen (); |
| SequenceEntry.sequenceGen = seqgen == null ? noop : seqgen; |
| |
| StringGen strgen = genFactory.createStringGen (); |
| StringEntry.stringGen = strgen == null ? noop : strgen; |
| |
| StructGen sgen = genFactory.createStructGen (); |
| StructEntry.structGen = sgen == null ? noop : sgen; |
| |
| TypedefGen tgen = genFactory.createTypedefGen (); |
| TypedefEntry.typedefGen = tgen == null ? noop : tgen; |
| |
| UnionGen ugen = genFactory.createUnionGen (); |
| UnionEntry.unionGen = ugen == null ? noop : ugen; |
| } // initGenerators |
| |
| /** |
| * Write the version number of this compiler to standard out. |
| **/ |
| protected void displayVersion () |
| { |
| String message = Util.getMessage ("Version.product", Util.getMessage ("Version.number")); |
| System.out.println (message); |
| } |
| |
| /** |
| * This is the repository of emitter arguments. |
| **/ |
| public Arguments arguments = null; |
| /** |
| * This hashtable contains <real name, alias> pairs. It is filled in by |
| * extenders in cases where they wish to override an IDL type name with |
| * some other name. For instance, when mapping to Java, there could be |
| * an overrideNames entry of <"TRUE", "true">. NOTE: Do NOT change this |
| * variable to a new Hash table. Just add elements to it. |
| **/ |
| protected Hashtable overrideNames = new Hashtable (); |
| /** |
| * This is the symbol table. It will be empty until the parse method |
| * executes. If errors are encountered, the state of the symbol table |
| * is undefined. |
| **/ |
| protected Hashtable symbolTable = new Hashtable (); |
| /** |
| * This is a vector of strings of the form "IDLfile" or <IDLfile>. It is |
| * a list of the files included in the given IDL file. It will be empty |
| * until the parse method executes. If errors are encountered, the state |
| * of this vector is undefined. |
| **/ |
| protected Vector includes = new Vector (); |
| /** |
| * This is a vector of IncludeEntry's. It is a list of the files included |
| * in the given IDL file. It mirrors the includes vector. It will be empty |
| * until the parse method executes. If errors are encountered, the state of |
| * this vector is undefined. |
| **/ |
| protected Vector includeEntries = new Vector (); |
| static Noop noop = new Noop (); |
| private GenFactory genFactory = null; |
| private SymtabFactory symtabFactory = null; |
| private ExprFactory exprFactory = null; |
| private Parser parser = null; |
| Preprocessor preprocessor = new Preprocessor (); |
| private NoPragma noPragma = new NoPragma (); |
| private Enumeration emitList = null; |
| private String[] keywords = null; |
| } // class Compile |