--          This file is part of SmallEiffel The GNU Eiffel Compiler.
--          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
--            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
--                       http://www.loria.fr/SmallEiffel
-- SmallEiffel 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. SmallEiffel 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  SmallEiffel;  see the file COPYING.  If not,
-- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-- Boston, MA 02111-1307, USA.
--
class MANIFEST_STRING
   --
   -- When using Manifest Constant STRING.
   --   
   
inherit EXPRESSION redefine is_manifest_string end;
   
creation {EIFFEL_PARSER} make

creation {CST_ATT_STRING} from_manifest_string

feature 
   
   start_position: POSITION;
	 -- Of the first character '%"'.
   
   to_string: STRING;
	 -- Eiffel contents of the string.
   
feature {NONE}
   
   break: ARRAY[INTEGER]; 
	 -- If not Void, places in `to_string' where extended notation (with
	 -- line(s) break) is used. The corresponding character in to string 
	 -- is put on next line.
   
   ascii: ARRAY[INTEGER];
	 -- If not Void, places in `to_string' where character are to be 
	 -- printed using asci code notation. 
   
   percent: ARRAY[INTEGER];
	 -- If not Void, places in `to_string' where character are to be 
	 -- printed using percent. 
		 
feature {MANIFEST_STRING,MANIFEST_STRING_POOL}
   
   mapping_c: STRING;
	 -- **** CHOISIR UN NOM COMMUM C/JVM ****
   
feature {NONE}
   
   make(sp: like start_position; numbering: INTEGER) is
      require
	 sp /= Void
      do
	 start_position := sp;
	 !!to_string.make(0);
	 !!mapping_c.make(12);
	 mapping_c.copy("ms");
	 numbering.append_in(mapping_c);
      ensure
	 start_position = sp
      end;

   from_manifest_string(model: like Current; numbering: INTEGER) is
      require 
	 model /= Void
      do
	 copy(model);
	 mapping_c := model.mapping_c.twin;
	 mapping_c.extend('_');
	 numbering.append_in(mapping_c);
      end;

feature 

   is_static          : BOOLEAN is false;     
   use_current        : BOOLEAN is false;     
   is_manifest_string : BOOLEAN is true;
   is_pre_computable  : BOOLEAN is true;
   c_simple           : BOOLEAN is true;
   can_be_dropped     : BOOLEAN is true;

   result_type: TYPE_STRING is
      do
	 Result := type_string;
      end;
   
   isa_dca_inline_argument: INTEGER is
      -- *** A FAIRE ??? ***
      do
      end;

   dca_inline_argument(formal_arg_type: TYPE) is
	 -- *** FAIRE ***
      do
      end;

   mapping_c_target(target_type: TYPE) is
      do
	 cpp.put_string(mapping_c);
      end;

   frozen mapping_c_arg(formal_arg_type: TYPE) is
      do
	 compile_to_c;
      end;

   compile_to_c is
      do
	 cpp.put_character('(');
	 cpp.put_string(fz_cast_t0_star);
	 cpp.put_string(mapping_c);
	 cpp.put_character(')');
      end;
   
   compile_to_c_old is do end;

   compile_to_jvm_old is do end;

   afd_check is do end;

   count: INTEGER is
      do
	 Result := to_string.count;
      end;
       
   compile_target_to_jvm, compile_to_jvm is
      local
	 idx: INTEGER;
      do
	 idx := fieldref_idx;
	 code_attribute.opcode_getstatic(idx,1);
      end;
   
   compile_to_jvm_assignment(a: ASSIGNMENT) is
      do
      end;
   
   jvm_branch_if_false: INTEGER is
      do
      end;

   jvm_branch_if_true: INTEGER is
      do
      end;
   
   compile_to_jvm_into(dest: TYPE): INTEGER is
      do
	 Result := 1;
	 compile_to_jvm;
      end;

   to_runnable(ct: TYPE): MANIFEST_STRING is
      local
	 bc: BASE_CLASS;
	 dummy: TYPE;
      do
	 dummy := type_string.to_runnable(ct);
	 if current_type = Void then
	    current_type := ct;
	    mapping_c.extend('_');
	    bc := start_position.base_class;
	    bc.id.append_in(mapping_c);
	    result_type.run_class.set_at_run_time;
	    manifest_string_pool.add_last(Current);
	    Result := Current;
	 else
	    Result := twin;
	    Result.set_current_type(ct);
	 end;
      end;
   
   precedence: INTEGER is
      do
	 Result := atomic_precedence;
      end;
   
   bracketed_pretty_print, pretty_print is
      local
	 i, column: INTEGER;
      do
	 from  
	    column := fmt.column;
	    fmt.put_character('%"');
	    i := 1;
	 until
	    i > to_string.count
	 loop
	    if is_on_next_line(i) then
	       fmt.put_string("%%%N");
	       from  
	       until
		  column = fmt.column
	       loop
		  fmt.put_character(' ');
	       end;
	       fmt.put_character('%%');
	    end;
	    pretty_print_character(i);
	    i := i + 1;
	 end;	 
	 fmt.put_character('%"');
      end;

   print_as_target is
      do
	 fmt.put_character('(');
	 pretty_print;
	 fmt.put_character(')');
	 fmt.put_character('.');
      end;

   short is
      local
	 i: INTEGER;
      do
	 short_print.hook_or("open_ms","%"");
	 from  
	    i := 1;
	 until
	    i > to_string.count
	 loop
	    short_character(i);
	    i := i + 1;
	 end;	 
	 short_print.hook_or("close_ms","%"");
      end;

   short_target is
      do
	 bracketed_short;
	 short_print.a_dot;
      end;
   
feature {EIFFEL_PARSER}
   
   add(ch: CHARACTER) is
	 -- Append `ch' to manifest string setting
	 -- ordinary printing mode.
      do
	 to_string.extend(ch);
      end;

   add_ascii(ch: CHARACTER) is
	 -- Append `ch' to manifest string setting
	 -- `ascii'  printing mode.
      do
	 to_string.extend(ch);
	 if ascii = Void then
	    ascii := <<to_string.count>>;
	 else
	    ascii.add_last(to_string.count);
	 end;
      end;

   add_percent(ch: CHARACTER) is
	 -- Append `ch' to manifest string setting
	 -- `percent'  printing mode.
      do
	 to_string.extend(ch);
	 if percent = Void then
	    percent := <<to_string.count>>;
	 else
	    percent.add_last(to_string.count);
	 end;
      end;

   break_line is
	 -- Next character will be a `break'.
      do
	 if break = Void then
	    break := <<to_string.count + 1>>;
	 else
	    break.add_last(to_string.count + 1);
	 end;
      end;
   
feature {NONE}   
   
   pretty_print_character(i: INTEGER) is
      require
	 1 <= i;
	 i <= count;
      local
	 val: INTEGER;
      do
	 if percent /= Void and then percent.fast_has(i) then
	    tmp_string.clear;
	    character_coding(to_string.item(i),tmp_string);
	    fmt.put_string(tmp_string);
	 elseif ascii /= Void and then ascii.fast_has(i) then
	    val := to_string.item(i).code;
	    fmt.put_string("%%/");
	    fmt.put_integer(val);
	    fmt.put_string(us_slash);
	 else
	    fmt.put_character(to_string.item(i));
	 end;
      end;

   short_character(i: INTEGER) is
      require
	 1 <= i;
	 i <= count;
      local
	 val: INTEGER;
	 second_slash: BOOLEAN;
	 c: CHARACTER;
      do
	 tmp_string.clear;
	 if percent /= Void and then percent.fast_has(i) then
	    character_coding(to_string.item(i),tmp_string);
	 elseif ascii /= Void and then ascii.fast_has(i) then
	    val := to_string.item(i).code;
	    tmp_string.append("%%/");
	    val.append_in(tmp_string);
	    tmp_string.append(us_slash);
	 end;
	 if tmp_string.count = 0 then
	    short_print.a_character(to_string.item(i));
	 else
	    from
	       val := 1;
	    until
	       val > tmp_string.count
	    loop
	       c := tmp_string.item(val);
	       if c = '%%' then
		  short_print.hook_or("Prcnt_ms","%%");
	       elseif c = '/' then
		  short_print.hook_or("Slash_ms",us_slash);
	       else
		  short_print.a_character(c);
	       end;
	       val := val + 1;
	    end;
	 end;
      end;
   
   is_on_next_line(i: INTEGER): BOOLEAN is 
      require
	 1 <= i;
	 i <= count;
      do
	 if break /= Void then
	    Result := break.fast_has(i);
	 end;
      end;
   
feature {NONE}
   
   tmp_string: STRING is
      once
	 !!Result.make(8);
      end;
 
feature {CREATION_CALL,EXPRESSION_WITH_COMMENT}
      
   jvm_assign is
      do
      end;

feature {MANIFEST_STRING_POOL}

   fieldref_idx: INTEGER is
      do
	 Result := constant_pool.idx_fieldref_for_manifest_string(mapping_c);
      end;

invariant
   
   start_position /= Void;

   to_string /= Void;

   mapping_c /= Void;

end -- MANIFEST_STRING

