home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / sofa / archive / SmallEiffel.lha / SmallEiffel / lib_se / print_jvm_class.e < prev    next >
Text File  |  1999-06-05  |  61KB  |  1,690 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class PRINT_JVM_CLASS
  17.    --
  18.    -- The `print_jvm_class' command.
  19.    --
  20.  
  21. inherit COMMAND_FLAGS; CP_INFO_TAGS;
  22.  
  23. creation make
  24.  
  25. feature {NONE}
  26.  
  27.    command_name: STRING is "print_jvm_class";
  28.  
  29.    bytes: FIXED_ARRAY[INTEGER] is
  30.          -- All bytes of the class file.
  31.       once
  32.          !!Result.with_capacity(4096);
  33.       end;
  34.  
  35.    constant_pool_count: INTEGER;
  36.  
  37.    access_flag: STRING;
  38.  
  39.    this_class_idx: INTEGER;
  40.  
  41.    super_class_idx: INTEGER;
  42.  
  43.    interfaces_count: INTEGER;
  44.  
  45.    fields_count: INTEGER;
  46.  
  47.    methods_count: INTEGER;
  48.  
  49.    attributes_count: INTEGER;
  50.  
  51.    make is
  52.       local
  53.          path: STRING;
  54.          file_of_bytes: BINARY_FILE_READ;
  55.          byte, i, index: INTEGER;
  56.          s: STRING;
  57.          interface_idx: INTEGER;
  58.       do
  59.          if argument_count /= 1 then
  60.             system_tools.bad_use_exit("print_jvm_class");
  61.          elseif is_flag_version(argument(1)) then
  62.          else
  63.             path := argument(1).twin;
  64.             if not path.has_suffix(".class") then
  65.                path.append(".class");
  66.             end;
  67.             !!file_of_bytes.connect_to(path);
  68.             if file_of_bytes.is_connected then
  69.                from
  70.                   io.put_string("Contents of file %"");
  71.                   io.put_string(file_of_bytes.path);
  72.                   io.put_string("%".%N");
  73.                   file_of_bytes.read_byte;
  74.                   if file_of_bytes.end_of_input then
  75.                      bad_class_file("Invalid empty class file.",0);
  76.                   end;
  77.                until
  78.                   file_of_bytes.end_of_input
  79.                loop
  80.                   byte := file_of_bytes.last_byte;
  81.                   bytes.add_last(byte)
  82.                   file_of_bytes.read_byte;
  83.                end;
  84.                file_of_bytes.disconnect;
  85.                io.put_string("Total bytes: ");
  86.                io.put_integer(bytes.count);
  87.                io.put_new_line;
  88.                io.put_string("Magic number: ");
  89.                s := hexa4_at(0);
  90.                if not ("0xCAFEBABE").is_equal(s) then
  91.                   bad_class_file("Invalid Magic number.",0);
  92.                else
  93.                   io.put_string(s);
  94.                   io.put_new_line;
  95.                end;
  96.                io.put_string("Minor version: ");
  97.                io.put_string(hexa2_at(4));
  98.                io.put_new_line;
  99.                io.put_string("Major version: ");
  100.                io.put_string(hexa2_at(6));
  101.                io.put_new_line;
  102.                io.put_string("Constant pool count: ");
  103.                constant_pool_count := u2_integer_at(8);
  104.                io.put_integer(constant_pool_count);
  105.                io.put_new_line;
  106.                io.put_string("Loading constant pool items :%N");
  107.                from
  108.                   constant_pool.reset(constant_pool_count - 1);
  109.                   index := 10; -- of first item in constant pool.
  110.                   i := 1;
  111.                until
  112.                   i >= constant_pool_count
  113.                loop
  114.                   index := load_cp_info(i,index);
  115.                   i := i + 1;
  116.                end;
  117.                io.put_string("Constant pool view :%N");
  118.                from
  119.                   index := 10; -- of first item in constant pool.
  120.                   i := 1;
  121.                until
  122.                   i >= constant_pool_count
  123.                loop
  124.                   tmp_string.clear;
  125.                   integer_to_hexa_in(i,tmp_string);
  126.                   tmp_string.extend(' ');
  127.                   extend_string(tmp_string,' ',6);
  128.                   i.append_in(tmp_string);
  129.                   tmp_string.extend(' ');
  130.                   extend_string(tmp_string,' ',12);
  131.                   tmp_string.extend('(');
  132.                   integer_to_hexa_in(index,tmp_string);
  133.                   tmp_string.extend(')');
  134.                   extend_string(tmp_string,' ',20);
  135.                   tmp_string.append(" : ");
  136.                   io.put_string(tmp_string);
  137.                   index := print_cp_info(i,index);
  138.                   io.put_new_line;
  139.                   i := i + 1;
  140.                end;
  141.                io.put_string("Access flag: 0x");
  142.                access_flag := character_at(index).to_hexadecimal;
  143.                index := index + 1;
  144.                character_at(index).to_hexadecimal_in(access_flag);
  145.                index := index + 1;
  146.                io.put_string(access_flag);
  147.                io.put_character(' ');
  148.                if access_flag.item(4) = '1' then
  149.                   io.put_string(" public ");
  150.                end;
  151.                if access_flag.item(3) = '1' then
  152.                   io.put_string(" final (no subclass)");
  153.                end;
  154.                if access_flag.item(3) = '2' then
  155.                   io.put_string(" super ");
  156.                end;
  157.                if access_flag.item(2) = '2' then
  158.                   io.put_string(" interface ");
  159.                end;
  160.                if access_flag.item(2) = '4' then
  161.                   io.put_string(" abstract ");
  162.                end;
  163.                io.put_new_line;
  164.                io.put_string("This Class: ");
  165.                this_class_idx := u2_integer_at(index);
  166.                index := index + 2;
  167.                if constant_pool.is_class(this_class_idx) then
  168.                   tmp_string.copy(" is ");
  169.                   constant_pool.view_in(tmp_string,this_class_idx);
  170.                   io.put_string(tmp_string);
  171.                else
  172.                   io.put_string("??%N");
  173.                   bad_class_file("Bad `this_class' value.",index - 2);
  174.                end;
  175.                io.put_new_line;
  176.                io.put_string("Super Class: ");
  177.                super_class_idx := u2_integer_at(index);
  178.                index := index + 2;
  179.                if constant_pool.is_class(super_class_idx) then
  180.                   tmp_string.copy("is ");
  181.                   constant_pool.view_in(tmp_string,super_class_idx);
  182.                   io.put_string(tmp_string);
  183.                else
  184.                   io.put_string("??%N");
  185.                   bad_class_file("Bad `super_class' value.",index - 2);
  186.                end;
  187.                io.put_new_line;
  188.                io.put_string("Interfaces count: ");
  189.                interfaces_count := u2_integer_at(index);
  190.                index := index + 2;
  191.                io.put_integer(interfaces_count);
  192.                i := interfaces_count;
  193.                if i > 0 then
  194.                   io.put_string(" {");
  195.                   from
  196.                   until
  197.                      i = 0
  198.                   loop
  199.                      interface_idx := u2_integer_at(index);
  200.                      index := index + 2;
  201.                      io.put_integer(interface_idx);
  202.                      i := i - 1;
  203.                      if i > 0 then
  204.                         io.put_character(',');
  205.                      end;
  206.                   end;
  207.                   io.put_character('}');
  208.                end;
  209.                io.put_new_line;
  210.                io.put_string("----- Fields count: ");
  211.                fields_count := u2_integer_at(index);
  212.                index := index + 2;
  213.                io.put_integer(fields_count);
  214.                io.put_new_line;
  215.                from
  216.                   i := 1
  217.                until
  218.                   i > fields_count
  219.                loop
  220.                   io.put_integer(i);
  221.                   if i < 10 then
  222.                      io.put_string("   ");
  223.                   elseif i < 100 then
  224.                      io.put_string("  ");
  225.                   else
  226.                      io.put_string(" ");
  227.                   end;
  228.                   io.put_string(": ");
  229.                   index := print_field_info(index);
  230.                   io.put_new_line;
  231.                   i := i + 1;
  232.                end;
  233.                io.put_string("----- Methods count: ");
  234.                methods_count := u2_integer_at(index);
  235.                index := index + 2;
  236.                io.put_integer(methods_count);
  237.                io.put_new_line;
  238.                from
  239.                   i := 1
  240.                until
  241.                   i > methods_count
  242.                loop
  243.                   io.put_integer(i);
  244.                   if i < 10 then
  245.                      io.put_string("   ");
  246.                   elseif i < 100 then
  247.                      io.put_string("  ");
  248.                   else
  249.                      io.put_string(" ");
  250.                   end;
  251.                   io.put_string(": ");
  252.                   index := print_method_info(index);
  253.                   io.put_new_line;
  254.                   i := i + 1;
  255.                end;
  256.                io.put_string("Attributes count: ");
  257.                attributes_count := u2_integer_at(index);
  258.                index := index + 2;
  259.                io.put_integer(attributes_count);
  260.                io.put_new_line;
  261.                from
  262.                   i := 1
  263.                until
  264.                   i > attributes_count
  265.                loop
  266.                   io.put_integer(i);
  267.                   if i < 10 then
  268.                      io.put_string("   ");
  269.                   elseif i < 100 then
  270.                      io.put_string("  ");
  271.                   else
  272.                      io.put_string(" ");
  273.                   end;
  274.                   io.put_string(": ");
  275.                   index := print_attribute_info(index);
  276.                   io.put_new_line;
  277.                   i := i + 1;
  278.                end;
  279.                check
  280.                   index = bytes.upper + 1
  281.                end;
  282.             else
  283.                io.put_string("File %"");
  284.                io.put_string(path);
  285.                io.put_string("%" not found.%N");
  286.             end;
  287.          end;
  288.       end;
  289.  
  290. feature {NONE} -- Low level access in `bytes' :
  291.  
  292.    character_at(index: INTEGER): CHARACTER is
  293.       do
  294.          Result := bytes.item(index).to_character;
  295.       end;
  296.  
  297.    u2_at(index: INTEGER): STRING is
  298.       do
  299.          !!Result.make(2);
  300.          Result.extend(character_at(index + 0));
  301.          Result.extend(character_at(index + 1));
  302.       end;
  303.  
  304.    u4_at(index: INTEGER): STRING is
  305.       do
  306.          !!Result.make(4);
  307.          Result.extend(character_at(index + 0));
  308.          Result.extend(character_at(index + 1));
  309.          Result.extend(character_at(index + 2));
  310.          Result.extend(character_at(index + 3));
  311.       end;
  312.  
  313.    u8_at(index: INTEGER): STRING is
  314.       do
  315.          !!Result.make(8);
  316.          Result.extend(character_at(index + 0));
  317.          Result.extend(character_at(index + 1));
  318.          Result.extend(character_at(index + 2));
  319.          Result.extend(character_at(index + 3));
  320.          Result.extend(character_at(index + 4));
  321.          Result.extend(character_at(index + 5));
  322.          Result.extend(character_at(index + 6));
  323.          Result.extend(character_at(index + 7));
  324.       end;
  325.  
  326.    hexa1_at(index: INTEGER): STRING is
  327.       do
  328.          !!Result.copy("0x");
  329.          bytes.item(index).to_character.to_hexadecimal_in(Result);
  330.       end;
  331.  
  332.    hexa2_at(index: INTEGER): STRING is
  333.       do
  334.          !!Result.copy("0x");
  335.          bytes.item(index + 0).to_character.to_hexadecimal_in(Result);
  336.          bytes.item(index + 1).to_character.to_hexadecimal_in(Result);
  337.       end;
  338.  
  339.    hexa4_at(index: INTEGER): STRING is
  340.       do
  341.          !!Result.copy("0x");
  342.          bytes.item(index + 0).to_character.to_hexadecimal_in(Result);
  343.          bytes.item(index + 1).to_character.to_hexadecimal_in(Result);
  344.          bytes.item(index + 2).to_character.to_hexadecimal_in(Result);
  345.          bytes.item(index + 3).to_character.to_hexadecimal_in(Result);
  346.       end;
  347.  
  348.    hexa8_at(index: INTEGER): STRING is
  349.       do
  350.          !!Result.copy("0x");
  351.          bytes.item(index + 0).to_character.to_hexadecimal_in(Result);
  352.          bytes.item(index + 1).to_character.to_hexadecimal_in(Result);
  353.          bytes.item(index + 2).to_character.to_hexadecimal_in(Result);
  354.          bytes.item(index + 3).to_character.to_hexadecimal_in(Result);
  355.          bytes.item(index + 4).to_character.to_hexadecimal_in(Result);
  356.          bytes.item(index + 5).to_character.to_hexadecimal_in(Result);
  357.          bytes.item(index + 6).to_character.to_hexadecimal_in(Result);
  358.          bytes.item(index + 7).to_character.to_hexadecimal_in(Result);
  359.       end;
  360.  
  361.    u2_integer_at(index: INTEGER): INTEGER is
  362.       do
  363.          Result := bytes.item(index) * 256 + bytes.item(index + 1);
  364.       end;
  365.  
  366.    u4_integer_at(index: INTEGER): INTEGER is
  367.       do
  368.          Result := bytes.item(index);
  369.          Result := Result * 256;
  370.          Result := Result + bytes.item(index + 1);
  371.          Result := Result * 256;
  372.          Result := Result + bytes.item(index + 2);
  373.          Result := Result * 256;
  374.          Result := Result + bytes.item(index + 3);
  375.       end;
  376.  
  377. feature {NONE} -- Basic stuff to view values :
  378.  
  379.    integer_to_hexa_in(int: INTEGER; str: STRING) is
  380.       require
  381.          int >= 0
  382.       do
  383.          str.append("0x");
  384.          inspect
  385.             int
  386.          when 0 .. 255 then
  387.             int.to_character.to_hexadecimal_in(str);
  388.          when 256 .. 65535 then
  389.             (int \\ 256).to_character.to_hexadecimal_in(str);
  390.             (int // 256).to_character.to_hexadecimal_in(str);
  391.          end;
  392.       end;
  393.  
  394.    extend_string(s: STRING; c: CHARACTER; length: INTEGER) is
  395.       do
  396.          from
  397.          until
  398.             s.count >= length
  399.          loop
  400.             s.extend(c);
  401.          end;
  402.       end;
  403.  
  404.  
  405. feature {NONE}
  406.  
  407.    bad_class_file(msg: STRING; at: INTEGER) is
  408.          -- If `at' is greater than 0, the corresponding byte
  409.          -- is shown during the class file dump.
  410.       require
  411.          bytes.valid_index(at)
  412.       local
  413.          fz_visible, fz_hexadec: STRING;
  414.          index: INTEGER;
  415.          byte: CHARACTER;
  416.          left_margin: INTEGER;
  417.       do
  418.          io.put_string(msg);
  419.          io.put_new_line;
  420.          io.put_string("Class file dump:%N");
  421.          from
  422.             !!fz_visible.make(16);
  423.             !!fz_hexadec.make(32);
  424.          until
  425.             index > bytes.upper
  426.          loop
  427.             if fz_visible.empty then
  428.                tmp_string.clear;
  429.                integer_to_hexa_in(index,tmp_string);
  430.                tmp_string.extend(' ');
  431.                extend_string(tmp_string,' ',9);
  432.                index.append_in(tmp_string);
  433.                tmp_string.extend(' ');
  434.                extend_string(tmp_string,' ',15);
  435.                io.put_string(tmp_string);
  436.                left_margin := tmp_string.count;
  437.             end;
  438.             byte := character_at(index);
  439.             byte.to_hexadecimal_in(fz_hexadec);
  440.             inspect
  441.                byte.code
  442.             when 32 .. 126 then
  443.                fz_visible.extend(byte);
  444.             else
  445.                fz_visible.extend('.');
  446.             end
  447.             if fz_visible.count = 16 then
  448.                show_dump_line(fz_hexadec,fz_visible,left_margin,index,at);
  449.             end;
  450.             index := index + 1;
  451.          end;
  452.          if fz_visible.count > 0 then
  453.             from
  454.                index := index - 1;
  455.             until
  456.                fz_visible.count = 16
  457.             loop
  458.                fz_visible.extend(' ');
  459.                fz_hexadec.append("  ");
  460.                index := index + 1;
  461.             end;
  462.             show_dump_line(fz_hexadec,fz_visible,left_margin,index,at);
  463.          end;
  464.          die_with_code(exit_failure_code);
  465.       end;
  466.  
  467.    show_dump_line(hexadec, visible: STRING; left_margin, index, at: INTEGER) is
  468.          -- Where `index - 15' is the index of `visible.item(1)'.
  469.       require
  470.          bytes.valid_index(at);
  471.          visible.count = 16;
  472.          hexadec.count = 32
  473.       local
  474.          min, max, i: INTEGER;
  475.       do
  476.          io.put_string(hexadec);
  477.          io.put_string(" ");
  478.          io.put_string(visible);
  479.          io.put_new_line;
  480.          min := index - 15;
  481.          max := index;
  482.          if (at > 0) and (min <= at) and (at <= max) then
  483.             from
  484.                tmp_string.clear;
  485.                extend_string(tmp_string,'_',left_margin);
  486.                i := min;
  487.             until
  488.                i = at
  489.             loop
  490.                tmp_string.append("__");
  491.                i := i + 1;
  492.             end;
  493.             io.put_string(tmp_string);
  494.             io.put_string("^^%N*** Error at this byte%N");
  495.             io.put_string("Remainder of the class file :%N");
  496.          end;
  497.          visible.clear;
  498.          hexadec.clear;
  499.       ensure
  500.          visible.empty;
  501.          hexadec.empty
  502.       end;
  503.  
  504. feature {NONE}
  505.  
  506.    load_cp_info(i: INTEGER; index: INTEGER): INTEGER is
  507.          -- Gives the index of the following item.
  508.       local
  509.          tag, i2, length: INTEGER;
  510.          utf8: STRING;
  511.       do
  512.          tmp_string.clear;
  513.          tmp_string.append("item #");
  514.          i.append_in(tmp_string);
  515.          extend_string(tmp_string,' ',8);
  516.          tmp_string.append(" : ");
  517.          io.put_string(tmp_string);
  518.          tag := bytes.item(index);
  519.          inspect
  520.             tag.to_character
  521.          when Constant_class then
  522.             io.put_string("CONSTANT_Class");
  523.             constant_pool.set_class(i,u2_at(index + 1));
  524.             Result := index + 3;
  525.          when Constant_fieldref then
  526.             io.put_string("CONSTANT_Fieldref");
  527.             constant_pool.set_fieldref(i,u4_at(index + 1));
  528.             Result := index + 5;
  529.          when Constant_methodref then
  530.             io.put_string("CONSTANT_Methodref");
  531.             constant_pool.set_methodref(i,u4_at(index + 1));
  532.             Result := index + 5;
  533.          when Constant_interfacemethodref then
  534.             io.put_string("CONSTANT_InterfaceMethodref");
  535.             constant_pool.set_interface_methodref(i,u4_at(index + 1));
  536.             Result := index + 5;
  537.          when Constant_string then
  538.             io.put_string("CONSTANT_String");
  539.             constant_pool.set_string(i,u2_at(index + 1));
  540.             Result := index + 3;
  541.          when Constant_integer then
  542.             io.put_string("CONSTANT_Integer");
  543.             constant_pool.set_integer(i,u4_at(index + 1));
  544.             Result := index + 5;
  545.          when Constant_float then
  546.             io.put_string("CONSTANT_Float");
  547.             constant_pool.set_float(i,u4_at(index + 1));
  548.             Result := index + 5;
  549.          when Constant_long then
  550.             io.put_string("CONSTANT_Long");
  551.             constant_pool.set_long(i,u8_at(index + 1));
  552.             Result := index + 9;
  553.          when Constant_double then
  554.             io.put_string("CONSTANT_Double");
  555.             constant_pool.set_double(i,u8_at(index + 1));
  556.             Result := index + 9;
  557.          when Constant_name_and_type then
  558.             io.put_string("CONSTANT_NameandType");
  559.             constant_pool.set_name_and_type(i,u4_at(index + 1));
  560.             Result := index + 5;
  561.          when Constant_utf8 then
  562.             io.put_string("CONSTANT_Utf8");
  563.             length := u2_integer_at(index + 1);
  564.             Result := index + 3;
  565.             !!utf8.make(length + 2);
  566.             utf8.extend(character_at(index + 1));
  567.             utf8.extend(character_at(index + 2));
  568.             from
  569.                i2 := length;
  570.             until
  571.                i2 = 0
  572.             loop
  573.                utf8.extend(character_at(Result));
  574.                Result := Result + 1;
  575.                i2 := i2 - 1;
  576.             end;
  577.             constant_pool.set_utf8(i,utf8);
  578.          else
  579.             io.put_string("Error while loading constant pool.%N");
  580.             io.put_string("Problem with item #");
  581.             io.put_integer(i);
  582.             io.put_string("%NBad cp_info tag : ");
  583.             io.put_integer(tag);
  584.             io.put_string("%N");
  585.             bad_class_file("Bad constant pool.",index);
  586.          end;
  587.          io.put_new_line;
  588.       end;
  589.  
  590. feature {NONE}
  591.  
  592.    u2_to_integer(u2: STRING): INTEGER is
  593.       require
  594.          u2.count = 2
  595.       do
  596.          Result := u2.item(1).code;
  597.          Result := Result * 256;
  598.          Result := Result + u2.item(2).code;
  599.       ensure
  600.          Result >= 0
  601.       end;
  602.  
  603.    print_cp_info(i: INTEGER; index: INTEGER): INTEGER is
  604.          -- Gives the index of the following item.
  605.       local
  606.          tag: INTEGER;
  607.          cp_info: CP_INFO;
  608.          info: STRING;
  609.          class_idx, name_idx, type_idx, string_idx: INTEGER;
  610.       do
  611.          tag := bytes.item(index);
  612.          cp_info := constant_pool.item(i);
  613.          info := cp_info.info;
  614.          check
  615.             tag.to_character = cp_info.tag
  616.          end;
  617.          inspect
  618.             tag.to_character
  619.          when Constant_class then -- CONSTANT_Class :
  620.             io.put_string("class at ");
  621.             class_idx := u2_to_integer(info);
  622.             if constant_pool.valid_index(class_idx) then
  623.                io.put_integer(class_idx);
  624.                io.put_string(": ");
  625.                cp_info := constant_pool.item(class_idx);
  626.                if cp_info.tag.code = 1 then
  627.                   tmp_string.clear;
  628.                   constant_pool.view_in(tmp_string,i);
  629.                   io.put_string(tmp_string);
  630.                else
  631.                   io.put_string("%NUtf8 index expected.%N");
  632.                   bad_class_file("Bad constant pool.",index + 1);
  633.                end;
  634.             else
  635.                io.put_string("Class index out of range.%N");
  636.                bad_class_file("Bad constant pool.",index + 1);
  637.             end;
  638.             Result := index + 3;
  639.          when Constant_fieldref then -- CONSTANT_Fieldref :
  640.             io.put_string("fieldref class: ");
  641.             print_cp_info_fields_methods(index,info);
  642.             Result := index + 5;
  643.          when Constant_methodref then -- CONSTANT_Methodref :
  644.             io.put_string("methodref class: ");
  645.             print_cp_info_fields_methods(index,info);
  646.             Result := index + 5;
  647.          when Constant_interfacemethodref then -- CONSTANT_InterfaceMethodref :
  648.             io.put_string("interface methodref class: ");
  649.             print_cp_info_fields_methods(index,info);
  650.             Result := index + 5;
  651.          when Constant_string then -- CONSTANT_String :
  652.             io.put_string("string at ");
  653.             string_idx := u2_to_integer(info);
  654.             if constant_pool.valid_index(string_idx) then
  655.                io.put_integer(string_idx);
  656.                io.put_string(" : %"");
  657.                cp_info := constant_pool.item(string_idx);
  658.                if cp_info.tag.code = 1 then
  659.                   tmp_string.clear;
  660.                   constant_pool.view_in(tmp_string,i);
  661.                   io.put_string(tmp_string);
  662.                   io.put_string("%"");
  663.                else
  664.                   io.put_string("%NUtf8 index expected.%N");
  665.                   bad_class_file("Bad constant pool.",index + 1);
  666.                end;
  667.             else
  668.                io.put_string("??%NString index out of range.%N");
  669.                bad_class_file("Bad constant pool.",index + 1);
  670.             end;
  671.             Result := index + 3;
  672.          when Constant_integer then -- CONSTANT_Integer :
  673.             io.put_string("integer: ");
  674.             io.put_string(hexa4_at(index + 1));
  675.             Result := index + 5;
  676.          when Constant_float then -- CONSTANT_Float :
  677.             io.put_string("float: ");
  678.             io.put_string(hexa4_at(index + 1));
  679.             Result := index + 5;
  680.          when Constant_long then -- CONSTANT_Long :
  681.             io.put_string("long: ");
  682.             io.put_string(hexa8_at(index + 1));
  683.             Result := index + 9;
  684.          when Constant_double then -- CONSTANT_Double :
  685.             io.put_string("double: ");
  686.             io.put_string(hexa8_at(index + 1));
  687.             Result := index + 9;
  688.          when Constant_name_and_type then -- CONSTANT_NameandType :
  689.             io.put_string("name: ");
  690.             name_idx := u2_to_integer(info.substring(1,2));
  691.             if constant_pool.valid_index(name_idx) then
  692.                cp_info := constant_pool.item(name_idx);
  693.                if cp_info.tag.code = 1 then
  694.                   tmp_string.clear;
  695.                   constant_pool.view_in(tmp_string,name_idx);
  696.                   io.put_string(tmp_string);
  697.                   io.put_string(" type: ");
  698.                   type_idx := u2_to_integer(info.substring(3,4));
  699.                   if constant_pool.valid_index(type_idx) then
  700.                      cp_info := constant_pool.item(type_idx);
  701.                      if cp_info.tag.code = 1 then
  702.                         tmp_string.clear;
  703.                         constant_pool.view_in(tmp_string,type_idx);
  704.                         io.put_string(tmp_string);
  705.                      else
  706.                         io.put_string("??%NUtf8 index expected.%N");
  707.                         bad_class_file("Bad constant pool.",index + 3);
  708.                      end;
  709.                   else
  710.                      io.put_string("%NType index out of range.%N");
  711.                      bad_class_file("Bad constant pool.",index + 3);
  712.                   end;
  713.                else
  714.                   io.put_string("%NUtf8 index expected.%N");
  715.                   bad_class_file("Bad constant pool.",index + 1);
  716.                end;
  717.             else
  718.                io.put_string("??%NClass index out of range.%N");
  719.                bad_class_file("Bad constant pool.",index + 1);
  720.             end;
  721.             Result := index + 5;
  722.          when Constant_utf8 then -- CONSTANT_Utf8 :
  723.             io.put_string("utf8: %"");
  724.             tmp_string.clear;
  725.             constant_pool.view_in(tmp_string,i);
  726.             io.put_string(tmp_string);
  727.             io.put_string("%"");
  728.             Result := index + 1 + cp_info.info.count;
  729.          end;
  730.       end;
  731.  
  732.    print_cp_info_fields_methods(index: INTEGER; info: STRING) is
  733.       require
  734.  
  735.       local
  736.          cp_info: CP_INFO;
  737.          class_idx, utf8_idx, name_and_type_idx: INTEGER;
  738.       do
  739.          class_idx := u2_to_integer(info.substring(1,2));
  740.          name_and_type_idx := u2_to_integer(info.substring(3,4));
  741.          if constant_pool.valid_index(class_idx) then
  742.             cp_info := constant_pool.item(class_idx);
  743.             if cp_info.tag.code = 7 then
  744.                utf8_idx := u2_to_integer(cp_info.info);
  745.                if constant_pool.valid_index(utf8_idx) then
  746.                   tmp_string.clear;
  747.                   constant_pool.view_in(tmp_string,class_idx);
  748.                   io.put_string(tmp_string);
  749.                   io.put_string(" name_and_type: ");
  750.                   if constant_pool.valid_index(name_and_type_idx) then
  751.                      tmp_string.clear;
  752.                      constant_pool.view_in(tmp_string,name_and_type_idx);
  753.                      io.put_string(tmp_string);
  754.                   else
  755.                      io.put_string("??%N*** Error: name_and_type_index expected.");
  756.                      bad_class_file("Bad constant pool.",index + 3);
  757.                   end;
  758.                else
  759.                   io.put_string("??%N*** Error: Class index expected.");
  760.                end;
  761.             else
  762.                io.put_string("%NClass index expected.%N");
  763.                bad_class_file("Bad constant pool.",index + 1);
  764.             end;
  765.          else
  766.             io.put_string("??%NClass index out of range.%N");
  767.             bad_class_file("Bad constant pool.",index + 1);
  768.          end;
  769.       end;
  770.  
  771. feature {NONE}
  772.  
  773.    print_field_info(index: INTEGER): INTEGER is
  774.       local
  775.          access_flags_idx, flag, name_idx: INTEGER;
  776.          descriptor_idx, field_attributes_count: INTEGER;
  777.       do
  778.          access_flags_idx := index;
  779.          Result := index + 2;
  780.          io.put_string("access flags (");
  781.          io.put_string(hexa2_at(access_flags_idx));
  782.          io.put_string("): ");
  783.          flag := bytes.item(access_flags_idx + 1);
  784.          inspect
  785.             flag \\ 10
  786.          when 1 then
  787.             io.put_string("public ");
  788.          when 2 then
  789.             io.put_string("private ");
  790.          when 4 then
  791.             io.put_string("protected ");
  792.          else
  793.          end;
  794.          if flag >= 10 then
  795.             if flag < 40 then
  796.                io.put_string("final");
  797.             elseif flag > 40 then
  798.                io.put_string("transient");
  799.             else
  800.                io.put_string("volatile");
  801.             end;
  802.          end;
  803.          io.put_string("%N");
  804.          io.put_string("Field name: ");
  805.          name_idx := u2_integer_at(Result);
  806.          Result := Result + 2;
  807.          if constant_pool.valid_index(name_idx) then
  808.             tmp_string.clear;
  809.             constant_pool.view_in(tmp_string,name_idx);
  810.             io.put_string(tmp_string);
  811.             descriptor_idx := u2_integer_at(Result);
  812.             Result := Result + 2;
  813.             io.put_string(" descriptor: ");
  814.             if constant_pool.valid_index(descriptor_idx) then
  815.                tmp_string.clear;
  816.                constant_pool.view_in(tmp_string,descriptor_idx);
  817.                io.put_string(tmp_string);
  818.                field_attributes_count := u2_integer_at(Result);
  819.                Result := Result + 2;
  820.                io.put_new_line;
  821.                io.put_string("Attributes count: ");
  822.                io.put_integer(field_attributes_count);
  823.                io.put_new_line;
  824.                from
  825.                until
  826.                   field_attributes_count = 0
  827.                loop
  828.                   Result := print_attribute_info(Result);
  829.                   field_attributes_count := field_attributes_count - 1;
  830.                end;
  831.             else
  832.                io.put_string("??%NDescriptor index out of range.%N");
  833.                bad_class_file("Bad constant pool.",Result - 2);
  834.             end;
  835.          else
  836.             io.put_string("??%NName index out of range.%N");
  837.             bad_class_file("Bad constant pool.",Result - 2);
  838.          end;
  839.       end;
  840.  
  841.    print_attribute_info(index: INTEGER): INTEGER is
  842.       local
  843.          attribute_name_idx, attribute_length: INTEGER;
  844.          attribute_name: STRING;
  845.          tmp: INTEGER;
  846.       do
  847.          attribute_name_idx := u2_integer_at(index);
  848.          Result := index + 2;
  849.          io.put_string("Attribute Name: ");
  850.          tmp_string.clear;
  851.          constant_pool.view_in(tmp_string,attribute_name_idx);
  852.          io.put_string(tmp_string);
  853.          attribute_name := tmp_string.twin;
  854.          attribute_length := u4_integer_at(Result);
  855.          Result := Result + 4;
  856.          io.put_string(" length: ");
  857.          io.put_integer(attribute_length);
  858.          io.put_character(' ');
  859.          if ("Code").is_equal(attribute_name) then
  860.             tmp := print_code_attribute(Result,attribute_length);
  861.             Result := Result + attribute_length;
  862.          else
  863.             io.put_string(" Ignored (skipped)%N");
  864.             Result := Result + attribute_length;
  865.          end;
  866.       end;
  867.  
  868.  
  869.    print_method_info(index: INTEGER): INTEGER is
  870.       local
  871.          access_flags_idx, flag, name_idx: INTEGER;
  872.          descriptor_idx, method_attributes_count: INTEGER;
  873.       do
  874.          access_flags_idx := index;
  875.          Result := index + 2;
  876.          io.put_string("access flags (");
  877.          io.put_string(hexa2_at(access_flags_idx));
  878.          io.put_string("): ");
  879.          flag := bytes.item(access_flags_idx + 1);
  880.          inspect
  881.             flag \\ 10
  882.          when 1 then
  883.             io.put_string("public ");
  884.          when 2 then
  885.             io.put_string("private ");
  886.          when 4 then
  887.             io.put_string("protected ");
  888.          else
  889.          end;
  890.          if flag >= 10 then
  891.             if flag < 40 then
  892.                io.put_string("final");
  893.             elseif flag > 40 then
  894.                io.put_string("transient");
  895.             else
  896.                io.put_string("volatile");
  897.             end;
  898.          end;
  899.          io.put_new_line;
  900.          name_idx := u2_integer_at(Result);
  901.          Result := Result + 2;
  902.          io.put_string("Method name: ");
  903.          tmp_string.clear;
  904.          constant_pool.view_in(tmp_string,name_idx);
  905.          io.put_string(tmp_string);
  906.          io.put_string(" descriptor: ");
  907.          descriptor_idx := u2_integer_at(Result);
  908.          Result := Result + 2;
  909.          tmp_string.clear;
  910.          constant_pool.view_in(tmp_string,descriptor_idx);
  911.          io.put_string(tmp_string);
  912.          io.put_new_line;
  913.          io.put_string("Attributes count: ");
  914.          method_attributes_count := u2_integer_at(Result);
  915.          Result := Result + 2;
  916.          io.put_integer(method_attributes_count);
  917.          io.put_new_line;
  918.          from
  919.          until
  920.             method_attributes_count = 0
  921.          loop
  922.             Result := print_attribute_info(Result);
  923.             method_attributes_count := method_attributes_count - 1;
  924.          end;
  925.       end;
  926.  
  927.    print_code_attribute(index, length: INTEGER): INTEGER is
  928.       local
  929.          code_length: INTEGER;
  930.          exception_table_length: INTEGER;
  931.          max_stack, max_locals: INTEGER;
  932.          -- idx: INTEGER;
  933.          local_attributes_count: INTEGER;
  934.       do
  935.          io.put_string("%Nmax_stack: ");
  936.          max_stack := u2_integer_at(index);
  937.          Result := index + 2;
  938.          io.put_integer(max_stack);
  939.          io.put_string(" max_locals: ");
  940.          max_locals := u2_integer_at(Result);
  941.          Result := Result + 2;
  942.          io.put_integer(max_locals);
  943.          io.put_string(" code_length: ");
  944.          code_length := u4_integer_at(Result);
  945.          Result := Result + 4;
  946.          io.put_integer(code_length);
  947.          io.put_new_line;
  948.          print_byte_code(Result,code_length);
  949.          Result := Result + code_length;
  950.          exception_table_length := u2_integer_at(Result);
  951.          Result := Result + 2;
  952.          io.put_string("Exception(s): ");
  953.          io.put_integer(exception_table_length);
  954.          io.put_new_line;
  955.          print_exception_table(Result,exception_table_length);
  956.          Result := Result + exception_table_length * 8;
  957.          io.put_string("Attributes count: ");
  958.          local_attributes_count := u2_integer_at(Result);
  959.          Result := Result + 2;
  960.          io.put_integer(local_attributes_count);
  961.          io.put_new_line;
  962.          from
  963.          until
  964.             local_attributes_count = 0
  965.          loop
  966.             Result := print_attribute_info(Result);
  967.             local_attributes_count := local_attributes_count - 1;
  968.          end;
  969.       end;
  970.  
  971.    inst_view(byte_idx: INTEGER; cp_idx_type: CHARACTER) is
  972.       local
  973.          cp_idx: INTEGER;
  974.          cp_info: CP_INFO;
  975.       do
  976.          cp_idx := u2_integer_at(byte_idx);
  977.          if constant_pool.valid_index(cp_idx) then
  978.             cp_info := constant_pool.item(cp_idx);
  979.             if cp_info.tag = cp_idx_type then
  980.                constant_pool.view_in(inst,cp_idx);
  981.             else
  982.                tmp_string.clear;
  983.                tmp_string.append("????%N");
  984.                tmp_string.append("Invalid type entry in constant pool at: ");
  985.                cp_idx.append_in(tmp_string);
  986.                tmp_string.append(" : ");
  987.                constant_pool.view_in(tmp_string,cp_idx);
  988.                tmp_string.append("%NExpected tag: ");
  989.                cp_idx_type.code.append_in(tmp_string);
  990.                tmp_string.append(" (");
  991.                cp_info_tag_name_in(cp_idx_type,tmp_string);
  992.                tmp_string.append(")%NActual   tag: ");
  993.                cp_info.tag.code.append_in(tmp_string);
  994.                tmp_string.append(" (");
  995.                cp_info_tag_name_in(cp_info.tag,tmp_string);
  996.                tmp_string.append(")%N");
  997.                io.put_string(tmp_string);
  998.                bad_class_file("Constant pool type index error.",byte_idx);
  999.             end;
  1000.          else
  1001.             io.put_string("????%N");
  1002.             bad_class_file("Valid index in constant pool expected.",byte_idx);
  1003.          end;
  1004.       end;
  1005.  
  1006.    u2sign_extended_view(str: STRING; idx: INTEGER) is
  1007.       local
  1008.          byte: INTEGER;
  1009.       do
  1010.          byte := bytes.item(idx);
  1011.          str.append(hexa1_at(idx));
  1012.          str.append(" (");
  1013.          if byte < 128 then
  1014.             byte.append_in(str);
  1015.          else
  1016.             (byte - 256).append_in(str)
  1017.          end;
  1018.          str.append(")");
  1019.       end;
  1020.  
  1021.    print_one_instruction(pc_idx, pc: INTEGER): INTEGER is
  1022.          -- Return the following `pc_idx'.
  1023.       local
  1024.          opcode: INTEGER;
  1025.          idx: INTEGER;
  1026.       do
  1027.          Result := pc_idx + 1;
  1028.          opcode := bytes.item(pc_idx);
  1029.          inspect
  1030.             opcode
  1031.          when 0 then
  1032.             inst_opcode("nop (Do nothing)");
  1033.          when 1 then
  1034.             inst_opcode("aconst_null (Push null)");
  1035.          when 2 then
  1036.             inst_opcode("iconst_m1 (Push int -1)");
  1037.          when 3 .. 8 then
  1038.             inst_opcode("iconst_");
  1039.             (opcode - 3).append_in(inst);
  1040.             inst.append(" (Push int ");
  1041.             (opcode - 3).append_in(inst);
  1042.             inst.extend(')');
  1043.          when 9 then
  1044.             inst_opcode("lconst_0 (Push long 0)");
  1045.          when 10 then
  1046.             inst_opcode("lconst_1 (Push long 1)");
  1047.          when 11 .. 13 then
  1048.             inst_opcode("fconst_");
  1049.             (opcode - 11).append_in(inst);
  1050.          when 14 .. 15 then
  1051.             inst_opcode("dconst_");
  1052.             (opcode - 14).append_in(inst);
  1053.          when 16 then
  1054.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1055.             inst_opcode("bipush ");
  1056.             u2sign_extended_view(inst,pc_idx + 1);
  1057.             Result := Result + 1;
  1058.          when 17 then
  1059.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1060.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1061.             inst_opcode("sipush ");
  1062.             inst.append(hexa2_at(pc_idx + 1));
  1063.             inst_opcode("(Push short with sign-extension)");
  1064.             Result := Result + 2;
  1065.          when 18 then
  1066.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1067.             idx := bytes.item(pc_idx + 1);
  1068.             inst_opcode("ldc at ");
  1069.             idx.append_in(inst);
  1070.             inst.append(" : ");
  1071.             if constant_pool.valid_index(idx) then
  1072.                constant_pool.view_in(inst,idx);
  1073.             else
  1074.                io.put_string("??%N");
  1075.                bad_class_file("Constant pool index out of range.",pc_idx + 1);
  1076.             end;
  1077.             Result := Result + 1;
  1078.          when 19 then
  1079.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1080.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1081.             inst_opcode("ldc_w ");
  1082.             idx := u2_integer_at(pc_idx + 1);
  1083.             if constant_pool.valid_index(idx) then
  1084.                constant_pool.view_in(inst,idx);
  1085.             else
  1086.                io.put_string("????%N");
  1087.                bad_class_file("Constant pool index out of range.",pc_idx + 1);
  1088.             end;
  1089.             Result := Result + 2;
  1090.          when 20 then
  1091.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1092.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1093.             inst_opcode("ldc2_w ");
  1094.             idx := u2_integer_at(pc_idx + 1);
  1095.             if constant_pool.valid_index(idx) then
  1096.                constant_pool.view_in(inst,idx);
  1097.             else
  1098.                io.put_string("????%N");
  1099.                bad_class_file("CONSTANT_Long or CONSTANT_Double expected.",pc_idx + 1);
  1100.             end;
  1101.             Result := Result + 2;
  1102.          when 21 then
  1103.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1104.             inst_opcode("iload ");
  1105.             bytes.item(pc_idx + 1).append_in(inst);
  1106.             inst.append(" (load int from local #");
  1107.             bytes.item(pc_idx + 1).append_in(inst);
  1108.             inst.extend(')');
  1109.             Result := Result + 1;
  1110.          when 22 then
  1111.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1112.             inst_opcode("lload ");
  1113.             bytes.item(pc_idx + 1).append_in(inst);
  1114.             inst.append(" (load long from local #");
  1115.             bytes.item(pc_idx + 1).append_in(inst);
  1116.             inst.extend(')');
  1117.             Result := Result + 1;
  1118.          when 23 then
  1119.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1120.             inst_opcode("fload ");
  1121.             bytes.item(pc_idx + 1).append_in(inst);
  1122.             inst.append(" (load float from local #");
  1123.             bytes.item(pc_idx + 1).append_in(inst);
  1124.             inst.extend(')');
  1125.             Result := Result + 1;
  1126.          when 24 then
  1127.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1128.             inst_opcode("dload ");
  1129.             bytes.item(pc_idx + 1).append_in(inst);
  1130.             inst.append(" (load double from local #");
  1131.             bytes.item(pc_idx + 1).append_in(inst);
  1132.             inst.extend(')');
  1133.             Result := Result + 1;
  1134.          when 25 then
  1135.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1136.             inst_opcode("aload ");
  1137.             bytes.item(pc_idx + 1).append_in(inst);
  1138.             inst.append(" (load reference from local #");
  1139.             bytes.item(pc_idx + 1).append_in(inst);
  1140.             inst.extend(')');
  1141.             Result := Result + 1;
  1142.          when 26 .. 29 then
  1143.             inst_opcode("iload_");
  1144.             (opcode - 26).append_in(inst);
  1145.             inst.append(" (load int from local #");
  1146.             (opcode - 26).append_in(inst);
  1147.             inst.extend(')');
  1148.          when 30 .. 33 then
  1149.             inst_opcode("lload_");
  1150.             (opcode - 30).append_in(inst);
  1151.             inst.append(" (load long from local #");
  1152.             (opcode - 30).append_in(inst);
  1153.             inst.extend(')');
  1154.          when 34 .. 37 then
  1155.             inst_opcode("fload_");
  1156.             (opcode - 34).append_in(inst);
  1157.             inst.append(" (load float from local #");
  1158.             (opcode - 34).append_in(inst);
  1159.             inst.extend(')');
  1160.          when 38 .. 41 then
  1161.             inst_opcode("dload_");
  1162.             (opcode - 38).append_in(inst);
  1163.             inst.append(" (load double from local #");
  1164.             (opcode - 38).append_in(inst);
  1165.             inst.extend(')');
  1166.          when 42 .. 45 then
  1167.             inst_opcode("aload_");
  1168.             (opcode - 42).append_in(inst);
  1169.             inst.append(" (load reference from local #");
  1170.             (opcode - 42).append_in(inst);
  1171.             inst.extend(')');
  1172.          when 46 then
  1173.             inst_opcode("iaload");
  1174.          when 47 then
  1175.             inst_opcode("laload");
  1176.          when 48 then
  1177.             inst_opcode("faload");
  1178.          when 49 then
  1179.             inst_opcode("daload");
  1180.          when 50 then
  1181.             inst_opcode("aaload");
  1182.          when 51 then
  1183.             inst_opcode("baload");
  1184.          when 52 then
  1185.             inst_opcode("caload");
  1186.          when 53 then
  1187.             inst_opcode("saload");
  1188.          when 54 then
  1189.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1190.             inst_opcode("istore ");
  1191.             bytes.item(pc_idx + 1).append_in(inst);
  1192.             inst.append(" (store int into local #");
  1193.             bytes.item(pc_idx + 1).append_in(inst);
  1194.             inst.extend(')');
  1195.             Result := Result + 1;
  1196.          when 55 then
  1197.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1198.             inst_opcode("lstore ");
  1199.             bytes.item(pc_idx + 1).append_in(inst);
  1200.             inst.append(" (store long into local #");
  1201.             bytes.item(pc_idx + 1).append_in(inst);
  1202.             inst.extend(')');
  1203.             Result := Result + 1;
  1204.          when 56 then
  1205.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1206.             inst_opcode("fstore ");
  1207.             bytes.item(pc_idx + 1).append_in(inst);
  1208.             inst.append(" (store float into local #");
  1209.             bytes.item(pc_idx + 1).append_in(inst);
  1210.             inst.extend(')');
  1211.             Result := Result + 1;
  1212.          when 57 then
  1213.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1214.             inst_opcode("dstore ");
  1215.             bytes.item(pc_idx + 1).append_in(inst);
  1216.             inst.append(" (store double into local #");
  1217.             bytes.item(pc_idx + 1).append_in(inst);
  1218.             inst.extend(')');
  1219.             Result := Result + 1;
  1220.          when 58 then
  1221.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1222.             inst_opcode("astore ");
  1223.             bytes.item(pc_idx + 1).append_in(inst);
  1224.             inst.append(" (store reference into local #");
  1225.             bytes.item(pc_idx + 1).append_in(inst);
  1226.             inst.extend(')');
  1227.             Result := Result + 1;
  1228.          when 59 .. 62 then
  1229.             inst_opcode("istore_");
  1230.             (opcode - 59).append_in(inst);
  1231.          when 63 .. 66 then
  1232.             inst_opcode("lstore_");
  1233.             (opcode - 63).append_in(inst);
  1234.             inst.append(" (store long into local #");
  1235.             (opcode - 63).append_in(inst);
  1236.             inst.extend(')');
  1237.          when 67 .. 70 then
  1238.             inst_opcode("fstore_");
  1239.             (opcode - 67).append_in(inst);
  1240.             inst.append(" (store float into local #");
  1241.             (opcode - 67).append_in(inst);
  1242.             inst.extend(')');
  1243.          when 71 .. 74 then
  1244.             inst_opcode("dstore_");
  1245.             (opcode - 71).append_in(inst);
  1246.             inst.append(" (store double into local #");
  1247.             (opcode - 71).append_in(inst);
  1248.             inst.extend(')');
  1249.          when 75 .. 78 then
  1250.             inst_opcode("astore_");
  1251.             (opcode - 75).append_in(inst);
  1252.             inst.append(" (store reference into local #");
  1253.             (opcode - 75).append_in(inst);
  1254.             inst.extend(')');
  1255.          when 79 then
  1256.             inst_opcode("iastore");
  1257.          when 80 then
  1258.             inst_opcode("lastore");
  1259.          when 81 then
  1260.             inst_opcode("fastore");
  1261.          when 82 then
  1262.             inst_opcode("dastore");
  1263.          when 83 then
  1264.             inst_opcode("aastore");
  1265.          when 84 then
  1266.             inst_opcode("bastore");
  1267.          when 85 then
  1268.             inst_opcode("castore");
  1269.          when 86 then
  1270.             inst_opcode("sastore");
  1271.          when 87 then
  1272.             inst_opcode("pop (...,w => ...)");
  1273.          when 88 then
  1274.             inst_opcode("pop2 (...,w1,w2 => ...)");
  1275.          when 89 then
  1276.             inst_opcode("dup (...,w => ...,w,w)");
  1277.          when 90 then
  1278.             inst_opcode("dup_x1 (...,w2,w1 => ...,w1,w2,w1)");
  1279.          when 91 then
  1280.             inst_opcode("dup_x2 (...,w3,w2,w1 => ...,w1,w3,w2,w1)");
  1281.          when 92 then
  1282.             inst_opcode("dup2 (...,w2,w1 => ...,w2,w1,w2,w1)");
  1283.          when 93 then
  1284.             inst_opcode("dup2_x1 (...,w3,w2,w1 => ...,w2,w1,w3,w2,w1)");
  1285.          when 94 then
  1286.             inst_opcode("dup2_x2 (...,w4,w3,w2,w1 => ...,w2,w1,w4,w3,w2,w1)");
  1287.          when 95 then
  1288.             inst_opcode("swap (...,w2,w1 => ...,w1,w2)");
  1289.          when 96 then
  1290.             inst_opcode("iadd");
  1291.          when 97 then
  1292.             inst_opcode("ladd");
  1293.          when 98 then
  1294.             inst_opcode("fadd");
  1295.          when 99 then
  1296.             inst_opcode("dadd");
  1297.          when 100 then
  1298.             inst_opcode("isub");
  1299.          when 101 then
  1300.             inst_opcode("lsub");
  1301.          when 102 then
  1302.             inst_opcode("fsub");
  1303.          when 103 then
  1304.             inst_opcode("dsub");
  1305.          when 104 then
  1306.             inst_opcode("imul");
  1307.          when 105 then
  1308.             inst_opcode("lmul");
  1309.          when 106 then
  1310.             inst_opcode("fmul");
  1311.          when 107 then
  1312.             inst_opcode("dmul");
  1313.          when 108 then
  1314.             inst_opcode("idiv");
  1315.          when 109 then
  1316.             inst_opcode("ldiv");
  1317.          when 110 then
  1318.             inst_opcode("fdiv");
  1319.          when 111 then
  1320.             inst_opcode("ddiv");
  1321.          when 112 then
  1322.             inst_opcode("irem");
  1323.          when 116 then
  1324.             inst_opcode("ineg");
  1325.          when 117 then
  1326.             inst_opcode("lneg");
  1327.          when 118 then
  1328.             inst_opcode("fneg");
  1329.          when 119 then
  1330.             inst_opcode("dneg");
  1331.          when 120 then
  1332.             inst_opcode("ishl");
  1333.          when 124 then
  1334.             inst_opcode("iushr");
  1335.          when 126 then
  1336.             inst_opcode("iand");
  1337.          when 128 then
  1338.             inst_opcode("ior");
  1339.          when 130 then
  1340.             inst_opcode("ixor");
  1341.          when 132 then
  1342.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1343.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1344.             inst_opcode("iinc local #");
  1345.             bytes.item(pc_idx + 1).append_in(inst);
  1346.             inst.append(" with: :");
  1347.             inst.append(hexa1_at(pc_idx + 2));
  1348.             inst.append(" (sign-extended)");
  1349.             Result := Result + 2;
  1350.          when 133 then
  1351.             inst_opcode("i2l (Convert int to long)");
  1352.          when 134 then
  1353.             inst_opcode("i2f (Convert int to float)");
  1354.          when 135 then
  1355.             inst_opcode("i2d (Convert int to double)");
  1356.          when 136 then
  1357.             inst_opcode("l2i (Convert long to int)");
  1358.          when 137 then
  1359.             inst_opcode("l2f (Convert long to float)");
  1360.          when 138 then
  1361.             inst_opcode("l2d (Convert long to double)");
  1362.          when 139 then
  1363.             inst_opcode("f2i (Convert float to int)");
  1364.          when 140 then
  1365.             inst_opcode("f2l (Convert float to long)");
  1366.          when 141 then
  1367.             inst_opcode("f2d (Convert float to double)");
  1368.          when 142 then
  1369.             inst_opcode("d2i (Convert double to int)");
  1370.          when 143 then
  1371.             inst_opcode("d2l (Convert double to long)");
  1372.          when 144 then
  1373.             inst_opcode("d2f (Convert double to float)");
  1374.          when 145 then
  1375.             inst_opcode("i2b (Convert int to byte)");
  1376.          when 146 then
  1377.             inst_opcode("i2c (Convert int to char)");
  1378.          when 149 then
  1379.             inst_opcode("fcmpl");
  1380.          when 150 then
  1381.             inst_opcode("fcmpg");
  1382.          when 151 .. 152 then
  1383.             inst_opcode("dcmp");
  1384.             inspect
  1385.                opcode
  1386.             when 151 then
  1387.                inst.append("l");
  1388.             when 152 then
  1389.                inst.append("g");
  1390.             end;
  1391.          when 153 .. 158 then
  1392.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1393.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1394.             inst_opcode("if");
  1395.             inspect
  1396.                opcode
  1397.             when 153 then
  1398.                inst.append("eq");
  1399.             when 154 then
  1400.                inst.append("ne");
  1401.             when 155 then
  1402.                inst.append("lt");
  1403.             when 156 then
  1404.                inst.append("ge");
  1405.             when 157 then
  1406.                inst.append("gt");
  1407.             when 158 then
  1408.                inst.append("le");
  1409.             end;
  1410.             inst.extend(' ');
  1411.             view_pc(u2_integer_at(pc_idx + 1),pc);
  1412.             Result := Result + 2;
  1413.          when 159 .. 166 then
  1414.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1415.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1416.             inst_opcode("if_");
  1417.             inspect
  1418.                opcode
  1419.             when 159 .. 164 then
  1420.                inst.extend('i');
  1421.             else
  1422.                inst.extend('a');
  1423.             end;
  1424.             inst.append("cmp");
  1425.             inspect
  1426.                opcode
  1427.             when 159 then
  1428.                inst.append("eq");
  1429.             when 160 then
  1430.                inst.append("ne");
  1431.             when 161 then
  1432.                inst.append("lt");
  1433.             when 162 then
  1434.                inst.append("ge");
  1435.             when 163 then
  1436.                inst.append("gt");
  1437.             when 164 then
  1438.                inst.append("le");
  1439.             when 165 then
  1440.                inst.append("eq");
  1441.             when 166 then
  1442.                inst.append("ne");
  1443.             end;
  1444.             inst.extend(' ');
  1445.             view_pc(u2_integer_at(pc_idx + 1),pc);
  1446.             Result := Result + 2;
  1447.          when 167 then
  1448.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1449.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1450.             inst_opcode("goto ");
  1451.             view_pc(u2_integer_at(pc_idx + 1),pc);
  1452.             Result := Result + 2;
  1453.          when 172 then
  1454.             inst_opcode("ireturn");
  1455.          when 173 then
  1456.             inst_opcode("lreturn");
  1457.          when 174 then
  1458.             inst_opcode("freturn");
  1459.          when 175 then
  1460.             inst_opcode("dreturn");
  1461.          when 176 then
  1462.             inst_opcode("areturn");
  1463.          when 177 then
  1464.             inst_opcode("return");
  1465.          when 178 then
  1466.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1467.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1468.             inst_opcode("getstatic ");
  1469.             inst_view(pc_idx + 1,Constant_fieldref);
  1470.             Result := Result + 2;
  1471.          when 179 then
  1472.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1473.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1474.             inst_opcode("putstatic ");
  1475.             inst_view(pc_idx + 1,Constant_fieldref);
  1476.             Result := Result + 2;
  1477.          when 180 then
  1478.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1479.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1480.             inst_opcode("getfield ");
  1481.             inst_view(pc_idx + 1,Constant_fieldref);
  1482.             Result := Result + 2;
  1483.          when 181 then
  1484.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1485.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1486.             inst_opcode("putfield ");
  1487.             inst_view(pc_idx + 1,Constant_fieldref);
  1488.             Result := Result + 2;
  1489.          when 182 then
  1490.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1491.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1492.             inst_opcode("invokevirtual ");
  1493.             inst_view(pc_idx + 1,Constant_methodref);
  1494.             Result := Result + 2;
  1495.          when 183 then
  1496.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1497.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1498.             inst_opcode("invokespecial ");
  1499.             inst_view(pc_idx + 1,Constant_methodref);
  1500.             Result := Result + 2;
  1501.          when 184 then
  1502.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1503.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1504.             inst_opcode("invokestatic ");
  1505.             inst_view(pc_idx + 1,Constant_methodref);
  1506.             Result := Result + 2;
  1507.          when 185 then
  1508.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1509.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1510.             inst_opcode("invokeinterface ");
  1511.             inst_view(pc_idx + 1,Constant_interfacemethodref);
  1512.             Result := Result + 2;
  1513.          when 187 then
  1514.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1515.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1516.             inst_opcode("new ");
  1517.             inst_view(pc_idx + 1,Constant_class);
  1518.             Result := Result + 2;
  1519.          when 188 then
  1520.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1521.             inst_opcode("newarray of ");
  1522.             inspect
  1523.                bytes.item(pc_idx + 1)
  1524.             when 4 then
  1525.                inst.append("boolean");
  1526.             when 5 then
  1527.                inst.append("character");
  1528.             when 6 then
  1529.                inst.append("float");
  1530.             when 7 then
  1531.                inst.append("double");
  1532.             when 8 then
  1533.                inst.append("byte");
  1534.             when 9 then
  1535.                inst.append("short");
  1536.             when 10 then
  1537.                inst.append("int");
  1538.             when 11 then
  1539.                inst.append("long");
  1540.             else
  1541.                io.put_string("??%NInvalid newarray instruction.%N");
  1542.                bad_class_file("Bad array type.",pc_idx + 1);
  1543.             end;
  1544.             Result := Result + 1
  1545.          when 189 then
  1546.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1547.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1548.             inst_opcode("anewarray of ");
  1549.             inst_view(pc_idx + 1,Constant_class);
  1550.             Result := Result + 2;
  1551.          when 190 then
  1552.             inst_opcode("arraylength");
  1553.          when 191 then
  1554.             inst_opcode("athrow");
  1555.          when 192 then
  1556.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1557.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1558.             inst_opcode("checkcast ");
  1559.             inst_view(pc_idx + 1,Constant_class);
  1560.             Result := Result + 2;
  1561.          when 193 then
  1562.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1563.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1564.             inst_opcode("instanceof ");
  1565.             inst_view(pc_idx + 1,Constant_class);
  1566.             Result := Result + 2;
  1567.          when 198 then
  1568.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1569.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1570.             inst_opcode("ifnull ");
  1571.             view_pc(u2_integer_at(pc_idx + 1),pc);
  1572.             Result := Result + 2;
  1573.          when 199 then
  1574.             character_at(pc_idx + 1).to_hexadecimal_in(inst);
  1575.             character_at(pc_idx + 2).to_hexadecimal_in(inst);
  1576.             inst_opcode("ifnonnull ");
  1577.             view_pc(u2_integer_at(pc_idx + 1),pc);
  1578.             Result := Result + 2;
  1579.          else
  1580.             io.put_string(inst);
  1581.             io.put_new_line;
  1582.             io.put_string("Unknown Opcode: ");
  1583.             io.put_integer(opcode);
  1584.             io.put_string(" (0x");
  1585.             io.put_string(opcode.to_character.to_hexadecimal);
  1586.             io.put_string(")%N");
  1587.             bad_class_file("Unknown Opcode.",pc_idx);
  1588.          end;
  1589.       ensure
  1590.          Result >= pc_idx + 1
  1591.       end;
  1592.  
  1593.    print_byte_code(start_idx, length: INTEGER) is
  1594.          -- Print the byte code stored in range :
  1595.          --    [`start_idx' .. `start_idx' + `length']
  1596.       require
  1597.          bytes.valid_index(start_idx);
  1598.          length >= 0
  1599.       local
  1600.          pc_idx, pc: INTEGER;
  1601.       do
  1602.          from
  1603.             pc_idx := start_idx;
  1604.          until
  1605.             pc_idx = start_idx + length
  1606.          loop
  1607.             pc := pc_idx - start_idx;
  1608.             tmp_string.copy("  ");
  1609.             integer_to_hexa_in(pc,tmp_string);
  1610.             tmp_string.append("  ");
  1611.             pc.append_in(tmp_string);
  1612.             tmp_string.extend(' ');
  1613.             extend_string(tmp_string,' ',12);
  1614.             character_at(pc_idx).to_hexadecimal_in(tmp_string);
  1615.             io.put_string(tmp_string);
  1616.             inst.clear;
  1617.             pc_idx := print_one_instruction(pc_idx, pc_idx - start_idx);
  1618.             io.put_string(inst);
  1619.             io.put_new_line;
  1620.          end;
  1621.       end;
  1622.  
  1623.    print_exception_table(index, length: INTEGER) is
  1624.       local
  1625.          i, idx: INTEGER;
  1626.  
  1627.       do
  1628.          from
  1629.             i := length
  1630.           idx := index;
  1631.          until
  1632.             i = 0
  1633.          loop
  1634.             io.put_string("start:   ");
  1635.           io.put_integer(u2_integer_at(idx));
  1636.             io.put_string("%Nend:     ");
  1637.           io.put_integer(u2_integer_at(idx + 2));
  1638.             io.put_string("%Nhandler: ");
  1639.           io.put_integer(u2_integer_at(idx + 4));
  1640.             io.put_string("%Ntype:    ");
  1641.           io.put_integer(u2_integer_at(idx + 6));
  1642.           inst.copy("");
  1643.             inst_view(idx + 6, Constant_class);
  1644.           io.put_string(" (class ");
  1645.           io.put_string(inst);
  1646.           io.put_string(")%N");
  1647.             i := i - 1;
  1648.           idx := idx + 8;
  1649.          end;
  1650.       end;
  1651.  
  1652. feature {NONE}
  1653.  
  1654.    tmp_string: STRING is
  1655.       once
  1656.          !!Result.make(32);
  1657.       end;
  1658.  
  1659. feature {NONE}
  1660.  
  1661.    inst_opcode(msg: STRING) is
  1662.       do
  1663.          extend_string(inst,' ',4);
  1664.          inst.extend(' ');
  1665.          inst.append(msg);
  1666.       end;
  1667.  
  1668.    inst: STRING is
  1669.       once
  1670.          !!Result.make(80);
  1671.       end;
  1672.  
  1673. feature {NONE}
  1674.  
  1675.    view_pc(offset, pc: INTEGER) is
  1676.       local
  1677.          view: INTEGER;
  1678.          bits: BIT Integer_bits;
  1679.       do
  1680.          if offset < ((2 ^ 15) - 1) then
  1681.             view := pc + offset;
  1682.          else
  1683.             view := (offset - (2 ^ 16)) + pc;
  1684.          end;
  1685.          view.append_in(inst);
  1686.       end;
  1687.  
  1688. end -- PRINT_JVM_CLASS
  1689.  
  1690.