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 local elements
= entities
9 assert_function
= function(f
)
10 assert(entities
.is_function(f
), 'argument is not a function')
14 local path
= string.match(arg
[0], '(.*/)[^%/]+') or ''
15 local xmlstream
, idindex
= dofile(path
..'xml.lua')(my
.readfile(filename
))
16 io
.stderr
:write'parsed XML\n'
17 local code
= xmlstream
[1]
19 local decompound
= function(n
)
20 -- test function pointer
21 local r
, a
= string.match(n
, '(.-) %(%*%) (%b())')
23 -- only single arguments are supported
24 return 'function', r
, string.match(a
, '%(([^,]*)%))')
30 local arg_iter
= function(f
)
36 while a
and a
.label
~='Argument' do
41 onlyargs
= onlyargs
+ 1
43 local d
, g
, p
, n
= type_properties(a
)
46 return (a
and onlyargs
), a
, (a
and retn
), stackn
-1
51 assert(loadfile
'types.lua')(base_types
)
55 for _
, v
in pairs(xmlstream
.byid
) do if v
.xarg
.fullname
then
56 local o
= t
[v
.xarg
.fullname
] or {}
58 t
[v
.xarg
.fullname
] = o
60 get_from_fullname
= function(n
)
62 assert(ret
, 'unknown identifier: '..n
)
65 get_unique_fullname
= function(n
)
68 assert(ret
, 'unknown identifier: '..n
)
69 assert(type(ret
)=='table' and #ret
==1, 'ambiguous identifier: '..n
)
76 local push_enum
= function(fullname
)
78 return 'lqtL_pushenum(L, '..tostring(j
)..', "'..fullname
..'");'
81 local push_pointer
= function(fullname
)
83 return 'lqtL_pushudata(L, '..tostring(j
)..', "' .. fullname
.. '*");'
86 local push_class
= function(fullname
)
88 return 'lqtL_passudata(L, new '..fullname
..'('..tostring(j
)..'), "' .. fullname
.. '*");'
91 local push_constref
= function(fullname
) -- FIXME: is it correct?
93 return 'lqtL_passudata(L, new '..fullname
..'('..tostring(j
)..'), "' .. fullname
.. '*");'
96 local push_ref
= function(fullname
)
98 return 'lqtL_passudata(L, &'..tostring(j
)..', "' .. fullname
.. '*");'
102 local get_enum
= function(fullname
)
104 return 'static_cast< ' ..
105 fullname
.. ' >(lqtL_toenum(L, '..tostring(i
)..', "' .. fullname
.. '"));'
108 local get_pointer
= function(fullname
)
110 return 'static_cast< ' ..
111 fullname
.. ' *>(lqtL_toudata(L, '..tostring(i
)..', "' .. fullname
.. '*"));'
114 local get_class
= function(fullname
)
116 return '*static_cast< ' ..
117 fullname
.. ' *>(lqtL_toudata(L, '..tostring(i
)..', "' .. fullname
.. '*"));'
120 local get_constref
= function(fullname
)
122 return '*static_cast< ' ..
123 fullname
.. ' *>(lqtL_toudata(L, '..tostring(i
)..', "' .. fullname
.. '*"));'
126 local get_ref
= function(fullname
)
128 return '*static_cast< ' ..
129 fullname
.. ' *>(lqtL_toudata(L, '..tostring(i
)..', "' .. fullname
.. '*"));'
133 type_properties
= function(t
)
134 local typename
= type(t
)=='string' and t
or t
.xarg
.type_name
136 if base_types
[typename
] then
137 local ret
= base_types
[typename
]
138 return ret
.desc
, ret
.get
, ret
.push
, ret
.num
142 if type(t
)=='string' or t
.xarg
.type_base
==typename
then
143 local identifier
= get_unique_fullname(typename
)
144 local fn
= identifier
.xarg
.fullname
145 if identifier
.label
=='Enum' then
146 return 'enum;', get_enum(fn
), push_enum(fn
), 1
147 elseif identifier
.label
=='Class' then
148 --assert(entities.class_is_copy_constructible(bt))
149 return typename
..'*;', get_class(fn
), push_class(fn
), 1
151 error('unknown identifier type: '..identifier
.label
)
153 elseif t
.xarg
.array
or t
.xarg
.type_name
:match
'%b[]' then -- FIXME: another hack
154 error'I cannot manipulate arrays'
155 elseif string.match(typename
, '%(%*%)') then
156 -- function pointer type
157 -- FIXME: the XML description does not contain this info
158 error'I cannot manipulate function pointers'
159 elseif t
.xarg
.indirections
then
160 if t
.xarg
.indirections
=='1' then
161 local b
= get_unique_fullname(t
.xarg
.type_base
)
162 if b
.label
=='Class' then
163 -- TODO: check if other modifiers are in place?
164 return t
.xarg
.type_base
..'*;',
165 get_pointer(t
.xarg
.type_base
),
166 push_pointer(t
.xarg
.type_base
), 1
168 error('I cannot manipulate pointers to '..t
.xarg
.type_base
)
171 error'I cannot manipulate double pointers'
173 -- this is any combination of constant, volatile and reference
174 local ret_get
, ret_push
= nil, nil
175 if typename
==(t
.xarg
.type_base
..' const&') then
176 local bt
= get_unique_fullname(t
.xarg
.type_base
)
177 --assert(entities.class_is_copy_constructible(bt))
178 ret_get
= get_constref(t
.xarg
.type_base
)
179 ret_push
= entities
.class_is_copy_constructible(bt
) and push_constref(t
.xarg
.type_base
) or nil
180 elseif typename
==(t
.xarg
.type_base
..'&') then
181 ret_get
= get_ref(t
.xarg
.type_base
)
182 ret_push
= push_ref(t
.xarg
.type_base
)
184 assert(ret_get
, 'cannot get non-base type '..typename
..' from stack')
185 return type_properties(t
.xarg
.type_base
), ret_get
, ret_push
, 1
189 entities
.return_type
= function(f
)
191 if entities
.is_destructor(f
) then
193 elseif entities
.is_constructor(f
) then
194 -- FIXME: hack follows!
195 assert((f
.xarg
.type_name
==f
.xarg
.type_base
)
196 or (f
.xarg
.type_name
==f
.xarg
.type_base
..'&'), 'return type of constructor is strange')
197 f
.xarg
.type_name
= f
.xarg
.type_base
..'&'
200 elseif f
.xarg
.type_name
=='' or f
.xarg
.type_name
=='void' then
207 function_description
= function(f
)
209 local args_on_stack
= '' -- arguments_on_stack(f) -- FIXME: use another method
210 return f
.xarg
.type_name
.. ' ' .. f
.xarg
.fullname
.. ' (' .. args_on_stack
.. ')'..
211 (f
.xarg
.static
=='1' and ' [static]' or '')..
212 (f
.xarg
.virtual
=='1' and ' [virtual]' or '')..
213 (entities
.is_constructor(f
) and ' [constructor]' or '')..
214 (entities
.is_destructor(f
) and ' [destructor]' or '')..
215 ' [in ' .. tostring(f
.xarg
.member_of
) .. ']'
218 local argument_number
= function(f
)
220 local narg
, sarg
= 0, 0
221 for i
, a
, s
, r
in arg_iter(f
) do
225 if entities
.is_destructor(f
) then
227 elseif entities
.is_constructor(f
) then
228 elseif entities
.takes_this_pointer(f
) then
229 narg
, sarg
= narg
+ 1, sarg
+ 1
234 local argument_assert
= function(f
)
236 local narg
= argument_number(f
)
237 return 'luaL_checkany(L, '..tostring(narg
)..')'
240 local argument
= function(n
)
241 return 'arg'..tostring(n
)
244 local get_args
= function(f
, indent
)
246 indent
= indent
or ' '
247 local ret
, shift
= '', 0
248 if entities
.takes_this_pointer(f
) then
250 ret
= ret
.. indent
.. f
.xarg
.member_of_class
.. '* self = '
251 ret
= ret
.. get_pointer(f
.xarg
.member_of_class
)(1) .. ';\n' -- (void)self;\n'
253 for argi
, a
, stacki
in arg_iter(f
) do
254 local _d
, g
, _p
, _n
= type_properties(a
)
255 ret
= ret
.. indent
.. a
.xarg
.type_name
.. ' ' .. argument(argi
) .. ' = '
256 ret
= ret
.. g(stacki
+ shift
) .. ';\n' -- .. '(void) '..argument(argi)..';\n'
261 local arg_list
= function(f
, pre
)
263 if entities
.is_destructor(f
) then
267 for i
in arg_iter(f
) do
268 ret
= ret
.. ((i
>1 or pre
) and ', ' or '') .. argument(i
)
271 return '('..pre
..ret
..')'
275 local function_static_call
= function(f
)
277 if entities
.is_destructor(f
) then
278 return 'delete (self)'
279 elseif entities
.is_constructor(f
) then
280 return '*new lqt_shell_class' .. f
.parent
.xarg
.id
.. arg_list(f
, 'L')
281 -- f.xarg.fullname..arg_list(f)
282 elseif entities
.takes_this_pointer(f
) then
283 return 'self->'..f
.xarg
.fullname
..arg_list(f
)
285 return f
.xarg
.fullname
..arg_list(f
)
289 local function_shell_call
= function(f
)
291 assert(f
.xarg
.member_of_class
, 'not a shell class member')
292 if entities
.is_destructor(f
) then
293 return 'delete (self)'
294 elseif entities
.is_constructor(f
) then
295 return '*new lqt_shell_class' .. f
.parent
.xarg
.id
.. arg_list(f
)
296 -- f.xarg.fullname..arg_list(f)
297 elseif f
.xarg
.access
=='public' then
298 return function_static_call(f
)
299 elseif entities
.takes_this_pointer(f
) then
300 return 'self->'..f
.xarg
.fullname
..arg_list(f
)
302 return f
.xarg
.fullname
..arg_list(f
)
306 local collect_return
= function(f
)
308 local ret_t
= entities
.return_type(f
)
312 return ret_t
.xarg
.type_name
.. ' ret = '
316 local give_back_return
= function(f
)
318 local ret_t
= entities
.return_type(f
)
322 local _d
, _g
, p
, _n
= type_properties(ret_t
)
327 local return_statement
= function(f
)
329 local ret_t
= entities
.return_type(f
)
333 local _d
, _g
, _p
, n
= type_properties(ret_t
)
334 return 'return '..tostring(n
)
338 -- TODO: constructors wait for deciding if shell class is needed
339 local calling_code
= function(f
)
341 local ret
, indent
= '', ' '
344 ret
= ret
..indent
..argument_assert(f
)..';\n'
346 ret
= ret
..get_args(f
, indent
)
348 --if entities.is_constructor(f) then
349 --elseif entities.is_destructor(f) then
355 args = args .. (i > 1 and ', ' or '') .. argument(i)
357 args = '('..args..')';
358 local call_line = f.xarg.fullname .. args .. ';\n'
359 local ret_type = entities.return_type(f)
361 call_line = ret_type.xarg.type_name .. ' ret = ' .. call_line
362 local _d, _g, p, n = type_properties(ret_type)
363 call_line = call_line .. indent .. p'ret' .. '\n'
364 call_line = call_line .. indent .. 'return ' .. tostring(n) .. ';\n'
367 local call_line
= function_static_call(f
)
368 ret
= ret
.. indent
.. collect_return(f
) .. call_line
.. ';\n'
369 local treat_return
= give_back_return(f
)
370 ret
= treat_return
and (ret
..indent
..treat_return
..';\n') or ret
371 ret
= ret
.. indent
.. return_statement(f
) .. ';\n'
384 #include
"lqt_common.hpp"
387 #define lqtL_getinteger lua_tointeger
388 #define lqtL_getstring lua_tostring
389 #define lqtL_getnumber lua_tonumber
394 local CLASS_FILTERS
= {
395 function(c
) return c
.xarg
.fullname
:match
'%b<>' end,
396 function(c
) return c
.xarg
.name
:match
'_' end,
397 --function(c) return c.xarg.fullname:match'Q.-Data' end,
398 function(c
) return c
.xarg
.class_type
=='struct' end,
399 function(c
) return c
.xarg
.fullname
=='QVariant::Private::Data' end,
400 function(c
) return c
.xarg
.fullname
=='QTextStreamManipulator' end,
402 local FUNCTIONS_FILTERS
= {
403 function(f
) return not pcall(calling_code
, f
) end,
404 function(f
) return f
.xarg
.name
:match
'^[_%w]*'=='operator' end,
405 function(f
) return f
.xarg
.fullname
:match
'%b<>' end,
406 function(f
) return f
.xarg
.name
:match
'_' end,
407 function(f
) return f
.xarg
.fullname
:match
'QInternal' end,
408 function(f
) return f
.xarg
.access
~='public' end,
409 function(f
) return f
.xarg
.fullname
=='QVariant::canConvert' end,
411 local filter_out
= function(f
, t
)
412 local ret
, msg
, F
= nil, next(t
, nil)
413 while (not ret
) and F
do
415 msg
, F
= next(t
, msg
)
420 local choose_function
= function(f1
, f2
)
426 local function_proto
= function(f
)
428 local larg1
, larg2
= '', ''
429 for i
, a
in arg_iter(f
) do
430 if a
.xarg
.type_name
=='void' then
431 larg1
, larg2
= '', ''
434 larg1
= larg1
.. (i
>1 and ', ' or '')
435 if string.match(a
.xarg
.type_name
, '%(%*%)') then
436 larg1
= larg1
.. a
.xarg
.type_name
:gsub('%(%*%)', '(*'..argument(i
)..')')
437 elseif string.match(a
.xarg
.type_name
, '%[.*%]') then
438 larg1
= larg1
.. a
.xarg
.type_name
:gsub('(%[.*%])', argument(i
)..'%1')
440 larg1
= larg1
.. a
.xarg
.type_name
.. ' ' .. argument(i
)
442 larg2
= larg2
.. (i
>1 and ', ' or '') .. argument(i
)
448 get_virtuals
= function(c
)
449 assert(entities
.is_class(c
), 'not a class')
450 local ret
, impl
= {}, {}
451 for _
, f
in ipairs(c
) do
452 if entities
.is_function(f
) and f
.xarg
.virtual
=='1'
453 and not string.match(f
.xarg
.name
, '~') then
455 impl
[f
.xarg
.name
] = #ret
458 -- virtual functions in base classes are not included and
459 -- reimplementation are not marked as virtuals
460 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
461 local bvirt
= get_virtuals(get_unique_fullname(b
))
462 for _
, v
in ipairs(bvirt
) do
463 if not impl
[v
.xarg
.name
] then
465 impl
[v
.xarg
.name
] = #ret
470 -- this wants to return the top-most virtual implementation
471 -- so that it knows to which version it should fallback
472 for _
, f
in ipairs(c
) do
473 if impl
[f
.xarg
.name
] and f
.xarg
.access
~='private' then
474 ret
[ impl
[f
.xarg
.name
] ] = f
481 local virtual_proto
= function(f
)
483 local ret
= 'virtual '..f
.xarg
.type_name
..' '..f
.xarg
.name
..'('
484 local larg1
, larg2
= function_proto(f
)
485 ret
= ret
.. larg1
.. ')'
489 local virtual_body
= function(f
, n
)
491 local ret
= f
.xarg
.type_name
..' '..n
..'::'..f
.xarg
.name
..'('
492 local larg1
, larg2
= function_proto(f
)
493 ret
= ret
.. larg1
.. [[) {
494 int oldtop = lua_gettop(L);
495 lqtL_pushudata(L, this, "]]..f
.parent
.xarg
.fullname
..[[*");
496 lua_getfield(L, -1, "]]..f
.xarg
.name
..[[");
498 if (!lua_isnil(L, -2)) {
500 for i
, a
in arg_iter(f
) do
501 local _d
, _g
, p
, _n
= type_properties(a
)
502 ret
= ret
.. ' ' .. p(argument(i
)) .. ';\n'
505 if (!lua_pcall(L, lua_gettop(L)-oldtop+1, LUA_MULTRET, 0)) {
507 if f
.xarg
.type_name
=='void' then
508 ret
= ret
.. 'return;\n'
510 local _d
, g
, _p
, _n
= type_properties(f
)
511 ret
= ret
.. g('oldtop+1') .. ';\n'
516 lua_settop(L, oldtop);
518 if f
.xarg
.abstract
then
519 if f
.xarg
.type_name
~='void' then
521 if f
.xarg
.type_name
~=f
.xarg
.type_base
then
522 dc
= entities
.default_constructor(f
)
524 local st
, err
= pcall(get_unique_fullname
, f
.xarg
.type_base
)
525 dc
= entities
.default_constructor(st
and err
or f
)
527 if not dc
then return nil end
528 ret
= ret
.. 'return ' .. dc
.. ';\n'
530 ret
= ret
.. 'return;\n'
533 if f
.type_name
~='void' then
534 ret
= ret
.. 'return this->' .. f
.xarg
.fullname
.. '(' .. larg2
.. ');\n'
536 ret
= ret
.. 'this->' .. f
.xarg
.fullname
.. '(' .. larg2
.. ');\n'
543 local examine_class
= function(c
)
544 assert(entities
.is_class(c
), 'not a class')
545 local constr
, destr
= {}, nil
546 for _
, f
in ipairs(c
) do
547 if entities
.is_function(f
) then
548 if entities
.is_constructor(f
) then
549 table.insert(constr
, f
)
550 elseif entities
.is_destructor(f
) then
551 assert(not destr
, 'cannot have more than one destructor!')
557 local public_f, protected_f, virtual_f, virt_prot_f, abstract_f = {}, {}, {}, {}, {}
558 for _, f in ipairs(c) do
559 if entities.is_function(f) then
560 if f.xarg.abstract=='1' then
561 table.insert(abstract_f, f)
562 elseif f.xarg.virtual=='1' and f.xarg.access=='protected' then
563 table.insert(virt_prot_f, f)
564 elseif f.xarg.virtual=='1' and f.xarg.access=='public' then
565 table.insert(virtual_f, f)
566 elseif f.xarg.virtual~='1' and f.xarg.access=='protected' then
567 table.insert(protected_f, f)
568 elseif f.xarg.virtual~='1' and f.xarg.access=='public' then
569 table.insert(public_f, f)
574 local cname
= 'lqt_shell_class'..c
.xarg
.id
575 local ret
= 'class '..cname
..' : public '..c
.xarg
.fullname
..' {\npublic:\n'
576 ret
= ret
.. 'lua_State *L;\n'
577 local onlyprivate
= true
578 for _
, f
in ipairs(constr
) do
579 if f
.xarg
.access
~='private' then
580 local st
, larg1
, larg2
= pcall(function_proto
, f
)
581 --assert(larg1 and larg2, 'cannot reproduce prototype of function')
584 larg1
= (larg1
=='') and '' or (', '..larg1
)
585 ret
= ret
.. cname
.. '(lua_State *l'..larg1
..'):'..c
.xarg
.fullname
..'('
586 ret
= ret
.. larg2
.. '), L(l) {} // '..f
.xarg
.id
..'\n'
591 ret
= ret
.. cname
.. '(lua_State *l):L(l) {} // automatic \n'
592 elseif onlyprivate
then
593 error('cannot bind class: '..c
.xarg
.fullname
..': it has only private constructors')
595 ret
= ret
.. 'virtual ~'..cname
..'() { lqtL_unregister(L, this); }\n'
597 local virtuals
= get_virtuals(c
)
599 for _
, f
in ipairs(virtuals
) do
600 local st
, bd
= pcall(virtual_body
, f
, cname
)
602 ret
= ret
.. virtual_proto(f
) .. ';\n'
603 ret2
= ret2
.. bd
.. '\n'
607 ret
= ret
.. '};\n' .. ret2
612 for _
, v
in pairs(xmlstream
.byid
) do
613 --if string.find(v.label, 'Function')==1 and v.xarg.virtual and v.xarg.abstract then io.stderr:write(v.xarg.fullname, '\n') end
614 if string.find(v
.label
, 'Function')==1 and (not filter_out(v
, FUNCTIONS_FILTERS
)) then
615 local status
, err
= pcall(function_description
, v
)
616 --io[status and 'stdout' or 'stderr']:write((status and '' or v.xarg.fullname..': ')..err..'\n')
617 if true or status
then
618 local s
, e
= pcall(calling_code
, v
)
619 --io[s and 'stdout' or 'stderr']:write((s and ''
620 --or ('error calling '..v.xarg.fullname..': '))..e..(s and '' or '\n'))
622 io
.stdout
:write('extern "C" int bound_function'..v
.xarg
.id
..' (lua_State *L) {\n')
624 io
.stdout
:write('}\n') -- FIXME
626 io
.stderr
:write(e
, '\n')
631 --io[status and 'stdout' or 'stderr']:write((status and '' or v.xarg.fullname..': ')..err..'\n')
632 elseif false and v
.label
=='Class' and not filter_out(v
, CLASS_FILTERS
) then -- do not support templates yet
633 local st
, ret
= pcall(examine_class
, v
)
634 if st
then print(ret
) else io
.stderr
:write(ret
, '\n') end
637 --table.foreach(name_list, print)
640 local make_function
= function(f
)
641 local fret
, s
, e
= '', pcall(calling_code
, f
)
642 if s
and not filter_out(f
, FUNCTIONS_FILTERS
) then
643 fret
= fret
.. 'static int bound_function'..f
.xarg
.id
..' (lua_State *L) {\n'
650 local do_class
= function(fn
)
651 local c
= get_unique_fullname(fn
)
653 ret
= ret
.. examine_class(c
)
656 for _, o in pairs(c.byname) do
657 if o.label=='Overloaded' then
658 io.stderr:write('overload: ', o.xarg.name, ' ', #o, '\n')
659 for __, f in pairs(o) do
660 ret = ret .. make_function(f)
663 ret = ret .. make_function(o)
669 for _
, f
in ipairs(c
) do
670 if entities
.is_function(f
) and not filter_out(f
, FUNCTIONS_FILTERS
) then
671 local _
, argnum
= argument_number(f
) -- care about arguments on stack
672 names
[f
.xarg
.name
] = names
[f
.xarg
.name
] or {}
673 names
[f
.xarg
.name
][argnum
] = names
[f
.xarg
.name
][argnum
] or {}
674 table.insert(names
[f
.xarg
.name
][argnum
], f
)
679 for n, t in pairs(names) do
680 io.stderr:write(n, ' ', tostring(t), '\n')
681 for a, f in pairs(t) do
682 io.stderr:write(' ', tostring(a), '\n')
683 for _, g in pairs(f) do
684 io.stderr:write(' ', g.xarg.id, '\n')
690 local fcomp
= function(f
, g
)
691 if pcall(calling_code
, f
) and not pcall(calling_code
, g
) then
692 elseif entities
.takes_this_pointer(g
) and not entities
.takes_this_pointer(f
) then
694 elseif argument_number(f
) > argument_number(g
) then
696 elseif argument_number(f
) < argument_number(g
) then
699 local fa
, ga
= {}, {}
700 for _
, a
in arg_iter(f
) do
703 for _
, a
in arg_iter(g
) do
707 if base_types
[fa
[i]]
and not base_types
[ga
[i]]
then
709 elseif base_types
[fa
[i]]
and base_types
[ga
[i]]
then
710 return false -- TODO: better handling
720 for name
, t
in pairs(names
) do
721 local call_this_one
= nil
722 local fname
= 'lqt_bind_'..(tostring(name
):match
'%~' and 'delete' or 'function')
723 .. '_' .. tostring(name
):gsub('%~', '')
724 for k
, n
in pairs(t
) do
726 t
[k
] = calling_code(n
[1]):gsub('\n(.)', '\n %1')
727 call_this_one
= call_this_one
and (call_this_one
.. ' } else ') or ' '
728 call_this_one
= call_this_one
.. 'if (lua_gettop(L)=='..tostring(k
)..') {\n'
729 call_this_one
= call_this_one
.. t
[k
]
731 call_this_one
= 'static int ' .. fname
.. ' (lua_State *L) {\n'
733 .. ' }\n return luaL_error(L, "wrong number of arguments");\n}\n'
735 metatable
[name
] = fname
738 io
.write('static const luaL_Reg metatable_'..c
.xarg
.name
..'[] = {\n')
739 for n
, f
in pairs(metatable
) do
740 io
.write( ' { "', n
, '", ', f
, ' },\n')
743 io
.write('\n\nextern "C" int lqtL_open_', c
.xarg
.name
, ' (lua_State *L) {\n')
744 io
.write(' luaL_register(L, "QObject", metatable_', c
.xarg
.name
, ');\n')
745 io
.write(' return 0;\n')
750 local copy_functions
= function(index
)
751 local ret
, copied
= {}, 0
752 for e
in pairs(index
) do
753 if e
.label
:match
'^Function'
754 and (e
.xarg
.name
:match
'^[_%w]*'=='operator'
755 or e
.xarg
.fullname
:match
'%b<>'
756 or e
.xarg
.name
:match
'_'
757 or e
.xarg
.name
:match
'[xX]11'
758 or e
.xarg
.fullname
:match
'QInternal'
759 or e
.xarg
.access
=='private'
760 or e
.xarg
.fullname
=='QVariant::canConvert') then
765 --removed = removed + (e.label:match'^Function' and 1 or 0)
766 --removed = removed + 1
772 local fix_functions
= function(index
)
773 for f
in pairs(index
) do
775 for i
, a
in ipairs(f
) do
776 if a
.label
=='Argument' then
777 table.insert(args
, a
)
781 if elements
.is_constructor(f
) then
782 f
.return_type
= f
.xarg
.type_base
..'&'
783 elseif elements
.is_destructor(f
) then
786 f
.return_type
= f
.xarg
.type_name
792 local copy_enums
= function(index
)
794 for e
in pairs(index
) do
796 and e
.xarg
.access
~='public' then
803 local fix_enums
= function(index
)
804 for e
in pairs(index
) do
806 for _
, v
in ipairs(e
) do
807 if v
.label
=='Enumerators' then
808 values
[#values
] = v
.xarg
.name
816 local copy_classes
= function(index
)
818 for e
in pairs(index
) do
820 and e
.xarg
.access
~='public'
821 and not e
.xarg
.fullname
:match
'%b<>' then
828 local fill_virtuals
= function(index
)
830 for c
in pairs(index
) do
831 classes
[c
.xarg
.fullname
] = c
834 get_virtuals
= function(c
)
836 for _
, f
in ipairs(c
) do
837 if f
.label
=='Function' and f
.xarg
.virtual
=='1' then
838 local n
= string.match(f
.xarg
.name
, '~') or f
.xarg
.name
842 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
843 local base
= classes
[b
]
844 if type(base
)=='table' then
845 local bv
= get_virtuals(base
)
846 for n
, f
in pairs(bv
) do
847 if not ret
[n
] then ret
[n
] = f
end
851 for _
, f
in ipairs(c
) do
852 if f
.label
=='Function'
853 and f
.xarg
.access
~='private'
854 and (ret
[string.match(f
.xarg
.name
, '~') or f
.xarg
.name
]) then
856 local n
= string.match(f
.xarg
.name
, '~')or f
.xarg
.name
862 for c
in pairs(index
) do
863 c
.virtuals
= get_virtuals(c
)
868 local fill_special_methods
= function(index
, functions
)
869 for c
in pairs(index
) do
870 local construct
, destruct
= {}, nil
871 local n
= c
.xarg
.name
872 local auto
, copy
= true, nil
873 for _
, f
in ipairs(c
) do
874 if n
==f
.xarg
.name
then
877 f
[1].xarg
.type_name
==(n
..' const&') then
882 if n
==f
.xarg
.name
then
883 table.insert(construct
, f
)
884 elseif f
.xarg
.name
:match
'~' then
889 construct
.auto
= auto
890 construct
.copy
= copy
891 c
.constructors
= construct
892 c
.destructor
= destruct
897 local functions
= copy_functions(idindex
)
898 local functions
= fix_functions(functions
)
900 local enums
= copy_enums(idindex
)
901 local enums
= fix_enums(enums
)
903 local classes
= copy_classes(idindex
)
904 local classes
= fill_virtuals(classes
)
905 local classes
= fill_special_methods(classes
)
907 local ntable
= function(t
) local ret
=0 for _
in pairs(t
) do ret
=ret
+1 end return ret
end
909 print(ntable(functions
))
911 print(ntable(classes
))
913 local print_virtuals
= function(index
)
914 for c
in pairs(index
) do
916 for n
, f
in pairs(c
.virtuals
) do print(' '..n
, f
.xarg
.fullname
) end
920 --print_virtuals(classes)
922 --print(copy_functions(idindex))