1 /*
   2  * Copyright (c) 1999, 2007, 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 
  36 package com.sun.tools.corba.se.idl;
  37 
  38 // NOTES:
  39 // -F46082.51<daz> Remove -stateful option. "Stateful interfaces" obsolete.
  40 // -D58319<daz> Add -version option.  Note that this may occur as the last
  41 //  argument on the command-line.
  42 // -F60858.1<daz> Add -corba [level] option.  Accept IDL upto this level, and
  43 //  behave in a "proprietary manner" otherwise.
  44 // -D62023<daz> Add -noWarn option to supress warnings.
  45 
  46 import java.io.DataInputStream;
  47 import java.io.IOException;
  48 import java.util.Hashtable;
  49 import java.util.Properties;
  50 import java.util.Vector;
  51 import java.util.StringTokenizer;
  52 import java.lang.reflect.Modifier;
  53 import java.lang.reflect.Field;
  54 
  55 import com.sun.tools.corba.se.idl.som.cff.FileLocator;
  56 
  57 /**
  58  * This class is responsible for parsing the command line arguments to the
  59  * compiler.  To add new arguments to the compiler, this class must be extended
  60  * and the parseOtherArgs method overridden.
  61  **/
  62 public class Arguments
  63 {
  64   /**
  65    * Method parseOtherArgs() is called when the framework detects arguments
  66    * which are unknown to it.  The default implementation of this method simply
  67    * throws an InvalidArgument exception.  Any overriding implementation
  68    * must check the arguments passed to it for validity and process the
  69    * arguments appropriately.  If it detects an invalid argument, it should
  70    * throw an InvalidArgument exception.  Arguments MUST be of the form
  71    * `/<arg> [<qualifiers>]' or `-<arg> [<qualifiers>]' where <qualifiers>
  72    * is optional (for example, -iC:\includes, `C:\includes' is the qualifier
  73    * for the argument `i').
  74    * @param args The arguments which are unknown by the framework.
  75    * @param properties Environment-style properties collected from the
  76    * file idl.config.
  77    * @exception idl.InvalidArgument if the argument is unknown.
  78    **/
  79   protected void parseOtherArgs (String[] args, Properties properties) throws InvalidArgument
  80   {
  81     if (args.length > 0)
  82       throw new InvalidArgument (args[0]);
  83   } // parseOtherArgs
  84 
  85 
  86     protected void setDebugFlags( String args )
  87     {
  88         StringTokenizer st = new StringTokenizer( args, "," ) ;
  89         while (st.hasMoreTokens()) {
  90             String token = st.nextToken() ;
  91 
  92             // If there is a public boolean data member in this class
  93             // named token + "DebugFlag", set it to true.
  94             try {
  95                 Field fld = this.getClass().getField( token + "DebugFlag" ) ;
  96                 int mod = fld.getModifiers() ;
  97                 if (Modifier.isPublic( mod ) && !Modifier.isStatic( mod ))
  98                     if (fld.getType() == boolean.class)
  99                         fld.setBoolean( this, true ) ;
 100             } catch (Exception exc) {
 101                 // ignore it
 102             }
 103         }
 104     }
 105 
 106     /**
 107     * Collect the command-line parameters.
 108     **/
 109     void parseArgs (String[] args) throws InvalidArgument {
 110         Vector unknownArgs = new Vector ();
 111         int    i           = 0;
 112 
 113         try {
 114             // Process command line parameters
 115             for (i = 0; i < args.length - 1; ++i) {
 116                 String lcArg = args[i].toLowerCase ();
 117                 if (lcArg.charAt (0) != '-' && lcArg.charAt (0) != '/')
 118                     throw new InvalidArgument (args[i]);
 119                 if (lcArg.charAt (0) == '-' ) {
 120                     lcArg = lcArg.substring (1);
 121                 }
 122 
 123                 // Include path
 124                 if (lcArg.equals ("i")) {
 125                     includePaths.addElement (args[++i]);
 126                 } else if (lcArg.startsWith ("i")) {
 127                     includePaths.addElement (args[i].substring (2));
 128                 } else if (lcArg.equals ("v") || lcArg.equals ("verbose")) {
 129                     // Verbose mode
 130                     verbose = true;
 131                 } else if (lcArg.equals ("d")) {
 132                     // Define symbol
 133                     definedSymbols.put (args[++i], "");
 134                 } else if (lcArg.equals( "debug" )) {
 135                     // Turn on debug flags
 136                     setDebugFlags( args[++i] ) ;
 137                 } else if (lcArg.startsWith ("d")) {
 138                     definedSymbols.put (args[i].substring (2), "");
 139                 } else if (lcArg.equals ("emitall")) {
 140                     // Emit bindings for included sources
 141                     emitAll = true;
 142                 } else if (lcArg.equals ("keep")) {
 143                     // Keep old files
 144                     keepOldFiles = true;
 145                 } else if (lcArg.equals ("nowarn")) {
 146                     // <d62023> Suppress warnings
 147                     noWarn = true;
 148                 } else if (lcArg.equals ("trace")) {
 149                     // Allow tracing.
 150                     Runtime.getRuntime ().traceMethodCalls (true);
 151                 }
 152                 // <f46082.51> Remove -stateful feature.
 153                 //else if (lcArg.equals ("stateful"))
 154                 //{
 155                 //  Emit stateful bindings.
 156                 //  parseStateful = true;
 157                 //}
 158                 // CPPModule
 159                 else if ( lcArg.equals ("cppmodule")) {
 160                     cppModule = true;
 161                 } else if (lcArg.equals ("version"))  {
 162                     // Version
 163                     versionRequest = true;
 164                 } else if (lcArg.equals ("corba"))  {
 165                     // CORBA level
 166                     if (i + 1 >= args.length)
 167                         throw new InvalidArgument (args[i]);
 168                     String level = args[++i];
 169                     if (level.charAt (0) == '-')
 170                         throw new InvalidArgument (args[i - 1]);
 171                     try {
 172                         corbaLevel = new Float (level).floatValue ();
 173                     } catch (NumberFormatException e) {
 174                         throw new InvalidArgument (args[i]);
 175                     }
 176                 } else {
 177                     unknownArgs.addElement (args[i]);
 178                     ++i;
 179                     while (i < (args.length - 1) &&
 180                         args[i].charAt (0) != '-' &&
 181                         args[i].charAt (0) != '/') {
 182                         unknownArgs.addElement (args[i++]);
 183                     }
 184                     --i;
 185                 }
 186             }
 187         } catch (ArrayIndexOutOfBoundsException e) {
 188             // If there is any array indexing problem, it is probably
 189             // because the qualifier on the last argument is missing.
 190             // Report that this last argument is invalid.
 191             throw new InvalidArgument (args[args.length - 1]);
 192         }
 193 
 194         // <d57319>
 195         // The last argument is the file argument or "-version", which may
 196         // be specified without a file argument.
 197         if (i == args.length - 1) {
 198             if (args[i].toLowerCase ().equals ("-version"))
 199                 versionRequest = true;
 200             else
 201                 file = args[i];
 202         } else
 203             throw new InvalidArgument ();
 204 
 205         // Get and process the idl.config file.
 206         Properties props = new Properties ();
 207         try {
 208           DataInputStream stream = FileLocator.locateFileInClassPath ("idl.config");
 209           props.load (stream);
 210           addIncludePaths (props);
 211         } catch (IOException e) {
 212         }
 213 
 214         // Call parseOtherArgs.  By default, if there are unknown args,
 215         // InvalidArgument is called.  A call to parseOtherArgs is useful
 216         // only when this framework has been extended.
 217         String[] otherArgs;
 218         if (unknownArgs.size () > 0) {
 219             otherArgs = new String[unknownArgs.size ()];
 220             unknownArgs.copyInto (otherArgs);
 221         } else
 222             otherArgs = new String[0];
 223 
 224         parseOtherArgs (otherArgs, props);
 225     } // parseArgs
 226 
 227   /**
 228    *
 229    **/
 230   private void addIncludePaths (Properties props)
 231   {
 232     String paths = props.getProperty ("includes");
 233     if (paths != null)
 234     {
 235       String separator = System.getProperty ("path.separator");
 236       int end = -separator.length (); // so the first pass paths == original paths
 237       do
 238       {
 239         paths = paths.substring (end + separator.length ());
 240         end = paths.indexOf (separator);
 241         if (end < 0)
 242           end = paths.length ();
 243         includePaths.addElement (paths.substring (0, end));
 244       }
 245       while (end != paths.length ());
 246     }
 247   } // addIncludePaths
 248 
 249   /**
 250    * The name of the IDL file.
 251    **/
 252   public String file = null;
 253 
 254   /**
 255    * True if the user wishes to see processing remarks.
 256    **/
 257   public boolean verbose = false;
 258 
 259   /**
 260    * If this is true, then existing files should not be overwritten
 261    * by the compiler.
 262    **/
 263   public boolean keepOldFiles = false;
 264 
 265   /**
 266    * If this is true, then the types in all included files are also emitted.
 267    **/
 268   public boolean emitAll = false;
 269 
 270   // <f46082.51> Remove -stateful feature.
 271   ///**
 272   // * If this is true, then stateful interfaces (for the Objects-by-Value
 273   // * proposal) are allowed.  This is not yet a standard, so it must
 274   // * explicitly be called for by setting the -stateful argument to the
 275   // * compiler.  If -stateful does not appear on the command line, then
 276   // * the IDL will be parsed according to the standards.
 277   // **/
 278   //public boolean   parseStateful  = false;
 279   /**
 280    * A list of strings, each of which is a path from which included files
 281    * are found.
 282    **/
 283   public Vector includePaths = new Vector ();
 284 
 285   /**
 286    * A table of defined symbols.  The key is the symbol name; the value
 287    * (if any) is the replacement value for the symbol.
 288    **/
 289   public Hashtable definedSymbols = new Hashtable ();
 290 
 291   /**
 292    * <f46082.46.01> True if new module entries are created for each
 293    * re-opened module.
 294    **/
 295   public boolean cppModule = false;
 296 
 297   /**
 298    * -version option.
 299    **/
 300   public boolean versionRequest = false;  // <D58319>
 301 
 302   // <f60858.1> Specify the maximal level of the CORBA spec. the parser
 303   // will support.
 304   //
 305   // NOTE: For BOSS 3.0, specify at 2.2.  Raise to greater value in future
 306   //       releases.
 307   /**
 308    * -corba [level] option, where [level] is a floating-point number indicating
 309    * the maximal level of CORBA IDL the parser framework can accept.
 310    **/
 311   public float corbaLevel = 2.2f;
 312   // <d62023>
 313   /**
 314    * -noWarn option.  Suppress warnings when true.
 315    **/
 316   public boolean noWarn = false;  // Issue warnings by default.
 317 
 318     // Currently defined debug flags.  Any additions must be called xxxDebugFlag.
 319     // All debug flags must be public boolean types.
 320     // These are set by passing the flag -ORBDebug x,y,z in the ORB init args.
 321     // Note that x,y,z must not contain spaces.
 322     public boolean scannerDebugFlag = false ;
 323     public boolean tokenDebugFlag = false ;
 324 
 325 } // class Arguments