|
1 -- Prosody IM |
|
2 -- Copyright (C) 2008-2009 Matthew Wild |
|
3 -- Copyright (C) 2008-2009 Waqas Hussain |
|
4 -- |
|
5 -- This project is MIT/X11 licensed. Please see the |
|
6 -- COPYING file in the source package for more information. |
|
7 -- |
|
8 -- Based on Kepler Compat-5.1 code |
|
9 -- Copyright Kepler Project 2004-2006 (http://www.keplerproject.org/compat) |
|
10 -- $Id: compat-5.1.lua,v 1.22 2006/02/20 21:12:47 carregal Exp $ |
|
11 -- |
|
12 |
|
13 local LUA_DIRSEP = '/' |
|
14 local LUA_OFSEP = '_' |
|
15 local OLD_LUA_OFSEP = '' |
|
16 local POF = 'luaopen_' |
|
17 local LUA_PATH_MARK = '?' |
|
18 local LUA_IGMARK = ':' |
|
19 |
|
20 local assert, error, getfenv, ipairs, loadfile, loadlib, pairs, setfenv, setmetatable, type = assert, error, getfenv, ipairs, loadfile, loadlib, pairs, setfenv, setmetatable, type |
|
21 local find, format, gfind, gsub, sub = string.find, string.format, string.gfind, string.gsub, string.sub |
|
22 |
|
23 if package.nonglobal_module then return; end |
|
24 package.nonglobal_module = true; |
|
25 |
|
26 local _PACKAGE = package |
|
27 local _LOADED = package.loaded |
|
28 local _PRELOAD = package.preload |
|
29 |
|
30 -- |
|
31 -- looks for a file `name' in given path |
|
32 -- |
|
33 local function findfile (name, pname) |
|
34 name = gsub (name, "%.", LUA_DIRSEP) |
|
35 local path = _PACKAGE[pname] |
|
36 assert (type(path) == "string", format ("package.%s must be a string", pname)) |
|
37 for c in gfind (path, "[^;]+") do |
|
38 c = gsub (c, "%"..LUA_PATH_MARK, name) |
|
39 local f = io.open (c) |
|
40 if f then |
|
41 f:close () |
|
42 return c |
|
43 end |
|
44 end |
|
45 return nil -- not found |
|
46 end |
|
47 |
|
48 |
|
49 -- |
|
50 -- check whether library is already loaded |
|
51 -- |
|
52 local function loader_preload (name) |
|
53 assert (type(name) == "string", format ( |
|
54 "bad argument #1 to `require' (string expected, got %s)", type(name))) |
|
55 assert (type(_PRELOAD) == "table", "`package.preload' must be a table") |
|
56 return _PRELOAD[name] |
|
57 end |
|
58 |
|
59 |
|
60 -- |
|
61 -- Lua library loader |
|
62 -- |
|
63 local function loader_Lua (name) |
|
64 assert (type(name) == "string", format ( |
|
65 "bad argument #1 to `require' (string expected, got %s)", type(name))) |
|
66 local filename = findfile (name, "path") |
|
67 if not filename then |
|
68 return false |
|
69 end |
|
70 local f, err = loadfile (filename) |
|
71 if not f then |
|
72 error (format ("error loading module `%s' (%s)", name, err)) |
|
73 end |
|
74 return f |
|
75 end |
|
76 |
|
77 |
|
78 local function mkfuncname (name) |
|
79 name = gsub (name, "^.*%"..LUA_IGMARK, "") |
|
80 name = gsub (name, "%.", LUA_OFSEP) |
|
81 return POF..name |
|
82 end |
|
83 |
|
84 local function old_mkfuncname (name) |
|
85 --name = gsub (name, "^.*%"..LUA_IGMARK, "") |
|
86 name = gsub (name, "%.", OLD_LUA_OFSEP) |
|
87 return POF..name |
|
88 end |
|
89 |
|
90 -- |
|
91 -- C library loader |
|
92 -- |
|
93 local function loader_C (name) |
|
94 assert (type(name) == "string", format ( |
|
95 "bad argument #1 to `require' (string expected, got %s)", type(name))) |
|
96 local filename = findfile (name, "cpath") |
|
97 if not filename then |
|
98 return false |
|
99 end |
|
100 local funcname = mkfuncname (name) |
|
101 local f, err = loadlib (filename, funcname) |
|
102 if not f then |
|
103 funcname = old_mkfuncname (name) |
|
104 f, err = loadlib (filename, funcname) |
|
105 if not f then |
|
106 error (format ("error loading module `%s' (%s)", name, err)) |
|
107 end |
|
108 end |
|
109 return f |
|
110 end |
|
111 |
|
112 |
|
113 local function loader_Croot (name) |
|
114 local p = gsub (name, "^([^.]*).-$", "%1") |
|
115 if p == "" then |
|
116 return |
|
117 end |
|
118 local filename = findfile (p, "cpath") |
|
119 if not filename then |
|
120 return |
|
121 end |
|
122 local funcname = mkfuncname (name) |
|
123 local f, err, where = loadlib (filename, funcname) |
|
124 if f then |
|
125 return f |
|
126 elseif where ~= "init" then |
|
127 error (format ("error loading module `%s' (%s)", name, err)) |
|
128 end |
|
129 end |
|
130 |
|
131 -- create `loaders' table |
|
132 package.loaders = package.loaders or { loader_preload, loader_Lua, loader_C, loader_Croot, } |
|
133 local _LOADERS = package.loaders |
|
134 |
|
135 |
|
136 -- |
|
137 -- iterate over available loaders |
|
138 -- |
|
139 local function load (name, loaders) |
|
140 -- iterate over available loaders |
|
141 assert (type (loaders) == "table", "`package.loaders' must be a table") |
|
142 for i, loader in ipairs (loaders) do |
|
143 local f = loader (name) |
|
144 if f then |
|
145 return f |
|
146 end |
|
147 end |
|
148 error (format ("module `%s' not found", name)) |
|
149 end |
|
150 |
|
151 -- sentinel |
|
152 local sentinel = function () end |
|
153 |
|
154 local old_require = _G.require; |
|
155 local dep_path = {}; |
|
156 local current_env = nil; |
|
157 function _G.require(modname) |
|
158 --table.insert(dep_path, modname); |
|
159 --if getfenv(2) == getfenv(0) --[[and rawget(_G, "__locked")]] then |
|
160 -- print("**** Uh-oh, require called from locked global env at "..table.concat(dep_path, "->"), debug.traceback()); |
|
161 --end |
|
162 if not current_env and rawget(_G, "__locked") then |
|
163 _G.prosody.unlock_globals(); |
|
164 _G.__locked = false; |
|
165 end |
|
166 local old_current_env; |
|
167 old_current_env, current_env = current_env, getfenv(2); |
|
168 local ok, ret = pcall(old_require, modname); |
|
169 current_env = old_current_env; |
|
170 if not current_env and rawget(_G, "__locked") == false then |
|
171 _G.prosody.lock_globals(); |
|
172 end |
|
173 --table.remove(dep_path); |
|
174 if not ok then error(ret, 0); end |
|
175 return ret; |
|
176 end |
|
177 |
|
178 |
|
179 -- findtable |
|
180 local function findtable (t, f) |
|
181 assert (type(f)=="string", "not a valid field name ("..tostring(f)..")") |
|
182 local ff = f.."." |
|
183 local ok, e, w = find (ff, '(.-)%.', 1) |
|
184 while ok do |
|
185 local nt = rawget (t, w) |
|
186 if not nt then |
|
187 nt = {} |
|
188 t[w] = nt |
|
189 elseif type(t) ~= "table" then |
|
190 return sub (f, e+1) |
|
191 end |
|
192 t = nt |
|
193 ok, e, w = find (ff, '(.-)%.', e+1) |
|
194 end |
|
195 return t |
|
196 end |
|
197 |
|
198 -- |
|
199 -- new package.seeall function |
|
200 -- |
|
201 function _PACKAGE.seeall (module) |
|
202 local t = type(module) |
|
203 assert (t == "table", "bad argument #1 to package.seeall (table expected, got "..t..")") |
|
204 local meta = getmetatable (module) |
|
205 if not meta then |
|
206 meta = {} |
|
207 setmetatable (module, meta) |
|
208 end |
|
209 meta.__index = _G |
|
210 end |
|
211 |
|
212 |
|
213 -- |
|
214 -- new module function |
|
215 -- |
|
216 function _G.module (modname, ...) |
|
217 local ns = _LOADED[modname]; |
|
218 if type(ns) ~= "table" then |
|
219 --if not current_env then |
|
220 -- print("module outside require for "..modname.." at "..debug.traceback()); |
|
221 --end |
|
222 ns = findtable (current_env or getfenv(2), modname); |
|
223 if not ns then |
|
224 error (string.format ("name conflict for module '%s'", modname)) |
|
225 end |
|
226 _LOADED[modname] = ns |
|
227 end |
|
228 if not ns._NAME then |
|
229 ns._NAME = modname |
|
230 ns._M = ns |
|
231 ns._PACKAGE = gsub (modname, "[^.]*$", "") |
|
232 end |
|
233 setfenv (2, ns) |
|
234 for i, f in ipairs (arg) do |
|
235 f (ns) |
|
236 end |
|
237 end |