5 Copyright (c) 2007-2008 Mauro Iazzi
7 Permission is hereby granted, free of charge, to any person
8 obtaining a copy of this software and associated documentation
9 files (the "Software"), to deal in the Software without
10 restriction, including without limitation the rights to use,
11 copy, modify, merge, publish, distribute, sublicense, and/or sell
12 copies of the Software, and to permit persons to whom the
13 Software is furnished to do so, subject to the following
16 The above copyright notice and this permission notice shall be
17 included in all copies or substantial portions of the Software.
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
21 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
23 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
26 OTHER DEALINGS IN THE SOFTWARE.
30 local path
= string.match(arg
[0], '(.*/)[^%/]+') or ''
35 local module_name
= nil
37 local output_includes
= {
43 while select(i
, ...) do
44 local argi
= select(i
, ...)
47 module_name
= select(i
, ...)
48 elseif argi
=='-d' then
50 dirname
= select(i
, ...)
51 elseif argi
=='-i' then
53 table.insert(output_includes
, (select(i
, ...)))
54 elseif argi
=='-t' then
56 table.insert(typefiles
, (select(i
, ...)))
57 elseif argi
=='-h' then
59 hppname
= select(i
, ...)
60 elseif argi
=='-c' then
62 cppname
= select(i
, ...)
63 elseif argi
=='-o' then
65 local name
= select(i
, ...)
66 cppname
= name
..'.cpp'
67 hppname
= name
..'.hpp'
69 filename
= filename
and error'duplicate filename' or argi
73 dirname
= dirname
or ''
76 local readfile
= function(fn
)
77 local f
= assert(io
.open(fn
))
83 local fprint
= function(f
)
85 for i
= 1, select('#',...) do
86 f
:write((i
==1) and '' or '\t', tostring(select(i
,...)))
92 local debug
= fprint(io
.stderr
)
93 local cpp
, hpp
= nil, nil
95 local cppfile
= assert(io
.open(dirname
.. cppname
, 'w'))
101 local hppfile
= assert(io
.open(dirname
.. hppname
, 'w'))
102 hpp
= fprint(hppfile
)
107 local xmlstream
, idindex
= dofile(path
..'xml.lua')(readfile(filename
))
109 ----------------------------------------------------------------------------------
111 local copy_functions
= function(index
)
113 for e
in pairs(index
) do
114 if e
.label
:match
'^Function' then
123 local fix_arguments
= function(all
)
125 for e
in pairs(all
or {}) do
126 if e
.xarg
.fullname
then fullnames
[e
.xarg
.fullname
] = true end
128 for a
in pairs(all
) do
129 if a
.label
=='Argument'
130 and a
.xarg
.default
=='1'
131 and string.match(a
.xarg
.defaultvalue
, '%D') then
132 local dv
= a
.xarg
.defaultvalue
133 if not fullnames
[dv
] then
134 dv
= a
.xarg
.context
..'::'..dv
136 if fullnames
[dv
] then
137 a
.xarg
.defaultvalue
= dv
140 a
.xarg
.defaultvalue
= nil
147 local fix_functions
= function(index
)
148 for f
in pairs(index
) do
150 for i
, a
in ipairs(f
) do
151 -- avoid bogus 'void' arguments
152 if a
.xarg
.type_name
=='void' and i
==1 and f
[2]==nil then break end
153 if a
.label
=='Argument' then
154 table.insert(args
, a
)
158 local is_constructor
= function(f
)
159 return (f
.xarg
.member_of_class
and f
.xarg
.member_of_class
~=''
160 and f
.xarg
.fullname
==(f
.xarg
.member_of_class
..'::'..f
.xarg
.name
) -- this should be always true
161 and string.match(f
.xarg
.member_of_class
, f
.xarg
.name
..'$'))
163 if is_constructor(f
) then
164 f
.xarg
.fullname
= '*new '..f
.xarg
.fullname
165 f
.return_type
= f
.xarg
.type_base
..'&'
167 elseif string.match(f
.xarg
.name
, '~') or f
.xarg
.type_name
=='void' then
170 if false and f
.xarg
.access
=='protected' then
171 local shellname
= 'lqt_shell_'..string.gsub(f
.parent
.xarg
.fullname
, '::', '_LQT_')
172 f
.xarg
.fullname
= shellname
..'::'..f
.xarg
.name
173 if f
.xarg
.static
~='1' then
175 local newarg
= { label
='Argument', xarg
= {
176 type_name
= f
.xarg
.member_of_class
..'*',
178 table.insert(args
, newarg
, 1)
181 f
.return_type
= f
.xarg
.type_name
187 local copy_enums
= function(index
)
189 for e
in pairs(index
) do
191 and not string.match(e
.xarg
.fullname
, '%b<>')
192 and e
.xarg
.access
=='public' then
199 local fill_enums
= function(index
)
200 for e
in pairs(index
) do
202 for _
, v
in ipairs(e
) do
203 if v
.label
=='Enumerator' then
204 table.insert(values
, v
)
212 local copy_classes
= function(index
)
214 for e
in pairs(index
) do
216 and e
.xarg
.access
~='private'
217 and not (e
.xarg
.fullname
:match
'%b<>'
218 or e
.xarg
.fullname
=='QDebug::Stream'
219 or e
.xarg
.fullname
=='QForeachContainerBase'
220 or e
.xarg
.fullname
=='QByteArray::Data'
221 or e
.xarg
.fullname
=='QVariant::Private::Data'
222 or e
.xarg
.fullname
=='QRegion::QRegionData'
223 or e
.xarg
.fullname
=='QTextStreamManipulator'
224 or e
.xarg
.fullname
=='QString::Data'
225 or e
.xarg
.fullname
=='QThreadStorageData'
233 local fill_virtuals
= function(index
)
235 for c
in pairs(index
) do
236 classes
[c
.xarg
.fullname
] = c
239 get_virtuals
= function(c
)
241 for _
, f
in ipairs(c
) do
242 if f
.label
=='Function' and f
.xarg
.virtual
=='1' then
243 local n
= string.match(f
.xarg
.name
, '~') or f
.xarg
.name
244 if n
~='~' then ret
[n
] = f
end
247 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
248 local base
= classes
[b
]
249 if type(base
)=='table' then
250 local bv
= get_virtuals(base
)
251 for n
, f
in pairs(bv
) do
252 if not ret
[n
] then ret
[n
] = f
end
256 for _
, f
in ipairs(c
) do
257 if f
.label
=='Function'
258 and f
.xarg
.access
~='private'
259 and (ret
[string.match(f
.xarg
.name
, '~') or f
.xarg
.name
]) then
261 local n
= string.match(f
.xarg
.name
, '~')or f
.xarg
.name
267 for c
in pairs(index
) do
268 c
.virtuals
= get_virtuals(c
)
269 for _
, f
in pairs(c
.virtuals
) do
270 if f
.xarg
.abstract
=='1' then c
.abstract
=true break end
276 local distinguish_methods
= function(index
)
277 for c
in pairs(index
) do
278 local construct
, destruct
, normal
= {}, nil, {}
279 local n
= c
.xarg
.name
281 for _
, f
in ipairs(c
) do
282 if n
==f
.xarg
.name
then
283 table.insert(construct
, f
)
284 elseif f
.xarg
.name
:match
'~' then
287 if (not string.match(f
.xarg
.name
, '^operator%W'))
288 and (not f
.xarg
.member_template_parameters
) then
289 table.insert(normal
, f
)
293 c
.constructors
= construct
294 c
.destructor
= destruct
300 local fill_public_destr
= function(index
)
302 for c
in pairs(index
) do
303 classes
[c
.xarg
.fullname
] = c
305 local destr_is_public
306 destr_is_public
= function(c
)
308 return c
.destructor
.xarg
.access
=='public'
310 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
311 local base
= classes
[b
]
312 if base
and not destr_is_public(base
) then
319 for c
in pairs(index
) do
320 c
.public_destr
= destr_is_public(c
)
325 local fill_copy_constructor
= function(index
)
327 for c
in pairs(index
) do
328 classes
[c
.xarg
.name
] = c
330 for c
in pairs(index
) do
332 for _
, f
in ipairs(c
.constructors
) do
334 and f
.arguments
[1].xarg
.type_name
==c
.xarg
.fullname
..' const&' then
339 c
.copy_constructor
= copy
341 local copy_constr_is_public
342 copy_constr_is_public
= function(c
)
343 if c
.copy_constructor
then
344 return (c
.copy_constructor
.xarg
.access
=='public')
345 or (c
.copy_constructor
.xarg
.access
=='protected')
348 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
349 local base
= classes
[b
]
350 if base
and not copy_constr_is_public(base
) then
357 for c
in pairs(index
) do
358 c
.public_constr
= copy_constr_is_public(c
)
363 local fill_typesystem_with_enums
= function(enums
, types
)
365 for e
in pairs(enums
) do
366 if not types
[e
.xarg
.fullname
] then
368 types
[e
.xarg
.fullname
] = {
370 return 'lqtL_pushenum(L, '..n
..', "'..e
.xarg
.fullname
..'")', 1
373 return 'static_cast<'..e
.xarg
.fullname
..'>'
374 ..'(lqtL_toenum(L, '..n
..', "'..e
.xarg
.fullname
..'"))', 1
377 return 'lqtL_isenum(L, '..n
..', "'..e
.xarg
.fullname
..'")', 1
381 --io.stderr:write(e.xarg.fullname, ': already present\n')
387 local fill_typesystem_with_classes
= function(classes
, types
)
389 for c
in pairs(classes
) do
390 if not types
[c
.xarg
.fullname
] then
392 types
[c
.xarg
.fullname
..'*'] = {
393 -- the argument is a pointer to class
395 return 'lqtL_passudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
398 return 'static_cast<'..c
.xarg
.fullname
..'*>'
399 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
402 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
405 types
[c
.xarg
.fullname
..' const*'] = {
406 -- the argument is a pointer to constant class instance
408 return 'lqtL_passudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
411 return 'static_cast<'..c
.xarg
.fullname
..'*>'
412 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
415 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
418 types
[c
.xarg
.fullname
..'&'] = {
419 -- the argument is a reference to class
421 return 'lqtL_passudata(L, &'..n
..', "'..c
.xarg
.fullname
..'*")', 1
424 return '*static_cast<'..c
.xarg
.fullname
..'*>'
425 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
428 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
431 if c
.public_constr
and c
.shell
then
432 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
433 types
[c
.xarg
.fullname
] = {
434 -- the argument is the class itself
436 return 'lqtL_passudata(L, new '..shellname
437 ..'(L, '..n
..'), "'..c
.xarg
.fullname
..'*")', 1
440 return '*static_cast<'..c
.xarg
.fullname
..'*>'
441 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
444 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
447 types
[c
.xarg
.fullname
..' const&'] = {
448 -- the argument is a pointer to class
450 return 'lqtL_passudata(L, new '..shellname
451 ..'(L, '..n
..'), "'..c
.xarg
.fullname
..'*")', 1
454 return '*static_cast<'..c
.xarg
.fullname
..'*>'
455 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
458 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
467 local fill_wrapper_code
= function(f
, types
)
468 if f
.wrapper_code
then return f
end
469 local stackn
, argn
= 1, 1
470 local wrap
, line
= '', ''
471 if f
.xarg
.member_of_class
and f
.xarg
.static
~='1' then
472 if not types
[f
.xarg
.member_of_class
..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
473 local sget
, sn
= types
[f
.xarg
.member_of_class
..'*'].get(stackn
)
474 wrap
= wrap
.. ' ' .. f
.xarg
.member_of_class
.. '* self = ' .. sget
.. ';\n'
478 lua_pushstring(L, "this pointer is NULL");
483 line
= 'self->'..f
.xarg
.fullname
..'('
485 line
= f
.xarg
.fullname
..'('
487 for i
, a
in ipairs(f
.arguments
) do
488 if not types
[a
.xarg
.type_name
] then return nil end
489 local aget
, an
= types
[a
.xarg
.type_name
].get(stackn
)
490 wrap
= wrap
.. ' ' .. a
.xarg
.type_name
.. ' arg' .. tostring(argn
) .. ' = '
491 if a
.xarg
.default
=='1' and an
>0 then
492 wrap
= wrap
.. 'lua_isnoneornil(L, '..stackn
..')'
493 for j
= stackn
+1,stackn
+an
-1 do
494 wrap
= wrap
.. ' && lua_isnoneornil(L, '..j
..')'
496 local dv
= a
.xarg
.defaultvalue
497 wrap
= wrap
.. ' ? static_cast< ' .. a
.xarg
.type_name
.. ' >(' .. dv
.. ') : '
499 wrap
= wrap
.. aget
.. ';\n'
500 line
= line
.. (argn
==1 and 'arg' or ', arg') .. argn
505 -- FIXME: hack follows for constructors
506 if f
.calling_line
then line
= f
.calling_line
end
507 if f
.return_type
then line
= f
.return_type
.. ' ret = ' .. line
end
508 wrap
= wrap
.. ' ' .. line
.. ';\n lua_settop(L, 0);\n' -- lua_pop(L, '..stackn..');\n'
509 if f
.return_type
then
510 if not types
[f
.return_type
] then return nil end
511 local rput
, rn
= types
[f
.return_type
].push
'ret'
512 wrap
= wrap
.. ' luaL_checkstack(L, '..rn
..', "cannot grow stack for return value");\n'
513 wrap
= wrap
.. ' '..rput
..';\n return '..rn
..';\n'
515 wrap
= wrap
.. ' return 0;\n'
517 f
.wrapper_code
= wrap
521 local fill_test_code
= function(f
, types
)
524 if f
.xarg
.member_of_class
and f
.xarg
.static
~='1' then
525 if not types
[f
.xarg
.member_of_class
..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
526 local stest
, sn
= types
[f
.xarg
.member_of_class
..'*'].test(stackn
)
527 test
= test
.. ' && ' .. stest
530 for i
, a
in ipairs(f
.arguments
) do
531 if not types
[a
.xarg
.type_name
] then return nil end -- print(a.xarg.type_name) return nil end
532 local atest
, an
= types
[a
.xarg
.type_name
].test(stackn
)
533 if a
.xarg
.default
=='1' and an
>0 then
534 test
= test
.. ' && (lqtL_missarg(L, ' .. stackn
.. ', ' .. an
.. ') || '
535 test
= test
.. atest
.. ')'
537 test
= test
.. ' && ' .. atest
541 -- can't make use of default values if I fix number of args
542 test
= '(lua_gettop(L)<' .. stackn
.. ')' .. test
547 local fill_wrappers
= function(functions
, types
)
549 for f
in pairs(functions
) do
550 f
= fill_wrapper_code(f
, types
)
552 f
= assert(fill_test_code(f
, types
), f
.xarg
.fullname
) -- MUST pass
554 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
..' (lua_State *L) {\n'
555 .. f
.wrapper_code
.. '}\n'
562 local argument_name
= function(tn
, an
)
564 if string.match(tn
, '%(%*%)') then
565 ret
= string.gsub(tn
, '%(%*%)', '(*'..an
..')', 1)
566 elseif string.match(tn
, '%[.*%]') then
567 ret
= string.gsub(tn
, '(%[.*%])', an
..'%1')
569 ret
= tn
.. ' ' .. an
574 local virtual_overload
= function(v
, types
)
576 if v
.virtual_overload
then return v
end
578 if v
.return_type
and not types
[v
.return_type
] then return nil end
579 local rget
, rn
= '', 0
580 if v
.return_type
then rget
, rn
= types
[v
.return_type
].get
'oldtop+1' end
581 local retget
= (v
.return_type
and argument_name(v
.return_type
, 'ret')
582 .. ' = ' .. rget
.. ';' or '') .. 'lua_settop(L, oldtop);return'
583 .. (v
.return_type
and ' ret' or '')
584 -- make argument push
585 local pushlines
, stack
= '', 0
586 for i
, a
in ipairs(v
.arguments
) do
587 if not types
[a
.xarg
.type_name
] then return nil end
588 local apush
, an
= types
[a
.xarg
.type_name
].push('arg'..i
)
589 pushlines
= pushlines
.. ' ' .. apush
.. ';\n'
593 local luacall
= 'lua_pcall(L, '..stack
..', '..rn
..', 0)'
594 -- make prototype and fallback
595 local proto
= (v
.return_type
or 'void')..' ;;'..v
.xarg
.name
..' ('
597 for i
, a
in ipairs(v
.arguments
) do
598 proto
= proto
.. (i
>1 and ', ' or '')
599 .. argument_name(a
.xarg
.type_name
, 'arg'..i
)
600 fallback
= fallback
.. (i
>1 and ', arg' or 'arg') .. i
602 proto
= proto
.. ')' .. (v
.xarg
.constant
=='1' and ' const' or '')
603 fallback
= (v
.return_type
and 'return this->' or 'this->')
604 .. v
.xarg
.fullname
.. '(' .. fallback
.. ');\n}\n'
606 int oldtop = lua_gettop(L);
607 lqtL_pushudata(L, this, "]]..v
.xarg
.member_of_class
..[[*");
608 lua_getfield(L, -1, "]]..v
.xarg
.name
..[[");
609 if (lua_isfunction(L, -1)) {
611 ]] .. pushlines
.. [[
612 if (]]..luacall
..[[) {
616 lua_settop(L, oldtop);
618 v
.virtual_overload
= ret
619 v
.virtual_proto
= string.gsub(proto
, ';;', '', 1)
623 local fill_shell_class
= function(c
, types
)
624 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
625 local shell
= 'class ' .. shellname
.. ' : public ' .. c
.xarg
.fullname
.. ' {\npublic:\n'
626 shell
= shell
.. ' lua_State *L;\n'
627 for _
, constr
in ipairs(c
.constructors
) do
628 if constr
.xarg
.access
~='private' then
629 local cline
= ' '..shellname
..' (lua_State *l'
631 for i
, a
in ipairs(constr
.arguments
) do
632 cline
= cline
.. ', ' .. argument_name(a
.xarg
.type_name
, 'arg'..i
)
633 argline
= argline
.. (i
>1 and ', arg' or 'arg') .. i
635 cline
= cline
.. ') : ' .. c
.xarg
.fullname
636 .. '(' .. argline
.. '), L(l) '
637 .. '{ lqtL_register(L, this); }\n'
638 shell
= shell
.. cline
641 if c
.copy_constructor
==nil and c
.public_constr
then
642 local cline
= ' '..shellname
..' (lua_State *l, '..c
.xarg
.fullname
..' const& arg1)'
643 cline
= cline
.. ' : ' .. c
.xarg
.fullname
.. '(arg1), L(l) {}\n'
644 shell
= shell
.. cline
646 for i
, v
in pairs(c
.virtuals
) do
647 if v
.xarg
.access
~='private' then
648 local vret
= virtual_overload(v
, types
)
649 if v
.virtual_proto
then shell
= shell
.. ' virtual ' .. v
.virtual_proto
.. ';\n' end
652 shell
= shell
.. ' ~'..shellname
..'() { lqtL_unregister(L, this); }\n'
653 shell
= shell
.. '};\n'
654 c
.shell_class
= shell
658 local fill_shell_classes
= function(classes
, types
)
660 for c
in pairs(classes
) do
662 c
= fill_shell_class(c
, types
)
663 if c
then ret
[c
] = true else error(c
.xarg
.fullname
) end
669 local print_shell_classes
= function(classes
)
670 for c
in pairs(classes
) do
675 --io.stderr:write(c.fullname, '\n')
682 local print_virtual_overloads
= function(classes
)
683 for c
in pairs(classes
) do
684 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
685 for _
,v
in pairs(c
.virtuals
) do
686 if v
.virtual_overload
then
687 cpp((string.gsub(v
.virtual_overload
, ';;', shellname
..'::', 1)))
694 local print_wrappers
= function(index
)
695 for c
in pairs(index
) do
697 for _
, f
in ipairs(c
.methods
) do
698 if f
.wrapper_code
then
699 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
700 ..' (lua_State *L) {\n'.. f
.wrapper_code
.. '}\n'
701 if f
.xarg
.access
=='public' then
703 meta
[f
] = f
.xarg
.name
708 for _
, f
in ipairs(c
.constructors
) do
709 if f
.wrapper_code
then
710 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
711 ..' (lua_State *L) {\n'.. f
.wrapper_code
.. '}\n'
712 if f
.xarg
.access
=='public' then
718 --local shellname = 'lqt_shell_'..string.gsub(c.xarg.fullname, '::', '_LQT_')
719 local out
= 'extern "C" int lqt_delete'..c
.xarg
.id
..' (lua_State *L) {\n'
720 out
= out
..' '..c
.xarg
.fullname
..' *p = static_cast<'
721 ..c
.xarg
.fullname
..'*>(lqtL_toudata(L, 1, "'..c
.xarg
.fullname
..'*"));\n'
722 out
= out
.. ' if (p) delete p;\n return 0;\n}\n'
730 local print_metatable
= function(c
)
732 for m
, n
in pairs(c
.meta
) do
733 methods
[n
] = methods
[n
] or {}
734 table.insert(methods
[n
], m
)
736 for n
, l
in pairs(methods
) do
737 local disp
= 'extern "C" int lqt_dispatcher_'..n
..c
.xarg
.id
..' (lua_State *L) {\n'
738 for _
, f
in ipairs(l
) do
739 disp
= disp
..' if ('..f
.test_code
..') return lqt_bind'..f
.xarg
.id
..'(L);\n'
741 disp
= disp
.. ' lua_settop(L, 0);\n'
742 disp
= disp
.. ' lua_pushstring(L, "incorrect or extra arguments");\n'
743 disp
= disp
.. ' return lua_error(L);\n}\n'
746 local metatable
= 'static luaL_Reg lqt_metatable'..c
.xarg
.id
..'[] = {\n'
747 for n
, l
in pairs(methods
) do
748 metatable
= metatable
.. ' { "'..n
..'", lqt_dispatcher_'..n
..c
.xarg
.id
..' },\n'
751 metatable
= metatable
.. ' { "delete", lqt_delete'..c
.xarg
.id
..' },\n'
753 metatable
= metatable
.. ' { 0, 0 },\n};\n'
756 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]*);') do
757 bases
= bases
.. '{"' .. b
.. '*"}, '
759 bases
= 'static lqt_Base lqt_base'..c
.xarg
.id
..'[] = { '..bases
..'{NULL} };\n'
764 local print_metatables
= function(classes
)
765 for c
in pairs(classes
) do
771 local print_class_list
= function(classes
)
772 local list
= 'static lqt_Class lqt_class_list[] = {\n'
773 for c
in pairs(classes
) do
774 class
= '{ lqt_metatable'..c
.xarg
.id
..', lqt_base'..c
.xarg
.id
..', "'..c
.xarg
.fullname
..'*" },\n'
775 list
= list
.. ' ' .. class
777 list
= list
.. ' { 0, 0, 0 },\n};\n'
782 local fix_methods_wrappers
= function(classes
)
783 for c
in pairs(classes
) do
784 -- if class seems abstract but has a shell class
786 -- is it really abstract?
788 for _
, f
in pairs(c
.virtuals
) do
789 -- if it is abstract but we cannot overload
790 -- FIXME: this always fails: f.virtual_overload is not filled yet
791 -- maybe this check must be moved later:
792 -- we don't use shell class to move instances to Lua
793 -- but we want to instantiate if we can wrap all virtuals...
794 if f
.xarg
.abstract
=='1' and not f
.virtual_overload
then a
= true break end
798 c
.shell
= (not c
.abstract
) and c
.public_destr
799 for _
, constr
in ipairs(c
.constructors
) do
800 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
801 constr
.calling_line
= '*new '..shellname
..'(L'
802 for i
=1,#(constr
.arguments
) do
803 constr
.calling_line
= constr
.calling_line
.. ', arg' .. i
805 constr
.calling_line
= constr
.calling_line
.. ')'
811 local print_enum_tables
= function(enums
)
812 for e
in pairs(enums
) do
813 local table = 'static lqt_Enum lqt_enum'..e
.xarg
.id
..'[] = {\n'
814 --io.stderr:write(e.xarg.fullname, '\t', #e.values, '\n')
815 for _
,v
in pairs(e
.values
) do
816 table = table .. ' { "' .. v
.xarg
.name
817 .. '", static_cast<int>('..v
.xarg
.fullname
..') },\n'
819 table = table .. ' { 0, 0 }\n'
820 table = table .. '};\n'
826 local print_enum_creator
= function(enums
)
827 local out
= 'static lqt_Enumlist lqt_enum_list[] = {\n'
828 for e
in pairs(enums
) do
829 out
= out
..' { lqt_enum'..e
.xarg
.id
..', "'..e
.xarg
.fullname
..'" },\n'
831 out
= out
..' { 0, 0 },\n};\n'
832 out
= out
.. 'extern "C" int lqt_create_enums (lua_State *L) {\n'
833 out
= out
.. ' lqtL_createenumlist(L, lqt_enum_list); return 0;\n}\n'
838 local print_openmodule
= function(n
)
841 extern "C" int luaopen_]]..n
..[[ (lua_State *L) {
843 lqtL_createclasses(L, lqt_class_list);
849 --------------------------------------------------------------------------------------
851 local typesystem
= {}
854 for i
, ft
in ipairs(typefiles
) do
857 setmetatable(typesystem
, {
858 __newindex
= function(t
, k
, v
)
859 --debug('added type', k)
862 __index
= function(t
, k
)
864 --if not ret then debug("unknown type:", tostring(k), ret) end
870 fix_arguments(idindex
) -- fixes default arguments if they are context-relative
871 local functions
= copy_functions(idindex
) -- picks functions and fixes label
872 local functions
= fix_functions(functions
) -- fixes name and fullname and fills arguments
874 local enums
= copy_enums(idindex
) -- picks enums if public
875 local enums
= fill_enums(enums
) -- fills field "values"
877 local classes
= copy_classes(idindex
) -- picks classes if not private and not blacklisted
878 local classes
= fill_virtuals(classes
) -- does that, destructor ("~") excluded
879 local classes
= distinguish_methods(classes
) -- does that
880 local classes
= fill_public_destr(classes
) -- does that: checks if destructor is public
881 local classes
= fill_copy_constructor(classes
) -- does that: checks if copy contructor is public or protected
882 local classes
= fix_methods_wrappers(classes
)
884 local enums
= fill_typesystem_with_enums(enums
, typesystem
) -- does that
885 local classes
= fill_typesystem_with_classes(classes
, typesystem
)
886 local functions
= fill_wrappers(functions
, typesystem
)
887 local classes
= fill_shell_classes(classes
, typesystem
)
889 ------------- BEGIN OUTPUT
892 hpp('#ifndef LQT_BIND_'..module_name
)
893 hpp('#define LQT_BIND_'..module_name
)
896 for _
, i
in ipairs(output_includes
) do
901 cpp('#include "'..tostring(hppname
)..'"')
905 local classes
= print_shell_classes(classes
) -- does that
906 local classes
= print_virtual_overloads(classes
, typesystem
) -- does that
907 local classes
= print_wrappers(classes
) -- does that + FIXME: checks if has shell for constr/destr and compiles metatable list
908 local enums
= print_enum_tables(enums
) -- does that
909 local enums
= print_enum_creator(enums
) -- does that + print enum list
910 local classes
= print_metatables(classes
) -- does that + print dispatchers
911 local classes
= print_class_list(classes
) -- does that
913 print_openmodule(module_name
) -- does that
915 hpp('#endif // LQT_BIND_'..module_name
)