-- 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 NATIVE_C_PLUS_PLUS
inherit NATIVE
creation make
feature
use_current(er: EXTERNAL_ROUTINE): BOOLEAN is do end
stupid_switch_function(run_time_set: RUN_TIME_SET; name: STRING)
: BOOLEAN is
do
Result := true
end
stupid_switch_procedure(run_time_set: RUN_TIME_SET; name: STRING)
: BOOLEAN is
do
Result := true
end
notify_external_assignments(args: FORMAL_ARG_LIST; rt: E_TYPE) is
do
assignment_handler.from_external(start_position, args, rt)
end
c_define_function(rf8: RUN_FEATURE_8; bcn, name: STRING) is
do
standard_c_define_function(rf8, bcn, name)
cpp.c_plus_plus_register(Current)
rf8_memory := rf8
end
c_mapping_function(rf8: RUN_FEATURE_8; bcn, name: STRING) is
do
if ace.boost then
c_mapping_external(rf8.base_feature,rf8.arg_count)
else
rf8.default_mapping_function
end
end
c_define_procedure(rf7: RUN_FEATURE_7; bcn, name: STRING) is
do
standard_c_define_procedure(rf7, bcn, name)
cpp.c_plus_plus_register(Current)
rf7_memory := rf7
end
c_mapping_procedure(rf7: RUN_FEATURE_7; bcn, name: STRING) is
do
if ace.boost then
c_mapping_external(rf7.base_feature,rf7.arg_count)
cpp.put_string(fz_00)
else
rf7.default_mapping_procedure
end
end
jvm_add_method_for_function(rf8: RUN_FEATURE_8; bcn, name: STRING) is
do
end
jvm_define_function(rf8: RUN_FEATURE_8; bcn, name: STRING) is
do
fe_c2jvm(rf8)
end
jvm_mapping_function(rf8: RUN_FEATURE_8; bcn, name: STRING) is
do
fe_c2jvm(rf8)
end
jvm_add_method_for_procedure(rf7: RUN_FEATURE_7; bcn, name: STRING) is
do
end
jvm_define_procedure(rf7: RUN_FEATURE_7; bcn, name: STRING) is
do
fe_c2jvm(rf7)
end
jvm_mapping_procedure(rf7: RUN_FEATURE_7; bcn, name: STRING) is
do
fe_c2jvm(rf7)
end
feature {C_PRETTY_PRINTER}
c_plus_plus_definition is
do
if rf8_memory /= Void then
c_plus_plus_function_definition(rf8_memory)
else
c_plus_plus_procedure_definition(rf7_memory)
end
end
feature {NONE}
rf7_memory: RUN_FEATURE_7
rf8_memory: RUN_FEATURE_8
standard_c_define_function(rf8: RUN_FEATURE_8; bcn, name: STRING) is
do
rf8.external_c_prototype_from(external_tag.start_position)
if ace.no_check then
body.clear
body.extend('R')
body.extend('=')
wrapped_external_call(rf8.base_feature,rf8.arg_count)
rf8.c_define_with_body(body)
end
end
standard_c_define_procedure(rf7: RUN_FEATURE_7; bcn, name: STRING) is
do
rf7.external_c_prototype_from(external_tag.start_position)
if ace.no_check then
body.clear
wrapped_external_call(rf7.base_feature,rf7.arg_count)
rf7.c_define_with_body(body)
end
end
c_mapping_external(er: EXTERNAL_ROUTINE; arg_count: INTEGER) is
local
eruc, tcbd: BOOLEAN
do
eruc := use_current(er)
if not eruc then
tcbd := cpp.target_cannot_be_dropped
if tcbd then
cpp.put_character(',')
end
end
cpp.put_string(er.external_name)
cpp.put_character('(')
if eruc then
cpp.put_target_as_value
end
if arg_count > 0 then
if eruc then
cpp.put_character(',')
end
cpp.put_arguments
end
cpp.put_character(')')
if not eruc and then tcbd then
cpp.put_character(')')
end
end
wrapped_external_call(er: EXTERNAL_ROUTINE; arg_count: INTEGER) is
local
i: INTEGER
do
body.append(er.external_name)
body.extend('(')
if use_current(er) then
body.extend('C')
if arg_count > 0 then
body.extend(',')
end
end
from
i := 1
until
i > arg_count
loop
body.extend('a')
i.append_in(body)
i := i + 1
if i <= arg_count then
body.extend(',')
end
end
body.append(fz_14)
end
c_plus_plus_function_definition(rf8: RUN_FEATURE_8) is
require
cpp.on_c
local
er: EXTERNAL_ROUTINE
args_count: INTEGER
do
er := rf8.base_feature
if not external_routine_memory.fast_has(er) then
external_routine_memory.add_last(er)
rf8.c_plus_plus_prototype(er)
body.clear
body.append(once "return ((")
rf8.result_type.c_type_for_external_in(body)
body.extend(')')
if rf8.arguments /= Void then
args_count := rf8.arguments.count
end
parse_external(args_count,external_tag.to_string,er)
body.append(once ");%N}%N")
cpp.put_string(body)
end
end
c_plus_plus_procedure_definition(rf7: RUN_FEATURE_7) is
require
cpp.on_c
local
er: EXTERNAL_ROUTINE
args_count: INTEGER
do
er := rf7.base_feature
if not external_routine_memory.fast_has(er) then
external_routine_memory.add_last(er)
rf7.c_plus_plus_prototype(er)
body.clear
if rf7.arguments /= Void then
args_count := rf7.arguments.count
end
parse_external(args_count,external_tag.to_string,er)
body.append(once ";%N}%N")
cpp.put_string(body)
end
end
parse_external(args_count: INTEGER; tag: STRING; er: EXTERNAL_ROUTINE) is
-- Lazy parsing (hope the tag is correct) of this syntax :
--
-- External -> "%"C++" [ "[" C++_feature "]" ]
-- [ "(" {Type "," ...} ")" [ ":" Type ] ]
-- [ "|" {include "," ...} ]
-- "%""
-- C++_feature -> "static" C++_Class |
-- "new" C++_Class |
-- "delete" C++_Class |
-- "data_member" C++_Class |
-- C++_Class
-- include -> "%"" Manifest string "%"" |
-- "<" Manifest_string ">"
-- C++_Class -> Identifier include
local
i, state, args, parenthesis: INTEGER
c: CHARACTER
do
from
check
tag.has_prefix(once "C++")
end
i := 4
until
i > tag.count
loop
c := tag.item(i)
inspect
state
when 0 then
-- Looks like : "C++"
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when '[' then
i := i + 1
state := 1
else
i := error_at(i,tag,state)
end
when 1 then
-- Looks like : "C++ [" :
if c = ' ' or else c = '%T' or else c = '%N' then
i := i + 1
elseif i = tag.substring_index(once "static ",i) then
i := i + 7
i := parse_cpp_class(i,tag)
body.append(once "::")
body.append(er.c_plus_plus_name)
state := 2
elseif i = tag.substring_index(once "new ",i) then
i := i + 4
body.append(once "new ")
i := parse_cpp_class(i,tag)
state := 3
elseif i = tag.substring_index(once "delete ",i) then
i := i + 7
body.append(once "delete((")
i := parse_cpp_class(i,tag)
body.append(once "*)a1)")
if args /= 0 or else args_count /= 1 then
i := error_at(i,tag,state)
else
state := 4
end
elseif i = tag.substring_index(once "data_member ",i) then
i := error_at(i,tag,state); -- really necessary ?
else
args := args + 1
body.append(once "((")
i := parse_cpp_class(i,tag)
body.append(once "*)a1)->")
body.append(er.c_plus_plus_name)
state := 5
end
when 2 then
-- Looks like : "C++ [ static C++_Class " :
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when ']' then
i := i + 1
state := 8
else
i := error_at(i,tag,state)
end
when 3 then
-- Looks like : "C++ [ new C++_Class" :
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when ']' then
i := i + 1
state := 6
else
i := error_at(i,tag,state)
end
when 4 then
-- Looks like : "C++ [ delete C++_Class " :
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when ']' then
i := i + 1
state := 10
else
i := error_at(i,tag,state)
end
when 5 then
-- Looks like : "C++ [C++_Class" :
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when ']' then
i := i + 1
state := 7
else
i := error_at(i,tag,state)
end
when 6 then
-- Looks like : "C++ [ new C++_CLASS ]" :
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when '(' then
i := parse_args(i,tag,args,args_count)
state := 13
else
i := error_at(i,tag,state)
end
when 7 then
-- Looks like : "C++ [ C++_Class ] :
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when '(' then
i := parse_args(i,tag,args,args_count)
state := 11
else
i := error_at(i,tag,state)
end
when 8 then
-- Looks like : "C++ [ static C++_Class ]" :
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when '(' then
i := parse_args(i,tag,args,args_count)
state := 9
else
i := error_at(i,tag,state)
end
when 9 then
-- Looks like : "C++ [ static C++_Class ] ({type, ...})" :
i := i + 1
when 10 then
-- Looks like : "C++ [ delete C++_Class ]" :
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when '(' then
parenthesis := parenthesis + 1
i := i + 1
when ')' then
if parenthesis > 1 then
i := error_at(i,tag,state)
else
i := i + 1
end
else
i := error_at(i,tag,state)
end
when 11 then
-- Looks like : "C++ * ( { type , ... } )" :
inspect
c
when ':' then
state := 12
when '|' then
state := 13
else
end
i := i + 1
when 12 then
-- Looks like : "C++ * ( { type , ... } ) : " :
inspect
c
when '|' then
state := 13
else
end
i := i + 1
when 13 then
-- Looks like : "C++ * |" :
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when '<', '%"' then
i := parse_include(i,tag)
when ',' then
i := i + 1
else
i := error_at(i,tag,state)
end
end
end
end
parse_args(s: INTEGER; tag: STRING; args, args_count: INTEGER): INTEGER is
require
tag.item(s) = '('
local
i, parenthesis, a, state: INTEGER
c: CHARACTER
do
from
a := args
state := 40
body.extend('(')
i := s + 1
until
i > tag.count or else Result > i
loop
c := tag.item(i)
inspect
state
when 40 then
-- Before arg type :
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when ')' then
Result := i + 1
else
body.extend('(')
state := 41
end
when 41 then
-- Inside some type :
inspect
c
when ',' then
i := i + 1
body.extend(')')
a := a + 1
body.extend('a')
a.append_in(body)
if a < args_count then
body.extend(',')
end
state := 40
when '(' then
body.extend(c)
parenthesis := parenthesis + 1
i := i + 1
when ')' then
if parenthesis = 0 then
body.extend(')')
a := a + 1
body.extend('a')
a.append_in(body)
Result := i + 1
else
body.extend(c)
parenthesis := parenthesis - 1
i := i + 1
end
else
body.extend(c)
i := i + 1
end
end
end
body.extend(')')
if Result = 0 or else a /= args_count then
Result := error_at(i,tag,state)
end
end
parse_include(s: INTEGER; tag: STRING): INTEGER is
require
(once "%"<").has(tag.item(s))
local
include: STRING
i: INTEGER; c: CHARACTER
do
from
buffer.clear
buffer.extend(tag.item(s))
i := s + 1
until
i > tag.count or else Result > i
loop
c := tag.item(i)
inspect
c
when '%"', '>' then
buffer.extend(c)
include := buffer.twin
if not include_memory.has(include) then
include_memory.add_last(include)
cpp.add_include(include)
end
Result := i + 1
else
buffer.extend(c)
i := i + 1
end
end
if Result = 0 then
Result := error_at(i,tag,20)
end
end
parse_cpp_class(s: INTEGER; tag: STRING): INTEGER is
local
i, state: INTEGER
c: CHARACTER
do
from
state := 30
i := s
until
i > tag.count or else state > 32
loop
c := tag.item(i)
inspect
state
when 30 then
-- Nothing :
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when '<', '>', '%"', '(', ')' then
i := error_at(i,tag,state)
else
state := 31
end
when 31 then
-- Inside Identifier :
inspect
c
when ' ', '%T', '%N' then
state := 32
when '<', '%"' then
i := parse_include(i,tag)
state := 33
else
body.extend(c)
i := i + 1
end
when 32 then
-- After Identifier :
inspect
c
when ' ', '%T', '%N' then
i := i + 1
when '<', '%"' then
i := parse_include(i,tag)
state := 33
else
i := error_at(i,tag,state)
end
end
end
Result := i
end
error_at(error_index: INTEGER; tag: STRING; state: INTEGER): INTEGER is
do
if rf7_memory /= Void then
error_handler.add_position(rf7_memory.base_feature.start_position)
else
error_handler.add_position(rf8_memory.base_feature.start_position)
end
error_handler.append("Bad external %"C++%" definition.%Nexternal %"")
error_handler.append(tag)
error_handler.append("%"%N_________")
from
Result := 1
until
Result > error_index
loop
error_handler.extend('_')
Result := Result + 1
end
error_handler.extend('^')
error_handler.append("%NSee SmartEiffel/tutorial/external/C++ directory %
%for more information.%N (Internal state = ")
error_handler.append(state.to_string)
error_handler.extend(')')
error_handler.print_as_error
Result := tag.count + 1
end
include_memory: FIXED_ARRAY[STRING] is
once
!!Result.with_capacity(4)
end
external_routine_memory: FIXED_ARRAY[EXTERNAL_ROUTINE] is
once
!!Result.with_capacity(4)
end
end -- NATIVE_C_PLUS_PLUS