LCOV - code coverage report
Current view: top level - external/lua/src - liolib.c (source / functions) Hit Total Coverage
Test: rapport Lines: 70 355 19.7 %
Date: 2021-12-10 16:22:55 Functions: 12 46 26.1 %
Branches: 12 165 7.3 %

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

Generated by: LCOV version 1.15