LCOV - code coverage report
Current view: top level - src - liolib.c Coverage Total Hit
Test: Lua 5.3.6 Lines: 97.9 % 335 328
Test Date: 2024-04-28 10:23:15
Legend: Lines: hit not hit

            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              : 
        

Generated by: LCOV version 2.0-1