added compat 5.1 license copied from website
[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 -- Compat-5.1 is free software: it can be used for both academic and commercial
8 -- purposes at absolutely no cost. There are no royalties or GNU-like
9 -- "copyleft" restrictions. Compat-5.1 qualifies as Open Source software. Its
10 -- licenses are compatible with GPL. Compat-5.1 is not in the public domain and
11 -- the Kepler Project keep its copyright. The legal details are below.
12 --   
13 -- The spirit of the license is that you are free to use Compat-5.1 for any
14 -- purpose at no cost without having to ask us. The only requirement is that if
15 -- you do use Compat-5.1, then you should give us credit by including the
16 -- appropriate copyright notice somewhere in your product or its documentation.
17 --   
18 -- The Compat-5.1 library is designed and implemented by Roberto Ierusalimschy,
19 -- Diego Nehab, André Carregal and Tomás Guisasola. The implementation is not
20 -- derived from licensed software.
21 --
22
23 _COMPAT51 = "Compat-5.1 R5"
24
25 local LUA_DIRSEP = '/'
26 local LUA_OFSEP = '_'
27 local OLD_LUA_OFSEP = ''
28 local POF = 'luaopen_'
29 local LUA_PATH_MARK = '?'
30 local LUA_IGMARK = ':'
31
32 local assert, error, getfenv, ipairs, loadfile, loadlib, pairs, setfenv, setmetatable, type = assert, error, getfenv, ipairs, loadfile, loadlib, pairs, setfenv, setmetatable, type
33 local find, format, gfind, gsub, sub = string.find, string.format, string.gfind, string.gsub, string.sub
34
35 --
36 -- avoid overwriting the package table if it's already there
37 --
38 package = package or {}
39 local _PACKAGE = package
40
41 package.path = LUA_PATH or os.getenv("LUA_PATH") or
42              ("./?.lua;" ..
43               "/usr/local/share/lua/5.0/?.lua;" ..
44               "/usr/local/share/lua/5.0/?/?.lua;" ..
45               "/usr/local/share/lua/5.0/?/init.lua" )
46  
47 package.cpath = LUA_CPATH or os.getenv("LUA_CPATH") or
48              "./?.so;" ..
49              "./l?.so;" ..
50              "/usr/local/lib/lua/5.0/?.so;" ..
51              "/usr/local/lib/lua/5.0/l?.so"
52
53 --
54 -- make sure require works with standard libraries
55 --
56 package.loaded = package.loaded or {}
57 package.loaded.debug = debug
58 package.loaded.string = string
59 package.loaded.math = math
60 package.loaded.io = io
61 package.loaded.os = os
62 package.loaded.table = table 
63 package.loaded.base = _G
64 package.loaded.coroutine = coroutine
65 local _LOADED = package.loaded
66
67 --
68 -- avoid overwriting the package.preload table if it's already there
69 --
70 package.preload = package.preload or {}
71 local _PRELOAD = package.preload
72
73
74 --
75 -- looks for a file `name' in given path
76 --
77 local function findfile (name, pname)
78         name = gsub (name, "%.", LUA_DIRSEP)
79         local path = _PACKAGE[pname]
80         assert (type(path) == "string", format ("package.%s must be a string", pname))
81         for c in gfind (path, "[^;]+") do
82                 c = gsub (c, "%"..LUA_PATH_MARK, name)
83                 local f = io.open (c)
84                 if f then
85                         f:close ()
86                         return c
87                 end
88         end
89         return nil -- not found
90 end
91
92
93 --
94 -- check whether library is already loaded
95 --
96 local function loader_preload (name)
97         assert (type(name) == "string", format (
98                 "bad argument #1 to `require' (string expected, got %s)", type(name)))
99         assert (type(_PRELOAD) == "table", "`package.preload' must be a table")
100         return _PRELOAD[name]
101 end
102
103
104 --
105 -- Lua library loader
106 --
107 local function loader_Lua (name)
108         assert (type(name) == "string", format (
109                 "bad argument #1 to `require' (string expected, got %s)", type(name)))
110         local filename = findfile (name, "path")
111         if not filename then
112                 return false
113         end
114         local f, err = loadfile (filename)
115         if not f then
116                 error (format ("error loading module `%s' (%s)", name, err))
117         end
118         return f
119 end
120
121
122 local function mkfuncname (name)
123         name = gsub (name, "^.*%"..LUA_IGMARK, "")
124         name = gsub (name, "%.", LUA_OFSEP)
125         return POF..name
126 end
127
128 local function old_mkfuncname (name)
129         --name = gsub (name, "^.*%"..LUA_IGMARK, "")
130         name = gsub (name, "%.", OLD_LUA_OFSEP)
131         return POF..name
132 end
133
134 --
135 -- C library loader
136 --
137 local function loader_C (name)
138         assert (type(name) == "string", format (
139                 "bad argument #1 to `require' (string expected, got %s)", type(name)))
140         local filename = findfile (name, "cpath")
141         if not filename then
142                 return false
143         end
144         local funcname = mkfuncname (name)
145         local f, err = loadlib (filename, funcname)
146         if not f then
147                 funcname = old_mkfuncname (name)
148                 f, err = loadlib (filename, funcname)
149                 if not f then
150                         error (format ("error loading module `%s' (%s)", name, err))
151                 end
152         end
153         return f
154 end
155
156
157 local function loader_Croot (name)
158         local p = gsub (name, "^([^.]*).-$", "%1")
159         if p == "" then
160                 return
161         end
162         local filename = findfile (p, "cpath")
163         if not filename then
164                 return
165         end
166         local funcname = mkfuncname (name)
167         local f, err, where = loadlib (filename, funcname)
168         if f then
169                 return f
170         elseif where ~= "init" then
171                 error (format ("error loading module `%s' (%s)", name, err))
172         end
173 end
174
175 -- create `loaders' table
176 package.loaders = package.loaders or { loader_preload, loader_Lua, loader_C, loader_Croot, }
177 local _LOADERS = package.loaders
178
179
180 --
181 -- iterate over available loaders
182 --
183 local function load (name, loaders)
184         -- iterate over available loaders
185         assert (type (loaders) == "table", "`package.loaders' must be a table")
186         for i, loader in ipairs (loaders) do
187                 local f = loader (name)
188                 if f then
189                         return f
190                 end
191         end
192         error (format ("module `%s' not found", name))
193 end
194
195 -- sentinel
196 local sentinel = function () end
197
198 --
199 -- new require
200 --
201 function _G.require (modname)
202         assert (type(modname) == "string", format (
203                 "bad argument #1 to `require' (string expected, got %s)", type(name)))
204         local p = _LOADED[modname]
205         if p then -- is it there?
206                 if p == sentinel then
207                         error (format ("loop or previous error loading module '%s'", modname))
208                 end
209                 return p -- package is already loaded
210         end
211         local init = load (modname, _LOADERS)
212         _LOADED[modname] = sentinel
213         local actual_arg = _G.arg
214         _G.arg = { modname }
215         local res = init (modname)
216         if res then
217                 _LOADED[modname] = res
218         end
219         _G.arg = actual_arg
220         if _LOADED[modname] == sentinel then
221                 _LOADED[modname] = true
222         end
223         return _LOADED[modname]
224 end
225
226
227 -- findtable
228 local function findtable (t, f)
229         assert (type(f)=="string", "not a valid field name ("..tostring(f)..")")
230         local ff = f.."."
231         local ok, e, w = find (ff, '(.-)%.', 1)
232         while ok do
233                 local nt = rawget (t, w)
234                 if not nt then
235                         nt = {}
236                         t[w] = nt
237                 elseif type(t) ~= "table" then
238                         return sub (f, e+1)
239                 end
240                 t = nt
241                 ok, e, w = find (ff, '(.-)%.', e+1)
242         end
243         return t
244 end
245
246 --
247 -- new package.seeall function
248 --
249 function _PACKAGE.seeall (module)
250         local t = type(module)
251         assert (t == "table", "bad argument #1 to package.seeall (table expected, got "..t..")")
252         local meta = getmetatable (module)
253         if not meta then
254                 meta = {}
255                 setmetatable (module, meta)
256         end
257         meta.__index = _G
258 end
259
260
261 --
262 -- new module function
263 --
264 function _G.module (modname, ...)
265         local ns = _LOADED[modname]
266         if type(ns) ~= "table" then
267                 ns = findtable (_G, modname)
268                 if not ns then
269                         error (string.format ("name conflict for module '%s'", modname))
270                 end
271                 _LOADED[modname] = ns
272         end
273         if not ns._NAME then
274                 ns._NAME = modname
275                 ns._M = ns
276                 ns._PACKAGE = gsub (modname, "[^.]*$", "")
277         end
278         setfenv (2, ns)
279         for i, f in ipairs (arg) do
280                 f (ns)
281         end
282 end