fixed a bug : stand alone expression was failing
[ikh.git] / lua / src / liolib.c
blob4814aa2c2aec802bc8d6439f52f7d17e3e3dac48
1 /*
2 ** $Id: liolib.c,v 2.108 2011/11/25 12:50:03 roberto Exp $
3 ** Standard I/O (and system) library
4 ** See Copyright Notice in lua.h
5 */
8 /*
9 ** POSIX idiosyncrasy!
10 ** This definition must come before the inclusion of 'stdio.h'; it
11 ** should not affect non-POSIX systems
13 #if !defined(_FILE_OFFSET_BITS)
14 #define _FILE_OFFSET_BITS 64
15 #endif
18 #include <errno.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
23 #define liolib_c
24 #define LUA_LIB
26 #include "lua.h"
28 #include "lauxlib.h"
29 #include "lualib.h"
34 ** {======================================================
35 ** lua_popen spawns a new process connected to the current
36 ** one through the file streams.
37 ** =======================================================
40 #if !defined(lua_popen) /* { */
42 #if defined(LUA_USE_POPEN) /* { */
44 #define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m))
45 #define lua_pclose(L,file) ((void)L, pclose(file))
47 #elif defined(LUA_WIN) /* }{ */
49 #define lua_popen(L,c,m) ((void)L, _popen(c,m))
50 #define lua_pclose(L,file) ((void)L, _pclose(file))
53 #else /* }{ */
55 #define lua_popen(L,c,m) ((void)((void)c, m), \
56 luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
57 #define lua_pclose(L,file) ((void)((void)L, file), -1)
60 #endif /* } */
62 #endif /* } */
64 /* }====================================================== */
68 ** {======================================================
69 ** lua_fseek/lua_ftell: configuration for longer offsets
70 ** =======================================================
73 #if !defined(lua_fseek) /* { */
75 #if defined(LUA_USE_POSIX)
77 #define l_fseek(f,o,w) fseeko(f,o,w)
78 #define l_ftell(f) ftello(f)
79 #define l_seeknum off_t
81 #elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \
82 && defined(_MSC_VER) && (_MSC_VER >= 1400)
83 /* Windows (but not DDK) and Visual C++ 2005 or higher */
85 #define l_fseek(f,o,w) _fseeki64(f,o,w)
86 #define l_ftell(f) _ftelli64(f)
87 #define l_seeknum __int64
89 #else
91 #define l_fseek(f,o,w) fseek(f,o,w)
92 #define l_ftell(f) ftell(f)
93 #define l_seeknum long
95 #endif
97 #endif /* } */
99 /* }====================================================== */
102 #define IO_PREFIX "_IO_"
103 #define IO_INPUT (IO_PREFIX "input")
104 #define IO_OUTPUT (IO_PREFIX "output")
107 typedef luaL_Stream LStream;
110 #define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
112 #define isclosed(p) ((p)->closef == NULL)
115 static int io_type (lua_State *L) {
116 LStream *p;
117 luaL_checkany(L, 1);
118 p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
119 if (p == NULL)
120 lua_pushnil(L); /* not a file */
121 else if (isclosed(p))
122 lua_pushliteral(L, "closed file");
123 else
124 lua_pushliteral(L, "file");
125 return 1;
129 static int f_tostring (lua_State *L) {
130 LStream *p = tolstream(L);
131 if (isclosed(p))
132 lua_pushliteral(L, "file (closed)");
133 else
134 lua_pushfstring(L, "file (%p)", p->f);
135 return 1;
139 static FILE *tofile (lua_State *L) {
140 LStream *p = tolstream(L);
141 if (isclosed(p))
142 luaL_error(L, "attempt to use a closed file");
143 lua_assert(p->f);
144 return p->f;
149 ** When creating file handles, always creates a `closed' file handle
150 ** before opening the actual file; so, if there is a memory error, the
151 ** file is not left opened.
153 static LStream *newprefile (lua_State *L) {
154 LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
155 p->closef = NULL; /* mark file handle as 'closed' */
156 luaL_setmetatable(L, LUA_FILEHANDLE);
157 return p;
161 static int aux_close (lua_State *L) {
162 LStream *p = tolstream(L);
163 lua_CFunction cf = p->closef;
164 p->closef = NULL; /* mark stream as closed */
165 return (*cf)(L); /* close it */
169 static int io_close (lua_State *L) {
170 if (lua_isnone(L, 1)) /* no argument? */
171 lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */
172 tofile(L); /* make sure argument is an open stream */
173 return aux_close(L);
177 static int f_gc (lua_State *L) {
178 LStream *p = tolstream(L);
179 if (!isclosed(p) && p->f != NULL)
180 aux_close(L); /* ignore closed and incompletely open files */
181 return 0;
186 ** function to close regular files
188 static int io_fclose (lua_State *L) {
189 LStream *p = tolstream(L);
190 int res = fclose(p->f);
191 return luaL_fileresult(L, (res == 0), NULL);
195 static LStream *newfile (lua_State *L) {
196 LStream *p = newprefile(L);
197 p->f = NULL;
198 p->closef = &io_fclose;
199 return p;
203 static void opencheck (lua_State *L, const char *fname, const char *mode) {
204 LStream *p = newfile(L);
205 p->f = fopen(fname, mode);
206 if (p->f == NULL)
207 luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno));
211 static int io_open (lua_State *L) {
212 const char *filename = luaL_checkstring(L, 1);
213 const char *mode = luaL_optstring(L, 2, "r");
214 LStream *p = newfile(L);
215 int i = 0;
216 /* check whether 'mode' matches '[rwa]%+?b?' */
217 if (!(mode[i] != '\0' && strchr("rwa", mode[i++]) != NULL &&
218 (mode[i] != '+' || ++i) && /* skip if char is '+' */
219 (mode[i] != 'b' || ++i) && /* skip if char is 'b' */
220 (mode[i] == '\0')))
221 return luaL_error(L, "invalid mode " LUA_QS
222 " (should match " LUA_QL("[rwa]%%+?b?") ")", mode);
223 p->f = fopen(filename, mode);
224 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
229 ** function to close 'popen' files
231 static int io_pclose (lua_State *L) {
232 LStream *p = tolstream(L);
233 return luaL_execresult(L, lua_pclose(L, p->f));
237 static int io_popen (lua_State *L) {
238 const char *filename = luaL_checkstring(L, 1);
239 const char *mode = luaL_optstring(L, 2, "r");
240 LStream *p = newprefile(L);
241 p->f = lua_popen(L, filename, mode);
242 p->closef = &io_pclose;
243 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
247 static int io_tmpfile (lua_State *L) {
248 LStream *p = newfile(L);
249 p->f = tmpfile();
250 return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
254 static FILE *getiofile (lua_State *L, const char *findex) {
255 LStream *p;
256 lua_getfield(L, LUA_REGISTRYINDEX, findex);
257 p = (LStream *)lua_touserdata(L, -1);
258 if (isclosed(p))
259 luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX));
260 return p->f;
264 static int g_iofile (lua_State *L, const char *f, const char *mode) {
265 if (!lua_isnoneornil(L, 1)) {
266 const char *filename = lua_tostring(L, 1);
267 if (filename)
268 opencheck(L, filename, mode);
269 else {
270 tofile(L); /* check that it's a valid file handle */
271 lua_pushvalue(L, 1);
273 lua_setfield(L, LUA_REGISTRYINDEX, f);
275 /* return current value */
276 lua_getfield(L, LUA_REGISTRYINDEX, f);
277 return 1;
281 static int io_input (lua_State *L) {
282 return g_iofile(L, IO_INPUT, "r");
286 static int io_output (lua_State *L) {
287 return g_iofile(L, IO_OUTPUT, "w");
291 static int io_readline (lua_State *L);
294 static void aux_lines (lua_State *L, int toclose) {
295 int i;
296 int n = lua_gettop(L) - 1; /* number of arguments to read */
297 /* ensure that arguments will fit here and into 'io_readline' stack */
298 luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options");
299 lua_pushvalue(L, 1); /* file handle */
300 lua_pushinteger(L, n); /* number of arguments to read */
301 lua_pushboolean(L, toclose); /* close/not close file when finished */
302 for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1); /* copy arguments */
303 lua_pushcclosure(L, io_readline, 3 + n);
307 static int f_lines (lua_State *L) {
308 tofile(L); /* check that it's a valid file handle */
309 aux_lines(L, 0);
310 return 1;
314 static int io_lines (lua_State *L) {
315 int toclose;
316 if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */
317 if (lua_isnil(L, 1)) { /* no file name? */
318 lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */
319 lua_replace(L, 1); /* put it at index 1 */
320 tofile(L); /* check that it's a valid file handle */
321 toclose = 0; /* do not close it after iteration */
323 else { /* open a new file */
324 const char *filename = luaL_checkstring(L, 1);
325 opencheck(L, filename, "r");
326 lua_replace(L, 1); /* put file at index 1 */
327 toclose = 1; /* close it after iteration */
329 aux_lines(L, toclose);
330 return 1;
335 ** {======================================================
336 ** READ
337 ** =======================================================
341 static int read_number (lua_State *L, FILE *f) {
342 lua_Number d;
343 if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
344 lua_pushnumber(L, d);
345 return 1;
347 else {
348 lua_pushnil(L); /* "result" to be removed */
349 return 0; /* read fails */
354 static int test_eof (lua_State *L, FILE *f) {
355 int c = getc(f);
356 ungetc(c, f);
357 lua_pushlstring(L, NULL, 0);
358 return (c != EOF);
362 static int read_line (lua_State *L, FILE *f, int chop) {
363 luaL_Buffer b;
364 luaL_buffinit(L, &b);
365 for (;;) {
366 size_t l;
367 char *p = luaL_prepbuffer(&b);
368 if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
369 luaL_pushresult(&b); /* close buffer */
370 return (lua_rawlen(L, -1) > 0); /* check whether read something */
372 l = strlen(p);
373 if (l == 0 || p[l-1] != '\n')
374 luaL_addsize(&b, l);
375 else {
376 luaL_addsize(&b, l - chop); /* chop 'eol' if needed */
377 luaL_pushresult(&b); /* close buffer */
378 return 1; /* read at least an `eol' */
384 #define MAX_SIZE_T (~(size_t)0)
386 static void read_all (lua_State *L, FILE *f) {
387 size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */
388 luaL_Buffer b;
389 luaL_buffinit(L, &b);
390 for (;;) {
391 char *p = luaL_prepbuffsize(&b, rlen);
392 size_t nr = fread(p, sizeof(char), rlen, f);
393 luaL_addsize(&b, nr);
394 if (nr < rlen) break; /* eof? */
395 else if (rlen <= (MAX_SIZE_T / 4)) /* avoid buffers too large */
396 rlen *= 2; /* double buffer size at each iteration */
398 luaL_pushresult(&b); /* close buffer */
402 static int read_chars (lua_State *L, FILE *f, size_t n) {
403 size_t nr; /* number of chars actually read */
404 char *p;
405 luaL_Buffer b;
406 luaL_buffinit(L, &b);
407 p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */
408 nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */
409 luaL_addsize(&b, nr);
410 luaL_pushresult(&b); /* close buffer */
411 return (nr > 0); /* true iff read something */
415 static int g_read (lua_State *L, FILE *f, int first) {
416 int nargs = lua_gettop(L) - 1;
417 int success;
418 int n;
419 clearerr(f);
420 if (nargs == 0) { /* no arguments? */
421 success = read_line(L, f, 1);
422 n = first+1; /* to return 1 result */
424 else { /* ensure stack space for all results and for auxlib's buffer */
425 luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
426 success = 1;
427 for (n = first; nargs-- && success; n++) {
428 if (lua_type(L, n) == LUA_TNUMBER) {
429 size_t l = (size_t)lua_tointeger(L, n);
430 success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
432 else {
433 const char *p = lua_tostring(L, n);
434 luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
435 switch (p[1]) {
436 case 'n': /* number */
437 success = read_number(L, f);
438 break;
439 case 'l': /* line */
440 success = read_line(L, f, 1);
441 break;
442 case 'L': /* line with end-of-line */
443 success = read_line(L, f, 0);
444 break;
445 case 'a': /* file */
446 read_all(L, f); /* read entire file */
447 success = 1; /* always success */
448 break;
449 default:
450 return luaL_argerror(L, n, "invalid format");
455 if (ferror(f))
456 return luaL_fileresult(L, 0, NULL);
457 if (!success) {
458 lua_pop(L, 1); /* remove last result */
459 lua_pushnil(L); /* push nil instead */
461 return n - first;
465 static int io_read (lua_State *L) {
466 return g_read(L, getiofile(L, IO_INPUT), 1);
470 static int f_read (lua_State *L) {
471 return g_read(L, tofile(L), 2);
475 static int io_readline (lua_State *L) {
476 LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
477 int i;
478 int n = (int)lua_tointeger(L, lua_upvalueindex(2));
479 if (isclosed(p)) /* file is already closed? */
480 return luaL_error(L, "file is already closed");
481 lua_settop(L , 1);
482 for (i = 1; i <= n; i++) /* push arguments to 'g_read' */
483 lua_pushvalue(L, lua_upvalueindex(3 + i));
484 n = g_read(L, p->f, 2); /* 'n' is number of results */
485 lua_assert(n > 0); /* should return at least a nil */
486 if (!lua_isnil(L, -n)) /* read at least one value? */
487 return n; /* return them */
488 else { /* first result is nil: EOF or error */
489 if (n > 1) { /* is there error information? */
490 /* 2nd result is error message */
491 return luaL_error(L, "%s", lua_tostring(L, -n + 1));
493 if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
494 lua_settop(L, 0);
495 lua_pushvalue(L, lua_upvalueindex(1));
496 aux_close(L); /* close it */
498 return 0;
502 /* }====================================================== */
505 static int g_write (lua_State *L, FILE *f, int arg) {
506 int nargs = lua_gettop(L) - arg;
507 int status = 1;
508 for (; nargs--; arg++) {
509 if (lua_type(L, arg) == LUA_TNUMBER) {
510 /* optimization: could be done exactly as for strings */
511 status = status &&
512 fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
514 else {
515 size_t l;
516 const char *s = luaL_checklstring(L, arg, &l);
517 status = status && (fwrite(s, sizeof(char), l, f) == l);
520 if (status) return 1; /* file handle already on stack top */
521 else return luaL_fileresult(L, status, NULL);
525 static int io_write (lua_State *L) {
526 return g_write(L, getiofile(L, IO_OUTPUT), 1);
530 static int f_write (lua_State *L) {
531 FILE *f = tofile(L);
532 lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
533 return g_write(L, f, 2);
537 static int f_seek (lua_State *L) {
538 static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
539 static const char *const modenames[] = {"set", "cur", "end", NULL};
540 FILE *f = tofile(L);
541 int op = luaL_checkoption(L, 2, "cur", modenames);
542 lua_Number p3 = luaL_optnumber(L, 3, 0);
543 l_seeknum offset = (l_seeknum)p3;
544 luaL_argcheck(L, (lua_Number)offset == p3, 3,
545 "not an integer in proper range");
546 op = l_fseek(f, offset, mode[op]);
547 if (op)
548 return luaL_fileresult(L, 0, NULL); /* error */
549 else {
550 lua_pushnumber(L, (lua_Number)l_ftell(f));
551 return 1;
556 static int f_setvbuf (lua_State *L) {
557 static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
558 static const char *const modenames[] = {"no", "full", "line", NULL};
559 FILE *f = tofile(L);
560 int op = luaL_checkoption(L, 2, NULL, modenames);
561 lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
562 int res = setvbuf(f, NULL, mode[op], sz);
563 return luaL_fileresult(L, res == 0, NULL);
568 static int io_flush (lua_State *L) {
569 return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
573 static int f_flush (lua_State *L) {
574 return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
579 ** functions for 'io' library
581 static const luaL_Reg iolib[] = {
582 {"close", io_close},
583 {"flush", io_flush},
584 {"input", io_input},
585 {"lines", io_lines},
586 {"open", io_open},
587 {"output", io_output},
588 {"popen", io_popen},
589 {"read", io_read},
590 {"tmpfile", io_tmpfile},
591 {"type", io_type},
592 {"write", io_write},
593 {NULL, NULL}
598 ** methods for file handles
600 static const luaL_Reg flib[] = {
601 {"close", io_close},
602 {"flush", f_flush},
603 {"lines", f_lines},
604 {"read", f_read},
605 {"seek", f_seek},
606 {"setvbuf", f_setvbuf},
607 {"write", f_write},
608 {"__gc", f_gc},
609 {"__tostring", f_tostring},
610 {NULL, NULL}
614 static void createmeta (lua_State *L) {
615 luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
616 lua_pushvalue(L, -1); /* push metatable */
617 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
618 luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */
619 lua_pop(L, 1); /* pop new metatable */
624 ** function to (not) close the standard files stdin, stdout, and stderr
626 static int io_noclose (lua_State *L) {
627 LStream *p = tolstream(L);
628 p->closef = &io_noclose; /* keep file opened */
629 lua_pushnil(L);
630 lua_pushliteral(L, "cannot close standard file");
631 return 2;
635 static void createstdfile (lua_State *L, FILE *f, const char *k,
636 const char *fname) {
637 LStream *p = newprefile(L);
638 p->f = f;
639 p->closef = &io_noclose;
640 if (k != NULL) {
641 lua_pushvalue(L, -1);
642 lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */
644 lua_setfield(L, -2, fname); /* add file to module */
648 LUAMOD_API int luaopen_io (lua_State *L) {
649 luaL_newlib(L, iolib); /* new module */
650 createmeta(L);
651 /* create (and set) default files */
652 createstdfile(L, stdin, IO_INPUT, "stdin");
653 createstdfile(L, stdout, IO_OUTPUT, "stdout");
654 createstdfile(L, stderr, NULL, "stderr");
655 return 1;