PageRenderTime 776ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 1ms

/tools/tolua++-1.0.93/src/bin/lua/package.lua

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