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 fill_special_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 if #(f
.arguments
or {})==1 and
284 f
.arguments
[1].xarg
.type_name
==(c
.xarg
.fullname
..' const&') then
285 copy
= f
.xarg
.access
or 'PUBLIC?'
288 if n
==f
.xarg
.name
then
289 table.insert(construct
, f
)
290 elseif f
.xarg
.name
:match
'~' then
293 if (not string.match(f
.xarg
.name
, '^operator%W'))
294 and (not f
.xarg
.member_template_parameters
) then
295 table.insert(normal
, f
)
299 construct
.copy
= (copy
==nil and 'auto' or copy
) -- FIXME: must try
300 c
.constructors
= construct
301 c
.destructor
= destruct
and (destruct
.xarg
.access
or 'PUBLIC?') or 'auto'
307 local fill_copy_constructor
= function(index
)
309 for c
in pairs(index
) do
310 classes
[c
.xarg
.name
] = c
314 if c
.destructor
=='auto' then
316 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
317 local base
= classes
[b
]
318 if base
and destr(base
)=='private' then
319 c
.destructor
= 'private'
327 copy_constr
= function(c
)
328 if c
.constructors
.copy
=='auto' then
330 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
331 local base
= classes
[b
]
332 if base
and copy_constr(base
)=='private' then
333 c
.constructors
.copy
= 'private'
338 return c
.constructors
.copy
340 for c
in pairs(index
) do
341 c
.constructors
.copy
= copy_constr(c
)
342 c
.destructor
= destr(c
)
343 --io.stderr:write(c.xarg.fullname, '\t', c.constructors.copy, '\n')
344 --io.stderr:write(c.xarg.fullname, '\t', c.destructor, '\n')
349 local fill_typesystem_with_enums
= function(enums
, types
)
351 for e
in pairs(enums
) do
352 if not types
[e
.xarg
.fullname
] then
354 types
[e
.xarg
.fullname
] = {
356 return 'lqtL_pushenum(L, '..n
..', "'..e
.xarg
.fullname
..'")', 1
359 return 'static_cast<'..e
.xarg
.fullname
..'>'
360 ..'(lqtL_toenum(L, '..n
..', "'..e
.xarg
.fullname
..'"))', 1
363 return 'lqtL_isenum(L, '..n
..', "'..e
.xarg
.fullname
..'")', 1
367 --io.stderr:write(e.xarg.fullname, ': already present\n')
373 local fill_typesystem_with_classes
= function(classes
, types
)
375 for c
in pairs(classes
) do
376 if not types
[c
.xarg
.fullname
] then
378 types
[c
.xarg
.fullname
..'*'] = {
379 -- the argument is a pointer to class
381 return 'lqtL_passudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
384 return 'static_cast<'..c
.xarg
.fullname
..'*>'
385 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
388 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
391 types
[c
.xarg
.fullname
..' const*'] = {
392 -- the argument is a pointer to constant class instance
394 return 'lqtL_passudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
397 return 'static_cast<'..c
.xarg
.fullname
..'*>'
398 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
401 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
404 types
[c
.xarg
.fullname
..'&'] = {
405 -- the argument is a reference to class
407 return 'lqtL_passudata(L, &'..n
..', "'..c
.xarg
.fullname
..'*")', 1
410 return '*static_cast<'..c
.xarg
.fullname
..'*>'
411 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
414 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
417 if c
.constructors
.copy
~='private' then -- and c.destructor~='private' then
418 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
419 types
[c
.xarg
.fullname
] = {
420 -- the argument is the class itself
422 return 'lqtL_passudata(L, new '..shellname
423 ..'(L, '..n
..'), "'..c
.xarg
.fullname
..'*")', 1
426 return '*static_cast<'..c
.xarg
.fullname
..'*>'
427 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
430 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
433 types
[c
.xarg
.fullname
..' const&'] = {
434 -- the argument is a pointer to class
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
448 --io.stderr:write(c.xarg.fullname, ': no copy constructor\n')
451 --io.stderr:write(c.xarg.fullname, ': already present\n')
457 local fill_wrapper_code
= function(f
, types
)
458 local stackn
, argn
= 1, 1
459 local wrap
, line
= '', ''
460 if f
.xarg
.member_of_class
and f
.xarg
.static
~='1' then
461 if not types
[f
.xarg
.member_of_class
..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
462 local sget
, sn
= types
[f
.xarg
.member_of_class
..'*'].get(stackn
)
463 wrap
= wrap
.. ' ' .. f
.xarg
.member_of_class
.. '* self = ' .. sget
.. ';\n'
467 lua_pushstring(L, "this pointer is NULL");
472 line
= 'self->'..f
.xarg
.fullname
..'('
474 line
= f
.xarg
.fullname
..'('
476 for i
, a
in ipairs(f
.arguments
) do
477 if not types
[a
.xarg
.type_name
] then return nil end
478 local aget
, an
= types
[a
.xarg
.type_name
].get(stackn
)
479 wrap
= wrap
.. ' ' .. a
.xarg
.type_name
.. ' arg' .. tostring(argn
) .. ' = '
480 if a
.xarg
.default
=='1' and an
>0 then
481 wrap
= wrap
.. 'lua_isnoneornil(L, '..stackn
..')'
482 for j
= stackn
+1,stackn
+an
-1 do
483 wrap
= wrap
.. ' && lua_isnoneornil(L, '..j
..')'
485 local dv
= a
.xarg
.defaultvalue
486 wrap
= wrap
.. ' ? static_cast< ' .. a
.xarg
.type_name
.. ' >(' .. dv
.. ') : '
488 wrap
= wrap
.. aget
.. ';\n'
489 line
= line
.. (argn
==1 and 'arg' or ', arg') .. argn
494 -- FIXME: hack follows for constructors
495 if f
.calling_line
then line
= f
.calling_line
end
496 if f
.return_type
then line
= f
.return_type
.. ' ret = ' .. line
end
497 wrap
= wrap
.. ' ' .. line
.. ';\n lua_settop(L, 0);\n' -- lua_pop(L, '..stackn..');\n'
498 if f
.return_type
then
499 if not types
[f
.return_type
] then return nil end
500 local rput
, rn
= types
[f
.return_type
].push
'ret'
501 wrap
= wrap
.. ' luaL_checkstack(L, '..rn
..', "cannot grow stack for return value");\n'
502 wrap
= wrap
.. ' '..rput
..';\n return '..rn
..';\n'
504 wrap
= wrap
.. ' return 0;\n'
506 f
.wrapper_code
= wrap
510 local fill_test_code
= function(f
, types
)
513 if f
.xarg
.member_of_class
and f
.xarg
.static
~='1' then
514 if not types
[f
.xarg
.member_of_class
..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
515 local stest
, sn
= types
[f
.xarg
.member_of_class
..'*'].test(stackn
)
516 test
= test
.. ' && ' .. stest
519 for i
, a
in ipairs(f
.arguments
) do
520 if not types
[a
.xarg
.type_name
] then return nil end -- print(a.xarg.type_name) return nil end
521 local atest
, an
= types
[a
.xarg
.type_name
].test(stackn
)
522 if a
.xarg
.default
=='1' and an
>0 then
523 test
= test
.. ' && (lqtL_missarg(L, ' .. stackn
.. ', ' .. an
.. ') || '
524 test
= test
.. atest
.. ')'
526 test
= test
.. ' && ' .. atest
530 -- can't make use of default values if I fix number of args
531 test
= '(lua_gettop(L)<' .. stackn
.. ')' .. test
536 local fill_wrappers
= function(functions
, types
)
538 for f
in pairs(functions
) do
539 f
= fill_wrapper_code(f
, types
)
541 f
= assert(fill_test_code(f
, types
), f
.xarg
.fullname
) -- MUST pass
543 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
..' (lua_State *L) {\n'
544 .. f
.wrapper_code
.. '}\n'
551 local argument_name
= function(tn
, an
)
553 if string.match(tn
, '%(%*%)') then
554 ret
= string.gsub(tn
, '%(%*%)', '(*'..an
..')', 1)
555 elseif string.match(tn
, '%[.*%]') then
556 ret
= string.gsub(tn
, '(%[.*%])', an
..'%1')
558 ret
= tn
.. ' ' .. an
563 local virtual_overload
= function(v
, types
)
565 if v
.virtual_overload
then return v
end
567 if v
.return_type
and not types
[v
.return_type
] then return nil end
568 local rget
, rn
= '', 0
569 if v
.return_type
then rget
, rn
= types
[v
.return_type
].get
'oldtop+1' end
570 local retget
= (v
.return_type
and argument_name(v
.return_type
, 'ret')
571 .. ' = ' .. rget
.. ';' or '') .. 'lua_settop(L, oldtop);return'
572 .. (v
.return_type
and ' ret' or '')
573 -- make argument push
574 local pushlines
, stack
= '', 0
575 for i
, a
in ipairs(v
.arguments
) do
576 if not types
[a
.xarg
.type_name
] then return nil end
577 local apush
, an
= types
[a
.xarg
.type_name
].push('arg'..i
)
578 pushlines
= pushlines
.. ' ' .. apush
.. ';\n'
582 local luacall
= 'lua_pcall(L, '..stack
..', '..rn
..', 0)'
583 -- make prototype and fallback
584 local proto
= (v
.return_type
or 'void')..' ;;'..v
.xarg
.name
..' ('
586 for i
, a
in ipairs(v
.arguments
) do
587 proto
= proto
.. (i
>1 and ', ' or '')
588 .. argument_name(a
.xarg
.type_name
, 'arg'..i
)
589 fallback
= fallback
.. (i
>1 and ', arg' or 'arg') .. i
591 proto
= proto
.. ')' .. (v
.xarg
.constant
=='1' and ' const' or '')
592 fallback
= (v
.return_type
and 'return this->' or 'this->')
593 .. v
.xarg
.fullname
.. '(' .. fallback
.. ');\n}\n'
595 int oldtop = lua_gettop(L);
596 lqtL_pushudata(L, this, "]]..v
.xarg
.member_of_class
..[[*");
597 lua_getfield(L, -1, "]]..v
.xarg
.name
..[[");
598 if (lua_isfunction(L, -1)) {
600 ]] .. pushlines
.. [[
601 if (]]..luacall
..[[) {
605 lua_settop(L, oldtop);
607 v
.virtual_overload
= ret
608 v
.virtual_proto
= string.gsub(proto
, ';;', '', 1)
612 local fill_shell_class
= function(c
, types
)
613 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
614 local shell
= 'class ' .. shellname
.. ' : public ' .. c
.xarg
.fullname
.. ' {\npublic:\n'
615 shell
= shell
.. ' lua_State *L;\n'
616 for _
, constr
in ipairs(c
.constructors
) do
617 if constr
.xarg
.access
~='private' then
618 local cline
= ' '..shellname
..' (lua_State *l'
620 for i
, a
in ipairs(constr
.arguments
) do
621 cline
= cline
.. ', ' .. argument_name(a
.xarg
.type_name
, 'arg'..i
)
622 argline
= argline
.. (i
>1 and ', arg' or 'arg') .. i
624 cline
= cline
.. ') : ' .. c
.xarg
.fullname
625 .. '(' .. argline
.. '), L(l) '
626 .. '{ lqtL_register(L, this); }\n'
627 shell
= shell
.. cline
630 if c
.constructors
.copy
=='auto' then
631 local cline
= ' '..shellname
..' (lua_State *l, '..c
.xarg
.fullname
..' const& arg1)'
632 cline
= cline
.. ' : ' .. c
.xarg
.fullname
.. '(arg1), L(l) {}\n'
633 shell
= shell
.. cline
635 for i
, v
in pairs(c
.virtuals
) do
636 if v
.xarg
.access
~='private' then
637 local vret
= virtual_overload(v
, types
)
638 if v
.virtual_proto
then shell
= shell
.. ' virtual ' .. v
.virtual_proto
.. ';\n' end
641 shell
= shell
.. ' ~'..shellname
..'() { lqtL_unregister(L, this); }\n'
642 shell
= shell
.. '};\n'
643 c
.shell_class
= shell
647 local fill_shell_classes
= function(classes
, types
)
649 for c
in pairs(classes
) do
651 c
= fill_shell_class(c
, types
)
652 if c
then ret
[c
] = true else error(c
.xarg
.fullname
) end
658 local print_shell_classes
= function(classes
)
659 for c
in pairs(classes
) do
664 --io.stderr:write(c.fullname, '\n')
671 local print_virtual_overloads
= function(classes
)
672 for c
in pairs(classes
) do
673 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
674 for _
,v
in pairs(c
.virtuals
) do
675 if v
.virtual_overload
then
676 cpp((string.gsub(v
.virtual_overload
, ';;', shellname
..'::', 1)))
683 local print_wrappers
= function(index
)
684 for c
in pairs(index
) do
686 for _
, f
in ipairs(c
.methods
) do
687 if f
.wrapper_code
then
688 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
689 ..' (lua_State *L) {\n'.. f
.wrapper_code
.. '}\n'
690 if f
.xarg
.access
=='public' then
692 meta
[f
] = f
.xarg
.name
697 for _
, f
in ipairs(c
.constructors
) 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
707 --local shellname = 'lqt_shell_'..string.gsub(c.xarg.fullname, '::', '_LQT_')
708 local out
= 'extern "C" int lqt_delete'..c
.xarg
.id
..' (lua_State *L) {\n'
709 out
= out
..' '..c
.xarg
.fullname
..' *p = static_cast<'
710 ..c
.xarg
.fullname
..'*>(lqtL_toudata(L, 1, "'..c
.xarg
.fullname
..'*"));\n'
711 out
= out
.. ' if (p) delete p;\n return 0;\n}\n'
719 local print_metatable
= function(c
)
721 for m
, n
in pairs(c
.meta
) do
722 methods
[n
] = methods
[n
] or {}
723 table.insert(methods
[n
], m
)
725 for n
, l
in pairs(methods
) do
726 local disp
= 'extern "C" int lqt_dispatcher_'..n
..c
.xarg
.id
..' (lua_State *L) {\n'
727 for _
, f
in ipairs(l
) do
728 disp
= disp
..' if ('..f
.test_code
..') return lqt_bind'..f
.xarg
.id
..'(L);\n'
730 disp
= disp
.. ' lua_settop(L, 0);\n'
731 disp
= disp
.. ' lua_pushstring(L, "incorrect or extra arguments");\n'
732 disp
= disp
.. ' return lua_error(L);\n}\n'
735 local metatable
= 'static luaL_Reg lqt_metatable'..c
.xarg
.id
..'[] = {\n'
736 for n
, l
in pairs(methods
) do
737 metatable
= metatable
.. ' { "'..n
..'", lqt_dispatcher_'..n
..c
.xarg
.id
..' },\n'
740 metatable
= metatable
.. ' { "delete", lqt_delete'..c
.xarg
.id
..' },\n'
742 metatable
= metatable
.. ' { 0, 0 },\n};\n'
745 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]*);') do
746 bases
= bases
.. '{"' .. b
.. '*"}, '
748 bases
= 'static lqt_Base lqt_base'..c
.xarg
.id
..'[] = { '..bases
..'{NULL} };\n'
753 local print_metatables
= function(classes
)
754 for c
in pairs(classes
) do
760 local print_class_list
= function(classes
)
761 local list
= 'static lqt_Class lqt_class_list[] = {\n'
762 for c
in pairs(classes
) do
763 class
= '{ lqt_metatable'..c
.xarg
.id
..', lqt_base'..c
.xarg
.id
..', "'..c
.xarg
.fullname
..'*" },\n'
764 list
= list
.. ' ' .. class
766 list
= list
.. ' { 0, 0, 0 },\n};\n'
771 local fix_methods_wrappers
= function(classes
)
772 for c
in pairs(classes
) do
773 -- if class seems abstract but has a shell class
774 -- FIXME: destructor should not matter?
775 if c
.abstract
and c
.destructor
~='private' then
776 -- is it really abstract?
778 for _
, f
in pairs(c
.virtuals
) do
779 -- if it is abstract but we cannot overload
780 if f
.xarg
.abstract
=='1' and not f
.virtual_overload
then a
= true break end
784 -- FIXME: destructor should not matter?
785 c
.shell
= (not c
.abstract
) and (c
.destructor
~='private')
786 for _
, constr
in ipairs(c
.constructors
) do
787 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
788 constr
.calling_line
= '*new '..shellname
..'(L'
789 for i
=1,#(constr
.arguments
) do
790 constr
.calling_line
= constr
.calling_line
.. ', arg' .. i
792 constr
.calling_line
= constr
.calling_line
.. ')'
798 local print_enum_tables
= function(enums
)
799 for e
in pairs(enums
) do
800 local table = 'static lqt_Enum lqt_enum'..e
.xarg
.id
..'[] = {\n'
801 --io.stderr:write(e.xarg.fullname, '\t', #e.values, '\n')
802 for _
,v
in pairs(e
.values
) do
803 table = table .. ' { "' .. v
.xarg
.name
804 .. '", static_cast<int>('..v
.xarg
.fullname
..') },\n'
806 table = table .. ' { 0, 0 }\n'
807 table = table .. '};\n'
813 local print_enum_creator
= function(enums
)
814 local out
= 'static lqt_Enumlist lqt_enum_list[] = {\n'
815 for e
in pairs(enums
) do
816 out
= out
..' { lqt_enum'..e
.xarg
.id
..', "'..e
.xarg
.fullname
..'" },\n'
818 out
= out
..' { 0, 0 },\n};\n'
819 out
= out
.. 'extern "C" int lqt_create_enums (lua_State *L) {\n'
820 out
= out
.. ' lqtL_createenumlist(L, lqt_enum_list); return 0;\n}\n'
825 local print_openmodule
= function(n
)
828 extern "C" int luaopen_]]..n
..[[ (lua_State *L) {
830 lqtL_createclasses(L, lqt_class_list);
836 --------------------------------------------------------------------------------------
838 local typesystem
= {}
841 for i
, ft
in ipairs(typefiles
) do
844 setmetatable(typesystem
, {
845 __newindex
= function(t
, k
, v
)
846 --debug('added type', k)
849 __index
= function(t
, k
)
851 --if not ret then debug("unknown type:", tostring(k), ret) end
857 fix_arguments(idindex
) -- fixes default arguments if they are context-relative
858 local functions
= copy_functions(idindex
) -- pics functions and fixes label
859 local functions
= fix_functions(functions
) -- fixes name and fullname and fills arguments
861 local enums
= copy_enums(idindex
) -- picks enums if public
862 local enums
= fill_enums(enums
) -- fills field "values"
864 local classes
= copy_classes(idindex
) -- picks classes if not private and not blacklisted
865 local classes
= fill_virtuals(classes
) -- does that, destructor ("~") excluded
866 local classes
= fill_special_methods(classes
)
867 local classes
= fill_copy_constructor(classes
)
868 local classes
= fix_methods_wrappers(classes
)
870 local enums
= fill_typesystem_with_enums(enums
, typesystem
) -- does that
871 local classes
= fill_typesystem_with_classes(classes
, typesystem
)
872 local functions
= fill_wrappers(functions
, typesystem
)
873 local classes
= fill_shell_classes(classes
, typesystem
)
875 ------------- BEGIN OUTPUT
878 hpp('#ifndef LQT_BIND_'..module_name
)
879 hpp('#define LQT_BIND_'..module_name
)
882 for _
, i
in ipairs(output_includes
) do
887 cpp('#include "'..tostring(hppname
)..'"')
891 local classes
= print_shell_classes(classes
) -- does that
892 local classes
= print_virtual_overloads(classes
, typesystem
) -- does that
893 local classes
= print_wrappers(classes
) -- does that + FIXME: checks if has shell for constr/destr and compiles metatable list
894 local enums
= print_enum_tables(enums
) -- does that
895 local enums
= print_enum_creator(enums
) -- does that + print enum list
896 local classes
= print_metatables(classes
) -- does that + print dispatchers
897 local classes
= print_class_list(classes
) -- does that
899 print_openmodule(module_name
) -- does that
901 hpp('#endif // LQT_BIND_'..module_name
)