Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/kicklib/src/external/tolua/lua/package.lua @ 8043

Last change on this file since 8043 was 7941, checked in by rgrieder, 14 years ago

Kicked CEGUILua from our repository and adjusted the build system accordingly.
The Linux part is still missing though.

  • Property svn:eol-style set to native
File size: 11.4 KB
Line 
1-- tolua: package class
2-- Written by Waldemar Celes
3-- TeCGraf/PUC-Rio
4-- Jul 1998
5-- $Id: $
6
7-- This code is free software; you can redistribute it and/or modify it.
8-- The software provided hereunder is on an "as is" basis, and
9-- the author has no obligation to provide maintenance, support, updates,
10-- enhancements, or modifications.
11
12
13
14-- Package class
15-- Represents the whole package being bound.
16-- The following fields are stored:
17--    {i} = list of objects in the package.
18classPackage = {
19    classtype = 'package'
20}
21classPackage.__index = classPackage
22setmetatable(classPackage,classContainer)
23
24-- Print method
25function classPackage:print ()
26    print("Package: "..self.name)
27    local i=1
28    while self[i] do
29        self[i]:print("","")
30        i = i+1
31    end
32end
33
34function classPackage:preprocess ()
35
36    -- avoid preprocessing embedded Lua code
37    local L = {}
38    self.code = gsub(self.code,"\n%s*%$%[","\1") -- deal with embedded lua code
39    self.code = gsub(self.code,"\n%s*%$%]","\2")
40    self.code = gsub(self.code,"(%b\1\2)", function (c)
41                                               tinsert(L,c)
42                                               return "\n#["..getn(L).."]#"
43                                           end
44    )
45    -- avoid preprocessing embedded C code
46    local C = {}
47    self.code = gsub(self.code,"\n%s*%$%<","\3") -- deal with embedded C code
48    self.code = gsub(self.code,"\n%s*%$%>","\4")
49    self.code = gsub(self.code,"(%b\3\4)", function (c)
50                                               tinsert(C,c)
51                                               return "\n#<"..getn(C)..">#"
52                                           end
53    )
54    -- avoid preprocessing embedded C code
55    self.code = gsub(self.code,"\n%s*%$%{","\5") -- deal with embedded C code
56    self.code = gsub(self.code,"\n%s*%$%}","\6")
57    self.code = gsub(self.code,"(%b\5\6)", function (c)
58                                               tinsert(C,c)
59                                               return "\n#<"..getn(C)..">#"
60                                           end
61    )
62
63    --self.code = gsub(self.code,"\n%s*#[^d][^\n]*\n", "\n\n") -- eliminate preprocessor directives that don't start with 'd'
64    self.code = gsub(self.code,"\n[ \t]*#[ \t]*[^d%<%[]", "\n//") -- eliminate preprocessor directives that don't start with 'd'
65
66    -- avoid preprocessing verbatim lines
67    local V = {}
68    self.code = gsub(self.code,"\n(%s*%$[^%[%]][^\n]*)", function (v)
69                                                             tinsert(V,v)
70                                                             return "\n#"..getn(V).."#"
71                                                         end
72    )
73
74    -- perform global substitution
75
76    self.code = gsub(self.code,"(//[^\n]*)","")     -- eliminate C++ comments
77    self.code = gsub(self.code,"/%*","\1")
78    self.code = gsub(self.code,"%*/","\2")
79    self.code = gsub(self.code,"%b\1\2","")
80    self.code = gsub(self.code,"\1","/%*")
81    self.code = gsub(self.code,"\2","%*/")
82    self.code = gsub(self.code,"%s*@%s*","@") -- eliminate spaces beside @
83    self.code = gsub(self.code,"%s?inline(%s)","%1") -- eliminate 'inline' keyword
84    --self.code = gsub(self.code,"%s?extern(%s)","%1") -- eliminate 'extern' keyword
85    --self.code = gsub(self.code,"%s?virtual(%s)","%1") -- eliminate 'virtual' keyword
86    --self.code = gsub(self.code,"public:","") -- eliminate 'public:' keyword
87    self.code = gsub(self.code,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*'
88    self.code = gsub(self.code,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*'
89    self.code = gsub(self.code,"([^%w_])char%s*%*","%1_cstring ")  -- substitute 'char*'
90    self.code = gsub(self.code,"([^%w_])lua_State%s*%*","%1_lstate ")  -- substitute 'lua_State*'
91
92    -- restore embedded Lua code
93    self.code = gsub(self.code,"%#%[(%d+)%]%#", function (n)
94                                                    return L[tonumber(n)]
95                                                end
96    )
97    -- restore embedded C code
98    self.code = gsub(self.code,"%#%<(%d+)%>%#", function (n)
99                                                    return C[tonumber(n)]
100                                                end
101    )
102    -- restore verbatim lines
103    self.code = gsub(self.code,"%#(%d+)%#", function (n)
104                                                return V[tonumber(n)]
105                                            end
106    )
107
108    self.code = string.gsub(self.code, "\n%s*%$([^\n]+)", function (l)
109                                                              Verbatim(l.."\n")
110                                                              return "\n"
111                                                          end
112    )
113end
114
115-- translate verbatim
116function classPackage:preamble ()
117    output('/*\n')
118    output('** Lua binding: '..self.name..'\n')
119    output('** Generated automatically by '..TOLUA_VERSION..' on '..date()..'.\n')
120    output('*/\n\n')
121
122    output('#ifndef __cplusplus\n')
123    output('#include <stdlib.h>\n')
124    output('#endif\n')
125    output('#include <string.h>\n\n')
126    output('#include <tolua++.h>\n\n')
127
128    if flags.H then
129        output('#include "'..flags.H..'"\n')
130    end
131
132    local i=1
133    while self[i] do
134        self[i]:preamble()
135        i = i+1
136    end
137
138    if self:requirecollection(_collect) then
139        output('\n')
140        output('/* function to release collected object via destructor */')
141        output('#ifdef __cplusplus\n')
142        for i,v in pairs(_collect) do
143            output('\nstatic int '..v..' (lua_State* tolua_S)')
144            output('{')
145            output(' '..i..'* self = ('..i..'*) tolua_tousertype(tolua_S,1,0);')
146            output('    delete self;')
147            output('    return 0;')
148            output('}')
149        end
150        output('#endif\n\n')
151    end
152
153    output('\n')
154    output('/* function to register type */')
155    output('static void tolua_reg_types (lua_State* tolua_S)')
156    output('{')
157    foreach(_usertype,function(n,v) output(' tolua_usertype(tolua_S,"',v,'");') end)
158    if flags.t then
159        output("#ifndef Mtolua_typeid\n#define Mtolua_typeid(L,TI,T)\n#endif\n")
160        foreach(_usertype,function(n,v) output(' Mtolua_typeid(tolua_S,typeid(',v,'), "',v,'");') end)
161    end
162    output('}')
163    output('\n')
164end
165
166-- register package
167-- write package open function
168function classPackage:register (pre)
169    pre = pre or ''
170    push(self)
171    output(pre.."/* Open function */")
172    output(pre.."int tolua_"..self.name.."_open (lua_State* tolua_S)")
173    output(pre.."{")
174    output(pre.." tolua_open(tolua_S);")
175    output(pre.." tolua_reg_types(tolua_S);")
176    output(pre.." tolua_module(tolua_S,NULL,",self:hasvar(),");")
177    output(pre.." tolua_beginmodule(tolua_S,NULL);")
178    local i=1
179    while self[i] do
180        self[i]:register(pre.."  ")
181        i = i+1
182    end
183    output(pre.." tolua_endmodule(tolua_S);")
184    output(pre.." return 1;")
185    output(pre.."}")
186
187    output("\n\n")
188    output("#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501\n");
189    output(pre.."int luaopen_"..self.name.." (lua_State* tolua_S) {")
190    output(pre.." return tolua_"..self.name.."_open(tolua_S);")
191    output(pre.."};")
192    output("#endif\n\n")
193
194    pop()
195end
196
197-- write header file
198function classPackage:header ()
199    output('/*\n') output('** Lua binding: '..self.name..'\n')
200    output('** Generated automatically by '..TOLUA_VERSION..' on '..date()..'.\n')
201    output('*/\n\n')
202
203    if flags.H then
204        output('#include "'..flags.w..'/'..self.name..'Prereqs.h"\n')
205        output('/* Exported function */')
206        output('_'..self.name..'Export')
207        output('int  tolua_'..self.name..'_open (lua_State* tolua_S);')
208        output('\n')
209    end
210end
211
212-- Internal constructor
213function _Package (self)
214    setmetatable(self,classPackage)
215    return self
216end
217
218-- Parse C header file with tolua directives
219-- *** Thanks to Ariel Manzur for fixing bugs in nested directives ***
220function extract_code(fn,s)
221    local code = '\n$#include "'..flags.w..'/'..fn..'"\n'
222    s= "\n" .. s .. "\n" -- add blank lines as sentinels
223
224    -- eliminate export macro problems in class declarations
225    s = gsub(s, ' _%w*Export ', ' ')
226
227    local _,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n")
228    while e do
229        t = strlower(t)
230        if t == "begin" then
231            _,e,c = strfind(s,"(.-)\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[Ee][Nn][Dd][^\n]*\n",e)
232            if not e then
233             tolua_error("Unbalanced 'tolua_begin' directive in header file")
234            end
235        end
236        code = code .. c .. "\n"
237        _,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n",e)
238    end
239    return code
240end
241
242-- Constructor
243-- Expects the package name, the file extension, and the file text.
244function Package (name,fn)
245    local ext = "pkg"
246
247    -- open input file, if any
248    if fn then
249        local file
250        if flags.f then
251            if string.sub(flags.f, 1, 1) == '/' or string.sub(flags.f, 1, 1) == '\\' or (string.len(flags.f) > 1 and string.sub(flags.f, 2, 2) == ':') then
252                file = flags.f
253            else
254                file = flags.w..'/'..flags.f
255            end
256        else
257            file = flags.f
258        end
259        local st, msg = readfrom(file)
260        if not st then
261            error('#'..msg..' path: '..flags.f)
262        end
263        local _; _, _, ext = strfind(fn,".*%.(.*)$")
264    end
265    local code = "\n" .. read('*a')
266    if ext == 'h' or ext == 'hpp' then
267        code = extract_code(fn,code)
268    end
269
270    -- close file
271    if fn then
272        readfrom()
273    end
274
275    -- prepare working directory
276    local current_path
277    if not flags.w and flags.f then
278        current_path = gsub(flags.f, '(/)[^/]*%.?[^/]*$', '%1')
279    elseif flags.w then
280        if not (string.sub(flags.w, string.len(flags.w)) == '/') then
281            current_path = flags.w..'/'
282        else
283            current_path = flags.w
284        end
285    else
286        current_path = ''
287    end
288
289    -- deal with include directive
290    local nsubst
291    repeat
292        code,nsubst = gsub(code,'\n%s*%$(.)file%s*"(.-)"([^\n]*)\n',
293            function (kind,fn,extra)
294                local _, _, ext = strfind(fn,".*%.(.*)$")
295                local fp,msg = openfile(current_path..fn,'r')
296                if not fp then
297                    error('#'..msg..': '..fn)
298                end
299                local s = read(fp,'*a')
300                closefile(fp)
301                if kind == 'c' or kind == 'h' then
302                    return extract_code(fn,s)
303                elseif kind == 'p' then
304                    return "\n\n" .. s
305                elseif kind == 'l' then
306                    return "\n$[--##"..fn.."\n" .. s .. "\n$]\n"
307                elseif kind == 'i' then
308                    local t = {code=s}
309                    extra = string.gsub(extra, "^%s*,%s*", "")
310                    local pars = split_c_tokens(extra, ",")
311                    include_file_hook(t, fn, unpack(pars))
312                    return "\n\n" .. t.code
313                else
314                    error('#Invalid include directive (use $cfile, $pfile, $lfile or $ifile)')
315                end
316            end
317        )
318    until nsubst==0
319
320    -- deal with renaming directive
321    repeat -- I don't know why this is necesary
322        code,nsubst = gsub(code,'\n%s*%$renaming%s*(.-)%s*\n', function (r) appendrenaming(r) return "\n" end)
323    until nsubst == 0
324
325    local t = _Package(_Container{name=name, code=code})
326    push(t)
327    preprocess_hook(t)
328    t:preprocess()
329    preparse_hook(t)
330    t:parse(t.code)
331    pop()
332    return t
333end
334
335
Note: See TracBrowser for help on using the repository browser.