Skip to content

Commit

Permalink
WIP on wrapper-generator
Browse files Browse the repository at this point in the history
  • Loading branch information
tybor committed Sep 17, 2009
1 parent 9e9103a commit 828deee
Show file tree
Hide file tree
Showing 9 changed files with 1,213 additions and 1,045 deletions.
56 changes: 54 additions & 2 deletions src/tools/wrappers-generator/c_file.e
Expand Up @@ -6,14 +6,66 @@ inherit
NAMED_NODE
STORABLE_NODE

insert
EIFFEL_NAME_CONVERTER
FILE_TOOLS

creation make

feature
store is
do
files.put(Current,id)
end

invariant name.is_equal(once U"File")

emit_functions is
-- Emit all the function contained into Current file into a deferred class.
local
my_functions: LINKED_LIST[C_FUNCTION]; output: TERMINAL_OUTPUT_STREAM
class_name, header: STRING; path: POSIX_PATH_NAME

do
header := c_name.to_utf8
my_functions := functions.reference_at(id)
if my_functions/=Void and then is_to_be_emitted(header) then
if directory = Void then
log(once "Outputting wrapper for functions in file @(1) on standard output.%N",
<<header>>)
output := std_output
else
-- Compute Eiffel class name from header name
class_name := class_name_from_header(header)
create path.make_from_string(directory)
path.add_last(class_name.as_lower+once ".e")
if path.is_file then
log(once "Copying existing file @(1) onto @(1).orig.%N",<<path.to_string>>)
copy_to(path.to_string, path.to_string+once ".orig")
end
log(once "Outputting wrapper for functions found in file @(1) on @(2).%N",
<<header, path.to_string>>)
create {TEXT_FILE_WRITE} output.connect_to(path.to_string)
end
emit_functions_class_header_on(output)

end
end

emit_functions_class_headers (a_stream: OUTPUT_STREAM) is
-- Put on `output' the header on an "external" class named 'class_name'
-- from the beginning until the "feature {} -- External calls" label
-- included
do
a_stream.append(automatically_generated_header)
a_stream.append(deferred_class)
a_stream.append(class_name) -- line
a_stream.put('%N')
emit_description_on(class_descriptions.reference_at(class_name),a_stream)
a_stream.append(struct_inherits) --line
a_stream.put_message(once "insert @(1)%N",<<typedefs_class_name>>)
a_stream.append(externals_header) --line
end


invariant name.is_equal(once U"File")
end

97 changes: 96 additions & 1 deletion src/tools/wrappers-generator/c_function.e
Expand Up @@ -6,7 +6,7 @@ inherit
NAMED_NODE
FILED_NODE
STORABLE_NODE

WRAPPABLE_NODE
creation make

feature
Expand All @@ -17,5 +17,100 @@ feature

returns: UNICODE_STRING is do Result:=attribute_at(once U"returns") end

wrap_on (a_stream: OUTPUT_STREAM) is
local name: STRING
do
unwrappable:=False
name := adapt(c_name.as_utf8.as_lower)
-- TODO: this way of assigning feature names is not entirely
-- bullet-proof. In fact MyFunction and myfunction will get the same
-- Eiffel feature name. Let me say that if the code you are going
-- wrapping presents such issues it is not worth your time AFAIK. Paolo
-- 2009-02-06.
if is_public(name) then
log(once "Function @(1)",<<name>>)
a_stream.put_message(once "%T@(1)", <<name>>)
if children_count > 0 then put_arguments_on (a_stream) end
put_return_type_on (a_stream)
emit_description_on(feature_description(class_name, name),a_stream)
append_function_body(a_stream)
-- if unwrappable then log("Function @(1) is not wrappable.%N", <<name>>) end
log_string(once "%N")
else log(once "Skipping 'hidden' function @(1)%N", <<name>>)
end
end
do
end

c_function_name: STRING
-- The untranslated C name of the function currently being wrapped

variadic: BOOLEAN
-- Is the function currently being emitted variadic?

unwrappable: BOOLEAN
-- Is the function currently being emitted unwrappable?


append_function_arguments (a_node: XML_COMPOSITE_NODE) is
-- Append the arguments of function referred by `a_node' into
-- `buffer'. If an Ellipsis ("...") is found `variadic' flag
-- is set to True
require
node_not_void: a_node /= Void
is_function_node: a_node.name.is_equal(once U"Function")
has_arguments: a_node.children_count > 0
local
i: INTEGER; child: XML_NODE
do
variadic := False
buffer.append(once " (")
log(once "(@(1) args: ",<<a_node.children_count.out>>)
append_function_argument(a_node.child(1))
from i:=2 until i>a_node.children_count or variadic or unwrappable loop
buffer.append(once "; ") -- check a_node/=Void end
child:=a_node.child(i) -- check child/=Void end
append_function_argument(child)
i := i + 1
end
log_string(once ")")
buffer.append(once ")")
end


put_return_type_on (a_stream: OUTPUT_STREAM) is
-- Append the Eiffel equivalent type of the return type of
-- `a_node' to `a_stream' and the "is" keyword, i.e. ": INTEGER_32 is " or ":
-- POINTER is". When result of `a_node' is "void" only " is" is appended.
require
node_not_void: a_node /= Void
is_function_node: a_node.name.is_equal(once U"Function")
local eiffel_type
do
eiffel_type := types.at(returns).wrapper_type
if returns = Void then
a_stream.put_message ("%N%T%T%T-- unwrappable return type: @(1)%N", <<last_error>>)
log(once "Unwrappable return type: @(1)... ",<<last_error>>)
unwrappable:=True
last_error := Void -- Error handled, reset it.
elseif returns.is_empty then
-- Nothing; the correct "return type" of a C function returning void (i.e. a command) is an empty string.
else
a_stream.append(once ": ")
a_stream.append(returns)
end
buffer.append(once " is%N")
end

append_function_body (a_node: XML_COMPOSITE_NODE) is
-- Append the body of function referred by `a_node'
require
node_not_void: a_node /= Void
is_function_node: a_node.name.is_equal(once U"Function")
c_function_name_not_void: c_function_name /= Void
deferred
end


invariant name.is_equal(once U"Function")
end

0 comments on commit 828deee

Please sign in to comment.