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 | |
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 | |
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 | |
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 | |
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 | |
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 |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |