754054b404cbbb8ddf24f22386bcea23e38a98f4
[rrdtool.git] / bindings / lua / compat-5.1r5 / compat-5.1.c
1 /*
2 ** Compat-5.1
3 ** Copyright Kepler Project 2004-2006 (http://www.keplerproject.org/compat)
4 ** $Id$
5
6 Compat-5.1 is free software: it can be used for both academic and commercial
7 purposes at absolutely no cost. There are no royalties or GNU-like
8 "copyleft" restrictions. Compat-5.1 qualifies as Open Source software. Its
9 licenses are compatible with GPL. Compat-5.1 is not in the public domain and
10 the Kepler Project keep its copyright. The legal details are below.
11
12 The spirit of the license is that you are free to use Compat-5.1 for any
13 purpose at no cost without having to ask us. The only requirement is that if
14 you do use Compat-5.1, then you should give us credit by including the
15 appropriate copyright notice somewhere in your product or its documentation.
16
17 The Compat-5.1 library is designed and implemented by Roberto Ierusalimschy,
18 Diego Nehab, André Carregal and Tomás Guisasola. The implementation is not
19 derived from licensed software.
20
21 */
22
23 #include <stdio.h>
24 #include <string.h>
25 #include "lua.h"
26 #include "lauxlib.h"
27 #include "compat-5.1.h"
28
29 static void getfield(lua_State *L, int idx, const char *name) {
30     const char *end = strchr(name, '.');
31     lua_pushvalue(L, idx);
32     while (end) {
33         lua_pushlstring(L, name, end - name);
34         lua_gettable(L, -2);
35         lua_remove(L, -2);
36         if (lua_isnil(L, -1)) return;
37         name = end+1;
38         end = strchr(name, '.');
39     }
40     lua_pushstring(L, name);
41     lua_gettable(L, -2);
42     lua_remove(L, -2);
43 }
44
45 static void setfield(lua_State *L, int idx, const char *name) {
46     const char *end = strchr(name, '.');
47     lua_pushvalue(L, idx);
48     while (end) {
49         lua_pushlstring(L, name, end - name);
50         lua_gettable(L, -2);
51         /* create table if not found */
52         if (lua_isnil(L, -1)) {
53             lua_pop(L, 1);
54             lua_newtable(L);
55             lua_pushlstring(L, name, end - name);
56             lua_pushvalue(L, -2);
57             lua_settable(L, -4);
58         }
59         lua_remove(L, -2);
60         name = end+1;
61         end = strchr(name, '.');
62     }
63     lua_pushstring(L, name);
64     lua_pushvalue(L, -3);
65     lua_settable(L, -3);
66     lua_pop(L, 2);
67 }
68
69 LUALIB_API void luaL_module(lua_State *L, const char *libname,
70                               const luaL_reg *l, int nup) {
71   if (libname) {
72     getfield(L, LUA_GLOBALSINDEX, libname);  /* check whether lib already exists */
73     if (lua_isnil(L, -1)) { 
74       int env, ns;
75       lua_pop(L, 1); /* get rid of nil */
76       lua_pushliteral(L, "require");
77       lua_gettable(L, LUA_GLOBALSINDEX); /* look for require */
78       lua_getfenv(L, -1); /* getfenv(require) */
79       lua_remove(L, -2); /* remove function require */
80       env = lua_gettop(L);
81
82       lua_newtable(L); /* create namespace for lib */
83       ns = lua_gettop(L);
84       getfield(L, env, "package.loaded"); /* get package.loaded table */
85       if (lua_isnil(L, -1)) { /* create package.loaded table */
86           lua_pop(L, 1); /* remove previous result */
87           lua_newtable(L);
88           lua_pushvalue(L, -1);
89           setfield(L, env, "package.loaded");
90       }
91       else if (!lua_istable(L, -1))
92         luaL_error(L, "name conflict for library `%s'", libname);
93       lua_pushstring(L, libname);
94       lua_pushvalue(L, ns); 
95       lua_settable(L, -3); /* package.loaded[libname] = ns */
96       lua_pop(L, 1); /* get rid of package.loaded table */
97       lua_pushvalue(L, ns); /* copy namespace */
98       setfield(L, LUA_GLOBALSINDEX, libname);
99       lua_remove (L, env); /* remove env */
100     }
101     lua_insert(L, -(nup+1));  /* move library table to below upvalues */
102   }
103   for (; l->name; l++) {
104     int i;
105     lua_pushstring(L, l->name);
106     for (i=0; i<nup; i++)  /* copy upvalues to the top */
107       lua_pushvalue(L, -(nup+1));
108     lua_pushcclosure(L, l->func, nup);
109     lua_settable(L, -(nup+3));
110   }
111   lua_pop(L, nup);  /* remove upvalues */
112 }
113