diff options
author | Li Jin <dragon-fly@qq.com> | 2020-06-22 16:50:40 +0800 |
---|---|---|
committer | Li Jin <dragon-fly@qq.com> | 2020-06-22 16:50:40 +0800 |
commit | cd2b60b101a398cb9356d746364e70eaed1860f1 (patch) | |
tree | a1fe71b76faabc4883f16905a94164ce5c23e692 /src/lua/liolib.c | |
parent | 88c1052e700f38cf3d8ad82d469da4c487760b7e (diff) | |
download | yuescript-cd2b60b101a398cb9356d746364e70eaed1860f1.tar.gz yuescript-cd2b60b101a398cb9356d746364e70eaed1860f1.tar.bz2 yuescript-cd2b60b101a398cb9356d746364e70eaed1860f1.zip |
add support for local variable declared with attribute 'close' and 'const' for Lua 5.4.
Diffstat (limited to '')
-rw-r--r-- | src/lua/liolib.c (renamed from src/lua-5.3/liolib.c) | 112 |
1 files changed, 75 insertions, 37 deletions
diff --git a/src/lua-5.3/liolib.c b/src/lua/liolib.c index 8a9e75c..7ac3444 100644 --- a/src/lua-5.3/liolib.c +++ b/src/lua/liolib.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 2.151.1.1 2017/04/19 17:29:57 roberto Exp $ | 2 | ** $Id: liolib.c $ |
3 | ** Standard I/O (and system) library | 3 | ** Standard I/O (and system) library |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -39,7 +39,7 @@ | |||
39 | /* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */ | 39 | /* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */ |
40 | static int l_checkmode (const char *mode) { | 40 | static int l_checkmode (const char *mode) { |
41 | return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && | 41 | return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && |
42 | (*mode != '+' || (++mode, 1)) && /* skip if char is '+' */ | 42 | (*mode != '+' || ((void)(++mode), 1)) && /* skip if char is '+' */ |
43 | (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */ | 43 | (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */ |
44 | } | 44 | } |
45 | 45 | ||
@@ -68,7 +68,7 @@ static int l_checkmode (const char *mode) { | |||
68 | 68 | ||
69 | /* ISO C definitions */ | 69 | /* ISO C definitions */ |
70 | #define l_popen(L,c,m) \ | 70 | #define l_popen(L,c,m) \ |
71 | ((void)((void)c, m), \ | 71 | ((void)c, (void)m, \ |
72 | luaL_error(L, "'popen' not supported"), \ | 72 | luaL_error(L, "'popen' not supported"), \ |
73 | (FILE*)0) | 73 | (FILE*)0) |
74 | #define l_pclose(L,file) ((void)L, (void)file, -1) | 74 | #define l_pclose(L,file) ((void)L, (void)file, -1) |
@@ -133,6 +133,7 @@ static int l_checkmode (const char *mode) { | |||
133 | /* }====================================================== */ | 133 | /* }====================================================== */ |
134 | 134 | ||
135 | 135 | ||
136 | |||
136 | #define IO_PREFIX "_IO_" | 137 | #define IO_PREFIX "_IO_" |
137 | #define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1) | 138 | #define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1) |
138 | #define IO_INPUT (IO_PREFIX "input") | 139 | #define IO_INPUT (IO_PREFIX "input") |
@@ -152,7 +153,7 @@ static int io_type (lua_State *L) { | |||
152 | luaL_checkany(L, 1); | 153 | luaL_checkany(L, 1); |
153 | p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); | 154 | p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); |
154 | if (p == NULL) | 155 | if (p == NULL) |
155 | lua_pushnil(L); /* not a file */ | 156 | luaL_pushfail(L); /* not a file */ |
156 | else if (isclosed(p)) | 157 | else if (isclosed(p)) |
157 | lua_pushliteral(L, "closed file"); | 158 | lua_pushliteral(L, "closed file"); |
158 | else | 159 | else |
@@ -186,7 +187,7 @@ static FILE *tofile (lua_State *L) { | |||
186 | ** handle is in a consistent state. | 187 | ** handle is in a consistent state. |
187 | */ | 188 | */ |
188 | static LStream *newprefile (lua_State *L) { | 189 | static LStream *newprefile (lua_State *L) { |
189 | LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); | 190 | LStream *p = (LStream *)lua_newuserdatauv(L, sizeof(LStream), 0); |
190 | p->closef = NULL; /* mark file handle as 'closed' */ | 191 | p->closef = NULL; /* mark file handle as 'closed' */ |
191 | luaL_setmetatable(L, LUA_FILEHANDLE); | 192 | luaL_setmetatable(L, LUA_FILEHANDLE); |
192 | return p; | 193 | return p; |
@@ -214,7 +215,7 @@ static int f_close (lua_State *L) { | |||
214 | 215 | ||
215 | static int io_close (lua_State *L) { | 216 | static int io_close (lua_State *L) { |
216 | if (lua_isnone(L, 1)) /* no argument? */ | 217 | if (lua_isnone(L, 1)) /* no argument? */ |
217 | lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ | 218 | lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use default output */ |
218 | return f_close(L); | 219 | return f_close(L); |
219 | } | 220 | } |
220 | 221 | ||
@@ -269,6 +270,7 @@ static int io_open (lua_State *L) { | |||
269 | */ | 270 | */ |
270 | static int io_pclose (lua_State *L) { | 271 | static int io_pclose (lua_State *L) { |
271 | LStream *p = tolstream(L); | 272 | LStream *p = tolstream(L); |
273 | errno = 0; | ||
272 | return luaL_execresult(L, l_pclose(L, p->f)); | 274 | return luaL_execresult(L, l_pclose(L, p->f)); |
273 | } | 275 | } |
274 | 276 | ||
@@ -295,7 +297,7 @@ static FILE *getiofile (lua_State *L, const char *findex) { | |||
295 | lua_getfield(L, LUA_REGISTRYINDEX, findex); | 297 | lua_getfield(L, LUA_REGISTRYINDEX, findex); |
296 | p = (LStream *)lua_touserdata(L, -1); | 298 | p = (LStream *)lua_touserdata(L, -1); |
297 | if (isclosed(p)) | 299 | if (isclosed(p)) |
298 | luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN); | 300 | luaL_error(L, "default %s file is closed", findex + IOPREF_LEN); |
299 | return p->f; | 301 | return p->f; |
300 | } | 302 | } |
301 | 303 | ||
@@ -336,12 +338,22 @@ static int io_readline (lua_State *L); | |||
336 | */ | 338 | */ |
337 | #define MAXARGLINE 250 | 339 | #define MAXARGLINE 250 |
338 | 340 | ||
341 | /* | ||
342 | ** Auxiliary function to create the iteration function for 'lines'. | ||
343 | ** The iteration function is a closure over 'io_readline', with | ||
344 | ** the following upvalues: | ||
345 | ** 1) The file being read (first value in the stack) | ||
346 | ** 2) the number of arguments to read | ||
347 | ** 3) a boolean, true iff file has to be closed when finished ('toclose') | ||
348 | ** *) a variable number of format arguments (rest of the stack) | ||
349 | */ | ||
339 | static void aux_lines (lua_State *L, int toclose) { | 350 | static void aux_lines (lua_State *L, int toclose) { |
340 | int n = lua_gettop(L) - 1; /* number of arguments to read */ | 351 | int n = lua_gettop(L) - 1; /* number of arguments to read */ |
341 | luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); | 352 | luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); |
353 | lua_pushvalue(L, 1); /* file */ | ||
342 | lua_pushinteger(L, n); /* number of arguments to read */ | 354 | lua_pushinteger(L, n); /* number of arguments to read */ |
343 | lua_pushboolean(L, toclose); /* close/not close file when finished */ | 355 | lua_pushboolean(L, toclose); /* close/not close file when finished */ |
344 | lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */ | 356 | lua_rotate(L, 2, 3); /* move the three values to their positions */ |
345 | lua_pushcclosure(L, io_readline, 3 + n); | 357 | lua_pushcclosure(L, io_readline, 3 + n); |
346 | } | 358 | } |
347 | 359 | ||
@@ -353,6 +365,11 @@ static int f_lines (lua_State *L) { | |||
353 | } | 365 | } |
354 | 366 | ||
355 | 367 | ||
368 | /* | ||
369 | ** Return an iteration function for 'io.lines'. If file has to be | ||
370 | ** closed, also returns the file itself as a second result (to be | ||
371 | ** closed as the state at the exit of a generic for). | ||
372 | */ | ||
356 | static int io_lines (lua_State *L) { | 373 | static int io_lines (lua_State *L) { |
357 | int toclose; | 374 | int toclose; |
358 | if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ | 375 | if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ |
@@ -368,8 +385,15 @@ static int io_lines (lua_State *L) { | |||
368 | lua_replace(L, 1); /* put file at index 1 */ | 385 | lua_replace(L, 1); /* put file at index 1 */ |
369 | toclose = 1; /* close it after iteration */ | 386 | toclose = 1; /* close it after iteration */ |
370 | } | 387 | } |
371 | aux_lines(L, toclose); | 388 | aux_lines(L, toclose); /* push iteration function */ |
372 | return 1; | 389 | if (toclose) { |
390 | lua_pushnil(L); /* state */ | ||
391 | lua_pushnil(L); /* control */ | ||
392 | lua_pushvalue(L, 1); /* file is the to-be-closed variable (4th result) */ | ||
393 | return 4; | ||
394 | } | ||
395 | else | ||
396 | return 1; | ||
373 | } | 397 | } |
374 | 398 | ||
375 | 399 | ||
@@ -435,7 +459,7 @@ static int readdigits (RN *rn, int hex) { | |||
435 | /* | 459 | /* |
436 | ** Read a number: first reads a valid prefix of a numeral into a buffer. | 460 | ** Read a number: first reads a valid prefix of a numeral into a buffer. |
437 | ** Then it calls 'lua_stringtonumber' to check whether the format is | 461 | ** Then it calls 'lua_stringtonumber' to check whether the format is |
438 | ** correct and to convert it to a Lua number | 462 | ** correct and to convert it to a Lua number. |
439 | */ | 463 | */ |
440 | static int read_number (lua_State *L, FILE *f) { | 464 | static int read_number (lua_State *L, FILE *f) { |
441 | RN rn; | 465 | RN rn; |
@@ -447,7 +471,7 @@ static int read_number (lua_State *L, FILE *f) { | |||
447 | decp[1] = '.'; /* always accept a dot */ | 471 | decp[1] = '.'; /* always accept a dot */ |
448 | l_lockfile(rn.f); | 472 | l_lockfile(rn.f); |
449 | do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ | 473 | do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ |
450 | test2(&rn, "-+"); /* optional signal */ | 474 | test2(&rn, "-+"); /* optional sign */ |
451 | if (test2(&rn, "00")) { | 475 | if (test2(&rn, "00")) { |
452 | if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ | 476 | if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ |
453 | else count = 1; /* count initial '0' as a valid digit */ | 477 | else count = 1; /* count initial '0' as a valid digit */ |
@@ -456,7 +480,7 @@ static int read_number (lua_State *L, FILE *f) { | |||
456 | if (test2(&rn, decp)) /* decimal point? */ | 480 | if (test2(&rn, decp)) /* decimal point? */ |
457 | count += readdigits(&rn, hex); /* fractional part */ | 481 | count += readdigits(&rn, hex); /* fractional part */ |
458 | if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */ | 482 | if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */ |
459 | test2(&rn, "-+"); /* exponent signal */ | 483 | test2(&rn, "-+"); /* exponent sign */ |
460 | readdigits(&rn, 0); /* exponent digits */ | 484 | readdigits(&rn, 0); /* exponent digits */ |
461 | } | 485 | } |
462 | ungetc(rn.c, rn.f); /* unread look-ahead char */ | 486 | ungetc(rn.c, rn.f); /* unread look-ahead char */ |
@@ -481,17 +505,17 @@ static int test_eof (lua_State *L, FILE *f) { | |||
481 | 505 | ||
482 | static int read_line (lua_State *L, FILE *f, int chop) { | 506 | static int read_line (lua_State *L, FILE *f, int chop) { |
483 | luaL_Buffer b; | 507 | luaL_Buffer b; |
484 | int c = '\0'; | 508 | int c; |
485 | luaL_buffinit(L, &b); | 509 | luaL_buffinit(L, &b); |
486 | while (c != EOF && c != '\n') { /* repeat until end of line */ | 510 | do { /* may need to read several chunks to get whole line */ |
487 | char *buff = luaL_prepbuffer(&b); /* preallocate buffer */ | 511 | char *buff = luaL_prepbuffer(&b); /* preallocate buffer space */ |
488 | int i = 0; | 512 | int i = 0; |
489 | l_lockfile(f); /* no memory errors can happen inside the lock */ | 513 | l_lockfile(f); /* no memory errors can happen inside the lock */ |
490 | while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n') | 514 | while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n') |
491 | buff[i++] = c; | 515 | buff[i++] = c; /* read up to end of line or buffer limit */ |
492 | l_unlockfile(f); | 516 | l_unlockfile(f); |
493 | luaL_addsize(&b, i); | 517 | luaL_addsize(&b, i); |
494 | } | 518 | } while (c != EOF && c != '\n'); /* repeat until end of line */ |
495 | if (!chop && c == '\n') /* want a newline and have one? */ | 519 | if (!chop && c == '\n') /* want a newline and have one? */ |
496 | luaL_addchar(&b, c); /* add ending newline to result */ | 520 | luaL_addchar(&b, c); /* add ending newline to result */ |
497 | luaL_pushresult(&b); /* close buffer */ | 521 | luaL_pushresult(&b); /* close buffer */ |
@@ -528,14 +552,14 @@ static int read_chars (lua_State *L, FILE *f, size_t n) { | |||
528 | 552 | ||
529 | static int g_read (lua_State *L, FILE *f, int first) { | 553 | static int g_read (lua_State *L, FILE *f, int first) { |
530 | int nargs = lua_gettop(L) - 1; | 554 | int nargs = lua_gettop(L) - 1; |
531 | int success; | 555 | int n, success; |
532 | int n; | ||
533 | clearerr(f); | 556 | clearerr(f); |
534 | if (nargs == 0) { /* no arguments? */ | 557 | if (nargs == 0) { /* no arguments? */ |
535 | success = read_line(L, f, 1); | 558 | success = read_line(L, f, 1); |
536 | n = first+1; /* to return 1 result */ | 559 | n = first + 1; /* to return 1 result */ |
537 | } | 560 | } |
538 | else { /* ensure stack space for all results and for auxlib's buffer */ | 561 | else { |
562 | /* ensure stack space for all results and for auxlib's buffer */ | ||
539 | luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); | 563 | luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); |
540 | success = 1; | 564 | success = 1; |
541 | for (n = first; nargs-- && success; n++) { | 565 | for (n = first; nargs-- && success; n++) { |
@@ -570,7 +594,7 @@ static int g_read (lua_State *L, FILE *f, int first) { | |||
570 | return luaL_fileresult(L, 0, NULL); | 594 | return luaL_fileresult(L, 0, NULL); |
571 | if (!success) { | 595 | if (!success) { |
572 | lua_pop(L, 1); /* remove last result */ | 596 | lua_pop(L, 1); /* remove last result */ |
573 | lua_pushnil(L); /* push nil instead */ | 597 | luaL_pushfail(L); /* push nil instead */ |
574 | } | 598 | } |
575 | return n - first; | 599 | return n - first; |
576 | } | 600 | } |
@@ -586,6 +610,9 @@ static int f_read (lua_State *L) { | |||
586 | } | 610 | } |
587 | 611 | ||
588 | 612 | ||
613 | /* | ||
614 | ** Iteration function for 'lines'. | ||
615 | */ | ||
589 | static int io_readline (lua_State *L) { | 616 | static int io_readline (lua_State *L) { |
590 | LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); | 617 | LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); |
591 | int i; | 618 | int i; |
@@ -600,14 +627,14 @@ static int io_readline (lua_State *L) { | |||
600 | lua_assert(n > 0); /* should return at least a nil */ | 627 | lua_assert(n > 0); /* should return at least a nil */ |
601 | if (lua_toboolean(L, -n)) /* read at least one value? */ | 628 | if (lua_toboolean(L, -n)) /* read at least one value? */ |
602 | return n; /* return them */ | 629 | return n; /* return them */ |
603 | else { /* first result is nil: EOF or error */ | 630 | else { /* first result is false: EOF or error */ |
604 | if (n > 1) { /* is there error information? */ | 631 | if (n > 1) { /* is there error information? */ |
605 | /* 2nd result is error message */ | 632 | /* 2nd result is error message */ |
606 | return luaL_error(L, "%s", lua_tostring(L, -n + 1)); | 633 | return luaL_error(L, "%s", lua_tostring(L, -n + 1)); |
607 | } | 634 | } |
608 | if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ | 635 | if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ |
609 | lua_settop(L, 0); | 636 | lua_settop(L, 0); /* clear stack */ |
610 | lua_pushvalue(L, lua_upvalueindex(1)); | 637 | lua_pushvalue(L, lua_upvalueindex(1)); /* push file at index 1 */ |
611 | aux_close(L); /* close it */ | 638 | aux_close(L); /* close it */ |
612 | } | 639 | } |
613 | return 0; | 640 | return 0; |
@@ -716,26 +743,37 @@ static const luaL_Reg iolib[] = { | |||
716 | /* | 743 | /* |
717 | ** methods for file handles | 744 | ** methods for file handles |
718 | */ | 745 | */ |
719 | static const luaL_Reg flib[] = { | 746 | static const luaL_Reg meth[] = { |
720 | {"close", f_close}, | ||
721 | {"flush", f_flush}, | ||
722 | {"lines", f_lines}, | ||
723 | {"read", f_read}, | 747 | {"read", f_read}, |
748 | {"write", f_write}, | ||
749 | {"lines", f_lines}, | ||
750 | {"flush", f_flush}, | ||
724 | {"seek", f_seek}, | 751 | {"seek", f_seek}, |
752 | {"close", f_close}, | ||
725 | {"setvbuf", f_setvbuf}, | 753 | {"setvbuf", f_setvbuf}, |
726 | {"write", f_write}, | 754 | {NULL, NULL} |
755 | }; | ||
756 | |||
757 | |||
758 | /* | ||
759 | ** metamethods for file handles | ||
760 | */ | ||
761 | static const luaL_Reg metameth[] = { | ||
762 | {"__index", NULL}, /* place holder */ | ||
727 | {"__gc", f_gc}, | 763 | {"__gc", f_gc}, |
764 | {"__close", f_gc}, | ||
728 | {"__tostring", f_tostring}, | 765 | {"__tostring", f_tostring}, |
729 | {NULL, NULL} | 766 | {NULL, NULL} |
730 | }; | 767 | }; |
731 | 768 | ||
732 | 769 | ||
733 | static void createmeta (lua_State *L) { | 770 | static void createmeta (lua_State *L) { |
734 | luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ | 771 | luaL_newmetatable(L, LUA_FILEHANDLE); /* metatable for file handles */ |
735 | lua_pushvalue(L, -1); /* push metatable */ | 772 | luaL_setfuncs(L, metameth, 0); /* add metamethods to new metatable */ |
736 | lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ | 773 | luaL_newlibtable(L, meth); /* create method table */ |
737 | luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ | 774 | luaL_setfuncs(L, meth, 0); /* add file methods to method table */ |
738 | lua_pop(L, 1); /* pop new metatable */ | 775 | lua_setfield(L, -2, "__index"); /* metatable.__index = method table */ |
776 | lua_pop(L, 1); /* pop metatable */ | ||
739 | } | 777 | } |
740 | 778 | ||
741 | 779 | ||
@@ -745,7 +783,7 @@ static void createmeta (lua_State *L) { | |||
745 | static int io_noclose (lua_State *L) { | 783 | static int io_noclose (lua_State *L) { |
746 | LStream *p = tolstream(L); | 784 | LStream *p = tolstream(L); |
747 | p->closef = &io_noclose; /* keep file opened */ | 785 | p->closef = &io_noclose; /* keep file opened */ |
748 | lua_pushnil(L); | 786 | luaL_pushfail(L); |
749 | lua_pushliteral(L, "cannot close standard file"); | 787 | lua_pushliteral(L, "cannot close standard file"); |
750 | return 2; | 788 | return 2; |
751 | } | 789 | } |