feat(jdk8): move files to new folder to avoid resources compiled.

This commit is contained in:
2025-09-07 15:25:52 +08:00
parent 3f0047bf6f
commit 8c35cfb1c0
17415 changed files with 217 additions and 213 deletions

View File

@@ -0,0 +1,53 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
/**
* This exception is thrown when an unqualified class name
* is used that can be resolved in more than one way.
*
* 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.
*/
public
class AmbiguousClass extends ClassNotFound {
/**
* The class that was not found
*/
public Identifier name1;
public Identifier name2;
/**
* Constructor
*/
public AmbiguousClass(Identifier name1, Identifier name2) {
super(name1.getName());
this.name1 = name1;
this.name2 = name2;
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.util.Enumeration;
/**
* This exception is thrown when a field reference is
* ambiguous.
*
* 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.
*/
public
class AmbiguousMember extends Exception {
/**
* The field that was not found
*/
public MemberDefinition field1;
public MemberDefinition field2;
/**
* Constructor
*/
public AmbiguousMember(MemberDefinition field1, MemberDefinition field2) {
super(field1.getName() + " + " + field2.getName());
this.field1 = field1;
this.field2 = field2;
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
/**
* This class represents an Java array type.
* It overrides the relevant methods in class Type.
*
* 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.
*
* @author Arthur van Hoff
*/
public final
class ArrayType extends Type {
/**
* The type of the element.
*/
Type elemType;
/**
* Construct an array type. Use Type.tArray to create
* a new array type.
*/
ArrayType(String typeSig, Type elemType) {
super(TC_ARRAY, typeSig);
this.elemType = elemType;
}
public Type getElementType() {
return elemType;
}
public int getArrayDimension() {
return elemType.getArrayDimension() + 1;
}
public String typeString(String id, boolean abbrev, boolean ret) {
return getElementType().typeString(id, abbrev, ret) + "[]";
}
}

View File

@@ -0,0 +1,112 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.io.IOException;
import java.io.DataInputStream;
import java.io.DataOutputStream;
/**
* This class is used to represent an attribute from a binary class.
* This class should go away once arrays are objects.
*
* 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.
*/
public final
class BinaryAttribute implements Constants {
Identifier name;
byte data[];
BinaryAttribute next;
/**
* Constructor
*/
BinaryAttribute(Identifier name, byte data[], BinaryAttribute next) {
this.name = name;
this.data = data;
this.next = next;
}
/**
* Load a list of attributes
*/
public static BinaryAttribute load(DataInputStream in, BinaryConstantPool cpool, int mask) throws IOException {
BinaryAttribute atts = null;
int natt = in.readUnsignedShort(); // JVM 4.6 method_info.attrutes_count
for (int i = 0 ; i < natt ; i++) {
// id from JVM 4.7 attribute_info.attribute_name_index
Identifier id = cpool.getIdentifier(in.readUnsignedShort());
// id from JVM 4.7 attribute_info.attribute_length
int len = in.readInt();
if (id.equals(idCode) && ((mask & ATT_CODE) == 0)) {
in.skipBytes(len);
} else {
byte data[] = new byte[len];
in.readFully(data);
atts = new BinaryAttribute(id, data, atts);
}
}
return atts;
}
// write out the Binary attributes to the given stream
// (note that attributes may be null)
static void write(BinaryAttribute attributes, DataOutputStream out,
BinaryConstantPool cpool, Environment env) throws IOException {
// count the number of attributes
int attributeCount = 0;
for (BinaryAttribute att = attributes; att != null; att = att.next)
attributeCount++;
out.writeShort(attributeCount);
// write out each attribute
for (BinaryAttribute att = attributes; att != null; att = att.next) {
Identifier name = att.name;
byte data[] = att.data;
// write the identifier
out.writeShort(cpool.indexString(name.toString(), env));
// write the length
out.writeInt(data.length);
// write the data
out.write(data, 0, data.length);
}
}
/**
* Accessors
*/
public Identifier getName() { return name; }
public byte getData()[] { return data; }
public BinaryAttribute getNextAttribute() { return next; }
}

View File

@@ -0,0 +1,534 @@
/*
* Copyright (c) 1994, 2006, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.io.IOException;
import java.io.DataInputStream;
import java.io.OutputStream;
import java.io.DataOutputStream;
import java.io.ByteArrayInputStream;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
/**
* 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.
*/
public final
class BinaryClass extends ClassDefinition implements Constants {
BinaryConstantPool cpool;
BinaryAttribute atts;
Vector dependencies;
private boolean haveLoadedNested = false;
/**
* Constructor
*/
public BinaryClass(Object source, ClassDeclaration declaration, int modifiers,
ClassDeclaration superClass, ClassDeclaration interfaces[],
Vector dependencies) {
super(source, 0, declaration, modifiers, null, null);
this.dependencies = dependencies;
this.superClass = superClass;
this.interfaces = interfaces;
}
/**
* Flags used by basicCheck() to avoid duplicate calls.
* (Part of fix for 4105911)
*/
private boolean basicCheckDone = false;
private boolean basicChecking = false;
/**
* Ready a BinaryClass for further checking. Note that, until recently,
* BinaryClass relied on the default basicCheck() provided by
* ClassDefinition. The definition here has been added to ensure that
* the information generated by collectInheritedMethods is available
* for BinaryClasses.
*/
protected void basicCheck(Environment env) throws ClassNotFound {
if (tracing) env.dtEnter("BinaryClass.basicCheck: " + getName());
// We need to guard against duplicate calls to basicCheck(). They
// can lead to calling collectInheritedMethods() for this class
// from within a previous call to collectInheritedMethods() for
// this class. That is not allowed.
// (Part of fix for 4105911)
if (basicChecking || basicCheckDone) {
if (tracing) env.dtExit("BinaryClass.basicCheck: OK " + getName());
return;
}
if (tracing) env.dtEvent("BinaryClass.basicCheck: CHECKING " + getName());
basicChecking = true;
super.basicCheck(env);
// Collect inheritance information.
if (doInheritanceChecks) {
collectInheritedMethods(env);
}
basicCheckDone = true;
basicChecking = false;
if (tracing) env.dtExit("BinaryClass.basicCheck: " + getName());
}
/**
* Load a binary class
*/
public static BinaryClass load(Environment env, DataInputStream in) throws IOException {
return load(env, in, ~(ATT_CODE|ATT_ALLCLASSES));
}
public static BinaryClass load(Environment env,
DataInputStream in, int mask) throws IOException {
// Read the header
int magic = in.readInt(); // JVM 4.1 ClassFile.magic
if (magic != JAVA_MAGIC) {
throw new ClassFormatError("wrong magic: " + magic + ", expected " + JAVA_MAGIC);
}
int minor_version = in.readUnsignedShort(); // JVM 4.1 ClassFile.minor_version
int version = in.readUnsignedShort(); // JVM 4.1 ClassFile.major_version
if (version < JAVA_MIN_SUPPORTED_VERSION) {
throw new ClassFormatError(
sun.tools.javac.Main.getText(
"javac.err.version.too.old",
String.valueOf(version)));
} else if ((version > JAVA_MAX_SUPPORTED_VERSION)
|| (version == JAVA_MAX_SUPPORTED_VERSION
&& minor_version > JAVA_MAX_SUPPORTED_MINOR_VERSION)) {
throw new ClassFormatError(
sun.tools.javac.Main.getText(
"javac.err.version.too.recent",
version+"."+minor_version));
}
// Read the constant pool
BinaryConstantPool cpool = new BinaryConstantPool(in);
// The dependencies of this class
Vector dependencies = cpool.getDependencies(env);
// Read modifiers
int classMod = in.readUnsignedShort() & ACCM_CLASS; // JVM 4.1 ClassFile.access_flags
// Read the class name - from JVM 4.1 ClassFile.this_class
ClassDeclaration classDecl = cpool.getDeclaration(env, in.readUnsignedShort());
// Read the super class name (may be null) - from JVM 4.1 ClassFile.super_class
ClassDeclaration superClassDecl = cpool.getDeclaration(env, in.readUnsignedShort());
// Read the interface names - from JVM 4.1 ClassFile.interfaces_count
ClassDeclaration interfaces[] = new ClassDeclaration[in.readUnsignedShort()];
for (int i = 0 ; i < interfaces.length ; i++) {
// JVM 4.1 ClassFile.interfaces[]
interfaces[i] = cpool.getDeclaration(env, in.readUnsignedShort());
}
// Allocate the class
BinaryClass c = new BinaryClass(null, classDecl, classMod, superClassDecl,
interfaces, dependencies);
c.cpool = cpool;
// Add any additional dependencies
c.addDependency(superClassDecl);
// Read the fields
int nfields = in.readUnsignedShort(); // JVM 4.1 ClassFile.fields_count
for (int i = 0 ; i < nfields ; i++) {
// JVM 4.5 field_info.access_flags
int fieldMod = in.readUnsignedShort() & ACCM_FIELD;
// JVM 4.5 field_info.name_index
Identifier fieldName = cpool.getIdentifier(in.readUnsignedShort());
// JVM 4.5 field_info.descriptor_index
Type fieldType = cpool.getType(in.readUnsignedShort());
BinaryAttribute atts = BinaryAttribute.load(in, cpool, mask);
c.addMember(new BinaryMember(c, fieldMod, fieldType, fieldName, atts));
}
// Read the methods
int nmethods = in.readUnsignedShort(); // JVM 4.1 ClassFile.methods_count
for (int i = 0 ; i < nmethods ; i++) {
// JVM 4.6 method_info.access_flags
int methMod = in.readUnsignedShort() & ACCM_METHOD;
// JVM 4.6 method_info.name_index
Identifier methName = cpool.getIdentifier(in.readUnsignedShort());
// JVM 4.6 method_info.descriptor_index
Type methType = cpool.getType(in.readUnsignedShort());
BinaryAttribute atts = BinaryAttribute.load(in, cpool, mask);
c.addMember(new BinaryMember(c, methMod, methType, methName, atts));
}
// Read the class attributes
c.atts = BinaryAttribute.load(in, cpool, mask);
// See if the SourceFile is known
byte data[] = c.getAttribute(idSourceFile);
if (data != null) {
DataInputStream dataStream = new DataInputStream(new ByteArrayInputStream(data));
// JVM 4.7.2 SourceFile_attribute.sourcefile_index
c.source = cpool.getString(dataStream.readUnsignedShort());
}
// See if the Documentation is know
data = c.getAttribute(idDocumentation);
if (data != null) {
c.documentation = new DataInputStream(new ByteArrayInputStream(data)).readUTF();
}
// Was it compiled as deprecated?
if (c.getAttribute(idDeprecated) != null) {
c.modifiers |= M_DEPRECATED;
}
// Was it synthesized by the compiler?
if (c.getAttribute(idSynthetic) != null) {
c.modifiers |= M_SYNTHETIC;
}
return c;
}
/**
* Called when an environment ties a binary definition to a declaration.
* At this point, auxiliary definitions may be loaded.
*/
public void loadNested(Environment env) {
loadNested(env, 0);
}
public void loadNested(Environment env, int flags) {
// Sanity check.
if (haveLoadedNested) {
// Duplicate calls most likely should not occur, but they do
// in javap. Be tolerant of them for the time being.
// throw new CompilerError("multiple loadNested");
if (tracing) env.dtEvent("loadNested: DUPLICATE CALL SKIPPED");
return;
}
haveLoadedNested = true;
// Read class-nesting information.
try {
byte data[];
data = getAttribute(idInnerClasses);
if (data != null) {
initInnerClasses(env, data, flags);
}
} catch (IOException ee) {
// The inner classes attribute is not well-formed.
// It may, for example, contain no data. Report this.
// We used to throw a CompilerError here (bug 4095108).
env.error(0, "malformed.attribute", getClassDeclaration(),
idInnerClasses);
if (tracing)
env.dtEvent("loadNested: MALFORMED ATTRIBUTE (InnerClasses)");
}
}
private void initInnerClasses(Environment env,
byte data[],
int flags) throws IOException {
DataInputStream ds = new DataInputStream(new ByteArrayInputStream(data));
int nrec = ds.readUnsignedShort(); // InnerClasses_attribute.number_of_classes
for (int i = 0; i < nrec; i++) {
// For each inner class name transformation, we have a record
// with the following fields:
//
// u2 inner_class_info_index; // CONSTANT_Class_info index
// u2 outer_class_info_index; // CONSTANT_Class_info index
// u2 inner_name_index; // CONSTANT_Utf8_info index
// u2 inner_class_access_flags; // access_flags bitmask
//
// The spec states that outer_class_info_index is 0 iff
// the inner class is not a member of its enclosing class (i.e.
// it is a local or anonymous class). The spec also states
// that if a class is anonymous then inner_name_index should
// be 0.
//
// Prior to jdk1.2, javac did not implement the spec. Instead
// it <em>always</em> set outer_class_info_index to the
// enclosing outer class and if the class was anonymous,
// it set inner_name_index to be the index of a CONSTANT_Utf8
// entry containing the null string "" (idNull). This code is
// designed to handle either kind of class file.
//
// See also the compileClass() method in SourceClass.java.
// Read in the inner_class_info
// InnerClasses_attribute.classes.inner_class_info_index
int inner_index = ds.readUnsignedShort();
// could check for zero.
ClassDeclaration inner = cpool.getDeclaration(env, inner_index);
// Read in the outer_class_info. Note that the index will be
// zero if the class is "not a member".
ClassDeclaration outer = null;
// InnerClasses_attribute.classes.outer_class_info_index
int outer_index = ds.readUnsignedShort();
if (outer_index != 0) {
outer = cpool.getDeclaration(env, outer_index);
}
// Read in the inner_name_index. This may be zero. An anonymous
// class will either have an inner_nm_index of zero (as the spec
// dictates) or it will have an inner_nm of idNull (for classes
// generated by pre-1.2 compilers). Handle both.
Identifier inner_nm = idNull;
// InnerClasses_attribute.classes.inner_name_index
int inner_nm_index = ds.readUnsignedShort();
if (inner_nm_index != 0) {
inner_nm = Identifier.lookup(cpool.getString(inner_nm_index));
}
// Read in the modifiers for the inner class.
// InnerClasses_attribute.classes.inner_name_index
int mods = ds.readUnsignedShort();
// Is the class accessible?
// The old code checked for
//
// (!inner_nm.equals(idNull) && (mods & M_PRIVATE) == 0)
//
// which we will preserve to keep it working for class files
// generated by 1.1 compilers. In addition we check for
//
// (outer != null)
//
// as an additional check that only makes sense with 1.2
// generated files. Note that it is entirely possible that
// the M_PRIVATE bit is always enough. We are being
// conservative here.
//
// The ATT_ALLCLASSES flag causes the M_PRIVATE modifier
// to be ignored, and is used by tools such as 'javap' that
// wish to examine all classes regardless of the normal access
// controls that apply during compilation. Note that anonymous
// and local classes are still not considered accessible, though
// named local classes in jdk1.1 may slip through. Note that
// this accessibility test is an optimization, and it is safe to
// err on the side of greater accessibility.
boolean accessible =
(outer != null) &&
(!inner_nm.equals(idNull)) &&
((mods & M_PRIVATE) == 0 ||
(flags & ATT_ALLCLASSES) != 0);
// The reader should note that there has been a significant change
// in the way that the InnerClasses attribute is being handled.
// In particular, previously the compiler called initInner() for
// <em>every</em> inner class. Now the compiler does not call
// initInner() if the inner class is inaccessible. This means
// that inaccessible inner classes don't have any of the processing
// from initInner() done for them: fixing the access flags,
// setting outerClass, setting outerMember in their outerClass,
// etc. We believe this is fine: if the class is inaccessible
// and binary, then everyone who needs to see its internals
// has already been compiled. Hopefully.
if (accessible) {
Identifier nm =
Identifier.lookupInner(outer.getName(), inner_nm);
// Tell the type module about the nesting relation:
Type.tClass(nm);
if (inner.equals(getClassDeclaration())) {
// The inner class in the record is this class.
try {
ClassDefinition outerClass = outer.getClassDefinition(env);
initInner(outerClass, mods);
} catch (ClassNotFound e) {
// report the error elsewhere
}
} else if (outer.equals(getClassDeclaration())) {
// The outer class in the record is this class.
try {
ClassDefinition innerClass =
inner.getClassDefinition(env);
initOuter(innerClass, mods);
} catch (ClassNotFound e) {
// report the error elsewhere
}
}
}
}
}
private void initInner(ClassDefinition outerClass, int mods) {
if (getOuterClass() != null)
return; // already done
/******
// Maybe set static, protected, or private.
if ((modifiers & M_PUBLIC) != 0)
mods &= M_STATIC;
else
mods &= M_PRIVATE | M_PROTECTED | M_STATIC;
modifiers |= mods;
******/
// For an inner class, the class access may have been weakened
// from that originally declared the source. We must take the
// actual access permissions against which we check any source
// we are currently compiling from the InnerClasses attribute.
// We attempt to guard here against bogus combinations of modifiers.
if ((mods & M_PRIVATE) != 0) {
// Private cannot be combined with public or protected.
mods &= ~(M_PUBLIC | M_PROTECTED);
} else if ((mods & M_PROTECTED) != 0) {
// Protected cannot be combined with public.
mods &= ~M_PUBLIC;
}
if ((mods & M_INTERFACE) != 0) {
// All interfaces are implicitly abstract.
// All interfaces that are members of a type are implicitly static.
mods |= (M_ABSTRACT | M_STATIC);
}
if (outerClass.isInterface()) {
// All types that are members of interfaces are implicitly
// public and static.
mods |= (M_PUBLIC | M_STATIC);
mods &= ~(M_PRIVATE | M_PROTECTED);
}
modifiers = mods;
setOuterClass(outerClass);
for (MemberDefinition field = getFirstMember();
field != null;
field = field.getNextMember()) {
if (field.isUplevelValue()
&& outerClass.getType().equals(field.getType())
&& field.getName().toString().startsWith(prefixThis)) {
setOuterMember(field);
}
}
}
private void initOuter(ClassDefinition innerClass, int mods) {
if (innerClass instanceof BinaryClass)
((BinaryClass)innerClass).initInner(this, mods);
addMember(new BinaryMember(innerClass));
}
/**
* Write the class out to a given stream. This function mirrors the loader.
*/
public void write(Environment env, OutputStream out) throws IOException {
DataOutputStream data = new DataOutputStream(out);
// write out the header
data.writeInt(JAVA_MAGIC);
data.writeShort(env.getMinorVersion());
data.writeShort(env.getMajorVersion());
// Write out the constant pool
cpool.write(data, env);
// Write class information
data.writeShort(getModifiers() & ACCM_CLASS);
data.writeShort(cpool.indexObject(getClassDeclaration(), env));
data.writeShort((getSuperClass() != null)
? cpool.indexObject(getSuperClass(), env) : 0);
data.writeShort(interfaces.length);
for (int i = 0 ; i < interfaces.length ; i++) {
data.writeShort(cpool.indexObject(interfaces[i], env));
}
// count the fields and the methods
int fieldCount = 0, methodCount = 0;
for (MemberDefinition f = firstMember; f != null; f = f.getNextMember())
if (f.isMethod()) methodCount++; else fieldCount++;
// write out each the field count, and then each field
data.writeShort(fieldCount);
for (MemberDefinition f = firstMember; f != null; f = f.getNextMember()) {
if (!f.isMethod()) {
data.writeShort(f.getModifiers() & ACCM_FIELD);
String name = f.getName().toString();
String signature = f.getType().getTypeSignature();
data.writeShort(cpool.indexString(name, env));
data.writeShort(cpool.indexString(signature, env));
BinaryAttribute.write(((BinaryMember)f).atts, data, cpool, env);
}
}
// write out each method count, and then each method
data.writeShort(methodCount);
for (MemberDefinition f = firstMember; f != null; f = f.getNextMember()) {
if (f.isMethod()) {
data.writeShort(f.getModifiers() & ACCM_METHOD);
String name = f.getName().toString();
String signature = f.getType().getTypeSignature();
data.writeShort(cpool.indexString(name, env));
data.writeShort(cpool.indexString(signature, env));
BinaryAttribute.write(((BinaryMember)f).atts, data, cpool, env);
}
}
// write out the class attributes
BinaryAttribute.write(atts, data, cpool, env);
data.flush();
}
/**
* Get the dependencies
*/
public Enumeration getDependencies() {
return dependencies.elements();
}
/**
* Add a dependency
*/
public void addDependency(ClassDeclaration c) {
if ((c != null) && !dependencies.contains(c)) {
dependencies.addElement(c);
}
}
/**
* Get the constant pool
*/
public BinaryConstantPool getConstants() {
return cpool;
}
/**
* Get a class attribute
*/
public byte getAttribute(Identifier name)[] {
for (BinaryAttribute att = atts ; att != null ; att = att.next) {
if (att.name.equals(name)) {
return att.data;
}
}
return null;
}
}

View File

@@ -0,0 +1,111 @@
/*
* Copyright (c) 1995, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.io.*;
/**
* 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.
*/
public class BinaryCode implements Constants {
int maxStack; // maximum stack used by code
int maxLocals; // maximum locals used by code
BinaryExceptionHandler exceptionHandlers[];
BinaryAttribute atts; // code attributes
BinaryConstantPool cpool; // constant pool of the class
byte code[]; // the byte code
/**
* Construct the binary code from the code attribute
*/
public
BinaryCode(byte data[], BinaryConstantPool cpool, Environment env) {
DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
try {
this.cpool = cpool;
// JVM 4.7.4 CodeAttribute.max_stack
this.maxStack = in.readUnsignedShort();
// JVM 4.7.4 CodeAttribute.max_locals
this.maxLocals = in.readUnsignedShort();
// JVM 4.7.4 CodeAttribute.code_length
int code_length = in.readInt();
this.code = new byte[code_length];
// JVM 4.7.4 CodeAttribute.code[]
in.read(this.code);
// JVM 4.7.4 CodeAttribute.exception_table_length
int exception_count = in.readUnsignedShort();
this.exceptionHandlers = new BinaryExceptionHandler[exception_count];
for (int i = 0; i < exception_count; i++) {
// JVM 4.7.4 CodeAttribute.exception_table.start_pc
int start = in.readUnsignedShort();
// JVM 4.7.4 CodeAttribute.exception_table.end_pc
int end = in.readUnsignedShort();
// JVM 4.7.4 CodeAttribute.exception_table.handler_pc
int handler = in.readUnsignedShort();
// JVM 4.7.4 CodeAttribute.exception_table.catch_type
ClassDeclaration xclass = cpool.getDeclaration(env, in.readUnsignedShort());
this.exceptionHandlers[i] =
new BinaryExceptionHandler(start, end, handler, xclass);
}
this.atts = BinaryAttribute.load(in, cpool, ~0);
if (in.available() != 0) {
System.err.println("Should have exhausted input stream!");
}
} catch (IOException e) {
throw new CompilerError(e);
}
}
/**
* Accessors
*/
public BinaryExceptionHandler getExceptionHandlers()[] {
return exceptionHandlers;
}
public byte getCode()[] { return code; }
public int getMaxStack() { return maxStack; }
public int getMaxLocals() { return maxLocals; }
public BinaryAttribute getAttributes() { return atts; }
/**
* Load a binary class
*/
public static
BinaryCode load(BinaryMember bf, BinaryConstantPool cpool, Environment env) {
byte code[] = bf.getAttribute(idCode);
return (code != null) ? new BinaryCode(code, cpool, env) : null;
}
}

View File

@@ -0,0 +1,351 @@
/*
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.io.IOException;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.util.Vector;
import java.util.Hashtable;
/**
* This class is used to represent a constant table once
* it is read from a class file.
*
* 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.
*/
public final
class BinaryConstantPool implements Constants {
private byte types[];
private Object cpool[];
/**
* Constructor
*/
BinaryConstantPool(DataInputStream in) throws IOException {
// JVM 4.1 ClassFile.constant_pool_count
types = new byte[in.readUnsignedShort()];
cpool = new Object[types.length];
for (int i = 1 ; i < cpool.length ; i++) {
int j = i;
// JVM 4.4 cp_info.tag
switch(types[i] = in.readByte()) {
case CONSTANT_UTF8:
cpool[i] = in.readUTF();
break;
case CONSTANT_INTEGER:
cpool[i] = new Integer(in.readInt());
break;
case CONSTANT_FLOAT:
cpool[i] = new Float(in.readFloat());
break;
case CONSTANT_LONG:
cpool[i++] = new Long(in.readLong());
break;
case CONSTANT_DOUBLE:
cpool[i++] = new Double(in.readDouble());
break;
case CONSTANT_CLASS:
case CONSTANT_STRING:
// JVM 4.4.3 CONSTANT_String_info.string_index
// or JVM 4.4.1 CONSTANT_Class_info.name_index
cpool[i] = new Integer(in.readUnsignedShort());
break;
case CONSTANT_FIELD:
case CONSTANT_METHOD:
case CONSTANT_INTERFACEMETHOD:
case CONSTANT_NAMEANDTYPE:
// JVM 4.4.2 CONSTANT_*ref_info.class_index & name_and_type_index
cpool[i] = new Integer((in.readUnsignedShort() << 16) | in.readUnsignedShort());
break;
case CONSTANT_METHODHANDLE:
cpool[i] = readBytes(in, 3);
break;
case CONSTANT_METHODTYPE:
cpool[i] = readBytes(in, 2);
break;
case CONSTANT_INVOKEDYNAMIC:
cpool[i] = readBytes(in, 4);
break;
case 0:
default:
throw new ClassFormatError("invalid constant type: " + (int)types[i]);
}
}
}
private byte[] readBytes(DataInputStream in, int cnt) throws IOException {
byte[] b = new byte[cnt];
in.readFully(b);
return b;
}
/**
* get a integer
*/
public int getInteger(int n) {
return (n == 0) ? 0 : ((Number)cpool[n]).intValue();
}
/**
* get a value
*/
public Object getValue(int n) {
return (n == 0) ? null : cpool[n];
}
/**
* get a string
*/
public String getString(int n) {
return (n == 0) ? null : (String)cpool[n];
}
/**
* get an identifier
*/
public Identifier getIdentifier(int n) {
return (n == 0) ? null : Identifier.lookup(getString(n));
}
/**
* get class declaration
*/
public ClassDeclaration getDeclarationFromName(Environment env, int n) {
return (n == 0) ? null : env.getClassDeclaration(Identifier.lookup(getString(n).replace('/','.')));
}
/**
* get class declaration
*/
public ClassDeclaration getDeclaration(Environment env, int n) {
return (n == 0) ? null : getDeclarationFromName(env, getInteger(n));
}
/**
* get a type from a type signature
*/
public Type getType(int n) {
return Type.tType(getString(n));
}
/**
* get the type of constant given an index
*/
public int getConstantType(int n) {
return types[n];
}
/**
* get the n-th constant from the constant pool
*/
public Object getConstant(int n, Environment env) {
int constant_type = getConstantType(n);
switch (constant_type) {
case CONSTANT_INTEGER:
case CONSTANT_FLOAT:
case CONSTANT_LONG:
case CONSTANT_DOUBLE:
case CONSTANT_METHODHANDLE:
case CONSTANT_METHODTYPE:
case CONSTANT_INVOKEDYNAMIC:
return getValue(n);
case CONSTANT_CLASS:
return getDeclaration(env, n);
case CONSTANT_STRING:
return getString(getInteger(n));
case CONSTANT_FIELD:
case CONSTANT_METHOD:
case CONSTANT_INTERFACEMETHOD:
try {
int key = getInteger(n);
ClassDefinition clazz =
getDeclaration(env, key >> 16).getClassDefinition(env);
int name_and_type = getInteger(key & 0xFFFF);
Identifier id = getIdentifier(name_and_type >> 16);
Type type = getType(name_and_type & 0xFFFF);
for (MemberDefinition field = clazz.getFirstMatch(id);
field != null;
field = field.getNextMatch()) {
Type field_type = field.getType();
if ((constant_type == CONSTANT_FIELD)
? (field_type == type)
: (field_type.equalArguments(type)))
return field;
}
} catch (ClassNotFound e) {
}
return null;
default:
throw new ClassFormatError("invalid constant type: " +
constant_type);
}
}
/**
* Get a list of dependencies, ie: all the classes referenced in this
* constant pool.
*/
public Vector getDependencies(Environment env) {
Vector v = new Vector();
for (int i = 1 ; i < cpool.length ; i++) {
switch(types[i]) {
case CONSTANT_CLASS:
v.addElement(getDeclarationFromName(env, getInteger(i)));
break;
}
}
return v;
}
Hashtable indexHashObject, indexHashAscii;
Vector MoreStuff;
/**
* Find the index of an Object in the constant pool
*/
public int indexObject(Object obj, Environment env) {
if (indexHashObject == null)
createIndexHash(env);
Integer result = (Integer)indexHashObject.get(obj);
if (result == null)
throw new IndexOutOfBoundsException("Cannot find object " + obj + " of type " +
obj.getClass() + " in constant pool");
return result.intValue();
}
/**
* Find the index of an ascii string in the constant pool. If it's not in
* the constant pool, then add it at the end.
*/
public int indexString(String string, Environment env) {
if (indexHashObject == null)
createIndexHash(env);
Integer result = (Integer)indexHashAscii.get(string);
if (result == null) {
if (MoreStuff == null) MoreStuff = new Vector();
result = new Integer(cpool.length + MoreStuff.size());
MoreStuff.addElement(string);
indexHashAscii.put(string, result);
}
return result.intValue();
}
/**
* Create a hash table of all the items in the constant pool that could
* possibly be referenced from the outside.
*/
public void createIndexHash(Environment env) {
indexHashObject = new Hashtable();
indexHashAscii = new Hashtable();
for (int i = 1; i < cpool.length; i++) {
if (types[i] == CONSTANT_UTF8) {
indexHashAscii.put(cpool[i], new Integer(i));
} else {
try {
indexHashObject.put(getConstant(i, env), new Integer(i));
} catch (ClassFormatError e) { }
}
}
}
/**
* Write out the contents of the constant pool, including any additions
* that have been added.
*/
public void write(DataOutputStream out, Environment env) throws IOException {
int length = cpool.length;
if (MoreStuff != null)
length += MoreStuff.size();
out.writeShort(length);
for (int i = 1 ; i < cpool.length; i++) {
int type = types[i];
Object x = cpool[i];
out.writeByte(type);
switch (type) {
case CONSTANT_UTF8:
out.writeUTF((String) x);
break;
case CONSTANT_INTEGER:
out.writeInt(((Number)x).intValue());
break;
case CONSTANT_FLOAT:
out.writeFloat(((Number)x).floatValue());
break;
case CONSTANT_LONG:
out.writeLong(((Number)x).longValue());
i++;
break;
case CONSTANT_DOUBLE:
out.writeDouble(((Number)x).doubleValue());
i++;
break;
case CONSTANT_CLASS:
case CONSTANT_STRING:
out.writeShort(((Number)x).intValue());
break;
case CONSTANT_FIELD:
case CONSTANT_METHOD:
case CONSTANT_INTERFACEMETHOD:
case CONSTANT_NAMEANDTYPE: {
int value = ((Number)x).intValue();
out.writeShort(value >> 16);
out.writeShort(value & 0xFFFF);
break;
}
case CONSTANT_METHODHANDLE:
case CONSTANT_METHODTYPE:
case CONSTANT_INVOKEDYNAMIC:
out.write((byte[])x, 0, ((byte[])x).length);
break;
default:
throw new ClassFormatError("invalid constant type: "
+ (int)types[i]);
}
}
for (int i = cpool.length; i < length; i++) {
String string = (String)(MoreStuff.elementAt(i - cpool.length));
out.writeByte(CONSTANT_UTF8);
out.writeUTF(string);
}
}
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (c) 1995, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
/**
* A single exception handler. This class hangs off BinaryCode.
*
* 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.
*/
public class BinaryExceptionHandler {
public int startPC;
public int endPC;
public int handlerPC;
public ClassDeclaration exceptionClass;
BinaryExceptionHandler(int start, int end,
int handler, ClassDeclaration xclass) {
startPC = start;
endPC = end;
handlerPC = handler;
exceptionClass = xclass;
}
}

View File

@@ -0,0 +1,260 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import sun.tools.tree.*;
import java.util.Vector;
import java.util.Hashtable;
import java.io.IOException;
import java.io.DataInputStream;
import java.io.ByteArrayInputStream;
/**
* This class represents a binary member
*
* 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.
*/
public final
class BinaryMember extends MemberDefinition {
Expression value;
BinaryAttribute atts;
/**
* Constructor
*/
public BinaryMember(ClassDefinition clazz, int modifiers, Type type,
Identifier name, BinaryAttribute atts) {
super(0, clazz, modifiers, type, name, null, null);
this.atts = atts;
// Was it compiled as deprecated?
if (getAttribute(idDeprecated) != null) {
this.modifiers |= M_DEPRECATED;
}
// Was it synthesized by the compiler?
if (getAttribute(idSynthetic) != null) {
this.modifiers |= M_SYNTHETIC;
}
}
/**
* Constructor for an inner class.
*/
public BinaryMember(ClassDefinition innerClass) {
super(innerClass);
}
/**
* Inline allowed (currently only allowed for the constructor of Object).
*/
public boolean isInlineable(Environment env, boolean fromFinal) {
// It is possible for 'getSuperClass()' to return null due to error
// recovery from cyclic inheritace. Can this cause a problem here?
return isConstructor() && (getClassDefinition().getSuperClass() == null);
}
/**
* Get arguments
*/
public Vector getArguments() {
if (isConstructor() && (getClassDefinition().getSuperClass() == null)) {
Vector v = new Vector();
v.addElement(new LocalMember(0, getClassDefinition(), 0,
getClassDefinition().getType(), idThis));
return v;
}
return null;
}
/**
* Get exceptions
*/
public ClassDeclaration[] getExceptions(Environment env) {
if ((!isMethod()) || (exp != null)) {
return exp;
}
byte data[] = getAttribute(idExceptions);
if (data == null) {
return new ClassDeclaration[0];
}
try {
BinaryConstantPool cpool = ((BinaryClass)getClassDefinition()).getConstants();
DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
// JVM 4.7.5 Exceptions_attribute.number_of_exceptions
int n = in.readUnsignedShort();
exp = new ClassDeclaration[n];
for (int i = 0 ; i < n ; i++) {
// JVM 4.7.5 Exceptions_attribute.exception_index_table[]
exp[i] = cpool.getDeclaration(env, in.readUnsignedShort());
}
return exp;
} catch (IOException e) {
throw new CompilerError(e);
}
}
/**
* Get documentation
*/
public String getDocumentation() {
if (documentation != null) {
return documentation;
}
byte data[] = getAttribute(idDocumentation);
if (data == null) {
return null;
}
try {
return documentation = new DataInputStream(new ByteArrayInputStream(data)).readUTF();
} catch (IOException e) {
throw new CompilerError(e);
}
}
/**
* Check if constant: Will it inline away to a constant?
* This override is needed to solve bug 4128266. It is also
* integral to the solution of 4119776.
*/
private boolean isConstantCache = false;
private boolean isConstantCached = false;
public boolean isConstant() {
if (!isConstantCached) {
isConstantCache = isFinal()
&& isVariable()
&& getAttribute(idConstantValue) != null;
isConstantCached = true;
}
return isConstantCache;
}
/**
* Get the value
*/
public Node getValue(Environment env) {
if (isMethod()) {
return null;
}
if (!isFinal()) {
return null;
}
if (getValue() != null) {
return (Expression)getValue();
}
byte data[] = getAttribute(idConstantValue);
if (data == null) {
return null;
}
try {
BinaryConstantPool cpool = ((BinaryClass)getClassDefinition()).getConstants();
// JVM 4.7.3 ConstantValue.constantvalue_index
Object obj = cpool.getValue(new DataInputStream(new ByteArrayInputStream(data)).readUnsignedShort());
switch (getType().getTypeCode()) {
case TC_BOOLEAN:
setValue(new BooleanExpression(0, ((Number)obj).intValue() != 0));
break;
case TC_BYTE:
case TC_SHORT:
case TC_CHAR:
case TC_INT:
setValue(new IntExpression(0, ((Number)obj).intValue()));
break;
case TC_LONG:
setValue(new LongExpression(0, ((Number)obj).longValue()));
break;
case TC_FLOAT:
setValue(new FloatExpression(0, ((Number)obj).floatValue()));
break;
case TC_DOUBLE:
setValue(new DoubleExpression(0, ((Number)obj).doubleValue()));
break;
case TC_CLASS:
setValue(new StringExpression(0, (String)cpool.getValue(((Number)obj).intValue())));
break;
}
return (Expression)getValue();
} catch (IOException e) {
throw new CompilerError(e);
}
}
/**
* Get a field attribute
*/
public byte[] getAttribute(Identifier name) {
for (BinaryAttribute att = atts ; att != null ; att = att.next) {
if (att.name.equals(name)) {
return att.data;
}
}
return null;
}
public boolean deleteAttribute(Identifier name) {
BinaryAttribute walker = null, next = null;
boolean succeed = false;
while (atts.name.equals(name)) {
atts = atts.next;
succeed = true;
}
for (walker = atts; walker != null; walker = next) {
next = walker.next;
if (next != null) {
if (next.name.equals(name)) {
walker.next = next.next;
next = next.next;
succeed = true;
}
}
}
for (walker = atts; walker != null; walker = walker.next) {
if (walker.name.equals(name)) {
throw new InternalError("Found attribute " + name);
}
}
return succeed;
}
/*
* Add an attribute to a field
*/
public void addAttribute(Identifier name, byte data[], Environment env) {
this.atts = new BinaryAttribute(name, data, this.atts);
// Make sure that the new attribute is in the constant pool
((BinaryClass)(this.clazz)).cpool.indexString(name.toString(), env);
}
}

View File

@@ -0,0 +1,270 @@
/*
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
/**
* This class represents an Java class declaration. It refers
* to either a binary or source definition.
*
* ClassDefinitions are loaded on demand, this means that
* class declarations are late bound. The definition of the
* class is obtained in stages. The status field describes
* the state of the class definition:
*
* CS_UNDEFINED - the definition is not yet loaded
* CS_UNDECIDED - a binary definition is loaded, but it is
* still unclear if the source definition need to
* be loaded
* CS_BINARY - the binary class is loaded
* CS_PARSED - the class is loaded from the source file, the
* type information is available, but the class has
* not yet been compiled.
* CS_CHECKED - the class is loaded from the source file and has
* been type-checked.
* CS_COMPILED - the class has been type checked, compiled,
* and written out.
* CS_NOTFOUND - no class definition could be found
*
* 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.
*/
public final
class ClassDeclaration implements Constants {
int status;
Type type;
ClassDefinition definition;
/**
* Constructor
*/
public ClassDeclaration(Identifier name) {
this.type = Type.tClass(name);
}
/**
* Get the status of the class
*/
public int getStatus() {
return status;
}
/**
* Get the name of the class
*/
public Identifier getName() {
return type.getClassName();
}
/**
* Get the type of the class
*/
public Type getType() {
return type;
}
/**
* Check if the class is defined
*/
public boolean isDefined() {
switch (status) {
case CS_BINARY:
case CS_PARSED:
case CS_CHECKED:
case CS_COMPILED:
return true;
}
return false;
}
/**
* Get the definition of this class. Returns null if
* the class is not yet defined.
*/
public ClassDefinition getClassDefinition() {
return definition;
}
/**
* This is a flag for use by getClassDefinition(env). It is
* used to mark that a class has been successfully looked up
* by that method before.
*/
private boolean found = false;
/**
* Get the definition of this class, if the class is not
* yet defined, load the definition. Loading a class may
* throw various exceptions.
*/
public ClassDefinition getClassDefinition(Environment env)
throws ClassNotFound {
if (tracing) env.dtEvent("getClassDefinition: " +
getName() + ", status " + getStatus());
// The majority of calls to getClassDefinition() are duplicates.
// This check makes them fast. It also allows us to avoid
// duplicate, useless calls to basicCheck(). In the future it
// would be good to add an additional status value, CS_BASICCHECKED.
if (found) {
return definition;
}
for(;;) {
switch (status) {
case CS_UNDEFINED:
case CS_UNDECIDED:
case CS_SOURCE:
env.loadDefinition(this);
break;
case CS_BINARY:
case CS_PARSED:
//+FIX FOR BUGID 4056065
//definition.basicCheck(env);
if (!definition.isInsideLocal()) {
// Classes inside a block, including anonymous classes,
// are checked when their surrounding member is checked.
definition.basicCheck(env);
}
//-FIX FOR BUGID 4056065
found = true;
return definition;
case CS_CHECKED:
case CS_COMPILED:
found = true;
return definition;
default:
throw new ClassNotFound(getName());
}
}
}
/**
* Get the definition of this class, if the class is not
* yet defined, load the definition. Loading a class may
* throw various exceptions. Perform no basicCheck() on this
* class.
*/
public ClassDefinition getClassDefinitionNoCheck(Environment env) throws ClassNotFound {
if (tracing) env.dtEvent("getClassDefinition: " +
getName() + ", status " + getStatus());
for(;;) {
switch (status) {
case CS_UNDEFINED:
case CS_UNDECIDED:
case CS_SOURCE:
env.loadDefinition(this);
break;
case CS_BINARY:
case CS_PARSED:
case CS_CHECKED:
case CS_COMPILED:
return definition;
default:
throw new ClassNotFound(getName());
}
}
}
/**
* Set the class definition
*/
public void setDefinition(ClassDefinition definition, int status) {
// Sanity checks.
// The name of the definition should match that of the declaration.
if ((definition != null) && !getName().equals(definition.getName())) {
throw new CompilerError("setDefinition: name mismatch: " +
this + ", " + definition);
}
// The status states can be considered ordered in the same
// manner as their numerical values. We expect classes to
// progress through a sequence of monotonically increasing
// states. NOTE: There are currently exceptions to this rule
// which are believed to be legitimate. In particular, a
// class may be checked more than once, though we believe that
// this is unnecessary and may be avoided.
/*-----------------*
if (status <= this.status) {
System.out.println("STATUS REGRESSION: " +
this + " FROM " + this.status + " TO " + status);
}
*------------------*/
this.definition = definition;
this.status = status;
}
/**
* Equality
*/
public boolean equals(Object obj) {
if (obj instanceof ClassDeclaration) {
return type.equals(((ClassDeclaration)obj).type);
}
return false;
}
@Override
public int hashCode() {
return type.hashCode();
}
/**
* toString
*/
public String toString() {
String name = getName().toString();
String type = "type ";
String nested = getName().isInner() ? "nested " : "";
if (getClassDefinition() != null) {
if (getClassDefinition().isInterface()) {
type = "interface ";
} else {
type = "class ";
}
if (!getClassDefinition().isTopLevel()) {
nested = "inner ";
if (getClassDefinition().isLocal()) {
nested = "local ";
if (!getClassDefinition().isAnonymous()) {
name = getClassDefinition().getLocalName() +
" (" + name + ")";
}
}
}
}
return nested + type + name;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
/*
* Copyright (c) 1995, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.zip.*;
/**
* This class is used to represent a file loaded from the class path, and
* can either be a regular file or a zip file entry.
*
* 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.
*/
public
class ClassFile {
/*
* Non-null if this represents a regular file
*/
private File file;
/*
* Non-null if this represents a zip file entry
*/
private ZipFile zipFile;
private ZipEntry zipEntry;
/**
* Constructor for instance representing a regular file
*/
public ClassFile(File file) {
this.file = file;
}
/**
* Constructor for instance representing a zip file entry
*/
public ClassFile(ZipFile zf, ZipEntry ze) {
this.zipFile = zf;
this.zipEntry = ze;
}
/**
* Returns true if this is zip file entry
*/
public boolean isZipped() {
return zipFile != null;
}
/**
* Returns input stream to either regular file or zip file entry
*/
public InputStream getInputStream() throws IOException {
if (file != null) {
return new FileInputStream(file);
} else {
try {
return zipFile.getInputStream(zipEntry);
} catch (ZipException e) {
throw new IOException(e.getMessage());
}
}
}
/**
* Returns true if file exists.
*/
public boolean exists() {
return file != null ? file.exists() : true;
}
/**
* Returns true if this is a directory.
*/
public boolean isDirectory() {
return file != null ? file.isDirectory() :
zipEntry.getName().endsWith("/");
}
/**
* Return last modification time
*/
public long lastModified() {
return file != null ? file.lastModified() : zipEntry.getTime();
}
/**
* Get file path. The path for a zip file entry will also include
* the zip file name.
*/
public String getPath() {
if (file != null) {
return file.getPath();
} else {
return zipFile.getName() + "(" + zipEntry.getName() + ")";
}
}
/**
* Get name of file entry excluding directory name
*/
public String getName() {
return file != null ? file.getName() : zipEntry.getName();
}
//JCOV
/**
* Get absolute name of file entry
*/
public String getAbsoluteName() {
String absoluteName;
if (file != null) {
try {
absoluteName = file.getCanonicalPath();
} catch (IOException e) {
absoluteName = file.getAbsolutePath();
}
} else {
absoluteName = zipFile.getName() + "(" + zipEntry.getName() + ")";
}
return absoluteName;
}
// end JCOV
/**
* Get length of file
*/
public long length() {
return file != null ? file.length() : zipEntry.getSize();
}
public String toString() {
return (file != null) ? file.toString() : zipEntry.toString();
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
/**
* This exception is thrown when a class definition is needed
* and the class can't be found.
*
* 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.
*/
public
class ClassNotFound extends Exception {
/**
* The class that was not found
*/
public Identifier name;
/**
* Create a ClassNotFound exception
*/
public ClassNotFound(Identifier nm) {
super(nm.toString());
name = nm;
}
}

View File

@@ -0,0 +1,314 @@
/*
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.util.Enumeration;
import java.util.Hashtable;
import java.io.File;
import java.io.IOException;
import java.util.zip.*;
/**
* This class is used to represent a class path, which can contain both
* directories and zip files.
*
* 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.
*/
public
class ClassPath {
static final char dirSeparator = File.pathSeparatorChar;
/**
* The original class path string
*/
String pathstr;
/**
* List of class path entries
*/
private ClassPathEntry[] path;
/**
* Build a class path from the specified path string
*/
public ClassPath(String pathstr) {
init(pathstr);
}
/**
* Build a class path from the specified array of class path
* element strings. This constructor, and the corresponding
* "init" method, were added as part of the fix for 6473331, which
* adds support for Class-Path manifest entries in JAR files to
* rmic. It is conceivable that the value of a Class-Path
* manifest entry will contain a path separator, which would cause
* incorrect behavior if the expanded path were passed to the
* previous constructor as a single path-separator-delimited
* string; use of this constructor avoids that problem.
*/
public ClassPath(String[] patharray) {
init(patharray);
}
/**
* Build a default class path from the path strings specified by
* the properties sun.boot.class.path and env.class.path, in that
* order.
*/
public ClassPath() {
String syscp = System.getProperty("sun.boot.class.path");
String envcp = System.getProperty("env.class.path");
if (envcp == null) envcp = ".";
String cp = syscp + File.pathSeparator + envcp;
init(cp);
}
private void init(String pathstr) {
int i, j, n;
// Save original class path string
this.pathstr = pathstr;
if (pathstr.length() == 0) {
this.path = new ClassPathEntry[0];
}
// Count the number of path separators
i = n = 0;
while ((i = pathstr.indexOf(dirSeparator, i)) != -1) {
n++; i++;
}
// Build the class path
ClassPathEntry[] path = new ClassPathEntry[n+1];
int len = pathstr.length();
for (i = n = 0; i < len; i = j + 1) {
if ((j = pathstr.indexOf(dirSeparator, i)) == -1) {
j = len;
}
if (i == j) {
path[n] = new ClassPathEntry();
path[n++].dir = new File(".");
} else {
File file = new File(pathstr.substring(i, j));
if (file.isFile()) {
try {
ZipFile zip = new ZipFile(file);
path[n] = new ClassPathEntry();
path[n++].zip = zip;
} catch (ZipException e) {
} catch (IOException e) {
// Ignore exceptions, at least for now...
}
} else {
path[n] = new ClassPathEntry();
path[n++].dir = file;
}
}
}
// Trim class path to exact size
this.path = new ClassPathEntry[n];
System.arraycopy((Object)path, 0, (Object)this.path, 0, n);
}
private void init(String[] patharray) {
// Save original class path string
if (patharray.length == 0) {
this.pathstr = "";
} else {
StringBuilder sb = new StringBuilder(patharray[0]);
for (int i = 1; i < patharray.length; i++) {
sb.append(File.pathSeparatorChar);
sb.append(patharray[i]);
}
this.pathstr = sb.toString();
}
// Build the class path
ClassPathEntry[] path = new ClassPathEntry[patharray.length];
int n = 0;
for (String name : patharray) {
File file = new File(name);
if (file.isFile()) {
try {
ZipFile zip = new ZipFile(file);
path[n] = new ClassPathEntry();
path[n++].zip = zip;
} catch (ZipException e) {
} catch (IOException e) {
// Ignore exceptions, at least for now...
}
} else {
path[n] = new ClassPathEntry();
path[n++].dir = file;
}
}
// Trim class path to exact size
this.path = new ClassPathEntry[n];
System.arraycopy((Object)path, 0, (Object)this.path, 0, n);
}
/**
* Find the specified directory in the class path
*/
public ClassFile getDirectory(String name) {
return getFile(name, true);
}
/**
* Load the specified file from the class path
*/
public ClassFile getFile(String name) {
return getFile(name, false);
}
private final String fileSeparatorChar = "" + File.separatorChar;
private ClassFile getFile(String name, boolean isDirectory) {
String subdir = name;
String basename = "";
if (!isDirectory) {
int i = name.lastIndexOf(File.separatorChar);
subdir = name.substring(0, i + 1);
basename = name.substring(i + 1);
} else if (!subdir.equals("")
&& !subdir.endsWith(fileSeparatorChar)) {
// zip files are picky about "foo" vs. "foo/".
// also, the getFiles caches are keyed with a trailing /
subdir = subdir + File.separatorChar;
name = subdir; // Note: isDirectory==true & basename==""
}
for (int i = 0; i < path.length; i++) {
if (path[i].zip != null) {
String newname = name.replace(File.separatorChar, '/');
ZipEntry entry = path[i].zip.getEntry(newname);
if (entry != null) {
return new ClassFile(path[i].zip, entry);
}
} else {
File file = new File(path[i].dir.getPath(), name);
String list[] = path[i].getFiles(subdir);
if (isDirectory) {
if (list.length > 0) {
return new ClassFile(file);
}
} else {
for (int j = 0; j < list.length; j++) {
if (basename.equals(list[j])) {
// Don't bother checking !file.isDir,
// since we only look for names which
// cannot already be packages (foo.java, etc).
return new ClassFile(file);
}
}
}
}
}
return null;
}
/**
* Returns list of files given a package name and extension.
*/
public Enumeration getFiles(String pkg, String ext) {
Hashtable files = new Hashtable();
for (int i = path.length; --i >= 0; ) {
if (path[i].zip != null) {
Enumeration e = path[i].zip.entries();
while (e.hasMoreElements()) {
ZipEntry entry = (ZipEntry)e.nextElement();
String name = entry.getName();
name = name.replace('/', File.separatorChar);
if (name.startsWith(pkg) && name.endsWith(ext)) {
files.put(name, new ClassFile(path[i].zip, entry));
}
}
} else {
String[] list = path[i].getFiles(pkg);
for (int j = 0; j < list.length; j++) {
String name = list[j];
if (name.endsWith(ext)) {
name = pkg + File.separatorChar + name;
File file = new File(path[i].dir.getPath(), name);
files.put(name, new ClassFile(file));
}
}
}
}
return files.elements();
}
/**
* Release resources.
*/
public void close() throws IOException {
for (int i = path.length; --i >= 0; ) {
if (path[i].zip != null) {
path[i].zip.close();
}
}
}
/**
* Returns original class path string
*/
public String toString() {
return pathstr;
}
}
/**
* A class path entry, which can either be a directory or an open zip file.
*/
class ClassPathEntry {
File dir;
ZipFile zip;
Hashtable subdirs = new Hashtable(29); // cache of sub-directory listings
String[] getFiles(String subdir) {
String files[] = (String[]) subdirs.get(subdir);
if (files == null) {
// search the directory, exactly once
File sd = new File(dir.getPath(), subdir);
if (sd.isDirectory()) {
files = sd.list();
if (files == null) {
// should not happen, but just in case, fail silently
files = new String[0];
}
if (files.length == 0) {
String nonEmpty[] = { "" };
files = nonEmpty;
}
} else {
files = new String[0];
}
subdirs.put(subdir, files);
}
return files;
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
/**
* This class represents an Java class type.
* It overrides the relevant methods in class Type.
*
* 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.
*
* @author Arthur van Hoff
*/
public final
class ClassType extends Type {
/**
* The fully qualified class name.
*/
Identifier className;
/**
* Construct a class type. Use Type.tClass to create
* a new class type.
*/
ClassType(String typeSig, Identifier className) {
super(TC_CLASS, typeSig);
this.className = className;
}
public Identifier getClassName() {
return className;
}
public String typeString(String id, boolean abbrev, boolean ret) {
String s = (abbrev ? getClassName().getFlatName() :
Identifier.lookup(getClassName().getQualifier(),
getClassName().getFlatName())).toString();
return (id.length() > 0) ? s + " " + id : s;
}
}

View File

@@ -0,0 +1,62 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
/**
* This exception is thrown when an internal compiler error occurs
*
* 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.
*/
public
class CompilerError extends Error {
Throwable e;
/**
* Constructor
*/
public CompilerError(String msg) {
super(msg);
this.e = this;
}
/**
* Create an exception given another exception.
*/
public CompilerError(Exception e) {
super(e.getMessage());
this.e = e;
}
public void printStackTrace() {
if (e == this)
super.printStackTrace();
else
e.printStackTrace();
}
}

View File

@@ -0,0 +1,591 @@
/*
* Copyright (c) 1994, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
/**
* This interface defines constant that are used
* throughout the compiler. It inherits from RuntimeConstants,
* which is an autogenerated class that contains contstants
* defined in the interpreter.
*
* 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.
*
* @author Arthur van Hoff
*/
public
interface Constants extends RuntimeConstants {
/*
* Enable/disable inclusion of certain debug tracing code in the
* compiler. When included, the tracing code may be selectively
* enabled at runtime, otherwise we save the space/time overhead.
* Should normally be 'false' for a release version.
*/
public static final boolean tracing = true;
/*
* Frequently used identifiers
*/
Identifier idAppend = Identifier.lookup("append");
Identifier idClassInit = Identifier.lookup("<clinit>");
Identifier idCode = Identifier.lookup("Code");
Identifier idInit = Identifier.lookup("<init>");
Identifier idLength = Identifier.lookup("length");
Identifier idNull = Identifier.lookup("");
Identifier idStar = Identifier.lookup("*");
Identifier idSuper = Identifier.lookup("super");
Identifier idThis = Identifier.lookup("this");
Identifier idClass = Identifier.lookup("class");
Identifier idToString = Identifier.lookup("toString");
Identifier idValueOf = Identifier.lookup("valueOf");
Identifier idNew = Identifier.lookup("new");
Identifier idGetClass = Identifier.lookup("getClass");
Identifier idTYPE = Identifier.lookup("TYPE");
Identifier idFinallyReturnValue = Identifier.lookup("<return>");
Identifier idJavaLang = Identifier.lookup("java.lang");
Identifier idJavaLangCloneable = Identifier.lookup("java.lang.Cloneable");
Identifier idJavaLangError = Identifier.lookup("java.lang.Error");
Identifier idJavaLangException = Identifier.lookup("java.lang.Exception");
Identifier idJavaLangObject = Identifier.lookup("java.lang.Object");
Identifier idJavaLangClass = Identifier.lookup("java.lang.Class");
Identifier idJavaLangRuntimeException =
Identifier.lookup("java.lang.RuntimeException");
Identifier idJavaLangString = Identifier.lookup("java.lang.String");
Identifier idJavaLangStringBuffer =
Identifier.lookup("java.lang.StringBuffer");
Identifier idJavaLangThrowable = Identifier.lookup("java.lang.Throwable");
Identifier idJavaIoSerializable = Identifier.lookup("java.io.Serializable");
Identifier idConstantValue = Identifier.lookup("ConstantValue");
Identifier idLocalVariableTable = Identifier.lookup("LocalVariableTable");
Identifier idLineNumberTable = Identifier.lookup("LineNumberTable");
// JCOV
Identifier idCoverageTable = Identifier.lookup("CoverageTable");
// end JCOV
Identifier idSourceFile = Identifier.lookup("SourceFile");
Identifier idDocumentation = Identifier.lookup("Documentation");
Identifier idDeprecated = Identifier.lookup("Deprecated");
Identifier idSynthetic = Identifier.lookup("Synthetic");
Identifier idExceptions = Identifier.lookup("Exceptions");
Identifier idInnerClasses = Identifier.lookup("InnerClasses");
/* methods we need to know about */
Identifier idClone = Identifier.lookup("clone");
/* This is not a real signature marker, since it is also
* an identifier constituent character.
*/
char SIGC_INNERCLASS = '$';
String SIG_INNERCLASS = "$";
String prefixThis = "this$";
String prefixVal = "val$";
String prefixLoc = "loc$";
String prefixAccess = "access$";
String prefixClass = "class$";
String prefixArray = "array$";
/*
* Flags
*/
int F_VERBOSE = 1 << 0;
int F_DUMP = 1 << 1;
int F_WARNINGS = 1 << 2;
// The meaning of -g has changed, so F_DEBUG flag is removed.
// public static final int F_DEBUG = 1 << 3;
int F_DEBUG_LINES = 1 << 12;
int F_DEBUG_VARS = 1 << 13;
int F_DEBUG_SOURCE = 1 << 18;
// The meaning of -O has changed, so F_OPTIMIZE flag is removed.
// public static final int F_OPTIMIZE = 1 << 4;
int F_OPT = 1 << 14;
int F_OPT_INTERCLASS = 1 << 15;
int F_DEPENDENCIES = 1 << 5;
// JCOV
int F_COVERAGE = 1 << 6;
int F_COVDATA = 1 << 7;
// end JCOV
int F_DEPRECATION = 1 << 9;
int F_PRINT_DEPENDENCIES = 1 << 10;
int F_VERSION12 = 1 << 11;
int F_ERRORSREPORTED = 1 << 16;
int F_STRICTDEFAULT = 1 << 17;
/*
* Modifiers.
*
* There has been much confusion regarding modifiers. There
* are a number of distinct usages:
*
* - in classfiles to annotate classes, as per JVM pg. 102.
* - in classfiles to annotate methods, as per JVM pg. 104.
* - in classfiles to annotate InnerClass attributes, as per
* http://java.sun.com/products/jdk/1.1/docs/guide/innerclasses
* - in the compiler to record java source level modifiers,
* as per JLS pg. 157 et al., plus misc. info such as whether
* a method is deprecated
* - in the JVM to record misc. info, such as whether a method has
* has been compiled
*
* To make matters worse, the terms "access flags" and "modifiers"
* are often used interchangably, and some information that might
* make sense as a flag is expressed using attributes (ie. Synthetic).
*
* The constants defined herein have been divided by whether they
* make sense only within the compiler (M_* and MM_*) or whether
* they only make sense to the JVM (ACC_* and ACCM_*). At an earlier
* time these were all lumped together. Future maintenance should
* strive to keep the distinction clear.
*
* Note that modifier M_STRICTFP is not in general recoverable from
* the ACC_STRICT bit in classfiles.
*
* Note also that the modifiers M_LOCAL and M_ANONYMOUS do not appear
* in the InnerClass attribute, as they are above the first 16 bits.
*/
// Modifiers meaningful to both Java source and the JVM. These
// have been kept the same bit in the M_* and ACC_* forms
// to avoid destabilizing the compiler.
int M_PUBLIC = ACC_PUBLIC;
int M_PRIVATE = ACC_PRIVATE;
int M_PROTECTED = ACC_PROTECTED;
int M_STATIC = ACC_STATIC;
int M_TRANSIENT = ACC_TRANSIENT;
int M_SYNCHRONIZED = ACC_SYNCHRONIZED; // collides with ACC_SUPER
int M_ABSTRACT = ACC_ABSTRACT;
int M_NATIVE = ACC_NATIVE;
int M_FINAL = ACC_FINAL;
int M_VOLATILE = ACC_VOLATILE;
int M_INTERFACE = ACC_INTERFACE;
// Modifiers not meaningful to the JVM. The JVM only allows 16 bits
// for modifiers, so keeping these in the unusable bits after the first
// 16 is a good idea.
int M_ANONYMOUS = 0x00010000;
int M_LOCAL = 0x00020000;
int M_DEPRECATED = 0x00040000;
int M_SYNTHETIC = 0x00080000;
int M_INLINEABLE = 0x00100000;
int M_STRICTFP = 0x00200000;
String paraDeprecated = "@deprecated";
// Masks for modifiers that apply to Java source code
int MM_CLASS = M_PUBLIC
| M_INTERFACE
| M_FINAL
| M_ABSTRACT
| M_STRICTFP;
int MM_MEMBER = M_PUBLIC
| M_PRIVATE
| M_PROTECTED
| M_FINAL
| M_STATIC;
int MM_FIELD = MM_MEMBER
| M_TRANSIENT
| M_VOLATILE;
int MM_METHOD = MM_MEMBER
| M_SYNCHRONIZED
| M_ABSTRACT
| M_NATIVE
| M_STRICTFP;
// Masks for modifiers that apply to class files.
// Note that the M_SYNTHETIC modifier is never written out to a class file.
// Synthetic members are indicated using the "Synthetic" attribute.
int ACCM_CLASS = ACC_PUBLIC
| ACC_INTERFACE
| ACC_FINAL
| ACC_ABSTRACT
| ACC_SUPER
| ACC_STRICT;
int ACCM_MEMBER = ACC_PUBLIC
| ACC_PRIVATE
| ACC_PROTECTED
| ACC_FINAL
| ACC_STATIC;
// The M_ANONYMOUS and M_LOCAL modifiers are not mentioned in the
// inner classes specification and are never written to classfiles.
// Also note that ACC_SUPER should never be set in an InnerClass
// attribute.
int ACCM_INNERCLASS = ACC_PUBLIC
| ACC_PRIVATE
| ACC_PROTECTED
| ACC_STATIC
| ACC_ABSTRACT
| ACC_FINAL
| ACC_INTERFACE
| ACC_STRICT;
int ACCM_FIELD = ACCM_MEMBER
| ACC_TRANSIENT
| ACC_VOLATILE;
int ACCM_METHOD = ACCM_MEMBER
| ACC_SYNCHRONIZED
| ACC_ABSTRACT
| ACC_NATIVE
| ACC_STRICT;
/*
* Type codes
*/
int TC_BOOLEAN = 0;
int TC_BYTE = 1;
int TC_CHAR = 2;
int TC_SHORT = 3;
int TC_INT = 4;
int TC_LONG = 5;
int TC_FLOAT = 6;
int TC_DOUBLE = 7;
int TC_NULL = 8;
int TC_ARRAY = 9;
int TC_CLASS = 10;
int TC_VOID = 11;
int TC_METHOD = 12;
int TC_ERROR = 13;
// JCOV
/*
* Cover's types
*/
int CT_FIRST_KIND = 1;
int CT_METHOD = 1;
int CT_FIKT_METHOD = 2;
int CT_BLOCK = 3;
int CT_FIKT_RET = 4;
int CT_CASE = 5;
int CT_SWITH_WO_DEF = 6;
int CT_BRANCH_TRUE = 7;
int CT_BRANCH_FALSE = 8;
int CT_LAST_KIND = 8;
// end JCOV
/*
* Type Masks
*/
int TM_NULL = 1 << TC_NULL;
int TM_VOID = 1 << TC_VOID;
int TM_BOOLEAN = 1 << TC_BOOLEAN;
int TM_BYTE = 1 << TC_BYTE;
int TM_CHAR = 1 << TC_CHAR;
int TM_SHORT = 1 << TC_SHORT;
int TM_INT = 1 << TC_INT;
int TM_LONG = 1 << TC_LONG;
int TM_FLOAT = 1 << TC_FLOAT;
int TM_DOUBLE = 1 << TC_DOUBLE;
int TM_ARRAY = 1 << TC_ARRAY;
int TM_CLASS = 1 << TC_CLASS;
int TM_METHOD = 1 << TC_METHOD;
int TM_ERROR = 1 << TC_ERROR;
int TM_INT32 = TM_BYTE | TM_SHORT | TM_CHAR | TM_INT;
int TM_NUM32 = TM_INT32 | TM_FLOAT;
int TM_NUM64 = TM_LONG | TM_DOUBLE;
int TM_INTEGER = TM_INT32 | TM_LONG;
int TM_REAL = TM_FLOAT | TM_DOUBLE;
int TM_NUMBER = TM_INTEGER | TM_REAL;
int TM_REFERENCE = TM_ARRAY | TM_CLASS | TM_NULL;
/*
* Class status
*/
int CS_UNDEFINED = 0;
int CS_UNDECIDED = 1;
int CS_BINARY = 2;
int CS_SOURCE = 3;
int CS_PARSED = 4;
int CS_CHECKED = 5;
int CS_COMPILED = 6;
int CS_NOTFOUND = 7;
/*
* Attributes
*/
int ATT_ALL = 0xFFFFFFFF;
int ATT_CODE = 1 << 1;
int ATT_ALLCLASSES = 1 << 2;
/*
* Number of bits used in file offsets. The line number and
* file offset are concatenated into a long, with enough room
* for other information to be added later if desired (such as
* token lengths). For the moment explicit bit manipulations
* are used to modify the fields. This makes sense for efficiency
* but at some point these ought to be better encapsulated.
*/
int WHEREOFFSETBITS = 32;
long MAXFILESIZE = (1L << WHEREOFFSETBITS) - 1;
long MAXLINENUMBER = (1L << (64 - WHEREOFFSETBITS)) - 1;
/*
* Operators
*/
int COMMA = 0;
int ASSIGN = 1;
int ASGMUL = 2;
int ASGDIV = 3;
int ASGREM = 4;
int ASGADD = 5;
int ASGSUB = 6;
int ASGLSHIFT = 7;
int ASGRSHIFT = 8;
int ASGURSHIFT = 9;
int ASGBITAND = 10;
int ASGBITOR = 11;
int ASGBITXOR = 12;
int COND = 13;
int OR = 14;
int AND = 15;
int BITOR = 16;
int BITXOR = 17;
int BITAND = 18;
int NE = 19;
int EQ = 20;
int GE = 21;
int GT = 22;
int LE = 23;
int LT = 24;
int INSTANCEOF = 25;
int LSHIFT = 26;
int RSHIFT = 27;
int URSHIFT = 28;
int ADD = 29;
int SUB = 30;
int DIV = 31;
int REM = 32;
int MUL = 33;
int CAST = 34; // (x)y
int POS = 35; // +x
int NEG = 36; // -x
int NOT = 37;
int BITNOT = 38;
int PREINC = 39; // ++x
int PREDEC = 40; // --x
int NEWARRAY = 41;
int NEWINSTANCE = 42;
int NEWFROMNAME = 43;
int POSTINC = 44; // x++
int POSTDEC = 45; // x--
int FIELD = 46;
int METHOD = 47; // x(y)
int ARRAYACCESS = 48; // x[y]
int NEW = 49;
int INC = 50;
int DEC = 51;
int CONVERT = 55; // implicit conversion
int EXPR = 56; // (x)
int ARRAY = 57; // {x, y, ...}
int GOTO = 58;
/*
* Value tokens
*/
int IDENT = 60;
int BOOLEANVAL = 61;
int BYTEVAL = 62;
int CHARVAL = 63;
int SHORTVAL = 64;
int INTVAL = 65;
int LONGVAL = 66;
int FLOATVAL = 67;
int DOUBLEVAL = 68;
int STRINGVAL = 69;
/*
* Type keywords
*/
int BYTE = 70;
int CHAR = 71;
int SHORT = 72;
int INT = 73;
int LONG = 74;
int FLOAT = 75;
int DOUBLE = 76;
int VOID = 77;
int BOOLEAN = 78;
/*
* Expression keywords
*/
int TRUE = 80;
int FALSE = 81;
int THIS = 82;
int SUPER = 83;
int NULL = 84;
/*
* Statement keywords
*/
int IF = 90;
int ELSE = 91;
int FOR = 92;
int WHILE = 93;
int DO = 94;
int SWITCH = 95;
int CASE = 96;
int DEFAULT = 97;
int BREAK = 98;
int CONTINUE = 99;
int RETURN = 100;
int TRY = 101;
int CATCH = 102;
int FINALLY = 103;
int THROW = 104;
int STAT = 105;
int EXPRESSION = 106;
int DECLARATION = 107;
int VARDECLARATION = 108;
/*
* Declaration keywords
*/
int IMPORT = 110;
int CLASS = 111;
int EXTENDS = 112;
int IMPLEMENTS = 113;
int INTERFACE = 114;
int PACKAGE = 115;
/*
* Modifier keywords
*/
int PRIVATE = 120;
int PUBLIC = 121;
int PROTECTED = 122;
int CONST = 123;
int STATIC = 124;
int TRANSIENT = 125;
int SYNCHRONIZED = 126;
int NATIVE = 127;
int FINAL = 128;
int VOLATILE = 129;
int ABSTRACT = 130;
int STRICTFP = 131;
/*
* Punctuation
*/
int SEMICOLON = 135;
int COLON = 136;
int QUESTIONMARK = 137;
int LBRACE = 138;
int RBRACE = 139;
int LPAREN = 140;
int RPAREN = 141;
int LSQBRACKET = 142;
int RSQBRACKET = 143;
int THROWS = 144;
/*
* Special tokens
*/
int ERROR = 145; // an error
int COMMENT = 146; // not used anymore.
int TYPE = 147;
int LENGTH = 148;
int INLINERETURN = 149;
int INLINEMETHOD = 150;
int INLINENEWINSTANCE = 151;
/*
* Operator precedence
*/
int opPrecedence[] = {
10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
11, 11, 11, 12, 13, 14, 15, 16, 17, 18,
18, 19, 19, 19, 19, 19, 20, 20, 20, 21,
21, 22, 22, 22, 23, 24, 24, 24, 24, 24,
24, 25, 25, 26, 26, 26, 26, 26, 26
};
/*
* Operator names
*/
String opNames[] = {
",", "=", "*=", "/=", "%=",
"+=", "-=", "<<=", ">>=", ">>>=",
"&=", "|=", "^=", "?:", "||",
"&&", "|", "^", "&", "!=",
"==", ">=", ">", "<=", "<",
"instanceof", "<<", ">>", ">>>", "+",
"-", "/", "%", "*", "cast",
"+", "-", "!", "~", "++",
"--", "new", "new", "new", "++",
"--", "field","method","[]", "new",
"++", "--", null, null, null,
"convert", "expr", "array", "goto", null,
"Identifier", "boolean", "byte", "char", "short",
"int", "long", "float", "double", "string",
"byte", "char", "short", "int", "long",
"float", "double", "void", "boolean", null,
"true", "false", "this", "super", "null",
null, null, null, null, null,
"if", "else", "for", "while","do",
"switch", "case", "default", "break", "continue",
"return", "try", "catch", "finally", "throw",
"stat", "expression", "declaration", "declaration", null,
"import", "class", "extends", "implements", "interface",
"package", null, null, null, null,
"private", "public", "protected", "const", "static",
"transient", "synchronized", "native", "final", "volatile",
"abstract", "strictfp", null, null, null,
";", ":", "?", "{", "}",
"(", ")", "[", "]", "throws",
"error", "comment", "type", "length", "inline-return",
"inline-method", "inline-new"
};
}

View File

@@ -0,0 +1,998 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.util.Stack;
import java.io.IOException;
import sun.tools.tree.Context;
//JCOV
import java.io.File;
//end JCOV
/**
* This class defines the environment for a compilation.
* It is used to load classes, resolve class names and
* report errors. It is an abstract class, a subclass
* must define implementations for some of the functions.<p>
*
* An environment has a source object associated with it.
* This is the thing against which errors are reported, it
* is usually a file name, a field or a class.<p>
*
* Environments can be nested to change the source object.<p>
*
* 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.
*
* @author Arthur van Hoff
*/
public class Environment implements Constants {
/**
* The actual environment to which everything is forwarded.
*/
Environment env;
/**
* External character encoding name
*/
String encoding;
/**
* The object that is currently being parsed/compiled.
* It is either a file name (String) or a field (MemberDefinition)
* or a class (ClassDeclaration or ClassDefinition).
*/
Object source;
public Environment(Environment env, Object source) {
if (env != null && env.env != null && env.getClass() == this.getClass())
env = env.env; // a small optimization
this.env = env;
this.source = source;
}
public Environment() {
this(null, null);
}
/**
* Tells whether an Identifier refers to a package which should be
* exempt from the "exists" check in Imports#resolve().
*/
public boolean isExemptPackage(Identifier id) {
return env.isExemptPackage(id);
}
/**
* Return a class declaration given a fully qualified class name.
*/
public ClassDeclaration getClassDeclaration(Identifier nm) {
return env.getClassDeclaration(nm);
}
/**
* Return a class definition given a fully qualified class name.
* <p>
* Should be called only with 'internal' class names, i.e., the result
* of a call to 'resolveName' or a synthetic class name.
*/
public final ClassDefinition getClassDefinition(Identifier nm) throws ClassNotFound {
if (nm.isInner()) {
ClassDefinition c = getClassDefinition(nm.getTopName());
Identifier tail = nm.getFlatName();
walkTail:
while (tail.isQualified()) {
tail = tail.getTail();
Identifier head = tail.getHead();
//System.out.println("CLASS: " + c + " HEAD: " + head + " TAIL: " + tail);
String hname = head.toString();
// If the name is of the form 'ClassName.N$localName', where N is
// a number, the field 'N$localName' may not necessarily be a member
// of the class named by 'ClassName', but might be a member of some
// inaccessible class contained within it. We use 'getLocalClass'
// to do the lookup in this case. This is part of a fix for bugid
// 4054523 and 4030421. See also 'BatchEnvironment.makeClassDefinition'.
// This should also work for anonymous class names of the form
// 'ClassName.N'. Note that the '.' qualifications get converted to
// '$' characters when determining the external name of the class and
// the name of the class file.
if (hname.length() > 0
&& Character.isDigit(hname.charAt(0))) {
ClassDefinition localClass = c.getLocalClass(hname);
if (localClass != null) {
c = localClass;
continue walkTail;
}
} else {
for (MemberDefinition f = c.getFirstMatch(head);
f != null; f = f.getNextMatch()) {
if (f.isInnerClass()) {
c = f.getInnerClass();
continue walkTail;
}
}
}
throw new ClassNotFound(Identifier.lookupInner(c.getName(), head));
}
//System.out.println("FOUND " + c + " FOR " + nm);
return c;
}
return getClassDeclaration(nm).getClassDefinition(this);
}
/**
* Return a class declaration given a type. Only works for
* class types.
*/
public ClassDeclaration getClassDeclaration(Type t) {
return getClassDeclaration(t.getClassName());
}
/**
* Return a class definition given a type. Only works for
* class types.
*/
public final ClassDefinition getClassDefinition(Type t) throws ClassNotFound {
return getClassDefinition(t.getClassName());
}
/**
* Check if a class exists (without actually loading it).
* (Since inner classes cannot in general be examined without
* loading source, this method does not accept inner names.)
*/
public boolean classExists(Identifier nm) {
return env.classExists(nm);
}
public final boolean classExists(Type t) {
return !t.isType(TC_CLASS) || classExists(t.getClassName());
}
/**
* Get the package path for a package
*/
public Package getPackage(Identifier pkg) throws IOException {
return env.getPackage(pkg);
}
/**
* Load the definition of a class.
*/
public void loadDefinition(ClassDeclaration c) {
env.loadDefinition(c);
}
/**
* Return the source of the environment (ie: the thing being compiled/parsed).
*/
public final Object getSource() {
return source;
}
/**
* Resolve a type. Make sure that all the classes referred to by
* the type have a definition. Report errors. Return true if
* the type is well-formed. Presently used for types appearing
* in member declarations, which represent named types internally as
* qualified identifiers. Type names appearing in local variable
* declarations and within expressions are represented as identifier
* or field expressions, and are resolved by 'toType', which delegates
* handling of the non-inner portion of the name to this method.
* <p>
* In 'toType', the various stages of qualification are represented by
* separate AST nodes. Here, we are given a single identifier which
* contains the entire qualification structure. It is not possible in
* general to set the error location to the exact position of a component
* that is in error, so an error message must refer to the entire qualified
* name. An attempt to keep track of the string length of the components of
* the name and to offset the location accordingly fails because the initial
* prefix of the name may have been rewritten by an earlier call to
* 'resolveName'. See 'SourceMember.resolveTypeStructure'. The situation
* is actually even worse than this, because only a single location is
* passed in for an entire declaration, which may contain many type names.
* All error messages are thus poorly localized. These checks should be
* done while traversing the parse tree for the type, not the type descriptor.
* <p>
* DESIGN NOTE:
* As far as I can tell, the two-stage resolution of names represented in
* string form is an artifact of the late implementation of inner classes
* and the use of mangled names internally within the compiler. All
* qualified names should have their hiearchical structure made explicit
* in the parse tree at the phase at which they are presented for static
* semantic checking. This would affect class names appearing in 'extends',
* 'implements', and 'throws' clauses, as well as in member declarations.
*/
public boolean resolve(long where, ClassDefinition c, Type t) {
switch (t.getTypeCode()) {
case TC_CLASS: {
ClassDefinition def;
try {
Identifier nm = t.getClassName();
if (!nm.isQualified() && !nm.isInner() && !classExists(nm)) {
resolve(nm); // elicit complaints about ambiguity
}
def = getQualifiedClassDefinition(where, nm, c, false);
if (!c.canAccess(this, def.getClassDeclaration())) {
// Reported error location may be imprecise
// if the name is qualified.
error(where, "cant.access.class", def);
return true; // return false later
}
def.noteUsedBy(c, where, env);
} catch (AmbiguousClass ee) {
error(where, "ambig.class", ee.name1, ee.name2);
return false;
} catch (ClassNotFound e) {
// For now, report "class.and.package" only when the code
// is going to fail anyway.
try {
if (e.name.isInner() &&
getPackage(e.name.getTopName()).exists()) {
env.error(where, "class.and.package",
e.name.getTopName());
}
} catch (IOException ee) {
env.error(where, "io.exception", "package check");
}
// This error message is also emitted for 'new' expressions.
// error(where, "class.not.found", e.name, "declaration");
error(where, "class.not.found.no.context", e.name);
return false;
}
return true;
}
case TC_ARRAY:
return resolve(where, c, t.getElementType());
case TC_METHOD:
boolean ok = resolve(where, c, t.getReturnType());
Type args[] = t.getArgumentTypes();
for (int i = args.length ; i-- > 0 ; ) {
ok &= resolve(where, c, args[i]);
}
return ok;
}
return true;
}
/**
* Given its fully-qualified name, verify that a class is defined and accessible.
* Used to check components of qualified names in contexts where a class is expected.
* Like 'resolve', but is given a single type name, not a type descriptor.
*/
public boolean resolveByName(long where, ClassDefinition c, Identifier nm) {
return resolveByName(where, c, nm, false);
}
public boolean resolveExtendsByName(long where, ClassDefinition c, Identifier nm) {
return resolveByName(where, c, nm, true);
}
private boolean resolveByName(long where, ClassDefinition c,
Identifier nm, boolean isExtends) {
ClassDefinition def;
try {
if (!nm.isQualified() && !nm.isInner() && !classExists(nm)) {
resolve(nm); // elicit complaints about ambiguity
}
def = getQualifiedClassDefinition(where, nm, c, isExtends);
ClassDeclaration decl = def.getClassDeclaration();
if (!((!isExtends && c.canAccess(this, decl))
||
(isExtends && c.extendsCanAccess(this, decl)))) {
error(where, "cant.access.class", def);
return true; // return false later
}
} catch (AmbiguousClass ee) {
error(where, "ambig.class", ee.name1, ee.name2);
return false;
} catch (ClassNotFound e) {
// For now, report "class.and.package" only when the code
// is going to fail anyway.
try {
if (e.name.isInner() &&
getPackage(e.name.getTopName()).exists()) {
env.error(where, "class.and.package",
e.name.getTopName());
}
} catch (IOException ee) {
env.error(where, "io.exception", "package check");
}
error(where, "class.not.found", e.name, "type name");
return false;
}
return true;
}
/**
* Like 'getClassDefinition(env)', but check access on each component.
* Currently called only by 'resolve' above. It is doubtful that calls
* to 'getClassDefinition(env)' are appropriate now.
*/
public final ClassDefinition
getQualifiedClassDefinition(long where,
Identifier nm,
ClassDefinition ctxClass,
boolean isExtends) throws ClassNotFound {
if (nm.isInner()) {
ClassDefinition c = getClassDefinition(nm.getTopName());
Identifier tail = nm.getFlatName();
walkTail:
while (tail.isQualified()) {
tail = tail.getTail();
Identifier head = tail.getHead();
// System.out.println("CLASS: " + c + " HEAD: " + head + " TAIL: " + tail);
String hname = head.toString();
// Handle synthesized names of local and anonymous classes.
// See 'getClassDefinition(env)' above.
if (hname.length() > 0
&& Character.isDigit(hname.charAt(0))) {
ClassDefinition localClass = c.getLocalClass(hname);
if (localClass != null) {
c = localClass;
continue walkTail;
}
} else {
for (MemberDefinition f = c.getFirstMatch(head);
f != null; f = f.getNextMatch()) {
if (f.isInnerClass()) {
ClassDeclaration rdecl = c.getClassDeclaration();
c = f.getInnerClass();
ClassDeclaration fdecl = c.getClassDeclaration();
// This check is presumably applicable even if the
// original source-code name (expanded by 'resolveNames')
// was a simple, unqualified name. Hopefully, JLS 2e
// will clarify the matter.
if ((!isExtends
&& !ctxClass.canAccess(env, fdecl))
||
(isExtends
&& !ctxClass.extendsCanAccess(env, fdecl))) {
// Reported error location is imprecise.
env.error(where, "no.type.access", head, rdecl, ctxClass);
}
// The JLS 6.6.2 restrictions on access to protected members
// depend in an essential way upon the syntactic form of the name.
// Since the compiler has previously expanded the class names
// here into fully-qualified form ('resolveNames'), this check
// cannot be performed here. Unfortunately, the original names
// are clobbered during 'basicCheck', which is also the phase that
// resolves the inheritance structure, required to implement the
// access restrictions. Pending a large-scale revision of the
// name-resolution machinery, we forgo this check, with the result
// that the JLS 6.6.2 restrictions are not enforced for some cases
// of qualified access to inner classes. Some qualified names are
// resolved elsewhere via a different mechanism, and will be
// treated correctly -- see 'FieldExpression.checkCommon'.
/*---------------------------------------*
if (f.isProtected()) {
Type rty = Type.tClass(rdecl.getName()); // hack
if (!ctxClass.protectedAccess(env, f, rty)) {
// Reported error location is imprecise.
env.error(where, "invalid.protected.type.use",
head, ctxClass, rty);
}
}
*---------------------------------------*/
continue walkTail;
}
}
}
throw new ClassNotFound(Identifier.lookupInner(c.getName(), head));
}
//System.out.println("FOUND " + c + " FOR " + nm);
return c;
}
return getClassDeclaration(nm).getClassDefinition(this);
}
/**
* Resolve the names within a type, returning the adjusted type.
* Adjust class names to reflect scoping.
* Do not report errors.
* <p>
* NOTE: It would be convenient to check for errors here, such as
* verifying that each component of a qualified name exists and is
* accessible. Why must this be done in a separate phase?
* <p>
* If the 'synth' argument is true, indicating that the member whose
* type is being resolved is synthetic, names are resolved with respect
* to the package scope. (Fix for 4097882)
*/
public Type resolveNames(ClassDefinition c, Type t, boolean synth) {
if (tracing) dtEvent("Environment.resolveNames: " + c + ", " + t);
switch (t.getTypeCode()) {
case TC_CLASS: {
Identifier name = t.getClassName();
Identifier rname;
if (synth) {
rname = resolvePackageQualifiedName(name);
} else {
rname = c.resolveName(this, name);
}
if (name != rname) {
t = Type.tClass(rname);
}
break;
}
case TC_ARRAY:
t = Type.tArray(resolveNames(c, t.getElementType(), synth));
break;
case TC_METHOD: {
Type ret = t.getReturnType();
Type rret = resolveNames(c, ret, synth);
Type args[] = t.getArgumentTypes();
Type rargs[] = new Type[args.length];
boolean changed = (ret != rret);
for (int i = args.length ; i-- > 0 ; ) {
Type arg = args[i];
Type rarg = resolveNames(c, arg, synth);
rargs[i] = rarg;
if (arg != rarg) {
changed = true;
}
}
if (changed) {
t = Type.tMethod(rret, rargs);
}
break;
}
}
return t;
}
/**
* Resolve a class name, using only package and import directives.
* Report no errors.
* <p>
*/
public Identifier resolveName(Identifier name) {
// This logic is pretty exactly parallel to that of
// ClassDefinition.resolveName().
if (name.isQualified()) {
// Try to resolve the first identifier component,
// because inner class names take precedence over
// package prefixes. (Cf. ClassDefinition.resolveName.)
Identifier rhead = resolveName(name.getHead());
if (rhead.hasAmbigPrefix()) {
// The first identifier component refers to an
// ambiguous class. Limp on. We throw away the
// rest of the classname as it is irrelevant.
// (part of solution for 4059855).
return rhead;
}
if (!this.classExists(rhead)) {
return this.resolvePackageQualifiedName(name);
}
try {
return this.getClassDefinition(rhead).
resolveInnerClass(this, name.getTail());
} catch (ClassNotFound ee) {
// return partially-resolved name someone else can fail on
return Identifier.lookupInner(rhead, name.getTail());
}
}
try {
return resolve(name);
} catch (AmbiguousClass ee) {
// Don't force a resolution of the name if it is ambiguous.
// Forcing the resolution would tack the current package
// name onto the front of the class, which would be wrong.
// Instead, mark the name as ambiguous and let a later stage
// find the error by calling env.resolve(name).
// (part of solution for 4059855).
if (name.hasAmbigPrefix()) {
return name;
} else {
return name.addAmbigPrefix();
}
} catch (ClassNotFound ee) {
// last chance to make something halfway sensible
Imports imports = getImports();
if (imports != null)
return imports.forceResolve(this, name);
}
return name;
}
/**
* Discover if name consists of a package prefix, followed by the
* name of a class (that actually exists), followed possibly by
* some inner class names. If we can't find a class that exists,
* return the name unchanged.
* <p>
* This routine is used after a class name fails to
* be resolved by means of imports or inner classes.
* However, import processing uses this routine directly,
* since import names must be exactly qualified to start with.
*/
public final Identifier resolvePackageQualifiedName(Identifier name) {
Identifier tail = null;
for (;;) {
if (classExists(name)) {
break;
}
if (!name.isQualified()) {
name = (tail == null) ? name : Identifier.lookup(name, tail);
tail = null;
break;
}
Identifier nm = name.getName();
tail = (tail == null)? nm: Identifier.lookup(nm, tail);
name = name.getQualifier();
}
if (tail != null)
name = Identifier.lookupInner(name, tail);
return name;
}
/**
* Resolve a class name, using only package and import directives.
*/
public Identifier resolve(Identifier nm) throws ClassNotFound {
if (env == null) return nm; // a pretty useless no-op
return env.resolve(nm);
}
/**
* Get the imports used to resolve class names.
*/
public Imports getImports() {
if (env == null) return null; // lame default
return env.getImports();
}
/**
* Create a new class.
*/
public ClassDefinition makeClassDefinition(Environment origEnv, long where,
IdentifierToken name,
String doc, int modifiers,
IdentifierToken superClass,
IdentifierToken interfaces[],
ClassDefinition outerClass) {
if (env == null) return null; // lame default
return env.makeClassDefinition(origEnv, where, name,
doc, modifiers,
superClass, interfaces, outerClass);
}
/**
* Create a new field.
*/
public MemberDefinition makeMemberDefinition(Environment origEnv, long where,
ClassDefinition clazz,
String doc, int modifiers,
Type type, Identifier name,
IdentifierToken argNames[],
IdentifierToken expIds[],
Object value) {
if (env == null) return null; // lame default
return env.makeMemberDefinition(origEnv, where, clazz, doc, modifiers,
type, name, argNames, expIds, value);
}
/**
* Returns true if the given method is applicable to the given arguments
*/
public boolean isApplicable(MemberDefinition m, Type args[]) throws ClassNotFound {
Type mType = m.getType();
if (!mType.isType(TC_METHOD))
return false;
Type mArgs[] = mType.getArgumentTypes();
if (args.length != mArgs.length)
return false;
for (int i = args.length ; --i >= 0 ;)
if (!isMoreSpecific(args[i], mArgs[i]))
return false;
return true;
}
/**
* Returns true if "best" is in every argument at least as good as "other"
*/
public boolean isMoreSpecific(MemberDefinition best, MemberDefinition other)
throws ClassNotFound {
Type bestType = best.getClassDeclaration().getType();
Type otherType = other.getClassDeclaration().getType();
boolean result = isMoreSpecific(bestType, otherType)
&& isApplicable(other, best.getType().getArgumentTypes());
// System.out.println("isMoreSpecific: " + best + "/" + other
// + " => " + result);
return result;
}
/**
* Returns true if "from" is a more specific type than "to"
*/
public boolean isMoreSpecific(Type from, Type to) throws ClassNotFound {
return implicitCast(from, to);
}
/**
* Return true if an implicit cast from this type to
* the given type is allowed.
*/
public boolean implicitCast(Type from, Type to) throws ClassNotFound {
if (from == to)
return true;
int toTypeCode = to.getTypeCode();
switch(from.getTypeCode()) {
case TC_BYTE:
if (toTypeCode == TC_SHORT)
return true;
case TC_SHORT:
case TC_CHAR:
if (toTypeCode == TC_INT) return true;
case TC_INT:
if (toTypeCode == TC_LONG) return true;
case TC_LONG:
if (toTypeCode == TC_FLOAT) return true;
case TC_FLOAT:
if (toTypeCode == TC_DOUBLE) return true;
case TC_DOUBLE:
default:
return false;
case TC_NULL:
return to.inMask(TM_REFERENCE);
case TC_ARRAY:
if (!to.isType(TC_ARRAY)) {
return (to == Type.tObject || to == Type.tCloneable
|| to == Type.tSerializable);
} else {
// both are arrays. recurse down both until one isn't an array
do {
from = from.getElementType();
to = to.getElementType();
} while (from.isType(TC_ARRAY) && to.isType(TC_ARRAY));
if ( from.inMask(TM_ARRAY|TM_CLASS)
&& to.inMask(TM_ARRAY|TM_CLASS)) {
return isMoreSpecific(from, to);
} else {
return (from.getTypeCode() == to.getTypeCode());
}
}
case TC_CLASS:
if (toTypeCode == TC_CLASS) {
ClassDefinition fromDef = getClassDefinition(from);
ClassDefinition toDef = getClassDefinition(to);
return toDef.implementedBy(this,
fromDef.getClassDeclaration());
} else {
return false;
}
}
}
/**
* Return true if an explicit cast from this type to
* the given type is allowed.
*/
public boolean explicitCast(Type from, Type to) throws ClassNotFound {
if (implicitCast(from, to)) {
return true;
}
if (from.inMask(TM_NUMBER)) {
return to.inMask(TM_NUMBER);
}
if (from.isType(TC_CLASS) && to.isType(TC_CLASS)) {
ClassDefinition fromClass = getClassDefinition(from);
ClassDefinition toClass = getClassDefinition(to);
if (toClass.isFinal()) {
return fromClass.implementedBy(this,
toClass.getClassDeclaration());
}
if (fromClass.isFinal()) {
return toClass.implementedBy(this,
fromClass.getClassDeclaration());
}
// The code here used to omit this case. If both types
// involved in a cast are interfaces, then JLS 5.5 requires
// that we do a simple test -- make sure none of the methods
// in toClass and fromClass have the same signature but
// different return types. (bug number 4028359)
if (toClass.isInterface() && fromClass.isInterface()) {
return toClass.couldImplement(fromClass);
}
return toClass.isInterface() ||
fromClass.isInterface() ||
fromClass.superClassOf(this, toClass.getClassDeclaration());
}
if (to.isType(TC_ARRAY)) {
if (from.isType(TC_ARRAY)) {
Type t1 = from.getElementType();
Type t2 = to.getElementType();
while ((t1.getTypeCode() == TC_ARRAY)
&& (t2.getTypeCode() == TC_ARRAY)) {
t1 = t1.getElementType();
t2 = t2.getElementType();
}
if (t1.inMask(TM_ARRAY|TM_CLASS) &&
t2.inMask(TM_ARRAY|TM_CLASS)) {
return explicitCast(t1, t2);
}
} else if (from == Type.tObject || from == Type.tCloneable
|| from == Type.tSerializable)
return true;
}
return false;
}
/**
* Flags.
*/
public int getFlags() {
return env.getFlags();
}
/**
* Debugging flags. There used to be a method debug()
* that has been replaced because -g has changed meaning
* (it now cooperates with -O and line number, variable
* range and source file info can be toggled separately).
*/
public final boolean debug_lines() {
return (getFlags() & F_DEBUG_LINES) != 0;
}
public final boolean debug_vars() {
return (getFlags() & F_DEBUG_VARS) != 0;
}
public final boolean debug_source() {
return (getFlags() & F_DEBUG_SOURCE) != 0;
}
/**
* Optimization flags. There used to be a method optimize()
* that has been replaced because -O has changed meaning in
* javac to be replaced with -O and -O:interclass.
*/
public final boolean opt() {
return (getFlags() & F_OPT) != 0;
}
public final boolean opt_interclass() {
return (getFlags() & F_OPT_INTERCLASS) != 0;
}
/**
* Verbose
*/
public final boolean verbose() {
return (getFlags() & F_VERBOSE) != 0;
}
/**
* Dump debugging stuff
*/
public final boolean dump() {
return (getFlags() & F_DUMP) != 0;
}
/**
* Verbose
*/
public final boolean warnings() {
return (getFlags() & F_WARNINGS) != 0;
}
/**
* Dependencies
*/
public final boolean dependencies() {
return (getFlags() & F_DEPENDENCIES) != 0;
}
/**
* Print Dependencies to stdout
*/
public final boolean print_dependencies() {
return (getFlags() & F_PRINT_DEPENDENCIES) != 0;
}
/**
* Deprecation warnings are enabled.
*/
public final boolean deprecation() {
return (getFlags() & F_DEPRECATION) != 0;
}
/**
* Do not support virtual machines before version 1.2.
* This option is not supported and is only here for testing purposes.
*/
public final boolean version12() {
return (getFlags() & F_VERSION12) != 0;
}
/**
* Floating point is strict by default
*/
public final boolean strictdefault() {
return (getFlags() & F_STRICTDEFAULT) != 0;
}
/**
* Release resources, if any.
*/
public void shutdown() {
if (env != null) {
env.shutdown();
}
}
/**
* Issue an error.
* source - the input source, usually a file name string
* offset - the offset in the source of the error
* err - the error number (as defined in this interface)
* arg1 - an optional argument to the error (null if not applicable)
* arg2 - a second optional argument to the error (null if not applicable)
* arg3 - a third optional argument to the error (null if not applicable)
*/
public void error(Object source, long where, String err, Object arg1, Object arg2, Object arg3) {
env.error(source, where, err, arg1, arg2, arg3);
}
public final void error(long where, String err, Object arg1, Object arg2, Object arg3) {
error(source, where, err, arg1, arg2, arg3);
}
public final void error(long where, String err, Object arg1, Object arg2) {
error(source, where, err, arg1, arg2, null);
}
public final void error(long where, String err, Object arg1) {
error(source, where, err, arg1, null, null);
}
public final void error(long where, String err) {
error(source, where, err, null, null, null);
}
/**
* Output a string. This can either be an error message or something
* for debugging. This should be used instead of println.
*/
public void output(String msg) {
env.output(msg);
}
private static boolean debugging = (System.getProperty("javac.debug") != null);
public static void debugOutput(Object msg) {
if (Environment.debugging)
System.out.println(msg.toString());
}
/**
* set character encoding name
*/
public void setCharacterEncoding(String encoding) {
this.encoding = encoding;
}
/**
* Return character encoding name
*/
public String getCharacterEncoding() {
return encoding;
}
/**
* Return major version to use in generated class files.
*/
public short getMajorVersion() {
if (env==null) return JAVA_DEFAULT_VERSION; // needed for javah
return env.getMajorVersion();
}
/**
* Return minor version to use in generated class files.
*/
public short getMinorVersion() {
if (env==null) return JAVA_DEFAULT_MINOR_VERSION; // needed for javah
return env.getMinorVersion();
}
// JCOV
/**
* get coverage flag
*/
public final boolean coverage() {
return (getFlags() & F_COVERAGE) != 0;
}
/**
* get flag of generation the coverage data file
*/
public final boolean covdata() {
return (getFlags() & F_COVDATA) != 0;
}
/**
* Return the coverage data file
*/
public File getcovFile() {
return env.getcovFile();
}
// end JCOV
/**
* Debug tracing.
* Currently, this code is used only for tracing the loading and
* checking of classes, particularly the demand-driven aspects.
* This code should probably be integrated with 'debugOutput' above,
* but we need to give more thought to the issue of classifying debugging
* messages and allowing those only those of interest to be enabled.
*
* Calls to these methods are generally conditioned on the final variable
* 'Constants.tracing', which allows the calls to be completely omitted
* in a production release to avoid space and time overhead.
*/
private static boolean dependtrace =
(System.getProperty("javac.trace.depend") != null);
public void dtEnter(String s) {
if (dependtrace) System.out.println(">>> " + s);
}
public void dtExit(String s) {
if (dependtrace) System.out.println("<<< " + s);
}
public void dtEvent(String s) {
if (dependtrace) System.out.println(s);
}
/**
* Enable diagnostic dump of class modifier bits, including those
* in InnerClasses attributes, as they are written to the classfile.
* In the future, may also enable dumping field and method modifiers.
*/
private static boolean dumpmodifiers =
(System.getProperty("javac.dump.modifiers") != null);
public boolean dumpModifiers() { return dumpmodifiers; }
}

View File

@@ -0,0 +1,329 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.util.Hashtable;
import java.io.PrintStream;
import java.util.Enumeration;
/**
* A class to represent identifiers.<p>
*
* An identifier instance is very similar to a String. The difference
* is that identifier can't be instanciated directly, instead they are
* looked up in a hash table. This means that identifiers with the same
* name map to the same identifier object. This makes comparisons of
* identifiers much faster.<p>
*
* A lot of identifiers are qualified, that is they have '.'s in them.
* Each qualified identifier is chopped up into the qualifier and the
* name. The qualifier is cached in the value field.<p>
*
* Unqualified identifiers can have a type. This type is an integer that
* can be used by a scanner as a token value. This value has to be set
* using the setType method.<p>
*
* 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.
*
* @author Arthur van Hoff
*/
public final
class Identifier implements Constants {
/**
* The hashtable of identifiers
*/
static Hashtable hash = new Hashtable(3001, 0.5f);
/**
* The name of the identifier
*/
String name;
/**
* The value of the identifier, for keywords this is an
* instance of class Integer, for qualified names this is
* another identifier (the qualifier).
*/
Object value;
/**
* The Type which corresponds to this Identifier. This is used as
* cache for Type.tClass() and shouldn't be used outside of that
* context.
*/
Type typeObject = null;
/**
* The index of INNERCLASS_PREFIX in the name, or -1 if none.
*/
private int ipos;
/**
* Construct an identifier. Don't call this directly,
* use lookup instead.
* @see Identifier.lookup
*/
private Identifier(String name) {
this.name = name;
this.ipos = name.indexOf(INNERCLASS_PREFIX);
}
/**
* Get the type of the identifier.
*/
int getType() {
return ((value != null) && (value instanceof Integer)) ?
((Integer)value).intValue() : IDENT;
}
/**
* Set the type of the identifier.
*/
void setType(int t) {
value = new Integer(t);
//System.out.println("type(" + this + ")=" + t);
}
/**
* Lookup an identifier.
*/
public static synchronized Identifier lookup(String s) {
//System.out.println("lookup(" + s + ")");
Identifier id = (Identifier)hash.get(s);
if (id == null) {
hash.put(s, id = new Identifier(s));
}
return id;
}
/**
* Lookup a qualified identifier.
*/
public static Identifier lookup(Identifier q, Identifier n) {
// lookup("", x) => x
if (q == idNull) return n;
// lookup(lookupInner(c, ""), n) => lookupInner(c, lookup("", n))
if (q.name.charAt(q.name.length()-1) == INNERCLASS_PREFIX)
return lookup(q.name+n.name);
Identifier id = lookup(q + "." + n);
if (!n.isQualified() && !q.isInner())
id.value = q;
return id;
}
/**
* Lookup an inner identifier.
* (Note: n can be idNull.)
*/
public static Identifier lookupInner(Identifier c, Identifier n) {
Identifier id;
if (c.isInner()) {
if (c.name.charAt(c.name.length()-1) == INNERCLASS_PREFIX)
id = lookup(c.name+n);
else
id = lookup(c, n);
} else {
id = lookup(c + "." + INNERCLASS_PREFIX + n);
}
id.value = c.value;
return id;
}
/**
* Convert to a string.
*/
public String toString() {
return name;
}
/**
* Check if the name is qualified (ie: it contains a '.').
*/
public boolean isQualified() {
if (value == null) {
int idot = ipos;
if (idot <= 0)
idot = name.length();
else
idot -= 1; // back up over previous dot
int index = name.lastIndexOf('.', idot-1);
value = (index < 0) ? idNull : Identifier.lookup(name.substring(0, index));
}
return (value instanceof Identifier) && (value != idNull);
}
/**
* Return the qualifier. The null identifier is returned if
* the name was not qualified. The qualifier does not include
* any inner part of the name.
*/
public Identifier getQualifier() {
return isQualified() ? (Identifier)value : idNull;
}
/**
* Return the unqualified name.
* In the case of an inner name, the unqualified name
* will itself contain components.
*/
public Identifier getName() {
return isQualified() ?
Identifier.lookup(name.substring(((Identifier)value).name.length() + 1)) : this;
}
/** A space character, which precedes the first inner class
* name in a qualified name, and thus marks the qualification
* as involving inner classes, instead of merely packages.<p>
* Ex: <tt>java.util.Vector. Enumerator</tt>.
*/
public static final char INNERCLASS_PREFIX = ' ';
/* Explanation:
* Since much of the compiler's low-level name resolution code
* operates in terms of Identifier objects. This includes the
* code which walks around the file system and reports what
* classes are where. It is important to get nesting information
* right as early as possible, since it affects the spelling of
* signatures. Thus, the low-level import and resolve code must
* be able Identifier type must be able to report the nesting
* of types, which implied that that information must be carried
* by Identifiers--or that the low-level interfaces be significantly
* changed.
*/
/**
* Check if the name is inner (ie: it contains a ' ').
*/
public boolean isInner() {
return (ipos > 0);
}
/**
* Return the class name, without its qualifier,
* and with any nesting flattened into a new qualfication structure.
* If the original identifier is inner,
* the result will be qualified, and can be further
* decomposed by means of <tt>getQualifier</tt> and <tt>getName</tt>.
* <p>
* For example:
* <pre>
* Identifier id = Identifier.lookup("pkg.Foo. Bar");
* id.getName().name => "Foo. Bar"
* id.getFlatName().name => "Foo.Bar"
* </pre>
*/
public Identifier getFlatName() {
if (isQualified()) {
return getName().getFlatName();
}
if (ipos > 0 && name.charAt(ipos-1) == '.') {
if (ipos+1 == name.length()) {
// last component is idNull
return Identifier.lookup(name.substring(0,ipos-1));
}
String n = name.substring(ipos+1);
String t = name.substring(0,ipos);
return Identifier.lookup(t+n);
}
// Not inner. Just return the same as getName()
return this;
}
public Identifier getTopName() {
if (!isInner()) return this;
return Identifier.lookup(getQualifier(), getFlatName().getHead());
}
/**
* Yet another way to slice qualified identifiers:
* The head of an identifier is its first qualifier component,
* and the tail is the rest of them.
*/
public Identifier getHead() {
Identifier id = this;
while (id.isQualified())
id = id.getQualifier();
return id;
}
/**
* @see getHead
*/
public Identifier getTail() {
Identifier id = getHead();
if (id == this)
return idNull;
else
return Identifier.lookup(name.substring(id.name.length() + 1));
}
// Unfortunately, the current structure of the compiler requires
// that the resolveName() family of methods (which appear in
// Environment.java, Context.java, and ClassDefinition.java) raise
// no exceptions and emit no errors. When we are in resolveName()
// and we find a method that is ambiguous, we need to
// unambiguously mark it as such, so that later stages of the
// compiler realize that they should give an ambig.class rather than
// a class.not.found error. To mark it we add a special prefix
// which cannot occur in the program source. The routines below
// are used to check, add, and remove this prefix.
// (part of solution for 4059855).
/**
* A special prefix to add to ambiguous names.
*/
private static final String ambigPrefix = "<<ambiguous>>";
/**
* Determine whether an Identifier has been marked as ambiguous.
*/
public boolean hasAmbigPrefix() {
return (name.startsWith(ambigPrefix));
}
/**
* Add ambigPrefix to `this' to make a new Identifier marked as
* ambiguous. It is important that this new Identifier not refer
* to an existing class.
*/
public Identifier addAmbigPrefix() {
return Identifier.lookup(ambigPrefix + name);
}
/**
* Remove the ambigPrefix from `this' to get the original identifier.
*/
public Identifier removeAmbigPrefix() {
if (hasAmbigPrefix()) {
return Identifier.lookup(name.substring(ambigPrefix.length()));
} else {
return this;
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright (c) 1996, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
/**
* Information about the occurrence of an identifier.
* The parser produces these to represent name which cannot yet be
* bound to field definitions.
*
* 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.
*
* @see
*/
public
class IdentifierToken {
long where;
int modifiers;
Identifier id;
public IdentifierToken(long where, Identifier id) {
this.where = where;
this.id = id;
}
/** Use this constructor when the identifier is synthesized.
* The location will be 0.
*/
public IdentifierToken(Identifier id) {
this.where = 0;
this.id = id;
}
public IdentifierToken(long where, Identifier id, int modifiers) {
this.where = where;
this.id = id;
this.modifiers = modifiers;
}
/** The source location of this identifier occurrence. */
public long getWhere() {
return where;
}
/** The identifier itself (possibly qualified). */
public Identifier getName() {
return id;
}
/** The modifiers associated with the occurrence, if any. */
public int getModifiers() {
return modifiers;
}
public String toString() {
return id.toString();
}
/**
* Return defaultWhere if id is null or id.where is missing (0).
* Otherwise, return id.where.
*/
public static long getWhere(IdentifierToken id, long defaultWhere) {
return (id != null && id.where != 0) ? id.where : defaultWhere;
}
}

View File

@@ -0,0 +1,503 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.util.Hashtable;
import java.util.Vector;
import java.util.Enumeration;
import java.util.List;
import java.util.Collections;
import java.io.IOException;
/**
* This class describes the classes and packages imported
* from a source file. A Hashtable called bindings is maintained
* to quickly map symbol names to classes. This table is flushed
* everytime a new import is added.
*
* A class name is resolved as follows:
* - if it is a qualified name then return the corresponding class
* - if the name corresponds to an individually imported class then return that class
* - check if the class is defined in any of the imported packages,
* if it is then return it, make sure it is defined in only one package
* - assume that the class is defined in the current package
*
* 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.
*/
public
class Imports implements Constants {
/**
* The current package, which is implicitly imported,
* and has precedence over other imported packages.
*/
Identifier currentPackage = idNull;
/**
* A location for the current package declaration. Used to
* report errors against the current package.
*/
long currentPackageWhere = 0;
/**
* The imported classes, including memoized imports from packages.
*/
Hashtable classes = new Hashtable();
/**
* The imported package identifiers. This will not contain duplicate
* imports for the same package. It will also not contain the
* current package.
*/
Vector packages = new Vector();
/**
* The (originally) imported classes.
* A vector of IdentifierToken.
*/
Vector singles = new Vector();
/**
* Are the import names checked yet?
*/
protected int checked;
/**
* Constructor, always import java.lang.
*/
public Imports(Environment env) {
addPackage(idJavaLang);
}
/**
* Check the names of the imports.
*/
public synchronized void resolve(Environment env) {
if (checked != 0) {
return;
}
checked = -1;
// After all class information has been read, now we can
// safely inspect import information for errors.
// If we did this before all parsing was finished,
// we could get vicious circularities, since files can
// import each others' classes.
// A note: the resolution of the package java.lang takes place
// in the sun.tools.javac.BatchEnvironment#setExemptPackages().
// Make sure that the current package's name does not collide
// with the name of an existing class. (bug 4101529)
//
// This change has been backed out because, on WIN32, it
// failed to distinguish between java.awt.event and
// java.awt.Event when looking for a directory. We will
// add this back in later.
//
// if (currentPackage != idNull) {
// Identifier resolvedName =
// env.resolvePackageQualifiedName(currentPackage);
//
// Identifier className = resolvedName.getTopName();
//
// if (importable(className, env)) {
// // The name of the current package is also the name
// // of a class.
// env.error(currentPackageWhere, "package.class.conflict",
// currentPackage, className);
// }
// }
Vector resolvedPackages = new Vector();
for (Enumeration e = packages.elements() ; e.hasMoreElements() ;) {
IdentifierToken t = (IdentifierToken)e.nextElement();
Identifier nm = t.getName();
long where = t.getWhere();
// Check to see if this package is exempt from the "exists"
// check. See the note in
// sun.tools.javac.BatchEnvironment#setExemptPackages()
// for more information.
if (env.isExemptPackage(nm)) {
resolvedPackages.addElement(t);
continue;
}
// (Note: This code is moved from BatchParser.importPackage().)
try {
Identifier rnm = env.resolvePackageQualifiedName(nm);
if (importable(rnm, env)) {
// This name is a real class; better not be a package too.
if (env.getPackage(rnm.getTopName()).exists()) {
env.error(where, "class.and.package",
rnm.getTopName());
}
// Pass an "inner" name to the imports.
if (!rnm.isInner())
rnm = Identifier.lookupInner(rnm, idNull);
nm = rnm;
} else if (!env.getPackage(nm).exists()) {
env.error(where, "package.not.found", nm, "import");
} else if (rnm.isInner()) {
// nm exists, and rnm.getTopName() is a parent package
env.error(where, "class.and.package", rnm.getTopName());
}
resolvedPackages.addElement(new IdentifierToken(where, nm));
} catch (IOException ee) {
env.error(where, "io.exception", "import");
}
}
packages = resolvedPackages;
for (Enumeration e = singles.elements() ; e.hasMoreElements() ;) {
IdentifierToken t = (IdentifierToken)e.nextElement();
Identifier nm = t.getName();
long where = t.getWhere();
Identifier pkg = nm.getQualifier();
// (Note: This code is moved from BatchParser.importClass().)
nm = env.resolvePackageQualifiedName(nm);
if (!env.classExists(nm.getTopName())) {
env.error(where, "class.not.found", nm, "import");
}
// (Note: This code is moved from Imports.addClass().)
Identifier snm = nm.getFlatName().getName();
// make sure it isn't already imported explicitly
Identifier className = (Identifier)classes.get(snm);
if (className != null) {
Identifier f1 = Identifier.lookup(className.getQualifier(),
className.getFlatName());
Identifier f2 = Identifier.lookup(nm.getQualifier(),
nm.getFlatName());
if (!f1.equals(f2)) {
env.error(where, "ambig.class", nm, className);
}
}
classes.put(snm, nm);
// The code here needs to check to see, if we
// are importing an inner class, that all of its
// enclosing classes are visible to us. To check this,
// we need to construct a definition for the class.
// The code here used to call...
//
// ClassDefinition def = env.getClassDefinition(nm);
//
// ...but that interfered with the basicCheck()'ing of
// interfaces in certain cases (bug no. 4086139). Never
// fear. Instead we load the class with a call to the
// new getClassDefinitionNoCheck() which does no basicCheck() and
// lets us answer the questions we are interested in w/o
// interfering with the demand-driven nature of basicCheck().
try {
// Get a declaration
ClassDeclaration decl = env.getClassDeclaration(nm);
// Get the definition (no env argument)
ClassDefinition def = decl.getClassDefinitionNoCheck(env);
// Get the true name of the package containing this class.
// `pkg' from above is insufficient. It includes the
// names of our enclosing classes. Fix for 4086815.
Identifier importedPackage = def.getName().getQualifier();
// Walk out the outerClass chain, ensuring that each level
// is visible from our perspective.
for (; def != null; def = def.getOuterClass()) {
if (def.isPrivate()
|| !(def.isPublic()
|| importedPackage.equals(currentPackage))) {
env.error(where, "cant.access.class", def);
break;
}
}
} catch (AmbiguousClass ee) {
env.error(where, "ambig.class", ee.name1, ee.name2);
} catch (ClassNotFound ee) {
env.error(where, "class.not.found", ee.name, "import");
}
}
checked = 1;
}
/**
* Lookup a class, given the current set of imports,
* AmbiguousClass exception is thrown if the name can be
* resolved in more than one way. A ClassNotFound exception
* is thrown if the class is not found in the imported classes
* and packages.
*/
public synchronized Identifier resolve(Environment env, Identifier nm) throws ClassNotFound {
if (tracing) env.dtEnter("Imports.resolve: " + nm);
// If the class has the special ambiguous prefix, then we will
// get the original AmbiguousClass exception by removing the
// prefix and proceeding in the normal fashion.
// (part of solution for 4059855)
if (nm.hasAmbigPrefix()) {
nm = nm.removeAmbigPrefix();
}
if (nm.isQualified()) {
// Don't bother it is already qualified
if (tracing) env.dtExit("Imports.resolve: QUALIFIED " + nm);
return nm;
}
if (checked <= 0) {
checked = 0;
resolve(env);
}
// Check if it was imported before
Identifier className = (Identifier)classes.get(nm);
if (className != null) {
if (tracing) env.dtExit("Imports.resolve: PREVIOUSLY IMPORTED " + nm);
return className;
}
// Note: the section below has changed a bit during the fix
// for bug 4093217. The current package is no longer grouped
// with the rest of the import-on-demands; it is now checked
// separately. Also, the list of import-on-demands is now
// guarranteed to be duplicate-free, so the code below can afford
// to be a bit simpler.
// First we look in the current package. The current package
// is given precedence over the rest of the import-on-demands,
// which means, among other things, that a class in the current
// package cannot be ambiguous.
Identifier id = Identifier.lookup(currentPackage, nm);
if (importable(id, env)) {
className = id;
} else {
// If it isn't in the current package, try to find it in
// our import-on-demands.
Enumeration e = packages.elements();
while (e.hasMoreElements()) {
IdentifierToken t = (IdentifierToken)e.nextElement();
id = Identifier.lookup(t.getName(), nm);
if (importable(id, env)) {
if (className == null) {
// We haven't found any other matching classes yet.
// Set className to what we've found and continue
// looking for an ambiguity.
className = id;
} else {
if (tracing)
env.dtExit("Imports.resolve: AMBIGUOUS " + nm);
// We've found an ambiguity.
throw new AmbiguousClass(className, id);
}
}
}
}
// Make sure a class was found
if (className == null) {
if (tracing) env.dtExit("Imports.resolve: NOT FOUND " + nm);
throw new ClassNotFound(nm);
}
// Remember the binding
classes.put(nm, className);
if (tracing) env.dtExit("Imports.resolve: FIRST IMPORT " + nm);
return className;
}
/**
* Check to see if 'id' names an importable class in `env'.
* This method was made public and static for utility.
*/
static public boolean importable(Identifier id, Environment env) {
if (!id.isInner()) {
return env.classExists(id);
} else if (!env.classExists(id.getTopName())) {
return false;
} else {
// load the top class and look inside it
try {
// There used to be a call to...
// env.getClassDeclaration(id.getTopName());
// ...here. It has been replaced with the
// two statements below. These should be functionally
// the same except for the fact that
// getClassDefinitionNoCheck() does not call
// basicCheck(). This allows us to avoid a circular
// need to do basicChecking that can arise with
// certain patterns of importing and inheritance.
// This is a fix for a variant of bug 4086139.
//
// Note: the special case code in env.getClassDefinition()
// which handles inner class names is not replicated below.
// This should be okay, as we are looking up id.getTopName(),
// not id.
ClassDeclaration decl =
env.getClassDeclaration(id.getTopName());
ClassDefinition c =
decl.getClassDefinitionNoCheck(env);
return c.innerClassExists(id.getFlatName().getTail());
} catch (ClassNotFound ee) {
return false;
}
}
}
/**
* Suppose a resolve() call has failed.
* This routine can be used silently to give a reasonable
* default qualification (the current package) to the identifier.
* This decision is recorded for future reference.
*/
public synchronized Identifier forceResolve(Environment env, Identifier nm) {
if (nm.isQualified())
return nm;
Identifier className = (Identifier)classes.get(nm);
if (className != null) {
return className;
}
className = Identifier.lookup(currentPackage, nm);
classes.put(nm, className);
return className;
}
/**
* Add a class import
*/
public synchronized void addClass(IdentifierToken t) {
singles.addElement(t);
}
// for compatibility
public void addClass(Identifier nm) throws AmbiguousClass {
addClass(new IdentifierToken(nm));
}
/**
* Add a package import, or perhaps an inner class scope.
* Ignore any duplicate imports.
*/
public synchronized void addPackage(IdentifierToken t) {
final Identifier name = t.getName();
// If this is a duplicate import for the current package,
// ignore it.
if (name == currentPackage) {
return;
}
// If this is a duplicate of a package which has already been
// added to the list, ignore it.
final int size = packages.size();
for (int i = 0; i < size; i++) {
if (name == ((IdentifierToken)packages.elementAt(i)).getName()) {
return;
}
}
// Add the package to the list.
packages.addElement(t);
}
// for compatibility
public void addPackage(Identifier id) {
addPackage(new IdentifierToken(id));
}
/**
* Specify the current package with an IdentifierToken.
*/
public synchronized void setCurrentPackage(IdentifierToken t) {
currentPackage = t.getName();
currentPackageWhere = t.getWhere();
}
/**
* Specify the current package
*/
public synchronized void setCurrentPackage(Identifier id) {
currentPackage = id;
}
/**
* Report the current package
*/
public Identifier getCurrentPackage() {
return currentPackage;
}
/**
* Return an unmodifiable list of IdentifierToken representing
* packages specified as imports.
*/
public List getImportedPackages() {
return Collections.unmodifiableList(packages);
}
/**
* Return an unmodifiable list of IdentifierToken representing
* classes specified as imports.
*/
public List getImportedClasses() {
return Collections.unmodifiableList(singles);
}
/**
* Extend an environment with my resolve() method.
*/
public Environment newEnvironment(Environment env) {
return new ImportEnvironment(env, this);
}
}
final
class ImportEnvironment extends Environment {
Imports imports;
ImportEnvironment(Environment env, Imports imports) {
super(env, env.getSource());
this.imports = imports;
}
public Identifier resolve(Identifier nm) throws ClassNotFound {
return imports.resolve(this, nm);
}
public Imports getImports() {
return imports;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,278 @@
/*
* Copyright (c) 1997, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.util.*;
/**
* The MethodSet structure is used to store methods for a class.
* It maintains the invariant that it never stores two methods
* with the same signature. MethodSets are able to lookup
* all methods with a given name and the unique method with a given
* signature (name, args).
*
* 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.
*/
public
class MethodSet {
/**
* A Map containing Lists of MemberDefinitions. The Lists
* contain methods which share the same name.
*/
private final Map lookupMap;
/**
* The number of methods stored in the MethodSet.
*/
private int count;
/**
* Is this MethodSet currently frozen? See freeze() for more details.
*/
private boolean frozen;
/**
* Creates a brand new MethodSet
*/
public MethodSet() {
frozen = false;
lookupMap = new HashMap();
count = 0;
}
/**
* Returns the number of distinct methods stored in the MethodSet.
*/
public int size() {
return count;
}
/**
* Adds `method' to the MethodSet. No method of the same signature
* should be already defined.
*/
public void add(MemberDefinition method) {
// Check for late additions.
if (frozen) {
throw new CompilerError("add()");
}
// todo: Check for method??
Identifier name = method.getName();
// Get a List containing all methods of this name.
List methodList = (List) lookupMap.get(name);
if (methodList == null) {
// There is no method with this name already.
// Create a List, and insert it into the hash.
methodList = new ArrayList();
lookupMap.put(name, methodList);
}
// Make sure that no method with the same signature has already
// been added to the MethodSet.
int size = methodList.size();
for (int i = 0; i < size; i++) {
if (((MemberDefinition) methodList.get(i))
.getType().equalArguments(method.getType())) {
throw new CompilerError("duplicate addition");
}
}
// We add the method to the appropriate list.
methodList.add(method);
count++;
}
/**
* Adds `method' to the MethodSet, replacing any previous definition
* with the same signature.
*/
public void replace(MemberDefinition method) {
// Check for late additions.
if (frozen) {
throw new CompilerError("replace()");
}
// todo: Check for method??
Identifier name = method.getName();
// Get a List containing all methods of this name.
List methodList = (List) lookupMap.get(name);
if (methodList == null) {
// There is no method with this name already.
// Create a List, and insert it into the hash.
methodList = new ArrayList();
lookupMap.put(name, methodList);
}
// Replace the element which has the same signature as
// `method'.
int size = methodList.size();
for (int i = 0; i < size; i++) {
if (((MemberDefinition) methodList.get(i))
.getType().equalArguments(method.getType())) {
methodList.set(i, method);
return;
}
}
// We add the method to the appropriate list.
methodList.add(method);
count++;
}
/**
* If the MethodSet contains a method with the same signature
* then lookup() returns it. Otherwise, this method returns null.
*/
public MemberDefinition lookupSig(Identifier name, Type type) {
// Go through all methods of the same name and see if any
// have the right signature.
Iterator matches = lookupName(name);
MemberDefinition candidate;
while (matches.hasNext()) {
candidate = (MemberDefinition) matches.next();
if (candidate.getType().equalArguments(type)) {
return candidate;
}
}
// No match.
return null;
}
/**
* Returns an Iterator of all methods contained in the
* MethodSet which have a given name.
*/
public Iterator lookupName(Identifier name) {
// Find the List containing all methods of this name, and
// return that List's Iterator.
List methodList = (List) lookupMap.get(name);
if (methodList == null) {
// If there is no method of this name, return a bogus, empty
// Iterator.
return Collections.emptyIterator();
}
return methodList.iterator();
}
/**
* Returns an Iterator of all methods in the MethodSet
*/
public Iterator iterator() {
//----------------------------------------------------------
// The inner class MethodIterator is used to create our
// Iterator of all methods in the MethodSet.
class MethodIterator implements Iterator {
Iterator hashIter = lookupMap.values().iterator();
Iterator listIter = Collections.emptyIterator();
public boolean hasNext() {
if (listIter.hasNext()) {
return true;
} else {
if (hashIter.hasNext()) {
listIter = ((List) hashIter.next())
.iterator();
// The following should be always true.
if (listIter.hasNext()) {
return true;
} else {
throw new
CompilerError("iterator() in MethodSet");
}
}
}
// We've run out of Lists.
return false;
}
public Object next() {
return listIter.next();
}
public void remove() {
throw new UnsupportedOperationException();
}
}
// end MethodIterator
//----------------------------------------------------------
// A one-liner.
return new MethodIterator();
}
/**
* After freeze() is called, the MethodSet becomes (mostly)
* immutable. Any calls to add() or addMeet() lead to
* CompilerErrors. Note that the entries themselves are still
* (unfortunately) open for mischievous and wanton modification.
*/
public void freeze() {
frozen = true;
}
/**
* Tells whether freeze() has been called on this MethodSet.
*/
public boolean isFrozen() {
return frozen;
}
/**
* Returns a (big) string representation of this MethodSet
*/
public String toString() {
int len = size();
StringBuffer buf = new StringBuffer();
Iterator all = iterator();
buf.append("{");
while (all.hasNext()) {
buf.append(all.next().toString());
len--;
if (len > 0) {
buf.append(", ");
}
}
buf.append("}");
return buf.toString();
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
/**
* This class represents an Java method type.
* It overrides the relevant methods in class Type.
*
* 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.
*
* @author Arthur van Hoff
*/
public final
class MethodType extends Type {
/**
* The return type.
*/
Type returnType;
/**
* The argument types.
*/
Type argTypes[];
/**
* Construct a method type. Use Type.tMethod to create
* a new method type.
* @see Type.tMethod
*/
MethodType(String typeSig, Type returnType, Type argTypes[]) {
super(TC_METHOD, typeSig);
this.returnType = returnType;
this.argTypes = argTypes;
}
public Type getReturnType() {
return returnType;
}
public Type getArgumentTypes()[] {
return argTypes;
}
public boolean equalArguments(Type t) {
if (t.typeCode != TC_METHOD) {
return false;
}
MethodType m = (MethodType)t;
if (argTypes.length != m.argTypes.length) {
return false;
}
for (int i = argTypes.length - 1 ; i >= 0 ; i--) {
if (argTypes[i] != m.argTypes[i]) {
return false;
}
}
return true;
}
public int stackSize() {
int n = 0;
for (int i = 0 ; i < argTypes.length ; i++) {
n += argTypes[i].stackSize();
}
return n;
}
public String typeString(String id, boolean abbrev, boolean ret) {
StringBuffer buf = new StringBuffer();
buf.append(id);
buf.append('(');
for (int i = 0 ; i < argTypes.length ; i++) {
if (i > 0) {
buf.append(", ");
}
buf.append(argTypes[i].typeString("", abbrev, ret));
}
buf.append(')');
return ret ? getReturnType().typeString(buf.toString(), abbrev, ret) : buf.toString();
}
}

View File

@@ -0,0 +1,161 @@
/*
* Copyright (c) 1995, 2004, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.util.Enumeration;
import java.io.File;
import java.io.IOException;
/**
* This class is used to represent the classes in a package.
*
* 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.
*/
public
class Package {
/**
* The path which we use to locate source files.
*/
ClassPath sourcePath;
/**
* The path which we use to locate class (binary) files.
*/
ClassPath binaryPath;
/**
* The path name of the package.
*/
String pkg;
/**
* Create a package given a class path, and package name.
*/
public Package(ClassPath path, Identifier pkg) throws IOException {
this(path, path, pkg);
}
/**
* Create a package given a source path, binary path, and package
* name.
*/
public Package(ClassPath sourcePath,
ClassPath binaryPath,
Identifier pkg)
throws IOException {
if (pkg.isInner())
pkg = Identifier.lookup(pkg.getQualifier(), pkg.getFlatName());
this.sourcePath = sourcePath;
this.binaryPath = binaryPath;
this.pkg = pkg.toString().replace('.', File.separatorChar);
}
/**
* Check if a class is defined in this package.
* (If it is an inner class name, it is assumed to exist
* only if its binary file exists. This is somewhat pessimistic.)
*/
public boolean classExists(Identifier className) {
return getBinaryFile(className) != null ||
!className.isInner() &&
getSourceFile(className) != null;
}
/**
* Check if the package exists
*/
public boolean exists() {
// Look for the directory on our binary path.
ClassFile dir = binaryPath.getDirectory(pkg);
if (dir != null && dir.isDirectory()) {
return true;
}
if (sourcePath != binaryPath) {
// Look for the directory on our source path.
dir = sourcePath.getDirectory(pkg);
if (dir != null && dir.isDirectory()) {
return true;
}
}
/* Accommodate ZIP files without CEN entries for directories
* (packages): look on class path for at least one binary
* file or one source file with the right package prefix
*/
String prefix = pkg + File.separator;
return binaryPath.getFiles(prefix, ".class").hasMoreElements()
|| sourcePath.getFiles(prefix, ".java").hasMoreElements();
}
private String makeName(String fileName) {
return pkg.equals("") ? fileName : pkg + File.separator + fileName;
}
/**
* Get the .class file of a class
*/
public ClassFile getBinaryFile(Identifier className) {
className = Type.mangleInnerType(className);
String fileName = className.toString() + ".class";
return binaryPath.getFile(makeName(fileName));
}
/**
* Get the .java file of a class
*/
public ClassFile getSourceFile(Identifier className) {
// The source file of an inner class is that of its outer class.
className = className.getTopName();
String fileName = className.toString() + ".java";
return sourcePath.getFile(makeName(fileName));
}
public ClassFile getSourceFile(String fileName) {
if (fileName.endsWith(".java")) {
return sourcePath.getFile(makeName(fileName));
}
return null;
}
public Enumeration getSourceFiles() {
return sourcePath.getFiles(pkg, ".java");
}
public Enumeration getBinaryFiles() {
return binaryPath.getFiles(pkg, ".class");
}
public String toString() {
if (pkg.equals("")) {
return "unnamed package";
}
return "package " + pkg;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 1996, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import sun.tools.tree.*;
/**
* This is the protocol by which a Parser makes callbacks
* to the later phases of the compiler.
* <p>
* (As a backwards compatibility trick, Parser implements
* this protocol, so that an instance of a Parser subclass
* can handle its own actions. The preferred way to use a
* Parser, however, is to instantiate it directly with a
* reference to your own ParserActions implementation.)
*
* 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.
*
* @author John R. Rose
*/
public interface ParserActions {
/**
* package declaration
*/
void packageDeclaration(long off, IdentifierToken nm);
/**
* import class
*/
void importClass(long off, IdentifierToken nm);
/**
* import package
*/
void importPackage(long off, IdentifierToken nm);
/**
* Define class
* @return a cookie for the class
* This cookie is used by the parser when calling defineField
* and endClass, and is not examined otherwise.
*/
ClassDefinition beginClass(long off, String doc,
int mod, IdentifierToken nm,
IdentifierToken sup, IdentifierToken impl[]);
/**
* End class
* @param c a cookie returned by the corresponding beginClass call
*/
void endClass(long off, ClassDefinition c);
/**
* Define a field
* @param c a cookie returned by the corresponding beginClass call
*/
void defineField(long where, ClassDefinition c,
String doc, int mod, Type t,
IdentifierToken nm, IdentifierToken args[],
IdentifierToken exp[], Node val);
}

View File

@@ -0,0 +1,742 @@
/*
* Copyright (c) 1998, 2013, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
/**
* 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.
*/
public interface RuntimeConstants {
/* Signature Characters */
char SIGC_VOID = 'V';
String SIG_VOID = "V";
char SIGC_BOOLEAN = 'Z';
String SIG_BOOLEAN = "Z";
char SIGC_BYTE = 'B';
String SIG_BYTE = "B";
char SIGC_CHAR = 'C';
String SIG_CHAR = "C";
char SIGC_SHORT = 'S';
String SIG_SHORT = "S";
char SIGC_INT = 'I';
String SIG_INT = "I";
char SIGC_LONG = 'J';
String SIG_LONG = "J";
char SIGC_FLOAT = 'F';
String SIG_FLOAT = "F";
char SIGC_DOUBLE = 'D';
String SIG_DOUBLE = "D";
char SIGC_ARRAY = '[';
String SIG_ARRAY = "[";
char SIGC_CLASS = 'L';
String SIG_CLASS = "L";
char SIGC_METHOD = '(';
String SIG_METHOD = "(";
char SIGC_ENDCLASS = ';';
String SIG_ENDCLASS = ";";
char SIGC_ENDMETHOD = ')';
String SIG_ENDMETHOD = ")";
char SIGC_PACKAGE = '/';
String SIG_PACKAGE = "/";
/* Class File Constants */
int JAVA_MAGIC = 0xcafebabe;
int JAVA_MIN_SUPPORTED_VERSION = 45;
int JAVA_MAX_SUPPORTED_VERSION = 52;
int JAVA_MAX_SUPPORTED_MINOR_VERSION = 0;
/* Generate class file version for 1.1 by default */
int JAVA_DEFAULT_VERSION = 45;
int JAVA_DEFAULT_MINOR_VERSION = 3;
/* Constant table */
int CONSTANT_UTF8 = 1;
int CONSTANT_UNICODE = 2;
int CONSTANT_INTEGER = 3;
int CONSTANT_FLOAT = 4;
int CONSTANT_LONG = 5;
int CONSTANT_DOUBLE = 6;
int CONSTANT_CLASS = 7;
int CONSTANT_STRING = 8;
int CONSTANT_FIELD = 9;
int CONSTANT_METHOD = 10;
int CONSTANT_INTERFACEMETHOD = 11;
int CONSTANT_NAMEANDTYPE = 12;
int CONSTANT_METHODHANDLE = 15;
int CONSTANT_METHODTYPE = 16;
int CONSTANT_INVOKEDYNAMIC = 18;
/* Access and modifier flags */
int ACC_PUBLIC = 0x00000001;
int ACC_PRIVATE = 0x00000002;
int ACC_PROTECTED = 0x00000004;
int ACC_STATIC = 0x00000008;
int ACC_FINAL = 0x00000010;
int ACC_SYNCHRONIZED = 0x00000020;
int ACC_VOLATILE = 0x00000040;
int ACC_TRANSIENT = 0x00000080;
int ACC_NATIVE = 0x00000100;
int ACC_INTERFACE = 0x00000200;
int ACC_ABSTRACT = 0x00000400;
int ACC_SUPER = 0x00000020;
int ACC_STRICT = 0x00000800;
/* Type codes */
int T_CLASS = 0x00000002;
int T_BOOLEAN = 0x00000004;
int T_CHAR = 0x00000005;
int T_FLOAT = 0x00000006;
int T_DOUBLE = 0x00000007;
int T_BYTE = 0x00000008;
int T_SHORT = 0x00000009;
int T_INT = 0x0000000a;
int T_LONG = 0x0000000b;
/* Opcodes */
int opc_try = -3;
int opc_dead = -2;
int opc_label = -1;
int opc_nop = 0;
int opc_aconst_null = 1;
int opc_iconst_m1 = 2;
int opc_iconst_0 = 3;
int opc_iconst_1 = 4;
int opc_iconst_2 = 5;
int opc_iconst_3 = 6;
int opc_iconst_4 = 7;
int opc_iconst_5 = 8;
int opc_lconst_0 = 9;
int opc_lconst_1 = 10;
int opc_fconst_0 = 11;
int opc_fconst_1 = 12;
int opc_fconst_2 = 13;
int opc_dconst_0 = 14;
int opc_dconst_1 = 15;
int opc_bipush = 16;
int opc_sipush = 17;
int opc_ldc = 18;
int opc_ldc_w = 19;
int opc_ldc2_w = 20;
int opc_iload = 21;
int opc_lload = 22;
int opc_fload = 23;
int opc_dload = 24;
int opc_aload = 25;
int opc_iload_0 = 26;
int opc_iload_1 = 27;
int opc_iload_2 = 28;
int opc_iload_3 = 29;
int opc_lload_0 = 30;
int opc_lload_1 = 31;
int opc_lload_2 = 32;
int opc_lload_3 = 33;
int opc_fload_0 = 34;
int opc_fload_1 = 35;
int opc_fload_2 = 36;
int opc_fload_3 = 37;
int opc_dload_0 = 38;
int opc_dload_1 = 39;
int opc_dload_2 = 40;
int opc_dload_3 = 41;
int opc_aload_0 = 42;
int opc_aload_1 = 43;
int opc_aload_2 = 44;
int opc_aload_3 = 45;
int opc_iaload = 46;
int opc_laload = 47;
int opc_faload = 48;
int opc_daload = 49;
int opc_aaload = 50;
int opc_baload = 51;
int opc_caload = 52;
int opc_saload = 53;
int opc_istore = 54;
int opc_lstore = 55;
int opc_fstore = 56;
int opc_dstore = 57;
int opc_astore = 58;
int opc_istore_0 = 59;
int opc_istore_1 = 60;
int opc_istore_2 = 61;
int opc_istore_3 = 62;
int opc_lstore_0 = 63;
int opc_lstore_1 = 64;
int opc_lstore_2 = 65;
int opc_lstore_3 = 66;
int opc_fstore_0 = 67;
int opc_fstore_1 = 68;
int opc_fstore_2 = 69;
int opc_fstore_3 = 70;
int opc_dstore_0 = 71;
int opc_dstore_1 = 72;
int opc_dstore_2 = 73;
int opc_dstore_3 = 74;
int opc_astore_0 = 75;
int opc_astore_1 = 76;
int opc_astore_2 = 77;
int opc_astore_3 = 78;
int opc_iastore = 79;
int opc_lastore = 80;
int opc_fastore = 81;
int opc_dastore = 82;
int opc_aastore = 83;
int opc_bastore = 84;
int opc_castore = 85;
int opc_sastore = 86;
int opc_pop = 87;
int opc_pop2 = 88;
int opc_dup = 89;
int opc_dup_x1 = 90;
int opc_dup_x2 = 91;
int opc_dup2 = 92;
int opc_dup2_x1 = 93;
int opc_dup2_x2 = 94;
int opc_swap = 95;
int opc_iadd = 96;
int opc_ladd = 97;
int opc_fadd = 98;
int opc_dadd = 99;
int opc_isub = 100;
int opc_lsub = 101;
int opc_fsub = 102;
int opc_dsub = 103;
int opc_imul = 104;
int opc_lmul = 105;
int opc_fmul = 106;
int opc_dmul = 107;
int opc_idiv = 108;
int opc_ldiv = 109;
int opc_fdiv = 110;
int opc_ddiv = 111;
int opc_irem = 112;
int opc_lrem = 113;
int opc_frem = 114;
int opc_drem = 115;
int opc_ineg = 116;
int opc_lneg = 117;
int opc_fneg = 118;
int opc_dneg = 119;
int opc_ishl = 120;
int opc_lshl = 121;
int opc_ishr = 122;
int opc_lshr = 123;
int opc_iushr = 124;
int opc_lushr = 125;
int opc_iand = 126;
int opc_land = 127;
int opc_ior = 128;
int opc_lor = 129;
int opc_ixor = 130;
int opc_lxor = 131;
int opc_iinc = 132;
int opc_i2l = 133;
int opc_i2f = 134;
int opc_i2d = 135;
int opc_l2i = 136;
int opc_l2f = 137;
int opc_l2d = 138;
int opc_f2i = 139;
int opc_f2l = 140;
int opc_f2d = 141;
int opc_d2i = 142;
int opc_d2l = 143;
int opc_d2f = 144;
int opc_i2b = 145;
int opc_i2c = 146;
int opc_i2s = 147;
int opc_lcmp = 148;
int opc_fcmpl = 149;
int opc_fcmpg = 150;
int opc_dcmpl = 151;
int opc_dcmpg = 152;
int opc_ifeq = 153;
int opc_ifne = 154;
int opc_iflt = 155;
int opc_ifge = 156;
int opc_ifgt = 157;
int opc_ifle = 158;
int opc_if_icmpeq = 159;
int opc_if_icmpne = 160;
int opc_if_icmplt = 161;
int opc_if_icmpge = 162;
int opc_if_icmpgt = 163;
int opc_if_icmple = 164;
int opc_if_acmpeq = 165;
int opc_if_acmpne = 166;
int opc_goto = 167;
int opc_jsr = 168;
int opc_ret = 169;
int opc_tableswitch = 170;
int opc_lookupswitch = 171;
int opc_ireturn = 172;
int opc_lreturn = 173;
int opc_freturn = 174;
int opc_dreturn = 175;
int opc_areturn = 176;
int opc_return = 177;
int opc_getstatic = 178;
int opc_putstatic = 179;
int opc_getfield = 180;
int opc_putfield = 181;
int opc_invokevirtual = 182;
int opc_invokespecial = 183;
int opc_invokestatic = 184;
int opc_invokeinterface = 185;
int opc_invokedynamic = 186;
int opc_new = 187;
int opc_newarray = 188;
int opc_anewarray = 189;
int opc_arraylength = 190;
int opc_athrow = 191;
int opc_checkcast = 192;
int opc_instanceof = 193;
int opc_monitorenter = 194;
int opc_monitorexit = 195;
int opc_wide = 196;
int opc_multianewarray = 197;
int opc_ifnull = 198;
int opc_ifnonnull = 199;
int opc_goto_w = 200;
int opc_jsr_w = 201;
int opc_breakpoint = 202;
/* Opcode Names */
String opcNames[] = {
"nop",
"aconst_null",
"iconst_m1",
"iconst_0",
"iconst_1",
"iconst_2",
"iconst_3",
"iconst_4",
"iconst_5",
"lconst_0",
"lconst_1",
"fconst_0",
"fconst_1",
"fconst_2",
"dconst_0",
"dconst_1",
"bipush",
"sipush",
"ldc",
"ldc_w",
"ldc2_w",
"iload",
"lload",
"fload",
"dload",
"aload",
"iload_0",
"iload_1",
"iload_2",
"iload_3",
"lload_0",
"lload_1",
"lload_2",
"lload_3",
"fload_0",
"fload_1",
"fload_2",
"fload_3",
"dload_0",
"dload_1",
"dload_2",
"dload_3",
"aload_0",
"aload_1",
"aload_2",
"aload_3",
"iaload",
"laload",
"faload",
"daload",
"aaload",
"baload",
"caload",
"saload",
"istore",
"lstore",
"fstore",
"dstore",
"astore",
"istore_0",
"istore_1",
"istore_2",
"istore_3",
"lstore_0",
"lstore_1",
"lstore_2",
"lstore_3",
"fstore_0",
"fstore_1",
"fstore_2",
"fstore_3",
"dstore_0",
"dstore_1",
"dstore_2",
"dstore_3",
"astore_0",
"astore_1",
"astore_2",
"astore_3",
"iastore",
"lastore",
"fastore",
"dastore",
"aastore",
"bastore",
"castore",
"sastore",
"pop",
"pop2",
"dup",
"dup_x1",
"dup_x2",
"dup2",
"dup2_x1",
"dup2_x2",
"swap",
"iadd",
"ladd",
"fadd",
"dadd",
"isub",
"lsub",
"fsub",
"dsub",
"imul",
"lmul",
"fmul",
"dmul",
"idiv",
"ldiv",
"fdiv",
"ddiv",
"irem",
"lrem",
"frem",
"drem",
"ineg",
"lneg",
"fneg",
"dneg",
"ishl",
"lshl",
"ishr",
"lshr",
"iushr",
"lushr",
"iand",
"land",
"ior",
"lor",
"ixor",
"lxor",
"iinc",
"i2l",
"i2f",
"i2d",
"l2i",
"l2f",
"l2d",
"f2i",
"f2l",
"f2d",
"d2i",
"d2l",
"d2f",
"i2b",
"i2c",
"i2s",
"lcmp",
"fcmpl",
"fcmpg",
"dcmpl",
"dcmpg",
"ifeq",
"ifne",
"iflt",
"ifge",
"ifgt",
"ifle",
"if_icmpeq",
"if_icmpne",
"if_icmplt",
"if_icmpge",
"if_icmpgt",
"if_icmple",
"if_acmpeq",
"if_acmpne",
"goto",
"jsr",
"ret",
"tableswitch",
"lookupswitch",
"ireturn",
"lreturn",
"freturn",
"dreturn",
"areturn",
"return",
"getstatic",
"putstatic",
"getfield",
"putfield",
"invokevirtual",
"invokespecial",
"invokestatic",
"invokeinterface",
"invokedynamic",
"new",
"newarray",
"anewarray",
"arraylength",
"athrow",
"checkcast",
"instanceof",
"monitorenter",
"monitorexit",
"wide",
"multianewarray",
"ifnull",
"ifnonnull",
"goto_w",
"jsr_w",
"breakpoint"
};
/* Opcode Lengths */
int opcLengths[] = {
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
2,
3,
2,
3,
3,
2,
2,
2,
2,
2,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
2,
2,
2,
2,
2,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
3,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
1,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
3,
2,
99,
99,
1,
1,
1,
1,
1,
1,
3,
3,
3,
3,
3,
3,
3,
5,
5,
3,
2,
3,
1,
1,
3,
3,
1,
1,
0,
4,
3,
3,
5,
5,
1
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,242 @@
/*
* Copyright (c) 1995, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.FilterReader;
import java.io.UnsupportedEncodingException;
/**
* An input stream for java programs. The stream treats either "\n", "\r"
* or "\r\n" as the end of a line, it always returns \n. It also parses
* UNICODE characters expressed as \uffff. However, if it sees "\\", the
* second slash cannot begin a unicode sequence. It keeps track of the current
* position in the input stream.
*
* 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.
*
* @author Arthur van Hoff
*/
public
class ScannerInputReader extends FilterReader implements Constants {
// A note. This class does not really properly subclass FilterReader.
// Since this class only overrides the single character read method,
// and not the multi-character read method, any use of the latter
// will not work properly. Any attempt to use this code outside of
// the compiler should take that into account.
//
// For efficiency, it might be worth moving this code to Scanner and
// getting rid of this class.
Environment env;
long pos;
private long chpos;
private int pushBack = -1;
public ScannerInputReader(Environment env, InputStream in)
throws UnsupportedEncodingException
{
// ScannerInputStream has been modified to no longer use
// BufferedReader. It now does its own buffering for
// performance.
super(env.getCharacterEncoding() != null ?
new InputStreamReader(in, env.getCharacterEncoding()) :
new InputStreamReader(in));
// Start out the buffer empty.
currentIndex = 0;
numChars = 0;
this.env = env;
chpos = Scanner.LINEINC;
}
//------------------------------------------------------------
// Buffering code.
// The size of our buffer.
private static final int BUFFERLEN = 10 * 1024;
// A character buffer.
private final char[] buffer = new char[BUFFERLEN];
// The index of the next character to be "read" from the buffer.
private int currentIndex;
// The number of characters in the buffer. -1 if EOF is reached.
private int numChars;
/**
* Get the next character from our buffer.
* Note: this method has been inlined by hand in the `read' method
* below. Any changes made to this method should be equally applied
* to that code.
*/
private int getNextChar() throws IOException {
// Check to see if we have either run out of characters in our
// buffer or gotten to EOF on a previous call.
if (currentIndex >= numChars) {
numChars = in.read(buffer);
if (numChars == -1) {
// We have reached EOF.
return -1;
}
// No EOF. currentIndex points to first char in buffer.
currentIndex = 0;
}
return buffer[currentIndex++];
}
//------------------------------------------------------------
public int read(char[] buffer, int off, int len) {
throw new CompilerError(
"ScannerInputReader is not a fully implemented reader.");
}
public int read() throws IOException {
pos = chpos;
chpos += Scanner.OFFSETINC;
int c = pushBack;
if (c == -1) {
getchar: try {
// Here the call...
// c = getNextChar();
// has been inlined by hand for performance.
if (currentIndex >= numChars) {
numChars = in.read(buffer);
if (numChars == -1) {
// We have reached EOF.
c = -1;
break getchar;
}
// No EOF. currentIndex points to first char in buffer.
currentIndex = 0;
}
c = buffer[currentIndex++];
} catch (java.io.CharConversionException e) {
env.error(pos, "invalid.encoding.char");
// this is fatal error
return -1;
}
} else {
pushBack = -1;
}
// parse special characters
switch (c) {
case -2:
// -2 is a special code indicating a pushback of a backslash that
// definitely isn't the start of a unicode sequence.
return '\\';
case '\\':
if ((c = getNextChar()) != 'u') {
pushBack = (c == '\\' ? -2 : c);
return '\\';
}
// we have a unicode sequence
chpos += Scanner.OFFSETINC;
while ((c = getNextChar()) == 'u') {
chpos += Scanner.OFFSETINC;
}
// unicode escape sequence
int d = 0;
for (int i = 0 ; i < 4 ; i++, chpos += Scanner.OFFSETINC, c = getNextChar()) {
switch (c) {
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
d = (d << 4) + c - '0';
break;
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
d = (d << 4) + 10 + c - 'a';
break;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
d = (d << 4) + 10 + c - 'A';
break;
default:
env.error(pos, "invalid.escape.char");
pushBack = c;
return d;
}
}
pushBack = c;
// To read the following line, switch \ and /...
// Handle /u000a, /u000A, /u000d, /u000D properly as
// line terminators as per JLS 3.4, even though they are encoded
// (this properly respects the order given in JLS 3.2).
switch (d) {
case '\n':
chpos += Scanner.LINEINC;
return '\n';
case '\r':
if ((c = getNextChar()) != '\n') {
pushBack = c;
} else {
chpos += Scanner.OFFSETINC;
}
chpos += Scanner.LINEINC;
return '\n';
default:
return d;
}
case '\n':
chpos += Scanner.LINEINC;
return '\n';
case '\r':
if ((c = getNextChar()) != '\n') {
pushBack = c;
} else {
chpos += Scanner.OFFSETINC;
}
chpos += Scanner.LINEINC;
return '\n';
default:
return c;
}
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
/**
* Syntax errors, should always be caught inside the
* parser for error recovery.
*
* 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.
*/
public
class SyntaxError extends Exception {
}

View File

@@ -0,0 +1,455 @@
/*
* Copyright (c) 1994, 2003, Oracle and/or its affiliates. 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.tools.java;
import java.util.Hashtable;
/**
* This class represents an Java Type.<p>
*
* It encapsulates an Java type signature and it provides
* quick access to the components of the type. Note that
* all types are hashed into a hashtable (typeHash), that
* means that each distinct type is only allocated once,
* saving space and making equality checks cheap.<p>
*
* For simple types use the constants defined in this class.
* (Type.tInt, Type.tShort, ...). To create complex types use
* the static methods Type.tArray, Type.tMethod or Type.tClass.
*
* For classes, arrays and method types a sub class of class
* type is created which defines the extra type components.
*
* 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.
*
* @see ArrayType
* @see ClassType
* @see MethodType
* @author Arthur van Hoff
*/
public
class Type implements Constants {
/**
* This hashtable is used to cache types
*/
private static final Hashtable typeHash = new Hashtable(231);
/**
* The TypeCode of this type. The value of this field is one
* of the TC_* contant values defined in Constants.
* @see Constants
*/
protected int typeCode;
/**
* The TypeSignature of this type. This type signature is
* equivalent to the runtime type signatures used by the
* interpreter.
*/
protected String typeSig;
/*
* Predefined types.
*/
public static final Type noArgs[] = new Type[0];
public static final Type tError = new Type(TC_ERROR, "?");
public static final Type tPackage = new Type(TC_ERROR, ".");
public static final Type tNull = new Type(TC_NULL, "*");
public static final Type tVoid = new Type(TC_VOID, SIG_VOID);
public static final Type tBoolean = new Type(TC_BOOLEAN, SIG_BOOLEAN);
public static final Type tByte = new Type(TC_BYTE, SIG_BYTE);
public static final Type tChar = new Type(TC_CHAR, SIG_CHAR);
public static final Type tShort = new Type(TC_SHORT, SIG_SHORT);
public static final Type tInt = new Type(TC_INT, SIG_INT);
public static final Type tFloat = new Type(TC_FLOAT, SIG_FLOAT);
public static final Type tLong = new Type(TC_LONG, SIG_LONG);
public static final Type tDouble = new Type(TC_DOUBLE, SIG_DOUBLE);
public static final Type tObject = Type.tClass(idJavaLangObject);
public static final Type tClassDesc = Type.tClass(idJavaLangClass);
public static final Type tString = Type.tClass(idJavaLangString);
public static final Type tCloneable = Type.tClass(idJavaLangCloneable);
public static final Type tSerializable = Type.tClass(idJavaIoSerializable);
/**
* Create a type given a typecode and a type signature.
*/
protected Type(int typeCode, String typeSig) {
this.typeCode = typeCode;
this.typeSig = typeSig;
typeHash.put(typeSig, this);
}
/**
* Return the Java type signature.
*/
public final String getTypeSignature() {
return typeSig;
}
/**
* Return the type code.
*/
public final int getTypeCode() {
return typeCode;
}
/**
* Return the type mask. The bits in this mask correspond
* to the TM_* constants defined in Constants. Only one bit
* is set at a type.
* @see Constants
*/
public final int getTypeMask() {
return 1 << typeCode;
}
/**
* Check for a certain type.
*/
public final boolean isType(int tc) {
return typeCode == tc;
}
/**
* Check to see if this is the bogus type "array of void"
*
* Although this highly degenerate "type" is not constructable from
* the grammar, the Parser accepts it. Rather than monkey with the
* Parser, we check for the bogus type at specific points and give
* a nice error.
*/
public boolean isVoidArray() {
// a void type is not a void array.
if (!isType(TC_ARRAY)) {
return false;
}
// If this is an array, find out what its element type is.
Type type = this;
while (type.isType(TC_ARRAY))
type = type.getElementType();
return type.isType(TC_VOID);
}
/**
* Check for a certain set of types.
*/
public final boolean inMask(int tm) {
return ((1 << typeCode) & tm) != 0;
}
/**
* Create an array type.
*/
public static synchronized Type tArray(Type elem) {
String sig = new String(SIG_ARRAY + elem.getTypeSignature());
Type t = (Type)typeHash.get(sig);
if (t == null) {
t = new ArrayType(sig, elem);
}
return t;
}
/**
* Return the element type of an array type. Only works
* for array types.
*/
public Type getElementType() {
throw new CompilerError("getElementType");
}
/**
* Return the array dimension. Only works for
* array types.
*/
public int getArrayDimension() {
return 0;
}
/**
* Create a class type.
* @arg className the fully qualified class name
*/
public static synchronized Type tClass(Identifier className) {
if (className.isInner()) {
Type t = tClass(mangleInnerType(className));
if (t.getClassName() != className)
// Somebody got here first with a mangled name.
// (Perhaps it came from a binary.)
changeClassName(t.getClassName(), className);
return t;
}
// see if we've cached the object in the Identifier
if (className.typeObject != null) {
return className.typeObject;
}
String sig =
new String(SIG_CLASS +
className.toString().replace('.', SIGC_PACKAGE) +
SIG_ENDCLASS);
Type t = (Type)typeHash.get(sig);
if (t == null) {
t = new ClassType(sig, className);
}
className.typeObject = t; // cache the Type object in the Identifier
return t;
}
/**
* Return the ClassName. Only works on class types.
*/
public Identifier getClassName() {
throw new CompilerError("getClassName:" + this);
}
/**
* Given an inner identifier, return the non-inner, mangled
* representation used to manage signatures.
*
* Note: It is changed to 'public' for Jcov file generation.
* (see Assembler.java)
*/
public static Identifier mangleInnerType(Identifier className) {
// Map "pkg.Foo. Bar" to "pkg.Foo$Bar".
if (!className.isInner()) return className;
Identifier mname = Identifier.lookup(
className.getFlatName().toString().
replace('.', SIGC_INNERCLASS) );
if (mname.isInner()) throw new CompilerError("mangle "+mname);
return Identifier.lookup(className.getQualifier(), mname);
}
/**
* We have learned that a signature means something other
* that what we thought it meant. Live with it: Change all
* affected data structures to reflect the new name of the old type.
* <p>
* (This is necessary because of an ambiguity between the
* low-level signatures of inner types and their manglings.
* Note that the latter are also valid class names.)
*/
static void changeClassName(Identifier oldName, Identifier newName) {
// Note: If we are upgrading "pkg.Foo$Bar" to "pkg.Foo. Bar",
// we assume someone else will come along and deal with any types
// inner within Bar. So, there's only one change to make.
((ClassType)Type.tClass(oldName)).className = newName;
}
/**
* Create a method type with no arguments.
*/
public static synchronized Type tMethod(Type ret) {
return tMethod(ret, noArgs);
}
/**
* Create a method type with arguments.
*/
public static synchronized Type tMethod(Type returnType, Type argTypes[]) {
StringBuffer buf = new StringBuffer();
buf.append(SIG_METHOD);
for (int i = 0 ; i < argTypes.length ; i++) {
buf.append(argTypes[i].getTypeSignature());
}
buf.append(SIG_ENDMETHOD);
buf.append(returnType.getTypeSignature());
String sig = buf.toString();
Type t = (Type)typeHash.get(sig);
if (t == null) {
t = new MethodType(sig, returnType, argTypes);
}
return t;
}
/**
* Return the return type. Only works for method types.
*/
public Type getReturnType() {
throw new CompilerError("getReturnType");
}
/**
* Return the argument types. Only works for method types.
*/
public Type getArgumentTypes()[] {
throw new CompilerError("getArgumentTypes");
}
/**
* Create a Type from an Java type signature.
* @exception CompilerError invalid type signature.
*/
public static synchronized Type tType(String sig) {
Type t = (Type)typeHash.get(sig);
if (t != null) {
return t;
}
switch (sig.charAt(0)) {
case SIGC_ARRAY:
return Type.tArray(tType(sig.substring(1)));
case SIGC_CLASS:
return Type.tClass(Identifier.lookup(sig.substring(1, sig.length() - 1).replace(SIGC_PACKAGE, '.')));
case SIGC_METHOD: {
Type argv[] = new Type[8];
int argc = 0;
int i, j;
for (i = 1 ; sig.charAt(i) != SIGC_ENDMETHOD ; i = j) {
for (j = i ; sig.charAt(j) == SIGC_ARRAY ; j++);
if (sig.charAt(j++) == SIGC_CLASS) {
while (sig.charAt(j++) != SIGC_ENDCLASS);
}
if (argc == argv.length) {
Type newargv[] = new Type[argc * 2];
System.arraycopy(argv, 0, newargv, 0, argc);
argv = newargv;
}
argv[argc++] = tType(sig.substring(i, j));
}
Type argtypes[] = new Type[argc];
System.arraycopy(argv, 0, argtypes, 0, argc);
return Type.tMethod(tType(sig.substring(i + 1)), argtypes);
}
}
throw new CompilerError("invalid TypeSignature:" + sig);
}
/**
* Check if the type arguments are the same.
* @return true if both types are method types and the
* argument types are identical.
*/
public boolean equalArguments(Type t) {
return false;
}
/**
* Return the amount of space this type takes up on the
* Java operand stack. For a method this is equal to the
* total space taken up by the arguments.
*/
public int stackSize() {
switch (typeCode) {
case TC_ERROR:
case TC_VOID:
return 0;
case TC_BOOLEAN:
case TC_BYTE:
case TC_SHORT:
case TC_CHAR:
case TC_INT:
case TC_FLOAT:
case TC_ARRAY:
case TC_CLASS:
return 1;
case TC_LONG:
case TC_DOUBLE:
return 2;
}
throw new CompilerError("stackSize " + toString());
}
/**
* Return the type code offset. This offset can be added to
* an opcode to get the right opcode type. Most opcodes
* are ordered: int, long, float, double, array. For
* example: iload, lload fload, dload, aload. So the
* appropriate opcode is iadd + type.getTypeCodeOffset().
*/
public int getTypeCodeOffset() {
switch (typeCode) {
case TC_BOOLEAN:
case TC_BYTE:
case TC_SHORT:
case TC_CHAR:
case TC_INT:
return 0;
case TC_LONG:
return 1;
case TC_FLOAT:
return 2;
case TC_DOUBLE:
return 3;
case TC_NULL:
case TC_ARRAY:
case TC_CLASS:
return 4;
}
throw new CompilerError("invalid typecode: " + typeCode);
}
/**
* Convert a Type to a string, if abbrev is true class names are
* not fully qualified, if ret is true the return type is included.
*/
public String typeString(String id, boolean abbrev, boolean ret) {
String s = null;
switch (typeCode) {
case TC_NULL: s = "null"; break;
case TC_VOID: s = "void"; break;
case TC_BOOLEAN: s = "boolean"; break;
case TC_BYTE: s = "byte"; break;
case TC_CHAR: s = "char"; break;
case TC_SHORT: s = "short"; break;
case TC_INT: s = "int"; break;
case TC_LONG: s = "long"; break;
case TC_FLOAT: s = "float"; break;
case TC_DOUBLE: s = "double"; break;
case TC_ERROR: s = "<error>";
if (this==tPackage) s = "<package>";
break;
default: s = "unknown";
}
return (id.length() > 0) ? s + " " + id : s;
}
/**
* Create a type string, given an identifier.
*/
public String typeString(String id) {
return typeString(id, false, true);
}
/**
* Convert to a String
*/
public String toString() {
return typeString("", false, true);
}
}