History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/tools/java (33 of 18352 files). Show all

Unified · Split

33 files
  1. java/pkg/sun/tools/java/AmbiguousClass.java +53 −0
  2. java/pkg/sun/tools/java/AmbiguousMember.java +54 −0
  3. java/pkg/sun/tools/java/ArrayType.java +65 −0
  4. java/pkg/sun/tools/java/BinaryAttribute.java +112 −0
  5. java/pkg/sun/tools/java/BinaryClass.java +534 −0
  6. java/pkg/sun/tools/java/BinaryCode.java +111 −0
  7. java/pkg/sun/tools/java/BinaryConstantPool.java +327 −0
  8. java/pkg/sun/tools/java/BinaryExceptionHandler.java +49 −0
  9. java/pkg/sun/tools/java/BinaryMember.java +260 −0
  10. java/pkg/sun/tools/java/ClassDeclaration.java +265 −0
  11. java/pkg/sun/tools/java/ClassDefinition.java +2085 −0
  12. java/pkg/sun/tools/java/ClassFile.java +162 −0
  13. java/pkg/sun/tools/java/ClassNotFound.java +50 −0
  14. java/pkg/sun/tools/java/ClassPath.java +314 −0
  15. java/pkg/sun/tools/java/ClassType.java +64 −0
  16. java/pkg/sun/tools/java/CompilerError.java +62 −0
  17. java/pkg/sun/tools/java/Constants.java +591 −0
  18. java/pkg/sun/tools/java/Environment.java +998 −0
  19. java/pkg/sun/tools/java/Identifier.java +329 −0
  20. java/pkg/sun/tools/java/IdentifierToken.java +91 −0
  21. java/pkg/sun/tools/java/Imports.java +503 −0
  22. java/pkg/sun/tools/java/MemberDefinition.java +1007 −0
  23. java/pkg/sun/tools/java/MethodSet.java +278 −0
  24. java/pkg/sun/tools/java/MethodType.java +107 −0
  25. java/pkg/sun/tools/java/Package.java +161 −0
  26. java/pkg/sun/tools/java/Parser.java +2130 −0
  27. java/pkg/sun/tools/java/ParserActions.java +87 −0
  28. java/pkg/sun/tools/java/RuntimeConstants.java +739 −0
  29. java/pkg/sun/tools/java/Scanner.java +1341 −0
  30. java/pkg/sun/tools/java/ScannerInputReader.java +242 −0
  31. java/pkg/sun/tools/java/SyntaxError.java +39 −0
  32. java/pkg/sun/tools/java/Type.java +455 −0
  33. java/pkg/sun/tools/java/mkfile +39 −0
java/pkg/sun/tools/java/AmbiguousClass.java+53−0
@@ -0,0 +1,53 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+/**
29+ * This exception is thrown when an unqualified class name
30+ * is used that can be resolved in more than one way.
31+ *
32+ * WARNING: The contents of this source file are not part of any
33+ * supported API. Code that depends on them does so at its own risk:
34+ * they are subject to change or removal without notice.
35+ */
36+
37+public
38+class AmbiguousClass extends ClassNotFound {
39+ /**
40+ * The class that was not found
41+ */
42+ public Identifier name1;
43+ public Identifier name2;
44+
45+ /**
46+ * Constructor
47+ */
48+ public AmbiguousClass(Identifier name1, Identifier name2) {
49+ super(name1.getName());
50+ this.name1 = name1;
51+ this.name2 = name2;
52+ }
53+}
java/pkg/sun/tools/java/AmbiguousMember.java+54−0
@@ -0,0 +1,54 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.util.Enumeration;
29+
30+/**
31+ * This exception is thrown when a field reference is
32+ * ambiguous.
33+ *
34+ * WARNING: The contents of this source file are not part of any
35+ * supported API. Code that depends on them does so at its own risk:
36+ * they are subject to change or removal without notice.
37+ */
38+public
39+class AmbiguousMember extends Exception {
40+ /**
41+ * The field that was not found
42+ */
43+ public MemberDefinition field1;
44+ public MemberDefinition field2;
45+
46+ /**
47+ * Constructor
48+ */
49+ public AmbiguousMember(MemberDefinition field1, MemberDefinition field2) {
50+ super(field1.getName() + " + " + field2.getName());
51+ this.field1 = field1;
52+ this.field2 = field2;
53+ }
54+}
java/pkg/sun/tools/java/ArrayType.java+65−0
@@ -0,0 +1,65 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+/**
29+ * This class represents an Java array type.
30+ * It overrides the relevant methods in class Type.
31+ *
32+ * WARNING: The contents of this source file are not part of any
33+ * supported API. Code that depends on them does so at its own risk:
34+ * they are subject to change or removal without notice.
35+ *
36+ * @author Arthur van Hoff
37+ */
38+public final
39+class ArrayType extends Type {
40+ /**
41+ * The type of the element.
42+ */
43+ Type elemType;
44+
45+ /**
46+ * Construct an array type. Use Type.tArray to create
47+ * a new array type.
48+ */
49+ ArrayType(String typeSig, Type elemType) {
50+ super(TC_ARRAY, typeSig);
51+ this.elemType = elemType;
52+ }
53+
54+ public Type getElementType() {
55+ return elemType;
56+ }
57+
58+ public int getArrayDimension() {
59+ return elemType.getArrayDimension() + 1;
60+ }
61+
62+ public String typeString(String id, boolean abbrev, boolean ret) {
63+ return getElementType().typeString(id, abbrev, ret) + "[]";
64+ }
65+}
java/pkg/sun/tools/java/BinaryAttribute.java+112−0
@@ -0,0 +1,112 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.io.IOException;
29+import java.io.DataInputStream;
30+import java.io.DataOutputStream;
31+
32+/**
33+ * This class is used to represent an attribute from a binary class.
34+ * This class should go away once arrays are objects.
35+ *
36+ * WARNING: The contents of this source file are not part of any
37+ * supported API. Code that depends on them does so at its own risk:
38+ * they are subject to change or removal without notice.
39+ */
40+public final
41+class BinaryAttribute implements Constants {
42+ Identifier name;
43+ byte data[];
44+ BinaryAttribute next;
45+
46+ /**
47+ * Constructor
48+ */
49+ BinaryAttribute(Identifier name, byte data[], BinaryAttribute next) {
50+ this.name = name;
51+ this.data = data;
52+ this.next = next;
53+ }
54+
55+ /**
56+ * Load a list of attributes
57+ */
58+ public static BinaryAttribute load(DataInputStream in, BinaryConstantPool cpool, int mask) throws IOException {
59+ BinaryAttribute atts = null;
60+ int natt = in.readUnsignedShort(); // JVM 4.6 method_info.attrutes_count
61+
62+ for (int i = 0 ; i < natt ; i++) {
63+ // id from JVM 4.7 attribute_info.attribute_name_index
64+ Identifier id = cpool.getIdentifier(in.readUnsignedShort());
65+ // id from JVM 4.7 attribute_info.attribute_length
66+ int len = in.readInt();
67+
68+ if (id.equals(idCode) && ((mask & ATT_CODE) == 0)) {
69+ in.skipBytes(len);
70+ } else {
71+ byte data[] = new byte[len];
72+ in.readFully(data);
73+ atts = new BinaryAttribute(id, data, atts);
74+ }
75+ }
76+ return atts;
77+ }
78+
79+ // write out the Binary attributes to the given stream
80+ // (note that attributes may be null)
81+ static void write(BinaryAttribute attributes, DataOutputStream out,
82+ BinaryConstantPool cpool, Environment env) throws IOException {
83+ // count the number of attributes
84+ int attributeCount = 0;
85+ for (BinaryAttribute att = attributes; att != null; att = att.next)
86+ attributeCount++;
87+ out.writeShort(attributeCount);
88+
89+ // write out each attribute
90+ for (BinaryAttribute att = attributes; att != null; att = att.next) {
91+ Identifier name = att.name;
92+ byte data[] = att.data;
93+ // write the identifier
94+ out.writeShort(cpool.indexString(name.toString(), env));
95+ // write the length
96+ out.writeInt(data.length);
97+ // write the data
98+ out.write(data, 0, data.length);
99+ }
100+ }
101+
102+ /**
103+ * Accessors
104+ */
105+
106+ public Identifier getName() { return name; }
107+
108+ public byte getData()[] { return data; }
109+
110+ public BinaryAttribute getNextAttribute() { return next; }
111+
112+}
java/pkg/sun/tools/java/BinaryClass.java+534−0
@@ -0,0 +1,534 @@
1+/*
2+ * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.io.IOException;
29+import java.io.DataInputStream;
30+import java.io.OutputStream;
31+import java.io.DataOutputStream;
32+import java.io.ByteArrayInputStream;
33+import java.util.Hashtable;
34+import java.util.Vector;
35+import java.util.Enumeration;
36+
37+/**
38+ * WARNING: The contents of this source file are not part of any
39+ * supported API. Code that depends on them does so at its own risk:
40+ * they are subject to change or removal without notice.
41+ */
42+public final
43+class BinaryClass extends ClassDefinition implements Constants {
44+ BinaryConstantPool cpool;
45+ BinaryAttribute atts;
46+ Vector dependencies;
47+ private boolean haveLoadedNested = false;
48+
49+ /**
50+ * Constructor
51+ */
52+ public BinaryClass(Object source, ClassDeclaration declaration, int modifiers,
53+ ClassDeclaration superClass, ClassDeclaration interfaces[],
54+ Vector dependencies) {
55+ super(source, 0, declaration, modifiers, null, null);
56+ this.dependencies = dependencies;
57+ this.superClass = superClass;
58+ this.interfaces = interfaces;
59+ }
60+
61+ /**
62+ * Flags used by basicCheck() to avoid duplicate calls.
63+ * (Part of fix for 4105911)
64+ */
65+ private boolean basicCheckDone = false;
66+ private boolean basicChecking = false;
67+
68+ /**
69+ * Ready a BinaryClass for further checking. Note that, until recently,
70+ * BinaryClass relied on the default basicCheck() provided by
71+ * ClassDefinition. The definition here has been added to ensure that
72+ * the information generated by collectInheritedMethods is available
73+ * for BinaryClasses.
74+ */
75+ protected void basicCheck(Environment env) throws ClassNotFound {
76+ if (tracing) env.dtEnter("BinaryClass.basicCheck: " + getName());
77+
78+ // We need to guard against duplicate calls to basicCheck(). They
79+ // can lead to calling collectInheritedMethods() for this class
80+ // from within a previous call to collectInheritedMethods() for
81+ // this class. That is not allowed.
82+ // (Part of fix for 4105911)
83+ if (basicChecking || basicCheckDone) {
84+ if (tracing) env.dtExit("BinaryClass.basicCheck: OK " + getName());
85+ return;
86+ }
87+
88+ if (tracing) env.dtEvent("BinaryClass.basicCheck: CHECKING " + getName());
89+ basicChecking = true;
90+
91+ super.basicCheck(env);
92+
93+ // Collect inheritance information.
94+ if (doInheritanceChecks) {
95+ collectInheritedMethods(env);
96+ }
97+
98+ basicCheckDone = true;
99+ basicChecking = false;
100+ if (tracing) env.dtExit("BinaryClass.basicCheck: " + getName());
101+ }
102+
103+ /**
104+ * Load a binary class
105+ */
106+ public static BinaryClass load(Environment env, DataInputStream in) throws IOException {
107+ return load(env, in, ~(ATT_CODE|ATT_ALLCLASSES));
108+ }
109+
110+ public static BinaryClass load(Environment env,
111+ DataInputStream in, int mask) throws IOException {
112+ // Read the header
113+ int magic = in.readInt(); // JVM 4.1 ClassFile.magic
114+ if (magic != JAVA_MAGIC) {
115+ throw new ClassFormatError("wrong magic: " + magic + ", expected " + JAVA_MAGIC);
116+ }
117+ int minor_version = in.readUnsignedShort(); // JVM 4.1 ClassFile.minor_version
118+ int version = in.readUnsignedShort(); // JVM 4.1 ClassFile.major_version
119+ if (version < JAVA_MIN_SUPPORTED_VERSION) {
120+ throw new ClassFormatError(
121+ sun.tools.javac.Main.getText(
122+ "javac.err.version.too.old",
123+ String.valueOf(version)));
124+ } else if ((version > JAVA_MAX_SUPPORTED_VERSION)
125+ || (version == JAVA_MAX_SUPPORTED_VERSION
126+ && minor_version > JAVA_MAX_SUPPORTED_MINOR_VERSION)) {
127+ throw new ClassFormatError(
128+ sun.tools.javac.Main.getText(
129+ "javac.err.version.too.recent",
130+ version+"."+minor_version));
131+ }
132+
133+ // Read the constant pool
134+ BinaryConstantPool cpool = new BinaryConstantPool(in);
135+
136+ // The dependencies of this class
137+ Vector dependencies = cpool.getDependencies(env);
138+
139+ // Read modifiers
140+ int classMod = in.readUnsignedShort() & ACCM_CLASS; // JVM 4.1 ClassFile.access_flags
141+
142+ // Read the class name - from JVM 4.1 ClassFile.this_class
143+ ClassDeclaration classDecl = cpool.getDeclaration(env, in.readUnsignedShort());
144+
145+ // Read the super class name (may be null) - from JVM 4.1 ClassFile.super_class
146+ ClassDeclaration superClassDecl = cpool.getDeclaration(env, in.readUnsignedShort());
147+
148+ // Read the interface names - from JVM 4.1 ClassFile.interfaces_count
149+ ClassDeclaration interfaces[] = new ClassDeclaration[in.readUnsignedShort()];
150+ for (int i = 0 ; i < interfaces.length ; i++) {
151+ // JVM 4.1 ClassFile.interfaces[]
152+ interfaces[i] = cpool.getDeclaration(env, in.readUnsignedShort());
153+ }
154+
155+ // Allocate the class
156+ BinaryClass c = new BinaryClass(null, classDecl, classMod, superClassDecl,
157+ interfaces, dependencies);
158+ c.cpool = cpool;
159+
160+ // Add any additional dependencies
161+ c.addDependency(superClassDecl);
162+
163+ // Read the fields
164+ int nfields = in.readUnsignedShort(); // JVM 4.1 ClassFile.fields_count
165+ for (int i = 0 ; i < nfields ; i++) {
166+ // JVM 4.5 field_info.access_flags
167+ int fieldMod = in.readUnsignedShort() & ACCM_FIELD;
168+ // JVM 4.5 field_info.name_index
169+ Identifier fieldName = cpool.getIdentifier(in.readUnsignedShort());
170+ // JVM 4.5 field_info.descriptor_index
171+ Type fieldType = cpool.getType(in.readUnsignedShort());
172+ BinaryAttribute atts = BinaryAttribute.load(in, cpool, mask);
173+ c.addMember(new BinaryMember(c, fieldMod, fieldType, fieldName, atts));
174+ }
175+
176+ // Read the methods
177+ int nmethods = in.readUnsignedShort(); // JVM 4.1 ClassFile.methods_count
178+ for (int i = 0 ; i < nmethods ; i++) {
179+ // JVM 4.6 method_info.access_flags
180+ int methMod = in.readUnsignedShort() & ACCM_METHOD;
181+ // JVM 4.6 method_info.name_index
182+ Identifier methName = cpool.getIdentifier(in.readUnsignedShort());
183+ // JVM 4.6 method_info.descriptor_index
184+ Type methType = cpool.getType(in.readUnsignedShort());
185+ BinaryAttribute atts = BinaryAttribute.load(in, cpool, mask);
186+ c.addMember(new BinaryMember(c, methMod, methType, methName, atts));
187+ }
188+
189+ // Read the class attributes
190+ c.atts = BinaryAttribute.load(in, cpool, mask);
191+
192+ // See if the SourceFile is known
193+ byte data[] = c.getAttribute(idSourceFile);
194+ if (data != null) {
195+ DataInputStream dataStream = new DataInputStream(new ByteArrayInputStream(data));
196+ // JVM 4.7.2 SourceFile_attribute.sourcefile_index
197+ c.source = cpool.getString(dataStream.readUnsignedShort());
198+ }
199+
200+ // See if the Documentation is know
201+ data = c.getAttribute(idDocumentation);
202+ if (data != null) {
203+ c.documentation = new DataInputStream(new ByteArrayInputStream(data)).readUTF();
204+ }
205+
206+ // Was it compiled as deprecated?
207+ if (c.getAttribute(idDeprecated) != null) {
208+ c.modifiers |= M_DEPRECATED;
209+ }
210+
211+ // Was it synthesized by the compiler?
212+ if (c.getAttribute(idSynthetic) != null) {
213+ c.modifiers |= M_SYNTHETIC;
214+ }
215+
216+ return c;
217+ }
218+
219+ /**
220+ * Called when an environment ties a binary definition to a declaration.
221+ * At this point, auxiliary definitions may be loaded.
222+ */
223+
224+ public void loadNested(Environment env) {
225+ loadNested(env, 0);
226+ }
227+
228+ public void loadNested(Environment env, int flags) {
229+ // Sanity check.
230+ if (haveLoadedNested) {
231+ // Duplicate calls most likely should not occur, but they do
232+ // in javap. Be tolerant of them for the time being.
233+ // throw new CompilerError("multiple loadNested");
234+ if (tracing) env.dtEvent("loadNested: DUPLICATE CALL SKIPPED");
235+ return;
236+ }
237+ haveLoadedNested = true;
238+ // Read class-nesting information.
239+ try {
240+ byte data[];
241+ data = getAttribute(idInnerClasses);
242+ if (data != null) {
243+ initInnerClasses(env, data, flags);
244+ }
245+ } catch (IOException ee) {
246+ // The inner classes attribute is not well-formed.
247+ // It may, for example, contain no data. Report this.
248+ // We used to throw a CompilerError here (bug 4095108).
249+ env.error(0, "malformed.attribute", getClassDeclaration(),
250+ idInnerClasses);
251+ if (tracing)
252+ env.dtEvent("loadNested: MALFORMED ATTRIBUTE (InnerClasses)");
253+ }
254+ }
255+
256+ private void initInnerClasses(Environment env,
257+ byte data[],
258+ int flags) throws IOException {
259+ DataInputStream ds = new DataInputStream(new ByteArrayInputStream(data));
260+ int nrec = ds.readUnsignedShort(); // InnerClasses_attribute.number_of_classes
261+ for (int i = 0; i < nrec; i++) {
262+ // For each inner class name transformation, we have a record
263+ // with the following fields:
264+ //
265+ // u2 inner_class_info_index; // CONSTANT_Class_info index
266+ // u2 outer_class_info_index; // CONSTANT_Class_info index
267+ // u2 inner_name_index; // CONSTANT_Utf8_info index
268+ // u2 inner_class_access_flags; // access_flags bitmask
269+ //
270+ // The spec states that outer_class_info_index is 0 iff
271+ // the inner class is not a member of its enclosing class (i.e.
272+ // it is a local or anonymous class). The spec also states
273+ // that if a class is anonymous then inner_name_index should
274+ // be 0.
275+ //
276+ // Prior to jdk1.2, javac did not implement the spec. Instead
277+ // it <em>always</em> set outer_class_info_index to the
278+ // enclosing outer class and if the class was anonymous,
279+ // it set inner_name_index to be the index of a CONSTANT_Utf8
280+ // entry containing the null string "" (idNull). This code is
281+ // designed to handle either kind of class file.
282+ //
283+ // See also the compileClass() method in SourceClass.java.
284+
285+ // Read in the inner_class_info
286+ // InnerClasses_attribute.classes.inner_class_info_index
287+ int inner_index = ds.readUnsignedShort();
288+ // could check for zero.
289+ ClassDeclaration inner = cpool.getDeclaration(env, inner_index);
290+
291+ // Read in the outer_class_info. Note that the index will be
292+ // zero if the class is "not a member".
293+ ClassDeclaration outer = null;
294+ // InnerClasses_attribute.classes.outer_class_info_index
295+ int outer_index = ds.readUnsignedShort();
296+ if (outer_index != 0) {
297+ outer = cpool.getDeclaration(env, outer_index);
298+ }
299+
300+ // Read in the inner_name_index. This may be zero. An anonymous
301+ // class will either have an inner_nm_index of zero (as the spec
302+ // dictates) or it will have an inner_nm of idNull (for classes
303+ // generated by pre-1.2 compilers). Handle both.
304+ Identifier inner_nm = idNull;
305+ // InnerClasses_attribute.classes.inner_name_index
306+ int inner_nm_index = ds.readUnsignedShort();
307+ if (inner_nm_index != 0) {
308+ inner_nm = Identifier.lookup(cpool.getString(inner_nm_index));
309+ }
310+
311+ // Read in the modifiers for the inner class.
312+ // InnerClasses_attribute.classes.inner_name_index
313+ int mods = ds.readUnsignedShort();
314+
315+ // Is the class accessible?
316+ // The old code checked for
317+ //
318+ // (!inner_nm.equals(idNull) && (mods & M_PRIVATE) == 0)
319+ //
320+ // which we will preserve to keep it working for class files
321+ // generated by 1.1 compilers. In addition we check for
322+ //
323+ // (outer != null)
324+ //
325+ // as an additional check that only makes sense with 1.2
326+ // generated files. Note that it is entirely possible that
327+ // the M_PRIVATE bit is always enough. We are being
328+ // conservative here.
329+ //
330+ // The ATT_ALLCLASSES flag causes the M_PRIVATE modifier
331+ // to be ignored, and is used by tools such as 'javap' that
332+ // wish to examine all classes regardless of the normal access
333+ // controls that apply during compilation. Note that anonymous
334+ // and local classes are still not considered accessible, though
335+ // named local classes in jdk1.1 may slip through. Note that
336+ // this accessibility test is an optimization, and it is safe to
337+ // err on the side of greater accessibility.
338+ boolean accessible =
339+ (outer != null) &&
340+ (!inner_nm.equals(idNull)) &&
341+ ((mods & M_PRIVATE) == 0 ||
342+ (flags & ATT_ALLCLASSES) != 0);
343+
344+ // The reader should note that there has been a significant change
345+ // in the way that the InnerClasses attribute is being handled.
346+ // In particular, previously the compiler called initInner() for
347+ // <em>every</em> inner class. Now the compiler does not call
348+ // initInner() if the inner class is inaccessible. This means
349+ // that inaccessible inner classes don't have any of the processing
350+ // from initInner() done for them: fixing the access flags,
351+ // setting outerClass, setting outerMember in their outerClass,
352+ // etc. We believe this is fine: if the class is inaccessible
353+ // and binary, then everyone who needs to see its internals
354+ // has already been compiled. Hopefully.
355+
356+ if (accessible) {
357+ Identifier nm =
358+ Identifier.lookupInner(outer.getName(), inner_nm);
359+
360+ // Tell the type module about the nesting relation:
361+ Type.tClass(nm);
362+
363+ if (inner.equals(getClassDeclaration())) {
364+ // The inner class in the record is this class.
365+ try {
366+ ClassDefinition outerClass = outer.getClassDefinition(env);
367+ initInner(outerClass, mods);
368+ } catch (ClassNotFound e) {
369+ // report the error elsewhere
370+ }
371+ } else if (outer.equals(getClassDeclaration())) {
372+ // The outer class in the record is this class.
373+ try {
374+ ClassDefinition innerClass =
375+ inner.getClassDefinition(env);
376+ initOuter(innerClass, mods);
377+ } catch (ClassNotFound e) {
378+ // report the error elsewhere
379+ }
380+ }
381+ }
382+ }
383+ }
384+
385+ private void initInner(ClassDefinition outerClass, int mods) {
386+ if (getOuterClass() != null)
387+ return; // already done
388+ /******
389+ // Maybe set static, protected, or private.
390+ if ((modifiers & M_PUBLIC) != 0)
391+ mods &= M_STATIC;
392+ else
393+ mods &= M_PRIVATE | M_PROTECTED | M_STATIC;
394+ modifiers |= mods;
395+ ******/
396+ // For an inner class, the class access may have been weakened
397+ // from that originally declared the source. We must take the
398+ // actual access permissions against which we check any source
399+ // we are currently compiling from the InnerClasses attribute.
400+ // We attempt to guard here against bogus combinations of modifiers.
401+ if ((mods & M_PRIVATE) != 0) {
402+ // Private cannot be combined with public or protected.
403+ mods &= ~(M_PUBLIC | M_PROTECTED);
404+ } else if ((mods & M_PROTECTED) != 0) {
405+ // Protected cannot be combined with public.
406+ mods &= ~M_PUBLIC;
407+ }
408+ if ((mods & M_INTERFACE) != 0) {
409+ // All interfaces are implicitly abstract.
410+ // All interfaces that are members of a type are implicitly static.
411+ mods |= (M_ABSTRACT | M_STATIC);
412+ }
413+ if (outerClass.isInterface()) {
414+ // All types that are members of interfaces are implicitly
415+ // public and static.
416+ mods |= (M_PUBLIC | M_STATIC);
417+ mods &= ~(M_PRIVATE | M_PROTECTED);
418+ }
419+ modifiers = mods;
420+
421+ setOuterClass(outerClass);
422+
423+ for (MemberDefinition field = getFirstMember();
424+ field != null;
425+ field = field.getNextMember()) {
426+ if (field.isUplevelValue()
427+ && outerClass.getType().equals(field.getType())
428+ && field.getName().toString().startsWith(prefixThis)) {
429+ setOuterMember(field);
430+ }
431+ }
432+ }
433+
434+ private void initOuter(ClassDefinition innerClass, int mods) {
435+ if (innerClass instanceof BinaryClass)
436+ ((BinaryClass)innerClass).initInner(this, mods);
437+ addMember(new BinaryMember(innerClass));
438+ }
439+
440+ /**
441+ * Write the class out to a given stream. This function mirrors the loader.
442+ */
443+ public void write(Environment env, OutputStream out) throws IOException {
444+ DataOutputStream data = new DataOutputStream(out);
445+
446+ // write out the header
447+ data.writeInt(JAVA_MAGIC);
448+ data.writeShort(env.getMinorVersion());
449+ data.writeShort(env.getMajorVersion());
450+
451+ // Write out the constant pool
452+ cpool.write(data, env);
453+
454+ // Write class information
455+ data.writeShort(getModifiers() & ACCM_CLASS);
456+ data.writeShort(cpool.indexObject(getClassDeclaration(), env));
457+ data.writeShort((getSuperClass() != null)
458+ ? cpool.indexObject(getSuperClass(), env) : 0);
459+ data.writeShort(interfaces.length);
460+ for (int i = 0 ; i < interfaces.length ; i++) {
461+ data.writeShort(cpool.indexObject(interfaces[i], env));
462+ }
463+
464+ // count the fields and the methods
465+ int fieldCount = 0, methodCount = 0;
466+ for (MemberDefinition f = firstMember; f != null; f = f.getNextMember())
467+ if (f.isMethod()) methodCount++; else fieldCount++;
468+
469+ // write out each the field count, and then each field
470+ data.writeShort(fieldCount);
471+ for (MemberDefinition f = firstMember; f != null; f = f.getNextMember()) {
472+ if (!f.isMethod()) {
473+ data.writeShort(f.getModifiers() & ACCM_FIELD);
474+ String name = f.getName().toString();
475+ String signature = f.getType().getTypeSignature();
476+ data.writeShort(cpool.indexString(name, env));
477+ data.writeShort(cpool.indexString(signature, env));
478+ BinaryAttribute.write(((BinaryMember)f).atts, data, cpool, env);
479+ }
480+ }
481+
482+ // write out each method count, and then each method
483+ data.writeShort(methodCount);
484+ for (MemberDefinition f = firstMember; f != null; f = f.getNextMember()) {
485+ if (f.isMethod()) {
486+ data.writeShort(f.getModifiers() & ACCM_METHOD);
487+ String name = f.getName().toString();
488+ String signature = f.getType().getTypeSignature();
489+ data.writeShort(cpool.indexString(name, env));
490+ data.writeShort(cpool.indexString(signature, env));
491+ BinaryAttribute.write(((BinaryMember)f).atts, data, cpool, env);
492+ }
493+ }
494+
495+ // write out the class attributes
496+ BinaryAttribute.write(atts, data, cpool, env);
497+ data.flush();
498+ }
499+
500+ /**
501+ * Get the dependencies
502+ */
503+ public Enumeration getDependencies() {
504+ return dependencies.elements();
505+ }
506+
507+ /**
508+ * Add a dependency
509+ */
510+ public void addDependency(ClassDeclaration c) {
511+ if ((c != null) && !dependencies.contains(c)) {
512+ dependencies.addElement(c);
513+ }
514+ }
515+
516+ /**
517+ * Get the constant pool
518+ */
519+ public BinaryConstantPool getConstants() {
520+ return cpool;
521+ }
522+
523+ /**
524+ * Get a class attribute
525+ */
526+ public byte getAttribute(Identifier name)[] {
527+ for (BinaryAttribute att = atts ; att != null ; att = att.next) {
528+ if (att.name.equals(name)) {
529+ return att.data;
530+ }
531+ }
532+ return null;
533+ }
534+}
java/pkg/sun/tools/java/BinaryCode.java+111−0
@@ -0,0 +1,111 @@
1+/*
2+ * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+
27+package sun.tools.java;
28+
29+import java.io.*;
30+
31+/**
32+ * WARNING: The contents of this source file are not part of any
33+ * supported API. Code that depends on them does so at its own risk:
34+ * they are subject to change or removal without notice.
35+ */
36+public class BinaryCode implements Constants {
37+ int maxStack; // maximum stack used by code
38+ int maxLocals; // maximum locals used by code
39+ BinaryExceptionHandler exceptionHandlers[];
40+ BinaryAttribute atts; // code attributes
41+ BinaryConstantPool cpool; // constant pool of the class
42+ byte code[]; // the byte code
43+
44+ /**
45+ * Construct the binary code from the code attribute
46+ */
47+
48+ public
49+ BinaryCode(byte data[], BinaryConstantPool cpool, Environment env) {
50+ DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
51+ try {
52+ this.cpool = cpool;
53+ // JVM 4.7.4 CodeAttribute.max_stack
54+ this.maxStack = in.readUnsignedShort();
55+ // JVM 4.7.4 CodeAttribute.max_locals
56+ this.maxLocals = in.readUnsignedShort();
57+ // JVM 4.7.4 CodeAttribute.code_length
58+ int code_length = in.readInt();
59+ this.code = new byte[code_length];
60+ // JVM 4.7.4 CodeAttribute.code[]
61+ in.read(this.code);
62+ // JVM 4.7.4 CodeAttribute.exception_table_length
63+ int exception_count = in.readUnsignedShort();
64+ this.exceptionHandlers = new BinaryExceptionHandler[exception_count];
65+ for (int i = 0; i < exception_count; i++) {
66+ // JVM 4.7.4 CodeAttribute.exception_table.start_pc
67+ int start = in.readUnsignedShort();
68+ // JVM 4.7.4 CodeAttribute.exception_table.end_pc
69+ int end = in.readUnsignedShort();
70+ // JVM 4.7.4 CodeAttribute.exception_table.handler_pc
71+ int handler = in.readUnsignedShort();
72+ // JVM 4.7.4 CodeAttribute.exception_table.catch_type
73+ ClassDeclaration xclass = cpool.getDeclaration(env, in.readUnsignedShort());
74+ this.exceptionHandlers[i] =
75+ new BinaryExceptionHandler(start, end, handler, xclass);
76+ }
77+ this.atts = BinaryAttribute.load(in, cpool, ~0);
78+ if (in.available() != 0) {
79+ System.err.println("Should have exhausted input stream!");
80+ }
81+ } catch (IOException e) {
82+ throw new CompilerError(e);
83+ }
84+ }
85+
86+
87+ /**
88+ * Accessors
89+ */
90+
91+ public BinaryExceptionHandler getExceptionHandlers()[] {
92+ return exceptionHandlers;
93+ }
94+
95+ public byte getCode()[] { return code; }
96+
97+ public int getMaxStack() { return maxStack; }
98+
99+ public int getMaxLocals() { return maxLocals; }
100+
101+ public BinaryAttribute getAttributes() { return atts; }
102+
103+ /**
104+ * Load a binary class
105+ */
106+ public static
107+ BinaryCode load(BinaryMember bf, BinaryConstantPool cpool, Environment env) {
108+ byte code[] = bf.getAttribute(idCode);
109+ return (code != null) ? new BinaryCode(code, cpool, env) : null;
110+ }
111+}
java/pkg/sun/tools/java/BinaryConstantPool.java+327−0
@@ -0,0 +1,327 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.io.IOException;
29+import java.io.DataInputStream;
30+import java.io.DataOutputStream;
31+import java.util.Vector;
32+import java.util.Hashtable;
33+
34+/**
35+ * This class is used to represent a constant table once
36+ * it is read from a class file.
37+ *
38+ * WARNING: The contents of this source file are not part of any
39+ * supported API. Code that depends on them does so at its own risk:
40+ * they are subject to change or removal without notice.
41+ */
42+public final
43+class BinaryConstantPool implements Constants {
44+ private byte types[];
45+ private Object cpool[];
46+
47+ /**
48+ * Constructor
49+ */
50+ BinaryConstantPool(DataInputStream in) throws IOException {
51+ // JVM 4.1 ClassFile.constant_pool_count
52+ types = new byte[in.readUnsignedShort()];
53+ cpool = new Object[types.length];
54+ for (int i = 1 ; i < cpool.length ; i++) {
55+ int j = i;
56+ // JVM 4.4 cp_info.tag
57+ switch(types[i] = in.readByte()) {
58+ case CONSTANT_UTF8:
59+ cpool[i] = in.readUTF();
60+ break;
61+
62+ case CONSTANT_INTEGER:
63+ cpool[i] = new Integer(in.readInt());
64+ break;
65+ case CONSTANT_FLOAT:
66+ cpool[i] = new Float(in.readFloat());
67+ break;
68+ case CONSTANT_LONG:
69+ cpool[i++] = new Long(in.readLong());
70+ break;
71+ case CONSTANT_DOUBLE:
72+ cpool[i++] = new Double(in.readDouble());
73+ break;
74+
75+ case CONSTANT_CLASS:
76+ case CONSTANT_STRING:
77+ // JVM 4.4.3 CONSTANT_String_info.string_index
78+ // or JVM 4.4.1 CONSTANT_Class_info.name_index
79+ cpool[i] = new Integer(in.readUnsignedShort());
80+ break;
81+
82+ case CONSTANT_FIELD:
83+ case CONSTANT_METHOD:
84+ case CONSTANT_INTERFACEMETHOD:
85+ case CONSTANT_NAMEANDTYPE:
86+ // JVM 4.4.2 CONSTANT_*ref_info.class_index & name_and_type_index
87+ cpool[i] = new Integer((in.readUnsignedShort() << 16) | in.readUnsignedShort());
88+ break;
89+
90+ case 0:
91+ default:
92+ throw new ClassFormatError("invalid constant type: " + (int)types[i]);
93+ }
94+ }
95+ }
96+
97+ /**
98+ * get a integer
99+ */
100+ public int getInteger(int n) {
101+ return (n == 0) ? 0 : ((Number)cpool[n]).intValue();
102+ }
103+
104+ /**
105+ * get a value
106+ */
107+ public Object getValue(int n) {
108+ return (n == 0) ? null : cpool[n];
109+ }
110+
111+ /**
112+ * get a string
113+ */
114+ public String getString(int n) {
115+ return (n == 0) ? null : (String)cpool[n];
116+ }
117+
118+ /**
119+ * get an identifier
120+ */
121+ public Identifier getIdentifier(int n) {
122+ return (n == 0) ? null : Identifier.lookup(getString(n));
123+ }
124+
125+ /**
126+ * get class declaration
127+ */
128+ public ClassDeclaration getDeclarationFromName(Environment env, int n) {
129+ return (n == 0) ? null : env.getClassDeclaration(Identifier.lookup(getString(n).replace('/','.')));
130+ }
131+
132+ /**
133+ * get class declaration
134+ */
135+ public ClassDeclaration getDeclaration(Environment env, int n) {
136+ return (n == 0) ? null : getDeclarationFromName(env, getInteger(n));
137+ }
138+
139+ /**
140+ * get a type from a type signature
141+ */
142+ public Type getType(int n) {
143+ return Type.tType(getString(n));
144+ }
145+
146+ /**
147+ * get the type of constant given an index
148+ */
149+ public int getConstantType(int n) {
150+ return types[n];
151+ }
152+
153+ /**
154+ * get the n-th constant from the constant pool
155+ */
156+ public Object getConstant(int n, Environment env) {
157+ int constant_type = getConstantType(n);
158+ switch (constant_type) {
159+ case CONSTANT_INTEGER:
160+ case CONSTANT_FLOAT:
161+ case CONSTANT_LONG:
162+ case CONSTANT_DOUBLE:
163+ return getValue(n);
164+
165+ case CONSTANT_CLASS:
166+ return getDeclaration(env, n);
167+
168+ case CONSTANT_STRING:
169+ return getString(getInteger(n));
170+
171+ case CONSTANT_FIELD:
172+ case CONSTANT_METHOD:
173+ case CONSTANT_INTERFACEMETHOD:
174+ try {
175+ int key = getInteger(n);
176+ ClassDefinition clazz =
177+ getDeclaration(env, key >> 16).getClassDefinition(env);
178+ int name_and_type = getInteger(key & 0xFFFF);
179+ Identifier id = getIdentifier(name_and_type >> 16);
180+ Type type = getType(name_and_type & 0xFFFF);
181+
182+ for (MemberDefinition field = clazz.getFirstMatch(id);
183+ field != null;
184+ field = field.getNextMatch()) {
185+ Type field_type = field.getType();
186+ if ((constant_type == CONSTANT_FIELD)
187+ ? (field_type == type)
188+ : (field_type.equalArguments(type)))
189+ return field;
190+ }
191+ } catch (ClassNotFound e) {
192+ }
193+ return null;
194+
195+ default:
196+ throw new ClassFormatError("invalid constant type: " +
197+ constant_type);
198+ }
199+ }
200+
201+
202+ /**
203+ * Get a list of dependencies, ie: all the classes referenced in this
204+ * constant pool.
205+ */
206+ public Vector getDependencies(Environment env) {
207+ Vector v = new Vector();
208+ for (int i = 1 ; i < cpool.length ; i++) {
209+ switch(types[i]) {
210+ case CONSTANT_CLASS:
211+ v.addElement(getDeclarationFromName(env, getInteger(i)));
212+ break;
213+ }
214+ }
215+ return v;
216+ }
217+
218+ Hashtable indexHashObject, indexHashAscii;
219+ Vector MoreStuff;
220+
221+ /**
222+ * Find the index of an Object in the constant pool
223+ */
224+ public int indexObject(Object obj, Environment env) {
225+ if (indexHashObject == null)
226+ createIndexHash(env);
227+ Integer result = (Integer)indexHashObject.get(obj);
228+ if (result == null)
229+ throw new IndexOutOfBoundsException("Cannot find object " + obj + " of type " +
230+ obj.getClass() + " in constant pool");
231+ return result.intValue();
232+ }
233+
234+ /**
235+ * Find the index of an ascii string in the constant pool. If it's not in
236+ * the constant pool, then add it at the end.
237+ */
238+ public int indexString(String string, Environment env) {
239+ if (indexHashObject == null)
240+ createIndexHash(env);
241+ Integer result = (Integer)indexHashAscii.get(string);
242+ if (result == null) {
243+ if (MoreStuff == null) MoreStuff = new Vector();
244+ result = new Integer(cpool.length + MoreStuff.size());
245+ MoreStuff.addElement(string);
246+ indexHashAscii.put(string, result);
247+ }
248+ return result.intValue();
249+ }
250+
251+ /**
252+ * Create a hash table of all the items in the constant pool that could
253+ * possibly be referenced from the outside.
254+ */
255+
256+ public void createIndexHash(Environment env) {
257+ indexHashObject = new Hashtable();
258+ indexHashAscii = new Hashtable();
259+ for (int i = 1; i < cpool.length; i++) {
260+ if (types[i] == CONSTANT_UTF8) {
261+ indexHashAscii.put(cpool[i], new Integer(i));
262+ } else {
263+ try {
264+ indexHashObject.put(getConstant(i, env), new Integer(i));
265+ } catch (ClassFormatError e) { }
266+ }
267+ }
268+ }
269+
270+
271+ /**
272+ * Write out the contents of the constant pool, including any additions
273+ * that have been added.
274+ */
275+ public void write(DataOutputStream out, Environment env) throws IOException {
276+ int length = cpool.length;
277+ if (MoreStuff != null)
278+ length += MoreStuff.size();
279+ out.writeShort(length);
280+ for (int i = 1 ; i < cpool.length; i++) {
281+ int type = types[i];
282+ Object x = cpool[i];
283+ out.writeByte(type);
284+ switch (type) {
285+ case CONSTANT_UTF8:
286+ out.writeUTF((String) x);
287+ break;
288+ case CONSTANT_INTEGER:
289+ out.writeInt(((Number)x).intValue());
290+ break;
291+ case CONSTANT_FLOAT:
292+ out.writeFloat(((Number)x).floatValue());
293+ break;
294+ case CONSTANT_LONG:
295+ out.writeLong(((Number)x).longValue());
296+ i++;
297+ break;
298+ case CONSTANT_DOUBLE:
299+ out.writeDouble(((Number)x).doubleValue());
300+ i++;
301+ break;
302+ case CONSTANT_CLASS:
303+ case CONSTANT_STRING:
304+ out.writeShort(((Number)x).intValue());
305+ break;
306+ case CONSTANT_FIELD:
307+ case CONSTANT_METHOD:
308+ case CONSTANT_INTERFACEMETHOD:
309+ case CONSTANT_NAMEANDTYPE: {
310+ int value = ((Number)x).intValue();
311+ out.writeShort(value >> 16);
312+ out.writeShort(value & 0xFFFF);
313+ break;
314+ }
315+ default:
316+ throw new ClassFormatError("invalid constant type: "
317+ + (int)types[i]);
318+ }
319+ }
320+ for (int i = cpool.length; i < length; i++) {
321+ String string = (String)(MoreStuff.elementAt(i - cpool.length));
322+ out.writeByte(CONSTANT_UTF8);
323+ out.writeUTF(string);
324+ }
325+ }
326+
327+}
java/pkg/sun/tools/java/BinaryExceptionHandler.java+49−0
@@ -0,0 +1,49 @@
1+/*
2+ * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+/**
29+ * A single exception handler. This class hangs off BinaryCode.
30+ *
31+ * WARNING: The contents of this source file are not part of any
32+ * supported API. Code that depends on them does so at its own risk:
33+ * they are subject to change or removal without notice.
34+ */
35+
36+public class BinaryExceptionHandler {
37+ public int startPC;
38+ public int endPC;
39+ public int handlerPC;
40+ public ClassDeclaration exceptionClass;
41+
42+ BinaryExceptionHandler(int start, int end,
43+ int handler, ClassDeclaration xclass) {
44+ startPC = start;
45+ endPC = end;
46+ handlerPC = handler;
47+ exceptionClass = xclass;
48+ }
49+}
java/pkg/sun/tools/java/BinaryMember.java+260−0
@@ -0,0 +1,260 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import sun.tools.tree.*;
29+import java.util.Vector;
30+import java.util.Hashtable;
31+import java.io.IOException;
32+import java.io.DataInputStream;
33+import java.io.ByteArrayInputStream;
34+
35+/**
36+ * This class represents a binary member
37+ *
38+ * WARNING: The contents of this source file are not part of any
39+ * supported API. Code that depends on them does so at its own risk:
40+ * they are subject to change or removal without notice.
41+ */
42+public final
43+class BinaryMember extends MemberDefinition {
44+ Expression value;
45+ BinaryAttribute atts;
46+
47+ /**
48+ * Constructor
49+ */
50+ public BinaryMember(ClassDefinition clazz, int modifiers, Type type,
51+ Identifier name, BinaryAttribute atts) {
52+ super(0, clazz, modifiers, type, name, null, null);
53+ this.atts = atts;
54+
55+ // Was it compiled as deprecated?
56+ if (getAttribute(idDeprecated) != null) {
57+ this.modifiers |= M_DEPRECATED;
58+ }
59+
60+ // Was it synthesized by the compiler?
61+ if (getAttribute(idSynthetic) != null) {
62+ this.modifiers |= M_SYNTHETIC;
63+ }
64+ }
65+
66+ /**
67+ * Constructor for an inner class.
68+ */
69+ public BinaryMember(ClassDefinition innerClass) {
70+ super(innerClass);
71+ }
72+
73+ /**
74+ * Inline allowed (currently only allowed for the constructor of Object).
75+ */
76+ public boolean isInlineable(Environment env, boolean fromFinal) {
77+ // It is possible for 'getSuperClass()' to return null due to error
78+ // recovery from cyclic inheritace. Can this cause a problem here?
79+ return isConstructor() && (getClassDefinition().getSuperClass() == null);
80+ }
81+
82+ /**
83+ * Get arguments
84+ */
85+ public Vector getArguments() {
86+ if (isConstructor() && (getClassDefinition().getSuperClass() == null)) {
87+ Vector v = new Vector();
88+ v.addElement(new LocalMember(0, getClassDefinition(), 0,
89+ getClassDefinition().getType(), idThis));
90+ return v;
91+ }
92+ return null;
93+ }
94+
95+ /**
96+ * Get exceptions
97+ */
98+ public ClassDeclaration[] getExceptions(Environment env) {
99+ if ((!isMethod()) || (exp != null)) {
100+ return exp;
101+ }
102+ byte data[] = getAttribute(idExceptions);
103+ if (data == null) {
104+ return new ClassDeclaration[0];
105+ }
106+
107+ try {
108+ BinaryConstantPool cpool = ((BinaryClass)getClassDefinition()).getConstants();
109+ DataInputStream in = new DataInputStream(new ByteArrayInputStream(data));
110+ // JVM 4.7.5 Exceptions_attribute.number_of_exceptions
111+ int n = in.readUnsignedShort();
112+ exp = new ClassDeclaration[n];
113+ for (int i = 0 ; i < n ; i++) {
114+ // JVM 4.7.5 Exceptions_attribute.exception_index_table[]
115+ exp[i] = cpool.getDeclaration(env, in.readUnsignedShort());
116+ }
117+ return exp;
118+ } catch (IOException e) {
119+ throw new CompilerError(e);
120+ }
121+ }
122+
123+ /**
124+ * Get documentation
125+ */
126+ public String getDocumentation() {
127+ if (documentation != null) {
128+ return documentation;
129+ }
130+ byte data[] = getAttribute(idDocumentation);
131+ if (data == null) {
132+ return null;
133+ }
134+ try {
135+ return documentation = new DataInputStream(new ByteArrayInputStream(data)).readUTF();
136+ } catch (IOException e) {
137+ throw new CompilerError(e);
138+ }
139+ }
140+
141+ /**
142+ * Check if constant: Will it inline away to a constant?
143+ * This override is needed to solve bug 4128266. It is also
144+ * integral to the solution of 4119776.
145+ */
146+ private boolean isConstantCache = false;
147+ private boolean isConstantCached = false;
148+ public boolean isConstant() {
149+ if (!isConstantCached) {
150+ isConstantCache = isFinal()
151+ && isVariable()
152+ && getAttribute(idConstantValue) != null;
153+ isConstantCached = true;
154+ }
155+ return isConstantCache;
156+ }
157+
158+ /**
159+ * Get the value
160+ */
161+ public Node getValue(Environment env) {
162+ if (isMethod()) {
163+ return null;
164+ }
165+ if (!isFinal()) {
166+ return null;
167+ }
168+ if (getValue() != null) {
169+ return (Expression)getValue();
170+ }
171+ byte data[] = getAttribute(idConstantValue);
172+ if (data == null) {
173+ return null;
174+ }
175+
176+ try {
177+ BinaryConstantPool cpool = ((BinaryClass)getClassDefinition()).getConstants();
178+ // JVM 4.7.3 ConstantValue.constantvalue_index
179+ Object obj = cpool.getValue(new DataInputStream(new ByteArrayInputStream(data)).readUnsignedShort());
180+ switch (getType().getTypeCode()) {
181+ case TC_BOOLEAN:
182+ setValue(new BooleanExpression(0, ((Number)obj).intValue() != 0));
183+ break;
184+ case TC_BYTE:
185+ case TC_SHORT:
186+ case TC_CHAR:
187+ case TC_INT:
188+ setValue(new IntExpression(0, ((Number)obj).intValue()));
189+ break;
190+ case TC_LONG:
191+ setValue(new LongExpression(0, ((Number)obj).longValue()));
192+ break;
193+ case TC_FLOAT:
194+ setValue(new FloatExpression(0, ((Number)obj).floatValue()));
195+ break;
196+ case TC_DOUBLE:
197+ setValue(new DoubleExpression(0, ((Number)obj).doubleValue()));
198+ break;
199+ case TC_CLASS:
200+ setValue(new StringExpression(0, (String)cpool.getValue(((Number)obj).intValue())));
201+ break;
202+ }
203+ return (Expression)getValue();
204+ } catch (IOException e) {
205+ throw new CompilerError(e);
206+ }
207+ }
208+
209+ /**
210+ * Get a field attribute
211+ */
212+ public byte[] getAttribute(Identifier name) {
213+ for (BinaryAttribute att = atts ; att != null ; att = att.next) {
214+ if (att.name.equals(name)) {
215+ return att.data;
216+ }
217+ }
218+ return null;
219+ }
220+
221+ public boolean deleteAttribute(Identifier name) {
222+ BinaryAttribute walker = null, next = null;
223+
224+ boolean succeed = false;
225+
226+ while (atts.name.equals(name)) {
227+ atts = atts.next;
228+ succeed = true;
229+ }
230+ for (walker = atts; walker != null; walker = next) {
231+ next = walker.next;
232+ if (next != null) {
233+ if (next.name.equals(name)) {
234+ walker.next = next.next;
235+ next = next.next;
236+ succeed = true;
237+ }
238+ }
239+ }
240+ for (walker = atts; walker != null; walker = walker.next) {
241+ if (walker.name.equals(name)) {
242+ throw new InternalError("Found attribute " + name);
243+ }
244+ }
245+
246+ return succeed;
247+ }
248+
249+
250+
251+ /*
252+ * Add an attribute to a field
253+ */
254+ public void addAttribute(Identifier name, byte data[], Environment env) {
255+ this.atts = new BinaryAttribute(name, data, this.atts);
256+ // Make sure that the new attribute is in the constant pool
257+ ((BinaryClass)(this.clazz)).cpool.indexString(name.toString(), env);
258+ }
259+
260+}
java/pkg/sun/tools/java/ClassDeclaration.java+265−0
@@ -0,0 +1,265 @@
1+/*
2+ * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+/**
29+ * This class represents an Java class declaration. It refers
30+ * to either a binary or source definition.
31+ *
32+ * ClassDefinitions are loaded on demand, this means that
33+ * class declarations are late bound. The definition of the
34+ * class is obtained in stages. The status field describes
35+ * the state of the class definition:
36+ *
37+ * CS_UNDEFINED - the definition is not yet loaded
38+ * CS_UNDECIDED - a binary definition is loaded, but it is
39+ * still unclear if the source definition need to
40+ * be loaded
41+ * CS_BINARY - the binary class is loaded
42+ * CS_PARSED - the class is loaded from the source file, the
43+ * type information is available, but the class has
44+ * not yet been compiled.
45+ * CS_CHECKED - the class is loaded from the source file and has
46+ * been type-checked.
47+ * CS_COMPILED - the class has been type checked, compiled,
48+ * and written out.
49+ * CS_NOTFOUND - no class definition could be found
50+ *
51+ * WARNING: The contents of this source file are not part of any
52+ * supported API. Code that depends on them does so at its own risk:
53+ * they are subject to change or removal without notice.
54+ */
55+
56+public final
57+class ClassDeclaration implements Constants {
58+ int status;
59+ Type type;
60+ ClassDefinition definition;
61+
62+ /**
63+ * Constructor
64+ */
65+ public ClassDeclaration(Identifier name) {
66+ this.type = Type.tClass(name);
67+ }
68+
69+ /**
70+ * Get the status of the class
71+ */
72+ public int getStatus() {
73+ return status;
74+ }
75+
76+ /**
77+ * Get the name of the class
78+ */
79+ public Identifier getName() {
80+ return type.getClassName();
81+ }
82+
83+ /**
84+ * Get the type of the class
85+ */
86+ public Type getType() {
87+ return type;
88+ }
89+
90+ /**
91+ * Check if the class is defined
92+ */
93+ public boolean isDefined() {
94+ switch (status) {
95+ case CS_BINARY:
96+ case CS_PARSED:
97+ case CS_CHECKED:
98+ case CS_COMPILED:
99+ return true;
100+ }
101+ return false;
102+ }
103+
104+ /**
105+ * Get the definition of this class. Returns null if
106+ * the class is not yet defined.
107+ */
108+ public ClassDefinition getClassDefinition() {
109+ return definition;
110+ }
111+
112+ /**
113+ * This is a flag for use by getClassDefinition(env). It is
114+ * used to mark that a class has been successfully looked up
115+ * by that method before.
116+ */
117+ private boolean found = false;
118+
119+ /**
120+ * Get the definition of this class, if the class is not
121+ * yet defined, load the definition. Loading a class may
122+ * throw various exceptions.
123+ */
124+ public ClassDefinition getClassDefinition(Environment env)
125+ throws ClassNotFound {
126+ if (tracing) env.dtEvent("getClassDefinition: " +
127+ getName() + ", status " + getStatus());
128+
129+ // The majority of calls to getClassDefinition() are duplicates.
130+ // This check makes them fast. It also allows us to avoid
131+ // duplicate, useless calls to basicCheck(). In the future it
132+ // would be good to add an additional status value, CS_BASICCHECKED.
133+ if (found) {
134+ return definition;
135+ }
136+
137+ for(;;) {
138+ switch (status) {
139+ case CS_UNDEFINED:
140+ case CS_UNDECIDED:
141+ case CS_SOURCE:
142+ env.loadDefinition(this);
143+ break;
144+
145+ case CS_BINARY:
146+ case CS_PARSED:
147+ //+FIX FOR BUGID 4056065
148+ //definition.basicCheck(env);
149+ if (!definition.isInsideLocal()) {
150+ // Classes inside a block, including anonymous classes,
151+ // are checked when their surrounding member is checked.
152+ definition.basicCheck(env);
153+ }
154+ //-FIX FOR BUGID 4056065
155+ found = true;
156+ return definition;
157+
158+ case CS_CHECKED:
159+ case CS_COMPILED:
160+ found = true;
161+ return definition;
162+
163+ default:
164+ throw new ClassNotFound(getName());
165+ }
166+ }
167+ }
168+
169+ /**
170+ * Get the definition of this class, if the class is not
171+ * yet defined, load the definition. Loading a class may
172+ * throw various exceptions. Perform no basicCheck() on this
173+ * class.
174+ */
175+ public ClassDefinition getClassDefinitionNoCheck(Environment env) throws ClassNotFound {
176+ if (tracing) env.dtEvent("getClassDefinition: " +
177+ getName() + ", status " + getStatus());
178+ for(;;) {
179+ switch (status) {
180+ case CS_UNDEFINED:
181+ case CS_UNDECIDED:
182+ case CS_SOURCE:
183+ env.loadDefinition(this);
184+ break;
185+
186+ case CS_BINARY:
187+ case CS_PARSED:
188+ case CS_CHECKED:
189+ case CS_COMPILED:
190+ return definition;
191+
192+ default:
193+ throw new ClassNotFound(getName());
194+ }
195+ }
196+ }
197+
198+ /**
199+ * Set the class definition
200+ */
201+ public void setDefinition(ClassDefinition definition, int status) {
202+
203+ // Sanity checks.
204+
205+ // The name of the definition should match that of the declaration.
206+ if ((definition != null) && !getName().equals(definition.getName())) {
207+ throw new CompilerError("setDefinition: name mismatch: " +
208+ this + ", " + definition);
209+ }
210+
211+ // The status states can be considered ordered in the same
212+ // manner as their numerical values. We expect classes to
213+ // progress through a sequence of monotonically increasing
214+ // states. NOTE: There are currently exceptions to this rule
215+ // which are believed to be legitimate. In particular, a
216+ // class may be checked more than once, though we believe that
217+ // this is unnecessary and may be avoided.
218+ /*-----------------*
219+ if (status <= this.status) {
220+ System.out.println("STATUS REGRESSION: " +
221+ this + " FROM " + this.status + " TO " + status);
222+ }
223+ *------------------*/
224+
225+ this.definition = definition;
226+ this.status = status;
227+ }
228+
229+ /**
230+ * Equality
231+ */
232+ public boolean equals(Object obj) {
233+ if ((obj != null) && (obj instanceof ClassDeclaration)) {
234+ return type.equals(((ClassDeclaration)obj).type);
235+ }
236+ return false;
237+ }
238+
239+ /**
240+ * toString
241+ */
242+ public String toString() {
243+ String name = getName().toString();
244+ String type = "type ";
245+ String nested = getName().isInner() ? "nested " : "";
246+ if (getClassDefinition() != null) {
247+ if (getClassDefinition().isInterface()) {
248+ type = "interface ";
249+ } else {
250+ type = "class ";
251+ }
252+ if (!getClassDefinition().isTopLevel()) {
253+ nested = "inner ";
254+ if (getClassDefinition().isLocal()) {
255+ nested = "local ";
256+ if (!getClassDefinition().isAnonymous()) {
257+ name = getClassDefinition().getLocalName() +
258+ " (" + name + ")";
259+ }
260+ }
261+ }
262+ }
263+ return nested + type + name;
264+ }
265+}
java/pkg/sun/tools/java/ClassDefinition.java+2085−0
@@ -0,0 +1,2085 @@
1+/*
2+ * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.util.*;
29+import java.io.OutputStream;
30+import java.io.PrintStream;
31+import sun.tools.tree.Context;
32+import sun.tools.tree.Vset;
33+import sun.tools.tree.Expression;
34+import sun.tools.tree.LocalMember;
35+import sun.tools.tree.UplevelReference;
36+
37+/**
38+ * This class is a Java class definition
39+ *
40+ * WARNING: The contents of this source file are not part of any
41+ * supported API. Code that depends on them does so at its own risk:
42+ * they are subject to change or removal without notice.
43+ */
44+public
45+class ClassDefinition implements Constants {
46+
47+ protected Object source;
48+ protected long where;
49+ protected int modifiers;
50+ protected Identifier localName; // for local classes
51+ protected ClassDeclaration declaration;
52+ protected IdentifierToken superClassId;
53+ protected IdentifierToken interfaceIds[];
54+ protected ClassDeclaration superClass;
55+ protected ClassDeclaration interfaces[];
56+ protected ClassDefinition outerClass;
57+ protected MemberDefinition outerMember;
58+ protected MemberDefinition innerClassMember; // field for me in outerClass
59+ protected MemberDefinition firstMember;
60+ protected MemberDefinition lastMember;
61+ protected boolean resolved;
62+ protected String documentation;
63+ protected boolean error;
64+ protected boolean nestError;
65+ protected UplevelReference references;
66+ protected boolean referencesFrozen;
67+ private Hashtable fieldHash = new Hashtable(31);
68+ private int abstr;
69+
70+ // Table of local and anonymous classes whose internal names are constructed
71+ // using the current class as a prefix. This is part of a fix for
72+ // bugid 4054523 and 4030421. See also 'Environment.getClassDefinition'
73+ // and 'BatchEnvironment.makeClassDefinition'. Allocated on demand.
74+ private Hashtable localClasses = null;
75+ private final int LOCAL_CLASSES_SIZE = 31;
76+
77+ // The immediately surrounding context in which the class appears.
78+ // Set at the beginning of checking, upon entry to 'SourceClass.checkInternal'.
79+ // Null for classes that are not local or inside a local class.
80+ // At present, this field exists only for the benefit of 'resolveName' as part
81+ // of the fix for 4095716.
82+ protected Context classContext;
83+
84+ // The saved class context is now also used in 'SourceClass.getAccessMember'.
85+ // Provide read-only access via this method. Part of fix for 4098093.
86+ public Context getClassContext() {
87+ return classContext;
88+ }
89+
90+
91+ /**
92+ * Constructor
93+ */
94+ protected ClassDefinition(Object source, long where, ClassDeclaration declaration,
95+ int modifiers, IdentifierToken superClass, IdentifierToken interfaces[]) {
96+ this.source = source;
97+ this.where = where;
98+ this.declaration = declaration;
99+ this.modifiers = modifiers;
100+ this.superClassId = superClass;
101+ this.interfaceIds = interfaces;
102+ }
103+
104+ /**
105+ * Get the source of the class
106+ */
107+ public final Object getSource() {
108+ return source;
109+ }
110+
111+ /**
112+ * Check if there were any errors in this class.
113+ */
114+ public final boolean getError() {
115+ return error;
116+ }
117+
118+ /**
119+ * Mark this class to be erroneous.
120+ */
121+ public final void setError() {
122+ this.error = true;
123+ setNestError();
124+ }
125+
126+ /**
127+ * Check if there were any errors in our class nest.
128+ */
129+ public final boolean getNestError() {
130+ // Check to see if our error value is set, or if any of our
131+ // outer classes' error values are set. This will work in
132+ // conjunction with setError(), which sets the error value
133+ // of its outer class, to yield true is any of our nest
134+ // siblings has an error. This addresses bug 4111488: either
135+ // code should be generated for all classes in a nest, or
136+ // none of them.
137+ return nestError || ((outerClass != null) ? outerClass.getNestError() : false);
138+ }
139+
140+ /**
141+ * Mark this class, and all siblings in its class nest, to be
142+ * erroneous.
143+ */
144+ public final void setNestError() {
145+ this.nestError = true;
146+ if (outerClass != null) {
147+ // If we have an outer class, set it to be erroneous as well.
148+ // This will work in conjunction with getError(), which checks
149+ // the error value of its outer class, to set the whole class
150+ // nest to be erroneous. This address bug 4111488: either
151+ // code should be generated for all classes in a nest, or
152+ // none of them.
153+ outerClass.setNestError();
154+ }
155+ }
156+
157+ /**
158+ * Get the position in the input
159+ */
160+ public final long getWhere() {
161+ return where;
162+ }
163+
164+ /**
165+ * Get the class declaration
166+ */
167+ public final ClassDeclaration getClassDeclaration() {
168+ return declaration;
169+ }
170+
171+ /**
172+ * Get the class' modifiers
173+ */
174+ public final int getModifiers() {
175+ return modifiers;
176+ }
177+ public final void subModifiers(int mod) {
178+ modifiers &= ~mod;
179+ }
180+ public final void addModifiers(int mod) {
181+ modifiers |= mod;
182+ }
183+
184+ // *** DEBUG ***
185+ protected boolean supersCheckStarted = !(this instanceof sun.tools.javac.SourceClass);
186+
187+ /**
188+ * Get the class' super class
189+ */
190+ public final ClassDeclaration getSuperClass() {
191+ /*---
192+ if (superClass == null && superClassId != null)
193+ throw new CompilerError("getSuperClass "+superClassId);
194+ // There are obscure cases where null is the right answer,
195+ // in order to enable some error reporting later on.
196+ // For example: class T extends T.N { class N { } }
197+ ---*/
198+
199+ // *** DEBUG ***
200+ // This method should not be called if the superclass has not been resolved.
201+ if (!supersCheckStarted) throw new CompilerError("unresolved super");
202+
203+ return superClass;
204+ }
205+
206+ /**
207+ * Get the super class, and resolve names now if necessary.
208+ *
209+ * It is only possible to resolve names at this point if we are
210+ * a source class. The provision of this method at this level
211+ * in the class hierarchy is dubious, but see 'getInnerClass' below.
212+ * All other calls to 'getSuperClass(env)' appear in 'SourceClass'.
213+ * NOTE: An older definition of this method has been moved to
214+ * 'SourceClass', where it overrides this one.
215+ *
216+ * @see #resolveTypeStructure
217+ */
218+
219+ public ClassDeclaration getSuperClass(Environment env) {
220+ return getSuperClass();
221+ }
222+
223+ /**
224+ * Get the class' interfaces
225+ */
226+ public final ClassDeclaration getInterfaces()[] {
227+ if (interfaces == null) throw new CompilerError("getInterfaces");
228+ return interfaces;
229+ }
230+
231+ /**
232+ * Get the class' enclosing class (or null if not inner)
233+ */
234+ public final ClassDefinition getOuterClass() {
235+ return outerClass;
236+ }
237+
238+ /**
239+ * Set the class' enclosing class. Must be done at most once.
240+ */
241+ protected final void setOuterClass(ClassDefinition outerClass) {
242+ if (this.outerClass != null) throw new CompilerError("setOuterClass");
243+ this.outerClass = outerClass;
244+ }
245+
246+ /**
247+ * Set the class' enclosing current instance pointer.
248+ * Must be done at most once.
249+ */
250+ protected final void setOuterMember(MemberDefinition outerMember) {
251+
252+ if (isStatic() || !isInnerClass()) throw new CompilerError("setOuterField");
253+ if (this.outerMember != null) throw new CompilerError("setOuterField");
254+ this.outerMember = outerMember;
255+ }
256+
257+ /**
258+ * Tell if the class is inner.
259+ * This predicate also returns true for top-level nested types.
260+ * To test for a true inner class as seen by the programmer,
261+ * use <tt>!isTopLevel()</tt>.
262+ */
263+ public final boolean isInnerClass() {
264+ return outerClass != null;
265+ }
266+
267+ /**
268+ * Tell if the class is a member of another class.
269+ * This is false for package members and for block-local classes.
270+ */
271+ public final boolean isMember() {
272+ return outerClass != null && !isLocal();
273+ }
274+
275+ /**
276+ * Tell if the class is "top-level", which is either a package member,
277+ * or a static member of another top-level class.
278+ */
279+ public final boolean isTopLevel() {
280+ return outerClass == null || isStatic() || isInterface();
281+ }
282+
283+ /**
284+ * Tell if the class is local or inside a local class,
285+ * which means it cannot be mentioned outside of its file.
286+ */
287+
288+ // The comment above is true only because M_LOCAL is set
289+ // whenever M_ANONYMOUS is. I think it is risky to assume that
290+ // isAnonymous(x) => isLocal(x).
291+
292+ public final boolean isInsideLocal() {
293+ return isLocal() ||
294+ (outerClass != null && outerClass.isInsideLocal());
295+ }
296+
297+ /**
298+ * Tell if the class is local or or anonymous class, or inside
299+ * such a class, which means it cannot be mentioned outside of
300+ * its file.
301+ */
302+ public final boolean isInsideLocalOrAnonymous() {
303+ return isLocal() || isAnonymous () ||
304+ (outerClass != null && outerClass.isInsideLocalOrAnonymous());
305+ }
306+
307+ /**
308+ * Return a simple identifier for this class (idNull if anonymous).
309+ */
310+ public Identifier getLocalName() {
311+ if (localName != null) {
312+ return localName;
313+ }
314+ // This is also the name of the innerClassMember, if any:
315+ return getName().getFlatName().getName();
316+ }
317+
318+ /**
319+ * Set the local name of a class. Must be a local class.
320+ */
321+ public void setLocalName(Identifier name) {
322+ if (isLocal()) {
323+ localName = name;
324+ }
325+ }
326+
327+ /**
328+ * If inner, get the field for this class in the enclosing class
329+ */
330+ public final MemberDefinition getInnerClassMember() {
331+ if (outerClass == null)
332+ return null;
333+ if (innerClassMember == null) {
334+ // We must find the field in the outer class.
335+ Identifier nm = getName().getFlatName().getName();
336+ for (MemberDefinition field = outerClass.getFirstMatch(nm);
337+ field != null; field = field.getNextMatch()) {
338+ if (field.isInnerClass()) {
339+ innerClassMember = field;
340+ break;
341+ }
342+ }
343+ if (innerClassMember == null)
344+ throw new CompilerError("getInnerClassField");
345+ }
346+ return innerClassMember;
347+ }
348+
349+ /**
350+ * If inner, return an innermost uplevel self pointer, if any exists.
351+ * Otherwise, return null.
352+ */
353+ public final MemberDefinition findOuterMember() {
354+ return outerMember;
355+ }
356+
357+ /**
358+ * See if this is a (nested) static class.
359+ */
360+ public final boolean isStatic() {
361+ return (modifiers & ACC_STATIC) != 0;
362+ }
363+
364+ /**
365+ * Get the class' top-level enclosing class
366+ */
367+ public final ClassDefinition getTopClass() {
368+ ClassDefinition p, q;
369+ for (p = this; (q = p.outerClass) != null; p = q)
370+ ;
371+ return p;
372+ }
373+
374+ /**
375+ * Get the class' first field or first match
376+ */
377+ public final MemberDefinition getFirstMember() {
378+ return firstMember;
379+ }
380+ public final MemberDefinition getFirstMatch(Identifier name) {
381+ return (MemberDefinition)fieldHash.get(name);
382+ }
383+
384+ /**
385+ * Get the class' name
386+ */
387+ public final Identifier getName() {
388+ return declaration.getName();
389+ }
390+
391+ /**
392+ * Get the class' type
393+ */
394+ public final Type getType() {
395+ return declaration.getType();
396+ }
397+
398+ /**
399+ * Get the class' documentation
400+ */
401+ public String getDocumentation() {
402+ return documentation;
403+ }
404+
405+ /**
406+ * Return true if the given documentation string contains a deprecation
407+ * paragraph. This is true if the string contains the tag @deprecated
408+ * is the first word in a line.
409+ */
410+ public static boolean containsDeprecated(String documentation) {
411+ if (documentation == null) {
412+ return false;
413+ }
414+ doScan:
415+ for (int scan = 0;
416+ (scan = documentation.indexOf(paraDeprecated, scan)) >= 0;
417+ scan += paraDeprecated.length()) {
418+ // make sure there is only whitespace between this word
419+ // and the beginning of the line
420+ for (int beg = scan-1; beg >= 0; beg--) {
421+ char ch = documentation.charAt(beg);
422+ if (ch == '\n' || ch == '\r') {
423+ break; // OK
424+ }
425+ if (!Character.isSpace(ch)) {
426+ continue doScan;
427+ }
428+ }
429+ // make sure the char after the word is space or end of line
430+ int end = scan+paraDeprecated.length();
431+ if (end < documentation.length()) {
432+ char ch = documentation.charAt(end);
433+ if (!(ch == '\n' || ch == '\r') && !Character.isSpace(ch)) {
434+ continue doScan;
435+ }
436+ }
437+ return true;
438+ }
439+ return false;
440+ }
441+
442+ public final boolean inSamePackage(ClassDeclaration c) {
443+ // find out if the class stored in c is defined in the same
444+ // package as the current class.
445+ return inSamePackage(c.getName().getQualifier());
446+ }
447+
448+ public final boolean inSamePackage(ClassDefinition c) {
449+ // find out if the class stored in c is defined in the same
450+ // package as the current class.
451+ return inSamePackage(c.getName().getQualifier());
452+ }
453+
454+ public final boolean inSamePackage(Identifier packageName) {
455+ return (getName().getQualifier().equals(packageName));
456+ }
457+
458+ /**
459+ * Checks
460+ */
461+ public final boolean isInterface() {
462+ return (getModifiers() & M_INTERFACE) != 0;
463+ }
464+ public final boolean isClass() {
465+ return (getModifiers() & M_INTERFACE) == 0;
466+ }
467+ public final boolean isPublic() {
468+ return (getModifiers() & M_PUBLIC) != 0;
469+ }
470+ public final boolean isPrivate() {
471+ return (getModifiers() & M_PRIVATE) != 0;
472+ }
473+ public final boolean isProtected() {
474+ return (getModifiers() & M_PROTECTED) != 0;
475+ }
476+ public final boolean isPackagePrivate() {
477+ return (modifiers & (M_PUBLIC | M_PRIVATE | M_PROTECTED)) == 0;
478+ }
479+ public final boolean isFinal() {
480+ return (getModifiers() & M_FINAL) != 0;
481+ }
482+ public final boolean isAbstract() {
483+ return (getModifiers() & M_ABSTRACT) != 0;
484+ }
485+ public final boolean isSynthetic() {
486+ return (getModifiers() & M_SYNTHETIC) != 0;
487+ }
488+ public final boolean isDeprecated() {
489+ return (getModifiers() & M_DEPRECATED) != 0;
490+ }
491+ public final boolean isAnonymous() {
492+ return (getModifiers() & M_ANONYMOUS) != 0;
493+ }
494+ public final boolean isLocal() {
495+ return (getModifiers() & M_LOCAL) != 0;
496+ }
497+ public final boolean hasConstructor() {
498+ return getFirstMatch(idInit) != null;
499+ }
500+
501+
502+ /**
503+ * Check to see if a class must be abstract. This method replaces
504+ * isAbstract(env)
505+ */
506+ public final boolean mustBeAbstract(Environment env) {
507+ // If it is declared abstract, return true.
508+ // (Fix for 4110534.)
509+ if (isAbstract()) {
510+ return true;
511+ }
512+
513+ // Check to see if the class should have been declared to be
514+ // abstract.
515+
516+ // We make sure that the inherited method collection has been
517+ // performed.
518+ collectInheritedMethods(env);
519+
520+ // We check for any abstract methods inherited or declared
521+ // by this class.
522+ Iterator methods = getMethods();
523+ while (methods.hasNext()) {
524+ MemberDefinition method = (MemberDefinition) methods.next();
525+
526+ if (method.isAbstract()) {
527+ return true;
528+ }
529+ }
530+
531+ // We check for hidden "permanently abstract" methods in
532+ // our superclasses.
533+ return getPermanentlyAbstractMethods().hasNext();
534+ }
535+
536+ /**
537+ * Check if this is a super class of another class
538+ */
539+ public boolean superClassOf(Environment env, ClassDeclaration otherClass)
540+ throws ClassNotFound {
541+ while (otherClass != null) {
542+ if (getClassDeclaration().equals(otherClass)) {
543+ return true;
544+ }
545+ otherClass = otherClass.getClassDefinition(env).getSuperClass();
546+ }
547+ return false;
548+ }
549+
550+ /**
551+ * Check if this is an enclosing class of another class
552+ */
553+ public boolean enclosingClassOf(ClassDefinition otherClass) {
554+ while ((otherClass = otherClass.getOuterClass()) != null) {
555+ if (this == otherClass) {
556+ return true;
557+ }
558+ }
559+ return false;
560+ }
561+
562+ /**
563+ * Check if this is a sub class of another class
564+ */
565+ public boolean subClassOf(Environment env, ClassDeclaration otherClass) throws ClassNotFound {
566+ ClassDeclaration c = getClassDeclaration();
567+ while (c != null) {
568+ if (c.equals(otherClass)) {
569+ return true;
570+ }
571+ c = c.getClassDefinition(env).getSuperClass();
572+ }
573+ return false;
574+ }
575+
576+ /**
577+ * Check if this class is implemented by another class
578+ */
579+ public boolean implementedBy(Environment env, ClassDeclaration c) throws ClassNotFound {
580+ for (; c != null ; c = c.getClassDefinition(env).getSuperClass()) {
581+ if (getClassDeclaration().equals(c)) {
582+ return true;
583+ }
584+ ClassDeclaration intf[] = c.getClassDefinition(env).getInterfaces();
585+ for (int i = 0 ; i < intf.length ; i++) {
586+ if (implementedBy(env, intf[i])) {
587+ return true;
588+ }
589+ }
590+ }
591+ return false;
592+ }
593+
594+ /**
595+ * Check to see if a class which implements interface `this' could
596+ * possibly implement the interface `intDef'. Note that the only
597+ * way that this can fail is if `this' and `intDef' have methods
598+ * which are of the same signature and different return types. This
599+ * method is used by Environment.explicitCast() to determine if a
600+ * cast between two interfaces is legal.
601+ *
602+ * This method should only be called on a class after it has been
603+ * basicCheck()'ed.
604+ */
605+ public boolean couldImplement(ClassDefinition intDef) {
606+ // Check to see if we could have done the necessary checks.
607+ if (!doInheritanceChecks) {
608+ throw new CompilerError("couldImplement: no checks");
609+ }
610+
611+ // This method should only be called for interfaces.
612+ if (!isInterface() || !intDef.isInterface()) {
613+ throw new CompilerError("couldImplement: not interface");
614+ }
615+
616+ // Make sure we are not called before we have collected our
617+ // inheritance information.
618+ if (allMethods == null) {
619+ throw new CompilerError("couldImplement: called early");
620+ }
621+
622+ // Get the other classes' methods. getMethods() in
623+ // general can return methods which are not visible to the
624+ // current package. We need to make sure that these do not
625+ // prevent this class from being implemented.
626+ Iterator otherMethods = intDef.getMethods();
627+
628+ while (otherMethods.hasNext()) {
629+ // Get one of the methods from intDef...
630+ MemberDefinition method =
631+ (MemberDefinition) otherMethods.next();
632+
633+ Identifier name = method.getName();
634+ Type type = method.getType();
635+
636+ // See if we implement a method of the same signature...
637+ MemberDefinition myMethod = allMethods.lookupSig(name, type);
638+
639+ //System.out.println("Comparing\n\t" + myMethod +
640+ // "\nand\n\t" + method);
641+
642+ if (myMethod != null) {
643+ // We do. Make sure the methods have the same return type.
644+ if (!myMethod.sameReturnType(method)) {
645+ return false;
646+ }
647+ }
648+ }
649+
650+ return true;
651+ }
652+
653+ /**
654+ * Check if another class can be accessed from the 'extends' or 'implements'
655+ * clause of this class.
656+ */
657+ public boolean extendsCanAccess(Environment env, ClassDeclaration c) throws ClassNotFound {
658+
659+ // Names in the 'extends' or 'implements' clause of an inner class
660+ // are checked as if they appeared in the body of the surrounding class.
661+ if (outerClass != null) {
662+ return outerClass.canAccess(env, c);
663+ }
664+
665+ // We are a package member.
666+
667+ ClassDefinition cdef = c.getClassDefinition(env);
668+
669+ if (cdef.isLocal()) {
670+ // No locals should be in scope in the 'extends' or
671+ // 'implements' clause of a package member.
672+ throw new CompilerError("top local");
673+ }
674+
675+ if (cdef.isInnerClass()) {
676+ MemberDefinition f = cdef.getInnerClassMember();
677+
678+ // Access to public member is always allowed.
679+ if (f.isPublic()) {
680+ return true;
681+ }
682+
683+ // Private access is ok only from the same class nest. This can
684+ // happen only if the class represented by 'this' encloses the inner
685+ // class represented by 'f'.
686+ if (f.isPrivate()) {
687+ return getClassDeclaration().equals(f.getTopClass().getClassDeclaration());
688+ }
689+
690+ // Protected or default access -- allow access if in same package.
691+ return getName().getQualifier().equals(f.getClassDeclaration().getName().getQualifier());
692+ }
693+
694+ // Access to public member is always allowed.
695+ if (cdef.isPublic()) {
696+ return true;
697+ }
698+
699+ // Default access -- allow access if in same package.
700+ return getName().getQualifier().equals(c.getName().getQualifier());
701+ }
702+
703+ /**
704+ * Check if another class can be accessed from within the body of this class.
705+ */
706+ public boolean canAccess(Environment env, ClassDeclaration c) throws ClassNotFound {
707+ ClassDefinition cdef = c.getClassDefinition(env);
708+
709+ if (cdef.isLocal()) {
710+ // if it's in scope, it's accessible
711+ return true;
712+ }
713+
714+ if (cdef.isInnerClass()) {
715+ return canAccess(env, cdef.getInnerClassMember());
716+ }
717+
718+ // Public access is always ok
719+ if (cdef.isPublic()) {
720+ return true;
721+ }
722+
723+ // It must be in the same package
724+ return getName().getQualifier().equals(c.getName().getQualifier());
725+ }
726+
727+ /**
728+ * Check if a field can be accessed from a class
729+ */
730+
731+ public boolean canAccess(Environment env, MemberDefinition f)
732+ throws ClassNotFound {
733+
734+ // Public access is always ok
735+ if (f.isPublic()) {
736+ return true;
737+ }
738+ // Protected access is ok from a subclass
739+ if (f.isProtected() && subClassOf(env, f.getClassDeclaration())) {
740+ return true;
741+ }
742+ // Private access is ok only from the same class nest
743+ if (f.isPrivate()) {
744+ return getTopClass().getClassDeclaration()
745+ .equals(f.getTopClass().getClassDeclaration());
746+ }
747+ // It must be in the same package
748+ return getName().getQualifier().equals(f.getClassDeclaration().getName().getQualifier());
749+ }
750+
751+ /**
752+ * Check if a class is entitled to inline access to a class from
753+ * another class.
754+ */
755+ public boolean permitInlinedAccess(Environment env, ClassDeclaration c)
756+ throws ClassNotFound {
757+
758+ return (env.opt() && c.equals(declaration)) ||
759+ (env.opt_interclass() && canAccess(env, c));
760+ }
761+
762+ /**
763+ * Check if a class is entitled to inline access to a method from
764+ * another class.
765+ */
766+ public boolean permitInlinedAccess(Environment env, MemberDefinition f)
767+ throws ClassNotFound {
768+ return (env.opt()
769+ && (f.clazz.getClassDeclaration().equals(declaration))) ||
770+ (env.opt_interclass() && canAccess(env, f));
771+ }
772+
773+ /**
774+ * We know the the field is marked protected (and not public) and that
775+ * the field is visible (as per canAccess). Can we access the field as
776+ * <accessor>.<field>, where <accessor> has the type <accessorType>?
777+ *
778+ * Protected fields can only be accessed when the accessorType is a
779+ * subclass of the current class
780+ */
781+ public boolean protectedAccess(Environment env, MemberDefinition f,
782+ Type accessorType)
783+ throws ClassNotFound
784+ {
785+
786+ return
787+ // static protected fields are accessible
788+ f.isStatic()
789+ || // allow array.clone()
790+ (accessorType.isType(TC_ARRAY) && (f.getName() == idClone)
791+ && (f.getType().getArgumentTypes().length == 0))
792+ || // <accessorType> is a subtype of the current class
793+ (accessorType.isType(TC_CLASS)
794+ && env.getClassDefinition(accessorType.getClassName())
795+ .subClassOf(env, getClassDeclaration()))
796+ || // we are accessing the field from a friendly class (same package)
797+ (getName().getQualifier()
798+ .equals(f.getClassDeclaration().getName().getQualifier()));
799+ }
800+
801+
802+ /**
803+ * Find or create an access method for a private member,
804+ * or return null if this is not possible.
805+ */
806+ public MemberDefinition getAccessMember(Environment env, Context ctx,
807+ MemberDefinition field, boolean isSuper) {
808+ throw new CompilerError("binary getAccessMember");
809+ }
810+
811+ /**
812+ * Find or create an update method for a private member,
813+ * or return null if this is not possible.
814+ */
815+ public MemberDefinition getUpdateMember(Environment env, Context ctx,
816+ MemberDefinition field, boolean isSuper) {
817+ throw new CompilerError("binary getUpdateMember");
818+ }
819+
820+ /**
821+ * Get a field from this class. Report ambiguous fields.
822+ * If no accessible field is found, this method may return an
823+ * inaccessible field to allow a useful error message.
824+ *
825+ * getVariable now takes the source class `source' as an argument.
826+ * This allows getVariable to check whether a field is inaccessible
827+ * before it signals that a field is ambiguous. The compiler used to
828+ * signal an ambiguity even when one of the fields involved was not
829+ * accessible. (bug 4053724)
830+ */
831+ public MemberDefinition getVariable(Environment env,
832+ Identifier nm,
833+ ClassDefinition source)
834+ throws AmbiguousMember, ClassNotFound {
835+
836+ return getVariable0(env, nm, source, true, true);
837+ }
838+
839+ /*
840+ * private fields are never inherited. package-private fields are
841+ * not inherited across package boundaries. To capture this, we
842+ * take two booleans as parameters: showPrivate indicates whether
843+ * we have passed a class boundary, and showPackage indicates whether
844+ * we have crossed a package boundary.
845+ */
846+ private MemberDefinition getVariable0(Environment env,
847+ Identifier nm,
848+ ClassDefinition source,
849+ boolean showPrivate,
850+ boolean showPackage)
851+ throws AmbiguousMember, ClassNotFound {
852+
853+ // Check to see if this field is defined in the current class
854+ for (MemberDefinition member = getFirstMatch(nm);
855+ member != null;
856+ member = member.getNextMatch()) {
857+ if (member.isVariable()) {
858+ if ((showPrivate || !member.isPrivate()) &&
859+ (showPackage || !member.isPackagePrivate())) {
860+ // It is defined in this class.
861+ return member;
862+ } else {
863+ // Even though this definition is not inherited,
864+ // it hides all definitions in supertypes.
865+ return null;
866+ }
867+ }
868+ }
869+
870+ // Find the field in our superclass.
871+ ClassDeclaration sup = getSuperClass();
872+ MemberDefinition field = null;
873+ if (sup != null) {
874+ field =
875+ sup.getClassDefinition(env)
876+ .getVariable0(env, nm, source,
877+ false,
878+ showPackage && inSamePackage(sup));
879+ }
880+
881+ // Find the field in our superinterfaces.
882+ for (int i = 0 ; i < interfaces.length ; i++) {
883+ // Try to look up the field in an interface. Since interfaces
884+ // only have public fields, the values of the two boolean
885+ // arguments are not important.
886+ MemberDefinition field2 =
887+ interfaces[i].getClassDefinition(env)
888+ .getVariable0(env, nm, source, true, true);
889+
890+ if (field2 != null) {
891+ // If we have two different, accessible fields, then
892+ // we've found an ambiguity.
893+ if (field != null &&
894+ source.canAccess(env, field) &&
895+ field2 != field) {
896+
897+ throw new AmbiguousMember(field2, field);
898+ }
899+ field = field2;
900+ }
901+ }
902+ return field;
903+ }
904+
905+ /**
906+ * Tells whether to report a deprecation error for this class.
907+ */
908+ public boolean reportDeprecated(Environment env) {
909+ return (isDeprecated()
910+ || (outerClass != null && outerClass.reportDeprecated(env)));
911+ }
912+
913+ /**
914+ * Note that this class is being used somehow by <tt>ref</tt>.
915+ * Report deprecation errors, etc.
916+ */
917+ public void noteUsedBy(ClassDefinition ref, long where, Environment env) {
918+ // (Have this deal with canAccess() checks, too?)
919+ if (reportDeprecated(env)) {
920+ env.error(where, "warn.class.is.deprecated", this);
921+ }
922+ }
923+
924+ /**
925+ * Get an inner class.
926+ * Look in supers but not outers.
927+ * (This is used directly to resolve expressions like "site.K", and
928+ * inside a loop to resolve lone names like "K" or the "K" in "K.L".)
929+ *
930+ * Called from 'Context' and 'FieldExpression' as well as this class.
931+ *
932+ * @see FieldExpression.checkCommon
933+ * @see resolveName
934+ */
935+ public MemberDefinition getInnerClass(Environment env, Identifier nm)
936+ throws ClassNotFound {
937+ // Note: AmbiguousClass will not be thrown unless and until
938+ // inner classes can be defined inside interfaces.
939+
940+ // Check if it is defined in the current class
941+ for (MemberDefinition field = getFirstMatch(nm);
942+ field != null ; field = field.getNextMatch()) {
943+ if (field.isInnerClass()) {
944+ if (field.getInnerClass().isLocal()) {
945+ continue; // ignore this name; it is internally generated
946+ }
947+ return field;
948+ }
949+ }
950+
951+ // Get it from the super class
952+ // It is likely that 'getSuperClass()' could be made to work here
953+ // but we would have to assure somehow that 'resolveTypeStructure'
954+ // has been called on the current class nest. Since we can get
955+ // here from 'resolveName', which is called from 'resolveSupers',
956+ // it is possible that the first attempt to resolve the superclass
957+ // will originate here, instead of in the call to 'getSuperClass'
958+ // in 'checkSupers'. See 'resolveTypeStructure', in which a call
959+ // to 'resolveSupers' precedes the call to 'checkSupers'. Why is
960+ // name resolution done twice, first in 'resolveName'?
961+ // NOTE: 'SourceMember.resolveTypeStructure' may initiate type
962+ // structure resolution for an inner class. Normally, this
963+ // occurs during the resolution of the outer class, but fields
964+ // added after the resolution of their containing class will
965+ // be resolved late -- see 'addMember(env,field)' below.
966+ // This should only happen for synthetic members, which should
967+ // never be an inner class.
968+ ClassDeclaration sup = getSuperClass(env);
969+ if (sup != null)
970+ return sup.getClassDefinition(env).getInnerClass(env, nm);
971+
972+ return null;
973+ }
974+
975+ /**
976+ * Lookup a method. This code implements the method lookup
977+ * mechanism specified in JLS 15.11.2.
978+ *
979+ * This mechanism cannot be used to lookup synthetic methods.
980+ */
981+ private MemberDefinition matchMethod(Environment env,
982+ ClassDefinition accessor,
983+ Identifier methodName,
984+ Type[] argumentTypes,
985+ boolean isAnonConstCall,
986+ Identifier accessPackage)
987+ throws AmbiguousMember, ClassNotFound {
988+
989+ if (allMethods == null || !allMethods.isFrozen()) {
990+ // This may be too restrictive.
991+ throw new CompilerError("matchMethod called early");
992+ // collectInheritedMethods(env);
993+ }
994+
995+ // A tentative maximally specific method.
996+ MemberDefinition tentative = null;
997+
998+ // A list of other methods which may be maximally specific too.
999+ List candidateList = null;
1000+
1001+ // Get all the methods inherited by this class which
1002+ // have the name `methodName'.
1003+ Iterator methods = allMethods.lookupName(methodName);
1004+
1005+ while (methods.hasNext()) {
1006+ MemberDefinition method = (MemberDefinition)methods.next();
1007+
1008+ // See if this method is applicable.
1009+ if (!env.isApplicable(method, argumentTypes)) {
1010+ continue;
1011+ }
1012+
1013+ // See if this method is accessible.
1014+ if (accessor != null) {
1015+ if (!accessor.canAccess(env, method)) {
1016+ continue;
1017+ }
1018+ } else if (isAnonConstCall) {
1019+ if (method.isPrivate() ||
1020+ (method.isPackagePrivate() &&
1021+ accessPackage != null &&
1022+ !inSamePackage(accessPackage))) {
1023+ // For anonymous constructor accesses, we
1024+ // haven't yet built an accessing class.
1025+ // We disallow anonymous classes from seeing
1026+ // private/package-private inaccessible
1027+ // constructors in their superclass.
1028+ continue;
1029+ }
1030+ } else {
1031+ // If accessor is null, we assume that the access
1032+ // is allowed. Query: is this option used?
1033+ }
1034+
1035+ if (tentative == null) {
1036+ // `method' becomes our tentative maximally specific match.
1037+ tentative = method;
1038+ } else {
1039+ if (env.isMoreSpecific(method, tentative)) {
1040+ // We have found a method which is a strictly better
1041+ // match than `tentative'. Replace it.
1042+ tentative = method;
1043+ } else {
1044+ // If this method could possibly be another
1045+ // maximally specific method, add it to our
1046+ // list of other candidates.
1047+ if (!env.isMoreSpecific(tentative,method)) {
1048+ if (candidateList == null) {
1049+ candidateList = new ArrayList();
1050+ }
1051+ candidateList.add(method);
1052+ }
1053+ }
1054+ }
1055+ }
1056+
1057+ if (tentative != null && candidateList != null) {
1058+ // Find out if our `tentative' match is a uniquely
1059+ // maximally specific.
1060+ Iterator candidates = candidateList.iterator();
1061+ while (candidates.hasNext()) {
1062+ MemberDefinition method = (MemberDefinition)candidates.next();
1063+ if (!env.isMoreSpecific(tentative, method)) {
1064+ throw new AmbiguousMember(tentative, method);
1065+ }
1066+ }
1067+ }
1068+
1069+ return tentative;
1070+ }
1071+
1072+ /**
1073+ * Lookup a method. This code implements the method lookup
1074+ * mechanism specified in JLS 15.11.2.
1075+ *
1076+ * This mechanism cannot be used to lookup synthetic methods.
1077+ */
1078+ public MemberDefinition matchMethod(Environment env,
1079+ ClassDefinition accessor,
1080+ Identifier methodName,
1081+ Type[] argumentTypes)
1082+ throws AmbiguousMember, ClassNotFound {
1083+
1084+ return matchMethod(env, accessor, methodName,
1085+ argumentTypes, false, null);
1086+ }
1087+
1088+ /**
1089+ * Lookup a method. This code implements the method lookup
1090+ * mechanism specified in JLS 15.11.2.
1091+ *
1092+ * This mechanism cannot be used to lookup synthetic methods.
1093+ */
1094+ public MemberDefinition matchMethod(Environment env,
1095+ ClassDefinition accessor,
1096+ Identifier methodName)
1097+ throws AmbiguousMember, ClassNotFound {
1098+
1099+ return matchMethod(env, accessor, methodName,
1100+ Type.noArgs, false, null);
1101+ }
1102+
1103+ /**
1104+ * A version of matchMethod to be used only for constructors
1105+ * when we cannot pass in a sourceClass argument. We just assert
1106+ * our package name.
1107+ *
1108+ * This is used only for anonymous classes, where we have to look up
1109+ * a (potentially) protected constructor with no valid sourceClass
1110+ * parameter available.
1111+ */
1112+ public MemberDefinition matchAnonConstructor(Environment env,
1113+ Identifier accessPackage,
1114+ Type argumentTypes[])
1115+ throws AmbiguousMember, ClassNotFound {
1116+
1117+ return matchMethod(env, null, idInit, argumentTypes,
1118+ true, accessPackage);
1119+ }
1120+
1121+ /**
1122+ * Find a method, ie: exact match in this class or any of the super
1123+ * classes.
1124+ *
1125+ * Only called by javadoc. For now I am holding off rewriting this
1126+ * code to rely on collectInheritedMethods(), as that code has
1127+ * not gotten along with javadoc in the past.
1128+ */
1129+ public MemberDefinition findMethod(Environment env, Identifier nm, Type t)
1130+ throws ClassNotFound {
1131+ // look in the current class
1132+ MemberDefinition f;
1133+ for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {
1134+ // Note that non-method types return false for equalArguments().
1135+ if (f.getType().equalArguments(t)) {
1136+ return f;
1137+ }
1138+ }
1139+
1140+ // constructors are not inherited
1141+ if (nm.equals(idInit)) {
1142+ return null;
1143+ }
1144+
1145+ // look in the super class
1146+ ClassDeclaration sup = getSuperClass();
1147+ if (sup == null)
1148+ return null;
1149+
1150+ return sup.getClassDefinition(env).findMethod(env, nm, t);
1151+ }
1152+
1153+ // We create a stub for this. Source classes do more work.
1154+ protected void basicCheck(Environment env) throws ClassNotFound {
1155+ // Do the outer class first.
1156+ if (outerClass != null)
1157+ outerClass.basicCheck(env);
1158+ }
1159+
1160+ /**
1161+ * Check this class.
1162+ */
1163+ public void check(Environment env) throws ClassNotFound {
1164+ }
1165+
1166+ public Vset checkLocalClass(Environment env, Context ctx,
1167+ Vset vset, ClassDefinition sup,
1168+ Expression args[], Type argTypes[]
1169+ ) throws ClassNotFound {
1170+ throw new CompilerError("checkLocalClass");
1171+ }
1172+
1173+ //---------------------------------------------------------------
1174+ // The non-synthetic methods defined in this class or in any
1175+ // of its parents (class or interface). This member is used
1176+ // to cache work done in collectInheritedMethods for use by
1177+ // getMethods() and matchMethod(). It should be accessed by
1178+ // no other method without forethought.
1179+ MethodSet allMethods = null;
1180+
1181+ // One of our superclasses may contain an abstract method which
1182+ // we are unable to ever implement. This happens when there is
1183+ // a package-private abstract method in our parent and we are in
1184+ // a different package than our parent. In these cases, we
1185+ // keep a list of the "permanently abstract" or "unimplementable"
1186+ // methods so that we can correctly detect that this class is
1187+ // indeed abstract and so that we can give somewhat comprehensible
1188+ // error messages.
1189+ private List permanentlyAbstractMethods = new ArrayList();
1190+
1191+ /**
1192+ * This method returns an Iterator of all abstract methods
1193+ * in our superclasses which we are unable to implement.
1194+ */
1195+ protected Iterator getPermanentlyAbstractMethods() {
1196+ // This method can only be called after collectInheritedMethods.
1197+ if (allMethods == null) {
1198+ throw new CompilerError("isPermanentlyAbstract() called early");
1199+ }
1200+
1201+ return permanentlyAbstractMethods.iterator();
1202+ }
1203+
1204+ /**
1205+ * A flag used by turnOffInheritanceChecks() to indicate if
1206+ * inheritance checks are on or off.
1207+ */
1208+ protected static boolean doInheritanceChecks = true;
1209+
1210+ /**
1211+ * This is a workaround to allow javadoc to turn off certain
1212+ * inheritance/override checks which interfere with javadoc
1213+ * badly. In the future it might be good to eliminate the
1214+ * shared sources of javadoc and javac to avoid the need for this
1215+ * sort of workaround.
1216+ */
1217+ public static void turnOffInheritanceChecks() {
1218+ doInheritanceChecks = false;
1219+ }
1220+
1221+ /**
1222+ * Add all of the methods declared in or above `parent' to
1223+ * `allMethods', the set of methods in the current class.
1224+ * `myMethods' is the set of all methods declared in this
1225+ * class, and `mirandaMethods' is a repository for Miranda methods.
1226+ * If mirandaMethods is null, no mirandaMethods will be
1227+ * generated.
1228+ *
1229+ * For a definition of Miranda methods, see the comment above the
1230+ * method addMirandaMethods() which occurs later in this file.
1231+ */
1232+ private void collectOneClass(Environment env,
1233+ ClassDeclaration parent,
1234+ MethodSet myMethods,
1235+ MethodSet allMethods,
1236+ MethodSet mirandaMethods) {
1237+
1238+ // System.out.println("Inheriting methods from " + parent);
1239+
1240+ try {
1241+ ClassDefinition pClass = parent.getClassDefinition(env);
1242+ Iterator methods = pClass.getMethods(env);
1243+ while (methods.hasNext()) {
1244+ MemberDefinition method =
1245+ (MemberDefinition) methods.next();
1246+
1247+ // Private methods are not inherited.
1248+ //
1249+ // Constructors are not inherited.
1250+ //
1251+ // Any non-abstract methods in an interface come
1252+ // from java.lang.Object. This means that they
1253+ // should have already been added to allMethods
1254+ // when we walked our superclass lineage.
1255+ if (method.isPrivate() ||
1256+ method.isConstructor() ||
1257+ (pClass.isInterface() && !method.isAbstract())) {
1258+
1259+ continue;
1260+ }
1261+
1262+ // Get the components of the methods' signature.
1263+ Identifier name = method.getName();
1264+ Type type = method.getType();
1265+
1266+ // Check for a method of the same signature which
1267+ // was locally declared.
1268+ MemberDefinition override =
1269+ myMethods.lookupSig(name, type);
1270+
1271+ // Is this method inaccessible due to package-private
1272+ // visibility?
1273+ if (method.isPackagePrivate() &&
1274+ !inSamePackage(method.getClassDeclaration())) {
1275+
1276+ if (override != null && this instanceof
1277+ sun.tools.javac.SourceClass) {
1278+ // We give a warning when a class shadows an
1279+ // inaccessible package-private method from
1280+ // its superclass. This warning is meant
1281+ // to prevent people from relying on overriding
1282+ // when it does not happen. This warning should
1283+ // probably be removed to be consistent with the
1284+ // general "no warnings" policy of this
1285+ // compiler.
1286+ //
1287+ // The `instanceof' above is a hack so that only
1288+ // SourceClass generates this warning, not a
1289+ // BinaryClass, for example.
1290+ env.error(method.getWhere(),
1291+ "warn.no.override.access",
1292+ override,
1293+ override.getClassDeclaration(),
1294+ method.getClassDeclaration());
1295+ }
1296+
1297+ // If our superclass has a package-private abstract
1298+ // method that we have no access to, then we add
1299+ // this method to our list of permanently abstract
1300+ // methods. The idea is, since we cannot override
1301+ // the method, we can never make this class
1302+ // non-abstract.
1303+ if (method.isAbstract()) {
1304+ permanentlyAbstractMethods.add(method);
1305+ }
1306+
1307+ // `method' is inaccessible. We do not inherit it.
1308+ continue;
1309+ }
1310+
1311+ if (override != null) {
1312+ // `method' and `override' have the same signature.
1313+ // We are required to check that `override' is a
1314+ // legal override of `method'
1315+
1316+ //System.out.println ("About to check override of " +
1317+ // method);
1318+
1319+ override.checkOverride(env, method);
1320+ } else {
1321+ // In the absence of a definition in the class
1322+ // itself, we check to see if this definition
1323+ // can be successfully merged with any other
1324+ // inherited definitions.
1325+
1326+ // Have we added a member of the same signature
1327+ // to `allMethods' already?
1328+ MemberDefinition formerMethod =
1329+ allMethods.lookupSig(name, type);
1330+
1331+ // If the previous definition is nonexistent or
1332+ // ignorable, replace it.
1333+ if (formerMethod == null) {
1334+ //System.out.println("Added " + method + " to " +
1335+ // this);
1336+
1337+ if (mirandaMethods != null &&
1338+ pClass.isInterface() && !isInterface()) {
1339+ // Whenever a class inherits a method
1340+ // from an interface, that method is
1341+ // one of our "miranda" methods. Early
1342+ // VMs require that these methods be
1343+ // added as true members to the class
1344+ // to enable method lookup to work in the
1345+ // VM.
1346+ method =
1347+ new sun.tools.javac.SourceMember(method,this,
1348+ env);
1349+ mirandaMethods.add(method);
1350+
1351+ //System.out.println("Added " + method +
1352+ // " to " + this + " as a Miranda");
1353+ }
1354+
1355+ // There is no previous inherited definition.
1356+ // Add `method' to `allMethods'.
1357+ allMethods.add(method);
1358+ } else if (isInterface() &&
1359+ !formerMethod.isAbstract() &&
1360+ method.isAbstract()) {
1361+ // If we are in an interface and we have inherited
1362+ // both an abstract method and a non-abstract method
1363+ // then we know that the non-abstract method is
1364+ // a placeholder from Object put in for type checking
1365+ // and the abstract method was already checked to
1366+ // be proper by our superinterface.
1367+ allMethods.replace(method);
1368+
1369+ } else {
1370+ // Okay, `formerMethod' and `method' both have the
1371+ // same signature. See if they are compatible.
1372+
1373+ //System.out.println ("About to check meet of " +
1374+ // method);
1375+
1376+ if (!formerMethod.checkMeet(env,
1377+ method,
1378+ this.getClassDeclaration())) {
1379+ // The methods are incompatible. Skip to
1380+ // next method.
1381+ continue;
1382+ }
1383+
1384+ if (formerMethod.couldOverride(env, method)) {
1385+ // Do nothing. The current definition
1386+ // is specific enough.
1387+
1388+ //System.out.println("trivial meet of " +
1389+ // method);
1390+ continue;
1391+ }
1392+
1393+ if (method.couldOverride(env, formerMethod)) {
1394+ // `method' is more specific than
1395+ // `formerMethod'. replace `formerMethod'.
1396+
1397+ //System.out.println("new def of " + method);
1398+ if (mirandaMethods != null &&
1399+ pClass.isInterface() && !isInterface()) {
1400+ // Whenever a class inherits a method
1401+ // from an interface, that method is
1402+ // one of our "miranda" methods. Early
1403+ // VMs require that these methods be
1404+ // added as true members to the class
1405+ // to enable method lookup to work in the
1406+ // VM.
1407+ method =
1408+ new sun.tools.javac.SourceMember(method,
1409+ this,env);
1410+
1411+ mirandaMethods.replace(method);
1412+
1413+ //System.out.println("Added " + method +
1414+ // " to " + this + " as a Miranda");
1415+ }
1416+
1417+ allMethods.replace(method);
1418+
1419+ continue;
1420+ }
1421+
1422+ // Neither method is more specific than the other.
1423+ // Oh well. We need to construct a nontrivial
1424+ // meet of the two methods.
1425+ //
1426+ // This is not yet implemented, so we give
1427+ // a message with a helpful workaround.
1428+ env.error(this.where,
1429+ "nontrivial.meet", method,
1430+ formerMethod.getClassDefinition(),
1431+ method.getClassDeclaration()
1432+ );
1433+ }
1434+ }
1435+ }
1436+ } catch (ClassNotFound ee) {
1437+ env.error(getWhere(), "class.not.found", ee.name, this);
1438+ }
1439+ }
1440+
1441+ /**
1442+ * <p>Collect all methods defined in this class or inherited from
1443+ * any of our superclasses or interfaces. Look for any
1444+ * incompatible definitions.
1445+ *
1446+ * <p>This function is also responsible for collecting the
1447+ * <em>Miranda</em> methods for a class. For a definition of
1448+ * Miranda methods, see the comment in addMirandaMethods()
1449+ * below.
1450+ */
1451+ protected void collectInheritedMethods(Environment env) {
1452+ // The methods defined in this class.
1453+ MethodSet myMethods;
1454+ MethodSet mirandaMethods;
1455+
1456+ //System.out.println("Called collectInheritedMethods() for " +
1457+ // this);
1458+
1459+ if (allMethods != null) {
1460+ if (allMethods.isFrozen()) {
1461+ // We have already done the collection. No need to
1462+ // do it again.
1463+ return;
1464+ } else {
1465+ // We have run into a circular need to collect our methods.
1466+ // This should not happen at this stage.
1467+ throw new CompilerError("collectInheritedMethods()");
1468+ }
1469+ }
1470+
1471+ myMethods = new MethodSet();
1472+ allMethods = new MethodSet();
1473+
1474+ // For testing, do not generate miranda methods.
1475+ if (env.version12()) {
1476+ mirandaMethods = null;
1477+ } else {
1478+ mirandaMethods = new MethodSet();
1479+ }
1480+
1481+ // Any methods defined in the current class get added
1482+ // to both the myMethods and the allMethods MethodSets.
1483+
1484+ for (MemberDefinition member = getFirstMember();
1485+ member != null;
1486+ member = member.nextMember) {
1487+
1488+ // We only collect methods. Initializers are not relevant.
1489+ if (member.isMethod() &&
1490+ !member.isInitializer()) {
1491+
1492+ //System.out.println("Declared in " + this + ", " + member);
1493+
1494+ ////////////////////////////////////////////////////////////
1495+ // PCJ 2003-07-30 modified the following code because with
1496+ // the covariant return type feature of the 1.5 compiler,
1497+ // there might be multiple methods with the same signature
1498+ // but different return types, and MethodSet doesn't
1499+ // support that. We use a new utility method that attempts
1500+ // to ensure that the appropriate method winds up in the
1501+ // MethodSet. See 4892308.
1502+ ////////////////////////////////////////////////////////////
1503+ // myMethods.add(member);
1504+ // allMethods.add(member);
1505+ ////////////////////////////////////////////////////////////
1506+ methodSetAdd(env, myMethods, member);
1507+ methodSetAdd(env, allMethods, member);
1508+ ////////////////////////////////////////////////////////////
1509+ }
1510+ }
1511+
1512+ // We're ready to start adding inherited methods. First add
1513+ // the methods from our superclass.
1514+
1515+ //System.out.println("About to start superclasses for " + this);
1516+
1517+ ClassDeclaration scDecl = getSuperClass(env);
1518+ if (scDecl != null) {
1519+ collectOneClass(env, scDecl,
1520+ myMethods, allMethods, mirandaMethods);
1521+
1522+ // Make sure that we add all unimplementable methods from our
1523+ // superclass to our list of unimplementable methods.
1524+ ClassDefinition sc = scDecl.getClassDefinition();
1525+ Iterator supIter = sc.getPermanentlyAbstractMethods();
1526+ while (supIter.hasNext()) {
1527+ permanentlyAbstractMethods.add(supIter.next());
1528+ }
1529+ }
1530+
1531+ // Now we inherit all of the methods from our interfaces.
1532+
1533+ //System.out.println("About to start interfaces for " + this);
1534+
1535+ for (int i = 0; i < interfaces.length; i++) {
1536+ collectOneClass(env, interfaces[i],
1537+ myMethods, allMethods, mirandaMethods);
1538+ }
1539+ allMethods.freeze();
1540+
1541+ // Now we have collected all of our methods from our superclasses
1542+ // and interfaces into our `allMethods' member. Good. As a last
1543+ // task, we add our collected miranda methods to this class.
1544+ //
1545+ // If we do not add the mirandas to the class explicitly, there
1546+ // will be no code generated for them.
1547+ if (mirandaMethods != null && mirandaMethods.size() > 0) {
1548+ addMirandaMethods(env, mirandaMethods.iterator());
1549+ }
1550+ }
1551+
1552+ ////////////////////////////////////////////////////////////
1553+ // PCJ 2003-07-30 added this utility method to insulate
1554+ // MethodSet additions from the covariant return type
1555+ // feature of the 1.5 compiler. When there are multiple
1556+ // methods with the same signature and different return
1557+ // types to be added, we try to ensure that the one with
1558+ // the most specific return type winds up in the MethodSet.
1559+ // This logic was not put into MethodSet itself because it
1560+ // requires access to an Environment for type relationship
1561+ // checking. No error checking is performed here, but that
1562+ // should be OK because this code is only still used by
1563+ // rmic. See 4892308.
1564+ ////////////////////////////////////////////////////////////
1565+ private static void methodSetAdd(Environment env,
1566+ MethodSet methodSet,
1567+ MemberDefinition newMethod)
1568+ {
1569+ MemberDefinition oldMethod = methodSet.lookupSig(newMethod.getName(),
1570+ newMethod.getType());
1571+ if (oldMethod != null) {
1572+ Type oldReturnType = oldMethod.getType().getReturnType();
1573+ Type newReturnType = newMethod.getType().getReturnType();
1574+ try {
1575+ if (env.isMoreSpecific(newReturnType, oldReturnType)) {
1576+ methodSet.replace(newMethod);
1577+ }
1578+ } catch (ClassNotFound ignore) {
1579+ }
1580+ } else {
1581+ methodSet.add(newMethod);
1582+ }
1583+ }
1584+ ////////////////////////////////////////////////////////////
1585+
1586+ /**
1587+ * Get an Iterator of all methods which could be accessed in an
1588+ * instance of this class.
1589+ */
1590+ public Iterator getMethods(Environment env) {
1591+ if (allMethods == null) {
1592+ collectInheritedMethods(env);
1593+ }
1594+ return getMethods();
1595+ }
1596+
1597+ /**
1598+ * Get an Iterator of all methods which could be accessed in an
1599+ * instance of this class. Throw a compiler error if we haven't
1600+ * generated this information yet.
1601+ */
1602+ public Iterator getMethods() {
1603+ if (allMethods == null) {
1604+ throw new CompilerError("getMethods: too early");
1605+ }
1606+ return allMethods.iterator();
1607+ }
1608+
1609+ // In early VM's there was a bug -- the VM didn't walk the interfaces
1610+ // of a class looking for a method, they only walked the superclass
1611+ // chain. This meant that abstract methods defined only in interfaces
1612+ // were not being found. To fix this bug, a counter-bug was introduced
1613+ // in the compiler -- the so-called Miranda methods. If a class
1614+ // does not provide a definition for an abstract method in one of
1615+ // its interfaces then the compiler inserts one in the class artificially.
1616+ // That way the VM didn't have to bother looking at the interfaces.
1617+ //
1618+ // This is a problem. Miranda methods are not part of the specification.
1619+ // But they continue to be inserted so that old VM's can run new code.
1620+ // Someday, when the old VM's are gone, perhaps classes can be compiled
1621+ // without Miranda methods. Towards this end, the compiler has a
1622+ // flag, -nomiranda, which can turn off the creation of these methods.
1623+ // Eventually that behavior should become the default.
1624+ //
1625+ // Why are they called Miranda methods? Well the sentence "If the
1626+ // class is not able to provide a method, then one will be provided
1627+ // by the compiler" is very similar to the sentence "If you cannot
1628+ // afford an attorney, one will be provided by the court," -- one
1629+ // of the so-called "Miranda" rights in the United States.
1630+
1631+ /**
1632+ * Add a list of methods to this class as miranda methods. This
1633+ * gets overridden with a meaningful implementation in SourceClass.
1634+ * BinaryClass should not need to do anything -- it should already
1635+ * have its miranda methods and, if it doesn't, then that doesn't
1636+ * affect our compilation.
1637+ */
1638+ protected void addMirandaMethods(Environment env,
1639+ Iterator mirandas) {
1640+ // do nothing.
1641+ }
1642+
1643+ //---------------------------------------------------------------
1644+
1645+ public void inlineLocalClass(Environment env) {
1646+ }
1647+
1648+ /**
1649+ * We create a stub for this. Source classes do more work.
1650+ * Some calls from 'SourceClass.checkSupers' execute this method.
1651+ * @see sun.tools.javac.SourceClass#resolveTypeStructure
1652+ */
1653+
1654+ public void resolveTypeStructure(Environment env) {
1655+ }
1656+
1657+ /**
1658+ * Look up an inner class name, from somewhere inside this class.
1659+ * Since supers and outers are in scope, search them too.
1660+ * <p>
1661+ * If no inner class is found, env.resolveName() is then called,
1662+ * to interpret the ambient package and import directives.
1663+ * <p>
1664+ * This routine operates on a "best-efforts" basis. If
1665+ * at some point a class is not found, the partially-resolved
1666+ * identifier is returned. Eventually, someone else has to
1667+ * try to get the ClassDefinition and diagnose the ClassNotFound.
1668+ * <p>
1669+ * resolveName() looks at surrounding scopes, and hence
1670+ * pulling in both inherited and uplevel types. By contrast,
1671+ * resolveInnerClass() is intended only for interpreting
1672+ * explicitly qualified names, and so look only at inherited
1673+ * types. Also, resolveName() looks for package prefixes,
1674+ * which appear similar to "very uplevel" outer classes.
1675+ * <p>
1676+ * A similar (but more complex) name-lookup process happens
1677+ * when field and identifier expressions denoting qualified names
1678+ * are type-checked. The added complexity comes from the fact
1679+ * that variables may occur in such names, and take precedence
1680+ * over class and package names.
1681+ * <p>
1682+ * In the expression type-checker, resolveInnerClass() is paralleled
1683+ * by code in FieldExpression.checkAmbigName(), which also calls
1684+ * ClassDefinition.getInnerClass() to interpret names of the form
1685+ * "OuterClass.Inner" (and also outerObject.Inner). The checking
1686+ * of an identifier expression that fails to be a variable is referred
1687+ * directly to resolveName().
1688+ */
1689+ public Identifier resolveName(Environment env, Identifier name) {
1690+ if (tracing) env.dtEvent("ClassDefinition.resolveName: " + name);
1691+ // This logic is pretty much exactly parallel to that of
1692+ // Environment.resolveName().
1693+ if (name.isQualified()) {
1694+ // Try to resolve the first identifier component,
1695+ // because inner class names take precedence over
1696+ // package prefixes. (Cf. Environment.resolveName.)
1697+ Identifier rhead = resolveName(env, name.getHead());
1698+
1699+ if (rhead.hasAmbigPrefix()) {
1700+ // The first identifier component refers to an
1701+ // ambiguous class. Limp on. We throw away the
1702+ // rest of the classname as it is irrelevant.
1703+ // (part of solution for 4059855).
1704+ return rhead;
1705+ }
1706+
1707+ if (!env.classExists(rhead)) {
1708+ return env.resolvePackageQualifiedName(name);
1709+ }
1710+ try {
1711+ return env.getClassDefinition(rhead).
1712+ resolveInnerClass(env, name.getTail());
1713+ } catch (ClassNotFound ee) {
1714+ // return partially-resolved name someone else can fail on
1715+ return Identifier.lookupInner(rhead, name.getTail());
1716+ }
1717+ }
1718+
1719+ // This method used to fail to look for local classes, thus a
1720+ // reference to a local class within, e.g., the type of a member
1721+ // declaration, would fail to resolve if the immediately enclosing
1722+ // context was an inner class. The code added below is ugly, but
1723+ // it works, and is lifted from existing code in 'Context.resolveName'
1724+ // and 'Context.getClassCommon'. See the comments there about the design.
1725+ // Fixes 4095716.
1726+
1727+ int ls = -2;
1728+ LocalMember lf = null;
1729+ if (classContext != null) {
1730+ lf = classContext.getLocalClass(name);
1731+ if (lf != null) {
1732+ ls = lf.getScopeNumber();
1733+ }
1734+ }
1735+
1736+ // Look for an unqualified name in enclosing scopes.
1737+ for (ClassDefinition c = this; c != null; c = c.outerClass) {
1738+ try {
1739+ MemberDefinition f = c.getInnerClass(env, name);
1740+ if (f != null &&
1741+ (lf == null || classContext.getScopeNumber(c) > ls)) {
1742+ // An uplevel member was found, and was nested more deeply than
1743+ // any enclosing local of the same name.
1744+ return f.getInnerClass().getName();
1745+ }
1746+ } catch (ClassNotFound ee) {
1747+ // a missing superclass, or something catastrophic
1748+ }
1749+ }
1750+
1751+ // No uplevel member found, so use the enclosing local if one was found.
1752+ if (lf != null) {
1753+ return lf.getInnerClass().getName();
1754+ }
1755+
1756+ // look in imports, etc.
1757+ return env.resolveName(name);
1758+ }
1759+
1760+ /**
1761+ * Interpret a qualified class name, which may have further subcomponents..
1762+ * Follow inheritance links, as in:
1763+ * class C { class N { } } class D extends C { } ... new D.N() ...
1764+ * Ignore outer scopes and packages.
1765+ * @see resolveName
1766+ */
1767+ public Identifier resolveInnerClass(Environment env, Identifier nm) {
1768+ if (nm.isInner()) throw new CompilerError("inner");
1769+ if (nm.isQualified()) {
1770+ Identifier rhead = resolveInnerClass(env, nm.getHead());
1771+ try {
1772+ return env.getClassDefinition(rhead).
1773+ resolveInnerClass(env, nm.getTail());
1774+ } catch (ClassNotFound ee) {
1775+ // return partially-resolved name someone else can fail on
1776+ return Identifier.lookupInner(rhead, nm.getTail());
1777+ }
1778+ } else {
1779+ try {
1780+ MemberDefinition f = getInnerClass(env, nm);
1781+ if (f != null) {
1782+ return f.getInnerClass().getName();
1783+ }
1784+ } catch (ClassNotFound ee) {
1785+ // a missing superclass, or something catastrophic
1786+ }
1787+ // Fake a good name for a diagnostic.
1788+ return Identifier.lookupInner(this.getName(), nm);
1789+ }
1790+ }
1791+
1792+ /**
1793+ * While resolving import directives, the question has arisen:
1794+ * does a given inner class exist? If the top-level class exists,
1795+ * we ask it about an inner class via this method.
1796+ * This method looks only at the literal name of the class,
1797+ * and does not attempt to follow inheritance links.
1798+ * This is necessary, since at the time imports are being
1799+ * processed, inheritance links have not been resolved yet.
1800+ * (Thus, an import directive must always spell a class
1801+ * name exactly.)
1802+ */
1803+ public boolean innerClassExists(Identifier nm) {
1804+ for (MemberDefinition field = getFirstMatch(nm.getHead()) ; field != null ; field = field.getNextMatch()) {
1805+ if (field.isInnerClass()) {
1806+ if (field.getInnerClass().isLocal()) {
1807+ continue; // ignore this name; it is internally generated
1808+ }
1809+ return !nm.isQualified() ||
1810+ field.getInnerClass().innerClassExists(nm.getTail());
1811+ }
1812+ }
1813+ return false;
1814+ }
1815+
1816+ /**
1817+ * Find any method with a given name.
1818+ */
1819+ public MemberDefinition findAnyMethod(Environment env, Identifier nm) throws ClassNotFound {
1820+ MemberDefinition f;
1821+ for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {
1822+ if (f.isMethod()) {
1823+ return f;
1824+ }
1825+ }
1826+
1827+ // look in the super class
1828+ ClassDeclaration sup = getSuperClass();
1829+ if (sup == null)
1830+ return null;
1831+ return sup.getClassDefinition(env).findAnyMethod(env, nm);
1832+ }
1833+
1834+ /**
1835+ * Given the fact that this class has no method "nm" matching "argTypes",
1836+ * find out if the mismatch can be blamed on a particular actual argument
1837+ * which disagrees with all of the overloadings.
1838+ * If so, return the code (i<<2)+(castOK<<1)+ambig, where
1839+ * "i" is the number of the offending argument, and
1840+ * "castOK" is 1 if a cast could fix the problem.
1841+ * The target type for the argument is returned in margTypeResult[0].
1842+ * If not all methods agree on this type, "ambig" is 1.
1843+ * If there is more than one method, the choice of target type is
1844+ * arbitrary.<p>
1845+ * Return -1 if every argument is acceptable to at least one method.
1846+ * Return -2 if there are no methods of the required arity.
1847+ * The value "start" gives the index of the first argument to begin
1848+ * checking.
1849+ */
1850+ public int diagnoseMismatch(Environment env, Identifier nm, Type argTypes[],
1851+ int start, Type margTypeResult[]) throws ClassNotFound {
1852+ int haveMatch[] = new int[argTypes.length];
1853+ Type margType[] = new Type[argTypes.length];
1854+ if (!diagnoseMismatch(env, nm, argTypes, start, haveMatch, margType))
1855+ return -2;
1856+ for (int i = start; i < argTypes.length; i++) {
1857+ if (haveMatch[i] < 4) {
1858+ margTypeResult[0] = margType[i];
1859+ return (i<<2) | haveMatch[i];
1860+ }
1861+ }
1862+ return -1;
1863+ }
1864+
1865+ private boolean diagnoseMismatch(Environment env, Identifier nm, Type argTypes[], int start,
1866+ int haveMatch[], Type margType[]) throws ClassNotFound {
1867+ // look in the current class
1868+ boolean haveOne = false;
1869+ MemberDefinition f;
1870+ for (f = getFirstMatch(nm) ; f != null ; f = f.getNextMatch()) {
1871+ if (!f.isMethod()) {
1872+ continue;
1873+ }
1874+ Type fArgTypes[] = f.getType().getArgumentTypes();
1875+ if (fArgTypes.length == argTypes.length) {
1876+ haveOne = true;
1877+ for (int i = start; i < argTypes.length; i++) {
1878+ Type at = argTypes[i];
1879+ Type ft = fArgTypes[i];
1880+ if (env.implicitCast(at, ft)) {
1881+ haveMatch[i] = 4;
1882+ continue;
1883+ } else if (haveMatch[i] <= 2 && env.explicitCast(at, ft)) {
1884+ if (haveMatch[i] < 2) margType[i] = null;
1885+ haveMatch[i] = 2;
1886+ } else if (haveMatch[i] > 0) {
1887+ continue;
1888+ }
1889+ if (margType[i] == null)
1890+ margType[i] = ft;
1891+ else if (margType[i] != ft)
1892+ haveMatch[i] |= 1;
1893+ }
1894+ }
1895+ }
1896+
1897+ // constructors are not inherited
1898+ if (nm.equals(idInit)) {
1899+ return haveOne;
1900+ }
1901+
1902+ // look in the super class
1903+ ClassDeclaration sup = getSuperClass();
1904+ if (sup != null) {
1905+ if (sup.getClassDefinition(env).diagnoseMismatch(env, nm, argTypes, start,
1906+ haveMatch, margType))
1907+ haveOne = true;
1908+ }
1909+ return haveOne;
1910+ }
1911+
1912+ /**
1913+ * Add a field (no checks)
1914+ */
1915+ public void addMember(MemberDefinition field) {
1916+ //System.out.println("ADD = " + field);
1917+ if (firstMember == null) {
1918+ firstMember = lastMember = field;
1919+ } else if (field.isSynthetic() && field.isFinal()
1920+ && field.isVariable()) {
1921+ // insert this at the front, because of initialization order
1922+ field.nextMember = firstMember;
1923+ firstMember = field;
1924+ field.nextMatch = (MemberDefinition)fieldHash.get(field.name);
1925+ } else {
1926+ lastMember.nextMember = field;
1927+ lastMember = field;
1928+ field.nextMatch = (MemberDefinition)fieldHash.get(field.name);
1929+ }
1930+ fieldHash.put(field.name, field);
1931+ }
1932+
1933+ /**
1934+ * Add a field (subclasses make checks)
1935+ */
1936+ public void addMember(Environment env, MemberDefinition field) {
1937+ addMember(field);
1938+ if (resolved) {
1939+ // a late addition
1940+ field.resolveTypeStructure(env);
1941+ }
1942+ }
1943+
1944+ /**
1945+ * Find or create an uplevel reference for the given target.
1946+ */
1947+ public UplevelReference getReference(LocalMember target) {
1948+ for (UplevelReference r = references; r != null; r = r.getNext()) {
1949+ if (r.getTarget() == target) {
1950+ return r;
1951+ }
1952+ }
1953+ return addReference(target);
1954+ }
1955+
1956+ protected UplevelReference addReference(LocalMember target) {
1957+ if (target.getClassDefinition() == this) {
1958+ throw new CompilerError("addReference "+target);
1959+ }
1960+ referencesMustNotBeFrozen();
1961+ UplevelReference r = new UplevelReference(this, target);
1962+ references = r.insertInto(references);
1963+ return r;
1964+ }
1965+
1966+ /**
1967+ * Return the list of all uplevel references.
1968+ */
1969+ public UplevelReference getReferences() {
1970+ return references;
1971+ }
1972+
1973+ /**
1974+ * Return the same value as getReferences.
1975+ * Also, mark the set of references frozen.
1976+ * After that, it is an error to add new references.
1977+ */
1978+ public UplevelReference getReferencesFrozen() {
1979+ referencesFrozen = true;
1980+ return references;
1981+ }
1982+
1983+ /**
1984+ * assertion check
1985+ */
1986+ public final void referencesMustNotBeFrozen() {
1987+ if (referencesFrozen) {
1988+ throw new CompilerError("referencesMustNotBeFrozen "+this);
1989+ }
1990+ }
1991+
1992+ /**
1993+ * Get helper method for class literal lookup.
1994+ */
1995+ public MemberDefinition getClassLiteralLookup(long fwhere) {
1996+ throw new CompilerError("binary class");
1997+ }
1998+
1999+ /**
2000+ * Add a dependency
2001+ */
2002+ public void addDependency(ClassDeclaration c) {
2003+ throw new CompilerError("addDependency");
2004+ }
2005+
2006+ /**
2007+ * Maintain a hash table of local and anonymous classes
2008+ * whose internal names are prefixed by the current class.
2009+ * The key is the simple internal name, less the prefix.
2010+ */
2011+
2012+ public ClassDefinition getLocalClass(String name) {
2013+ if (localClasses == null) {
2014+ return null;
2015+ } else {
2016+ return (ClassDefinition)localClasses.get(name);
2017+ }
2018+ }
2019+
2020+ public void addLocalClass(ClassDefinition c, String name) {
2021+ if (localClasses == null) {
2022+ localClasses = new Hashtable(LOCAL_CLASSES_SIZE);
2023+ }
2024+ localClasses.put(name, c);
2025+ }
2026+
2027+
2028+ /**
2029+ * Print for debugging
2030+ */
2031+ public void print(PrintStream out) {
2032+ if (isPublic()) {
2033+ out.print("public ");
2034+ }
2035+ if (isInterface()) {
2036+ out.print("interface ");
2037+ } else {
2038+ out.print("class ");
2039+ }
2040+ out.print(getName() + " ");
2041+ if (getSuperClass() != null) {
2042+ out.print("extends " + getSuperClass().getName() + " ");
2043+ }
2044+ if (interfaces.length > 0) {
2045+ out.print("implements ");
2046+ for (int i = 0 ; i < interfaces.length ; i++) {
2047+ if (i > 0) {
2048+ out.print(", ");
2049+ }
2050+ out.print(interfaces[i].getName());
2051+ out.print(" ");
2052+ }
2053+ }
2054+ out.println("{");
2055+
2056+ for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) {
2057+ out.print(" ");
2058+ f.print(out);
2059+ }
2060+
2061+ out.println("}");
2062+ }
2063+
2064+ /**
2065+ * Convert to String
2066+ */
2067+ public String toString() {
2068+ return getClassDeclaration().toString();
2069+ }
2070+
2071+ /**
2072+ * After the class has been written to disk, try to free up
2073+ * some storage.
2074+ */
2075+ public void cleanup(Environment env) {
2076+ if (env.dump()) {
2077+ env.output("[cleanup " + getName() + "]");
2078+ }
2079+ for (MemberDefinition f = getFirstMember() ; f != null ; f = f.getNextMember()) {
2080+ f.cleanup(env);
2081+ }
2082+ // keep "references" around, for the sake of local subclasses
2083+ documentation = null;
2084+ }
2085+}
java/pkg/sun/tools/java/ClassFile.java+162−0
@@ -0,0 +1,162 @@
1+/*
2+ * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.io.File;
29+import java.io.InputStream;
30+import java.io.FileInputStream;
31+import java.io.IOException;
32+import java.util.zip.*;
33+
34+/**
35+ * This class is used to represent a file loaded from the class path, and
36+ * can either be a regular file or a zip file entry.
37+ *
38+ * WARNING: The contents of this source file are not part of any
39+ * supported API. Code that depends on them does so at its own risk:
40+ * they are subject to change or removal without notice.
41+ */
42+public
43+class ClassFile {
44+ /*
45+ * Non-null if this represents a regular file
46+ */
47+ private File file;
48+
49+ /*
50+ * Non-null if this represents a zip file entry
51+ */
52+ private ZipFile zipFile;
53+ private ZipEntry zipEntry;
54+
55+ /**
56+ * Constructor for instance representing a regular file
57+ */
58+ public ClassFile(File file) {
59+ this.file = file;
60+ }
61+
62+ /**
63+ * Constructor for instance representing a zip file entry
64+ */
65+ public ClassFile(ZipFile zf, ZipEntry ze) {
66+ this.zipFile = zf;
67+ this.zipEntry = ze;
68+ }
69+
70+ /**
71+ * Returns true if this is zip file entry
72+ */
73+ public boolean isZipped() {
74+ return zipFile != null;
75+ }
76+
77+ /**
78+ * Returns input stream to either regular file or zip file entry
79+ */
80+ public InputStream getInputStream() throws IOException {
81+ if (file != null) {
82+ return new FileInputStream(file);
83+ } else {
84+ try {
85+ return zipFile.getInputStream(zipEntry);
86+ } catch (ZipException e) {
87+ throw new IOException(e.getMessage());
88+ }
89+ }
90+ }
91+
92+ /**
93+ * Returns true if file exists.
94+ */
95+ public boolean exists() {
96+ return file != null ? file.exists() : true;
97+ }
98+
99+ /**
100+ * Returns true if this is a directory.
101+ */
102+ public boolean isDirectory() {
103+ return file != null ? file.isDirectory() :
104+ zipEntry.getName().endsWith("/");
105+ }
106+
107+ /**
108+ * Return last modification time
109+ */
110+ public long lastModified() {
111+ return file != null ? file.lastModified() : zipEntry.getTime();
112+ }
113+
114+ /**
115+ * Get file path. The path for a zip file entry will also include
116+ * the zip file name.
117+ */
118+ public String getPath() {
119+ if (file != null) {
120+ return file.getPath();
121+ } else {
122+ return zipFile.getName() + "(" + zipEntry.getName() + ")";
123+ }
124+ }
125+
126+ /**
127+ * Get name of file entry excluding directory name
128+ */
129+ public String getName() {
130+ return file != null ? file.getName() : zipEntry.getName();
131+ }
132+
133+//JCOV
134+ /**
135+ * Get absolute name of file entry
136+ */
137+ public String getAbsoluteName() {
138+ String absoluteName;
139+ if (file != null) {
140+ try {
141+ absoluteName = file.getCanonicalPath();
142+ } catch (IOException e) {
143+ absoluteName = file.getAbsolutePath();
144+ }
145+ } else {
146+ absoluteName = zipFile.getName() + "(" + zipEntry.getName() + ")";
147+ }
148+ return absoluteName;
149+ }
150+// end JCOV
151+
152+ /**
153+ * Get length of file
154+ */
155+ public long length() {
156+ return file != null ? file.length() : zipEntry.getSize();
157+ }
158+
159+ public String toString() {
160+ return (file != null) ? file.toString() : zipEntry.toString();
161+ }
162+}
java/pkg/sun/tools/java/ClassNotFound.java+50−0
@@ -0,0 +1,50 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+/**
29+ * This exception is thrown when a class definition is needed
30+ * and the class can't be found.
31+ *
32+ * WARNING: The contents of this source file are not part of any
33+ * supported API. Code that depends on them does so at its own risk:
34+ * they are subject to change or removal without notice.
35+ */
36+public
37+class ClassNotFound extends Exception {
38+ /**
39+ * The class that was not found
40+ */
41+ public Identifier name;
42+
43+ /**
44+ * Create a ClassNotFound exception
45+ */
46+ public ClassNotFound(Identifier nm) {
47+ super(nm.toString());
48+ name = nm;
49+ }
50+}
java/pkg/sun/tools/java/ClassPath.java+314−0
@@ -0,0 +1,314 @@
1+/*
2+ * Copyright (c) 1994, 2007, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.util.Enumeration;
29+import java.util.Hashtable;
30+import java.io.File;
31+import java.io.IOException;
32+import java.util.zip.*;
33+
34+/**
35+ * This class is used to represent a class path, which can contain both
36+ * directories and zip files.
37+ *
38+ * WARNING: The contents of this source file are not part of any
39+ * supported API. Code that depends on them does so at its own risk:
40+ * they are subject to change or removal without notice.
41+ */
42+public
43+class ClassPath {
44+ static final char dirSeparator = File.pathSeparatorChar;
45+
46+ /**
47+ * The original class path string
48+ */
49+ String pathstr;
50+
51+ /**
52+ * List of class path entries
53+ */
54+ private ClassPathEntry[] path;
55+
56+ /**
57+ * Build a class path from the specified path string
58+ */
59+ public ClassPath(String pathstr) {
60+ init(pathstr);
61+ }
62+
63+ /**
64+ * Build a class path from the specified array of class path
65+ * element strings. This constructor, and the corresponding
66+ * "init" method, were added as part of the fix for 6473331, which
67+ * adds support for Class-Path manifest entries in JAR files to
68+ * rmic. It is conceivable that the value of a Class-Path
69+ * manifest entry will contain a path separator, which would cause
70+ * incorrect behavior if the expanded path were passed to the
71+ * previous constructor as a single path-separator-delimited
72+ * string; use of this constructor avoids that problem.
73+ */
74+ public ClassPath(String[] patharray) {
75+ init(patharray);
76+ }
77+
78+ /**
79+ * Build a default class path from the path strings specified by
80+ * the properties sun.boot.class.path and env.class.path, in that
81+ * order.
82+ */
83+ public ClassPath() {
84+ String syscp = System.getProperty("sun.boot.class.path");
85+ String envcp = System.getProperty("env.class.path");
86+ if (envcp == null) envcp = ".";
87+ String cp = syscp + File.pathSeparator + envcp;
88+ init(cp);
89+ }
90+
91+ private void init(String pathstr) {
92+ int i, j, n;
93+ // Save original class path string
94+ this.pathstr = pathstr;
95+
96+ if (pathstr.length() == 0) {
97+ this.path = new ClassPathEntry[0];
98+ }
99+
100+ // Count the number of path separators
101+ i = n = 0;
102+ while ((i = pathstr.indexOf(dirSeparator, i)) != -1) {
103+ n++; i++;
104+ }
105+ // Build the class path
106+ ClassPathEntry[] path = new ClassPathEntry[n+1];
107+ int len = pathstr.length();
108+ for (i = n = 0; i < len; i = j + 1) {
109+ if ((j = pathstr.indexOf(dirSeparator, i)) == -1) {
110+ j = len;
111+ }
112+ if (i == j) {
113+ path[n] = new ClassPathEntry();
114+ path[n++].dir = new File(".");
115+ } else {
116+ File file = new File(pathstr.substring(i, j));
117+ if (file.isFile()) {
118+ try {
119+ ZipFile zip = new ZipFile(file);
120+ path[n] = new ClassPathEntry();
121+ path[n++].zip = zip;
122+ } catch (ZipException e) {
123+ } catch (IOException e) {
124+ // Ignore exceptions, at least for now...
125+ }
126+ } else {
127+ path[n] = new ClassPathEntry();
128+ path[n++].dir = file;
129+ }
130+ }
131+ }
132+ // Trim class path to exact size
133+ this.path = new ClassPathEntry[n];
134+ System.arraycopy((Object)path, 0, (Object)this.path, 0, n);
135+ }
136+
137+ private void init(String[] patharray) {
138+ // Save original class path string
139+ if (patharray.length == 0) {
140+ this.pathstr = "";
141+ } else {
142+ StringBuilder sb = new StringBuilder(patharray[0]);
143+ for (int i = 1; i < patharray.length; i++) {
144+ sb.append(File.separator);
145+ sb.append(patharray[i]);
146+ }
147+ this.pathstr = sb.toString();
148+ }
149+
150+ // Build the class path
151+ ClassPathEntry[] path = new ClassPathEntry[patharray.length];
152+ int n = 0;
153+ for (String name : patharray) {
154+ File file = new File(name);
155+ if (file.isFile()) {
156+ try {
157+ ZipFile zip = new ZipFile(file);
158+ path[n] = new ClassPathEntry();
159+ path[n++].zip = zip;
160+ } catch (ZipException e) {
161+ } catch (IOException e) {
162+ // Ignore exceptions, at least for now...
163+ }
164+ } else {
165+ path[n] = new ClassPathEntry();
166+ path[n++].dir = file;
167+ }
168+ }
169+ // Trim class path to exact size
170+ this.path = new ClassPathEntry[n];
171+ System.arraycopy((Object)path, 0, (Object)this.path, 0, n);
172+ }
173+
174+ /**
175+ * Find the specified directory in the class path
176+ */
177+ public ClassFile getDirectory(String name) {
178+ return getFile(name, true);
179+ }
180+
181+ /**
182+ * Load the specified file from the class path
183+ */
184+ public ClassFile getFile(String name) {
185+ return getFile(name, false);
186+ }
187+
188+ private final String fileSeparatorChar = "" + File.separatorChar;
189+
190+ private ClassFile getFile(String name, boolean isDirectory) {
191+ String subdir = name;
192+ String basename = "";
193+ if (!isDirectory) {
194+ int i = name.lastIndexOf(File.separatorChar);
195+ subdir = name.substring(0, i + 1);
196+ basename = name.substring(i + 1);
197+ } else if (!subdir.equals("")
198+ && !subdir.endsWith(fileSeparatorChar)) {
199+ // zip files are picky about "foo" vs. "foo/".
200+ // also, the getFiles caches are keyed with a trailing /
201+ subdir = subdir + File.separatorChar;
202+ name = subdir; // Note: isDirectory==true & basename==""
203+ }
204+ for (int i = 0; i < path.length; i++) {
205+ if (path[i].zip != null) {
206+ String newname = name.replace(File.separatorChar, '/');
207+ ZipEntry entry = path[i].zip.getEntry(newname);
208+ if (entry != null) {
209+ return new ClassFile(path[i].zip, entry);
210+ }
211+ } else {
212+ File file = new File(path[i].dir.getPath(), name);
213+ String list[] = path[i].getFiles(subdir);
214+ if (isDirectory) {
215+ if (list.length > 0) {
216+ return new ClassFile(file);
217+ }
218+ } else {
219+ for (int j = 0; j < list.length; j++) {
220+ if (basename.equals(list[j])) {
221+ // Don't bother checking !file.isDir,
222+ // since we only look for names which
223+ // cannot already be packages (foo.java, etc).
224+ return new ClassFile(file);
225+ }
226+ }
227+ }
228+ }
229+ }
230+ return null;
231+ }
232+
233+ /**
234+ * Returns list of files given a package name and extension.
235+ */
236+ public Enumeration getFiles(String pkg, String ext) {
237+ Hashtable files = new Hashtable();
238+ for (int i = path.length; --i >= 0; ) {
239+ if (path[i].zip != null) {
240+ Enumeration e = path[i].zip.entries();
241+ while (e.hasMoreElements()) {
242+ ZipEntry entry = (ZipEntry)e.nextElement();
243+ String name = entry.getName();
244+ name = name.replace('/', File.separatorChar);
245+ if (name.startsWith(pkg) && name.endsWith(ext)) {
246+ files.put(name, new ClassFile(path[i].zip, entry));
247+ }
248+ }
249+ } else {
250+ String[] list = path[i].getFiles(pkg);
251+ for (int j = 0; j < list.length; j++) {
252+ String name = list[j];
253+ if (name.endsWith(ext)) {
254+ name = pkg + File.separatorChar + name;
255+ File file = new File(path[i].dir.getPath(), name);
256+ files.put(name, new ClassFile(file));
257+ }
258+ }
259+ }
260+ }
261+ return files.elements();
262+ }
263+
264+ /**
265+ * Release resources.
266+ */
267+ public void close() throws IOException {
268+ for (int i = path.length; --i >= 0; ) {
269+ if (path[i].zip != null) {
270+ path[i].zip.close();
271+ }
272+ }
273+ }
274+
275+ /**
276+ * Returns original class path string
277+ */
278+ public String toString() {
279+ return pathstr;
280+ }
281+}
282+
283+/**
284+ * A class path entry, which can either be a directory or an open zip file.
285+ */
286+class ClassPathEntry {
287+ File dir;
288+ ZipFile zip;
289+
290+ Hashtable subdirs = new Hashtable(29); // cache of sub-directory listings
291+ String[] getFiles(String subdir) {
292+ String files[] = (String[]) subdirs.get(subdir);
293+ if (files == null) {
294+ // search the directory, exactly once
295+ File sd = new File(dir.getPath(), subdir);
296+ if (sd.isDirectory()) {
297+ files = sd.list();
298+ if (files == null) {
299+ // should not happen, but just in case, fail silently
300+ files = new String[0];
301+ }
302+ if (files.length == 0) {
303+ String nonEmpty[] = { "" };
304+ files = nonEmpty;
305+ }
306+ } else {
307+ files = new String[0];
308+ }
309+ subdirs.put(subdir, files);
310+ }
311+ return files;
312+ }
313+
314+}
java/pkg/sun/tools/java/ClassType.java+64−0
@@ -0,0 +1,64 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+/**
29+ * This class represents an Java class type.
30+ * It overrides the relevant methods in class Type.
31+ *
32+ * WARNING: The contents of this source file are not part of any
33+ * supported API. Code that depends on them does so at its own risk:
34+ * they are subject to change or removal without notice.
35+ *
36+ * @author Arthur van Hoff
37+ */
38+public final
39+class ClassType extends Type {
40+ /**
41+ * The fully qualified class name.
42+ */
43+ Identifier className;
44+
45+ /**
46+ * Construct a class type. Use Type.tClass to create
47+ * a new class type.
48+ */
49+ ClassType(String typeSig, Identifier className) {
50+ super(TC_CLASS, typeSig);
51+ this.className = className;
52+ }
53+
54+ public Identifier getClassName() {
55+ return className;
56+ }
57+
58+ public String typeString(String id, boolean abbrev, boolean ret) {
59+ String s = (abbrev ? getClassName().getFlatName() :
60+ Identifier.lookup(getClassName().getQualifier(),
61+ getClassName().getFlatName())).toString();
62+ return (id.length() > 0) ? s + " " + id : s;
63+ }
64+}
java/pkg/sun/tools/java/CompilerError.java+62−0
@@ -0,0 +1,62 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+/**
29+ * This exception is thrown when an internal compiler error occurs
30+ *
31+ * WARNING: The contents of this source file are not part of any
32+ * supported API. Code that depends on them does so at its own risk:
33+ * they are subject to change or removal without notice.
34+ */
35+
36+public
37+class CompilerError extends Error {
38+ Throwable e;
39+
40+ /**
41+ * Constructor
42+ */
43+ public CompilerError(String msg) {
44+ super(msg);
45+ this.e = this;
46+ }
47+
48+ /**
49+ * Create an exception given another exception.
50+ */
51+ public CompilerError(Exception e) {
52+ super(e.getMessage());
53+ this.e = e;
54+ }
55+
56+ public void printStackTrace() {
57+ if (e == this)
58+ super.printStackTrace();
59+ else
60+ e.printStackTrace();
61+ }
62+}
java/pkg/sun/tools/java/Constants.java+591−0
@@ -0,0 +1,591 @@
1+/*
2+ * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+
27+package sun.tools.java;
28+
29+/**
30+ * This interface defines constant that are used
31+ * throughout the compiler. It inherits from RuntimeConstants,
32+ * which is an autogenerated class that contains contstants
33+ * defined in the interpreter.
34+ *
35+ * WARNING: The contents of this source file are not part of any
36+ * supported API. Code that depends on them does so at its own risk:
37+ * they are subject to change or removal without notice.
38+ *
39+ * @author Arthur van Hoff
40+ */
41+
42+public
43+interface Constants extends RuntimeConstants {
44+
45+ /*
46+ * Enable/disable inclusion of certain debug tracing code in the
47+ * compiler. When included, the tracing code may be selectively
48+ * enabled at runtime, otherwise we save the space/time overhead.
49+ * Should normally be 'false' for a release version.
50+ */
51+ public static final boolean tracing = true;
52+
53+ /*
54+ * Frequently used identifiers
55+ */
56+ Identifier idAppend = Identifier.lookup("append");
57+ Identifier idClassInit = Identifier.lookup("<clinit>");
58+ Identifier idCode = Identifier.lookup("Code");
59+ Identifier idInit = Identifier.lookup("<init>");
60+ Identifier idLength = Identifier.lookup("length");
61+ Identifier idNull = Identifier.lookup("");
62+ Identifier idStar = Identifier.lookup("*");
63+ Identifier idSuper = Identifier.lookup("super");
64+ Identifier idThis = Identifier.lookup("this");
65+ Identifier idClass = Identifier.lookup("class");
66+ Identifier idToString = Identifier.lookup("toString");
67+ Identifier idValueOf = Identifier.lookup("valueOf");
68+ Identifier idNew = Identifier.lookup("new");
69+ Identifier idGetClass = Identifier.lookup("getClass");
70+ Identifier idTYPE = Identifier.lookup("TYPE");
71+ Identifier idFinallyReturnValue = Identifier.lookup("<return>");
72+
73+ Identifier idJavaLang = Identifier.lookup("java.lang");
74+
75+ Identifier idJavaLangCloneable = Identifier.lookup("java.lang.Cloneable");
76+
77+ Identifier idJavaLangError = Identifier.lookup("java.lang.Error");
78+ Identifier idJavaLangException = Identifier.lookup("java.lang.Exception");
79+ Identifier idJavaLangObject = Identifier.lookup("java.lang.Object");
80+ Identifier idJavaLangClass = Identifier.lookup("java.lang.Class");
81+ Identifier idJavaLangRuntimeException =
82+ Identifier.lookup("java.lang.RuntimeException");
83+ Identifier idJavaLangString = Identifier.lookup("java.lang.String");
84+ Identifier idJavaLangStringBuffer =
85+ Identifier.lookup("java.lang.StringBuffer");
86+ Identifier idJavaLangThrowable = Identifier.lookup("java.lang.Throwable");
87+
88+ Identifier idJavaIoSerializable = Identifier.lookup("java.io.Serializable");
89+
90+
91+ Identifier idConstantValue = Identifier.lookup("ConstantValue");
92+ Identifier idLocalVariableTable = Identifier.lookup("LocalVariableTable");
93+ Identifier idLineNumberTable = Identifier.lookup("LineNumberTable");
94+// JCOV
95+ Identifier idCoverageTable = Identifier.lookup("CoverageTable");
96+// end JCOV
97+ Identifier idSourceFile = Identifier.lookup("SourceFile");
98+ Identifier idDocumentation = Identifier.lookup("Documentation");
99+ Identifier idDeprecated = Identifier.lookup("Deprecated");
100+ Identifier idSynthetic = Identifier.lookup("Synthetic");
101+ Identifier idExceptions = Identifier.lookup("Exceptions");
102+ Identifier idInnerClasses = Identifier.lookup("InnerClasses");
103+
104+ /* methods we need to know about */
105+ Identifier idClone = Identifier.lookup("clone");
106+
107+
108+ /* This is not a real signature marker, since it is also
109+ * an identifier constituent character.
110+ */
111+ char SIGC_INNERCLASS = '$';
112+ String SIG_INNERCLASS = "$";
113+
114+ String prefixThis = "this$";
115+ String prefixVal = "val$";
116+ String prefixLoc = "loc$";
117+ String prefixAccess = "access$";
118+ String prefixClass = "class$";
119+ String prefixArray = "array$";
120+
121+ /*
122+ * Flags
123+ */
124+ int F_VERBOSE = 1 << 0;
125+ int F_DUMP = 1 << 1;
126+ int F_WARNINGS = 1 << 2;
127+
128+ // The meaning of -g has changed, so F_DEBUG flag is removed.
129+ // public static final int F_DEBUG = 1 << 3;
130+ int F_DEBUG_LINES = 1 << 12;
131+ int F_DEBUG_VARS = 1 << 13;
132+ int F_DEBUG_SOURCE = 1 << 18;
133+
134+ // The meaning of -O has changed, so F_OPTIMIZE flag is removed.
135+ // public static final int F_OPTIMIZE = 1 << 4;
136+ int F_OPT = 1 << 14;
137+ int F_OPT_INTERCLASS = 1 << 15;
138+
139+ int F_DEPENDENCIES = 1 << 5;
140+
141+// JCOV
142+ int F_COVERAGE = 1 << 6;
143+ int F_COVDATA = 1 << 7;
144+// end JCOV
145+
146+ int F_DEPRECATION = 1 << 9;
147+ int F_PRINT_DEPENDENCIES = 1 << 10;
148+ int F_VERSION12 = 1 << 11;
149+
150+
151+ int F_ERRORSREPORTED = 1 << 16;
152+
153+ int F_STRICTDEFAULT = 1 << 17;
154+
155+ /*
156+ * Modifiers.
157+ *
158+ * There has been much confusion regarding modifiers. There
159+ * are a number of distinct usages:
160+ *
161+ * - in classfiles to annotate classes, as per JVM pg. 102.
162+ * - in classfiles to annotate methods, as per JVM pg. 104.
163+ * - in classfiles to annotate InnerClass attributes, as per
164+ * http://java.sun.com/products/jdk/1.1/docs/guide/innerclasses
165+ * - in the compiler to record java source level modifiers,
166+ * as per JLS pg. 157 et al., plus misc. info such as whether
167+ * a method is deprecated
168+ * - in the JVM to record misc. info, such as whether a method has
169+ * has been compiled
170+ *
171+ * To make matters worse, the terms "access flags" and "modifiers"
172+ * are often used interchangably, and some information that might
173+ * make sense as a flag is expressed using attributes (ie. Synthetic).
174+ *
175+ * The constants defined herein have been divided by whether they
176+ * make sense only within the compiler (M_* and MM_*) or whether
177+ * they only make sense to the JVM (ACC_* and ACCM_*). At an earlier
178+ * time these were all lumped together. Future maintenance should
179+ * strive to keep the distinction clear.
180+ *
181+ * Note that modifier M_STRICTFP is not in general recoverable from
182+ * the ACC_STRICT bit in classfiles.
183+ *
184+ * Note also that the modifiers M_LOCAL and M_ANONYMOUS do not appear
185+ * in the InnerClass attribute, as they are above the first 16 bits.
186+ */
187+
188+ // Modifiers meaningful to both Java source and the JVM. These
189+ // have been kept the same bit in the M_* and ACC_* forms
190+ // to avoid destabilizing the compiler.
191+ int M_PUBLIC = ACC_PUBLIC;
192+ int M_PRIVATE = ACC_PRIVATE;
193+ int M_PROTECTED = ACC_PROTECTED;
194+ int M_STATIC = ACC_STATIC;
195+ int M_TRANSIENT = ACC_TRANSIENT;
196+ int M_SYNCHRONIZED = ACC_SYNCHRONIZED; // collides with ACC_SUPER
197+ int M_ABSTRACT = ACC_ABSTRACT;
198+ int M_NATIVE = ACC_NATIVE;
199+ int M_FINAL = ACC_FINAL;
200+ int M_VOLATILE = ACC_VOLATILE;
201+ int M_INTERFACE = ACC_INTERFACE;
202+
203+ // Modifiers not meaningful to the JVM. The JVM only allows 16 bits
204+ // for modifiers, so keeping these in the unusable bits after the first
205+ // 16 is a good idea.
206+ int M_ANONYMOUS = 0x00010000;
207+ int M_LOCAL = 0x00020000;
208+ int M_DEPRECATED = 0x00040000;
209+ int M_SYNTHETIC = 0x00080000;
210+ int M_INLINEABLE = 0x00100000;
211+
212+ int M_STRICTFP = 0x00200000;
213+
214+ String paraDeprecated = "@deprecated";
215+
216+ // Masks for modifiers that apply to Java source code
217+ int MM_CLASS = M_PUBLIC
218+ | M_INTERFACE
219+ | M_FINAL
220+ | M_ABSTRACT
221+ | M_STRICTFP;
222+ int MM_MEMBER = M_PUBLIC
223+ | M_PRIVATE
224+ | M_PROTECTED
225+ | M_FINAL
226+ | M_STATIC;
227+ int MM_FIELD = MM_MEMBER
228+ | M_TRANSIENT
229+ | M_VOLATILE;
230+ int MM_METHOD = MM_MEMBER
231+ | M_SYNCHRONIZED
232+ | M_ABSTRACT
233+ | M_NATIVE
234+ | M_STRICTFP;
235+
236+ // Masks for modifiers that apply to class files.
237+ // Note that the M_SYNTHETIC modifier is never written out to a class file.
238+ // Synthetic members are indicated using the "Synthetic" attribute.
239+ int ACCM_CLASS = ACC_PUBLIC
240+ | ACC_INTERFACE
241+ | ACC_FINAL
242+ | ACC_ABSTRACT
243+ | ACC_SUPER
244+ | ACC_STRICT;
245+ int ACCM_MEMBER = ACC_PUBLIC
246+ | ACC_PRIVATE
247+ | ACC_PROTECTED
248+ | ACC_FINAL
249+ | ACC_STATIC;
250+ // The M_ANONYMOUS and M_LOCAL modifiers are not mentioned in the
251+ // inner classes specification and are never written to classfiles.
252+ // Also note that ACC_SUPER should never be set in an InnerClass
253+ // attribute.
254+ int ACCM_INNERCLASS = ACC_PUBLIC
255+ | ACC_PRIVATE
256+ | ACC_PROTECTED
257+ | ACC_STATIC
258+ | ACC_ABSTRACT
259+ | ACC_FINAL
260+ | ACC_INTERFACE
261+ | ACC_STRICT;
262+ int ACCM_FIELD = ACCM_MEMBER
263+ | ACC_TRANSIENT
264+ | ACC_VOLATILE;
265+ int ACCM_METHOD = ACCM_MEMBER
266+ | ACC_SYNCHRONIZED
267+ | ACC_ABSTRACT
268+ | ACC_NATIVE
269+ | ACC_STRICT;
270+
271+ /*
272+ * Type codes
273+ */
274+ int TC_BOOLEAN = 0;
275+ int TC_BYTE = 1;
276+ int TC_CHAR = 2;
277+ int TC_SHORT = 3;
278+ int TC_INT = 4;
279+ int TC_LONG = 5;
280+ int TC_FLOAT = 6;
281+ int TC_DOUBLE = 7;
282+ int TC_NULL = 8;
283+ int TC_ARRAY = 9;
284+ int TC_CLASS = 10;
285+ int TC_VOID = 11;
286+ int TC_METHOD = 12;
287+ int TC_ERROR = 13;
288+
289+// JCOV
290+ /*
291+ * Cover's types
292+ */
293+ int CT_FIRST_KIND = 1;
294+ int CT_METHOD = 1;
295+ int CT_FIKT_METHOD = 2;
296+ int CT_BLOCK = 3;
297+ int CT_FIKT_RET = 4;
298+ int CT_CASE = 5;
299+ int CT_SWITH_WO_DEF = 6;
300+ int CT_BRANCH_TRUE = 7;
301+ int CT_BRANCH_FALSE = 8;
302+ int CT_LAST_KIND = 8;
303+// end JCOV
304+
305+ /*
306+ * Type Masks
307+ */
308+ int TM_NULL = 1 << TC_NULL;
309+ int TM_VOID = 1 << TC_VOID;
310+ int TM_BOOLEAN = 1 << TC_BOOLEAN;
311+ int TM_BYTE = 1 << TC_BYTE;
312+ int TM_CHAR = 1 << TC_CHAR;
313+ int TM_SHORT = 1 << TC_SHORT;
314+ int TM_INT = 1 << TC_INT;
315+ int TM_LONG = 1 << TC_LONG;
316+ int TM_FLOAT = 1 << TC_FLOAT;
317+ int TM_DOUBLE = 1 << TC_DOUBLE;
318+ int TM_ARRAY = 1 << TC_ARRAY;
319+ int TM_CLASS = 1 << TC_CLASS;
320+ int TM_METHOD = 1 << TC_METHOD;
321+ int TM_ERROR = 1 << TC_ERROR;
322+
323+ int TM_INT32 = TM_BYTE | TM_SHORT | TM_CHAR | TM_INT;
324+ int TM_NUM32 = TM_INT32 | TM_FLOAT;
325+ int TM_NUM64 = TM_LONG | TM_DOUBLE;
326+ int TM_INTEGER = TM_INT32 | TM_LONG;
327+ int TM_REAL = TM_FLOAT | TM_DOUBLE;
328+ int TM_NUMBER = TM_INTEGER | TM_REAL;
329+ int TM_REFERENCE = TM_ARRAY | TM_CLASS | TM_NULL;
330+
331+ /*
332+ * Class status
333+ */
334+ int CS_UNDEFINED = 0;
335+ int CS_UNDECIDED = 1;
336+ int CS_BINARY = 2;
337+ int CS_SOURCE = 3;
338+ int CS_PARSED = 4;
339+ int CS_CHECKED = 5;
340+ int CS_COMPILED = 6;
341+ int CS_NOTFOUND = 7;
342+
343+
344+ /*
345+ * Attributes
346+ */
347+ int ATT_ALL = 0xFFFFFFFF;
348+ int ATT_CODE = 1 << 1;
349+ int ATT_ALLCLASSES = 1 << 2;
350+
351+ /*
352+ * Number of bits used in file offsets. The line number and
353+ * file offset are concatenated into a long, with enough room
354+ * for other information to be added later if desired (such as
355+ * token lengths). For the moment explicit bit manipulations
356+ * are used to modify the fields. This makes sense for efficiency
357+ * but at some point these ought to be better encapsulated.
358+ */
359+ int WHEREOFFSETBITS = 32;
360+ long MAXFILESIZE = (1L << WHEREOFFSETBITS) - 1;
361+ long MAXLINENUMBER = (1L << (64 - WHEREOFFSETBITS)) - 1;
362+
363+ /*
364+ * Operators
365+ */
366+ int COMMA = 0;
367+ int ASSIGN = 1;
368+
369+ int ASGMUL = 2;
370+ int ASGDIV = 3;
371+ int ASGREM = 4;
372+ int ASGADD = 5;
373+ int ASGSUB = 6;
374+ int ASGLSHIFT = 7;
375+ int ASGRSHIFT = 8;
376+ int ASGURSHIFT = 9;
377+ int ASGBITAND = 10;
378+ int ASGBITOR = 11;
379+ int ASGBITXOR = 12;
380+
381+ int COND = 13;
382+ int OR = 14;
383+ int AND = 15;
384+ int BITOR = 16;
385+ int BITXOR = 17;
386+ int BITAND = 18;
387+ int NE = 19;
388+ int EQ = 20;
389+ int GE = 21;
390+ int GT = 22;
391+ int LE = 23;
392+ int LT = 24;
393+ int INSTANCEOF = 25;
394+ int LSHIFT = 26;
395+ int RSHIFT = 27;
396+ int URSHIFT = 28;
397+ int ADD = 29;
398+ int SUB = 30;
399+ int DIV = 31;
400+ int REM = 32;
401+ int MUL = 33;
402+ int CAST = 34; // (x)y
403+ int POS = 35; // +x
404+ int NEG = 36; // -x
405+ int NOT = 37;
406+ int BITNOT = 38;
407+ int PREINC = 39; // ++x
408+ int PREDEC = 40; // --x
409+ int NEWARRAY = 41;
410+ int NEWINSTANCE = 42;
411+ int NEWFROMNAME = 43;
412+ int POSTINC = 44; // x++
413+ int POSTDEC = 45; // x--
414+ int FIELD = 46;
415+ int METHOD = 47; // x(y)
416+ int ARRAYACCESS = 48; // x[y]
417+ int NEW = 49;
418+ int INC = 50;
419+ int DEC = 51;
420+
421+ int CONVERT = 55; // implicit conversion
422+ int EXPR = 56; // (x)
423+ int ARRAY = 57; // {x, y, ...}
424+ int GOTO = 58;
425+
426+ /*
427+ * Value tokens
428+ */
429+ int IDENT = 60;
430+ int BOOLEANVAL = 61;
431+ int BYTEVAL = 62;
432+ int CHARVAL = 63;
433+ int SHORTVAL = 64;
434+ int INTVAL = 65;
435+ int LONGVAL = 66;
436+ int FLOATVAL = 67;
437+ int DOUBLEVAL = 68;
438+ int STRINGVAL = 69;
439+
440+ /*
441+ * Type keywords
442+ */
443+ int BYTE = 70;
444+ int CHAR = 71;
445+ int SHORT = 72;
446+ int INT = 73;
447+ int LONG = 74;
448+ int FLOAT = 75;
449+ int DOUBLE = 76;
450+ int VOID = 77;
451+ int BOOLEAN = 78;
452+
453+ /*
454+ * Expression keywords
455+ */
456+ int TRUE = 80;
457+ int FALSE = 81;
458+ int THIS = 82;
459+ int SUPER = 83;
460+ int NULL = 84;
461+
462+ /*
463+ * Statement keywords
464+ */
465+ int IF = 90;
466+ int ELSE = 91;
467+ int FOR = 92;
468+ int WHILE = 93;
469+ int DO = 94;
470+ int SWITCH = 95;
471+ int CASE = 96;
472+ int DEFAULT = 97;
473+ int BREAK = 98;
474+ int CONTINUE = 99;
475+ int RETURN = 100;
476+ int TRY = 101;
477+ int CATCH = 102;
478+ int FINALLY = 103;
479+ int THROW = 104;
480+ int STAT = 105;
481+ int EXPRESSION = 106;
482+ int DECLARATION = 107;
483+ int VARDECLARATION = 108;
484+
485+ /*
486+ * Declaration keywords
487+ */
488+ int IMPORT = 110;
489+ int CLASS = 111;
490+ int EXTENDS = 112;
491+ int IMPLEMENTS = 113;
492+ int INTERFACE = 114;
493+ int PACKAGE = 115;
494+
495+ /*
496+ * Modifier keywords
497+ */
498+ int PRIVATE = 120;
499+ int PUBLIC = 121;
500+ int PROTECTED = 122;
501+ int CONST = 123;
502+ int STATIC = 124;
503+ int TRANSIENT = 125;
504+ int SYNCHRONIZED = 126;
505+ int NATIVE = 127;
506+ int FINAL = 128;
507+ int VOLATILE = 129;
508+ int ABSTRACT = 130;
509+ int STRICTFP = 131;
510+
511+ /*
512+ * Punctuation
513+ */
514+ int SEMICOLON = 135;
515+ int COLON = 136;
516+ int QUESTIONMARK = 137;
517+ int LBRACE = 138;
518+ int RBRACE = 139;
519+ int LPAREN = 140;
520+ int RPAREN = 141;
521+ int LSQBRACKET = 142;
522+ int RSQBRACKET = 143;
523+ int THROWS = 144;
524+
525+ /*
526+ * Special tokens
527+ */
528+ int ERROR = 145; // an error
529+ int COMMENT = 146; // not used anymore.
530+ int TYPE = 147;
531+ int LENGTH = 148;
532+ int INLINERETURN = 149;
533+ int INLINEMETHOD = 150;
534+ int INLINENEWINSTANCE = 151;
535+
536+ /*
537+ * Operator precedence
538+ */
539+ int opPrecedence[] = {
540+ 10, 11, 11, 11, 11, 11, 11, 11, 11, 11,
541+ 11, 11, 11, 12, 13, 14, 15, 16, 17, 18,
542+ 18, 19, 19, 19, 19, 19, 20, 20, 20, 21,
543+ 21, 22, 22, 22, 23, 24, 24, 24, 24, 24,
544+ 24, 25, 25, 26, 26, 26, 26, 26, 26
545+ };
546+
547+ /*
548+ * Operator names
549+ */
550+ String opNames[] = {
551+ ",", "=", "*=", "/=", "%=",
552+ "+=", "-=", "<<=", ">>=", ">>>=",
553+ "&=", "|=", "^=", "?:", "||",
554+ "&&", "|", "^", "&", "!=",
555+ "==", ">=", ">", "<=", "<",
556+ "instanceof", "<<", ">>", ">>>", "+",
557+ "-", "/", "%", "*", "cast",
558+ "+", "-", "!", "~", "++",
559+ "--", "new", "new", "new", "++",
560+ "--", "field","method","[]", "new",
561+ "++", "--", null, null, null,
562+
563+ "convert", "expr", "array", "goto", null,
564+
565+ "Identifier", "boolean", "byte", "char", "short",
566+ "int", "long", "float", "double", "string",
567+
568+ "byte", "char", "short", "int", "long",
569+ "float", "double", "void", "boolean", null,
570+
571+ "true", "false", "this", "super", "null",
572+ null, null, null, null, null,
573+
574+ "if", "else", "for", "while","do",
575+ "switch", "case", "default", "break", "continue",
576+ "return", "try", "catch", "finally", "throw",
577+ "stat", "expression", "declaration", "declaration", null,
578+
579+ "import", "class", "extends", "implements", "interface",
580+ "package", null, null, null, null,
581+
582+ "private", "public", "protected", "const", "static",
583+ "transient", "synchronized", "native", "final", "volatile",
584+ "abstract", "strictfp", null, null, null,
585+
586+ ";", ":", "?", "{", "}",
587+ "(", ")", "[", "]", "throws",
588+ "error", "comment", "type", "length", "inline-return",
589+ "inline-method", "inline-new"
590+ };
591+}
java/pkg/sun/tools/java/Environment.java+998−0
@@ -0,0 +1,998 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.util.Stack;
29+import java.io.IOException;
30+import sun.tools.tree.Context;
31+//JCOV
32+import java.io.File;
33+//end JCOV
34+
35+/**
36+ * This class defines the environment for a compilation.
37+ * It is used to load classes, resolve class names and
38+ * report errors. It is an abstract class, a subclass
39+ * must define implementations for some of the functions.<p>
40+ *
41+ * An environment has a source object associated with it.
42+ * This is the thing against which errors are reported, it
43+ * is usually a file name, a field or a class.<p>
44+ *
45+ * Environments can be nested to change the source object.<p>
46+ *
47+ * WARNING: The contents of this source file are not part of any
48+ * supported API. Code that depends on them does so at its own risk:
49+ * they are subject to change or removal without notice.
50+ *
51+ * @author Arthur van Hoff
52+ */
53+
54+public class Environment implements Constants {
55+ /**
56+ * The actual environment to which everything is forwarded.
57+ */
58+ Environment env;
59+
60+ /**
61+ * External character encoding name
62+ */
63+ String encoding;
64+
65+ /**
66+ * The object that is currently being parsed/compiled.
67+ * It is either a file name (String) or a field (MemberDefinition)
68+ * or a class (ClassDeclaration or ClassDefinition).
69+ */
70+ Object source;
71+
72+ public Environment(Environment env, Object source) {
73+ if (env != null && env.env != null && env.getClass() == this.getClass())
74+ env = env.env; // a small optimization
75+ this.env = env;
76+ this.source = source;
77+ }
78+ public Environment() {
79+ this(null, null);
80+ }
81+
82+ /**
83+ * Tells whether an Identifier refers to a package which should be
84+ * exempt from the "exists" check in Imports#resolve().
85+ */
86+ public boolean isExemptPackage(Identifier id) {
87+ return env.isExemptPackage(id);
88+ }
89+
90+ /**
91+ * Return a class declaration given a fully qualified class name.
92+ */
93+ public ClassDeclaration getClassDeclaration(Identifier nm) {
94+ return env.getClassDeclaration(nm);
95+ }
96+
97+ /**
98+ * Return a class definition given a fully qualified class name.
99+ * <p>
100+ * Should be called only with 'internal' class names, i.e., the result
101+ * of a call to 'resolveName' or a synthetic class name.
102+ */
103+ public final ClassDefinition getClassDefinition(Identifier nm) throws ClassNotFound {
104+ if (nm.isInner()) {
105+ ClassDefinition c = getClassDefinition(nm.getTopName());
106+ Identifier tail = nm.getFlatName();
107+ walkTail:
108+ while (tail.isQualified()) {
109+ tail = tail.getTail();
110+ Identifier head = tail.getHead();
111+ //System.out.println("CLASS: " + c + " HEAD: " + head + " TAIL: " + tail);
112+ String hname = head.toString();
113+ // If the name is of the form 'ClassName.N$localName', where N is
114+ // a number, the field 'N$localName' may not necessarily be a member
115+ // of the class named by 'ClassName', but might be a member of some
116+ // inaccessible class contained within it. We use 'getLocalClass'
117+ // to do the lookup in this case. This is part of a fix for bugid
118+ // 4054523 and 4030421. See also 'BatchEnvironment.makeClassDefinition'.
119+ // This should also work for anonymous class names of the form
120+ // 'ClassName.N'. Note that the '.' qualifications get converted to
121+ // '$' characters when determining the external name of the class and
122+ // the name of the class file.
123+ if (hname.length() > 0
124+ && Character.isDigit(hname.charAt(0))) {
125+ ClassDefinition localClass = c.getLocalClass(hname);
126+ if (localClass != null) {
127+ c = localClass;
128+ continue walkTail;
129+ }
130+ } else {
131+ for (MemberDefinition f = c.getFirstMatch(head);
132+ f != null; f = f.getNextMatch()) {
133+ if (f.isInnerClass()) {
134+ c = f.getInnerClass();
135+ continue walkTail;
136+ }
137+ }
138+ }
139+ throw new ClassNotFound(Identifier.lookupInner(c.getName(), head));
140+ }
141+ //System.out.println("FOUND " + c + " FOR " + nm);
142+ return c;
143+ }
144+ return getClassDeclaration(nm).getClassDefinition(this);
145+ }
146+
147+
148+ /**
149+ * Return a class declaration given a type. Only works for
150+ * class types.
151+ */
152+ public ClassDeclaration getClassDeclaration(Type t) {
153+ return getClassDeclaration(t.getClassName());
154+ }
155+
156+ /**
157+ * Return a class definition given a type. Only works for
158+ * class types.
159+ */
160+ public final ClassDefinition getClassDefinition(Type t) throws ClassNotFound {
161+ return getClassDefinition(t.getClassName());
162+ }
163+
164+ /**
165+ * Check if a class exists (without actually loading it).
166+ * (Since inner classes cannot in general be examined without
167+ * loading source, this method does not accept inner names.)
168+ */
169+ public boolean classExists(Identifier nm) {
170+ return env.classExists(nm);
171+ }
172+
173+ public final boolean classExists(Type t) {
174+ return !t.isType(TC_CLASS) || classExists(t.getClassName());
175+ }
176+
177+ /**
178+ * Get the package path for a package
179+ */
180+ public Package getPackage(Identifier pkg) throws IOException {
181+ return env.getPackage(pkg);
182+ }
183+
184+ /**
185+ * Load the definition of a class.
186+ */
187+ public void loadDefinition(ClassDeclaration c) {
188+ env.loadDefinition(c);
189+ }
190+
191+ /**
192+ * Return the source of the environment (ie: the thing being compiled/parsed).
193+ */
194+ public final Object getSource() {
195+ return source;
196+ }
197+
198+ /**
199+ * Resolve a type. Make sure that all the classes referred to by
200+ * the type have a definition. Report errors. Return true if
201+ * the type is well-formed. Presently used for types appearing
202+ * in member declarations, which represent named types internally as
203+ * qualified identifiers. Type names appearing in local variable
204+ * declarations and within expressions are represented as identifier
205+ * or field expressions, and are resolved by 'toType', which delegates
206+ * handling of the non-inner portion of the name to this method.
207+ * <p>
208+ * In 'toType', the various stages of qualification are represented by
209+ * separate AST nodes. Here, we are given a single identifier which
210+ * contains the entire qualification structure. It is not possible in
211+ * general to set the error location to the exact position of a component
212+ * that is in error, so an error message must refer to the entire qualified
213+ * name. An attempt to keep track of the string length of the components of
214+ * the name and to offset the location accordingly fails because the initial
215+ * prefix of the name may have been rewritten by an earlier call to
216+ * 'resolveName'. See 'SourceMember.resolveTypeStructure'. The situation
217+ * is actually even worse than this, because only a single location is
218+ * passed in for an entire declaration, which may contain many type names.
219+ * All error messages are thus poorly localized. These checks should be
220+ * done while traversing the parse tree for the type, not the type descriptor.
221+ * <p>
222+ * DESIGN NOTE:
223+ * As far as I can tell, the two-stage resolution of names represented in
224+ * string form is an artifact of the late implementation of inner classes
225+ * and the use of mangled names internally within the compiler. All
226+ * qualified names should have their hiearchical structure made explicit
227+ * in the parse tree at the phase at which they are presented for static
228+ * semantic checking. This would affect class names appearing in 'extends',
229+ * 'implements', and 'throws' clauses, as well as in member declarations.
230+ */
231+ public boolean resolve(long where, ClassDefinition c, Type t) {
232+ switch (t.getTypeCode()) {
233+ case TC_CLASS: {
234+ ClassDefinition def;
235+ try {
236+ Identifier nm = t.getClassName();
237+ if (!nm.isQualified() && !nm.isInner() && !classExists(nm)) {
238+ resolve(nm); // elicit complaints about ambiguity
239+ }
240+ def = getQualifiedClassDefinition(where, nm, c, false);
241+ if (!c.canAccess(this, def.getClassDeclaration())) {
242+ // Reported error location may be imprecise
243+ // if the name is qualified.
244+ error(where, "cant.access.class", def);
245+ return true; // return false later
246+ }
247+ def.noteUsedBy(c, where, env);
248+ } catch (AmbiguousClass ee) {
249+ error(where, "ambig.class", ee.name1, ee.name2);
250+ return false;
251+ } catch (ClassNotFound e) {
252+ // For now, report "class.and.package" only when the code
253+ // is going to fail anyway.
254+ try {
255+ if (e.name.isInner() &&
256+ getPackage(e.name.getTopName()).exists()) {
257+ env.error(where, "class.and.package",
258+ e.name.getTopName());
259+ }
260+ } catch (IOException ee) {
261+ env.error(where, "io.exception", "package check");
262+ }
263+ // This error message is also emitted for 'new' expressions.
264+ // error(where, "class.not.found", e.name, "declaration");
265+ error(where, "class.not.found.no.context", e.name);
266+ return false;
267+ }
268+ return true;
269+ }
270+
271+ case TC_ARRAY:
272+ return resolve(where, c, t.getElementType());
273+
274+ case TC_METHOD:
275+ boolean ok = resolve(where, c, t.getReturnType());
276+ Type args[] = t.getArgumentTypes();
277+ for (int i = args.length ; i-- > 0 ; ) {
278+ ok &= resolve(where, c, args[i]);
279+ }
280+ return ok;
281+ }
282+ return true;
283+ }
284+
285+ /**
286+ * Given its fully-qualified name, verify that a class is defined and accessible.
287+ * Used to check components of qualified names in contexts where a class is expected.
288+ * Like 'resolve', but is given a single type name, not a type descriptor.
289+ */
290+ public boolean resolveByName(long where, ClassDefinition c, Identifier nm) {
291+ return resolveByName(where, c, nm, false);
292+ }
293+
294+ public boolean resolveExtendsByName(long where, ClassDefinition c, Identifier nm) {
295+ return resolveByName(where, c, nm, true);
296+ }
297+
298+ private boolean resolveByName(long where, ClassDefinition c,
299+ Identifier nm, boolean isExtends) {
300+ ClassDefinition def;
301+ try {
302+ if (!nm.isQualified() && !nm.isInner() && !classExists(nm)) {
303+ resolve(nm); // elicit complaints about ambiguity
304+ }
305+ def = getQualifiedClassDefinition(where, nm, c, isExtends);
306+ ClassDeclaration decl = def.getClassDeclaration();
307+ if (!((!isExtends && c.canAccess(this, decl))
308+ ||
309+ (isExtends && c.extendsCanAccess(this, decl)))) {
310+ error(where, "cant.access.class", def);
311+ return true; // return false later
312+ }
313+ } catch (AmbiguousClass ee) {
314+ error(where, "ambig.class", ee.name1, ee.name2);
315+ return false;
316+ } catch (ClassNotFound e) {
317+ // For now, report "class.and.package" only when the code
318+ // is going to fail anyway.
319+ try {
320+ if (e.name.isInner() &&
321+ getPackage(e.name.getTopName()).exists()) {
322+ env.error(where, "class.and.package",
323+ e.name.getTopName());
324+ }
325+ } catch (IOException ee) {
326+ env.error(where, "io.exception", "package check");
327+ }
328+ error(where, "class.not.found", e.name, "type name");
329+ return false;
330+ }
331+ return true;
332+ }
333+
334+ /**
335+ * Like 'getClassDefinition(env)', but check access on each component.
336+ * Currently called only by 'resolve' above. It is doubtful that calls
337+ * to 'getClassDefinition(env)' are appropriate now.
338+ */
339+ public final ClassDefinition
340+ getQualifiedClassDefinition(long where,
341+ Identifier nm,
342+ ClassDefinition ctxClass,
343+ boolean isExtends) throws ClassNotFound {
344+ if (nm.isInner()) {
345+ ClassDefinition c = getClassDefinition(nm.getTopName());
346+ Identifier tail = nm.getFlatName();
347+ walkTail:
348+ while (tail.isQualified()) {
349+ tail = tail.getTail();
350+ Identifier head = tail.getHead();
351+ // System.out.println("CLASS: " + c + " HEAD: " + head + " TAIL: " + tail);
352+ String hname = head.toString();
353+ // Handle synthesized names of local and anonymous classes.
354+ // See 'getClassDefinition(env)' above.
355+ if (hname.length() > 0
356+ && Character.isDigit(hname.charAt(0))) {
357+ ClassDefinition localClass = c.getLocalClass(hname);
358+ if (localClass != null) {
359+ c = localClass;
360+ continue walkTail;
361+ }
362+ } else {
363+ for (MemberDefinition f = c.getFirstMatch(head);
364+ f != null; f = f.getNextMatch()) {
365+ if (f.isInnerClass()) {
366+ ClassDeclaration rdecl = c.getClassDeclaration();
367+ c = f.getInnerClass();
368+ ClassDeclaration fdecl = c.getClassDeclaration();
369+ // This check is presumably applicable even if the
370+ // original source-code name (expanded by 'resolveNames')
371+ // was a simple, unqualified name. Hopefully, JLS 2e
372+ // will clarify the matter.
373+ if ((!isExtends
374+ && !ctxClass.canAccess(env, fdecl))
375+ ||
376+ (isExtends
377+ && !ctxClass.extendsCanAccess(env, fdecl))) {
378+ // Reported error location is imprecise.
379+ env.error(where, "no.type.access", head, rdecl, ctxClass);
380+ }
381+ // The JLS 6.6.2 restrictions on access to protected members
382+ // depend in an essential way upon the syntactic form of the name.
383+ // Since the compiler has previously expanded the class names
384+ // here into fully-qualified form ('resolveNames'), this check
385+ // cannot be performed here. Unfortunately, the original names
386+ // are clobbered during 'basicCheck', which is also the phase that
387+ // resolves the inheritance structure, required to implement the
388+ // access restrictions. Pending a large-scale revision of the
389+ // name-resolution machinery, we forgo this check, with the result
390+ // that the JLS 6.6.2 restrictions are not enforced for some cases
391+ // of qualified access to inner classes. Some qualified names are
392+ // resolved elsewhere via a different mechanism, and will be
393+ // treated correctly -- see 'FieldExpression.checkCommon'.
394+ /*---------------------------------------*
395+ if (f.isProtected()) {
396+ Type rty = Type.tClass(rdecl.getName()); // hack
397+ if (!ctxClass.protectedAccess(env, f, rty)) {
398+ // Reported error location is imprecise.
399+ env.error(where, "invalid.protected.type.use",
400+ head, ctxClass, rty);
401+ }
402+ }
403+ *---------------------------------------*/
404+ continue walkTail;
405+ }
406+ }
407+ }
408+ throw new ClassNotFound(Identifier.lookupInner(c.getName(), head));
409+ }
410+ //System.out.println("FOUND " + c + " FOR " + nm);
411+ return c;
412+ }
413+ return getClassDeclaration(nm).getClassDefinition(this);
414+ }
415+
416+ /**
417+ * Resolve the names within a type, returning the adjusted type.
418+ * Adjust class names to reflect scoping.
419+ * Do not report errors.
420+ * <p>
421+ * NOTE: It would be convenient to check for errors here, such as
422+ * verifying that each component of a qualified name exists and is
423+ * accessible. Why must this be done in a separate phase?
424+ * <p>
425+ * If the 'synth' argument is true, indicating that the member whose
426+ * type is being resolved is synthetic, names are resolved with respect
427+ * to the package scope. (Fix for 4097882)
428+ */
429+ public Type resolveNames(ClassDefinition c, Type t, boolean synth) {
430+ if (tracing) dtEvent("Environment.resolveNames: " + c + ", " + t);
431+ switch (t.getTypeCode()) {
432+ case TC_CLASS: {
433+ Identifier name = t.getClassName();
434+ Identifier rname;
435+ if (synth) {
436+ rname = resolvePackageQualifiedName(name);
437+ } else {
438+ rname = c.resolveName(this, name);
439+ }
440+ if (name != rname) {
441+ t = Type.tClass(rname);
442+ }
443+ break;
444+ }
445+
446+ case TC_ARRAY:
447+ t = Type.tArray(resolveNames(c, t.getElementType(), synth));
448+ break;
449+
450+ case TC_METHOD: {
451+ Type ret = t.getReturnType();
452+ Type rret = resolveNames(c, ret, synth);
453+ Type args[] = t.getArgumentTypes();
454+ Type rargs[] = new Type[args.length];
455+ boolean changed = (ret != rret);
456+ for (int i = args.length ; i-- > 0 ; ) {
457+ Type arg = args[i];
458+ Type rarg = resolveNames(c, arg, synth);
459+ rargs[i] = rarg;
460+ if (arg != rarg) {
461+ changed = true;
462+ }
463+ }
464+ if (changed) {
465+ t = Type.tMethod(rret, rargs);
466+ }
467+ break;
468+ }
469+ }
470+ return t;
471+ }
472+
473+ /**
474+ * Resolve a class name, using only package and import directives.
475+ * Report no errors.
476+ * <p>
477+ */
478+ public Identifier resolveName(Identifier name) {
479+ // This logic is pretty exactly parallel to that of
480+ // ClassDefinition.resolveName().
481+ if (name.isQualified()) {
482+ // Try to resolve the first identifier component,
483+ // because inner class names take precedence over
484+ // package prefixes. (Cf. ClassDefinition.resolveName.)
485+ Identifier rhead = resolveName(name.getHead());
486+
487+ if (rhead.hasAmbigPrefix()) {
488+ // The first identifier component refers to an
489+ // ambiguous class. Limp on. We throw away the
490+ // rest of the classname as it is irrelevant.
491+ // (part of solution for 4059855).
492+ return rhead;
493+ }
494+
495+ if (!this.classExists(rhead)) {
496+ return this.resolvePackageQualifiedName(name);
497+ }
498+ try {
499+ return this.getClassDefinition(rhead).
500+ resolveInnerClass(this, name.getTail());
501+ } catch (ClassNotFound ee) {
502+ // return partially-resolved name someone else can fail on
503+ return Identifier.lookupInner(rhead, name.getTail());
504+ }
505+ }
506+ try {
507+ return resolve(name);
508+ } catch (AmbiguousClass ee) {
509+ // Don't force a resolution of the name if it is ambiguous.
510+ // Forcing the resolution would tack the current package
511+ // name onto the front of the class, which would be wrong.
512+ // Instead, mark the name as ambiguous and let a later stage
513+ // find the error by calling env.resolve(name).
514+ // (part of solution for 4059855).
515+
516+ if (name.hasAmbigPrefix()) {
517+ return name;
518+ } else {
519+ return name.addAmbigPrefix();
520+ }
521+ } catch (ClassNotFound ee) {
522+ // last chance to make something halfway sensible
523+ Imports imports = getImports();
524+ if (imports != null)
525+ return imports.forceResolve(this, name);
526+ }
527+ return name;
528+ }
529+
530+ /**
531+ * Discover if name consists of a package prefix, followed by the
532+ * name of a class (that actually exists), followed possibly by
533+ * some inner class names. If we can't find a class that exists,
534+ * return the name unchanged.
535+ * <p>
536+ * This routine is used after a class name fails to
537+ * be resolved by means of imports or inner classes.
538+ * However, import processing uses this routine directly,
539+ * since import names must be exactly qualified to start with.
540+ */
541+ public final Identifier resolvePackageQualifiedName(Identifier name) {
542+ Identifier tail = null;
543+ for (;;) {
544+ if (classExists(name)) {
545+ break;
546+ }
547+ if (!name.isQualified()) {
548+ name = (tail == null) ? name : Identifier.lookup(name, tail);
549+ tail = null;
550+ break;
551+ }
552+ Identifier nm = name.getName();
553+ tail = (tail == null)? nm: Identifier.lookup(nm, tail);
554+ name = name.getQualifier();
555+ }
556+ if (tail != null)
557+ name = Identifier.lookupInner(name, tail);
558+ return name;
559+ }
560+
561+ /**
562+ * Resolve a class name, using only package and import directives.
563+ */
564+ public Identifier resolve(Identifier nm) throws ClassNotFound {
565+ if (env == null) return nm; // a pretty useless no-op
566+ return env.resolve(nm);
567+ }
568+
569+ /**
570+ * Get the imports used to resolve class names.
571+ */
572+ public Imports getImports() {
573+ if (env == null) return null; // lame default
574+ return env.getImports();
575+ }
576+
577+ /**
578+ * Create a new class.
579+ */
580+ public ClassDefinition makeClassDefinition(Environment origEnv, long where,
581+ IdentifierToken name,
582+ String doc, int modifiers,
583+ IdentifierToken superClass,
584+ IdentifierToken interfaces[],
585+ ClassDefinition outerClass) {
586+ if (env == null) return null; // lame default
587+ return env.makeClassDefinition(origEnv, where, name,
588+ doc, modifiers,
589+ superClass, interfaces, outerClass);
590+ }
591+
592+ /**
593+ * Create a new field.
594+ */
595+ public MemberDefinition makeMemberDefinition(Environment origEnv, long where,
596+ ClassDefinition clazz,
597+ String doc, int modifiers,
598+ Type type, Identifier name,
599+ IdentifierToken argNames[],
600+ IdentifierToken expIds[],
601+ Object value) {
602+ if (env == null) return null; // lame default
603+ return env.makeMemberDefinition(origEnv, where, clazz, doc, modifiers,
604+ type, name, argNames, expIds, value);
605+ }
606+
607+ /**
608+ * Returns true if the given method is applicable to the given arguments
609+ */
610+
611+ public boolean isApplicable(MemberDefinition m, Type args[]) throws ClassNotFound {
612+ Type mType = m.getType();
613+ if (!mType.isType(TC_METHOD))
614+ return false;
615+ Type mArgs[] = mType.getArgumentTypes();
616+ if (args.length != mArgs.length)
617+ return false;
618+ for (int i = args.length ; --i >= 0 ;)
619+ if (!isMoreSpecific(args[i], mArgs[i]))
620+ return false;
621+ return true;
622+ }
623+
624+
625+ /**
626+ * Returns true if "best" is in every argument at least as good as "other"
627+ */
628+ public boolean isMoreSpecific(MemberDefinition best, MemberDefinition other)
629+ throws ClassNotFound {
630+ Type bestType = best.getClassDeclaration().getType();
631+ Type otherType = other.getClassDeclaration().getType();
632+ boolean result = isMoreSpecific(bestType, otherType)
633+ && isApplicable(other, best.getType().getArgumentTypes());
634+ // System.out.println("isMoreSpecific: " + best + "/" + other
635+ // + " => " + result);
636+ return result;
637+ }
638+
639+ /**
640+ * Returns true if "from" is a more specific type than "to"
641+ */
642+
643+ public boolean isMoreSpecific(Type from, Type to) throws ClassNotFound {
644+ return implicitCast(from, to);
645+ }
646+
647+ /**
648+ * Return true if an implicit cast from this type to
649+ * the given type is allowed.
650+ */
651+ public boolean implicitCast(Type from, Type to) throws ClassNotFound {
652+ if (from == to)
653+ return true;
654+
655+ int toTypeCode = to.getTypeCode();
656+
657+ switch(from.getTypeCode()) {
658+ case TC_BYTE:
659+ if (toTypeCode == TC_SHORT)
660+ return true;
661+ case TC_SHORT:
662+ case TC_CHAR:
663+ if (toTypeCode == TC_INT) return true;
664+ case TC_INT:
665+ if (toTypeCode == TC_LONG) return true;
666+ case TC_LONG:
667+ if (toTypeCode == TC_FLOAT) return true;
668+ case TC_FLOAT:
669+ if (toTypeCode == TC_DOUBLE) return true;
670+ case TC_DOUBLE:
671+ default:
672+ return false;
673+
674+ case TC_NULL:
675+ return to.inMask(TM_REFERENCE);
676+
677+ case TC_ARRAY:
678+ if (!to.isType(TC_ARRAY)) {
679+ return (to == Type.tObject || to == Type.tCloneable
680+ || to == Type.tSerializable);
681+ } else {
682+ // both are arrays. recurse down both until one isn't an array
683+ do {
684+ from = from.getElementType();
685+ to = to.getElementType();
686+ } while (from.isType(TC_ARRAY) && to.isType(TC_ARRAY));
687+ if ( from.inMask(TM_ARRAY|TM_CLASS)
688+ && to.inMask(TM_ARRAY|TM_CLASS)) {
689+ return isMoreSpecific(from, to);
690+ } else {
691+ return (from.getTypeCode() == to.getTypeCode());
692+ }
693+ }
694+
695+ case TC_CLASS:
696+ if (toTypeCode == TC_CLASS) {
697+ ClassDefinition fromDef = getClassDefinition(from);
698+ ClassDefinition toDef = getClassDefinition(to);
699+ return toDef.implementedBy(this,
700+ fromDef.getClassDeclaration());
701+ } else {
702+ return false;
703+ }
704+ }
705+ }
706+
707+
708+ /**
709+ * Return true if an explicit cast from this type to
710+ * the given type is allowed.
711+ */
712+ public boolean explicitCast(Type from, Type to) throws ClassNotFound {
713+ if (implicitCast(from, to)) {
714+ return true;
715+ }
716+ if (from.inMask(TM_NUMBER)) {
717+ return to.inMask(TM_NUMBER);
718+ }
719+ if (from.isType(TC_CLASS) && to.isType(TC_CLASS)) {
720+ ClassDefinition fromClass = getClassDefinition(from);
721+ ClassDefinition toClass = getClassDefinition(to);
722+ if (toClass.isFinal()) {
723+ return fromClass.implementedBy(this,
724+ toClass.getClassDeclaration());
725+ }
726+ if (fromClass.isFinal()) {
727+ return toClass.implementedBy(this,
728+ fromClass.getClassDeclaration());
729+ }
730+
731+ // The code here used to omit this case. If both types
732+ // involved in a cast are interfaces, then JLS 5.5 requires
733+ // that we do a simple test -- make sure none of the methods
734+ // in toClass and fromClass have the same signature but
735+ // different return types. (bug number 4028359)
736+ if (toClass.isInterface() && fromClass.isInterface()) {
737+ return toClass.couldImplement(fromClass);
738+ }
739+
740+ return toClass.isInterface() ||
741+ fromClass.isInterface() ||
742+ fromClass.superClassOf(this, toClass.getClassDeclaration());
743+ }
744+ if (to.isType(TC_ARRAY)) {
745+ if (from.isType(TC_ARRAY)) {
746+ Type t1 = from.getElementType();
747+ Type t2 = to.getElementType();
748+ while ((t1.getTypeCode() == TC_ARRAY)
749+ && (t2.getTypeCode() == TC_ARRAY)) {
750+ t1 = t1.getElementType();
751+ t2 = t2.getElementType();
752+ }
753+ if (t1.inMask(TM_ARRAY|TM_CLASS) &&
754+ t2.inMask(TM_ARRAY|TM_CLASS)) {
755+ return explicitCast(t1, t2);
756+ }
757+ } else if (from == Type.tObject || from == Type.tCloneable
758+ || from == Type.tSerializable)
759+ return true;
760+ }
761+ return false;
762+ }
763+
764+ /**
765+ * Flags.
766+ */
767+ public int getFlags() {
768+ return env.getFlags();
769+ }
770+
771+ /**
772+ * Debugging flags. There used to be a method debug()
773+ * that has been replaced because -g has changed meaning
774+ * (it now cooperates with -O and line number, variable
775+ * range and source file info can be toggled separately).
776+ */
777+ public final boolean debug_lines() {
778+ return (getFlags() & F_DEBUG_LINES) != 0;
779+ }
780+ public final boolean debug_vars() {
781+ return (getFlags() & F_DEBUG_VARS) != 0;
782+ }
783+ public final boolean debug_source() {
784+ return (getFlags() & F_DEBUG_SOURCE) != 0;
785+ }
786+
787+ /**
788+ * Optimization flags. There used to be a method optimize()
789+ * that has been replaced because -O has changed meaning in
790+ * javac to be replaced with -O and -O:interclass.
791+ */
792+ public final boolean opt() {
793+ return (getFlags() & F_OPT) != 0;
794+ }
795+ public final boolean opt_interclass() {
796+ return (getFlags() & F_OPT_INTERCLASS) != 0;
797+ }
798+
799+ /**
800+ * Verbose
801+ */
802+ public final boolean verbose() {
803+ return (getFlags() & F_VERBOSE) != 0;
804+ }
805+
806+ /**
807+ * Dump debugging stuff
808+ */
809+ public final boolean dump() {
810+ return (getFlags() & F_DUMP) != 0;
811+ }
812+
813+ /**
814+ * Verbose
815+ */
816+ public final boolean warnings() {
817+ return (getFlags() & F_WARNINGS) != 0;
818+ }
819+
820+ /**
821+ * Dependencies
822+ */
823+ public final boolean dependencies() {
824+ return (getFlags() & F_DEPENDENCIES) != 0;
825+ }
826+
827+ /**
828+ * Print Dependencies to stdout
829+ */
830+ public final boolean print_dependencies() {
831+ return (getFlags() & F_PRINT_DEPENDENCIES) != 0;
832+ }
833+
834+ /**
835+ * Deprecation warnings are enabled.
836+ */
837+ public final boolean deprecation() {
838+ return (getFlags() & F_DEPRECATION) != 0;
839+ }
840+
841+ /**
842+ * Do not support virtual machines before version 1.2.
843+ * This option is not supported and is only here for testing purposes.
844+ */
845+ public final boolean version12() {
846+ return (getFlags() & F_VERSION12) != 0;
847+ }
848+
849+ /**
850+ * Floating point is strict by default
851+ */
852+ public final boolean strictdefault() {
853+ return (getFlags() & F_STRICTDEFAULT) != 0;
854+ }
855+
856+ /**
857+ * Release resources, if any.
858+ */
859+ public void shutdown() {
860+ if (env != null) {
861+ env.shutdown();
862+ }
863+ }
864+
865+ /**
866+ * Issue an error.
867+ * source - the input source, usually a file name string
868+ * offset - the offset in the source of the error
869+ * err - the error number (as defined in this interface)
870+ * arg1 - an optional argument to the error (null if not applicable)
871+ * arg2 - a second optional argument to the error (null if not applicable)
872+ * arg3 - a third optional argument to the error (null if not applicable)
873+ */
874+ public void error(Object source, long where, String err, Object arg1, Object arg2, Object arg3) {
875+ env.error(source, where, err, arg1, arg2, arg3);
876+ }
877+ public final void error(long where, String err, Object arg1, Object arg2, Object arg3) {
878+ error(source, where, err, arg1, arg2, arg3);
879+ }
880+ public final void error(long where, String err, Object arg1, Object arg2) {
881+ error(source, where, err, arg1, arg2, null);
882+ }
883+ public final void error(long where, String err, Object arg1) {
884+ error(source, where, err, arg1, null, null);
885+ }
886+ public final void error(long where, String err) {
887+ error(source, where, err, null, null, null);
888+ }
889+
890+ /**
891+ * Output a string. This can either be an error message or something
892+ * for debugging. This should be used instead of println.
893+ */
894+ public void output(String msg) {
895+ env.output(msg);
896+ }
897+
898+ private static boolean debugging = (System.getProperty("javac.debug") != null);
899+
900+ public static void debugOutput(Object msg) {
901+ if (Environment.debugging)
902+ System.out.println(msg.toString());
903+ }
904+
905+ /**
906+ * set character encoding name
907+ */
908+ public void setCharacterEncoding(String encoding) {
909+ this.encoding = encoding;
910+ }
911+
912+ /**
913+ * Return character encoding name
914+ */
915+ public String getCharacterEncoding() {
916+ return encoding;
917+ }
918+
919+ /**
920+ * Return major version to use in generated class files.
921+ */
922+ public short getMajorVersion() {
923+ if (env==null) return JAVA_DEFAULT_VERSION; // needed for javah
924+ return env.getMajorVersion();
925+ }
926+
927+ /**
928+ * Return minor version to use in generated class files.
929+ */
930+ public short getMinorVersion() {
931+ if (env==null) return JAVA_DEFAULT_MINOR_VERSION; // needed for javah
932+ return env.getMinorVersion();
933+ }
934+
935+// JCOV
936+ /**
937+ * get coverage flag
938+ */
939+ public final boolean coverage() {
940+ return (getFlags() & F_COVERAGE) != 0;
941+ }
942+
943+ /**
944+ * get flag of generation the coverage data file
945+ */
946+ public final boolean covdata() {
947+ return (getFlags() & F_COVDATA) != 0;
948+ }
949+
950+ /**
951+ * Return the coverage data file
952+ */
953+ public File getcovFile() {
954+ return env.getcovFile();
955+ }
956+
957+// end JCOV
958+
959+ /**
960+ * Debug tracing.
961+ * Currently, this code is used only for tracing the loading and
962+ * checking of classes, particularly the demand-driven aspects.
963+ * This code should probably be integrated with 'debugOutput' above,
964+ * but we need to give more thought to the issue of classifying debugging
965+ * messages and allowing those only those of interest to be enabled.
966+ *
967+ * Calls to these methods are generally conditioned on the final variable
968+ * 'Constants.tracing', which allows the calls to be completely omitted
969+ * in a production release to avoid space and time overhead.
970+ */
971+
972+ private static boolean dependtrace =
973+ (System.getProperty("javac.trace.depend") != null);
974+
975+ public void dtEnter(String s) {
976+ if (dependtrace) System.out.println(">>> " + s);
977+ }
978+
979+ public void dtExit(String s) {
980+ if (dependtrace) System.out.println("<<< " + s);
981+ }
982+
983+ public void dtEvent(String s) {
984+ if (dependtrace) System.out.println(s);
985+ }
986+
987+ /**
988+ * Enable diagnostic dump of class modifier bits, including those
989+ * in InnerClasses attributes, as they are written to the classfile.
990+ * In the future, may also enable dumping field and method modifiers.
991+ */
992+
993+ private static boolean dumpmodifiers =
994+ (System.getProperty("javac.dump.modifiers") != null);
995+
996+ public boolean dumpModifiers() { return dumpmodifiers; }
997+
998+}
java/pkg/sun/tools/java/Identifier.java+329−0
@@ -0,0 +1,329 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.util.Hashtable;
29+import java.io.PrintStream;
30+import java.util.Enumeration;
31+
32+/**
33+ * A class to represent identifiers.<p>
34+ *
35+ * An identifier instance is very similar to a String. The difference
36+ * is that identifier can't be instanciated directly, instead they are
37+ * looked up in a hash table. This means that identifiers with the same
38+ * name map to the same identifier object. This makes comparisons of
39+ * identifiers much faster.<p>
40+ *
41+ * A lot of identifiers are qualified, that is they have '.'s in them.
42+ * Each qualified identifier is chopped up into the qualifier and the
43+ * name. The qualifier is cached in the value field.<p>
44+ *
45+ * Unqualified identifiers can have a type. This type is an integer that
46+ * can be used by a scanner as a token value. This value has to be set
47+ * using the setType method.<p>
48+ *
49+ * WARNING: The contents of this source file are not part of any
50+ * supported API. Code that depends on them does so at its own risk:
51+ * they are subject to change or removal without notice.
52+ *
53+ * @author Arthur van Hoff
54+ */
55+
56+public final
57+class Identifier implements Constants {
58+ /**
59+ * The hashtable of identifiers
60+ */
61+ static Hashtable hash = new Hashtable(3001, 0.5f);
62+
63+ /**
64+ * The name of the identifier
65+ */
66+ String name;
67+
68+ /**
69+ * The value of the identifier, for keywords this is an
70+ * instance of class Integer, for qualified names this is
71+ * another identifier (the qualifier).
72+ */
73+ Object value;
74+
75+ /**
76+ * The Type which corresponds to this Identifier. This is used as
77+ * cache for Type.tClass() and shouldn't be used outside of that
78+ * context.
79+ */
80+ Type typeObject = null;
81+
82+ /**
83+ * The index of INNERCLASS_PREFIX in the name, or -1 if none.
84+ */
85+ private int ipos;
86+
87+ /**
88+ * Construct an identifier. Don't call this directly,
89+ * use lookup instead.
90+ * @see Identifier.lookup
91+ */
92+ private Identifier(String name) {
93+ this.name = name;
94+ this.ipos = name.indexOf(INNERCLASS_PREFIX);
95+ }
96+
97+ /**
98+ * Get the type of the identifier.
99+ */
100+ int getType() {
101+ return ((value != null) && (value instanceof Integer)) ?
102+ ((Integer)value).intValue() : IDENT;
103+ }
104+
105+ /**
106+ * Set the type of the identifier.
107+ */
108+ void setType(int t) {
109+ value = new Integer(t);
110+ //System.out.println("type(" + this + ")=" + t);
111+ }
112+
113+ /**
114+ * Lookup an identifier.
115+ */
116+ public static synchronized Identifier lookup(String s) {
117+ //System.out.println("lookup(" + s + ")");
118+ Identifier id = (Identifier)hash.get(s);
119+ if (id == null) {
120+ hash.put(s, id = new Identifier(s));
121+ }
122+ return id;
123+ }
124+
125+ /**
126+ * Lookup a qualified identifier.
127+ */
128+ public static Identifier lookup(Identifier q, Identifier n) {
129+ // lookup("", x) => x
130+ if (q == idNull) return n;
131+ // lookup(lookupInner(c, ""), n) => lookupInner(c, lookup("", n))
132+ if (q.name.charAt(q.name.length()-1) == INNERCLASS_PREFIX)
133+ return lookup(q.name+n.name);
134+ Identifier id = lookup(q + "." + n);
135+ if (!n.isQualified() && !q.isInner())
136+ id.value = q;
137+ return id;
138+ }
139+
140+ /**
141+ * Lookup an inner identifier.
142+ * (Note: n can be idNull.)
143+ */
144+ public static Identifier lookupInner(Identifier c, Identifier n) {
145+ Identifier id;
146+ if (c.isInner()) {
147+ if (c.name.charAt(c.name.length()-1) == INNERCLASS_PREFIX)
148+ id = lookup(c.name+n);
149+ else
150+ id = lookup(c, n);
151+ } else {
152+ id = lookup(c + "." + INNERCLASS_PREFIX + n);
153+ }
154+ id.value = c.value;
155+ return id;
156+ }
157+
158+ /**
159+ * Convert to a string.
160+ */
161+ public String toString() {
162+ return name;
163+ }
164+
165+ /**
166+ * Check if the name is qualified (ie: it contains a '.').
167+ */
168+ public boolean isQualified() {
169+ if (value == null) {
170+ int idot = ipos;
171+ if (idot <= 0)
172+ idot = name.length();
173+ else
174+ idot -= 1; // back up over previous dot
175+ int index = name.lastIndexOf('.', idot-1);
176+ value = (index < 0) ? idNull : Identifier.lookup(name.substring(0, index));
177+ }
178+ return (value instanceof Identifier) && (value != idNull);
179+ }
180+
181+ /**
182+ * Return the qualifier. The null identifier is returned if
183+ * the name was not qualified. The qualifier does not include
184+ * any inner part of the name.
185+ */
186+ public Identifier getQualifier() {
187+ return isQualified() ? (Identifier)value : idNull;
188+ }
189+
190+ /**
191+ * Return the unqualified name.
192+ * In the case of an inner name, the unqualified name
193+ * will itself contain components.
194+ */
195+ public Identifier getName() {
196+ return isQualified() ?
197+ Identifier.lookup(name.substring(((Identifier)value).name.length() + 1)) : this;
198+ }
199+
200+ /** A space character, which precedes the first inner class
201+ * name in a qualified name, and thus marks the qualification
202+ * as involving inner classes, instead of merely packages.<p>
203+ * Ex: <tt>java.util.Vector. Enumerator</tt>.
204+ */
205+ public static final char INNERCLASS_PREFIX = ' ';
206+
207+ /* Explanation:
208+ * Since much of the compiler's low-level name resolution code
209+ * operates in terms of Identifier objects. This includes the
210+ * code which walks around the file system and reports what
211+ * classes are where. It is important to get nesting information
212+ * right as early as possible, since it affects the spelling of
213+ * signatures. Thus, the low-level import and resolve code must
214+ * be able Identifier type must be able to report the nesting
215+ * of types, which implied that that information must be carried
216+ * by Identifiers--or that the low-level interfaces be significantly
217+ * changed.
218+ */
219+
220+ /**
221+ * Check if the name is inner (ie: it contains a ' ').
222+ */
223+ public boolean isInner() {
224+ return (ipos > 0);
225+ }
226+
227+ /**
228+ * Return the class name, without its qualifier,
229+ * and with any nesting flattened into a new qualfication structure.
230+ * If the original identifier is inner,
231+ * the result will be qualified, and can be further
232+ * decomposed by means of <tt>getQualifier</tt> and <tt>getName</tt>.
233+ * <p>
234+ * For example:
235+ * <pre>
236+ * Identifier id = Identifier.lookup("pkg.Foo. Bar");
237+ * id.getName().name => "Foo. Bar"
238+ * id.getFlatName().name => "Foo.Bar"
239+ * </pre>
240+ */
241+ public Identifier getFlatName() {
242+ if (isQualified()) {
243+ return getName().getFlatName();
244+ }
245+ if (ipos > 0 && name.charAt(ipos-1) == '.') {
246+ if (ipos+1 == name.length()) {
247+ // last component is idNull
248+ return Identifier.lookup(name.substring(0,ipos-1));
249+ }
250+ String n = name.substring(ipos+1);
251+ String t = name.substring(0,ipos);
252+ return Identifier.lookup(t+n);
253+ }
254+ // Not inner. Just return the same as getName()
255+ return this;
256+ }
257+
258+ public Identifier getTopName() {
259+ if (!isInner()) return this;
260+ return Identifier.lookup(getQualifier(), getFlatName().getHead());
261+ }
262+
263+ /**
264+ * Yet another way to slice qualified identifiers:
265+ * The head of an identifier is its first qualifier component,
266+ * and the tail is the rest of them.
267+ */
268+ public Identifier getHead() {
269+ Identifier id = this;
270+ while (id.isQualified())
271+ id = id.getQualifier();
272+ return id;
273+ }
274+
275+ /**
276+ * @see getHead
277+ */
278+ public Identifier getTail() {
279+ Identifier id = getHead();
280+ if (id == this)
281+ return idNull;
282+ else
283+ return Identifier.lookup(name.substring(id.name.length() + 1));
284+ }
285+
286+ // Unfortunately, the current structure of the compiler requires
287+ // that the resolveName() family of methods (which appear in
288+ // Environment.java, Context.java, and ClassDefinition.java) raise
289+ // no exceptions and emit no errors. When we are in resolveName()
290+ // and we find a method that is ambiguous, we need to
291+ // unambiguously mark it as such, so that later stages of the
292+ // compiler realize that they should give an ambig.class rather than
293+ // a class.not.found error. To mark it we add a special prefix
294+ // which cannot occur in the program source. The routines below
295+ // are used to check, add, and remove this prefix.
296+ // (part of solution for 4059855).
297+
298+ /**
299+ * A special prefix to add to ambiguous names.
300+ */
301+ private static final String ambigPrefix = "<<ambiguous>>";
302+
303+ /**
304+ * Determine whether an Identifier has been marked as ambiguous.
305+ */
306+ public boolean hasAmbigPrefix() {
307+ return (name.startsWith(ambigPrefix));
308+ }
309+
310+ /**
311+ * Add ambigPrefix to `this' to make a new Identifier marked as
312+ * ambiguous. It is important that this new Identifier not refer
313+ * to an existing class.
314+ */
315+ public Identifier addAmbigPrefix() {
316+ return Identifier.lookup(ambigPrefix + name);
317+ }
318+
319+ /**
320+ * Remove the ambigPrefix from `this' to get the original identifier.
321+ */
322+ public Identifier removeAmbigPrefix() {
323+ if (hasAmbigPrefix()) {
324+ return Identifier.lookup(name.substring(ambigPrefix.length()));
325+ } else {
326+ return this;
327+ }
328+ }
329+}
java/pkg/sun/tools/java/IdentifierToken.java+91−0
@@ -0,0 +1,91 @@
1+/*
2+ * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+/**
29+ * Information about the occurrence of an identifier.
30+ * The parser produces these to represent name which cannot yet be
31+ * bound to field definitions.
32+ *
33+ * WARNING: The contents of this source file are not part of any
34+ * supported API. Code that depends on them does so at its own risk:
35+ * they are subject to change or removal without notice.
36+ *
37+ * @see
38+ */
39+
40+public
41+class IdentifierToken {
42+ long where;
43+ int modifiers;
44+ Identifier id;
45+
46+ public IdentifierToken(long where, Identifier id) {
47+ this.where = where;
48+ this.id = id;
49+ }
50+
51+ /** Use this constructor when the identifier is synthesized.
52+ * The location will be 0.
53+ */
54+ public IdentifierToken(Identifier id) {
55+ this.where = 0;
56+ this.id = id;
57+ }
58+
59+ public IdentifierToken(long where, Identifier id, int modifiers) {
60+ this.where = where;
61+ this.id = id;
62+ this.modifiers = modifiers;
63+ }
64+
65+ /** The source location of this identifier occurrence. */
66+ public long getWhere() {
67+ return where;
68+ }
69+
70+ /** The identifier itself (possibly qualified). */
71+ public Identifier getName() {
72+ return id;
73+ }
74+
75+ /** The modifiers associated with the occurrence, if any. */
76+ public int getModifiers() {
77+ return modifiers;
78+ }
79+
80+ public String toString() {
81+ return id.toString();
82+ }
83+
84+ /**
85+ * Return defaultWhere if id is null or id.where is missing (0).
86+ * Otherwise, return id.where.
87+ */
88+ public static long getWhere(IdentifierToken id, long defaultWhere) {
89+ return (id != null && id.where != 0) ? id.where : defaultWhere;
90+ }
91+}
java/pkg/sun/tools/java/Imports.java+503−0
@@ -0,0 +1,503 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.util.Hashtable;
29+import java.util.Vector;
30+import java.util.Enumeration;
31+import java.util.List;
32+import java.util.Collections;
33+import java.io.IOException;
34+
35+/**
36+ * This class describes the classes and packages imported
37+ * from a source file. A Hashtable called bindings is maintained
38+ * to quickly map symbol names to classes. This table is flushed
39+ * everytime a new import is added.
40+ *
41+ * A class name is resolved as follows:
42+ * - if it is a qualified name then return the corresponding class
43+ * - if the name corresponds to an individually imported class then return that class
44+ * - check if the class is defined in any of the imported packages,
45+ * if it is then return it, make sure it is defined in only one package
46+ * - assume that the class is defined in the current package
47+ *
48+ * WARNING: The contents of this source file are not part of any
49+ * supported API. Code that depends on them does so at its own risk:
50+ * they are subject to change or removal without notice.
51+ */
52+
53+public
54+class Imports implements Constants {
55+ /**
56+ * The current package, which is implicitly imported,
57+ * and has precedence over other imported packages.
58+ */
59+ Identifier currentPackage = idNull;
60+
61+ /**
62+ * A location for the current package declaration. Used to
63+ * report errors against the current package.
64+ */
65+ long currentPackageWhere = 0;
66+
67+ /**
68+ * The imported classes, including memoized imports from packages.
69+ */
70+ Hashtable classes = new Hashtable();
71+
72+ /**
73+ * The imported package identifiers. This will not contain duplicate
74+ * imports for the same package. It will also not contain the
75+ * current package.
76+ */
77+ Vector packages = new Vector();
78+
79+ /**
80+ * The (originally) imported classes.
81+ * A vector of IdentifierToken.
82+ */
83+ Vector singles = new Vector();
84+
85+ /**
86+ * Are the import names checked yet?
87+ */
88+ protected int checked;
89+
90+ /**
91+ * Constructor, always import java.lang.
92+ */
93+ public Imports(Environment env) {
94+ addPackage(idJavaLang);
95+ }
96+
97+ /**
98+ * Check the names of the imports.
99+ */
100+ public synchronized void resolve(Environment env) {
101+ if (checked != 0) {
102+ return;
103+ }
104+ checked = -1;
105+
106+ // After all class information has been read, now we can
107+ // safely inspect import information for errors.
108+ // If we did this before all parsing was finished,
109+ // we could get vicious circularities, since files can
110+ // import each others' classes.
111+
112+ // A note: the resolution of the package java.lang takes place
113+ // in the sun.tools.javac.BatchEnvironment#setExemptPackages().
114+
115+ // Make sure that the current package's name does not collide
116+ // with the name of an existing class. (bug 4101529)
117+ //
118+ // This change has been backed out because, on WIN32, it
119+ // failed to distinguish between java.awt.event and
120+ // java.awt.Event when looking for a directory. We will
121+ // add this back in later.
122+ //
123+ // if (currentPackage != idNull) {
124+ // Identifier resolvedName =
125+ // env.resolvePackageQualifiedName(currentPackage);
126+ //
127+ // Identifier className = resolvedName.getTopName();
128+ //
129+ // if (importable(className, env)) {
130+ // // The name of the current package is also the name
131+ // // of a class.
132+ // env.error(currentPackageWhere, "package.class.conflict",
133+ // currentPackage, className);
134+ // }
135+ // }
136+
137+ Vector resolvedPackages = new Vector();
138+ for (Enumeration e = packages.elements() ; e.hasMoreElements() ;) {
139+ IdentifierToken t = (IdentifierToken)e.nextElement();
140+ Identifier nm = t.getName();
141+ long where = t.getWhere();
142+
143+ // Check to see if this package is exempt from the "exists"
144+ // check. See the note in
145+ // sun.tools.javac.BatchEnvironment#setExemptPackages()
146+ // for more information.
147+ if (env.isExemptPackage(nm)) {
148+ resolvedPackages.addElement(t);
149+ continue;
150+ }
151+
152+ // (Note: This code is moved from BatchParser.importPackage().)
153+ try {
154+ Identifier rnm = env.resolvePackageQualifiedName(nm);
155+ if (importable(rnm, env)) {
156+ // This name is a real class; better not be a package too.
157+ if (env.getPackage(rnm.getTopName()).exists()) {
158+ env.error(where, "class.and.package",
159+ rnm.getTopName());
160+ }
161+ // Pass an "inner" name to the imports.
162+ if (!rnm.isInner())
163+ rnm = Identifier.lookupInner(rnm, idNull);
164+ nm = rnm;
165+ } else if (!env.getPackage(nm).exists()) {
166+ env.error(where, "package.not.found", nm, "import");
167+ } else if (rnm.isInner()) {
168+ // nm exists, and rnm.getTopName() is a parent package
169+ env.error(where, "class.and.package", rnm.getTopName());
170+ }
171+ resolvedPackages.addElement(new IdentifierToken(where, nm));
172+ } catch (IOException ee) {
173+ env.error(where, "io.exception", "import");
174+ }
175+ }
176+ packages = resolvedPackages;
177+
178+ for (Enumeration e = singles.elements() ; e.hasMoreElements() ;) {
179+ IdentifierToken t = (IdentifierToken)e.nextElement();
180+ Identifier nm = t.getName();
181+ long where = t.getWhere();
182+ Identifier pkg = nm.getQualifier();
183+
184+ // (Note: This code is moved from BatchParser.importClass().)
185+ nm = env.resolvePackageQualifiedName(nm);
186+ if (!env.classExists(nm.getTopName())) {
187+ env.error(where, "class.not.found", nm, "import");
188+ }
189+
190+ // (Note: This code is moved from Imports.addClass().)
191+ Identifier snm = nm.getFlatName().getName();
192+
193+ // make sure it isn't already imported explicitly
194+ Identifier className = (Identifier)classes.get(snm);
195+ if (className != null) {
196+ Identifier f1 = Identifier.lookup(className.getQualifier(),
197+ className.getFlatName());
198+ Identifier f2 = Identifier.lookup(nm.getQualifier(),
199+ nm.getFlatName());
200+ if (!f1.equals(f2)) {
201+ env.error(where, "ambig.class", nm, className);
202+ }
203+ }
204+ classes.put(snm, nm);
205+
206+
207+ // The code here needs to check to see, if we
208+ // are importing an inner class, that all of its
209+ // enclosing classes are visible to us. To check this,
210+ // we need to construct a definition for the class.
211+ // The code here used to call...
212+ //
213+ // ClassDefinition def = env.getClassDefinition(nm);
214+ //
215+ // ...but that interfered with the basicCheck()'ing of
216+ // interfaces in certain cases (bug no. 4086139). Never
217+ // fear. Instead we load the class with a call to the
218+ // new getClassDefinitionNoCheck() which does no basicCheck() and
219+ // lets us answer the questions we are interested in w/o
220+ // interfering with the demand-driven nature of basicCheck().
221+
222+ try {
223+ // Get a declaration
224+ ClassDeclaration decl = env.getClassDeclaration(nm);
225+
226+ // Get the definition (no env argument)
227+ ClassDefinition def = decl.getClassDefinitionNoCheck(env);
228+
229+ // Get the true name of the package containing this class.
230+ // `pkg' from above is insufficient. It includes the
231+ // names of our enclosing classes. Fix for 4086815.
232+ Identifier importedPackage = def.getName().getQualifier();
233+
234+ // Walk out the outerClass chain, ensuring that each level
235+ // is visible from our perspective.
236+ for (; def != null; def = def.getOuterClass()) {
237+ if (def.isPrivate()
238+ || !(def.isPublic()
239+ || importedPackage.equals(currentPackage))) {
240+ env.error(where, "cant.access.class", def);
241+ break;
242+ }
243+ }
244+ } catch (AmbiguousClass ee) {
245+ env.error(where, "ambig.class", ee.name1, ee.name2);
246+ } catch (ClassNotFound ee) {
247+ env.error(where, "class.not.found", ee.name, "import");
248+ }
249+ }
250+ checked = 1;
251+ }
252+
253+ /**
254+ * Lookup a class, given the current set of imports,
255+ * AmbiguousClass exception is thrown if the name can be
256+ * resolved in more than one way. A ClassNotFound exception
257+ * is thrown if the class is not found in the imported classes
258+ * and packages.
259+ */
260+ public synchronized Identifier resolve(Environment env, Identifier nm) throws ClassNotFound {
261+ if (tracing) env.dtEnter("Imports.resolve: " + nm);
262+
263+ // If the class has the special ambiguous prefix, then we will
264+ // get the original AmbiguousClass exception by removing the
265+ // prefix and proceeding in the normal fashion.
266+ // (part of solution for 4059855)
267+ if (nm.hasAmbigPrefix()) {
268+ nm = nm.removeAmbigPrefix();
269+ }
270+
271+ if (nm.isQualified()) {
272+ // Don't bother it is already qualified
273+ if (tracing) env.dtExit("Imports.resolve: QUALIFIED " + nm);
274+ return nm;
275+ }
276+
277+ if (checked <= 0) {
278+ checked = 0;
279+ resolve(env);
280+ }
281+
282+ // Check if it was imported before
283+ Identifier className = (Identifier)classes.get(nm);
284+ if (className != null) {
285+ if (tracing) env.dtExit("Imports.resolve: PREVIOUSLY IMPORTED " + nm);
286+ return className;
287+ }
288+
289+ // Note: the section below has changed a bit during the fix
290+ // for bug 4093217. The current package is no longer grouped
291+ // with the rest of the import-on-demands; it is now checked
292+ // separately. Also, the list of import-on-demands is now
293+ // guarranteed to be duplicate-free, so the code below can afford
294+ // to be a bit simpler.
295+
296+ // First we look in the current package. The current package
297+ // is given precedence over the rest of the import-on-demands,
298+ // which means, among other things, that a class in the current
299+ // package cannot be ambiguous.
300+ Identifier id = Identifier.lookup(currentPackage, nm);
301+ if (importable(id, env)) {
302+ className = id;
303+ } else {
304+ // If it isn't in the current package, try to find it in
305+ // our import-on-demands.
306+ Enumeration e = packages.elements();
307+ while (e.hasMoreElements()) {
308+ IdentifierToken t = (IdentifierToken)e.nextElement();
309+ id = Identifier.lookup(t.getName(), nm);
310+
311+ if (importable(id, env)) {
312+ if (className == null) {
313+ // We haven't found any other matching classes yet.
314+ // Set className to what we've found and continue
315+ // looking for an ambiguity.
316+ className = id;
317+ } else {
318+ if (tracing)
319+ env.dtExit("Imports.resolve: AMBIGUOUS " + nm);
320+
321+ // We've found an ambiguity.
322+ throw new AmbiguousClass(className, id);
323+ }
324+ }
325+ }
326+ }
327+
328+ // Make sure a class was found
329+ if (className == null) {
330+ if (tracing) env.dtExit("Imports.resolve: NOT FOUND " + nm);
331+ throw new ClassNotFound(nm);
332+ }
333+
334+ // Remember the binding
335+ classes.put(nm, className);
336+ if (tracing) env.dtExit("Imports.resolve: FIRST IMPORT " + nm);
337+ return className;
338+ }
339+
340+ /**
341+ * Check to see if 'id' names an importable class in `env'.
342+ * This method was made public and static for utility.
343+ */
344+ static public boolean importable(Identifier id, Environment env) {
345+ if (!id.isInner()) {
346+ return env.classExists(id);
347+ } else if (!env.classExists(id.getTopName())) {
348+ return false;
349+ } else {
350+ // load the top class and look inside it
351+ try {
352+ // There used to be a call to...
353+ // env.getClassDeclaration(id.getTopName());
354+ // ...here. It has been replaced with the
355+ // two statements below. These should be functionally
356+ // the same except for the fact that
357+ // getClassDefinitionNoCheck() does not call
358+ // basicCheck(). This allows us to avoid a circular
359+ // need to do basicChecking that can arise with
360+ // certain patterns of importing and inheritance.
361+ // This is a fix for a variant of bug 4086139.
362+ //
363+ // Note: the special case code in env.getClassDefinition()
364+ // which handles inner class names is not replicated below.
365+ // This should be okay, as we are looking up id.getTopName(),
366+ // not id.
367+ ClassDeclaration decl =
368+ env.getClassDeclaration(id.getTopName());
369+ ClassDefinition c =
370+ decl.getClassDefinitionNoCheck(env);
371+
372+ return c.innerClassExists(id.getFlatName().getTail());
373+ } catch (ClassNotFound ee) {
374+ return false;
375+ }
376+ }
377+ }
378+
379+ /**
380+ * Suppose a resolve() call has failed.
381+ * This routine can be used silently to give a reasonable
382+ * default qualification (the current package) to the identifier.
383+ * This decision is recorded for future reference.
384+ */
385+ public synchronized Identifier forceResolve(Environment env, Identifier nm) {
386+ if (nm.isQualified())
387+ return nm;
388+
389+ Identifier className = (Identifier)classes.get(nm);
390+ if (className != null) {
391+ return className;
392+ }
393+
394+ className = Identifier.lookup(currentPackage, nm);
395+
396+ classes.put(nm, className);
397+ return className;
398+ }
399+
400+ /**
401+ * Add a class import
402+ */
403+ public synchronized void addClass(IdentifierToken t) {
404+ singles.addElement(t);
405+ }
406+ // for compatibility
407+ public void addClass(Identifier nm) throws AmbiguousClass {
408+ addClass(new IdentifierToken(nm));
409+ }
410+
411+ /**
412+ * Add a package import, or perhaps an inner class scope.
413+ * Ignore any duplicate imports.
414+ */
415+ public synchronized void addPackage(IdentifierToken t) {
416+ final Identifier name = t.getName();
417+
418+ // If this is a duplicate import for the current package,
419+ // ignore it.
420+ if (name == currentPackage) {
421+ return;
422+ }
423+
424+ // If this is a duplicate of a package which has already been
425+ // added to the list, ignore it.
426+ final int size = packages.size();
427+ for (int i = 0; i < size; i++) {
428+ if (name == ((IdentifierToken)packages.elementAt(i)).getName()) {
429+ return;
430+ }
431+ }
432+
433+ // Add the package to the list.
434+ packages.addElement(t);
435+ }
436+ // for compatibility
437+ public void addPackage(Identifier id) {
438+ addPackage(new IdentifierToken(id));
439+ }
440+
441+ /**
442+ * Specify the current package with an IdentifierToken.
443+ */
444+ public synchronized void setCurrentPackage(IdentifierToken t) {
445+ currentPackage = t.getName();
446+ currentPackageWhere = t.getWhere();
447+ }
448+
449+ /**
450+ * Specify the current package
451+ */
452+ public synchronized void setCurrentPackage(Identifier id) {
453+ currentPackage = id;
454+ }
455+
456+ /**
457+ * Report the current package
458+ */
459+ public Identifier getCurrentPackage() {
460+ return currentPackage;
461+ }
462+
463+ /**
464+ * Return an unmodifiable list of IdentifierToken representing
465+ * packages specified as imports.
466+ */
467+ public List getImportedPackages() {
468+ return Collections.unmodifiableList(packages);
469+ }
470+
471+ /**
472+ * Return an unmodifiable list of IdentifierToken representing
473+ * classes specified as imports.
474+ */
475+ public List getImportedClasses() {
476+ return Collections.unmodifiableList(singles);
477+ }
478+
479+ /**
480+ * Extend an environment with my resolve() method.
481+ */
482+ public Environment newEnvironment(Environment env) {
483+ return new ImportEnvironment(env, this);
484+ }
485+}
486+
487+final
488+class ImportEnvironment extends Environment {
489+ Imports imports;
490+
491+ ImportEnvironment(Environment env, Imports imports) {
492+ super(env, env.getSource());
493+ this.imports = imports;
494+ }
495+
496+ public Identifier resolve(Identifier nm) throws ClassNotFound {
497+ return imports.resolve(this, nm);
498+ }
499+
500+ public Imports getImports() {
501+ return imports;
502+ }
503+}
java/pkg/sun/tools/java/MemberDefinition.java+1007−0
@@ -0,0 +1,1007 @@
1+/*
2+ * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import sun.tools.tree.Node;
29+import sun.tools.tree.Vset;
30+import sun.tools.tree.Expression;
31+import sun.tools.tree.Statement;
32+import sun.tools.tree.Context;
33+import sun.tools.asm.Assembler;
34+import java.io.PrintStream;
35+import java.util.Vector;
36+import java.util.Map;
37+import java.util.HashMap;
38+
39+/**
40+ * This class defines a member of a Java class:
41+ * a variable, a method, or an inner class.
42+ *
43+ * WARNING: The contents of this source file are not part of any
44+ * supported API. Code that depends on them does so at its own risk:
45+ * they are subject to change or removal without notice.
46+ */
47+public
48+class MemberDefinition implements Constants {
49+ protected long where;
50+ protected int modifiers;
51+ protected Type type;
52+ protected String documentation;
53+ protected IdentifierToken expIds[];
54+ protected ClassDeclaration exp[];
55+ protected Node value;
56+ protected ClassDefinition clazz;
57+ protected Identifier name;
58+ protected ClassDefinition innerClass;
59+ protected MemberDefinition nextMember;
60+ protected MemberDefinition nextMatch;
61+ protected MemberDefinition accessPeer;
62+ protected boolean superAccessMethod;
63+
64+ /**
65+ * Constructor
66+ */
67+ public MemberDefinition(long where, ClassDefinition clazz, int modifiers,
68+ Type type, Identifier name,
69+ IdentifierToken expIds[], Node value) {
70+ if (expIds == null) {
71+ expIds = new IdentifierToken[0];
72+ }
73+ this.where = where;
74+ this.clazz = clazz;
75+ this.modifiers = modifiers;
76+ this.type = type;
77+ this.name = name;
78+ this.expIds = expIds;
79+ this.value = value;
80+ }
81+
82+ /**
83+ * Constructor for an inner class.
84+ * Inner classes are represented as fields right along with
85+ * variables and methods for simplicity of data structure,
86+ * and to reflect properly the textual declaration order.
87+ * <p>
88+ * This constructor calls the generic constructor for this
89+ * class, extracting all necessary values from the innerClass.
90+ */
91+ public MemberDefinition(ClassDefinition innerClass) {
92+ this(innerClass.getWhere(),
93+ innerClass.getOuterClass(),
94+ innerClass.getModifiers(),
95+ innerClass.getType(),
96+ innerClass.getName().getFlatName().getName(),
97+ null, null);
98+ this.innerClass = innerClass;
99+ }
100+
101+ /**
102+ * A cache of previously created proxy members. Used to ensure
103+ * uniqueness of proxy objects. See the makeProxyMember method
104+ * defined below.
105+ */
106+ static private Map proxyCache;
107+
108+ /**
109+ * Create a member which is externally the same as `field' but
110+ * is defined in class `classDef'. This is used by code
111+ * in sun.tools.tree.(MethodExpression,FieldExpression) as
112+ * part of the fix for bug 4135692.
113+ *
114+ * Proxy members should not be added, ala addMember(), to classes.
115+ * They are merely "stand-ins" to produce modified MethodRef
116+ * constant pool entries during code generation.
117+ *
118+ * We keep a cache of previously created proxy members not to
119+ * save time or space, but to ensure uniqueness of the proxy
120+ * member for any (field,classDef) pair. If these are not made
121+ * unique then we can end up generating duplicate MethodRef
122+ * constant pool entries during code generation.
123+ */
124+ public static MemberDefinition makeProxyMember(MemberDefinition field,
125+ ClassDefinition classDef,
126+ Environment env) {
127+
128+ if (proxyCache == null) {
129+ proxyCache = new HashMap();
130+ }
131+
132+ String key = field.toString() + "@" + classDef.toString();
133+ // System.out.println("Key is : " + key);
134+ MemberDefinition proxy = (MemberDefinition)proxyCache.get(key);
135+
136+ if (proxy != null)
137+ return proxy;
138+
139+ proxy = new MemberDefinition(field.getWhere(), classDef,
140+ field.getModifiers(), field.getType(),
141+ field.getName(), field.getExceptionIds(),
142+ null);
143+ proxy.exp = field.getExceptions(env);
144+ proxyCache.put(key, proxy);
145+
146+ return proxy;
147+ }
148+
149+ /**
150+ * Get the position in the input
151+ */
152+ public final long getWhere() {
153+ return where;
154+ }
155+
156+ /**
157+ * Get the class declaration
158+ */
159+ public final ClassDeclaration getClassDeclaration() {
160+ return clazz.getClassDeclaration();
161+ }
162+
163+ /**
164+ * A stub. Subclasses can do more checking.
165+ */
166+ public void resolveTypeStructure(Environment env) {
167+ }
168+
169+ /**
170+ * Get the class declaration in which the field is actually defined
171+ */
172+ public ClassDeclaration getDefiningClassDeclaration() {
173+ return getClassDeclaration();
174+ }
175+
176+ /**
177+ * Get the class definition
178+ */
179+ public final ClassDefinition getClassDefinition() {
180+ return clazz;
181+ }
182+
183+ /**
184+ * Get the field's top-level enclosing class
185+ */
186+ public final ClassDefinition getTopClass() {
187+ return clazz.getTopClass();
188+ }
189+
190+ /**
191+ * Get the field's modifiers
192+ */
193+ public final int getModifiers() {
194+ return modifiers;
195+ }
196+ public final void subModifiers(int mod) {
197+ modifiers &= ~mod;
198+ }
199+ public final void addModifiers(int mod) {
200+ modifiers |= mod;
201+ }
202+
203+ /**
204+ * Get the field's type
205+ */
206+ public final Type getType() {
207+ return type;
208+ }
209+
210+ /**
211+ * Get the field's name
212+ */
213+ public final Identifier getName() {
214+ return name;
215+ }
216+
217+ /**
218+ * Get arguments (a vector of LocalMember)
219+ */
220+ public Vector getArguments() {
221+ return isMethod() ? new Vector() : null;
222+ }
223+
224+ /**
225+ * Get the exceptions that are thrown by this method.
226+ */
227+ public ClassDeclaration[] getExceptions(Environment env) {
228+ if (expIds != null && exp == null) {
229+ if (expIds.length == 0)
230+ exp = new ClassDeclaration[0];
231+ else
232+ // we should have translated this already!
233+ throw new CompilerError("getExceptions "+this);
234+ }
235+ return exp;
236+ }
237+
238+ public final IdentifierToken[] getExceptionIds() {
239+ return expIds;
240+ }
241+
242+ /**
243+ * Get an inner class.
244+ */
245+ public ClassDefinition getInnerClass() {
246+ return innerClass;
247+ }
248+
249+ /**
250+ * Is this a synthetic field which holds a copy of,
251+ * or reference to, a local variable or enclosing instance?
252+ */
253+ public boolean isUplevelValue() {
254+ if (!isSynthetic() || !isVariable() || isStatic()) {
255+ return false;
256+ }
257+ String name = this.name.toString();
258+ return name.startsWith(prefixVal)
259+ || name.toString().startsWith(prefixLoc)
260+ || name.toString().startsWith(prefixThis);
261+ }
262+
263+ public boolean isAccessMethod() {
264+ // This no longer works, because access methods
265+ // for constructors do not use the standard naming
266+ // scheme.
267+ // return isSynthetic() && isMethod()
268+ // && name.toString().startsWith(prefixAccess);
269+ // Assume that a method is an access method if it has
270+ // an access peer. NOTE: An access method will not be
271+ // recognized as such until 'setAccessMethodTarget' has
272+ // been called on it.
273+ return isSynthetic() && isMethod() && (accessPeer != null);
274+ }
275+
276+ /**
277+ * Is this a synthetic method which provides access to a
278+ * visible private member?
279+ */
280+ public MemberDefinition getAccessMethodTarget() {
281+ if (isAccessMethod()) {
282+ for (MemberDefinition f = accessPeer; f != null; f = f.accessPeer) {
283+ // perhaps skip over another access for the same field
284+ if (!f.isAccessMethod()) {
285+ return f;
286+ }
287+ }
288+ }
289+ return null;
290+ }
291+
292+
293+ public void setAccessMethodTarget(MemberDefinition target) {
294+ if (getAccessMethodTarget() != target) {
295+ /*-------------------*
296+ if (!isAccessMethod() || accessPeer != null ||
297+ target.accessPeer != null) {
298+ throw new CompilerError("accessPeer");
299+ }
300+ *-------------------*/
301+ if (accessPeer != null || target.accessPeer != null) {
302+ throw new CompilerError("accessPeer");
303+ }
304+ accessPeer = target;
305+ }
306+ }
307+
308+ /**
309+ * If this method is a getter for a private field, return the setter.
310+ */
311+ public MemberDefinition getAccessUpdateMember() {
312+ if (isAccessMethod()) {
313+ for (MemberDefinition f = accessPeer; f != null; f = f.accessPeer) {
314+ if (f.isAccessMethod()) {
315+ return f;
316+ }
317+ }
318+ }
319+ return null;
320+ }
321+
322+ public void setAccessUpdateMember(MemberDefinition updater) {
323+ if (getAccessUpdateMember() != updater) {
324+ if (!isAccessMethod() ||
325+ updater.getAccessMethodTarget() != getAccessMethodTarget()) {
326+ throw new CompilerError("accessPeer");
327+ }
328+ updater.accessPeer = accessPeer;
329+ accessPeer = updater;
330+ }
331+ }
332+
333+ /**
334+ * Is this an access method for a field selection or method call
335+ * of the form '...super.foo' or '...super.foo()'?
336+ */
337+ public final boolean isSuperAccessMethod() {
338+ return superAccessMethod;
339+ }
340+
341+ /**
342+ * Mark this member as an access method for a field selection
343+ * or method call via the 'super' keyword.
344+ */
345+ public final void setIsSuperAccessMethod(boolean b) {
346+ superAccessMethod = b;
347+ }
348+
349+ /**
350+ * Tell if this is a final variable without an initializer.
351+ * Such variables are subject to definite single assignment.
352+ */
353+ public final boolean isBlankFinal() {
354+ return isFinal() && !isSynthetic() && getValue() == null;
355+ }
356+
357+ public boolean isNeverNull() {
358+ if (isUplevelValue()) {
359+ // loc$x and this$C are never null
360+ return !name.toString().startsWith(prefixVal);
361+ }
362+ return false;
363+ }
364+
365+ /**
366+ * Get the field's final value (may return null)
367+ */
368+ public Node getValue(Environment env) throws ClassNotFound {
369+ return value;
370+ }
371+ public final Node getValue() {
372+ return value;
373+ }
374+ public final void setValue(Node value) {
375+ this.value = value;
376+ }
377+ public Object getInitialValue() {
378+ return null;
379+ }
380+
381+ /**
382+ * Get the next field or the next match
383+ */
384+ public final MemberDefinition getNextMember() {
385+ return nextMember;
386+ }
387+ public final MemberDefinition getNextMatch() {
388+ return nextMatch;
389+ }
390+
391+ /**
392+ * Get the field's documentation
393+ */
394+ public String getDocumentation() {
395+ return documentation;
396+ }
397+
398+ /**
399+ * Request a check of the field definition.
400+ */
401+ public void check(Environment env) throws ClassNotFound {
402+ }
403+
404+ /**
405+ * Really check the field definition.
406+ */
407+ public Vset check(Environment env, Context ctx, Vset vset) throws ClassNotFound {
408+ return vset;
409+ }
410+
411+ /**
412+ * Generate code
413+ */
414+ public void code(Environment env, Assembler asm) throws ClassNotFound {
415+ throw new CompilerError("code");
416+ }
417+ public void codeInit(Environment env, Context ctx, Assembler asm) throws ClassNotFound {
418+ throw new CompilerError("codeInit");
419+ }
420+
421+ /**
422+ * Tells whether to report a deprecation error for this field.
423+ */
424+ public boolean reportDeprecated(Environment env) {
425+ return (isDeprecated() || clazz.reportDeprecated(env));
426+ }
427+
428+ /**
429+ * Check if a field can reach another field (only considers
430+ * forward references, not the access modifiers).
431+ */
432+ public final boolean canReach(Environment env, MemberDefinition f) {
433+ if (f.isLocal() || !f.isVariable() || !(isVariable() || isInitializer()))
434+ return true;
435+ if ((getClassDeclaration().equals(f.getClassDeclaration())) &&
436+ (isStatic() == f.isStatic())) {
437+ // They are located in the same class, and are either both
438+ // static or both non-static. Check the initialization order.
439+ while (((f = f.getNextMember()) != null) && (f != this));
440+ return f != null;
441+ }
442+ return true;
443+ }
444+
445+ //-----------------------------------------------------------------
446+ // The code in this section is intended to test certain kinds of
447+ // compatibility between methods. There are two kinds of compatibility
448+ // that the compiler may need to test. The first is whether one
449+ // method can legally override another. The second is whether two
450+ // method definitions can legally coexist. We use the word `meet'
451+ // to mean the intersection of two legally coexisting methods.
452+ // For more information on these kinds of compatibility, see the
453+ // comments/code for checkOverride() and checkMeet() below.
454+
455+ /**
456+ * Constants used by getAccessLevel() to represent the access
457+ * modifiers as numbers.
458+ */
459+ static final int PUBLIC_ACCESS = 1;
460+ static final int PROTECTED_ACCESS = 2;
461+ static final int PACKAGE_ACCESS = 3;
462+ static final int PRIVATE_ACCESS = 4;
463+
464+ /**
465+ * Return the access modifier of this member as a number. The idea
466+ * is that this number may be used to check properties like "the
467+ * access modifier of x is more restrictive than the access
468+ * modifier of y" with a simple inequality test:
469+ * "x.getAccessLevel() > y.getAccessLevel.
470+ *
471+ * This is an internal utility method.
472+ */
473+ private int getAccessLevel() {
474+ // Could just compute this once instead of recomputing.
475+ // Check to see if this is worth it.
476+ if (isPublic()) {
477+ return PUBLIC_ACCESS;
478+ } else if (isProtected()) {
479+ return PROTECTED_ACCESS;
480+ } else if (isPackagePrivate()) {
481+ return PACKAGE_ACCESS;
482+ } else if (isPrivate()) {
483+ return PRIVATE_ACCESS;
484+ } else {
485+ throw new CompilerError("getAccessLevel()");
486+ }
487+ }
488+
489+ /**
490+ * Munge our error message to report whether the override conflict
491+ * came from an inherited method or a declared method.
492+ */
493+ private void reportError(Environment env, String errorString,
494+ ClassDeclaration clazz,
495+ MemberDefinition method) {
496+
497+ if (clazz == null) {
498+ // For example:
499+ // "Instance method BLAH inherited from CLASSBLAH1 cannot be
500+ // overridden by the static method declared in CLASSBLAH2."
501+ env.error(getWhere(), errorString,
502+ this, getClassDeclaration(),
503+ method.getClassDeclaration());
504+ } else {
505+ // For example:
506+ // "In CLASSBLAH1, instance method BLAH inherited from CLASSBLAH2
507+ // cannot be overridden by the static method inherited from
508+ // CLASSBLAH3."
509+ env.error(clazz.getClassDefinition().getWhere(),
510+ //"inherit." + errorString,
511+ errorString,
512+ //clazz,
513+ this, getClassDeclaration(),
514+ method.getClassDeclaration());
515+ }
516+ }
517+
518+ /**
519+ * Convenience method to see if two methods return the same type
520+ */
521+ public boolean sameReturnType(MemberDefinition method) {
522+ // Make sure both are methods.
523+ if (!isMethod() || !method.isMethod()) {
524+ throw new CompilerError("sameReturnType: not method");
525+ }
526+
527+ Type myReturnType = getType().getReturnType();
528+ Type yourReturnType = method.getType().getReturnType();
529+
530+ return (myReturnType == yourReturnType);
531+ }
532+
533+ /**
534+ * Check to see if `this' can override/hide `method'. Caller is
535+ * responsible for verifying that `method' has the same signature
536+ * as `this'. Caller is also responsible for verifying that
537+ * `method' is visible to the class where this override is occurring.
538+ * This method is called for the case when class B extends A and both
539+ * A and B define some method.
540+ * <pre>
541+ * A - void foo() throws e1
542+ * |
543+ * |
544+ * B - void foo() throws e2
545+ * </pre>
546+ */
547+ public boolean checkOverride(Environment env, MemberDefinition method) {
548+ return checkOverride(env, method, null);
549+ }
550+
551+ /**
552+ * Checks whether `this' can override `method'. It `clazz' is
553+ * null, it reports the errors in the class where `this' is
554+ * declared. If `clazz' is not null, it reports the error in `clazz'.
555+ */
556+ private boolean checkOverride(Environment env,
557+ MemberDefinition method,
558+ ClassDeclaration clazz) {
559+ // This section of code is largely based on section 8.4.6.3
560+ // of the JLS.
561+
562+ boolean success = true;
563+
564+ // Sanity
565+ if (!isMethod()) {
566+ throw new CompilerError("checkOverride(), expected method");
567+ }
568+
569+ // Suppress checks for synthetic methods, as the compiler presumably
570+ // knows what it is doing, e.g., access methods.
571+ if (isSynthetic()) {
572+ // Sanity check: We generally do not intend for one synthetic
573+ // method to override another, though hiding of static members
574+ // is expected. This check may need to be changed if new uses
575+ // of synthetic methods are devised.
576+ //
577+ // Query: this code was copied from elsewhere. What
578+ // exactly is the role of the !isStatic() in the test?
579+ if (method.isFinal() ||
580+ (!method.isConstructor() &&
581+ !method.isStatic() && !isStatic())) {
582+ ////////////////////////////////////////////////////////////
583+ // NMG 2003-01-28 removed the following test because it is
584+ // invalidated by bridge methods inserted by the "generic"
585+ // (1.5) Java compiler. In 1.5, this code is used,
586+ // indirectly, by rmic
587+ ////////////////////////////////////////////////////////////
588+ // throw new CompilerError("checkOverride() synthetic");
589+ ////////////////////////////////////////////////////////////
590+ }
591+
592+ // We trust the compiler. (Ha!) We're done checking.
593+ return true;
594+ }
595+
596+ // Our caller should have verified that the method had the
597+ // same signature.
598+ if (getName() != method.getName() ||
599+ !getType().equalArguments(method.getType())) {
600+
601+ throw new CompilerError("checkOverride(), signature mismatch");
602+ }
603+
604+ // It is forbidden to `override' a static method with an instance
605+ // method.
606+ if (method.isStatic() && !isStatic()) {
607+ reportError(env, "override.static.with.instance", clazz, method);
608+ success = false;
609+ }
610+
611+ // It is forbidden to `hide' an instance method with a static
612+ // method.
613+ if (!method.isStatic() && isStatic()) {
614+ reportError(env, "hide.instance.with.static", clazz, method);
615+ success = false;
616+ }
617+
618+ // We cannot override a final method.
619+ if (method.isFinal()) {
620+ reportError(env, "override.final.method", clazz, method);
621+ success = false;
622+ }
623+
624+ // Give a warning when we override a deprecated method with
625+ // a non-deprecated one.
626+ //
627+ // We bend over backwards to suppress this warning if
628+ // the `method' has not been already compiled or
629+ // `this' has been already compiled.
630+ if (method.reportDeprecated(env) && !isDeprecated()
631+ && this instanceof sun.tools.javac.SourceMember) {
632+ reportError(env, "warn.override.is.deprecated",
633+ clazz, method);
634+ }
635+
636+ // Visibility may not be more restrictive
637+ if (getAccessLevel() > method.getAccessLevel()) {
638+ reportError(env, "override.more.restrictive", clazz, method);
639+ success = false;
640+ }
641+
642+ // Return type equality
643+ if (!sameReturnType(method)) {
644+ ////////////////////////////////////////////////////////////
645+ // PCJ 2003-07-30 removed the following error because it is
646+ // invalidated by the covariant return type feature of the
647+ // 1.5 compiler. The resulting check is now much looser
648+ // than the actual 1.5 language spec, but that should be OK
649+ // because this code is only still used by rmic. See 4892308.
650+ ////////////////////////////////////////////////////////////
651+ // reportError(env, "override.different.return", clazz, method);
652+ // success = false;
653+ ////////////////////////////////////////////////////////////
654+ }
655+
656+ // Exception agreeement
657+ if (!exceptionsFit(env, method)) {
658+ reportError(env, "override.incompatible.exceptions",
659+ clazz, method);
660+ success = false;
661+ }
662+
663+ return success;
664+ }
665+
666+ /**
667+ * Check to see if two method definitions are compatible, that is
668+ * do they have a `meet'. The meet of two methods is essentially
669+ * and `intersection' of
670+ * two methods. This method is called when some class C inherits
671+ * declarations for some method foo from two parents (superclass,
672+ * interfaces) but it does not, itself, have a declaration of foo.
673+ * Caller is responsible for making sure that both methods are
674+ * indeed visible in clazz.
675+ * <pre>
676+ * A - void foo() throws e1
677+ * \
678+ * \ B void foo() throws e2
679+ * \ /
680+ * \ /
681+ * C
682+ * </pre>
683+ */
684+ public boolean checkMeet(Environment env,
685+ MemberDefinition method,
686+ ClassDeclaration clazz) {
687+ // This section of code is largely based on Section 8.4.6
688+ // and 9.4.1 of the JLS.
689+
690+ // Sanity
691+ if (!isMethod()) {
692+ throw new CompilerError("checkMeet(), expected method");
693+ }
694+
695+ // Check for both non-abstract.
696+ if (!isAbstract() && !method.isAbstract()) {
697+ throw new CompilerError("checkMeet(), no abstract method");
698+ }
699+
700+ // If either method is non-abstract, then we need to check that
701+ // the abstract method can be properly overridden. We call
702+ // the checkOverride method to check this and generate any errors.
703+ // This test must follow the previous test.
704+ else if (!isAbstract()) {
705+ return checkOverride(env, method, clazz);
706+ } else if (!method.isAbstract()) {
707+ return method.checkOverride(env, this, clazz);
708+ }
709+
710+ // Both methods are abstract.
711+
712+ // Our caller should have verified that the method has the
713+ // same signature.
714+ if (getName() != method.getName() ||
715+ !getType().equalArguments(method.getType())) {
716+
717+ throw new CompilerError("checkMeet(), signature mismatch");
718+ }
719+
720+ // Check for return type equality
721+ if (!sameReturnType(method)) {
722+ // More args?
723+ env.error(clazz.getClassDefinition().getWhere(),
724+ "meet.different.return",
725+ this, this.getClassDeclaration(),
726+ method.getClassDeclaration());
727+ return false;
728+ }
729+
730+ // We don't have to check visibility -- there always
731+ // potentially exists a meet. Similarly with exceptions.
732+
733+ // There does exist a meet.
734+ return true;
735+ }
736+
737+ /**
738+ * This method is meant to be used to determine if one of two inherited
739+ * methods could override the other. Unlike checkOverride(), failure
740+ * is not an error. This method is only meant to be called after
741+ * checkMeet() has succeeded on the two methods.
742+ *
743+ * If you call couldOverride() without doing a checkMeet() first, then
744+ * you are on your own.
745+ */
746+ public boolean couldOverride(Environment env,
747+ MemberDefinition method) {
748+
749+ // Sanity
750+ if (!isMethod()) {
751+ throw new CompilerError("coulcOverride(), expected method");
752+ }
753+
754+ // couldOverride() is only called with `this' and `method' both
755+ // being inherited methods. Neither of them is defined in the
756+ // class which we are currently working on. Even though an
757+ // abstract method defined *in* a class can override a non-abstract
758+ // method defined in a superclass, an abstract method inherited
759+ // from an interface *never* can override a non-abstract method.
760+ // This comment may sound odd, but that's the way inheritance is.
761+ // The following check makes sure we aren't trying to override
762+ // an inherited non-abstract definition with an abstract definition
763+ // from an interface.
764+ if (!method.isAbstract()) {
765+ return false;
766+ }
767+
768+ // Visibility should be less restrictive
769+ if (getAccessLevel() > method.getAccessLevel()) {
770+ return false;
771+ }
772+
773+ // Exceptions
774+ if (!exceptionsFit(env, method)) {
775+ return false;
776+ }
777+
778+ // Potentially some deprecation warnings could be given here
779+ // when we merge two abstract methods, one of which is deprecated.
780+ // This is not currently reported.
781+
782+ return true;
783+ }
784+
785+ /**
786+ * Check to see if the exceptions of `this' fit within the
787+ * exceptions of `method'.
788+ */
789+ private boolean exceptionsFit(Environment env,
790+ MemberDefinition method) {
791+ ClassDeclaration e1[] = getExceptions(env); // my exceptions
792+ ClassDeclaration e2[] = method.getExceptions(env); // parent's
793+
794+ // This code is taken nearly verbatim from the old implementation
795+ // of checkOverride() in SourceClass.
796+ outer:
797+ for (int i = 0 ; i < e1.length ; i++) {
798+ try {
799+ ClassDefinition c1 = e1[i].getClassDefinition(env);
800+ for (int j = 0 ; j < e2.length ; j++) {
801+ if (c1.subClassOf(env, e2[j])) {
802+ continue outer;
803+ }
804+ }
805+ if (c1.subClassOf(env,
806+ env.getClassDeclaration(idJavaLangError)))
807+ continue outer;
808+ if (c1.subClassOf(env,
809+ env.getClassDeclaration(idJavaLangRuntimeException)))
810+ continue outer;
811+
812+ // the throws was neither something declared by a parent,
813+ // nor one of the ignorables.
814+ return false;
815+
816+ } catch (ClassNotFound ee) {
817+ // We were unable to find one of the exceptions.
818+ env.error(getWhere(), "class.not.found",
819+ ee.name, method.getClassDeclaration());
820+ }
821+ }
822+
823+ // All of the exceptions `fit'.
824+ return true;
825+ }
826+
827+ //-----------------------------------------------------------------
828+
829+ /**
830+ * Checks
831+ */
832+ public final boolean isPublic() {
833+ return (modifiers & M_PUBLIC) != 0;
834+ }
835+ public final boolean isPrivate() {
836+ return (modifiers & M_PRIVATE) != 0;
837+ }
838+ public final boolean isProtected() {
839+ return (modifiers & M_PROTECTED) != 0;
840+ }
841+ public final boolean isPackagePrivate() {
842+ return (modifiers & (M_PUBLIC | M_PRIVATE | M_PROTECTED)) == 0;
843+ }
844+ public final boolean isFinal() {
845+ return (modifiers & M_FINAL) != 0;
846+ }
847+ public final boolean isStatic() {
848+ return (modifiers & M_STATIC) != 0;
849+ }
850+ public final boolean isSynchronized() {
851+ return (modifiers & M_SYNCHRONIZED) != 0;
852+ }
853+ public final boolean isAbstract() {
854+ return (modifiers & M_ABSTRACT) != 0;
855+ }
856+ public final boolean isNative() {
857+ return (modifiers & M_NATIVE) != 0;
858+ }
859+ public final boolean isVolatile() {
860+ return (modifiers & M_VOLATILE) != 0;
861+ }
862+ public final boolean isTransient() {
863+ return (modifiers & M_TRANSIENT) != 0;
864+ }
865+ public final boolean isMethod() {
866+ return type.isType(TC_METHOD);
867+ }
868+ public final boolean isVariable() {
869+ return !type.isType(TC_METHOD) && innerClass == null;
870+ }
871+ public final boolean isSynthetic() {
872+ return (modifiers & M_SYNTHETIC) != 0;
873+ }
874+ public final boolean isDeprecated() {
875+ return (modifiers & M_DEPRECATED) != 0;
876+ }
877+ public final boolean isStrict() {
878+ return (modifiers & M_STRICTFP) != 0;
879+ }
880+ public final boolean isInnerClass() {
881+ return innerClass != null;
882+ }
883+ public final boolean isInitializer() {
884+ return getName().equals(idClassInit);
885+ }
886+ public final boolean isConstructor() {
887+ return getName().equals(idInit);
888+ }
889+ public boolean isLocal() {
890+ return false;
891+ }
892+ public boolean isInlineable(Environment env, boolean fromFinal) throws ClassNotFound {
893+ return (isStatic() || isPrivate() || isFinal() || isConstructor() || fromFinal) &&
894+ !(isSynchronized() || isNative());
895+ }
896+
897+ /**
898+ * Check if constant: Will it inline away to a constant?
899+ */
900+ public boolean isConstant() {
901+ if (isFinal() && isVariable() && value != null) {
902+ try {
903+ // If an infinite regress requeries this name,
904+ // deny that it is a constant.
905+ modifiers &= ~M_FINAL;
906+ return ((Expression)value).isConstant();
907+ } finally {
908+ modifiers |= M_FINAL;
909+ }
910+ }
911+ return false;
912+ }
913+
914+ /**
915+ * toString
916+ */
917+ public String toString() {
918+ Identifier name = getClassDefinition().getName();
919+ if (isInitializer()) {
920+ return isStatic() ? "static {}" : "instance {}";
921+ } else if (isConstructor()) {
922+ StringBuffer buf = new StringBuffer();
923+ buf.append(name);
924+ buf.append('(');
925+ Type argTypes[] = getType().getArgumentTypes();
926+ for (int i = 0 ; i < argTypes.length ; i++) {
927+ if (i > 0) {
928+ buf.append(',');
929+ }
930+ buf.append(argTypes[i].toString());
931+ }
932+ buf.append(')');
933+ return buf.toString();
934+ } else if (isInnerClass()) {
935+ return getInnerClass().toString();
936+ }
937+ return type.typeString(getName().toString());
938+ }
939+
940+ /**
941+ * Print for debugging
942+ */
943+ public void print(PrintStream out) {
944+ if (isPublic()) {
945+ out.print("public ");
946+ }
947+ if (isPrivate()) {
948+ out.print("private ");
949+ }
950+ if (isProtected()) {
951+ out.print("protected ");
952+ }
953+ if (isFinal()) {
954+ out.print("final ");
955+ }
956+ if (isStatic()) {
957+ out.print("static ");
958+ }
959+ if (isSynchronized()) {
960+ out.print("synchronized ");
961+ }
962+ if (isAbstract()) {
963+ out.print("abstract ");
964+ }
965+ if (isNative()) {
966+ out.print("native ");
967+ }
968+ if (isVolatile()) {
969+ out.print("volatile ");
970+ }
971+ if (isTransient()) {
972+ out.print("transient ");
973+ }
974+ out.println(toString() + ";");
975+ }
976+
977+ public void cleanup(Environment env) {
978+ documentation = null;
979+ if (isMethod() && value != null) {
980+ int cost = 0;
981+ if (isPrivate() || isInitializer()) {
982+ value = Statement.empty;
983+ } else if ((cost =
984+ ((Statement)value)
985+ .costInline(Statement.MAXINLINECOST, null, null))
986+ >= Statement.MAXINLINECOST) {
987+ // will never be inlined
988+ value = Statement.empty;
989+ } else {
990+ try {
991+ if (!isInlineable(null, true)) {
992+ value = Statement.empty;
993+ }
994+ }
995+ catch (ClassNotFound ee) { }
996+ }
997+ if (value != Statement.empty && env.dump()) {
998+ env.output("[after cleanup of " + getName() + ", " +
999+ cost + " expression cost units remain]");
1000+ }
1001+ } else if (isVariable()) {
1002+ if (isPrivate() || !isFinal() || type.isType(TC_ARRAY)) {
1003+ value = null;
1004+ }
1005+ }
1006+ }
1007+}
java/pkg/sun/tools/java/MethodSet.java+278−0
@@ -0,0 +1,278 @@
1+/*
2+ * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.util.*;
29+
30+/**
31+ * The MethodSet structure is used to store methods for a class.
32+ * It maintains the invariant that it never stores two methods
33+ * with the same signature. MethodSets are able to lookup
34+ * all methods with a given name and the unique method with a given
35+ * signature (name, args).
36+ *
37+ * WARNING: The contents of this source file are not part of any
38+ * supported API. Code that depends on them does so at its own risk:
39+ * they are subject to change or removal without notice.
40+ */
41+
42+public
43+class MethodSet {
44+
45+ /**
46+ * A Map containing Lists of MemberDefinitions. The Lists
47+ * contain methods which share the same name.
48+ */
49+ private final Map lookupMap;
50+
51+ /**
52+ * The number of methods stored in the MethodSet.
53+ */
54+ private int count;
55+
56+ /**
57+ * Is this MethodSet currently frozen? See freeze() for more details.
58+ */
59+ private boolean frozen;
60+
61+ /**
62+ * Creates a brand new MethodSet
63+ */
64+ public MethodSet() {
65+ frozen = false;
66+ lookupMap = new HashMap();
67+ count = 0;
68+ }
69+
70+ /**
71+ * Returns the number of distinct methods stored in the MethodSet.
72+ */
73+ public int size() {
74+ return count;
75+ }
76+
77+ /**
78+ * Adds `method' to the MethodSet. No method of the same signature
79+ * should be already defined.
80+ */
81+ public void add(MemberDefinition method) {
82+ // Check for late additions.
83+ if (frozen) {
84+ throw new CompilerError("add()");
85+ }
86+
87+ // todo: Check for method??
88+
89+ Identifier name = method.getName();
90+
91+ // Get a List containing all methods of this name.
92+ List methodList = (List) lookupMap.get(name);
93+
94+ if (methodList == null) {
95+ // There is no method with this name already.
96+ // Create a List, and insert it into the hash.
97+ methodList = new ArrayList();
98+ lookupMap.put(name, methodList);
99+ }
100+
101+ // Make sure that no method with the same signature has already
102+ // been added to the MethodSet.
103+ int size = methodList.size();
104+ for (int i = 0; i < size; i++) {
105+ if (((MemberDefinition) methodList.get(i))
106+ .getType().equalArguments(method.getType())) {
107+ throw new CompilerError("duplicate addition");
108+ }
109+ }
110+
111+ // We add the method to the appropriate list.
112+ methodList.add(method);
113+ count++;
114+ }
115+
116+ /**
117+ * Adds `method' to the MethodSet, replacing any previous definition
118+ * with the same signature.
119+ */
120+ public void replace(MemberDefinition method) {
121+ // Check for late additions.
122+ if (frozen) {
123+ throw new CompilerError("replace()");
124+ }
125+
126+ // todo: Check for method??
127+
128+ Identifier name = method.getName();
129+
130+ // Get a List containing all methods of this name.
131+ List methodList = (List) lookupMap.get(name);
132+
133+ if (methodList == null) {
134+ // There is no method with this name already.
135+ // Create a List, and insert it into the hash.
136+ methodList = new ArrayList();
137+ lookupMap.put(name, methodList);
138+ }
139+
140+ // Replace the element which has the same signature as
141+ // `method'.
142+ int size = methodList.size();
143+ for (int i = 0; i < size; i++) {
144+ if (((MemberDefinition) methodList.get(i))
145+ .getType().equalArguments(method.getType())) {
146+ methodList.set(i, method);
147+ return;
148+ }
149+ }
150+
151+ // We add the method to the appropriate list.
152+ methodList.add(method);
153+ count++;
154+ }
155+
156+ /**
157+ * If the MethodSet contains a method with the same signature
158+ * then lookup() returns it. Otherwise, this method returns null.
159+ */
160+ public MemberDefinition lookupSig(Identifier name, Type type) {
161+ // Go through all methods of the same name and see if any
162+ // have the right signature.
163+ Iterator matches = lookupName(name);
164+ MemberDefinition candidate;
165+
166+ while (matches.hasNext()) {
167+ candidate = (MemberDefinition) matches.next();
168+ if (candidate.getType().equalArguments(type)) {
169+ return candidate;
170+ }
171+ }
172+
173+ // No match.
174+ return null;
175+ }
176+
177+ /**
178+ * Returns an Iterator of all methods contained in the
179+ * MethodSet which have a given name.
180+ */
181+ public Iterator lookupName(Identifier name) {
182+ // Find the List containing all methods of this name, and
183+ // return that List's Iterator.
184+ List methodList = (List) lookupMap.get(name);
185+ if (methodList == null) {
186+ // If there is no method of this name, return a bogus, empty
187+ // Iterator.
188+ return Collections.emptyIterator();
189+ }
190+ return methodList.iterator();
191+ }
192+
193+ /**
194+ * Returns an Iterator of all methods in the MethodSet
195+ */
196+ public Iterator iterator() {
197+
198+ //----------------------------------------------------------
199+ // The inner class MethodIterator is used to create our
200+ // Iterator of all methods in the MethodSet.
201+ class MethodIterator implements Iterator {
202+ Iterator hashIter = lookupMap.values().iterator();
203+ Iterator listIter = Collections.emptyIterator();
204+
205+ public boolean hasNext() {
206+ if (listIter.hasNext()) {
207+ return true;
208+ } else {
209+ if (hashIter.hasNext()) {
210+ listIter = ((List) hashIter.next())
211+ .iterator();
212+
213+ // The following should be always true.
214+ if (listIter.hasNext()) {
215+ return true;
216+ } else {
217+ throw new
218+ CompilerError("iterator() in MethodSet");
219+ }
220+ }
221+ }
222+
223+ // We've run out of Lists.
224+ return false;
225+ }
226+
227+ public Object next() {
228+ return listIter.next();
229+ }
230+
231+ public void remove() {
232+ throw new UnsupportedOperationException();
233+ }
234+ }
235+ // end MethodIterator
236+ //----------------------------------------------------------
237+
238+ // A one-liner.
239+ return new MethodIterator();
240+ }
241+
242+ /**
243+ * After freeze() is called, the MethodSet becomes (mostly)
244+ * immutable. Any calls to add() or addMeet() lead to
245+ * CompilerErrors. Note that the entries themselves are still
246+ * (unfortunately) open for mischievous and wanton modification.
247+ */
248+ public void freeze() {
249+ frozen = true;
250+ }
251+
252+ /**
253+ * Tells whether freeze() has been called on this MethodSet.
254+ */
255+ public boolean isFrozen() {
256+ return frozen;
257+ }
258+
259+ /**
260+ * Returns a (big) string representation of this MethodSet
261+ */
262+ public String toString() {
263+ int len = size();
264+ StringBuffer buf = new StringBuffer();
265+ Iterator all = iterator();
266+ buf.append("{");
267+
268+ while (all.hasNext()) {
269+ buf.append(all.next().toString());
270+ len--;
271+ if (len > 0) {
272+ buf.append(", ");
273+ }
274+ }
275+ buf.append("}");
276+ return buf.toString();
277+ }
278+}
java/pkg/sun/tools/java/MethodType.java+107−0
@@ -0,0 +1,107 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+/**
29+ * This class represents an Java method type.
30+ * It overrides the relevant methods in class Type.
31+ *
32+ * WARNING: The contents of this source file are not part of any
33+ * supported API. Code that depends on them does so at its own risk:
34+ * they are subject to change or removal without notice.
35+ *
36+ * @author Arthur van Hoff
37+ */
38+public final
39+class MethodType extends Type {
40+ /**
41+ * The return type.
42+ */
43+ Type returnType;
44+
45+ /**
46+ * The argument types.
47+ */
48+ Type argTypes[];
49+
50+ /**
51+ * Construct a method type. Use Type.tMethod to create
52+ * a new method type.
53+ * @see Type.tMethod
54+ */
55+ MethodType(String typeSig, Type returnType, Type argTypes[]) {
56+ super(TC_METHOD, typeSig);
57+ this.returnType = returnType;
58+ this.argTypes = argTypes;
59+ }
60+
61+ public Type getReturnType() {
62+ return returnType;
63+ }
64+
65+ public Type getArgumentTypes()[] {
66+ return argTypes;
67+ }
68+
69+ public boolean equalArguments(Type t) {
70+ if (t.typeCode != TC_METHOD) {
71+ return false;
72+ }
73+ MethodType m = (MethodType)t;
74+ if (argTypes.length != m.argTypes.length) {
75+ return false;
76+ }
77+ for (int i = argTypes.length - 1 ; i >= 0 ; i--) {
78+ if (argTypes[i] != m.argTypes[i]) {
79+ return false;
80+ }
81+ }
82+ return true;
83+ }
84+
85+ public int stackSize() {
86+ int n = 0;
87+ for (int i = 0 ; i < argTypes.length ; i++) {
88+ n += argTypes[i].stackSize();
89+ }
90+ return n;
91+ }
92+
93+ public String typeString(String id, boolean abbrev, boolean ret) {
94+ StringBuffer buf = new StringBuffer();
95+ buf.append(id);
96+ buf.append('(');
97+ for (int i = 0 ; i < argTypes.length ; i++) {
98+ if (i > 0) {
99+ buf.append(", ");
100+ }
101+ buf.append(argTypes[i].typeString("", abbrev, ret));
102+ }
103+ buf.append(')');
104+
105+ return ret ? getReturnType().typeString(buf.toString(), abbrev, ret) : buf.toString();
106+ }
107+}
java/pkg/sun/tools/java/Package.java+161−0
@@ -0,0 +1,161 @@
1+/*
2+ * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.util.Enumeration;
29+import java.io.File;
30+import java.io.IOException;
31+
32+/**
33+ * This class is used to represent the classes in a package.
34+ *
35+ * WARNING: The contents of this source file are not part of any
36+ * supported API. Code that depends on them does so at its own risk:
37+ * they are subject to change or removal without notice.
38+ */
39+public
40+class Package {
41+ /**
42+ * The path which we use to locate source files.
43+ */
44+ ClassPath sourcePath;
45+
46+ /**
47+ * The path which we use to locate class (binary) files.
48+ */
49+ ClassPath binaryPath;
50+
51+ /**
52+ * The path name of the package.
53+ */
54+ String pkg;
55+
56+ /**
57+ * Create a package given a class path, and package name.
58+ */
59+ public Package(ClassPath path, Identifier pkg) throws IOException {
60+ this(path, path, pkg);
61+ }
62+
63+ /**
64+ * Create a package given a source path, binary path, and package
65+ * name.
66+ */
67+ public Package(ClassPath sourcePath,
68+ ClassPath binaryPath,
69+ Identifier pkg)
70+ throws IOException {
71+ if (pkg.isInner())
72+ pkg = Identifier.lookup(pkg.getQualifier(), pkg.getFlatName());
73+ this.sourcePath = sourcePath;
74+ this.binaryPath = binaryPath;
75+ this.pkg = pkg.toString().replace('.', File.separatorChar);
76+ }
77+
78+ /**
79+ * Check if a class is defined in this package.
80+ * (If it is an inner class name, it is assumed to exist
81+ * only if its binary file exists. This is somewhat pessimistic.)
82+ */
83+ public boolean classExists(Identifier className) {
84+ return getBinaryFile(className) != null ||
85+ !className.isInner() &&
86+ getSourceFile(className) != null;
87+ }
88+
89+ /**
90+ * Check if the package exists
91+ */
92+ public boolean exists() {
93+ // Look for the directory on our binary path.
94+ ClassFile dir = binaryPath.getDirectory(pkg);
95+ if (dir != null && dir.isDirectory()) {
96+ return true;
97+ }
98+
99+ if (sourcePath != binaryPath) {
100+ // Look for the directory on our source path.
101+ dir = sourcePath.getDirectory(pkg);
102+ if (dir != null && dir.isDirectory()) {
103+ return true;
104+ }
105+ }
106+
107+ /* Accommodate ZIP files without CEN entries for directories
108+ * (packages): look on class path for at least one binary
109+ * file or one source file with the right package prefix
110+ */
111+ String prefix = pkg + File.separator;
112+
113+ return binaryPath.getFiles(prefix, ".class").hasMoreElements()
114+ || sourcePath.getFiles(prefix, ".java").hasMoreElements();
115+ }
116+
117+ private String makeName(String fileName) {
118+ return pkg.equals("") ? fileName : pkg + File.separator + fileName;
119+ }
120+
121+ /**
122+ * Get the .class file of a class
123+ */
124+ public ClassFile getBinaryFile(Identifier className) {
125+ className = Type.mangleInnerType(className);
126+ String fileName = className.toString() + ".class";
127+ return binaryPath.getFile(makeName(fileName));
128+ }
129+
130+ /**
131+ * Get the .java file of a class
132+ */
133+ public ClassFile getSourceFile(Identifier className) {
134+ // The source file of an inner class is that of its outer class.
135+ className = className.getTopName();
136+ String fileName = className.toString() + ".java";
137+ return sourcePath.getFile(makeName(fileName));
138+ }
139+
140+ public ClassFile getSourceFile(String fileName) {
141+ if (fileName.endsWith(".java")) {
142+ return sourcePath.getFile(makeName(fileName));
143+ }
144+ return null;
145+ }
146+
147+ public Enumeration getSourceFiles() {
148+ return sourcePath.getFiles(pkg, ".java");
149+ }
150+
151+ public Enumeration getBinaryFiles() {
152+ return binaryPath.getFiles(pkg, ".class");
153+ }
154+
155+ public String toString() {
156+ if (pkg.equals("")) {
157+ return "unnamed package";
158+ }
159+ return "package " + pkg;
160+ }
161+}
java/pkg/sun/tools/java/Parser.java+2130−0
@@ -0,0 +1,2130 @@
1+/*
2+ * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import sun.tools.tree.*;
29+import java.io.IOException;
30+import java.io.InputStream;
31+import java.util.Enumeration;
32+import java.util.Vector;
33+
34+/**
35+ * This class is used to parse Java statements and expressions.
36+ * The result is a parse tree.<p>
37+ *
38+ * This class implements an operator precedence parser. Errors are
39+ * reported to the Environment object, if the error can't be
40+ * resolved immediately, a SyntaxError exception is thrown.<p>
41+ *
42+ * Error recovery is implemented by catching SyntaxError exceptions
43+ * and discarding input tokens until an input token is reached that
44+ * is possibly a legal continuation.<p>
45+ *
46+ * The parse tree that is constructed represents the input
47+ * exactly (no rewrites to simpler forms). This is important
48+ * if the resulting tree is to be used for code formatting in
49+ * a programming environment. Currently only documentation comments
50+ * are retained.<p>
51+ *
52+ * The parsing algorithm does NOT use any type information. Changes
53+ * in the type system do not affect the structure of the parse tree.
54+ * This restriction does introduce an ambiguity an expression of the
55+ * form: (e1) e2 is assumed to be a cast if e2 does not start with
56+ * an operator. That means that (a) - b is interpreted as subtract
57+ * b from a and not cast negative b to type a. However, if a is a
58+ * simple type (byte, int, ...) then it is assumed to be a cast.<p>
59+ *
60+ * WARNING: The contents of this source file are not part of any
61+ * supported API. Code that depends on them does so at its own risk:
62+ * they are subject to change or removal without notice.
63+ *
64+ * @author Arthur van Hoff
65+ */
66+
67+public
68+class Parser extends Scanner implements ParserActions, Constants {
69+ /**
70+ * Create a parser
71+ */
72+ protected Parser(Environment env, InputStream in) throws IOException {
73+ super(env, in);
74+ this.scanner = this;
75+ this.actions = this;
76+ }
77+
78+ /**
79+ * Create a parser, given a scanner.
80+ */
81+ protected Parser(Scanner scanner) throws IOException {
82+ super(scanner.env);
83+ this.scanner = scanner;
84+ ((Scanner)this).env = scanner.env;
85+ ((Scanner)this).token = scanner.token;
86+ ((Scanner)this).pos = scanner.pos;
87+ this.actions = this;
88+ }
89+
90+ /**
91+ * Create a parser, given a scanner and the semantic callback.
92+ */
93+ public Parser(Scanner scanner, ParserActions actions) throws IOException {
94+ this(scanner);
95+ this.actions = actions;
96+ }
97+
98+ /**
99+ * Usually <code>this.actions == (ParserActions)this</code>.
100+ * However, a delegate scanner can produce tokens for this parser,
101+ * in which case <code>(Scanner)this</code> is unused,
102+ * except for <code>this.token</code> and <code>this.pos</code>
103+ * instance variables which are filled from the real scanner
104+ * by <code>this.scan()</code> and the constructor.
105+ */
106+ ParserActions actions;
107+
108+ // Note: The duplication of methods allows pre-1.1 classes to
109+ // be binary compatible with the new version of the parser,
110+ // which now passes IdentifierTokens to the semantics phase,
111+ // rather than just Identifiers. This change is necessary,
112+ // since the parser is no longer responsible for managing the
113+ // resolution of type names. (That caused the "Vector" bug.)
114+ //
115+ // In a future release, the old "plain-Identifier" methods will
116+ // go away, and the corresponding "IdentifierToken" methods
117+ // may become abstract.
118+
119+ /**
120+ * package declaration
121+ * @deprecated
122+ */
123+ @Deprecated
124+ public void packageDeclaration(long off, IdentifierToken nm) {
125+ // By default, call the deprecated version.
126+ // Any application must override one of the packageDeclaration methods.
127+ packageDeclaration(off, nm.id);
128+ }
129+ /**
130+ * @deprecated
131+ */
132+ @Deprecated
133+ protected void packageDeclaration(long off, Identifier nm) {
134+ throw new RuntimeException("beginClass method is abstract");
135+ }
136+
137+ /**
138+ * import class
139+ * @deprecated
140+ */
141+ @Deprecated
142+ public void importClass(long off, IdentifierToken nm) {
143+ // By default, call the deprecated version.
144+ // Any application must override one of the packageDeclaration methods.
145+ importClass(off, nm.id);
146+ }
147+ /**
148+ * @deprecated Use the version with the IdentifierToken arguments.
149+ */
150+ @Deprecated
151+ protected void importClass(long off, Identifier nm) {
152+ throw new RuntimeException("importClass method is abstract");
153+ }
154+
155+ /**
156+ * import package
157+ * @deprecated
158+ */
159+ @Deprecated
160+ public void importPackage(long off, IdentifierToken nm) {
161+ // By default, call the deprecated version.
162+ // Any application must override one of the importPackage methods.
163+ importPackage(off, nm.id);
164+ }
165+ /**
166+ * @deprecated Use the version with the IdentifierToken arguments.
167+ */
168+ @Deprecated
169+ protected void importPackage(long off, Identifier nm) {
170+ throw new RuntimeException("importPackage method is abstract");
171+ }
172+
173+ /**
174+ * Define class
175+ * @deprecated
176+ */
177+ @Deprecated
178+ public ClassDefinition beginClass(long off, String doc,
179+ int mod, IdentifierToken nm,
180+ IdentifierToken sup,
181+ IdentifierToken impl[]) {
182+ // By default, call the deprecated version.
183+ // Any application must override one of the beginClass methods.
184+ Identifier supId = (sup == null) ? null : sup.id;
185+ Identifier implIds[] = null;
186+ if (impl != null) {
187+ implIds = new Identifier[impl.length];
188+ for (int i = 0; i < impl.length; i++) {
189+ implIds[i] = impl[i].id;
190+ }
191+ }
192+ beginClass(off, doc, mod, nm.id, supId, implIds);
193+ return getCurrentClass();
194+ }
195+ /**
196+ * @deprecated Use the version with the IdentifierToken arguments.
197+ */
198+ @Deprecated
199+ protected void beginClass(long off, String doc, int mod, Identifier nm,
200+ Identifier sup, Identifier impl[]) {
201+ throw new RuntimeException("beginClass method is abstract");
202+ }
203+
204+ /**
205+ * Report the current class under construction.
206+ * By default, it's a no-op which returns null.
207+ * It may only be called before the corresponding endClass().
208+ */
209+ protected ClassDefinition getCurrentClass() {
210+ return null;
211+ }
212+
213+ /**
214+ * End class
215+ * @deprecated
216+ */
217+ @Deprecated
218+ public void endClass(long off, ClassDefinition c) {
219+ // By default, call the deprecated version.
220+ // Any application must override one of the beginClass methods.
221+ endClass(off, c.getName().getFlatName().getName());
222+ }
223+ /**
224+ * @deprecated Use the version with the IdentifierToken arguments.
225+ */
226+ @Deprecated
227+ protected void endClass(long off, Identifier nm) {
228+ throw new RuntimeException("endClass method is abstract");
229+ }
230+
231+ /**
232+ * Define a field
233+ * @deprecated
234+ */
235+ @Deprecated
236+ public void defineField(long where, ClassDefinition c,
237+ String doc, int mod, Type t,
238+ IdentifierToken nm, IdentifierToken args[],
239+ IdentifierToken exp[], Node val) {
240+ // By default, call the deprecated version.
241+ // Any application must override one of the defineField methods.
242+ Identifier argIds[] = null;
243+ Identifier expIds[] = null;
244+ if (args != null) {
245+ argIds = new Identifier[args.length];
246+ for (int i = 0; i < args.length; i++) {
247+ argIds[i] = args[i].id;
248+ }
249+ }
250+ if (exp != null) {
251+ expIds = new Identifier[exp.length];
252+ for (int i = 0; i < exp.length; i++) {
253+ expIds[i] = exp[i].id;
254+ }
255+ }
256+ defineField(where, doc, mod, t, nm.id, argIds, expIds, val);
257+ }
258+
259+ /**
260+ * @deprecated Use the version with the IdentifierToken arguments.
261+ */
262+ @Deprecated
263+ protected void defineField(long where, String doc, int mod, Type t,
264+ Identifier nm, Identifier args[],
265+ Identifier exp[], Node val) {
266+ throw new RuntimeException("defineField method is abstract");
267+ }
268+
269+ /*
270+ * A growable array of nodes. It is used as a growable
271+ * buffer to hold argument lists and expression lists.
272+ * I'm not using Vector to make it more efficient.
273+ */
274+ private Node args[] = new Node[32];
275+ protected int argIndex = 0;
276+
277+ protected final void addArgument(Node n) {
278+ if (argIndex == args.length) {
279+ Node newArgs[] = new Node[args.length * 2];
280+ System.arraycopy(args, 0, newArgs, 0, args.length);
281+ args = newArgs;
282+ }
283+ args[argIndex++] = n;
284+ }
285+ protected final Expression exprArgs(int index)[] {
286+ Expression e[] = new Expression[argIndex - index];
287+ System.arraycopy(args, index, e, 0, argIndex - index);
288+ argIndex = index;
289+ return e;
290+ }
291+ protected final Statement statArgs(int index)[] {
292+ Statement s[] = new Statement[argIndex - index];
293+ System.arraycopy(args, index, s, 0, argIndex - index);
294+ argIndex = index;
295+ return s;
296+ }
297+
298+ /**
299+ * Expect a token, return its value, scan the next token or
300+ * throw an exception.
301+ */
302+ protected void expect(int t) throws SyntaxError, IOException {
303+ if (token != t) {
304+ switch (t) {
305+ case IDENT:
306+ env.error(scanner.prevPos, "identifier.expected");
307+ break;
308+ default:
309+ env.error(scanner.prevPos, "token.expected", opNames[t]);
310+ break;
311+ }
312+ throw new SyntaxError();
313+ }
314+ scan();
315+ }
316+
317+ /**
318+ * Parse a type expression. Does not parse the []'s.
319+ */
320+ protected Expression parseTypeExpression() throws SyntaxError, IOException {
321+ switch (token) {
322+ case VOID:
323+ return new TypeExpression(scan(), Type.tVoid);
324+ case BOOLEAN:
325+ return new TypeExpression(scan(), Type.tBoolean);
326+ case BYTE:
327+ return new TypeExpression(scan(), Type.tByte);
328+ case CHAR:
329+ return new TypeExpression(scan(), Type.tChar);
330+ case SHORT:
331+ return new TypeExpression(scan(), Type.tShort);
332+ case INT:
333+ return new TypeExpression(scan(), Type.tInt);
334+ case LONG:
335+ return new TypeExpression(scan(), Type.tLong);
336+ case FLOAT:
337+ return new TypeExpression(scan(), Type.tFloat);
338+ case DOUBLE:
339+ return new TypeExpression(scan(), Type.tDouble);
340+ case IDENT:
341+ Expression e = new IdentifierExpression(pos, scanner.idValue);
342+ scan();
343+ while (token == FIELD) {
344+ e = new FieldExpression(scan(), e, scanner.idValue);
345+ expect(IDENT);
346+ }
347+ return e;
348+ }
349+
350+ env.error(pos, "type.expected");
351+ throw new SyntaxError();
352+ }
353+
354+ /**
355+ * Parse a method invocation. Should be called when the current
356+ * then is the '(' of the argument list.
357+ */
358+ protected Expression parseMethodExpression(Expression e, Identifier id) throws SyntaxError, IOException {
359+ long p = scan();
360+ int i = argIndex;
361+ if (token != RPAREN) {
362+ addArgument(parseExpression());
363+ while (token == COMMA) {
364+ scan();
365+ addArgument(parseExpression());
366+ }
367+ }
368+ expect(RPAREN);
369+ return new MethodExpression(p, e, id, exprArgs(i));
370+ }
371+
372+ /**
373+ * Parse a new instance expression. Should be called when the current
374+ * token is the '(' of the argument list.
375+ */
376+ protected Expression parseNewInstanceExpression(long p, Expression outerArg, Expression type) throws SyntaxError, IOException {
377+ int i = argIndex;
378+ expect(LPAREN);
379+ if (token != RPAREN) {
380+ addArgument(parseExpression());
381+ while (token == COMMA) {
382+ scan();
383+ addArgument(parseExpression());
384+ }
385+ }
386+ expect(RPAREN);
387+ ClassDefinition body = null;
388+ if (token == LBRACE && !(type instanceof TypeExpression)) {
389+ long tp = pos;
390+ // x = new Type(arg) { subclass body ... }
391+ Identifier superName = FieldExpression.toIdentifier(type);
392+ if (superName == null) {
393+ env.error(type.getWhere(), "type.expected");
394+ }
395+ Vector ext = new Vector(1);
396+ Vector impl = new Vector(0);
397+ ext.addElement(new IdentifierToken(idNull));
398+ if (token == IMPLEMENTS || token == EXTENDS) {
399+ env.error(pos, "anonymous.extends");
400+ parseInheritance(ext, impl); // error recovery
401+ }
402+ body = parseClassBody(new IdentifierToken(tp, idNull),
403+ M_ANONYMOUS | M_LOCAL, EXPR, null,
404+ ext, impl, type.getWhere());
405+ }
406+ if (outerArg == null && body == null) {
407+ return new NewInstanceExpression(p, type, exprArgs(i));
408+ }
409+ return new NewInstanceExpression(p, type, exprArgs(i), outerArg, body);
410+ }
411+
412+ /**
413+ * Parse a primary expression.
414+ */
415+ protected Expression parseTerm() throws SyntaxError, IOException {
416+ switch (token) {
417+ case CHARVAL: {
418+ char v = scanner.charValue;
419+ return new CharExpression(scan(), v);
420+ }
421+ case INTVAL: {
422+ int v = scanner.intValue;
423+ long q = scan();
424+ if (v < 0 && radix == 10) env.error(q, "overflow.int.dec");
425+ return new IntExpression(q, v);
426+ }
427+ case LONGVAL: {
428+ long v = scanner.longValue;
429+ long q = scan();
430+ if (v < 0 && radix == 10) env.error(q, "overflow.long.dec");
431+ return new LongExpression(q, v);
432+ }
433+ case FLOATVAL: {
434+ float v = scanner.floatValue;
435+ return new FloatExpression(scan(), v);
436+ }
437+ case DOUBLEVAL: {
438+ double v = scanner.doubleValue;
439+ return new DoubleExpression(scan(), v);
440+ }
441+ case STRINGVAL: {
442+ String v = scanner.stringValue;
443+ return new StringExpression(scan(), v);
444+ }
445+ case IDENT: {
446+ Identifier v = scanner.idValue;
447+ long p = scan();
448+ return (token == LPAREN) ?
449+ parseMethodExpression(null, v) : new IdentifierExpression(p, v);
450+ }
451+
452+ case TRUE:
453+ return new BooleanExpression(scan(), true);
454+ case FALSE:
455+ return new BooleanExpression(scan(), false);
456+ case NULL:
457+ return new NullExpression(scan());
458+
459+ case THIS: {
460+ Expression e = new ThisExpression(scan());
461+ return (token == LPAREN) ? parseMethodExpression(e, idInit) : e;
462+ }
463+ case SUPER: {
464+ Expression e = new SuperExpression(scan());
465+ return (token == LPAREN) ? parseMethodExpression(e, idInit) : e;
466+ }
467+
468+ case VOID:
469+ case BOOLEAN:
470+ case BYTE:
471+ case CHAR:
472+ case SHORT:
473+ case INT:
474+ case LONG:
475+ case FLOAT:
476+ case DOUBLE:
477+ return parseTypeExpression();
478+
479+ case ADD: {
480+ long p = scan();
481+ switch (token) {
482+ case INTVAL: {
483+ int v = scanner.intValue;
484+ long q = scan();
485+ if (v < 0 && radix == 10) env.error(q, "overflow.int.dec");
486+ return new IntExpression(q, v);
487+ }
488+ case LONGVAL: {
489+ long v = scanner.longValue;
490+ long q = scan();
491+ if (v < 0 && radix == 10) env.error(q, "overflow.long.dec");
492+ return new LongExpression(q, v);
493+ }
494+ case FLOATVAL: {
495+ float v = scanner.floatValue;
496+ return new FloatExpression(scan(), v);
497+ }
498+ case DOUBLEVAL: {
499+ double v = scanner.doubleValue;
500+ return new DoubleExpression(scan(), v);
501+ }
502+ }
503+ return new PositiveExpression(p, parseTerm());
504+ }
505+ case SUB: {
506+ long p = scan();
507+ switch (token) {
508+ case INTVAL: {
509+ int v = -scanner.intValue;
510+ return new IntExpression(scan(), v);
511+ }
512+ case LONGVAL: {
513+ long v = -scanner.longValue;
514+ return new LongExpression(scan(), v);
515+ }
516+ case FLOATVAL: {
517+ float v = -scanner.floatValue;
518+ return new FloatExpression(scan(), v);
519+ }
520+ case DOUBLEVAL: {
521+ double v = -scanner.doubleValue;
522+ return new DoubleExpression(scan(), v);
523+ }
524+ }
525+ return new NegativeExpression(p, parseTerm());
526+ }
527+ case NOT:
528+ return new NotExpression(scan(), parseTerm());
529+ case BITNOT:
530+ return new BitNotExpression(scan(), parseTerm());
531+ case INC:
532+ return new PreIncExpression(scan(), parseTerm());
533+ case DEC:
534+ return new PreDecExpression(scan(), parseTerm());
535+
536+ case LPAREN: {
537+ // bracketed-expr: (expr)
538+ long p = scan();
539+ Expression e = parseExpression();
540+ expect(RPAREN);
541+
542+ if (e.getOp() == TYPE) {
543+ // cast-expr: (simple-type) expr
544+ return new CastExpression(p, e, parseTerm());
545+ }
546+
547+ switch (token) {
548+
549+ // We handle INC and DEC specially.
550+ // See the discussion in JLS section 15.14.1.
551+ // (Part of fix for 4044502.)
552+
553+ case INC:
554+ // We know this must be a postfix increment.
555+ return new PostIncExpression(scan(), e);
556+
557+ case DEC:
558+ // We know this must be a postfix decrement.
559+ return new PostDecExpression(scan(), e);
560+
561+ case LPAREN:
562+ case CHARVAL:
563+ case INTVAL:
564+ case LONGVAL:
565+ case FLOATVAL:
566+ case DOUBLEVAL:
567+ case STRINGVAL:
568+ case IDENT:
569+ case TRUE:
570+ case FALSE:
571+ case NOT:
572+ case BITNOT:
573+ case THIS:
574+ case SUPER:
575+ case NULL:
576+ case NEW:
577+ // cast-expr: (expr) expr
578+ return new CastExpression(p, e, parseTerm());
579+ }
580+ return new ExprExpression(p, e);
581+ }
582+
583+ case LBRACE: {
584+ // array initializer: {expr1, expr2, ... exprn}
585+ long p = scan();
586+ int i = argIndex;
587+ if (token != RBRACE) {
588+ addArgument(parseExpression());
589+ while (token == COMMA) {
590+ scan();
591+ if (token == RBRACE) {
592+ break;
593+ }
594+ addArgument(parseExpression());
595+ }
596+ }
597+ expect(RBRACE);
598+ return new ArrayExpression(p, exprArgs(i));
599+ }
600+
601+ case NEW: {
602+ long p = scan();
603+ int i = argIndex;
604+
605+ if (token == LPAREN) {
606+ scan();
607+ Expression e = parseExpression();
608+ expect(RPAREN);
609+ env.error(p, "not.supported", "new(...)");
610+ return new NullExpression(p);
611+ }
612+
613+ Expression e = parseTypeExpression();
614+
615+ if (token == LSQBRACKET) {
616+ while (token == LSQBRACKET) {
617+ scan();
618+ addArgument((token != RSQBRACKET) ? parseExpression() : null);
619+ expect(RSQBRACKET);
620+ }
621+ Expression[] dims = exprArgs(i);
622+ if (token == LBRACE) {
623+ return new NewArrayExpression(p, e, dims, parseTerm());
624+ }
625+ return new NewArrayExpression(p, e, dims);
626+ } else {
627+ return parseNewInstanceExpression(p, null, e);
628+ }
629+ }
630+ }
631+
632+ // System.err.println("NEAR: " + opNames[token]);
633+ env.error(scanner.prevPos, "missing.term");
634+ return new IntExpression(pos, 0);
635+ }
636+
637+ /**
638+ * Parse an expression.
639+ */
640+ protected Expression parseExpression() throws SyntaxError, IOException {
641+ for (Expression e = parseTerm() ; e != null ; e = e.order()) {
642+ Expression more = parseBinaryExpression(e);
643+ if (more == null)
644+ return e;
645+ e = more;
646+ }
647+ // this return is bogus
648+ return null;
649+ }
650+
651+ /**
652+ * Given a left-hand term, parse an operator and right-hand term.
653+ */
654+ protected Expression parseBinaryExpression(Expression e) throws SyntaxError, IOException {
655+ if (e != null) {
656+ switch (token) {
657+ case LSQBRACKET: {
658+ // index: expr1[expr2]
659+ long p = scan();
660+ Expression index = (token != RSQBRACKET) ? parseExpression() : null;
661+ expect(RSQBRACKET);
662+ e = new ArrayAccessExpression(p, e, index);
663+ break;
664+ }
665+
666+ case INC:
667+ e = new PostIncExpression(scan(), e);
668+ break;
669+ case DEC:
670+ e = new PostDecExpression(scan(), e);
671+ break;
672+ case FIELD: {
673+ long p = scan();
674+ if (token == THIS) {
675+ // class C { class N { ... C.this ... } }
676+ // class C { class N { N(C c){ ... c.this() ... } } }
677+ long q = scan();
678+ if (token == LPAREN) {
679+ e = new ThisExpression(q, e);
680+ e = parseMethodExpression(e, idInit);
681+ } else {
682+ e = new FieldExpression(p, e, idThis);
683+ }
684+ break;
685+ }
686+ if (token == SUPER) {
687+ // class D extends C.N { D(C.N n) { n.super(); } }
688+ // Also, 'C.super', as in:
689+ // class C extends CS { class N { ... C.super.foo ... } }
690+ // class C extends CS { class N { ... C.super.foo() ... } }
691+ long q = scan();
692+ if (token == LPAREN) {
693+ e = new SuperExpression(q, e);
694+ e = parseMethodExpression(e, idInit);
695+ } else {
696+ // We must check elsewhere that this expression
697+ // does not stand alone, but qualifies a member name.
698+ e = new FieldExpression(p, e, idSuper);
699+ }
700+ break;
701+ }
702+ if (token == NEW) {
703+ // new C().new N()
704+ scan();
705+ if (token != IDENT)
706+ expect(IDENT);
707+ e = parseNewInstanceExpression(p, e, parseTypeExpression());
708+ break;
709+ }
710+ if (token == CLASS) {
711+ // just class literals, really
712+ // Class c = C.class;
713+ scan();
714+ e = new FieldExpression(p, e, idClass);
715+ break;
716+ }
717+ Identifier id = scanner.idValue;
718+ expect(IDENT);
719+ if (token == LPAREN) {
720+ e = parseMethodExpression(e, id);
721+ } else {
722+ e = new FieldExpression(p, e, id);
723+ }
724+ break;
725+ }
726+ case INSTANCEOF:
727+ e = new InstanceOfExpression(scan(), e, parseTerm());
728+ break;
729+ case ADD:
730+ e = new AddExpression(scan(), e, parseTerm());
731+ break;
732+ case SUB:
733+ e = new SubtractExpression(scan(), e, parseTerm());
734+ break;
735+ case MUL:
736+ e = new MultiplyExpression(scan(), e, parseTerm());
737+ break;
738+ case DIV:
739+ e = new DivideExpression(scan(), e, parseTerm());
740+ break;
741+ case REM:
742+ e = new RemainderExpression(scan(), e, parseTerm());
743+ break;
744+ case LSHIFT:
745+ e = new ShiftLeftExpression(scan(), e, parseTerm());
746+ break;
747+ case RSHIFT:
748+ e = new ShiftRightExpression(scan(), e, parseTerm());
749+ break;
750+ case URSHIFT:
751+ e = new UnsignedShiftRightExpression(scan(), e, parseTerm());
752+ break;
753+ case LT:
754+ e = new LessExpression(scan(), e, parseTerm());
755+ break;
756+ case LE:
757+ e = new LessOrEqualExpression(scan(), e, parseTerm());
758+ break;
759+ case GT:
760+ e = new GreaterExpression(scan(), e, parseTerm());
761+ break;
762+ case GE:
763+ e = new GreaterOrEqualExpression(scan(), e, parseTerm());
764+ break;
765+ case EQ:
766+ e = new EqualExpression(scan(), e, parseTerm());
767+ break;
768+ case NE:
769+ e = new NotEqualExpression(scan(), e, parseTerm());
770+ break;
771+ case BITAND:
772+ e = new BitAndExpression(scan(), e, parseTerm());
773+ break;
774+ case BITXOR:
775+ e = new BitXorExpression(scan(), e, parseTerm());
776+ break;
777+ case BITOR:
778+ e = new BitOrExpression(scan(), e, parseTerm());
779+ break;
780+ case AND:
781+ e = new AndExpression(scan(), e, parseTerm());
782+ break;
783+ case OR:
784+ e = new OrExpression(scan(), e, parseTerm());
785+ break;
786+ case ASSIGN:
787+ e = new AssignExpression(scan(), e, parseTerm());
788+ break;
789+ case ASGMUL:
790+ e = new AssignMultiplyExpression(scan(), e, parseTerm());
791+ break;
792+ case ASGDIV:
793+ e = new AssignDivideExpression(scan(), e, parseTerm());
794+ break;
795+ case ASGREM:
796+ e = new AssignRemainderExpression(scan(), e, parseTerm());
797+ break;
798+ case ASGADD:
799+ e = new AssignAddExpression(scan(), e, parseTerm());
800+ break;
801+ case ASGSUB:
802+ e = new AssignSubtractExpression(scan(), e, parseTerm());
803+ break;
804+ case ASGLSHIFT:
805+ e = new AssignShiftLeftExpression(scan(), e, parseTerm());
806+ break;
807+ case ASGRSHIFT:
808+ e = new AssignShiftRightExpression(scan(), e, parseTerm());
809+ break;
810+ case ASGURSHIFT:
811+ e = new AssignUnsignedShiftRightExpression(scan(), e, parseTerm());
812+ break;
813+ case ASGBITAND:
814+ e = new AssignBitAndExpression(scan(), e, parseTerm());
815+ break;
816+ case ASGBITOR:
817+ e = new AssignBitOrExpression(scan(), e, parseTerm());
818+ break;
819+ case ASGBITXOR:
820+ e = new AssignBitXorExpression(scan(), e, parseTerm());
821+ break;
822+ case QUESTIONMARK: {
823+ long p = scan();
824+ Expression second = parseExpression();
825+ expect(COLON);
826+ Expression third = parseExpression();
827+
828+ // The grammar in the JLS does not allow assignment
829+ // expressions as the third part of a ?: expression.
830+ // Even though javac has no trouble parsing this,
831+ // check for this case and signal an error.
832+ // (fix for bug 4092958)
833+ if (third instanceof AssignExpression
834+ || third instanceof AssignOpExpression) {
835+ env.error(third.getWhere(), "assign.in.conditionalexpr");
836+ }
837+
838+ e = new ConditionalExpression(p, e, second, third);
839+ break;
840+ }
841+
842+ default:
843+ return null; // mark end of binary expressions
844+ }
845+ }
846+ return e; // return more binary expression stuff
847+ }
848+
849+ /**
850+ * Recover after a syntax error in a statement. This involves
851+ * discarding tokens until EOF or a possible continuation is
852+ * encountered.
853+ */
854+ protected boolean recoverStatement() throws SyntaxError, IOException {
855+ while (true) {
856+ switch (token) {
857+ case EOF:
858+ case RBRACE:
859+ case LBRACE:
860+ case IF:
861+ case FOR:
862+ case WHILE:
863+ case DO:
864+ case TRY:
865+ case CATCH:
866+ case FINALLY:
867+ case BREAK:
868+ case CONTINUE:
869+ case RETURN:
870+ // begin of a statement, return
871+ return true;
872+
873+ case VOID:
874+ case STATIC:
875+ case PUBLIC:
876+ case PRIVATE:
877+ case SYNCHRONIZED:
878+ case INTERFACE:
879+ case CLASS:
880+ case TRANSIENT:
881+ // begin of something outside a statement, panic some more
882+ expect(RBRACE);
883+ return false;
884+
885+ case LPAREN:
886+ match(LPAREN, RPAREN);
887+ scan();
888+ break;
889+
890+ case LSQBRACKET:
891+ match(LSQBRACKET, RSQBRACKET);
892+ scan();
893+ break;
894+
895+ default:
896+ // don't know what to do, skip
897+ scan();
898+ break;
899+ }
900+ }
901+ }
902+
903+ /**
904+ * Parse declaration, called after the type expression
905+ * has been parsed and the current token is IDENT.
906+ */
907+ protected Statement parseDeclaration(long p, int mod, Expression type) throws SyntaxError, IOException {
908+ int i = argIndex;
909+ if (token == IDENT) {
910+ addArgument(new VarDeclarationStatement(pos, parseExpression()));
911+ while (token == COMMA) {
912+ scan();
913+ addArgument(new VarDeclarationStatement(pos, parseExpression()));
914+ }
915+ }
916+ return new DeclarationStatement(p, mod, type, statArgs(i));
917+ }
918+
919+ /**
920+ * Check if an expression is a legal toplevel expression.
921+ * Only method, inc, dec, and new expression are allowed.
922+ */
923+ protected void topLevelExpression(Expression e) {
924+ switch (e.getOp()) {
925+ case ASSIGN:
926+ case ASGMUL:
927+ case ASGDIV:
928+ case ASGREM:
929+ case ASGADD:
930+ case ASGSUB:
931+ case ASGLSHIFT:
932+ case ASGRSHIFT:
933+ case ASGURSHIFT:
934+ case ASGBITAND:
935+ case ASGBITOR:
936+ case ASGBITXOR:
937+ case PREINC:
938+ case PREDEC:
939+ case POSTINC:
940+ case POSTDEC:
941+ case METHOD:
942+ case NEWINSTANCE:
943+ return;
944+ }
945+ env.error(e.getWhere(), "invalid.expr");
946+ }
947+
948+ /**
949+ * Parse a statement.
950+ */
951+ protected Statement parseStatement() throws SyntaxError, IOException {
952+ switch (token) {
953+ case SEMICOLON:
954+ return new CompoundStatement(scan(), new Statement[0]);
955+
956+ case LBRACE:
957+ return parseBlockStatement();
958+
959+ case IF: {
960+ // if-statement: if (expr) stat
961+ // if-statement: if (expr) stat else stat
962+ long p = scan();
963+
964+ expect(LPAREN);
965+ Expression c = parseExpression();
966+ expect(RPAREN);
967+ Statement t = parseStatement();
968+ if (token == ELSE) {
969+ scan();
970+ return new IfStatement(p, c, t, parseStatement());
971+ } else {
972+ return new IfStatement(p, c, t, null);
973+ }
974+ }
975+
976+ case ELSE: {
977+ // else-statement: else stat
978+ env.error(scan(), "else.without.if");
979+ return parseStatement();
980+ }
981+
982+ case FOR: {
983+ // for-statement: for (decl-expr? ; expr? ; expr?) stat
984+ long p = scan();
985+ Statement init = null;
986+ Expression cond = null, inc = null;
987+
988+ expect(LPAREN);
989+ if (token != SEMICOLON) {
990+ long p2 = pos;
991+ int mod = parseModifiers(M_FINAL);
992+ Expression e = parseExpression();
993+
994+ if (token == IDENT) {
995+ init = parseDeclaration(p2, mod, e);
996+ } else {
997+ if (mod != 0) {
998+ expect(IDENT); // should have been a declaration
999+ }
1000+ topLevelExpression(e);
1001+ while (token == COMMA) {
1002+ long p3 = scan();
1003+ Expression e2 = parseExpression();
1004+ topLevelExpression(e2);
1005+ e = new CommaExpression(p3, e, e2);
1006+ }
1007+ init = new ExpressionStatement(p2, e);
1008+ }
1009+ }
1010+ expect(SEMICOLON);
1011+ if (token != SEMICOLON) {
1012+ cond = parseExpression();
1013+ }
1014+ expect(SEMICOLON);
1015+ if (token != RPAREN) {
1016+ inc = parseExpression();
1017+ topLevelExpression(inc);
1018+ while (token == COMMA) {
1019+ long p2 = scan();
1020+ Expression e2 = parseExpression();
1021+ topLevelExpression(e2);
1022+ inc = new CommaExpression(p2, inc, e2);
1023+ }
1024+ }
1025+ expect(RPAREN);
1026+ return new ForStatement(p, init, cond, inc, parseStatement());
1027+ }
1028+
1029+ case WHILE: {
1030+ // while-statement: while (expr) stat
1031+ long p = scan();
1032+
1033+ expect(LPAREN);
1034+ Expression cond = parseExpression();
1035+ expect(RPAREN);
1036+ return new WhileStatement(p, cond, parseStatement());
1037+ }
1038+
1039+ case DO: {
1040+ // do-statement: do stat while (expr)
1041+ long p = scan();
1042+
1043+ Statement body = parseStatement();
1044+ expect(WHILE);
1045+ expect(LPAREN);
1046+ Expression cond = parseExpression();
1047+ expect(RPAREN);
1048+ expect(SEMICOLON);
1049+ return new DoStatement(p, body, cond);
1050+ }
1051+
1052+ case BREAK: {
1053+ // break-statement: break ;
1054+ long p = scan();
1055+ Identifier label = null;
1056+
1057+ if (token == IDENT) {
1058+ label = scanner.idValue;
1059+ scan();
1060+ }
1061+ expect(SEMICOLON);
1062+ return new BreakStatement(p, label);
1063+ }
1064+
1065+ case CONTINUE: {
1066+ // continue-statement: continue ;
1067+ long p = scan();
1068+ Identifier label = null;
1069+
1070+ if (token == IDENT) {
1071+ label = scanner.idValue;
1072+ scan();
1073+ }
1074+ expect(SEMICOLON);
1075+ return new ContinueStatement(p, label);
1076+ }
1077+
1078+ case RETURN: {
1079+ // return-statement: return ;
1080+ // return-statement: return expr ;
1081+ long p = scan();
1082+ Expression e = null;
1083+
1084+ if (token != SEMICOLON) {
1085+ e = parseExpression();
1086+ }
1087+ expect(SEMICOLON);
1088+ return new ReturnStatement(p, e);
1089+ }
1090+
1091+ case SWITCH: {
1092+ // switch statement: switch ( expr ) stat
1093+ long p = scan();
1094+ int i = argIndex;
1095+
1096+ expect(LPAREN);
1097+ Expression e = parseExpression();
1098+ expect(RPAREN);
1099+ expect(LBRACE);
1100+
1101+ while ((token != EOF) && (token != RBRACE)) {
1102+ int j = argIndex;
1103+ try {
1104+ switch (token) {
1105+ case CASE:
1106+ // case-statement: case expr:
1107+ addArgument(new CaseStatement(scan(), parseExpression()));
1108+ expect(COLON);
1109+ break;
1110+
1111+ case DEFAULT:
1112+ // default-statement: default:
1113+ addArgument(new CaseStatement(scan(), null));
1114+ expect(COLON);
1115+ break;
1116+
1117+ default:
1118+ addArgument(parseStatement());
1119+ break;
1120+ }
1121+ } catch (SyntaxError ee) {
1122+ argIndex = j;
1123+ if (!recoverStatement()) {
1124+ throw ee;
1125+ }
1126+ }
1127+ }
1128+ expect(RBRACE);
1129+ return new SwitchStatement(p, e, statArgs(i));
1130+ }
1131+
1132+ case CASE: {
1133+ // case-statement: case expr : stat
1134+ env.error(pos, "case.without.switch");
1135+ while (token == CASE) {
1136+ scan();
1137+ parseExpression();
1138+ expect(COLON);
1139+ }
1140+ return parseStatement();
1141+ }
1142+
1143+ case DEFAULT: {
1144+ // default-statement: default : stat
1145+ env.error(pos, "default.without.switch");
1146+ scan();
1147+ expect(COLON);
1148+ return parseStatement();
1149+ }
1150+
1151+ case TRY: {
1152+ // try-statement: try stat catch (type-expr ident) stat finally stat
1153+ long p = scan();
1154+ Statement init = null; // try-object specification
1155+ int i = argIndex;
1156+ boolean catches = false;
1157+
1158+ if (false && token == LPAREN) {
1159+ expect(LPAREN);
1160+ long p2 = pos;
1161+ int mod = parseModifiers(M_FINAL);
1162+ Expression e = parseExpression();
1163+
1164+ if (token == IDENT) {
1165+ init = parseDeclaration(p2, mod, e);
1166+ // leave check for try (T x, y) for semantic phase
1167+ } else {
1168+ if (mod != 0) {
1169+ expect(IDENT); // should have been a declaration
1170+ }
1171+ init = new ExpressionStatement(p2, e);
1172+ }
1173+ expect(RPAREN);
1174+ }
1175+
1176+ Statement s = parseBlockStatement();
1177+
1178+ if (init != null) {
1179+ // s = new FinallyStatement(p, init, s, 0);
1180+ }
1181+
1182+ while (token == CATCH) {
1183+ long pp = pos;
1184+ expect(CATCH);
1185+ expect(LPAREN);
1186+ int mod = parseModifiers(M_FINAL);
1187+ Expression t = parseExpression();
1188+ IdentifierToken id = scanner.getIdToken();
1189+ expect(IDENT);
1190+ id.modifiers = mod;
1191+ // We only catch Throwable's, so this is no longer required
1192+ // while (token == LSQBRACKET) {
1193+ // t = new ArrayAccessExpression(scan(), t, null);
1194+ // expect(RSQBRACKET);
1195+ // }
1196+ expect(RPAREN);
1197+ addArgument(new CatchStatement(pp, t, id, parseBlockStatement()));
1198+ catches = true;
1199+ }
1200+
1201+ if (catches)
1202+ s = new TryStatement(p, s, statArgs(i));
1203+
1204+ if (token == FINALLY) {
1205+ scan();
1206+ return new FinallyStatement(p, s, parseBlockStatement());
1207+ } else if (catches || init != null) {
1208+ return s;
1209+ } else {
1210+ env.error(pos, "try.without.catch.finally");
1211+ return new TryStatement(p, s, null);
1212+ }
1213+ }
1214+
1215+ case CATCH: {
1216+ // catch-statement: catch (expr ident) stat finally stat
1217+ env.error(pos, "catch.without.try");
1218+
1219+ Statement s;
1220+ do {
1221+ scan();
1222+ expect(LPAREN);
1223+ parseModifiers(M_FINAL);
1224+ parseExpression();
1225+ expect(IDENT);
1226+ expect(RPAREN);
1227+ s = parseBlockStatement();
1228+ } while (token == CATCH);
1229+
1230+ if (token == FINALLY) {
1231+ scan();
1232+ s = parseBlockStatement();
1233+ }
1234+ return s;
1235+ }
1236+
1237+ case FINALLY: {
1238+ // finally-statement: finally stat
1239+ env.error(pos, "finally.without.try");
1240+ scan();
1241+ return parseBlockStatement();
1242+ }
1243+
1244+ case THROW: {
1245+ // throw-statement: throw expr;
1246+ long p = scan();
1247+ Expression e = parseExpression();
1248+ expect(SEMICOLON);
1249+ return new ThrowStatement(p, e);
1250+ }
1251+
1252+ case GOTO: {
1253+ long p = scan();
1254+ expect(IDENT);
1255+ expect(SEMICOLON);
1256+ env.error(p, "not.supported", "goto");
1257+ return new CompoundStatement(p, new Statement[0]);
1258+ }
1259+
1260+ case SYNCHRONIZED: {
1261+ // synchronized-statement: synchronized (expr) stat
1262+ long p = scan();
1263+ expect(LPAREN);
1264+ Expression e = parseExpression();
1265+ expect(RPAREN);
1266+ return new SynchronizedStatement(p, e, parseBlockStatement());
1267+ }
1268+
1269+ case INTERFACE:
1270+ case CLASS:
1271+ // Inner class.
1272+ return parseLocalClass(0);
1273+
1274+ case CONST:
1275+ case ABSTRACT:
1276+ case FINAL:
1277+ case STRICTFP: {
1278+ // a declaration of some sort
1279+ long p = pos;
1280+
1281+ // A class which is local to a block is not a member, and so
1282+ // cannot be public, private, protected, or static. It is in
1283+ // effect private to the block, since it cannot be used outside
1284+ // its scope.
1285+ //
1286+ // However, any class (if it has a name) can be declared final,
1287+ // abstract, or strictfp.
1288+ int mod = parseModifiers(M_FINAL | M_ABSTRACT
1289+ | M_STRICTFP );
1290+
1291+ switch (token) {
1292+ case INTERFACE:
1293+ case CLASS:
1294+ return parseLocalClass(mod);
1295+
1296+ case BOOLEAN:
1297+ case BYTE:
1298+ case CHAR:
1299+ case SHORT:
1300+ case INT:
1301+ case LONG:
1302+ case FLOAT:
1303+ case DOUBLE:
1304+ case IDENT: {
1305+ if ((mod & (M_ABSTRACT | M_STRICTFP )) != 0) {
1306+ mod &= ~ (M_ABSTRACT | M_STRICTFP );
1307+ expect(CLASS);
1308+ }
1309+ Expression e = parseExpression();
1310+ if (token != IDENT) {
1311+ expect(IDENT);
1312+ }
1313+ // declaration: final expr expr
1314+ Statement s = parseDeclaration(p, mod, e);
1315+ expect(SEMICOLON);
1316+ return s;
1317+ }
1318+
1319+ default:
1320+ env.error(pos, "type.expected");
1321+ throw new SyntaxError();
1322+ }
1323+ }
1324+
1325+ case VOID:
1326+ case STATIC:
1327+ case PUBLIC:
1328+ case PRIVATE:
1329+ case TRANSIENT:
1330+ // This is the start of something outside a statement
1331+ env.error(pos, "statement.expected");
1332+ throw new SyntaxError();
1333+ }
1334+
1335+ long p = pos;
1336+ Expression e = parseExpression();
1337+
1338+ if (token == IDENT) {
1339+ // declaration: expr expr
1340+ Statement s = parseDeclaration(p, 0, e);
1341+ expect(SEMICOLON);
1342+ return s;
1343+ }
1344+ if (token == COLON) {
1345+ // label: id: stat
1346+ scan();
1347+ Statement s = parseStatement();
1348+ s.setLabel(env, e);
1349+ return s;
1350+ }
1351+
1352+ // it was just an expression...
1353+ topLevelExpression(e);
1354+ expect(SEMICOLON);
1355+ return new ExpressionStatement(p, e);
1356+ }
1357+
1358+ protected Statement parseBlockStatement() throws SyntaxError, IOException {
1359+ // compound statement: { stat1 stat2 ... statn }
1360+ if (token != LBRACE) {
1361+ // We're expecting a block statement. But we'll probably do the
1362+ // least damage if we try to parse a normal statement instead.
1363+ env.error(scanner.prevPos, "token.expected", opNames[LBRACE]);
1364+ return parseStatement();
1365+ }
1366+ long p = scan();
1367+ int i = argIndex;
1368+ while ((token != EOF) && (token != RBRACE)) {
1369+ int j = argIndex;
1370+ try {
1371+ addArgument(parseStatement());
1372+ } catch (SyntaxError e) {
1373+ argIndex = j;
1374+ if (!recoverStatement()) {
1375+ throw e;
1376+ }
1377+ }
1378+ }
1379+
1380+ expect(RBRACE);
1381+ return new CompoundStatement(p, statArgs(i));
1382+ }
1383+
1384+
1385+ /**
1386+ * Parse an identifier. ie: a.b.c returns "a.b.c"
1387+ * If star is true then "a.b.*" is allowed.
1388+ * The return value encodes both the identifier and its location.
1389+ */
1390+ protected IdentifierToken parseName(boolean star) throws SyntaxError, IOException {
1391+ IdentifierToken res = scanner.getIdToken();
1392+ expect(IDENT);
1393+
1394+ if (token != FIELD) {
1395+ return res;
1396+ }
1397+
1398+ StringBuffer buf = new StringBuffer(res.id.toString());
1399+
1400+ while (token == FIELD) {
1401+ scan();
1402+ if ((token == MUL) && star) {
1403+ scan();
1404+ buf.append(".*");
1405+ break;
1406+ }
1407+
1408+ buf.append('.');
1409+ if (token == IDENT) {
1410+ buf.append(scanner.idValue);
1411+ }
1412+ expect(IDENT);
1413+ }
1414+
1415+ res.id = Identifier.lookup(buf.toString());
1416+ return res;
1417+ }
1418+ /**
1419+ * @deprecated
1420+ * @see #parseName
1421+ */
1422+ @Deprecated
1423+ protected Identifier parseIdentifier(boolean star) throws SyntaxError, IOException {
1424+ return parseName(star).id;
1425+ }
1426+
1427+ /**
1428+ * Parse a type expression, this results in a Type.
1429+ * The parse includes trailing array brackets.
1430+ */
1431+ protected Type parseType() throws SyntaxError, IOException {
1432+ Type t;
1433+
1434+ switch (token) {
1435+ case IDENT:
1436+ t = Type.tClass(parseName(false).id);
1437+ break;
1438+ case VOID:
1439+ scan();
1440+ t = Type.tVoid;
1441+ break;
1442+ case BOOLEAN:
1443+ scan();
1444+ t = Type.tBoolean;
1445+ break;
1446+ case BYTE:
1447+ scan();
1448+ t = Type.tByte;
1449+ break;
1450+ case CHAR:
1451+ scan();
1452+ t = Type.tChar;
1453+ break;
1454+ case SHORT:
1455+ scan();
1456+ t = Type.tShort;
1457+ break;
1458+ case INT:
1459+ scan();
1460+ t = Type.tInt;
1461+ break;
1462+ case FLOAT:
1463+ scan();
1464+ t = Type.tFloat;
1465+ break;
1466+ case LONG:
1467+ scan();
1468+ t = Type.tLong;
1469+ break;
1470+ case DOUBLE:
1471+ scan();
1472+ t = Type.tDouble;
1473+ break;
1474+ default:
1475+ env.error(pos, "type.expected");
1476+ throw new SyntaxError();
1477+ }
1478+ return parseArrayBrackets(t);
1479+ }
1480+
1481+ /**
1482+ * Parse the tail of a type expression, which might be array brackets.
1483+ * Return the given type, as possibly modified by the suffix.
1484+ */
1485+ protected Type parseArrayBrackets(Type t) throws SyntaxError, IOException {
1486+
1487+ // Parse []'s
1488+ while (token == LSQBRACKET) {
1489+ scan();
1490+ if (token != RSQBRACKET) {
1491+ env.error(pos, "array.dim.in.decl");
1492+ parseExpression();
1493+ }
1494+ expect(RSQBRACKET);
1495+ t = Type.tArray(t);
1496+ }
1497+ return t;
1498+ }
1499+
1500+ /*
1501+ * Dealing with argument lists, I'm not using
1502+ * Vector for efficiency.
1503+ */
1504+
1505+ private int aCount = 0;
1506+ private Type aTypes[] = new Type[8];
1507+ private IdentifierToken aNames[] = new IdentifierToken[aTypes.length];
1508+
1509+ private void addArgument(int mod, Type t, IdentifierToken nm) {
1510+ nm.modifiers = mod;
1511+ if (aCount >= aTypes.length) {
1512+ Type newATypes[] = new Type[aCount * 2];
1513+ System.arraycopy(aTypes, 0, newATypes, 0, aCount);
1514+ aTypes = newATypes;
1515+ IdentifierToken newANames[] = new IdentifierToken[aCount * 2];
1516+ System.arraycopy(aNames, 0, newANames, 0, aCount);
1517+ aNames = newANames;
1518+ }
1519+ aTypes[aCount] = t;
1520+ aNames[aCount++] = nm;
1521+ }
1522+
1523+ /**
1524+ * Parse a possibly-empty sequence of modifier keywords.
1525+ * Return the resulting bitmask.
1526+ * Diagnose repeated modifiers, but make no other checks.
1527+ * Only modifiers mentioned in the given bitmask are scanned;
1528+ * an unmatched modifier must be handled by the caller.
1529+ */
1530+ protected int parseModifiers(int mask) throws IOException {
1531+ int mod = 0;
1532+ while (true) {
1533+ if (token==CONST) {
1534+ // const isn't in java, but handle a common C++ usage gently
1535+ env.error(pos, "not.supported", "const");
1536+ scan();
1537+ }
1538+ int nextmod = 0;
1539+ switch (token) {
1540+ case PRIVATE: nextmod = M_PRIVATE; break;
1541+ case PUBLIC: nextmod = M_PUBLIC; break;
1542+ case PROTECTED: nextmod = M_PROTECTED; break;
1543+ case STATIC: nextmod = M_STATIC; break;
1544+ case TRANSIENT: nextmod = M_TRANSIENT; break;
1545+ case FINAL: nextmod = M_FINAL; break;
1546+ case ABSTRACT: nextmod = M_ABSTRACT; break;
1547+ case NATIVE: nextmod = M_NATIVE; break;
1548+ case VOLATILE: nextmod = M_VOLATILE; break;
1549+ case SYNCHRONIZED: nextmod = M_SYNCHRONIZED; break;
1550+ case STRICTFP: nextmod = M_STRICTFP; break;
1551+ }
1552+ if ((nextmod & mask) == 0) {
1553+ break;
1554+ }
1555+ if ((nextmod & mod) != 0) {
1556+ env.error(pos, "repeated.modifier");
1557+ }
1558+ mod |= nextmod;
1559+ scan();
1560+ }
1561+ return mod;
1562+ }
1563+
1564+ private ClassDefinition curClass;
1565+
1566+ /**
1567+ * Parse a field.
1568+ */
1569+ protected void parseField() throws SyntaxError, IOException {
1570+
1571+ // Empty fields are not allowed by the JLS but are accepted by
1572+ // the compiler, and much code has come to rely on this. It has
1573+ // been decided that the language will be extended to legitimize them.
1574+ if (token == SEMICOLON) {
1575+ // empty field
1576+ scan();
1577+ return;
1578+ }
1579+
1580+ // Optional doc comment
1581+ String doc = scanner.docComment;
1582+
1583+ // The start of the field
1584+ long p = pos;
1585+
1586+ // Parse the modifiers
1587+ int mod = parseModifiers(MM_FIELD | MM_METHOD);
1588+
1589+ // Check for static initializer
1590+ // ie: static { ... }
1591+ // or an instance initializer (w/o the static).
1592+ if ((mod == (mod & M_STATIC)) && (token == LBRACE)) {
1593+ // static initializer
1594+ actions.defineField(p, curClass, doc, mod,
1595+ Type.tMethod(Type.tVoid),
1596+ new IdentifierToken(idClassInit), null, null,
1597+ parseStatement());
1598+ return;
1599+ }
1600+
1601+ // Check for inner class
1602+ if (token == CLASS || token == INTERFACE) {
1603+ parseNamedClass(mod, CLASS, doc);
1604+ return;
1605+ }
1606+
1607+ // Parse the type
1608+ p = pos;
1609+ Type t = parseType();
1610+ IdentifierToken id = null;
1611+
1612+ // Check that the type is followed by an Identifier
1613+ // (the name of the method or the first variable),
1614+ // otherwise it is a constructor.
1615+ switch (token) {
1616+ case IDENT:
1617+ id = scanner.getIdToken();
1618+ p = scan();
1619+ break;
1620+
1621+ case LPAREN:
1622+ // It is a constructor
1623+ id = new IdentifierToken(idInit);
1624+ if ((mod & M_STRICTFP) != 0)
1625+ env.error(pos, "bad.constructor.modifier");
1626+ break;
1627+
1628+ default:
1629+ expect(IDENT);
1630+ }
1631+
1632+ // If the next token is a left-bracket then we
1633+ // are dealing with a method or constructor, otherwise it is
1634+ // a list of variables
1635+ if (token == LPAREN) {
1636+ // It is a method or constructor declaration
1637+ scan();
1638+ aCount = 0;
1639+
1640+ if (token != RPAREN) {
1641+ // Parse argument type and identifier
1642+ // (arguments (like locals) are allowed to be final)
1643+ int am = parseModifiers(M_FINAL);
1644+ Type at = parseType();
1645+ IdentifierToken an = scanner.getIdToken();
1646+ expect(IDENT);
1647+
1648+ // Parse optional array specifier, ie: a[][]
1649+ at = parseArrayBrackets(at);
1650+ addArgument(am, at, an);
1651+
1652+ // If the next token is a comma then there are
1653+ // more arguments
1654+ while (token == COMMA) {
1655+ // Parse argument type and identifier
1656+ scan();
1657+ am = parseModifiers(M_FINAL);
1658+ at = parseType();
1659+ an = scanner.getIdToken();
1660+ expect(IDENT);
1661+
1662+ // Parse optional array specifier, ie: a[][]
1663+ at = parseArrayBrackets(at);
1664+ addArgument(am, at, an);
1665+ }
1666+ }
1667+ expect(RPAREN);
1668+
1669+ // Parse optional array sepecifier, ie: foo()[][]
1670+ t = parseArrayBrackets(t);
1671+
1672+ // copy arguments
1673+ Type atypes[] = new Type[aCount];
1674+ System.arraycopy(aTypes, 0, atypes, 0, aCount);
1675+
1676+ IdentifierToken anames[] = new IdentifierToken[aCount];
1677+ System.arraycopy(aNames, 0, anames, 0, aCount);
1678+
1679+ // Construct the type signature
1680+ t = Type.tMethod(t, atypes);
1681+
1682+ // Parse and ignore throws clause
1683+ IdentifierToken exp[] = null;
1684+ if (token == THROWS) {
1685+ Vector v = new Vector();
1686+ scan();
1687+ v.addElement(parseName(false));
1688+ while (token == COMMA) {
1689+ scan();
1690+ v.addElement(parseName(false));
1691+ }
1692+
1693+ exp = new IdentifierToken[v.size()];
1694+ v.copyInto(exp);
1695+ }
1696+
1697+ // Check if it is a method definition or a method declaration
1698+ // ie: foo() {...} or foo();
1699+ switch (token) {
1700+ case LBRACE: // It's a method definition
1701+
1702+ // Set the state of FP strictness for the body of the method
1703+ int oldFPstate = FPstate;
1704+ if ((mod & M_STRICTFP)!=0) {
1705+ FPstate = M_STRICTFP;
1706+ } else {
1707+ mod |= FPstate & M_STRICTFP;
1708+ }
1709+
1710+ actions.defineField(p, curClass, doc, mod, t, id,
1711+ anames, exp, parseStatement());
1712+
1713+ FPstate = oldFPstate;
1714+
1715+ break;
1716+
1717+ case SEMICOLON:
1718+ scan();
1719+ actions.defineField(p, curClass, doc, mod, t, id,
1720+ anames, exp, null);
1721+ break;
1722+
1723+ default:
1724+ // really expected a statement body here
1725+ if ((mod & (M_NATIVE | M_ABSTRACT)) == 0) {
1726+ expect(LBRACE);
1727+ } else {
1728+ expect(SEMICOLON);
1729+ }
1730+ }
1731+ return;
1732+ }
1733+
1734+ // It is a list of instance variables
1735+ while (true) {
1736+ p = pos; // get the current position
1737+ // parse the array brackets (if any)
1738+ // ie: var[][][]
1739+ Type vt = parseArrayBrackets(t);
1740+
1741+ // Parse the optional initializer
1742+ Node init = null;
1743+ if (token == ASSIGN) {
1744+ scan();
1745+ init = parseExpression();
1746+ }
1747+
1748+ // Define the variable
1749+ actions.defineField(p, curClass, doc, mod, vt, id,
1750+ null, null, init);
1751+
1752+ // If the next token is a comma, then there is more
1753+ if (token != COMMA) {
1754+ expect(SEMICOLON);
1755+ return;
1756+ }
1757+ scan();
1758+
1759+ // The next token must be an identifier
1760+ id = scanner.getIdToken();
1761+ expect(IDENT);
1762+ }
1763+ }
1764+
1765+ /**
1766+ * Recover after a syntax error in a field. This involves
1767+ * discarding tokens until an EOF or a possible legal
1768+ * continuation is encountered.
1769+ */
1770+ protected void recoverField(ClassDefinition newClass) throws SyntaxError, IOException {
1771+ while (true) {
1772+ switch (token) {
1773+ case EOF:
1774+ case STATIC:
1775+ case FINAL:
1776+ case PUBLIC:
1777+ case PRIVATE:
1778+ case SYNCHRONIZED:
1779+ case TRANSIENT:
1780+
1781+ case VOID:
1782+ case BOOLEAN:
1783+ case BYTE:
1784+ case CHAR:
1785+ case SHORT:
1786+ case INT:
1787+ case FLOAT:
1788+ case LONG:
1789+ case DOUBLE:
1790+ // possible begin of a field, continue
1791+ return;
1792+
1793+ case LBRACE:
1794+ match(LBRACE, RBRACE);
1795+ scan();
1796+ break;
1797+
1798+ case LPAREN:
1799+ match(LPAREN, RPAREN);
1800+ scan();
1801+ break;
1802+
1803+ case LSQBRACKET:
1804+ match(LSQBRACKET, RSQBRACKET);
1805+ scan();
1806+ break;
1807+
1808+ case RBRACE:
1809+ case INTERFACE:
1810+ case CLASS:
1811+ case IMPORT:
1812+ case PACKAGE:
1813+ // begin of something outside a class, panic more
1814+ actions.endClass(pos, newClass);
1815+ throw new SyntaxError();
1816+
1817+ default:
1818+ // don't know what to do, skip
1819+ scan();
1820+ break;
1821+ }
1822+ }
1823+ }
1824+
1825+ /**
1826+ * Parse a top-level class or interface declaration.
1827+ */
1828+ protected void parseClass() throws SyntaxError, IOException {
1829+ String doc = scanner.docComment;
1830+
1831+ // Parse the modifiers.
1832+ int mod = parseModifiers(MM_CLASS | MM_MEMBER);
1833+
1834+ parseNamedClass(mod, PACKAGE, doc);
1835+ }
1836+
1837+ // Current strict/default state of floating point. This is
1838+ // set and reset with a stack discipline around methods and named
1839+ // classes. Only M_STRICTFP may be set in this word. try...
1840+ // finally is not needed to protect setting and resetting because
1841+ // there are no error messages based on FPstate.
1842+ private int FPstate = 0;
1843+
1844+ /**
1845+ * Parse a block-local class or interface declaration.
1846+ */
1847+ protected Statement parseLocalClass(int mod) throws SyntaxError, IOException {
1848+ long p = pos;
1849+ ClassDefinition body = parseNamedClass(M_LOCAL | mod, STAT, null);
1850+ Statement ds[] = {
1851+ new VarDeclarationStatement(p, new LocalMember(body), null)
1852+ };
1853+ Expression type = new TypeExpression(p, body.getType());
1854+ return new DeclarationStatement(p, 0, type, ds);
1855+ }
1856+
1857+ /**
1858+ * Parse a named class or interface declaration,
1859+ * starting at "class" or "interface".
1860+ * @arg ctx Syntactic context of the class, one of {PACKAGE CLASS STAT EXPR}.
1861+ */
1862+ protected ClassDefinition parseNamedClass(int mod, int ctx, String doc) throws SyntaxError, IOException {
1863+ // Parse class/interface
1864+ switch (token) {
1865+ case INTERFACE:
1866+ scan();
1867+ mod |= M_INTERFACE;
1868+ break;
1869+
1870+ case CLASS:
1871+ scan();
1872+ break;
1873+
1874+ default:
1875+ env.error(pos, "class.expected");
1876+ break;
1877+ }
1878+
1879+ int oldFPstate = FPstate;
1880+ if ((mod & M_STRICTFP)!=0) {
1881+ FPstate = M_STRICTFP;
1882+ } else {
1883+ // The & (...) isn't really necessary here because we do maintain
1884+ // the invariant that FPstate has no extra bits set.
1885+ mod |= FPstate & M_STRICTFP;
1886+ }
1887+
1888+ // Parse the class name
1889+ IdentifierToken nm = scanner.getIdToken();
1890+ long p = pos;
1891+ expect(IDENT);
1892+
1893+ Vector ext = new Vector();
1894+ Vector impl = new Vector();
1895+ parseInheritance(ext, impl);
1896+
1897+ ClassDefinition tmp = parseClassBody(nm, mod, ctx, doc, ext, impl, p);
1898+
1899+ FPstate = oldFPstate;
1900+
1901+ return tmp;
1902+ }
1903+
1904+ protected void parseInheritance(Vector ext, Vector impl) throws SyntaxError, IOException {
1905+ // Parse extends clause
1906+ if (token == EXTENDS) {
1907+ scan();
1908+ ext.addElement(parseName(false));
1909+ while (token == COMMA) {
1910+ scan();
1911+ ext.addElement(parseName(false));
1912+ }
1913+ }
1914+
1915+ // Parse implements clause
1916+ if (token == IMPLEMENTS) {
1917+ scan();
1918+ impl.addElement(parseName(false));
1919+ while (token == COMMA) {
1920+ scan();
1921+ impl.addElement(parseName(false));
1922+ }
1923+ }
1924+ }
1925+
1926+ /**
1927+ * Parse the body of a class or interface declaration,
1928+ * starting at the left brace.
1929+ */
1930+ protected ClassDefinition parseClassBody(IdentifierToken nm, int mod,
1931+ int ctx, String doc,
1932+ Vector ext, Vector impl, long p
1933+ ) throws SyntaxError, IOException {
1934+ // Decide which is the super class
1935+ IdentifierToken sup = null;
1936+ if ((mod & M_INTERFACE) != 0) {
1937+ if (impl.size() > 0) {
1938+ env.error(((IdentifierToken)impl.elementAt(0)).getWhere(),
1939+ "intf.impl.intf");
1940+ }
1941+ impl = ext;
1942+ } else {
1943+ if (ext.size() > 0) {
1944+ if (ext.size() > 1) {
1945+ env.error(((IdentifierToken)ext.elementAt(1)).getWhere(),
1946+ "multiple.inherit");
1947+ }
1948+ sup = (IdentifierToken)ext.elementAt(0);
1949+ }
1950+ }
1951+
1952+ ClassDefinition oldClass = curClass;
1953+
1954+ // Begin a new class
1955+ IdentifierToken implids[] = new IdentifierToken[impl.size()];
1956+ impl.copyInto(implids);
1957+ ClassDefinition newClass =
1958+ actions.beginClass(p, doc, mod, nm, sup, implids);
1959+
1960+ // Parse fields
1961+ expect(LBRACE);
1962+ while ((token != EOF) && (token != RBRACE)) {
1963+ try {
1964+ curClass = newClass;
1965+ parseField();
1966+ } catch (SyntaxError e) {
1967+ recoverField(newClass);
1968+ } finally {
1969+ curClass = oldClass;
1970+ }
1971+ }
1972+ expect(RBRACE);
1973+
1974+ // End the class
1975+ actions.endClass(scanner.prevPos, newClass);
1976+ return newClass;
1977+ }
1978+
1979+ /**
1980+ * Recover after a syntax error in the file.
1981+ * This involves discarding tokens until an EOF
1982+ * or a possible legal continuation is encountered.
1983+ */
1984+ protected void recoverFile() throws IOException {
1985+ while (true) {
1986+ switch (token) {
1987+ case CLASS:
1988+ case INTERFACE:
1989+ // Start of a new source file statement, continue
1990+ return;
1991+
1992+ case LBRACE:
1993+ match(LBRACE, RBRACE);
1994+ scan();
1995+ break;
1996+
1997+ case LPAREN:
1998+ match(LPAREN, RPAREN);
1999+ scan();
2000+ break;
2001+
2002+ case LSQBRACKET:
2003+ match(LSQBRACKET, RSQBRACKET);
2004+ scan();
2005+ break;
2006+
2007+ case EOF:
2008+ return;
2009+
2010+ default:
2011+ // Don't know what to do, skip
2012+ scan();
2013+ break;
2014+ }
2015+ }
2016+ }
2017+
2018+ /**
2019+ * Parse an Java file.
2020+ */
2021+ public void parseFile() {
2022+ try {
2023+ try {
2024+ if (token == PACKAGE) {
2025+ // Package statement
2026+ long p = scan();
2027+ IdentifierToken id = parseName(false);
2028+ expect(SEMICOLON);
2029+ actions.packageDeclaration(p, id);
2030+ }
2031+ } catch (SyntaxError e) {
2032+ recoverFile();
2033+ }
2034+ while (token == IMPORT) {
2035+ try{
2036+ // Import statement
2037+ long p = scan();
2038+ IdentifierToken id = parseName(true);
2039+ expect(SEMICOLON);
2040+ if (id.id.getName().equals(idStar)) {
2041+ id.id = id.id.getQualifier();
2042+ actions.importPackage(p, id);
2043+ } else {
2044+ actions.importClass(p, id);
2045+ }
2046+ } catch (SyntaxError e) {
2047+ recoverFile();
2048+ }
2049+ }
2050+
2051+ while (token != EOF) {
2052+ try {
2053+ switch (token) {
2054+ case FINAL:
2055+ case PUBLIC:
2056+ case PRIVATE:
2057+ case ABSTRACT:
2058+ case CLASS:
2059+ case INTERFACE:
2060+ case STRICTFP:
2061+ // Start of a class
2062+ parseClass();
2063+ break;
2064+
2065+ case SEMICOLON:
2066+ // Bogus semicolon.
2067+ // According to the JLS (7.6,19.6), a TypeDeclaration
2068+ // may consist of a single semicolon, however, this
2069+ // usage is discouraged (JLS 7.6). In contrast,
2070+ // a FieldDeclaration may not be empty, and is flagged
2071+ // as an error. See parseField above.
2072+ scan();
2073+ break;
2074+
2075+ case EOF:
2076+ // The end
2077+ return;
2078+
2079+ default:
2080+ // Oops
2081+ env.error(pos, "toplevel.expected");
2082+ throw new SyntaxError();
2083+ }
2084+ } catch (SyntaxError e) {
2085+ recoverFile();
2086+ }
2087+ }
2088+ } catch (IOException e) {
2089+ env.error(pos, "io.exception", env.getSource());
2090+ return;
2091+ }
2092+ }
2093+
2094+ /**
2095+ * Usually <code>this.scanner == (Scanner)this</code>.
2096+ * However, a delegate scanner can produce tokens for this parser,
2097+ * in which case <code>(Scanner)this</code> is unused,
2098+ * except for <code>this.token</code> and <code>this.pos</code>
2099+ * instance variables which are filled from the real scanner
2100+ * by <code>this.scan()</code> and the constructor.
2101+ */
2102+ protected Scanner scanner;
2103+
2104+ // Design Note: We ought to disinherit Parser from Scanner.
2105+ // We also should split out the interface ParserActions from
2106+ // Parser, and make BatchParser implement ParserActions,
2107+ // not extend Parser. This would split scanning, parsing,
2108+ // and class building into distinct responsibility areas.
2109+ // (Perhaps tree building could be virtualized too.)
2110+
2111+ public long scan() throws IOException {
2112+ if (scanner != this && scanner != null) {
2113+ long result = scanner.scan();
2114+ ((Scanner)this).token = scanner.token;
2115+ ((Scanner)this).pos = scanner.pos;
2116+ return result;
2117+ }
2118+ return super.scan();
2119+ }
2120+
2121+ public void match(int open, int close) throws IOException {
2122+ if (scanner != this) {
2123+ scanner.match(open, close);
2124+ ((Scanner)this).token = scanner.token;
2125+ ((Scanner)this).pos = scanner.pos;
2126+ return;
2127+ }
2128+ super.match(open, close);
2129+ }
2130+}
java/pkg/sun/tools/java/ParserActions.java+87−0
@@ -0,0 +1,87 @@
1+/*
2+ * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import sun.tools.tree.*;
29+
30+/**
31+ * This is the protocol by which a Parser makes callbacks
32+ * to the later phases of the compiler.
33+ * <p>
34+ * (As a backwards compatibility trick, Parser implements
35+ * this protocol, so that an instance of a Parser subclass
36+ * can handle its own actions. The preferred way to use a
37+ * Parser, however, is to instantiate it directly with a
38+ * reference to your own ParserActions implementation.)
39+ *
40+ * WARNING: The contents of this source file are not part of any
41+ * supported API. Code that depends on them does so at its own risk:
42+ * they are subject to change or removal without notice.
43+ *
44+ * @author John R. Rose
45+ */
46+public interface ParserActions {
47+ /**
48+ * package declaration
49+ */
50+ void packageDeclaration(long off, IdentifierToken nm);
51+
52+ /**
53+ * import class
54+ */
55+ void importClass(long off, IdentifierToken nm);
56+
57+ /**
58+ * import package
59+ */
60+ void importPackage(long off, IdentifierToken nm);
61+
62+ /**
63+ * Define class
64+ * @return a cookie for the class
65+ * This cookie is used by the parser when calling defineField
66+ * and endClass, and is not examined otherwise.
67+ */
68+ ClassDefinition beginClass(long off, String doc,
69+ int mod, IdentifierToken nm,
70+ IdentifierToken sup, IdentifierToken impl[]);
71+
72+
73+ /**
74+ * End class
75+ * @param c a cookie returned by the corresponding beginClass call
76+ */
77+ void endClass(long off, ClassDefinition c);
78+
79+ /**
80+ * Define a field
81+ * @param c a cookie returned by the corresponding beginClass call
82+ */
83+ void defineField(long where, ClassDefinition c,
84+ String doc, int mod, Type t,
85+ IdentifierToken nm, IdentifierToken args[],
86+ IdentifierToken exp[], Node val);
87+}
java/pkg/sun/tools/java/RuntimeConstants.java+739−0
@@ -0,0 +1,739 @@
1+/*
2+ * Copyright (c) 1998, 2005, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+/**
29+ * WARNING: The contents of this source file are not part of any
30+ * supported API. Code that depends on them does so at its own risk:
31+ * they are subject to change or removal without notice.
32+ */
33+public interface RuntimeConstants {
34+
35+ /* Signature Characters */
36+ char SIGC_VOID = 'V';
37+ String SIG_VOID = "V";
38+ char SIGC_BOOLEAN = 'Z';
39+ String SIG_BOOLEAN = "Z";
40+ char SIGC_BYTE = 'B';
41+ String SIG_BYTE = "B";
42+ char SIGC_CHAR = 'C';
43+ String SIG_CHAR = "C";
44+ char SIGC_SHORT = 'S';
45+ String SIG_SHORT = "S";
46+ char SIGC_INT = 'I';
47+ String SIG_INT = "I";
48+ char SIGC_LONG = 'J';
49+ String SIG_LONG = "J";
50+ char SIGC_FLOAT = 'F';
51+ String SIG_FLOAT = "F";
52+ char SIGC_DOUBLE = 'D';
53+ String SIG_DOUBLE = "D";
54+ char SIGC_ARRAY = '[';
55+ String SIG_ARRAY = "[";
56+ char SIGC_CLASS = 'L';
57+ String SIG_CLASS = "L";
58+ char SIGC_METHOD = '(';
59+ String SIG_METHOD = "(";
60+ char SIGC_ENDCLASS = ';';
61+ String SIG_ENDCLASS = ";";
62+ char SIGC_ENDMETHOD = ')';
63+ String SIG_ENDMETHOD = ")";
64+ char SIGC_PACKAGE = '/';
65+ String SIG_PACKAGE = "/";
66+
67+ /* Class File Constants */
68+ int JAVA_MAGIC = 0xcafebabe;
69+ int JAVA_MIN_SUPPORTED_VERSION = 45;
70+ int JAVA_MAX_SUPPORTED_VERSION = 51;
71+ int JAVA_MAX_SUPPORTED_MINOR_VERSION = 0;
72+
73+ /* Generate class file version for 1.1 by default */
74+ int JAVA_DEFAULT_VERSION = 45;
75+ int JAVA_DEFAULT_MINOR_VERSION = 3;
76+
77+ /* Constant table */
78+ int CONSTANT_UTF8 = 1;
79+ int CONSTANT_UNICODE = 2;
80+ int CONSTANT_INTEGER = 3;
81+ int CONSTANT_FLOAT = 4;
82+ int CONSTANT_LONG = 5;
83+ int CONSTANT_DOUBLE = 6;
84+ int CONSTANT_CLASS = 7;
85+ int CONSTANT_STRING = 8;
86+ int CONSTANT_FIELD = 9;
87+ int CONSTANT_METHOD = 10;
88+ int CONSTANT_INTERFACEMETHOD = 11;
89+ int CONSTANT_NAMEANDTYPE = 12;
90+
91+ /* Access and modifier flags */
92+ int ACC_PUBLIC = 0x00000001;
93+ int ACC_PRIVATE = 0x00000002;
94+ int ACC_PROTECTED = 0x00000004;
95+ int ACC_STATIC = 0x00000008;
96+ int ACC_FINAL = 0x00000010;
97+ int ACC_SYNCHRONIZED = 0x00000020;
98+ int ACC_VOLATILE = 0x00000040;
99+ int ACC_TRANSIENT = 0x00000080;
100+ int ACC_NATIVE = 0x00000100;
101+ int ACC_INTERFACE = 0x00000200;
102+ int ACC_ABSTRACT = 0x00000400;
103+ int ACC_SUPER = 0x00000020;
104+ int ACC_STRICT = 0x00000800;
105+
106+ /* Type codes */
107+ int T_CLASS = 0x00000002;
108+ int T_BOOLEAN = 0x00000004;
109+ int T_CHAR = 0x00000005;
110+ int T_FLOAT = 0x00000006;
111+ int T_DOUBLE = 0x00000007;
112+ int T_BYTE = 0x00000008;
113+ int T_SHORT = 0x00000009;
114+ int T_INT = 0x0000000a;
115+ int T_LONG = 0x0000000b;
116+
117+ /* Opcodes */
118+ int opc_try = -3;
119+ int opc_dead = -2;
120+ int opc_label = -1;
121+ int opc_nop = 0;
122+ int opc_aconst_null = 1;
123+ int opc_iconst_m1 = 2;
124+ int opc_iconst_0 = 3;
125+ int opc_iconst_1 = 4;
126+ int opc_iconst_2 = 5;
127+ int opc_iconst_3 = 6;
128+ int opc_iconst_4 = 7;
129+ int opc_iconst_5 = 8;
130+ int opc_lconst_0 = 9;
131+ int opc_lconst_1 = 10;
132+ int opc_fconst_0 = 11;
133+ int opc_fconst_1 = 12;
134+ int opc_fconst_2 = 13;
135+ int opc_dconst_0 = 14;
136+ int opc_dconst_1 = 15;
137+ int opc_bipush = 16;
138+ int opc_sipush = 17;
139+ int opc_ldc = 18;
140+ int opc_ldc_w = 19;
141+ int opc_ldc2_w = 20;
142+ int opc_iload = 21;
143+ int opc_lload = 22;
144+ int opc_fload = 23;
145+ int opc_dload = 24;
146+ int opc_aload = 25;
147+ int opc_iload_0 = 26;
148+ int opc_iload_1 = 27;
149+ int opc_iload_2 = 28;
150+ int opc_iload_3 = 29;
151+ int opc_lload_0 = 30;
152+ int opc_lload_1 = 31;
153+ int opc_lload_2 = 32;
154+ int opc_lload_3 = 33;
155+ int opc_fload_0 = 34;
156+ int opc_fload_1 = 35;
157+ int opc_fload_2 = 36;
158+ int opc_fload_3 = 37;
159+ int opc_dload_0 = 38;
160+ int opc_dload_1 = 39;
161+ int opc_dload_2 = 40;
162+ int opc_dload_3 = 41;
163+ int opc_aload_0 = 42;
164+ int opc_aload_1 = 43;
165+ int opc_aload_2 = 44;
166+ int opc_aload_3 = 45;
167+ int opc_iaload = 46;
168+ int opc_laload = 47;
169+ int opc_faload = 48;
170+ int opc_daload = 49;
171+ int opc_aaload = 50;
172+ int opc_baload = 51;
173+ int opc_caload = 52;
174+ int opc_saload = 53;
175+ int opc_istore = 54;
176+ int opc_lstore = 55;
177+ int opc_fstore = 56;
178+ int opc_dstore = 57;
179+ int opc_astore = 58;
180+ int opc_istore_0 = 59;
181+ int opc_istore_1 = 60;
182+ int opc_istore_2 = 61;
183+ int opc_istore_3 = 62;
184+ int opc_lstore_0 = 63;
185+ int opc_lstore_1 = 64;
186+ int opc_lstore_2 = 65;
187+ int opc_lstore_3 = 66;
188+ int opc_fstore_0 = 67;
189+ int opc_fstore_1 = 68;
190+ int opc_fstore_2 = 69;
191+ int opc_fstore_3 = 70;
192+ int opc_dstore_0 = 71;
193+ int opc_dstore_1 = 72;
194+ int opc_dstore_2 = 73;
195+ int opc_dstore_3 = 74;
196+ int opc_astore_0 = 75;
197+ int opc_astore_1 = 76;
198+ int opc_astore_2 = 77;
199+ int opc_astore_3 = 78;
200+ int opc_iastore = 79;
201+ int opc_lastore = 80;
202+ int opc_fastore = 81;
203+ int opc_dastore = 82;
204+ int opc_aastore = 83;
205+ int opc_bastore = 84;
206+ int opc_castore = 85;
207+ int opc_sastore = 86;
208+ int opc_pop = 87;
209+ int opc_pop2 = 88;
210+ int opc_dup = 89;
211+ int opc_dup_x1 = 90;
212+ int opc_dup_x2 = 91;
213+ int opc_dup2 = 92;
214+ int opc_dup2_x1 = 93;
215+ int opc_dup2_x2 = 94;
216+ int opc_swap = 95;
217+ int opc_iadd = 96;
218+ int opc_ladd = 97;
219+ int opc_fadd = 98;
220+ int opc_dadd = 99;
221+ int opc_isub = 100;
222+ int opc_lsub = 101;
223+ int opc_fsub = 102;
224+ int opc_dsub = 103;
225+ int opc_imul = 104;
226+ int opc_lmul = 105;
227+ int opc_fmul = 106;
228+ int opc_dmul = 107;
229+ int opc_idiv = 108;
230+ int opc_ldiv = 109;
231+ int opc_fdiv = 110;
232+ int opc_ddiv = 111;
233+ int opc_irem = 112;
234+ int opc_lrem = 113;
235+ int opc_frem = 114;
236+ int opc_drem = 115;
237+ int opc_ineg = 116;
238+ int opc_lneg = 117;
239+ int opc_fneg = 118;
240+ int opc_dneg = 119;
241+ int opc_ishl = 120;
242+ int opc_lshl = 121;
243+ int opc_ishr = 122;
244+ int opc_lshr = 123;
245+ int opc_iushr = 124;
246+ int opc_lushr = 125;
247+ int opc_iand = 126;
248+ int opc_land = 127;
249+ int opc_ior = 128;
250+ int opc_lor = 129;
251+ int opc_ixor = 130;
252+ int opc_lxor = 131;
253+ int opc_iinc = 132;
254+ int opc_i2l = 133;
255+ int opc_i2f = 134;
256+ int opc_i2d = 135;
257+ int opc_l2i = 136;
258+ int opc_l2f = 137;
259+ int opc_l2d = 138;
260+ int opc_f2i = 139;
261+ int opc_f2l = 140;
262+ int opc_f2d = 141;
263+ int opc_d2i = 142;
264+ int opc_d2l = 143;
265+ int opc_d2f = 144;
266+ int opc_i2b = 145;
267+ int opc_i2c = 146;
268+ int opc_i2s = 147;
269+ int opc_lcmp = 148;
270+ int opc_fcmpl = 149;
271+ int opc_fcmpg = 150;
272+ int opc_dcmpl = 151;
273+ int opc_dcmpg = 152;
274+ int opc_ifeq = 153;
275+ int opc_ifne = 154;
276+ int opc_iflt = 155;
277+ int opc_ifge = 156;
278+ int opc_ifgt = 157;
279+ int opc_ifle = 158;
280+ int opc_if_icmpeq = 159;
281+ int opc_if_icmpne = 160;
282+ int opc_if_icmplt = 161;
283+ int opc_if_icmpge = 162;
284+ int opc_if_icmpgt = 163;
285+ int opc_if_icmple = 164;
286+ int opc_if_acmpeq = 165;
287+ int opc_if_acmpne = 166;
288+ int opc_goto = 167;
289+ int opc_jsr = 168;
290+ int opc_ret = 169;
291+ int opc_tableswitch = 170;
292+ int opc_lookupswitch = 171;
293+ int opc_ireturn = 172;
294+ int opc_lreturn = 173;
295+ int opc_freturn = 174;
296+ int opc_dreturn = 175;
297+ int opc_areturn = 176;
298+ int opc_return = 177;
299+ int opc_getstatic = 178;
300+ int opc_putstatic = 179;
301+ int opc_getfield = 180;
302+ int opc_putfield = 181;
303+ int opc_invokevirtual = 182;
304+ int opc_invokespecial = 183;
305+ int opc_invokestatic = 184;
306+ int opc_invokeinterface = 185;
307+ int opc_invokedynamic = 186;
308+ int opc_new = 187;
309+ int opc_newarray = 188;
310+ int opc_anewarray = 189;
311+ int opc_arraylength = 190;
312+ int opc_athrow = 191;
313+ int opc_checkcast = 192;
314+ int opc_instanceof = 193;
315+ int opc_monitorenter = 194;
316+ int opc_monitorexit = 195;
317+ int opc_wide = 196;
318+ int opc_multianewarray = 197;
319+ int opc_ifnull = 198;
320+ int opc_ifnonnull = 199;
321+ int opc_goto_w = 200;
322+ int opc_jsr_w = 201;
323+ int opc_breakpoint = 202;
324+
325+ /* Opcode Names */
326+ String opcNames[] = {
327+ "nop",
328+ "aconst_null",
329+ "iconst_m1",
330+ "iconst_0",
331+ "iconst_1",
332+ "iconst_2",
333+ "iconst_3",
334+ "iconst_4",
335+ "iconst_5",
336+ "lconst_0",
337+ "lconst_1",
338+ "fconst_0",
339+ "fconst_1",
340+ "fconst_2",
341+ "dconst_0",
342+ "dconst_1",
343+ "bipush",
344+ "sipush",
345+ "ldc",
346+ "ldc_w",
347+ "ldc2_w",
348+ "iload",
349+ "lload",
350+ "fload",
351+ "dload",
352+ "aload",
353+ "iload_0",
354+ "iload_1",
355+ "iload_2",
356+ "iload_3",
357+ "lload_0",
358+ "lload_1",
359+ "lload_2",
360+ "lload_3",
361+ "fload_0",
362+ "fload_1",
363+ "fload_2",
364+ "fload_3",
365+ "dload_0",
366+ "dload_1",
367+ "dload_2",
368+ "dload_3",
369+ "aload_0",
370+ "aload_1",
371+ "aload_2",
372+ "aload_3",
373+ "iaload",
374+ "laload",
375+ "faload",
376+ "daload",
377+ "aaload",
378+ "baload",
379+ "caload",
380+ "saload",
381+ "istore",
382+ "lstore",
383+ "fstore",
384+ "dstore",
385+ "astore",
386+ "istore_0",
387+ "istore_1",
388+ "istore_2",
389+ "istore_3",
390+ "lstore_0",
391+ "lstore_1",
392+ "lstore_2",
393+ "lstore_3",
394+ "fstore_0",
395+ "fstore_1",
396+ "fstore_2",
397+ "fstore_3",
398+ "dstore_0",
399+ "dstore_1",
400+ "dstore_2",
401+ "dstore_3",
402+ "astore_0",
403+ "astore_1",
404+ "astore_2",
405+ "astore_3",
406+ "iastore",
407+ "lastore",
408+ "fastore",
409+ "dastore",
410+ "aastore",
411+ "bastore",
412+ "castore",
413+ "sastore",
414+ "pop",
415+ "pop2",
416+ "dup",
417+ "dup_x1",
418+ "dup_x2",
419+ "dup2",
420+ "dup2_x1",
421+ "dup2_x2",
422+ "swap",
423+ "iadd",
424+ "ladd",
425+ "fadd",
426+ "dadd",
427+ "isub",
428+ "lsub",
429+ "fsub",
430+ "dsub",
431+ "imul",
432+ "lmul",
433+ "fmul",
434+ "dmul",
435+ "idiv",
436+ "ldiv",
437+ "fdiv",
438+ "ddiv",
439+ "irem",
440+ "lrem",
441+ "frem",
442+ "drem",
443+ "ineg",
444+ "lneg",
445+ "fneg",
446+ "dneg",
447+ "ishl",
448+ "lshl",
449+ "ishr",
450+ "lshr",
451+ "iushr",
452+ "lushr",
453+ "iand",
454+ "land",
455+ "ior",
456+ "lor",
457+ "ixor",
458+ "lxor",
459+ "iinc",
460+ "i2l",
461+ "i2f",
462+ "i2d",
463+ "l2i",
464+ "l2f",
465+ "l2d",
466+ "f2i",
467+ "f2l",
468+ "f2d",
469+ "d2i",
470+ "d2l",
471+ "d2f",
472+ "i2b",
473+ "i2c",
474+ "i2s",
475+ "lcmp",
476+ "fcmpl",
477+ "fcmpg",
478+ "dcmpl",
479+ "dcmpg",
480+ "ifeq",
481+ "ifne",
482+ "iflt",
483+ "ifge",
484+ "ifgt",
485+ "ifle",
486+ "if_icmpeq",
487+ "if_icmpne",
488+ "if_icmplt",
489+ "if_icmpge",
490+ "if_icmpgt",
491+ "if_icmple",
492+ "if_acmpeq",
493+ "if_acmpne",
494+ "goto",
495+ "jsr",
496+ "ret",
497+ "tableswitch",
498+ "lookupswitch",
499+ "ireturn",
500+ "lreturn",
501+ "freturn",
502+ "dreturn",
503+ "areturn",
504+ "return",
505+ "getstatic",
506+ "putstatic",
507+ "getfield",
508+ "putfield",
509+ "invokevirtual",
510+ "invokespecial",
511+ "invokestatic",
512+ "invokeinterface",
513+ "invokedynamic",
514+ "new",
515+ "newarray",
516+ "anewarray",
517+ "arraylength",
518+ "athrow",
519+ "checkcast",
520+ "instanceof",
521+ "monitorenter",
522+ "monitorexit",
523+ "wide",
524+ "multianewarray",
525+ "ifnull",
526+ "ifnonnull",
527+ "goto_w",
528+ "jsr_w",
529+ "breakpoint"
530+ };
531+
532+ /* Opcode Lengths */
533+ int opcLengths[] = {
534+ 1,
535+ 1,
536+ 1,
537+ 1,
538+ 1,
539+ 1,
540+ 1,
541+ 1,
542+ 1,
543+ 1,
544+ 1,
545+ 1,
546+ 1,
547+ 1,
548+ 1,
549+ 1,
550+ 2,
551+ 3,
552+ 2,
553+ 3,
554+ 3,
555+ 2,
556+ 2,
557+ 2,
558+ 2,
559+ 2,
560+ 1,
561+ 1,
562+ 1,
563+ 1,
564+ 1,
565+ 1,
566+ 1,
567+ 1,
568+ 1,
569+ 1,
570+ 1,
571+ 1,
572+ 1,
573+ 1,
574+ 1,
575+ 1,
576+ 1,
577+ 1,
578+ 1,
579+ 1,
580+ 1,
581+ 1,
582+ 1,
583+ 1,
584+ 1,
585+ 1,
586+ 1,
587+ 1,
588+ 2,
589+ 2,
590+ 2,
591+ 2,
592+ 2,
593+ 1,
594+ 1,
595+ 1,
596+ 1,
597+ 1,
598+ 1,
599+ 1,
600+ 1,
601+ 1,
602+ 1,
603+ 1,
604+ 1,
605+ 1,
606+ 1,
607+ 1,
608+ 1,
609+ 1,
610+ 1,
611+ 1,
612+ 1,
613+ 1,
614+ 1,
615+ 1,
616+ 1,
617+ 1,
618+ 1,
619+ 1,
620+ 1,
621+ 1,
622+ 1,
623+ 1,
624+ 1,
625+ 1,
626+ 1,
627+ 1,
628+ 1,
629+ 1,
630+ 1,
631+ 1,
632+ 1,
633+ 1,
634+ 1,
635+ 1,
636+ 1,
637+ 1,
638+ 1,
639+ 1,
640+ 1,
641+ 1,
642+ 1,
643+ 1,
644+ 1,
645+ 1,
646+ 1,
647+ 1,
648+ 1,
649+ 1,
650+ 1,
651+ 1,
652+ 1,
653+ 1,
654+ 1,
655+ 1,
656+ 1,
657+ 1,
658+ 1,
659+ 1,
660+ 1,
661+ 1,
662+ 1,
663+ 1,
664+ 1,
665+ 1,
666+ 3,
667+ 1,
668+ 1,
669+ 1,
670+ 1,
671+ 1,
672+ 1,
673+ 1,
674+ 1,
675+ 1,
676+ 1,
677+ 1,
678+ 1,
679+ 1,
680+ 1,
681+ 1,
682+ 1,
683+ 1,
684+ 1,
685+ 1,
686+ 1,
687+ 3,
688+ 3,
689+ 3,
690+ 3,
691+ 3,
692+ 3,
693+ 3,
694+ 3,
695+ 3,
696+ 3,
697+ 3,
698+ 3,
699+ 3,
700+ 3,
701+ 3,
702+ 3,
703+ 2,
704+ 99,
705+ 99,
706+ 1,
707+ 1,
708+ 1,
709+ 1,
710+ 1,
711+ 1,
712+ 3,
713+ 3,
714+ 3,
715+ 3,
716+ 3,
717+ 3,
718+ 3,
719+ 5,
720+ 5,
721+ 3,
722+ 2,
723+ 3,
724+ 1,
725+ 1,
726+ 3,
727+ 3,
728+ 1,
729+ 1,
730+ 0,
731+ 4,
732+ 3,
733+ 3,
734+ 5,
735+ 5,
736+ 1
737+ };
738+
739+}
java/pkg/sun/tools/java/Scanner.java+1341−0
@@ -0,0 +1,1341 @@
1+/*
2+ * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.io.IOException;
29+import java.io.InputStream;
30+import java.util.Hashtable;
31+
32+/**
33+ * A Scanner for Java tokens. Errors are reported
34+ * to the environment object.<p>
35+ *
36+ * The scanner keeps track of the current token,
37+ * the value of the current token (if any), and the start
38+ * position of the current token.<p>
39+ *
40+ * The scan() method advances the scanner to the next
41+ * token in the input.<p>
42+ *
43+ * The match() method is used to quickly match opening
44+ * brackets (ie: '(', '{', or '[') with their closing
45+ * counter part. This is useful during error recovery.<p>
46+ *
47+ * An position consists of: ((linenr << WHEREOFFSETBITS) | offset)
48+ * this means that both the line number and the exact offset into
49+ * the file are encoded in each position value.<p>
50+ *
51+ * The compiler treats either "\n", "\r" or "\r\n" as the
52+ * end of a line.<p>
53+ *
54+ * WARNING: The contents of this source file are not part of any
55+ * supported API. Code that depends on them does so at its own risk:
56+ * they are subject to change or removal without notice.
57+ *
58+ * @author Arthur van Hoff
59+ */
60+
61+public
62+class Scanner implements Constants {
63+ /**
64+ * The increment for each character.
65+ */
66+ public static final long OFFSETINC = 1;
67+
68+ /**
69+ * The increment for each line.
70+ */
71+ public static final long LINEINC = 1L << WHEREOFFSETBITS;
72+
73+ /**
74+ * End of input
75+ */
76+ public static final int EOF = -1;
77+
78+ /**
79+ * Where errors are reported
80+ */
81+ public Environment env;
82+
83+ /**
84+ * Input reader
85+ */
86+ protected ScannerInputReader in;
87+
88+ /**
89+ * If true, present all comments as tokens.
90+ * Contents are not saved, but positions are recorded accurately,
91+ * so the comment can be recovered from the text.
92+ * Line terminations are also returned as comment tokens,
93+ * and may be distinguished by their start and end positions,
94+ * which are equal (meaning, these tokens contain no chars).
95+ */
96+ public boolean scanComments = false;
97+
98+ /**
99+ * Current token
100+ */
101+ public int token;
102+
103+ /**
104+ * The position of the current token
105+ */
106+ public long pos;
107+
108+ /**
109+ * The position of the previous token
110+ */
111+ public long prevPos;
112+
113+ /**
114+ * The current character
115+ */
116+ protected int ch;
117+
118+ /*
119+ * Token values.
120+ */
121+ public char charValue;
122+ public int intValue;
123+ public long longValue;
124+ public float floatValue;
125+ public double doubleValue;
126+ public String stringValue;
127+ public Identifier idValue;
128+ public int radix; // Radix, when reading int or long
129+
130+ /*
131+ * A doc comment preceding the most recent token
132+ */
133+ public String docComment;
134+
135+ /*
136+ * A growable character buffer.
137+ */
138+ private int count;
139+ private char buffer[] = new char[1024];
140+ private void growBuffer() {
141+ char newBuffer[] = new char[buffer.length * 2];
142+ System.arraycopy(buffer, 0, newBuffer, 0, buffer.length);
143+ buffer = newBuffer;
144+ }
145+
146+ // The following two methods have been hand-inlined in
147+ // scanDocComment. If you make changes here, you should
148+ // check to see if scanDocComment also needs modification.
149+ private void putc(int ch) {
150+ if (count == buffer.length) {
151+ growBuffer();
152+ }
153+ buffer[count++] = (char)ch;
154+ }
155+
156+ private String bufferString() {
157+ return new String(buffer, 0, count);
158+ }
159+
160+ /**
161+ * Create a scanner to scan an input stream.
162+ */
163+ public Scanner(Environment env, InputStream in) throws IOException {
164+ this.env = env;
165+ useInputStream(in);
166+ }
167+
168+ /**
169+ * Setup input from the given input stream,
170+ * and scan the first token from it.
171+ */
172+ protected void useInputStream(InputStream in) throws IOException {
173+ try {
174+ this.in = new ScannerInputReader(env, in);
175+ } catch (Exception e) {
176+ env.setCharacterEncoding(null);
177+ this.in = new ScannerInputReader(env, in);
178+ }
179+
180+ ch = this.in.read();
181+ prevPos = this.in.pos;
182+
183+ scan();
184+ }
185+
186+ /**
187+ * Create a scanner to scan an input stream.
188+ */
189+ protected Scanner(Environment env) {
190+ this.env = env;
191+ // Expect the subclass to call useInputStream at the right time.
192+ }
193+
194+ /**
195+ * Define a keyword.
196+ */
197+ private static void defineKeyword(int val) {
198+ Identifier.lookup(opNames[val]).setType(val);
199+ }
200+
201+ /**
202+ * Initialized keyword and token Hashtables
203+ */
204+ static {
205+ // Statement keywords
206+ defineKeyword(FOR);
207+ defineKeyword(IF);
208+ defineKeyword(ELSE);
209+ defineKeyword(WHILE);
210+ defineKeyword(DO);
211+ defineKeyword(SWITCH);
212+ defineKeyword(CASE);
213+ defineKeyword(DEFAULT);
214+ defineKeyword(BREAK);
215+ defineKeyword(CONTINUE);
216+ defineKeyword(RETURN);
217+ defineKeyword(TRY);
218+ defineKeyword(CATCH);
219+ defineKeyword(FINALLY);
220+ defineKeyword(THROW);
221+
222+ // Type defineKeywords
223+ defineKeyword(BYTE);
224+ defineKeyword(CHAR);
225+ defineKeyword(SHORT);
226+ defineKeyword(INT);
227+ defineKeyword(LONG);
228+ defineKeyword(FLOAT);
229+ defineKeyword(DOUBLE);
230+ defineKeyword(VOID);
231+ defineKeyword(BOOLEAN);
232+
233+ // Expression keywords
234+ defineKeyword(INSTANCEOF);
235+ defineKeyword(TRUE);
236+ defineKeyword(FALSE);
237+ defineKeyword(NEW);
238+ defineKeyword(THIS);
239+ defineKeyword(SUPER);
240+ defineKeyword(NULL);
241+
242+ // Declaration keywords
243+ defineKeyword(IMPORT);
244+ defineKeyword(CLASS);
245+ defineKeyword(EXTENDS);
246+ defineKeyword(IMPLEMENTS);
247+ defineKeyword(INTERFACE);
248+ defineKeyword(PACKAGE);
249+ defineKeyword(THROWS);
250+
251+ // Modifier keywords
252+ defineKeyword(PRIVATE);
253+ defineKeyword(PUBLIC);
254+ defineKeyword(PROTECTED);
255+ defineKeyword(STATIC);
256+ defineKeyword(TRANSIENT);
257+ defineKeyword(SYNCHRONIZED);
258+ defineKeyword(NATIVE);
259+ defineKeyword(ABSTRACT);
260+ defineKeyword(VOLATILE);
261+ defineKeyword(FINAL);
262+ defineKeyword(STRICTFP);
263+
264+ // reserved keywords
265+ defineKeyword(CONST);
266+ defineKeyword(GOTO);
267+ }
268+
269+ /**
270+ * Scan a comment. This method should be
271+ * called once the initial /, * and the next
272+ * character have been read.
273+ */
274+ private void skipComment() throws IOException {
275+ while (true) {
276+ switch (ch) {
277+ case EOF:
278+ env.error(pos, "eof.in.comment");
279+ return;
280+
281+ case '*':
282+ if ((ch = in.read()) == '/') {
283+ ch = in.read();
284+ return;
285+ }
286+ break;
287+
288+ default:
289+ ch = in.read();
290+ break;
291+ }
292+ }
293+ }
294+
295+ /**
296+ * Scan a doc comment. This method should be called
297+ * once the initial /, * and * have been read. It gathers
298+ * the content of the comment (witout leading spaces and '*'s)
299+ * in the string buffer.
300+ */
301+ private String scanDocComment() throws IOException {
302+ // Note: this method has been hand-optimized to yield
303+ // better performance. This was done after it was noted
304+ // that javadoc spent a great deal of its time here.
305+ // This should also help the performance of the compiler
306+ // as well -- it scans the doc comments to find
307+ // @deprecated tags.
308+ //
309+ // The logic of the method has been completely rewritten
310+ // to avoid the use of flags that need to be looked at
311+ // for every character read. Members that are accessed
312+ // more than once have been stored in local variables.
313+ // The methods putc() and bufferString() have been
314+ // inlined by hand. Extra cases have been added to
315+ // switch statements to trick the compiler into generating
316+ // a tableswitch instead of a lookupswitch.
317+ //
318+ // This implementation aims to preserve the previous
319+ // behavior of this method.
320+
321+ int c;
322+
323+ // Put `in' in a local variable.
324+ final ScannerInputReader in = this.in;
325+
326+ // We maintain the buffer locally rather than calling putc().
327+ char[] buffer = this.buffer;
328+ int count = 0;
329+
330+ // We are called pointing at the second star of the doc
331+ // comment:
332+ //
333+ // Input: /** the rest of the comment ... */
334+ // ^
335+ //
336+ // We rely on this in the code below.
337+
338+ // Consume any number of stars.
339+ while ((c = in.read()) == '*')
340+ ;
341+
342+ // Is the comment of the form /**/, /***/, /****/, etc.?
343+ if (c == '/') {
344+ // Set ch and return
345+ ch = in.read();
346+ return "";
347+ }
348+
349+ // Skip a newline on the first line of the comment.
350+ if (c == '\n') {
351+ c = in.read();
352+ }
353+
354+ outerLoop:
355+ // The outerLoop processes the doc comment, looping once
356+ // for each line. For each line, it first strips off
357+ // whitespace, then it consumes any stars, then it
358+ // puts the rest of the line into our buffer.
359+ while (true) {
360+
361+ // The wsLoop consumes whitespace from the beginning
362+ // of each line.
363+ wsLoop:
364+ while (true) {
365+ switch (c) {
366+ case ' ':
367+ case '\t':
368+ // We could check for other forms of whitespace
369+ // as well, but this is left as is for minimum
370+ // disturbance of functionality.
371+ //
372+ // Just skip whitespace.
373+ c = in.read();
374+ break;
375+
376+ // We have added extra cases here to trick the
377+ // compiler into using a tableswitch instead of
378+ // a lookupswitch. They can be removed without
379+ // a change in meaning.
380+ case 10: case 11: case 12: case 13: case 14: case 15:
381+ case 16: case 17: case 18: case 19: case 20: case 21:
382+ case 22: case 23: case 24: case 25: case 26: case 27:
383+ case 28: case 29: case 30: case 31:
384+ default:
385+ // We've seen something that isn't whitespace,
386+ // jump out.
387+ break wsLoop;
388+ }
389+ } // end wsLoop.
390+
391+ // Are there stars here? If so, consume them all
392+ // and check for the end of comment.
393+ if (c == '*') {
394+ // Skip all of the stars...
395+ do {
396+ c = in.read();
397+ } while (c == '*');
398+
399+ // ...then check for the closing slash.
400+ if (c == '/') {
401+ // We're done with the doc comment.
402+ // Set ch and break out.
403+ ch = in.read();
404+ break outerLoop;
405+ }
406+ }
407+
408+ // The textLoop processes the rest of the characters
409+ // on the line, adding them to our buffer.
410+ textLoop:
411+ while (true) {
412+ switch (c) {
413+ case EOF:
414+ // We've seen a premature EOF. Break out
415+ // of the loop.
416+ env.error(pos, "eof.in.comment");
417+ ch = EOF;
418+ break outerLoop;
419+
420+ case '*':
421+ // Is this just a star? Or is this the
422+ // end of a comment?
423+ c = in.read();
424+ if (c == '/') {
425+ // This is the end of the comment,
426+ // set ch and return our buffer.
427+ ch = in.read();
428+ break outerLoop;
429+ }
430+ // This is just an ordinary star. Add it to
431+ // the buffer.
432+ if (count == buffer.length) {
433+ growBuffer();
434+ buffer = this.buffer;
435+ }
436+ buffer[count++] = '*';
437+ break;
438+
439+ case '\n':
440+ // We've seen a newline. Add it to our
441+ // buffer and break out of this loop,
442+ // starting fresh on a new line.
443+ if (count == buffer.length) {
444+ growBuffer();
445+ buffer = this.buffer;
446+ }
447+ buffer[count++] = '\n';
448+ c = in.read();
449+ break textLoop;
450+
451+ // Again, the extra cases here are a trick
452+ // to get the compiler to generate a tableswitch.
453+ case 0: case 1: case 2: case 3: case 4: case 5:
454+ case 6: case 7: case 8: case 11: case 12: case 13:
455+ case 14: case 15: case 16: case 17: case 18: case 19:
456+ case 20: case 21: case 22: case 23: case 24: case 25:
457+ case 26: case 27: case 28: case 29: case 30: case 31:
458+ case 32: case 33: case 34: case 35: case 36: case 37:
459+ case 38: case 39: case 40:
460+ default:
461+ // Add the character to our buffer.
462+ if (count == buffer.length) {
463+ growBuffer();
464+ buffer = this.buffer;
465+ }
466+ buffer[count++] = (char)c;
467+ c = in.read();
468+ break;
469+ }
470+ } // end textLoop
471+ } // end outerLoop
472+
473+ // We have scanned our doc comment. It is stored in
474+ // buffer. The previous implementation of scanDocComment
475+ // stripped off all trailing spaces and stars from the comment.
476+ // We will do this as well, so as to cause a minimum of
477+ // disturbance. Is this what we want?
478+ if (count > 0) {
479+ int i = count - 1;
480+ trailLoop:
481+ while (i > -1) {
482+ switch (buffer[i]) {
483+ case ' ':
484+ case '\t':
485+ case '*':
486+ i--;
487+ break;
488+ // And again, the extra cases here are a trick
489+ // to get the compiler to generate a tableswitch.
490+ case 0: case 1: case 2: case 3: case 4: case 5:
491+ case 6: case 7: case 8: case 10: case 11: case 12:
492+ case 13: case 14: case 15: case 16: case 17: case 18:
493+ case 19: case 20: case 21: case 22: case 23: case 24:
494+ case 25: case 26: case 27: case 28: case 29: case 30:
495+ case 31: case 33: case 34: case 35: case 36: case 37:
496+ case 38: case 39: case 40:
497+ default:
498+ break trailLoop;
499+ }
500+ }
501+ count = i + 1;
502+
503+ // Return the text of the doc comment.
504+ return new String(buffer, 0, count);
505+ } else {
506+ return "";
507+ }
508+ }
509+
510+ /**
511+ * Scan a number. The first digit of the number should be the current
512+ * character. We may be scanning hex, decimal, or octal at this point
513+ */
514+ private void scanNumber() throws IOException {
515+ boolean seenNonOctal = false;
516+ boolean overflow = false;
517+ boolean seenDigit = false; // used to detect invalid hex number 0xL
518+ radix = (ch == '0' ? 8 : 10);
519+ long value = ch - '0';
520+ count = 0;
521+ putc(ch); // save character in buffer
522+ numberLoop:
523+ for (;;) {
524+ switch (ch = in.read()) {
525+ case '.':
526+ if (radix == 16)
527+ break numberLoop; // an illegal character
528+ scanReal();
529+ return;
530+
531+ case '8': case '9':
532+ // We can't yet throw an error if reading an octal. We might
533+ // discover we're really reading a real.
534+ seenNonOctal = true;
535+ case '0': case '1': case '2': case '3':
536+ case '4': case '5': case '6': case '7':
537+ seenDigit = true;
538+ putc(ch);
539+ if (radix == 10) {
540+ overflow = overflow || (value * 10)/10 != value;
541+ value = (value * 10) + (ch - '0');
542+ overflow = overflow || (value - 1 < -1);
543+ } else if (radix == 8) {
544+ overflow = overflow || (value >>> 61) != 0;
545+ value = (value << 3) + (ch - '0');
546+ } else {
547+ overflow = overflow || (value >>> 60) != 0;
548+ value = (value << 4) + (ch - '0');
549+ }
550+ break;
551+
552+ case 'd': case 'D': case 'e': case 'E': case 'f': case 'F':
553+ if (radix != 16) {
554+ scanReal();
555+ return;
556+ }
557+ // fall through
558+ case 'a': case 'A': case 'b': case 'B': case 'c': case 'C':
559+ seenDigit = true;
560+ putc(ch);
561+ if (radix != 16)
562+ break numberLoop; // an illegal character
563+ overflow = overflow || (value >>> 60) != 0;
564+ value = (value << 4) + 10 +
565+ Character.toLowerCase((char)ch) - 'a';
566+ break;
567+
568+ case 'l': case 'L':
569+ ch = in.read(); // skip over 'l'
570+ longValue = value;
571+ token = LONGVAL;
572+ break numberLoop;
573+
574+ case 'x': case 'X':
575+ // if the first character is a '0' and this is the second
576+ // letter, then read in a hexadecimal number. Otherwise, error.
577+ if (count == 1 && radix == 8) {
578+ radix = 16;
579+ seenDigit = false;
580+ break;
581+ } else {
582+ // we'll get an illegal character error
583+ break numberLoop;
584+ }
585+
586+ default:
587+ intValue = (int)value;
588+ token = INTVAL;
589+ break numberLoop;
590+ }
591+ } // while true
592+
593+ // We have just finished reading the number. The next thing better
594+ // not be a letter or digit.
595+ // Note: There will be deprecation warnings against these uses
596+ // of Character.isJavaLetterOrDigit and Character.isJavaLetter.
597+ // Do not fix them yet; allow the compiler to run on pre-JDK1.1 VMs.
598+ if (Character.isJavaLetterOrDigit((char)ch) || ch == '.') {
599+ env.error(in.pos, "invalid.number");
600+ do { ch = in.read(); }
601+ while (Character.isJavaLetterOrDigit((char)ch) || ch == '.');
602+ intValue = 0;
603+ token = INTVAL;
604+ } else if (radix == 8 && seenNonOctal) {
605+ // A bogus octal literal.
606+ intValue = 0;
607+ token = INTVAL;
608+ env.error(pos, "invalid.octal.number");
609+ } else if (radix == 16 && seenDigit == false) {
610+ // A hex literal with no digits, 0xL, for example.
611+ intValue = 0;
612+ token = INTVAL;
613+ env.error(pos, "invalid.hex.number");
614+ } else {
615+ if (token == INTVAL) {
616+ // Check for overflow. Note that base 10 literals
617+ // have different rules than base 8 and 16.
618+ overflow = overflow ||
619+ (value & 0xFFFFFFFF00000000L) != 0 ||
620+ (radix == 10 && value > 2147483648L);
621+
622+ if (overflow) {
623+ intValue = 0;
624+
625+ // Give a specific error message which tells
626+ // the user the range.
627+ switch (radix) {
628+ case 8:
629+ env.error(pos, "overflow.int.oct");
630+ break;
631+ case 10:
632+ env.error(pos, "overflow.int.dec");
633+ break;
634+ case 16:
635+ env.error(pos, "overflow.int.hex");
636+ break;
637+ default:
638+ throw new CompilerError("invalid radix");
639+ }
640+ }
641+ } else {
642+ if (overflow) {
643+ longValue = 0;
644+
645+ // Give a specific error message which tells
646+ // the user the range.
647+ switch (radix) {
648+ case 8:
649+ env.error(pos, "overflow.long.oct");
650+ break;
651+ case 10:
652+ env.error(pos, "overflow.long.dec");
653+ break;
654+ case 16:
655+ env.error(pos, "overflow.long.hex");
656+ break;
657+ default:
658+ throw new CompilerError("invalid radix");
659+ }
660+ }
661+ }
662+ }
663+ }
664+
665+ /**
666+ * Scan a float. We are either looking at the decimal, or we have already
667+ * seen it and put it into the buffer. We haven't seen an exponent.
668+ * Scan a float. Should be called with the current character is either
669+ * the 'e', 'E' or '.'
670+ */
671+ private void scanReal() throws IOException {
672+ boolean seenExponent = false;
673+ boolean isSingleFloat = false;
674+ char lastChar;
675+ if (ch == '.') {
676+ putc(ch);
677+ ch = in.read();
678+ }
679+
680+ numberLoop:
681+ for ( ; ; ch = in.read()) {
682+ switch (ch) {
683+ case '0': case '1': case '2': case '3': case '4':
684+ case '5': case '6': case '7': case '8': case '9':
685+ putc(ch);
686+ break;
687+
688+ case 'e': case 'E':
689+ if (seenExponent)
690+ break numberLoop; // we'll get a format error
691+ putc(ch);
692+ seenExponent = true;
693+ break;
694+
695+ case '+': case '-':
696+ lastChar = buffer[count - 1];
697+ if (lastChar != 'e' && lastChar != 'E')
698+ break numberLoop; // this isn't an error, though!
699+ putc(ch);
700+ break;
701+
702+ case 'f': case 'F':
703+ ch = in.read(); // skip over 'f'
704+ isSingleFloat = true;
705+ break numberLoop;
706+
707+ case 'd': case 'D':
708+ ch = in.read(); // skip over 'd'
709+ // fall through
710+ default:
711+ break numberLoop;
712+ } // sswitch
713+ } // loop
714+
715+ // we have just finished reading the number. The next thing better
716+ // not be a letter or digit.
717+ if (Character.isJavaLetterOrDigit((char)ch) || ch == '.') {
718+ env.error(in.pos, "invalid.number");
719+ do { ch = in.read(); }
720+ while (Character.isJavaLetterOrDigit((char)ch) || ch == '.');
721+ doubleValue = 0;
722+ token = DOUBLEVAL;
723+ } else {
724+ token = isSingleFloat ? FLOATVAL : DOUBLEVAL;
725+ try {
726+ lastChar = buffer[count - 1];
727+ if (lastChar == 'e' || lastChar == 'E'
728+ || lastChar == '+' || lastChar == '-') {
729+ env.error(in.pos -1, "float.format");
730+ } else if (isSingleFloat) {
731+ String string = bufferString();
732+ floatValue = Float.valueOf(string).floatValue();
733+ if (Float.isInfinite(floatValue)) {
734+ env.error(pos, "overflow.float");
735+ } else if (floatValue == 0 && !looksLikeZero(string)) {
736+ env.error(pos, "underflow.float");
737+ }
738+ } else {
739+ String string = bufferString();
740+ doubleValue = Double.valueOf(string).doubleValue();
741+ if (Double.isInfinite(doubleValue)) {
742+ env.error(pos, "overflow.double");
743+ } else if (doubleValue == 0 && !looksLikeZero(string)) {
744+ env.error(pos, "underflow.double");
745+ }
746+ }
747+ } catch (NumberFormatException ee) {
748+ env.error(pos, "float.format");
749+ doubleValue = 0;
750+ floatValue = 0;
751+ }
752+ }
753+ return;
754+ }
755+
756+ // We have a token that parses as a number. Is this token possibly zero?
757+ // i.e. does it have a non-zero value in the mantissa?
758+ private static boolean looksLikeZero(String token) {
759+ int length = token.length();
760+ for (int i = 0; i < length; i++) {
761+ switch (token.charAt(i)) {
762+ case 0: case '.':
763+ continue;
764+ case '1': case '2': case '3': case '4': case '5':
765+ case '6': case '7': case '8': case '9':
766+ return false;
767+ case 'e': case 'E': case 'f': case 'F':
768+ return true;
769+ }
770+ }
771+ return true;
772+ }
773+
774+ /**
775+ * Scan an escape character.
776+ * @return the character or -1 if it escaped an
777+ * end-of-line.
778+ */
779+ private int scanEscapeChar() throws IOException {
780+ long p = in.pos;
781+
782+ switch (ch = in.read()) {
783+ case '0': case '1': case '2': case '3':
784+ case '4': case '5': case '6': case '7': {
785+ int n = ch - '0';
786+ for (int i = 2 ; i > 0 ; i--) {
787+ switch (ch = in.read()) {
788+ case '0': case '1': case '2': case '3':
789+ case '4': case '5': case '6': case '7':
790+ n = (n << 3) + ch - '0';
791+ break;
792+
793+ default:
794+ if (n > 0xFF) {
795+ env.error(p, "invalid.escape.char");
796+ }
797+ return n;
798+ }
799+ }
800+ ch = in.read();
801+ if (n > 0xFF) {
802+ env.error(p, "invalid.escape.char");
803+ }
804+ return n;
805+ }
806+
807+ case 'r': ch = in.read(); return '\r';
808+ case 'n': ch = in.read(); return '\n';
809+ case 'f': ch = in.read(); return '\f';
810+ case 'b': ch = in.read(); return '\b';
811+ case 't': ch = in.read(); return '\t';
812+ case '\\': ch = in.read(); return '\\';
813+ case '\"': ch = in.read(); return '\"';
814+ case '\'': ch = in.read(); return '\'';
815+ }
816+
817+ env.error(p, "invalid.escape.char");
818+ ch = in.read();
819+ return -1;
820+ }
821+
822+ /**
823+ * Scan a string. The current character
824+ * should be the opening " of the string.
825+ */
826+ private void scanString() throws IOException {
827+ token = STRINGVAL;
828+ count = 0;
829+ ch = in.read();
830+
831+ // Scan a String
832+ while (true) {
833+ switch (ch) {
834+ case EOF:
835+ env.error(pos, "eof.in.string");
836+ stringValue = bufferString();
837+ return;
838+
839+ case '\r':
840+ case '\n':
841+ ch = in.read();
842+ env.error(pos, "newline.in.string");
843+ stringValue = bufferString();
844+ return;
845+
846+ case '"':
847+ ch = in.read();
848+ stringValue = bufferString();
849+ return;
850+
851+ case '\\': {
852+ int c = scanEscapeChar();
853+ if (c >= 0) {
854+ putc((char)c);
855+ }
856+ break;
857+ }
858+
859+ default:
860+ putc(ch);
861+ ch = in.read();
862+ break;
863+ }
864+ }
865+ }
866+
867+ /**
868+ * Scan a character. The current character should be
869+ * the opening ' of the character constant.
870+ */
871+ private void scanCharacter() throws IOException {
872+ token = CHARVAL;
873+
874+ switch (ch = in.read()) {
875+ case '\\':
876+ int c = scanEscapeChar();
877+ charValue = (char)((c >= 0) ? c : 0);
878+ break;
879+
880+ case '\'':
881+ // There are two standard problems this case deals with. One
882+ // is the malformed single quote constant (i.e. the programmer
883+ // uses ''' instead of '\'') and the other is the empty
884+ // character constant (i.e. ''). Just consume any number of
885+ // single quotes and emit an error message.
886+ charValue = 0;
887+ env.error(pos, "invalid.char.constant");
888+ ch = in.read();
889+ while (ch == '\'') {
890+ ch = in.read();
891+ }
892+ return;
893+
894+ case '\r':
895+ case '\n':
896+ charValue = 0;
897+ env.error(pos, "invalid.char.constant");
898+ return;
899+
900+ default:
901+ charValue = (char)ch;
902+ ch = in.read();
903+ break;
904+ }
905+
906+ if (ch == '\'') {
907+ ch = in.read();
908+ } else {
909+ env.error(pos, "invalid.char.constant");
910+ while (true) {
911+ switch (ch) {
912+ case '\'':
913+ ch = in.read();
914+ return;
915+ case ';':
916+ case '\n':
917+ case EOF:
918+ return;
919+ default:
920+ ch = in.read();
921+ }
922+ }
923+ }
924+ }
925+
926+ /**
927+ * Scan an Identifier. The current character should
928+ * be the first character of the identifier.
929+ */
930+ private void scanIdentifier() throws IOException {
931+ count = 0;
932+
933+ while (true) {
934+ putc(ch);
935+ switch (ch = in.read()) {
936+ case 'a': case 'b': case 'c': case 'd': case 'e':
937+ case 'f': case 'g': case 'h': case 'i': case 'j':
938+ case 'k': case 'l': case 'm': case 'n': case 'o':
939+ case 'p': case 'q': case 'r': case 's': case 't':
940+ case 'u': case 'v': case 'w': case 'x': case 'y':
941+ case 'z':
942+ case 'A': case 'B': case 'C': case 'D': case 'E':
943+ case 'F': case 'G': case 'H': case 'I': case 'J':
944+ case 'K': case 'L': case 'M': case 'N': case 'O':
945+ case 'P': case 'Q': case 'R': case 'S': case 'T':
946+ case 'U': case 'V': case 'W': case 'X': case 'Y':
947+ case 'Z':
948+ case '0': case '1': case '2': case '3': case '4':
949+ case '5': case '6': case '7': case '8': case '9':
950+ case '$': case '_':
951+ break;
952+
953+ default:
954+ if (!Character.isJavaLetterOrDigit((char)ch)) {
955+ idValue = Identifier.lookup(bufferString());
956+ token = idValue.getType();
957+ return;
958+ }
959+ }
960+ }
961+ }
962+
963+ /**
964+ * The ending position of the current token
965+ */
966+ // Note: This should be part of the pos itself.
967+ public long getEndPos() {
968+ return in.pos;
969+ }
970+
971+ /**
972+ * If the current token is IDENT, return the identifier occurrence.
973+ * It will be freshly allocated.
974+ */
975+ public IdentifierToken getIdToken() {
976+ return (token != IDENT) ? null : new IdentifierToken(pos, idValue);
977+ }
978+
979+ /**
980+ * Scan the next token.
981+ * @return the position of the previous token.
982+ */
983+ public long scan() throws IOException {
984+ return xscan();
985+ }
986+
987+ protected long xscan() throws IOException {
988+ final ScannerInputReader in = this.in;
989+ long retPos = pos;
990+ prevPos = in.pos;
991+ docComment = null;
992+ while (true) {
993+ pos = in.pos;
994+
995+ switch (ch) {
996+ case EOF:
997+ token = EOF;
998+ return retPos;
999+
1000+ case '\n':
1001+ if (scanComments) {
1002+ ch = ' ';
1003+ // Avoid this path the next time around.
1004+ // Do not just call in.read; we want to present
1005+ // a null token (and also avoid read-ahead).
1006+ token = COMMENT;
1007+ return retPos;
1008+ }
1009+ case ' ':
1010+ case '\t':
1011+ case '\f':
1012+ ch = in.read();
1013+ break;
1014+
1015+ case '/':
1016+ switch (ch = in.read()) {
1017+ case '/':
1018+ // Parse a // comment
1019+ while (((ch = in.read()) != EOF) && (ch != '\n'));
1020+ if (scanComments) {
1021+ token = COMMENT;
1022+ return retPos;
1023+ }
1024+ break;
1025+
1026+ case '*':
1027+ ch = in.read();
1028+ if (ch == '*') {
1029+ docComment = scanDocComment();
1030+ } else {
1031+ skipComment();
1032+ }
1033+ if (scanComments) {
1034+ return retPos;
1035+ }
1036+ break;
1037+
1038+ case '=':
1039+ ch = in.read();
1040+ token = ASGDIV;
1041+ return retPos;
1042+
1043+ default:
1044+ token = DIV;
1045+ return retPos;
1046+ }
1047+ break;
1048+
1049+ case '"':
1050+ scanString();
1051+ return retPos;
1052+
1053+ case '\'':
1054+ scanCharacter();
1055+ return retPos;
1056+
1057+ case '0': case '1': case '2': case '3': case '4':
1058+ case '5': case '6': case '7': case '8': case '9':
1059+ scanNumber();
1060+ return retPos;
1061+
1062+ case '.':
1063+ switch (ch = in.read()) {
1064+ case '0': case '1': case '2': case '3': case '4':
1065+ case '5': case '6': case '7': case '8': case '9':
1066+ count = 0;
1067+ putc('.');
1068+ scanReal();
1069+ break;
1070+ default:
1071+ token = FIELD;
1072+ }
1073+ return retPos;
1074+
1075+ case '{':
1076+ ch = in.read();
1077+ token = LBRACE;
1078+ return retPos;
1079+
1080+ case '}':
1081+ ch = in.read();
1082+ token = RBRACE;
1083+ return retPos;
1084+
1085+ case '(':
1086+ ch = in.read();
1087+ token = LPAREN;
1088+ return retPos;
1089+
1090+ case ')':
1091+ ch = in.read();
1092+ token = RPAREN;
1093+ return retPos;
1094+
1095+ case '[':
1096+ ch = in.read();
1097+ token = LSQBRACKET;
1098+ return retPos;
1099+
1100+ case ']':
1101+ ch = in.read();
1102+ token = RSQBRACKET;
1103+ return retPos;
1104+
1105+ case ',':
1106+ ch = in.read();
1107+ token = COMMA;
1108+ return retPos;
1109+
1110+ case ';':
1111+ ch = in.read();
1112+ token = SEMICOLON;
1113+ return retPos;
1114+
1115+ case '?':
1116+ ch = in.read();
1117+ token = QUESTIONMARK;
1118+ return retPos;
1119+
1120+ case '~':
1121+ ch = in.read();
1122+ token = BITNOT;
1123+ return retPos;
1124+
1125+ case ':':
1126+ ch = in.read();
1127+ token = COLON;
1128+ return retPos;
1129+
1130+ case '-':
1131+ switch (ch = in.read()) {
1132+ case '-':
1133+ ch = in.read();
1134+ token = DEC;
1135+ return retPos;
1136+
1137+ case '=':
1138+ ch = in.read();
1139+ token = ASGSUB;
1140+ return retPos;
1141+ }
1142+ token = SUB;
1143+ return retPos;
1144+
1145+ case '+':
1146+ switch (ch = in.read()) {
1147+ case '+':
1148+ ch = in.read();
1149+ token = INC;
1150+ return retPos;
1151+
1152+ case '=':
1153+ ch = in.read();
1154+ token = ASGADD;
1155+ return retPos;
1156+ }
1157+ token = ADD;
1158+ return retPos;
1159+
1160+ case '<':
1161+ switch (ch = in.read()) {
1162+ case '<':
1163+ if ((ch = in.read()) == '=') {
1164+ ch = in.read();
1165+ token = ASGLSHIFT;
1166+ return retPos;
1167+ }
1168+ token = LSHIFT;
1169+ return retPos;
1170+
1171+ case '=':
1172+ ch = in.read();
1173+ token = LE;
1174+ return retPos;
1175+ }
1176+ token = LT;
1177+ return retPos;
1178+
1179+ case '>':
1180+ switch (ch = in.read()) {
1181+ case '>':
1182+ switch (ch = in.read()) {
1183+ case '=':
1184+ ch = in.read();
1185+ token = ASGRSHIFT;
1186+ return retPos;
1187+
1188+ case '>':
1189+ if ((ch = in.read()) == '=') {
1190+ ch = in.read();
1191+ token = ASGURSHIFT;
1192+ return retPos;
1193+ }
1194+ token = URSHIFT;
1195+ return retPos;
1196+ }
1197+ token = RSHIFT;
1198+ return retPos;
1199+
1200+ case '=':
1201+ ch = in.read();
1202+ token = GE;
1203+ return retPos;
1204+ }
1205+ token = GT;
1206+ return retPos;
1207+
1208+ case '|':
1209+ switch (ch = in.read()) {
1210+ case '|':
1211+ ch = in.read();
1212+ token = OR;
1213+ return retPos;
1214+
1215+ case '=':
1216+ ch = in.read();
1217+ token = ASGBITOR;
1218+ return retPos;
1219+ }
1220+ token = BITOR;
1221+ return retPos;
1222+
1223+ case '&':
1224+ switch (ch = in.read()) {
1225+ case '&':
1226+ ch = in.read();
1227+ token = AND;
1228+ return retPos;
1229+
1230+ case '=':
1231+ ch = in.read();
1232+ token = ASGBITAND;
1233+ return retPos;
1234+ }
1235+ token = BITAND;
1236+ return retPos;
1237+
1238+ case '=':
1239+ if ((ch = in.read()) == '=') {
1240+ ch = in.read();
1241+ token = EQ;
1242+ return retPos;
1243+ }
1244+ token = ASSIGN;
1245+ return retPos;
1246+
1247+ case '%':
1248+ if ((ch = in.read()) == '=') {
1249+ ch = in.read();
1250+ token = ASGREM;
1251+ return retPos;
1252+ }
1253+ token = REM;
1254+ return retPos;
1255+
1256+ case '^':
1257+ if ((ch = in.read()) == '=') {
1258+ ch = in.read();
1259+ token = ASGBITXOR;
1260+ return retPos;
1261+ }
1262+ token = BITXOR;
1263+ return retPos;
1264+
1265+ case '!':
1266+ if ((ch = in.read()) == '=') {
1267+ ch = in.read();
1268+ token = NE;
1269+ return retPos;
1270+ }
1271+ token = NOT;
1272+ return retPos;
1273+
1274+ case '*':
1275+ if ((ch = in.read()) == '=') {
1276+ ch = in.read();
1277+ token = ASGMUL;
1278+ return retPos;
1279+ }
1280+ token = MUL;
1281+ return retPos;
1282+
1283+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
1284+ case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
1285+ case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
1286+ case 's': case 't': case 'u': case 'v': case 'w': case 'x':
1287+ case 'y': case 'z':
1288+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
1289+ case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
1290+ case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
1291+ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
1292+ case 'Y': case 'Z':
1293+ case '$': case '_':
1294+ scanIdentifier();
1295+ return retPos;
1296+
1297+ case '\u001a':
1298+ // Our one concession to DOS.
1299+ if ((ch = in.read()) == EOF) {
1300+ token = EOF;
1301+ return retPos;
1302+ }
1303+ env.error(pos, "funny.char");
1304+ ch = in.read();
1305+ break;
1306+
1307+
1308+ default:
1309+ if (Character.isJavaLetter((char)ch)) {
1310+ scanIdentifier();
1311+ return retPos;
1312+ }
1313+ env.error(pos, "funny.char");
1314+ ch = in.read();
1315+ break;
1316+ }
1317+ }
1318+ }
1319+
1320+ /**
1321+ * Scan to a matching '}', ']' or ')'. The current token must be
1322+ * a '{', '[' or '(';
1323+ */
1324+ public void match(int open, int close) throws IOException {
1325+ int depth = 1;
1326+
1327+ while (true) {
1328+ scan();
1329+ if (token == open) {
1330+ depth++;
1331+ } else if (token == close) {
1332+ if (--depth == 0) {
1333+ return;
1334+ }
1335+ } else if (token == EOF) {
1336+ env.error(pos, "unbalanced.paren");
1337+ return;
1338+ }
1339+ }
1340+ }
1341+}
java/pkg/sun/tools/java/ScannerInputReader.java+242−0
@@ -0,0 +1,242 @@
1+/*
2+ * Copyright (c) 1995, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.io.IOException;
29+import java.io.InputStream;
30+import java.io.InputStreamReader;
31+import java.io.BufferedReader;
32+import java.io.FilterReader;
33+import java.io.UnsupportedEncodingException;
34+
35+/**
36+ * An input stream for java programs. The stream treats either "\n", "\r"
37+ * or "\r\n" as the end of a line, it always returns \n. It also parses
38+ * UNICODE characters expressed as \uffff. However, if it sees "\\", the
39+ * second slash cannot begin a unicode sequence. It keeps track of the current
40+ * position in the input stream.
41+ *
42+ * WARNING: The contents of this source file are not part of any
43+ * supported API. Code that depends on them does so at its own risk:
44+ * they are subject to change or removal without notice.
45+ *
46+ * @author Arthur van Hoff
47+ */
48+
49+public
50+class ScannerInputReader extends FilterReader implements Constants {
51+ // A note. This class does not really properly subclass FilterReader.
52+ // Since this class only overrides the single character read method,
53+ // and not the multi-character read method, any use of the latter
54+ // will not work properly. Any attempt to use this code outside of
55+ // the compiler should take that into account.
56+ //
57+ // For efficiency, it might be worth moving this code to Scanner and
58+ // getting rid of this class.
59+
60+ Environment env;
61+ long pos;
62+
63+ private long chpos;
64+ private int pushBack = -1;
65+
66+ public ScannerInputReader(Environment env, InputStream in)
67+ throws UnsupportedEncodingException
68+ {
69+ // ScannerInputStream has been modified to no longer use
70+ // BufferedReader. It now does its own buffering for
71+ // performance.
72+ super(env.getCharacterEncoding() != null ?
73+ new InputStreamReader(in, env.getCharacterEncoding()) :
74+ new InputStreamReader(in));
75+
76+ // Start out the buffer empty.
77+ currentIndex = 0;
78+ numChars = 0;
79+
80+ this.env = env;
81+ chpos = Scanner.LINEINC;
82+ }
83+
84+ //------------------------------------------------------------
85+ // Buffering code.
86+
87+ // The size of our buffer.
88+ private static final int BUFFERLEN = 10 * 1024;
89+
90+ // A character buffer.
91+ private final char[] buffer = new char[BUFFERLEN];
92+
93+ // The index of the next character to be "read" from the buffer.
94+ private int currentIndex;
95+
96+ // The number of characters in the buffer. -1 if EOF is reached.
97+ private int numChars;
98+
99+ /**
100+ * Get the next character from our buffer.
101+ * Note: this method has been inlined by hand in the `read' method
102+ * below. Any changes made to this method should be equally applied
103+ * to that code.
104+ */
105+ private int getNextChar() throws IOException {
106+ // Check to see if we have either run out of characters in our
107+ // buffer or gotten to EOF on a previous call.
108+ if (currentIndex >= numChars) {
109+ numChars = in.read(buffer);
110+ if (numChars == -1) {
111+ // We have reached EOF.
112+ return -1;
113+ }
114+
115+ // No EOF. currentIndex points to first char in buffer.
116+ currentIndex = 0;
117+ }
118+
119+ return buffer[currentIndex++];
120+ }
121+
122+ //------------------------------------------------------------
123+
124+ public int read(char[] buffer, int off, int len) {
125+ throw new CompilerError(
126+ "ScannerInputReader is not a fully implemented reader.");
127+ }
128+
129+ public int read() throws IOException {
130+ pos = chpos;
131+ chpos += Scanner.OFFSETINC;
132+
133+ int c = pushBack;
134+ if (c == -1) {
135+ getchar: try {
136+ // Here the call...
137+ // c = getNextChar();
138+ // has been inlined by hand for performance.
139+
140+ if (currentIndex >= numChars) {
141+ numChars = in.read(buffer);
142+ if (numChars == -1) {
143+ // We have reached EOF.
144+ c = -1;
145+ break getchar;
146+ }
147+
148+ // No EOF. currentIndex points to first char in buffer.
149+ currentIndex = 0;
150+ }
151+ c = buffer[currentIndex++];
152+
153+ } catch (java.io.CharConversionException e) {
154+ env.error(pos, "invalid.encoding.char");
155+ // this is fatal error
156+ return -1;
157+ }
158+ } else {
159+ pushBack = -1;
160+ }
161+
162+ // parse special characters
163+ switch (c) {
164+ case -2:
165+ // -2 is a special code indicating a pushback of a backslash that
166+ // definitely isn't the start of a unicode sequence.
167+ return '\\';
168+
169+ case '\\':
170+ if ((c = getNextChar()) != 'u') {
171+ pushBack = (c == '\\' ? -2 : c);
172+ return '\\';
173+ }
174+ // we have a unicode sequence
175+ chpos += Scanner.OFFSETINC;
176+ while ((c = getNextChar()) == 'u') {
177+ chpos += Scanner.OFFSETINC;
178+ }
179+
180+ // unicode escape sequence
181+ int d = 0;
182+ for (int i = 0 ; i < 4 ; i++, chpos += Scanner.OFFSETINC, c = getNextChar()) {
183+ switch (c) {
184+ case '0': case '1': case '2': case '3': case '4':
185+ case '5': case '6': case '7': case '8': case '9':
186+ d = (d << 4) + c - '0';
187+ break;
188+
189+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
190+ d = (d << 4) + 10 + c - 'a';
191+ break;
192+
193+ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
194+ d = (d << 4) + 10 + c - 'A';
195+ break;
196+
197+ default:
198+ env.error(pos, "invalid.escape.char");
199+ pushBack = c;
200+ return d;
201+ }
202+ }
203+ pushBack = c;
204+
205+ // To read the following line, switch \ and /...
206+ // Handle /u000a, /u000A, /u000d, /u000D properly as
207+ // line terminators as per JLS 3.4, even though they are encoded
208+ // (this properly respects the order given in JLS 3.2).
209+ switch (d) {
210+ case '\n':
211+ chpos += Scanner.LINEINC;
212+ return '\n';
213+ case '\r':
214+ if ((c = getNextChar()) != '\n') {
215+ pushBack = c;
216+ } else {
217+ chpos += Scanner.OFFSETINC;
218+ }
219+ chpos += Scanner.LINEINC;
220+ return '\n';
221+ default:
222+ return d;
223+ }
224+
225+ case '\n':
226+ chpos += Scanner.LINEINC;
227+ return '\n';
228+
229+ case '\r':
230+ if ((c = getNextChar()) != '\n') {
231+ pushBack = c;
232+ } else {
233+ chpos += Scanner.OFFSETINC;
234+ }
235+ chpos += Scanner.LINEINC;
236+ return '\n';
237+
238+ default:
239+ return c;
240+ }
241+ }
242+}
java/pkg/sun/tools/java/SyntaxError.java+39−0
@@ -0,0 +1,39 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+/**
29+ * Syntax errors, should always be caught inside the
30+ * parser for error recovery.
31+ *
32+ * WARNING: The contents of this source file are not part of any
33+ * supported API. Code that depends on them does so at its own risk:
34+ * they are subject to change or removal without notice.
35+ */
36+
37+public
38+class SyntaxError extends Exception {
39+}
java/pkg/sun/tools/java/Type.java+455−0
@@ -0,0 +1,455 @@
1+/*
2+ * Copyright (c) 1994, 2003, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.tools.java;
27+
28+import java.util.Hashtable;
29+
30+/**
31+ * This class represents an Java Type.<p>
32+ *
33+ * It encapsulates an Java type signature and it provides
34+ * quick access to the components of the type. Note that
35+ * all types are hashed into a hashtable (typeHash), that
36+ * means that each distinct type is only allocated once,
37+ * saving space and making equality checks cheap.<p>
38+ *
39+ * For simple types use the constants defined in this class.
40+ * (Type.tInt, Type.tShort, ...). To create complex types use
41+ * the static methods Type.tArray, Type.tMethod or Type.tClass.
42+ *
43+ * For classes, arrays and method types a sub class of class
44+ * type is created which defines the extra type components.
45+ *
46+ * WARNING: The contents of this source file are not part of any
47+ * supported API. Code that depends on them does so at its own risk:
48+ * they are subject to change or removal without notice.
49+ *
50+ * @see ArrayType
51+ * @see ClassType
52+ * @see MethodType
53+ * @author Arthur van Hoff
54+ */
55+public
56+class Type implements Constants {
57+ /**
58+ * This hashtable is used to cache types
59+ */
60+ private static final Hashtable typeHash = new Hashtable(231);
61+
62+ /**
63+ * The TypeCode of this type. The value of this field is one
64+ * of the TC_* contant values defined in Constants.
65+ * @see Constants
66+ */
67+ protected int typeCode;
68+
69+ /**
70+ * The TypeSignature of this type. This type signature is
71+ * equivalent to the runtime type signatures used by the
72+ * interpreter.
73+ */
74+ protected String typeSig;
75+
76+ /*
77+ * Predefined types.
78+ */
79+ public static final Type noArgs[] = new Type[0];
80+ public static final Type tError = new Type(TC_ERROR, "?");
81+ public static final Type tPackage = new Type(TC_ERROR, ".");
82+ public static final Type tNull = new Type(TC_NULL, "*");
83+ public static final Type tVoid = new Type(TC_VOID, SIG_VOID);
84+ public static final Type tBoolean = new Type(TC_BOOLEAN, SIG_BOOLEAN);
85+ public static final Type tByte = new Type(TC_BYTE, SIG_BYTE);
86+ public static final Type tChar = new Type(TC_CHAR, SIG_CHAR);
87+ public static final Type tShort = new Type(TC_SHORT, SIG_SHORT);
88+ public static final Type tInt = new Type(TC_INT, SIG_INT);
89+ public static final Type tFloat = new Type(TC_FLOAT, SIG_FLOAT);
90+ public static final Type tLong = new Type(TC_LONG, SIG_LONG);
91+ public static final Type tDouble = new Type(TC_DOUBLE, SIG_DOUBLE);
92+ public static final Type tObject = Type.tClass(idJavaLangObject);
93+ public static final Type tClassDesc = Type.tClass(idJavaLangClass);
94+ public static final Type tString = Type.tClass(idJavaLangString);
95+ public static final Type tCloneable = Type.tClass(idJavaLangCloneable);
96+ public static final Type tSerializable = Type.tClass(idJavaIoSerializable);
97+
98+ /**
99+ * Create a type given a typecode and a type signature.
100+ */
101+ protected Type(int typeCode, String typeSig) {
102+ this.typeCode = typeCode;
103+ this.typeSig = typeSig;
104+ typeHash.put(typeSig, this);
105+ }
106+
107+ /**
108+ * Return the Java type signature.
109+ */
110+ public final String getTypeSignature() {
111+ return typeSig;
112+ }
113+
114+ /**
115+ * Return the type code.
116+ */
117+ public final int getTypeCode() {
118+ return typeCode;
119+ }
120+
121+ /**
122+ * Return the type mask. The bits in this mask correspond
123+ * to the TM_* constants defined in Constants. Only one bit
124+ * is set at a type.
125+ * @see Constants
126+ */
127+ public final int getTypeMask() {
128+ return 1 << typeCode;
129+ }
130+
131+ /**
132+ * Check for a certain type.
133+ */
134+ public final boolean isType(int tc) {
135+ return typeCode == tc;
136+ }
137+
138+ /**
139+ * Check to see if this is the bogus type "array of void"
140+ *
141+ * Although this highly degenerate "type" is not constructable from
142+ * the grammar, the Parser accepts it. Rather than monkey with the
143+ * Parser, we check for the bogus type at specific points and give
144+ * a nice error.
145+ */
146+ public boolean isVoidArray() {
147+ // a void type is not a void array.
148+ if (!isType(TC_ARRAY)) {
149+ return false;
150+ }
151+ // If this is an array, find out what its element type is.
152+ Type type = this;
153+ while (type.isType(TC_ARRAY))
154+ type = type.getElementType();
155+
156+ return type.isType(TC_VOID);
157+ }
158+
159+
160+ /**
161+ * Check for a certain set of types.
162+ */
163+ public final boolean inMask(int tm) {
164+ return ((1 << typeCode) & tm) != 0;
165+ }
166+
167+ /**
168+ * Create an array type.
169+ */
170+ public static synchronized Type tArray(Type elem) {
171+ String sig = new String(SIG_ARRAY + elem.getTypeSignature());
172+ Type t = (Type)typeHash.get(sig);
173+ if (t == null) {
174+ t = new ArrayType(sig, elem);
175+ }
176+ return t;
177+ }
178+
179+ /**
180+ * Return the element type of an array type. Only works
181+ * for array types.
182+ */
183+ public Type getElementType() {
184+ throw new CompilerError("getElementType");
185+ }
186+
187+ /**
188+ * Return the array dimension. Only works for
189+ * array types.
190+ */
191+ public int getArrayDimension() {
192+ return 0;
193+ }
194+
195+ /**
196+ * Create a class type.
197+ * @arg className the fully qualified class name
198+ */
199+ public static synchronized Type tClass(Identifier className) {
200+ if (className.isInner()) {
201+ Type t = tClass(mangleInnerType(className));
202+ if (t.getClassName() != className)
203+ // Somebody got here first with a mangled name.
204+ // (Perhaps it came from a binary.)
205+ changeClassName(t.getClassName(), className);
206+ return t;
207+ }
208+ // see if we've cached the object in the Identifier
209+ if (className.typeObject != null) {
210+ return className.typeObject;
211+ }
212+ String sig =
213+ new String(SIG_CLASS +
214+ className.toString().replace('.', SIGC_PACKAGE) +
215+ SIG_ENDCLASS);
216+ Type t = (Type)typeHash.get(sig);
217+ if (t == null) {
218+ t = new ClassType(sig, className);
219+ }
220+
221+ className.typeObject = t; // cache the Type object in the Identifier
222+ return t;
223+ }
224+
225+ /**
226+ * Return the ClassName. Only works on class types.
227+ */
228+ public Identifier getClassName() {
229+ throw new CompilerError("getClassName:" + this);
230+ }
231+
232+ /**
233+ * Given an inner identifier, return the non-inner, mangled
234+ * representation used to manage signatures.
235+ *
236+ * Note: It is changed to 'public' for Jcov file generation.
237+ * (see Assembler.java)
238+ */
239+
240+ public static Identifier mangleInnerType(Identifier className) {
241+ // Map "pkg.Foo. Bar" to "pkg.Foo$Bar".
242+ if (!className.isInner()) return className;
243+ Identifier mname = Identifier.lookup(
244+ className.getFlatName().toString().
245+ replace('.', SIGC_INNERCLASS) );
246+ if (mname.isInner()) throw new CompilerError("mangle "+mname);
247+ return Identifier.lookup(className.getQualifier(), mname);
248+ }
249+
250+ /**
251+ * We have learned that a signature means something other
252+ * that what we thought it meant. Live with it: Change all
253+ * affected data structures to reflect the new name of the old type.
254+ * <p>
255+ * (This is necessary because of an ambiguity between the
256+ * low-level signatures of inner types and their manglings.
257+ * Note that the latter are also valid class names.)
258+ */
259+ static void changeClassName(Identifier oldName, Identifier newName) {
260+ // Note: If we are upgrading "pkg.Foo$Bar" to "pkg.Foo. Bar",
261+ // we assume someone else will come along and deal with any types
262+ // inner within Bar. So, there's only one change to make.
263+ ((ClassType)Type.tClass(oldName)).className = newName;
264+ }
265+
266+ /**
267+ * Create a method type with no arguments.
268+ */
269+ public static synchronized Type tMethod(Type ret) {
270+ return tMethod(ret, noArgs);
271+ }
272+
273+ /**
274+ * Create a method type with arguments.
275+ */
276+ public static synchronized Type tMethod(Type returnType, Type argTypes[]) {
277+ StringBuffer buf = new StringBuffer();
278+ buf.append(SIG_METHOD);
279+ for (int i = 0 ; i < argTypes.length ; i++) {
280+ buf.append(argTypes[i].getTypeSignature());
281+ }
282+ buf.append(SIG_ENDMETHOD);
283+ buf.append(returnType.getTypeSignature());
284+
285+ String sig = buf.toString();
286+ Type t = (Type)typeHash.get(sig);
287+ if (t == null) {
288+ t = new MethodType(sig, returnType, argTypes);
289+ }
290+ return t;
291+ }
292+
293+ /**
294+ * Return the return type. Only works for method types.
295+ */
296+ public Type getReturnType() {
297+ throw new CompilerError("getReturnType");
298+ }
299+
300+ /**
301+ * Return the argument types. Only works for method types.
302+ */
303+ public Type getArgumentTypes()[] {
304+ throw new CompilerError("getArgumentTypes");
305+ }
306+
307+ /**
308+ * Create a Type from an Java type signature.
309+ * @exception CompilerError invalid type signature.
310+ */
311+ public static synchronized Type tType(String sig) {
312+ Type t = (Type)typeHash.get(sig);
313+ if (t != null) {
314+ return t;
315+ }
316+
317+ switch (sig.charAt(0)) {
318+ case SIGC_ARRAY:
319+ return Type.tArray(tType(sig.substring(1)));
320+
321+ case SIGC_CLASS:
322+ return Type.tClass(Identifier.lookup(sig.substring(1, sig.length() - 1).replace(SIGC_PACKAGE, '.')));
323+
324+ case SIGC_METHOD: {
325+ Type argv[] = new Type[8];
326+ int argc = 0;
327+ int i, j;
328+
329+ for (i = 1 ; sig.charAt(i) != SIGC_ENDMETHOD ; i = j) {
330+ for (j = i ; sig.charAt(j) == SIGC_ARRAY ; j++);
331+ if (sig.charAt(j++) == SIGC_CLASS) {
332+ while (sig.charAt(j++) != SIGC_ENDCLASS);
333+ }
334+ if (argc == argv.length) {
335+ Type newargv[] = new Type[argc * 2];
336+ System.arraycopy(argv, 0, newargv, 0, argc);
337+ argv = newargv;
338+ }
339+ argv[argc++] = tType(sig.substring(i, j));
340+ }
341+
342+ Type argtypes[] = new Type[argc];
343+ System.arraycopy(argv, 0, argtypes, 0, argc);
344+ return Type.tMethod(tType(sig.substring(i + 1)), argtypes);
345+ }
346+ }
347+
348+ throw new CompilerError("invalid TypeSignature:" + sig);
349+ }
350+
351+ /**
352+ * Check if the type arguments are the same.
353+ * @return true if both types are method types and the
354+ * argument types are identical.
355+ */
356+ public boolean equalArguments(Type t) {
357+ return false;
358+ }
359+
360+ /**
361+ * Return the amount of space this type takes up on the
362+ * Java operand stack. For a method this is equal to the
363+ * total space taken up by the arguments.
364+ */
365+ public int stackSize() {
366+ switch (typeCode) {
367+ case TC_ERROR:
368+ case TC_VOID:
369+ return 0;
370+ case TC_BOOLEAN:
371+ case TC_BYTE:
372+ case TC_SHORT:
373+ case TC_CHAR:
374+ case TC_INT:
375+ case TC_FLOAT:
376+ case TC_ARRAY:
377+ case TC_CLASS:
378+ return 1;
379+ case TC_LONG:
380+ case TC_DOUBLE:
381+ return 2;
382+ }
383+ throw new CompilerError("stackSize " + toString());
384+ }
385+
386+ /**
387+ * Return the type code offset. This offset can be added to
388+ * an opcode to get the right opcode type. Most opcodes
389+ * are ordered: int, long, float, double, array. For
390+ * example: iload, lload fload, dload, aload. So the
391+ * appropriate opcode is iadd + type.getTypeCodeOffset().
392+ */
393+ public int getTypeCodeOffset() {
394+ switch (typeCode) {
395+ case TC_BOOLEAN:
396+ case TC_BYTE:
397+ case TC_SHORT:
398+ case TC_CHAR:
399+ case TC_INT:
400+ return 0;
401+ case TC_LONG:
402+ return 1;
403+ case TC_FLOAT:
404+ return 2;
405+ case TC_DOUBLE:
406+ return 3;
407+ case TC_NULL:
408+ case TC_ARRAY:
409+ case TC_CLASS:
410+ return 4;
411+ }
412+ throw new CompilerError("invalid typecode: " + typeCode);
413+ }
414+
415+ /**
416+ * Convert a Type to a string, if abbrev is true class names are
417+ * not fully qualified, if ret is true the return type is included.
418+ */
419+ public String typeString(String id, boolean abbrev, boolean ret) {
420+ String s = null;
421+
422+ switch (typeCode) {
423+ case TC_NULL: s = "null"; break;
424+ case TC_VOID: s = "void"; break;
425+ case TC_BOOLEAN: s = "boolean"; break;
426+ case TC_BYTE: s = "byte"; break;
427+ case TC_CHAR: s = "char"; break;
428+ case TC_SHORT: s = "short"; break;
429+ case TC_INT: s = "int"; break;
430+ case TC_LONG: s = "long"; break;
431+ case TC_FLOAT: s = "float"; break;
432+ case TC_DOUBLE: s = "double"; break;
433+ case TC_ERROR: s = "<error>";
434+ if (this==tPackage) s = "<package>";
435+ break;
436+ default: s = "unknown";
437+ }
438+
439+ return (id.length() > 0) ? s + " " + id : s;
440+ }
441+
442+ /**
443+ * Create a type string, given an identifier.
444+ */
445+ public String typeString(String id) {
446+ return typeString(id, false, true);
447+ }
448+
449+ /**
450+ * Convert to a String
451+ */
452+ public String toString() {
453+ return typeString("", false, true);
454+ }
455+}
java/pkg/sun/tools/java/mkfile+39−0
@@ -0,0 +1,39 @@
1+<../../../../../mkconfig
2+
3+TARG=\
4+ AmbiguousClass.dis\
5+ AmbiguousMember.dis\
6+ ArrayType.dis\
7+ BinaryAttribute.dis\
8+ BinaryClass.dis\
9+ BinaryCode.dis\
10+ BinaryConstantPool.dis\
11+ BinaryExceptionHandler.dis\
12+ BinaryMember.dis\
13+ ClassDeclaration.dis\
14+ ClassDefinition.dis\
15+ ClassFile.dis\
16+ ClassNotFound.dis\
17+ ClassPath.dis\
18+ ClassType.dis\
19+ CompilerError.dis\
20+ Constants.dis\
21+ Environment.dis\
22+ Identifier.dis\
23+ IdentifierToken.dis\
24+ Imports.dis\
25+ MemberDefinition.dis\
26+ MethodSet.dis\
27+ MethodType.dis\
28+ Package.dis\
29+ Parser.dis\
30+ ParserActions.dis\
31+ RuntimeConstants.dis\
32+ Scanner.dis\
33+ ScannerInputReader.dis\
34+ SyntaxError.dis\
35+ Type.dis\
36+
37+DISBIN=$ROOT/java/dis/java/java/sun/tools/java
38+
39+<$ROOT/mkfiles/mkjava