summaryrefslogtreecommitdiff
path: root/src/lib_aux.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib_aux.c')
-rw-r--r--src/lib_aux.c438
1 files changed, 438 insertions, 0 deletions
diff --git a/src/lib_aux.c b/src/lib_aux.c
new file mode 100644
index 00000000..1ae32dbc
--- /dev/null
+++ b/src/lib_aux.c
@@ -0,0 +1,438 @@
1/*
2** Auxiliary library for the Lua/C API.
3** Copyright (C) 2005-2009 Mike Pall. See Copyright Notice in luajit.h
4**
5** Major parts taken verbatim or adapted from the Lua interpreter.
6** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h
7*/
8
9#include <errno.h>
10#include <stdarg.h>
11#include <stdio.h>
12
13#define lib_aux_c
14#define LUA_LIB
15
16#include "lua.h"
17#include "lauxlib.h"
18
19#include "lj_obj.h"
20#include "lj_err.h"
21#include "lj_lib.h"
22
23/* convert a stack index to positive */
24#define abs_index(L, i) \
25 ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
26
27/* -- Type checks --------------------------------------------------------- */
28
29LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg)
30{
31 if (!lua_checkstack(L, size))
32 lj_err_callerv(L, LJ_ERR_STKOVM, msg);
33}
34
35LUALIB_API void luaL_checktype(lua_State *L, int narg, int tt)
36{
37 if (lua_type(L, narg) != tt)
38 lj_err_argt(L, narg, tt);
39}
40
41LUALIB_API void luaL_checkany(lua_State *L, int narg)
42{
43 lj_lib_checkany(L, narg);
44}
45
46LUALIB_API const char *luaL_checklstring(lua_State *L, int narg, size_t *len)
47{
48 GCstr *s = lj_lib_checkstr(L, narg);
49 if (len != NULL) *len = s->len;
50 return strdata(s);
51}
52
53LUALIB_API const char *luaL_optlstring(lua_State *L, int narg,
54 const char *def, size_t *len)
55{
56 GCstr *s = lj_lib_optstr(L, narg);
57 if (s) {
58 if (len != NULL) *len = s->len;
59 return strdata(s);
60 }
61 if (len != NULL) *len = def ? strlen(def) : 0;
62 return def;
63}
64
65LUALIB_API lua_Number luaL_checknumber(lua_State *L, int narg)
66{
67 return lj_lib_checknum(L, narg);
68}
69
70LUALIB_API lua_Number luaL_optnumber(lua_State *L, int narg, lua_Number def)
71{
72 lj_lib_opt(L, narg,
73 return lj_lib_checknum(L, narg);
74 ,
75 return def;
76 )
77}
78
79LUALIB_API lua_Integer luaL_checkinteger(lua_State *L, int narg)
80{
81#if LJ_64
82 return (lua_Integer)lj_lib_checknum(L, narg);
83#else
84 return lj_lib_checkint(L, narg);
85#endif
86}
87
88LUALIB_API lua_Integer luaL_optinteger(lua_State *L, int narg, lua_Integer def)
89{
90#if LJ_64
91 lj_lib_opt(L, narg,
92 return (lua_Integer)lj_lib_checknum(L, narg);
93 ,
94 return def;
95 )
96#else
97 return lj_lib_optint(L, narg, def);
98#endif
99}
100
101LUALIB_API int luaL_checkoption(lua_State *L, int narg, const char *def,
102 const char *const lst[])
103{
104 GCstr *s = lj_lib_optstr(L, narg);
105 const char *opt = s ? strdata(s) : def;
106 uint32_t i;
107 if (!opt) lj_err_argt(L, narg, LUA_TSTRING);
108 for (i = 0; lst[i]; i++)
109 if (strcmp(lst[i], opt) == 0)
110 return (int)i;
111 lj_err_argv(L, narg, LJ_ERR_INVOPTM, opt);
112}
113
114/* -- Module registration ------------------------------------------------- */
115
116LUALIB_API const char *luaL_findtable(lua_State *L, int idx,
117 const char *fname, int szhint)
118{
119 const char *e;
120 lua_pushvalue(L, idx);
121 do {
122 e = strchr(fname, '.');
123 if (e == NULL) e = fname + strlen(fname);
124 lua_pushlstring(L, fname, (size_t)(e - fname));
125 lua_rawget(L, -2);
126 if (lua_isnil(L, -1)) { /* no such field? */
127 lua_pop(L, 1); /* remove this nil */
128 lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
129 lua_pushlstring(L, fname, (size_t)(e - fname));
130 lua_pushvalue(L, -2);
131 lua_settable(L, -4); /* set new table into field */
132 } else if (!lua_istable(L, -1)) { /* field has a non-table value? */
133 lua_pop(L, 2); /* remove table and value */
134 return fname; /* return problematic part of the name */
135 }
136 lua_remove(L, -2); /* remove previous table */
137 fname = e + 1;
138 } while (*e == '.');
139 return NULL;
140}
141
142static int libsize(const luaL_Reg *l)
143{
144 int size = 0;
145 for (; l->name; l++) size++;
146 return size;
147}
148
149LUALIB_API void luaL_openlib(lua_State *L, const char *libname,
150 const luaL_Reg *l, int nup)
151{
152 if (libname) {
153 int size = libsize(l);
154 /* check whether lib already exists */
155 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
156 lua_getfield(L, -1, libname); /* get _LOADED[libname] */
157 if (!lua_istable(L, -1)) { /* not found? */
158 lua_pop(L, 1); /* remove previous result */
159 /* try global variable (and create one if it does not exist) */
160 if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
161 lj_err_callerv(L, LJ_ERR_BADMODN, libname);
162 lua_pushvalue(L, -1);
163 lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
164 }
165 lua_remove(L, -2); /* remove _LOADED table */
166 lua_insert(L, -(nup+1)); /* move library table to below upvalues */
167 }
168 for (; l->name; l++) {
169 int i;
170 for (i = 0; i < nup; i++) /* copy upvalues to the top */
171 lua_pushvalue(L, -nup);
172 lua_pushcclosure(L, l->func, nup);
173 lua_setfield(L, -(nup+2), l->name);
174 }
175 lua_pop(L, nup); /* remove upvalues */
176}
177
178LUALIB_API void luaL_register(lua_State *L, const char *libname,
179 const luaL_Reg *l)
180{
181 luaL_openlib(L, libname, l, 0);
182}
183
184LUALIB_API const char *luaL_gsub(lua_State *L, const char *s,
185 const char *p, const char *r)
186{
187 const char *wild;
188 size_t l = strlen(p);
189 luaL_Buffer b;
190 luaL_buffinit(L, &b);
191 while ((wild = strstr(s, p)) != NULL) {
192 luaL_addlstring(&b, s, (size_t)(wild - s)); /* push prefix */
193 luaL_addstring(&b, r); /* push replacement in place of pattern */
194 s = wild + l; /* continue after `p' */
195 }
196 luaL_addstring(&b, s); /* push last suffix */
197 luaL_pushresult(&b);
198 return lua_tostring(L, -1);
199}
200
201/* -- Buffer handling ----------------------------------------------------- */
202
203#define bufflen(B) ((size_t)((B)->p - (B)->buffer))
204#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
205
206static int emptybuffer(luaL_Buffer *B)
207{
208 size_t l = bufflen(B);
209 if (l == 0)
210 return 0; /* put nothing on stack */
211 lua_pushlstring(B->L, B->buffer, l);
212 B->p = B->buffer;
213 B->lvl++;
214 return 1;
215}
216
217static void adjuststack(luaL_Buffer *B)
218{
219 if (B->lvl > 1) {
220 lua_State *L = B->L;
221 int toget = 1; /* number of levels to concat */
222 size_t toplen = lua_strlen(L, -1);
223 do {
224 size_t l = lua_strlen(L, -(toget+1));
225 if (!(B->lvl - toget + 1 >= LUA_MINSTACK/2 || toplen > l))
226 break;
227 toplen += l;
228 toget++;
229 } while (toget < B->lvl);
230 lua_concat(L, toget);
231 B->lvl = B->lvl - toget + 1;
232 }
233}
234
235LUALIB_API char *luaL_prepbuffer(luaL_Buffer *B)
236{
237 if (emptybuffer(B))
238 adjuststack(B);
239 return B->buffer;
240}
241
242LUALIB_API void luaL_addlstring(luaL_Buffer *B, const char *s, size_t l)
243{
244 while (l--)
245 luaL_addchar(B, *s++);
246}
247
248LUALIB_API void luaL_addstring(luaL_Buffer *B, const char *s)
249{
250 luaL_addlstring(B, s, strlen(s));
251}
252
253LUALIB_API void luaL_pushresult(luaL_Buffer *B)
254{
255 emptybuffer(B);
256 lua_concat(B->L, B->lvl);
257 B->lvl = 1;
258}
259
260LUALIB_API void luaL_addvalue(luaL_Buffer *B)
261{
262 lua_State *L = B->L;
263 size_t vl;
264 const char *s = lua_tolstring(L, -1, &vl);
265 if (vl <= bufffree(B)) { /* fit into buffer? */
266 memcpy(B->p, s, vl); /* put it there */
267 B->p += vl;
268 lua_pop(L, 1); /* remove from stack */
269 } else {
270 if (emptybuffer(B))
271 lua_insert(L, -2); /* put buffer before new value */
272 B->lvl++; /* add new value into B stack */
273 adjuststack(B);
274 }
275}
276
277LUALIB_API void luaL_buffinit(lua_State *L, luaL_Buffer *B)
278{
279 B->L = L;
280 B->p = B->buffer;
281 B->lvl = 0;
282}
283
284/* -- Reference management ------------------------------------------------ */
285
286#define FREELIST_REF 0
287
288LUALIB_API int luaL_ref(lua_State *L, int t)
289{
290 int ref;
291 t = abs_index(L, t);
292 if (lua_isnil(L, -1)) {
293 lua_pop(L, 1); /* remove from stack */
294 return LUA_REFNIL; /* `nil' has a unique fixed reference */
295 }
296 lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
297 ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */
298 lua_pop(L, 1); /* remove it from stack */
299 if (ref != 0) { /* any free element? */
300 lua_rawgeti(L, t, ref); /* remove it from list */
301 lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */
302 } else { /* no free elements */
303 ref = (int)lua_objlen(L, t);
304 ref++; /* create new reference */
305 }
306 lua_rawseti(L, t, ref);
307 return ref;
308}
309
310LUALIB_API void luaL_unref(lua_State *L, int t, int ref)
311{
312 if (ref >= 0) {
313 t = abs_index(L, t);
314 lua_rawgeti(L, t, FREELIST_REF);
315 lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */
316 lua_pushinteger(L, ref);
317 lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
318 }
319}
320
321/* -- Load Lua code ------------------------------------------------------- */
322
323typedef struct FileReaderCtx {
324 FILE *fp;
325 char buf[LUAL_BUFFERSIZE];
326} FileReaderCtx;
327
328static const char *reader_file(lua_State *L, void *ud, size_t *size)
329{
330 FileReaderCtx *ctx = (FileReaderCtx *)ud;
331 UNUSED(L);
332 if (feof(ctx->fp)) return NULL;
333 *size = fread(ctx->buf, 1, sizeof(ctx->buf), ctx->fp);
334 return *size > 0 ? ctx->buf : NULL;
335}
336
337LUALIB_API int luaL_loadfile(lua_State *L, const char *filename)
338{
339 FileReaderCtx ctx;
340 int status;
341 const char *chunkname;
342 if (filename) {
343 ctx.fp = fopen(filename, "r");
344 if (ctx.fp == NULL) {
345 lua_pushfstring(L, "cannot open %s: %s", filename, strerror(errno));
346 return LUA_ERRFILE;
347 }
348 chunkname = lua_pushfstring(L, "@%s", filename);
349 } else {
350 ctx.fp = stdin;
351 chunkname = "=stdin";
352 }
353 status = lua_load(L, reader_file, &ctx, chunkname);
354 if (ferror(ctx.fp)) {
355 L->top -= filename ? 2 : 1;
356 lua_pushfstring(L, "cannot read %s: %s", chunkname+1, strerror(errno));
357 if (filename)
358 fclose(ctx.fp);
359 return LUA_ERRFILE;
360 }
361 if (filename) {
362 L->top--;
363 copyTV(L, L->top-1, L->top);
364 fclose(ctx.fp);
365 }
366 return status;
367}
368
369typedef struct StringReaderCtx {
370 const char *str;
371 size_t size;
372} StringReaderCtx;
373
374static const char *reader_string(lua_State *L, void *ud, size_t *size)
375{
376 StringReaderCtx *ctx = (StringReaderCtx *)ud;
377 UNUSED(L);
378 if (ctx->size == 0) return NULL;
379 *size = ctx->size;
380 ctx->size = 0;
381 return ctx->str;
382}
383
384LUALIB_API int luaL_loadbuffer(lua_State *L, const char *buf, size_t size,
385 const char *name)
386{
387 StringReaderCtx ctx;
388 ctx.str = buf;
389 ctx.size = size;
390 return lua_load(L, reader_string, &ctx, name);
391}
392
393LUALIB_API int luaL_loadstring(lua_State *L, const char *s)
394{
395 return luaL_loadbuffer(L, s, strlen(s), s);
396}
397
398/* -- Default allocator and panic function -------------------------------- */
399
400#ifdef LUAJIT_USE_SYSMALLOC
401
402static void *mem_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
403{
404 (void)ud;
405 (void)osize;
406 if (nsize == 0) {
407 free(ptr);
408 return NULL;
409 } else {
410 return realloc(ptr, nsize);
411 }
412}
413
414#define mem_create() NULL
415
416#else
417
418#include "lj_alloc.h"
419
420#define mem_alloc lj_alloc_f
421#define mem_create lj_alloc_create
422
423#endif
424
425static int panic(lua_State *L)
426{
427 fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
428 lua_tostring(L, -1));
429 return 0;
430}
431
432LUALIB_API lua_State *luaL_newstate(void)
433{
434 lua_State *L = lua_newstate(mem_alloc, mem_create());
435 if (L) G(L)->panic = panic;
436 return L;
437}
438