xref: /illumos-gate/usr/src/uts/common/fs/zfs/lua/lbaselib.c (revision dfc11533)
1*dfc11533SChris Williamson /*
2*dfc11533SChris Williamson ** $Id: lbaselib.c,v 1.276.1.1 2013/04/12 18:48:47 roberto Exp $
3*dfc11533SChris Williamson ** Basic library
4*dfc11533SChris Williamson ** See Copyright Notice in lua.h
5*dfc11533SChris Williamson */
6*dfc11533SChris Williamson 
7*dfc11533SChris Williamson /* The following built-in lua functions have been removed and are not available
8*dfc11533SChris Williamson  * for use in ZFS channel programs:
9*dfc11533SChris Williamson  *
10*dfc11533SChris Williamson  * dofile
11*dfc11533SChris Williamson  * loadfile
12*dfc11533SChris Williamson  * load
13*dfc11533SChris Williamson  * pcall
14*dfc11533SChris Williamson  * print
15*dfc11533SChris Williamson  * xpcall
16*dfc11533SChris Williamson  */
17*dfc11533SChris Williamson 
18*dfc11533SChris Williamson #include <sys/zfs_context.h>
19*dfc11533SChris Williamson #include <sys/ctype.h>
20*dfc11533SChris Williamson #define	toupper(C)	(((C) >= 'a' && (C) <= 'z')? (C) - 'a' + 'A': (C))
21*dfc11533SChris Williamson 
22*dfc11533SChris Williamson #define lbaselib_c
23*dfc11533SChris Williamson #define LUA_LIB
24*dfc11533SChris Williamson 
25*dfc11533SChris Williamson #include "lua.h"
26*dfc11533SChris Williamson 
27*dfc11533SChris Williamson #include "lauxlib.h"
28*dfc11533SChris Williamson #include "lualib.h"
29*dfc11533SChris Williamson 
30*dfc11533SChris Williamson #define SPACECHARS	" \f\n\r\t\v"
31*dfc11533SChris Williamson 
luaB_tonumber(lua_State * L)32*dfc11533SChris Williamson static int luaB_tonumber (lua_State *L) {
33*dfc11533SChris Williamson   if (lua_isnoneornil(L, 2)) {  /* standard conversion */
34*dfc11533SChris Williamson     int isnum;
35*dfc11533SChris Williamson     lua_Number n = lua_tonumberx(L, 1, &isnum);
36*dfc11533SChris Williamson     if (isnum) {
37*dfc11533SChris Williamson       lua_pushnumber(L, n);
38*dfc11533SChris Williamson       return 1;
39*dfc11533SChris Williamson     }  /* else not a number; must be something */
40*dfc11533SChris Williamson     luaL_checkany(L, 1);
41*dfc11533SChris Williamson   }
42*dfc11533SChris Williamson   else {
43*dfc11533SChris Williamson     size_t l;
44*dfc11533SChris Williamson     const char *s = luaL_checklstring(L, 1, &l);
45*dfc11533SChris Williamson     const char *e = s + l;  /* end point for 's' */
46*dfc11533SChris Williamson     int base = luaL_checkint(L, 2);
47*dfc11533SChris Williamson     int neg = 0;
48*dfc11533SChris Williamson     luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range");
49*dfc11533SChris Williamson     s += strspn(s, SPACECHARS);  /* skip initial spaces */
50*dfc11533SChris Williamson     if (*s == '-') { s++; neg = 1; }  /* handle signal */
51*dfc11533SChris Williamson     else if (*s == '+') s++;
52*dfc11533SChris Williamson     if (isalnum((unsigned char)*s)) {
53*dfc11533SChris Williamson       lua_Number n = 0;
54*dfc11533SChris Williamson       do {
55*dfc11533SChris Williamson         int digit = (isdigit((unsigned char)*s)) ? *s - '0'
56*dfc11533SChris Williamson                        : toupper((unsigned char)*s) - 'A' + 10;
57*dfc11533SChris Williamson         if (digit >= base) break;  /* invalid numeral; force a fail */
58*dfc11533SChris Williamson         n = n * (lua_Number)base + (lua_Number)digit;
59*dfc11533SChris Williamson         s++;
60*dfc11533SChris Williamson       } while (isalnum((unsigned char)*s));
61*dfc11533SChris Williamson       s += strspn(s, SPACECHARS);  /* skip trailing spaces */
62*dfc11533SChris Williamson       if (s == e) {  /* no invalid trailing characters? */
63*dfc11533SChris Williamson         lua_pushnumber(L, (neg) ? -n : n);
64*dfc11533SChris Williamson         return 1;
65*dfc11533SChris Williamson       }  /* else not a number */
66*dfc11533SChris Williamson     }  /* else not a number */
67*dfc11533SChris Williamson   }
68*dfc11533SChris Williamson   lua_pushnil(L);  /* not a number */
69*dfc11533SChris Williamson   return 1;
70*dfc11533SChris Williamson }
71*dfc11533SChris Williamson 
72*dfc11533SChris Williamson 
luaB_error(lua_State * L)73*dfc11533SChris Williamson static int luaB_error (lua_State *L) {
74*dfc11533SChris Williamson   int level = luaL_optint(L, 2, 1);
75*dfc11533SChris Williamson   lua_settop(L, 1);
76*dfc11533SChris Williamson   if (lua_isstring(L, 1) && level > 0) {  /* add extra information? */
77*dfc11533SChris Williamson     luaL_where(L, level);
78*dfc11533SChris Williamson     lua_pushvalue(L, 1);
79*dfc11533SChris Williamson     lua_concat(L, 2);
80*dfc11533SChris Williamson   }
81*dfc11533SChris Williamson   return lua_error(L);
82*dfc11533SChris Williamson }
83*dfc11533SChris Williamson 
84*dfc11533SChris Williamson 
luaB_getmetatable(lua_State * L)85*dfc11533SChris Williamson static int luaB_getmetatable (lua_State *L) {
86*dfc11533SChris Williamson   luaL_checkany(L, 1);
87*dfc11533SChris Williamson   if (!lua_getmetatable(L, 1)) {
88*dfc11533SChris Williamson     lua_pushnil(L);
89*dfc11533SChris Williamson     return 1;  /* no metatable */
90*dfc11533SChris Williamson   }
91*dfc11533SChris Williamson   luaL_getmetafield(L, 1, "__metatable");
92*dfc11533SChris Williamson   return 1;  /* returns either __metatable field (if present) or metatable */
93*dfc11533SChris Williamson }
94*dfc11533SChris Williamson 
95*dfc11533SChris Williamson 
luaB_setmetatable(lua_State * L)96*dfc11533SChris Williamson static int luaB_setmetatable (lua_State *L) {
97*dfc11533SChris Williamson   int t = lua_type(L, 2);
98*dfc11533SChris Williamson   luaL_checktype(L, 1, LUA_TTABLE);
99*dfc11533SChris Williamson   luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2,
100*dfc11533SChris Williamson                     "nil or table expected");
101*dfc11533SChris Williamson   if (luaL_getmetafield(L, 1, "__metatable"))
102*dfc11533SChris Williamson     return luaL_error(L, "cannot change a protected metatable");
103*dfc11533SChris Williamson   lua_settop(L, 2);
104*dfc11533SChris Williamson   lua_setmetatable(L, 1);
105*dfc11533SChris Williamson   return 1;
106*dfc11533SChris Williamson }
107*dfc11533SChris Williamson 
108*dfc11533SChris Williamson 
luaB_rawequal(lua_State * L)109*dfc11533SChris Williamson static int luaB_rawequal (lua_State *L) {
110*dfc11533SChris Williamson   luaL_checkany(L, 1);
111*dfc11533SChris Williamson   luaL_checkany(L, 2);
112*dfc11533SChris Williamson   lua_pushboolean(L, lua_rawequal(L, 1, 2));
113*dfc11533SChris Williamson   return 1;
114*dfc11533SChris Williamson }
115*dfc11533SChris Williamson 
116*dfc11533SChris Williamson 
luaB_rawlen(lua_State * L)117*dfc11533SChris Williamson static int luaB_rawlen (lua_State *L) {
118*dfc11533SChris Williamson   int t = lua_type(L, 1);
119*dfc11533SChris Williamson   luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1,
120*dfc11533SChris Williamson                    "table or string expected");
121*dfc11533SChris Williamson   lua_pushinteger(L, lua_rawlen(L, 1));
122*dfc11533SChris Williamson   return 1;
123*dfc11533SChris Williamson }
124*dfc11533SChris Williamson 
125*dfc11533SChris Williamson 
luaB_rawget(lua_State * L)126*dfc11533SChris Williamson static int luaB_rawget (lua_State *L) {
127*dfc11533SChris Williamson   luaL_checktype(L, 1, LUA_TTABLE);
128*dfc11533SChris Williamson   luaL_checkany(L, 2);
129*dfc11533SChris Williamson   lua_settop(L, 2);
130*dfc11533SChris Williamson   lua_rawget(L, 1);
131*dfc11533SChris Williamson   return 1;
132*dfc11533SChris Williamson }
133*dfc11533SChris Williamson 
luaB_rawset(lua_State * L)134*dfc11533SChris Williamson static int luaB_rawset (lua_State *L) {
135*dfc11533SChris Williamson   luaL_checktype(L, 1, LUA_TTABLE);
136*dfc11533SChris Williamson   luaL_checkany(L, 2);
137*dfc11533SChris Williamson   luaL_checkany(L, 3);
138*dfc11533SChris Williamson   lua_settop(L, 3);
139*dfc11533SChris Williamson   lua_rawset(L, 1);
140*dfc11533SChris Williamson   return 1;
141*dfc11533SChris Williamson }
142*dfc11533SChris Williamson 
143*dfc11533SChris Williamson 
luaB_collectgarbage(lua_State * L)144*dfc11533SChris Williamson static int luaB_collectgarbage (lua_State *L) {
145*dfc11533SChris Williamson   static const char *const opts[] = {"stop", "restart", "collect",
146*dfc11533SChris Williamson     "count", "step", "setpause", "setstepmul",
147*dfc11533SChris Williamson     "setmajorinc", "isrunning", "generational", "incremental", NULL};
148*dfc11533SChris Williamson   static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT,
149*dfc11533SChris Williamson     LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL,
150*dfc11533SChris Williamson     LUA_GCSETMAJORINC, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC};
151*dfc11533SChris Williamson   int o = optsnum[luaL_checkoption(L, 1, "collect", opts)];
152*dfc11533SChris Williamson   int ex = luaL_optint(L, 2, 0);
153*dfc11533SChris Williamson   int res = lua_gc(L, o, ex);
154*dfc11533SChris Williamson   switch (o) {
155*dfc11533SChris Williamson     case LUA_GCCOUNT: {
156*dfc11533SChris Williamson       int b = lua_gc(L, LUA_GCCOUNTB, 0);
157*dfc11533SChris Williamson       lua_pushnumber(L, res + ((lua_Number)b/1024));
158*dfc11533SChris Williamson       lua_pushinteger(L, b);
159*dfc11533SChris Williamson       return 2;
160*dfc11533SChris Williamson     }
161*dfc11533SChris Williamson     case LUA_GCSTEP: case LUA_GCISRUNNING: {
162*dfc11533SChris Williamson       lua_pushboolean(L, res);
163*dfc11533SChris Williamson       return 1;
164*dfc11533SChris Williamson     }
165*dfc11533SChris Williamson     default: {
166*dfc11533SChris Williamson       lua_pushinteger(L, res);
167*dfc11533SChris Williamson       return 1;
168*dfc11533SChris Williamson     }
169*dfc11533SChris Williamson   }
170*dfc11533SChris Williamson }
171*dfc11533SChris Williamson 
172*dfc11533SChris Williamson 
luaB_type(lua_State * L)173*dfc11533SChris Williamson static int luaB_type (lua_State *L) {
174*dfc11533SChris Williamson   luaL_checkany(L, 1);
175*dfc11533SChris Williamson   lua_pushstring(L, luaL_typename(L, 1));
176*dfc11533SChris Williamson   return 1;
177*dfc11533SChris Williamson }
178*dfc11533SChris Williamson 
179*dfc11533SChris Williamson 
pairsmeta(lua_State * L,const char * method,int iszero,lua_CFunction iter)180*dfc11533SChris Williamson static int pairsmeta (lua_State *L, const char *method, int iszero,
181*dfc11533SChris Williamson                       lua_CFunction iter) {
182*dfc11533SChris Williamson   if (!luaL_getmetafield(L, 1, method)) {  /* no metamethod? */
183*dfc11533SChris Williamson     luaL_checktype(L, 1, LUA_TTABLE);  /* argument must be a table */
184*dfc11533SChris Williamson     lua_pushcfunction(L, iter);  /* will return generator, */
185*dfc11533SChris Williamson     lua_pushvalue(L, 1);  /* state, */
186*dfc11533SChris Williamson     if (iszero) lua_pushinteger(L, 0);  /* and initial value */
187*dfc11533SChris Williamson     else lua_pushnil(L);
188*dfc11533SChris Williamson   }
189*dfc11533SChris Williamson   else {
190*dfc11533SChris Williamson     lua_pushvalue(L, 1);  /* argument 'self' to metamethod */
191*dfc11533SChris Williamson     lua_call(L, 1, 3);  /* get 3 values from metamethod */
192*dfc11533SChris Williamson   }
193*dfc11533SChris Williamson   return 3;
194*dfc11533SChris Williamson }
195*dfc11533SChris Williamson 
196*dfc11533SChris Williamson 
luaB_next(lua_State * L)197*dfc11533SChris Williamson static int luaB_next (lua_State *L) {
198*dfc11533SChris Williamson   luaL_checktype(L, 1, LUA_TTABLE);
199*dfc11533SChris Williamson   lua_settop(L, 2);  /* create a 2nd argument if there isn't one */
200*dfc11533SChris Williamson   if (lua_next(L, 1))
201*dfc11533SChris Williamson     return 2;
202*dfc11533SChris Williamson   else {
203*dfc11533SChris Williamson     lua_pushnil(L);
204*dfc11533SChris Williamson     return 1;
205*dfc11533SChris Williamson   }
206*dfc11533SChris Williamson }
207*dfc11533SChris Williamson 
208*dfc11533SChris Williamson 
luaB_pairs(lua_State * L)209*dfc11533SChris Williamson static int luaB_pairs (lua_State *L) {
210*dfc11533SChris Williamson   return pairsmeta(L, "__pairs", 0, luaB_next);
211*dfc11533SChris Williamson }
212*dfc11533SChris Williamson 
213*dfc11533SChris Williamson 
ipairsaux(lua_State * L)214*dfc11533SChris Williamson static int ipairsaux (lua_State *L) {
215*dfc11533SChris Williamson   int i = luaL_checkint(L, 2);
216*dfc11533SChris Williamson   luaL_checktype(L, 1, LUA_TTABLE);
217*dfc11533SChris Williamson   i++;  /* next value */
218*dfc11533SChris Williamson   lua_pushinteger(L, i);
219*dfc11533SChris Williamson   lua_rawgeti(L, 1, i);
220*dfc11533SChris Williamson   return (lua_isnil(L, -1)) ? 1 : 2;
221*dfc11533SChris Williamson }
222*dfc11533SChris Williamson 
223*dfc11533SChris Williamson 
luaB_ipairs(lua_State * L)224*dfc11533SChris Williamson static int luaB_ipairs (lua_State *L) {
225*dfc11533SChris Williamson   return pairsmeta(L, "__ipairs", 1, ipairsaux);
226*dfc11533SChris Williamson }
227*dfc11533SChris Williamson 
228*dfc11533SChris Williamson 
luaB_assert(lua_State * L)229*dfc11533SChris Williamson static int luaB_assert (lua_State *L) {
230*dfc11533SChris Williamson   if (!lua_toboolean(L, 1))
231*dfc11533SChris Williamson     return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!"));
232*dfc11533SChris Williamson   return lua_gettop(L);
233*dfc11533SChris Williamson }
234*dfc11533SChris Williamson 
235*dfc11533SChris Williamson 
luaB_select(lua_State * L)236*dfc11533SChris Williamson static int luaB_select (lua_State *L) {
237*dfc11533SChris Williamson   int n = lua_gettop(L);
238*dfc11533SChris Williamson   if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') {
239*dfc11533SChris Williamson     lua_pushinteger(L, n-1);
240*dfc11533SChris Williamson     return 1;
241*dfc11533SChris Williamson   }
242*dfc11533SChris Williamson   else {
243*dfc11533SChris Williamson     int i = luaL_checkint(L, 1);
244*dfc11533SChris Williamson     if (i < 0) i = n + i;
245*dfc11533SChris Williamson     else if (i > n) i = n;
246*dfc11533SChris Williamson     luaL_argcheck(L, 1 <= i, 1, "index out of range");
247*dfc11533SChris Williamson     return n - i;
248*dfc11533SChris Williamson   }
249*dfc11533SChris Williamson }
250*dfc11533SChris Williamson 
luaB_tostring(lua_State * L)251*dfc11533SChris Williamson static int luaB_tostring (lua_State *L) {
252*dfc11533SChris Williamson   luaL_checkany(L, 1);
253*dfc11533SChris Williamson   luaL_tolstring(L, 1, NULL);
254*dfc11533SChris Williamson   return 1;
255*dfc11533SChris Williamson }
256*dfc11533SChris Williamson 
257*dfc11533SChris Williamson static const luaL_Reg base_funcs[] = {
258*dfc11533SChris Williamson   {"assert", luaB_assert},
259*dfc11533SChris Williamson   {"collectgarbage", luaB_collectgarbage},
260*dfc11533SChris Williamson   {"error", luaB_error},
261*dfc11533SChris Williamson   {"getmetatable", luaB_getmetatable},
262*dfc11533SChris Williamson   {"ipairs", luaB_ipairs},
263*dfc11533SChris Williamson #if defined(LUA_COMPAT_LOADSTRING)
264*dfc11533SChris Williamson   {"loadstring", luaB_load},
265*dfc11533SChris Williamson #endif
266*dfc11533SChris Williamson   {"next", luaB_next},
267*dfc11533SChris Williamson   {"pairs", luaB_pairs},
268*dfc11533SChris Williamson   {"rawequal", luaB_rawequal},
269*dfc11533SChris Williamson   {"rawlen", luaB_rawlen},
270*dfc11533SChris Williamson   {"rawget", luaB_rawget},
271*dfc11533SChris Williamson   {"rawset", luaB_rawset},
272*dfc11533SChris Williamson   {"select", luaB_select},
273*dfc11533SChris Williamson   {"setmetatable", luaB_setmetatable},
274*dfc11533SChris Williamson   {"tonumber", luaB_tonumber},
275*dfc11533SChris Williamson   {"tostring", luaB_tostring},
276*dfc11533SChris Williamson   {"type", luaB_type},
277*dfc11533SChris Williamson   {NULL, NULL}
278*dfc11533SChris Williamson };
279*dfc11533SChris Williamson 
280*dfc11533SChris Williamson 
luaopen_base(lua_State * L)281*dfc11533SChris Williamson LUAMOD_API int luaopen_base (lua_State *L) {
282*dfc11533SChris Williamson   /* set global _G */
283*dfc11533SChris Williamson   lua_pushglobaltable(L);
284*dfc11533SChris Williamson   lua_pushglobaltable(L);
285*dfc11533SChris Williamson   lua_setfield(L, -2, "_G");
286*dfc11533SChris Williamson   /* open lib into global table */
287*dfc11533SChris Williamson   luaL_setfuncs(L, base_funcs, 0);
288*dfc11533SChris Williamson   lua_pushliteral(L, LUA_VERSION);
289*dfc11533SChris Williamson   lua_setfield(L, -2, "_VERSION");  /* set global _VERSION */
290*dfc11533SChris Williamson   return 1;
291*dfc11533SChris Williamson }
292*dfc11533SChris Williamson 
293