aboutsummaryrefslogtreecommitdiff
path: root/src/lj_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_lib.c')
-rw-r--r--src/lj_lib.c131
1 files changed, 116 insertions, 15 deletions
diff --git a/src/lj_lib.c b/src/lj_lib.c
index 5796766a..82a9e256 100644
--- a/src/lj_lib.c
+++ b/src/lj_lib.c
@@ -16,8 +16,14 @@
16#include "lj_func.h" 16#include "lj_func.h"
17#include "lj_bc.h" 17#include "lj_bc.h"
18#include "lj_dispatch.h" 18#include "lj_dispatch.h"
19#if LJ_HASFFI
20#include "lj_ctype.h"
21#endif
19#include "lj_vm.h" 22#include "lj_vm.h"
20#include "lj_strscan.h" 23#include "lj_strscan.h"
24#include "lj_strfmt.h"
25#include "lj_lex.h"
26#include "lj_bcdump.h"
21#include "lj_lib.h" 27#include "lj_lib.h"
22 28
23/* -- Library initialization ---------------------------------------------- */ 29/* -- Library initialization ---------------------------------------------- */
@@ -43,6 +49,28 @@ static GCtab *lib_create_table(lua_State *L, const char *libname, int hsize)
43 return tabV(L->top-1); 49 return tabV(L->top-1);
44} 50}
45 51
52static const uint8_t *lib_read_lfunc(lua_State *L, const uint8_t *p, GCtab *tab)
53{
54 int len = *p++;
55 GCstr *name = lj_str_new(L, (const char *)p, len);
56 LexState ls;
57 GCproto *pt;
58 GCfunc *fn;
59 memset(&ls, 0, sizeof(ls));
60 ls.L = L;
61 ls.p = (const char *)(p+len);
62 ls.pe = (const char *)~(uintptr_t)0;
63 ls.c = -1;
64 ls.level = (BCDUMP_F_STRIP|(LJ_BE*BCDUMP_F_BE));
65 ls.chunkname = name;
66 pt = lj_bcread_proto(&ls);
67 pt->firstline = ~(BCLine)0;
68 fn = lj_func_newL_empty(L, pt, tabref(L->env));
69 /* NOBARRIER: See below for common barrier. */
70 setfuncV(L, lj_tab_setstr(L, tab, name), fn);
71 return (const uint8_t *)ls.p;
72}
73
46void lj_lib_register(lua_State *L, const char *libname, 74void lj_lib_register(lua_State *L, const char *libname,
47 const uint8_t *p, const lua_CFunction *cf) 75 const uint8_t *p, const lua_CFunction *cf)
48{ 76{
@@ -87,6 +115,9 @@ void lj_lib_register(lua_State *L, const char *libname,
87 ofn = fn; 115 ofn = fn;
88 } else { 116 } else {
89 switch (tag | len) { 117 switch (tag | len) {
118 case LIBINIT_LUA:
119 p = lib_read_lfunc(L, p, tab);
120 break;
90 case LIBINIT_SET: 121 case LIBINIT_SET:
91 L->top -= 2; 122 L->top -= 2;
92 if (tvisstr(L->top+1) && strV(L->top+1)->len == 0) 123 if (tvisstr(L->top+1) && strV(L->top+1)->len == 0)
@@ -120,6 +151,37 @@ void lj_lib_register(lua_State *L, const char *libname,
120 } 151 }
121} 152}
122 153
154/* Push internal function on the stack. */
155GCfunc *lj_lib_pushcc(lua_State *L, lua_CFunction f, int id, int n)
156{
157 GCfunc *fn;
158 lua_pushcclosure(L, f, n);
159 fn = funcV(L->top-1);
160 fn->c.ffid = (uint8_t)id;
161 setmref(fn->c.pc, &G(L)->bc_cfunc_int);
162 return fn;
163}
164
165void lj_lib_prereg(lua_State *L, const char *name, lua_CFunction f, GCtab *env)
166{
167 luaL_findtable(L, LUA_REGISTRYINDEX, "_PRELOAD", 4);
168 lua_pushcfunction(L, f);
169 /* NOBARRIER: The function is new (marked white). */
170 setgcref(funcV(L->top-1)->c.env, obj2gco(env));
171 lua_setfield(L, -2, name);
172 L->top--;
173}
174
175int lj_lib_postreg(lua_State *L, lua_CFunction cf, int id, const char *name)
176{
177 GCfunc *fn = lj_lib_pushcf(L, cf, id);
178 GCtab *t = tabref(curr_func(L)->c.env); /* Reference to parent table. */
179 setfuncV(L, lj_tab_setstr(L, t, lj_str_newz(L, name)), fn);
180 lj_gc_anybarriert(L, t);
181 setfuncV(L, L->top++, fn);
182 return 1;
183}
184
123/* -- Type checks --------------------------------------------------------- */ 185/* -- Type checks --------------------------------------------------------- */
124 186
125TValue *lj_lib_checkany(lua_State *L, int narg) 187TValue *lj_lib_checkany(lua_State *L, int narg)
@@ -137,7 +199,7 @@ GCstr *lj_lib_checkstr(lua_State *L, int narg)
137 if (LJ_LIKELY(tvisstr(o))) { 199 if (LJ_LIKELY(tvisstr(o))) {
138 return strV(o); 200 return strV(o);
139 } else if (tvisnumber(o)) { 201 } else if (tvisnumber(o)) {
140 GCstr *s = lj_str_fromnumber(L, o); 202 GCstr *s = lj_strfmt_number(L, o);
141 setstrV(L, o, s); 203 setstrV(L, o, s);
142 return s; 204 return s;
143 } 205 }
@@ -196,20 +258,6 @@ int32_t lj_lib_optint(lua_State *L, int narg, int32_t def)
196 return (o < L->top && !tvisnil(o)) ? lj_lib_checkint(L, narg) : def; 258 return (o < L->top && !tvisnil(o)) ? lj_lib_checkint(L, narg) : def;
197} 259}
198 260
199int32_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
213GCfunc *lj_lib_checkfunc(lua_State *L, int narg) 261GCfunc *lj_lib_checkfunc(lua_State *L, int narg)
214{ 262{
215 TValue *o = L->base + narg-1; 263 TValue *o = L->base + narg-1;
@@ -256,3 +304,56 @@ int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst)
256 return def; 304 return def;
257} 305}
258 306
307/* -- Strict type checks -------------------------------------------------- */
308
309/* The following type checks do not coerce between strings and numbers.
310** And they handle plain int64_t/uint64_t FFI numbers, too.
311*/
312
313#if LJ_HASBUFFER
314GCstr *lj_lib_checkstrx(lua_State *L, int narg)
315{
316 TValue *o = L->base + narg-1;
317 if (!(o < L->top && tvisstr(o))) lj_err_argt(L, narg, LUA_TSTRING);
318 return strV(o);
319}
320
321int32_t lj_lib_checkintrange(lua_State *L, int narg, int32_t a, int32_t b)
322{
323 TValue *o = L->base + narg-1;
324 lj_assertL(b >= 0, "expected range must be non-negative");
325 if (o < L->top) {
326 if (LJ_LIKELY(tvisint(o))) {
327 int32_t i = intV(o);
328 if (i >= a && i <= b) return i;
329 } else if (LJ_LIKELY(tvisnum(o))) {
330 /* For performance reasons, this doesn't check for integerness or
331 ** integer overflow. Overflow detection still works, since all FPUs
332 ** return either MININT or MAXINT, which is then out of range.
333 */
334 int32_t i = (int32_t)numV(o);
335 if (i >= a && i <= b) return i;
336#if LJ_HASFFI
337 } else if (tviscdata(o)) {
338 GCcdata *cd = cdataV(o);
339 if (cd->ctypeid == CTID_INT64) {
340 int64_t i = *(int64_t *)cdataptr(cd);
341 if (i >= (int64_t)a && i <= (int64_t)b) return (int32_t)i;
342 } else if (cd->ctypeid == CTID_UINT64) {
343 uint64_t i = *(uint64_t *)cdataptr(cd);
344 if ((a < 0 || i >= (uint64_t)a) && i <= (uint64_t)b) return (int32_t)i;
345 } else {
346 goto badtype;
347 }
348#endif
349 } else {
350 goto badtype;
351 }
352 lj_err_arg(L, narg, LJ_ERR_NUMRNG);
353 }
354badtype:
355 lj_err_argt(L, narg, LUA_TNUMBER);
356 return 0; /* unreachable */
357}
358#endif
359