001    /*
002     * Copyright 2002-2008 Sun Microsystems, Inc.  All Rights Reserved.
003     * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004     *
005     * This code is free software; you can redistribute it and/or modify it
006     * under the terms of the GNU General Public License version 2 only, as
007     * published by the Free Software Foundation.  Sun designates this
008     * particular file as subject to the "Classpath" exception as provided
009     * by Sun in the LICENSE file that accompanied this code.
010     *
011     * This code is distributed in the hope that it will be useful, but WITHOUT
012     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013     * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014     * version 2 for more details (a copy is included in the LICENSE file that
015     * accompanied this code).
016     *
017     * You should have received a copy of the GNU General Public License version
018     * 2 along with this work; if not, write to the Free Software Foundation,
019     * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020     *
021     * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022     * CA 95054 USA or visit www.sun.com if you need additional information or
023     * have any questions.
024     */
025    
026    
027    package sun.tools.javap;
028    
029    import java.util.*;
030    import java.io.*;
031    
032    import static sun.tools.javap.RuntimeConstants.*;
033    
034    /**
035     * Program to print information about class files
036     *
037     * @author  Sucheta Dambalkar
038     */
039    public class JavapPrinter {
040        JavapEnvironment env;
041        ClassData cls;
042        byte[] code;
043        String lP= "";
044        PrintWriter out;
045    
046        public JavapPrinter(InputStream cname, PrintWriter out, JavapEnvironment env){
047            this.out = out;
048            this.cls =  new ClassData(cname);
049            this.env = env;
050        }
051    
052        /**
053         *  Entry point to print class file information.
054         */
055        public void print(){
056            printclassHeader();
057            printfields();
058            printMethods();
059            printend();
060        }
061    
062        /**
063         * Print a description of the class (not members).
064         */
065        public void printclassHeader(){
066            String srcName="";
067            if ((srcName = cls.getSourceName()) != "null") // requires debug info
068                out.println("Compiled from " + javaclassname(srcName));
069    
070            if(cls.isInterface())   {
071                // The only useful access modifier of an interface is
072                // public; interfaces are always marked as abstract and
073                // cannot be final.
074                out.print((cls.isPublic()?"public ":"") +
075                          "interface "+ javaclassname(cls.getClassName()));
076            }
077            else if(cls.isClass()) {
078                String []accflags =  cls.getAccess();
079                printAccess(accflags);
080                out.print("class "+ javaclassname(cls.getClassName()));
081    
082                if(cls.getSuperClassName() != null){
083                    out.print(" extends " + javaclassname(cls.getSuperClassName()));
084                }
085            }
086    
087            String []interfacelist =  cls.getSuperInterfaces();
088            if(interfacelist.length > 0){
089                if(cls.isClass()) {
090                    out.print(" implements ");
091                }
092                else if(cls.isInterface()){
093                    out.print(" extends ");
094                }
095    
096                for(int j = 0; j < interfacelist.length; j++){
097                    out.print(javaclassname(interfacelist[j]));
098    
099                    if((j+1) < interfacelist.length) {
100                        out.print(",");
101                    }
102                }
103            }
104    
105            // Print class attribute information.
106            if((env.showallAttr) || (env.showVerbose)){
107                printClassAttributes();
108            }
109            // Print verbose output.
110            if(env.showVerbose){
111                printverbosecls();
112            }
113            out.println("{");
114        }
115    
116        /**
117         * Print verbose output.
118         */
119        public void printverbosecls(){
120            out.println("  minor version: "+cls.getMinor_version());
121            out.println("  major version: "+cls.getMajor_version());
122            out.println("  Constant pool:");
123            printcp();
124            env.showallAttr = true;
125        }
126    
127        /**
128         * Print class attribute information.
129         */
130        public void printClassAttributes(){
131            out.println();
132            AttrData[] clsattrs = cls.getAttributes();
133            for(int i = 0; i < clsattrs.length; i++){
134                String clsattrname = clsattrs[i].getAttrName();
135                if(clsattrname.equals("SourceFile")){
136                    out.println("  SourceFile: "+ cls.getSourceName());
137                }else if(clsattrname.equals("InnerClasses")){
138                    printInnerClasses();
139                }else {
140                    printAttrData(clsattrs[i]);
141                }
142            }
143        }
144    
145        /**
146         * Print the fields
147         */
148        public void printfields(){
149            FieldData[] fields = cls.getFields();
150            for(int f = 0; f < fields.length; f++){
151                String[] accflags = fields[f].getAccess();
152                if(checkAccess(accflags)){
153                    if(!(env. showLineAndLocal || env.showDisassembled || env.showVerbose
154                         ||  env.showInternalSigs || env.showallAttr)){
155                        out.print("    ");
156                    }
157                    printAccess(accflags);
158                    out.println(fields[f].getType()+" " +fields[f].getName()+";");
159                    if (env.showInternalSigs) {
160                        out.println("  Signature: " + (fields[f].getInternalSig()));
161                    }
162    
163                    // print field attribute information.
164                    if (env.showallAttr){
165                        printFieldAttributes(fields[f]);
166    
167                    }
168                    if((env.showDisassembled) || (env.showLineAndLocal)){
169                        out.println();
170                    }
171                }
172            }
173        }
174    
175    
176        /* print field attribute information. */
177        public void printFieldAttributes(FieldData field){
178            Vector<?> fieldattrs = field.getAttributes();
179            for(int j = 0; j < fieldattrs.size(); j++){
180                String fieldattrname = ((AttrData)fieldattrs.elementAt(j)).getAttrName();
181                if(fieldattrname.equals("ConstantValue")){
182                    printConstantValue(field);
183                }else if (fieldattrname.equals("Deprecated")){
184                    out.println("Deprecated: "+ field.isDeprecated());
185                }else if (fieldattrname.equals("Synthetic")){
186                    out.println("  Synthetic: "+ field.isSynthetic());
187                }else {
188                    printAttrData((AttrData)fieldattrs.elementAt(j));
189                }
190            }
191            out.println();
192        }
193    
194        /**
195         * Print the methods
196         */
197        public void printMethods(){
198            MethodData[] methods = cls.getMethods();
199            for(int m = 0; m < methods.length; m++){
200                String[] accflags = methods[m].getAccess();
201                if(checkAccess(accflags)){
202                    if(!(env. showLineAndLocal || env.showDisassembled || env.showVerbose
203                         ||  env.showInternalSigs || env.showallAttr)){
204                        out.print("    ");
205                    }
206                    printMethodSignature(methods[m], accflags);
207                    printExceptions(methods[m]);
208                    out.println(";");
209    
210                    // Print internal signature of method.
211                    if (env.showInternalSigs){
212                        out.println("  Signature: " + (methods[m].getInternalSig()));
213                    }
214    
215                    //Print disassembled code.
216                    if(env.showDisassembled && ! env.showallAttr) {
217                        printcodeSequence(methods[m]);
218                        printExceptionTable(methods[m]);
219                        out.println();
220                    }
221    
222                    // Print line and local variable attribute information.
223                    if (env.showLineAndLocal) {
224                        printLineNumTable(methods[m]);
225                        printLocVarTable(methods[m]);
226                        out.println();
227                    }
228    
229                    // Print  method attribute information.
230                    if (env.showallAttr){
231                        printMethodAttributes(methods[m]);
232                    }
233                }
234            }
235        }
236    
237        /**
238         * Print method signature.
239         */
240        public void printMethodSignature(MethodData method, String[] accflags){
241            printAccess(accflags);
242    
243            if((method.getName()).equals("<init>")){
244                out.print(javaclassname(cls.getClassName()));
245                out.print(method.getParameters());
246            }else if((method.getName()).equals("<clinit>")){
247                out.print("{}");
248            }else{
249                out.print(method.getReturnType()+" ");
250                out.print(method.getName());
251                out.print(method.getParameters());
252            }
253        }
254    
255        /**
256         * print method attribute information.
257         */
258        public void printMethodAttributes(MethodData method){
259            Vector<?> methodattrs = method.getAttributes();
260            Vector<?> codeattrs =  method.getCodeAttributes();
261            for(int k = 0; k < methodattrs.size(); k++){
262                String methodattrname = ((AttrData)methodattrs.elementAt(k)).getAttrName();
263                if(methodattrname.equals("Code")){
264                    printcodeSequence(method);
265                    printExceptionTable(method);
266                    for(int c = 0; c < codeattrs.size(); c++){
267                        String codeattrname = ((AttrData)codeattrs.elementAt(c)).getAttrName();
268                        if(codeattrname.equals("LineNumberTable")){
269                            printLineNumTable(method);
270                        }else if(codeattrname.equals("LocalVariableTable")){
271                            printLocVarTable(method);
272                        }else if(codeattrname.equals("StackMapTable")) {
273                            // Java SE JSR 202 stack map tables
274                            printStackMapTable(method);
275                        }else if(codeattrname.equals("StackMap")) {
276                            // Java ME CLDC stack maps
277                            printStackMap(method);
278                        } else {
279                            printAttrData((AttrData)codeattrs.elementAt(c));
280                        }
281                    }
282                }else if(methodattrname.equals("Exceptions")){
283                    out.println("  Exceptions: ");
284                    printExceptions(method);
285                }else if (methodattrname.equals("Deprecated")){
286                    out.println("  Deprecated: "+ method.isDeprecated());
287                }else if (methodattrname.equals("Synthetic")){
288                    out.println("  Synthetic: "+ method.isSynthetic());
289                }else {
290                    printAttrData((AttrData)methodattrs.elementAt(k));
291                }
292            }
293            out.println();
294        }
295    
296        /**
297         * Print exceptions.
298         */
299        public void printExceptions(MethodData method){
300            int []exc_index_table = method.get_exc_index_table();
301            if (exc_index_table != null) {
302                if(!(env. showLineAndLocal || env.showDisassembled || env.showVerbose
303                     ||  env.showInternalSigs || env.showallAttr)){
304                    out.print("    ");
305                }
306                out.print("   throws ");
307                int k;
308                int l = exc_index_table.length;
309    
310                for (k=0; k<l; k++) {
311                    out.print(javaclassname(cls.getClassName(exc_index_table[k])));
312                    if (k<l-1) out.print(", ");
313                }
314            }
315        }
316    
317        /**
318         * Print code sequence.
319         */
320        public void  printcodeSequence(MethodData method){
321            code = method.getCode();
322            if(code != null){
323                out.println("  Code:");
324                if(env.showVerbose){
325                    printVerboseHeader(method);
326                }
327    
328                for (int pc=0; pc < code.length; ) {
329                    out.print("   "+pc+":\t");
330                    pc=pc+printInstr(pc);
331                    out.println();
332                }
333            }
334        }
335    
336        /**
337         * Print instructions.
338         */
339        public int printInstr(int pc){
340            int opcode = getUbyte(pc);
341            int opcode2;
342            String mnem;
343            switch (opcode) {
344            case opc_nonpriv:
345            case opc_priv:
346                opcode2 = getUbyte(pc+1);
347                mnem=Tables.opcName((opcode<<8)+opcode2);
348                if (mnem==null)
349                    // assume all (even nonexistent) priv and nonpriv instructions
350                    // are 2 bytes long
351                    mnem=Tables.opcName(opcode)+" "+opcode2;
352                out.print(mnem);
353                return 2;
354            case opc_wide: {
355                opcode2 = getUbyte(pc+1);
356                mnem=Tables.opcName((opcode<<8)+opcode2);
357                if (mnem==null) {
358                    // nonexistent opcode - but we have to print something
359                    out.print("bytecode "+opcode);
360                    return 1;
361                }
362                out.print(mnem+" "+getUShort(pc+2));
363                if (opcode2==opc_iinc) {
364                    out.print(", "+getShort(pc+4));
365                    return 6;
366                }
367                return 4;
368            }
369            }
370            mnem=Tables.opcName(opcode);
371            if (mnem==null) {
372                // nonexistent opcode - but we have to print something
373                out.print("bytecode "+opcode);
374                return 1;
375            }
376            if (opcode>opc_jsr_w) {
377                // pseudo opcodes should be printed as bytecodes
378                out.print("bytecode "+opcode);
379                return 1;
380            }
381            out.print(Tables.opcName(opcode));
382            switch (opcode) {
383            case opc_aload: case opc_astore:
384            case opc_fload: case opc_fstore:
385            case opc_iload: case opc_istore:
386            case opc_lload: case opc_lstore:
387            case opc_dload: case opc_dstore:
388            case opc_ret:
389                out.print("\t"+getUbyte(pc+1));
390                return  2;
391            case opc_iinc:
392                out.print("\t"+getUbyte(pc+1)+", "+getbyte(pc+2));
393                return  3;
394            case opc_tableswitch:{
395                int tb=align(pc+1);
396                int default_skip = getInt(tb); /* default skip pamount */
397                int low = getInt(tb+4);
398                int high = getInt(tb+8);
399                int count = high - low;
400                out.print("{ //"+low+" to "+high);
401                for (int i = 0; i <= count; i++)
402                    out.print( "\n\t\t" + (i+low) + ": "+lP+(pc+getInt(tb+12+4*i))+";");
403                out.print("\n\t\tdefault: "+lP+(default_skip + pc) + " }");
404                return tb-pc+16+count*4;
405            }
406    
407            case opc_lookupswitch:{
408                int tb=align(pc+1);
409                int default_skip = getInt(tb);
410                int npairs = getInt(tb+4);
411                out.print("{ //"+npairs);
412                for (int i = 1; i <= npairs; i++)
413                    out.print("\n\t\t"+getInt(tb+i*8)
414                                     +": "+lP+(pc+getInt(tb+4+i*8))+";"
415                                     );
416                out.print("\n\t\tdefault: "+lP+(default_skip + pc) + " }");
417                return tb-pc+(npairs+1)*8;
418            }
419            case opc_newarray:
420                int type=getUbyte(pc+1);
421                switch (type) {
422                case T_BOOLEAN:out.print(" boolean");break;
423                case T_BYTE:   out.print(" byte");   break;
424                case T_CHAR:   out.print(" char");   break;
425                case T_SHORT:  out.print(" short");  break;
426                case T_INT:    out.print(" int");    break;
427                case T_LONG:   out.print(" long");   break;
428                case T_FLOAT:  out.print(" float");  break;
429                case T_DOUBLE: out.print(" double"); break;
430                case T_CLASS:  out.print(" class"); break;
431                default:       out.print(" BOGUS TYPE:"+type);
432                }
433                return 2;
434    
435            case opc_anewarray: {
436                int index =  getUShort(pc+1);
437                out.print("\t#"+index+"; //");
438                PrintConstant(index);
439                return 3;
440            }
441    
442            case opc_sipush:
443                out.print("\t"+getShort(pc+1));
444                return 3;
445    
446            case opc_bipush:
447                out.print("\t"+getbyte(pc+1));
448                return 2;
449    
450            case opc_ldc: {
451                int index = getUbyte(pc+1);
452                out.print("\t#"+index+"; //");
453                PrintConstant(index);
454                return 2;
455            }
456    
457            case opc_ldc_w: case opc_ldc2_w:
458            case opc_instanceof: case opc_checkcast:
459            case opc_new:
460            case opc_putstatic: case opc_getstatic:
461            case opc_putfield: case opc_getfield:
462            case opc_invokevirtual:
463            case opc_invokespecial:
464            case opc_invokestatic: {
465                int index = getUShort(pc+1);
466                out.print("\t#"+index+"; //");
467                PrintConstant(index);
468                return 3;
469            }
470    
471            case opc_invokeinterface: {
472                int index = getUShort(pc+1), nargs=getUbyte(pc+3);
473                out.print("\t#"+index+",  "+nargs+"; //");
474                PrintConstant(index);
475                return 5;
476            }
477    
478            case opc_multianewarray: {
479                int index = getUShort(pc+1), dimensions=getUbyte(pc+3);
480                out.print("\t#"+index+",  "+dimensions+"; //");
481                PrintConstant(index);
482                return 4;
483            }
484            case opc_jsr: case opc_goto:
485            case opc_ifeq: case opc_ifge: case opc_ifgt:
486            case opc_ifle: case opc_iflt: case opc_ifne:
487            case opc_if_icmpeq: case opc_if_icmpne: case opc_if_icmpge:
488            case opc_if_icmpgt: case opc_if_icmple: case opc_if_icmplt:
489            case opc_if_acmpeq: case opc_if_acmpne:
490            case opc_ifnull: case opc_ifnonnull:
491                out.print("\t"+lP+(pc + getShort(pc+1)) );
492                return 3;
493    
494            case opc_jsr_w:
495            case opc_goto_w:
496                out.print("\t"+lP+(pc + getInt(pc+1)));
497                return 5;
498    
499            default:
500                return 1;
501            }
502        }
503        /**
504         * Print code attribute details.
505         */
506        public void printVerboseHeader(MethodData method) {
507            int argCount = method.getArgumentlength();
508            if (!method.isStatic())
509                ++argCount;  // for 'this'
510    
511            out.println("   Stack=" + method.getMaxStack()
512                               + ", Locals=" + method.getMaxLocals()
513                               + ", Args_size=" + argCount);
514    
515        }
516    
517    
518        /**
519         * Print the exception table for this method code
520         */
521        void printExceptionTable(MethodData method){//throws IOException
522            Vector<?> exception_table = method.getexception_table();
523            if (exception_table.size() > 0) {
524                out.println("  Exception table:");
525                out.println("   from   to  target type");
526                for (int idx = 0; idx < exception_table.size(); ++idx) {
527                    TrapData handler = (TrapData)exception_table.elementAt(idx);
528                    printFixedWidthInt(handler.start_pc, 6);
529                    printFixedWidthInt(handler.end_pc, 6);
530                    printFixedWidthInt(handler.handler_pc, 6);
531                    out.print("   ");
532                    int catch_cpx = handler.catch_cpx;
533                    if (catch_cpx == 0) {
534                        out.println("any");
535                    }else {
536                        out.print("Class ");
537                        out.println(cls.getClassName(catch_cpx));
538                        out.println("");
539                    }
540                }
541            }
542        }
543    
544        /**
545         * Print LineNumberTable attribute information.
546         */
547        public void printLineNumTable(MethodData method) {
548            int numlines = method.getnumlines();
549            Vector<?> lin_num_tb = method.getlin_num_tb();
550            if( lin_num_tb.size() > 0){
551                out.println("  LineNumberTable: ");
552                for (int i=0; i<numlines; i++) {
553                    LineNumData linnumtb_entry=(LineNumData)lin_num_tb.elementAt(i);
554                    out.println("   line " + linnumtb_entry.line_number + ": "
555                                   + linnumtb_entry.start_pc);
556                }
557            }
558            out.println();
559        }
560    
561        /**
562         * Print LocalVariableTable attribute information.
563         */
564        public void printLocVarTable(MethodData method){
565            int siz = method.getloc_var_tbsize();
566            if(siz > 0){
567                out.println("  LocalVariableTable: ");
568                out.print("   ");
569                out.println("Start  Length  Slot  Name   Signature");
570            }
571            Vector<?> loc_var_tb = method.getloc_var_tb();
572    
573            for (int i=0; i<siz; i++) {
574                LocVarData entry=(LocVarData)loc_var_tb.elementAt(i);
575    
576                out.println("   "+entry.start_pc+"      "+entry.length+"      "+
577                                   entry.slot+"    "+cls.StringValue(entry.name_cpx)  +
578                                   "       "+cls.StringValue(entry.sig_cpx));
579            }
580            out.println();
581        }
582    
583        /**
584         * Print StackMap attribute information.
585         */
586        public void printStackMap(MethodData method) {
587            StackMapData[] stack_map_tb = method.getStackMap();
588            int number_of_entries = stack_map_tb.length;
589            if (number_of_entries > 0) {
590                out.println("  StackMap: number_of_entries = " + number_of_entries);
591    
592                for (StackMapData frame : stack_map_tb) {
593                    frame.print(this);
594                }
595            }
596           out.println();
597        }
598    
599        /**
600         * Print StackMapTable attribute information.
601         */
602        public void printStackMapTable(MethodData method) {
603            StackMapTableData[] stack_map_tb = method.getStackMapTable();
604            int number_of_entries = stack_map_tb.length;
605            if (number_of_entries > 0) {
606                out.println("  StackMapTable: number_of_entries = " + number_of_entries);
607    
608                for (StackMapTableData frame : stack_map_tb) {
609                    frame.print(this);
610                }
611            }
612            out.println();
613        }
614    
615        void printMap(String name, int[] map) {
616            out.print(name);
617            for (int i=0; i<map.length; i++) {
618                int fulltype = map[i];
619                int type = fulltype & 0xFF;
620                int argument = fulltype >> 8;
621                switch (type) {
622                    case ITEM_Object:
623                        out.print(" ");
624                        PrintConstant(argument);
625                        break;
626                    case ITEM_NewObject:
627                        out.print(" " + Tables.mapTypeName(type));
628                        out.print(" " + argument);
629                        break;
630                    default:
631                        out.print(" " + Tables.mapTypeName(type));
632                }
633                out.print( (i==(map.length-1)? ' ' : ','));
634            }
635            out.println("]");
636        }
637    
638        /**
639         * Print ConstantValue attribute information.
640         */
641        public void printConstantValue(FieldData field){
642            out.print("  Constant value: ");
643            int cpx = (field.getConstantValueIndex());
644            byte tag=0;
645            try {
646                tag=cls.getTag(cpx);
647    
648            } catch (IndexOutOfBoundsException e) {
649                out.print("Error:");
650                return;
651            }
652            switch (tag) {
653            case CONSTANT_METHOD:
654            case CONSTANT_INTERFACEMETHOD:
655            case CONSTANT_FIELD: {
656                CPX2 x = cls.getCpoolEntry(cpx);
657                if (x.cpx1 == cls.getthis_cpx()) {
658                    // don't print class part for local references
659                    cpx=x.cpx2;
660                }
661            }
662            }
663            out.print(cls.TagString(tag)+" "+ cls.StringValue(cpx));
664        }
665    
666        /**
667         * Print InnerClass attribute information.
668         */
669        public void printInnerClasses(){//throws ioexception
670    
671            InnerClassData[] innerClasses = cls.getInnerClasses();
672            if(innerClasses != null){
673                if(innerClasses.length > 0){
674                    out.print("  ");
675                    out.println("InnerClass: ");
676                    for(int i = 0 ; i < innerClasses.length; i++){
677                        out.print("   ");
678                        //access
679                        String[] accflags = innerClasses[i].getAccess();
680                        if(checkAccess(accflags)){
681                            printAccess(accflags);
682                            if (innerClasses[i].inner_name_index!=0) {
683                                out.print("#"+innerClasses[i].inner_name_index+"= ");
684                            }
685                            out.print("#"+innerClasses[i].inner_class_info_index);
686                            if (innerClasses[i].outer_class_info_index!=0) {
687                                out.print(" of #"+innerClasses[i].outer_class_info_index);
688                            }
689                            out.print("; //");
690                            if (innerClasses[i].inner_name_index!=0) {
691                                out.print(cls.getName(innerClasses[i].inner_name_index)+"=");
692                            }
693                            PrintConstant(innerClasses[i].inner_class_info_index);
694                            if (innerClasses[i].outer_class_info_index!=0) {
695                                out.print(" of ");
696                                PrintConstant(innerClasses[i].outer_class_info_index);
697                            }
698                            out.println();
699                        }
700                    }
701    
702                }
703            }
704        }
705    
706        /**
707         * Print constant pool information.
708         */
709        public void printcp(){
710            int cpx = 1 ;
711    
712            while (cpx < cls.getCpoolCount()) {
713                out.print("const #"+cpx+" = ");
714                cpx+=PrintlnConstantEntry(cpx);
715            }
716            out.println();
717        }
718    
719        /**
720         * Print constant pool entry information.
721         */
722        @SuppressWarnings("fallthrough")
723        public int PrintlnConstantEntry(int cpx) {
724            int size=1;
725            byte tag=0;
726            try {
727                tag=cls.getTag(cpx);
728            } catch (IndexOutOfBoundsException e) {
729                out.println("  <Incorrect CP index>");
730                return 1;
731            }
732            out.print(cls.StringTag(cpx)+"\t");
733            Object x=cls.getCpoolEntryobj(cpx);
734            if (x==null) {
735                switch (tag) {
736                case CONSTANT_LONG:
737                case CONSTANT_DOUBLE:
738                    size=2;
739                }
740                out.println("null;");
741                return size;
742            }
743            String str=cls.StringValue(cpx);
744    
745            switch (tag) {
746            case CONSTANT_CLASS:
747            case CONSTANT_STRING:
748                out.println("#"+(((CPX)x).cpx)+";\t//  "+str);
749                break;
750            case CONSTANT_FIELD:
751            case CONSTANT_METHOD:
752            case CONSTANT_INTERFACEMETHOD:
753                out.println("#"+((CPX2)x).cpx1+".#"+((CPX2)x).cpx2+";\t//  "+str);
754                break;
755            case CONSTANT_NAMEANDTYPE:
756                out.println("#"+((CPX2)x).cpx1+":#"+((CPX2)x).cpx2+";//  "+str);
757                break;
758            case CONSTANT_LONG:
759            case CONSTANT_DOUBLE:
760                size=2;
761                // fall through
762            default:
763                out.println(str+";");
764            }
765            return size;
766        }
767    
768        /**
769         * Checks access of class, field or method.
770         */
771        public boolean checkAccess(String accflags[]){
772    
773            boolean ispublic = false;
774            boolean isprotected = false;
775            boolean isprivate = false;
776            boolean ispackage = false;
777    
778            for(int i= 0; i < accflags.length; i++){
779                if(accflags[i].equals("public")) ispublic = true;
780                else if (accflags[i].equals("protected")) isprotected = true;
781                else if (accflags[i].equals("private")) isprivate = true;
782            }
783    
784            if(!(ispublic || isprotected || isprivate)) ispackage = true;
785    
786            if((env.showAccess == env.PUBLIC) && (isprotected || isprivate || ispackage)) return false;
787            else if((env.showAccess == env.PROTECTED) && (isprivate || ispackage)) return false;
788            else if((env.showAccess == env.PACKAGE) && (isprivate)) return false;
789            else return true;
790        }
791    
792        /**
793         * Prints access of class, field or method.
794         */
795        public void printAccess(String []accflags){
796            for(int j = 0; j < accflags.length; j++){
797                out.print(accflags[j]+" ");
798            }
799        }
800    
801        /**
802         * Print an integer so that it takes 'length' characters in
803         * the output.  Temporary until formatting code is stable.
804         */
805        public void printFixedWidthInt(long x, int length) {
806            CharArrayWriter baStream = new CharArrayWriter();
807            PrintWriter pStream = new PrintWriter(baStream);
808            pStream.print(x);
809            String str = baStream.toString();
810            for (int cnt = length - str.length(); cnt > 0; --cnt)
811                out.print(' ');
812            out.print(str);
813        }
814    
815        protected int getbyte (int pc) {
816            return code[pc];
817        }
818    
819        protected int getUbyte (int pc) {
820            return code[pc]&0xFF;
821        }
822    
823        int getShort (int pc) {
824            return (code[pc]<<8) | (code[pc+1]&0xFF);
825        }
826    
827        int getUShort (int pc) {
828            return ((code[pc]<<8) | (code[pc+1]&0xFF))&0xFFFF;
829        }
830    
831        protected int getInt (int pc) {
832            return (getShort(pc)<<16) | (getShort(pc+2)&0xFFFF);
833        }
834    
835        /**
836         * Print constant value at that index.
837         */
838        void PrintConstant(int cpx) {
839            if (cpx==0) {
840                out.print("#0");
841                return;
842            }
843            byte tag=0;
844            try {
845                tag=cls.getTag(cpx);
846    
847            } catch (IndexOutOfBoundsException e) {
848                out.print("#"+cpx);
849                return;
850            }
851            switch (tag) {
852            case CONSTANT_METHOD:
853            case CONSTANT_INTERFACEMETHOD:
854            case CONSTANT_FIELD: {
855                // CPX2 x=(CPX2)(cpool[cpx]);
856                CPX2 x = cls.getCpoolEntry(cpx);
857                if (x.cpx1 == cls.getthis_cpx()) {
858                    // don't print class part for local references
859                    cpx=x.cpx2;
860                }
861            }
862            }
863            out.print(cls.TagString(tag)+" "+ cls.StringValue(cpx));
864        }
865    
866        protected static int  align (int n) {
867            return (n+3) & ~3 ;
868        }
869    
870        public void printend(){
871            out.println("}");
872            out.println();
873        }
874    
875        public String javaclassname(String name){
876            return name.replace('/','.');
877        }
878    
879        /**
880         * Print attribute data in hex.
881         */
882        public void printAttrData(AttrData attr){
883            byte []data = attr.getData();
884            int i = 0;
885            int j = 0;
886            out.print("  "+attr.getAttrName()+": ");
887            out.println("length = " + cls.toHex(attr.datalen));
888    
889            out.print("   ");
890    
891    
892            while (i < data.length){
893                String databytestring = cls.toHex(data[i]);
894                if(databytestring.equals("0x")) out.print("00");
895                else if(databytestring.substring(2).length() == 1){
896                    out.print("0"+databytestring.substring(2));
897                } else{
898                    out.print(databytestring.substring(2));
899                }
900    
901                 j++;
902                if(j == 16) {
903                    out.println();
904                    out.print("   ");
905                    j = 0;
906                }
907                else out.print(" ");
908                i++;
909            }
910            out.println();
911        }
912    }