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
,...)))
93 local debug
= fprint(io
.stderr
)
94 local cpp
, hpp
= nil, nil
96 local cppfile
= assert(io
.open(dirname
.. cppname
, 'w'))
102 local hppfile
= assert(io
.open(dirname
.. hppname
, 'w'))
103 hpp
= fprint(hppfile
)
108 local xmlstream
, idindex
= dofile(path
..'xml.lua')(readfile(filename
))
110 ----------------------------------------------------------------------------------
112 local copy_functions
= function(index
)
114 for e
in pairs(index
) do
115 if e
.label
:match
'^Function' then
124 local fix_arguments
= function(all
)
126 for e
in pairs(all
or {}) do
127 if e
.xarg
.fullname
then fullnames
[e
.xarg
.fullname
] = true end
129 for a
in pairs(all
) do
130 if a
.label
=='Argument'
131 and a
.xarg
.default
=='1'
132 and string.match(a
.xarg
.defaultvalue
, '%D') then
133 local dv
= a
.xarg
.defaultvalue
134 if not fullnames
[dv
] then
135 dv
= a
.xarg
.context
..'::'..dv
137 if fullnames
[dv
] then
138 a
.xarg
.defaultvalue
= dv
141 a
.xarg
.defaultvalue
= nil
148 local fix_functions
= function(index
)
149 for f
in pairs(index
) do
151 for i
, a
in ipairs(f
) do
152 -- avoid bogus 'void' arguments
153 if a
.xarg
.type_name
=='void' and i
==1 and f
[2]==nil then break end
154 if a
.label
=='Argument' then
155 table.insert(args
, a
)
159 local is_constructor
= function(f
)
160 return (f
.xarg
.member_of_class
and f
.xarg
.member_of_class
~=''
161 and f
.xarg
.fullname
==(f
.xarg
.member_of_class
..'::'..f
.xarg
.name
) -- this should be always true
162 and string.match(f
.xarg
.member_of_class
, f
.xarg
.name
..'$'))
164 if is_constructor(f
) then
165 f
.xarg
.fullname
= '*new '..f
.xarg
.fullname
166 f
.return_type
= f
.xarg
.type_base
..'&'
168 elseif string.match(f
.xarg
.name
, '~') or f
.xarg
.type_name
=='void' then
171 if false and f
.xarg
.access
=='protected' then
172 local shellname
= 'lqt_shell_'..string.gsub(f
.parent
.xarg
.fullname
, '::', '_LQT_')
173 f
.xarg
.fullname
= shellname
..'::'..f
.xarg
.name
174 if f
.xarg
.static
~='1' then
176 local newarg
= { label
='Argument', xarg
= {
177 type_name
= f
.xarg
.member_of_class
..'*',
179 table.insert(args
, newarg
, 1)
182 f
.return_type
= f
.xarg
.type_name
188 local copy_enums
= function(index
)
190 for e
in pairs(index
) do
192 and not string.match(e
.xarg
.fullname
, '%b<>')
193 and e
.xarg
.access
=='public' then
200 local fill_enums
= function(index
)
201 for e
in pairs(index
) do
203 for _
, v
in ipairs(e
) do
204 if v
.label
=='Enumerator' then
205 table.insert(values
, v
)
213 local copy_classes
= function(index
)
215 for e
in pairs(index
) do
217 and e
.xarg
.access
~='private'
218 and not (e
.xarg
.fullname
:match
'%b<>'
219 or e
.xarg
.fullname
=='QDebug::Stream'
220 or e
.xarg
.fullname
=='QForeachContainerBase'
221 or e
.xarg
.fullname
=='QByteArray::Data'
222 or e
.xarg
.fullname
=='QVariant::Private::Data'
223 or e
.xarg
.fullname
=='QRegion::QRegionData'
224 or e
.xarg
.fullname
=='QTextStreamManipulator'
225 or e
.xarg
.fullname
=='QString::Data'
226 or e
.xarg
.fullname
=='QThreadStorageData'
234 local fill_virtuals
= function(index
)
236 for c
in pairs(index
) do
237 classes
[c
.xarg
.fullname
] = c
240 get_virtuals
= function(c
)
242 for _
, f
in ipairs(c
) do
243 if f
.label
=='Function' and f
.xarg
.virtual
=='1' then
244 local n
= string.match(f
.xarg
.name
, '~') or f
.xarg
.name
245 if n
~='~' then ret
[n
] = f
end
248 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
249 local base
= classes
[b
]
250 if type(base
)=='table' then
251 local bv
= get_virtuals(base
)
252 for n
, f
in pairs(bv
) do
253 if not ret
[n
] then ret
[n
] = f
end
257 for _
, f
in ipairs(c
) do
258 if f
.label
=='Function'
259 and f
.xarg
.access
~='private'
260 and (ret
[string.match(f
.xarg
.name
, '~') or f
.xarg
.name
]) then
262 local n
= string.match(f
.xarg
.name
, '~')or f
.xarg
.name
268 for c
in pairs(index
) do
269 c
.virtuals
= get_virtuals(c
)
270 for _
, f
in pairs(c
.virtuals
) do
271 if f
.xarg
.abstract
=='1' then c
.abstract
=true break end
277 local distinguish_methods
= function(index
)
278 for c
in pairs(index
) do
279 local construct
, destruct
, normal
= {}, nil, {}
280 local n
= c
.xarg
.name
282 for _
, f
in ipairs(c
) do
283 if n
==f
.xarg
.name
then
284 table.insert(construct
, f
)
285 elseif f
.xarg
.name
:match
'~' then
288 if (not string.match(f
.xarg
.name
, '^operator%W'))
289 and (not f
.xarg
.member_template_parameters
) then
290 table.insert(normal
, f
)
294 c
.constructors
= construct
295 c
.destructor
= destruct
301 local fill_public_destr
= function(index
)
303 for c
in pairs(index
) do
304 classes
[c
.xarg
.fullname
] = c
306 local destr_is_public
307 destr_is_public
= function(c
)
309 return c
.destructor
.xarg
.access
=='public'
311 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
312 local base
= classes
[b
]
313 if base
and not destr_is_public(base
) then
320 for c
in pairs(index
) do
321 c
.public_destr
= destr_is_public(c
)
326 local fill_copy_constructor
= function(index
)
328 for c
in pairs(index
) do
329 classes
[c
.xarg
.name
] = c
331 for c
in pairs(index
) do
333 for _
, f
in ipairs(c
.constructors
) do
335 and f
.arguments
[1].xarg
.type_name
==c
.xarg
.fullname
..' const&' then
340 c
.copy_constructor
= copy
342 local copy_constr_is_public
343 copy_constr_is_public
= function(c
)
344 if c
.copy_constructor
then
345 return (c
.copy_constructor
.xarg
.access
=='public')
346 or (c
.copy_constructor
.xarg
.access
=='protected')
349 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
350 local base
= classes
[b
]
351 if base
and not copy_constr_is_public(base
) then
358 for c
in pairs(index
) do
359 c
.public_constr
= copy_constr_is_public(c
)
364 local fill_typesystem_with_enums
= function(enums
, types
)
366 for e
in pairs(enums
) do
367 if not types
[e
.xarg
.fullname
] then
369 types
[e
.xarg
.fullname
] = {
371 return 'lqtL_pushenum(L, '..n
..', "'..e
.xarg
.fullname
..'")', 1
374 return 'static_cast<'..e
.xarg
.fullname
..'>'
375 ..'(lqtL_toenum(L, '..n
..', "'..e
.xarg
.fullname
..'"))', 1
378 return 'lqtL_isenum(L, '..n
..', "'..e
.xarg
.fullname
..'")', 1
382 --io.stderr:write(e.xarg.fullname, ': already present\n')
388 local fill_typesystem_with_classes
= function(classes
, types
)
390 for c
in pairs(classes
) do
391 if not types
[c
.xarg
.fullname
] then
393 types
[c
.xarg
.fullname
..'*'] = {
394 -- the argument is a pointer to class
396 return 'lqtL_passudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
399 return 'static_cast<'..c
.xarg
.fullname
..'*>'
400 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
403 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
406 types
[c
.xarg
.fullname
..' const*'] = {
407 -- the argument is a pointer to constant class instance
409 return 'lqtL_passudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
412 return 'static_cast<'..c
.xarg
.fullname
..'*>'
413 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
416 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
419 types
[c
.xarg
.fullname
..'&'] = {
420 -- the argument is a reference to class
422 return 'lqtL_passudata(L, &'..n
..', "'..c
.xarg
.fullname
..'*")', 1
425 return '*static_cast<'..c
.xarg
.fullname
..'*>'
426 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
429 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
432 if c
.public_constr
and c
.shell
then
433 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
434 types
[c
.xarg
.fullname
] = {
435 -- the argument is the class itself
437 return 'lqtL_passudata(L, new '..shellname
438 ..'(L, '..n
..'), "'..c
.xarg
.fullname
..'*")', 1
441 return '*static_cast<'..c
.xarg
.fullname
..'*>'
442 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
445 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
448 types
[c
.xarg
.fullname
..' const&'] = {
449 -- the argument is a pointer to class
451 return 'lqtL_passudata(L, new '..shellname
452 ..'(L, '..n
..'), "'..c
.xarg
.fullname
..'*")', 1
455 return '*static_cast<'..c
.xarg
.fullname
..'*>'
456 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
459 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
468 local fill_wrapper_code
= function(f
, types
)
469 if f
.wrapper_code
then return f
end
470 local stackn
, argn
= 1, 1
471 local wrap
, line
= '', ''
472 if f
.xarg
.member_of_class
and f
.xarg
.static
~='1' then
473 if not types
[f
.xarg
.member_of_class
..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
474 local sget
, sn
= types
[f
.xarg
.member_of_class
..'*'].get(stackn
)
475 wrap
= wrap
.. ' ' .. f
.xarg
.member_of_class
.. '* self = ' .. sget
.. ';\n'
479 lua_pushstring(L, "this pointer is NULL");
484 line
= 'self->'..f
.xarg
.fullname
..'('
486 line
= f
.xarg
.fullname
..'('
488 for i
, a
in ipairs(f
.arguments
) do
489 if not types
[a
.xarg
.type_name
] then return nil end
490 local aget
, an
= types
[a
.xarg
.type_name
].get(stackn
)
491 wrap
= wrap
.. ' ' .. a
.xarg
.type_name
.. ' arg' .. tostring(argn
) .. ' = '
492 if a
.xarg
.default
=='1' and an
>0 then
493 wrap
= wrap
.. 'lua_isnoneornil(L, '..stackn
..')'
494 for j
= stackn
+1,stackn
+an
-1 do
495 wrap
= wrap
.. ' && lua_isnoneornil(L, '..j
..')'
497 local dv
= a
.xarg
.defaultvalue
498 wrap
= wrap
.. ' ? static_cast< ' .. a
.xarg
.type_name
.. ' >(' .. dv
.. ') : '
500 wrap
= wrap
.. aget
.. ';\n'
501 line
= line
.. (argn
==1 and 'arg' or ', arg') .. argn
506 -- FIXME: hack follows for constructors
507 if f
.calling_line
then line
= f
.calling_line
end
508 if f
.return_type
then line
= f
.return_type
.. ' ret = ' .. line
end
509 wrap
= wrap
.. ' ' .. line
.. ';\n lua_settop(L, 0);\n' -- lua_pop(L, '..stackn..');\n'
510 if f
.return_type
then
511 if not types
[f
.return_type
] then return nil end
512 local rput
, rn
= types
[f
.return_type
].push
'ret'
513 wrap
= wrap
.. ' luaL_checkstack(L, '..rn
..', "cannot grow stack for return value");\n'
514 wrap
= wrap
.. ' '..rput
..';\n return '..rn
..';\n'
516 wrap
= wrap
.. ' return 0;\n'
518 f
.wrapper_code
= wrap
522 local fill_test_code
= function(f
, types
)
525 if f
.xarg
.member_of_class
and f
.xarg
.static
~='1' then
526 if not types
[f
.xarg
.member_of_class
..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
527 local stest
, sn
= types
[f
.xarg
.member_of_class
..'*'].test(stackn
)
528 test
= test
.. ' && ' .. stest
531 for i
, a
in ipairs(f
.arguments
) do
532 if not types
[a
.xarg
.type_name
] then return nil end -- print(a.xarg.type_name) return nil end
533 local atest
, an
= types
[a
.xarg
.type_name
].test(stackn
)
534 if a
.xarg
.default
=='1' and an
>0 then
535 test
= test
.. ' && (lqtL_missarg(L, ' .. stackn
.. ', ' .. an
.. ') || '
536 test
= test
.. atest
.. ')'
538 test
= test
.. ' && ' .. atest
542 -- can't make use of default values if I fix number of args
543 test
= '(lua_gettop(L)<' .. stackn
.. ')' .. test
548 local fill_wrappers
= function(functions
, types
)
550 for f
in pairs(functions
) do
551 f
= fill_wrapper_code(f
, types
)
553 f
= assert(fill_test_code(f
, types
), f
.xarg
.fullname
) -- MUST pass
555 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
..' (lua_State *L) {\n'
556 .. f
.wrapper_code
.. '}\n'
563 local argument_name
= function(tn
, an
)
565 if string.match(tn
, '%(%*%)') then
566 ret
= string.gsub(tn
, '%(%*%)', '(*'..an
..')', 1)
567 elseif string.match(tn
, '%[.*%]') then
568 ret
= string.gsub(tn
, '(%[.*%])', an
..'%1')
570 ret
= tn
.. ' ' .. an
575 local virtual_overload
= function(v
, types
)
577 if v
.virtual_overload
then return v
end
579 if v
.return_type
and not types
[v
.return_type
] then return nil end
580 local rget
, rn
= '', 0
581 if v
.return_type
then rget
, rn
= types
[v
.return_type
].get
'oldtop+1' end
582 local retget
= (v
.return_type
and argument_name(v
.return_type
, 'ret')
583 .. ' = ' .. rget
.. ';' or '') .. 'lua_settop(L, oldtop);return'
584 .. (v
.return_type
and ' ret' or '')
585 -- make argument push
586 local pushlines
, stack
= '', 0
587 for i
, a
in ipairs(v
.arguments
) do
588 if not types
[a
.xarg
.type_name
] then return nil end
589 local apush
, an
= types
[a
.xarg
.type_name
].push('arg'..i
)
590 pushlines
= pushlines
.. ' ' .. apush
.. ';\n'
594 local luacall
= 'lua_pcall(L, '..stack
..', '..rn
..', 0)'
595 -- make prototype and fallback
596 local proto
= (v
.return_type
or 'void')..' ;;'..v
.xarg
.name
..' ('
598 for i
, a
in ipairs(v
.arguments
) do
599 proto
= proto
.. (i
>1 and ', ' or '')
600 .. argument_name(a
.xarg
.type_name
, 'arg'..i
)
601 fallback
= fallback
.. (i
>1 and ', arg' or 'arg') .. i
603 proto
= proto
.. ')' .. (v
.xarg
.constant
=='1' and ' const' or '')
604 fallback
= (v
.return_type
and 'return this->' or 'this->')
605 .. v
.xarg
.fullname
.. '(' .. fallback
.. ');\n}\n'
607 int oldtop = lua_gettop(L);
608 lqtL_pushudata(L, this, "]]..v
.xarg
.member_of_class
..[[*");
609 lua_getfield(L, -1, "]]..v
.xarg
.name
..[[");
610 if (lua_isfunction(L, -1)) {
612 ]] .. pushlines
.. [[
613 if (]]..luacall
..[[) {
617 lua_settop(L, oldtop);
619 v
.virtual_overload
= ret
620 v
.virtual_proto
= string.gsub(proto
, ';;', '', 1)
624 local fill_shell_class
= function(c
, types
)
625 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
626 local shell
= 'class ' .. shellname
.. ' : public ' .. c
.xarg
.fullname
.. ' {\npublic:\n'
627 shell
= shell
.. ' lua_State *L;\n'
628 for _
, constr
in ipairs(c
.constructors
) do
629 if constr
.xarg
.access
~='private' then
630 local cline
= ' '..shellname
..' (lua_State *l'
632 for i
, a
in ipairs(constr
.arguments
) do
633 cline
= cline
.. ', ' .. argument_name(a
.xarg
.type_name
, 'arg'..i
)
634 argline
= argline
.. (i
>1 and ', arg' or 'arg') .. i
636 cline
= cline
.. ') : ' .. c
.xarg
.fullname
637 .. '(' .. argline
.. '), L(l) '
638 .. '{ lqtL_register(L, this); }\n'
639 shell
= shell
.. cline
642 if c
.copy_constructor
==nil and c
.public_constr
then
643 local cline
= ' '..shellname
..' (lua_State *l, '..c
.xarg
.fullname
..' const& arg1)'
644 cline
= cline
.. ' : ' .. c
.xarg
.fullname
.. '(arg1), L(l) {}\n'
645 shell
= shell
.. cline
647 for i
, v
in pairs(c
.virtuals
) do
648 if v
.xarg
.access
~='private' then
649 local vret
= virtual_overload(v
, types
)
650 if v
.virtual_proto
then shell
= shell
.. ' virtual ' .. v
.virtual_proto
.. ';\n' end
653 shell
= shell
.. ' ~'..shellname
..'() { lqtL_unregister(L, this); }\n'
654 shell
= shell
.. '};\n'
655 c
.shell_class
= shell
659 local fill_shell_classes
= function(classes
, types
)
661 for c
in pairs(classes
) do
663 c
= fill_shell_class(c
, types
)
664 if c
then ret
[c
] = true else error(c
.xarg
.fullname
) end
670 local print_shell_classes
= function(classes
)
671 for c
in pairs(classes
) do
676 --io.stderr:write(c.fullname, '\n')
683 local print_virtual_overloads
= function(classes
)
684 for c
in pairs(classes
) do
685 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
686 for _
,v
in pairs(c
.virtuals
) do
687 if v
.virtual_overload
then
688 cpp((string.gsub(v
.virtual_overload
, ';;', shellname
..'::', 1)))
695 local print_wrappers
= function(index
)
696 for c
in pairs(index
) do
698 for _
, f
in ipairs(c
.methods
) do
699 if f
.wrapper_code
then
700 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
701 ..' (lua_State *L) {\n'.. f
.wrapper_code
.. '}\n'
702 if f
.xarg
.access
=='public' then
704 meta
[f
] = f
.xarg
.name
709 for _
, f
in ipairs(c
.constructors
) do
710 if f
.wrapper_code
then
711 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
712 ..' (lua_State *L) {\n'.. f
.wrapper_code
.. '}\n'
713 if f
.xarg
.access
=='public' then
719 --local shellname = 'lqt_shell_'..string.gsub(c.xarg.fullname, '::', '_LQT_')
720 local out
= 'extern "C" int lqt_delete'..c
.xarg
.id
..' (lua_State *L) {\n'
721 out
= out
..' '..c
.xarg
.fullname
..' *p = static_cast<'
722 ..c
.xarg
.fullname
..'*>(lqtL_toudata(L, 1, "'..c
.xarg
.fullname
..'*"));\n'
723 out
= out
.. ' if (p) delete p;\n return 0;\n}\n'
731 local print_metatable
= function(c
)
733 for m
, n
in pairs(c
.meta
) do
734 methods
[n
] = methods
[n
] or {}
735 table.insert(methods
[n
], m
)
737 for n
, l
in pairs(methods
) do
738 local disp
= 'extern "C" int lqt_dispatcher_'..n
..c
.xarg
.id
..' (lua_State *L) {\n'
739 for _
, f
in ipairs(l
) do
740 disp
= disp
..' if ('..f
.test_code
..') return lqt_bind'..f
.xarg
.id
..'(L);\n'
742 disp
= disp
.. ' lua_settop(L, 0);\n'
743 disp
= disp
.. ' lua_pushstring(L, "incorrect or extra arguments");\n'
744 disp
= disp
.. ' return lua_error(L);\n}\n'
747 local metatable
= 'static luaL_Reg lqt_metatable'..c
.xarg
.id
..'[] = {\n'
748 for n
, l
in pairs(methods
) do
749 metatable
= metatable
.. ' { "'..n
..'", lqt_dispatcher_'..n
..c
.xarg
.id
..' },\n'
752 metatable
= metatable
.. ' { "delete", lqt_delete'..c
.xarg
.id
..' },\n'
754 metatable
= metatable
.. ' { 0, 0 },\n};\n'
757 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]*);') do
758 bases
= bases
.. '{"' .. b
.. '*"}, '
760 bases
= 'static lqt_Base lqt_base'..c
.xarg
.id
..'[] = { '..bases
..'{NULL} };\n'
765 local print_metatables
= function(classes
)
766 for c
in pairs(classes
) do
772 local print_class_list
= function(classes
)
773 local list
= 'static lqt_Class lqt_class_list[] = {\n'
774 for c
in pairs(classes
) do
775 class
= '{ lqt_metatable'..c
.xarg
.id
..', lqt_base'..c
.xarg
.id
..', "'..c
.xarg
.fullname
..'*" },\n'
776 list
= list
.. ' ' .. class
778 list
= list
.. ' { 0, 0, 0 },\n};\n'
783 local fix_methods_wrappers
= function(classes
)
784 for c
in pairs(classes
) do
785 -- if class seems abstract but has a shell class
787 -- is it really abstract?
789 for _
, f
in pairs(c
.virtuals
) do
790 -- if it is abstract but we cannot overload
791 -- FIXME: this always fails: f.virtual_overload is not filled yet
792 -- maybe this check must be moved later:
793 -- we don't use shell class to move instances to Lua
794 -- but we want to instantiate if we can wrap all virtuals...
795 if f
.xarg
.abstract
=='1' and not f
.virtual_overload
then a
= true break end
799 c
.shell
= (not c
.abstract
) and c
.public_destr
800 for _
, constr
in ipairs(c
.constructors
) do
801 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
802 constr
.calling_line
= '*new '..shellname
..'(L'
803 for i
=1,#(constr
.arguments
) do
804 constr
.calling_line
= constr
.calling_line
.. ', arg' .. i
806 constr
.calling_line
= constr
.calling_line
.. ')'
812 local print_enum_tables
= function(enums
)
813 for e
in pairs(enums
) do
814 local table = 'static lqt_Enum lqt_enum'..e
.xarg
.id
..'[] = {\n'
815 --io.stderr:write(e.xarg.fullname, '\t', #e.values, '\n')
816 for _
,v
in pairs(e
.values
) do
817 table = table .. ' { "' .. v
.xarg
.name
818 .. '", static_cast<int>('..v
.xarg
.fullname
..') },\n'
820 table = table .. ' { 0, 0 }\n'
821 table = table .. '};\n'
827 local print_enum_creator
= function(enums
)
828 local out
= 'static lqt_Enumlist lqt_enum_list[] = {\n'
829 for e
in pairs(enums
) do
830 out
= out
..' { lqt_enum'..e
.xarg
.id
..', "'..e
.xarg
.fullname
..'" },\n'
832 out
= out
..' { 0, 0 },\n};\n'
833 out
= out
.. 'extern "C" int lqt_create_enums (lua_State *L) {\n'
834 out
= out
.. ' lqtL_createenumlist(L, lqt_enum_list); return 0;\n}\n'
839 local print_openmodule
= function(n
)
842 extern "C" int luaopen_]]..n
..[[ (lua_State *L) {
844 lqtL_createclasses(L, lqt_class_list);
850 --------------------------------------------------------------------------------------
852 local typesystem
= {}
855 for i
, ft
in ipairs(typefiles
) do
856 ts
= loadfile(ft
)(ts
)
858 setmetatable(typesystem
, {
859 __newindex
= function(t
, k
, v
)
860 --debug('added type', k)
863 __index
= function(t
, k
)
865 --if not ret then debug("unknown type:", tostring(k), ret) end
871 fix_arguments(idindex
) -- fixes default arguments if they are context-relative
872 local functions
= copy_functions(idindex
) -- picks functions and fixes label
873 local functions
= fix_functions(functions
) -- fixes name and fullname and fills arguments
875 local enums
= copy_enums(idindex
) -- picks enums if public
876 local enums
= fill_enums(enums
) -- fills field "values"
878 local classes
= copy_classes(idindex
) -- picks classes if not private and not blacklisted
879 local classes
= fill_virtuals(classes
) -- does that, destructor ("~") excluded
880 local classes
= distinguish_methods(classes
) -- does that
881 local classes
= fill_public_destr(classes
) -- does that: checks if destructor is public
882 local classes
= fill_copy_constructor(classes
) -- does that: checks if copy contructor is public or protected
883 local classes
= fix_methods_wrappers(classes
)
885 local enums
= fill_typesystem_with_enums(enums
, typesystem
) -- does that
886 local classes
= fill_typesystem_with_classes(classes
, typesystem
)
888 local functions
= fill_wrappers(functions
, typesystem
)
889 local classes
= fill_shell_classes(classes
, typesystem
) -- does that, also only selects those with a shell class
891 ------------- BEGIN OUTPUT
894 hpp('#ifndef LQT_BIND_'..module_name
)
895 hpp('#define LQT_BIND_'..module_name
)
898 for _
, i
in ipairs(output_includes
) do
903 cpp('#include "'..tostring(hppname
)..'"')
907 local classes
= print_shell_classes(classes
) -- does that
908 local classes
= print_virtual_overloads(classes
, typesystem
) -- does that
909 local classes
= print_wrappers(classes
) -- does that + FIXME: checks if has shell for constr/destr and compiles metatable list
910 local enums
= print_enum_tables(enums
) -- does that
911 local enums
= print_enum_creator(enums
) -- does that + print enum list
912 local classes
= print_metatables(classes
) -- does that + print dispatchers
913 local classes
= print_class_list(classes
) -- does that
915 print_openmodule(module_name
) -- does that
917 hpp('#endif // LQT_BIND_'..module_name
)