Sat, 08 Aug 2009 17:50:57 -0700
6868548: remove spurious ';' from after constant pool entries
Reviewed-by: ksrini
1 /*
2 * Copyright 2007-2008 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
26 package com.sun.tools.javap;
28 import com.sun.tools.classfile.ClassFile;
29 import com.sun.tools.classfile.ConstantPool;
30 import com.sun.tools.classfile.ConstantPoolException;
32 import static com.sun.tools.classfile.ConstantPool.*;
34 /*
35 * Write a constant pool entry.
36 *
37 * <p><b>This is NOT part of any API supported by Sun Microsystems. If
38 * you write code that depends on this, you do so at your own risk.
39 * This code and its internal interfaces are subject to change or
40 * deletion without notice.</b>
41 */
42 public class ConstantWriter extends BasicWriter {
43 public static ConstantWriter instance(Context context) {
44 ConstantWriter instance = context.get(ConstantWriter.class);
45 if (instance == null)
46 instance = new ConstantWriter(context);
47 return instance;
48 }
50 protected ConstantWriter(Context context) {
51 super(context);
52 context.put(ConstantWriter.class, this);
53 classWriter = ClassWriter.instance(context);
54 options = Options.instance(context);
55 }
57 protected void writeConstantPool() {
58 ConstantPool constant_pool = classWriter.getClassFile().constant_pool;
59 writeConstantPool(constant_pool);
60 }
62 protected void writeConstantPool(ConstantPool constant_pool) {
63 ConstantPool.Visitor<Integer, Void> v = new ConstantPool.Visitor<Integer,Void>() {
64 public Integer visitClass(CONSTANT_Class_info info, Void p) {
65 print("#" + info.name_index);
66 tab();
67 println("// " + stringValue(info));
68 return 1;
69 }
71 public Integer visitDouble(CONSTANT_Double_info info, Void p) {
72 println(stringValue(info));
73 return 2;
74 }
76 public Integer visitFieldref(CONSTANT_Fieldref_info info, Void p) {
77 print("#" + info.class_index + ".#" + info.name_and_type_index);
78 tab();
79 println("// " + stringValue(info));
80 return 1;
81 }
83 public Integer visitFloat(CONSTANT_Float_info info, Void p) {
84 println(stringValue(info));
85 return 1;
86 }
88 public Integer visitInteger(CONSTANT_Integer_info info, Void p) {
89 println(stringValue(info));
90 return 1;
91 }
93 public Integer visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
94 print("#" + info.class_index + ".#" + info.name_and_type_index);
95 tab();
96 println("// " + stringValue(info));
97 return 1;
98 }
100 public Integer visitLong(CONSTANT_Long_info info, Void p) {
101 println(stringValue(info));
102 return 2;
103 }
105 public Integer visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
106 print("#" + info.name_index + ":#" + info.type_index);
107 tab();
108 println("// " + stringValue(info));
109 return 1;
110 }
112 public Integer visitMethodref(CONSTANT_Methodref_info info, Void p) {
113 print("#" + info.class_index + ".#" + info.name_and_type_index);
114 tab();
115 println("// " + stringValue(info));
116 return 1;
117 }
119 public Integer visitString(CONSTANT_String_info info, Void p) {
120 print("#" + info.string_index);
121 tab();
122 println("// " + stringValue(info));
123 return 1;
124 }
126 public Integer visitUtf8(CONSTANT_Utf8_info info, Void p) {
127 println(stringValue(info));
128 return 1;
129 }
131 };
132 println("Constant pool:");
133 indent(+1);
134 int width = String.valueOf(constant_pool.size()).length() + 1;
135 int cpx = 1;
136 while (cpx < constant_pool.size()) {
137 print(String.format("const %" + width + "s", ("#" + cpx)));
138 try {
139 CPInfo cpInfo = constant_pool.get(cpx);
140 print(String.format(" = %-15s ", tagName(cpInfo.getTag())));
141 cpx += cpInfo.accept(v, null);
142 } catch (ConstantPool.InvalidIndex ex) {
143 // should not happen
144 }
145 }
146 indent(-1);
147 }
149 protected void write(int cpx) {
150 ClassFile classFile = classWriter.getClassFile();
151 if (cpx == 0) {
152 print("#0");
153 return;
154 }
156 CPInfo cpInfo;
157 try {
158 cpInfo = classFile.constant_pool.get(cpx);
159 } catch (ConstantPoolException e) {
160 print("#" + cpx);
161 return;
162 }
164 int tag = cpInfo.getTag();
165 switch (tag) {
166 case CONSTANT_Methodref:
167 case CONSTANT_InterfaceMethodref:
168 case CONSTANT_Fieldref:
169 // simplify references within this class
170 CPRefInfo ref = (CPRefInfo) cpInfo;
171 try {
172 if (ref.class_index == classFile.this_class)
173 cpInfo = classFile.constant_pool.get(ref.name_and_type_index);
174 } catch (ConstantPool.InvalidIndex e) {
175 // ignore, for now
176 }
177 }
178 print(tagName(tag) + " " + stringValue(cpInfo));
179 }
181 String tagName(int tag) {
182 switch (tag) {
183 case CONSTANT_Utf8:
184 return "Asciz";
185 case CONSTANT_Integer:
186 return "int";
187 case CONSTANT_Float:
188 return "float";
189 case CONSTANT_Long:
190 return "long";
191 case CONSTANT_Double:
192 return "double";
193 case CONSTANT_Class:
194 return "class";
195 case CONSTANT_String:
196 return "String";
197 case CONSTANT_Fieldref:
198 return "Field";
199 case CONSTANT_Methodref:
200 return "Method";
201 case CONSTANT_InterfaceMethodref:
202 return "InterfaceMethod";
203 case CONSTANT_NameAndType:
204 return "NameAndType";
205 default:
206 return "unknown tag";
207 }
208 }
210 String stringValue(int constant_pool_index) {
211 ClassFile classFile = classWriter.getClassFile();
212 try {
213 return stringValue(classFile.constant_pool.get(constant_pool_index));
214 } catch (ConstantPool.InvalidIndex e) {
215 return report(e);
216 }
217 }
219 String stringValue(CPInfo cpInfo) {
220 return stringValueVisitor.visit(cpInfo);
221 }
223 StringValueVisitor stringValueVisitor = new StringValueVisitor();
225 private class StringValueVisitor implements ConstantPool.Visitor<String, Void> {
226 public String visit(CPInfo info) {
227 return info.accept(this, null);
228 }
230 public String visitClass(CONSTANT_Class_info info, Void p) {
231 return getCheckedName(info);
232 }
234 String getCheckedName(CONSTANT_Class_info info) {
235 try {
236 return checkName(info.getName());
237 } catch (ConstantPoolException e) {
238 return report(e);
239 }
240 }
242 public String visitDouble(CONSTANT_Double_info info, Void p) {
243 return info.value + "d";
244 }
246 public String visitFieldref(CONSTANT_Fieldref_info info, Void p) {
247 return visitRef(info, p);
248 }
250 public String visitFloat(CONSTANT_Float_info info, Void p) {
251 return info.value + "f";
252 }
254 public String visitInteger(CONSTANT_Integer_info info, Void p) {
255 return String.valueOf(info.value);
256 }
258 public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, Void p) {
259 return visitRef(info, p);
260 }
262 public String visitLong(CONSTANT_Long_info info, Void p) {
263 return info.value + "l";
264 }
266 public String visitNameAndType(CONSTANT_NameAndType_info info, Void p) {
267 return getCheckedName(info) + ":" + getType(info);
268 }
270 String getCheckedName(CONSTANT_NameAndType_info info) {
271 try {
272 return checkName(info.getName());
273 } catch (ConstantPoolException e) {
274 return report(e);
275 }
276 }
278 String getType(CONSTANT_NameAndType_info info) {
279 try {
280 return info.getType();
281 } catch (ConstantPoolException e) {
282 return report(e);
283 }
284 }
286 public String visitMethodref(CONSTANT_Methodref_info info, Void p) {
287 return visitRef(info, p);
288 }
290 public String visitString(CONSTANT_String_info info, Void p) {
291 try {
292 ClassFile classFile = classWriter.getClassFile();
293 int string_index = info.string_index;
294 return stringValue(classFile.constant_pool.getUTF8Info(string_index));
295 } catch (ConstantPoolException e) {
296 return report(e);
297 }
298 }
300 public String visitUtf8(CONSTANT_Utf8_info info, Void p) {
301 String s = info.value;
302 StringBuilder sb = new StringBuilder();
303 for (int i = 0; i < s.length(); i++) {
304 char c = s.charAt(i);
305 switch (c) {
306 case '\t':
307 sb.append('\\').append('t');
308 break;
309 case '\n':
310 sb.append('\\').append('n');
311 break;
312 case '\r':
313 sb.append('\\').append('r');
314 break;
315 case '\"':
316 sb.append('\\').append('\"');
317 break;
318 default:
319 sb.append(c);
320 }
321 }
322 return sb.toString();
323 }
325 String visitRef(CPRefInfo info, Void p) {
326 String cn = getCheckedClassName(info);
327 String nat;
328 try {
329 nat = stringValue(info.getNameAndTypeInfo());
330 } catch (ConstantPoolException e) {
331 nat = report(e);
332 }
333 return cn + "." + nat;
334 }
336 String getCheckedClassName(CPRefInfo info) {
337 try {
338 return checkName(info.getClassName());
339 } catch (ConstantPoolException e) {
340 return report(e);
341 }
342 }
343 }
346 /* If name is a valid binary name, return it; otherwise quote it. */
347 private static String checkName(String name) {
348 if (name == null)
349 return "null";
351 int len = name.length();
352 if (len == 0)
353 return "\"\"";
355 int cc = '/';
356 int cp;
357 for (int k = 0; k < len; k += Character.charCount(cp)) {
358 cp = name.codePointAt(k);
359 if ((cc == '/' && !Character.isJavaIdentifierStart(cp))
360 || (cp != '/' && !Character.isJavaIdentifierPart(cp))) {
361 return "\"" + addEscapes(name) + "\"";
362 }
363 cc = cp;
364 }
366 return name;
367 }
369 /* If name requires escapes, put them in, so it can be a string body. */
370 private static String addEscapes(String name) {
371 String esc = "\\\"\n\t";
372 String rep = "\\\"nt";
373 StringBuilder buf = null;
374 int nextk = 0;
375 int len = name.length();
376 for (int k = 0; k < len; k++) {
377 char cp = name.charAt(k);
378 int n = esc.indexOf(cp);
379 if (n >= 0) {
380 if (buf == null)
381 buf = new StringBuilder(len * 2);
382 if (nextk < k)
383 buf.append(name, nextk, k);
384 buf.append('\\');
385 buf.append(rep.charAt(n));
386 nextk = k+1;
387 }
388 }
389 if (buf == null)
390 return name;
391 if (nextk < len)
392 buf.append(name, nextk, len);
393 return buf.toString();
394 }
396 private ClassWriter classWriter;
397 private Options options;
398 }