-- tolua: package class -- Written by Waldemar Celes -- TeCGraf/PUC-Rio -- Jul 1998 -- $Id: package.lua,v 1.4 2002/01/03 13:45:08 takkaria Exp $ -- This code is free software; you can redistribute it and/or modify it. -- The software provided hereunder is on an "as is" basis, and -- the author has no obligation to provide maintenance, support, updates, -- enhancements, or modifications. -- Package class -- Represents the whole package being bound. -- The following fields are stored: -- {i} = list of objects in the package. classPackage = { _base = classContainer, type = 'package' } settag(classPackage,tolua_tag) -- Print method function classPackage:print () print("Package: "..self.name) local i=1 while self[i] do self[i]:print("","") i = i+1 end end function classPackage:preprocess () self.code = "\n"..self.code -- add a blank sentinel line -- avoid preprocessing verbatim lines local V = {} self.code = gsub(self.code,"\n(%s*%$[^%[%]][^\n]*)",function (v) tinsert(%V,v) return "\n$"..getn(%V).."$" end) -- avoid preprocessing embedded lua code local C = {} self.code = gsub(self.code,"\n%s*%$%[","\1") -- deal with embedded Lua code self.code = gsub(self.code,"\n%s*%$%]","\2") self.code = gsub(self.code,"(%b\1\2)", function (c) tinsert(%C,c) return "\n$["..getn(%C).."]$" end) -- perform global substitution self.code = gsub(self.code,"(//[^\n]*)","") -- eliminate C++ comments self.code = gsub(self.code,"/%*","\1") self.code = gsub(self.code,"%*/","\2") self.code = gsub(self.code,"%b\1\2","") self.code = gsub(self.code,"\1","/%*") self.code = gsub(self.code,"\2","%*/") self.code = gsub(self.code,"%s*@%s*","@") -- eliminate spaces beside @ self.code = gsub(self.code,"%s?inline(%s)","%1") -- eliminate 'inline' keyword self.code = gsub(self.code,"%s?extern(%s)","%1") -- eliminate 'extern' keyword self.code = gsub(self.code,"%s?virtual(%s)","%1") -- eliminate 'virtual' keyword self.code = gsub(self.code,"public:","") -- eliminate 'public:' keyword self.code = gsub(self.code,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*' self.code = gsub(self.code,"([^%w_])void%s*%*","%1_userdata ") -- substitute 'void*' self.code = gsub(self.code,"([^%w_])char%s*%*","%1_cstring ") -- substitute 'char*' -- restore embedded code self.code = gsub(self.code,"%$%[(%d+)%]%$",function (n) return %C[tonumber(n)] end) -- restore verbatim lines self.code = gsub(self.code,"%$(%d+)%$",function (n) return %V[tonumber(n)] end) end -- translate verbatim function classPackage:preamble () output('/*\n') output('** Lua binding: '..self.name..'\n') output('** Generated automatically by '..TOLUA_VERSION..'\n') output('*/\n\n') output('#include "lua/tolua.h"\n\n') if not flags.h then output('/* Exported function */') output('int tolua_'..self.name..'_open (lua_State* tolua_S);') output('void tolua_'..self.name..'_close (lua_State* tolua_S);') output('\n') end local i=1 while self[i] do self[i]:preamble() i = i+1 end output('\n') output('/* function to register type */') output('static void toluaI_reg_types (lua_State* tolua_S)') output('{') foreach(_usertype,function(n,v) output(' tolua_usertype(tolua_S,"',v,'");') end) output('}') output('\n') output('/* error messages */') output('#define TOLUA_ERR_SELF tolua_error(tolua_S,\"invalid \'self\'\")') output('#define TOLUA_ERR_ASSIGN tolua_error(tolua_S,\"#vinvalid type in variable assignment.\")') output('\n') end -- register package -- write package open function function classPackage:register () output("/* Open function */") output("int tolua_"..self.name.."_open (lua_State* tolua_S)") output("{") output(" tolua_open(tolua_S);") output(" toluaI_reg_types(tolua_S);") local i=1 while self[i] do self[i]:register() i = i+1 end output(" return 1;") output("}") end -- unregister package -- write package close function function classPackage:unregister () output("/* Close function */") output("void tolua_"..self.name.."_close (lua_State* tolua_S)") output("{") local i=1 while self[i] do self[i]:unregister() i = i+1 end output("}") end -- write header file function classPackage:header () output('/*\n') output('** Lua binding: '..self.name..'\n') output('** Generated automatically by '..TOLUA_VERSION..'.\n') output('*/\n\n') if not flags.h then output('/* Exported function */') output('int tolua_'..self.name..'_open (lua_State* tolua_S);') output('void tolua_'..self.name..'_close (lua_State* tolua_S);') output('\n') end end -- Internal constructor function _Package (t) t._base = classPackage settag(t,tolua_tag) return t end -- Constructor -- Expects the base file name. -- It assumes the file has extension ".pkg". function Package (name) -- read file local code = read("*a") code = "\n" .. code -- add sentinel -- deal with include directive local nsubst repeat code,nsubst = gsub(code,"\n%s*%$<(.-)>%s*\n",function (fn) local fp,msg = openfile(fn,'r') if not fp then error('#'..msg..': '..fn) end local s = read(fp,'*a') closefile(fp) return "\n" .. s end) until nsubst==0 -- deal with include directive for C/C++ header files local nsubst repeat code,nsubst = gsub(code,"\n%s*%${(.-)}%s*\n", function (fn) local fp,msg = openfile(fn,'r') if not fp then error('#'..msg..': '..fn) end local s = read(fp,'*a') closefile(fp) -- extract marked code local T = {code="\n"} s= "\n" .. s .. "\n" -- add blank lines as sentinels -- extract one-line statments gsub(s,"\n(.-)[Tt][Oo][Ll][Uu][Aa]_[Ee][Xx][Pp][Oo][Rr][Tt][^\n]*\n", function (c) %T.code = %T.code .. c .. "\n" end ) -- extract multiline statments gsub(s,"\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[Bb][Ee][Gg][Ii][Nn][^\n]*".. "(.-)" .. "\n[^\n]*[Tt][Oo][Ll][Uu][Aa]_[Ee][Nn][Dd][^\n]*\n", function (c) %T.code = %T.code .. c .. "\n" end ) return T.code end) until nsubst==0 local t = _Package(_Container{name=name, code=code}) push(t) t:preprocess() t:parse(t.code) pop() return t end