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 36 package 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 42 import java.io.FileNotFoundException; 43 import java.io.IOException; 44 import java.util.Enumeration; 45 import java.util.Hashtable; 46 import java.util.Vector; 47 48 import com.sun.tools.corba.se.idl.constExpr.ExprFactory; 49 import 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 <idl file> 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 <include path> 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 <symbol> 70 * <dd>This is equivalent to the following line in an IDL file: #define <symbol> 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 **/ 214 public 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