Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/javac/Main.java
38918 views
/*1* Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.tools.javac;2627import sun.tools.java.*;28import sun.tools.util.CommandLine;29// JCOV30import sun.tools.asm.Assembler;31// end JCOV3233import java.util.*;34import java.io.*;35import java.text.MessageFormat;3637/**38* Main program of the Java compiler39*40* WARNING: The contents of this source file are not part of any41* supported API. Code that depends on them does so at its own risk:42* they are subject to change or removal without notice.43*44* @deprecated As of J2SE 1.3, the preferred way to compile Java45* language sources is by using the new compiler,46* com.sun.tools.javac.Main.47*/48@Deprecated49public50class Main implements Constants {51/**52* Name of the program.53*/54String program;5556/**57* The stream where error message are printed.58*/59OutputStream out;6061/**62* Constructor.63*/64public Main(OutputStream out, String program) {65this.out = out;66this.program = program;67}6869/**70* Exit status.71* We introduce a separate integer status variable, and do not alter the72* convention that 'compile' returns a boolean true upon a successful73* compilation with no errors. (JavaTest relies on this.)74*/7576public static final int EXIT_OK = 0; // Compilation completed with no errors.77public static final int EXIT_ERROR = 1; // Compilation completed but reported errors.78public static final int EXIT_CMDERR = 2; // Bad command-line arguments and/or switches.79public static final int EXIT_SYSERR = 3; // System error or resource exhaustion.80public static final int EXIT_ABNORMAL = 4; // Compiler terminated abnormally.8182private int exitStatus;8384public int getExitStatus() {85return exitStatus;86}8788public boolean compilationPerformedSuccessfully() {89return exitStatus == EXIT_OK || exitStatus == EXIT_ERROR;90}9192public boolean compilationReportedErrors () {93return exitStatus != EXIT_OK;94}9596/**97* Output a message.98*/99private void output(String msg) {100PrintStream out =101this.out instanceof PrintStream ? (PrintStream)this.out102: new PrintStream(this.out, true);103out.println(msg);104}105106/**107* Top level error message. This method is called when the108* environment could not be set up yet.109*/110private void error(String msg) {111exitStatus = EXIT_CMDERR;112output(getText(msg));113}114115private void error(String msg, String arg1) {116exitStatus = EXIT_CMDERR;117output(getText(msg, arg1));118}119120private void error(String msg, String arg1, String arg2) {121exitStatus = EXIT_CMDERR;122output(getText(msg, arg1, arg2));123}124125/**126* Print usage message and make exit status an error.127* Note: 'javac' invoked without any arguments is considered128* be an error.129*/130public void usage_error() {131error("main.usage", program);132}133134private static ResourceBundle messageRB;135136/**137* Initialize ResourceBundle138*/139static void initResource() {140try {141messageRB =142ResourceBundle.getBundle("sun.tools.javac.resources.javac");143} catch (MissingResourceException e) {144throw new Error("Fatal: Resource for javac is missing");145}146}147148/**149* get and format message string from resource150*/151public static String getText(String key) {152return getText(key, (String)null);153}154155public static String getText(String key, int num) {156return getText(key, Integer.toString(num));157}158159public static String getText(String key, String fixed) {160return getText(key, fixed, null);161}162163public static String getText(String key, String fixed1, String fixed2) {164return getText(key, fixed1, fixed2, null);165}166167public static String getText(String key, String fixed1,168String fixed2, String fixed3) {169if (messageRB == null) {170initResource();171}172try {173String message = messageRB.getString(key);174return MessageFormat.format(message, fixed1, fixed2, fixed3);175} catch (MissingResourceException e) {176if (fixed1 == null) fixed1 = "null";177if (fixed2 == null) fixed2 = "null";178if (fixed3 == null) fixed3 = "null";179String message = "JAVAC MESSAGE FILE IS BROKEN: key={0}, arguments={1}, {2}, {3}";180return MessageFormat.format(message, key, fixed1, fixed2, fixed3);181}182}183184// What major and minor version numbers to use for the -target flag.185// This should grow every time the minor version number accepted by186// the VM is incremented.187private static final String[] releases = { "1.1", "1.2", "1.3", "1.4" };188private static final short[] majorVersions = { 45, 46, 47, 48 };189private static final short[] minorVersions = { 3, 0, 0, 0 };190191/**192* Run the compiler193*/194public synchronized boolean compile(String argv[]) {195String sourcePathArg = null;196String classPathArg = null;197String sysClassPathArg = null;198String extDirsArg = null;199boolean verbosePath = false;200201String targetArg = null;202short majorVersion = JAVA_DEFAULT_VERSION;203short minorVersion = JAVA_DEFAULT_MINOR_VERSION;204205File destDir = null;206//JCOV207File covFile = null;208String optJcov = "-Xjcov";209String optJcovFile = "-Xjcov:file=";210//end JCOV211int flags = F_WARNINGS | F_DEBUG_LINES | F_DEBUG_SOURCE;212long tm = System.currentTimeMillis();213Vector v = new Vector();214boolean nowrite = false;215String props = null;216String encoding = null;217218// These flags are used to make sure conflicting -O and -g219// options aren't given.220String prior_g = null;221String prior_O = null;222223exitStatus = EXIT_OK;224225// Pre-process command line for @file arguments226try {227argv = CommandLine.parse(argv);228} catch (FileNotFoundException e) {229error("javac.err.cant.read", e.getMessage());230System.exit(1);231} catch (IOException e) {232e.printStackTrace();233System.exit(1);234}235236// Parse arguments237for (int i = 0 ; i < argv.length ; i++) {238if (argv[i].equals("-g")) {239if (prior_g!=null && !(prior_g.equals("-g")))240error("main.conflicting.options", prior_g, "-g");241prior_g = "-g";242flags |= F_DEBUG_LINES;243flags |= F_DEBUG_VARS;244flags |= F_DEBUG_SOURCE;245} else if (argv[i].equals("-g:none")) {246if (prior_g!=null && !(prior_g.equals("-g:none")))247error("main.conflicting.options", prior_g, "-g:none");248prior_g = "-g:none";249flags &= ~F_DEBUG_LINES;250flags &= ~F_DEBUG_VARS;251flags &= ~F_DEBUG_SOURCE;252} else if (argv[i].startsWith("-g:")) {253// We choose to have debugging options conflict even254// if they amount to the same thing (for example,255// -g:source,lines and -g:lines,source). However, multiple256// debugging options are allowed if they are textually257// identical.258if (prior_g!=null && !(prior_g.equals(argv[i])))259error("main.conflicting.options", prior_g, argv[i]);260prior_g = argv[i];261String args = argv[i].substring("-g:".length());262flags &= ~F_DEBUG_LINES;263flags &= ~F_DEBUG_VARS;264flags &= ~F_DEBUG_SOURCE;265while (true) {266if (args.startsWith("lines")) {267flags |= F_DEBUG_LINES;268args = args.substring("lines".length());269} else if (args.startsWith("vars")) {270flags |= F_DEBUG_VARS;271args = args.substring("vars".length());272} else if (args.startsWith("source")) {273flags |= F_DEBUG_SOURCE;274args = args.substring("source".length());275} else {276error("main.bad.debug.option",argv[i]);277usage_error();278return false; // Stop processing now279}280if (args.length() == 0) break;281if (args.startsWith(","))282args = args.substring(",".length());283}284} else if (argv[i].equals("-O")) {285// -O is accepted for backward compatibility, but286// is no longer effective. Use the undocumented287// -XO option to get the old behavior.288if (prior_O!=null && !(prior_O.equals("-O")))289error("main.conflicting.options", prior_O, "-O");290prior_O = "-O";291} else if (argv[i].equals("-nowarn")) {292flags &= ~F_WARNINGS;293} else if (argv[i].equals("-deprecation")) {294flags |= F_DEPRECATION;295} else if (argv[i].equals("-verbose")) {296flags |= F_VERBOSE;297} else if (argv[i].equals("-nowrite")) {298nowrite = true;299} else if (argv[i].equals("-classpath")) {300if ((i + 1) < argv.length) {301if (classPathArg!=null) {302error("main.option.already.seen","-classpath");303}304classPathArg = argv[++i];305} else {306error("main.option.requires.argument","-classpath");307usage_error();308return false; // Stop processing now309}310} else if (argv[i].equals("-sourcepath")) {311if ((i + 1) < argv.length) {312if (sourcePathArg != null) {313error("main.option.already.seen","-sourcepath");314}315sourcePathArg = argv[++i];316} else {317error("main.option.requires.argument","-sourcepath");318usage_error();319return false; // Stop processing now320}321} else if (argv[i].equals("-sysclasspath")) {322if ((i + 1) < argv.length) {323if (sysClassPathArg != null) {324error("main.option.already.seen","-sysclasspath");325}326sysClassPathArg = argv[++i];327} else {328error("main.option.requires.argument","-sysclasspath");329usage_error();330return false; // Stop processing now331}332} else if (argv[i].equals("-bootclasspath")) {333if ((i + 1) < argv.length) {334if (sysClassPathArg != null) {335error("main.option.already.seen","-bootclasspath");336}337sysClassPathArg = argv[++i];338} else {339error("main.option.requires.argument","-bootclasspath");340usage_error();341return false; // Stop processing now342}343} else if (argv[i].equals("-extdirs")) {344if ((i + 1) < argv.length) {345if (extDirsArg != null) {346error("main.option.already.seen","-extdirs");347}348extDirsArg = argv[++i];349} else {350error("main.option.requires.argument","-extdirs");351usage_error();352return false; // Stop processing now353}354} else if (argv[i].equals("-encoding")) {355if ((i + 1) < argv.length) {356if (encoding!=null)357error("main.option.already.seen","-encoding");358encoding = argv[++i];359} else {360error("main.option.requires.argument","-encoding");361usage_error();362return false; // Stop processing now363}364} else if (argv[i].equals("-target")) {365if ((i + 1) < argv.length) {366if (targetArg!=null)367error("main.option.already.seen","-target");368targetArg = argv[++i];369int j;370for (j=0; j<releases.length; j++) {371if (releases[j].equals(targetArg)) {372majorVersion = majorVersions[j];373minorVersion = minorVersions[j];374break;375}376}377if (j==releases.length) {378error("main.unknown.release",targetArg);379usage_error();380return false; // Stop processing now381}382} else {383error("main.option.requires.argument","-target");384usage_error();385return false; // Stop processing now386}387} else if (argv[i].equals("-d")) {388if ((i + 1) < argv.length) {389if (destDir!=null)390error("main.option.already.seen","-d");391destDir = new File(argv[++i]);392if (!destDir.exists()) {393error("main.no.such.directory",destDir.getPath());394usage_error();395return false; // Stop processing now396}397} else {398error("main.option.requires.argument","-d");399usage_error();400return false; // Stop processing now401}402// JCOV403} else if (argv[i].equals(optJcov)) {404flags |= F_COVERAGE;405flags &= ~F_OPT;406flags &= ~F_OPT_INTERCLASS;407} else if ((argv[i].startsWith(optJcovFile)) &&408(argv[i].length() > optJcovFile.length())) {409covFile = new File(argv[i].substring(optJcovFile.length()));410flags &= ~F_OPT;411flags &= ~F_OPT_INTERCLASS;412flags |= F_COVERAGE;413flags |= F_COVDATA;414// end JCOV415} else if (argv[i].equals("-XO")) {416// This is what -O used to be. Now undocumented.417if (prior_O!=null && !(prior_O.equals("-XO")))418error("main.conflicting.options", prior_O, "-XO");419prior_O = "-XO";420flags |= F_OPT;421} else if (argv[i].equals("-Xinterclass")) {422if (prior_O!=null && !(prior_O.equals("-Xinterclass")))423error("main.conflicting.options", prior_O, "-Xinterclass");424prior_O = "-Xinterclass";425flags |= F_OPT;426flags |= F_OPT_INTERCLASS;427flags |= F_DEPENDENCIES;428} else if (argv[i].equals("-Xdepend")) {429flags |= F_DEPENDENCIES;430} else if (argv[i].equals("-Xdebug")) {431flags |= F_DUMP;432// Unadvertised option used by JWS. The non-X version should433// be removed, but we'll leave it in until we find out for434// sure that no one still depends on that option syntax.435} else if (argv[i].equals("-xdepend") || argv[i].equals("-Xjws")) {436flags |= F_PRINT_DEPENDENCIES;437// change the default output in this case:438if (out == System.err) {439out = System.out;440}441} else if (argv[i].equals("-Xstrictdefault")) {442// Make strict floating point the default443flags |= F_STRICTDEFAULT;444} else if (argv[i].equals("-Xverbosepath")) {445verbosePath = true;446} else if (argv[i].equals("-Xstdout")) {447out = System.out;448} else if (argv[i].equals("-X")) {449error("main.unsupported.usage");450return false; // Stop processing now451} else if (argv[i].equals("-Xversion1.2")) {452// Inform the compiler that it need not target VMs453// earlier than version 1.2. This option is here454// for testing purposes only. It is deliberately455// kept orthogonal to the -target option in 1.2.0456// for the sake of stability. These options will457// be merged in a future release.458flags |= F_VERSION12;459} else if (argv[i].endsWith(".java")) {460v.addElement(argv[i]);461} else {462error("main.no.such.option",argv[i]);463usage_error();464return false; // Stop processing now465}466}467if (v.size() == 0 || exitStatus == EXIT_CMDERR) {468usage_error();469return false;470}471472// Create our Environment.473BatchEnvironment env = BatchEnvironment.create(out,474sourcePathArg,475classPathArg,476sysClassPathArg,477extDirsArg);478if (verbosePath) {479output(getText("main.path.msg",480env.sourcePath.toString(),481env.binaryPath.toString()));482}483484env.flags |= flags;485env.majorVersion = majorVersion;486env.minorVersion = minorVersion;487// JCOV488env.covFile = covFile;489// end JCOV490env.setCharacterEncoding(encoding);491492// Preload the "out of memory" error string just in case we run493// out of memory during the compile.494String noMemoryErrorString = getText("main.no.memory");495String stackOverflowErrorString = getText("main.stack.overflow");496497env.error(0, "warn.class.is.deprecated", "sun.tools.javac.Main");498499try {500// Parse all input files501for (Enumeration e = v.elements() ; e.hasMoreElements() ;) {502File file = new File((String)e.nextElement());503try {504env.parseFile(new ClassFile(file));505} catch (FileNotFoundException ee) {506env.error(0, "cant.read", file.getPath());507exitStatus = EXIT_CMDERR;508}509}510511// Do a post-read check on all newly-parsed classes,512// after they have all been read.513for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) {514ClassDeclaration c = (ClassDeclaration)e.nextElement();515if (c.getStatus() == CS_PARSED) {516if (c.getClassDefinition().isLocal())517continue;518try {519c.getClassDefinition(env);520} catch (ClassNotFound ee) {521}522}523}524525// compile all classes that need compilation526ByteArrayOutputStream buf = new ByteArrayOutputStream(4096);527boolean done;528529do {530done = true;531env.flushErrors();532for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) {533ClassDeclaration c = (ClassDeclaration)e.nextElement();534SourceClass src;535536switch (c.getStatus()) {537case CS_UNDEFINED:538if (!env.dependencies()) {539break;540}541// fall through542543case CS_SOURCE:544if (tracing)545env.dtEvent("Main.compile (SOURCE): loading, " + c);546done = false;547env.loadDefinition(c);548if (c.getStatus() != CS_PARSED) {549if (tracing)550env.dtEvent("Main.compile (SOURCE): not parsed, " + c);551break;552}553// fall through554555case CS_PARSED:556if (c.getClassDefinition().isInsideLocal()) {557// the enclosing block will check this one558if (tracing)559env.dtEvent("Main.compile (PARSED): skipping local class, " + c);560continue;561}562done = false;563if (tracing) env.dtEvent("Main.compile (PARSED): checking, " + c);564src = (SourceClass)c.getClassDefinition(env);565src.check(env);566c.setDefinition(src, CS_CHECKED);567// fall through568569case CS_CHECKED:570src = (SourceClass)c.getClassDefinition(env);571// bail out if there were any errors572if (src.getError()) {573if (tracing)574env.dtEvent("Main.compile (CHECKED): bailing out on error, " + c);575c.setDefinition(src, CS_COMPILED);576break;577}578done = false;579buf.reset();580if (tracing)581env.dtEvent("Main.compile (CHECKED): compiling, " + c);582src.compile(buf);583c.setDefinition(src, CS_COMPILED);584src.cleanup(env);585586if (src.getNestError() || nowrite) {587continue;588}589590String pkgName = c.getName().getQualifier().toString().replace('.', File.separatorChar);591String className = c.getName().getFlatName().toString().replace('.', SIGC_INNERCLASS) + ".class";592593File file;594if (destDir != null) {595if (pkgName.length() > 0) {596file = new File(destDir, pkgName);597if (!file.exists()) {598file.mkdirs();599}600file = new File(file, className);601} else {602file = new File(destDir, className);603}604} else {605ClassFile classfile = (ClassFile)src.getSource();606if (classfile.isZipped()) {607env.error(0, "cant.write", classfile.getPath());608exitStatus = EXIT_CMDERR;609continue;610}611file = new File(classfile.getPath());612file = new File(file.getParent(), className);613}614615// Create the file616try {617FileOutputStream out = new FileOutputStream(file.getPath());618buf.writeTo(out);619out.close();620621if (env.verbose()) {622output(getText("main.wrote", file.getPath()));623}624} catch (IOException ee) {625env.error(0, "cant.write", file.getPath());626exitStatus = EXIT_CMDERR;627}628629// Print class dependencies if requested (-xdepend)630if (env.print_dependencies()) {631src.printClassDependencies(env);632}633}634}635} while (!done);636} catch (OutOfMemoryError ee) {637// The compiler has run out of memory. Use the error string638// which we preloaded.639env.output(noMemoryErrorString);640exitStatus = EXIT_SYSERR;641return false;642} catch (StackOverflowError ee) {643env.output(stackOverflowErrorString);644exitStatus = EXIT_SYSERR;645return false;646} catch (Error ee) {647// We allow the compiler to take an exception silently if a program648// error has previously been detected. Presumably, this makes the649// compiler more robust in the face of bad error recovery.650if (env.nerrors == 0 || env.dump()) {651ee.printStackTrace();652env.error(0, "fatal.error");653exitStatus = EXIT_ABNORMAL;654}655} catch (Exception ee) {656if (env.nerrors == 0 || env.dump()) {657ee.printStackTrace();658env.error(0, "fatal.exception");659exitStatus = EXIT_ABNORMAL;660}661}662663int ndepfiles = env.deprecationFiles.size();664if (ndepfiles > 0 && env.warnings()) {665int ndeps = env.ndeprecations;666Object file1 = env.deprecationFiles.elementAt(0);667if (env.deprecation()) {668if (ndepfiles > 1) {669env.error(0, "warn.note.deprecations",670new Integer(ndepfiles), new Integer(ndeps));671} else {672env.error(0, "warn.note.1deprecation",673file1, new Integer(ndeps));674}675} else {676if (ndepfiles > 1) {677env.error(0, "warn.note.deprecations.silent",678new Integer(ndepfiles), new Integer(ndeps));679} else {680env.error(0, "warn.note.1deprecation.silent",681file1, new Integer(ndeps));682}683}684}685686env.flushErrors();687env.shutdown();688689boolean status = true;690if (env.nerrors > 0) {691String msg = "";692if (env.nerrors > 1) {693msg = getText("main.errors", env.nerrors);694} else {695msg = getText("main.1error");696}697if (env.nwarnings > 0) {698if (env.nwarnings > 1) {699msg += ", " + getText("main.warnings", env.nwarnings);700} else {701msg += ", " + getText("main.1warning");702}703}704output(msg);705if (exitStatus == EXIT_OK) {706// Allow EXIT_CMDERR or EXIT_ABNORMAL to take precedence.707exitStatus = EXIT_ERROR;708}709status = false;710} else {711if (env.nwarnings > 0) {712if (env.nwarnings > 1) {713output(getText("main.warnings", env.nwarnings));714} else {715output(getText("main.1warning"));716}717}718}719//JCOV720if (env.covdata()) {721Assembler CovAsm = new Assembler();722CovAsm.GenJCov(env);723}724// end JCOV725726// We're done727if (env.verbose()) {728tm = System.currentTimeMillis() - tm;729output(getText("main.done_in", Long.toString(tm)));730}731732return status;733}734735/**736* Main program737*/738public static void main(String argv[]) {739OutputStream out = System.err;740741// This is superceeded by the -Xstdout option, but we leave742// in the old property check for compatibility.743if (Boolean.getBoolean("javac.pipe.output")) {744out = System.out;745}746747Main compiler = new Main(out, "javac");748System.exit(compiler.compile(argv) ? 0 : compiler.exitStatus);749}750}751752753