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 filterfiles
= {}
38 local output_includes
= {
44 while select(i
, ...) do
45 local argi
= select(i
, ...)
48 module_name
= select(i
, ...)
49 elseif argi
=='-d' then
51 dirname
= select(i
, ...)
52 if dirname
~='' and not string.match(dirname
, '/$') then
53 dirname
= dirname
.. '/'
55 elseif argi
=='-i' then
57 table.insert(output_includes
, (select(i
, ...)))
58 elseif argi
=='-t' then
60 table.insert(typefiles
, (select(i
, ...)))
61 elseif argi
=='-f' then
63 table.insert(filterfiles
, (select(i
, ...)))
64 elseif argi
=='-h' then
66 hppname
= select(i
, ...)
67 elseif argi
=='-c' then
69 cppname
= select(i
, ...)
70 elseif argi
=='-o' then
72 local name
= select(i
, ...)
73 cppname
= name
..'.cpp'
74 hppname
= name
..'.hpp'
76 filename
= filename
and error'duplicate filename' or argi
80 dirname
= dirname
or ''
83 local readfile
= function(fn
)
84 local f
= assert(io
.open(fn
))
90 local fprint
= function(f
)
92 for i
= 1, select('#',...) do
93 f
:write((i
==1) and '' or '\t', tostring(select(i
,...)))
100 local debug
= fprint(io
.stderr
)
101 local cpp
, hpp
= nil, nil
103 local cppfile
= assert(io
.open(dirname
.. cppname
, 'w'))
104 cpp
= fprint(cppfile
)
109 local hppfile
= assert(io
.open(dirname
.. hppname
, 'w'))
110 hpp
= fprint(hppfile
)
115 local xmlstream
, idindex
= dofile(path
..'xml.lua')(readfile(filename
))
117 ----------------------------------------------------------------------------------
119 local copy_functions
= function(index
)
121 for e
in pairs(index
) do
122 if e
.label
:match
'^Function' then
131 local fix_arguments
= function(all
)
133 for e
in pairs(all
or {}) do
134 if e
.xarg
.fullname
then fullnames
[e
.xarg
.fullname
] = true end
136 for a
in pairs(all
) do
137 if a
.label
=='Argument'
138 and a
.xarg
.default
=='1'
139 and string.match(a
.xarg
.defaultvalue
, '%D') then
140 local dv
= a
.xarg
.defaultvalue
141 if not fullnames
[dv
] then
142 dv
= a
.xarg
.context
..'::'..dv
144 if fullnames
[dv
] then
145 a
.xarg
.defaultvalue
= dv
148 a
.xarg
.defaultvalue
= nil
155 local fix_functions
= function(index
)
156 for f
in pairs(index
) do
158 for i
, a
in ipairs(f
) do
159 -- avoid bogus 'void' arguments
160 if a
.xarg
.type_name
=='void' and i
==1 and f
[2]==nil then break end
161 if a
.label
=='Argument' then
162 table.insert(args
, a
)
166 f
.return_type
= f
.xarg
.type_name
167 if f
.xarg
.type_name
=='void' then
174 local copy_enums
= function(index
)
176 for e
in pairs(index
) do
178 and not string.match(e
.xarg
.fullname
, '%b<>')
179 and e
.xarg
.access
=='public' then
186 local fill_enums
= function(index
)
187 for e
in pairs(index
) do
189 for _
, v
in ipairs(e
) do
190 if v
.label
=='Enumerator' then
191 table.insert(values
, v
)
199 local copy_classes
= function(index
)
201 for e
in pairs(index
) do
203 and e
.xarg
.access
~='private'
204 and not (e
.xarg
.fullname
:match
'%b<>'
205 or e
.xarg
.fullname
=='QDebug::Stream'
206 or e
.xarg
.fullname
=='QForeachContainerBase'
207 or e
.xarg
.fullname
=='QByteArray::Data'
208 or e
.xarg
.fullname
=='QVariant::Private::Data'
209 or e
.xarg
.fullname
=='QRegion::QRegionData'
210 or e
.xarg
.fullname
=='QTextStreamManipulator'
211 or e
.xarg
.fullname
=='QString::Data'
212 or e
.xarg
.fullname
=='QThreadStorageData'
220 local fill_virtuals
= function(index
)
222 for c
in pairs(index
) do
223 classes
[c
.xarg
.fullname
] = c
226 get_virtuals
= function(c
)
228 for _
, f
in ipairs(c
) do
229 if f
.label
=='Function' and f
.xarg
.virtual
=='1' then
230 local n
= string.match(f
.xarg
.name
, '~') or f
.xarg
.name
231 if n
~='~' then ret
[n
] = f
end
234 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
235 local base
= classes
[b
]
236 if type(base
)=='table' then
237 local bv
= get_virtuals(base
)
238 for n
, f
in pairs(bv
) do
239 if not ret
[n
] then ret
[n
] = f
end
243 for _
, f
in ipairs(c
) do
244 if f
.label
=='Function'
245 and f
.xarg
.access
~='private'
246 and (ret
[string.match(f
.xarg
.name
, '~') or f
.xarg
.name
]) then
248 local n
= string.match(f
.xarg
.name
, '~')or f
.xarg
.name
254 for c
in pairs(index
) do
255 c
.virtuals
= get_virtuals(c
)
256 for _
, f
in pairs(c
.virtuals
) do
257 if f
.xarg
.abstract
=='1' then c
.abstract
=true break end
263 local distinguish_methods
= function(index
)
264 for c
in pairs(index
) do
265 local construct
, destruct
, normal
= {}, nil, {}
266 local n
= c
.xarg
.name
268 for _
, f
in ipairs(c
) do
269 if n
==f
.xarg
.name
then
270 table.insert(construct
, f
)
271 elseif f
.xarg
.name
:match
'~' then
274 if (not string.match(f
.xarg
.name
, '^operator%W'))
275 and (not f
.xarg
.member_template_parameters
) then
276 table.insert(normal
, f
)
280 c
.constructors
= construct
281 c
.destructor
= destruct
287 local fill_public_destr
= function(index
)
289 for c
in pairs(index
) do
290 classes
[c
.xarg
.fullname
] = c
292 local destr_is_public
293 destr_is_public
= function(c
)
295 return c
.destructor
.xarg
.access
=='public'
297 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
298 local base
= classes
[b
]
299 if base
and not destr_is_public(base
) then
306 for c
in pairs(index
) do
307 c
.public_destr
= destr_is_public(c
)
312 local fill_copy_constructor
= function(index
)
314 for c
in pairs(index
) do
315 classes
[c
.xarg
.name
] = c
317 for c
in pairs(index
) do
319 for _
, f
in ipairs(c
.constructors
) do
321 and f
.arguments
[1].xarg
.type_name
==c
.xarg
.fullname
..' const&' then
326 c
.copy_constructor
= copy
328 local copy_constr_is_public
329 copy_constr_is_public
= function(c
)
330 if c
.copy_constructor
then
331 return (c
.copy_constructor
.xarg
.access
=='public')
332 or (c
.copy_constructor
.xarg
.access
=='protected')
335 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
336 local base
= classes
[b
]
337 if base
and not copy_constr_is_public(base
) then
344 for c
in pairs(index
) do
345 c
.public_constr
= copy_constr_is_public(c
)
350 local fill_typesystem_with_enums
= function(enums
, types
)
352 for e
in pairs(enums
) do
353 if not types
[e
.xarg
.fullname
] then
355 types
[e
.xarg
.fullname
] = {
357 return 'lqtL_pushenum(L, '..n
..', "'..e
.xarg
.fullname
..'")', 1
360 return 'static_cast<'..e
.xarg
.fullname
..'>'
361 ..'(lqtL_toenum(L, '..n
..', "'..e
.xarg
.fullname
..'"))', 1
364 return 'lqtL_isenum(L, '..n
..', "'..e
.xarg
.fullname
..'")', 1
368 --io.stderr:write(e.xarg.fullname, ': already present\n')
374 local fill_typesystem_with_classes
= function(classes
, types
)
376 for c
in pairs(classes
) do
377 if not types
[c
.xarg
.fullname
] then
379 types
[c
.xarg
.fullname
..'*'] = {
380 -- the argument is a pointer to class
382 return 'lqtL_passudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
385 return 'static_cast<'..c
.xarg
.fullname
..'*>'
386 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
389 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
392 types
[c
.xarg
.fullname
..' const*'] = {
393 -- the argument is a pointer to constant class instance
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
..'&'] = {
406 -- the argument is a reference to class
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 if c
.public_constr
and c
.shell
then
419 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
420 types
[c
.xarg
.fullname
] = {
421 -- the argument is the class itself
423 return 'lqtL_passudata(L, new '..shellname
424 ..'(L, '..n
..'), "'..c
.xarg
.fullname
..'*")', 1
427 return '*static_cast<'..c
.xarg
.fullname
..'*>'
428 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
431 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
434 types
[c
.xarg
.fullname
..' const&'] = {
435 -- the argument is a pointer to class
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
454 local fill_wrapper_code
= function(f
, types
)
455 if f
.wrapper_code
then return f
end
456 local stackn
, argn
= 1, 1
457 local wrap
, line
= '', ''
458 if f
.xarg
.member_of_class
and f
.xarg
.static
~='1' then
459 if not types
[f
.xarg
.member_of_class
..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
460 local sget
, sn
= types
[f
.xarg
.member_of_class
..'*'].get(stackn
)
461 wrap
= wrap
.. ' ' .. f
.xarg
.member_of_class
.. '* self = ' .. sget
.. ';\n'
465 lua_pushstring(L, "this pointer is NULL");
470 line
= 'self->'..f
.xarg
.fullname
..'('
472 line
= f
.xarg
.fullname
..'('
474 for i
, a
in ipairs(f
.arguments
) do
475 if not types
[a
.xarg
.type_name
] then return nil end
476 local aget
, an
= types
[a
.xarg
.type_name
].get(stackn
)
477 wrap
= wrap
.. ' ' .. a
.xarg
.type_name
.. ' arg' .. tostring(argn
) .. ' = '
478 if a
.xarg
.default
=='1' and an
>0 then
479 wrap
= wrap
.. 'lua_isnoneornil(L, '..stackn
..')'
480 for j
= stackn
+1,stackn
+an
-1 do
481 wrap
= wrap
.. ' && lua_isnoneornil(L, '..j
..')'
483 local dv
= a
.xarg
.defaultvalue
484 wrap
= wrap
.. ' ? static_cast< ' .. a
.xarg
.type_name
.. ' >(' .. dv
.. ') : '
486 wrap
= wrap
.. aget
.. ';\n'
487 line
= line
.. (argn
==1 and 'arg' or ', arg') .. argn
492 -- FIXME: hack follows for constructors
493 if f
.calling_line
then line
= f
.calling_line
end
494 if f
.return_type
then line
= f
.return_type
.. ' ret = ' .. line
end
495 wrap
= wrap
.. ' ' .. line
.. ';\n lua_settop(L, 0);\n' -- lua_pop(L, '..stackn..');\n'
496 if f
.return_type
then
497 if not types
[f
.return_type
] then return nil end
498 local rput
, rn
= types
[f
.return_type
].push
'ret'
499 wrap
= wrap
.. ' luaL_checkstack(L, '..rn
..', "cannot grow stack for return value");\n'
500 wrap
= wrap
.. ' '..rput
..';\n return '..rn
..';\n'
502 wrap
= wrap
.. ' return 0;\n'
504 f
.wrapper_code
= wrap
508 local fill_test_code
= function(f
, types
)
511 if f
.xarg
.member_of_class
and f
.xarg
.static
~='1' then
512 if not types
[f
.xarg
.member_of_class
..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
513 local stest
, sn
= types
[f
.xarg
.member_of_class
..'*'].test(stackn
)
514 test
= test
.. ' && ' .. stest
517 for i
, a
in ipairs(f
.arguments
) do
518 if not types
[a
.xarg
.type_name
] then return nil end -- print(a.xarg.type_name) return nil end
519 local atest
, an
= types
[a
.xarg
.type_name
].test(stackn
)
520 if a
.xarg
.default
=='1' and an
>0 then
521 test
= test
.. ' && (lqtL_missarg(L, ' .. stackn
.. ', ' .. an
.. ') || '
522 test
= test
.. atest
.. ')'
524 test
= test
.. ' && ' .. atest
528 -- can't make use of default values if I fix number of args
529 test
= '(lua_gettop(L)<' .. stackn
.. ')' .. test
534 local fill_wrappers
= function(functions
, types
)
536 for f
in pairs(functions
) do
537 f
= fill_wrapper_code(f
, types
)
539 f
= assert(fill_test_code(f
, types
), f
.xarg
.fullname
) -- MUST pass
541 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
..' (lua_State *L) {\n'
542 .. f
.wrapper_code
.. '}\n'
549 local argument_name
= function(tn
, an
)
551 if string.match(tn
, '%(%*%)') then
552 ret
= string.gsub(tn
, '%(%*%)', '(*'..an
..')', 1)
553 elseif string.match(tn
, '%[.*%]') then
554 ret
= string.gsub(tn
, '(%[.*%])', an
..'%1')
556 ret
= tn
.. ' ' .. an
561 local virtual_overload
= function(v
, types
)
563 if v
.virtual_overload
then return v
end
565 if v
.return_type
and not types
[v
.return_type
] then return nil end
566 local rget
, rn
= '', 0
567 if v
.return_type
then rget
, rn
= types
[v
.return_type
].get
'oldtop+1' end
568 local retget
= (v
.return_type
and argument_name(v
.return_type
, 'ret')
569 .. ' = ' .. rget
.. ';' or '') .. 'lua_settop(L, oldtop);return'
570 .. (v
.return_type
and ' ret' or '')
571 -- make argument push
572 local pushlines
, stack
= '', 0
573 for i
, a
in ipairs(v
.arguments
) do
574 if not types
[a
.xarg
.type_name
] then return nil end
575 local apush
, an
= types
[a
.xarg
.type_name
].push('arg'..i
)
576 pushlines
= pushlines
.. ' ' .. apush
.. ';\n'
580 local luacall
= 'lua_pcall(L, '..stack
..', '..rn
..', 0)'
581 -- make prototype and fallback
582 local proto
= (v
.return_type
or 'void')..' ;;'..v
.xarg
.name
..' ('
584 for i
, a
in ipairs(v
.arguments
) do
585 proto
= proto
.. (i
>1 and ', ' or '')
586 .. argument_name(a
.xarg
.type_name
, 'arg'..i
)
587 fallback
= fallback
.. (i
>1 and ', arg' or 'arg') .. i
589 proto
= proto
.. ')' .. (v
.xarg
.constant
=='1' and ' const' or '')
590 fallback
= (v
.return_type
and 'return this->' or 'this->')
591 .. v
.xarg
.fullname
.. '(' .. fallback
.. ');\n}\n'
593 int oldtop = lua_gettop(L);
594 lqtL_pushudata(L, this, "]]..v
.xarg
.member_of_class
..[[*");
595 lua_getfield(L, -1, "]]..v
.xarg
.name
..[[");
596 if (lua_isfunction(L, -1)) {
598 ]] .. pushlines
.. [[
599 if (]]..luacall
..[[) {
603 lua_settop(L, oldtop);
605 v
.virtual_overload
= ret
606 v
.virtual_proto
= string.gsub(proto
, ';;', '', 1)
610 local fill_shell_class
= function(c
, types
)
611 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
612 local shell
= 'class ' .. shellname
.. ' : public ' .. c
.xarg
.fullname
.. ' {\npublic:\n'
613 shell
= shell
.. ' lua_State *L;\n'
614 for _
, constr
in ipairs(c
.constructors
) do
615 if constr
.xarg
.access
~='private' then
616 local cline
= ' '..shellname
..' (lua_State *l'
618 for i
, a
in ipairs(constr
.arguments
) do
619 cline
= cline
.. ', ' .. argument_name(a
.xarg
.type_name
, 'arg'..i
)
620 argline
= argline
.. (i
>1 and ', arg' or 'arg') .. i
622 cline
= cline
.. ') : ' .. c
.xarg
.fullname
623 .. '(' .. argline
.. '), L(l) '
624 .. '{ lqtL_register(L, this); }\n'
625 shell
= shell
.. cline
628 if c
.copy_constructor
==nil and c
.public_constr
then
629 local cline
= ' '..shellname
..' (lua_State *l, '..c
.xarg
.fullname
..' const& arg1)'
630 cline
= cline
.. ' : ' .. c
.xarg
.fullname
.. '(arg1), L(l) {}\n'
631 shell
= shell
.. cline
633 for i
, v
in pairs(c
.virtuals
) do
634 if v
.xarg
.access
~='private' then
635 local vret
= virtual_overload(v
, types
)
636 if v
.virtual_proto
then shell
= shell
.. ' virtual ' .. v
.virtual_proto
.. ';\n' end
639 shell
= shell
.. ' ~'..shellname
..'() { lqtL_unregister(L, this); }\n'
640 shell
= shell
.. '};\n'
641 c
.shell_class
= shell
645 local fill_shell_classes
= function(classes
, types
)
647 for c
in pairs(classes
) do
649 c
= fill_shell_class(c
, types
)
650 if c
then ret
[c
] = true else error(c
.xarg
.fullname
) end
656 local print_shell_classes
= function(classes
)
657 for c
in pairs(classes
) do
662 --io.stderr:write(c.fullname, '\n')
669 local print_virtual_overloads
= function(classes
)
670 for c
in pairs(classes
) do
671 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
672 for _
,v
in pairs(c
.virtuals
) do
673 if v
.virtual_overload
then
674 cpp((string.gsub(v
.virtual_overload
, ';;', shellname
..'::', 1)))
681 local print_wrappers
= function(index
)
682 for c
in pairs(index
) do
684 for _
, f
in ipairs(c
.methods
) do
685 if f
.wrapper_code
then
686 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
687 ..' (lua_State *L) {\n'.. f
.wrapper_code
.. '}\n'
688 if f
.xarg
.access
=='public' then
690 meta
[f
] = f
.xarg
.name
695 for _
, f
in ipairs(c
.constructors
) do
696 if f
.wrapper_code
then
697 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
698 ..' (lua_State *L) {\n'.. f
.wrapper_code
.. '}\n'
699 if f
.xarg
.access
=='public' then
705 --local shellname = 'lqt_shell_'..string.gsub(c.xarg.fullname, '::', '_LQT_')
706 local out
= 'extern "C" int lqt_delete'..c
.xarg
.id
..' (lua_State *L) {\n'
707 out
= out
..' '..c
.xarg
.fullname
..' *p = static_cast<'
708 ..c
.xarg
.fullname
..'*>(lqtL_toudata(L, 1, "'..c
.xarg
.fullname
..'*"));\n'
709 out
= out
.. ' if (p) delete p;\n return 0;\n}\n'
717 local print_metatable
= function(c
)
719 for m
, n
in pairs(c
.meta
) do
720 methods
[n
] = methods
[n
] or {}
721 table.insert(methods
[n
], m
)
723 for n
, l
in pairs(methods
) do
724 local disp
= 'extern "C" int lqt_dispatcher_'..n
..c
.xarg
.id
..' (lua_State *L) {\n'
725 for _
, f
in ipairs(l
) do
726 disp
= disp
..' if ('..f
.test_code
..') return lqt_bind'..f
.xarg
.id
..'(L);\n'
728 disp
= disp
.. ' lua_settop(L, 0);\n'
729 disp
= disp
.. ' lua_pushstring(L, "incorrect or extra arguments");\n'
730 disp
= disp
.. ' return lua_error(L);\n}\n'
733 local metatable
= 'static luaL_Reg lqt_metatable'..c
.xarg
.id
..'[] = {\n'
734 for n
, l
in pairs(methods
) do
735 metatable
= metatable
.. ' { "'..n
..'", lqt_dispatcher_'..n
..c
.xarg
.id
..' },\n'
738 metatable
= metatable
.. ' { "delete", lqt_delete'..c
.xarg
.id
..' },\n'
740 metatable
= metatable
.. ' { 0, 0 },\n};\n'
743 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]*);') do
744 bases
= bases
.. '{"' .. b
.. '*"}, '
746 bases
= 'static lqt_Base lqt_base'..c
.xarg
.id
..'[] = { '..bases
..'{NULL} };\n'
751 local print_metatables
= function(classes
)
752 for c
in pairs(classes
) do
758 local print_class_list
= function(classes
)
759 local list
= 'static lqt_Class lqt_class_list[] = {\n'
760 for c
in pairs(classes
) do
761 class
= '{ lqt_metatable'..c
.xarg
.id
..', lqt_base'..c
.xarg
.id
..', "'..c
.xarg
.fullname
..'*" },\n'
762 list
= list
.. ' ' .. class
764 list
= list
.. ' { 0, 0, 0 },\n};\n'
769 local fix_methods_wrappers
= function(classes
)
770 for c
in pairs(classes
) do
771 -- if class seems abstract but has a shell class
773 -- is it really abstract?
775 for _
, f
in pairs(c
.virtuals
) do
776 -- if it is abstract but we cannot overload
777 -- FIXME: this always fails: f.virtual_overload is not filled yet
778 -- maybe this check must be moved later:
779 -- we don't use shell class to move instances to Lua
780 -- but we want to instantiate if we can wrap all virtuals...
781 if f
.xarg
.abstract
=='1' and not f
.virtual_overload
then a
= true break end
785 c
.shell
= (not c
.abstract
) and c
.public_destr
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
.. ')'
793 constr
.xarg
.static
= '1'
794 constr
.return_type
= constr
.xarg
.type_base
..'&'
797 c
.destructor
.return_type
= nil
803 local print_enum_tables
= function(enums
)
804 for e
in pairs(enums
) do
805 local table = 'static lqt_Enum lqt_enum'..e
.xarg
.id
..'[] = {\n'
806 --io.stderr:write(e.xarg.fullname, '\t', #e.values, '\n')
807 for _
,v
in pairs(e
.values
) do
808 table = table .. ' { "' .. v
.xarg
.name
809 .. '", static_cast<int>('..v
.xarg
.fullname
..') },\n'
811 table = table .. ' { 0, 0 }\n'
812 table = table .. '};\n'
818 local print_enum_creator
= function(enums
)
819 local out
= 'static lqt_Enumlist lqt_enum_list[] = {\n'
820 for e
in pairs(enums
) do
821 out
= out
..' { lqt_enum'..e
.xarg
.id
..', "'..e
.xarg
.fullname
..'" },\n'
823 out
= out
..' { 0, 0 },\n};\n'
824 out
= out
.. 'extern "C" int lqt_create_enums (lua_State *L) {\n'
825 out
= out
.. ' lqtL_createenumlist(L, lqt_enum_list); return 0;\n}\n'
830 local print_openmodule
= function(n
)
833 extern "C" int luaopen_]]..n
..[[ (lua_State *L) {
835 lqtL_createclasses(L, lqt_class_list);
841 --------------------------------------------------------------------------------------
843 local typesystem
= {}
846 for i
, ft
in ipairs(typefiles
) do
847 ts
= loadfile(ft
)(ts
)
849 setmetatable(typesystem
, {
850 __newindex
= function(t
, k
, v
)
851 --debug('added type', k)
854 __index
= function(t
, k
)
856 --if not ret then debug("unknown type:", tostring(k), ret) end
862 fix_arguments(idindex
) -- fixes default arguments if they are context-relative
863 local functions
= copy_functions(idindex
) -- picks functions and fixes label
864 local functions
= fix_functions(functions
) -- fixes name and fullname and fills arguments
866 local enums
= copy_enums(idindex
) -- picks enums if public
867 local enums
= fill_enums(enums
) -- fills field "values"
869 local classes
= copy_classes(idindex
) -- picks classes if not private and not blacklisted
870 local classes
= fill_virtuals(classes
) -- does that, destructor ("~") excluded
871 local classes
= distinguish_methods(classes
) -- does that
872 local classes
= fill_public_destr(classes
) -- does that: checks if destructor is public
873 local classes
= fill_copy_constructor(classes
) -- does that: checks if copy contructor is public or protected
874 local classes
= fix_methods_wrappers(classes
)
876 for _
, f
in ipairs(filterfiles
) do
877 classes
, enums
= loadfile(f
)(classes
, enums
)
880 local enums
= fill_typesystem_with_enums(enums
, typesystem
) -- does that
881 local classes
= fill_typesystem_with_classes(classes
, typesystem
)
883 local functions
= fill_wrappers(functions
, typesystem
)
884 local classes
= fill_shell_classes(classes
, typesystem
) -- does that, also only selects those with a shell class
886 ------------- BEGIN OUTPUT
889 hpp('#ifndef LQT_BIND_'..module_name
)
890 hpp('#define LQT_BIND_'..module_name
)
893 for _
, i
in ipairs(output_includes
) do
898 cpp('#include "'..tostring(hppname
)..'"')
902 local classes
= print_shell_classes(classes
) -- does that
903 local classes
= print_virtual_overloads(classes
, typesystem
) -- does that
904 local classes
= print_wrappers(classes
) -- does that + FIXME: checks if has shell for constr/destr and compiles metatable list
905 local enums
= print_enum_tables(enums
) -- does that
906 local enums
= print_enum_creator(enums
) -- does that + print enum list
907 local classes
= print_metatables(classes
) -- does that + print dispatchers
908 local classes
= print_class_list(classes
) -- does that
910 print_openmodule(module_name
) -- does that
912 hpp('#endif // LQT_BIND_'..module_name
)