LCOV - code coverage report
Current view: top level - AP_Scripting/lua/src - liolib.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 94 323 29.1 %
Date: 2026-09-09 11:02:08 Functions: 15 45 33.3 %

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

Generated by: LCOV version 1.14