2 ** Library function support.
3 ** Copyright (C) 2005-2014 Mike Pall. See Copyright Notice in luajit.h
18 #include "lj_dispatch.h"
20 #include "lj_strscan.h"
21 #include "lj_strfmt.h"
23 #include "lj_bcdump.h"
26 /* -- Library initialization ---------------------------------------------- */
28 static GCtab
*lib_create_table(lua_State
*L
, const char *libname
, int hsize
)
31 luaL_findtable(L
, LUA_REGISTRYINDEX
, "_LOADED", 16);
32 lua_getfield(L
, -1, libname
);
33 if (!tvistab(L
->top
-1)) {
35 if (luaL_findtable(L
, LUA_GLOBALSINDEX
, libname
, hsize
) != NULL
)
36 lj_err_callerv(L
, LJ_ERR_BADMODN
, libname
);
37 settabV(L
, L
->top
, tabV(L
->top
-1));
39 lua_setfield(L
, -3, libname
); /* _LOADED[libname] = new table */
42 settabV(L
, L
->top
-1, tabV(L
->top
));
44 lua_createtable(L
, 0, hsize
);
46 return tabV(L
->top
-1);
49 static const uint8_t *lib_read_lfunc(lua_State
*L
, const uint8_t *p
, GCtab
*tab
)
52 GCstr
*name
= lj_str_new(L
, (const char *)p
, len
);
56 memset(&ls
, 0, sizeof(ls
));
58 ls
.p
= (const char *)(p
+len
);
59 ls
.pe
= (const char *)~(uintptr_t)0;
61 ls
.level
= (BCDUMP_F_STRIP
|(LJ_BE
*BCDUMP_F_BE
));
63 pt
= lj_bcread_proto(&ls
);
64 pt
->firstline
= ~(BCLine
)0;
65 fn
= lj_func_newL_empty(L
, pt
, tabref(L
->env
));
66 /* NOBARRIER: See below for common barrier. */
67 setfuncV(L
, lj_tab_setstr(L
, tab
, name
), fn
);
68 return (const uint8_t *)ls
.p
;
71 void lj_lib_register(lua_State
*L
, const char *libname
,
72 const uint8_t *p
, const lua_CFunction
*cf
)
74 GCtab
*env
= tabref(L
->env
);
77 BCIns
*bcff
= &L2GG(L
)->bcff
[*p
++];
78 GCtab
*tab
= lib_create_table(L
, libname
, *p
++);
79 ptrdiff_t tpos
= L
->top
- L
->base
;
81 /* Avoid barriers further down. */
82 lj_gc_anybarriert(L
, tab
);
87 MSize len
= tag
& LIBINIT_LENMASK
;
88 tag
&= LIBINIT_TAGMASK
;
89 if (tag
!= LIBINIT_STRING
) {
91 MSize nuv
= (MSize
)(L
->top
- L
->base
- tpos
);
92 GCfunc
*fn
= lj_func_newC(L
, nuv
, env
);
94 L
->top
= L
->base
+ tpos
;
95 memcpy(fn
->c
.upvalue
, L
->top
, sizeof(TValue
)*nuv
);
97 fn
->c
.ffid
= (uint8_t)(ffid
++);
98 name
= (const char *)p
;
100 if (tag
== LIBINIT_CF
)
101 setmref(fn
->c
.pc
, &G(L
)->bc_cfunc_int
);
103 setmref(fn
->c
.pc
, bcff
++);
104 if (tag
== LIBINIT_ASM_
)
105 fn
->c
.f
= ofn
->c
.f
; /* Copy handler from previous function. */
107 fn
->c
.f
= *cf
++; /* Get cf or handler from C function table. */
109 /* NOBARRIER: See above for common barrier. */
110 setfuncV(L
, lj_tab_setstr(L
, tab
, lj_str_new(L
, name
, len
)), fn
);
116 p
= lib_read_lfunc(L
, p
, tab
);
120 if (tvisstr(L
->top
+1) && strV(L
->top
+1)->len
== 0)
122 else /* NOBARRIER: See above for common barrier. */
123 copyTV(L
, lj_tab_set(L
, tab
, L
->top
+1), L
->top
);
126 memcpy(&L
->top
->n
, p
, sizeof(double));
131 copyTV(L
, L
->top
, L
->top
- *p
++);
135 setfuncV(L
, L
->top
++, ofn
);
143 setstrV(L
, L
->top
++, lj_str_new(L
, (const char *)p
, len
));
151 /* Push internal function on the stack. */
152 GCfunc
*lj_lib_pushcc(lua_State
*L
, lua_CFunction f
, int id
, int n
)
155 lua_pushcclosure(L
, f
, n
);
156 fn
= funcV(L
->top
-1);
157 fn
->c
.ffid
= (uint8_t)id
;
158 setmref(fn
->c
.pc
, &G(L
)->bc_cfunc_int
);
162 void lj_lib_prereg(lua_State
*L
, const char *name
, lua_CFunction f
, GCtab
*env
)
164 luaL_findtable(L
, LUA_REGISTRYINDEX
, "_PRELOAD", 4);
165 lua_pushcfunction(L
, f
);
166 /* NOBARRIER: The function is new (marked white). */
167 setgcref(funcV(L
->top
-1)->c
.env
, obj2gco(env
));
168 lua_setfield(L
, -2, name
);
172 int lj_lib_postreg(lua_State
*L
, lua_CFunction cf
, int id
, const char *name
)
174 GCfunc
*fn
= lj_lib_pushcf(L
, cf
, id
);
175 GCtab
*t
= tabref(curr_func(L
)->c
.env
); /* Reference to parent table. */
176 setfuncV(L
, lj_tab_setstr(L
, t
, lj_str_newz(L
, name
)), fn
);
177 lj_gc_anybarriert(L
, t
);
178 setfuncV(L
, L
->top
++, fn
);
182 /* -- Type checks --------------------------------------------------------- */
184 TValue
*lj_lib_checkany(lua_State
*L
, int narg
)
186 TValue
*o
= L
->base
+ narg
-1;
188 lj_err_arg(L
, narg
, LJ_ERR_NOVAL
);
192 GCstr
*lj_lib_checkstr(lua_State
*L
, int narg
)
194 TValue
*o
= L
->base
+ narg
-1;
196 if (LJ_LIKELY(tvisstr(o
))) {
198 } else if (tvisnumber(o
)) {
199 GCstr
*s
= lj_strfmt_number(L
, o
);
204 lj_err_argt(L
, narg
, LUA_TSTRING
);
205 return NULL
; /* unreachable */
208 GCstr
*lj_lib_optstr(lua_State
*L
, int narg
)
210 TValue
*o
= L
->base
+ narg
-1;
211 return (o
< L
->top
&& !tvisnil(o
)) ? lj_lib_checkstr(L
, narg
) : NULL
;
215 void lj_lib_checknumber(lua_State
*L
, int narg
)
217 TValue
*o
= L
->base
+ narg
-1;
218 if (!(o
< L
->top
&& lj_strscan_numberobj(o
)))
219 lj_err_argt(L
, narg
, LUA_TNUMBER
);
223 lua_Number
lj_lib_checknum(lua_State
*L
, int narg
)
225 TValue
*o
= L
->base
+ narg
-1;
227 (tvisnumber(o
) || (tvisstr(o
) && lj_strscan_num(strV(o
), o
)))))
228 lj_err_argt(L
, narg
, LUA_TNUMBER
);
229 if (LJ_UNLIKELY(tvisint(o
))) {
230 lua_Number n
= (lua_Number
)intV(o
);
238 int32_t lj_lib_checkint(lua_State
*L
, int narg
)
240 TValue
*o
= L
->base
+ narg
-1;
241 if (!(o
< L
->top
&& lj_strscan_numberobj(o
)))
242 lj_err_argt(L
, narg
, LUA_TNUMBER
);
243 if (LJ_LIKELY(tvisint(o
))) {
246 int32_t i
= lj_num2int(numV(o
));
247 if (LJ_DUALNUM
) setintV(o
, i
);
252 int32_t lj_lib_optint(lua_State
*L
, int narg
, int32_t def
)
254 TValue
*o
= L
->base
+ narg
-1;
255 return (o
< L
->top
&& !tvisnil(o
)) ? lj_lib_checkint(L
, narg
) : def
;
258 GCfunc
*lj_lib_checkfunc(lua_State
*L
, int narg
)
260 TValue
*o
= L
->base
+ narg
-1;
261 if (!(o
< L
->top
&& tvisfunc(o
)))
262 lj_err_argt(L
, narg
, LUA_TFUNCTION
);
266 GCtab
*lj_lib_checktab(lua_State
*L
, int narg
)
268 TValue
*o
= L
->base
+ narg
-1;
269 if (!(o
< L
->top
&& tvistab(o
)))
270 lj_err_argt(L
, narg
, LUA_TTABLE
);
274 GCtab
*lj_lib_checktabornil(lua_State
*L
, int narg
)
276 TValue
*o
= L
->base
+ narg
-1;
283 lj_err_arg(L
, narg
, LJ_ERR_NOTABN
);
284 return NULL
; /* unreachable */
287 int lj_lib_checkopt(lua_State
*L
, int narg
, int def
, const char *lst
)
289 GCstr
*s
= def
>= 0 ? lj_lib_optstr(L
, narg
) : lj_lib_checkstr(L
, narg
);
291 const char *opt
= strdata(s
);
294 for (i
= 0; *(const uint8_t *)lst
; i
++) {
295 if (*(const uint8_t *)lst
== len
&& memcmp(opt
, lst
+1, len
) == 0)
297 lst
+= 1+*(const uint8_t *)lst
;
299 lj_err_argv(L
, narg
, LJ_ERR_INVOPTM
, opt
);