/*
* 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:
java com.sun.tools.corba.se.idl.toJava.compile [options] <idl file>
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.
Options:
-i <include path>
- By default, the current directory is scanned for included files.
This option adds another directory. See also Note 1 below.
-d <symbol>
- This is equivalent to the following line in an IDL file:
#define <symbol>
-emitAll
- Emit all types, including those found in #included files.
-v
- Verbose mode.
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:
includes=<path1>;<path2>;...;<pathN>
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.
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.
To Extend the compiler:
You only need to extend the compiler if you want it to generate something
other than what it currently generates.
Step 1 - Implement the generator interfaces:
Each generator interface defines one method: generate (Hashtable, XXXEntry, PrintWriter);
- The Hashtable is the symbol table; each element is a SymtabEntry (or a
subclass of SymtabEntry) and is keyed by its fully qualified name;
- 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.
- 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.
Step 2 - Implement the GenFactory interface:
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).
Step 3 - Extend com.sun.tools.corba.se.idl.Factories:
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.
Step 4 - Extend com.sun.tools.corba.se.idl.Compile:
Your extension of com.sun.tools.corba.se.idl.Compile should contain a minimum of
two methods:
- protected com.sun.tools.corba.se.idl.Factories ()
- This method overrides com.sun.tools.corba.se.idl.Compile.factories and returns your
extension from Step 3.
- public static void main (String[] args)
- This main method must instantiate this class and call its start method.
Given that the extension of Factories is MyFactories, the extension of
Compile could be:
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);
}
}
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:
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);
}
}
}
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.
/**
* Compiler usage:
* <br><br>
*
* {@code 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>{@code -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>{@code -d <symbol>}
* <dd>This is equivalent to the following line in an IDL file: {@code #define <symbol>}
*
* <dt>{@code -emitAll}
* <dd>Emit all types, including those found in #included files.
*
* <dt>{@code -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>{@code
* 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.
/**
* 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.
/**
* 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.
/**
* 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.
/**
* 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.
/**
* 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.
/**
* 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. /**
* This hashtable contains {@code <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 {@code <"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.
/**
* 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. /**
* This is a vector of strings of the form {@code "IDLfile"} or {@code <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.
/**
* 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