Main.java :  » 6.0-JDK-Modules-sun » tools » sun » tools » javac » Java Open Source

Java Open Source » 6.0 JDK Modules sun » tools 
tools » sun » tools » javac » Main.java
/*
 * Copyright 1994-2004 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.tools.javac;

import sun.tools.java.*;
import sun.tools.util.CommandLine;
// JCOV
import sun.tools.asm.Assembler;
// end JCOV

import java.util.*;
import java.io.*;
import java.text.MessageFormat;

/**
 * Main program of the Java compiler
 *
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 *
 * @deprecated As of J2SE 1.3, the preferred way to compile Java 
 * language sources is by using the new compiler,
 * com.sun.tools.javac.Main.
 */
@Deprecated
public
class Main implements Constants {
    /**
     * Name of the program.
     */
    String program;

    /**
     * The stream where error message are printed.
     */
    OutputStream out;

    /**
     * Constructor.
     */
    public Main(OutputStream out, String program) {
  this.out = out;
  this.program = program;
    }

    /**
     * Exit status.
     * We introduce a separate integer status variable, and do not alter the
     * convention that 'compile' returns a boolean true upon a successful
     * compilation with no errors.  (JavaTest relies on this.)
     */

    public static final int EXIT_OK = 0;  // Compilation completed with no errors.
    public static final int EXIT_ERROR = 1;  // Compilation completed but reported errors.
    public static final int EXIT_CMDERR = 2;  // Bad command-line arguments and/or switches.
    public static final int EXIT_SYSERR = 3;  // System error or resource exhaustion.
    public static final int EXIT_ABNORMAL = 4;  // Compiler terminated abnormally.

    private int exitStatus;
    
    public int getExitStatus() {
  return exitStatus;
    }

    public boolean compilationPerformedSuccessfully() {
  return exitStatus == EXIT_OK || exitStatus == EXIT_ERROR;
    }
    
    public boolean compilationReportedErrors () {
  return exitStatus != EXIT_OK;
    }

    /**
     * Output a message.
     */
    private void output(String msg) {
  PrintStream out =
      this.out instanceof PrintStream ? (PrintStream)this.out
              : new PrintStream(this.out, true);
  out.println(msg);
    }
    
    /**
     * Top level error message.  This method is called when the
     * environment could not be set up yet.
     */
    private void error(String msg) {
  exitStatus = EXIT_CMDERR;
  output(getText(msg));
    }

    private void error(String msg, String arg1) {
  exitStatus = EXIT_CMDERR;
  output(getText(msg, arg1));
    }

    private void error(String msg, String arg1, String arg2) {
  exitStatus = EXIT_CMDERR;
  output(getText(msg, arg1, arg2));
    }
    
    /**
     * Print usage message and make exit status an error.
     * Note: 'javac' invoked without any arguments is considered
     * be an error.
     */
    public void usage_error() {
  error("main.usage", program);
    }
    
    private static ResourceBundle messageRB;

    /**
     * Initialize ResourceBundle
     */
    static void initResource() {
  try {
      messageRB =
    ResourceBundle.getBundle("sun.tools.javac.resources.javac");
  } catch (MissingResourceException e) {
      throw new Error("Fatal: Resource for javac is missing");
  }
    }
    
    /**
     * get and format message string from resource
     */
    public static String getText(String key) {
  return getText(key, (String)null);
    }
    
    public static String getText(String key, int num) {
  return getText(key, Integer.toString(num));
    }

    public static String getText(String key, String fixed) {
  return getText(key, fixed, null);
    }

    public static String getText(String key, String fixed1, String fixed2) {
  return getText(key, fixed1, fixed2, null);
    }

    public static String getText(String key, String fixed1,
         String fixed2, String fixed3) {
  if (messageRB == null) {
      initResource();
  }
  try {
      String message = messageRB.getString(key);
      return MessageFormat.format(message, fixed1, fixed2, fixed3);
  } catch (MissingResourceException e) {
      if (fixed1 == null)  fixed1 = "null";
      if (fixed2 == null)  fixed2 = "null";
      if (fixed3 == null)  fixed3 = "null";
      String message = "JAVAC MESSAGE FILE IS BROKEN: key={0}, arguments={1}, {2}, {3}";
      return MessageFormat.format(message, key, fixed1, fixed2, fixed3);
  }
    }

    // What major and minor version numbers to use for the -target flag.
    // This should grow every time the minor version number accepted by
    // the VM is incremented.
    private static final String[] releases =      { "1.1", "1.2", "1.3", "1.4" };
    private static final short[] majorVersions =  {    45,    46,    47,    48 };
    private static final short[] minorVersions =  {     3,     0,     0,     0 };

