2 ** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $
3 ** Auxiliary functions for building Lua libraries
4 ** See Copyright Notice in lua.h
16 /* This file uses only the official API of Lua.
17 ** Any function declared here could be written as an application function.
28 #define FREELIST_REF 0 /* free list of references */
31 /* convert a stack index to positive */
32 #define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
33 lua_gettop(L) + (i) + 1)
37 ** {======================================================
38 ** Error-report functions
39 ** =======================================================
43 LUALIB_API
int luaL_argerror (lua_State
*L
, int narg
, const char *extramsg
) {
45 if (!lua_getstack(L
, 0, &ar
)) /* no stack frame? */
46 return luaL_error(L
, "bad argument #%d (%s)", narg
, extramsg
);
47 lua_getinfo(L
, "n", &ar
);
48 if (strcmp(ar
.namewhat
, "method") == 0) {
49 narg
--; /* do not count `self' */
50 if (narg
== 0) /* error is in the self argument itself? */
51 return luaL_error(L
, "calling " LUA_QS
" on bad self (%s)",
56 return luaL_error(L
, "bad argument #%d to " LUA_QS
" (%s)",
57 narg
, ar
.name
, extramsg
);
61 LUALIB_API
int luaL_typerror (lua_State
*L
, int narg
, const char *tname
) {
62 const char *msg
= lua_pushfstring(L
, "%s expected, got %s",
63 tname
, luaL_typename(L
, narg
));
64 return luaL_argerror(L
, narg
, msg
);
68 static void tag_error (lua_State
*L
, int narg
, int tag
) {
69 luaL_typerror(L
, narg
, lua_typename(L
, tag
));
73 LUALIB_API
void luaL_where (lua_State
*L
, int level
) {
75 if (lua_getstack(L
, level
, &ar
)) { /* check function at level */
76 lua_getinfo(L
, "Sl", &ar
); /* get info about it */
77 if (ar
.currentline
> 0) { /* is there info? */
78 lua_pushfstring(L
, "%s:%d: ", ar
.short_src
, ar
.currentline
);
82 lua_pushliteral(L
, ""); /* else, no information available... */
86 LUALIB_API
int luaL_error (lua_State
*L
, const char *fmt
, ...) {
90 lua_pushvfstring(L
, fmt
, argp
);
96 /* }====================================================== */
99 LUALIB_API
int luaL_checkoption (lua_State
*L
, int narg
, const char *def
,
100 const char *const lst
[]) {
101 const char *name
= (def
) ? luaL_optstring(L
, narg
, def
) :
102 luaL_checkstring(L
, narg
);
104 for (i
=0; lst
[i
]; i
++)
105 if (strcmp(lst
[i
], name
) == 0)
107 return luaL_argerror(L
, narg
,
108 lua_pushfstring(L
, "invalid option " LUA_QS
, name
));
112 LUALIB_API
int luaL_newmetatable (lua_State
*L
, const char *tname
) {
113 lua_getfield(L
, LUA_REGISTRYINDEX
, tname
); /* get registry.name */
114 if (!lua_isnil(L
, -1)) /* name already in use? */
115 return 0; /* leave previous value on top, but return 0 */
117 lua_newtable(L
); /* create metatable */
118 lua_pushvalue(L
, -1);
119 lua_setfield(L
, LUA_REGISTRYINDEX
, tname
); /* registry.name = metatable */
124 LUALIB_API
void *luaL_checkudata (lua_State
*L
, int ud
, const char *tname
) {
125 void *p
= lua_touserdata(L
, ud
);
126 if (p
!= NULL
) { /* value is a userdata? */
127 if (lua_getmetatable(L
, ud
)) { /* does it have a metatable? */
128 lua_getfield(L
, LUA_REGISTRYINDEX
, tname
); /* get correct metatable */
129 if (lua_rawequal(L
, -1, -2)) { /* does it have the correct mt? */
130 lua_pop(L
, 2); /* remove both metatables */
135 luaL_typerror(L
, ud
, tname
); /* else error */
136 return NULL
; /* to avoid warnings */
140 LUALIB_API
void luaL_checkstack (lua_State
*L
, int space
, const char *mes
) {
141 if (!lua_checkstack(L
, space
))
142 luaL_error(L
, "stack overflow (%s)", mes
);
146 LUALIB_API
void luaL_checktype (lua_State
*L
, int narg
, int t
) {
147 if (lua_type(L
, narg
) != t
)
148 tag_error(L
, narg
, t
);
152 LUALIB_API
void luaL_checkany (lua_State
*L
, int narg
) {
153 if (lua_type(L
, narg
) == LUA_TNONE
)
154 luaL_argerror(L
, narg
, "value expected");
158 LUALIB_API
const char *luaL_checklstring (lua_State
*L
, int narg
, size_t *len
) {
159 const char *s
= lua_tolstring(L
, narg
, len
);
160 if (!s
) tag_error(L
, narg
, LUA_TSTRING
);
165 LUALIB_API
const char *luaL_optlstring (lua_State
*L
, int narg
,
166 const char *def
, size_t *len
) {
167 if (lua_isnoneornil(L
, narg
)) {
169 *len
= (def
? strlen(def
) : 0);
172 else return luaL_checklstring(L
, narg
, len
);
176 LUALIB_API lua_Number
luaL_checknumber (lua_State
*L
, int narg
) {
177 lua_Number d
= lua_tonumber(L
, narg
);
178 if (d
== 0 && !lua_isnumber(L
, narg
)) /* avoid extra test when d is not 0 */
179 tag_error(L
, narg
, LUA_TNUMBER
);
184 LUALIB_API lua_Number
luaL_optnumber (lua_State
*L
, int narg
, lua_Number def
) {
185 return luaL_opt(L
, luaL_checknumber
, narg
, def
);
189 LUALIB_API lua_Integer
luaL_checkinteger (lua_State
*L
, int narg
) {
190 lua_Integer d
= lua_tointeger(L
, narg
);
191 if (d
== 0 && !lua_isnumber(L
, narg
)) /* avoid extra test when d is not 0 */
192 tag_error(L
, narg
, LUA_TNUMBER
);
197 LUALIB_API lua_Integer
luaL_optinteger (lua_State
*L
, int narg
,
199 return luaL_opt(L
, luaL_checkinteger
, narg
, def
);
203 LUALIB_API
int luaL_checkboolean (lua_State
*L
, int narg
) {
204 int b
= lua_toboolean(L
, narg
);
205 if( b
== 0 && !lua_isboolean(L
, narg
))
206 tag_error(L
, narg
, LUA_TBOOLEAN
);
211 LUALIB_API
int luaL_optboolean (lua_State
*L
, int narg
, int def
) {
212 return luaL_opt(L
, luaL_checkboolean
, narg
, def
);
216 LUALIB_API
int luaL_getmetafield (lua_State
*L
, int obj
, const char *event
) {
217 if (!lua_getmetatable(L
, obj
)) /* no metatable? */
219 lua_pushstring(L
, event
);
221 if (lua_isnil(L
, -1)) {
222 lua_pop(L
, 2); /* remove metatable and metafield */
226 lua_remove(L
, -2); /* remove only metatable */
232 LUALIB_API
int luaL_callmeta (lua_State
*L
, int obj
, const char *event
) {
233 obj
= abs_index(L
, obj
);
234 if (!luaL_getmetafield(L
, obj
, event
)) /* no metafield? */
236 lua_pushvalue(L
, obj
);
242 LUALIB_API
void (luaL_register
) (lua_State
*L
, const char *libname
,
244 luaI_openlib(L
, libname
, l
, 0);
248 static int libsize (const luaL_Reg
*l
) {
250 for (; l
->name
; l
++) size
++;
255 LUALIB_API
void luaI_openlib (lua_State
*L
, const char *libname
,
256 const luaL_Reg
*l
, int nup
) {
258 int size
= libsize(l
);
259 /* check whether lib already exists */
260 luaL_findtable(L
, LUA_REGISTRYINDEX
, "_LOADED", 1);
261 lua_getfield(L
, -1, libname
); /* get _LOADED[libname] */
262 if (!lua_istable(L
, -1)) { /* not found? */
263 lua_pop(L
, 1); /* remove previous result */
264 /* try global variable (and create one if it does not exist) */
265 if (luaL_findtable(L
, LUA_GLOBALSINDEX
, libname
, size
) != NULL
)
266 luaL_error(L
, "name conflict for module " LUA_QS
, libname
);
267 lua_pushvalue(L
, -1);
268 lua_setfield(L
, -3, libname
); /* _LOADED[libname] = new table */
270 lua_remove(L
, -2); /* remove _LOADED table */
271 lua_insert(L
, -(nup
+1)); /* move library table to below upvalues */
273 for (; l
->name
; l
++) {
275 for (i
=0; i
<nup
; i
++) /* copy upvalues to the top */
276 lua_pushvalue(L
, -nup
);
277 lua_pushcclosure(L
, l
->func
, nup
);
278 lua_setfield(L
, -(nup
+2), l
->name
);
280 lua_pop(L
, nup
); /* remove upvalues */
286 ** {======================================================
287 ** getn-setn: size for arrays
288 ** =======================================================
291 #if defined(LUA_COMPAT_GETN)
293 static int checkint (lua_State
*L
, int topop
) {
294 int n
= (lua_type(L
, -1) == LUA_TNUMBER
) ? lua_tointeger(L
, -1) : -1;
300 static void getsizes (lua_State
*L
) {
301 lua_getfield(L
, LUA_REGISTRYINDEX
, "LUA_SIZES");
302 if (lua_isnil(L
, -1)) { /* no `size' table? */
303 lua_pop(L
, 1); /* remove nil */
304 lua_newtable(L
); /* create it */
305 lua_pushvalue(L
, -1); /* `size' will be its own metatable */
306 lua_setmetatable(L
, -2);
307 lua_pushliteral(L
, "kv");
308 lua_setfield(L
, -2, "__mode"); /* metatable(N).__mode = "kv" */
309 lua_pushvalue(L
, -1);
310 lua_setfield(L
, LUA_REGISTRYINDEX
, "LUA_SIZES"); /* store in register */
315 LUALIB_API
void luaL_setn (lua_State
*L
, int t
, int n
) {
317 lua_pushliteral(L
, "n");
319 if (checkint(L
, 1) >= 0) { /* is there a numeric field `n'? */
320 lua_pushliteral(L
, "n"); /* use it */
321 lua_pushinteger(L
, n
);
324 else { /* use `sizes' */
327 lua_pushinteger(L
, n
);
328 lua_rawset(L
, -3); /* sizes[t] = n */
329 lua_pop(L
, 1); /* remove `sizes' */
334 LUALIB_API
int luaL_getn (lua_State
*L
, int t
) {
337 lua_pushliteral(L
, "n"); /* try t.n */
339 if ((n
= checkint(L
, 1)) >= 0) return n
;
340 getsizes(L
); /* else try sizes[t] */
343 if ((n
= checkint(L
, 2)) >= 0) return n
;
344 return (int)lua_objlen(L
, t
);
349 /* }====================================================== */
353 LUALIB_API
const char *luaL_gsub (lua_State
*L
, const char *s
, const char *p
,
356 size_t l
= strlen(p
);
358 luaL_buffinit(L
, &b
);
359 while ((wild
= strstr(s
, p
)) != NULL
) {
360 luaL_addlstring(&b
, s
, wild
- s
); /* push prefix */
361 luaL_addstring(&b
, r
); /* push replacement in place of pattern */
362 s
= wild
+ l
; /* continue after `p' */
364 luaL_addstring(&b
, s
); /* push last suffix */
366 return lua_tostring(L
, -1);
370 LUALIB_API
const char *luaL_findtable (lua_State
*L
, int idx
,
371 const char *fname
, int szhint
) {
373 lua_pushvalue(L
, idx
);
375 e
= strchr(fname
, '.');
376 if (e
== NULL
) e
= fname
+ strlen(fname
);
377 lua_pushlstring(L
, fname
, e
- fname
);
379 if (lua_isnil(L
, -1)) { /* no such field? */
380 lua_pop(L
, 1); /* remove this nil */
381 lua_createtable(L
, 0, (*e
== '.' ? 1 : szhint
)); /* new table for field */
382 lua_pushlstring(L
, fname
, e
- fname
);
383 lua_pushvalue(L
, -2);
384 lua_settable(L
, -4); /* set new table into field */
386 else if (!lua_istable(L
, -1)) { /* field has a non-table value? */
387 lua_pop(L
, 2); /* remove table and value */
388 return fname
; /* return problematic part of the name */
390 lua_remove(L
, -2); /* remove previous table */
399 ** {======================================================
400 ** Generic Buffer manipulation
401 ** =======================================================
405 #define bufflen(B) ((B)->p - (B)->buffer)
406 #define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
408 #define LIMIT (LUA_MINSTACK/2)
411 static int emptybuffer (luaL_Buffer
*B
) {
412 size_t l
= bufflen(B
);
413 if (l
== 0) return 0; /* put nothing on stack */
415 lua_pushlstring(B
->L
, B
->buffer
, l
);
423 static void adjuststack (luaL_Buffer
*B
) {
426 int toget
= 1; /* number of levels to concat */
427 size_t toplen
= lua_strlen(L
, -1);
429 size_t l
= lua_strlen(L
, -(toget
+1));
430 if (B
->lvl
- toget
+ 1 >= LIMIT
|| toplen
> l
) {
435 } while (toget
< B
->lvl
);
436 lua_concat(L
, toget
);
437 B
->lvl
= B
->lvl
- toget
+ 1;
442 LUALIB_API
char *luaL_prepbuffer (luaL_Buffer
*B
) {
449 LUALIB_API
void luaL_addlstring (luaL_Buffer
*B
, const char *s
, size_t l
) {
451 luaL_addchar(B
, *s
++);
455 LUALIB_API
void luaL_addstring (luaL_Buffer
*B
, const char *s
) {
456 luaL_addlstring(B
, s
, strlen(s
));
460 LUALIB_API
void luaL_pushresult (luaL_Buffer
*B
) {
462 lua_concat(B
->L
, B
->lvl
);
467 LUALIB_API
void luaL_addvalue (luaL_Buffer
*B
) {
470 const char *s
= lua_tolstring(L
, -1, &vl
);
471 if (vl
<= bufffree(B
)) { /* fit into buffer? */
472 memcpy(B
->p
, s
, vl
); /* put it there */
474 lua_pop(L
, 1); /* remove from stack */
478 lua_insert(L
, -2); /* put buffer before new value */
479 B
->lvl
++; /* add new value into B stack */
485 LUALIB_API
void luaL_buffinit (lua_State
*L
, luaL_Buffer
*B
) {
491 /* }====================================================== */
494 LUALIB_API
int luaL_ref (lua_State
*L
, int t
) {
497 if (lua_isnil(L
, -1)) {
498 lua_pop(L
, 1); /* remove from stack */
499 return LUA_REFNIL
; /* `nil' has a unique fixed reference */
501 lua_rawgeti(L
, t
, FREELIST_REF
); /* get first free element */
502 ref
= (int)lua_tointeger(L
, -1); /* ref = t[FREELIST_REF] */
503 lua_pop(L
, 1); /* remove it from stack */
504 if (ref
!= 0) { /* any free element? */
505 lua_rawgeti(L
, t
, ref
); /* remove it from list */
506 lua_rawseti(L
, t
, FREELIST_REF
); /* (t[FREELIST_REF] = t[ref]) */
508 else { /* no free elements */
509 ref
= (int)lua_objlen(L
, t
);
510 ref
++; /* create new reference */
512 lua_rawseti(L
, t
, ref
);
517 LUALIB_API
void luaL_unref (lua_State
*L
, int t
, int ref
) {
520 lua_rawgeti(L
, t
, FREELIST_REF
);
521 lua_rawseti(L
, t
, ref
); /* t[ref] = t[FREELIST_REF] */
522 lua_pushinteger(L
, ref
);
523 lua_rawseti(L
, t
, FREELIST_REF
); /* t[FREELIST_REF] = ref */
530 ** {======================================================
532 ** =======================================================
535 typedef struct LoadF
{
538 char buff
[LUAL_BUFFERSIZE
];
541 static const char *getF(lua_State
*L
, void *ud
, size_t *size
) {
542 LoadF
*lf
= (LoadF
*)ud
;
549 *size
= rb
->read(lf
->f
, lf
->buff
, LUAL_BUFFERSIZE
);
550 if (*size
<= 0) return NULL
;
551 return (*size
> 0) ? lf
->buff
: NULL
;
555 static int errfile (lua_State
*L
, const char *what
, int fnameindex
) {
556 const char *serr
= strerror(errno
);
557 const char *filename
= lua_tostring(L
, fnameindex
) + 1;
558 lua_pushfstring(L
, "cannot %s %s: %s", what
, filename
, serr
);
559 lua_remove(L
, fnameindex
);
563 LUALIB_API
int luaL_loadfile (lua_State
*L
, const char *filename
) {
566 int fnameindex
= lua_gettop(L
) + 1; /* index of filename on the stack */
568 lf
.f
= rb
->open(filename
, O_RDONLY
);
569 lua_pushfstring(L
, "@%s", filename
);
570 if (lf
.f
< 0) return errfile(L
, "open", fnameindex
);
571 status
= lua_load(L
, getF
, &lf
, lua_tostring(L
, -1));
573 lua_remove(L
, fnameindex
);
578 typedef struct LoadS
{
584 static const char *getS (lua_State
*L
, void *ud
, size_t *size
) {
585 LoadS
*ls
= (LoadS
*)ud
;
587 if (ls
->size
== 0) return NULL
;
594 LUALIB_API
int luaL_loadbuffer (lua_State
*L
, const char *buff
, size_t size
,
599 return lua_load(L
, getS
, &ls
, name
);
603 LUALIB_API
int (luaL_loadstring
) (lua_State
*L
, const char *s
) {
604 return luaL_loadbuffer(L
, s
, strlen(s
), s
);
609 /* }====================================================== */
612 static void *l_alloc (void *ud
, void *ptr
, size_t osize
, size_t nsize
) {
620 return realloc(ptr
, nsize
);
624 static int panic (lua_State
*L
) {
625 DEBUGF("PANIC: unprotected error in call to Lua API (%s)\n",
626 lua_tostring(L
, -1));
627 rb
->splashf(5 * HZ
, "PANIC: unprotected error in call to Lua API (%s)",
628 lua_tostring(L
, -1));
634 LUALIB_API lua_State
*luaL_newstate (void) {
635 lua_State
*L
= lua_newstate(l_alloc
, NULL
);
636 if (L
) lua_atpanic(L
, &panic
);