diff options
Diffstat (limited to 'lbaselib.c')
-rw-r--r-- | lbaselib.c | 84 |
1 files changed, 61 insertions, 23 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lbaselib.c,v 1.221 2009/10/23 19:12:19 roberto Exp roberto $ | 2 | ** $Id: lbaselib.c,v 1.222 2009/11/09 18:55:17 roberto Exp roberto $ |
3 | ** Basic library | 3 | ** Basic library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -276,13 +276,11 @@ static int luaB_loadfile (lua_State *L) { | |||
276 | 276 | ||
277 | 277 | ||
278 | /* | 278 | /* |
279 | ** Reader for generic `load' function: `lua_load' uses the | 279 | ** {====================================================== |
280 | ** stack for internal stuff, so the reader cannot change the | 280 | ** Generic Read function |
281 | ** stack top. Instead, it keeps its resulting string in a | 281 | ** ======================================================= |
282 | ** reserved slot inside the stack. | ||
283 | */ | 282 | */ |
284 | 283 | ||
285 | |||
286 | static const char *checkrights (lua_State *L, const char *mode, const char *s) { | 284 | static const char *checkrights (lua_State *L, const char *mode, const char *s) { |
287 | if (strchr(mode, 'b') == NULL && *s == LUA_SIGNATURE[0]) | 285 | if (strchr(mode, 'b') == NULL && *s == LUA_SIGNATURE[0]) |
288 | return lua_pushstring(L, "attempt to load a binary chunk"); | 286 | return lua_pushstring(L, "attempt to load a binary chunk"); |
@@ -292,24 +290,42 @@ static const char *checkrights (lua_State *L, const char *mode, const char *s) { | |||
292 | } | 290 | } |
293 | 291 | ||
294 | 292 | ||
293 | /* | ||
294 | ** reserves a slot, above all arguments, to hold a copy of the returned | ||
295 | ** string to avoid it being collected while parsed | ||
296 | */ | ||
297 | #define RESERVEDSLOT 4 | ||
298 | |||
299 | |||
300 | /* | ||
301 | ** Reader for generic `load' function: `lua_load' uses the | ||
302 | ** stack for internal stuff, so the reader cannot change the | ||
303 | ** stack top. Instead, it keeps its resulting string in a | ||
304 | ** reserved slot inside the stack. | ||
305 | */ | ||
306 | typedef struct { /* reader state */ | ||
307 | int f; /* position of reader function on stack */ | ||
308 | const char *mode; /* allowed modes (binary/text) */ | ||
309 | } Readstat; | ||
310 | |||
295 | static const char *generic_reader (lua_State *L, void *ud, size_t *size) { | 311 | static const char *generic_reader (lua_State *L, void *ud, size_t *size) { |
296 | const char *s; | 312 | const char *s; |
297 | const char **mode = (const char **)ud; | 313 | Readstat *stat = (Readstat *)ud; |
298 | luaL_checkstack(L, 2, "too many nested functions"); | 314 | luaL_checkstack(L, 2, "too many nested functions"); |
299 | lua_pushvalue(L, 1); /* get function */ | 315 | lua_pushvalue(L, stat->f); /* get function */ |
300 | lua_call(L, 0, 1); /* call it */ | 316 | lua_call(L, 0, 1); /* call it */ |
301 | if (lua_isnil(L, -1)) { | 317 | if (lua_isnil(L, -1)) { |
302 | *size = 0; | 318 | *size = 0; |
303 | return NULL; | 319 | return NULL; |
304 | } | 320 | } |
305 | else if ((s = lua_tostring(L, -1)) != NULL) { | 321 | else if ((s = lua_tostring(L, -1)) != NULL) { |
306 | if (*mode != NULL) { /* first time? */ | 322 | if (stat->mode != NULL) { /* first time? */ |
307 | s = checkrights(L, *mode, s); /* check whether chunk format is allowed */ | 323 | s = checkrights(L, stat->mode, s); /* check mode */ |
308 | *mode = NULL; /* to avoid further checks */ | 324 | stat->mode = NULL; /* to avoid further checks */ |
309 | if (s) luaL_error(L, s); | 325 | if (s) luaL_error(L, s); |
310 | } | 326 | } |
311 | lua_replace(L, 3); /* save string in a reserved stack slot */ | 327 | lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ |
312 | return lua_tolstring(L, 3, size); | 328 | return lua_tolstring(L, RESERVEDSLOT, size); |
313 | } | 329 | } |
314 | else { | 330 | else { |
315 | luaL_error(L, "reader function must return a string"); | 331 | luaL_error(L, "reader function must return a string"); |
@@ -318,30 +334,51 @@ static const char *generic_reader (lua_State *L, void *ud, size_t *size) { | |||
318 | } | 334 | } |
319 | 335 | ||
320 | 336 | ||
321 | static int luaB_load (lua_State *L) { | 337 | static int luaB_load_aux (lua_State *L, int farg) { |
322 | int status; | 338 | int status; |
323 | const char *s = lua_tostring(L, 1); | 339 | Readstat stat; |
324 | const char *mode = luaL_optstring(L, 3, "bt"); | 340 | const char *s = lua_tostring(L, farg); |
341 | stat.mode = luaL_optstring(L, farg + 2, "bt"); | ||
325 | if (s != NULL) { /* loading a string? */ | 342 | if (s != NULL) { /* loading a string? */ |
326 | const char *chunkname = luaL_optstring(L, 2, s); | 343 | const char *chunkname = luaL_optstring(L, farg + 1, s); |
327 | status = (checkrights(L, mode, s) != NULL) | 344 | status = (checkrights(L, stat.mode, s) != NULL) |
328 | || luaL_loadbuffer(L, s, lua_objlen(L, 1), chunkname); | 345 | || luaL_loadbuffer(L, s, lua_objlen(L, farg), chunkname); |
329 | } | 346 | } |
330 | else { /* loading from a reader function */ | 347 | else { /* loading from a reader function */ |
331 | const char *chunkname = luaL_optstring(L, 2, "=(load)"); | 348 | const char *chunkname = luaL_optstring(L, farg + 1, "=(load)"); |
332 | luaL_checktype(L, 1, LUA_TFUNCTION); | 349 | luaL_checktype(L, farg, LUA_TFUNCTION); |
333 | lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ | 350 | stat.f = farg; |
334 | status = lua_load(L, generic_reader, &mode, chunkname); | 351 | lua_settop(L, RESERVEDSLOT); /* create reserved slot */ |
352 | status = lua_load(L, generic_reader, &stat, chunkname); | ||
335 | } | 353 | } |
336 | return load_aux(L, status); | 354 | return load_aux(L, status); |
337 | } | 355 | } |
338 | 356 | ||
339 | 357 | ||
358 | static int luaB_load (lua_State *L) { | ||
359 | return luaB_load_aux(L, 1); | ||
360 | } | ||
361 | |||
362 | |||
363 | static int luaB_loadin (lua_State *L) { | ||
364 | int n; | ||
365 | luaL_checktype(L, 1, LUA_TTABLE); | ||
366 | n = luaB_load_aux(L, 2); | ||
367 | if (n == 1) { /* success? */ | ||
368 | lua_pushvalue(L, 1); /* environment for loaded function */ | ||
369 | lua_setfenv(L, -2); | ||
370 | } | ||
371 | return n; | ||
372 | } | ||
373 | |||
374 | |||
340 | static int luaB_loadstring (lua_State *L) { | 375 | static int luaB_loadstring (lua_State *L) { |
341 | lua_settop(L, 2); | 376 | lua_settop(L, 2); |
342 | lua_pushliteral(L, "tb"); | 377 | lua_pushliteral(L, "tb"); |
343 | return luaB_load(L); /* dostring(s, n) == load(s, n, "tb") */ | 378 | return luaB_load(L); /* dostring(s, n) == load(s, n, "tb") */ |
379 | |||
344 | } | 380 | } |
381 | /* }====================================================== */ | ||
345 | 382 | ||
346 | 383 | ||
347 | static int dofilecont (lua_State *L) { | 384 | static int dofilecont (lua_State *L) { |
@@ -481,6 +518,7 @@ static const luaL_Reg base_funcs[] = { | |||
481 | {"getmetatable", luaB_getmetatable}, | 518 | {"getmetatable", luaB_getmetatable}, |
482 | {"loadfile", luaB_loadfile}, | 519 | {"loadfile", luaB_loadfile}, |
483 | {"load", luaB_load}, | 520 | {"load", luaB_load}, |
521 | {"loadin", luaB_loadin}, | ||
484 | {"loadstring", luaB_loadstring}, | 522 | {"loadstring", luaB_loadstring}, |
485 | {"next", luaB_next}, | 523 | {"next", luaB_next}, |
486 | {"pcall", luaB_pcall}, | 524 | {"pcall", luaB_pcall}, |