J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 1 | /* |
Kelly O'Hair | fe008ae | 2010-05-25 15:58:33 -0700 | [diff] [blame] | 2 | * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved. |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 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 |
Kelly O'Hair | fe008ae | 2010-05-25 15:58:33 -0700 | [diff] [blame] | 7 | * published by the Free Software Foundation. Oracle designates this |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 8 | * particular file as subject to the "Classpath" exception as provided |
Kelly O'Hair | fe008ae | 2010-05-25 15:58:33 -0700 | [diff] [blame] | 9 | * by Oracle in the LICENSE file that accompanied this code. |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 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 | * |
Kelly O'Hair | fe008ae | 2010-05-25 15:58:33 -0700 | [diff] [blame] | 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. |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 24 | */ |
| 25 | |
| 26 | package sun.tools.javac; |
| 27 | |
| 28 | import sun.tools.java.*; |
| 29 | import sun.tools.util.CommandLine; |
| 30 | // JCOV |
| 31 | import sun.tools.asm.Assembler; |
| 32 | // end JCOV |
| 33 | |
| 34 | import java.util.*; |
| 35 | import java.io.*; |
| 36 | import java.text.MessageFormat; |
| 37 | |
| 38 | /** |
| 39 | * Main program of the Java compiler |
| 40 | * |
| 41 | * WARNING: The contents of this source file are not part of any |
| 42 | * supported API. Code that depends on them does so at its own risk: |
| 43 | * they are subject to change or removal without notice. |
| 44 | * |
| 45 | * @deprecated As of J2SE 1.3, the preferred way to compile Java |
| 46 | * language sources is by using the new compiler, |
| 47 | * com.sun.tools.javac.Main. |
| 48 | */ |
| 49 | @Deprecated |
| 50 | public |
| 51 | class Main implements Constants { |
| 52 | /** |
| 53 | * Name of the program. |
| 54 | */ |
| 55 | String program; |
| 56 | |
| 57 | /** |
| 58 | * The stream where error message are printed. |
| 59 | */ |
| 60 | OutputStream out; |
| 61 | |
| 62 | /** |
| 63 | * Constructor. |
| 64 | */ |
| 65 | public Main(OutputStream out, String program) { |
| 66 | this.out = out; |
| 67 | this.program = program; |
| 68 | } |
| 69 | |
| 70 | /** |
| 71 | * Exit status. |
| 72 | * We introduce a separate integer status variable, and do not alter the |
| 73 | * convention that 'compile' returns a boolean true upon a successful |
| 74 | * compilation with no errors. (JavaTest relies on this.) |
| 75 | */ |
| 76 | |
| 77 | public static final int EXIT_OK = 0; // Compilation completed with no errors. |
| 78 | public static final int EXIT_ERROR = 1; // Compilation completed but reported errors. |
| 79 | public static final int EXIT_CMDERR = 2; // Bad command-line arguments and/or switches. |
| 80 | public static final int EXIT_SYSERR = 3; // System error or resource exhaustion. |
| 81 | public static final int EXIT_ABNORMAL = 4; // Compiler terminated abnormally. |
| 82 | |
| 83 | private int exitStatus; |
| 84 | |
| 85 | public int getExitStatus() { |
| 86 | return exitStatus; |
| 87 | } |
| 88 | |
| 89 | public boolean compilationPerformedSuccessfully() { |
| 90 | return exitStatus == EXIT_OK || exitStatus == EXIT_ERROR; |
| 91 | } |
| 92 | |
| 93 | public boolean compilationReportedErrors () { |
| 94 | return exitStatus != EXIT_OK; |
| 95 | } |
| 96 | |
| 97 | /** |
| 98 | * Output a message. |
| 99 | */ |
| 100 | private void output(String msg) { |
| 101 | PrintStream out = |
| 102 | this.out instanceof PrintStream ? (PrintStream)this.out |
| 103 | : new PrintStream(this.out, true); |
| 104 | out.println(msg); |
| 105 | } |
| 106 | |
| 107 | /** |
| 108 | * Top level error message. This method is called when the |
| 109 | * environment could not be set up yet. |
| 110 | */ |
| 111 | private void error(String msg) { |
| 112 | exitStatus = EXIT_CMDERR; |
| 113 | output(getText(msg)); |
| 114 | } |
| 115 | |
| 116 | private void error(String msg, String arg1) { |
| 117 | exitStatus = EXIT_CMDERR; |
| 118 | output(getText(msg, arg1)); |
| 119 | } |
| 120 | |
| 121 | private void error(String msg, String arg1, String arg2) { |
| 122 | exitStatus = EXIT_CMDERR; |
| 123 | output(getText(msg, arg1, arg2)); |
| 124 | } |
| 125 | |
| 126 | /** |
| 127 | * Print usage message and make exit status an error. |
| 128 | * Note: 'javac' invoked without any arguments is considered |
| 129 | * be an error. |
| 130 | */ |
| 131 | public void usage_error() { |
| 132 | error("main.usage", program); |
| 133 | } |
| 134 | |
| 135 | private static ResourceBundle messageRB; |
| 136 | |
| 137 | /** |
| 138 | * Initialize ResourceBundle |
| 139 | */ |
| 140 | static void initResource() { |
| 141 | try { |
| 142 | messageRB = |
| 143 | ResourceBundle.getBundle("sun.tools.javac.resources.javac"); |
| 144 | } catch (MissingResourceException e) { |
| 145 | throw new Error("Fatal: Resource for javac is missing"); |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | /** |
| 150 | * get and format message string from resource |
| 151 | */ |
| 152 | public static String getText(String key) { |
| 153 | return getText(key, (String)null); |
| 154 | } |
| 155 | |
| 156 | public static String getText(String key, int num) { |
| 157 | return getText(key, Integer.toString(num)); |
| 158 | } |
| 159 | |
| 160 | public static String getText(String key, String fixed) { |
| 161 | return getText(key, fixed, null); |
| 162 | } |
| 163 | |
| 164 | public static String getText(String key, String fixed1, String fixed2) { |
| 165 | return getText(key, fixed1, fixed2, null); |
| 166 | } |
| 167 | |
| 168 | public static String getText(String key, String fixed1, |
| 169 | String fixed2, String fixed3) { |
| 170 | if (messageRB == null) { |
| 171 | initResource(); |
| 172 | } |
| 173 | try { |
| 174 | String message = messageRB.getString(key); |
| 175 | return MessageFormat.format(message, fixed1, fixed2, fixed3); |
| 176 | } catch (MissingResourceException e) { |
| 177 | if (fixed1 == null) fixed1 = "null"; |
| 178 | if (fixed2 == null) fixed2 = "null"; |
| 179 | if (fixed3 == null) fixed3 = "null"; |
| 180 | String message = "JAVAC MESSAGE FILE IS BROKEN: key={0}, arguments={1}, {2}, {3}"; |
| 181 | return MessageFormat.format(message, key, fixed1, fixed2, fixed3); |
| 182 | } |
| 183 | } |
| 184 | |
| 185 | // What major and minor version numbers to use for the -target flag. |
| 186 | // This should grow every time the minor version number accepted by |
| 187 | // the VM is incremented. |
| 188 | private static final String[] releases = { "1.1", "1.2", "1.3", "1.4" }; |
| 189 | private static final short[] majorVersions = { 45, 46, 47, 48 }; |
| 190 | private static final short[] minorVersions = { 3, 0, 0, 0 }; |
| 191 | |
| 192 | /** |
| 193 | * Run the compiler |
| 194 | */ |
Joe Darcy | 002e08e | 2014-04-10 08:43:46 -0700 | [diff] [blame] | 195 | @SuppressWarnings("fallthrough") |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 196 | public synchronized boolean compile(String argv[]) { |
| 197 | String sourcePathArg = null; |
| 198 | String classPathArg = null; |
| 199 | String sysClassPathArg = null; |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 200 | boolean verbosePath = false; |
| 201 | |
| 202 | String targetArg = null; |
| 203 | short majorVersion = JAVA_DEFAULT_VERSION; |
| 204 | short minorVersion = JAVA_DEFAULT_MINOR_VERSION; |
| 205 | |
| 206 | File destDir = null; |
| 207 | //JCOV |
| 208 | File covFile = null; |
| 209 | String optJcov = "-Xjcov"; |
| 210 | String optJcovFile = "-Xjcov:file="; |
| 211 | //end JCOV |
| 212 | int flags = F_WARNINGS | F_DEBUG_LINES | F_DEBUG_SOURCE; |
| 213 | long tm = System.currentTimeMillis(); |
Neil Toda | 8c6d88b | 2014-07-31 17:01:24 -0700 | [diff] [blame] | 214 | Vector<String> v = new Vector<>(); |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 215 | boolean nowrite = false; |
| 216 | String props = null; |
| 217 | String encoding = null; |
| 218 | |
| 219 | // These flags are used to make sure conflicting -O and -g |
| 220 | // options aren't given. |
| 221 | String prior_g = null; |
| 222 | String prior_O = null; |
| 223 | |
| 224 | exitStatus = EXIT_OK; |
| 225 | |
| 226 | // Pre-process command line for @file arguments |
| 227 | try { |
| 228 | argv = CommandLine.parse(argv); |
| 229 | } catch (FileNotFoundException e) { |
| 230 | error("javac.err.cant.read", e.getMessage()); |
| 231 | System.exit(1); |
| 232 | } catch (IOException e) { |
| 233 | e.printStackTrace(); |
| 234 | System.exit(1); |
| 235 | } |
| 236 | |
| 237 | // Parse arguments |
| 238 | for (int i = 0 ; i < argv.length ; i++) { |
| 239 | if (argv[i].equals("-g")) { |
| 240 | if (prior_g!=null && !(prior_g.equals("-g"))) |
| 241 | error("main.conflicting.options", prior_g, "-g"); |
| 242 | prior_g = "-g"; |
| 243 | flags |= F_DEBUG_LINES; |
| 244 | flags |= F_DEBUG_VARS; |
| 245 | flags |= F_DEBUG_SOURCE; |
| 246 | } else if (argv[i].equals("-g:none")) { |
| 247 | if (prior_g!=null && !(prior_g.equals("-g:none"))) |
| 248 | error("main.conflicting.options", prior_g, "-g:none"); |
| 249 | prior_g = "-g:none"; |
| 250 | flags &= ~F_DEBUG_LINES; |
| 251 | flags &= ~F_DEBUG_VARS; |
| 252 | flags &= ~F_DEBUG_SOURCE; |
| 253 | } else if (argv[i].startsWith("-g:")) { |
| 254 | // We choose to have debugging options conflict even |
| 255 | // if they amount to the same thing (for example, |
| 256 | // -g:source,lines and -g:lines,source). However, multiple |
| 257 | // debugging options are allowed if they are textually |
| 258 | // identical. |
| 259 | if (prior_g!=null && !(prior_g.equals(argv[i]))) |
| 260 | error("main.conflicting.options", prior_g, argv[i]); |
| 261 | prior_g = argv[i]; |
| 262 | String args = argv[i].substring("-g:".length()); |
| 263 | flags &= ~F_DEBUG_LINES; |
| 264 | flags &= ~F_DEBUG_VARS; |
| 265 | flags &= ~F_DEBUG_SOURCE; |
| 266 | while (true) { |
| 267 | if (args.startsWith("lines")) { |
| 268 | flags |= F_DEBUG_LINES; |
| 269 | args = args.substring("lines".length()); |
| 270 | } else if (args.startsWith("vars")) { |
| 271 | flags |= F_DEBUG_VARS; |
| 272 | args = args.substring("vars".length()); |
| 273 | } else if (args.startsWith("source")) { |
| 274 | flags |= F_DEBUG_SOURCE; |
| 275 | args = args.substring("source".length()); |
| 276 | } else { |
| 277 | error("main.bad.debug.option",argv[i]); |
| 278 | usage_error(); |
| 279 | return false; // Stop processing now |
| 280 | } |
| 281 | if (args.length() == 0) break; |
| 282 | if (args.startsWith(",")) |
| 283 | args = args.substring(",".length()); |
| 284 | } |
| 285 | } else if (argv[i].equals("-O")) { |
| 286 | // -O is accepted for backward compatibility, but |
| 287 | // is no longer effective. Use the undocumented |
| 288 | // -XO option to get the old behavior. |
| 289 | if (prior_O!=null && !(prior_O.equals("-O"))) |
| 290 | error("main.conflicting.options", prior_O, "-O"); |
| 291 | prior_O = "-O"; |
| 292 | } else if (argv[i].equals("-nowarn")) { |
| 293 | flags &= ~F_WARNINGS; |
| 294 | } else if (argv[i].equals("-deprecation")) { |
| 295 | flags |= F_DEPRECATION; |
| 296 | } else if (argv[i].equals("-verbose")) { |
| 297 | flags |= F_VERBOSE; |
| 298 | } else if (argv[i].equals("-nowrite")) { |
| 299 | nowrite = true; |
| 300 | } else if (argv[i].equals("-classpath")) { |
| 301 | if ((i + 1) < argv.length) { |
| 302 | if (classPathArg!=null) { |
| 303 | error("main.option.already.seen","-classpath"); |
| 304 | } |
| 305 | classPathArg = argv[++i]; |
| 306 | } else { |
| 307 | error("main.option.requires.argument","-classpath"); |
| 308 | usage_error(); |
| 309 | return false; // Stop processing now |
| 310 | } |
| 311 | } else if (argv[i].equals("-sourcepath")) { |
| 312 | if ((i + 1) < argv.length) { |
| 313 | if (sourcePathArg != null) { |
| 314 | error("main.option.already.seen","-sourcepath"); |
| 315 | } |
| 316 | sourcePathArg = argv[++i]; |
| 317 | } else { |
| 318 | error("main.option.requires.argument","-sourcepath"); |
| 319 | usage_error(); |
| 320 | return false; // Stop processing now |
| 321 | } |
| 322 | } else if (argv[i].equals("-sysclasspath")) { |
| 323 | if ((i + 1) < argv.length) { |
| 324 | if (sysClassPathArg != null) { |
| 325 | error("main.option.already.seen","-sysclasspath"); |
| 326 | } |
| 327 | sysClassPathArg = argv[++i]; |
| 328 | } else { |
| 329 | error("main.option.requires.argument","-sysclasspath"); |
| 330 | usage_error(); |
| 331 | return false; // Stop processing now |
| 332 | } |
| 333 | } else if (argv[i].equals("-bootclasspath")) { |
| 334 | if ((i + 1) < argv.length) { |
| 335 | if (sysClassPathArg != null) { |
| 336 | error("main.option.already.seen","-bootclasspath"); |
| 337 | } |
| 338 | sysClassPathArg = argv[++i]; |
| 339 | } else { |
| 340 | error("main.option.requires.argument","-bootclasspath"); |
| 341 | usage_error(); |
| 342 | return false; // Stop processing now |
| 343 | } |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 344 | } else if (argv[i].equals("-encoding")) { |
| 345 | if ((i + 1) < argv.length) { |
| 346 | if (encoding!=null) |
| 347 | error("main.option.already.seen","-encoding"); |
| 348 | encoding = argv[++i]; |
| 349 | } else { |
| 350 | error("main.option.requires.argument","-encoding"); |
| 351 | usage_error(); |
| 352 | return false; // Stop processing now |
| 353 | } |
| 354 | } else if (argv[i].equals("-target")) { |
| 355 | if ((i + 1) < argv.length) { |
| 356 | if (targetArg!=null) |
| 357 | error("main.option.already.seen","-target"); |
| 358 | targetArg = argv[++i]; |
| 359 | int j; |
| 360 | for (j=0; j<releases.length; j++) { |
| 361 | if (releases[j].equals(targetArg)) { |
| 362 | majorVersion = majorVersions[j]; |
| 363 | minorVersion = minorVersions[j]; |
| 364 | break; |
| 365 | } |
| 366 | } |
| 367 | if (j==releases.length) { |
| 368 | error("main.unknown.release",targetArg); |
| 369 | usage_error(); |
| 370 | return false; // Stop processing now |
| 371 | } |
| 372 | } else { |
| 373 | error("main.option.requires.argument","-target"); |
| 374 | usage_error(); |
| 375 | return false; // Stop processing now |
| 376 | } |
| 377 | } else if (argv[i].equals("-d")) { |
| 378 | if ((i + 1) < argv.length) { |
| 379 | if (destDir!=null) |
| 380 | error("main.option.already.seen","-d"); |
| 381 | destDir = new File(argv[++i]); |
| 382 | if (!destDir.exists()) { |
| 383 | error("main.no.such.directory",destDir.getPath()); |
| 384 | usage_error(); |
| 385 | return false; // Stop processing now |
| 386 | } |
| 387 | } else { |
| 388 | error("main.option.requires.argument","-d"); |
| 389 | usage_error(); |
| 390 | return false; // Stop processing now |
| 391 | } |
| 392 | // JCOV |
| 393 | } else if (argv[i].equals(optJcov)) { |
| 394 | flags |= F_COVERAGE; |
| 395 | flags &= ~F_OPT; |
| 396 | flags &= ~F_OPT_INTERCLASS; |
| 397 | } else if ((argv[i].startsWith(optJcovFile)) && |
| 398 | (argv[i].length() > optJcovFile.length())) { |
| 399 | covFile = new File(argv[i].substring(optJcovFile.length())); |
| 400 | flags &= ~F_OPT; |
| 401 | flags &= ~F_OPT_INTERCLASS; |
| 402 | flags |= F_COVERAGE; |
| 403 | flags |= F_COVDATA; |
| 404 | // end JCOV |
| 405 | } else if (argv[i].equals("-XO")) { |
| 406 | // This is what -O used to be. Now undocumented. |
| 407 | if (prior_O!=null && !(prior_O.equals("-XO"))) |
| 408 | error("main.conflicting.options", prior_O, "-XO"); |
| 409 | prior_O = "-XO"; |
| 410 | flags |= F_OPT; |
| 411 | } else if (argv[i].equals("-Xinterclass")) { |
| 412 | if (prior_O!=null && !(prior_O.equals("-Xinterclass"))) |
| 413 | error("main.conflicting.options", prior_O, "-Xinterclass"); |
| 414 | prior_O = "-Xinterclass"; |
| 415 | flags |= F_OPT; |
| 416 | flags |= F_OPT_INTERCLASS; |
| 417 | flags |= F_DEPENDENCIES; |
| 418 | } else if (argv[i].equals("-Xdepend")) { |
| 419 | flags |= F_DEPENDENCIES; |
| 420 | } else if (argv[i].equals("-Xdebug")) { |
| 421 | flags |= F_DUMP; |
| 422 | // Unadvertised option used by JWS. The non-X version should |
| 423 | // be removed, but we'll leave it in until we find out for |
| 424 | // sure that no one still depends on that option syntax. |
| 425 | } else if (argv[i].equals("-xdepend") || argv[i].equals("-Xjws")) { |
| 426 | flags |= F_PRINT_DEPENDENCIES; |
| 427 | // change the default output in this case: |
| 428 | if (out == System.err) { |
| 429 | out = System.out; |
| 430 | } |
| 431 | } else if (argv[i].equals("-Xstrictdefault")) { |
| 432 | // Make strict floating point the default |
| 433 | flags |= F_STRICTDEFAULT; |
| 434 | } else if (argv[i].equals("-Xverbosepath")) { |
| 435 | verbosePath = true; |
| 436 | } else if (argv[i].equals("-Xstdout")) { |
| 437 | out = System.out; |
| 438 | } else if (argv[i].equals("-X")) { |
| 439 | error("main.unsupported.usage"); |
| 440 | return false; // Stop processing now |
| 441 | } else if (argv[i].equals("-Xversion1.2")) { |
| 442 | // Inform the compiler that it need not target VMs |
| 443 | // earlier than version 1.2. This option is here |
| 444 | // for testing purposes only. It is deliberately |
| 445 | // kept orthogonal to the -target option in 1.2.0 |
| 446 | // for the sake of stability. These options will |
| 447 | // be merged in a future release. |
| 448 | flags |= F_VERSION12; |
| 449 | } else if (argv[i].endsWith(".java")) { |
| 450 | v.addElement(argv[i]); |
| 451 | } else { |
| 452 | error("main.no.such.option",argv[i]); |
| 453 | usage_error(); |
| 454 | return false; // Stop processing now |
| 455 | } |
| 456 | } |
| 457 | if (v.size() == 0 || exitStatus == EXIT_CMDERR) { |
| 458 | usage_error(); |
| 459 | return false; |
| 460 | } |
| 461 | |
| 462 | // Create our Environment. |
| 463 | BatchEnvironment env = BatchEnvironment.create(out, |
| 464 | sourcePathArg, |
| 465 | classPathArg, |
Chris Hegarty | 441905c | 2014-12-03 14:22:58 +0000 | [diff] [blame] | 466 | sysClassPathArg); |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 467 | if (verbosePath) { |
| 468 | output(getText("main.path.msg", |
| 469 | env.sourcePath.toString(), |
| 470 | env.binaryPath.toString())); |
| 471 | } |
| 472 | |
| 473 | env.flags |= flags; |
| 474 | env.majorVersion = majorVersion; |
| 475 | env.minorVersion = minorVersion; |
| 476 | // JCOV |
| 477 | env.covFile = covFile; |
| 478 | // end JCOV |
| 479 | env.setCharacterEncoding(encoding); |
| 480 | |
| 481 | // Preload the "out of memory" error string just in case we run |
| 482 | // out of memory during the compile. |
| 483 | String noMemoryErrorString = getText("main.no.memory"); |
| 484 | String stackOverflowErrorString = getText("main.stack.overflow"); |
| 485 | |
| 486 | env.error(0, "warn.class.is.deprecated", "sun.tools.javac.Main"); |
| 487 | |
| 488 | try { |
| 489 | // Parse all input files |
Neil Toda | 8c6d88b | 2014-07-31 17:01:24 -0700 | [diff] [blame] | 490 | for (Enumeration<String> e = v.elements() ; e.hasMoreElements() ;) { |
| 491 | File file = new File(e.nextElement()); |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 492 | try { |
Chris Hegarty | 441905c | 2014-12-03 14:22:58 +0000 | [diff] [blame] | 493 | env.parseFile(ClassFile.newClassFile(file)); |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 494 | } catch (FileNotFoundException ee) { |
| 495 | env.error(0, "cant.read", file.getPath()); |
| 496 | exitStatus = EXIT_CMDERR; |
| 497 | } |
| 498 | } |
| 499 | |
| 500 | // Do a post-read check on all newly-parsed classes, |
| 501 | // after they have all been read. |
Neil Toda | 8c6d88b | 2014-07-31 17:01:24 -0700 | [diff] [blame] | 502 | for (Enumeration<ClassDeclaration> e = env.getClasses() ; e.hasMoreElements() ; ) { |
| 503 | ClassDeclaration c = e.nextElement(); |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 504 | if (c.getStatus() == CS_PARSED) { |
| 505 | if (c.getClassDefinition().isLocal()) |
| 506 | continue; |
| 507 | try { |
| 508 | c.getClassDefinition(env); |
| 509 | } catch (ClassNotFound ee) { |
| 510 | } |
| 511 | } |
| 512 | } |
| 513 | |
| 514 | // compile all classes that need compilation |
| 515 | ByteArrayOutputStream buf = new ByteArrayOutputStream(4096); |
| 516 | boolean done; |
| 517 | |
| 518 | do { |
| 519 | done = true; |
| 520 | env.flushErrors(); |
Neil Toda | 8c6d88b | 2014-07-31 17:01:24 -0700 | [diff] [blame] | 521 | for (Enumeration<ClassDeclaration> e = env.getClasses() ; e.hasMoreElements() ; ) { |
| 522 | ClassDeclaration c = e.nextElement(); |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 523 | SourceClass src; |
| 524 | |
| 525 | switch (c.getStatus()) { |
| 526 | case CS_UNDEFINED: |
| 527 | if (!env.dependencies()) { |
| 528 | break; |
| 529 | } |
| 530 | // fall through |
| 531 | |
| 532 | case CS_SOURCE: |
| 533 | if (tracing) |
| 534 | env.dtEvent("Main.compile (SOURCE): loading, " + c); |
| 535 | done = false; |
| 536 | env.loadDefinition(c); |
| 537 | if (c.getStatus() != CS_PARSED) { |
| 538 | if (tracing) |
| 539 | env.dtEvent("Main.compile (SOURCE): not parsed, " + c); |
| 540 | break; |
| 541 | } |
| 542 | // fall through |
| 543 | |
| 544 | case CS_PARSED: |
| 545 | if (c.getClassDefinition().isInsideLocal()) { |
| 546 | // the enclosing block will check this one |
| 547 | if (tracing) |
| 548 | env.dtEvent("Main.compile (PARSED): skipping local class, " + c); |
| 549 | continue; |
| 550 | } |
| 551 | done = false; |
| 552 | if (tracing) env.dtEvent("Main.compile (PARSED): checking, " + c); |
| 553 | src = (SourceClass)c.getClassDefinition(env); |
| 554 | src.check(env); |
| 555 | c.setDefinition(src, CS_CHECKED); |
| 556 | // fall through |
| 557 | |
| 558 | case CS_CHECKED: |
| 559 | src = (SourceClass)c.getClassDefinition(env); |
| 560 | // bail out if there were any errors |
| 561 | if (src.getError()) { |
| 562 | if (tracing) |
| 563 | env.dtEvent("Main.compile (CHECKED): bailing out on error, " + c); |
| 564 | c.setDefinition(src, CS_COMPILED); |
| 565 | break; |
| 566 | } |
| 567 | done = false; |
| 568 | buf.reset(); |
| 569 | if (tracing) |
| 570 | env.dtEvent("Main.compile (CHECKED): compiling, " + c); |
| 571 | src.compile(buf); |
| 572 | c.setDefinition(src, CS_COMPILED); |
| 573 | src.cleanup(env); |
| 574 | |
| 575 | if (src.getNestError() || nowrite) { |
| 576 | continue; |
| 577 | } |
| 578 | |
| 579 | String pkgName = c.getName().getQualifier().toString().replace('.', File.separatorChar); |
| 580 | String className = c.getName().getFlatName().toString().replace('.', SIGC_INNERCLASS) + ".class"; |
| 581 | |
| 582 | File file; |
| 583 | if (destDir != null) { |
| 584 | if (pkgName.length() > 0) { |
| 585 | file = new File(destDir, pkgName); |
| 586 | if (!file.exists()) { |
| 587 | file.mkdirs(); |
| 588 | } |
| 589 | file = new File(file, className); |
| 590 | } else { |
| 591 | file = new File(destDir, className); |
| 592 | } |
| 593 | } else { |
| 594 | ClassFile classfile = (ClassFile)src.getSource(); |
| 595 | if (classfile.isZipped()) { |
| 596 | env.error(0, "cant.write", classfile.getPath()); |
| 597 | exitStatus = EXIT_CMDERR; |
| 598 | continue; |
| 599 | } |
| 600 | file = new File(classfile.getPath()); |
| 601 | file = new File(file.getParent(), className); |
| 602 | } |
| 603 | |
| 604 | // Create the file |
| 605 | try { |
| 606 | FileOutputStream out = new FileOutputStream(file.getPath()); |
| 607 | buf.writeTo(out); |
| 608 | out.close(); |
| 609 | |
| 610 | if (env.verbose()) { |
| 611 | output(getText("main.wrote", file.getPath())); |
| 612 | } |
| 613 | } catch (IOException ee) { |
| 614 | env.error(0, "cant.write", file.getPath()); |
| 615 | exitStatus = EXIT_CMDERR; |
| 616 | } |
| 617 | |
| 618 | // Print class dependencies if requested (-xdepend) |
| 619 | if (env.print_dependencies()) { |
| 620 | src.printClassDependencies(env); |
| 621 | } |
| 622 | } |
| 623 | } |
| 624 | } while (!done); |
| 625 | } catch (OutOfMemoryError ee) { |
| 626 | // The compiler has run out of memory. Use the error string |
| 627 | // which we preloaded. |
| 628 | env.output(noMemoryErrorString); |
| 629 | exitStatus = EXIT_SYSERR; |
| 630 | return false; |
| 631 | } catch (StackOverflowError ee) { |
| 632 | env.output(stackOverflowErrorString); |
| 633 | exitStatus = EXIT_SYSERR; |
| 634 | return false; |
| 635 | } catch (Error ee) { |
| 636 | // We allow the compiler to take an exception silently if a program |
| 637 | // error has previously been detected. Presumably, this makes the |
| 638 | // compiler more robust in the face of bad error recovery. |
| 639 | if (env.nerrors == 0 || env.dump()) { |
| 640 | ee.printStackTrace(); |
| 641 | env.error(0, "fatal.error"); |
| 642 | exitStatus = EXIT_ABNORMAL; |
| 643 | } |
| 644 | } catch (Exception ee) { |
| 645 | if (env.nerrors == 0 || env.dump()) { |
| 646 | ee.printStackTrace(); |
| 647 | env.error(0, "fatal.exception"); |
| 648 | exitStatus = EXIT_ABNORMAL; |
| 649 | } |
| 650 | } |
| 651 | |
| 652 | int ndepfiles = env.deprecationFiles.size(); |
| 653 | if (ndepfiles > 0 && env.warnings()) { |
| 654 | int ndeps = env.ndeprecations; |
| 655 | Object file1 = env.deprecationFiles.elementAt(0); |
| 656 | if (env.deprecation()) { |
| 657 | if (ndepfiles > 1) { |
| 658 | env.error(0, "warn.note.deprecations", |
Otavio Goncalves de Santana | 1ebe2a4 | 2014-07-15 11:22:14 -0700 | [diff] [blame] | 659 | ndepfiles, ndeps); |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 660 | } else { |
| 661 | env.error(0, "warn.note.1deprecation", |
Otavio Goncalves de Santana | 1ebe2a4 | 2014-07-15 11:22:14 -0700 | [diff] [blame] | 662 | file1, ndeps); |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 663 | } |
| 664 | } else { |
| 665 | if (ndepfiles > 1) { |
| 666 | env.error(0, "warn.note.deprecations.silent", |
Otavio Goncalves de Santana | 1ebe2a4 | 2014-07-15 11:22:14 -0700 | [diff] [blame] | 667 | ndepfiles, ndeps); |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 668 | } else { |
| 669 | env.error(0, "warn.note.1deprecation.silent", |
Otavio Goncalves de Santana | 1ebe2a4 | 2014-07-15 11:22:14 -0700 | [diff] [blame] | 670 | file1, ndeps); |
J. Duke | 319a3b9 | 2007-12-01 00:00:00 +0000 | [diff] [blame] | 671 | } |
| 672 | } |
| 673 | } |
| 674 | |
| 675 | env.flushErrors(); |
| 676 | env.shutdown(); |
| 677 | |
| 678 | boolean status = true; |
| 679 | if (env.nerrors > 0) { |
| 680 | String msg = ""; |
| 681 | if (env.nerrors > 1) { |
| 682 | msg = getText("main.errors", env.nerrors); |
| 683 | } else { |
| 684 | msg = getText("main.1error"); |
| 685 | } |
| 686 | if (env.nwarnings > 0) { |
| 687 | if (env.nwarnings > 1) { |
| 688 | msg += ", " + getText("main.warnings", env.nwarnings); |
| 689 | } else { |
| 690 | msg += ", " + getText("main.1warning"); |
| 691 | } |
| 692 | } |
| 693 | output(msg); |
| 694 | if (exitStatus == EXIT_OK) { |
| 695 | // Allow EXIT_CMDERR or EXIT_ABNORMAL to take precedence. |
| 696 | exitStatus = EXIT_ERROR; |
| 697 | } |
| 698 | status = false; |
| 699 | } else { |
| 700 | if (env.nwarnings > 0) { |
| 701 | if (env.nwarnings > 1) { |
| 702 | output(getText("main.warnings", env.nwarnings)); |
| 703 | } else { |
| 704 | output(getText("main.1warning")); |
| 705 | } |
| 706 | } |
| 707 | } |
| 708 | //JCOV |
| 709 | if (env.covdata()) { |
| 710 | Assembler CovAsm = new Assembler(); |
| 711 | CovAsm.GenJCov(env); |
| 712 | } |
| 713 | // end JCOV |
| 714 | |
| 715 | // We're done |
| 716 | if (env.verbose()) { |
| 717 | tm = System.currentTimeMillis() - tm; |
| 718 | output(getText("main.done_in", Long.toString(tm))); |
| 719 | } |
| 720 | |
| 721 | return status; |
| 722 | } |
| 723 | |
| 724 | /** |
| 725 | * Main program |
| 726 | */ |
| 727 | public static void main(String argv[]) { |
| 728 | OutputStream out = System.err; |
| 729 | |
| 730 | // This is superceeded by the -Xstdout option, but we leave |
| 731 | // in the old property check for compatibility. |
| 732 | if (Boolean.getBoolean("javac.pipe.output")) { |
| 733 | out = System.out; |
| 734 | } |
| 735 | |
| 736 | Main compiler = new Main(out, "javac"); |
| 737 | System.exit(compiler.compile(argv) ? 0 : compiler.exitStatus); |
| 738 | } |
| 739 | } |