/* * 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