Make typesystem global variable
[lqt/mk.git] / generator / generator.lua
blob76488193adf3d4fb97550a1526a9b657da04945c
1 #!/usr/bin/lua
3 --[[
5 Copyright (c) 2007-2009 Mauro Iazzi
6 Copyright (c) 2008 Peter K�mmel
7 Copyright (c) 2010 Michal Kottman
9 Permission is hereby granted, free of charge, to any person
10 obtaining a copy of this software and associated documentation
11 files (the "Software"), to deal in the Software without
12 restriction, including without limitation the rights to use,
13 copy, modify, merge, publish, distribute, sublicense, and/or sell
14 copies of the Software, and to permit persons to whom the
15 Software is furnished to do so, subject to the following
16 conditions:
18 The above copyright notice and this permission notice shall be
19 included in all copies or substantial portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
23 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
25 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 OTHER DEALINGS IN THE SOFTWARE.
30 --]]
32 local osseparator = package.config:sub(1,1)
34 local path = string.match(arg[0], '(.*'..osseparator..')[^%'..osseparator..']+') or ''
35 if path == "" then
36 --- remove script name
37 path = string.sub(arg[0], 1, #arg[0] - #'generator.lua')
38 end
40 local filename = nil
41 local dirname = nil
42 module_name = nil
43 template_file = path .. 'qtemplates.lua'
44 local typefiles = {}
45 local filterfiles = {}
46 output_includes = {
47 'lqt_common.hpp',
51 local i = 1
52 while select(i, ...) do
53 local argi = select(i, ...)
54 if argi=='-n' then
55 i = i + 1
56 module_name = select(i, ...)
57 elseif argi=='-i' then
58 i = i + 1
59 table.insert(output_includes, (select(i, ...)))
60 elseif argi=='-t' then
61 i = i + 1
62 table.insert(typefiles, (select(i, ...)))
63 elseif argi=='-f' then
64 i = i + 1
65 table.insert(filterfiles, (select(i, ...)))
66 elseif argi=='-c' then
67 i = i + 1
68 template_file = select(i, ...)
69 else
70 filename = filename and error'duplicate filename' or argi
71 end
72 i = i + 1
73 end
74 end
76 local my_includes = ''
77 for _, i in ipairs(output_includes) do
78 if string.match(i, '^<.+>$') then
79 my_includes = my_includes .. '#include '..i..'\n'
80 elseif string.match(i, '^".+"$') then
81 my_includes = my_includes .. '#include '..i..'\n'
82 else
83 my_includes = my_includes .. '#include "'..i..'"\n'
84 end
85 end
86 output_includes = my_includes .. '\n'
88 local readfile = function(fn)
89 local f = assert(io.open(fn))
90 local s = f:read'*a'
91 f:close()
92 return s
93 end
95 function fprint(f)
96 return function(...)
97 for i = 1, select('#',...) do
98 f:write((i==1) and '' or '\t', tostring(select(i,...)))
99 end
100 f:write'\n'
101 f:flush()
105 _src = '_src'..osseparator
106 local debug = fprint(io.stderr)
108 local warn = true
109 local ignore_file = assert(io.open('ignores_'..module_name..'.csv', 'w'))
110 function ignore(name, cause, context)
111 if warn then
112 ignore_file:write(name..';'..cause..';'..(context or '')..'\n')
116 local xmlstream, idindex = dofile(path..'xml.lua')(readfile(filename))
118 -- Remove duplicate entries (~4300/20000 for QtCore)
119 local dups = {}
120 local remove = {}
121 for e in pairs(idindex) do
122 if e.xarg and e.xarg.id and dups[e.xarg.id] then
123 -- print('Duplicate!', dups[e.xarg.id], e.xarg.name, e.xarg.id)
124 remove[e] = true
126 dups[e.xarg.id] = true
128 for e in pairs(remove) do
129 idindex[e] = nil
132 package.path = path..'?.lua;' .. package.path
134 require('class_types')
136 ----------------------------------------------------------------------------------
138 typesystem = dofile(path..'types.lua')
140 local ts = {}
141 for i, ft in ipairs(typefiles) do
142 ts = assert(loadfile(ft))(ts)
144 setmetatable(typesystem, {
145 __newindex = function(t, k, v)
146 --debug('added type', k)
147 ts[k] = v
148 end,
149 __index = function(t, k)
150 local ret = ts[k]
151 -- if not ret then debug("unknown type:", tostring(k), ret) end
152 return ret
153 end,
158 -- helper function
159 function argument_name(tn, an)
160 local ret
161 if string.match(tn, '%(%*%)') then
162 ret = string.gsub(tn, '%(%*%)', '(*'..an..')', 1)
163 elseif string.match(tn, '%[.*%]') then
164 ret = string.gsub(tn, '%s*(%[.*%])', ' '..an..'%1')
165 else
166 ret = tn .. ' ' .. an
168 return ret
171 local gen_id = 0
172 for e in pairs(idindex) do
173 if e.xarg and e.xarg.id then
174 local id = assert(tonumber(e.xarg.id:match("_(%d+)")))
175 if id > gen_id then gen_id = id + 1 end
177 end
179 function next_id() gen_id = gen_id + 1; return "_" .. gen_id end
182 --- Constructs the code that pushes arguments to the Lua stack.
183 -- Returns the code as a string, and stack increment. In case that an unknown
184 -- type is encountered, nil and the unknown type is returned.
185 function make_pushlines(args)
186 local pushlines, stack = '', 0
187 for i, a in ipairs(args) do
188 if not typesystem[a.xarg.type_name] then return nil, a.xarg.type_name end
189 local apush, an = typesystem[a.xarg.type_name].push('arg'..i)
190 pushlines = pushlines .. ' ' .. apush .. ';\n'
191 stack = stack + an
193 return pushlines, stack
196 require 'enums'
197 require 'classes'
199 fullnames = {}
201 for e in pairs(idindex) do
202 if e.xarg.fullname then fullnames[e.xarg.fullname] = e end
205 enums.preprocess(idindex)
206 classes.preprocess(idindex)
208 enums.process(idindex, typesystem)
209 classes.process(idindex, typesystem, filterfiles)
211 ------------- BEGIN OUTPUT
213 enums.output()
214 classes.output()
216 --print_openmodule(module_name) -- does that