LCOV - code coverage report
Current view: top level - src - liolib.c Coverage Total Hit
Test: Lua 5.2.4 Lines: 96.2 % 291 280
Test Date: 2024-04-28 10:23:12
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              : ** $Id: liolib.c,v 2.112.1.1 2013/04/12 18:48:47 roberto Exp $
       3              : ** Standard I/O (and system) library
       4              : ** See Copyright Notice in lua.h
       5              : */
       6              : 
       7              : 
       8              : /*
       9              : ** This definition must come before the inclusion of 'stdio.h'; it
      10              : ** should not affect non-POSIX systems
      11              : */
      12              : #if !defined(_FILE_OFFSET_BITS)
      13              : #define _LARGEFILE_SOURCE       1
      14              : #define _FILE_OFFSET_BITS       64
      15              : #endif
      16              : 
      17              : 
      18              : #include <errno.h>
      19              : #include <stdio.h>
      20              : #include <stdlib.h>
      21              : #include <string.h>
      22              : 
      23              : #define liolib_c
      24              : #define LUA_LIB
      25              : 
      26              : #include "lua.h"
      27              : 
      28              : #include "lauxlib.h"
      29              : #include "lualib.h"
      30              : 
      31              : 
      32              : #if !defined(lua_checkmode)
      33              : 
      34              : /*
      35              : ** Check whether 'mode' matches '[rwa]%+?b?'.
      36              : ** Change this macro to accept other modes for 'fopen' besides
      37              : ** the standard ones.
      38              : */
      39              : #define lua_checkmode(mode) \
      40              :         (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \
      41              :         (*mode != '+' || ++mode) &&  /* skip if char is '+' */  \
      42              :         (*mode != 'b' || ++mode) &&  /* skip if char is 'b' */  \
      43              :         (*mode == '\0'))
      44              : 
      45              : #endif
      46              : 
      47              : /*
      48              : ** {======================================================
      49              : ** lua_popen spawns a new process connected to the current
      50              : ** one through the file streams.
      51              : ** =======================================================
      52              : */
      53              : 
      54              : #if !defined(lua_popen) /* { */
      55              : 
      56              : #if defined(LUA_USE_POPEN)      /* { */
      57              : 
      58              : #define lua_popen(L,c,m)        ((void)L, fflush(NULL), popen(c,m))
      59              : #define lua_pclose(L,file)      ((void)L, pclose(file))
      60              : 
      61              : #elif defined(LUA_WIN)          /* }{ */
      62              : 
      63              : #define lua_popen(L,c,m)                ((void)L, _popen(c,m))
      64              : #define lua_pclose(L,file)              ((void)L, _pclose(file))
      65              : 
      66              : 
      67              : #else                           /* }{ */
      68              : 
      69              : #define lua_popen(L,c,m)                ((void)((void)c, m),  \
      70              :                 luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
      71              : #define lua_pclose(L,file)              ((void)((void)L, file), -1)
      72              : 
      73              : 
      74              : #endif                          /* } */
      75              : 
      76              : #endif                  /* } */
      77              : 
      78              : /* }====================================================== */
      79              : 
      80              : 
      81              : /*
      82              : ** {======================================================
      83              : ** lua_fseek: configuration for longer offsets
      84              : ** =======================================================
      85              : */
      86              : 
      87              : #if !defined(lua_fseek) && !defined(LUA_ANSI)   /* { */
      88              : 
      89              : #if defined(LUA_USE_POSIX)      /* { */
      90              : 
      91              : #define l_fseek(f,o,w)          fseeko(f,o,w)
      92              : #define l_ftell(f)              ftello(f)
      93              : #define l_seeknum               off_t
      94              : 
      95              : #elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \
      96              :    && defined(_MSC_VER) && (_MSC_VER >= 1400)        /* }{ */
      97              : /* Windows (but not DDK) and Visual C++ 2005 or higher */
      98              : 
      99              : #define l_fseek(f,o,w)          _fseeki64(f,o,w)
     100              : #define l_ftell(f)              _ftelli64(f)
     101              : #define l_seeknum               __int64
     102              : 
     103              : #endif  /* } */
     104              : 
     105              : #endif                  /* } */
     106              : 
     107              : 
     108              : #if !defined(l_fseek)           /* default definitions */
     109              : #define l_fseek(f,o,w)          fseek(f,o,w)
     110              : #define l_ftell(f)              ftell(f)
     111              : #define l_seeknum               long
     112              : #endif
     113              : 
     114              : /* }====================================================== */
     115              : 
     116              : 
     117              : #define IO_PREFIX       "_IO_"
     118              : #define IO_INPUT        (IO_PREFIX "input")
     119              : #define IO_OUTPUT       (IO_PREFIX "output")
     120              : 
     121              : 
     122              : typedef luaL_Stream LStream;
     123              : 
     124              : 
     125              : #define tolstream(L)    ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
     126              : 
     127              : #define isclosed(p)     ((p)->closef == NULL)
     128              : 
     129              : 
     130            9 : static int io_type (lua_State *L) {
     131              :   LStream *p;
     132            9 :   luaL_checkany(L, 1);
     133            9 :   p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
     134            9 :   if (p == NULL)
     135            1 :     lua_pushnil(L);  /* not a file */
     136            8 :   else if (isclosed(p))
     137            2 :     lua_pushliteral(L, "closed file");
     138              :   else
     139            6 :     lua_pushliteral(L, "file");
     140            9 :   return 1;
     141              : }
     142              : 
     143              : 
     144           12 : static int f_tostring (lua_State *L) {
     145           12 :   LStream *p = tolstream(L);
     146           12 :   if (isclosed(p))
     147            2 :     lua_pushliteral(L, "file (closed)");
     148              :   else
     149           10 :     lua_pushfstring(L, "file (%p)", p->f);
     150           12 :   return 1;
     151              : }
     152              : 
     153              : 
     154          267 : static FILE *tofile (lua_State *L) {
     155          267 :   LStream *p = tolstream(L);
     156          267 :   if (isclosed(p))
     157            6 :     luaL_error(L, "attempt to use a closed file");
     158              :   lua_assert(p->f);
     159          261 :   return p->f;
     160              : }
     161              : 
     162              : 
     163              : /*
     164              : ** When creating file handles, always creates a `closed' file handle
     165              : ** before opening the actual file; so, if there is a memory error, the
     166              : ** file is not left opened.
     167              : */
     168          384 : static LStream *newprefile (lua_State *L) {
     169          384 :   LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
     170          384 :   p->closef = NULL;  /* mark file handle as 'closed' */
     171          384 :   luaL_setmetatable(L, LUA_FILEHANDLE);
     172          384 :   return p;
     173              : }
     174              : 
     175              : 
     176          356 : static int aux_close (lua_State *L) {
     177          356 :   LStream *p = tolstream(L);
     178          356 :   lua_CFunction cf = p->closef;
     179          356 :   p->closef = NULL;  /* mark stream as closed */
     180          356 :   return (*cf)(L);  /* close it */
     181              : }
     182              : 
     183              : 
     184          115 : static int io_close (lua_State *L) {
     185          115 :   if (lua_isnone(L, 1))  /* no argument? */
     186            3 :     lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT);  /* use standard output */
     187          115 :   tofile(L);  /* make sure argument is an open stream */
     188          113 :   return aux_close(L);
     189              : }
     190              : 
     191              : 
     192          357 : static int f_gc (lua_State *L) {
     193          357 :   LStream *p = tolstream(L);
     194          357 :   if (!isclosed(p) && p->f != NULL)
     195          242 :     aux_close(L);  /* ignore closed and incompletely open files */
     196          357 :   return 0;
     197              : }
     198              : 
     199              : 
     200              : /*
     201              : ** function to close regular files
     202              : */
     203           62 : static int io_fclose (lua_State *L) {
     204           62 :   LStream *p = tolstream(L);
     205           62 :   int res = fclose(p->f);
     206           62 :   return luaL_fileresult(L, (res == 0), NULL);
     207              : }
     208              : 
     209              : 
     210           66 : static LStream *newfile (lua_State *L) {
     211           66 :   LStream *p = newprefile(L);
     212           66 :   p->f = NULL;
     213           66 :   p->closef = &io_fclose;
     214           66 :   return p;
     215              : }
     216              : 
     217              : 
     218            5 : static void opencheck (lua_State *L, const char *fname, const char *mode) {
     219            5 :   LStream *p = newfile(L);
     220            5 :   p->f = fopen(fname, mode);
     221            5 :   if (p->f == NULL)
     222            2 :     luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno));
     223            3 : }
     224              : 
     225              : 
     226           58 : static int io_open (lua_State *L) {
     227           58 :   const char *filename = luaL_checkstring(L, 1);
     228           58 :   const char *mode = luaL_optstring(L, 2, "r");
     229           58 :   LStream *p = newfile(L);
     230           58 :   const char *md = mode;  /* to traverse/check mode */
     231           58 :   luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode");
     232           57 :   p->f = fopen(filename, mode);
     233           57 :   return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
     234              : }
     235              : 
     236              : 
     237              : /*
     238              : ** function to close 'popen' files
     239              : */
     240           60 : static int io_pclose (lua_State *L) {
     241           60 :   LStream *p = tolstream(L);
     242           60 :   return luaL_execresult(L, lua_pclose(L, p->f));
     243              : }
     244              : 
     245              : 
     246           60 : static int io_popen (lua_State *L) {
     247           60 :   const char *filename = luaL_checkstring(L, 1);
     248           60 :   const char *mode = luaL_optstring(L, 2, "r");
     249           60 :   LStream *p = newprefile(L);
     250           60 :   p->f = lua_popen(L, filename, mode);
     251           60 :   p->closef = &io_pclose;
     252           60 :   return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
     253              : }
     254              : 
     255              : 
     256            3 : static int io_tmpfile (lua_State *L) {
     257            3 :   LStream *p = newfile(L);
     258            3 :   p->f = tmpfile();
     259            3 :   return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
     260              : }
     261              : 
     262              : 
     263            8 : static FILE *getiofile (lua_State *L, const char *findex) {
     264              :   LStream *p;
     265            8 :   lua_getfield(L, LUA_REGISTRYINDEX, findex);
     266            8 :   p = (LStream *)lua_touserdata(L, -1);
     267            8 :   if (isclosed(p))
     268            0 :     luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX));
     269            8 :   return p->f;
     270              : }
     271              : 
     272              : 
     273           11 : static int g_iofile (lua_State *L, const char *f, const char *mode) {
     274           11 :   if (!lua_isnoneornil(L, 1)) {
     275            7 :     const char *filename = lua_tostring(L, 1);
     276            7 :     if (filename)
     277            3 :       opencheck(L, filename, mode);
     278              :     else {
     279            4 :       tofile(L);  /* check that it's a valid file handle */
     280            4 :       lua_pushvalue(L, 1);
     281              :     }
     282            6 :     lua_setfield(L, LUA_REGISTRYINDEX, f);
     283              :   }
     284              :   /* return current value */
     285           10 :   lua_getfield(L, LUA_REGISTRYINDEX, f);
     286           10 :   return 1;
     287              : }
     288              : 
     289              : 
     290            6 : static int io_input (lua_State *L) {
     291            6 :   return g_iofile(L, IO_INPUT, "r");
     292              : }
     293              : 
     294              : 
     295            5 : static int io_output (lua_State *L) {
     296            5 :   return g_iofile(L, IO_OUTPUT, "w");
     297              : }
     298              : 
     299              : 
     300              : static int io_readline (lua_State *L);
     301              : 
     302              : 
     303            8 : static void aux_lines (lua_State *L, int toclose) {
     304              :   int i;
     305            8 :   int n = lua_gettop(L) - 1;  /* number of arguments to read */
     306              :   /* ensure that arguments will fit here and into 'io_readline' stack */
     307            8 :   luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options");
     308            8 :   lua_pushvalue(L, 1);  /* file handle */
     309            8 :   lua_pushinteger(L, n);  /* number of arguments to read */
     310            8 :   lua_pushboolean(L, toclose);  /* close/not close file when finished */
     311            9 :   for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1);  /* copy arguments */
     312            8 :   lua_pushcclosure(L, io_readline, 3 + n);
     313            8 : }
     314              : 
     315              : 
     316            5 : static int f_lines (lua_State *L) {
     317            5 :   tofile(L);  /* check that it's a valid file handle */
     318            5 :   aux_lines(L, 0);
     319            5 :   return 1;
     320              : }
     321              : 
     322              : 
     323            4 : static int io_lines (lua_State *L) {
     324              :   int toclose;
     325            4 :   if (lua_isnone(L, 1)) lua_pushnil(L);  /* at least one argument */
     326            4 :   if (lua_isnil(L, 1)) {  /* no file name? */
     327            2 :     lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT);  /* get default input */
     328            2 :     lua_replace(L, 1);  /* put it at index 1 */
     329            2 :     tofile(L);  /* check that it's a valid file handle */
     330            2 :     toclose = 0;  /* do not close it after iteration */
     331              :   }
     332              :   else {  /* open a new file */
     333            2 :     const char *filename = luaL_checkstring(L, 1);
     334            2 :     opencheck(L, filename, "r");
     335            1 :     lua_replace(L, 1);  /* put file at index 1 */
     336            1 :     toclose = 1;  /* close it after iteration */
     337              :   }
     338            3 :   aux_lines(L, toclose);
     339            3 :   return 1;
     340              : }
     341              : 
     342              : 
     343              : /*
     344              : ** {======================================================
     345              : ** READ
     346              : ** =======================================================
     347              : */
     348              : 
     349              : 
     350           14 : static int read_number (lua_State *L, FILE *f) {
     351              :   lua_Number d;
     352           14 :   if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
     353           12 :     lua_pushnumber(L, d);
     354           12 :     return 1;
     355              :   }
     356              :   else {
     357            2 :    lua_pushnil(L);  /* "result" to be removed */
     358            2 :    return 0;  /* read fails */
     359              :   }
     360              : }
     361              : 
     362              : 
     363            1 : static int test_eof (lua_State *L, FILE *f) {
     364            1 :   int c = getc(f);
     365            1 :   ungetc(c, f);
     366            1 :   lua_pushlstring(L, NULL, 0);
     367            1 :   return (c != EOF);
     368              : }
     369              : 
     370              : 
     371          261 : static int read_line (lua_State *L, FILE *f, int chop) {
     372              :   luaL_Buffer b;
     373          261 :   luaL_buffinit(L, &b);
     374            0 :   for (;;) {
     375              :     size_t l;
     376          261 :     char *p = luaL_prepbuffer(&b);
     377          261 :     if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {  /* eof? */
     378           17 :       luaL_pushresult(&b);  /* close buffer */
     379           17 :       return (lua_rawlen(L, -1) > 0);  /* check whether read something */
     380              :     }
     381          244 :     l = strlen(p);
     382          244 :     if (l == 0 || p[l-1] != '\n')
     383            0 :       luaL_addsize(&b, l);
     384              :     else {
     385          244 :       luaL_addsize(&b, l - chop);  /* chop 'eol' if needed */
     386          244 :       luaL_pushresult(&b);  /* close buffer */
     387          244 :       return 1;  /* read at least an `eol' */
     388              :     }
     389              :   }
     390              : }
     391              : 
     392              : 
     393              : #define MAX_SIZE_T      (~(size_t)0)
     394              : 
     395            1 : static void read_all (lua_State *L, FILE *f) {
     396            1 :   size_t rlen = LUAL_BUFFERSIZE;  /* how much to read in each cycle */
     397              :   luaL_Buffer b;
     398            1 :   luaL_buffinit(L, &b);
     399            0 :   for (;;) {
     400            1 :     char *p = luaL_prepbuffsize(&b, rlen);
     401            1 :     size_t nr = fread(p, sizeof(char), rlen, f);
     402            1 :     luaL_addsize(&b, nr);
     403            1 :     if (nr < rlen) break;  /* eof? */
     404            0 :     else if (rlen <= (MAX_SIZE_T / 4))  /* avoid buffers too large */
     405            0 :       rlen *= 2;  /* double buffer size at each iteration */
     406              :   }
     407            1 :   luaL_pushresult(&b);  /* close buffer */
     408            1 : }
     409              : 
     410              : 
     411            4 : static int read_chars (lua_State *L, FILE *f, size_t n) {
     412              :   size_t nr;  /* number of chars actually read */
     413              :   char *p;
     414              :   luaL_Buffer b;
     415            4 :   luaL_buffinit(L, &b);
     416            4 :   p = luaL_prepbuffsize(&b, n);  /* prepare buffer to read whole block */
     417            4 :   nr = fread(p, sizeof(char), n, f);  /* try to read 'n' chars */
     418            4 :   luaL_addsize(&b, nr);
     419            4 :   luaL_pushresult(&b);  /* close buffer */
     420            4 :   return (nr > 0);  /* true iff read something */
     421              : }
     422              : 
     423              : 
     424          273 : static int g_read (lua_State *L, FILE *f, int first) {
     425          273 :   int nargs = lua_gettop(L) - 1;
     426              :   int success;
     427              :   int n;
     428          273 :   clearerr(f);
     429          273 :   if (nargs == 0) {  /* no arguments? */
     430          176 :     success = read_line(L, f, 1);
     431          176 :     n = first+1;  /* to return 1 result */
     432              :   }
     433              :   else {  /* ensure stack space for all results and for auxlib's buffer */
     434           97 :     luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
     435           97 :     success = 1;
     436          202 :     for (n = first; nargs-- && success; n++) {
     437          106 :       if (lua_type(L, n) == LUA_TNUMBER) {
     438            5 :         size_t l = (size_t)lua_tointeger(L, n);
     439            5 :         success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
     440              :       }
     441              :       else {
     442          101 :         const char *p = lua_tostring(L, n);
     443          101 :         luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
     444          101 :         switch (p[1]) {
     445           14 :           case 'n':  /* number */
     446           14 :             success = read_number(L, f);
     447           14 :             break;
     448           83 :           case 'l':  /* line */
     449           83 :             success = read_line(L, f, 1);
     450           83 :             break;
     451            2 :           case 'L':  /* line with end-of-line */
     452            2 :             success = read_line(L, f, 0);
     453            2 :             break;
     454            1 :           case 'a':  /* file */
     455            1 :             read_all(L, f);  /* read entire file */
     456            1 :             success = 1; /* always success */
     457            1 :             break;
     458            1 :           default:
     459            1 :             return luaL_argerror(L, n, "invalid format");
     460              :         }
     461              :       }
     462              :     }
     463              :   }
     464          272 :   if (ferror(f))
     465            0 :     return luaL_fileresult(L, 0, NULL);
     466          272 :   if (!success) {
     467           19 :     lua_pop(L, 1);  /* remove last result */
     468           19 :     lua_pushnil(L);  /* push nil instead */
     469              :   }
     470          272 :   return n - first;
     471              : }
     472              : 
     473              : 
     474            5 : static int io_read (lua_State *L) {
     475            5 :   return g_read(L, getiofile(L, IO_INPUT), 1);
     476              : }
     477              : 
     478              : 
     479           95 : static int f_read (lua_State *L) {
     480           95 :   return g_read(L, tofile(L), 2);
     481              : }
     482              : 
     483              : 
     484          174 : static int io_readline (lua_State *L) {
     485          174 :   LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
     486              :   int i;
     487          174 :   int n = (int)lua_tointeger(L, lua_upvalueindex(2));
     488          174 :   if (isclosed(p))  /* file is already closed? */
     489            0 :     return luaL_error(L, "file is already closed");
     490          174 :   lua_settop(L , 1);
     491          175 :   for (i = 1; i <= n; i++)  /* push arguments to 'g_read' */
     492            1 :     lua_pushvalue(L, lua_upvalueindex(3 + i));
     493          174 :   n = g_read(L, p->f, 2);  /* 'n' is number of results */
     494              :   lua_assert(n > 0);  /* should return at least a nil */
     495          174 :   if (!lua_isnil(L, -n))  /* read at least one value? */
     496          170 :     return n;  /* return them */
     497              :   else {  /* first result is nil: EOF or error */
     498            4 :     if (n > 1) {  /* is there error information? */
     499              :       /* 2nd result is error message */
     500            0 :       return luaL_error(L, "%s", lua_tostring(L, -n + 1));
     501              :     }
     502            4 :     if (lua_toboolean(L, lua_upvalueindex(3))) {  /* generator created file? */
     503            1 :       lua_settop(L, 0);
     504            1 :       lua_pushvalue(L, lua_upvalueindex(1));
     505            1 :       aux_close(L);  /* close it */
     506              :     }
     507            4 :     return 0;
     508              :   }
     509              : }
     510              : 
     511              : /* }====================================================== */
     512              : 
     513              : 
     514           39 : static int g_write (lua_State *L, FILE *f, int arg) {
     515           39 :   int nargs = lua_gettop(L) - arg;
     516           39 :   int status = 1;
     517           79 :   for (; nargs--; arg++) {
     518           40 :     if (lua_type(L, arg) == LUA_TNUMBER) {
     519              :       /* optimization: could be done exactly as for strings */
     520            2 :       status = status &&
     521            1 :           fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
     522              :     }
     523              :     else {
     524              :       size_t l;
     525           39 :       const char *s = luaL_checklstring(L, arg, &l);
     526           39 :       status = status && (fwrite(s, sizeof(char), l, f) == l);
     527              :     }
     528              :   }
     529           39 :   if (status) return 1;  /* file handle already on stack top */
     530            0 :   else return luaL_fileresult(L, status, NULL);
     531              : }
     532              : 
     533              : 
     534            2 : static int io_write (lua_State *L) {
     535            2 :   return g_write(L, getiofile(L, IO_OUTPUT), 1);
     536              : }
     537              : 
     538              : 
     539           38 : static int f_write (lua_State *L) {
     540           38 :   FILE *f = tofile(L);
     541           37 :   lua_pushvalue(L, 1);  /* push file at the stack top (to be returned) */
     542           37 :   return g_write(L, f, 2);
     543              : }
     544              : 
     545              : 
     546            3 : static int f_seek (lua_State *L) {
     547              :   static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
     548              :   static const char *const modenames[] = {"set", "cur", "end", NULL};
     549            3 :   FILE *f = tofile(L);
     550            2 :   int op = luaL_checkoption(L, 2, "cur", modenames);
     551            1 :   lua_Number p3 = luaL_optnumber(L, 3, 0);
     552            1 :   l_seeknum offset = (l_seeknum)p3;
     553            1 :   luaL_argcheck(L, (lua_Number)offset == p3, 3,
     554              :                   "not an integer in proper range");
     555            1 :   op = l_fseek(f, offset, mode[op]);
     556            1 :   if (op)
     557            0 :     return luaL_fileresult(L, 0, NULL);  /* error */
     558              :   else {
     559            1 :     lua_pushnumber(L, (lua_Number)l_ftell(f));
     560            1 :     return 1;
     561              :   }
     562              : }
     563              : 
     564              : 
     565            3 : static int f_setvbuf (lua_State *L) {
     566              :   static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
     567              :   static const char *const modenames[] = {"no", "full", "line", NULL};
     568            3 :   FILE *f = tofile(L);
     569            3 :   int op = luaL_checkoption(L, 2, NULL, modenames);
     570            3 :   lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
     571            3 :   int res = setvbuf(f, NULL, mode[op], sz);
     572            3 :   return luaL_fileresult(L, res == 0, NULL);
     573              : }
     574              : 
     575              : 
     576              : 
     577            1 : static int io_flush (lua_State *L) {
     578            1 :   return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
     579              : }
     580              : 
     581              : 
     582            2 : static int f_flush (lua_State *L) {
     583            2 :   return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
     584              : }
     585              : 
     586              : 
     587              : /*
     588              : ** functions for 'io' library
     589              : */
     590              : static const luaL_Reg iolib[] = {
     591              :   {"close", io_close},
     592              :   {"flush", io_flush},
     593              :   {"input", io_input},
     594              :   {"lines", io_lines},
     595              :   {"open", io_open},
     596              :   {"output", io_output},
     597              :   {"popen", io_popen},
     598              :   {"read", io_read},
     599              :   {"tmpfile", io_tmpfile},
     600              :   {"type", io_type},
     601              :   {"write", io_write},
     602              :   {NULL, NULL}
     603              : };
     604              : 
     605              : 
     606              : /*
     607              : ** methods for file handles
     608              : */
     609              : static const luaL_Reg flib[] = {
     610              :   {"close", io_close},
     611              :   {"flush", f_flush},
     612              :   {"lines", f_lines},
     613              :   {"read", f_read},
     614              :   {"seek", f_seek},
     615              :   {"setvbuf", f_setvbuf},
     616              :   {"write", f_write},
     617              :   {"__gc", f_gc},
     618              :   {"__tostring", f_tostring},
     619              :   {NULL, NULL}
     620              : };
     621              : 
     622              : 
     623           86 : static void createmeta (lua_State *L) {
     624           86 :   luaL_newmetatable(L, LUA_FILEHANDLE);  /* create metatable for file handles */
     625           86 :   lua_pushvalue(L, -1);  /* push metatable */
     626           86 :   lua_setfield(L, -2, "__index");  /* metatable.__index = metatable */
     627           86 :   luaL_setfuncs(L, flib, 0);  /* add file methods to new metatable */
     628           86 :   lua_pop(L, 1);  /* pop new metatable */
     629           86 : }
     630              : 
     631              : 
     632              : /*
     633              : ** function to (not) close the standard files stdin, stdout, and stderr
     634              : */
     635          234 : static int io_noclose (lua_State *L) {
     636          234 :   LStream *p = tolstream(L);
     637          234 :   p->closef = &io_noclose;  /* keep file opened */
     638          234 :   lua_pushnil(L);
     639          234 :   lua_pushliteral(L, "cannot close standard file");
     640          234 :   return 2;
     641              : }
     642              : 
     643              : 
     644          258 : static void createstdfile (lua_State *L, FILE *f, const char *k,
     645              :                            const char *fname) {
     646          258 :   LStream *p = newprefile(L);
     647          258 :   p->f = f;
     648          258 :   p->closef = &io_noclose;
     649          258 :   if (k != NULL) {
     650          172 :     lua_pushvalue(L, -1);
     651          172 :     lua_setfield(L, LUA_REGISTRYINDEX, k);  /* add file to registry */
     652              :   }
     653          258 :   lua_setfield(L, -2, fname);  /* add file to module */
     654          258 : }
     655              : 
     656              : 
     657           86 : LUAMOD_API int luaopen_io (lua_State *L) {
     658           86 :   luaL_newlib(L, iolib);  /* new module */
     659           86 :   createmeta(L);
     660              :   /* create (and set) default files */
     661           86 :   createstdfile(L, stdin, IO_INPUT, "stdin");
     662           86 :   createstdfile(L, stdout, IO_OUTPUT, "stdout");
     663           86 :   createstdfile(L, stderr, NULL, "stderr");
     664           86 :   return 1;
     665              : }
     666              : 
        

Generated by: LCOV version 2.0-1