001: /*
002: * Copyright 1999-2004 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025: /*
026: * COMPONENT_NAME: idl.parser
027: *
028: * ORIGINS: 27
029: *
030: * Licensed Materials - Property of IBM
031: * 5639-D57 (C) COPYRIGHT International Business Machines Corp. 1997, 1999
032: * RMI-IIOP v1.0
033: *
034: * @(#)Compile.java 1.21 07/05/05
035: */
036:
037: package com.sun.tools.corba.se.idl;
038:
039: // NOTES:
040: // -D56351<daz> Update computation of RepositoryIDs to CORBA 2.3 (see spec.).
041: // -D58319<daz> Display version info. for -version option.
042:
043: import java.io.FileNotFoundException;
044: import java.io.IOException;
045: import java.util.Enumeration;
046: import java.util.Hashtable;
047: import java.util.Vector;
048:
049: import com.sun.tools.corba.se.idl.constExpr.ExprFactory;
050: import com.sun.tools.corba.se.idl.constExpr.DefaultExprFactory;
051:
052: /**
053: * Compiler usage:
054: * <br><br>
055: *
056: * java com.sun.tools.corba.se.idl.toJava.compile [options] <idl file>
057: * <br><br>
058: *
059: * where <idl file> is the name of a file containing IDL definitions,
060: * and [options] is any combination of the options listed below. The options
061: * and the idl file name can appear in any order.
062: * <br><br>
063: *
064: * Options:
065: * <dl>
066: * <dt>-i <include path>
067: * <dd>By default, the current directory is scanned for included files.
068: * This option adds another directory. See also Note 1 below.
069: *
070: * <dt>-d <symbol>
071: * <dd>This is equivalent to the following line in an IDL file: #define <symbol>
072: *
073: * <dt>-emitAll
074: * <dd>Emit all types, including those found in #included files.
075: *
076: * <dt>-v
077: * <dd>Verbose mode.
078: * </dl>
079: *
080: * Note 1: If you have an include path or paths that you will always be using,
081: * it can get tedious putting these on the command with the -i option all the
082: * time. Instead, these can be placed into a config file called idl.config.
083: * This file must be in the CLASSPATH. The format of the includes line is:
084: *
085: * <pre>
086: * includes=<path1>;<path2>;...;<pathN>
087: * </pre>
088: *
089: * Note that the path separator character, here shown as a semicolon, is
090: * machine dependent. For instance, on Windows 95 this character is a
091: * semicolon, on UNIX it is a colon.
092: *
093: * <p>
094: * Note 2: If you are directly invoking the main method on this class (not
095: * a subclass), then it will only check that the IDL file is syntactically
096: * correct. It does not generate any files. Only extensions to this
097: * framework generate files, therefore an extension must be invoked if you
098: * want files to be generated.
099: * <br><br>
100: *
101: * To Extend the compiler:
102: * <br><br>
103: *
104: * You only need to extend the compiler if you want it to generate something
105: * other than what it currently generates.
106: * <br><br>
107: *
108: * Step 1 - Implement the generator interfaces:
109: * <br><br>
110: *
111: * Each generator interface defines one method: generate (Hashtable, XXXEntry, PrintWriter);
112: * <br>
113: * - The Hashtable is the symbol table; each element is a SymtabEntry (or a
114: * subclass of SymtabEntry) and is keyed by its fully qualified name;
115: * <br>
116: * - XXXEntry is the appropriate entry for the type to be generated. For
117: * example: AttributeGen defines generate (Hashtable, AttributeEntry, PrintWriter);
118: * ConstGen defines generate (Hashtable, ConstEntry, PrintWriter); etc.
119: * <br>
120: * - The PrintWriter is a stream to the file being generated. For the
121: * generators called by the compiler framework, this will be null. The
122: * generator is responsible for creating and opening files. But for
123: * generators that are called by other generators - for instance,
124: * MethodGen.generate will most likely be called by InterfaceGen.generate -
125: * this parameter is provided so that the proper file can be written to.
126: * <br><br>
127: *
128: * Step 2 - Implement the GenFactory interface:
129: * <br><br>
130: *
131: * All of the generators implemented in Step 1 must be created somehow. There
132: * is an interface for a factory, GenFactory, which must be implemented. The
133: * name of this factory must be set in the extension to the Compile class (see
134: * Step 3, below).
135: * <br><br>
136: *
137: * Step 3 - Extend com.sun.tools.corba.se.idl.Factories:
138: * <br><br>
139: *
140: * Extend com.sun.tools.corba.se.idl.Factories and override the method genFactory. This
141: * method must return an instance of the factory which you implemented in
142: * step 2. Your extension of this class may also do more, this is only the
143: * minimum. See com.sun.tools.corba.se.idl.Factories for more information.
144: * <br><br>
145: *
146: * Step 4 - Extend com.sun.tools.corba.se.idl.Compile:
147: * <br><br>
148: *
149: * Your extension of com.sun.tools.corba.se.idl.Compile should contain a minimum of
150: * two methods:
151: * <dl>
152: * <dt>protected com.sun.tools.corba.se.idl.Factories ()
153: * <dd>This method overrides com.sun.tools.corba.se.idl.Compile.factories and returns your
154: * extension from Step 3.
155: *
156: * <dt>public static void main (String[] args)
157: * <dd>This main method must instantiate this class and call its start method.
158: * </dl>
159: *
160: * Given that the extension of Factories is MyFactories, the extension of
161: * Compile could be:
162: *
163: * <pre>
164: * public class MyCompile extends com.sun.tools.corba.se.idl.Compile
165: * {
166: * protected com.sun.tools.corba.se.idl.Factories factories ()
167: * {
168: * return new MyFactories ();
169: * }
170: * public static void main (String[] args)
171: * {
172: * MyCompile compile = new MyCompile ();
173: * compile.start (args);
174: * }
175: * }
176: * </pre>
177: *
178: * If you would like a bit more control over the processing of the framework,
179: * you can replace compile.start with what it calls. But then you also have
180: * to handle the exceptions which start handles for you:
181: * <pre>
182: * public class MyCompile extends com.sun.tools.corba.se.idl.Compile
183: * {
184: * ...
185: *
186: * public static void main (String[] args)
187: * {
188: * MyCompile compile = new MyCompile ();
189: * try
190: * {
191: * compile.init (args);
192: * java.util.Enumeration emitList = compile.parse ();
193: * compile.generate ();
194: * }
195: * catch (com.sun.tools.corba.se.idl.InvalidArgument e)
196: * {
197: * System.err.println (e);
198: * }
199: * catch (java.io.IOException e)
200: * {
201: * System.err.println (e);
202: * }
203: * }
204: * }
205: * </pre>
206: *
207: * Note that compile.parse returns an enumeration. This enumerates the
208: * SymtabEntry's which should be generated. If the parse method detects
209: * errors, it returns null. Note that you do not have to check that
210: * `emitList' is valid before calling generate (that's done internally), but
211: * if you do any processing between parse and generate, emitList should be
212: * checked before executing that code.
213: * <br><br>
214: **/
215: public class Compile {
216: public Compile() {
217: noPragma.init(preprocessor);
218: preprocessor.registerPragma(noPragma);
219:
220: // <d41197> Reset static variables to allow parsing multiple sources.
221: // DO NOT reset SymtabEntry.maxKey because it crashes IDLC.
222: ParseException.detected = false;
223: SymtabEntry.includeStack = new java.util.Stack();
224: SymtabEntry.setEmit = true;
225: //SymtabEntry.maxKey = -1;
226: Parser.repIDStack = new java.util.Stack(); // <d56351>
227: } // ctor
228:
229: public static void main(String[] args) {
230: (new Compile()).start(args);
231: } // main
232:
233: protected Factories factories() {
234: return new Factories();
235: } // genFactoryName
236:
237: protected void registerPragma(PragmaHandler handler) {
238: handler.init(preprocessor);
239: preprocessor.registerPragma(handler);
240: } // registerPragma
241:
242: /**
243: * Initialize the framework.
244: **/
245: protected void init(String[] args) throws InvalidArgument {
246: initFactories();
247: arguments.parseArgs(args);
248: initGenerators();
249: parser = new Parser(preprocessor, arguments, overrideNames,
250: symbolTable, symtabFactory, exprFactory, keywords);
251: preprocessor.init(parser);
252: parser.includes = includes;
253: parser.includeEntries = includeEntries;
254: } // init
255:
256: /**
257: * Parse the IDL file and return an enumeration of the symbols to be
258: * generated. All elements of the Enumeration will be extensions of
259: * SymtabEntry. If any errors were encountered during parsing, null
260: * will be returned.
261: **/
262: protected Enumeration parse() throws IOException {
263: if (arguments.verbose)
264: System.out.println(Util.getMessage("Compile.parsing",
265: arguments.file));
266: parser.parse(arguments.file);
267: if (!ParseException.detected) {
268: parser.forwardEntryCheck();
269:
270: // <46082.03> Revert to "IDL:"-style (i.e., regular) repository ID.
271: //parser.updateRepositoryIds();
272: }
273: if (arguments.verbose)
274: System.out.println(Util.getMessage("Compile.parseDone",
275: arguments.file));
276: if (ParseException.detected) {
277: symbolTable = null;
278: emitList = null;
279: } else {
280: symbolTable = parser.symbolTable;
281: emitList = parser.emitList.elements();
282: }
283: return emitList;
284: } // parse
285:
286: /**
287: * Invoke the generators.
288: **/
289: protected void generate() throws IOException {
290: /*
291: // print the symbol table
292: Enumeration v = parser.symbolTable.elements ();
293: Enumeration k = parser.symbolTable.keys ();
294: while (k.hasMoreElements ())
295: System.out.println (k.nextElement () + ": " + v.nextElement ());
296: */
297: if (ParseException.detected)
298: emitList = null;
299: else
300: emitList = parser.emitList.elements();
301: if (emitList != null) {
302: // Emit the output files for all of the types in the IDL file
303: if (arguments.verbose)
304: System.out.println();
305: while (emitList.hasMoreElements()) {
306: SymtabEntry entry = (SymtabEntry) emitList
307: .nextElement();
308: if (arguments.verbose)
309: if (entry.generator() instanceof Noop)
310: ; // Nothing will be generated, so don't say so.
311: else if (entry.module().equals(""))
312: System.out.println(Util.getMessage(
313: "Compile.generating", entry.name()));
314: else
315: System.out.println(Util.getMessage(
316: "Compile.generating", entry.module()
317: + '/' + entry.name()));
318: entry.generate(symbolTable, null);
319: if (arguments.verbose)
320: if (entry.generator() instanceof Noop)
321: ; // Nothing will be generated, so don't say so.
322: else if (entry.module().equals(""))
323: System.out.println(Util.getMessage(
324: "Compile.genDone", entry.name()));
325: else
326: System.out.println(Util.getMessage(
327: "Compile.genDone", entry.module() + '/'
328: + entry.name()));
329: }
330: }
331: } // generate
332:
333: /**
334: * Start the parse/code generation process. This method calls init,
335: * parse, generate. If more control is desired, rather than call start,
336: * those three methods could be called explicitly.
337: **/
338: public void start(String[] args) {
339: try {
340: init(args);
341: if (arguments.versionRequest) // <d59319>
342: displayVersion();
343: else {
344: parse();
345: generate();
346: }
347: } catch (InvalidArgument e) {
348: System.err.println(e);
349: } catch (IOException e) {
350: System.err.println(e);
351: }
352: } // start
353:
354: private void initFactories() {
355: // Get the factories.
356: Factories factories = factories();
357: if (factories == null)
358: factories = new Factories();
359:
360: // Get the argument processor from the factories.
361: Arguments tmpArgs = factories.arguments();
362: if (tmpArgs == null)
363: arguments = new Arguments();
364: else
365: arguments = tmpArgs;
366:
367: // Get the symbol table entry factory from the factories.
368: SymtabFactory tmpSTF = factories.symtabFactory();
369: if (tmpSTF == null)
370: symtabFactory = new DefaultSymtabFactory();
371: else
372: symtabFactory = tmpSTF;
373:
374: // Get the expression factory from the factories.
375: ExprFactory tmpExpF = factories.exprFactory();
376: if (tmpExpF == null)
377: exprFactory = new DefaultExprFactory();
378: else
379: exprFactory = tmpExpF;
380:
381: // Get the generator factory from the factories.
382: GenFactory tmpGenF = factories.genFactory();
383: if (tmpGenF == null)
384: genFactory = noop;
385: else
386: genFactory = tmpGenF;
387:
388: // Get the language keywords.
389: keywords = factories.languageKeywords();
390: if (keywords == null)
391: keywords = new String[0];
392: } // initFactories
393:
394: private void initGenerators() {
395: AttributeGen agen = genFactory.createAttributeGen();
396: AttributeEntry.attributeGen = agen == null ? noop : agen;
397:
398: ConstGen cgen = genFactory.createConstGen();
399: ConstEntry.constGen = cgen == null ? noop : cgen;
400:
401: EnumGen egen = genFactory.createEnumGen();
402: EnumEntry.enumGen = egen == null ? noop : egen;
403:
404: ExceptionGen exgen = genFactory.createExceptionGen();
405: ExceptionEntry.exceptionGen = exgen == null ? noop : exgen;
406:
407: ForwardGen fgen = genFactory.createForwardGen();
408: ForwardEntry.forwardGen = fgen == null ? noop : fgen;
409:
410: ForwardValueGen fvgen = genFactory.createForwardValueGen();
411: ForwardValueEntry.forwardValueGen = fvgen == null ? noop
412: : fvgen;
413:
414: IncludeGen ingen = genFactory.createIncludeGen();
415: IncludeEntry.includeGen = ingen == null ? noop : ingen;
416:
417: InterfaceGen igen = genFactory.createInterfaceGen();
418: InterfaceEntry.interfaceGen = igen == null ? noop : igen;
419:
420: ValueGen vgen = genFactory.createValueGen();
421: ValueEntry.valueGen = vgen == null ? noop : vgen;
422:
423: ValueBoxGen vbgen = genFactory.createValueBoxGen();
424: ValueBoxEntry.valueBoxGen = vbgen == null ? noop : vbgen;
425:
426: MethodGen mgen = genFactory.createMethodGen();
427: MethodEntry.methodGen = mgen == null ? noop : mgen;
428:
429: ModuleGen modgen = genFactory.createModuleGen();
430: ModuleEntry.moduleGen = modgen == null ? noop : modgen;
431:
432: NativeGen ngen = genFactory.createNativeGen();
433: NativeEntry.nativeGen = ngen == null ? noop : ngen;
434:
435: ParameterGen pgen = genFactory.createParameterGen();
436: ParameterEntry.parameterGen = pgen == null ? noop : pgen;
437:
438: PragmaGen prgen = genFactory.createPragmaGen();
439: PragmaEntry.pragmaGen = prgen == null ? noop : prgen;
440:
441: PrimitiveGen primgen = genFactory.createPrimitiveGen();
442: PrimitiveEntry.primitiveGen = primgen == null ? noop : primgen;
443:
444: SequenceGen seqgen = genFactory.createSequenceGen();
445: SequenceEntry.sequenceGen = seqgen == null ? noop : seqgen;
446:
447: StringGen strgen = genFactory.createStringGen();
448: StringEntry.stringGen = strgen == null ? noop : strgen;
449:
450: StructGen sgen = genFactory.createStructGen();
451: StructEntry.structGen = sgen == null ? noop : sgen;
452:
453: TypedefGen tgen = genFactory.createTypedefGen();
454: TypedefEntry.typedefGen = tgen == null ? noop : tgen;
455:
456: UnionGen ugen = genFactory.createUnionGen();
457: UnionEntry.unionGen = ugen == null ? noop : ugen;
458: } // initGenerators
459:
460: /**
461: * Write the version number of this compiler to standard out.
462: **/
463: protected void displayVersion() {
464: String message = Util.getMessage("Version.product", Util
465: .getMessage("Version.number"));
466: System.out.println(message);
467: }
468:
469: /**
470: * This is the repository of emitter arguments.
471: **/
472: public Arguments arguments = null;
473: /**
474: * This hashtable contains <real name, alias> pairs. It is filled in by
475: * extenders in cases where they wish to override an IDL type name with
476: * some other name. For instance, when mapping to Java, there could be
477: * an overrideNames entry of <"TRUE", "true">. NOTE: Do NOT change this
478: * variable to a new Hash table. Just add elements to it.
479: **/
480: protected Hashtable overrideNames = new Hashtable();
481: /**
482: * This is the symbol table. It will be empty until the parse method
483: * executes. If errors are encountered, the state of the symbol table
484: * is undefined.
485: **/
486: protected Hashtable symbolTable = new Hashtable();
487: /**
488: * This is a vector of strings of the form "IDLfile" or <IDLfile>. It is
489: * a list of the files included in the given IDL file. It will be empty
490: * until the parse method executes. If errors are encountered, the state
491: * of this vector is undefined.
492: **/
493: protected Vector includes = new Vector();
494: /**
495: * This is a vector of IncludeEntry's. It is a list of the files included
496: * in the given IDL file. It mirrors the includes vector. It will be empty
497: * until the parse method executes. If errors are encountered, the state of
498: * this vector is undefined.
499: **/
500: protected Vector includeEntries = new Vector();
501: static Noop noop = new Noop();
502: private GenFactory genFactory = null;
503: private SymtabFactory symtabFactory = null;
504: private ExprFactory exprFactory = null;
505: private Parser parser = null;
506: Preprocessor preprocessor = new Preprocessor();
507: private NoPragma noPragma = new NoPragma();
508: private Enumeration emitList = null;
509: private String[] keywords = null;
510: } // class Compile
|