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 ''
33 local module_name
= nil
35 local filterfiles
= {}
36 local output_includes
= {
42 while select(i
, ...) do
43 local argi
= select(i
, ...)
46 module_name
= select(i
, ...)
47 elseif argi
=='-i' then
49 table.insert(output_includes
, (select(i
, ...)))
50 elseif argi
=='-t' then
52 table.insert(typefiles
, (select(i
, ...)))
53 elseif argi
=='-f' then
55 table.insert(filterfiles
, (select(i
, ...)))
57 filename
= filename
and error'duplicate filename' or argi
63 local readfile
= function(fn
)
64 local f
= assert(io
.open(fn
))
70 local fprint
= function(f
)
72 for i
= 1, select('#',...) do
73 f
:write((i
==1) and '' or '\t', tostring(select(i
,...)))
80 local debug
= fprint(io
.stderr
)
81 local print_head
= fprint(assert(io
.open(module_name
..'_src/'..module_name
..'_head.hpp', 'w')))
82 local print_meta
= fprint(assert(io
.open(module_name
..'_src/'..module_name
..'_meta.cpp', 'w')))
83 local print_enum
= fprint(assert(io
.open(module_name
..'_src/'..module_name
..'_enum.cpp', 'w')))
84 local print_virt
= fprint(assert(io
.open(module_name
..'_src/'..module_name
..'_virt.cpp', 'w')))
86 local xmlstream
, idindex
= dofile(path
..'xml.lua')(readfile(filename
))
88 ----------------------------------------------------------------------------------
90 local copy_functions
= function(index
)
92 for e
in pairs(index
) do
93 if e
.label
:match
'^Function' then
102 local fix_arguments
= function(all
)
104 for e
in pairs(all
or {}) do
105 if e
.xarg
.fullname
then fullnames
[e
.xarg
.fullname
] = true end
107 for a
in pairs(all
) do
108 if a
.label
=='Argument'
109 and a
.xarg
.default
=='1'
110 and string.match(a
.xarg
.defaultvalue
, '%D') then
111 local dv
= a
.xarg
.defaultvalue
112 if not fullnames
[dv
] then
113 dv
= a
.xarg
.context
..'::'..dv
115 if fullnames
[dv
] then
116 a
.xarg
.defaultvalue
= dv
119 a
.xarg
.defaultvalue
= nil
126 local fix_functions
= function(index
)
127 for f
in pairs(index
) do
129 for i
, a
in ipairs(f
) do
130 -- avoid bogus 'void' arguments
131 if a
.xarg
.type_name
=='void' and i
==1 and f
[2]==nil then break end
132 if a
.label
=='Argument' then
133 table.insert(args
, a
)
137 f
.return_type
= f
.xarg
.type_name
138 if f
.xarg
.type_name
=='void' then
145 local copy_enums
= function(index
)
147 for e
in pairs(index
) do
149 and not string.match(e
.xarg
.fullname
, '%b<>')
150 and e
.xarg
.access
=='public' then
157 local fill_enums
= function(index
)
158 for e
in pairs(index
) do
160 for _
, v
in ipairs(e
) do
161 if v
.label
=='Enumerator' then
162 table.insert(values
, v
)
170 local copy_classes
= function(index
)
172 for e
in pairs(index
) do
174 and e
.xarg
.access
~='private'
175 and not (e
.xarg
.fullname
:match
'%b<>'
176 or e
.xarg
.fullname
=='QDebug::Stream'
177 or e
.xarg
.fullname
=='QForeachContainerBase'
178 or e
.xarg
.fullname
=='QByteArray::Data'
179 or e
.xarg
.fullname
=='QVariant::Private::Data'
180 or e
.xarg
.fullname
=='QRegion::QRegionData'
181 or e
.xarg
.fullname
=='QTextStreamManipulator'
182 or e
.xarg
.fullname
=='QString::Data'
183 or e
.xarg
.fullname
=='QThreadStorageData'
191 local fill_virtuals
= function(index
)
193 for c
in pairs(index
) do
194 classes
[c
.xarg
.fullname
] = c
197 get_virtuals
= function(c
)
199 for _
, f
in ipairs(c
) do
200 if f
.label
=='Function' and f
.xarg
.virtual
=='1' then
201 local n
= string.match(f
.xarg
.name
, '~') or f
.xarg
.name
202 if n
~='~' then ret
[n
] = f
end
205 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
206 local base
= classes
[b
]
207 if type(base
)=='table' then
208 local bv
= get_virtuals(base
)
209 for n
, f
in pairs(bv
) do
210 if not ret
[n
] then ret
[n
] = f
end
214 for _
, f
in ipairs(c
) do
215 if f
.label
=='Function'
216 and f
.xarg
.access
~='private'
217 and (ret
[string.match(f
.xarg
.name
, '~') or f
.xarg
.name
]) then
219 local n
= string.match(f
.xarg
.name
, '~')or f
.xarg
.name
225 for c
in pairs(index
) do
226 c
.virtuals
= get_virtuals(c
)
227 for _
, f
in pairs(c
.virtuals
) do
228 if f
.xarg
.abstract
=='1' then c
.abstract
=true break end
234 local distinguish_methods
= function(index
)
235 for c
in pairs(index
) do
236 local construct
, destruct
, normal
= {}, nil, {}
237 local n
= c
.xarg
.name
239 for _
, f
in ipairs(c
) do
240 if n
==f
.xarg
.name
then
241 table.insert(construct
, f
)
242 elseif f
.xarg
.name
:match
'~' then
245 if (not string.match(f
.xarg
.name
, '^operator%W'))
246 and (not f
.xarg
.member_template_parameters
) then
247 table.insert(normal
, f
)
251 c
.constructors
= construct
252 c
.destructor
= destruct
258 local fill_public_destr
= function(index
)
260 for c
in pairs(index
) do
261 classes
[c
.xarg
.fullname
] = c
263 local destr_is_public
264 destr_is_public
= function(c
)
266 return c
.destructor
.xarg
.access
=='public'
268 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
269 local base
= classes
[b
]
270 if base
and not destr_is_public(base
) then
277 for c
in pairs(index
) do
278 c
.public_destr
= destr_is_public(c
)
283 local fill_copy_constructor
= function(index
)
285 for c
in pairs(index
) do
286 classes
[c
.xarg
.name
] = c
288 for c
in pairs(index
) do
290 for _
, f
in ipairs(c
.constructors
) do
292 and f
.arguments
[1].xarg
.type_name
==c
.xarg
.fullname
..' const&' then
297 c
.copy_constructor
= copy
299 local copy_constr_is_public
300 copy_constr_is_public
= function(c
)
301 if c
.copy_constructor
then
302 return (c
.copy_constructor
.xarg
.access
=='public')
303 or (c
.copy_constructor
.xarg
.access
=='protected')
306 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
307 local base
= classes
[b
]
308 if base
and not copy_constr_is_public(base
) then
315 for c
in pairs(index
) do
316 c
.public_constr
= copy_constr_is_public(c
)
321 local fill_typesystem_with_enums
= function(enums
, types
)
323 for e
in pairs(enums
) do
324 if not types
[e
.xarg
.fullname
] then
326 types
[e
.xarg
.fullname
] = {
328 return 'lqtL_pushenum(L, '..n
..', "'..e
.xarg
.fullname
..'")', 1
331 return 'static_cast<'..e
.xarg
.fullname
..'>'
332 ..'(lqtL_toenum(L, '..n
..', "'..e
.xarg
.fullname
..'"))', 1
335 return 'lqtL_isenum(L, '..n
..', "'..e
.xarg
.fullname
..'")', 1
339 --io.stderr:write(e.xarg.fullname, ': already present\n')
345 local fill_typesystem_with_classes
= function(classes
, types
)
347 for c
in pairs(classes
) do
348 if not types
[c
.xarg
.fullname
] then
350 types
[c
.xarg
.fullname
..'*'] = {
351 -- the argument is a pointer to class
353 return 'lqtL_passudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
356 return 'static_cast<'..c
.xarg
.fullname
..'*>'
357 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
360 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
363 types
[c
.xarg
.fullname
..' const*'] = {
364 -- the argument is a pointer to constant class instance
366 return 'lqtL_passudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
369 return 'static_cast<'..c
.xarg
.fullname
..'*>'
370 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
373 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
376 types
[c
.xarg
.fullname
..'&'] = {
377 -- the argument is a reference to class
379 return 'lqtL_passudata(L, &'..n
..', "'..c
.xarg
.fullname
..'*")', 1
382 return '*static_cast<'..c
.xarg
.fullname
..'*>'
383 ..'(lqtL_toudata(L, '..n
..', "'..c
.xarg
.fullname
..'*"))', 1
386 return 'lqtL_isudata(L, '..n
..', "'..c
.xarg
.fullname
..'*")', 1
389 if c
.public_constr
and c
.shell
then
390 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
391 types
[c
.xarg
.fullname
] = {
392 -- the argument is the class itself
394 return 'lqtL_passudata(L, new '..shellname
395 ..'(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 class
408 return 'lqtL_passudata(L, new '..shellname
409 ..'(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
425 local argument_name
= function(tn
, an
)
427 if string.match(tn
, '%(%*%)') then
428 ret
= string.gsub(tn
, '%(%*%)', '(*'..an
..')', 1)
429 elseif string.match(tn
, '%[.*%]') then
430 ret
= string.gsub(tn
, '(%[.*%])', an
..'%1')
432 ret
= tn
.. ' ' .. an
437 local fill_wrapper_code
= function(f
, types
)
438 if f
.wrapper_code
then return f
end
439 local stackn
, argn
= 1, 1
440 local wrap
, line
= ' int oldtop = lua_gettop(L);\n', ''
441 if f
.xarg
.abstract
then return nil end
442 if f
.xarg
.member_of_class
and f
.xarg
.static
~='1' then
443 if not types
[f
.xarg
.member_of_class
..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
444 local sget
, sn
= types
[f
.xarg
.member_of_class
..'*'].get(stackn
)
445 wrap
= wrap
.. ' ' .. f
.xarg
.member_of_class
.. '* self = ' .. sget
.. ';\n'
449 lua_pushstring(L, "this pointer is NULL");
454 line
= 'self->'..f
.xarg
.fullname
..'('
456 line
= f
.xarg
.fullname
..'('
458 for i
, a
in ipairs(f
.arguments
) do
459 if not types
[a
.xarg
.type_name
] then return nil end
460 local aget
, an
, arg_as
= types
[a
.xarg
.type_name
].get(stackn
)
461 wrap
= wrap
.. ' ' .. argument_name(arg_as
or a
.xarg
.type_name
, 'arg'..argn
) .. ' = '
462 if a
.xarg
.default
=='1' and an
>0 then
463 wrap
= wrap
.. 'lua_isnoneornil(L, '..stackn
..')'
464 for j
= stackn
+1,stackn
+an
-1 do
465 wrap
= wrap
.. ' && lua_isnoneornil(L, '..j
..')'
467 local dv
= a
.xarg
.defaultvalue
468 wrap
= wrap
.. ' ? static_cast< ' .. a
.xarg
.type_name
.. ' >(' .. dv
.. ') : '
470 wrap
= wrap
.. aget
.. ';\n'
471 line
= line
.. (argn
==1 and 'arg' or ', arg') .. argn
476 -- FIXME: hack follows for constructors
477 if f
.calling_line
then line
= f
.calling_line
end
478 if f
.return_type
then line
= f
.return_type
.. ' ret = ' .. line
end
479 wrap
= wrap
.. ' ' .. line
.. ';\n lua_settop(L, oldtop);\n' -- lua_pop(L, '..stackn..');\n'
480 if f
.return_type
then
481 if not types
[f
.return_type
] then return nil end
482 local rput
, rn
= types
[f
.return_type
].push
'ret'
483 wrap
= wrap
.. ' luaL_checkstack(L, '..rn
..', "cannot grow stack for return value");\n'
484 wrap
= wrap
.. ' '..rput
..';\n return '..rn
..';\n'
486 wrap
= wrap
.. ' return 0;\n'
488 f
.wrapper_code
= wrap
492 local fill_test_code
= function(f
, types
)
495 if f
.xarg
.member_of_class
and f
.xarg
.static
~='1' then
496 if not types
[f
.xarg
.member_of_class
..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
497 local stest
, sn
= types
[f
.xarg
.member_of_class
..'*'].test(stackn
)
498 test
= test
.. ' && ' .. stest
501 for i
, a
in ipairs(f
.arguments
) do
502 if not types
[a
.xarg
.type_name
] then return nil end -- print(a.xarg.type_name) return nil end
503 local atest
, an
= types
[a
.xarg
.type_name
].test(stackn
)
504 if a
.xarg
.default
=='1' and an
>0 then
505 test
= test
.. ' && (lqtL_missarg(L, ' .. stackn
.. ', ' .. an
.. ') || '
506 test
= test
.. atest
.. ')'
508 test
= test
.. ' && ' .. atest
512 -- can't make use of default values if I fix number of args
513 test
= '(lua_gettop(L)<' .. stackn
.. ')' .. test
518 local fill_wrappers
= function(functions
, types
)
520 for f
in pairs(functions
) do
521 f
= fill_wrapper_code(f
, types
)
523 f
= assert(fill_test_code(f
, types
), f
.xarg
.fullname
) -- MUST pass
525 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
..' (lua_State *L) {\n'
526 .. f
.wrapper_code
.. '}\n'
533 local virtual_overload
= function(v
, types
)
535 if v
.virtual_overload
then return v
end
537 if v
.return_type
and not types
[v
.return_type
] then return nil end
538 local rget
, rn
= '', 0
539 if v
.return_type
then rget
, rn
, ret_as
= types
[v
.return_type
].get
'oldtop+1' end
540 local retget
= (v
.return_type
and argument_name(ret_as
or v
.return_type
, 'ret')
541 .. ' = ' .. rget
.. ';' or '') .. 'lua_settop(L, oldtop);return'
542 .. (v
.return_type
and ' ret' or '')
543 -- make argument push
544 local pushlines
, stack
= '', 0
545 for i
, a
in ipairs(v
.arguments
) do
546 if not types
[a
.xarg
.type_name
] then return nil end
547 local apush
, an
= types
[a
.xarg
.type_name
].push('arg'..i
)
548 pushlines
= pushlines
.. ' ' .. apush
.. ';\n'
552 local luacall
= 'lua_pcall(L, '..(stack
+1)..', '..rn
..', 0)'
553 -- make prototype and fallback
554 local proto
= (v
.return_type
or 'void')..' ;;'..v
.xarg
.name
..' ('
556 for i
, a
in ipairs(v
.arguments
) do
557 proto
= proto
.. (i
>1 and ', ' or '')
558 .. argument_name(a
.xarg
.type_name
, 'arg'..i
)
559 fallback
= fallback
.. (i
>1 and ', arg' or 'arg') .. i
561 proto
= proto
.. ')' .. (v
.xarg
.constant
=='1' and ' const' or '')
562 fallback
= (v
.return_type
and 'return this->' or 'this->')
563 .. v
.xarg
.fullname
.. '(' .. fallback
.. ');\n}\n'
565 int oldtop = lua_gettop(L);
566 lqtL_pushudata(L, this, "]]..v
.xarg
.member_of_class
..[[*");
567 lua_getfield(L, -1, "]]..v
.xarg
.name
..[[");
568 if (lua_isfunction(L, -1)) {
570 ]] .. pushlines
.. [[
571 if (!]]..luacall
..[[) {
575 lua_settop(L, oldtop);
577 v
.virtual_overload
= ret
578 v
.virtual_proto
= string.gsub(proto
, ';;', '', 1)
582 local fill_shell_class
= function(c
, types
)
583 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
584 local shell
= 'class ' .. shellname
.. ' : public ' .. c
.xarg
.fullname
.. ' {\npublic:\n'
585 shell
= shell
.. ' lua_State *L;\n'
586 for _
, constr
in ipairs(c
.constructors
) do
587 if constr
.xarg
.access
~='private' then
588 local cline
= ' '..shellname
..' (lua_State *l'
590 for i
, a
in ipairs(constr
.arguments
) do
591 cline
= cline
.. ', ' .. argument_name(a
.xarg
.type_name
, 'arg'..i
)
592 argline
= argline
.. (i
>1 and ', arg' or 'arg') .. i
594 cline
= cline
.. ') : ' .. c
.xarg
.fullname
595 .. '(' .. argline
.. '), L(l) '
596 .. '{ lqtL_register(L, this); }\n'
597 shell
= shell
.. cline
600 if c
.copy_constructor
==nil and c
.public_constr
then
601 local cline
= ' '..shellname
..' (lua_State *l, '..c
.xarg
.fullname
..' const& arg1)'
602 cline
= cline
.. ' : ' .. c
.xarg
.fullname
.. '(arg1), L(l) {}\n'
603 shell
= shell
.. cline
605 for i
, v
in pairs(c
.virtuals
) do
606 if v
.xarg
.access
~='private' then
607 if v
.virtual_proto
then shell
= shell
.. ' virtual ' .. v
.virtual_proto
.. ';\n' end
610 shell
= shell
.. ' ~'..shellname
..'() { lqtL_unregister(L, this); }\n'
611 shell
= shell
.. '};\n'
612 c
.shell_class
= shell
616 local fill_virtual_overloads
= function(classes
, types
)
617 for c
in pairs(classes
) do
618 for i
, v
in pairs(c
.virtuals
) do
619 if v
.xarg
.access
~='private' then
620 local vret
= virtual_overload(v
, types
)
627 local fill_shell_classes
= function(classes
, types
)
629 for c
in pairs(classes
) do
631 c
= fill_shell_class(c
, types
)
632 if c
then ret
[c
] = true end
639 local print_shell_classes
= function(classes
)
640 for c
in pairs(classes
) do
643 print_head(c
.shell_class
)
645 --io.stderr:write(c.fullname, '\n')
652 local print_virtual_overloads
= function(classes
)
653 for c
in pairs(classes
) do
655 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
656 for _
,v
in pairs(c
.virtuals
) do
657 if v
.virtual_overload
then
658 print_virt((string.gsub(v
.virtual_overload
, ';;', shellname
..'::', 1)))
666 local print_wrappers
= function(index
)
667 for c
in pairs(index
) do
669 for _
, f
in ipairs(c
.methods
) do
670 if f
.wrapper_code
then
671 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
672 ..' (lua_State *L) {\n'.. f
.wrapper_code
.. '}\n'
673 if f
.xarg
.access
=='public' then
675 meta
[f
] = f
.xarg
.name
680 for _
, f
in ipairs(c
.constructors
) do
681 if f
.wrapper_code
then
682 local out
= 'extern "C" int lqt_bind'..f
.xarg
.id
683 ..' (lua_State *L) {\n'.. f
.wrapper_code
.. '}\n'
684 if f
.xarg
.access
=='public' then
690 --local shellname = 'lqt_shell_'..string.gsub(c.xarg.fullname, '::', '_LQT_')
691 local out
= 'extern "C" int lqt_delete'..c
.xarg
.id
..' (lua_State *L) {\n'
692 out
= out
..' '..c
.xarg
.fullname
..' *p = static_cast<'
693 ..c
.xarg
.fullname
..'*>(lqtL_toudata(L, 1, "'..c
.xarg
.fullname
..'*"));\n'
694 out
= out
.. ' if (p) delete p;\n return 0;\n}\n'
702 local print_metatable
= function(c
)
704 for m
, n
in pairs(c
.meta
) do
705 methods
[n
] = methods
[n
] or {}
706 table.insert(methods
[n
], m
)
708 for n
, l
in pairs(methods
) do
709 local disp
= 'extern "C" int lqt_dispatcher_'..n
..c
.xarg
.id
..' (lua_State *L) {\n'
710 for _
, f
in ipairs(l
) do
711 disp
= disp
..' if ('..f
.test_code
..') return lqt_bind'..f
.xarg
.id
..'(L);\n'
713 disp
= disp
.. ' lua_settop(L, 0);\n'
714 disp
= disp
.. ' lua_pushstring(L, "incorrect or extra arguments");\n'
715 disp
= disp
.. ' return lua_error(L);\n}\n'
718 local metatable
= 'static luaL_Reg lqt_metatable'..c
.xarg
.id
..'[] = {\n'
719 for n
, l
in pairs(methods
) do
720 metatable
= metatable
.. ' { "'..n
..'", lqt_dispatcher_'..n
..c
.xarg
.id
..' },\n'
723 metatable
= metatable
.. ' { "delete", lqt_delete'..c
.xarg
.id
..' },\n'
725 metatable
= metatable
.. ' { 0, 0 },\n};\n'
726 print_meta(metatable
)
728 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]*);') do
729 bases
= bases
.. '{"' .. b
.. '*"}, '
731 bases
= 'static lqt_Base lqt_base'..c
.xarg
.id
..'[] = { '..bases
..'{NULL} };\n'
736 local print_metatables
= function(classes
)
737 for c
in pairs(classes
) do
743 local print_class_list
= function(classes
)
744 local list
= 'static lqt_Class lqt_class_list[] = {\n'
745 for c
in pairs(classes
) do
746 class
= '{ lqt_metatable'..c
.xarg
.id
..', lqt_base'..c
.xarg
.id
..', "'..c
.xarg
.fullname
..'*" },\n'
747 list
= list
.. ' ' .. class
749 list
= list
.. ' { 0, 0, 0 },\n};\n'
754 local fix_methods_wrappers
= function(classes
)
755 for c
in pairs(classes
) do
756 -- if class seems abstract but has a shell class
758 -- is it really abstract?
760 for _
, f
in pairs(c
.virtuals
) do
761 -- if it is abstract but we cannot overload
762 -- FIXME: this always fails: f.virtual_overload is not filled yet
763 -- maybe this check must be moved later:
764 -- we don't use shell class to move instances to Lua
765 -- but we want to instantiate if we can wrap all virtuals...
766 if f
.xarg
.abstract
=='1' and not f
.virtual_overload
then a
= true break end
770 c
.shell
= (not c
.abstract
) and c
.public_destr
771 for _
, constr
in ipairs(c
.constructors
) do
772 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
773 constr
.calling_line
= '*new '..shellname
..'(L'
774 for i
=1,#(constr
.arguments
) do
775 constr
.calling_line
= constr
.calling_line
.. ', arg' .. i
777 constr
.calling_line
= constr
.calling_line
.. ')'
778 constr
.xarg
.static
= '1'
779 constr
.return_type
= constr
.xarg
.type_base
..'&'
782 c
.destructor
.return_type
= nil
788 local print_enum_tables
= function(enums
)
789 for e
in pairs(enums
) do
790 local table = 'static lqt_Enum lqt_enum'..e
.xarg
.id
..'[] = {\n'
791 --io.stderr:write(e.xarg.fullname, '\t', #e.values, '\n')
792 for _
,v
in pairs(e
.values
) do
793 table = table .. ' { "' .. v
.xarg
.name
794 .. '", static_cast<int>('..v
.xarg
.fullname
..') },\n'
796 table = table .. ' { 0, 0 }\n'
797 table = table .. '};\n'
803 local print_enum_creator
= function(enums
, n
)
804 local out
= 'static lqt_Enumlist lqt_enum_list[] = {\n'
805 for e
in pairs(enums
) do
806 out
= out
..' { lqt_enum'..e
.xarg
.id
..', "'..e
.xarg
.fullname
..'" },\n'
808 out
= out
..' { 0, 0 },\n};\n'
809 out
= out
.. 'void lqt_create_enums_'..n
..' (lua_State *L) {\n'
810 out
= out
.. ' lqtL_createenumlist(L, lqt_enum_list); return;\n}\n'
815 local print_openmodule
= function(n
)
818 void lqt_create_enums_]]..n
..[[(lua_State*);
820 extern "C" int luaopen_]]..n
..[[ (lua_State *L) {
821 lqt_create_enums_]]..n
..[[(L);
822 lqtL_createclasses(L, lqt_class_list);
828 --------------------------------------------------------------------------------------
830 local typesystem
= {}
833 for i
, ft
in ipairs(typefiles
) do
834 ts
= loadfile(ft
)(ts
)
836 setmetatable(typesystem
, {
837 __newindex
= function(t
, k
, v
)
838 --debug('added type', k)
841 __index
= function(t
, k
)
843 --if not ret then debug("unknown type:", tostring(k), ret) end
849 fix_arguments(idindex
) -- fixes default arguments if they are context-relative
850 local functions
= copy_functions(idindex
) -- picks functions and fixes label
851 local functions
= fix_functions(functions
) -- fixes name and fullname and fills arguments
853 local enums
= copy_enums(idindex
) -- picks enums if public
854 local enums
= fill_enums(enums
) -- fills field "values"
856 local classes
= copy_classes(idindex
) -- picks classes if not private and not blacklisted
857 local classes
= fill_virtuals(classes
) -- does that, destructor ("~") excluded
858 local classes
= distinguish_methods(classes
) -- does that
859 local classes
= fill_public_destr(classes
) -- does that: checks if destructor is public
860 local classes
= fill_copy_constructor(classes
) -- does that: checks if copy contructor is public or protected
861 local classes
= fix_methods_wrappers(classes
)
863 for _
, f
in ipairs(filterfiles
) do
864 classes
, enums
= loadfile(f
)(classes
, enums
)
867 local enums
= fill_typesystem_with_enums(enums
, typesystem
) -- does that
868 local classes
= fill_typesystem_with_classes(classes
, typesystem
)
870 local functions
= fill_wrappers(functions
, typesystem
)
871 local classes
= fill_virtual_overloads(classes
, typesystem
) -- does that
872 local classes
= fill_shell_classes(classes
, typesystem
) -- does that
874 ------------- BEGIN OUTPUT
877 print_head('#ifndef LQT_BIND_'..module_name
)
878 print_head('#define LQT_BIND_'..module_name
)
881 for _
, i
in ipairs(output_includes
) do
882 print_head('#include '..i
)
886 print_enum('#include "'..module_name
..'_head.hpp'..'"\n\n')
887 print_meta('#include "'..module_name
..'_head.hpp'..'"\n\n')
888 print_virt('#include "'..module_name
..'_head.hpp'..'"\n\n')
890 local classes
= print_shell_classes(classes
) -- does that
891 local classes
= print_virtual_overloads(classes
, typesystem
) -- does that
892 local classes
= print_wrappers(classes
) -- does that + compiles metatable list
893 local enums
= print_enum_tables(enums
) -- does that
894 local enums
= print_enum_creator(enums
, module_name
) -- does that + print enum list
895 local classes
= print_metatables(classes
) -- does that + print dispatchers
896 local classes
= print_class_list(classes
) -- does that
898 print_openmodule(module_name
) -- does that
900 print_head('#endif // LQT_BIND_'..module_name
)