1 /*
   2  * Copyright (c) 1994, 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 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      */
 195     public synchronized boolean compile(String argv[]) {
 196         String sourcePathArg = null;
 197         String classPathArg = null;
 198         String sysClassPathArg = null;
 199         String extDirsArg = null;
 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();
 214         Vector v = new Vector();
 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                 }
 344             } else if (argv[i].equals("-extdirs")) {
 345                 if ((i + 1) < argv.length) {
 346                     if (extDirsArg != null) {
 347                         error("main.option.already.seen","-extdirs");
 348                     }
 349                     extDirsArg = argv[++i];
 350                 } else {
 351                     error("main.option.requires.argument","-extdirs");
 352                     usage_error();
 353                     return false;  // Stop processing now
 354                 }
 355             } else if (argv[i].equals("-encoding")) {
 356                 if ((i + 1) < argv.length) {
 357                     if (encoding!=null)
 358                        error("main.option.already.seen","-encoding");
 359                     encoding = argv[++i];
 360                 } else {
 361                     error("main.option.requires.argument","-encoding");
 362                     usage_error();
 363                     return false; // Stop processing now
 364                 }
 365             } else if (argv[i].equals("-target")) {
 366                 if ((i + 1) < argv.length) {
 367                     if (targetArg!=null)
 368                        error("main.option.already.seen","-target");
 369                     targetArg = argv[++i];
 370                     int j;
 371                     for (j=0; j<releases.length; j++) {
 372                         if (releases[j].equals(targetArg)) {
 373                             majorVersion = majorVersions[j];
 374                             minorVersion = minorVersions[j];
 375                             break;
 376                         }
 377                     }
 378                     if (j==releases.length) {
 379                         error("main.unknown.release",targetArg);
 380                         usage_error();
 381                         return false; // Stop processing now
 382                     }
 383                 } else {
 384                     error("main.option.requires.argument","-target");
 385                     usage_error();
 386                     return false; // Stop processing now
 387                 }
 388             } else if (argv[i].equals("-d")) {
 389                 if ((i + 1) < argv.length) {
 390                     if (destDir!=null)
 391                        error("main.option.already.seen","-d");
 392                     destDir = new File(argv[++i]);
 393                     if (!destDir.exists()) {
 394                         error("main.no.such.directory",destDir.getPath());
 395                         usage_error();
 396                         return false; // Stop processing now
 397                     }
 398                 } else {
 399                     error("main.option.requires.argument","-d");
 400                     usage_error();
 401                     return false; // Stop processing now
 402                 }
 403 // JCOV
 404             } else if (argv[i].equals(optJcov)) {
 405                     flags |= F_COVERAGE;
 406                     flags &= ~F_OPT;
 407                     flags &= ~F_OPT_INTERCLASS;
 408             } else if ((argv[i].startsWith(optJcovFile)) &&
 409                        (argv[i].length() > optJcovFile.length())) {
 410                     covFile = new File(argv[i].substring(optJcovFile.length()));
 411                     flags &= ~F_OPT;
 412                     flags &= ~F_OPT_INTERCLASS;
 413                     flags |= F_COVERAGE;
 414                     flags |= F_COVDATA;
 415 // end JCOV
 416             } else if (argv[i].equals("-XO")) {
 417                 // This is what -O used to be.  Now undocumented.
 418                 if (prior_O!=null && !(prior_O.equals("-XO")))
 419                    error("main.conflicting.options", prior_O, "-XO");
 420                 prior_O = "-XO";
 421                 flags |= F_OPT;
 422             } else if (argv[i].equals("-Xinterclass")) {
 423                 if (prior_O!=null && !(prior_O.equals("-Xinterclass")))
 424                    error("main.conflicting.options", prior_O, "-Xinterclass");
 425                 prior_O = "-Xinterclass";
 426                 flags |= F_OPT;
 427                 flags |= F_OPT_INTERCLASS;
 428                 flags |= F_DEPENDENCIES;
 429             } else if (argv[i].equals("-Xdepend")) {
 430                 flags |= F_DEPENDENCIES;
 431             } else if (argv[i].equals("-Xdebug")) {
 432                 flags |= F_DUMP;
 433             // Unadvertised option used by JWS.  The non-X version should
 434             // be removed, but we'll leave it in until we find out for
 435             // sure that no one still depends on that option syntax.
 436             } else if (argv[i].equals("-xdepend") || argv[i].equals("-Xjws")) {
 437                 flags |= F_PRINT_DEPENDENCIES;
 438                 // change the default output in this case:
 439                 if (out == System.err) {
 440                     out = System.out;
 441                 }
 442             } else if (argv[i].equals("-Xstrictdefault")) {
 443                 // Make strict floating point the default
 444                 flags |= F_STRICTDEFAULT;
 445             } else if (argv[i].equals("-Xverbosepath")) {
 446                 verbosePath = true;
 447             } else if (argv[i].equals("-Xstdout")) {
 448                 out = System.out;
 449             } else if (argv[i].equals("-X")) {
 450                 error("main.unsupported.usage");
 451                 return false; // Stop processing now
 452             } else if (argv[i].equals("-Xversion1.2")) {
 453                 // Inform the compiler that it need not target VMs
 454                 // earlier than version 1.2.  This option is here
 455                 // for testing purposes only.  It is deliberately
 456                 // kept orthogonal to the -target option in 1.2.0
 457                 // for the sake of stability.  These options will
 458                 // be merged in a future release.
 459                 flags |= F_VERSION12;
 460             } else if (argv[i].endsWith(".java")) {
 461                 v.addElement(argv[i]);
 462             } else {
 463                 error("main.no.such.option",argv[i]);
 464                 usage_error();
 465                 return false; // Stop processing now
 466             }
 467         }
 468         if (v.size() == 0 || exitStatus == EXIT_CMDERR) {
 469             usage_error();
 470             return false;
 471         }
 472 
 473         // Create our Environment.
 474         BatchEnvironment env = BatchEnvironment.create(out,
 475                                                        sourcePathArg,
 476                                                        classPathArg,
 477                                                        sysClassPathArg,
 478                                                        extDirsArg);
 479         if (verbosePath) {
 480             output(getText("main.path.msg",
 481                            env.sourcePath.toString(),
 482                            env.binaryPath.toString()));
 483         }
 484 
 485         env.flags |= flags;
 486         env.majorVersion = majorVersion;
 487         env.minorVersion = minorVersion;
 488 // JCOV
 489         env.covFile = covFile;
 490 // end JCOV
 491         env.setCharacterEncoding(encoding);
 492 
 493         // Preload the "out of memory" error string just in case we run
 494         // out of memory during the compile.
 495         String noMemoryErrorString = getText("main.no.memory");
 496         String stackOverflowErrorString = getText("main.stack.overflow");
 497 
 498         env.error(0, "warn.class.is.deprecated", "sun.tools.javac.Main");
 499 
 500         try {
 501             // Parse all input files
 502             for (Enumeration e = v.elements() ; e.hasMoreElements() ;) {
 503                 File file = new File((String)e.nextElement());
 504                 try {
 505                     env.parseFile(new ClassFile(file));
 506                 } catch (FileNotFoundException ee) {
 507                     env.error(0, "cant.read", file.getPath());
 508                     exitStatus = EXIT_CMDERR;
 509                 }
 510             }
 511 
 512             // Do a post-read check on all newly-parsed classes,
 513             // after they have all been read.
 514             for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) {
 515                 ClassDeclaration c = (ClassDeclaration)e.nextElement();
 516                 if (c.getStatus() == CS_PARSED) {
 517                     if (c.getClassDefinition().isLocal())
 518                         continue;
 519                     try {
 520                         c.getClassDefinition(env);
 521                     } catch (ClassNotFound ee) {
 522                     }
 523                 }
 524             }
 525 
 526             // compile all classes that need compilation
 527             ByteArrayOutputStream buf = new ByteArrayOutputStream(4096);
 528             boolean done;
 529 
 530             do {
 531                 done = true;
 532                 env.flushErrors();
 533                 for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) {
 534                     ClassDeclaration c = (ClassDeclaration)e.nextElement();
 535                     SourceClass src;
 536 
 537                     switch (c.getStatus()) {
 538                       case CS_UNDEFINED:
 539                         if (!env.dependencies()) {
 540                             break;
 541                         }
 542                         // fall through
 543 
 544                       case CS_SOURCE:
 545                         if (tracing)
 546                             env.dtEvent("Main.compile (SOURCE): loading, " + c);
 547                         done = false;
 548                         env.loadDefinition(c);
 549                         if (c.getStatus() != CS_PARSED) {
 550                             if (tracing)
 551                                 env.dtEvent("Main.compile (SOURCE): not parsed, " + c);
 552                             break;
 553                         }
 554                         // fall through
 555 
 556                       case CS_PARSED:
 557                         if (c.getClassDefinition().isInsideLocal()) {
 558                             // the enclosing block will check this one
 559                             if (tracing)
 560                                 env.dtEvent("Main.compile (PARSED): skipping local class, " + c);
 561                             continue;
 562                         }
 563                         done = false;
 564                         if (tracing) env.dtEvent("Main.compile (PARSED): checking, " + c);
 565                         src = (SourceClass)c.getClassDefinition(env);
 566                         src.check(env);
 567                         c.setDefinition(src, CS_CHECKED);
 568                         // fall through
 569 
 570                       case CS_CHECKED:
 571                         src = (SourceClass)c.getClassDefinition(env);
 572                         // bail out if there were any errors
 573                         if (src.getError()) {
 574                             if (tracing)
 575                                 env.dtEvent("Main.compile (CHECKED): bailing out on error, " + c);
 576                             c.setDefinition(src, CS_COMPILED);
 577                             break;
 578                         }
 579                         done = false;
 580                         buf.reset();
 581                         if (tracing)
 582                             env.dtEvent("Main.compile (CHECKED): compiling, " + c);
 583                         src.compile(buf);
 584                         c.setDefinition(src, CS_COMPILED);
 585                         src.cleanup(env);
 586 
 587                         if (src.getNestError() || nowrite) {
 588                             continue;
 589                         }
 590 
 591                         String pkgName = c.getName().getQualifier().toString().replace('.', File.separatorChar);
 592                         String className = c.getName().getFlatName().toString().replace('.', SIGC_INNERCLASS) + ".class";
 593 
 594                         File file;
 595                         if (destDir != null) {
 596                             if (pkgName.length() > 0) {
 597                                 file = new File(destDir, pkgName);
 598                                 if (!file.exists()) {
 599                                     file.mkdirs();
 600                                 }
 601                                 file = new File(file, className);
 602                             } else {
 603                                 file = new File(destDir, className);
 604                             }
 605                         } else {
 606                             ClassFile classfile = (ClassFile)src.getSource();
 607                             if (classfile.isZipped()) {
 608                                 env.error(0, "cant.write", classfile.getPath());
 609                                 exitStatus = EXIT_CMDERR;
 610                                 continue;
 611                             }
 612                             file = new File(classfile.getPath());
 613                             file = new File(file.getParent(), className);
 614                         }
 615 
 616                         // Create the file
 617                         try {
 618                             FileOutputStream out = new FileOutputStream(file.getPath());
 619                             buf.writeTo(out);
 620                             out.close();
 621 
 622                             if (env.verbose()) {
 623                                 output(getText("main.wrote", file.getPath()));
 624                             }
 625                         } catch (IOException ee) {
 626                             env.error(0, "cant.write", file.getPath());
 627                             exitStatus = EXIT_CMDERR;
 628                         }
 629 
 630                         // Print class dependencies if requested (-xdepend)
 631                         if (env.print_dependencies()) {
 632                             src.printClassDependencies(env);
 633                         }
 634                     }
 635                 }
 636             } while (!done);
 637         } catch (OutOfMemoryError ee) {
 638             // The compiler has run out of memory.  Use the error string
 639             // which we preloaded.
 640             env.output(noMemoryErrorString);
 641             exitStatus = EXIT_SYSERR;
 642             return false;
 643         } catch (StackOverflowError ee) {
 644             env.output(stackOverflowErrorString);
 645             exitStatus = EXIT_SYSERR;
 646             return false;
 647         } catch (Error ee) {
 648             // We allow the compiler to take an exception silently if a program
 649             // error has previously been detected.  Presumably, this makes the
 650             // compiler more robust in the face of bad error recovery.
 651             if (env.nerrors == 0 || env.dump()) {
 652                 ee.printStackTrace();
 653                 env.error(0, "fatal.error");
 654                 exitStatus = EXIT_ABNORMAL;
 655             }
 656         } catch (Exception ee) {
 657             if (env.nerrors == 0 || env.dump()) {
 658                 ee.printStackTrace();
 659                 env.error(0, "fatal.exception");
 660                 exitStatus = EXIT_ABNORMAL;
 661             }
 662         }
 663 
 664         int ndepfiles = env.deprecationFiles.size();
 665         if (ndepfiles > 0 && env.warnings()) {
 666             int ndeps = env.ndeprecations;
 667             Object file1 = env.deprecationFiles.elementAt(0);
 668             if (env.deprecation()) {
 669                 if (ndepfiles > 1) {
 670                     env.error(0, "warn.note.deprecations",
 671                               new Integer(ndepfiles), new Integer(ndeps));
 672                 } else {
 673                     env.error(0, "warn.note.1deprecation",
 674                               file1, new Integer(ndeps));
 675                 }
 676             } else {
 677                 if (ndepfiles > 1) {
 678                     env.error(0, "warn.note.deprecations.silent",
 679                               new Integer(ndepfiles), new Integer(ndeps));
 680                 } else {
 681                     env.error(0, "warn.note.1deprecation.silent",
 682                               file1, new Integer(ndeps));
 683                 }
 684             }
 685         }
 686 
 687         env.flushErrors();
 688         env.shutdown();
 689 
 690         boolean status = true;
 691         if (env.nerrors > 0) {
 692             String msg = "";
 693             if (env.nerrors > 1) {
 694                 msg = getText("main.errors", env.nerrors);
 695             } else {
 696                 msg = getText("main.1error");
 697             }
 698             if (env.nwarnings > 0) {
 699                 if (env.nwarnings > 1) {
 700                     msg += ", " + getText("main.warnings", env.nwarnings);
 701                 } else {
 702                     msg += ", " + getText("main.1warning");
 703                 }
 704             }
 705             output(msg);
 706             if (exitStatus == EXIT_OK) {
 707                 // Allow EXIT_CMDERR or EXIT_ABNORMAL to take precedence.
 708                 exitStatus = EXIT_ERROR;
 709             }
 710             status = false;
 711         } else {
 712             if (env.nwarnings > 0) {
 713                 if (env.nwarnings > 1) {
 714                     output(getText("main.warnings", env.nwarnings));
 715                 } else {
 716                     output(getText("main.1warning"));
 717                 }
 718             }
 719         }
 720 //JCOV
 721         if (env.covdata()) {
 722             Assembler CovAsm = new Assembler();
 723             CovAsm.GenJCov(env);
 724         }
 725 // end JCOV
 726 
 727         // We're done
 728         if (env.verbose()) {
 729             tm = System.currentTimeMillis() - tm;
 730             output(getText("main.done_in", Long.toString(tm)));
 731         }
 732 
 733         return status;
 734     }
 735 
 736     /**
 737      * Main program
 738      */
 739     public static void main(String argv[]) {
 740         OutputStream out = System.err;
 741 
 742         // This is superceeded by the -Xstdout option, but we leave
 743         // in the old property check for compatibility.
 744         if (Boolean.getBoolean("javac.pipe.output")) {
 745             out = System.out;
 746         }
 747 
 748         Main compiler = new Main(out, "javac");
 749         System.exit(compiler.compile(argv) ? 0 : compiler.exitStatus);
 750     }
 751 }