fix off by 1 error
[rrdtool.git] / bindings / lua / compat-5.1r5 / compat-5.1.lua
1 --
2 -- Compat-5.1
3 -- Copyright Kepler Project 2004-2006 (http://www.keplerproject.org/compat)
4 -- According to Lua 5.1
5 -- $Id: compat-5.1.lua,v 1.22 2006/02/20 21:12:47 carregal Exp $
6 --
7 -- Copyright © 2004-2006 The Kepler Project.
8 --   
9 -- Permission is hereby granted, free of charge, to any person obtaining a copy
10 -- of this software and associated documentation files (the "Software"), to
11 -- deal in the Software without restriction, including without limitation the
12 -- rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
13 -- sell copies of the Software, and to permit persons to whom the Software is
14 -- furnished to do so, subject to the following conditions:
15 -- 
16 -- The above copyright notice and this permission notice shall be included in 
17 -- all copies or substantial portions of the Software.
18 -- 
19 -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR  
20 -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 -- IN THE SOFTWARE.   
26 --
27
28 _COMPAT51 = "Compat-5.1 R5"
29
30 local LUA_DIRSEP = '/'
31 local LUA_OFSEP = '_'
32 local OLD_LUA_OFSEP = ''
33 local POF = 'luaopen_'
34 local LUA_PATH_MARK = '?'
35 local LUA_IGMARK = ':'
36
37 local assert, error, getfenv, ipairs, loadfile, loadlib, pairs, setfenv, setmetatable, type = assert, error, getfenv, ipairs, loadfile, loadlib, pairs, setfenv, setmetatable, type
38 local find, format, gfind, gsub, sub = string.find, string.format, string.gfind, string.gsub, string.sub
39
40 --
41 -- avoid overwriting the package table if it's already there
42 --
43 package = package or {}
44 local _PACKAGE = package
45
46 package.path = LUA_PATH or os.getenv("LUA_PATH") or
47              ("./?.lua;" ..
48               "/usr/local/share/lua/5.0/?.lua;" ..
49               "/usr/local/share/lua/5.0/?/?.lua;" ..
50               "/usr/local/share/lua/5.0/?/init.lua" )
51  
52 package.cpath = LUA_CPATH or os.getenv("LUA_CPATH") or
53              "./?.so;" ..
54              "./l?.so;" ..
55              "/usr/local/lib/lua/5.0/?.so;" ..
56              "/usr/local/lib/lua/5.0/l?.so"
57
58 --
59 -- make sure require works with standard libraries
60 --
61 package.loaded = package.loaded or {}
62 package.loaded.debug = debug
63 package.loaded.string = string
64 package.loaded.math = math
65 package.loaded.io = io
66 package.loaded.os = os
67 package.loaded.table = table 
68 package.loaded.base = _G
69 package.loaded.coroutine = coroutine
70 local _LOADED = package.loaded
71
72 --
73 -- avoid overwriting the package.preload table if it's already there
74 --
75 package.preload = package.preload or {}
76 local _PRELOAD = package.preload
77
78
79 --
80 -- looks for a file `name' in given path
81 --
82 local function findfile (name, pname)
83         name = gsub (name, "%.", LUA_DIRSEP)
84         local path = _PACKAGE[pname]
85         assert (type(path) == "string", format ("package.%s must be a string", pname))
86         for c in gfind (path, "[^;]+") do
87                 c = gsub (c, "%"..LUA_PATH_MARK, name)
88                 local f = io.open (c)
89                 if f then
90                         f:close ()
91                         return c
92                 end
93         end
94         return nil -- not found
95 end
96
97
98 --
99 -- check whether library is already loaded
100 --
101 local function loader_preload (name)
102         assert (type(name) == "string", format (
103                 "bad argument #1 to `require' (string expected, got %s)", type(name)))
104         assert (type(_PRELOAD) == "table", "`package.preload' must be a table")
105         return _PRELOAD[name]
106 end
107
108
109 --
110 -- Lua library loader
111 --
112 local function loader_Lua (name)
113         assert (type(name) == "string", format (
114                 "bad argument #1 to `require' (string expected, got %s)", type(name)))
115         local filename = findfile (name, "path")
116         if not filename then
117                 return false
118         end
119         local f, err = loadfile (filename)
120         if not f then
121                 error (format ("error loading module `%s' (%s)", name, err))
122         end
123         return f
124 end
125
126
127 local function mkfuncname (name)
128         name = gsub (name, "^.*%"..LUA_IGMARK, "")
129         name = gsub (name, "%.", LUA_OFSEP)
130         return POF..name
131 end
132
133 local function old_mkfuncname (name)
134         --name = gsub (name, "^.*%"..LUA_IGMARK, "")
135         name = gsub (name, "%.", OLD_LUA_OFSEP)
136         return POF..name
137 end
138
139 --
140 -- C library loader
141 --
142 local function loader_C (name)
143         assert (type(name) == "string", format (
144                 "bad argument #1 to `require' (string expected, got %s)", type(name)))
145         local filename = findfile (name, "cpath")
146         if not filename then
147                 return false
148         end
149         local funcname = mkfuncname (name)
150         local f, err = loadlib (filename, funcname)
151         if not f then
152                 funcname = old_mkfuncname (name)
153                 f, err = loadlib (filename, funcname)
154                 if not f then
155                         error (format ("error loading module `%s' (%s)", name, err))
156                 end
157         end
158         return f
159 end
160
161
162 local function loader_Croot (name)
163         local p = gsub (name, "^([^.]*).-$", "%1")
164         if p == "" then
165                 return
166         end
167         local filename = findfile (p, "cpath")
168         if not filename then
169                 return
170         end
171         local funcname = mkfuncname (name)
172         local f, err, where = loadlib (filename, funcname)
173         if f then
174                 return f
175         elseif where ~= "init" then
176                 error (format ("error loading module `%s' (%s)", name, err))
177         end
178 end
179
180 -- create `loaders' table
181 package.loaders = package.loaders or { loader_preload, loader_Lua, loader_C, loader_Croot, }
182 local _LOADERS = package.loaders
183
184
185 --
186 -- iterate over available loaders
187 --
188 local function load (name, loaders)
189         -- iterate over available loaders
190         assert (type (loaders) == "table", "`package.loaders' must be a table")
191         for i, loader in ipairs (loaders) do
192                 local f = loader (name)
193                 if f then
194                         return f
195                 end
196         end
197         error (format ("module `%s' not found", name))
198 end
199
200 -- sentinel
201 local sentinel = function () end
202
203 --
204 -- new require
205 --
206 function _G.require (modname)
207         assert (type(modname) == "string", format (
208                 "bad argument #1 to `require' (string expected, got %s)", type(name)))
209         local p = _LOADED[modname]
210         if p then -- is it there?
211                 if p == sentinel then
212                         error (format ("loop or previous error loading module '%s'", modname))
213                 end
214                 return p -- package is already loaded
215         end
216         local init = load (modname, _LOADERS)
217         _LOADED[modname] = sentinel
218         local actual_arg = _G.arg
219         _G.arg = { modname }
220         local res = init (modname)
221         if res then
222                 _LOADED[modname] = res
223         end
224         _G.arg = actual_arg
225         if _LOADED[modname] == sentinel then
226                 _LOADED[modname] = true
227         end
228         return _LOADED[modname]
229 end
230
231
232 -- findtable
233 local function findtable (t, f)
234         assert (type(f)=="string", "not a valid field name ("..tostring(f)..")")
235         local ff = f.."."
236         local ok, e, w = find (ff, '(.-)%.', 1)
237         while ok do
238                 local nt = rawget (t, w)
239                 if not nt then
240                         nt = {}
241                         t[w] = nt
242                 elseif type(t) ~= "table" then
243                         return sub (f, e+1)
244                 end
245                 t = nt
246                 ok, e, w = find (ff, '(.-)%.', e+1)
247         end
248         return t
249 end
250
251 --
252 -- new package.seeall function
253 --
254 function _PACKAGE.seeall (module)
255         local t = type(module)
256         assert (t == "table", "bad argument #1 to package.seeall (table expected, got "..t..")")
257         local meta = getmetatable (module)
258         if not meta then
259                 meta = {}
260                 setmetatable (module, meta)
261         end
262         meta.__index = _G
263 end
264
265
266 --
267 -- new module function
268 --
269 function _G.module (modname, ...)
270         local ns = _LOADED[modname]
271         if type(ns) ~= "table" then
272                 ns = findtable (_G, modname)
273                 if not ns then
274                         error (string.format ("name conflict for module '%s'", modname))
275                 end
276                 _LOADED[modname] = ns
277         end
278         if not ns._NAME then
279                 ns._NAME = modname
280                 ns._M = ns
281                 ns._PACKAGE = gsub (modname, "[^.]*$", "")
282         end
283         setfenv (2, ns)
284         for i, f in ipairs (arg) do
285                 f (ns)
286         end
287 end