home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 3
/
AACD03.BIN
/
AACD
/
Programming
/
sofa
/
archive
/
SmallEiffel.lha
/
SmallEiffel
/
lib_se
/
c_pretty_printer.e
< prev
next >
Wrap
Text File
|
1999-06-17
|
69KB
|
2,451 lines
-- 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://SmallEiffel.loria.fr
-- 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 C_PRETTY_PRINTER
--
-- Singleton in charge of handling C code pretty printing.
-- This singleton is shared via the GLOBALS.`cpp' once function.
--
inherit CODE_PRINTER;
creation make
feature {NONE}
make is
do
end;
feature
on_h: BOOLEAN is
require
small_eiffel.is_ready
do
Result := current_out = out_h;
end;
on_c: BOOLEAN is
require
small_eiffel.is_ready
do
Result := current_out = out_c;
end;
swap_on_c is
do
current_out := out_c;
ensure
on_c;
end;
swap_on_h is
do
current_out := out_h;
ensure
on_h;
end;
put_extern1(decl: STRING) is
do
incr_elt_c_count(5);
out_h.put_string(fz_extern);
out_h.put_string(decl);
out_h.put_string(fz_00);
out_c.put_string(decl);
out_c.put_string(fz_00);
end;
put_extern2(decl: STRING; init: CHARACTER) is
do
incr_elt_c_count(5);
out_h.put_string(fz_extern);
out_h.put_string(decl);
out_h.put_string(fz_00);
out_c.put_string(decl);
out_c.put_character('=');
out_c.put_character(init);
out_c.put_string(fz_00);
end;
put_extern3(var, value: STRING) is
do
incr_elt_c_count(5);
out_c.put_string("char ");
out_c.put_string(var);
out_c.put_string("[]=%"");
out_c.put_string(value);
out_c.put_string("%";%N");
out_h.put_string("extern char ");
out_h.put_string(var);
out_h.put_character('[');
out_h.put_character(']');
out_h.put_string(fz_00);
end;
put_extern4(t, var: STRING; value: INTEGER) is
do
incr_elt_c_count(5);
out_c.put_string(t);
out_c.put_character(' ');
out_c.put_string(var);
out_c.put_character('[');
out_c.put_integer(value);
out_c.put_string("];%N");
out_h.put_string(fz_extern);
out_h.put_string(t);
out_h.put_character(' ');
out_h.put_string(var);
out_h.put_character('[');
out_h.put_character(']');
out_h.put_string(fz_00);
end;
put_extern5(decl: STRING; init: STRING) is
do
incr_elt_c_count(5);
out_h.put_string(fz_extern);
out_h.put_string(decl);
out_h.put_string(fz_00);
out_c.put_string(decl);
out_c.put_character('=');
out_c.put_string(init);
out_c.put_string(fz_00);
end;
put_extern6(decl: STRING; init: INTEGER) is
do
incr_elt_c_count(5);
out_h.put_string(fz_extern);
out_h.put_string(decl);
out_h.put_string(fz_00);
out_c.put_string(decl);
out_c.put_character('=');
out_c.put_integer(init);
out_c.put_string(fz_00);
end;
put_extern7(decl: STRING) is
do
incr_elt_c_count(5);
out_h.put_string(fz_extern);
out_h.put_string(decl);
out_h.put_string(fz_00);
out_c.put_string(decl);
out_c.put_character('=');
end;
put_c_heading(heading: STRING) is
do
incr_elt_c_count(50);
out_h.put_string(heading);
out_h.put_string(fz_00);
out_c.put_string("%N%N");
out_c.put_string(heading);
out_c.put_string(fz_11);
end;
put_c_function(heading, body:STRING) is
require
not heading.empty;
body /= Void
do
put_c_heading(heading);
out_c.put_string(body);
out_c.put_string(fz_12);
end;
put_string(c: STRING) is
require
small_eiffel.is_ready
do
current_out.put_string(c);
end;
put_string_c(s: STRING) is
require
small_eiffel.is_ready;
on_c
do
tmp_string.clear;
manifest_string_pool.string_to_c_code(s,tmp_string);
out_c.put_string(tmp_string);
end;
put_character(c: CHARACTER) is
require
small_eiffel.is_ready
do
current_out.put_character(c);
end;
put_integer(i: INTEGER) is
require
small_eiffel.is_ready
do
current_out.put_integer(i);
end;
put_real(r: REAL) is
require
small_eiffel.is_ready
do
current_out.put_real(r);
end;
put_array1(array_name: CHARACTER; value: INTEGER) is
do
current_out.put_character(array_name);
current_out.put_character('[');
current_out.put_integer(value);
current_out.put_character(']');
end;
put_se_string_from_external_copy(c_string: STRING) is
do
current_out.put_string("se_string_from_external_copy(");
put_string_c(c_string);
current_out.put_character(')');
end;
put_position(p: POSITION) is
require
small_eiffel.is_ready
do
if p = Void then
put_string("0,0,0");
else
put_integer(p.line);
put_character(',');
put_integer(p.column);
put_character(',');
put_integer(p.base_class.id);
end;
end;
put_position_in_ds(p: POSITION) is
require
small_eiffel.is_ready
do
if p = Void then
out_c.put_string("ds.l=0;%Nds.c=0;%Nds.f=0;%N");
else
out_c.put_string("ds.l=");
out_c.put_integer(p.line);
out_c.put_string(";%Nds.c=");
out_c.put_integer(p.column);
out_c.put_string(";%Nds.f=");
out_c.put_integer(p.base_class.id);
out_c.put_string(fz_00);
end;
end;
put_target_as_target is
-- Produce C code to pass the current stacked target as
-- a target of a new call : user expanded are passed with
-- a pointer and class invariant code is produced.
require
small_eiffel.is_ready
local
code: INTEGER;
rf: RUN_FEATURE;
target: EXPRESSION;
args: EFFECTIVE_ARG_LIST;
ct: TYPE;
ivt_flag: BOOLEAN;
do
code := stack_code.item(top);
inspect
code
when C_direct_call then
target := stack_target.item(top);
rf := stack_rf.item(top);
ct := rf.current_type;
target.mapping_c_target(ct);
when C_check_id then
target := stack_target.item(top);
rf := stack_rf.item(top);
ct := rf.current_type;
check
ct.is_reference;
end;
if run_control.boost then
target.mapping_c_target(ct);
else
ivt_flag := call_invariant_start(ct);
check_id(target,rf.id);
if ivt_flag then
call_invariant_end;
end;
end;
when C_inline_dca then
put_character('(');
stack_rf.item(top).current_type.mapping_cast;
put_character('(');
put_target_as_value;
put_string(fz_13);
when C_same_target then
rf := stack_rf.item(top);
args := stack_args.item(top);
top := top - 1;
put_target_as_target;
top := top + 1;
stack_code.put(code,top);
stack_rf.put(rf,top);
stack_args.put(args,top);
else
common_put_target;
end;
end;
put_target_as_value is
-- Produce C code for a simple access to the stacked target.
-- User's expanded values are not given using a pointer.
-- There is no C code to check the class invariant.
require
small_eiffel.is_ready
local
code: INTEGER;
rf, static_rf: RUN_FEATURE;
target: EXPRESSION;
args: EFFECTIVE_ARG_LIST;
c0c: CALL_0_C;
direct_rf: RUN_FEATURE;
do
code := stack_code.item(top);
inspect
code
when C_direct_call then
stack_target.item(top).compile_to_c;
when C_check_id then
stack_rf.item(top).current_type.mapping_cast;
stack_target.item(top).compile_to_c;
when C_inline_dca then
rf := stack_rf.item(top);
target := stack_target.item(top);
args := stack_args.item(top);
static_rf := stack_static_rf.item(top);
top := top - 1;
c0c ?= target;
direct_rf := c0c.run_feature;
direct_rf.mapping_c;
top := top + 1;
stack_code.put(code,top);
stack_rf.put(rf,top);
stack_target.put(target,top);
stack_args.put(args,top);
stack_static_rf.put(static_rf,top);
when C_same_target then
rf := stack_rf.item(top);
args := stack_args.item(top);
top := top - 1;
put_target_as_value;
top := top + 1;
stack_code.put(code,top);
stack_rf.put(rf,top);
stack_args.put(args,top);
else
common_put_target;
end;
end;
put_error0(msg: STRING) is
-- Print `msg' and then stop execution.
-- Also print stack when not -boost.
do
put_string("error0(");
put_string_c(msg);
put_string(",NULL);%N");
end;
put_comment(str: STRING) is
do
put_string(fz_open_c_comment);
put_string(str);
put_string(fz_close_c_comment);
end;
put_comment_line(str: STRING) is
do
put_character('%N');
put_comment(str);
put_character('%N');
end;
define_main(rf3: RUN_FEATURE_3) is
do
swap_on_c;
-- Declare eiffel_root_object :
tmp_string.clear;
tmp_string.extend('T');
rf3.run_class.id.append_in(tmp_string);
tmp_string.append("*eiffel_root_object");
put_extern5(tmp_string,fz_null);
--
put_extern1("int se_argc");
put_extern1("char**se_argv");
define_initialize_eiffel_runtime(rf3);
if not no_main then
really_define_c_main(rf3);
end;
incr_elt_c_count(50);
end;
trace_boolean_expression(e: EXPRESSION) is
-- Produce a C boolean expression including trace code.
require
e.result_type.is_boolean;
run_control.no_check;
do
put_character('(');
se_trace_exp(e.start_position);
put_character(',');
e.compile_to_c;
put_character(')');
end;
feature {MANIFEST_STRING_POOL}
starting_manifest_string_definition(count: INTEGER) is
do
if count > 500 then
if elt_c_count > 1000 then
elt_c_count := elt_c_count_max;
end;
end;
end;
feature {SMALL_EIFFEL}
get_started is
require
small_eiffel.is_ready
local
no_check: BOOLEAN;
do
echo.file_removing(path_make);
no_check := run_control.no_check;
top := -1;
if no_split then
sfw_connect(out_c,path_c);
else
backup_sfw_connect(out_c,path_c);
end;
current_out := out_c;
add_first_include;
!!out_h.make;
sfw_connect(out_h,path_h);
current_out := out_h;
put_banner(out_h);
out_h.put_character('%N');
sys_runtime_h(fz_base);
current_out := out_c;
ensure
on_c
end;
cecil_define is
local
save_out_h: like out_h;
do
save_out_h := out_h;
cecil_pool.c_define_users;
out_h := save_out_h;
end;
define_used_basics is
-- Produce C code only when used.
local
no_check: BOOLEAN;
do
no_check := run_control.no_check;
echo.put_string("Define used basics.%N");
if sprintf_double_flag then
put_extern1("char*_spfd");
end;
if to_expanded_mem /= Void then
define_to_expanded;
end;
if to_reference_mem /= Void then
define_to_reference;
end;
bit_constant_definition;
if sure_void_count > 0 then
echo.put_string("Calls with a Void target : ");
echo.put_integer(sure_void_count);
echo.put_string(" (yes it is dangerous).%N");
end;
echo.print_count("Direct Call",direct_call_count);
echo.print_count("Check Id Call",check_id_count);
echo.print_count("Switched Call",switch_count);
echo.print_count("Inlined Procedure",inlined_procedure_count);
echo.print_count("Inlined Function",inlined_function_count);
echo.print_count("Static Expression",static_expression_count);
echo.print_count("Procedure",procedure_count);
echo.print_count("Function",function_count);
echo.print_count("Procedure without Current",real_procedure_count);
echo.print_count("Function without Current",real_function_count);
echo.print_count("Pre-Computed Once Function Call",
pre_computed_once.count);
echo.put_string("Internal stacks size used : ");
echo.put_integer(stack_code.count);
echo.put_character('%N');
end;
customize_runtime is
do
if run_control.no_check then
sys_runtime_h_and_c("no_check");
if run_control.trace then
put_extern2("int se_trace_flag",'0');
out_c.put_string("#define SE_TRACE 1%N");
end;
cpp.sys_runtime_h_and_c("trace");
else
cpp.sys_runtime_h_and_c("boost");
end;
if basic_directory_used then
cpp.sys_runtime_h_and_c("basic_directory");
end;
exceptions_handler.get_started;
end;
feature {RUN_FEATURE,NATIVE}
target_cannot_be_dropped: BOOLEAN is
-- True when top target cannot be dropped because we are
-- not sure that target is non Void or that target has
-- no side effects. When Result is true, printed
-- C code is : "(((void)(<target>))"
require
small_eiffel.is_ready
local
target: EXPRESSION;
target_type: TYPE;
do
inspect
stack_code.item(top)
when C_direct_call, C_check_id then
target := stack_target.item(top);
target_type := target.result_type;
Result := not target.can_be_dropped;
when C_inline_dca then
Result := true;
when C_same_target then
top := top - 1;
Result := target_cannot_be_dropped;
top := top + 1;
else
end;
if Result then
put_string("((/*UT*/(void)(");
if target_type = Void then
put_target_as_target;
elseif target_type.is_user_expanded then
put_target_as_value;
else
put_target_as_target;
end;
put_string(fz_13);
end;
end;
arguments_cannot_be_dropped: BOOLEAN is
-- True when arguments cannot be dropped.
-- Printed C code is like :
-- "(((void)<exp1>),((void)<exp2>),...((void)<expN>)"
do
if not no_args_to_eval then
Result := true;
put_string("((/*UA*/(void)(");
put_arguments;
put_string(fz_13);
end;
end;
cannot_drop_all: BOOLEAN is
-- Result is true when something (target or one argument)
-- cannot be dropped. Thus when something cannot be dropped,
-- Result is true and C code is printed :
-- "(((void)<exp1>),((void)<exp2>),...((void)<expN>)"
do
if target_cannot_be_dropped then
Result := true;
put_character(',');
if arguments_cannot_be_dropped then
put_character(')');
else
put_character('0');
end;
else
Result := arguments_cannot_be_dropped;
end;
end;
feature
put_arguments is
-- Produce code to access effective arguments list.
require
small_eiffel.is_ready
local
code: INTEGER;
rf, static_rf: RUN_FEATURE;
target: EXPRESSION;
args: EFFECTIVE_ARG_LIST;
fal: FORMAL_ARG_LIST;
switch: SWITCH;
do
code := stack_code.item(top);
inspect
code
when C_expanded_initialize then
when C_inside_twin then
put_ith_argument(1);
when C_direct_call then
fal := stack_rf.item(top).arguments;
stack_args.item(top).compile_to_c(fal);
when C_check_id then
fal := stack_rf.item(top).arguments;
stack_args.item(top).compile_to_c(fal);
when C_switch then
fal := stack_rf.item(top).arguments;
static_rf := stack_static_rf.item(top);
switch.put_arguments(static_rf,fal);
when C_inside_new then
fal := stack_rf.item(top).arguments;
stack_args.item(top).compile_to_c(fal);
when C_inline_dca then
rf := stack_rf.item(top);
target := stack_target.item(top);
args := stack_args.item(top);
static_rf := stack_static_rf.item(top);
top := top - 1;
args.dca_inline(rf.arguments);
top := top + 1;
stack_code.put(code,top);
stack_rf.put(rf,top);
stack_target.put(target,top);
stack_args.put(args,top);
stack_static_rf.put(static_rf,top);
when C_same_target then
fal := stack_rf.item(top).arguments;
stack_args.item(top).compile_to_c(fal);
when C_inline_one_pc then
when C_precursor then
fal := stack_rf.item(top).arguments;
stack_args.item(top).compile_to_c(fal);
end;
end;
put_ith_argument(index: INTEGER) is
-- Produce code to access to the ith argument.
require
small_eiffel.is_ready
index >= 1
local
code: INTEGER;
rf, static_rf: RUN_FEATURE;
target: EXPRESSION;
args: EFFECTIVE_ARG_LIST;
fal: FORMAL_ARG_LIST;
switch: SWITCH;
do
code := stack_code.item(top);
inspect
code
when C_direct_call then
fal := stack_rf.item(top).arguments;
stack_args.item(top).compile_to_c_ith(fal,index);
when C_check_id then
fal := stack_rf.item(top).arguments;
stack_args.item(top).compile_to_c_ith(fal,index);
when C_switch then
fal := stack_rf.item(top).arguments;
static_rf := stack_static_rf.item(top);
switch.put_ith_argument(static_rf,fal,index);
when C_inside_new then
fal := stack_rf.item(top).arguments;
stack_args.item(top).compile_to_c_ith(fal,index);
when C_inline_dca then
rf := stack_rf.item(top);
target := stack_target.item(top);
args := stack_args.item(top);
static_rf := stack_static_rf.item(top);
top := top - 1;
if rf /= Void then
args.dca_inline_ith(rf.arguments,index);
else
-- No rf for "=" and "/=".
args.dca_inline_ith(static_rf.arguments,index);
end;
top := top + 1;
stack_code.put(code,top);
stack_rf.put(rf,top);
stack_target.put(target,top);
stack_args.put(args,top);
stack_static_rf.put(static_rf,top);
when C_same_target then
fal := stack_rf.item(top).arguments;
stack_args.item(top).compile_to_c_ith(fal,index);
when C_inline_one_pc then
print_argument(index);
when C_inside_twin then
check
index = 1
end;
if stack_rf.item(top).current_type.is_reference then
put_string("((T0*)C)");
else
put_string("*C");
end;
end;
end;
feature {NATIVE_SMALL_EIFFEL}
put_c_inline_h is
local
c_code: STRING;
do
c_code := get_inline_ms.to_string;
if not c_inline_h_mem.fast_has(c_code) then
c_inline_h_mem.add_last(c_code);
out_h.put_string(c_code);
out_h.put_character('%N');
end;
end;
put_c_inline_c is
local
c_code: MANIFEST_STRING;
do
c_code := get_inline_ms;
out_c.put_string(c_code.to_string);
end;
put_trace_switch is
do
if run_control.trace then
put_string("se_trace_flag=(");
put_ith_argument(1);
put_string(fz_14);
end;
end;
feature {NATIVE_SMALL_EIFFEL}
put_generating_type(t: TYPE) is
local
rc: RUN_CLASS;
do
put_string(fz_cast_t0_star);
put_character('(');
put_character('t');
put_character('[');
if t.is_reference then
rc := t.run_class;
if rc.is_tagged then
put_character('(');
put_target_as_value;
put_character(')');
put_string(fz_arrow_id);
else
put_integer(rc.id);
end;
else
put_integer(t.id);
end;
put_character(']');
put_character(')');
end;
put_generator(t: TYPE) is
require
t.is_run_type;
local
rc: RUN_CLASS;
do
put_string(fz_cast_t0_star);
put_character('(');
put_character('g');
put_character('[');
if t.is_reference then
rc := t.run_class;
if rc.is_tagged then
put_character('(');
put_target_as_value;
put_character(')');
put_string(fz_arrow_id);
else
put_integer(rc.id);
end;
else
put_integer(t.id);
end;
put_character(']');
put_character(')');
end;
put_to_pointer is
do
put_string("((void*)");
put_target_as_value;
put_character(')');
end;
put_object_size(t: TYPE) is
require
t.is_run_type;
local
tcbd: BOOLEAN;
do
tcbd := target_cannot_be_dropped;
if tcbd then
out_c.put_character(',');
end;
out_c.put_string("sizeof(T");
out_c.put_integer(t.id);
out_c.put_character(')');
if tcbd then
out_c.put_character(')');
end;
end;
feature {CECIL_POOL}
connect_cecil_out_h(user_path_h: STRING) is
do
!!out_h.make;
sfw_connect(out_h,user_path_h);
sys_runtime_h(fz_base);
out_h.put_string(
"extern void*eiffel_root_object;%N%N%
%typedef char* T9;%N%
%/* Available Eiffel routines via -cecil:%N*/%N");
end;
disconnect_cecil_out_h is
do
out_h.disconnect;
end;
feature {TYPE}
to_reference(src, dest: TYPE) is
-- Put the name of the corresponding conversion
-- fonction. Memorize arguments for later definition
-- of the function.
require
small_eiffel.is_ready;
src.is_expanded;
dest.is_reference;
local
src_rc, dest_rc: RUN_CLASS;
do
src_rc := src.run_class;
dest_rc := dest.run_class;
check
src_rc.at_run_time;
dest_rc.at_run_time;
end;
if to_reference_mem = Void then
to_reference_mem := <<src_rc,dest_rc>>;
elseif not to_reference_mem.fast_has(src_rc) then
to_reference_mem.add_last(src_rc);
to_reference_mem.add_last(dest_rc);
end;
tmp_string.clear;
conversion_name(dest_rc.id);
put_string(tmp_string);
end;
to_expanded(src, dest: TYPE) is
-- Put the name of the corresponding conversion
-- fonction. Memorize arguments for later definition
-- of the function.
require
small_eiffel.is_ready;
src.is_reference;
dest.is_expanded;
local
src_rc, dest_rc: RUN_CLASS;
do
src_rc := src.run_class;
dest_rc := dest.run_class;
check
src_rc.at_run_time;
dest_rc.at_run_time;
end;
if to_expanded_mem = Void then
to_expanded_mem := <<src_rc,dest_rc>>;
elseif not to_expanded_mem.fast_has(src_rc) then
to_expanded_mem.add_last(src_rc);
to_expanded_mem.add_last(dest_rc);
end;
tmp_string.clear;
conversion_name(dest_rc.id);
put_string(tmp_string);
end;
feature {CECIL_POOL,RUN_FEATURE}
push_direct(rf: RUN_FEATURE; t: EXPRESSION; args: EFFECTIVE_ARG_LIST) is
require
rf /= Void;
t /= Void
do
stack_push(C_direct_call);
stack_rf.put(rf,top);
stack_target.put(t,top);
stack_args.put(args,top);
direct_call_count := direct_call_count + 1;
end;
feature {RUN_FEATURE_8}
set_basic_directory_used is
do
basic_directory_used := true;
end;
feature {RUN_FEATURE_3}
push_inline_one_pc is
do
stack_push(C_inline_one_pc);
end;
feature {RUN_FEATURE_3,RUN_FEATURE_4}
push_inline_dca(relay_rf: RUN_FEATURE; dpca: CALL_PROC_CALL) is
-- Where `dpca' is inside `relay_rf'.
require
relay_rf /= Void;
dpca /= Void
do
stack_push(C_inline_dca);
stack_rf.put(dpca.run_feature,top);
stack_static_rf.put(relay_rf,top);
stack_target.put(dpca.target,top);
stack_args.put(dpca.arguments,top);
direct_call_count := direct_call_count + 1;
end;
push_same_target(rf: RUN_FEATURE; args: EFFECTIVE_ARG_LIST) is
require
rf /= Void
do
stack_push(C_same_target);
stack_rf.put(rf,top);
stack_args.put(args,top);
end;
feature {CECIL_POOL}
push_cpc(up_rf: RUN_FEATURE; r: ARRAY[RUN_CLASS];
t: EXPRESSION; args: EFFECTIVE_ARG_LIST) is
local
dyn_rf: RUN_FEATURE;
do
if r = Void then
push_void(up_rf,t,args);
up_rf.mapping_c;
pop;
elseif r.count = 1 then
dyn_rf := r.first.dynamic(up_rf);
push_check(dyn_rf,t,args);
dyn_rf.mapping_c;
pop;
else
use_switch(up_rf,r,t,args);
end;
end;
feature {SWITCH}
push_switch(rf, static_rf: RUN_FEATURE) is
require
rf /= Void;
static_rf /= Void;
rf.run_class.dynamic(static_rf) = rf
do
stack_push(C_switch);
stack_rf.put(rf,top);
stack_static_rf.put(static_rf,top);
end;
feature {CREATION_CALL_3_4,LOCAL_VAR_LIST}
expanded_writable(rf3: RUN_FEATURE_3; writable: EXPRESSION) is
-- Call the expanded initializer `rf3' using `writable'
-- as target.
require
rf3.current_type.is_expanded;
writable /= Void
do
stack_push(C_expanded_initialize);
stack_target.put(writable,top);
stack_rf.put(Void,top); -- *** UNNEEDED ???
direct_call_count := direct_call_count + 1;
rf3.mapping_c;
pop;
if call_invariant_start(rf3.current_type) then
put_character('&');
writable.compile_to_c;
call_invariant_end;
put_string(fz_00);
end;
end;
feature {CREATION_CALL}
push_new(rf: RUN_FEATURE; args: EFFECTIVE_ARG_LIST) is
require
rf /= Void;
do
stack_push(C_inside_new);
stack_rf.put(rf,top);
stack_args.put(args,top);
direct_call_count := direct_call_count + 1;
end;
feature {NATIVE}
inside_twin(cpy: RUN_FEATURE) is
do
stack_push(C_inside_twin);
stack_rf.put(cpy,top);
cpy.mapping_c;
pop;
end;
feature {E_FEATURE,RUN_FEATURE}
stupid_switch(up_rf: RUN_FEATURE): BOOLEAN is
require
small_eiffel.is_ready;
up_rf.run_class.running /= Void
local
r: ARRAY[RUN_CLASS];
do
r := up_rf.run_class.running;
if r.count > 1 then
Result := stupid_switch_n(up_rf,r);
else
Result := true;
end;
end;
feature {ASSERTION}
check_assertion(e: EXPRESSION; tag_name: TAG_NAME) is
-- Produce a C boolean expression including trace code
-- and assertion check.
require
e.result_type.is_boolean
do
se_trace_ins(e.start_position);
put_string("ac_");
put_string(check_assertion_mode);
put_character('(');
if e.is_static then
static_expression_count := static_expression_count + 1;
end;
e.compile_to_c;
put_character(',');
if tag_name /= Void then
put_string_c(tag_name.to_string);
else
put_string(fz_null);
end;
put_string(fz_14);
end;
feature {ASSERTION_LIST}
set_check_assertion_mode(s: STRING) is
require
s /= Void
do
check_assertion_mode := s;
ensure
check_assertion_mode = s
end;
increment_static_expression_count(increment: INTEGER) is
do
static_expression_count := static_expression_count + increment;
end;
feature
se_trace_ins(p: POSITION) is
do
if run_control.no_check then
se_trace_exp(p);
out_c.put_string(fz_00);
end;
end;
se_trace_exp(p: POSITION) is
do
if run_control.no_check then
out_c.put_string("se_trace(&ds,");
put_position(p);
out_c.put_character(')');
end;
end;
feature -- Numbering of inspect variables :
inspect_incr is
do
inspect_level := inspect_level + 1;
end;
inspect_decr is
do
inspect_level := inspect_level - 1;
end;
put_inspect is
do
put_character('z');
put_integer(inspect_level);
end;
feature -- Printing Current, local or argument :
inline_level_incr is
do
inline_level := inline_level + 1;
end;
inline_level_decr is
do
inline_level := inline_level - 1;
end;
print_current is
local
level: INTEGER;
do
put_character('C');
level := inline_level;
if level > 0 then
put_integer(level);
end;
end;
print_argument(rank: INTEGER) is
local
code: INTEGER;
do
code := ('a').code + inline_level;
put_character(code.to_character);
put_integer(rank);
end;
print_local(name: STRING) is
local
level: INTEGER;
do
from
level := inline_level + 1;
until
level = 0
loop
put_character('_');
level := level - 1;
end;
put_string(name);
end;
feature {E_LOOP}
variant_check(e: EXPRESSION) is
do
se_trace_ins(e.start_position);
put_string("v=ac_lvc(c++,v,");
e.compile_to_c;
put_string(fz_14);
end;
feature {RUN_FEATURE}
current_class_invariant(current_type: TYPE) is
-- Add some C code to check class invariant with Current
-- at the end of a routine for `Current'.
require
current_type.is_run_type
local
rc: RUN_CLASS;
do
rc := need_invariant(current_type);
if rc /= Void then
if rc.current_type.is_reference then
out_c.put_string("if(se_rci(C))");
end;
out_c.put_string(fz_se_i);
out_c.put_integer(rc.id);
out_c.put_string("(&ds,C);%N");
end;
end;
feature
call_invariant_start(target_type: TYPE): BOOLEAN is
-- Start printing call of invariant only when it is needed
-- (`target_type' really has an invariant and when mode is
-- `-invariant_check').
-- When Result is true, `call_invariant_end' must be called to
-- finish the job.
require
target_type.is_run_type;
local
rc: RUN_CLASS;
do
rc := need_invariant(target_type);
if rc /= Void then
out_c.put_string(fz_se_i);
out_c.put_integer(rc.id);
out_c.put_string("(&ds,");
Result := true;
end;
end;
call_invariant_end is
do
out_c.put_character(')');
end;
feature
macro_def(str: STRING; id: INTEGER) is
do
tmp_string.clear;
tmp_string.extend('#');
tmp_string.append(fz_define);
tmp_string.extend(' ');
tmp_string.append(str);
tmp_string.extend(' ');
id.append_in(tmp_string);
tmp_string.extend('%N');
out_h.put_string(tmp_string);
end;
feature {CREATION_CALL}
expanded_attributes(rt: TYPE) is
-- Produce C code to initialize expanded attribute
-- of the new object juste created in variable "n".
require
small_eiffel.is_ready;
rt.is_run_type
local
wa: ARRAY[RUN_FEATURE];
a: RUN_FEATURE;
at: TYPE;
i: INTEGER;
rf3: RUN_FEATURE_3;
do
wa := rt.run_class.writable_attributes;
if wa /= Void then
from
i := wa.upper;
until
i = 0
loop
a := wa.item(i);
at := a.result_type.run_type;
rf3 := at.expanded_initializer;
if rf3 /= Void then
stack_push(C_expanded_initialize);
stack_target.put(Void,top);
stack_rf.put(a,top);
direct_call_count := direct_call_count + 1;
rf3.mapping_c;
pop;
end;
i := i - 1;
end;
end;
end;
feature
set_no_split is
do
no_split := true;
end;
write_make_file is
local
score: DOUBLE;
do
out_h.put_character('%N');
out_h.disconnect;
out_c.put_character('%N');
out_c.disconnect;
sfw_connect(out_make,path_make);
if no_split then
write_make_file_no_split;
else
write_make_file_split;
end;
if system_tools.strip_executable(tmp_string) then
echo_make;
end;
out_make.disconnect;
if nb_errors > 0 then
echo.file_removing(path_make);
else
echo.put_string("Type inference score : ");
score := direct_call_count + check_id_count;
score := (score / (score + switch_count)) * 100.0;
echo.put_double_format(score,2);
echo.put_character('%%');
echo.put_character('%N');
end;
eiffel_parser.show_nb_warnings;
eiffel_parser.show_nb_errors;
echo.put_string(fz_02);
end;
feature {C_PRETTY_PRINTER}
no_split: BOOLEAN;
feature {CALL_PROC_CALL}
put_cpc(cpc: CALL_PROC_CALL) is
local
target: EXPRESSION;
target_type: TYPE;
run_feature: RUN_FEATURE;
do
target := cpc.target;
target_type := target.result_type.run_type;
run_feature := cpc.run_feature;
if target_type.is_expanded then
push_direct(run_feature,target,cpc.arguments);
run_feature.mapping_c;
pop;
elseif target.is_current then
push_direct(run_feature,target,cpc.arguments);
run_feature.mapping_c;
pop;
elseif target.is_manifest_string then
push_direct(run_feature,target,cpc.arguments);
run_feature.mapping_c;
pop;
else
push_cpc(run_feature,
target_type.run_class.running,
target,
cpc.arguments);
end;
end;
feature {NATIVE_SMALL_EIFFEL}
sprintf_double_is_used is
do
sprintf_double_flag := true;
end;
feature
sys_runtime_h(name: STRING) is
-- Inline corresponding SmallEiffel/sys/runtime/`name'.h file.
require
name /= Void
do
system_tools.sys_runtime(name,'h');
put_file(tmp_file_read,out_h);
end;
sys_runtime_c(name: STRING) is
-- Inline corresponding SmallEiffel/sys/runtime/`name'.c file.
require
name /= Void
do
system_tools.sys_runtime(name,'c');
put_file(tmp_file_read,out_c);
end;
sys_runtime_h_and_c(name: STRING) is
do
sys_runtime_h(name);
sys_runtime_c(name);
end;
feature {SYSTEM_TOOLS}
echo_make is
do
out_make.put_string(tmp_string);
out_make.put_character('%N');
end;
put_c_file(sfr: STD_FILE_READ) is
require
not sfr.end_of_input
do
put_file(sfr,out_c);
ensure
not sfr.is_connected
end;
feature
put_recompilation_comment(key: INTEGER) is
do
out_c.put_string(fz_open_c_comment);
out_c.put_integer(key);
out_c.put_string(fz_close_c_comment);
end;
feature
no_main: BOOLEAN;
set_no_main is
do
no_main := true;
ensure
no_main
end;
set_c_size (value: INTEGER) is
do
elt_c_size := value;
end;
set_c_count_max (value: INTEGER) is
do
elt_c_count_max := value;
end;
feature {COMPOUND,ASSERTION_LIST}
se_tmp_open_declaration: BOOLEAN is
-- True if some `se_tmpXX' is needed.
local
i: INTEGER;
rf: RUN_FEATURE;
do
from
tmp_string.copy(fz_11);
i := se_tmp_list.upper;
until
i < 0
loop
rf := se_tmp_list.item(i);
if rf /= Void then
Result := true;
rf.result_type.c_type_for_result_in(tmp_string);
tmp_string.append(" se_tmp");
i.append_in(tmp_string);
tmp_string.append(fz_00);
end;
i := i - 1;
end;
if Result then
se_tmp_level := se_tmp_level + 1;
out_c.put_string(tmp_string);
end;
end;
se_tmp_close_declaration is
do
check
se_tmp_level > 0
end;
se_tmp_level := se_tmp_level - 1;
out_c.put_string(fz_12);
if se_tmp_level = 0 then
se_tmp_list.clear;
end;
end;
feature {RUN_FEATURE_4, RUN_FEATURE_11}
se_tmp_add(rf: RUN_FEATURE) is
do
se_tmp_list.add_last(rf);
end;
se_tmp_open(rf: RUN_FEATURE): INTEGER is
-- Result >= 0 implies a temporary variable is used and thus
-- `se_tmp_close' must be called.
-- Result < 0 indicate that no temporary variable is mandatory.
local
rt: TYPE;
do
rt := rf.result_type;
if rt.is_user_expanded and then not rt.is_dummy_expanded then
Result := se_tmp_list.fast_index_of(rf);
check
se_tmp_list.valid_index(Result)
end;
se_tmp_list.put(Void,Result);
out_c.put_string("(*(se_tmp");
out_c.put_integer(Result);
out_c.put_character('=');
else
Result := -1
end;
end;
se_tmp_close(i: INTEGER) is
do
check
se_tmp_list.item(i) = Void
end;
out_c.put_string(",&se_tmp");
out_c.put_integer(i);
out_c.put_string(fz_13);
end;
feature {BIT_CONSTANT}
register_bit_constant(bc: BIT_CONSTANT) is
require
bc.result_type.is_c_unsigned_ptr
do
if bit_constant_pool = void then
!!bit_constant_pool.with_capacity(4);
end;
bit_constant_pool.add_last(bc);
out_c.put_string(fz_se_bit_constant);
out_c.put_integer(bit_constant_pool.upper);
end;
bit_constant_definition is
local
i: INTEGER;
bc: BIT_CONSTANT;
type_bit: TYPE_BIT;
do
if bit_constant_pool /= Void then
from
i := bit_constant_pool.upper;
until
i < 0
loop
tmp_string.clear;
bc := bit_constant_pool.item(i)
type_bit := bc.result_type;
tmp_string.clear;
type_bit.c_type_for_target_in(tmp_string);
tmp_string.extend(' ');
tmp_string.append(fz_se_bit_constant);
i.append_in(tmp_string);
put_extern7(tmp_string);
out_c.put_character('{');
bc.c_define;
out_c.put_character('}');
out_c.put_character(';');
out_c.put_character('%N');
i := i - 1;
end;
end;
end;
feature {RUN_CLASS}
finished_run_class is
-- Add some padding space.
do
if elt_c_count > elt_c_size then
elt_c_count := elt_c_count_max;
end;
end;
feature {SWITCH}
finished_switch(running_count: INTEGER) is
-- Add some padding space.
do
elt_c_count := elt_c_count + 4 * running_count;
end;
feature {NONE}
out_c: STD_FILE_WRITE is
-- The current *.c output file.
once
!!Result.make;
end;
out_h: STD_FILE_WRITE;
-- The *.h output file.
current_out: STD_FILE_WRITE;
-- Is `out_c' or `out_h'.
out_make: STD_FILE_WRITE is
-- The *.make output file.
once
!!Result.make;
end;
incr_elt_c_count(i: INTEGER) is
do
check
out_c.is_connected;
end;
if no_split then
else
elt_c_count := elt_c_count + i;
if elt_c_count >= elt_c_count_max then
elt_c_count := 0;
out_c.put_character('%N');
out_c.disconnect;
split_count := split_count + 1;
path_c_in(path_c,split_count);
backup_sfw_connect(out_c,path_c);
add_first_include;
if current_out /= out_h then
current_out := out_c;
end;
end;
end;
end;
no_args_to_eval: BOOLEAN is
-- True if there is no C code to produce to eval arguments.
-- For example because there are no arguments or because
-- we are inside a switching function for example.
require
small_eiffel.is_ready
local
code: INTEGER;
args: EFFECTIVE_ARG_LIST;
do
code := stack_code.item(top);
inspect
code
when C_direct_call,
C_check_id,
C_inside_new,
C_same_target
then
args := stack_args.item(top);
if args = Void then
Result := true;
else
Result := args.can_be_dropped;
end;
when C_inline_dca then
top := top - 1;
Result := no_args_to_eval;
top := top + 1;
else
Result := true;
end;
end;
c_inline_h_mem: FIXED_ARRAY[STRING] is
once
!!Result.with_capacity(4);
end;
to_expanded_mem, to_reference_mem: ARRAY[RUN_CLASS];
conversion_name(dest_id: INTEGER) is
do
tmp_string.append(fz_to_t);
dest_id.append_in(tmp_string);
end;
define_to_reference is
local
i: INTEGER;
src_rc, dest_rc: RUN_CLASS;
src_type, dest_type: TYPE;
do
from
i := 1;
until
i > to_reference_mem.upper
loop
src_rc := to_reference_mem.item(i);
i := i + 1;
dest_rc := to_reference_mem.item(i);
i := i + 1;
src_type := src_rc.current_type;
dest_type := dest_rc.current_type;
echo.put_string(msg2);
echo.put_string(src_type.run_time_mark);
echo.put_string(" to ");
echo.put_string(dest_type.run_time_mark);
echo.put_string(msg1);
tmp_string.copy(fz_t0_star);
conversion_name(dest_rc.id);
tmp_string.extend('(');
src_type.c_type_for_result_in(tmp_string);
tmp_string.append(" s)");
put_c_heading(tmp_string);
swap_on_c;
gc_handler.allocation(dest_rc);
if not src_type.is_dummy_expanded then
out_c.put_string("n->_item=s;%N");
end;
out_c.put_string("return (T0*)n;%N}%N");
end;
end;
define_to_expanded is
local
i: INTEGER;
src_rc, dest_rc: RUN_CLASS;
src_type, dest_type: TYPE;
do
from
i := 1;
until
i > to_expanded_mem.upper
loop
src_rc := to_expanded_mem.item(i);
i := i + 1;
dest_rc := to_expanded_mem.item(i);
i := i + 1;
src_type := src_rc.current_type;
dest_type := dest_rc.current_type;
echo.put_string(msg2);
echo.put_string(src_type.run_time_mark);
echo.put_string(" to ");
echo.put_string(dest_type.run_time_mark);
echo.put_string(msg1);
tmp_string.clear;
dest_type.c_type_for_result_in(tmp_string);
tmp_string.extend(' ');
conversion_name(dest_rc.id);
tmp_string.append("(T0*s)");
out_h.put_string(tmp_string);
out_h.put_string(fz_00);
out_c.put_string(tmp_string);
tmp_string.copy(fz_11);
-- NYI ...
tmp_string.append(fz_12);
out_c.put_string(tmp_string);
end;
end;
push_void(rf: RUN_FEATURE; target: EXPRESSION; args: EFFECTIVE_ARG_LIST) is
require
rf /= Void;
target /= Void
do
eh.add_position(target.start_position);
eh.append("Call on a Void or a bad target. Dynamic ");
eh.add_type(target.result_type.run_type," is concerned. ")
eh.print_as_warning;
if run_control.boost then
exceptions_handler.se_evobt;
else
put_string("se_evobt(");
target.compile_to_c;
put_character(',');
put_position(target.start_position);
put_string(fz_14);
end;
push_direct(rf,target,args);
sure_void_count := sure_void_count + 1;
end;
push_check(rf: RUN_FEATURE; t: EXPRESSION; args: EFFECTIVE_ARG_LIST) is
require
rf /= Void;
t /= Void;
do
stack_push(C_check_id);
stack_rf.put(rf,top);
stack_target.put(t,top);
stack_args.put(args,top);
end;
expanded_initializer(t: TYPE; a: RUN_FEATURE) is
-- ***** CHANGE THIS ******
-- Call the expanded initializer for type `t' if any.
-- The result is assigned in writable `w' or to attribute
-- `a' of the brand new created object in "n".
require
t.is_expanded;
a /= Void
local
rf: RUN_FEATURE;
do
rf := t.expanded_initializer;
if rf /= Void then
stack_push(C_expanded_initialize);
stack_target.put(Void,top);
stack_rf.put(a,top);
direct_call_count := direct_call_count + 1;
rf.mapping_c;
pop;
end;
end;
use_switch(up_rf: RUN_FEATURE; r: ARRAY[RUN_CLASS];
t: EXPRESSION; args: EFFECTIVE_ARG_LIST) is
require
up_rf /= Void;
r.count > 1
t /= Void;
on_c;
local
rt: TYPE;
rc: RUN_CLASS;
rf: RUN_FEATURE;
switch: SWITCH;
do
if run_control.boost and then stupid_switch(up_rf) then
direct_call_count := direct_call_count + 1;
switch_collection.remove(up_rf);
put_string(fz_open_c_comment);
put_character('X');
put_integer(up_rf.current_type.id);
put_string(up_rf.name.to_string);
put_string(fz_close_c_comment);
rt := up_rf.result_type;
if rt /= Void then
tmp_string.copy(fz_17);
rt.c_type_for_result_in(tmp_string);
tmp_string.extend(')');
put_string(tmp_string);
end;
rc := r.item(1);
rf := rc.dynamic(up_rf);
push_direct(rf,t,args);
rf.mapping_c;
pop;
if rt /= Void then
put_character(')');
end;
else
switch_count := switch_count + 1;
out_c.put_string(switch.name(up_rf));
out_c.put_character('(');
if run_control.no_check then
out_c.put_string("&ds,");
put_position(t.start_position)
out_c.put_character(',');
end;
t.compile_to_c;
if args /= Void then
out_c.put_character(',');
args.compile_to_c(up_rf.arguments);
end;
put_character(')');
if up_rf.result_type = Void then
out_c.put_string(fz_00);
end;
end;
end;
stupid_switch_n(up_rf: RUN_FEATURE; r: ARRAY[RUN_CLASS]): BOOLEAN is
require
small_eiffel.is_ready;
r.count > 1
local
i: INTEGER;
up_f: E_FEATURE;
dyn_rf: RUN_FEATURE;
rc: RUN_CLASS;
do
from
Result := true;
i := r.upper;
up_f := up_rf.base_feature;
until
not Result or else i = 0
loop
rc := r.item(i);
dyn_rf := rc.dynamic(up_rf);
if up_f = dyn_rf.base_feature then
if dyn_rf.name.to_string /= up_rf.name.to_string then
Result := false;
end;
else
Result := false;
end;
i := i - 1;
end;
if not Result then
Result := attribute_read_removal(up_rf,r);
if Result then
cpp.put_comment("SSWA2");
end;
end;
if Result then
Result := up_f.stupid_switch(up_rf,r);
end;
end;
attribute_read_removal(up_rf: RUN_FEATURE; r: ARRAY[RUN_CLASS]): BOOLEAN is
require
small_eiffel.is_ready;
r.count > 1
local
rf2a, rf2b: RUN_FEATURE_2;
offseta, offsetb: INTEGER;
rta, rtb: TYPE;
i: INTEGER;
rc: RUN_CLASS;
do
from
Result := true;
i := r.upper;
until
not Result or else i = 0
loop
rc := r.item(i);
rf2b ?= rc.dynamic(up_rf);
if rf2b /= Void then
offsetb := rc.offset_of(rf2b);
end;
if rf2a = Void then
rf2a := rf2b;
offseta := offsetb;
end;
if rf2b = Void then
Result := false;
else
Result := offseta = offsetb;
if Result then
rta := rf2a.result_type;
rtb := rf2b.result_type;
if rta.is_reference then
Result := rtb.is_reference;
elseif rta.run_time_mark = rtb.run_time_mark then
elseif rta.is_native_array then
if rta.generic_list.first.is_reference then
Result := rtb.generic_list.first.is_reference;
end;
else
Result := false;
end;
end
end;
i := i - 1;
end;
end;
define_initialize_eiffel_runtime(rf3: RUN_FEATURE_3) is
require
on_c
local
no_check: BOOLEAN;
rc: RUN_CLASS;
ct: TYPE;
do
no_check := run_control.no_check;
ct := rf3.current_type;
rc := rf3.run_class;
echo.put_string("Define initialize stuff.%N");
small_eiffel.define_extern_tables;
put_c_heading("void initialize_eiffel_runtime(int argc,char*argv[])");
if no_check then
out_c.put_string(
"se_frame_descriptor irfd={%"Initialysing runtime.%",0,0,%"%",1};%N%
%se_dump_stack ds = {NULL,NULL,0,0,0,NULL,NULL};%N%
%ds.fd=&irfd;%N%
%ds.caller=se_dst;%N");
end;
out_c.put_string("se_argc=argc;%Nse_argv=argv;%N");
gc_handler.initialize_runtime;
exceptions_handler.initialize_runtime;
if no_check then
small_eiffel.initialize_path_table;
end;
if run_control.generator_used then
small_eiffel.initialize_generator;
end;
if run_control.generating_type_used then
small_eiffel.initialize_generating_type;
end;
if not exceptions_handler.used then
out_c.put_string(
"#ifdef SIGINT%Nsignal(SIGINT,sigrsp);%N#endif%N%
%#ifdef SIGQUIT%Nsignal(SIGQUIT,sigrsp);%N#endif%N%
%#ifdef SIGTERM%Nsignal(SIGTERM,sigrsp);%N#endif%N%
%#ifdef SIGBREAK%Nsignal(SIGBREAK,sigrsp);%N#endif%N%
%#ifdef SIGKILL%Nsignal(SIGKILL,sigrsp);%N#endif%N");
end;
manifest_string_pool.c_call_initialize;
once_pre_computing;
if run_control.trace then
out_c.put_string("se_trace_flag=1;%N");
end;
if sprintf_double_flag then
out_c.put_string("_spfd=malloc(32);%N%
%_spfd[0]='%%';%N%
%_spfd[1]='.';%N");
end;
if not gc_handler.is_off then
out_c.put_string("gc_is_off=0;%N");
end;
gc_handler.allocation_of(fz_eiffel_root_object,rc);
if run_control.no_check then
out_c.put_string("se_dst=NULL;%N");
end;
out_c.put_string(fz_12);
ensure
on_c
end;
define_is_equal_prototype(id: INTEGER) is
do
tmp_string.copy("T6 r");
(id).append_in(tmp_string);
tmp_string.append(as_is_equal);
tmp_string.append("(T");
(id).append_in(tmp_string);
tmp_string.append("*C, T0*a1)");
out_h.put_string(tmp_string);
out_c.put_string(tmp_string);
end;
check_assertion_mode: STRING;
inspect_level: INTEGER;
inline_level: INTEGER;
check_id(e: EXPRESSION; id: INTEGER) is
-- Produce a C expression checking that `e' is not void and
-- that `e' is really of type `id'.
-- The result of the C expression is the pointer to the
-- corresponding Object.
require
e.result_type.run_type.is_reference;
id > 0;
do
if run_control.no_check then
put_string("((T");
put_integer(id);
put_string("*)ci(");
put_integer(id);
put_character(',');
e.compile_to_c;
put_character(',');
put_position(e.start_position);
put_string(fz_13);
check_id_count := check_id_count + 1;
else
e.compile_to_c;
direct_call_count := direct_call_count + 1;
end;
end;
same_base_feature(r: ARRAY[RUN_CLASS]; up_rf: RUN_FEATURE): BOOLEAN is
-- True if all have the same final name and the same base_feature.
require
not r.empty;
up_rf /= Void
local
i: INTEGER;
up_bf, bf: E_FEATURE;
up_name, name: FEATURE_NAME;
rf: RUN_FEATURE;
do
from
up_bf := up_rf.base_feature;
up_name := up_rf.name;
i := r.lower;
Result := true;
until
not Result or else i > r.upper
loop
rf := r.item(i).dynamic(up_rf);
bf := rf.base_feature;
name := rf.name;
Result := name.is_equal(up_name) and then bf = up_bf;
i := i + 1;
end;
end;
tmp_string: STRING is
once
!!Result.make(256);
end;
tmp_string2: STRING is
once
!!Result.make(128);
end;
tmp_string3: STRING is
once
!!Result.make(128);
end;
once_pre_computing is
local
i: INTEGER;
of_array: FIXED_ARRAY[ONCE_FUNCTION];
rf6: RUN_FEATURE_6;
of: ONCE_FUNCTION;
do
if pre_computed_once.upper >= 0 then
echo.put_string(fz_04);
echo.put_string(fz_05);
from
i := pre_computed_once.upper;
!!of_array.with_capacity(1 + i // 2);
until
i < 0
loop
rf6 := pre_computed_once.item(i);
of := rf6.base_feature;
if not of_array.fast_has(of) then
of_array.add_last(of);
rf6.c_pre_computing;
end;
i := i - 1;
end;
echo.print_count(fz_04,of_array.count);
end;
end;
need_invariant(target_type: TYPE): RUN_CLASS is
-- Give the good RUN_CLASS when `target_type' need some
-- class invariant checking.
require
target_type.is_run_type
do
if run_control.invariant_check then
Result := target_type.run_type.run_class;
if Result.at_run_time and then
Result.class_invariant /= Void then
else
Result := Void;
end;
end;
end;
split_count: INTEGER;
-- Number of *.c files.
elt_c_count: INTEGER;
-- Number of elements already in current *.c file.
elt_c_size: INTEGER;
elt_c_count_max: INTEGER;
-- One unit is about 1 source line.
path_h: STRING is
once
Result := system_tools.path_h;
ensure
Result.has_suffix(h_suffix)
end;
path_c: STRING is
once
if no_split then
Result := path_h.twin;
Result.remove_last(1);
Result.extend('c');
else
split_count := 1;
!!Result.make(path_h.count + 4);
path_c_in(Result,split_count);
end;
ensure
Result.has_suffix(c_suffix);
end;
path_make: STRING is
once
Result := path_h.twin;
Result.remove_last(2);
Result.append(system_tools.make_suffix);
ensure
Result.has_suffix(system_tools.make_suffix);
end;
add_first_include is
do
put_banner(out_c);
out_c.put_string("#include %"");
out_c.put_string(path_h);
out_c.put_string(fz_18);
end;
put_banner(output: STD_FILE_WRITE) is
require
output /= Void;
output.is_connected;
do
output.put_string(fz_open_c_comment);
output.put_string(
"%N-- ANSI C code generated by :%N");
output.put_string(small_eiffel.copyright);
output.put_string(fz_close_c_comment);
output.put_character('%N');
end;
c_code_saved: BOOLEAN;
get_inline_ms: MANIFEST_STRING is
local
e: EXPRESSION;
do
e := stack_args.item(top).expression(1);
Result ?= e;
if Result = Void then
eh.add_position(e.start_position);
fatal_error("Bad usage of C inlining (argument%
% is not a manifest string).");
end;
end;
backup_sfw_connect(sfw: STD_FILE_WRITE; c_path: STRING) is
require
not no_split
local
object_suffix: STRING;
do
object_suffix := system_tools.object_suffix;
tmp_path.copy(c_path);
tmp_path.remove_last(2);
tmp_path.append(object_suffix);
if file_exists(tmp_path) then
if file_exists(c_path) then
c_path.put('d',c_path.count);
end;
end;
sfw_connect(sfw,c_path);
end;
path_c_in(str: STRING; number: INTEGER) is
do
str.clear;
str.append(path_h);
str.remove_last(2);
number.append_in(str);
str.extend('.');
str.extend('c');
end;
write_make_file_split is
require
not no_split
local
i: INTEGER;
no_change, recompile: BOOLEAN;
do
no_change := true;
from
i := split_count;
until
i = 0
loop
recompile := true;
path_c_in(tmp_path,i);
tmp_string.copy(tmp_path);
tmp_string.put('d',tmp_string.count);
if file_exists(tmp_string) then
if file_tools.same_files(tmp_path,tmp_string) then
echo.put_string(fz_01);
echo.put_string(tmp_path);
echo.put_string("%" not changed.%N");
echo.file_removing(tmp_string);
recompile := false;
else
echo.file_renaming(tmp_string,tmp_path);
end;
end;
if recompile then
tmp_string2.copy(path_h);
tmp_string2.remove_last(2);
i.append_in(tmp_string2);
tmp_string2.extend('.');
tmp_string2.extend('c');
system_tools.split_mode_c_compiler_command(tmp_string,tmp_string2);
echo_make;
no_change := false;
end;
i := i - 1;
end;
if no_change and then output_name /= Void then
no_change := file_exists(output_name)
else
no_change := false;
end;
if no_change then
echo.put_string("Executable is up-to-date %
%(no C compilation, no linking done).%N");
else
tmp_string2.copy(path_h);
tmp_string2.remove_last(2);
system_tools.split_mode_linker_command(tmp_string,
tmp_string2,split_count);
echo_make;
end;
end;
write_make_file_no_split is
require
no_split
do
system_tools.no_split_mode_command(tmp_string,path_c);
echo_make;
end;
common_put_target is
local
rf: RUN_FEATURE;
flag: BOOLEAN;
e: EXPRESSION;
ct: TYPE;
do
inspect
stack_code.item(top)
when C_inside_twin then
rf := stack_rf.item(top);
ct := rf.current_type;
if ct.is_reference then
out_c.put_character('(');
ct.mapping_cast;
out_c.put_character('R');
out_c.put_character(')');
else
out_c.put_character('&');
out_c.put_character('R');
end;
when C_inside_new then
out_c.put_character('n');
when C_switch then
rf := stack_rf.item(top);
flag := call_invariant_start(rf.current_type);
out_c.put_string("((T");
out_c.put_integer(rf.id);
out_c.put_string("*)C)");
if flag then
call_invariant_end;
end;
when C_expanded_initialize then
e := stack_target.item(top);
if e /= Void then
out_c.put_character('&');
e.compile_to_c;
else
out_c.put_string("&n->_");
out_c.put_string(stack_rf.item(top).name.to_string);
end;
when C_inline_one_pc then
print_current;
when C_precursor then
out_c.put_character('C');
end;
end;
msg1: STRING is " type conversion.%N";
msg2: STRING is "Automatic ";
sprintf_double_flag: BOOLEAN;
put_file(sfr: STD_FILE_READ; output: STD_FILE_WRITE) is
require
not sfr.end_of_input
do
from
sfr.read_character;
until
sfr.end_of_input
loop
output.put_character(sfr.last_character);
sfr.read_character;
end;
sfr.disconnect;
ensure
not sfr.is_connected
end;
really_define_c_main(rf3: RUN_FEATURE_3) is
require
not no_main
local
id: INTEGER;
rc: RUN_CLASS;
ct: TYPE;
do
echo.put_string("Define C main function.%N");
ct := rf3.current_type;
rc := rf3.run_class;
id := rc.id;
system_tools.put_c_main_function_type(out_c);
out_c.put_string(" main(int argc,char*argv[]){%N%
%initialize_eiffel_runtime(argc,argv);%N");
out_c.put_string("{T");
out_c.put_integer(id);
out_c.put_string("*n=eiffel_root_object;%N");
if run_control.no_check then
out_c.put_string("se_frame_descriptor root={%"System root.%",1,0,%"");
c_frame_descriptor_format.clear;
ct.c_frame_descriptor;
out_c.put_string(c_frame_descriptor_format);
out_c.put_string("%",1};%N%
%se_dump_stack ds;%N%
%ds.fd=&root;%N%
%ds.current=((void**)(&n));%N");
put_position_in_ds(rf3.start_position);
out_c.put_string("ds.caller=NULL;%Nse_dst=&ds;/*link*/%N");
end;
expanded_attributes(ct);
push_new(rf3,Void);
rf3.mapping_c;
pop;
if run_control.invariant_check then
if rc.class_invariant /= Void then
out_c.put_string(fz_se_i);
out_c.put_integer(id);
out_c.put_string("(&ds,n);%N");
end;
end;
gc_handler.gc_info_before_exit;
system_tools.put_c_main_function_exit(out_c);
end;
basic_directory_used: BOOLEAN;
bit_constant_pool: FIXED_ARRAY[BIT_CONSTANT];
fz_se_bit_constant: STRING is "se_bit_constant";
se_tmp_level: INTEGER;
se_tmp_list: FIXED_ARRAY[RUN_FEATURE] is
once
!!Result.with_capacity(4);
end;
fz_base: STRING is "base";
fz_no_check: STRING is "no_check";
end -- C_PRETTY_PRINTER