AttributeWriter.java revision 3294:9adfb22ff08f
1/* 2 * Copyright (c) 2007, 2016, 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 com.sun.tools.javap; 27 28import com.sun.tools.classfile.AccessFlags; 29import com.sun.tools.classfile.AnnotationDefault_attribute; 30import com.sun.tools.classfile.Attribute; 31import com.sun.tools.classfile.Attributes; 32import com.sun.tools.classfile.BootstrapMethods_attribute; 33import com.sun.tools.classfile.CharacterRangeTable_attribute; 34import com.sun.tools.classfile.CharacterRangeTable_attribute.Entry; 35import com.sun.tools.classfile.Code_attribute; 36import com.sun.tools.classfile.CompilationID_attribute; 37import com.sun.tools.classfile.ConcealedPackages_attribute; 38import com.sun.tools.classfile.ConstantPool; 39import com.sun.tools.classfile.ConstantPoolException; 40import com.sun.tools.classfile.ConstantValue_attribute; 41import com.sun.tools.classfile.DefaultAttribute; 42import com.sun.tools.classfile.Deprecated_attribute; 43import com.sun.tools.classfile.EnclosingMethod_attribute; 44import com.sun.tools.classfile.Exceptions_attribute; 45import com.sun.tools.classfile.Hashes_attribute; 46import com.sun.tools.classfile.InnerClasses_attribute; 47import com.sun.tools.classfile.InnerClasses_attribute.Info; 48import com.sun.tools.classfile.LineNumberTable_attribute; 49import com.sun.tools.classfile.LocalVariableTable_attribute; 50import com.sun.tools.classfile.LocalVariableTypeTable_attribute; 51import com.sun.tools.classfile.MainClass_attribute; 52import com.sun.tools.classfile.MethodParameters_attribute; 53import com.sun.tools.classfile.Module_attribute; 54import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute; 55import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute; 56import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute; 57import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute; 58import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute; 59import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute; 60import com.sun.tools.classfile.Signature_attribute; 61import com.sun.tools.classfile.SourceDebugExtension_attribute; 62import com.sun.tools.classfile.SourceFile_attribute; 63import com.sun.tools.classfile.SourceID_attribute; 64import com.sun.tools.classfile.StackMapTable_attribute; 65import com.sun.tools.classfile.StackMap_attribute; 66import com.sun.tools.classfile.Synthetic_attribute; 67import com.sun.tools.classfile.TargetPlatform_attribute; 68import com.sun.tools.classfile.Version_attribute; 69 70import static com.sun.tools.classfile.AccessFlags.*; 71 72import com.sun.tools.javac.util.Assert; 73import com.sun.tools.javac.util.StringUtils; 74 75/* 76 * A writer for writing Attributes as text. 77 * 78 * <p><b>This is NOT part of any supported API. 79 * If you write code that depends on this, you do so at your own risk. 80 * This code and its internal interfaces are subject to change or 81 * deletion without notice.</b> 82 */ 83public class AttributeWriter extends BasicWriter 84 implements Attribute.Visitor<Void,Void> 85{ 86 public static AttributeWriter instance(Context context) { 87 AttributeWriter instance = context.get(AttributeWriter.class); 88 if (instance == null) 89 instance = new AttributeWriter(context); 90 return instance; 91 } 92 93 protected AttributeWriter(Context context) { 94 super(context); 95 context.put(AttributeWriter.class, this); 96 annotationWriter = AnnotationWriter.instance(context); 97 codeWriter = CodeWriter.instance(context); 98 constantWriter = ConstantWriter.instance(context); 99 options = Options.instance(context); 100 } 101 102 public void write(Object owner, Attribute attr, ConstantPool constant_pool) { 103 if (attr != null) { 104 Assert.checkNonNull(constant_pool); 105 Assert.checkNonNull(owner); 106 this.constant_pool = constant_pool; 107 this.owner = owner; 108 attr.accept(this, null); 109 } 110 } 111 112 public void write(Object owner, Attributes attrs, ConstantPool constant_pool) { 113 if (attrs != null) { 114 Assert.checkNonNull(constant_pool); 115 Assert.checkNonNull(owner); 116 this.constant_pool = constant_pool; 117 this.owner = owner; 118 for (Attribute attr: attrs) 119 attr.accept(this, null); 120 } 121 } 122 123 @Override 124 public Void visitDefault(DefaultAttribute attr, Void ignore) { 125 if (attr.reason != null) { 126 report(attr.reason); 127 } 128 byte[] data = attr.info; 129 int i = 0; 130 int j = 0; 131 print(" "); 132 try { 133 print(attr.getName(constant_pool)); 134 } catch (ConstantPoolException e) { 135 report(e); 136 print("attribute name = #" + attr.attribute_name_index); 137 } 138 print(": "); 139 println("length = 0x" + toHex(attr.info.length)); 140 141 print(" "); 142 143 while (i < data.length) { 144 print(toHex(data[i], 2)); 145 146 j++; 147 if (j == 16) { 148 println(); 149 print(" "); 150 j = 0; 151 } else { 152 print(" "); 153 } 154 i++; 155 } 156 println(); 157 return null; 158 } 159 160 @Override 161 public Void visitAnnotationDefault(AnnotationDefault_attribute attr, Void ignore) { 162 println("AnnotationDefault:"); 163 indent(+1); 164 print("default_value: "); 165 annotationWriter.write(attr.default_value); 166 indent(-1); 167 return null; 168 } 169 170 @Override 171 public Void visitBootstrapMethods(BootstrapMethods_attribute attr, Void p) { 172 println(Attribute.BootstrapMethods + ":"); 173 for (int i = 0; i < attr.bootstrap_method_specifiers.length ; i++) { 174 BootstrapMethods_attribute.BootstrapMethodSpecifier bsm = attr.bootstrap_method_specifiers[i]; 175 indent(+1); 176 print(i + ": #" + bsm.bootstrap_method_ref + " "); 177 println(constantWriter.stringValue(bsm.bootstrap_method_ref)); 178 indent(+1); 179 println("Method arguments:"); 180 indent(+1); 181 for (int j = 0; j < bsm.bootstrap_arguments.length; j++) { 182 print("#" + bsm.bootstrap_arguments[j] + " "); 183 println(constantWriter.stringValue(bsm.bootstrap_arguments[j])); 184 } 185 indent(-3); 186 } 187 return null; 188 } 189 190 @Override 191 public Void visitCharacterRangeTable(CharacterRangeTable_attribute attr, Void ignore) { 192 println("CharacterRangeTable:"); 193 indent(+1); 194 for (Entry e : attr.character_range_table) { 195 print(String.format(" %2d, %2d, %6x, %6x, %4x", 196 e.start_pc, e.end_pc, 197 e.character_range_start, e.character_range_end, 198 e.flags)); 199 tab(); 200 print(String.format("// %2d, %2d, %4d:%02d, %4d:%02d", 201 e.start_pc, e.end_pc, 202 (e.character_range_start >> 10), (e.character_range_start & 0x3ff), 203 (e.character_range_end >> 10), (e.character_range_end & 0x3ff))); 204 if ((e.flags & CharacterRangeTable_attribute.CRT_STATEMENT) != 0) 205 print(", statement"); 206 if ((e.flags & CharacterRangeTable_attribute.CRT_BLOCK) != 0) 207 print(", block"); 208 if ((e.flags & CharacterRangeTable_attribute.CRT_ASSIGNMENT) != 0) 209 print(", assignment"); 210 if ((e.flags & CharacterRangeTable_attribute.CRT_FLOW_CONTROLLER) != 0) 211 print(", flow-controller"); 212 if ((e.flags & CharacterRangeTable_attribute.CRT_FLOW_TARGET) != 0) 213 print(", flow-target"); 214 if ((e.flags & CharacterRangeTable_attribute.CRT_INVOKE) != 0) 215 print(", invoke"); 216 if ((e.flags & CharacterRangeTable_attribute.CRT_CREATE) != 0) 217 print(", create"); 218 if ((e.flags & CharacterRangeTable_attribute.CRT_BRANCH_TRUE) != 0) 219 print(", branch-true"); 220 if ((e.flags & CharacterRangeTable_attribute.CRT_BRANCH_FALSE) != 0) 221 print(", branch-false"); 222 println(); 223 } 224 indent(-1); 225 return null; 226 } 227 228 @Override 229 public Void visitCode(Code_attribute attr, Void ignore) { 230 codeWriter.write(attr, constant_pool); 231 return null; 232 } 233 234 @Override 235 public Void visitCompilationID(CompilationID_attribute attr, Void ignore) { 236 constantWriter.write(attr.compilationID_index); 237 return null; 238 } 239 240 private String getJavaPackage(ConcealedPackages_attribute attr, int index) { 241 try { 242 return getJavaName(attr.getPackage(index, constant_pool)); 243 } catch (ConstantPoolException e) { 244 return report(e); 245 } 246 } 247 248 @Override 249 public Void visitConcealedPackages(ConcealedPackages_attribute attr, Void ignore) { 250 println("ConcealedPackages: "); 251 indent(+1); 252 for (int i = 0; i < attr.packages_count; i++) { 253 print("#" + attr.packages_index[i]); 254 tab(); 255 println("// " + getJavaPackage(attr, i)); 256 } 257 indent(-1); 258 return null; 259 } 260 261 @Override 262 public Void visitConstantValue(ConstantValue_attribute attr, Void ignore) { 263 print("ConstantValue: "); 264 constantWriter.write(attr.constantvalue_index); 265 println(); 266 return null; 267 } 268 269 @Override 270 public Void visitDeprecated(Deprecated_attribute attr, Void ignore) { 271 println("Deprecated: true"); 272 return null; 273 } 274 275 @Override 276 public Void visitEnclosingMethod(EnclosingMethod_attribute attr, Void ignore) { 277 print("EnclosingMethod: #" + attr.class_index + ".#" + attr.method_index); 278 tab(); 279 print("// " + getJavaClassName(attr)); 280 if (attr.method_index != 0) 281 print("." + getMethodName(attr)); 282 println(); 283 return null; 284 } 285 286 private String getJavaClassName(EnclosingMethod_attribute a) { 287 try { 288 return getJavaName(a.getClassName(constant_pool)); 289 } catch (ConstantPoolException e) { 290 return report(e); 291 } 292 } 293 294 private String getMethodName(EnclosingMethod_attribute a) { 295 try { 296 return a.getMethodName(constant_pool); 297 } catch (ConstantPoolException e) { 298 return report(e); 299 } 300 } 301 302 @Override 303 public Void visitExceptions(Exceptions_attribute attr, Void ignore) { 304 println("Exceptions:"); 305 indent(+1); 306 print("throws "); 307 for (int i = 0; i < attr.number_of_exceptions; i++) { 308 if (i > 0) 309 print(", "); 310 print(getJavaException(attr, i)); 311 } 312 println(); 313 indent(-1); 314 return null; 315 } 316 317 private String getJavaException(Exceptions_attribute attr, int index) { 318 try { 319 return getJavaName(attr.getException(index, constant_pool)); 320 } catch (ConstantPoolException e) { 321 return report(e); 322 } 323 } 324 325 @Override 326 public Void visitHashes(Hashes_attribute attr, Void ignore) { 327 println("Hashes:"); 328 indent(+1); 329 print("algorithm #" + attr.algorithm_index); 330 tab(); 331 println("// " + getAlgorithm(attr)); 332 for (Hashes_attribute.Entry e : attr.hashes_table) { 333 print("#" + e.requires_index + ", #" + e.hash_index); 334 tab(); 335 println("// " + getRequires(e) + ": " + getHash(e)); 336 } 337 indent(-1); 338 return null; 339 } 340 341 private String getAlgorithm(Hashes_attribute attr) { 342 try { 343 return constant_pool.getUTF8Value(attr.algorithm_index); 344 } catch (ConstantPoolException e) { 345 return report(e); 346 } 347 } 348 349 private String getRequires(Hashes_attribute.Entry entry) { 350 try { 351 return constant_pool.getUTF8Value(entry.requires_index); 352 } catch (ConstantPoolException e) { 353 return report(e); 354 } 355 } 356 357 private String getHash(Hashes_attribute.Entry entry) { 358 try { 359 return constant_pool.getUTF8Value(entry.hash_index); 360 } catch (ConstantPoolException e) { 361 return report(e); 362 } 363 } 364 365 @Override 366 public Void visitInnerClasses(InnerClasses_attribute attr, Void ignore) { 367 boolean first = true; 368 for (Info info : attr.classes) { 369 //access 370 AccessFlags access_flags = info.inner_class_access_flags; 371 if (options.checkAccess(access_flags)) { 372 if (first) { 373 writeInnerClassHeader(); 374 first = false; 375 } 376 for (String name: access_flags.getInnerClassModifiers()) 377 print(name + " "); 378 if (info.inner_name_index != 0) { 379 print("#" + info.inner_name_index + "= "); 380 } 381 print("#" + info.inner_class_info_index); 382 if (info.outer_class_info_index != 0) { 383 print(" of #" + info.outer_class_info_index); 384 } 385 print(";"); 386 tab(); 387 print("// "); 388 if (info.inner_name_index != 0) { 389 print(getInnerName(constant_pool, info) + "="); 390 } 391 constantWriter.write(info.inner_class_info_index); 392 if (info.outer_class_info_index != 0) { 393 print(" of "); 394 constantWriter.write(info.outer_class_info_index); 395 } 396 println(); 397 } 398 } 399 if (!first) 400 indent(-1); 401 return null; 402 } 403 404 String getInnerName(ConstantPool constant_pool, InnerClasses_attribute.Info info) { 405 try { 406 return info.getInnerName(constant_pool); 407 } catch (ConstantPoolException e) { 408 return report(e); 409 } 410 } 411 412 private void writeInnerClassHeader() { 413 println("InnerClasses:"); 414 indent(+1); 415 } 416 417 @Override 418 public Void visitLineNumberTable(LineNumberTable_attribute attr, Void ignore) { 419 println("LineNumberTable:"); 420 indent(+1); 421 for (LineNumberTable_attribute.Entry entry: attr.line_number_table) { 422 println("line " + entry.line_number + ": " + entry.start_pc); 423 } 424 indent(-1); 425 return null; 426 } 427 428 @Override 429 public Void visitLocalVariableTable(LocalVariableTable_attribute attr, Void ignore) { 430 println("LocalVariableTable:"); 431 indent(+1); 432 println("Start Length Slot Name Signature"); 433 for (LocalVariableTable_attribute.Entry entry : attr.local_variable_table) { 434 println(String.format("%5d %7d %5d %5s %s", 435 entry.start_pc, entry.length, entry.index, 436 constantWriter.stringValue(entry.name_index), 437 constantWriter.stringValue(entry.descriptor_index))); 438 } 439 indent(-1); 440 return null; 441 } 442 443 @Override 444 public Void visitLocalVariableTypeTable(LocalVariableTypeTable_attribute attr, Void ignore) { 445 println("LocalVariableTypeTable:"); 446 indent(+1); 447 println("Start Length Slot Name Signature"); 448 for (LocalVariableTypeTable_attribute.Entry entry : attr.local_variable_table) { 449 println(String.format("%5d %7d %5d %5s %s", 450 entry.start_pc, entry.length, entry.index, 451 constantWriter.stringValue(entry.name_index), 452 constantWriter.stringValue(entry.signature_index))); 453 } 454 indent(-1); 455 return null; 456 } 457 458 @Override 459 public Void visitMainClass(MainClass_attribute attr, Void ignore) { 460 print("MainClass: #" + attr.main_class_index); 461 tab(); 462 print("// " + getJavaClassName(attr)); 463 println(); 464 return null; 465 } 466 467 private String getJavaClassName(MainClass_attribute a) { 468 try { 469 return getJavaName(a.getMainClassName(constant_pool)); 470 } catch (ConstantPoolException e) { 471 return report(e); 472 } 473 } 474 475 private static final String format = "%-31s%s"; 476 477 @Override 478 public Void visitMethodParameters(MethodParameters_attribute attr, 479 Void ignore) { 480 481 final String header = String.format(format, "Name", "Flags"); 482 println("MethodParameters:"); 483 indent(+1); 484 println(header); 485 for (MethodParameters_attribute.Entry entry : 486 attr.method_parameter_table) { 487 String namestr = 488 entry.name_index != 0 ? 489 constantWriter.stringValue(entry.name_index) : "<no name>"; 490 String flagstr = 491 (0 != (entry.flags & ACC_FINAL) ? "final " : "") + 492 (0 != (entry.flags & ACC_MANDATED) ? "mandated " : "") + 493 (0 != (entry.flags & ACC_SYNTHETIC) ? "synthetic" : ""); 494 println(String.format(format, namestr, flagstr)); 495 } 496 indent(-1); 497 return null; 498 } 499 500 @Override 501 public Void visitModule(Module_attribute attr, Void ignore) { 502 println("Module:"); 503 indent(+1); 504 printRequiresTable(attr); 505 printExportsTable(attr); 506 printUsesTable(attr); 507 printProvidesTable(attr); 508 indent(-1); 509 return null; 510 } 511 512 protected void printRequiresTable(Module_attribute attr) { 513 Module_attribute.RequiresEntry[] entries = attr.requires; 514 println(entries.length + "\t// " + "requires"); 515 indent(+1); 516 for (Module_attribute.RequiresEntry e: entries) { 517 print("#" + e.requires_index + "," + 518 String.format("%x", e.requires_flags)+ "\t// requires"); 519 if ((e.requires_flags & Module_attribute.ACC_PUBLIC) != 0) 520 print(" public"); 521 if ((e.requires_flags & Module_attribute.ACC_SYNTHETIC) != 0) 522 print(" synthetic"); 523 if ((e.requires_flags & Module_attribute.ACC_MANDATED) != 0) 524 print(" mandated"); 525 println(" " + constantWriter.stringValue(e.requires_index)); 526 } 527 indent(-1); 528 } 529 530 protected void printExportsTable(Module_attribute attr) { 531 Module_attribute.ExportsEntry[] entries = attr.exports; 532 println(entries.length + "\t// " + "exports"); 533 indent(+1); 534 for (Module_attribute.ExportsEntry e: entries) { 535 print("#" + e.exports_index + "\t// exports"); 536 print(" " + constantWriter.stringValue(e.exports_index)); 537 if (e.exports_to_index.length == 0) { 538 println(); 539 } else { 540 println(" to ... " + e.exports_to_index.length); 541 indent(+1); 542 for (int to: e.exports_to_index) { 543 println("#" + to + "\t// ... to " + constantWriter.stringValue(to)); 544 } 545 indent(-1); 546 } 547 } 548 indent(-1); 549 } 550 551 protected void printUsesTable(Module_attribute attr) { 552 int[] entries = attr.uses_index; 553 println(entries.length + "\t// " + "uses services"); 554 indent(+1); 555 for (int e: entries) { 556 println("#" + e + "\t// uses " + constantWriter.stringValue(e)); 557 } 558 indent(-1); 559 } 560 561 protected void printProvidesTable(Module_attribute attr) { 562 Module_attribute.ProvidesEntry[] entries = attr.provides; 563 println(entries.length + "\t// " + "provides services"); 564 indent(+1); 565 for (Module_attribute.ProvidesEntry e: entries) { 566 print("#" + e.provides_index + ",#" + 567 e.with_index + "\t// provides "); 568 print(constantWriter.stringValue(e.provides_index)); 569 print (" with "); 570 println(constantWriter.stringValue(e.with_index)); 571 } 572 indent(-1); 573 } 574 575 @Override 576 public Void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations_attribute attr, Void ignore) { 577 println("RuntimeVisibleAnnotations:"); 578 indent(+1); 579 for (int i = 0; i < attr.annotations.length; i++) { 580 print(i + ": "); 581 annotationWriter.write(attr.annotations[i]); 582 println(); 583 } 584 indent(-1); 585 return null; 586 } 587 588 @Override 589 public Void visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, Void ignore) { 590 println("RuntimeInvisibleAnnotations:"); 591 indent(+1); 592 for (int i = 0; i < attr.annotations.length; i++) { 593 print(i + ": "); 594 annotationWriter.write(attr.annotations[i]); 595 println(); 596 } 597 indent(-1); 598 return null; 599 } 600 601 @Override 602 public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore) { 603 println("RuntimeVisibleTypeAnnotations:"); 604 indent(+1); 605 for (int i = 0; i < attr.annotations.length; i++) { 606 print(i + ": "); 607 annotationWriter.write(attr.annotations[i]); 608 println(); 609 } 610 indent(-1); 611 return null; 612 } 613 614 @Override 615 public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore) { 616 println("RuntimeInvisibleTypeAnnotations:"); 617 indent(+1); 618 for (int i = 0; i < attr.annotations.length; i++) { 619 print(i + ": "); 620 annotationWriter.write(attr.annotations[i]); 621 println(); 622 } 623 indent(-1); 624 return null; 625 } 626 627 @Override 628 public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) { 629 println("RuntimeVisibleParameterAnnotations:"); 630 indent(+1); 631 for (int param = 0; param < attr.parameter_annotations.length; param++) { 632 println("parameter " + param + ": "); 633 indent(+1); 634 for (int i = 0; i < attr.parameter_annotations[param].length; i++) { 635 print(i + ": "); 636 annotationWriter.write(attr.parameter_annotations[param][i]); 637 println(); 638 } 639 indent(-1); 640 } 641 indent(-1); 642 return null; 643 } 644 645 @Override 646 public Void visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, Void ignore) { 647 println("RuntimeInvisibleParameterAnnotations:"); 648 indent(+1); 649 for (int param = 0; param < attr.parameter_annotations.length; param++) { 650 println(param + ": "); 651 indent(+1); 652 for (int i = 0; i < attr.parameter_annotations[param].length; i++) { 653 print(i + ": "); 654 annotationWriter.write(attr.parameter_annotations[param][i]); 655 println(); 656 } 657 indent(-1); 658 } 659 indent(-1); 660 return null; 661 } 662 663 @Override 664 public Void visitSignature(Signature_attribute attr, Void ignore) { 665 print("Signature: #" + attr.signature_index); 666 tab(); 667 println("// " + getSignature(attr)); 668 return null; 669 } 670 671 String getSignature(Signature_attribute info) { 672 try { 673 return info.getSignature(constant_pool); 674 } catch (ConstantPoolException e) { 675 return report(e); 676 } 677 } 678 679 @Override 680 public Void visitSourceDebugExtension(SourceDebugExtension_attribute attr, Void ignore) { 681 println("SourceDebugExtension:"); 682 indent(+1); 683 for (String s: attr.getValue().split("[\r\n]+")) { 684 println(s); 685 } 686 indent(-1); 687 return null; 688 } 689 690 @Override 691 public Void visitSourceFile(SourceFile_attribute attr, Void ignore) { 692 println("SourceFile: \"" + getSourceFile(attr) + "\""); 693 return null; 694 } 695 696 private String getSourceFile(SourceFile_attribute attr) { 697 try { 698 return attr.getSourceFile(constant_pool); 699 } catch (ConstantPoolException e) { 700 return report(e); 701 } 702 } 703 704 @Override 705 public Void visitSourceID(SourceID_attribute attr, Void ignore) { 706 constantWriter.write(attr.sourceID_index); 707 return null; 708 } 709 710 @Override 711 public Void visitStackMap(StackMap_attribute attr, Void ignore) { 712 println("StackMap: number_of_entries = " + attr.number_of_entries); 713 indent(+1); 714 StackMapTableWriter w = new StackMapTableWriter(); 715 for (StackMapTable_attribute.stack_map_frame entry : attr.entries) { 716 w.write(entry); 717 } 718 indent(-1); 719 return null; 720 } 721 722 @Override 723 public Void visitStackMapTable(StackMapTable_attribute attr, Void ignore) { 724 println("StackMapTable: number_of_entries = " + attr.number_of_entries); 725 indent(+1); 726 StackMapTableWriter w = new StackMapTableWriter(); 727 for (StackMapTable_attribute.stack_map_frame entry : attr.entries) { 728 w.write(entry); 729 } 730 indent(-1); 731 return null; 732 } 733 734 class StackMapTableWriter // also handles CLDC StackMap attributes 735 implements StackMapTable_attribute.stack_map_frame.Visitor<Void,Void> { 736 public void write(StackMapTable_attribute.stack_map_frame frame) { 737 frame.accept(this, null); 738 } 739 740 @Override 741 public Void visit_same_frame(StackMapTable_attribute.same_frame frame, Void p) { 742 printHeader(frame, "/* same */"); 743 return null; 744 } 745 746 @Override 747 public Void visit_same_locals_1_stack_item_frame(StackMapTable_attribute.same_locals_1_stack_item_frame frame, Void p) { 748 printHeader(frame, "/* same_locals_1_stack_item */"); 749 indent(+1); 750 printMap("stack", frame.stack); 751 indent(-1); 752 return null; 753 } 754 755 @Override 756 public Void visit_same_locals_1_stack_item_frame_extended(StackMapTable_attribute.same_locals_1_stack_item_frame_extended frame, Void p) { 757 printHeader(frame, "/* same_locals_1_stack_item_frame_extended */"); 758 indent(+1); 759 println("offset_delta = " + frame.offset_delta); 760 printMap("stack", frame.stack); 761 indent(-1); 762 return null; 763 } 764 765 @Override 766 public Void visit_chop_frame(StackMapTable_attribute.chop_frame frame, Void p) { 767 printHeader(frame, "/* chop */"); 768 indent(+1); 769 println("offset_delta = " + frame.offset_delta); 770 indent(-1); 771 return null; 772 } 773 774 @Override 775 public Void visit_same_frame_extended(StackMapTable_attribute.same_frame_extended frame, Void p) { 776 printHeader(frame, "/* same_frame_extended */"); 777 indent(+1); 778 println("offset_delta = " + frame.offset_delta); 779 indent(-1); 780 return null; 781 } 782 783 @Override 784 public Void visit_append_frame(StackMapTable_attribute.append_frame frame, Void p) { 785 printHeader(frame, "/* append */"); 786 indent(+1); 787 println("offset_delta = " + frame.offset_delta); 788 printMap("locals", frame.locals); 789 indent(-1); 790 return null; 791 } 792 793 @Override 794 public Void visit_full_frame(StackMapTable_attribute.full_frame frame, Void p) { 795 if (frame instanceof StackMap_attribute.stack_map_frame) { 796 printHeader(frame, "offset = " + frame.offset_delta); 797 indent(+1); 798 } else { 799 printHeader(frame, "/* full_frame */"); 800 indent(+1); 801 println("offset_delta = " + frame.offset_delta); 802 } 803 printMap("locals", frame.locals); 804 printMap("stack", frame.stack); 805 indent(-1); 806 return null; 807 } 808 809 void printHeader(StackMapTable_attribute.stack_map_frame frame, String extra) { 810 print("frame_type = " + frame.frame_type + " "); 811 println(extra); 812 } 813 814 void printMap(String name, StackMapTable_attribute.verification_type_info[] map) { 815 print(name + " = ["); 816 for (int i = 0; i < map.length; i++) { 817 StackMapTable_attribute.verification_type_info info = map[i]; 818 int tag = info.tag; 819 switch (tag) { 820 case StackMapTable_attribute.verification_type_info.ITEM_Object: 821 print(" "); 822 constantWriter.write(((StackMapTable_attribute.Object_variable_info) info).cpool_index); 823 break; 824 case StackMapTable_attribute.verification_type_info.ITEM_Uninitialized: 825 print(" " + mapTypeName(tag)); 826 print(" " + ((StackMapTable_attribute.Uninitialized_variable_info) info).offset); 827 break; 828 default: 829 print(" " + mapTypeName(tag)); 830 } 831 print(i == (map.length - 1) ? " " : ","); 832 } 833 println("]"); 834 } 835 836 String mapTypeName(int tag) { 837 switch (tag) { 838 case StackMapTable_attribute.verification_type_info.ITEM_Top: 839 return "top"; 840 841 case StackMapTable_attribute.verification_type_info.ITEM_Integer: 842 return "int"; 843 844 case StackMapTable_attribute.verification_type_info.ITEM_Float: 845 return "float"; 846 847 case StackMapTable_attribute.verification_type_info.ITEM_Long: 848 return "long"; 849 850 case StackMapTable_attribute.verification_type_info.ITEM_Double: 851 return "double"; 852 853 case StackMapTable_attribute.verification_type_info.ITEM_Null: 854 return "null"; 855 856 case StackMapTable_attribute.verification_type_info.ITEM_UninitializedThis: 857 return "this"; 858 859 case StackMapTable_attribute.verification_type_info.ITEM_Object: 860 return "CP"; 861 862 case StackMapTable_attribute.verification_type_info.ITEM_Uninitialized: 863 return "uninitialized"; 864 865 default: 866 report("unrecognized verification_type_info tag: " + tag); 867 return "[tag:" + tag + "]"; 868 } 869 } 870 } 871 872 @Override 873 public Void visitSynthetic(Synthetic_attribute attr, Void ignore) { 874 println("Synthetic: true"); 875 return null; 876 } 877 878 @Override 879 public Void visitTargetPlatform(TargetPlatform_attribute attr, Void ignore) { 880 println("TargetPlatform:"); 881 indent(+1); 882 print("os_name: #" + attr.os_name_index); 883 if (attr.os_name_index != 0) { 884 tab(); 885 print("// " + getOSName(attr)); 886 } 887 println(); 888 print("os_arch: #" + attr.os_arch_index); 889 if (attr.os_arch_index != 0) { 890 tab(); 891 print("// " + getOSArch(attr)); 892 } 893 println(); 894 print("os_version: #" + attr.os_version_index); 895 if (attr.os_version_index != 0) { 896 tab(); 897 print("// " + getOSVersion(attr)); 898 } 899 println(); 900 indent(-1); 901 return null; 902 } 903 904 private String getOSName(TargetPlatform_attribute attr) { 905 try { 906 return constant_pool.getUTF8Value(attr.os_name_index); 907 } catch (ConstantPoolException e) { 908 return report(e); 909 } 910 } 911 912 private String getOSArch(TargetPlatform_attribute attr) { 913 try { 914 return constant_pool.getUTF8Value(attr.os_arch_index); 915 } catch (ConstantPoolException e) { 916 return report(e); 917 } 918 } 919 920 private String getOSVersion(TargetPlatform_attribute attr) { 921 try { 922 return constant_pool.getUTF8Value(attr.os_version_index); 923 } catch (ConstantPoolException e) { 924 return report(e); 925 } 926 } 927 928 @Override 929 public Void visitVersion(Version_attribute attr, Void ignore) { 930 print("Version: #" + attr.version_index); 931 indent(+1); 932 tab(); 933 println("// " + getVersion(attr)); 934 indent(-1); 935 return null; 936 } 937 938 private String getVersion(Version_attribute attr) { 939 try { 940 return constant_pool.getUTF8Value(attr.version_index); 941 } catch (ConstantPoolException e) { 942 return report(e); 943 } 944 } 945 946 static String getJavaName(String name) { 947 return name.replace('/', '.'); 948 } 949 950 String toHex(byte b, int w) { 951 return toHex(b & 0xff, w); 952 } 953 954 static String toHex(int i) { 955 return StringUtils.toUpperCase(Integer.toString(i, 16)); 956 } 957 958 static String toHex(int i, int w) { 959 String s = StringUtils.toUpperCase(Integer.toHexString(i)); 960 while (s.length() < w) 961 s = "0" + s; 962 return StringUtils.toUpperCase(s); 963 } 964 965 private final AnnotationWriter annotationWriter; 966 private final CodeWriter codeWriter; 967 private final ConstantWriter constantWriter; 968 private final Options options; 969 970 private ConstantPool constant_pool; 971 private Object owner; 972} 973