diff options
Diffstat (limited to 'liolib.c')
| -rw-r--r-- | liolib.c | 58 |
1 files changed, 43 insertions, 15 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: liolib.c,v 1.124 2001/10/26 17:33:30 roberto Exp $ | 2 | ** $Id: liolib.c,v 1.1 2001/11/29 22:14:34 rieru Exp rieru $ |
| 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 | */ |
| @@ -61,6 +61,7 @@ static int pushresult (lua_State *L, int i) { | |||
| 61 | } | 61 | } |
| 62 | 62 | ||
| 63 | 63 | ||
| 64 | |||
| 64 | /* | 65 | /* |
| 65 | ** {====================================================== | 66 | ** {====================================================== |
| 66 | ** FILE Operations | 67 | ** FILE Operations |
| @@ -68,14 +69,30 @@ static int pushresult (lua_State *L, int i) { | |||
| 68 | */ | 69 | */ |
| 69 | 70 | ||
| 70 | 71 | ||
| 71 | #define checkfile(L,f) (strcmp(lua_type(L,(f)), FILEHANDLE) == 0) | 72 | |
| 73 | static int checkfile (lua_State *L, int findex, const char *tname) { | ||
| 74 | int res; | ||
| 75 | lua_geteventtable(L, findex); | ||
| 76 | lua_pushstring(L, tname); | ||
| 77 | lua_gettable(L, LUA_REGISTRYINDEX); | ||
| 78 | res = lua_equal(L, -1, -2); | ||
| 79 | lua_pop(L, 2); | ||
| 80 | return res; | ||
| 81 | } | ||
| 82 | |||
| 83 | |||
| 84 | /* temporary?? should be in auxlib... */ | ||
| 85 | static void *luaL_check_userdata (lua_State *L, int findex, const char *tn) { | ||
| 86 | luaL_arg_check(L, checkfile(L, findex, tn), findex, "bad file"); | ||
| 87 | return lua_touserdata(L, findex); | ||
| 88 | } | ||
| 72 | 89 | ||
| 73 | 90 | ||
| 74 | static FILE *getopthandle (lua_State *L, int inout) { | 91 | static FILE *getopthandle (lua_State *L, int inout) { |
| 75 | FILE *p = (FILE *)(lua_touserdata(L, 1)); | 92 | FILE *p = (FILE *)(lua_touserdata(L, 1)); |
| 76 | if (p != NULL) { /* is it a userdata ? */ | 93 | if (p != NULL) { /* is it a userdata ? */ |
| 77 | if (!checkfile(L, 1)) { /* not a valid file handle? */ | 94 | if (!checkfile(L, 1, FILEHANDLE)) { /* not a valid file handle? */ |
| 78 | if (strcmp(lua_type(L, 1), CLOSEDFILEHANDLE) == 0) | 95 | if (checkfile(L, 1, CLOSEDFILEHANDLE)) |
| 79 | luaL_argerror(L, 1, "file is closed"); | 96 | luaL_argerror(L, 1, "file is closed"); |
| 80 | else | 97 | else |
| 81 | luaL_argerror(L, 1, "(invalid value)"); | 98 | luaL_argerror(L, 1, "(invalid value)"); |
| @@ -84,7 +101,7 @@ static FILE *getopthandle (lua_State *L, int inout) { | |||
| 84 | } | 101 | } |
| 85 | else { /* try global value */ | 102 | else { /* try global value */ |
| 86 | lua_getglobal(L, filenames[inout]); | 103 | lua_getglobal(L, filenames[inout]); |
| 87 | if (!checkfile(L,-1)) | 104 | if (!checkfile(L, -1, FILEHANDLE)) |
| 88 | luaL_verror(L, "global variable `%.10s' is not a valid file handle", | 105 | luaL_verror(L, "global variable `%.10s' is not a valid file handle", |
| 89 | filenames[inout]); | 106 | filenames[inout]); |
| 90 | p = (FILE *)(lua_touserdata(L, -1)); | 107 | p = (FILE *)(lua_touserdata(L, -1)); |
| @@ -95,7 +112,9 @@ static FILE *getopthandle (lua_State *L, int inout) { | |||
| 95 | 112 | ||
| 96 | static void newfile (lua_State *L, FILE *f) { | 113 | static void newfile (lua_State *L, FILE *f) { |
| 97 | lua_newuserdatabox(L, f); | 114 | lua_newuserdatabox(L, f); |
| 98 | lua_settag(L, lua_name2tag(L, FILEHANDLE)); | 115 | lua_pushliteral(L, FILEHANDLE); |
| 116 | lua_gettable(L, LUA_REGISTRYINDEX); | ||
| 117 | lua_seteventtable(L, -2); | ||
| 99 | } | 118 | } |
| 100 | 119 | ||
| 101 | 120 | ||
| @@ -130,7 +149,9 @@ static int io_close (lua_State *L) { | |||
| 130 | int status = 1; | 149 | int status = 1; |
| 131 | if (f != stdin && f != stdout && f != stderr) { | 150 | if (f != stdin && f != stdout && f != stderr) { |
| 132 | lua_settop(L, 1); /* make sure file is on top */ | 151 | lua_settop(L, 1); /* make sure file is on top */ |
| 133 | lua_settag(L, lua_name2tag(L, CLOSEDFILEHANDLE)); | 152 | lua_pushliteral(L, CLOSEDFILEHANDLE); |
| 153 | lua_gettable(L, LUA_REGISTRYINDEX); | ||
| 154 | lua_seteventtable(L, 1); | ||
| 134 | status = (CLOSEFILE(L, f) == 0); | 155 | status = (CLOSEFILE(L, f) == 0); |
| 135 | } | 156 | } |
| 136 | return pushresult(L, status); | 157 | return pushresult(L, status); |
| @@ -301,7 +322,7 @@ static int io_read (lua_State *L) { | |||
| 301 | luaL_check_stack(L, nargs+LUA_MINSTACK, "too many arguments"); | 322 | luaL_check_stack(L, nargs+LUA_MINSTACK, "too many arguments"); |
| 302 | success = 1; | 323 | success = 1; |
| 303 | for (n = 1; n<=nargs && success; n++) { | 324 | for (n = 1; n<=nargs && success; n++) { |
| 304 | if (lua_rawtag(L, n) == LUA_TNUMBER) { | 325 | if (lua_type(L, n) == LUA_TNUMBER) { |
| 305 | size_t l = (size_t)lua_tonumber(L, n); | 326 | size_t l = (size_t)lua_tonumber(L, n); |
| 306 | success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); | 327 | success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); |
| 307 | } | 328 | } |
| @@ -353,7 +374,7 @@ static int io_write (lua_State *L) { | |||
| 353 | int arg; | 374 | int arg; |
| 354 | int status = 1; | 375 | int status = 1; |
| 355 | for (arg=1; arg<=nargs; arg++) { | 376 | for (arg=1; arg<=nargs; arg++) { |
| 356 | if (lua_rawtag(L, arg) == LUA_TNUMBER) { | 377 | if (lua_type(L, arg) == LUA_TNUMBER) { |
| 357 | /* optimization: could be done exactly as for strings */ | 378 | /* optimization: could be done exactly as for strings */ |
| 358 | status = status && | 379 | status = status && |
| 359 | fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; | 380 | fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; |
| @@ -514,7 +535,7 @@ static int io_time (lua_State *L) { | |||
| 514 | else { | 535 | else { |
| 515 | time_t t; | 536 | time_t t; |
| 516 | struct tm ts; | 537 | struct tm ts; |
| 517 | luaL_check_rawtype(L, 1, LUA_TTABLE); | 538 | luaL_check_type(L, 1, LUA_TTABLE); |
| 518 | lua_settop(L, 1); /* make sure table is at the top */ | 539 | lua_settop(L, 1); /* make sure table is at the top */ |
| 519 | ts.tm_sec = getfield(L, "sec", 0); | 540 | ts.tm_sec = getfield(L, "sec", 0); |
| 520 | ts.tm_min = getfield(L, "min", 0); | 541 | ts.tm_min = getfield(L, "min", 0); |
| @@ -677,8 +698,18 @@ static const luaL_reg iolib[] = { | |||
| 677 | 698 | ||
| 678 | 699 | ||
| 679 | LUALIB_API int lua_iolibopen (lua_State *L) { | 700 | LUALIB_API int lua_iolibopen (lua_State *L) { |
| 680 | int iotag = lua_newtype(L, FILEHANDLE, LUA_TUSERDATA); | 701 | lua_pushliteral(L, FILEHANDLE); |
| 681 | lua_newtype(L, CLOSEDFILEHANDLE, LUA_TUSERDATA); | 702 | lua_newtable(L); /* event table for FILEHANDLE */ |
| 703 | /* close files when collected */ | ||
| 704 | lua_pushliteral(L, "gc"); | ||
| 705 | lua_pushcfunction(L, file_collect); | ||
| 706 | lua_settable(L, -3); | ||
| 707 | /* put new eventtable into registry */ | ||
| 708 | lua_settable(L, LUA_REGISTRYINDEX); /* registry.FILEHANDLE = eventtable */ | ||
| 709 | lua_pushliteral(L, CLOSEDFILEHANDLE); | ||
| 710 | /* event table for CLOSEDFILEHANDLE */ | ||
| 711 | lua_newtable(L); | ||
| 712 | lua_settable(L, LUA_REGISTRYINDEX); | ||
| 682 | luaL_openl(L, iolib); | 713 | luaL_openl(L, iolib); |
| 683 | /* predefined file handles */ | 714 | /* predefined file handles */ |
| 684 | newfilewithname(L, stdin, basicfiles[INFILE]); | 715 | newfilewithname(L, stdin, basicfiles[INFILE]); |
| @@ -686,9 +717,6 @@ LUALIB_API int lua_iolibopen (lua_State *L) { | |||
| 686 | newfilewithname(L, stderr, "_STDERR"); | 717 | newfilewithname(L, stderr, "_STDERR"); |
| 687 | resetfile(L, INFILE); | 718 | resetfile(L, INFILE); |
| 688 | resetfile(L, OUTFILE); | 719 | resetfile(L, OUTFILE); |
| 689 | /* close files when collected */ | ||
| 690 | lua_pushcfunction(L, file_collect); | ||
| 691 | lua_settagmethod(L, iotag, "gc"); | ||
| 692 | return 0; | 720 | return 0; |
| 693 | } | 721 | } |
| 694 | 722 | ||
