1 /*
2 ** Library function support.
3 ** Copyright (C) 2005-2014 Mike Pall. See Copyright Notice in luajit.h
4 */
5
6 #define lj_lib_c
7 #define LUA_CORE
8
9 #include "lauxlib.h"
10
11 #include "lj_obj.h"
12 #include "lj_gc.h"
13 #include "lj_err.h"
14 #include "lj_str.h"
15 #include "lj_tab.h"
16 #include "lj_func.h"
17 #include "lj_bc.h"
18 #include "lj_dispatch.h"
19 #include "lj_vm.h"
20 #include "lj_strscan.h"
21 #include "lj_lib.h"
22
23 /* -- Library initialization ---------------------------------------------- */
24
lib_create_table(lua_State * L,const char * libname,int hsize)25 static GCtab *lib_create_table(lua_State *L, const char *libname, int hsize)
26 {
27 if (libname) {
28 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
29 lua_getfield(L, -1, libname);
30 if (!tvistab(L->top-1)) {
31 L->top--;
32 if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, hsize) != NULL)
33 lj_err_callerv(L, LJ_ERR_BADMODN, libname);
34 settabV(L, L->top, tabV(L->top-1));
35 L->top++;
36 lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
37 }
38 L->top--;
39 settabV(L, L->top-1, tabV(L->top));
40 } else {
41 lua_createtable(L, 0, hsize);
42 }
43 return tabV(L->top-1);
44 }
45
lj_lib_register(lua_State * L,const char * libname,const uint8_t * p,const lua_CFunction * cf)46 void lj_lib_register(lua_State *L, const char *libname,
47 const uint8_t *p, const lua_CFunction *cf)
48 {
49 GCtab *env = tabref(L->env);
50 GCfunc *ofn = NULL;
51 int ffid = *p++;
52 BCIns *bcff = &L2GG(L)->bcff[*p++];
53 GCtab *tab = lib_create_table(L, libname, *p++);
54 ptrdiff_t tpos = L->top - L->base;
55
56 /* Avoid barriers further down. */
57 lj_gc_anybarriert(L, tab);
58 tab->nomm = 0;
59
60 for (;;) {
61 uint32_t tag = *p++;
62 MSize len = tag & LIBINIT_LENMASK;
63 tag &= LIBINIT_TAGMASK;
64 if (tag != LIBINIT_STRING) {
65 const char *name;
66 MSize nuv = (MSize)(L->top - L->base - tpos);
67 GCfunc *fn = lj_func_newC(L, nuv, env);
68 if (nuv) {
69 L->top = L->base + tpos;
70 memcpy(fn->c.upvalue, L->top, sizeof(TValue)*nuv);
71 }
72 fn->c.ffid = (uint8_t)(ffid++);
73 name = (const char *)p;
74 p += len;
75 if (tag == LIBINIT_CF)
76 setmref(fn->c.pc, &G(L)->bc_cfunc_int);
77 else
78 setmref(fn->c.pc, bcff++);
79 if (tag == LIBINIT_ASM_)
80 fn->c.f = ofn->c.f; /* Copy handler from previous function. */
81 else
82 fn->c.f = *cf++; /* Get cf or handler from C function table. */
83 if (len) {
84 /* NOBARRIER: See above for common barrier. */
85 setfuncV(L, lj_tab_setstr(L, tab, lj_str_new(L, name, len)), fn);
86 }
87 ofn = fn;
88 } else {
89 switch (tag | len) {
90 case LIBINIT_SET:
91 L->top -= 2;
92 if (tvisstr(L->top+1) && strV(L->top+1)->len == 0)
93 env = tabV(L->top);
94 else /* NOBARRIER: See above for common barrier. */
95 copyTV(L, lj_tab_set(L, tab, L->top+1), L->top);
96 break;
97 case LIBINIT_NUMBER:
98 memcpy(&L->top->n, p, sizeof(double));
99 L->top++;
100 p += sizeof(double);
101 break;
102 case LIBINIT_COPY:
103 copyTV(L, L->top, L->top - *p++);
104 L->top++;
105 break;
106 case LIBINIT_LASTCL:
107 setfuncV(L, L->top++, ofn);
108 break;
109 case LIBINIT_FFID:
110 ffid++;
111 break;
112 case LIBINIT_END:
113 return;
114 default:
115 setstrV(L, L->top++, lj_str_new(L, (const char *)p, len));
116 p += len;
117 break;
118 }
119 }
120 }
121 }
122
123 /* -- Type checks --------------------------------------------------------- */
124
lj_lib_checkany(lua_State * L,int narg)125 TValue *lj_lib_checkany(lua_State *L, int narg)
126 {
127 TValue *o = L->base + narg-1;
128 if (o >= L->top)
129 lj_err_arg(L, narg, LJ_ERR_NOVAL);
130 return o;
131 }
132
lj_lib_checkstr(lua_State * L,int narg)133 GCstr *lj_lib_checkstr(lua_State *L, int narg)
134 {
135 TValue *o = L->base + narg-1;
136 if (o < L->top) {
137 if (LJ_LIKELY(tvisstr(o))) {
138 return strV(o);
139 } else if (tvisnumber(o)) {
140 GCstr *s = lj_str_fromnumber(L, o);
141 setstrV(L, o, s);
142 return s;
143 }
144 }
145 lj_err_argt(L, narg, LUA_TSTRING);
146 return NULL; /* unreachable */
147 }
148
lj_lib_optstr(lua_State * L,int narg)149 GCstr *lj_lib_optstr(lua_State *L, int narg)
150 {
151 TValue *o = L->base + narg-1;
152 return (o < L->top && !tvisnil(o)) ? lj_lib_checkstr(L, narg) : NULL;
153 }
154
155 #if LJ_DUALNUM
lj_lib_checknumber(lua_State * L,int narg)156 void lj_lib_checknumber(lua_State *L, int narg)
157 {
158 TValue *o = L->base + narg-1;
159 if (!(o < L->top && lj_strscan_numberobj(o)))
160 lj_err_argt(L, narg, LUA_TNUMBER);
161 }
162 #endif
163
lj_lib_checknum(lua_State * L,int narg)164 lua_Number lj_lib_checknum(lua_State *L, int narg)
165 {
166 TValue *o = L->base + narg-1;
167 if (!(o < L->top &&
168 (tvisnumber(o) || (tvisstr(o) && lj_strscan_num(strV(o), o)))))
169 lj_err_argt(L, narg, LUA_TNUMBER);
170 if (LJ_UNLIKELY(tvisint(o))) {
171 lua_Number n = (lua_Number)intV(o);
172 setnumV(o, n);
173 return n;
174 } else {
175 return numV(o);
176 }
177 }
178
lj_lib_checkint(lua_State * L,int narg)179 int32_t lj_lib_checkint(lua_State *L, int narg)
180 {
181 TValue *o = L->base + narg-1;
182 if (!(o < L->top && lj_strscan_numberobj(o)))
183 lj_err_argt(L, narg, LUA_TNUMBER);
184 if (LJ_LIKELY(tvisint(o))) {
185 return intV(o);
186 } else {
187 int32_t i = lj_num2int(numV(o));
188 if (LJ_DUALNUM) setintV(o, i);
189 return i;
190 }
191 }
192
lj_lib_optint(lua_State * L,int narg,int32_t def)193 int32_t lj_lib_optint(lua_State *L, int narg, int32_t def)
194 {
195 TValue *o = L->base + narg-1;
196 return (o < L->top && !tvisnil(o)) ? lj_lib_checkint(L, narg) : def;
197 }
198
lj_lib_checkbit(lua_State * L,int narg)199 int32_t lj_lib_checkbit(lua_State *L, int narg)
200 {
201 TValue *o = L->base + narg-1;
202 if (!(o < L->top && lj_strscan_numberobj(o)))
203 lj_err_argt(L, narg, LUA_TNUMBER);
204 if (LJ_LIKELY(tvisint(o))) {
205 return intV(o);
206 } else {
207 int32_t i = lj_num2bit(numV(o));
208 if (LJ_DUALNUM) setintV(o, i);
209 return i;
210 }
211 }
212
lj_lib_checkfunc(lua_State * L,int narg)213 GCfunc *lj_lib_checkfunc(lua_State *L, int narg)
214 {
215 TValue *o = L->base + narg-1;
216 if (!(o < L->top && tvisfunc(o)))
217 lj_err_argt(L, narg, LUA_TFUNCTION);
218 return funcV(o);
219 }
220
lj_lib_checktab(lua_State * L,int narg)221 GCtab *lj_lib_checktab(lua_State *L, int narg)
222 {
223 TValue *o = L->base + narg-1;
224 if (!(o < L->top && tvistab(o)))
225 lj_err_argt(L, narg, LUA_TTABLE);
226 return tabV(o);
227 }
228
lj_lib_checktabornil(lua_State * L,int narg)229 GCtab *lj_lib_checktabornil(lua_State *L, int narg)
230 {
231 TValue *o = L->base + narg-1;
232 if (o < L->top) {
233 if (tvistab(o))
234 return tabV(o);
235 else if (tvisnil(o))
236 return NULL;
237 }
238 lj_err_arg(L, narg, LJ_ERR_NOTABN);
239 return NULL; /* unreachable */
240 }
241
lj_lib_checkopt(lua_State * L,int narg,int def,const char * lst)242 int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst)
243 {
244 GCstr *s = def >= 0 ? lj_lib_optstr(L, narg) : lj_lib_checkstr(L, narg);
245 if (s) {
246 const char *opt = strdata(s);
247 MSize len = s->len;
248 int i;
249 for (i = 0; *(const uint8_t *)lst; i++) {
250 if (*(const uint8_t *)lst == len && memcmp(opt, lst+1, len) == 0)
251 return i;
252 lst += 1+*(const uint8_t *)lst;
253 }
254 lj_err_argv(L, narg, LJ_ERR_INVOPTM, opt);
255 }
256 return def;
257 }
258
259