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 #include <grub/file.h>
18 /* This file uses only the official API of Lua.
19 ** Any function declared here could be written as an application function.
30 #define FREELIST_REF 0 /* free list of references */
33 /* convert a stack index to positive */
34 #define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
35 lua_gettop(L) + (i) + 1)
39 ** {======================================================
40 ** Error-report functions
41 ** =======================================================
45 LUALIB_API
int luaL_argerror (lua_State
*L
, int narg
, const char *extramsg
) {
47 if (!lua_getstack(L
, 0, &ar
)) /* no stack frame? */
48 return luaL_error(L
, "bad argument #%d (%s)", narg
, extramsg
);
49 lua_getinfo(L
, "n", &ar
);
50 if (strcmp(ar
.namewhat
, "method") == 0) {
51 narg
--; /* do not count `self' */
52 if (narg
== 0) /* error is in the self argument itself? */
53 return luaL_error(L
, "calling " LUA_QS
" on bad self (%s)",
58 return luaL_error(L
, "bad argument #%d to " LUA_QS
" (%s)",
59 narg
, ar
.name
, extramsg
);
63 LUALIB_API
int luaL_typerror (lua_State
*L
, int narg
, const char *tname
) {
64 const char *msg
= lua_pushfstring(L
, "%s expected, got %s",
65 tname
, luaL_typename(L
, narg
));
66 return luaL_argerror(L
, narg
, msg
);
70 static void tag_error (lua_State
*L
, int narg
, int tag
) {
71 luaL_typerror(L
, narg
, lua_typename(L
, tag
));
75 LUALIB_API
void luaL_where (lua_State
*L
, int level
) {
77 if (lua_getstack(L
, level
, &ar
)) { /* check function at level */
78 lua_getinfo(L
, "Sl", &ar
); /* get info about it */
79 if (ar
.currentline
> 0) { /* is there info? */
80 lua_pushfstring(L
, "%s:%d: ", ar
.short_src
, ar
.currentline
);
84 lua_pushliteral(L
, ""); /* else, no information available... */
88 LUALIB_API
int luaL_error (lua_State
*L
, const char *fmt
, ...) {
92 lua_pushvfstring(L
, fmt
, argp
);
98 /* }====================================================== */
101 LUALIB_API
int luaL_checkoption (lua_State
*L
, int narg
, const char *def
,
102 const char *const lst
[]) {
103 const char *name
= (def
) ? luaL_optstring(L
, narg
, def
) :
104 luaL_checkstring(L
, narg
);
106 for (i
=0; lst
[i
]; i
++)
107 if (strcmp(lst
[i
], name
) == 0)
109 return luaL_argerror(L
, narg
,
110 lua_pushfstring(L
, "invalid option " LUA_QS
, name
));
114 LUALIB_API
int luaL_newmetatable (lua_State
*L
, const char *tname
) {
115 lua_getfield(L
, LUA_REGISTRYINDEX
, tname
); /* get registry.name */
116 if (!lua_isnil(L
, -1)) /* name already in use? */
117 return 0; /* leave previous value on top, but return 0 */
119 lua_newtable(L
); /* create metatable */
120 lua_pushvalue(L
, -1);
121 lua_setfield(L
, LUA_REGISTRYINDEX
, tname
); /* registry.name = metatable */
126 LUALIB_API
void *luaL_checkudata (lua_State
*L
, int ud
, const char *tname
) {
127 void *p
= lua_touserdata(L
, ud
);
128 if (p
!= NULL
) { /* value is a userdata? */
129 if (lua_getmetatable(L
, ud
)) { /* does it have a metatable? */
130 lua_getfield(L
, LUA_REGISTRYINDEX
, tname
); /* get correct metatable */
131 if (lua_rawequal(L
, -1, -2)) { /* does it have the correct mt? */
132 lua_pop(L
, 2); /* remove both metatables */
137 luaL_typerror(L
, ud
, tname
); /* else error */
138 return NULL
; /* to avoid warnings */
142 LUALIB_API
void luaL_checkstack (lua_State
*L
, int space
, const char *mes
) {
143 if (!lua_checkstack(L
, space
))
144 luaL_error(L
, "stack overflow (%s)", mes
);
148 LUALIB_API
void luaL_checktype (lua_State
*L
, int narg
, int t
) {
149 if (lua_type(L
, narg
) != t
)
150 tag_error(L
, narg
, t
);
154 LUALIB_API
void luaL_checkany (lua_State
*L
, int narg
) {
155 if (lua_type(L
, narg
) == LUA_TNONE
)
156 luaL_argerror(L
, narg
, "value expected");
160 LUALIB_API
const char *luaL_checklstring (lua_State
*L
, int narg
, size_t *len
) {
161 const char *s
= lua_tolstring(L
, narg
, len
);
162 if (!s
) tag_error(L
, narg
, LUA_TSTRING
);
167 LUALIB_API
const char *luaL_optlstring (lua_State
*L
, int narg
,
168 const char *def
, size_t *len
) {
169 if (lua_isnoneornil(L
, narg
)) {
171 *len
= (def
? strlen(def
) : 0);
174 else return luaL_checklstring(L
, narg
, len
);
178 LUALIB_API lua_Number
luaL_checknumber (lua_State
*L
, int narg
) {
179 lua_Number d
= lua_tonumber(L
, narg
);
180 if (d
== 0 && !lua_isnumber(L
, narg
)) /* avoid extra test when d is not 0 */
181 tag_error(L
, narg
, LUA_TNUMBER
);
186 LUALIB_API lua_Number
luaL_optnumber (lua_State
*L
, int narg
, lua_Number def
) {
187 return luaL_opt(L
, luaL_checknumber
, narg
, def
);
191 LUALIB_API lua_Integer
luaL_checkinteger (lua_State
*L
, int narg
) {
192 lua_Integer d
= lua_tointeger(L
, narg
);
193 if (d
== 0 && !lua_isnumber(L
, narg
)) /* avoid extra test when d is not 0 */
194 tag_error(L
, narg
, LUA_TNUMBER
);
199 LUALIB_API lua_Integer
luaL_optinteger (lua_State
*L
, int narg
,
201 return luaL_opt(L
, luaL_checkinteger
, narg
, def
);
205 LUALIB_API
int luaL_getmetafield (lua_State
*L
, int obj
, const char *event
) {
206 if (!lua_getmetatable(L
, obj
)) /* no metatable? */
208 lua_pushstring(L
, event
);
210 if (lua_isnil(L
, -1)) {
211 lua_pop(L
, 2); /* remove metatable and metafield */
215 lua_remove(L
, -2); /* remove only metatable */
221 LUALIB_API
int luaL_callmeta (lua_State
*L
, int obj
, const char *event
) {
222 obj
= abs_index(L
, obj
);
223 if (!luaL_getmetafield(L
, obj
, event
)) /* no metafield? */
225 lua_pushvalue(L
, obj
);
231 LUALIB_API
void (luaL_register
) (lua_State
*L
, const char *libname
,
233 luaI_openlib(L
, libname
, l
, 0);
237 static int libsize (const luaL_Reg
*l
) {
239 for (; l
->name
; l
++) size
++;
244 LUALIB_API
void luaI_openlib (lua_State
*L
, const char *libname
,
245 const luaL_Reg
*l
, int nup
) {
247 int size
= libsize(l
);
248 /* check whether lib already exists */
249 luaL_findtable(L
, LUA_REGISTRYINDEX
, "_LOADED", 1);
250 lua_getfield(L
, -1, libname
); /* get _LOADED[libname] */
251 if (!lua_istable(L
, -1)) { /* not found? */
252 lua_pop(L
, 1); /* remove previous result */
253 /* try global variable (and create one if it does not exist) */
254 if (luaL_findtable(L
, LUA_GLOBALSINDEX
, libname
, size
) != NULL
)
255 luaL_error(L
, "name conflict for module " LUA_QS
, libname
);
256 lua_pushvalue(L
, -1);
257 lua_setfield(L
, -3, libname
); /* _LOADED[libname] = new table */
259 lua_remove(L
, -2); /* remove _LOADED table */
260 lua_insert(L
, -(nup
+1)); /* move library table to below upvalues */
262 for (; l
->name
; l
++) {
264 for (i
=0; i
<nup
; i
++) /* copy upvalues to the top */
265 lua_pushvalue(L
, -nup
);
266 lua_pushcclosure(L
, l
->func
, nup
);
267 lua_setfield(L
, -(nup
+2), l
->name
);
269 lua_pop(L
, nup
); /* remove upvalues */
275 ** {======================================================
276 ** getn-setn: size for arrays
277 ** =======================================================
280 #if defined(LUA_COMPAT_GETN)
282 static int checkint (lua_State
*L
, int topop
) {
283 int n
= (lua_type(L
, -1) == LUA_TNUMBER
) ? lua_tointeger(L
, -1) : -1;
289 static void getsizes (lua_State
*L
) {
290 lua_getfield(L
, LUA_REGISTRYINDEX
, "LUA_SIZES");
291 if (lua_isnil(L
, -1)) { /* no `size' table? */
292 lua_pop(L
, 1); /* remove nil */
293 lua_newtable(L
); /* create it */
294 lua_pushvalue(L
, -1); /* `size' will be its own metatable */
295 lua_setmetatable(L
, -2);
296 lua_pushliteral(L
, "kv");
297 lua_setfield(L
, -2, "__mode"); /* metatable(N).__mode = "kv" */
298 lua_pushvalue(L
, -1);
299 lua_setfield(L
, LUA_REGISTRYINDEX
, "LUA_SIZES"); /* store in register */
304 LUALIB_API
void luaL_setn (lua_State
*L
, int t
, int n
) {
306 lua_pushliteral(L
, "n");
308 if (checkint(L
, 1) >= 0) { /* is there a numeric field `n'? */
309 lua_pushliteral(L
, "n"); /* use it */
310 lua_pushinteger(L
, n
);
313 else { /* use `sizes' */
316 lua_pushinteger(L
, n
);
317 lua_rawset(L
, -3); /* sizes[t] = n */
318 lua_pop(L
, 1); /* remove `sizes' */
323 LUALIB_API
int luaL_getn (lua_State
*L
, int t
) {
326 lua_pushliteral(L
, "n"); /* try t.n */
328 if ((n
= checkint(L
, 1)) >= 0) return n
;
329 getsizes(L
); /* else try sizes[t] */
332 if ((n
= checkint(L
, 2)) >= 0) return n
;
333 return (int)lua_objlen(L
, t
);
338 /* }====================================================== */
342 LUALIB_API
const char *luaL_gsub (lua_State
*L
, const char *s
, const char *p
,
345 size_t l
= strlen(p
);
347 luaL_buffinit(L
, &b
);
348 while ((wild
= strstr(s
, p
)) != NULL
) {
349 luaL_addlstring(&b
, s
, wild
- s
); /* push prefix */
350 luaL_addstring(&b
, r
); /* push replacement in place of pattern */
351 s
= wild
+ l
; /* continue after `p' */
353 luaL_addstring(&b
, s
); /* push last suffix */
355 return lua_tostring(L
, -1);
359 LUALIB_API
const char *luaL_findtable (lua_State
*L
, int idx
,
360 const char *fname
, int szhint
) {
362 lua_pushvalue(L
, idx
);
364 e
= strchr(fname
, '.');
365 if (e
== NULL
) e
= fname
+ strlen(fname
);
366 lua_pushlstring(L
, fname
, e
- fname
);
368 if (lua_isnil(L
, -1)) { /* no such field? */
369 lua_pop(L
, 1); /* remove this nil */
370 lua_createtable(L
, 0, (*e
== '.' ? 1 : szhint
)); /* new table for field */
371 lua_pushlstring(L
, fname
, e
- fname
);
372 lua_pushvalue(L
, -2);
373 lua_settable(L
, -4); /* set new table into field */
375 else if (!lua_istable(L
, -1)) { /* field has a non-table value? */
376 lua_pop(L
, 2); /* remove table and value */
377 return fname
; /* return problematic part of the name */
379 lua_remove(L
, -2); /* remove previous table */
388 ** {======================================================
389 ** Generic Buffer manipulation
390 ** =======================================================
394 #define bufflen(B) ((B)->p - (B)->buffer)
395 #define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B)))
397 #define LIMIT (LUA_MINSTACK/2)
400 static int emptybuffer (luaL_Buffer
*B
) {
401 size_t l
= bufflen(B
);
402 if (l
== 0) return 0; /* put nothing on stack */
404 lua_pushlstring(B
->L
, B
->buffer
, l
);
412 static void adjuststack (luaL_Buffer
*B
) {
415 int toget
= 1; /* number of levels to concat */
416 size_t toplen
= lua_strlen(L
, -1);
418 size_t l
= lua_strlen(L
, -(toget
+1));
419 if (B
->lvl
- toget
+ 1 >= LIMIT
|| toplen
> l
) {
424 } while (toget
< B
->lvl
);
425 lua_concat(L
, toget
);
426 B
->lvl
= B
->lvl
- toget
+ 1;
431 LUALIB_API
char *luaL_prepbuffer (luaL_Buffer
*B
) {
438 LUALIB_API
void luaL_addlstring (luaL_Buffer
*B
, const char *s
, size_t l
) {
440 luaL_addchar(B
, *s
++);
444 LUALIB_API
void luaL_addstring (luaL_Buffer
*B
, const char *s
) {
445 luaL_addlstring(B
, s
, strlen(s
));
449 LUALIB_API
void luaL_pushresult (luaL_Buffer
*B
) {
451 lua_concat(B
->L
, B
->lvl
);
456 LUALIB_API
void luaL_addvalue (luaL_Buffer
*B
) {
459 const char *s
= lua_tolstring(L
, -1, &vl
);
460 if (vl
<= bufffree(B
)) { /* fit into buffer? */
461 memcpy(B
->p
, s
, vl
); /* put it there */
463 lua_pop(L
, 1); /* remove from stack */
467 lua_insert(L
, -2); /* put buffer before new value */
468 B
->lvl
++; /* add new value into B stack */
474 LUALIB_API
void luaL_buffinit (lua_State
*L
, luaL_Buffer
*B
) {
480 /* }====================================================== */
483 LUALIB_API
int luaL_ref (lua_State
*L
, int t
) {
486 if (lua_isnil(L
, -1)) {
487 lua_pop(L
, 1); /* remove from stack */
488 return LUA_REFNIL
; /* `nil' has a unique fixed reference */
490 lua_rawgeti(L
, t
, FREELIST_REF
); /* get first free element */
491 ref
= (int)lua_tointeger(L
, -1); /* ref = t[FREELIST_REF] */
492 lua_pop(L
, 1); /* remove it from stack */
493 if (ref
!= 0) { /* any free element? */
494 lua_rawgeti(L
, t
, ref
); /* remove it from list */
495 lua_rawseti(L
, t
, FREELIST_REF
); /* (t[FREELIST_REF] = t[ref]) */
497 else { /* no free elements */
498 ref
= (int)lua_objlen(L
, t
);
499 ref
++; /* create new reference */
501 lua_rawseti(L
, t
, ref
);
506 LUALIB_API
void luaL_unref (lua_State
*L
, int t
, int ref
) {
509 lua_rawgeti(L
, t
, FREELIST_REF
);
510 lua_rawseti(L
, t
, ref
); /* t[ref] = t[FREELIST_REF] */
511 lua_pushinteger(L
, ref
);
512 lua_rawseti(L
, t
, FREELIST_REF
); /* t[FREELIST_REF] = ref */
519 ** {======================================================
521 ** =======================================================
527 grub_getc (grub_file_t file
)
531 return (grub_file_read (file
, &c
, 1) != 1) ? GRUB_EOF
: c
;
535 #define grub_eof(file) (file->offset >= file->size)
537 typedef struct LoadF
{
541 char buff
[LUAL_BUFFERSIZE
];
545 static const char *getF (lua_State
*L
, void *ud
, size_t *size
) {
546 LoadF
*lf
= (LoadF
*)ud
;
555 s
= sizeof (lf
->buff
);
559 lf
->buff
[0] = lf
->ungetc
;
565 if (grub_eof(lf
->f
)) return NULL
;
566 s
= grub_file_read(lf
->f
, p
, s
);
570 *size
= s
+ (p
- lf
->buff
);
571 return (*size
> 0) ? lf
->buff
: NULL
;
574 static int errfile (lua_State
*L
, const char *what
, int fnameindex
) {
575 const char *serr
= grub_errmsg
;
576 const char *filename
= lua_tostring(L
, fnameindex
) + 1;
577 lua_pushfstring(L
, "cannot %s %s: %s", what
, filename
, serr
);
578 lua_remove(L
, fnameindex
);
582 LUALIB_API
int luaL_loadfile (lua_State
*L
, const char *filename
) {
584 int status
, readstatus
;
586 int fnameindex
= lua_gettop(L
) + 1; /* index of filename on the stack */
588 if (filename
== NULL
) {
589 lua_pushliteral(L
, "=stdin");
590 return errfile(L
, "open", fnameindex
);
593 lua_pushfstring(L
, "@%s", filename
);
594 lf
.f
= grub_file_open(filename
);
595 if (lf
.f
== NULL
) return errfile(L
, "open", fnameindex
);
599 if (c
== '#') { /* Unix exec. file? */
601 while ((c
= grub_getc(lf
.f
)) != GRUB_EOF
&& c
!= '\n') ; /* skip first line */
602 if (c
== '\n') c
= grub_getc(lf
.f
);
604 if (c
== LUA_SIGNATURE
[0] && filename
) { /* binary file? */
605 /* skip eventual `#!...' */
606 while ((c
= grub_getc(lf
.f
)) != GRUB_EOF
&& c
!= LUA_SIGNATURE
[0]) ;
610 status
= lua_load(L
, getF
, &lf
, lua_tostring(L
, -1));
611 readstatus
= grub_errno
;
612 grub_file_close(lf
.f
); /* close file (even in case of errors) */
614 lua_settop(L
, fnameindex
); /* ignore results from `lua_load' */
615 return errfile(L
, "read", fnameindex
);
617 lua_remove(L
, fnameindex
);
621 typedef struct LoadS
{
627 static const char *getS (lua_State
*L
, void *ud
, size_t *size
) {
628 LoadS
*ls
= (LoadS
*)ud
;
630 if (ls
->size
== 0) return NULL
;
637 LUALIB_API
int luaL_loadbuffer (lua_State
*L
, const char *buff
, size_t size
,
642 return lua_load(L
, getS
, &ls
, name
);
646 LUALIB_API
int (luaL_loadstring
) (lua_State
*L
, const char *s
) {
647 return luaL_loadbuffer(L
, s
, strlen(s
), s
);
652 /* }====================================================== */
655 static void *l_alloc (void *ud
, void *ptr
, size_t osize
, size_t nsize
) {
663 return realloc(ptr
, nsize
);
667 static int panic (lua_State
*L
) {
668 (void)L
; /* to avoid warnings */
670 fprintf(stderr
, "PANIC: unprotected error in call to Lua API (%s)\n",
671 lua_tostring(L
, -1));
673 grub_fatal ("PANIC: unprotected error in call to Lua API (%s)\n",
674 lua_tostring(L
, -1));
680 LUALIB_API lua_State
*luaL_newstate (void) {
681 lua_State
*L
= lua_newstate(l_alloc
, NULL
);
682 if (L
) lua_atpanic(L
, &panic
);