    /**
     * Run the compiler
     */
    public synchronized boolean compile(String argv[]) {
  String sourcePathArg = null;
  String classPathArg = null;
  String sysClassPathArg = null;
  String extDirsArg = null;
  boolean verbosePath = false;

  String targetArg = null;
  short majorVersion = JAVA_DEFAULT_VERSION;
  short minorVersion = JAVA_DEFAULT_MINOR_VERSION;
  
  File destDir = null;
//JCOV
  File covFile = null;
  String optJcov = "-Xjcov";
  String optJcovFile = "-Xjcov:file=";
//end JCOV
  int flags = F_WARNINGS | F_DEBUG_LINES | F_DEBUG_SOURCE;
  long tm = System.currentTimeMillis();
  Vector v = new Vector();
  boolean nowrite = false;
  String props = null;
  String encoding = null;

  // These flags are used to make sure conflicting -O and -g
  // options aren't given.
  String prior_g = null;
  String prior_O = null;
  
  exitStatus = EXIT_OK;

  // Pre-process command line for @file arguments
  try {
      argv = CommandLine.parse(argv);
  } catch (FileNotFoundException e) {
      error("javac.err.cant.read", e.getMessage());
      System.exit(1);
  } catch (IOException e) {
      e.printStackTrace();
      System.exit(1);
  }

  // Parse arguments
  for (int i = 0 ; i < argv.length ; i++) {
      if (argv[i].equals("-g")) {
    if (prior_g!=null && !(prior_g.equals("-g"))) 
       error("main.conflicting.options", prior_g, "-g");
    prior_g = "-g";
    flags |= F_DEBUG_LINES;
    flags |= F_DEBUG_VARS;
    flags |= F_DEBUG_SOURCE;
      } else if (argv[i].equals("-g:none")) {
    if (prior_g!=null && !(prior_g.equals("-g:none")))
       error("main.conflicting.options", prior_g, "-g:none");
    prior_g = "-g:none";
    flags &= ~F_DEBUG_LINES;
    flags &= ~F_DEBUG_VARS;
    flags &= ~F_DEBUG_SOURCE;
      } else if (argv[i].startsWith("-g:")) {
    // We choose to have debugging options conflict even
    // if they amount to the same thing (for example,
    // -g:source,lines and -g:lines,source).  However, multiple
    // debugging options are allowed if they are textually
    // identical.
    if (prior_g!=null && !(prior_g.equals(argv[i])))
       error("main.conflicting.options", prior_g, argv[i]);
    prior_g = argv[i];
    String args = argv[i].substring("-g:".length());
    flags &= ~F_DEBUG_LINES;
    flags &= ~F_DEBUG_VARS;
    flags &= ~F_DEBUG_SOURCE;
    while (true) {
        if (args.startsWith("lines")) {
      flags |= F_DEBUG_LINES;
      args = args.substring("lines".length());
        } else if (args.startsWith("vars")) {
      flags |= F_DEBUG_VARS;
      args = args.substring("vars".length());
        } else if (args.startsWith("source")) {
      flags |= F_DEBUG_SOURCE;
      args = args.substring("source".length());
        } else {
      error("main.bad.debug.option",argv[i]);
      usage_error();
      return false;  // Stop processing now
        }
        if (args.length() == 0) break;
        if (args.startsWith(","))
      args = args.substring(",".length());
    }
      } else if (argv[i].equals("-O")) {
    // -O is accepted for backward compatibility, but
    // is no longer effective.  Use the undocumented
    // -XO option to get the old behavior.
    if (prior_O!=null && !(prior_O.equals("-O")))
        error("main.conflicting.options", prior_O, "-O");
    prior_O = "-O";
      } else if (argv[i].equals("-nowarn")) {
    flags &= ~F_WARNINGS;
      } else if (argv[i].equals("-deprecation")) {
    flags |= F_DEPRECATION;
      } else if (argv[i].equals("-verbose")) {
    flags |= F_VERBOSE;
      } else if (argv[i].equals("-nowrite")) {
    nowrite = true;
      } else if (argv[i].equals("-classpath")) {
    if ((i + 1) < argv.length) {
        if (classPathArg!=null) {
           error("main.option.already.seen","-classpath");
        }
        classPathArg = argv[++i];
    } else {
        error("main.option.requires.argument","-classpath");
        usage_error();
        return false;  // Stop processing now
    }
      } else if (argv[i].equals("-sourcepath")) {
    if ((i + 1) < argv.length) {
        if (sourcePathArg != null) {
      error("main.option.already.seen","-sourcepath");
        }
        sourcePathArg = argv[++i];
    } else {
        error("main.option.requires.argument","-sourcepath");
        usage_error();
        return false;  // Stop processing now
    }
      } else if (argv[i].equals("-sysclasspath")) {
    if ((i + 1) < argv.length) {
        if (sysClassPathArg != null) {
      error("main.option.already.seen","-sysclasspath");
        }
        sysClassPathArg = argv[++i];
    } else {
        error("main.option.requires.argument","-sysclasspath");
        usage_error();
        return false;  // Stop processing now
    }
      } else if (argv[i].equals("-bootclasspath")) {
    if ((i + 1) < argv.length) {
        if (sysClassPathArg != null) {
      error("main.option.already.seen","-bootclasspath");
        }
        sysClassPathArg = argv[++i];
    } else {
        error("main.option.requires.argument","-bootclasspath");
        usage_error();
        return false;  // Stop processing now
    }
      } else if (argv[i].equals("-extdirs")) {
    if ((i + 1) < argv.length) {
        if (extDirsArg != null) {
      error("main.option.already.seen","-extdirs");
        }
        extDirsArg = argv[++i];
    } else {
        error("main.option.requires.argument","-extdirs");
        usage_error();
        return false;  // Stop processing now
    }
            } else if (argv[i].equals("-encoding")) {
                if ((i + 1) < argv.length) {
        if (encoding!=null)
           error("main.option.already.seen","-encoding");
                    encoding = argv[++i];
                } else {
                    error("main.option.requires.argument","-encoding");
                    usage_error();
                    return false; // Stop processing now
                }
      } else if (argv[i].equals("-target")) {
    if ((i + 1) < argv.length) {
        if (targetArg!=null)
           error("main.option.already.seen","-target");
        targetArg = argv[++i];
        int j;
        for (j=0; j<releases.length; j++) {
      if (releases[j].equals(targetArg)) {
          majorVersion = majorVersions[j];
          minorVersion = minorVersions[j];
          break;
      }
        }
        if (j==releases.length) {
      error("main.unknown.release",targetArg);
      usage_error();
      return false; // Stop processing now
        }
    } else {
        error("main.option.requires.argument","-target");
        usage_error();
        return false; // Stop processing now
    }
      } else if (argv[i].equals("-d")) {
    if ((i + 1) < argv.length) {
        if (destDir!=null)
           error("main.option.already.seen","-d");
        destDir = new File(argv[++i]);
        if (!destDir.exists()) {
      error("main.no.such.directory",destDir.getPath());
      usage_error();
      return false; // Stop processing now
        }
    } else {
        error("main.option.requires.argument","-d");
        usage_error();
        return false; // Stop processing now
    }
// JCOV
      } else if (argv[i].equals(optJcov)) {
        flags |= F_COVERAGE;
        flags &= ~F_OPT;
        flags &= ~F_OPT_INTERCLASS;
      } else if ((argv[i].startsWith(optJcovFile)) && 
           (argv[i].length() > optJcovFile.length())) {
        covFile = new File(argv[i].substring(optJcovFile.length()));
        flags &= ~F_OPT;
        flags &= ~F_OPT_INTERCLASS;
        flags |= F_COVERAGE;
        flags |= F_COVDATA;
// end JCOV
      } else if (argv[i].equals("-XO")) {
    // This is what -O used to be.  Now undocumented.
    if (prior_O!=null && !(prior_O.equals("-XO")))
       error("main.conflicting.options", prior_O, "-XO");
    prior_O = "-XO";
    flags |= F_OPT;
      } else if (argv[i].equals("-Xinterclass")) {
    if (prior_O!=null && !(prior_O.equals("-Xinterclass")))
       error("main.conflicting.options", prior_O, "-Xinterclass");
    prior_O = "-Xinterclass";
    flags |= F_OPT;
    flags |= F_OPT_INTERCLASS;
    flags |= F_DEPENDENCIES;
      } else if (argv[i].equals("-Xdepend")) {
    flags |= F_DEPENDENCIES;
      } else if (argv[i].equals("-Xdebug")) {
    flags |= F_DUMP;
      // Unadvertised option used by JWS.  The non-X version should
      // be removed, but we'll leave it in until we find out for 
      // sure that no one still depends on that option syntax.
      } else if (argv[i].equals("-xdepend") || argv[i].equals("-Xjws")) {
    flags |= F_PRINT_DEPENDENCIES;
    // change the default output in this case:
    if (out == System.err) {
        out = System.out;
    }
      } else if (argv[i].equals("-Xstrictdefault")) {
    // Make strict floating point the default
    flags |= F_STRICTDEFAULT;
      } else if (argv[i].equals("-Xverbosepath")) {
    verbosePath = true;
      } else if (argv[i].equals("-Xstdout")) {
    out = System.out;
      } else if (argv[i].equals("-X")) {
    error("main.unsupported.usage");
    return false; // Stop processing now
      } else if (argv[i].equals("-Xversion1.2")) {
    // Inform the compiler that it need not target VMs
    // earlier than version 1.2.  This option is here
    // for testing purposes only.  It is deliberately
    // kept orthogonal to the -target option in 1.2.0
    // for the sake of stability.  These options will
    // be merged in a future release.
    flags |= F_VERSION12;
      } else if (argv[i].endsWith(".java")) {
    v.addElement(argv[i]);
      } else {
    error("main.no.such.option",argv[i]);
    usage_error();
    return false; // Stop processing now
      }
  }
  if (v.size() == 0 || exitStatus == EXIT_CMDERR) {
      usage_error();
      return false;
  }

  // Create our Environment.
  BatchEnvironment env = BatchEnvironment.create(out,
                   sourcePathArg,
                   classPathArg,
                   sysClassPathArg,
                   extDirsArg);
  if (verbosePath) {
      output(getText("main.path.msg",
         env.sourcePath.toString(),
         env.binaryPath.toString()));
  }

  env.flags |= flags;
  env.majorVersion = majorVersion;
  env.minorVersion = minorVersion;
// JCOV
  env.covFile = covFile;
// end JCOV
  env.setCharacterEncoding(encoding);
  
  // Preload the "out of memory" error string just in case we run
  // out of memory during the compile.
  String noMemoryErrorString = getText("main.no.memory");
  String stackOverflowErrorString = getText("main.stack.overflow");

  env.error(0, "warn.class.is.deprecated", "sun.tools.javac.Main");

  try {
      // Parse all input files
      for (Enumeration e = v.elements() ; e.hasMoreElements() ;) {
    File file = new File((String)e.nextElement());
    try {
        env.parseFile(new ClassFile(file));
    } catch (FileNotFoundException ee) {
        env.error(0, "cant.read", file.getPath());
        exitStatus = EXIT_CMDERR;
    }
      }

      // Do a post-read check on all newly-parsed classes,
      // after they have all been read.
      for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) {
    ClassDeclaration c = (ClassDeclaration)e.nextElement();
    if (c.getStatus() == CS_PARSED) {
        if (c.getClassDefinition().isLocal())
      continue;
        try {
      c.getClassDefinition(env);
        } catch (ClassNotFound ee) {
        }
    }
      }

      // compile all classes that need compilation
      ByteArrayOutputStream buf = new ByteArrayOutputStream(4096);
      boolean done;

      do {
    done = true;
    env.flushErrors();
    for (Enumeration e = env.getClasses() ; e.hasMoreElements() ; ) {
        ClassDeclaration c = (ClassDeclaration)e.nextElement();
        SourceClass src;

        switch (c.getStatus()) {
          case CS_UNDEFINED:
      if (!env.dependencies()) {
          break;
      }
      // fall through

          case CS_SOURCE:
      if (tracing)
          env.dtEvent("Main.compile (SOURCE): loading, " + c);
      done = false;
      env.loadDefinition(c);
      if (c.getStatus() != CS_PARSED) {
          if (tracing)
        env.dtEvent("Main.compile (SOURCE): not parsed, " + c);
          break;
      }
      // fall through

          case CS_PARSED:
      if (c.getClassDefinition().isInsideLocal()) {
          // the enclosing block will check this one
          if (tracing)
        env.dtEvent("Main.compile (PARSED): skipping local class, " + c);
          continue;
      }
      done = false;
      if (tracing) env.dtEvent("Main.compile (PARSED): checking, " + c);
      src = (SourceClass)c.getClassDefinition(env);
      src.check(env);
      c.setDefinition(src, CS_CHECKED);
      // fall through
      
          case CS_CHECKED:
      src = (SourceClass)c.getClassDefinition(env);
      // bail out if there were any errors
      if (src.getError()) {
          if (tracing)
        env.dtEvent("Main.compile (CHECKED): bailing out on error, " + c);
          c.setDefinition(src, CS_COMPILED);
          break;
      }
      done = false;
      buf.reset();
      if (tracing)
          env.dtEvent("Main.compile (CHECKED): compiling, " + c);
      src.compile(buf);
      c.setDefinition(src, CS_COMPILED);
      src.cleanup(env);

      if (src.getNestError() || nowrite) {
          continue;
      }

      String pkgName = c.getName().getQualifier().toString().replace('.', File.separatorChar);
      String className = c.getName().getFlatName().toString().replace('.', SIGC_INNERCLASS) + ".class";

      File file;
      if (destDir != null) {
          if (pkgName.length() > 0) {
        file = new File(destDir, pkgName);
        if (!file.exists()) {
            file.mkdirs();
        }
        file = new File(file, className);
          } else {
        file = new File(destDir, className);
          }
      } else {
          ClassFile classfile = (ClassFile)src.getSource();
          if (classfile.isZipped()) {
        env.error(0, "cant.write", classfile.getPath());
        exitStatus = EXIT_CMDERR;
        continue;
          }
          file = new File(classfile.getPath());
          file = new File(file.getParent(), className);
      }

      // Create the file
      try {
          FileOutputStream out = new FileOutputStream(file.getPath());
          buf.writeTo(out);
          out.close();
                            
          if (env.verbose()) {
        output(getText("main.wrote", file.getPath()));
          }
      } catch (IOException ee) {
          env.error(0, "cant.write", file.getPath());
          exitStatus = EXIT_CMDERR;
      }
      
      // Print class dependencies if requested (-xdepend)
      if (env.print_dependencies()) {
          src.printClassDependencies(env);
      }
        }
    }
      } while (!done);
  } catch (OutOfMemoryError ee) {
      // The compiler has run out of memory.  Use the error string
      // which we preloaded.
      env.output(noMemoryErrorString);
      exitStatus = EXIT_SYSERR;
      return false;
  } catch (StackOverflowError ee) {
      env.output(stackOverflowErrorString);
      exitStatus = EXIT_SYSERR;
      return false;
  } catch (Error ee) {
      // We allow the compiler to take an exception silently if a program
      // error has previously been detected.  Presumably, this makes the
      // compiler more robust in the face of bad error recovery.
      if (env.nerrors == 0 || env.dump()) {
    ee.printStackTrace();
    env.error(0, "fatal.error");
    exitStatus = EXIT_ABNORMAL;
      }
  } catch (Exception ee) {
      if (env.nerrors == 0 || env.dump()) {
    ee.printStackTrace();
    env.error(0, "fatal.exception");
    exitStatus = EXIT_ABNORMAL;
      }
  }

