Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/unity_build/src/external/tolua/lua/package.lua @ 8688

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

Removed the need to declare the tolua interface explicitly (DeclareToluaInterface).
This is now automatically done in the ToluaBindLibrary.cc files.
That also removes the need for tolua bind header files.

  • Property svn:eol-style set to native
File size: 11.6 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    post_include_hook(self.name)
139
140    output('\n')
141    output('#ifdef ORXONOX_RELEASE\n')
142    output('#  define TOLUA_RELEASE\n')
143    output('#endif\n')
144
145    if self:requirecollection(_collect) then
146        output('\n')
147        output('/* function to release collected object via destructor */')
148        output('#ifdef __cplusplus\n')
149        for i,v in pairs(_collect) do
150            output('\nstatic int '..v..' (lua_State* tolua_S)')
151            output('{')
152            output(' '..i..'* self = ('..i..'*) tolua_tousertype(tolua_S,1,0);')
153            output('    delete self;')
154            output('    return 0;')
155            output('}')
156        end
157        output('#endif\n\n')
158    end
159
160    output('\n')
161    output('/* function to register type */')
162    output('static void tolua_reg_types (lua_State* tolua_S)')
163    output('{')
164    foreach(_usertype,function(n,v) output(' tolua_usertype(tolua_S,"',v,'");') end)
165    if flags.t then
166        output("#ifndef Mtolua_typeid\n#define Mtolua_typeid(L,TI,T)\n#endif\n")
167        foreach(_usertype,function(n,v) output(' Mtolua_typeid(tolua_S,typeid(',v,'), "',v,'");') end)
168    end
169    output('}')
170    output('\n')
171end
172
173-- register package
174-- write package open function
175function classPackage:register (pre)
176    pre = pre or ''
177    push(self)
178    output(pre.."/* Open function */")
179    output(pre.."int tolua_"..self.name.."_open (lua_State* tolua_S)")
180    output(pre.."{")
181    output(pre.." tolua_open(tolua_S);")
182    output(pre.." tolua_reg_types(tolua_S);")
183    output(pre.." tolua_module(tolua_S,NULL,",self:hasvar(),");")
184    output(pre.." tolua_beginmodule(tolua_S,NULL);")
185    local i=1
186    while self[i] do
187        self[i]:register(pre.."  ")
188        i = i+1
189    end
190    output(pre.." tolua_endmodule(tolua_S);")
191    output(pre.." return 1;")
192    output(pre.."}")
193
194    output("\n\n")
195    output("#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501\n");
196    output(pre.."int luaopen_"..self.name.." (lua_State* tolua_S) {")
197    output(pre.." return tolua_"..self.name.."_open(tolua_S);")
198    output(pre.."};")
199    output("#endif\n\n")
200
201    pop()
202end
203
204-- write header file
205function classPackage:header ()
206    output('/*\n') output('** Lua binding: '..self.name..'\n')
207    output('** Generated automatically by '..TOLUA_VERSION..' on '..date()..'.\n')
208    output('*/\n\n')
209
210    if flags.H then
211        output('#include "'..flags.w..'/'..self.name..'Prereqs.h"\n')
212        output('/* Exported function */')
213        output('_'..self.name..'Export')
214        output('int  tolua_'..self.name..'_open (lua_State* tolua_S);')
215        output('\n')
216    end
217end
218
219-- Internal constructor
220function _Package (self)
221    setmetatable(self,classPackage)
222    return self
223end
224
225-- Parse C header file with tolua directives
226-- *** Thanks to Ariel Manzur for fixing bugs in nested directives ***
227function extract_code(fn,s)
228    local code = '\n$#include "'..flags.w..'/'..fn..'"\n'
229    s= "\n" .. s .. "\n" -- add blank lines as sentinels
230
231    -- eliminate export macro problems in class declarations
232    s = gsub(s, ' _%w*Export ', ' ')
233
234    local _,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n")
235    while e do
236        t = strlower(t)
237        if t == "begin" then
238            _,e,c = strfind(s,"(.-)\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[Ee][Nn][Dd][^\n]*\n",e)
239            if not e then
240             tolua_error("Unbalanced 'tolua_begin' directive in header file")
241            end
242        end
243        code = code .. c .. "\n"
244        _,e,c,t = strfind(s, "\n([^\n]-)[Tt][Oo][Ll][Uu][Aa]_([^%s]*)[^\n]*\n",e)
245    end
246    return code
247end
248
249-- Constructor
250-- Expects the package name, the file extension, and the file text.
251function Package (name,fn)
252    local ext = "pkg"
253
254    -- open input file, if any
255    if fn then
256        local file
257        if flags.f then
258            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
259                file = flags.f
260            else
261                file = flags.w..'/'..flags.f
262            end
263        else
264            file = flags.f
265        end
266        local st, msg = readfrom(file)
267        if not st then
268            error('#'..msg..' path: '..flags.f)
269        end
270        local _; _, _, ext = strfind(fn,".*%.(.*)$")
271    end
272    local code = "\n" .. read('*a')
273    if ext == 'h' or ext == 'hpp' then
274        code = extract_code(fn,code)
275    end
276
277    -- close file
278    if fn then
279        readfrom()
280    end
281
282    -- prepare working directory
283    local current_path
284    if not flags.w and flags.f then
285        current_path = gsub(flags.f, '(/)[^/]*%.?[^/]*$', '%1')
286    elseif flags.w then
287        if not (string.sub(flags.w, string.len(flags.w)) == '/') then
288            current_path = flags.w..'/'
289        else
290            current_path = flags.w
291        end
292    else
293        current_path = ''
294    end
295
296    -- deal with include directive
297    local nsubst
298    repeat
299        code,nsubst = gsub(code,'\n%s*%$(.)file%s*"(.-)"([^\n]*)\n',
300            function (kind,fn,extra)
301                local _, _, ext = strfind(fn,".*%.(.*)$")
302                local fp,msg = openfile(current_path..fn,'r')
303                if not fp then
304                    error('#'..msg..': '..fn)
305                end
306                local s = read(fp,'*a')
307                closefile(fp)
308                if kind == 'c' or kind == 'h' then
309                    return extract_code(fn,s)
310                elseif kind == 'p' then
311                    return "\n\n" .. s
312                elseif kind == 'l' then
313                    return "\n$[--##"..fn.."\n" .. s .. "\n$]\n"
314                elseif kind == 'i' then
315                    local t = {code=s}
316                    extra = string.gsub(extra, "^%s*,%s*", "")
317                    local pars = split_c_tokens(extra, ",")
318                    include_file_hook(t, fn, unpack(pars))
319                    return "\n\n" .. t.code
320                else
321                    error('#Invalid include directive (use $cfile, $pfile, $lfile or $ifile)')
322                end
323            end
324        )
325    until nsubst==0
326
327    -- deal with renaming directive
328    repeat -- I don't know why this is necesary
329        code,nsubst = gsub(code,'\n%s*%$renaming%s*(.-)%s*\n', function (r) appendrenaming(r) return "\n" end)
330    until nsubst == 0
331
332    local t = _Package(_Container{name=name, code=code})
333    push(t)
334    preprocess_hook(t)
335    t:preprocess()
336    preparse_hook(t)
337    t:parse(t.code)
338    pop()
339    return t
340end
341
342
Note: See TracBrowser for help on using the repository browser.