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 my_includes
= ''
64 for _
, i
in ipairs(output_includes
) do
65 my_includes
= my_includes
.. '#include '..i
..'\n'
67 output_includes
= my_includes
.. '\n'
69 local readfile
= function(fn
)
70 local f
= assert(io
.open(fn
))
76 local fprint
= function(f
)
78 for i
= 1, select('#',...) do
79 f
:write((i
==1) and '' or '\t', tostring(select(i
,...)))
86 local debug
= fprint(io
.stderr
)
87 local print_enum
= fprint(assert(io
.open(module_name
..'_src/'..module_name
..'_enum.cpp', 'w')))
88 local print_slot_h
= fprint(assert(io
.open(module_name
..'_src/'..module_name
..'_slot.hpp', 'w')))
89 local print_slot_c
= fprint(assert(io
.open(module_name
..'_src/'..module_name
..'_slot.cpp', 'w')))
91 local xmlstream
, idindex
= dofile(path
..'xml.lua')(readfile(filename
))
93 ----------------------------------------------------------------------------------
95 local copy_functions
= function(index
)
97 for e
in pairs(index
) do
98 if e
.label
:match
'^Function' then
107 local fix_arguments
= function(all
)
109 for e
in pairs(all
or {}) do
110 if e
.xarg
.fullname
then fullnames
[e
.xarg
.fullname
] = true end
112 for a
in pairs(all
) do
113 if a
.label
=='Argument'
114 and a
.xarg
.default
=='1'
115 and (not string.match(a
.xarg
.defaultvalue
, '^[-+]?%d+%.?%d*$'))
116 and a
.xarg
.defaultvalue
~='true'
117 and a
.xarg
.defaultvalue
~='false'
118 and (not string.match(a
.xarg
.defaultvalue
, '^0[xX]%d+$')) then
119 local dv
, call = string.match(a
.xarg
.defaultvalue
, '(.-)(%b())')
120 dv
= dv
or a
.xarg
.defaultvalue
122 if not fullnames
[dv
] then
123 dv
= a
.xarg
.context
..'::'..dv
..call
125 if fullnames
[dv
] then
126 a
.xarg
.defaultvalue
= dv
..call
129 a
.xarg
.defaultvalue
= nil
136 local fix_functions
= function(index
)
137 for f
in pairs(index
) do
139 for i
, a
in ipairs(f
) do
140 -- avoid bogus 'void' arguments
141 if a
.xarg
.type_name
=='void' and i
==1 and f
[2]==nil then break end
142 if a
.label
=='Argument' then
143 table.insert(args
, a
)
147 f
.return_type
= f
.xarg
.type_name
148 if f
.xarg
.type_name
=='void' then
155 local copy_enums
= function(index
)
157 for e
in pairs(index
) do
159 and not string.match(e
.xarg
.fullname
, '%b<>')
160 and e
.xarg
.access
=='public' then
167 local fill_enums
= function(index
)
168 for e
in pairs(index
) do
170 for _
, v
in ipairs(e
) do
171 if v
.label
=='Enumerator' then
172 table.insert(values
, v
)
180 local copy_classes
= function(index
)
182 for e
in pairs(index
) do
184 and e
.xarg
.access
~='private'
185 and not e
.xarg
.fullname
:match
'%b<>' then
192 local fill_virtuals
= function(index
)
194 for c
in pairs(index
) do
195 classes
[c
.xarg
.fullname
] = c
198 get_virtuals
= function(c
)
200 for _
, f
in ipairs(c
) do
201 if f
.label
=='Function' and f
.xarg
.virtual
=='1' then
202 local n
= string.match(f
.xarg
.name
, '~') or f
.xarg
.name
203 if n
~='~' then ret
[n
] = f
end
206 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
207 local base
= classes
[b
]
208 if type(base
)=='table' then
209 local bv
= get_virtuals(base
)
210 for n
, f
in pairs(bv
) do
211 if not ret
[n
] then ret
[n
] = f
end
215 for _
, f
in ipairs(c
) do
216 if f
.label
=='Function'
217 and f
.xarg
.access
~='private'
218 and (ret
[string.match(f
.xarg
.name
, '~') or f
.xarg
.name
]) then
220 local n
= string.match(f
.xarg
.name
, '~')or f
.xarg
.name
226 for c
in pairs(index
) do
227 c
.virtuals
= get_virtuals(c
)
228 for _
, f
in pairs(c
.virtuals
) do
229 if f
.xarg
.abstract
=='1' then c
.abstract
=true break end
235 local distinguish_methods
= function(index
)
236 for c
in pairs(index
) do
237 local construct
, destruct
, normal
= {}, nil, {}
238 local n
= c
.xarg
.name
240 for _
, f
in ipairs(c
) do
241 if n
==f
.xarg
.name
then
242 table.insert(construct
, f
)
243 elseif f
.xarg
.name
:match
'~' then
246 if (not string.match(f
.xarg
.name
, '^operator%W'))
247 and (not f
.xarg
.member_template_parameters
) then
248 table.insert(normal
, f
)
252 c
.constructors
= construct
253 c
.destructor
= destruct
259 local fill_public_destr
= function(index
)
261 for c
in pairs(index
) do
262 classes
[c
.xarg
.fullname
] = c
264 local destr_is_public
265 destr_is_public
= function(c
)
267 return c
.destructor
.xarg
.access
=='public'
269 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
270 local base
= classes
[b
]
271 if base
and not destr_is_public(base
) then
278 for c
in pairs(index
) do
279 c
.public_destr
= destr_is_public(c
)
284 local fill_copy_constructor
= function(index
)
286 for c
in pairs(index
) do
287 classes
[c
.xarg
.name
] = c
289 for c
in pairs(index
) do
291 for _
, f
in ipairs(c
.constructors
) do
293 and f
.arguments
[1].xarg
.type_name
==c
.xarg
.fullname
..' const&' then
298 c
.copy_constructor
= copy
300 local copy_constr_is_public
301 copy_constr_is_public
= function(c
)
302 if c
.copy_constructor
then
303 return (c
.copy_constructor
.xarg
.access
=='public')
304 or (c
.copy_constructor
.xarg
.access
=='protected')
307 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]+);') do
308 local base
= classes
[b
]
309 if base
and not copy_constr_is_public(base
) then
316 for c
in pairs(index
) do
317 c
.public_constr
= copy_constr_is_public(c
)
322 local fill_typesystem_with_enums
= function(enums
, types
)
323 local etype
= function(en
)
326 return 'lqtL_pushenum(L, '..n
..', "'..en
..'")', 1
329 return 'static_cast<'..en
..'>'
330 ..'(lqtL_toenum(L, '..n
..', "'..en
..'"))', 1
333 return 'lqtL_isenum(L, '..n
..', "'..en
..'")', 1
338 for e
in pairs(enums
) do
339 if types
[e
.xarg
.fullname
]==nil then
341 types
[e
.xarg
.fullname
] = etype(e
.xarg
.fullname
)
343 --io.stderr:write(e.xarg.fullname, ': already present\n')
349 local fill_typesystem_with_classes
= function(classes
, types
)
350 local pointer_t
= function(fn
)
352 -- the argument is a pointer to class
354 return 'lqtL_passudata(L, '..n
..', "'..fn
..'*")', 1
357 return 'static_cast<'..fn
..'*>'
358 ..'(lqtL_toudata(L, '..n
..', "'..fn
..'*"))', 1
361 return 'lqtL_isudata(L, '..n
..', "'..fn
..'*")', 1
365 local pointer_const_t
= function(fn
)
367 -- the argument is a pointer to constant class instance
369 return 'lqtL_passudata(L, '..n
..', "'..fn
..'*")', 1
372 return 'static_cast<'..fn
..'*>'
373 ..'(lqtL_toudata(L, '..n
..', "'..fn
..'*"))', 1
376 return 'lqtL_isudata(L, '..n
..', "'..fn
..'*")', 1
380 local ref_t
= function(fn
)
382 -- the argument is a reference to class
384 return 'lqtL_passudata(L, &'..n
..', "'..fn
..'*")', 1
387 return '*static_cast<'..fn
..'*>'
388 ..'(lqtL_toudata(L, '..n
..', "'..fn
..'*"))', 1
391 return 'lqtL_isudata(L, '..n
..', "'..fn
..'*")', 1
395 local instance_t
= function(fn
)
397 -- the argument is the class itself
399 return 'lqtL_copyudata(L, &'..n
..', "'..fn
..'*")', 1
402 return '*static_cast<'..fn
..'*>'
403 ..'(lqtL_toudata(L, '..n
..', "'..fn
..'*"))', 1
406 return 'lqtL_isudata(L, '..n
..', "'..fn
..'*")', 1
410 local const_ref_t
= function(fn
)
412 -- the argument is a pointer to class
414 return 'lqtL_copyudata(L, &'..n
..', "'..fn
..'*")', 1, string.gsub(fn
, ' const&$', '')
417 return '*static_cast<'..fn
..'*>'
418 ..'(lqtL_toudata(L, '..n
..', "'..fn
..'*"))', 1
421 return 'lqtL_isudata(L, '..n
..', "'..fn
..'*")', 1
426 for c
in pairs(classes
) do
427 if types
[c
.xarg
.fullname
]==nil then
429 types
[c
.xarg
.fullname
..'*'] = pointer_t(c
.xarg
.fullname
)
430 types
[c
.xarg
.fullname
..' const*'] = pointer_const_t(c
.xarg
.fullname
)
431 types
[c
.xarg
.fullname
..'&'] = ref_t(c
.xarg
.fullname
)
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
] = instance_t(c
.xarg
.fullname
, shellname
)
435 types
[c
.xarg
.fullname
..' const&'] = const_ref_t(c
.xarg
.fullname
, shellname
)
442 local argument_name
= function(tn
, an
)
444 if string.match(tn
, '%(%*%)') then
445 ret
= string.gsub(tn
, '%(%*%)', '(*'..an
..')', 1)
446 elseif string.match(tn
, '%[.*%]') then
447 ret
= string.gsub(tn
, '(%[.*%])', an
..'%1')
449 ret
= tn
.. ' ' .. an
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
= ' int oldtop = lua_gettop(L);\n', ''
458 if f
.xarg
.abstract
then return nil end
459 if f
.xarg
.member_of_class
and f
.xarg
.static
~='1' then
460 if not types
[f
.xarg
.member_of_class
..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
461 local sget
, sn
= types
[f
.xarg
.member_of_class
..'*'].get(stackn
)
462 wrap
= wrap
.. ' ' .. f
.xarg
.member_of_class
.. '* self = ' .. sget
.. ';\n'
466 lua_pushstring(L, "this pointer is NULL");
471 line
= 'self->'..f
.xarg
.fullname
..'('
473 line
= f
.xarg
.fullname
..'('
475 for i
, a
in ipairs(f
.arguments
) do
476 if not types
[a
.xarg
.type_name
] then return nil end
477 local aget
, an
, arg_as
= types
[a
.xarg
.type_name
].get(stackn
)
478 wrap
= wrap
.. ' ' .. argument_name(arg_as
or a
.xarg
.type_name
, 'arg'..argn
) .. ' = '
479 if a
.xarg
.default
=='1' and an
>0 then
480 wrap
= wrap
.. 'lua_isnoneornil(L, '..stackn
..')'
481 for j
= stackn
+1,stackn
+an
-1 do
482 wrap
= wrap
.. ' && lua_isnoneornil(L, '..j
..')'
484 local dv
= a
.xarg
.defaultvalue
485 wrap
= wrap
.. ' ? static_cast< ' .. a
.xarg
.type_name
.. ' >(' .. dv
.. ') : '
487 wrap
= wrap
.. aget
.. ';\n'
488 line
= line
.. (argn
==1 and 'arg' or ', arg') .. argn
493 -- FIXME: hack follows for constructors
494 if f
.calling_line
then line
= f
.calling_line
end
495 if f
.return_type
then line
= f
.return_type
.. ' ret = ' .. line
end
496 wrap
= wrap
.. ' ' .. line
.. ';\n lua_settop(L, oldtop);\n' -- lua_pop(L, '..stackn..');\n'
497 if f
.return_type
then
498 if not types
[f
.return_type
] then return nil end
499 local rput
, rn
= types
[f
.return_type
].push
'ret'
500 wrap
= wrap
.. ' luaL_checkstack(L, '..rn
..', "cannot grow stack for return value");\n'
501 wrap
= wrap
.. ' '..rput
..';\n return '..rn
..';\n'
503 wrap
= wrap
.. ' return 0;\n'
505 f
.wrapper_code
= wrap
509 local fill_test_code
= function(f
, types
)
512 if f
.xarg
.member_of_class
and f
.xarg
.static
~='1' then
513 if not types
[f
.xarg
.member_of_class
..'*'] then return nil end -- print(f.xarg.member_of_class) return nil end
514 local stest
, sn
= types
[f
.xarg
.member_of_class
..'*'].test(stackn
)
515 test
= test
.. ' && ' .. stest
518 for i
, a
in ipairs(f
.arguments
) do
519 if not types
[a
.xarg
.type_name
] then return nil end -- print(a.xarg.type_name) return nil end
520 local atest
, an
= types
[a
.xarg
.type_name
].test(stackn
)
521 if a
.xarg
.default
=='1' and an
>0 then
522 test
= test
.. ' && (lqtL_missarg(L, ' .. stackn
.. ', ' .. an
.. ') || '
523 test
= test
.. atest
.. ')'
525 test
= test
.. ' && ' .. atest
529 -- can't make use of default values if I fix number of args
530 test
= '(lua_gettop(L)<' .. stackn
.. ')' .. test
535 local fill_wrappers
= function(functions
, types
)
537 for f
in pairs(functions
) do
538 f
= fill_wrapper_code(f
, types
)
540 f
= assert(fill_test_code(f
, types
), f
.xarg
.fullname
) -- MUST pass
542 --local out = 'extern "C" int lqt_bind'..f.xarg.id..' (lua_State *L) {\n'
543 --.. f.wrapper_code .. '}\n'
550 local make_pushlines
= function(args
, types
)
551 local pushlines
, stack
= '', 0
552 for i
, a
in ipairs(args
) do
553 if not types
[a
.xarg
.type_name
] then return nil end
554 local apush
, an
= types
[a
.xarg
.type_name
].push('arg'..i
)
555 pushlines
= pushlines
.. ' ' .. apush
.. ';\n'
558 return pushlines
, stack
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
, ret_as
= types
[v
.return_type
].get
'oldtop+1' end
568 local retget
= (v
.return_type
and argument_name(ret_as
or 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
= make_pushlines(v
.arguments
, types
)
573 if not pushlines
then return nil end
575 local luacall
= 'lua_pcall(L, '..(stack
+1)..', '..rn
..', 0)'
576 -- make prototype and fallback
577 local proto
= (v
.return_type
or 'void')..' ;;'..v
.xarg
.name
..' ('
579 for i
, a
in ipairs(v
.arguments
) do
580 proto
= proto
.. (i
>1 and ', ' or '')
581 .. argument_name(a
.xarg
.type_name
, 'arg'..i
)
582 fallback
= fallback
.. (i
>1 and ', arg' or 'arg') .. i
584 proto
= proto
.. ')' .. (v
.xarg
.constant
=='1' and ' const' or '')
585 fallback
= (v
.return_type
and 'return this->' or 'this->')
586 .. v
.xarg
.fullname
.. '(' .. fallback
.. ');\n}\n'
588 int oldtop = lua_gettop(L);
589 lqtL_pushudata(L, this, "]]..v
.xarg
.member_of_class
..[[*");
590 lua_getfield(L, -1, "]]..v
.xarg
.name
..[[");
591 if (lua_isfunction(L, -1)) {
593 ]] .. pushlines
.. [[
594 if (!]]..luacall
..[[) {
598 lua_settop(L, oldtop);
600 v
.virtual_overload
= ret
601 v
.virtual_proto
= string.gsub(proto
, ';;', '', 1)
605 local fill_shell_class
= function(c
, types
)
606 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
607 local shell
= 'class ' .. shellname
.. ' : public ' .. c
.xarg
.fullname
.. ' {\npublic:\n'
608 shell
= shell
.. ' lua_State *L;\n'
609 for _
, constr
in ipairs(c
.constructors
) do
610 if constr
.xarg
.access
~='private' then
611 local cline
= ' '..shellname
..' (lua_State *l'
613 for i
, a
in ipairs(constr
.arguments
) do
614 cline
= cline
.. ', ' .. argument_name(a
.xarg
.type_name
, 'arg'..i
)
615 argline
= argline
.. (i
>1 and ', arg' or 'arg') .. i
617 cline
= cline
.. ') : ' .. c
.xarg
.fullname
618 .. '(' .. argline
.. '), L(l) '
619 .. '{ lqtL_register(L, this); }\n'
620 shell
= shell
.. cline
623 if c
.copy_constructor
==nil and c
.public_constr
then
624 local cline
= ' '..shellname
..' (lua_State *l, '..c
.xarg
.fullname
..' const& arg1)'
625 cline
= cline
.. ' : ' .. c
.xarg
.fullname
.. '(arg1), L(l) {}\n'
626 shell
= shell
.. cline
628 for i
, v
in pairs(c
.virtuals
) do
629 if v
.xarg
.access
~='private' then
630 if v
.virtual_proto
then shell
= shell
.. ' virtual ' .. v
.virtual_proto
.. ';\n' end
633 shell
= shell
.. ' ~'..shellname
..'() { lqtL_unregister(L, this); }\n'
634 shell
= shell
.. '};\n'
635 c
.shell_class
= shell
639 local fill_virtual_overloads
= function(classes
, types
)
640 for c
in pairs(classes
) do
641 for i
, v
in pairs(c
.virtuals
) do
642 if v
.xarg
.access
~='private' then
643 local vret
= virtual_overload(v
, types
)
650 local fill_shell_classes
= function(classes
, types
)
652 for c
in pairs(classes
) do
654 c
= fill_shell_class(c
, types
)
655 if c
then ret
[c
] = true end
662 local print_shell_classes
= function(classes
)
664 for c
in pairs(classes
) do
665 if fhead
then fhead
:close() end
666 local n
= string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
667 fhead
= assert(io
.open(module_name
..'_src/'..module_name
..'_head_'..n
..'.hpp', 'w'))
668 local print_head
= function(...)
672 print_head('#ifndef LQT_HEAD_'..n
)
673 print_head('#define LQT_HEAD_'..n
)
674 print_head(output_includes
)
675 print_head('#include <'..string.match(c
.xarg
.fullname
, '^[^:]+')..'>')
679 print_head(c
.shell_class
)
681 --io.stderr:write(c.fullname, '\n')
684 print_head('#endif // LQT_HEAD_'..n
)
686 if fhead
then fhead
:close() end
690 local print_virtual_overloads
= function(classes
)
691 for c
in pairs(classes
) do
694 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
695 for _
,v
in pairs(c
.virtuals
) do
696 if v
.virtual_overload
then
697 vo
= vo
.. string.gsub(v
.virtual_overload
, ';;', shellname
..'::', 1)
700 c
.virtual_overloads
= vo
706 local print_wrappers
= function(index
)
707 for c
in pairs(index
) do
710 for _
, f
in ipairs(c
.methods
) do
711 if f
.wrapper_code
and f
.xarg
.virtual
~='1' then
712 local out
= 'static int lqt_bind'..f
.xarg
.id
713 ..' (lua_State *L) {\n'.. f
.wrapper_code
.. '}\n'
714 if f
.xarg
.access
=='public' then
716 wrappers
= wrappers
.. out
.. '\n'
717 meta
[f
] = f
.xarg
.name
722 for _
, f
in ipairs(c
.constructors
) do
723 if f
.wrapper_code
then
724 local out
= 'static int lqt_bind'..f
.xarg
.id
725 ..' (lua_State *L) {\n'.. f
.wrapper_code
.. '}\n'
726 if f
.xarg
.access
=='public' then
728 wrappers
= wrappers
.. out
.. '\n'
733 --local shellname = 'lqt_shell_'..string.gsub(c.xarg.fullname, '::', '_LQT_')
734 local out
= 'static int lqt_delete'..c
.xarg
.id
..' (lua_State *L) {\n'
735 out
= out
..' '..c
.xarg
.fullname
..' *p = static_cast<'
736 ..c
.xarg
.fullname
..'*>(lqtL_toudata(L, 1, "'..c
.xarg
.fullname
..'*"));\n'
737 out
= out
.. ' if (p) delete p;\n return 0;\n}\n'
739 wrappers
= wrappers
.. out
.. '\n'
742 c
.wrappers
= wrappers
747 local print_metatable
= function(c
)
749 local wrappers
= c
.wrappers
750 for m
, n
in pairs(c
.meta
) do
751 methods
[n
] = methods
[n
] or {}
752 table.insert(methods
[n
], m
)
754 for n
, l
in pairs(methods
) do
755 local disp
= 'static int lqt_dispatcher_'..n
..c
.xarg
.id
..' (lua_State *L) {\n'
756 for _
, f
in ipairs(l
) do
757 disp
= disp
..' if ('..f
.test_code
..') return lqt_bind'..f
.xarg
.id
..'(L);\n'
759 disp
= disp
.. ' lua_settop(L, 0);\n'
760 disp
= disp
.. ' lua_pushstring(L, "incorrect or extra arguments");\n'
761 disp
= disp
.. ' return lua_error(L);\n}\n'
763 wrappers
= wrappers
.. disp
.. '\n'
765 local metatable
= 'static luaL_Reg lqt_metatable'..c
.xarg
.id
..'[] = {\n'
766 for n
, l
in pairs(methods
) do
767 metatable
= metatable
.. ' { "'..n
..'", lqt_dispatcher_'..n
..c
.xarg
.id
..' },\n'
770 metatable
= metatable
.. ' { "delete", lqt_delete'..c
.xarg
.id
..' },\n'
772 metatable
= metatable
.. ' { 0, 0 },\n};\n'
773 --print_meta(metatable)
774 wrappers
= wrappers
.. metatable
.. '\n'
776 for b
in string.gmatch(c
.xarg
.bases
or '', '([^;]*);') do
777 bases
= bases
.. '{"' .. b
.. '*", (char*)(void*)static_cast<'..b
..'*>(static_cast<'..c
.xarg
.fullname
..'*>(NULL))-(char*)NULL}, '
779 bases
= 'static lqt_Base lqt_base'..c
.xarg
.id
..'[] = { '..bases
..'{NULL, NULL} };\n'
781 wrappers
= wrappers
.. bases
.. '\n'
782 c
.wrappers
= wrappers
786 local print_metatables
= function(classes
)
787 for c
in pairs(classes
) do
793 local print_single_class
= function(c
)
794 local n
= string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
795 local fmeta
= assert(io
.open(module_name
..'_src/'..module_name
..'_meta_'..n
..'.cpp', 'w'))
796 local print_meta
= function(...)
800 print_meta('#include "'..module_name
..'_head_'..n
..'.hpp'..'"\n\n')
801 print_meta(c
.wrappers
)
802 if c
.virtual_overloads
then
803 print_meta(c
.virtual_overloads
)
805 print_meta('extern "C" int luaopen_'..n
..' (lua_State *L) {')
806 print_meta('\tlqtL_createclass(L, "'
807 ..n
..'*", lqt_metatable'
808 ..c
.xarg
.id
..', lqt_base'
810 print_meta
'\treturn 0;'
816 local print_class_list
= function(classes
)
817 local big_picture
= {}
818 for c
in pairs(classes
) do
819 local n
= string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
820 print_single_class(c
)
821 table.insert(big_picture
, 'luaopen_'..n
)
823 if fmeta
then fmeta
:close() end
824 fmeta
= assert(io
.open(module_name
..'_src/'..module_name
..'_meta.cpp', 'w'))
825 local print_meta
= function(...)
829 print_meta('#include "lqt_common.hpp"')
830 for _
, p
in ipairs(big_picture
) do
831 print_meta('extern "C" int '..p
..' (lua_State *);')
833 print_meta('extern "C" int lqt_slot (lua_State *);')
834 print_meta('int lqt_create_enums_'..module_name
..' (lua_State *);')
835 print_meta('extern "C" int luaopen_'..module_name
..' (lua_State *L) {')
836 for _
, p
in ipairs(big_picture
) do
837 print_meta('\t'..p
..'(L);')
839 print_meta('\tlqt_create_enums_'..module_name
..'(L);')
840 print_meta('\tlua_pushcfunction(L, lqt_slot);')
841 print_meta('\tlua_setglobal(L, "newslot");')
842 print_meta('\treturn 0;\n}')
843 if fmeta
then fmeta
:close() end
847 local fix_methods_wrappers
= function(classes
)
848 for c
in pairs(classes
) do
849 c
.shell
= (not c
.abstract
) and c
.public_destr
850 for _
, constr
in ipairs(c
.constructors
) do
851 local shellname
= 'lqt_shell_'..string.gsub(c
.xarg
.fullname
, '::', '_LQT_')
852 constr
.calling_line
= '*new '..shellname
..'(L'
853 for i
=1,#(constr
.arguments
) do
854 constr
.calling_line
= constr
.calling_line
.. ', arg' .. i
856 constr
.calling_line
= constr
.calling_line
.. ')'
857 constr
.xarg
.static
= '1'
858 constr
.return_type
= constr
.xarg
.type_base
..'&'
861 c
.destructor
.return_type
= nil
867 local print_enum_tables
= function(enums
)
868 for e
in pairs(enums
) do
869 local table = 'static lqt_Enum lqt_enum'..e
.xarg
.id
..'[] = {\n'
870 --io.stderr:write(e.xarg.fullname, '\t', #e.values, '\n')
871 for _
,v
in pairs(e
.values
) do
872 table = table .. ' { "' .. v
.xarg
.name
873 .. '", static_cast<int>('..v
.xarg
.fullname
..') },\n'
875 table = table .. ' { 0, 0 }\n'
876 table = table .. '};\n'
882 local print_enum_creator
= function(enums
, n
)
883 local out
= 'static lqt_Enumlist lqt_enum_list[] = {\n'
884 for e
in pairs(enums
) do
885 out
= out
..' { lqt_enum'..e
.xarg
.id
..', "'..e
.xarg
.fullname
..'" },\n'
887 out
= out
..' { 0, 0 },\n};\n'
888 out
= out
.. 'void lqt_create_enums_'..n
..' (lua_State *L) {\n'
889 out
= out
.. ' lqtL_createenumlist(L, lqt_enum_list); return;\n}\n'
894 local copy_signals
= function(functions
)
896 for f
in pairs(functions
) do
897 if f
.xarg
.signal
=='1' then
904 local slots_for_signals
= function(signals
, types
)
906 for sig
in pairs(signals
) do
907 local args
, comma
= '(', ''
908 for i
, a
in ipairs(sig
.arguments
) do
909 args
= args
.. comma
.. a
.xarg
.type_name
.. ' arg'..i
913 local pushlines
, stack
= make_pushlines(sig
.arguments
, types
)
914 if not ret
['void slot '..args
] and pushlines
then
915 ret
['void slot '..args
] = 'void LqtSlotAcceptor::slot '..args
..[[ {
916 int oldtop = lua_gettop(L);
917 lqtL_pushudata(L, this, "QObject*");
918 lua_getfield(L, -1, "slot]]..string.gsub(args
, ' arg.', '')..[[");
919 if (lua_isnil(L, -1)) {
921 lua_getfield(L, -1, "slot");
923 if (!lua_isfunction(L, -1)) {
924 lua_settop(L, oldtop);
928 ]] .. pushlines
.. [[
929 if (lua_pcall(L, ]]..stack
..[[+1, 0, 0)) {
932 lua_settop(L, oldtop);
940 local print_slots
= function(s
)
941 print_slot_h
'class LqtSlotAcceptor : public QObject {'
942 print_slot_h
' Q_OBJECT'
943 print_slot_h
' lua_State *L;'
944 print_slot_h
' public:'
945 print_slot_h
' LqtSlotAcceptor(lua_State *l, QObject *p=NULL) : QObject(p), L(l) { lqtL_register(L, this); }'
946 print_slot_h
' virtual ~LqtSlotAcceptor() { lqtL_unregister(L, this); }'
947 print_slot_h
' public slots:'
948 for p
, b
in pairs(s
) do
949 print_slot_h(' '..p
..';')
952 for p
, b
in pairs(s
) do
957 extern "C" int lqt_slot (lua_State *L) {
958 QObject *parent = static_cast<QObject*>(lqtL_toudata(L, 1, "QObject*"));
959 lqtL_passudata(L, new LqtSlotAcceptor(L, parent), "QObject*");
966 --------------------------------------------------------------------------------------
968 local typesystem
= {}
971 for i
, ft
in ipairs(typefiles
) do
972 ts
= loadfile(ft
)(ts
)
974 setmetatable(typesystem
, {
975 __newindex
= function(t
, k
, v
)
976 --debug('added type', k)
979 __index
= function(t
, k
)
981 --if not ret then debug("unknown type:", tostring(k), ret) end
987 fix_arguments(idindex
) -- fixes default arguments if they are context-relative
988 local functions
= copy_functions(idindex
) -- picks functions and fixes label
989 local functions
= fix_functions(functions
) -- fixes name and fullname and fills arguments
991 local enums
= copy_enums(idindex
) -- picks enums if public
992 local enums
= fill_enums(enums
) -- fills field "values"
994 local classes
= copy_classes(idindex
) -- picks classes if not private and not blacklisted
995 local classes
= fill_virtuals(classes
) -- does that, destructor ("~") excluded
996 local classes
= distinguish_methods(classes
) -- does that
997 local classes
= fill_public_destr(classes
) -- does that: checks if destructor is public
998 local classes
= fill_copy_constructor(classes
) -- does that: checks if copy contructor is public or protected
999 local classes
= fix_methods_wrappers(classes
)
1001 for _
, f
in ipairs(filterfiles
) do
1002 classes
, enums
= loadfile(f
)(classes
, enums
)
1005 local enums
= fill_typesystem_with_enums(enums
, typesystem
) -- does that
1006 local classes
= fill_typesystem_with_classes(classes
, typesystem
)
1008 local functions
= fill_wrappers(functions
, typesystem
)
1009 local classes
= fill_virtual_overloads(classes
, typesystem
) -- does that
1010 local classes
= fill_shell_classes(classes
, typesystem
) -- does that
1012 local signals
= copy_signals(functions
)
1013 local slots
= slots_for_signals(signals
, typesystem
)
1016 ------------- BEGIN OUTPUT
1020 print_enum(output_includes
)
1021 print_slot_h(output_includes
)
1022 print_slot_c('#include "'..module_name
..'_slot.hpp'..'"\n\n')
1025 local classes
= print_shell_classes(classes
) -- does that
1026 local classes
= print_virtual_overloads(classes
, typesystem
) -- does that
1027 local enums
= print_enum_tables(enums
) -- does that
1028 local enums
= print_enum_creator(enums
, module_name
) -- does that + print enum list
1029 local classes
= print_wrappers(classes
) -- just compiles metatable list
1030 local classes
= print_metatables(classes
) -- just collects the wrappers + generates dispatchers
1031 local classes
= print_class_list(classes
) -- does that + prints everything related to class
1033 local slots
= print_slots(slots
)
1035 --print_openmodule(module_name) -- does that