--          This file is part of SmartEiffel The GNU Eiffel Compiler.
--       Copyright (C) 1994-2002 LORIA - INRIA - U.H.P. Nancy 1 - FRANCE
--          Dominique COLNET and Suzanne COLLIN - SmartEiffel@loria.fr
--                       http://SmartEiffel.loria.fr
-- SmartEiffel is  free  software;  you can  redistribute it and/or modify it
-- under the terms of the GNU General Public License as published by the Free
-- Software  Foundation;  either  version  2, or (at your option)  any  later
-- version. SmartEiffel is distributed in the hope that it will be useful,but
-- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
-- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
-- for  more  details.  You  should  have  received a copy of the GNU General
-- Public  License  along  with  SmartEiffel;  see the file COPYING.  If not,
-- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-- Boston, MA 02111-1307, USA.
--
class CP_INFO
   --
   -- Print a human readable version of a JVM *.class generated
   -- by SmartEiffel.
   --

inherit CP_INFO_TAGS

creation clear

feature {PRINT_JVM_CLASS}

   tag: CHARACTER; -- Must be one defined in CP_INFO_TAGS.

   info: STRING; -- Contains the corresponding information.

feature {CONSTANT_POOL}

   clear is
      do
         tag := Constant_empty
         if info = Void then
            !!info.make(4)
         else
            info.clear
         end
      end

   is_tagged(tag_value: CHARACTER): BOOLEAN is
      do
         Result := tag = tag_value
      end

feature

   set_class(i: STRING) is
      require
         i.count = 2
      do
         tag := Constant_class
         info.copy(i)
      end

   set_fieldref(i: STRING) is
      require
         i.count = 4
      do
         tag := Constant_fieldref
         info.copy(i)
      end

   set_methodref(i: STRING) is
      require
         i.count = 4
      do
         tag := Constant_methodref
         info.copy(i)
      end

   set_interface_methodref(i: STRING) is
      require
         i.count = 4
      do
         tag := Constant_interfacemethodref
         info.copy(i)
      end

   set_string(str: STRING) is
      require
         str.count >= 2
      local
         i: INTEGER
         c: CHARACTER
      do
         tag := Constant_string
         info.clear
         info.extend(str.item(1))
         info.extend(str.item(2))
         from
            i := 3
         until
            i > str.count
         loop
            c := str.item(i)
            if c = '%U' then
               info.extend('%/192/')
               info.extend('%/128/')
            else
               info.extend(c)
            end
            i := i + 1
         end
      end

   set_integer(i: STRING) is
      require
         i.count = 4
      do
         tag := Constant_integer
         info.copy(i)
      end

   set_float(i: STRING) is
      require
         i.count = 4
      do
         tag := Constant_float
         info.copy(i)
      end

   set_long(i: STRING) is
      require
         i.count = 8
      do
         tag := Constant_long
         info.copy(i)
      end

   set_double(i: STRING) is
      require
         i.count = 8
      do
         tag := Constant_double
         info.copy(i)
      end

   set_name_and_type(i: STRING) is
      require
         i.count = 4
      do
         tag := Constant_name_and_type
         info.copy(i)
      end

   set_utf8(i: STRING) is
      require
         i.count >= 2
      do
         tag := Constant_utf8
         info.copy(i)
      ensure
         info.count = u2_to_integer(1) + 2
      end

feature -- Testing :

   is_class: BOOLEAN is
      do
         Result := tag = Constant_class
      end

   is_fieldref: BOOLEAN is
      do
         Result := tag = Constant_fieldref
      end

   is_methodref: BOOLEAN is
      do
         Result := tag = Constant_methodref
      end

   is_interface_methodref: BOOLEAN is
      do
         Result := tag = Constant_interfacemethodref
      end

   is_string: BOOLEAN is
      do
         Result := tag = Constant_string
      end

   is_integer: BOOLEAN is
      do
         Result := tag = Constant_integer
      end

   is_float: BOOLEAN is
      do
         Result := tag = Constant_float
      end

   is_long: BOOLEAN is
      do
         Result := tag = Constant_long
      end

   is_double: BOOLEAN is
      do
         Result := tag = Constant_double
      end

   is_name_and_type: BOOLEAN is
      do
         Result := tag = Constant_name_and_type
      end

   is_utf8: BOOLEAN is
      do
         Result := tag = Constant_utf8
      end

