0N/A/*
2362N/A * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.tools.javac;
0N/A
0N/Aimport sun.tools.java.*;
0N/Aimport sun.tools.tree.*;
0N/A
0N/Aimport java.io.IOException;
0N/Aimport java.io.InputStream;
0N/Aimport java.util.Vector;
0N/Aimport java.util.Enumeration;
0N/A
0N/A/**
0N/A * Batch file parser, this needs more work.
0N/A *
0N/A * WARNING: The contents of this source file are not part of any
0N/A * supported API. Code that depends on them does so at its own risk:
0N/A * they are subject to change or removal without notice.
0N/A */
0N/A@Deprecated
0N/Apublic
0N/Aclass BatchParser extends Parser {
0N/A /**
0N/A * The current package
0N/A */
0N/A protected Identifier pkg;
0N/A
0N/A /**
0N/A * The current imports
0N/A */
0N/A protected Imports imports;
0N/A
0N/A /**
0N/A * The classes defined in this file
0N/A */
0N/A protected Vector classes;
0N/A
0N/A
0N/A /**
0N/A * The current class
0N/A */
0N/A protected SourceClass sourceClass;
0N/A
0N/A /**
0N/A * The toplevel environment
0N/A */
0N/A protected Environment toplevelEnv;
0N/A
0N/A /**
0N/A * Create a batch file parser
0N/A */
0N/A public BatchParser(Environment env, InputStream in) throws IOException {
0N/A super(env, in);
0N/A
0N/A imports = new Imports(env);
0N/A classes = new Vector();
0N/A toplevelEnv = imports.newEnvironment(env);
0N/A }
0N/A
0N/A /**
0N/A * Package declaration
0N/A */
0N/A public void packageDeclaration(long where, IdentifierToken t) {
0N/A Identifier nm = t.getName();
0N/A //System.out.println("package " + nm);
0N/A if (pkg == null) {
0N/A // This code has been changed to pass an IdentifierToken,
0N/A // rather than an Identifier, to setCurrentPackage(). Imports
0N/A // now needs the location of the token.
0N/A pkg = t.getName();
0N/A imports.setCurrentPackage(t);
0N/A } else {
0N/A env.error(where, "package.repeated");
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Import class
0N/A */
0N/A public void importClass(long pos, IdentifierToken t) {
0N/A //System.out.println("import class " + t);
0N/A imports.addClass(t);
0N/A }
0N/A
0N/A /**
0N/A * Import package
0N/A */
0N/A public void importPackage(long pos, IdentifierToken t) {
0N/A //System.out.println("import package " + t);
0N/A imports.addPackage(t);
0N/A }
0N/A
0N/A /**
0N/A * Define class
0N/A */
0N/A public ClassDefinition beginClass(long where, String doc, int mod,
0N/A IdentifierToken t,
0N/A IdentifierToken sup,
0N/A IdentifierToken interfaces[]) {
0N/A
0N/A // If this class is nested, the modifier bits set here will
0N/A // be copied into the 'SourceMember' object for the inner class
0N/A // created during the call to 'makeClassDefinition' below.
0N/A // When writing the class file, we will look there for the
0N/A // 'untransformed' modifiers. The modifiers in the ClassDefinition
0N/A // object will end up as the 'transformed' modifiers. Note that
0N/A // there are some bits set here that are not legal class modifiers
0N/A // according to the JVMS, e.g., M_PRIVATE and M_STATIC. These are
0N/A // masked off while writing the class file, but are preserved in
0N/A // the InnerClasses attributes.
0N/A
0N/A if (tracing) toplevelEnv.dtEnter("beginClass: " + sourceClass);
0N/A
0N/A SourceClass outerClass = sourceClass;
0N/A
0N/A if (outerClass == null && pkg != null) {
0N/A t = new IdentifierToken(t.getWhere(),
0N/A Identifier.lookup(pkg, t.getName()));
0N/A }
0N/A
0N/A // The defaults for anonymous and local classes should be documented!
0N/A
0N/A if ((mod & M_ANONYMOUS) != 0) {
0N/A mod |= (M_FINAL | M_PRIVATE);
0N/A }
0N/A if ((mod & M_LOCAL) != 0) {
0N/A mod |= M_PRIVATE;
0N/A }
0N/A
0N/A // Certain modifiers are implied as follows:
0N/A //
0N/A // 1. Any interface (nested or not) is implicitly deemed to be abstract,
0N/A // whether it is explicitly marked so or not. (Java 1.0.)
0N/A // 2. A interface which is a member of a type is implicitly deemed to
0N/A // be static, whether it is explicitly marked so or not. (InnerClasses)
0N/A // 3a. A type which is a member of an interface is implicitly deemed
0N/A // to be public, whether it is explicitly marked so or not. (InnerClasses)
0N/A // 3b. A type which is a member of an interface is implicitly deemed
0N/A // to be static, whether it is explicitly marked so or not. (InnerClasses)
0N/A
0N/A if ((mod & M_INTERFACE) != 0) {
0N/A // Rule 1.
0N/A mod |= M_ABSTRACT;
0N/A if (outerClass != null) {
0N/A // Rule 2.
0N/A mod |= M_STATIC;
0N/A }
0N/A }
0N/A
0N/A if (outerClass != null && outerClass.isInterface()) {
0N/A // Rule 3a.
0N/A // For interface members, neither 'private' nor 'protected'
0N/A // are legal modifiers. We avoid setting M_PUBLIC in some
0N/A // cases in order to avoid interfering with error detection
0N/A // and reporting. This is patched up, after reporting an
0N/A // error, by 'SourceClass.addMember'.
0N/A if ((mod & (M_PRIVATE | M_PROTECTED)) == 0)
0N/A mod |= M_PUBLIC;
0N/A // Rule 3b.
0N/A mod |= M_STATIC;
0N/A }
0N/A
0N/A // For nested classes, we must transform 'protected' to 'public'
0N/A // and 'private' to package scope. This must be done later,
0N/A // because any modifiers set here will be copied into the
0N/A // 'MemberDefinition' for the nested class, which must represent
0N/A // the original untransformed modifiers. Also, compile-time
0N/A // checks should be performed against the actual, untransformed
0N/A // modifiers. This is in contrast to transformations that implement
0N/A // implicit modifiers, such as M_STATIC and M_FINAL for fields
0N/A // of interfaces.
0N/A
0N/A sourceClass = (SourceClass)
0N/A toplevelEnv.makeClassDefinition(toplevelEnv, where, t,
0N/A doc, mod, sup,
0N/A interfaces, outerClass);
0N/A
0N/A sourceClass.getClassDeclaration().setDefinition(sourceClass, CS_PARSED);
0N/A env = new Environment(toplevelEnv, sourceClass);
0N/A
0N/A if (tracing) toplevelEnv.dtEvent("beginClass: SETTING UP DEPENDENCIES");
0N/A
0N/A // The code which adds artificial dependencies between
0N/A // classes in the same source file has been moved to
0N/A // BatchEnvironment#parseFile().
0N/A
0N/A if (tracing) toplevelEnv.dtEvent("beginClass: ADDING TO CLASS LIST");
0N/A
0N/A classes.addElement(sourceClass);
0N/A
0N/A if (tracing) toplevelEnv.dtExit("beginClass: " + sourceClass);
0N/A
0N/A return sourceClass;
0N/A }
0N/A
0N/A /**
0N/A * Report the current class under construction.
0N/A */
0N/A public ClassDefinition getCurrentClass() {
0N/A return sourceClass;
0N/A }
0N/A
0N/A /**
0N/A * End class
0N/A */
0N/A public void endClass(long where, ClassDefinition c) {
0N/A
0N/A if (tracing) toplevelEnv.dtEnter("endClass: " + sourceClass);
0N/A
0N/A // c == sourceClass; don't bother to check
0N/A sourceClass.setEndPosition(where);
0N/A SourceClass outerClass = (SourceClass) sourceClass.getOuterClass();
0N/A sourceClass = outerClass;
0N/A env = toplevelEnv;
0N/A if (sourceClass != null)
0N/A env = new Environment(env, sourceClass);
0N/A
0N/A if (tracing) toplevelEnv.dtExit("endClass: " + sourceClass);
0N/A }
0N/A
0N/A /**
0N/A * Define a method
0N/A */
0N/A public void defineField(long where, ClassDefinition c,
0N/A String doc, int mod, Type t,
0N/A IdentifierToken name, IdentifierToken args[],
0N/A IdentifierToken exp[], Node val) {
0N/A // c == sourceClass; don't bother to check
0N/A Identifier nm = name.getName();
0N/A // Members that are nested classes are not created with 'defineField',
0N/A // so these transformations do not apply to them. See 'beginClass' above.
0N/A if (sourceClass.isInterface()) {
0N/A // Members of interfaces are implicitly public.
0N/A if ((mod & (M_PRIVATE | M_PROTECTED)) == 0)
0N/A // For interface members, neither 'private' nor 'protected'
0N/A // are legal modifiers. Avoid setting M_PUBLIC in some cases
0N/A // to avoid interfering with later error detection. This will
0N/A // be fixed up after the error is reported.
0N/A mod |= M_PUBLIC;
0N/A // Methods of interfaces are implicitly abstract.
0N/A // Fields of interfaces are implicitly static and final.
0N/A if (t.isType(TC_METHOD)) {
0N/A mod |= M_ABSTRACT;
0N/A } else {
0N/A mod |= M_STATIC | M_FINAL;
0N/A }
0N/A }
0N/A if (nm.equals(idInit)) {
0N/A // The parser reports "idInit" when in reality it has found
0N/A // that there is no method name at all present.
0N/A // So, decide if it's really a constructor, or a syntax error.
0N/A Type rt = t.getReturnType();
0N/A Identifier retname = !rt.isType(TC_CLASS) ? idStar /*no match*/
0N/A : rt.getClassName();
0N/A Identifier clsname = sourceClass.getLocalName();
0N/A if (clsname.equals(retname)) {
0N/A t = Type.tMethod(Type.tVoid, t.getArgumentTypes());
0N/A } else if (clsname.equals(retname.getFlatName().getName())) {
0N/A // It appears to be a constructor with spurious qualification.
0N/A t = Type.tMethod(Type.tVoid, t.getArgumentTypes());
0N/A env.error(where, "invalid.method.decl.qual");
0N/A } else if (retname.isQualified() || retname.equals(idStar)) {
0N/A // It appears to be a type name with no method name.
0N/A env.error(where, "invalid.method.decl.name");
0N/A return;
0N/A } else {
0N/A // We assume the type name is missing, even though the
0N/A // simple name that's present might have been intended
0N/A // to be a type: "String (){}" vs. "toString(){}".
0N/A env.error(where, "invalid.method.decl");
0N/A return;
0N/A }
0N/A }
0N/A
0N/A if (args == null && t.isType(TC_METHOD)) {
0N/A args = new IdentifierToken[0];
0N/A }
0N/A
0N/A if (exp == null && t.isType(TC_METHOD)) {
0N/A exp = new IdentifierToken[0];
0N/A }
0N/A
0N/A MemberDefinition f = env.makeMemberDefinition(env, where, sourceClass,
0N/A doc, mod, t, nm,
0N/A args, exp, val);
0N/A if (env.dump()) {
0N/A f.print(System.out);
0N/A }
0N/A }
0N/A}