summaryrefslogtreecommitdiff
path: root/src/lj_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_lib.c')
-rw-r--r--src/lj_lib.c216
1 files changed, 216 insertions, 0 deletions
diff --git a/src/lj_lib.c b/src/lj_lib.c
new file mode 100644
index 00000000..683c66d6
--- /dev/null
+++ b/src/lj_lib.c
@@ -0,0 +1,216 @@
1/*
2** Library function support.
3** Copyright (C) 2005-2009 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_vm.h"
18#include "lj_lib.h"
19
20/* -- Library initialization ---------------------------------------------- */
21
22static GCtab *lib_create_table(lua_State *L, const char *libname, int hsize)
23{
24 if (libname) {
25 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
26 lua_getfield(L, -1, libname);
27 if (!tvistab(L->top-1)) {
28 L->top--;
29 if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, hsize) != NULL)
30 lj_err_callerv(L, LJ_ERR_BADMODN, libname);
31 settabV(L, L->top, tabV(L->top-1));
32 L->top++;
33 lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
34 }
35 L->top--;
36 settabV(L, L->top-1, tabV(L->top));
37 } else {
38 lua_createtable(L, 0, hsize);
39 }
40 return tabV(L->top-1);
41}
42
43void lj_lib_register(lua_State *L, const char *libname,
44 const uint8_t *p, const lua_CFunction *cf)
45{
46 GCtab *env = tabref(L->env);
47 GCfunc *ofn = NULL;
48 int ffid = *p++;
49 GCtab *tab = lib_create_table(L, libname, *p++);
50 ptrdiff_t tpos = L->top - L->base;
51
52 /* Avoid barriers further down. */
53 if (isblack(obj2gco(tab))) lj_gc_barrierback(G(L), tab);
54 tab->nomm = 0;
55
56 for (;;) {
57 uint32_t tag = *p++;
58 MSize len = tag & LIBINIT_LENMASK;
59 tag &= LIBINIT_TAGMASK;
60 if (tag != LIBINIT_STRING) {
61 const char *name;
62 MSize nuv = (MSize)(L->top - L->base - tpos);
63 GCfunc *fn = lj_func_newC(L, nuv, env);
64 if (nuv) {
65 L->top = L->base + tpos;
66 memcpy(fn->c.upvalue, L->top, sizeof(TValue)*nuv);
67 }
68 fn->c.ffid = (uint8_t)(ffid++);
69 name = (const char *)p;
70 p += len;
71 if (tag != LIBINIT_CF) {
72 fn->c.gate = makeasmfunc(p[0] + (p[1] << 8));
73 p += 2;
74 }
75 if (tag == LIBINIT_ASM_)
76 fn->c.f = ofn->c.f; /* Copy handler from previous function. */
77 else
78 fn->c.f = *cf++; /* Get cf or handler from C function table. */
79 if (len) {
80 /* NOBARRIER: See above for common barrier. */
81 setfuncV(L, lj_tab_setstr(L, tab, lj_str_new(L, name, len)), fn);
82 }
83 ofn = fn;
84 } else {
85 switch (tag | len) {
86 case LIBINIT_SET:
87 L->top -= 2;
88 if (tvisstr(L->top+1) && strV(L->top+1)->len == 0)
89 env = tabV(L->top);
90 else /* NOBARRIER: See above for common barrier. */
91 copyTV(L, lj_tab_set(L, tab, L->top+1), L->top);
92 break;
93 case LIBINIT_NUMBER:
94 memcpy(&L->top->n, p, sizeof(double));
95 L->top++;
96 p += sizeof(double);
97 break;
98 case LIBINIT_COPY:
99 copyTV(L, L->top, L->top - *p++);
100 L->top++;
101 break;
102 case LIBINIT_LASTCL:
103 setfuncV(L, L->top++, ofn);
104 break;
105 case LIBINIT_FFID:
106 ffid++;
107 break;
108 case LIBINIT_END:
109 return;
110 default:
111 setstrV(L, L->top++, lj_str_new(L, (const char *)p, len));
112 p += len;
113 break;
114 }
115 }
116 }
117}
118
119/* -- Type checks --------------------------------------------------------- */
120
121TValue *lj_lib_checkany(lua_State *L, int narg)
122{
123 TValue *o = L->base + narg-1;
124 if (o >= L->top)
125 lj_err_arg(L, narg, LJ_ERR_NOVAL);
126 return o;
127}
128
129GCstr *lj_lib_checkstr(lua_State *L, int narg)
130{
131 TValue *o = L->base + narg-1;
132 if (o < L->top) {
133 if (LJ_LIKELY(tvisstr(o))) {
134 return strV(o);
135 } else if (tvisnum(o)) {
136 GCstr *s = lj_str_fromnum(L, &o->n);
137 setstrV(L, o, s);
138 return s;
139 }
140 }
141 lj_err_argt(L, narg, LUA_TSTRING);
142 return NULL; /* unreachable */
143}
144
145GCstr *lj_lib_optstr(lua_State *L, int narg)
146{
147 TValue *o = L->base + narg-1;
148 return (o < L->top && !tvisnil(o)) ? lj_lib_checkstr(L, narg) : NULL;
149}
150
151lua_Number lj_lib_checknum(lua_State *L, int narg)
152{
153 TValue *o = L->base + narg-1;
154 if (!(o < L->top &&
155 (tvisnum(o) || (tvisstr(o) && lj_str_numconv(strVdata(o), o)))))
156 lj_err_argt(L, narg, LUA_TNUMBER);
157 return numV(o);
158}
159
160int32_t lj_lib_checkint(lua_State *L, int narg)
161{
162 return lj_num2int(lj_lib_checknum(L, narg));
163}
164
165int32_t lj_lib_optint(lua_State *L, int narg, int32_t def)
166{
167 TValue *o = L->base + narg-1;
168 return (o < L->top && !tvisnil(o)) ? lj_lib_checkint(L, narg) : def;
169}
170
171GCfunc *lj_lib_checkfunc(lua_State *L, int narg)
172{
173 TValue *o = L->base + narg-1;
174 if (!(o < L->top && tvisfunc(o)))
175 lj_err_argt(L, narg, LUA_TFUNCTION);
176 return funcV(o);
177}
178
179GCtab *lj_lib_checktab(lua_State *L, int narg)
180{
181 TValue *o = L->base + narg-1;
182 if (!(o < L->top && tvistab(o)))
183 lj_err_argt(L, narg, LUA_TTABLE);
184 return tabV(o);
185}
186
187GCtab *lj_lib_checktabornil(lua_State *L, int narg)
188{
189 TValue *o = L->base + narg-1;
190 if (o < L->top) {
191 if (tvistab(o))
192 return tabV(o);
193 else if (tvisnil(o))
194 return NULL;
195 }
196 lj_err_arg(L, narg, LJ_ERR_NOTABN);
197 return NULL; /* unreachable */
198}
199
200int lj_lib_checkopt(lua_State *L, int narg, int def, const char *lst)
201{
202 GCstr *s = def >= 0 ? lj_lib_optstr(L, narg) : lj_lib_checkstr(L, narg);
203 if (s) {
204 const char *opt = strdata(s);
205 MSize len = s->len;
206 int i;
207 for (i = 0; *(const uint8_t *)lst; i++) {
208 if (*(const uint8_t *)lst == len && memcmp(opt, lst+1, len) == 0)
209 return i;
210 lst += 1+*(const uint8_t *)lst;
211 }
212 lj_err_argv(L, narg, LJ_ERR_INVOPTM, opt);
213 }
214 return def;
215}
216