feature

   view_in(str: STRING) is
         -- Append in `str' a human readable version.
         -- Note: assume `constant_pool' is checked.
      local
         idx, length, i: INTEGER
      do
         inspect
            tag
         when Constant_class then
            idx := u2_to_integer(1)
            constant_pool.view_in(str,idx)
         when Constant_fieldref then
            idx := u2_to_integer(1)
            constant_pool.view_in(str,idx)
            str.extend('.')
            idx := u2_to_integer(3)
            constant_pool.view_in(str,idx)
         when Constant_methodref then
            idx := u2_to_integer(1)
            constant_pool.view_in(str,idx)
            str.extend('.')
            idx := u2_to_integer(3)
            constant_pool.view_in(str,idx)
         when Constant_interfacemethodref then
         when Constant_string then
            idx := u2_to_integer(1)
            constant_pool.view_in(str,idx)
         when Constant_integer then
         when Constant_float then
         when Constant_long then
         when Constant_double then
         when Constant_name_and_type then
            idx := u2_to_integer(1)
            constant_pool.view_in(str,idx)
            str.extend(':')
            idx := u2_to_integer(3)
            constant_pool.view_in(str,idx)
         when Constant_utf8 then
            from
               length := u2_to_integer(1)
               i := 3
            until
               length = 0
            loop
               str.extend(info.item(i))
               i := i + 1
               length := length - 1
            end
         end
      end

feature {CONSTANT_POOL}

   b_put is
      do
         jvm.b_put_u1(tag)
         jvm.b_put_byte_string(info)
      end

feature {CONSTANT_POOL} -- Update and search :
   -- *** ACOMPLETER AU FUR ET A MESURE ***

   is_class_idx(utf8: INTEGER): BOOLEAN is
      do
         if Constant_class = tag then
            Result := u2_to_integer(1) = utf8
         end
      end

   is_fieldref_idx(c, nt: INTEGER): BOOLEAN is
      do
         if Constant_fieldref = tag then
            if u2_to_integer(1) = c then
               Result := u2_to_integer(3) = nt
            end
         end
      end

   is_methodref_idx(c, nt: INTEGER): BOOLEAN is
      do
         if Constant_methodref = tag then
            if u2_to_integer(1) = c then
               Result := u2_to_integer(3) = nt
            end
         end
      end

   is_name_and_type_idx(n, d: INTEGER): BOOLEAN is
      do
         if Constant_name_and_type = tag then
            if u2_to_integer(1) = n then
               Result := u2_to_integer(3) = d
            end
         end
      end

   is_string_idx(utf8: INTEGER): BOOLEAN is
      do
         if Constant_string = tag then
            Result := u2_to_integer(1) = utf8
         end
      end

   is_utf8_idx(contents: STRING): BOOLEAN is
      local
         i1, i2: INTEGER
      do
         if Constant_utf8 = tag then
            if u2_to_integer(1) = contents.count then
               from
                  i1 := contents.count + 1
                  i2 := info.count + 1
                  check
                     i1 + 2 = i2
                  end
                  Result := true
               until
                  not Result or else i1 = 1
               loop
                  i1 := i1 - 1
                  i2 := i2 - 1
                  Result := contents.item(i1) = info.item(i2)
               end
            end
         end
      end

feature {NONE}

   u2_to_integer(i: INTEGER): INTEGER is
      do
         Result := info.item(i).code * 256
         Result := Result + info.item(i + 1).code
      end

end -- CP_INFO

