diff options
Diffstat (limited to '')
-rw-r--r-- | src/lj_lib.c | 75 |
1 files changed, 60 insertions, 15 deletions
diff --git a/src/lj_lib.c b/src/lj_lib.c index 45ea5d05..8bdf6912 100644 --- a/src/lj_lib.c +++ b/src/lj_lib.c | |||
@@ -18,6 +18,9 @@ | |||
18 | #include "lj_dispatch.h" | 18 | #include "lj_dispatch.h" |
19 | #include "lj_vm.h" | 19 | #include "lj_vm.h" |
20 | #include "lj_strscan.h" | 20 | #include "lj_strscan.h" |
21 | #include "lj_strfmt.h" | ||
22 | #include "lj_lex.h" | ||
23 | #include "lj_bcdump.h" | ||
21 | #include "lj_lib.h" | 24 | #include "lj_lib.h" |
22 | 25 | ||
23 | /* -- Library initialization ---------------------------------------------- */ | 26 | /* -- Library initialization ---------------------------------------------- */ |
@@ -43,6 +46,28 @@ static GCtab *lib_create_table(lua_State *L, const char *libname, int hsize) | |||
43 | return tabV(L->top-1); | 46 | return tabV(L->top-1); |
44 | } | 47 | } |
45 | 48 | ||
49 | static const uint8_t *lib_read_lfunc(lua_State *L, const uint8_t *p, GCtab *tab) | ||
50 | { | ||
51 | int len = *p++; | ||
52 | GCstr *name = lj_str_new(L, (const char *)p, len); | ||
53 | LexState ls; | ||
54 | GCproto *pt; | ||
55 | GCfunc *fn; | ||
56 | memset(&ls, 0, sizeof(ls)); | ||
57 | ls.L = L; | ||
58 | ls.p = (const char *)(p+len); | ||
59 | ls.pe = (const char *)~(uintptr_t)0; | ||
60 | ls.c = -1; | ||
61 | ls.level = (BCDUMP_F_STRIP|(LJ_BE*BCDUMP_F_BE)); | ||
62 | ls.chunkname = name; | ||
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; | ||
69 | } | ||
70 | |||
46 | void lj_lib_register(lua_State *L, const char *libname, | 71 | void lj_lib_register(lua_State *L, const char *libname, |
47 | const uint8_t *p, const lua_CFunction *cf) | 72 | const uint8_t *p, const lua_CFunction *cf) |
48 | { | 73 | { |
@@ -87,6 +112,9 @@ void lj_lib_register(lua_State *L, const char *libname, | |||
87 | ofn = fn; | 112 | ofn = fn; |
88 | } else { | 113 | } else { |
89 | switch (tag | len) { | 114 | switch (tag | len) { |
115 | case LIBINIT_LUA: | ||
116 | p = lib_read_lfunc(L, p, tab); | ||
117 | break; | ||
90 | case LIBINIT_SET: | 118 | case LIBINIT_SET: |
91 | L->top -= 2; | 119 | L->top -= 2; |
92 | if (tvisstr(L->top+1) && strV(L->top+1)->len == 0) | 120 | if (tvisstr(L->top+1) && strV(L->top+1)->len == 0) |
@@ -120,6 +148,37 @@ void lj_lib_register(lua_State *L, const char *libname, | |||
120 | } | 148 | } |
121 | } | 149 | } |
122 | 150 | ||
151 | /* Push internal function on the stack. */ | ||
152 | GCfunc *lj_lib_pushcc(lua_State *L, lua_CFunction f, int id, int n) | ||
153 | { | ||
154 | GCfunc *fn; | ||
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); | ||
159 | return fn; | ||
160 | } | ||
161 | |||
162 | void lj_lib_prereg(lua_State *L, const char *name, lua_CFunction f, GCtab *env) | ||
163 | { | ||
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); | ||
169 | L->top--; | ||
170 | } | ||
171 | |||
172 | int lj_lib_postreg(lua_State *L, lua_CFunction cf, int id, const char *name) | ||
173 | { | ||
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); | ||
179 | return 1; | ||
180 | } | ||
181 | |||
123 | /* -- Type checks --------------------------------------------------------- */ | 182 | /* -- Type checks --------------------------------------------------------- */ |
124 | 183 | ||
125 | TValue *lj_lib_checkany(lua_State *L, int narg) | 184 | TValue *lj_lib_checkany(lua_State *L, int narg) |
@@ -137,7 +196,7 @@ GCstr *lj_lib_checkstr(lua_State *L, int narg) | |||
137 | if (LJ_LIKELY(tvisstr(o))) { | 196 | if (LJ_LIKELY(tvisstr(o))) { |
138 | return strV(o); | 197 | return strV(o); |
139 | } else if (tvisnumber(o)) { | 198 | } else if (tvisnumber(o)) { |
140 | GCstr *s = lj_str_fromnumber(L, o); | 199 | GCstr *s = lj_strfmt_number(L, o); |
141 | setstrV(L, o, s); | 200 | setstrV(L, o, s); |
142 | return s; | 201 | return s; |
143 | } | 202 | } |
@@ -196,20 +255,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; | 255 | return (o < L->top && !tvisnil(o)) ? lj_lib_checkint(L, narg) : def; |
197 | } | 256 | } |
198 | 257 | ||
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) | 258 | GCfunc *lj_lib_checkfunc(lua_State *L, int narg) |
214 | { | 259 | { |
215 | TValue *o = L->base + narg-1; | 260 | TValue *o = L->base + narg-1; |