diff options
| author | Roberto I <roberto@inf.puc-rio.br> | 2026-04-23 17:58:55 -0300 |
|---|---|---|
| committer | Roberto I <roberto@inf.puc-rio.br> | 2026-04-23 17:58:55 -0300 |
| commit | 4c5d5063a54c0088729b16fb25a333f0f9f836b0 (patch) | |
| tree | 66cb68ffbc68a08b3327dcaf73404c7a2e7b412d | |
| parent | 3228a97c6a953dcf397944161bb64b12f1ff5384 (diff) | |
| download | lua-4c5d5063a54c0088729b16fb25a333f0f9f836b0.tar.gz lua-4c5d5063a54c0088729b16fb25a333f0f9f836b0.tar.bz2 lua-4c5d5063a54c0088729b16fb25a333f0f9f836b0.zip | |
'load' reader function doesn't need to preserve stack
| -rw-r--r-- | lbaselib.c | 27 |
1 files changed, 9 insertions, 18 deletions
| @@ -366,33 +366,24 @@ static int luaB_loadfile (lua_State *L) { | |||
| 366 | 366 | ||
| 367 | 367 | ||
| 368 | /* | 368 | /* |
| 369 | ** reserved slot, above all arguments, to hold a copy of the returned | 369 | ** Reader for generic 'load' function. |
| 370 | ** string to avoid it being collected while parsed. 'load' has four | ||
| 371 | ** optional arguments (chunk, source name, mode, and environment). | ||
| 372 | */ | ||
| 373 | #define RESERVEDSLOT 5 | ||
| 374 | |||
| 375 | |||
| 376 | /* | ||
| 377 | ** Reader for generic 'load' function: 'lua_load' uses the | ||
| 378 | ** stack for internal stuff, so the reader cannot change the | ||
| 379 | ** stack top. Instead, it keeps its resulting string in a | ||
| 380 | ** reserved slot inside the stack. | ||
| 381 | */ | 370 | */ |
| 382 | static const char *generic_reader (lua_State *L, void *ud, size_t *size) { | 371 | static const char *generic_reader (lua_State *L, void *ud, size_t *size) { |
| 383 | (void)(ud); /* not used */ | 372 | int *firstcall = cast(int *, ud); |
| 384 | luaL_checkstack(L, 2, "too many nested functions"); | 373 | luaL_checkstack(L, 2, "too many nested functions"); |
| 374 | if (*firstcall) | ||
| 375 | *firstcall = 0; | ||
| 376 | else | ||
| 377 | lua_pop(L, 1); /* remove previous result */ | ||
| 385 | lua_pushvalue(L, 1); /* get function */ | 378 | lua_pushvalue(L, 1); /* get function */ |
| 386 | lua_call(L, 0, 1); /* call it */ | 379 | lua_call(L, 0, 1); /* call it */ |
| 387 | if (lua_isnil(L, -1)) { | 380 | if (lua_isnil(L, -1)) { |
| 388 | lua_pop(L, 1); /* pop result */ | ||
| 389 | *size = 0; | 381 | *size = 0; |
| 390 | return NULL; | 382 | return NULL; |
| 391 | } | 383 | } |
| 392 | else if (l_unlikely(!lua_isstring(L, -1))) | 384 | else if (l_unlikely(!lua_isstring(L, -1))) |
| 393 | luaL_error(L, "reader function must return a string"); | 385 | luaL_error(L, "reader function must return a string"); |
| 394 | lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ | 386 | return lua_tolstring(L, -1, size); |
| 395 | return lua_tolstring(L, RESERVEDSLOT, size); | ||
| 396 | } | 387 | } |
| 397 | 388 | ||
| 398 | 389 | ||
| @@ -407,10 +398,10 @@ static int luaB_load (lua_State *L) { | |||
| 407 | status = luaL_loadbufferx(L, s, l, chunkname, mode); | 398 | status = luaL_loadbufferx(L, s, l, chunkname, mode); |
| 408 | } | 399 | } |
| 409 | else { /* loading from a reader function */ | 400 | else { /* loading from a reader function */ |
| 401 | int firstcall = 1; /* userdata for generic_reader */ | ||
| 410 | const char *chunkname = luaL_optstring(L, 2, "=(load)"); | 402 | const char *chunkname = luaL_optstring(L, 2, "=(load)"); |
| 411 | luaL_checktype(L, 1, LUA_TFUNCTION); | 403 | luaL_checktype(L, 1, LUA_TFUNCTION); |
| 412 | lua_settop(L, RESERVEDSLOT); /* create reserved slot */ | 404 | status = lua_load(L, generic_reader, &firstcall, chunkname, mode); |
| 413 | status = lua_load(L, generic_reader, NULL, chunkname, mode); | ||
| 414 | } | 405 | } |
| 415 | return load_aux(L, status, env); | 406 | return load_aux(L, status, env); |
| 416 | } | 407 | } |
