diff options
-rw-r--r-- | liolib.c | 267 |
1 files changed, 128 insertions, 139 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 2.98 2011/02/21 19:12:54 roberto Exp roberto $ | 2 | ** $Id: liolib.c,v 2.99 2011/03/03 16:34:46 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 | */ |
@@ -19,8 +19,6 @@ | |||
19 | #include "lualib.h" | 19 | #include "lualib.h" |
20 | 20 | ||
21 | 21 | ||
22 | #define MAX_SIZE_T (~(size_t)0) | ||
23 | |||
24 | 22 | ||
25 | /* | 23 | /* |
26 | ** lua_popen spawns a new process connected to the current one through | 24 | ** lua_popen spawns a new process connected to the current one through |
@@ -51,11 +49,15 @@ | |||
51 | #endif /* } */ | 49 | #endif /* } */ |
52 | 50 | ||
53 | 51 | ||
54 | #define IO_INPUT 1 | 52 | #define IO_PREFIX "lua_io_" |
55 | #define IO_OUTPUT 2 | 53 | #define IO_INPUT (IO_PREFIX "input") |
54 | #define IO_OUTPUT (IO_PREFIX "output") | ||
56 | 55 | ||
57 | 56 | ||
58 | static const char *const fnames[] = {"input", "output"}; | 57 | typedef struct LStream { |
58 | FILE *f; /* stream */ | ||
59 | lua_CFunction closef; /* to close stream (NULL for closed streams) */ | ||
60 | } LStream; | ||
59 | 61 | ||
60 | 62 | ||
61 | static void fileerror (lua_State *L, int arg, const char *filename) { | 63 | static void fileerror (lua_State *L, int arg, const char *filename) { |
@@ -64,16 +66,18 @@ static void fileerror (lua_State *L, int arg, const char *filename) { | |||
64 | } | 66 | } |
65 | 67 | ||
66 | 68 | ||
67 | #define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) | 69 | #define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) |
70 | |||
71 | #define isclosed(p) ((p)->closef == NULL) | ||
68 | 72 | ||
69 | 73 | ||
70 | static int io_type (lua_State *L) { | 74 | static int io_type (lua_State *L) { |
71 | void *ud; | 75 | LStream *p; |
72 | luaL_checkany(L, 1); | 76 | luaL_checkany(L, 1); |
73 | ud = luaL_testudata(L, 1, LUA_FILEHANDLE); | 77 | p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); |
74 | if (ud == NULL) | 78 | if (p == NULL) |
75 | lua_pushnil(L); /* not a file */ | 79 | lua_pushnil(L); /* not a file */ |
76 | else if (*((FILE **)ud) == NULL) | 80 | else if (isclosed(p)) |
77 | lua_pushliteral(L, "closed file"); | 81 | lua_pushliteral(L, "closed file"); |
78 | else | 82 | else |
79 | lua_pushliteral(L, "file"); | 83 | lua_pushliteral(L, "file"); |
@@ -81,11 +85,22 @@ static int io_type (lua_State *L) { | |||
81 | } | 85 | } |
82 | 86 | ||
83 | 87 | ||
88 | static int f_tostring (lua_State *L) { | ||
89 | LStream *p = tolstream(L); | ||
90 | if (isclosed(p)) | ||
91 | lua_pushliteral(L, "file (closed)"); | ||
92 | else | ||
93 | lua_pushfstring(L, "file (%p)", p->f); | ||
94 | return 1; | ||
95 | } | ||
96 | |||
97 | |||
84 | static FILE *tofile (lua_State *L) { | 98 | static FILE *tofile (lua_State *L) { |
85 | FILE **f = tofilep(L); | 99 | LStream *p = tolstream(L); |
86 | if (*f == NULL) | 100 | if (isclosed(p)) |
87 | luaL_error(L, "attempt to use a closed file"); | 101 | luaL_error(L, "attempt to use a closed file"); |
88 | return *f; | 102 | lua_assert(p->f); |
103 | return p->f; | ||
89 | } | 104 | } |
90 | 105 | ||
91 | 106 | ||
@@ -94,40 +109,35 @@ static FILE *tofile (lua_State *L) { | |||
94 | ** before opening the actual file; so, if there is a memory error, the | 109 | ** before opening the actual file; so, if there is a memory error, the |
95 | ** file is not left opened. | 110 | ** file is not left opened. |
96 | */ | 111 | */ |
97 | static FILE **newprefile (lua_State *L) { | 112 | static LStream *newprefile (lua_State *L) { |
98 | FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); | 113 | LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); |
99 | *pf = NULL; /* file handle is currently `closed' */ | 114 | p->closef = NULL; /* mark file handle as 'closed' */ |
100 | luaL_setmetatable(L, LUA_FILEHANDLE); | 115 | luaL_setmetatable(L, LUA_FILEHANDLE); |
101 | return pf; | 116 | return p; |
102 | } | 117 | } |
103 | 118 | ||
104 | 119 | ||
105 | static FILE **newfile (lua_State *L) { | 120 | static int aux_close (lua_State *L) { |
106 | FILE **pf = newprefile(L); | 121 | LStream *p = tolstream(L); |
107 | lua_pushvalue(L, lua_upvalueindex(1)); /* set upvalue... */ | 122 | lua_CFunction cf = p->closef; |
108 | lua_setuservalue(L, -2); /* ... as environment for new file */ | 123 | p->closef = NULL; /* mark stream as closed */ |
109 | return pf; | 124 | return (*cf)(L); /* close it */ |
110 | } | 125 | } |
111 | 126 | ||
112 | 127 | ||
113 | /* | 128 | static int io_close (lua_State *L) { |
114 | ** function to (not) close the standard files stdin, stdout, and stderr | 129 | if (lua_isnone(L, 1)) /* no argument? */ |
115 | */ | 130 | lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ |
116 | static int io_noclose (lua_State *L) { | 131 | tofile(L); /* make sure argument is an open stream */ |
117 | lua_pushnil(L); | 132 | return aux_close(L); |
118 | lua_pushliteral(L, "cannot close standard file"); | ||
119 | return 2; | ||
120 | } | 133 | } |
121 | 134 | ||
122 | 135 | ||
123 | /* | 136 | static int f_gc (lua_State *L) { |
124 | ** function to close 'popen' files | 137 | LStream *p = tolstream(L); |
125 | */ | 138 | if (!isclosed(p) && p->f != NULL) |
126 | static int io_pclose (lua_State *L) { | 139 | aux_close(L); /* ignore closed and incompletely open files */ |
127 | FILE **p = tofilep(L); | 140 | return 0; |
128 | int stat = lua_pclose(L, *p); | ||
129 | *p = NULL; /* mark stream as closed (for GC) */ | ||
130 | return luaL_execresult(L, stat); | ||
131 | } | 141 | } |
132 | 142 | ||
133 | 143 | ||
@@ -135,111 +145,90 @@ static int io_pclose (lua_State *L) { | |||
135 | ** function to close regular files | 145 | ** function to close regular files |
136 | */ | 146 | */ |
137 | static int io_fclose (lua_State *L) { | 147 | static int io_fclose (lua_State *L) { |
138 | FILE **p = tofilep(L); | 148 | LStream *p = tolstream(L); |
139 | int ok = (fclose(*p) == 0); | 149 | int res = fclose(p->f); |
140 | *p = NULL; /* mark stream as closed (for GC) */ | 150 | return luaL_fileresult(L, (res == 0), NULL); |
141 | return luaL_fileresult(L, ok, NULL); | ||
142 | } | 151 | } |
143 | 152 | ||
144 | 153 | ||
145 | static int aux_close (lua_State *L) { | 154 | static LStream *newfile (lua_State *L) { |
146 | lua_getuservalue(L, 1); | 155 | LStream *p = newprefile(L); |
147 | lua_getfield(L, -1, "__close"); | 156 | p->f = NULL; |
148 | return (lua_tocfunction(L, -1))(L); | 157 | p->closef = &io_fclose; |
149 | } | 158 | return p; |
150 | |||
151 | |||
152 | static int io_close (lua_State *L) { | ||
153 | if (lua_isnone(L, 1)) | ||
154 | lua_rawgeti(L, lua_upvalueindex(1), IO_OUTPUT); | ||
155 | tofile(L); /* make sure argument is a file */ | ||
156 | return aux_close(L); | ||
157 | } | ||
158 | |||
159 | |||
160 | static int io_gc (lua_State *L) { | ||
161 | FILE *f = *tofilep(L); | ||
162 | if (f != NULL) /* ignore closed files */ | ||
163 | aux_close(L); | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | |||
168 | static int io_tostring (lua_State *L) { | ||
169 | FILE *f = *tofilep(L); | ||
170 | if (f == NULL) | ||
171 | lua_pushliteral(L, "file (closed)"); | ||
172 | else | ||
173 | lua_pushfstring(L, "file (%p)", f); | ||
174 | return 1; | ||
175 | } | 159 | } |
176 | 160 | ||
177 | 161 | ||
178 | static int io_open (lua_State *L) { | 162 | static int io_open (lua_State *L) { |
179 | const char *filename = luaL_checkstring(L, 1); | 163 | const char *filename = luaL_checkstring(L, 1); |
180 | const char *mode = luaL_optstring(L, 2, "r"); | 164 | const char *mode = luaL_optstring(L, 2, "r"); |
181 | FILE **pf; | 165 | LStream *p = newfile(L); |
182 | int i = 0; | 166 | int i = 0; |
183 | /* check whether 'mode' matches '[rwa]%+?b?' */ | 167 | /* check whether 'mode' matches '[rwa]%+?b?' */ |
184 | if (!(mode[i] != '\0' && strchr("rwa", mode[i++]) != NULL && | 168 | if (!(mode[i] != '\0' && strchr("rwa", mode[i++]) != NULL && |
185 | (mode[i] != '+' || ++i) && /* skip if char is '+' */ | 169 | (mode[i] != '+' || ++i) && /* skip if char is '+' */ |
186 | (mode[i] != 'b' || ++i) && /* skip if char is 'b' */ | 170 | (mode[i] != 'b' || ++i) && /* skip if char is 'b' */ |
187 | (mode[i] == '\0'))) | 171 | (mode[i] == '\0'))) |
188 | luaL_error(L, "invalid mode " LUA_QL("%s") | 172 | return luaL_error(L, "invalid mode " LUA_QL("%s") |
189 | " (should match " LUA_QL("[rwa]%%+?b?") ")", mode); | 173 | " (should match " LUA_QL("[rwa]%%+?b?") ")", mode); |
190 | pf = newfile(L); | 174 | p->f = fopen(filename, mode); |
191 | *pf = fopen(filename, mode); | 175 | return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; |
192 | return (*pf == NULL) ? luaL_fileresult(L, 0, filename) : 1; | ||
193 | } | 176 | } |
194 | 177 | ||
195 | 178 | ||
196 | /* | 179 | /* |
197 | ** this function has a separated environment, which defines the | 180 | ** function to close 'popen' files |
198 | ** correct __close for 'popen' files | ||
199 | */ | 181 | */ |
182 | static int io_pclose (lua_State *L) { | ||
183 | LStream *p = tolstream(L); | ||
184 | return luaL_execresult(L, lua_pclose(L, p->f)); | ||
185 | } | ||
186 | |||
187 | |||
200 | static int io_popen (lua_State *L) { | 188 | static int io_popen (lua_State *L) { |
201 | const char *filename = luaL_checkstring(L, 1); | 189 | const char *filename = luaL_checkstring(L, 1); |
202 | const char *mode = luaL_optstring(L, 2, "r"); | 190 | const char *mode = luaL_optstring(L, 2, "r"); |
203 | FILE **pf = newfile(L); | 191 | LStream *p = newprefile(L); |
204 | *pf = lua_popen(L, filename, mode); | 192 | p->f = lua_popen(L, filename, mode); |
205 | return (*pf == NULL) ? luaL_fileresult(L, 0, filename) : 1; | 193 | p->closef = &io_pclose; |
194 | return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; | ||
206 | } | 195 | } |
207 | 196 | ||
208 | 197 | ||
209 | static int io_tmpfile (lua_State *L) { | 198 | static int io_tmpfile (lua_State *L) { |
210 | FILE **pf = newfile(L); | 199 | LStream *p = newfile(L); |
211 | *pf = tmpfile(); | 200 | p->f = tmpfile(); |
212 | return (*pf == NULL) ? luaL_fileresult(L, 0, NULL) : 1; | 201 | return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; |
213 | } | 202 | } |
214 | 203 | ||
215 | 204 | ||
216 | static FILE *getiofile (lua_State *L, int findex) { | 205 | static FILE *getiofile (lua_State *L, const char *findex) { |
217 | FILE *f; | 206 | LStream *p; |
218 | lua_rawgeti(L, lua_upvalueindex(1), findex); | 207 | lua_getfield(L, LUA_REGISTRYINDEX, findex); |
219 | f = *(FILE **)lua_touserdata(L, -1); | 208 | p = (LStream *)lua_touserdata(L, -1); |
220 | if (f == NULL) | 209 | if (isclosed(p)) |
221 | luaL_error(L, "standard %s file is closed", fnames[findex - 1]); | 210 | luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX)); |
222 | return f; | 211 | return p->f; |
223 | } | 212 | } |
224 | 213 | ||
225 | 214 | ||
226 | static int g_iofile (lua_State *L, int f, const char *mode) { | 215 | static int g_iofile (lua_State *L, const char *f, const char *mode) { |
227 | if (!lua_isnoneornil(L, 1)) { | 216 | if (!lua_isnoneornil(L, 1)) { |
228 | const char *filename = lua_tostring(L, 1); | 217 | const char *filename = lua_tostring(L, 1); |
229 | if (filename) { | 218 | if (filename) { |
230 | FILE **pf = newfile(L); | 219 | LStream *p = newfile(L); |
231 | *pf = fopen(filename, mode); | 220 | p->f = fopen(filename, mode); |
232 | if (*pf == NULL) | 221 | if (p->f == NULL) |
233 | fileerror(L, 1, filename); | 222 | fileerror(L, 1, filename); |
234 | } | 223 | } |
235 | else { | 224 | else { |
236 | tofile(L); /* check that it's a valid file handle */ | 225 | tofile(L); /* check that it's a valid file handle */ |
237 | lua_pushvalue(L, 1); | 226 | lua_pushvalue(L, 1); |
238 | } | 227 | } |
239 | lua_rawseti(L, lua_upvalueindex(1), f); | 228 | lua_setfield(L, LUA_REGISTRYINDEX, f); |
240 | } | 229 | } |
241 | /* return current value */ | 230 | /* return current value */ |
242 | lua_rawgeti(L, lua_upvalueindex(1), f); | 231 | lua_getfield(L, LUA_REGISTRYINDEX, f); |
243 | return 1; | 232 | return 1; |
244 | } | 233 | } |
245 | 234 | ||
@@ -281,16 +270,16 @@ static int io_lines (lua_State *L) { | |||
281 | int toclose; | 270 | int toclose; |
282 | if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ | 271 | if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ |
283 | if (lua_isnil(L, 1)) { /* no file name? */ | 272 | if (lua_isnil(L, 1)) { /* no file name? */ |
284 | lua_rawgeti(L, lua_upvalueindex(1), IO_INPUT); /* get default input */ | 273 | lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ |
285 | lua_replace(L, 1); /* put it at index 1 */ | 274 | lua_replace(L, 1); /* put it at index 1 */ |
286 | tofile(L); /* check that it's a valid file handle */ | 275 | tofile(L); /* check that it's a valid file handle */ |
287 | toclose = 0; /* do not close it after iteration */ | 276 | toclose = 0; /* do not close it after iteration */ |
288 | } | 277 | } |
289 | else { /* open a new file */ | 278 | else { /* open a new file */ |
290 | const char *filename = luaL_checkstring(L, 1); | 279 | const char *filename = luaL_checkstring(L, 1); |
291 | FILE **pf = newfile(L); | 280 | LStream *p = newfile(L); |
292 | *pf = fopen(filename, "r"); | 281 | p->f = fopen(filename, "r"); |
293 | if (*pf == NULL) | 282 | if (p->f == NULL) |
294 | fileerror(L, 1, filename); | 283 | fileerror(L, 1, filename); |
295 | lua_replace(L, 1); /* put file at index 1 */ | 284 | lua_replace(L, 1); /* put file at index 1 */ |
296 | toclose = 1; /* close it after iteration */ | 285 | toclose = 1; /* close it after iteration */ |
@@ -350,6 +339,8 @@ static int read_line (lua_State *L, FILE *f, int chop) { | |||
350 | } | 339 | } |
351 | 340 | ||
352 | 341 | ||
342 | #define MAX_SIZE_T (~(size_t)0) | ||
343 | |||
353 | static void read_all (lua_State *L, FILE *f) { | 344 | static void read_all (lua_State *L, FILE *f) { |
354 | size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ | 345 | size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ |
355 | luaL_Buffer b; | 346 | luaL_Buffer b; |
@@ -440,15 +431,15 @@ static int f_read (lua_State *L) { | |||
440 | 431 | ||
441 | 432 | ||
442 | static int io_readline (lua_State *L) { | 433 | static int io_readline (lua_State *L) { |
443 | FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); | 434 | LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); |
444 | int i; | 435 | int i; |
445 | int n = (int)lua_tointeger(L, lua_upvalueindex(2)); | 436 | int n = (int)lua_tointeger(L, lua_upvalueindex(2)); |
446 | if (f == NULL) /* file is already closed? */ | 437 | if (isclosed(p)) /* file is already closed? */ |
447 | luaL_error(L, "file is already closed"); | 438 | return luaL_error(L, "file is already closed"); |
448 | lua_settop(L , 1); | 439 | lua_settop(L , 1); |
449 | for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ | 440 | for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ |
450 | lua_pushvalue(L, lua_upvalueindex(3 + i)); | 441 | lua_pushvalue(L, lua_upvalueindex(3 + i)); |
451 | n = g_read(L, f, 2); /* 'n' is number of results */ | 442 | n = g_read(L, p->f, 2); /* 'n' is number of results */ |
452 | lua_assert(n > 0); /* should return at least a nil */ | 443 | lua_assert(n > 0); /* should return at least a nil */ |
453 | if (!lua_isnil(L, -n)) /* read at least one value? */ | 444 | if (!lua_isnil(L, -n)) /* read at least one value? */ |
454 | return n; /* return them */ | 445 | return n; /* return them */ |
@@ -494,7 +485,7 @@ static int io_write (lua_State *L) { | |||
494 | 485 | ||
495 | 486 | ||
496 | static int f_write (lua_State *L) { | 487 | static int f_write (lua_State *L) { |
497 | FILE * f = tofile(L); | 488 | FILE *f = tofile(L); |
498 | lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ | 489 | lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ |
499 | return g_write(L, f, 2); | 490 | return g_write(L, f, 2); |
500 | } | 491 | } |
@@ -538,6 +529,9 @@ static int f_flush (lua_State *L) { | |||
538 | } | 529 | } |
539 | 530 | ||
540 | 531 | ||
532 | /* | ||
533 | ** functions for 'io' library | ||
534 | */ | ||
541 | static const luaL_Reg iolib[] = { | 535 | static const luaL_Reg iolib[] = { |
542 | {"close", io_close}, | 536 | {"close", io_close}, |
543 | {"flush", io_flush}, | 537 | {"flush", io_flush}, |
@@ -554,6 +548,9 @@ static const luaL_Reg iolib[] = { | |||
554 | }; | 548 | }; |
555 | 549 | ||
556 | 550 | ||
551 | /* | ||
552 | ** methods for file handles | ||
553 | */ | ||
557 | static const luaL_Reg flib[] = { | 554 | static const luaL_Reg flib[] = { |
558 | {"close", io_close}, | 555 | {"close", io_close}, |
559 | {"flush", f_flush}, | 556 | {"flush", f_flush}, |
@@ -562,8 +559,8 @@ static const luaL_Reg flib[] = { | |||
562 | {"seek", f_seek}, | 559 | {"seek", f_seek}, |
563 | {"setvbuf", f_setvbuf}, | 560 | {"setvbuf", f_setvbuf}, |
564 | {"write", f_write}, | 561 | {"write", f_write}, |
565 | {"__gc", io_gc}, | 562 | {"__gc", f_gc}, |
566 | {"__tostring", io_tostring}, | 563 | {"__tostring", f_tostring}, |
567 | {NULL, NULL} | 564 | {NULL, NULL} |
568 | }; | 565 | }; |
569 | 566 | ||
@@ -577,46 +574,38 @@ static void createmeta (lua_State *L) { | |||
577 | } | 574 | } |
578 | 575 | ||
579 | 576 | ||
580 | static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { | 577 | /* |
581 | *newprefile(L) = f; | 578 | ** function to (not) close the standard files stdin, stdout, and stderr |
582 | if (k > 0) { | 579 | */ |
583 | lua_pushvalue(L, -1); /* copy new file */ | 580 | static int io_noclose (lua_State *L) { |
584 | lua_rawseti(L, 1, k); /* add it to common upvalue */ | 581 | LStream *p = tolstream(L); |
585 | } | 582 | p->closef = &io_noclose; /* keep file opened */ |
586 | lua_pushvalue(L, 3); /* get environment for default files */ | 583 | lua_pushnil(L); |
587 | lua_setuservalue(L, -2); /* set it as environment for file */ | 584 | lua_pushliteral(L, "cannot close standard file"); |
588 | lua_setfield(L, 2, fname); /* add file to module */ | 585 | return 2; |
589 | } | 586 | } |
590 | 587 | ||
591 | 588 | ||
592 | /* | 589 | static void createstdfile (lua_State *L, FILE *f, const char *k, |
593 | ** pushes a new table with {__close = cls} | 590 | const char *fname) { |
594 | */ | 591 | LStream *p = newprefile(L); |
595 | static void newenv (lua_State *L, lua_CFunction cls) { | 592 | p->f = f; |
596 | lua_createtable(L, 0, 1); | 593 | p->closef = &io_noclose; |
597 | lua_pushcfunction(L, cls); | 594 | if (k != NULL) { |
598 | lua_setfield(L, -2, "__close"); | 595 | lua_pushvalue(L, -1); |
596 | lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ | ||
597 | } | ||
598 | lua_setfield(L, -2, fname); /* add file to module */ | ||
599 | } | 599 | } |
600 | 600 | ||
601 | 601 | ||
602 | LUAMOD_API int luaopen_io (lua_State *L) { | 602 | LUAMOD_API int luaopen_io (lua_State *L) { |
603 | lua_settop(L, 0); | 603 | luaL_newlib(L, iolib); /* new module */ |
604 | createmeta(L); | 604 | createmeta(L); |
605 | /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ | ||
606 | newenv(L, io_fclose); /* upvalue for all io functions at index 1 */ | ||
607 | luaL_newlibtable(L, iolib); /* new module at index 2 */ | ||
608 | lua_pushvalue(L, 1); /* copy of env to be consumed by 'setfuncs' */ | ||
609 | luaL_setfuncs(L, iolib, 1); | ||
610 | /* create (and set) default files */ | 605 | /* create (and set) default files */ |
611 | newenv(L, io_noclose); /* environment for default files at index 3 */ | ||
612 | createstdfile(L, stdin, IO_INPUT, "stdin"); | 606 | createstdfile(L, stdin, IO_INPUT, "stdin"); |
613 | createstdfile(L, stdout, IO_OUTPUT, "stdout"); | 607 | createstdfile(L, stdout, IO_OUTPUT, "stdout"); |
614 | createstdfile(L, stderr, 0, "stderr"); | 608 | createstdfile(L, stderr, NULL, "stderr"); |
615 | lua_pop(L, 1); /* pop environment for default files */ | ||
616 | lua_getfield(L, 2, "popen"); | ||
617 | newenv(L, io_pclose); /* create environment for 'popen' streams */ | ||
618 | lua_setupvalue(L, -2, 1); /* set it as upvalue for 'popen' */ | ||
619 | lua_pop(L, 1); /* pop 'popen' */ | ||
620 | return 1; | 609 | return 1; |
621 | } | 610 | } |
622 | 611 | ||