aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lauxlib.c307
1 files changed, 163 insertions, 144 deletions
diff --git a/lauxlib.c b/lauxlib.c
index c645c32c..2175fec9 100644
--- a/lauxlib.c
+++ b/lauxlib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lauxlib.c,v 1.167 2007/05/15 18:46:12 roberto Exp roberto $ 2** $Id: lauxlib.c,v 1.168 2007/06/21 13:48:04 roberto Exp roberto $
3** Auxiliary functions for building Lua libraries 3** Auxiliary functions for building Lua libraries
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -25,13 +25,6 @@
25#include "lauxlib.h" 25#include "lauxlib.h"
26 26
27 27
28/* number of prereserved references (for internal use) */
29#define RESERVED_REFS 1 /* only FREELIST_REF is reserved */
30
31#define FREELIST_REF 1 /* free list of references */
32
33
34
35/* convert a stack index to positive */ 28/* convert a stack index to positive */
36#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ 29#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \
37 lua_gettop(L) + (i) + 1) 30 lua_gettop(L) + (i) + 1)
@@ -43,7 +36,6 @@
43** ======================================================= 36** =======================================================
44*/ 37*/
45 38
46
47LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { 39LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) {
48 lua_Debug ar; 40 lua_Debug ar;
49 if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ 41 if (!lua_getstack(L, 0, &ar)) /* no stack frame? */
@@ -100,18 +92,11 @@ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) {
100/* }====================================================== */ 92/* }====================================================== */
101 93
102 94
103LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, 95/*
104 const char *const lst[]) { 96** {======================================================
105 const char *name = (def) ? luaL_optstring(L, narg, def) : 97** Userdata's metatable manipulation
106 luaL_checkstring(L, narg); 98** =======================================================
107 int i; 99*/
108 for (i=0; lst[i]; i++)
109 if (strcmp(lst[i], name) == 0)
110 return i;
111 return luaL_argerror(L, narg,
112 lua_pushfstring(L, "invalid option " LUA_QS, name));
113}
114
115 100
116LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { 101LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) {
117 lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ 102 lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */
@@ -146,6 +131,27 @@ LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) {
146 return p; 131 return p;
147} 132}
148 133
134/* }====================================================== */
135
136
137/*
138** {======================================================
139** Argument check functions
140** =======================================================
141*/
142
143LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def,
144 const char *const lst[]) {
145 const char *name = (def) ? luaL_optstring(L, narg, def) :
146 luaL_checkstring(L, narg);
147 int i;
148 for (i=0; lst[i]; i++)
149 if (strcmp(lst[i], name) == 0)
150 return i;
151 return luaL_argerror(L, narg,
152 lua_pushfstring(L, "invalid option " LUA_QS, name));
153}
154
149 155
150LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { 156LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) {
151 if (!lua_checkstack(L, space)) 157 if (!lua_checkstack(L, space))
@@ -209,128 +215,7 @@ LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg,
209 return luaL_opt(L, luaL_checkinteger, narg, def); 215 return luaL_opt(L, luaL_checkinteger, narg, def);
210} 216}
211 217
212 218/* }====================================================== */
213LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
214 if (!lua_getmetatable(L, obj)) /* no metatable? */
215 return 0;
216 lua_pushstring(L, event);
217 lua_rawget(L, -2);
218 if (lua_isnil(L, -1)) {
219 lua_pop(L, 2); /* remove metatable and metafield */
220 return 0;
221 }
222 else {
223 lua_remove(L, -2); /* remove only metatable */
224 return 1;
225 }
226}
227
228
229LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
230 obj = abs_index(L, obj);
231 if (!luaL_getmetafield(L, obj, event)) /* no metafield? */
232 return 0;
233 lua_pushvalue(L, obj);
234 lua_call(L, 1, 1);
235 return 1;
236}
237
238
239LUALIB_API const char *luaL_tostring (lua_State *L, int idx) {
240 if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */
241 switch (lua_type(L, idx)) {
242 case LUA_TNUMBER:
243 return lua_pushstring(L, lua_tostring(L, idx));
244 case LUA_TSTRING:
245 lua_pushvalue(L, idx);
246 break;
247 case LUA_TBOOLEAN:
248 return lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false"));
249 case LUA_TNIL:
250 return lua_pushliteral(L, "nil");
251 default:
252 return lua_pushfstring(L, "%s: %p", luaL_typename(L, idx),
253 lua_topointer(L, idx));
254 }
255 }
256 return lua_tostring(L, -1);
257}
258
259
260static int libsize (const luaL_Reg *l) {
261 int size = 0;
262 for (; l->name; l++) size++;
263 return size;
264}
265
266
267LUALIB_API void luaL_register (lua_State *L, const char *libname,
268 const luaL_Reg *l) {
269 if (libname) {
270 int size = libsize(l);
271 /* check whether lib already exists */
272 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", size);
273 lua_getfield(L, -1, libname); /* get _LOADED[libname] */
274 if (!lua_istable(L, -1)) { /* not found? */
275 lua_pop(L, 1); /* remove previous result */
276 /* try global variable (and create one if it does not exist) */
277 if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
278 luaL_error(L, "name conflict for module " LUA_QS, libname);
279 lua_pushvalue(L, -1);
280 lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
281 }
282 lua_remove(L, -2); /* remove _LOADED table */
283 }
284 for (; l->name; l++) {
285 lua_pushcfunction(L, l->func);
286 lua_setfield(L, -2, l->name);
287 }
288}
289
290
291LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
292 const char *r) {
293 const char *wild;
294 size_t l = strlen(p);
295 luaL_Buffer b;
296 luaL_buffinit(L, &b);
297 while ((wild = strstr(s, p)) != NULL) {
298 luaL_addlstring(&b, s, wild - s); /* push prefix */
299 luaL_addstring(&b, r); /* push replacement in place of pattern */
300 s = wild + l; /* continue after `p' */
301 }
302 luaL_addstring(&b, s); /* push last suffix */
303 luaL_pushresult(&b);
304 return lua_tostring(L, -1);
305}
306
307
308LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
309 const char *fname, int szhint) {
310 const char *e;
311 lua_pushvalue(L, idx);
312 do {
313 e = strchr(fname, '.');
314 if (e == NULL) e = fname + strlen(fname);
315 lua_pushlstring(L, fname, e - fname);
316 lua_rawget(L, -2);
317 if (lua_isnil(L, -1)) { /* no such field? */
318 lua_pop(L, 1); /* remove this nil */
319 lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
320 lua_pushlstring(L, fname, e - fname);
321 lua_pushvalue(L, -2);
322 lua_settable(L, -4); /* set new table into field */
323 }
324 else if (!lua_istable(L, -1)) { /* field has a non-table value? */
325 lua_pop(L, 2); /* remove table and value */
326 return fname; /* return problematic part of the name */
327 }
328 lua_remove(L, -2); /* remove previous table */
329 fname = e + 1;
330 } while (*e == '.');
331 return NULL;
332}
333
334 219
335 220
336/* 221/*
@@ -429,6 +314,18 @@ LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) {
429/* }====================================================== */ 314/* }====================================================== */
430 315
431 316
317/*
318** {======================================================
319** Reference system
320** =======================================================
321*/
322
323/* number of prereserved references (for internal use) */
324#define RESERVED_REFS 1 /* only FREELIST_REF is reserved */
325
326#define FREELIST_REF 1 /* free list of references */
327
328
432LUALIB_API int luaL_ref (lua_State *L, int t) { 329LUALIB_API int luaL_ref (lua_State *L, int t) {
433 int ref; 330 int ref;
434 t = abs_index(L, t); 331 t = abs_index(L, t);
@@ -464,6 +361,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) {
464 } 361 }
465} 362}
466 363
364/* }====================================================== */
467 365
468 366
469/* 367/*
@@ -572,9 +470,130 @@ LUALIB_API int luaL_loadstring (lua_State *L, const char *s) {
572 return luaL_loadbuffer(L, s, strlen(s), s); 470 return luaL_loadbuffer(L, s, strlen(s), s);
573} 471}
574 472
473/* }====================================================== */
575 474
576 475
577/* }====================================================== */ 476
477LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) {
478 if (!lua_getmetatable(L, obj)) /* no metatable? */
479 return 0;
480 lua_pushstring(L, event);
481 lua_rawget(L, -2);
482 if (lua_isnil(L, -1)) {
483 lua_pop(L, 2); /* remove metatable and metafield */
484 return 0;
485 }
486 else {
487 lua_remove(L, -2); /* remove only metatable */
488 return 1;
489 }
490}
491
492
493LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) {
494 obj = abs_index(L, obj);
495 if (!luaL_getmetafield(L, obj, event)) /* no metafield? */
496 return 0;
497 lua_pushvalue(L, obj);
498 lua_call(L, 1, 1);
499 return 1;
500}
501
502
503LUALIB_API const char *luaL_tostring (lua_State *L, int idx) {
504 if (!luaL_callmeta(L, idx, "__tostring")) { /* no metafield? */
505 switch (lua_type(L, idx)) {
506 case LUA_TNUMBER:
507 return lua_pushstring(L, lua_tostring(L, idx));
508 case LUA_TSTRING:
509 lua_pushvalue(L, idx);
510 break;
511 case LUA_TBOOLEAN:
512 return lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false"));
513 case LUA_TNIL:
514 return lua_pushliteral(L, "nil");
515 default:
516 return lua_pushfstring(L, "%s: %p", luaL_typename(L, idx),
517 lua_topointer(L, idx));
518 }
519 }
520 return lua_tostring(L, -1);
521}
522
523
524static int libsize (const luaL_Reg *l) {
525 int size = 0;
526 for (; l->name; l++) size++;
527 return size;
528}
529
530
531LUALIB_API void luaL_register (lua_State *L, const char *libname,
532 const luaL_Reg *l) {
533 if (libname) {
534 int size = libsize(l);
535 /* check whether lib already exists */
536 luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", size);
537 lua_getfield(L, -1, libname); /* get _LOADED[libname] */
538 if (!lua_istable(L, -1)) { /* not found? */
539 lua_pop(L, 1); /* remove previous result */
540 /* try global variable (and create one if it does not exist) */
541 if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL)
542 luaL_error(L, "name conflict for module " LUA_QS, libname);
543 lua_pushvalue(L, -1);
544 lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */
545 }
546 lua_remove(L, -2); /* remove _LOADED table */
547 }
548 for (; l->name; l++) {
549 lua_pushcfunction(L, l->func);
550 lua_setfield(L, -2, l->name);
551 }
552}
553
554
555LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p,
556 const char *r) {
557 const char *wild;
558 size_t l = strlen(p);
559 luaL_Buffer b;
560 luaL_buffinit(L, &b);
561 while ((wild = strstr(s, p)) != NULL) {
562 luaL_addlstring(&b, s, wild - s); /* push prefix */
563 luaL_addstring(&b, r); /* push replacement in place of pattern */
564 s = wild + l; /* continue after `p' */
565 }
566 luaL_addstring(&b, s); /* push last suffix */
567 luaL_pushresult(&b);
568 return lua_tostring(L, -1);
569}
570
571
572LUALIB_API const char *luaL_findtable (lua_State *L, int idx,
573 const char *fname, int szhint) {
574 const char *e;
575 lua_pushvalue(L, idx);
576 do {
577 e = strchr(fname, '.');
578 if (e == NULL) e = fname + strlen(fname);
579 lua_pushlstring(L, fname, e - fname);
580 lua_rawget(L, -2);
581 if (lua_isnil(L, -1)) { /* no such field? */
582 lua_pop(L, 1); /* remove this nil */
583 lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */
584 lua_pushlstring(L, fname, e - fname);
585 lua_pushvalue(L, -2);
586 lua_settable(L, -4); /* set new table into field */
587 }
588 else if (!lua_istable(L, -1)) { /* field has a non-table value? */
589 lua_pop(L, 2); /* remove table and value */
590 return fname; /* return problematic part of the name */
591 }
592 lua_remove(L, -2); /* remove previous table */
593 fname = e + 1;
594 } while (*e == '.');
595 return NULL;
596}
578 597
579 598
580static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { 599static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {