4 Copyright (c) 2007 Mauro Iazzi
6 Permission is hereby granted, free of charge, to any person
7 obtaining a copy of this software and associated documentation
8 files (the "Software"), to deal in the Software without
9 restriction, including without limitation the rights to use,
10 copy, modify, merge, publish, distribute, sublicense, and/or sell
11 copies of the Software, and to permit persons to whom the
12 Software is furnished to do so, subject to the following
15 The above copyright notice and this permission notice shall be
16 included in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 OTHER DEALINGS IN THE SOFTWARE.
34 my_typename
= 'QObject'
42 hpp
= function(fn
) io
.write(hpp_text
) print() end
43 cpp
= function(fn
) io
.write(cpp_text
) print() end
44 wr
= function(fn
) local f
= io
.open('bind.hpp', 'w') f
:write(hpp_text
) f
:write'\n' f
:close() end
46 xmlf
= io
.open(filename
, 'r')
47 xmls
= xmls
or xmlf
:read('*a')
49 xmlt
= xmlt
or lxp
.lom
.parse(xmls
)
53 ------------ FIND -------------
54 find
= function (t
, f
)
55 if type(t
)~='table' then
62 for k
,v
in pairs(t
) do
63 ret
= ret
or find(v
, f
)
69 name_search
= function (n
)
71 return (type(t
)=='table') and (type(t
.attr
)=='table') and (t
.attr
.name
==n
)
75 id_search
= function (i
)
77 return (type(t
)=='table') and (type(t
.attr
)=='table') and (t
.attr
.id
==i
) -- or ((type(i)=='table') and i[t.attr.id])
81 tag_search
= function (n
)
83 return (type(t
)=='table') and (t
.tag==n
) -- or ((type(i)==table) and i[t.attr.id])
87 find_name
= function (n
) return find(xmlt
, name_search(n
)) end
88 find_id
= function (n
) return find(xmlt
, id_search(n
)) end
91 ------------ ---- -------------
94 type_name = function (t, el)
95 if el.tag == 'FundamentalType' then
97 elseif (el.tag == 'Class') or (el.tag == 'Struct') then
99 elseif el.tag == 'Typedef' then
100 return type_name_by_id(t, el.attr.type)
101 elseif el.tag == 'PointerType' then
102 return type_name_by_id(t, el.attr.type) .. ' *'
103 elseif el.tag == 'ReferenceType' then
104 return type_name_by_id(t, el.attr.type) .. '&'
105 elseif el.tag == 'CvQualifiedType' then
106 return ( (el.attr.volatile=='1') and 'volatile ' or '') .. ( (el.attr.const=='1') and 'const ' or '') .. type_name_by_id(t, el.attr.type)
115 setmetatable(type_name
, {
116 __call
= function (t
, el
)
117 print('getting name of', el
, el
.tag)
118 if t
[el
] then return t
[el
] end
119 if el
.tag == 'FundamentalType' then
121 elseif (el
.tag == 'Class') or (el
.tag == 'Struct') then
123 elseif el
.tag == 'Typedef' then
124 t
[el
] = t(find_id(el
.attr
.type))
125 elseif el
.tag == 'PointerType' then
126 t
[el
] = t(find_id(el
.attr
.type)) .. ' *'
127 elseif el
.tag == 'ReferenceType' then
128 t
[el
] = t(find_id(el
.attr
.type)) .. '&'
129 elseif el
.tag == 'CvQualifiedType' then
130 t
[el
] = ( (el
.attr
.volatile
=='1') and 'volatile ' or '') .. ( (el
.attr
.const
=='1') and 'const ' or '') .. t(find_id(el
.attr
.type))
131 elseif el
.tag == 'Enumeration' then
132 t
[el
] = ((find_id(el
.attr
.context
).attr
.name
=='::') and '' or
133 (find_id(el
.attr
.context
).attr
.name
) .. '::') .. el
.attr
.name
136 -- table.foreach(el, print)
137 -- table.foreach(el.attr, print)
138 -- print (el.attr.id)
147 function get_base_pointer_to(n
, i
)
148 return '*static_cast<' .. n
.. '**>(luaL_checkudata(L, ' .. tostring(i
) .. ', "' .. n
.. '*"))'
155 local type_from_stack_mt
= {
156 ['const char *'] = function(i
) return 'lua_tostring(L, ' .. tostring(i
) .. ')' end,
157 ['short int'] = function(i
) return 'lua_tointeger(L, ' .. tostring(i
) .. ')' end,
158 ['unsigned short int'] = function(i
) return 'lua_tointeger(L, ' .. tostring(i
) .. ')' end,
159 ['int'] = function(i
) return 'lua_tointeger(L, ' .. tostring(i
) .. ')' end,
160 ['unsigned int'] = function(i
) return 'lua_tointeger(L, ' .. tostring(i
) .. ')' end,
161 ['long int'] = function(i
) return 'lua_tointeger(L, ' .. tostring(i
) .. ')' end,
162 ['unsigned long int'] = function(i
) return 'lua_tointeger(L, ' .. tostring(i
) .. ')' end,
163 ['long long int'] = function(i
) return 'lua_tointeger(L, ' .. tostring(i
) .. ')' end,
164 ['unsigned long long int'] = function(i
) return 'lua_tointeger(L, ' .. tostring(i
) .. ')' end,
165 ['float'] = function(i
) return 'lua_tonumber(L, ' .. tostring(i
) .. ')' end,
166 ['double'] = function(i
) return 'lua_tonumber(L, ' .. tostring(i
) .. ')' end,
167 ['bool'] = function(i
) return '(bool)lua_toboolean(L, ' .. tostring(i
) .. ')' end,
168 ['void *'] = function(i
) return 'lua_touserdata(L, ' .. tostring(i
) .. ')' end,
169 ['void * *'] = function(i
) return 'static_cast<void **>(lua_touserdata(L, ' .. tostring(i
) .. '))' end,
171 setmetatable(type_from_stack
, type_from_stack_mt
)
172 type_from_stack_mt
.__call
= function (t
, el
, i
)
173 local name
= type_name(el
)
174 -- if t[el] then return t[el] end
175 if type(type_from_stack_mt
[name
])=='function' then
176 t
[el
] = type_from_stack_mt
[name
](i
)
178 if (el
.tag=='Class') or (el
.tag=='Struct') then
179 t
[el
] = '*' .. get_base_pointer_to(name
, i
)
180 elseif (el
.tag=='CvQualifiedType') then
181 t
[el
] = t(find_id(el
.attr
.type), i
)
182 elseif (el
.tag=='ReferenceType') then
183 t
[el
] = t(find_id(el
.attr
.type), i
)
184 elseif (el
.tag=='Enumeration') then
185 t
[el
] = 'static_cast<'..name
..'>(luaL_toenum(L, '..tostring(i
)..', "'..name
..'"))'
186 elseif (el
.tag=='PointerType') then
187 t
[el
] = 'static_cast<'..type_name(el
).. '>(&(' .. t(find_id(el
.attr
.type), i
) .. '))'
190 print (el
.tag, el
, rawget(t
,el
) or '<>')
191 return rawget(t
,el
) or '<>'
195 type_on_stack_test
= {}
197 local type_on_stack_test_mt
= {
198 ['const char *'] = function(i
) return '(lua_type(L, ' .. tostring(i
) .. ')==LUA_TSTRING)' end,
199 ['short int'] = function(i
) return 'lua_isinteger(L, ' .. tostring(i
) .. ')' end,
200 ['unsigned short int'] = function(i
) return 'lua_isnumber(L, ' .. tostring(i
) .. ')' end,
201 ['int'] = function(i
) return 'lua_tointeger(L, ' .. tostring(i
) .. ')' end,
202 ['unsigned int'] = function(i
) return 'lua_isnumber(L, ' .. tostring(i
) .. ')' end,
203 ['long int'] = function(i
) return 'lua_isnumber(L, ' .. tostring(i
) .. ')' end,
204 ['unsigned long int'] = function(i
) return 'lua_isnumber(L, ' .. tostring(i
) .. ')' end,
205 ['long long int'] = function(i
) return 'lua_isnumber(L, ' .. tostring(i
) .. ')' end,
206 ['unsigned long long int'] = function(i
) return 'lua_isnumber(L, ' .. tostring(i
) .. ')' end,
207 ['float'] = function(i
) return 'lua_isnumber(L, ' .. tostring(i
) .. ')' end,
208 ['double'] = function(i
) return 'lua_isnumber(L, ' .. tostring(i
) .. ')' end,
209 ['bool'] = function(i
) return 'lua_isboolean(L, ' .. tostring(i
) .. ')' end,
210 ['void *'] = function(i
) return 'lua_isuserdata(L, ' .. tostring(i
) .. ')' end,
211 ['void * *'] = function(i
) return 'lua_isuserdata(L, ' .. tostring(i
) .. ')' end,
214 -- more precise integer test
215 -- function(i) return '(lua_isnumber(L, ' .. tostring(i) .. ') && (lua_tointeger(L, ' .. tostring(i) .. ') == lua_tonumber(L, ' .. tostring(i) .. ')))' end,
217 setmetatable(type_on_stack_test
, type_on_stack_test_mt
)
218 type_on_stack_test_mt
.__call
= function (t
, el
, i
)
219 print ('TESTING ARGUMENT', i
)
220 local name
= type_name(el
)
221 -- if t[el] then return t[el] end
222 if type(type_on_stack_test_mt
[name
])=='function' then
223 t
[el
] = type_on_stack_test_mt
[name
](i
)
225 if (el
.tag=='Class') then
226 t
[el
] = 'luaL_testudata(L, ' .. tostring(i
) .. ', "' .. name
.. '*")'
227 elseif (el
.tag=='CvQualifiedType') then
228 t
[el
] = t(find_id(el
.attr
.type), i
)
229 elseif (el
.tag=='ReferenceType') then
230 t
[el
] = t(find_id(el
.attr
.type), i
)
231 elseif (el
.tag=='PointerType') then
232 t
[el
] = t(find_id(el
.attr
.type), i
)
233 elseif (el
.tag=='Enumeration') then
234 t
[el
] = 'luaL_isenum(L, '..tostring(i
)..', "'..name
..'")'
237 print (el
.tag, el
, rawget(t
,el
) or '<>')
238 return rawget(t
,el
) or '<>'
243 cpairs
= function (t
, c
)
244 return function (table, key
, val
)
245 key
, val
= next(table, key
, val
)
246 while not c(val
) and key
~=nil do key
, val
= next(table, key
, val
) end
253 ------------------ MAIN PROGRAM ----------------------
255 my_class
= find_name(my_typename
)
257 if not my_members
then
259 for s
in string.gmatch(my_class
.attr
.members
, '(_%d+) ') do
260 print("member found:", s
)
261 table.insert(my_members
, find(xmlt
, id_search(s
)))
266 for i
, m
in pairs(my_members
) do
267 if m
.attr
.access
=='public' then
268 table.insert( public_members
, m
)
273 getarg
= function (a
, n
, i
, def
)
275 local a_t
= a
.attr
.id
276 local argtype
= type_name(a
)
277 print ('getting arg type', argtype
, a_t
)
278 ret
= ret
.. ' ' .. argtype
.. ' ' .. n
.. ' = '
279 .. (def
and (type_on_stack_test(a
, i
) .. '?') or '') .. type_from_stack(a
, i
)
280 ret
= ret
.. (def
and (':' .. tostring(def
)) or '') .. '; // '..tostring(def
)..'\n'
284 function pointer_search(id
)
286 return (type(t
)=='table') and (t
.tag=='PointerType') and (type(t
.attr
)=='table') and (t
.attr
.type==id
)
290 function function_body(p
, n
)
294 ret
= ret
.. 'static int ' .. n
.. '(lua_State *L) {\n'
297 if p
.attr
.static
~='1' then
298 -- ret = ret .. ' ' .. my_typename .. ' *__lua__obj = *static_cast<' .. my_typename
299 -- .. '**>(luaL_checkudata(L, 1, "'.. my_typename .. '**"));\n'
300 ret
= ret
.. getarg( find(xmlt
, pointer_search(my_class
.attr
.id
)) or error'FUCK!', '__lua__obj', 1)
306 for argi
= 1, table.maxn(p
) do
307 if (type(p
[argi
])=='table') and (p
[argi
].tag=='Argument') then
308 table.insert(args
, p
[argi
])
312 for argi
= 1, table.maxn(args
) do
313 local arg
= args
[argi
]
314 local argname
= 'arg' .. tostring(argi
)
315 if (type(arg
)=='table') and (arg
.tag=='Argument') then
316 local def
= arg
.attr
.default
or nil
317 local argt
= find_id(arg
.attr
.type)
318 if def
and find_id(arg
.attr
.type).tag=='Enumeration' then
319 local cont
= find_id(argt
.attr
.context
).attr
.name
320 def
= ((cont
=='::') and '' or (cont
.. '::')) .. def
322 ret
= ret
.. getarg(argt
, argname
, argi
+isstatic
, def
)
326 if p
.attr
.static
~='1' then
327 ret
= ret
.. ' __lua__obj->' .. p
.attr
.name
.. '('
328 if table.maxn(args
) > 0 then ret
= ret
.. 'arg1' end
329 for argi
= 2, table.maxn(args
) do
330 ret
= ret
.. ', arg' .. tostring(argi
)
334 ret
= ret
.. p
.attr
.name
.. '('
335 if table.maxn(args
) > 0 then ret
= ret
.. 'arg1' end
336 for argi
= 2, table.maxn(args
) do
337 ret
= ret
.. ', arg' .. tostring(argi
)
342 ret
= ret
.. ' return 1;\n'
349 function function_test(p
, score
)
353 ret
= ret
.. ' ' .. score
.. ' = 0;\n'
355 if p
.attr
.static
~='1' then
356 ret
= ret
.. ' ' .. score
.. ' += ' .. type_on_stack_test( find(xmlt
, pointer_search(my_class
.attr
.id
)), 1 )
357 .. '?premium:-premium*premium;\n'
362 for argi
= 1, table.maxn(p
) do
363 if (type(p
[argi
])=='table') and (p
[argi
].tag=='Argument') then
364 table.insert(args
, p
[argi
])
368 for argi
= 1, table.maxn(args
) do
369 local arg
= args
[argi
]
370 print ( 'ARGUMENT TEST', argi
)
371 local argname
= 'arg' .. tostring(argi
)
372 if (type(arg
)=='table') and (arg
.tag=='Argument') then
373 ret
= ret
.. ' if (' .. type_on_stack_test( find_id(arg
.attr
.type) , argi
+isstatic
) .. ') {\n'
374 ret
= ret
.. ' ' .. score
.. ' += premium;\n'
375 ret
= ret
.. ' } else if (' .. tostring(arg
.attr
.default
and true or false) .. ') {\n'
376 ret
= ret
.. ' ' .. score
.. ' += premium-1; // '..tostring(arg
, arg
.attr
.default
)..';\n'
377 ret
= ret
.. ' } else {\n'
378 ret
= ret
.. ' ' .. score
.. ' -= premium*premium;\n'
381 -- ret = ret .. ' ' .. score .. ' += ' .. type_on_stack_test( find_id(arg.attr.type) , argi+isstatic )
382 -- .. '?' .. tostring(premium) .. ':-' .. tostring(premium) .. '*' .. tostring(premium) .. ';\n'
386 -- print ('|||||||||||||||||||', ret)
395 hpp_text
= hpp_text
.. [[
397 static int luaL_toenum(lua_State *L, int index, const char *name) {
399 lua_getfield(L, LUA_REGISTRYINDEX, "Enumerations");
401 if (!lua_istable(L, -1)) { lua_pop(L, 1); return -1; }
403 lua_pushstring(L, name);
407 if (!lua_istable(L, -1)) { lua_pop(L, 1); return -1; }
409 lua_pushvalue(L, index);
413 ret = lua_tointeger(L, -1);
420 static bool luaL_isenum(lua_State *L, int index, const char *name) {
422 lua_getfield(L, LUA_REGISTRYINDEX, "Enumerations");
424 if (!lua_istable(L, -1)) { lua_pop(L, 1); return false; }
426 lua_pushstring(L, name);
430 if (!lua_istable(L, -1)) { lua_pop(L, 1); return false; }
432 lua_pushvalue(L, index);
436 ret = (bool)lua_isnumber(L, -1);
443 static bool luaL_testudata(lua_State *L, int index, const char *name) {
445 lua_getmetatable(L, index);
446 lua_getfield(L, LUA_REGISTRYINDEX, name);
447 ret = (bool)lua_equal(L, -1, -2);
454 hpp_text
= hpp_text
.. 'class LuaWrap' .. my_typename
.. ': public ' .. my_typename
.. ' {\n'
456 hpp_text
= hpp_text
.. 'public:\n'
458 overloaded_public
= {}
459 for i
, p
in pairs(public_members
) do
460 print('=========EXAMINING MEMBER==========', i
)
461 if p
.tag=='Method' then
462 if overloaded_public
[p
.attr
.name
]==nil then
463 overloaded_public
[p
.attr
.name
] = { p
}
465 table.insert(overloaded_public
[p
.attr
.name
], p
)
471 for n
, l
in pairs(overloaded_public
) do
472 print('=========MAKING METHOD==========', n
)
473 if table.maxn(l
) == 1 then
475 hpp_text
= hpp_text
.. function_body(l
[1], 'LuaCallWrap__'..n
)
477 local dispatcher
= 'static int '..'LuaWrapCall__'..n
..'(lua_State *L) {\n'
478 dispatcher
= dispatcher
.. ' int scores['..tostring(table.maxn(l
))..'];\n'
479 dispatcher
= dispatcher
.. ' const int premium = 11+lua_gettop(L);\n'
481 for j
= 1, table.maxn(l
) do
482 hpp_text
= hpp_text
.. function_body(l
[j
], 'LuaCallWrap__'..n
..'__LuaOverloadedVersion__'..j
)
483 local test
= function_test(l
[j
], 'scores['..j
..']', table.maxn(l
)+11)
484 dispatcher
= dispatcher
.. test
488 dispatcher
= dispatcher
.. ' int best = 1;\n'
489 dispatcher
= dispatcher
.. ' for (int i=1;i<='.. table.maxn(l
) ..';i++) {\n'
490 dispatcher
= dispatcher
.. ' if (scores[best] < scores[i]) { best = i; }\n'
491 dispatcher
= dispatcher
.. ' }\n'
492 dispatcher
= dispatcher
.. ' switch (best) {\n'
493 for j
= 1, table.maxn(l
) do
494 dispatcher
= dispatcher
.. ' case ' .. tostring(j
) .. ': return ' .. 'LuaCallWrap__'..n
..'__LuaOverloadedVersion__'..j
..'(L); break;\n'
496 dispatcher
= dispatcher
.. ' }\n'
498 dispatcher
= dispatcher
.. '};\n'
500 hpp_text
= hpp_text
.. dispatcher
504 hpp_text
= hpp_text
.. 'private:\n'
506 hpp_text
= hpp_text
.. 'protected:\n'
507 hpp_text
= hpp_text
.. ' lua_State *L;\n'
508 hpp_text
= hpp_text
.. '};'
511 hpp_text = hpp_text .. '\n'
512 hpp_text = hpp_text .. 'class LuaWrap' .. my_typename .. ': public ' .. my_typename .. ' {\n'
513 hpp_text = hpp_text .. 'private:\n' .. hpp_public
514 hpp_text = hpp_text .. 'private:\n' .. hpp_private
515 hpp_text = hpp_text .. 'protected:\n' .. hpp_protected
516 hpp_text = hpp_text .. '};'