Line data Source code
1 : /*
2 : ** $Id: liolib.c,v 2.151.1.1 2017/04/19 17:29:57 roberto Exp $
3 : ** Standard I/O (and system) library
4 : ** See Copyright Notice in lua.h
5 : */
6 :
7 : #define liolib_c
8 : #define LUA_LIB
9 :
10 : #include "lprefix.h"
11 :
12 :
13 : #include <ctype.h>
14 : #include <errno.h>
15 : #include <locale.h>
16 : #include <stdio.h>
17 : #include <stdlib.h>
18 : #include <string.h>
19 :
20 : #include "lua.h"
21 :
22 : #include "lauxlib.h"
23 : #include "lualib.h"
24 :
25 :
26 :
27 :
28 : /*
29 : ** Change this macro to accept other modes for 'fopen' besides
30 : ** the standard ones.
31 : */
32 : #if !defined(l_checkmode)
33 :
34 : /* accepted extensions to 'mode' in 'fopen' */
35 : #if !defined(L_MODEEXT)
36 : #define L_MODEEXT "b"
37 : #endif
38 :
39 : /* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
40 61 : static int l_checkmode (const char *mode) {
41 61 : return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&
42 182 : (*mode != '+' || (++mode, 1)) && /* skip if char is '+' */
43 60 : (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */
44 : }
45 :
46 : #endif
47 :
48 : /*
49 : ** {======================================================
50 : ** l_popen spawns a new process connected to the current
51 : ** one through the file streams.
52 : ** =======================================================
53 : */
54 :
55 : #if !defined(l_popen) /* { */
56 :
57 : #if defined(LUA_USE_POSIX) /* { */
58 :
59 : #define l_popen(L,c,m) (fflush(NULL), popen(c,m))
60 : #define l_pclose(L,file) (pclose(file))
61 :
62 : #elif defined(LUA_USE_WINDOWS) /* }{ */
63 :
64 : #define l_popen(L,c,m) (_popen(c,m))
65 : #define l_pclose(L,file) (_pclose(file))
66 :
67 : #else /* }{ */
68 :
69 : /* ISO C definitions */
70 : #define l_popen(L,c,m) \
71 : ((void)((void)c, m), \
72 : luaL_error(L, "'popen' not supported"), \
73 : (FILE*)0)
74 : #define l_pclose(L,file) ((void)L, (void)file, -1)
75 :
76 : #endif /* } */
77 :
78 : #endif /* } */
79 :
80 : /* }====================================================== */
81 :
82 :
83 : #if !defined(l_getc) /* { */
84 :
85 : #if defined(LUA_USE_POSIX)
86 : #define l_getc(f) getc_unlocked(f)
87 : #define l_lockfile(f) flockfile(f)
88 : #define l_unlockfile(f) funlockfile(f)
89 : #else
90 : #define l_getc(f) getc(f)
91 : #define l_lockfile(f) ((void)0)
92 : #define l_unlockfile(f) ((void)0)
93 : #endif
94 :
95 : #endif /* } */
96 :
97 :
98 : /*
99 : ** {======================================================
100 : ** l_fseek: configuration for longer offsets
101 : ** =======================================================
102 : */
103 :
104 : #if !defined(l_fseek) /* { */
105 :
106 : #if defined(LUA_USE_POSIX) /* { */
107 :
108 : #include <sys/types.h>
109 :
110 : #define l_fseek(f,o,w) fseeko(f,o,w)
111 : #define l_ftell(f) ftello(f)
112 : #define l_seeknum off_t
113 :
114 : #elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \
115 : && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */
116 :
117 : /* Windows (but not DDK) and Visual C++ 2005 or higher */
118 : #define l_fseek(f,o,w) _fseeki64(f,o,w)
119 : #define l_ftell(f) _ftelli64(f)
120 : #define l_seeknum __int64
121 :
122 : #else /* }{ */
123 :
124 : /* ISO C definitions */
125 : #define l_fseek(f,o,w) fseek(f,o,w)
126 : #define l_ftell(f) ftell(f)
127 : #define l_seeknum long
128 :
129 : #endif /* } */
130 :
131 : #endif /* } */
132 :
133 : /* }====================================================== */
134 :
135 :
136 : #define IO_PREFIX "_IO_"
137 : #define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1)
138 : #define IO_INPUT (IO_PREFIX "input")
139 : #define IO_OUTPUT (IO_PREFIX "output")
140 :
141 :
142 : typedef luaL_Stream LStream;
143 :
144 :
145 : #define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
146 :
147 : #define isclosed(p) ((p)->closef == NULL)
148 :
149 :
150 9 : static int io_type (lua_State *L) {
151 : LStream *p;
152 9 : luaL_checkany(L, 1);
153 9 : p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
154 9 : if (p == NULL)
155 1 : lua_pushnil(L); /* not a file */
156 8 : else if (isclosed(p))
157 2 : lua_pushliteral(L, "closed file");
158 : else
159 6 : lua_pushliteral(L, "file");
160 9 : return 1;
161 : }
162 :
163 :
164 12 : static int f_tostring (lua_State *L) {
165 12 : LStream *p = tolstream(L);
166 12 : if (isclosed(p))
167 2 : lua_pushliteral(L, "file (closed)");
168 : else
169 10 : lua_pushfstring(L, "file (%p)", p->f);
170 12 : return 1;
171 : }
172 :
173 :
174 277 : static FILE *tofile (lua_State *L) {
175 277 : LStream *p = tolstream(L);
176 277 : if (isclosed(p))
177 6 : luaL_error(L, "attempt to use a closed file");
178 : lua_assert(p->f);
179 271 : return p->f;
180 : }
181 :
182 :
183 : /*
184 : ** When creating file handles, always creates a 'closed' file handle
185 : ** before opening the actual file; so, if there is a memory error, the
186 : ** handle is in a consistent state.
187 : */
188 389 : static LStream *newprefile (lua_State *L) {
189 389 : LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
190 389 : p->closef = NULL; /* mark file handle as 'closed' */
191 389 : luaL_setmetatable(L, LUA_FILEHANDLE);
192 389 : return p;
193 : }
194 :
195 :
196 : /*
197 : ** Calls the 'close' function from a file handle. The 'volatile' avoids
198 : ** a bug in some versions of the Clang compiler (e.g., clang 3.0 for
199 : ** 32 bits).
200 : */
201 361 : static int aux_close (lua_State *L) {
202 361 : LStream *p = tolstream(L);
203 361 : volatile lua_CFunction cf = p->closef;
204 361 : p->closef = NULL; /* mark stream as closed */
205 361 : return (*cf)(L); /* close it */
206 : }
207 :
208 :
209 120 : static int f_close (lua_State *L) {
210 120 : tofile(L); /* make sure argument is an open stream */
211 118 : return aux_close(L);
212 : }
213 :
214 :
215 9 : static int io_close (lua_State *L) {
216 9 : if (lua_isnone(L, 1)) /* no argument? */
217 3 : lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */
218 9 : return f_close(L);
219 : }
220 :
221 :
222 362 : static int f_gc (lua_State *L) {
223 362 : LStream *p = tolstream(L);
224 362 : if (!isclosed(p) && p->f != NULL)
225 242 : aux_close(L); /* ignore closed and incompletely open files */
226 362 : return 0;
227 : }
228 :
229 :
230 : /*
231 : ** function to close regular files
232 : */
233 65 : static int io_fclose (lua_State *L) {
234 65 : LStream *p = tolstream(L);
235 65 : int res = fclose(p->f);
236 65 : return luaL_fileresult(L, (res == 0), NULL);
237 : }
238 :
239 :
240 69 : static LStream *newfile (lua_State *L) {
241 69 : LStream *p = newprefile(L);
242 69 : p->f = NULL;
243 69 : p->closef = &io_fclose;
244 69 : return p;
245 : }
246 :
247 :
248 5 : static void opencheck (lua_State *L, const char *fname, const char *mode) {
249 5 : LStream *p = newfile(L);
250 5 : p->f = fopen(fname, mode);
251 5 : if (p->f == NULL)
252 2 : luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
253 3 : }
254 :
255 :
256 61 : static int io_open (lua_State *L) {
257 61 : const char *filename = luaL_checkstring(L, 1);
258 61 : const char *mode = luaL_optstring(L, 2, "r");
259 61 : LStream *p = newfile(L);
260 61 : const char *md = mode; /* to traverse/check mode */
261 61 : luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
262 60 : p->f = fopen(filename, mode);
263 60 : return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
264 : }
265 :
266 :
267 : /*
268 : ** function to close 'popen' files
269 : */
270 62 : static int io_pclose (lua_State *L) {
271 62 : LStream *p = tolstream(L);
272 62 : return luaL_execresult(L, l_pclose(L, p->f));
273 : }
274 :
275 :
276 62 : static int io_popen (lua_State *L) {
277 62 : const char *filename = luaL_checkstring(L, 1);
278 62 : const char *mode = luaL_optstring(L, 2, "r");
279 62 : LStream *p = newprefile(L);
280 62 : luaL_argcheck(L, ((mode[0] == 'r' || mode[0] == 'w') && mode[1] == '\0'),
281 : 2, "invalid mode");
282 62 : p->f = l_popen(L, filename, mode);
283 62 : p->closef = &io_pclose;
284 62 : return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
285 : }
286 :
287 :
288 3 : static int io_tmpfile (lua_State *L) {
289 3 : LStream *p = newfile(L);
290 3 : p->f = tmpfile();
291 3 : return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
292 : }
293 :
294 :
295 8 : static FILE *getiofile (lua_State *L, const char *findex) {
296 : LStream *p;
297 8 : lua_getfield(L, LUA_REGISTRYINDEX, findex);
298 8 : p = (LStream *)lua_touserdata(L, -1);
299 8 : if (isclosed(p))
300 0 : luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN);
301 8 : return p->f;
302 : }
303 :
304 :
305 11 : static int g_iofile (lua_State *L, const char *f, const char *mode) {
306 11 : if (!lua_isnoneornil(L, 1)) {
307 7 : const char *filename = lua_tostring(L, 1);
308 7 : if (filename)
309 3 : opencheck(L, filename, mode);
310 : else {
311 4 : tofile(L); /* check that it's a valid file handle */
312 4 : lua_pushvalue(L, 1);
313 : }
314 6 : lua_setfield(L, LUA_REGISTRYINDEX, f);
315 : }
316 : /* return current value */
317 10 : lua_getfield(L, LUA_REGISTRYINDEX, f);
318 10 : return 1;
319 : }
320 :
321 :
322 6 : static int io_input (lua_State *L) {
323 6 : return g_iofile(L, IO_INPUT, "r");
324 : }
325 :
326 :
327 5 : static int io_output (lua_State *L) {
328 5 : return g_iofile(L, IO_OUTPUT, "w");
329 : }
330 :
331 :
332 : static int io_readline (lua_State *L);
333 :
334 :
335 : /*
336 : ** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
337 : ** in the limit for upvalues of a closure)
338 : */
339 : #define MAXARGLINE 250
340 :
341 8 : static void aux_lines (lua_State *L, int toclose) {
342 8 : int n = lua_gettop(L) - 1; /* number of arguments to read */
343 8 : luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
344 8 : lua_pushinteger(L, n); /* number of arguments to read */
345 8 : lua_pushboolean(L, toclose); /* close/not close file when finished */
346 8 : lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */
347 8 : lua_pushcclosure(L, io_readline, 3 + n);
348 8 : }
349 :
350 :
351 5 : static int f_lines (lua_State *L) {
352 5 : tofile(L); /* check that it's a valid file handle */
353 5 : aux_lines(L, 0);
354 5 : return 1;
355 : }
356 :
357 :
358 4 : static int io_lines (lua_State *L) {
359 : int toclose;
360 4 : if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */
361 4 : if (lua_isnil(L, 1)) { /* no file name? */
362 2 : lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */
363 2 : lua_replace(L, 1); /* put it at index 1 */
364 2 : tofile(L); /* check that it's a valid file handle */
365 2 : toclose = 0; /* do not close it after iteration */
366 : }
367 : else { /* open a new file */
368 2 : const char *filename = luaL_checkstring(L, 1);
369 2 : opencheck(L, filename, "r");
370 1 : lua_replace(L, 1); /* put file at index 1 */
371 1 : toclose = 1; /* close it after iteration */
372 : }
373 3 : aux_lines(L, toclose);
374 3 : return 1;
375 : }
376 :
377 :
378 : /*
379 : ** {======================================================
380 : ** READ
381 : ** =======================================================
382 : */
383 :
384 :
385 : /* maximum length of a numeral */
386 : #if !defined (L_MAXLENNUM)
387 : #define L_MAXLENNUM 200
388 : #endif
389 :
390 :
391 : /* auxiliary structure used by 'read_number' */
392 : typedef struct {
393 : FILE *f; /* file being read */
394 : int c; /* current character (look ahead) */
395 : int n; /* number of elements in buffer 'buff' */
396 : char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */
397 : } RN;
398 :
399 :
400 : /*
401 : ** Add current char to buffer (if not out of space) and read next one
402 : */
403 260 : static int nextc (RN *rn) {
404 260 : if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */
405 1 : rn->buff[0] = '\0'; /* invalidate result */
406 1 : return 0; /* fail */
407 : }
408 : else {
409 259 : rn->buff[rn->n++] = rn->c; /* save current char */
410 259 : rn->c = l_getc(rn->f); /* read next one */
411 259 : return 1;
412 : }
413 : }
414 :
415 :
416 : /*
417 : ** Accept current char if it is in 'set' (of size 2)
418 : */
419 57 : static int test2 (RN *rn, const char *set) {
420 57 : if (rn->c == set[0] || rn->c == set[1])
421 10 : return nextc(rn);
422 47 : else return 0;
423 : }
424 :
425 :
426 : /*
427 : ** Read a sequence of (hex)digits
428 : */
429 20 : static int readdigits (RN *rn, int hex) {
430 20 : int count = 0;
431 269 : while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn))
432 249 : count++;
433 20 : return count;
434 : }
435 :
436 :
437 : /*
438 : ** Read a number: first reads a valid prefix of a numeral into a buffer.
439 : ** Then it calls 'lua_stringtonumber' to check whether the format is
440 : ** correct and to convert it to a Lua number
441 : */
442 14 : static int read_number (lua_State *L, FILE *f) {
443 : RN rn;
444 14 : int count = 0;
445 14 : int hex = 0;
446 : char decp[2];
447 14 : rn.f = f; rn.n = 0;
448 14 : decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */
449 14 : decp[1] = '.'; /* always accept a dot */
450 14 : l_lockfile(rn.f);
451 37 : do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
452 14 : test2(&rn, "-+"); /* optional signal */
453 14 : if (test2(&rn, "00")) {
454 2 : if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */
455 1 : else count = 1; /* count initial '0' as a valid digit */
456 : }
457 14 : count += readdigits(&rn, hex); /* integral part */
458 14 : if (test2(&rn, decp)) /* decimal point? */
459 5 : count += readdigits(&rn, hex); /* fractional part */
460 14 : if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */
461 1 : test2(&rn, "-+"); /* exponent signal */
462 1 : readdigits(&rn, 0); /* exponent digits */
463 : }
464 14 : ungetc(rn.c, rn.f); /* unread look-ahead char */
465 14 : l_unlockfile(rn.f);
466 14 : rn.buff[rn.n] = '\0'; /* finish string */
467 14 : if (lua_stringtonumber(L, rn.buff)) /* is this a valid number? */
468 11 : return 1; /* ok */
469 : else { /* invalid format */
470 3 : lua_pushnil(L); /* "result" to be removed */
471 3 : return 0; /* read fails */
472 : }
473 : }
474 :
475 :
476 1 : static int test_eof (lua_State *L, FILE *f) {
477 1 : int c = getc(f);
478 1 : ungetc(c, f); /* no-op when c == EOF */
479 1 : lua_pushliteral(L, "");
480 1 : return (c != EOF);
481 : }
482 :
483 :
484 263 : static int read_line (lua_State *L, FILE *f, int chop) {
485 : luaL_Buffer b;
486 263 : int c = '\0';
487 263 : luaL_buffinit(L, &b);
488 526 : while (c != EOF && c != '\n') { /* repeat until end of line */
489 263 : char *buff = luaL_prepbuffer(&b); /* preallocate buffer */
490 263 : int i = 0;
491 263 : l_lockfile(f); /* no memory errors can happen inside the lock */
492 9123 : while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n')
493 8860 : buff[i++] = c;
494 263 : l_unlockfile(f);
495 263 : luaL_addsize(&b, i);
496 : }
497 263 : if (!chop && c == '\n') /* want a newline and have one? */
498 1 : luaL_addchar(&b, c); /* add ending newline to result */
499 263 : luaL_pushresult(&b); /* close buffer */
500 : /* return ok if read something (either a newline or something else) */
501 263 : return (c == '\n' || lua_rawlen(L, -1) > 0);
502 : }
503 :
504 :
505 2 : static void read_all (lua_State *L, FILE *f) {
506 : size_t nr;
507 : luaL_Buffer b;
508 2 : luaL_buffinit(L, &b);
509 : do { /* read file in chunks of LUAL_BUFFERSIZE bytes */
510 2 : char *p = luaL_prepbuffer(&b);
511 2 : nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
512 2 : luaL_addsize(&b, nr);
513 2 : } while (nr == LUAL_BUFFERSIZE);
514 2 : luaL_pushresult(&b); /* close buffer */
515 2 : }
516 :
517 :
518 4 : static int read_chars (lua_State *L, FILE *f, size_t n) {
519 : size_t nr; /* number of chars actually read */
520 : char *p;
521 : luaL_Buffer b;
522 4 : luaL_buffinit(L, &b);
523 4 : p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */
524 4 : nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */
525 4 : luaL_addsize(&b, nr);
526 4 : luaL_pushresult(&b); /* close buffer */
527 4 : return (nr > 0); /* true iff read something */
528 : }
529 :
530 :
531 276 : static int g_read (lua_State *L, FILE *f, int first) {
532 276 : int nargs = lua_gettop(L) - 1;
533 : int success;
534 : int n;
535 276 : clearerr(f);
536 276 : if (nargs == 0) { /* no arguments? */
537 176 : success = read_line(L, f, 1);
538 176 : n = first+1; /* to return 1 result */
539 : }
540 : else { /* ensure stack space for all results and for auxlib's buffer */
541 100 : luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
542 100 : success = 1;
543 208 : for (n = first; nargs-- && success; n++) {
544 109 : if (lua_type(L, n) == LUA_TNUMBER) {
545 5 : size_t l = (size_t)luaL_checkinteger(L, n);
546 5 : success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
547 : }
548 : else {
549 104 : const char *p = luaL_checkstring(L, n);
550 104 : if (*p == '*') p++; /* skip optional '*' (for compatibility) */
551 104 : switch (*p) {
552 14 : case 'n': /* number */
553 14 : success = read_number(L, f);
554 14 : break;
555 85 : case 'l': /* line */
556 85 : success = read_line(L, f, 1);
557 85 : break;
558 2 : case 'L': /* line with end-of-line */
559 2 : success = read_line(L, f, 0);
560 2 : break;
561 2 : case 'a': /* file */
562 2 : read_all(L, f); /* read entire file */
563 2 : success = 1; /* always success */
564 2 : break;
565 1 : default:
566 1 : return luaL_argerror(L, n, "invalid format");
567 : }
568 : }
569 : }
570 : }
571 275 : if (ferror(f))
572 0 : return luaL_fileresult(L, 0, NULL);
573 275 : if (!success) {
574 19 : lua_pop(L, 1); /* remove last result */
575 19 : lua_pushnil(L); /* push nil instead */
576 : }
577 275 : return n - first;
578 : }
579 :
580 :
581 5 : static int io_read (lua_State *L) {
582 5 : return g_read(L, getiofile(L, IO_INPUT), 1);
583 : }
584 :
585 :
586 98 : static int f_read (lua_State *L) {
587 98 : return g_read(L, tofile(L), 2);
588 : }
589 :
590 :
591 174 : static int io_readline (lua_State *L) {
592 174 : LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
593 : int i;
594 174 : int n = (int)lua_tointeger(L, lua_upvalueindex(2));
595 174 : if (isclosed(p)) /* file is already closed? */
596 0 : return luaL_error(L, "file is already closed");
597 174 : lua_settop(L , 1);
598 174 : luaL_checkstack(L, n, "too many arguments");
599 175 : for (i = 1; i <= n; i++) /* push arguments to 'g_read' */
600 1 : lua_pushvalue(L, lua_upvalueindex(3 + i));
601 174 : n = g_read(L, p->f, 2); /* 'n' is number of results */
602 : lua_assert(n > 0); /* should return at least a nil */
603 174 : if (lua_toboolean(L, -n)) /* read at least one value? */
604 170 : return n; /* return them */
605 : else { /* first result is nil: EOF or error */
606 4 : if (n > 1) { /* is there error information? */
607 : /* 2nd result is error message */
608 0 : return luaL_error(L, "%s", lua_tostring(L, -n + 1));
609 : }
610 4 : if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
611 1 : lua_settop(L, 0);
612 1 : lua_pushvalue(L, lua_upvalueindex(1));
613 1 : aux_close(L); /* close it */
614 : }
615 4 : return 0;
616 : }
617 : }
618 :
619 : /* }====================================================== */
620 :
621 :
622 41 : static int g_write (lua_State *L, FILE *f, int arg) {
623 41 : int nargs = lua_gettop(L) - arg;
624 41 : int status = 1;
625 83 : for (; nargs--; arg++) {
626 42 : if (lua_type(L, arg) == LUA_TNUMBER) {
627 : /* optimization: could be done exactly as for strings */
628 1 : int len = lua_isinteger(L, arg)
629 1 : ? fprintf(f, LUA_INTEGER_FMT,
630 1 : (LUAI_UACINT)lua_tointeger(L, arg))
631 1 : : fprintf(f, LUA_NUMBER_FMT,
632 0 : (LUAI_UACNUMBER)lua_tonumber(L, arg));
633 1 : status = status && (len > 0);
634 : }
635 : else {
636 : size_t l;
637 41 : const char *s = luaL_checklstring(L, arg, &l);
638 41 : status = status && (fwrite(s, sizeof(char), l, f) == l);
639 : }
640 : }
641 41 : if (status) return 1; /* file handle already on stack top */
642 0 : else return luaL_fileresult(L, status, NULL);
643 : }
644 :
645 :
646 2 : static int io_write (lua_State *L) {
647 2 : return g_write(L, getiofile(L, IO_OUTPUT), 1);
648 : }
649 :
650 :
651 40 : static int f_write (lua_State *L) {
652 40 : FILE *f = tofile(L);
653 39 : lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
654 39 : return g_write(L, f, 2);
655 : }
656 :
657 :
658 3 : static int f_seek (lua_State *L) {
659 : static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
660 : static const char *const modenames[] = {"set", "cur", "end", NULL};
661 3 : FILE *f = tofile(L);
662 2 : int op = luaL_checkoption(L, 2, "cur", modenames);
663 1 : lua_Integer p3 = luaL_optinteger(L, 3, 0);
664 1 : l_seeknum offset = (l_seeknum)p3;
665 1 : luaL_argcheck(L, (lua_Integer)offset == p3, 3,
666 : "not an integer in proper range");
667 1 : op = l_fseek(f, offset, mode[op]);
668 1 : if (op)
669 0 : return luaL_fileresult(L, 0, NULL); /* error */
670 : else {
671 1 : lua_pushinteger(L, (lua_Integer)l_ftell(f));
672 1 : return 1;
673 : }
674 : }
675 :
676 :
677 3 : static int f_setvbuf (lua_State *L) {
678 : static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
679 : static const char *const modenames[] = {"no", "full", "line", NULL};
680 3 : FILE *f = tofile(L);
681 3 : int op = luaL_checkoption(L, 2, NULL, modenames);
682 3 : lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
683 3 : int res = setvbuf(f, NULL, mode[op], (size_t)sz);
684 3 : return luaL_fileresult(L, res == 0, NULL);
685 : }
686 :
687 :
688 :
689 1 : static int io_flush (lua_State *L) {
690 1 : return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
691 : }
692 :
693 :
694 2 : static int f_flush (lua_State *L) {
695 2 : return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
696 : }
697 :
698 :
699 : /*
700 : ** functions for 'io' library
701 : */
702 : static const luaL_Reg iolib[] = {
703 : {"close", io_close},
704 : {"flush", io_flush},
705 : {"input", io_input},
706 : {"lines", io_lines},
707 : {"open", io_open},
708 : {"output", io_output},
709 : {"popen", io_popen},
710 : {"read", io_read},
711 : {"tmpfile", io_tmpfile},
712 : {"type", io_type},
713 : {"write", io_write},
714 : {NULL, NULL}
715 : };
716 :
717 :
718 : /*
719 : ** methods for file handles
720 : */
721 : static const luaL_Reg flib[] = {
722 : {"close", f_close},
723 : {"flush", f_flush},
724 : {"lines", f_lines},
725 : {"read", f_read},
726 : {"seek", f_seek},
727 : {"setvbuf", f_setvbuf},
728 : {"write", f_write},
729 : {"__gc", f_gc},
730 : {"__tostring", f_tostring},
731 : {NULL, NULL}
732 : };
733 :
734 :
735 86 : static void createmeta (lua_State *L) {
736 86 : luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
737 86 : lua_pushvalue(L, -1); /* push metatable */
738 86 : lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
739 86 : luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */
740 86 : lua_pop(L, 1); /* pop new metatable */
741 86 : }
742 :
743 :
744 : /*
745 : ** function to (not) close the standard files stdin, stdout, and stderr
746 : */
747 234 : static int io_noclose (lua_State *L) {
748 234 : LStream *p = tolstream(L);
749 234 : p->closef = &io_noclose; /* keep file opened */
750 234 : lua_pushnil(L);
751 234 : lua_pushliteral(L, "cannot close standard file");
752 234 : return 2;
753 : }
754 :
755 :
756 258 : static void createstdfile (lua_State *L, FILE *f, const char *k,
757 : const char *fname) {
758 258 : LStream *p = newprefile(L);
759 258 : p->f = f;
760 258 : p->closef = &io_noclose;
761 258 : if (k != NULL) {
762 172 : lua_pushvalue(L, -1);
763 172 : lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */
764 : }
765 258 : lua_setfield(L, -2, fname); /* add file to module */
766 258 : }
767 :
768 :
769 86 : LUAMOD_API int luaopen_io (lua_State *L) {
770 86 : luaL_newlib(L, iolib); /* new module */
771 86 : createmeta(L);
772 : /* create (and set) default files */
773 86 : createstdfile(L, stdin, IO_INPUT, "stdin");
774 86 : createstdfile(L, stdout, IO_OUTPUT, "stdout");
775 86 : createstdfile(L, stderr, NULL, "stderr");
776 86 : return 1;
777 : }
778 :
|