  int ndepfiles = env.deprecationFiles.size();
  if (ndepfiles > 0 && env.warnings()) {
      int ndeps = env.ndeprecations;
      Object file1 = env.deprecationFiles.elementAt(0);
      if (env.deprecation()) {
    if (ndepfiles > 1) {
        env.error(0, "warn.note.deprecations",
            new Integer(ndepfiles), new Integer(ndeps));
    } else {
        env.error(0, "warn.note.1deprecation",
            file1, new Integer(ndeps));
    }
      } else {
    if (ndepfiles > 1) {
        env.error(0, "warn.note.deprecations.silent",
            new Integer(ndepfiles), new Integer(ndeps));
    } else {
        env.error(0, "warn.note.1deprecation.silent",
            file1, new Integer(ndeps));
    }
      }
  }

  env.flushErrors();
  env.shutdown();

  boolean status = true;
  if (env.nerrors > 0) {
      String msg = "";
      if (env.nerrors > 1) {
    msg = getText("main.errors", env.nerrors);
      } else {
    msg = getText("main.1error");
      }
      if (env.nwarnings > 0) {
    if (env.nwarnings > 1) {
        msg += ", " + getText("main.warnings", env.nwarnings);
    } else {
        msg += ", " + getText("main.1warning");
    }
      }
      output(msg);
      if (exitStatus == EXIT_OK) {
    // Allow EXIT_CMDERR or EXIT_ABNORMAL to take precedence.
    exitStatus = EXIT_ERROR;
      }
      status = false;
  } else {
      if (env.nwarnings > 0) {
    if (env.nwarnings > 1) {
        output(getText("main.warnings", env.nwarnings));
    } else {
        output(getText("main.1warning"));
    }
      }
  }
//JCOV
  if (env.covdata()) {
            Assembler CovAsm = new Assembler();
            CovAsm.GenJCov(env);
  }
// end JCOV

  // We're done
  if (env.verbose()) {
      tm = System.currentTimeMillis() - tm;
      output(getText("main.done_in", Long.toString(tm)));
  }
  
  return status;
    }

    /**
     * Main program
     */
    public static void main(String argv[]) {
  OutputStream out = System.err;

  // This is superceeded by the -Xstdout option, but we leave
  // in the old property check for compatibility.
  if (Boolean.getBoolean("javac.pipe.output")) {
      out = System.out;
  }

  Main compiler = new Main(out, "javac");
  System.exit(compiler.compile(argv) ? 0 : compiler.exitStatus);
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.