4 readfile
= function(fn
) local f
= assert(io
.open(fn
)) local s
= f
:read'*a' f
:close() return s
end
7 local entities
= dofile'entities.lua'
8 assert_function
= function(f
)
9 assert(entities
.is_function(f
), 'argument is not a function')
13 local path
= string.match(arg
[0], '(.*/)[^%/]+') or ''
14 local xmlstream
= dofile(path
..'xml.lua')(my
.readfile(filename
))
15 local code
= xmlstream
[1]
17 local decompound
= function(n
)
18 -- test function pointer
19 local r
, a
= string.match(n
, '(.-) %(%*%) (%b())')
21 -- only single arguments are supported
22 return 'function', r
, string.match(a
, '%(([^,]*)%))')
28 local base_types
= dofile'types.lua'
32 for _
, v
in pairs(xmlstream
.byid
) do if v
.xarg
.fullname
then
33 local o
= t
[v
.xarg
.fullname
] or {}
35 t
[v
.xarg
.fullname
] = o
37 get_from_fullname
= function(n
)
44 type_on_stack
= function(t
)
45 local typename
= type(t
)=='string' and t
or t
.xarg
.type_name
46 if rawget(base_types
, typename
) then
47 local ret
= rawget(base_types
, typename
).on_stack
50 if type(t
)=='string' or t
.xarg
.type_base
==typename
then
51 local identifier
= get_from_fullname(typename
)
52 assert(identifier
and #identifier
==1, 'cannot resolve base type: '..typename
)
53 identifier
= identifier
[1]
54 if identifier
.label
=='Enum' then
56 elseif identifier
.label
=='Class' then
59 error('unknown identifier type: '..identifier
.label
)
63 error'I cannot manipulate arrays'
64 elseif string.match(typename
, '%(%*%)') then
65 -- function pointer type
66 -- FIXME: the XML description does not contain this info
67 error'I cannot manipulate function pointers'
68 elseif t
.xarg
.indirections
then
69 if t
.xarg
.indirections
=='1' then
70 local b
= assert(get_from_fullname(t
.xarg
.type_base
), 'unknown type base')[1]
71 if b
.label
=='Class' then
72 return t
.xarg
.type_base
..'*;'
74 error('I cannot manipulate pointers to '..t
.xarg
.type_base
)
77 error'I cannot manipulate double pointers'
79 -- this is any combination of constant, volatile and reference
80 -- we ignore this info and treat this as normal value
81 return type_on_stack(t
.xarg
.type_base
)
86 local get_enum
= function(fullname
)
89 return fullname
.. ' arg' .. tostring(i
) .. ' = static_cast< ' ..
90 fullname
.. ' >(LqtGetEnumType(L, '..tostring(j
)..', "' .. fullname
.. '"));'
93 local get_pointer
= function(fullname
)
96 return fullname
.. ' arg' .. tostring(i
) .. '* = static_cast< ' ..
97 fullname
.. ' *>(LqtGetClassType(L, '..tostring(j
)..', "' .. fullname
.. '*"));'
100 local get_class
= function(fullname
)
103 return fullname
.. ' arg' .. tostring(i
) .. ' = *static_cast< ' ..
104 fullname
.. ' *>(LqtGetClassType(L, '..tostring(j
)..', "' .. fullname
.. '*"));'
107 local get_constref
= function(fullname
)
110 return fullname
.. ' const& arg' .. tostring(i
) .. ' = *static_cast< ' ..
111 fullname
.. ' *>(LqtGetClassType(L, '..tostring(j
)..', "' .. fullname
.. '*"));'
114 local get_ref
= function(fullname
)
117 return fullname
.. '& arg' .. tostring(i
) .. ' = *static_cast< ' ..
118 fullname
.. ' *>(LqtGetClassType(L, '..tostring(j
)..', "' .. fullname
.. '*"));'
122 type_properties
= function(t
)
123 local typename
= type(t
)=='string' and t
or t
.xarg
.type_name
125 if rawget(base_types
, typename
) then
126 local ret
= rawget(base_types
, typename
)
127 return ret
.on_stack
, ret
.get
131 if type(t
)=='string' or t
.xarg
.type_base
==typename
then
132 local identifier
= get_from_fullname(typename
)
133 assert(identifier
and #identifier
==1, 'cannot resolve base type: '..typename
)
134 identifier
= identifier
[1]
135 if identifier
.label
=='Enum' then
136 return 'string;', get_enum(identifier
.xarg
.fullname
)
137 elseif identifier
.label
=='Class' then
138 return typename
..'*;', get_class(identifier
.xarg
.fullname
)
140 error('unknown identifier type: '..identifier
.label
)
142 elseif t
.xarg
.array
then
143 error'I cannot manipulate arrays'
144 elseif string.match(typename
, '%(%*%)') then
145 -- function pointer type
146 -- FIXME: the XML description does not contain this info
147 error'I cannot manipulate function pointers'
148 elseif t
.xarg
.indirections
then
149 if t
.xarg
.indirections
=='1' then
150 local b
= get_from_fullname(t
.xarg
.type_base
)
151 b
= assert(b
, 'unknown base type '..t
.xarg
.type_base
)[1]
152 if b
.label
=='Class' then
153 -- TODO: check if other modifiers are in place?
154 return t
.xarg
.type_base
..'*;', get_pointer(t
.xarg
.type_base
)
156 error('I cannot manipulate pointers to '..t
.xarg
.type_base
)
159 error'I cannot manipulate double pointers'
161 -- this is any combination of constant, volatile and reference
163 if typename
==(t
.xarg
.type_base
..' const&') then
164 ret_get
= get_constref(t
.xarg
.type_base
)
165 elseif typename
==(t
.xarg
.type_base
..'&') then
166 ret_get
= get_ref(t
.xarg
.type_base
)
168 assert(ret_get
, 'cannot get non-base type '..typename
..' from stack')
169 return type_properties(t
.xarg
.type_base
), ret_get
173 entities
.return_type
= function(f
)
175 if entities
.is_destructor(f
) then
177 elseif entities
.is_constructor(f
) then
178 -- FIXME: hack follows!
179 assert(f
.xarg
.type_name
==f
.xarg
.type_base
, 'return type of constructor is strange')
180 f
.xarg
.type_name
= f
.xarg
.type_base
..'*'
181 f
.xarg
.indirections
='1'
183 elseif f
.xarg
.type_name
=='' or f
.xarg
.type_name
=='void' then
191 local arguments_on_stack
= function(f
)
193 local args_on_stack
= ''
194 --print('=====', f.xarg.fullname)
195 for _
,a
in ipairs(f
) do
196 --local st, err = pcall(type_on_stack, a)
197 --if not st then table.foreach(a, print) end
199 local err
= type_properties(a
)
200 args_on_stack
= args_on_stack
.. err
202 if entities
.takes_this_pointer(f
) then
203 args_on_stack
= f
.xarg
.member_of
.. '*;' .. args_on_stack
208 function_description
= function(f
)
210 local args_on_stack
= arguments_on_stack(f
)
211 return f
.xarg
.type_name
.. ' ' .. f
.xarg
.fullname
.. ' (' .. args_on_stack
.. ')'..
212 (f
.xarg
.static
=='1' and ' [static]' or '')..
213 (f
.xarg
.virtual
=='1' and ' [virtual]' or '')..
214 (entities
.is_constructor(f
) and ' [constructor]' or '')..
215 (entities
.is_destructor(f
) and ' [destructor]' or '')..
216 ' [in ' .. tostring(f
.xarg
.member_of
) .. ']'
219 -- TODO: must wait for a way to specify pushing base types
220 local calling_code
= function(f
)
222 local ret
, indent
= '', ' '
224 for _
,a
in ipairs(f
) do if a
.label
=='Argument' then
226 local d
, g
, p
= type_properties(a
)
227 ret
= ret
.. indent
.. g(n
) .. '\n'
229 if entities
.is_constructor(f
) then
230 elseif entities
.is_constructor(f
) then
231 elseif entities
.takes_this_pointer(f
) then
235 args
= args
.. (i
> 1 and ', arg' or 'arg') .. tostring(i
)
237 args
= '('..args
..')';
238 local ret_type
= entities
.return_type(f
)
239 ret_type
= ret_type
and ret_type
.xarg
.type_name
or nil
240 local call_line
= (ret_type
and (ret_type
..' ret = ') or '')
241 call_line
= call_line
.. f
.xarg
.fullname
.. args
242 ret
= ret
.. indent
.. call_line
.. ';\n'
247 for _
, v
in pairs(xmlstream
.byid
) do
248 if string.find(v
.label
, 'Function')==1 then
249 local status
, err
= pcall(function_description
, v
)
250 --io[status and 'stdout' or 'stderr']:write((status and '' or v.xarg.fullname..': ')..err..'\n')
252 local s
, e
= pcall(calling_code
, v
)
253 io
[s
and 'stdout' or 'stderr']:write((s
and ''
254 or ('error calling '..v
.xarg
.fullname
..': '))..e
..(s
and '' or '\n'))
256 --io[status and 'stdout' or 'stderr']:write((status and '' or v.xarg.fullname..': ')..err..'\n')
259 --table.foreach(name_list, print)