diff options
Diffstat (limited to 'liolib.c')
-rw-r--r-- | liolib.c | 94 |
1 files changed, 49 insertions, 45 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 1.111 2001/03/26 14:31:49 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 1.112 2001/04/23 16:35:45 roberto Exp roberto $ |
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 | */ |
@@ -48,15 +48,17 @@ int pclose(); */ | |||
48 | #define OUTFILE 1 | 48 | #define OUTFILE 1 |
49 | #define NOFILE 2 | 49 | #define NOFILE 2 |
50 | 50 | ||
51 | #define FILEHANDLE l_s("FileHandle") | 51 | #define FILEHANDLE l_s("FileHandle") |
52 | #define CLOSEDFILEHANDLE l_s("ClosedFileHandle") | ||
52 | 53 | ||
53 | 54 | ||
54 | static const l_char *const filenames[] = {l_s("_INPUT"), l_s("_OUTPUT")}; | 55 | static const l_char *const filenames[] = {l_s("_INPUT"), l_s("_OUTPUT")}; |
56 | static const l_char *const basicfiles[] = {l_s("_STDIN"), l_s("_STDOUT")}; | ||
55 | 57 | ||
56 | 58 | ||
57 | static int pushresult (lua_State *L, int i) { | 59 | static int pushresult (lua_State *L, int i) { |
58 | if (i) { | 60 | if (i) { |
59 | lua_pushuserdata(L, NULL); | 61 | lua_newuserdatabox(L, NULL); |
60 | return 1; | 62 | return 1; |
61 | } | 63 | } |
62 | else { | 64 | else { |
@@ -81,16 +83,15 @@ static int pushresult (lua_State *L, int i) { | |||
81 | static FILE *getopthandle (lua_State *L, int inout) { | 83 | static FILE *getopthandle (lua_State *L, int inout) { |
82 | FILE *p = (FILE *)lua_touserdata(L, 1); | 84 | FILE *p = (FILE *)lua_touserdata(L, 1); |
83 | if (p != NULL) { /* is it a userdata ? */ | 85 | if (p != NULL) { /* is it a userdata ? */ |
84 | if (!checkfile(L, 1)) { | 86 | if (!checkfile(L, 1)) { /* not a valid file handle? */ |
85 | if (strcmp(lua_xtypename(L, 1), l_s("ClosedFileHandle")) == 0) | 87 | if (strcmp(lua_xtypename(L, 1), CLOSEDFILEHANDLE) == 0) |
86 | luaL_argerror(L, 1, l_s("file is closed")); | 88 | luaL_argerror(L, 1, l_s("file is closed")); |
87 | else | 89 | else |
88 | luaL_argerror(L, 1, l_s("(invalid value)")); | 90 | luaL_argerror(L, 1, l_s("(invalid value)")); |
89 | } | 91 | } |
90 | /* move it to stack top */ | 92 | lua_pushvalue(L, 1); lua_remove(L, 1); /* move it to stack top */ |
91 | lua_pushvalue(L, 1); lua_remove(L, 1); | ||
92 | } | 93 | } |
93 | else if (inout != NOFILE) { /* try global value */ | 94 | else { /* try global value */ |
94 | lua_getglobal(L, filenames[inout]); | 95 | lua_getglobal(L, filenames[inout]); |
95 | if (!checkfile(L,-1)) | 96 | if (!checkfile(L,-1)) |
96 | luaL_verror(L, l_s("global variable `%.10s' is not a valid file handle"), | 97 | luaL_verror(L, l_s("global variable `%.10s' is not a valid file handle"), |
@@ -101,46 +102,50 @@ static FILE *getopthandle (lua_State *L, int inout) { | |||
101 | } | 102 | } |
102 | 103 | ||
103 | 104 | ||
104 | static void pushfile (lua_State *L, FILE *f) { | 105 | static void newfile (lua_State *L, FILE *f) { |
105 | lua_pushusertag(L, f, lua_name2tag(L, FILEHANDLE)); | 106 | lua_newuserdatabox(L, f); |
107 | lua_settag(L, lua_name2tag(L, FILEHANDLE)); | ||
106 | } | 108 | } |
107 | 109 | ||
108 | 110 | ||
109 | static void setfilebyname (lua_State *L, FILE *f, const l_char *name) { | 111 | static void newfilewithname (lua_State *L, FILE *f, const l_char *name) { |
110 | pushfile(L, f); | 112 | newfile(L, f); |
111 | lua_setglobal(L, name); | 113 | lua_setglobal(L, name); |
112 | } | 114 | } |
113 | 115 | ||
114 | 116 | ||
115 | #define setfile(L,f,inout) (setfilebyname(L,f,filenames[inout])) | 117 | static int setnewfile (lua_State *L, FILE *f, int inout) { |
116 | |||
117 | |||
118 | static int setreturn (lua_State *L, FILE *f, int inout) { | ||
119 | if (f == NULL) | 118 | if (f == NULL) |
120 | return pushresult(L, 0); | 119 | return pushresult(L, 0); |
121 | else { | 120 | else { |
122 | if (inout != NOFILE) | 121 | newfile(L, f); |
123 | setfile(L, f, inout); | 122 | if (inout != NOFILE) { |
124 | pushfile(L, f); | 123 | lua_pushvalue(L, -1); |
124 | lua_setglobal(L, filenames[inout]); | ||
125 | } | ||
125 | return 1; | 126 | return 1; |
126 | } | 127 | } |
127 | } | 128 | } |
128 | 129 | ||
129 | 130 | ||
130 | static int closefile (lua_State *L, FILE *f) { | 131 | static void resetfile (lua_State *L, int inout) { |
131 | if (f == stdin || f == stdout || f == stderr) | 132 | lua_getglobal(L, basicfiles[inout]); |
132 | return 1; | 133 | lua_setglobal(L, filenames[inout]); |
133 | else { | ||
134 | lua_pushuserdata(L, f); | ||
135 | lua_settag(L, lua_name2tag(L, l_s("ClosedFileHandle"))); | ||
136 | return (CLOSEFILE(L, f) == 0); | ||
137 | } | ||
138 | } | 134 | } |
139 | 135 | ||
140 | 136 | ||
141 | static int io_close (lua_State *L) { | 137 | static int io_close (lua_State *L) { |
142 | FILE *f = (FILE *)luaL_check_userdata(L, 1, FILEHANDLE); | 138 | FILE *f; |
143 | return pushresult(L, closefile(L, f)); | 139 | int status; |
140 | lua_settop(L, 1); | ||
141 | f = luaL_check_userdata(L, 1, FILEHANDLE); | ||
142 | if (f == stdin || f == stdout || f == stderr) | ||
143 | status = 1; | ||
144 | else { | ||
145 | lua_settag(L, lua_name2tag(L, CLOSEDFILEHANDLE)); | ||
146 | status = (CLOSEFILE(L, f) == 0); | ||
147 | } | ||
148 | return pushresult(L, status); | ||
144 | } | 149 | } |
145 | 150 | ||
146 | 151 | ||
@@ -154,12 +159,12 @@ static int file_collect (lua_State *L) { | |||
154 | 159 | ||
155 | static int io_open (lua_State *L) { | 160 | static int io_open (lua_State *L) { |
156 | FILE *f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2)); | 161 | FILE *f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2)); |
157 | return setreturn(L, f, NOFILE); | 162 | return setnewfile(L, f, NOFILE); |
158 | } | 163 | } |
159 | 164 | ||
160 | 165 | ||
161 | static int io_tmpfile (lua_State *L) { | 166 | static int io_tmpfile (lua_State *L) { |
162 | return setreturn(L, tmpfile(), NOFILE); | 167 | return setnewfile(L, tmpfile(), NOFILE); |
163 | } | 168 | } |
164 | 169 | ||
165 | 170 | ||
@@ -167,16 +172,15 @@ static int io_tmpfile (lua_State *L) { | |||
167 | static int io_fromto (lua_State *L, int inout, const l_char *mode) { | 172 | static int io_fromto (lua_State *L, int inout, const l_char *mode) { |
168 | FILE *current; | 173 | FILE *current; |
169 | if (lua_isnull(L, 1)) { | 174 | if (lua_isnull(L, 1)) { |
170 | closefile(L, getopthandle(L, inout)); | 175 | getopthandle(L, inout); |
171 | current = (inout == 0) ? stdin : stdout; | 176 | resetfile(L, inout); |
177 | return io_close(L); | ||
172 | } | 178 | } |
173 | else if (checkfile(L, 1)) /* deprecated option */ | ||
174 | current = (FILE *)lua_touserdata(L, 1); | ||
175 | else { | 179 | else { |
176 | const l_char *s = luaL_check_string(L, 1); | 180 | const l_char *s = luaL_check_string(L, 1); |
177 | current = (*s == l_c('|')) ? popen(s+1, mode) : fopen(s, mode); | 181 | current = (*s == l_c('|')) ? popen(s+1, mode) : fopen(s, mode); |
182 | return setnewfile(L, current, inout); | ||
178 | } | 183 | } |
179 | return setreturn(L, current, inout); | ||
180 | } | 184 | } |
181 | 185 | ||
182 | 186 | ||
@@ -192,7 +196,7 @@ static int io_writeto (lua_State *L) { | |||
192 | 196 | ||
193 | static int io_appendto (lua_State *L) { | 197 | static int io_appendto (lua_State *L) { |
194 | FILE *current = fopen(luaL_check_string(L, 1), l_s("a")); | 198 | FILE *current = fopen(luaL_check_string(L, 1), l_s("a")); |
195 | return setreturn(L, current, OUTFILE); | 199 | return setnewfile(L, current, OUTFILE); |
196 | } | 200 | } |
197 | 201 | ||
198 | 202 | ||
@@ -388,8 +392,8 @@ static int io_seek (lua_State *L) { | |||
388 | 392 | ||
389 | 393 | ||
390 | static int io_flush (lua_State *L) { | 394 | static int io_flush (lua_State *L) { |
391 | FILE *f = getopthandle(L, NOFILE); | 395 | FILE *f = (lua_isnull(L, 1)) ? (FILE *)NULL : |
392 | luaL_arg_check(L, f || lua_isnull(L, 1), 1, l_s("invalid file handle")); | 396 | (FILE *)luaL_check_userdata(L, 1, FILEHANDLE); |
393 | return pushresult(L, fflush(f) == 0); | 397 | return pushresult(L, fflush(f) == 0); |
394 | } | 398 | } |
395 | 399 | ||
@@ -679,14 +683,14 @@ static const luaL_reg iolib[] = { | |||
679 | 683 | ||
680 | LUALIB_API int lua_iolibopen (lua_State *L) { | 684 | LUALIB_API int lua_iolibopen (lua_State *L) { |
681 | int iotag = lua_newxtype(L, FILEHANDLE, LUA_TUSERDATA); | 685 | int iotag = lua_newxtype(L, FILEHANDLE, LUA_TUSERDATA); |
682 | lua_newxtype(L, l_s("ClosedFileHandle"), LUA_TUSERDATA); | 686 | lua_newxtype(L, CLOSEDFILEHANDLE, LUA_TUSERDATA); |
683 | luaL_openl(L, iolib); | 687 | luaL_openl(L, iolib); |
684 | /* predefined file handles */ | 688 | /* predefined file handles */ |
685 | setfile(L, stdin, INFILE); | 689 | newfilewithname(L, stdin, basicfiles[INFILE]); |
686 | setfile(L, stdout, OUTFILE); | 690 | newfilewithname(L, stdout, basicfiles[OUTFILE]); |
687 | setfilebyname(L, stdin, l_s("_STDIN")); | 691 | newfilewithname(L, stderr, l_s("_STDERR")); |
688 | setfilebyname(L, stdout, l_s("_STDOUT")); | 692 | resetfile(L, INFILE); |
689 | setfilebyname(L, stderr, l_s("_STDERR")); | 693 | resetfile(L, OUTFILE); |
690 | /* close files when collected */ | 694 | /* close files when collected */ |
691 | lua_pushcfunction(L, file_collect); | 695 | lua_pushcfunction(L, file_collect); |
692 | lua_settagmethod(L, iotag, l_s("gc")); | 696 | lua_settagmethod(L, iotag, l_s("gc")); |