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