Fix 32/64 bit portability issue with upval->v.
[luajit-2.0/celess22.git] / src / lib_aux.c
blob5f4e3e8c73f0a75b6838158cddcabeb8a4e6936c
1 /*
2 ** Auxiliary library for the Lua/C API.
3 ** Copyright (C) 2005-2010 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 */
9 #include <errno.h>
10 #include <stdarg.h>
11 #include <stdio.h>
13 #define lib_aux_c
14 #define LUA_LIB
16 #include "lua.h"
17 #include "lauxlib.h"
19 #include "lj_obj.h"
20 #include "lj_err.h"
21 #include "lj_lib.h"
23 /* -- Module registration ------------------------------------------------- */
25 LUALIB_API const char *luaL_findtable(lua_State *L, int idx,
26 const char *fname, int szhint)
28 const char *e;
29 lua_pushvalue(L, idx);
30 do {
31 e = strchr(fname, '.');
32 if (e == NULL) e = fname + strlen(fname);
33 lua_pushlstring(L, fname, (size_t)(e - fname));
34 lua_rawget(L, -2);
35 if (lua_isnil(L, -1)) { /* no such field? */
36 lua_pop(L, 1); /* remove this nil */
37 lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
38 lua_pushlstring(L, fname, (size_t)(e - fname));
39 lua_pushvalue(L, -2);
40 lua_settable(L, -4); /* set new table into field */
41 } else if (!lua_istable(L, -1)) { /* field has a non-table value? */
42 lua_pop(L, 2); /* remove table and value */
43 return fname; /* return problematic part of the name */
45 lua_remove(L, -2); /* remove previous table */
46 fname = e + 1;
47 } while (*e == '.');
48 return NULL;
51 static int libsize(const luaL_Reg *l)
53 int size = 0;
54 for (; l->name; l++) size++;
55 return size;
58 LUALIB_API void luaL_openlib(lua_State *L, const char *libname,
59 const luaL_Reg *l, int nup)
61 lj_lib_checkfpu(L);
62 if (libname) {
63 int size = libsize(l);
64 /* check whether lib already exists */
65 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 16);
66 lua_getfield(L, -1, libname); /* get _LOADED[libname] */
67 if (!lua_istable(L, -1)) { /* not found? */
68 lua_pop(L, 1); /* remove previous result */
69 /* try global variable (and create one if it does not exist) */
70 if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
71 lj_err_callerv(L, LJ_ERR_BADMODN, libname);
72 lua_pushvalue(L, -1);
73 lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
75 lua_remove(L, -2); /* remove _LOADED table */
76 lua_insert(L, -(nup+1)); /* move library table to below upvalues */
78 for (; l->name; l++) {
79 int i;
80 for (i = 0; i < nup; i++) /* copy upvalues to the top */
81 lua_pushvalue(L, -nup);
82 lua_pushcclosure(L, l->func, nup);
83 lua_setfield(L, -(nup+2), l->name);
85 lua_pop(L, nup); /* remove upvalues */
88 LUALIB_API void luaL_register(lua_State *L, const char *libname,
89 const luaL_Reg *l)
91 luaL_openlib(L, libname, l, 0);
94 LUALIB_API const char *luaL_gsub(lua_State *L, const char *s,
95 const char *p, const char *r)
97 const char *wild;
98 size_t l = strlen(p);
99 luaL_Buffer b;
100 luaL_buffinit(L, &b);
101 while ((wild = strstr(s, p)) != NULL) {
102 luaL_addlstring(&b, s, (size_t)(wild - s)); /* push prefix */
103 luaL_addstring(&b, r); /* push replacement in place of pattern */
104 s = wild + l; /* continue after `p' */
106 luaL_addstring(&b, s); /* push last suffix */
107 luaL_pushresult(&b);
108 return lua_tostring(L, -1);
111 /* -- Buffer handling ----------------------------------------------------- */
113 #define bufflen(B) ((size_t)((B)->p - (B)->buffer))
114 #define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
116 static int emptybuffer(luaL_Buffer *B)
118 size_t l = bufflen(B);
119 if (l == 0)
120 return 0; /* put nothing on stack */
121 lua_pushlstring(B->L, B->buffer, l);
122 B->p = B->buffer;
123 B->lvl++;
124 return 1;
127 static void adjuststack(luaL_Buffer *B)
129 if (B->lvl > 1) {
130 lua_State *L = B->L;
131 int toget = 1; /* number of levels to concat */
132 size_t toplen = lua_strlen(L, -1);
133 do {
134 size_t l = lua_strlen(L, -(toget+1));
135 if (!(B->lvl - toget + 1 >= LUA_MINSTACK/2 || toplen > l))
136 break;
137 toplen += l;
138 toget++;
139 } while (toget < B->lvl);
140 lua_concat(L, toget);
141 B->lvl = B->lvl - toget + 1;
145 LUALIB_API char *luaL_prepbuffer(luaL_Buffer *B)
147 if (emptybuffer(B))
148 adjuststack(B);
149 return B->buffer;
152 LUALIB_API void luaL_addlstring(luaL_Buffer *B, const char *s, size_t l)
154 while (l--)
155 luaL_addchar(B, *s++);
158 LUALIB_API void luaL_addstring(luaL_Buffer *B, const char *s)
160 luaL_addlstring(B, s, strlen(s));
163 LUALIB_API void luaL_pushresult(luaL_Buffer *B)
165 emptybuffer(B);
166 lua_concat(B->L, B->lvl);
167 B->lvl = 1;
170 LUALIB_API void luaL_addvalue(luaL_Buffer *B)
172 lua_State *L = B->L;
173 size_t vl;
174 const char *s = lua_tolstring(L, -1, &vl);
175 if (vl <= bufffree(B)) { /* fit into buffer? */
176 memcpy(B->p, s, vl); /* put it there */
177 B->p += vl;
178 lua_pop(L, 1); /* remove from stack */
179 } else {
180 if (emptybuffer(B))
181 lua_insert(L, -2); /* put buffer before new value */
182 B->lvl++; /* add new value into B stack */
183 adjuststack(B);
187 LUALIB_API void luaL_buffinit(lua_State *L, luaL_Buffer *B)
189 B->L = L;
190 B->p = B->buffer;
191 B->lvl = 0;
194 /* -- Reference management ------------------------------------------------ */
196 #define FREELIST_REF 0
198 /* Convert a stack index to an absolute index. */
199 #define abs_index(L, i) \
200 ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1)
202 LUALIB_API int luaL_ref(lua_State *L, int t)
204 int ref;
205 t = abs_index(L, t);
206 if (lua_isnil(L, -1)) {
207 lua_pop(L, 1); /* remove from stack */
208 return LUA_REFNIL; /* `nil' has a unique fixed reference */
210 lua_rawgeti(L, t, FREELIST_REF); /* get first free element */
211 ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */
212 lua_pop(L, 1); /* remove it from stack */
213 if (ref != 0) { /* any free element? */
214 lua_rawgeti(L, t, ref); /* remove it from list */
215 lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */
216 } else { /* no free elements */
217 ref = (int)lua_objlen(L, t);
218 ref++; /* create new reference */
220 lua_rawseti(L, t, ref);
221 return ref;
224 LUALIB_API void luaL_unref(lua_State *L, int t, int ref)
226 if (ref >= 0) {
227 t = abs_index(L, t);
228 lua_rawgeti(L, t, FREELIST_REF);
229 lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */
230 lua_pushinteger(L, ref);
231 lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */
235 /* -- Load Lua code ------------------------------------------------------- */
237 typedef struct FileReaderCtx {
238 FILE *fp;
239 char buf[LUAL_BUFFERSIZE];
240 } FileReaderCtx;
242 static const char *reader_file(lua_State *L, void *ud, size_t *size)
244 FileReaderCtx *ctx = (FileReaderCtx *)ud;
245 UNUSED(L);
246 if (feof(ctx->fp)) return NULL;
247 *size = fread(ctx->buf, 1, sizeof(ctx->buf), ctx->fp);
248 return *size > 0 ? ctx->buf : NULL;
251 LUALIB_API int luaL_loadfile(lua_State *L, const char *filename)
253 FileReaderCtx ctx;
254 int status;
255 const char *chunkname;
256 if (filename) {
257 ctx.fp = fopen(filename, "r");
258 if (ctx.fp == NULL) {
259 lua_pushfstring(L, "cannot open %s: %s", filename, strerror(errno));
260 return LUA_ERRFILE;
262 chunkname = lua_pushfstring(L, "@%s", filename);
263 } else {
264 ctx.fp = stdin;
265 chunkname = "=stdin";
267 status = lua_load(L, reader_file, &ctx, chunkname);
268 if (ferror(ctx.fp)) {
269 L->top -= filename ? 2 : 1;
270 lua_pushfstring(L, "cannot read %s: %s", chunkname+1, strerror(errno));
271 if (filename)
272 fclose(ctx.fp);
273 return LUA_ERRFILE;
275 if (filename) {
276 L->top--;
277 copyTV(L, L->top-1, L->top);
278 fclose(ctx.fp);
280 return status;
283 typedef struct StringReaderCtx {
284 const char *str;
285 size_t size;
286 } StringReaderCtx;
288 static const char *reader_string(lua_State *L, void *ud, size_t *size)
290 StringReaderCtx *ctx = (StringReaderCtx *)ud;
291 UNUSED(L);
292 if (ctx->size == 0) return NULL;
293 *size = ctx->size;
294 ctx->size = 0;
295 return ctx->str;
298 LUALIB_API int luaL_loadbuffer(lua_State *L, const char *buf, size_t size,
299 const char *name)
301 StringReaderCtx ctx;
302 ctx.str = buf;
303 ctx.size = size;
304 return lua_load(L, reader_string, &ctx, name);
307 LUALIB_API int luaL_loadstring(lua_State *L, const char *s)
309 return luaL_loadbuffer(L, s, strlen(s), s);
312 /* -- Default allocator and panic function -------------------------------- */
314 #ifdef LUAJIT_USE_SYSMALLOC
316 static void *mem_alloc(void *ud, void *ptr, size_t osize, size_t nsize)
318 (void)ud;
319 (void)osize;
320 if (nsize == 0) {
321 free(ptr);
322 return NULL;
323 } else {
324 return realloc(ptr, nsize);
328 #define mem_create() NULL
330 #else
332 #include "lj_alloc.h"
334 #define mem_alloc lj_alloc_f
335 #define mem_create lj_alloc_create
337 #endif
339 static int panic(lua_State *L)
341 fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n",
342 lua_tostring(L, -1));
343 return 0;
346 LUALIB_API lua_State *luaL_newstate(void)
348 lua_State *L = lua_newstate(mem_alloc, mem_create());
349 if (L) G(L)->panic = panic;
350 return L;