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
26package 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
37public
38class 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
26package sun.tools.java;
27
28import 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 */
38public
39class 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
26package 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 */
38public final
39class 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
26package sun.tools.java;
27
28import java.io.IOException;
29import java.io.DataInputStream;
30import 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 */
40public final
41class 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
26package sun.tools.java;
27
28import java.io.IOException;
29import java.io.DataInputStream;
30import java.io.OutputStream;
31import java.io.DataOutputStream;
32import java.io.ByteArrayInputStream;
33import java.util.Hashtable;
34import java.util.Vector;
35import 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 */
42public final
43class 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
27package sun.tools.java;
28
29import 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 */
36public 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
26package sun.tools.java;
27
28import java.io.IOException;
29import java.io.DataInputStream;
30import java.io.DataOutputStream;
31import java.util.Vector;
32import 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 */
42public final
43class 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
26package 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
36public 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
26package sun.tools.java;
27
28import sun.tools.tree.*;
29import java.util.Vector;
30import java.util.Hashtable;
31import java.io.IOException;
32import java.io.DataInputStream;
33import 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 */
42public final
43class 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
26package 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
56public final
57class 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
26package sun.tools.java;
27
28import java.util.*;
29import java.io.OutputStream;
30import java.io.PrintStream;
31import sun.tools.tree.Context;
32import sun.tools.tree.Vset;
33import sun.tools.tree.Expression;
34import sun.tools.tree.LocalMember;
35import 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 */
44public
45class 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
26package sun.tools.java;
27
28import java.io.File;
29import java.io.InputStream;
30import java.io.FileInputStream;
31import java.io.IOException;
32import 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 */
42public
43class 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
26package 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 */
36public
37class 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
26package sun.tools.java;
27
28import java.util.Enumeration;
29import java.util.Hashtable;
30import java.io.File;
31import java.io.IOException;
32import 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 */
42public
43class 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 */
286class 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
26package 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 */
38public final
39class 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
26package 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
36public
37class 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
27package 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
42public
43interface 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
26package sun.tools.java;
27
28import java.util.Stack;
29import java.io.IOException;
30import sun.tools.tree.Context;
31//JCOV
32import 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
54public 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
26package sun.tools.java;
27
28import java.util.Hashtable;
29import java.io.PrintStream;
30import 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
56public final
57class 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
26package 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
40public
41class 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
26package sun.tools.java;
27
28import java.util.Hashtable;
29import java.util.Vector;
30import java.util.Enumeration;
31import java.util.List;
32import java.util.Collections;
33import 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
53public
54class 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
487final
488class 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
26package sun.tools.java;
27
28import sun.tools.tree.Node;
29import sun.tools.tree.Vset;
30import sun.tools.tree.Expression;
31import sun.tools.tree.Statement;
32import sun.tools.tree.Context;
33import sun.tools.asm.Assembler;
34import java.io.PrintStream;
35import java.util.Vector;
36import java.util.Map;
37import 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 */
47public
48class 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
26package sun.tools.java;
27
28import 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
42public
43class 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
26package 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 */
38public final
39class 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
26package sun.tools.java;
27
28import java.util.Enumeration;
29import java.io.File;
30import 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 */
39public
40class 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
26package sun.tools.java;
27
28import sun.tools.tree.*;
29import java.io.IOException;
30import java.io.InputStream;
31import java.util.Enumeration;
32import 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
67public
68class 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
26package sun.tools.java;
27
28import 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 */
46public 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
26package 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 */
33public 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
26package sun.tools.java;
27
28import java.io.IOException;
29import java.io.InputStream;
30import 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
61public
62class 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
26package sun.tools.java;
27
28import java.io.IOException;
29import java.io.InputStream;
30import java.io.InputStreamReader;
31import java.io.BufferedReader;
32import java.io.FilterReader;
33import 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
49public
50class 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
26package 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
37public
38class 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
26package sun.tools.java;
27
28import 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 */
55public
56class 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
3TARG=\
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
37DISBIN=$ROOT/java/dis/java/java/sun/tools/java
38
39<$ROOT/mkfiles/mkjava