diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-10-31 14:54:45 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-10-31 14:54:45 -0300 |
commit | 947a372f5860a76fcafb4a2845abc322e440d6fc (patch) | |
tree | e35840847207c850af5262f93f863f583d2af76d /liolib.c | |
parent | e073cbc2e538369e0611abfc9948f301aea6aef3 (diff) | |
download | lua-947a372f5860a76fcafb4a2845abc322e440d6fc.tar.gz lua-947a372f5860a76fcafb4a2845abc322e440d6fc.tar.bz2 lua-947a372f5860a76fcafb4a2845abc322e440d6fc.zip |
State in generic 'for' acts as a to-be-closed variable
The implicit variable 'state' in a generic 'for' is marked as a
to-be-closed variable, so that the state will be closed as soon
as the loop ends, no matter how.
Taking advantage of this new facility, the call 'io.lines(filename)'
now returns the open file as a second result. Therefore,
an iteraction like 'for l in io.lines(name)...' will close the
file even when the loop ends with a break or an error.
Diffstat (limited to 'liolib.c')
-rw-r--r-- | liolib.c | 35 |
1 files changed, 29 insertions, 6 deletions
@@ -354,12 +354,22 @@ static int io_readline (lua_State *L); | |||
354 | */ | 354 | */ |
355 | #define MAXARGLINE 250 | 355 | #define MAXARGLINE 250 |
356 | 356 | ||
357 | /* | ||
358 | ** Auxiliar function to create the iteration function for 'lines'. | ||
359 | ** The iteration function is a closure over 'io_readline', with | ||
360 | ** the following upvalues: | ||
361 | ** 1) The file being read (first value in the stack) | ||
362 | ** 2) the number of arguments to read | ||
363 | ** 3) a boolean, true iff file has to be closed when finished ('toclose') | ||
364 | ** *) a variable number of format arguments (rest of the stack) | ||
365 | */ | ||
357 | static void aux_lines (lua_State *L, int toclose) { | 366 | static void aux_lines (lua_State *L, int toclose) { |
358 | int n = lua_gettop(L) - 1; /* number of arguments to read */ | 367 | int n = lua_gettop(L) - 1; /* number of arguments to read */ |
359 | luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); | 368 | luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); |
369 | lua_pushvalue(L, 1); /* file */ | ||
360 | lua_pushinteger(L, n); /* number of arguments to read */ | 370 | lua_pushinteger(L, n); /* number of arguments to read */ |
361 | lua_pushboolean(L, toclose); /* close/not close file when finished */ | 371 | lua_pushboolean(L, toclose); /* close/not close file when finished */ |
362 | lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */ | 372 | lua_rotate(L, 2, 3); /* move the three values to their positions */ |
363 | lua_pushcclosure(L, io_readline, 3 + n); | 373 | lua_pushcclosure(L, io_readline, 3 + n); |
364 | } | 374 | } |
365 | 375 | ||
@@ -371,6 +381,11 @@ static int f_lines (lua_State *L) { | |||
371 | } | 381 | } |
372 | 382 | ||
373 | 383 | ||
384 | /* | ||
385 | ** Return an iteration function for 'io.lines'. If file has to be | ||
386 | ** closed, also returns the file itself as a second result (to be | ||
387 | ** closed as the state at the exit of a generic for). | ||
388 | */ | ||
374 | static int io_lines (lua_State *L) { | 389 | static int io_lines (lua_State *L) { |
375 | int toclose; | 390 | int toclose; |
376 | if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ | 391 | if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ |
@@ -386,8 +401,13 @@ static int io_lines (lua_State *L) { | |||
386 | lua_replace(L, 1); /* put file at index 1 */ | 401 | lua_replace(L, 1); /* put file at index 1 */ |
387 | toclose = 1; /* close it after iteration */ | 402 | toclose = 1; /* close it after iteration */ |
388 | } | 403 | } |
389 | aux_lines(L, toclose); | 404 | aux_lines(L, toclose); /* push iteration function */ |
390 | return 1; | 405 | if (toclose) { |
406 | lua_pushvalue(L, 1); /* file will be second result */ | ||
407 | return 2; | ||
408 | } | ||
409 | else | ||
410 | return 1; | ||
391 | } | 411 | } |
392 | 412 | ||
393 | 413 | ||
@@ -453,7 +473,7 @@ static int readdigits (RN *rn, int hex) { | |||
453 | /* | 473 | /* |
454 | ** Read a number: first reads a valid prefix of a numeral into a buffer. | 474 | ** Read a number: first reads a valid prefix of a numeral into a buffer. |
455 | ** Then it calls 'lua_stringtonumber' to check whether the format is | 475 | ** Then it calls 'lua_stringtonumber' to check whether the format is |
456 | ** correct and to convert it to a Lua number | 476 | ** correct and to convert it to a Lua number. |
457 | */ | 477 | */ |
458 | static int read_number (lua_State *L, FILE *f) { | 478 | static int read_number (lua_State *L, FILE *f) { |
459 | RN rn; | 479 | RN rn; |
@@ -604,6 +624,9 @@ static int f_read (lua_State *L) { | |||
604 | } | 624 | } |
605 | 625 | ||
606 | 626 | ||
627 | /* | ||
628 | ** Iteration function for 'lines'. | ||
629 | */ | ||
607 | static int io_readline (lua_State *L) { | 630 | static int io_readline (lua_State *L) { |
608 | LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); | 631 | LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); |
609 | int i; | 632 | int i; |
@@ -624,8 +647,8 @@ static int io_readline (lua_State *L) { | |||
624 | return luaL_error(L, "%s", lua_tostring(L, -n + 1)); | 647 | return luaL_error(L, "%s", lua_tostring(L, -n + 1)); |
625 | } | 648 | } |
626 | if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ | 649 | if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ |
627 | lua_settop(L, 0); | 650 | lua_settop(L, 0); /* clear stack */ |
628 | lua_pushvalue(L, lua_upvalueindex(1)); | 651 | lua_pushvalue(L, lua_upvalueindex(1)); /* push file at index 1 */ |
629 | aux_close(L); /* close it */ | 652 | aux_close(L); /* close it */ |
630 | } | 653 | } |
631 | return 0; | 654 | return 0; |