lua/liolib.c

Go to the documentation of this file.
00001 /*
00002 ** $Id: liolib.c,v 2.108 2011/11/25 12:50:03 roberto Exp $
00003 ** Standard I/O (and system) library
00004 ** See Copyright Notice in lua.h
00005 */
00006 
00007 
00008 /*
00009 ** POSIX idiosyncrasy!
00010 ** This definition must come before the inclusion of 'stdio.h'; it
00011 ** should not affect non-POSIX systems
00012 */
00013 #if !defined(_FILE_OFFSET_BITS)
00014 #define _FILE_OFFSET_BITS 64
00015 #endif
00016 
00017 
00018 #include <errno.h>
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022 
00023 #define liolib_c
00024 #define LUA_LIB
00025 
00026 #include "lua.h"
00027 
00028 #include "lauxlib.h"
00029 #include "lualib.h"
00030 
00031 
00032 
00033 /*
00034 ** {======================================================
00035 ** lua_popen spawns a new process connected to the current
00036 ** one through the file streams.
00037 ** =======================================================
00038 */
00039 
00040 #if !defined(lua_popen) /* { */
00041 
00042 #if defined(LUA_USE_POPEN)  /* { */
00043 
00044 #define lua_popen(L,c,m)    ((void)L, fflush(NULL), popen(c,m))
00045 #define lua_pclose(L,file)  ((void)L, pclose(file))
00046 
00047 #elif defined(LUA_WIN)      /* }{ */
00048 
00049 #define lua_popen(L,c,m)        ((void)L, _popen(c,m))
00050 #define lua_pclose(L,file)      ((void)L, _pclose(file))
00051 
00052 
00053 #else               /* }{ */
00054 
00055 #define lua_popen(L,c,m)        ((void)((void)c, m),  \
00056         luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
00057 #define lua_pclose(L,file)      ((void)((void)L, file), -1)
00058 
00059 
00060 #endif              /* } */
00061 
00062 #endif          /* } */
00063 
00064 /* }====================================================== */
00065 
00066 
00067 /*
00068 ** {======================================================
00069 ** lua_fseek/lua_ftell: configuration for longer offsets
00070 ** =======================================================
00071 */
00072 
00073 #if !defined(lua_fseek) /* { */
00074 
00075 #if defined(LUA_USE_POSIX)
00076 
00077 #define l_fseek(f,o,w)      fseeko(f,o,w)
00078 #define l_ftell(f)      ftello(f)
00079 #define l_seeknum       off_t
00080 
00081 #elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \
00082    && defined(_MSC_VER) && (_MSC_VER >= 1400)
00083 /* Windows (but not DDK) and Visual C++ 2005 or higher */
00084 
00085 #define l_fseek(f,o,w)      _fseeki64(f,o,w)
00086 #define l_ftell(f)      _ftelli64(f)
00087 #define l_seeknum       __int64
00088 
00089 #else
00090 
00091 #define l_fseek(f,o,w)      fseek(f,o,w)
00092 #define l_ftell(f)      ftell(f)
00093 #define l_seeknum       long
00094 
00095 #endif
00096 
00097 #endif          /* } */
00098 
00099 /* }====================================================== */
00100 
00101 
00102 #define IO_PREFIX   "_IO_"
00103 #define IO_INPUT    (IO_PREFIX "input")
00104 #define IO_OUTPUT   (IO_PREFIX "output")
00105 
00106 
00107 typedef luaL_Stream LStream;
00108 
00109 
00110 #define tolstream(L)    ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
00111 
00112 #define isclosed(p) ((p)->closef == NULL)
00113 
00114 
00115 static int io_type (lua_State *L) {
00116   LStream *p;
00117   luaL_checkany(L, 1);
00118   p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
00119   if (p == NULL)
00120     lua_pushnil(L);  /* not a file */
00121   else if (isclosed(p))
00122     lua_pushliteral(L, "closed file");
00123   else
00124     lua_pushliteral(L, "file");
00125   return 1;
00126 }
00127 
00128 
00129 static int f_tostring (lua_State *L) {
00130   LStream *p = tolstream(L);
00131   if (isclosed(p))
00132     lua_pushliteral(L, "file (closed)");
00133   else
00134     lua_pushfstring(L, "file (%p)", p->f);
00135   return 1;
00136 }
00137 
00138 
00139 static FILE *tofile (lua_State *L) {
00140   LStream *p = tolstream(L);
00141   if (isclosed(p))
00142     luaL_error(L, "attempt to use a closed file");
00143   lua_assert(p->f);
00144   return p->f;
00145 }
00146 
00147 
00148 /*
00149 ** When creating file handles, always creates a `closed' file handle
00150 ** before opening the actual file; so, if there is a memory error, the
00151 ** file is not left opened.
00152 */
00153 static LStream *newprefile (lua_State *L) {
00154   LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
00155   p->closef = NULL;  /* mark file handle as 'closed' */
00156   luaL_setmetatable(L, LUA_FILEHANDLE);
00157   return p;
00158 }
00159 
00160 
00161 static int aux_close (lua_State *L) {
00162   LStream *p = tolstream(L);
00163   lua_CFunction cf = p->closef;
00164   p->closef = NULL;  /* mark stream as closed */
00165   return (*cf)(L);  /* close it */
00166 }
00167 
00168 
00169 static int io_close (lua_State *L) {
00170   if (lua_isnone(L, 1))  /* no argument? */
00171     lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT);  /* use standard output */
00172   tofile(L);  /* make sure argument is an open stream */
00173   return aux_close(L);
00174 }
00175 
00176 
00177 static int f_gc (lua_State *L) {
00178   LStream *p = tolstream(L);
00179   if (!isclosed(p) && p->f != NULL)
00180     aux_close(L);  /* ignore closed and incompletely open files */
00181   return 0;
00182 }
00183 
00184 
00185 /*
00186 ** function to close regular files
00187 */
00188 static int io_fclose (lua_State *L) {
00189   LStream *p = tolstream(L);
00190   int res = fclose(p->f);
00191   return luaL_fileresult(L, (res == 0), NULL);
00192 }
00193 
00194 
00195 static LStream *newfile (lua_State *L) {
00196   LStream *p = newprefile(L);
00197   p->f = NULL;
00198   p->closef = &io_fclose;
00199   return p;
00200 }
00201 
00202 
00203 static void opencheck (lua_State *L, const char *fname, const char *mode) {
00204   LStream *p = newfile(L);
00205   p->f = fopen(fname, mode);
00206   if (p->f == NULL)
00207     luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno));
00208 }
00209 
00210 
00211 static int io_open (lua_State *L) {
00212   const char *filename = luaL_checkstring(L, 1);
00213   const char *mode = luaL_optstring(L, 2, "r");
00214   LStream *p = newfile(L);
00215   int i = 0;
00216   /* check whether 'mode' matches '[rwa]%+?b?' */
00217   if (!(mode[i] != '\0' && strchr("rwa", mode[i++]) != NULL &&
00218        (mode[i] != '+' || ++i) &&  /* skip if char is '+' */
00219        (mode[i] != 'b' || ++i) &&  /* skip if char is 'b' */
00220        (mode[i] == '\0')))
00221     return luaL_error(L, "invalid mode " LUA_QS
00222                          " (should match " LUA_QL("[rwa]%%+?b?") ")", mode);
00223   p->f = fopen(filename, mode);
00224   return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
00225 }
00226 
00227 
00228 /*
00229 ** function to close 'popen' files
00230 */
00231 static int io_pclose (lua_State *L) {
00232   LStream *p = tolstream(L);
00233   return luaL_execresult(L, lua_pclose(L, p->f));
00234 }
00235 
00236 
00237 static int io_popen (lua_State *L) {
00238   const char *filename = luaL_checkstring(L, 1);
00239   const char *mode = luaL_optstring(L, 2, "r");
00240   LStream *p = newprefile(L);
00241   p->f = lua_popen(L, filename, mode);
00242   p->closef = &io_pclose;
00243   return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
00244 }
00245 
00246 
00247 static int io_tmpfile (lua_State *L) {
00248   LStream *p = newfile(L);
00249   p->f = tmpfile();
00250   return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
00251 }
00252 
00253 
00254 static FILE *getiofile (lua_State *L, const char *findex) {
00255   LStream *p;
00256   lua_getfield(L, LUA_REGISTRYINDEX, findex);
00257   p = (LStream *)lua_touserdata(L, -1);
00258   if (isclosed(p))
00259     luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX));
00260   return p->f;
00261 }
00262 
00263 
00264 static int g_iofile (lua_State *L, const char *f, const char *mode) {
00265   if (!lua_isnoneornil(L, 1)) {
00266     const char *filename = lua_tostring(L, 1);
00267     if (filename)
00268       opencheck(L, filename, mode);
00269     else {
00270       tofile(L);  /* check that it's a valid file handle */
00271       lua_pushvalue(L, 1);
00272     }
00273     lua_setfield(L, LUA_REGISTRYINDEX, f);
00274   }
00275   /* return current value */
00276   lua_getfield(L, LUA_REGISTRYINDEX, f);
00277   return 1;
00278 }
00279 
00280 
00281 static int io_input (lua_State *L) {
00282   return g_iofile(L, IO_INPUT, "r");
00283 }
00284 
00285 
00286 static int io_output (lua_State *L) {
00287   return g_iofile(L, IO_OUTPUT, "w");
00288 }
00289 
00290 
00291 static int io_readline (lua_State *L);
00292 
00293 
00294 static void aux_lines (lua_State *L, int toclose) {
00295   int i;
00296   int n = lua_gettop(L) - 1;  /* number of arguments to read */
00297   /* ensure that arguments will fit here and into 'io_readline' stack */
00298   luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options");
00299   lua_pushvalue(L, 1);  /* file handle */
00300   lua_pushinteger(L, n);  /* number of arguments to read */
00301   lua_pushboolean(L, toclose);  /* close/not close file when finished */
00302   for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1);  /* copy arguments */
00303   lua_pushcclosure(L, io_readline, 3 + n);
00304 }
00305 
00306 
00307 static int f_lines (lua_State *L) {
00308   tofile(L);  /* check that it's a valid file handle */
00309   aux_lines(L, 0);
00310   return 1;
00311 }
00312 
00313 
00314 static int io_lines (lua_State *L) {
00315   int toclose;
00316   if (lua_isnone(L, 1)) lua_pushnil(L);  /* at least one argument */
00317   if (lua_isnil(L, 1)) {  /* no file name? */
00318     lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT);  /* get default input */
00319     lua_replace(L, 1);  /* put it at index 1 */
00320     tofile(L);  /* check that it's a valid file handle */
00321     toclose = 0;  /* do not close it after iteration */
00322   }
00323   else {  /* open a new file */
00324     const char *filename = luaL_checkstring(L, 1);
00325     opencheck(L, filename, "r");
00326     lua_replace(L, 1);  /* put file at index 1 */
00327     toclose = 1;  /* close it after iteration */
00328   }
00329   aux_lines(L, toclose);
00330   return 1;
00331 }
00332 
00333 
00334 /*
00335 ** {======================================================
00336 ** READ
00337 ** =======================================================
00338 */
00339 
00340 
00341 static int read_number (lua_State *L, FILE *f) {
00342   lua_Number d;
00343   if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
00344     lua_pushnumber(L, d);
00345     return 1;
00346   }
00347   else {
00348    lua_pushnil(L);  /* "result" to be removed */
00349    return 0;  /* read fails */
00350   }
00351 }
00352 
00353 
00354 static int test_eof (lua_State *L, FILE *f) {
00355   int c = getc(f);
00356   ungetc(c, f);
00357   lua_pushlstring(L, NULL, 0);
00358   return (c != EOF);
00359 }
00360 
00361 
00362 static int read_line (lua_State *L, FILE *f, int chop) {
00363   luaL_Buffer b;
00364   luaL_buffinit(L, &b);
00365   for (;;) {
00366     size_t l;
00367     char *p = luaL_prepbuffer(&b);
00368     if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {  /* eof? */
00369       luaL_pushresult(&b);  /* close buffer */
00370       return (lua_rawlen(L, -1) > 0);  /* check whether read something */
00371     }
00372     l = strlen(p);
00373     if (l == 0 || p[l-1] != '\n')
00374       luaL_addsize(&b, l);
00375     else {
00376       luaL_addsize(&b, l - chop);  /* chop 'eol' if needed */
00377       luaL_pushresult(&b);  /* close buffer */
00378       return 1;  /* read at least an `eol' */
00379     }
00380   }
00381 }
00382 
00383 
00384 #define MAX_SIZE_T  (~(size_t)0)
00385 
00386 static void read_all (lua_State *L, FILE *f) {
00387   size_t rlen = LUAL_BUFFERSIZE;  /* how much to read in each cycle */
00388   luaL_Buffer b;
00389   luaL_buffinit(L, &b);
00390   for (;;) {
00391     char *p = luaL_prepbuffsize(&b, rlen);
00392     size_t nr = fread(p, sizeof(char), rlen, f);
00393     luaL_addsize(&b, nr);
00394     if (nr < rlen) break;  /* eof? */
00395     else if (rlen <= (MAX_SIZE_T / 4))  /* avoid buffers too large */
00396       rlen *= 2;  /* double buffer size at each iteration */
00397   }
00398   luaL_pushresult(&b);  /* close buffer */
00399 }
00400 
00401 
00402 static int read_chars (lua_State *L, FILE *f, size_t n) {
00403   size_t nr;  /* number of chars actually read */
00404   char *p;
00405   luaL_Buffer b;
00406   luaL_buffinit(L, &b);
00407   p = luaL_prepbuffsize(&b, n);  /* prepare buffer to read whole block */
00408   nr = fread(p, sizeof(char), n, f);  /* try to read 'n' chars */
00409   luaL_addsize(&b, nr);
00410   luaL_pushresult(&b);  /* close buffer */
00411   return (nr > 0);  /* true iff read something */
00412 }
00413 
00414 
00415 static int g_read (lua_State *L, FILE *f, int first) {
00416   int nargs = lua_gettop(L) - 1;
00417   int success;
00418   int n;
00419   clearerr(f);
00420   if (nargs == 0) {  /* no arguments? */
00421     success = read_line(L, f, 1);
00422     n = first+1;  /* to return 1 result */
00423   }
00424   else {  /* ensure stack space for all results and for auxlib's buffer */
00425     luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
00426     success = 1;
00427     for (n = first; nargs-- && success; n++) {
00428       if (lua_type(L, n) == LUA_TNUMBER) {
00429         size_t l = (size_t)lua_tointeger(L, n);
00430         success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
00431       }
00432       else {
00433         const char *p = lua_tostring(L, n);
00434         luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
00435         switch (p[1]) {
00436           case 'n':  /* number */
00437             success = read_number(L, f);
00438             break;
00439           case 'l':  /* line */
00440             success = read_line(L, f, 1);
00441             break;
00442           case 'L':  /* line with end-of-line */
00443             success = read_line(L, f, 0);
00444             break;
00445           case 'a':  /* file */
00446             read_all(L, f);  /* read entire file */
00447             success = 1; /* always success */
00448             break;
00449           default:
00450             return luaL_argerror(L, n, "invalid format");
00451         }
00452       }
00453     }
00454   }
00455   if (ferror(f))
00456     return luaL_fileresult(L, 0, NULL);
00457   if (!success) {
00458     lua_pop(L, 1);  /* remove last result */
00459     lua_pushnil(L);  /* push nil instead */
00460   }
00461   return n - first;
00462 }
00463 
00464 
00465 static int io_read (lua_State *L) {
00466   return g_read(L, getiofile(L, IO_INPUT), 1);
00467 }
00468 
00469 
00470 static int f_read (lua_State *L) {
00471   return g_read(L, tofile(L), 2);
00472 }
00473 
00474 
00475 static int io_readline (lua_State *L) {
00476   LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
00477   int i;
00478   int n = (int)lua_tointeger(L, lua_upvalueindex(2));
00479   if (isclosed(p))  /* file is already closed? */
00480     return luaL_error(L, "file is already closed");
00481   lua_settop(L , 1);
00482   for (i = 1; i <= n; i++)  /* push arguments to 'g_read' */
00483     lua_pushvalue(L, lua_upvalueindex(3 + i));
00484   n = g_read(L, p->f, 2);  /* 'n' is number of results */
00485   lua_assert(n > 0);  /* should return at least a nil */
00486   if (!lua_isnil(L, -n))  /* read at least one value? */
00487     return n;  /* return them */
00488   else {  /* first result is nil: EOF or error */
00489     if (n > 1) {  /* is there error information? */
00490       /* 2nd result is error message */
00491       return luaL_error(L, "%s", lua_tostring(L, -n + 1));
00492     }
00493     if (lua_toboolean(L, lua_upvalueindex(3))) {  /* generator created file? */
00494       lua_settop(L, 0);
00495       lua_pushvalue(L, lua_upvalueindex(1));
00496       aux_close(L);  /* close it */
00497     }
00498     return 0;
00499   }
00500 }
00501 
00502 /* }====================================================== */
00503 
00504 
00505 static int g_write (lua_State *L, FILE *f, int arg) {
00506   int nargs = lua_gettop(L) - arg;
00507   int status = 1;
00508   for (; nargs--; arg++) {
00509     if (lua_type(L, arg) == LUA_TNUMBER) {
00510       /* optimization: could be done exactly as for strings */
00511       status = status &&
00512           fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
00513     }
00514     else {
00515       size_t l;
00516       const char *s = luaL_checklstring(L, arg, &l);
00517       status = status && (fwrite(s, sizeof(char), l, f) == l);
00518     }
00519   }
00520   if (status) return 1;  /* file handle already on stack top */
00521   else return luaL_fileresult(L, status, NULL);
00522 }
00523 
00524 
00525 static int io_write (lua_State *L) {
00526   return g_write(L, getiofile(L, IO_OUTPUT), 1);
00527 }
00528 
00529 
00530 static int f_write (lua_State *L) {
00531   FILE *f = tofile(L);
00532   lua_pushvalue(L, 1);  /* push file at the stack top (to be returned) */
00533   return g_write(L, f, 2);
00534 }
00535 
00536 
00537 static int f_seek (lua_State *L) {
00538   static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
00539   static const char *const modenames[] = {"set", "cur", "end", NULL};
00540   FILE *f = tofile(L);
00541   int op = luaL_checkoption(L, 2, "cur", modenames);
00542   lua_Number p3 = luaL_optnumber(L, 3, 0);
00543   l_seeknum offset = (l_seeknum)p3;
00544   luaL_argcheck(L, (lua_Number)offset == p3, 3,
00545                   "not an integer in proper range");
00546   op = l_fseek(f, offset, mode[op]);
00547   if (op)
00548     return luaL_fileresult(L, 0, NULL);  /* error */
00549   else {
00550     lua_pushnumber(L, (lua_Number)l_ftell(f));
00551     return 1;
00552   }
00553 }
00554 
00555 
00556 static int f_setvbuf (lua_State *L) {
00557   static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
00558   static const char *const modenames[] = {"no", "full", "line", NULL};
00559   FILE *f = tofile(L);
00560   int op = luaL_checkoption(L, 2, NULL, modenames);
00561   lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
00562   int res = setvbuf(f, NULL, mode[op], sz);
00563   return luaL_fileresult(L, res == 0, NULL);
00564 }
00565 
00566 
00567 
00568 static int io_flush (lua_State *L) {
00569   return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
00570 }
00571 
00572 
00573 static int f_flush (lua_State *L) {
00574   return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
00575 }
00576 
00577 
00578 /*
00579 ** functions for 'io' library
00580 */
00581 static const luaL_Reg iolib[] = {
00582   {"close", io_close},
00583   {"flush", io_flush},
00584   {"input", io_input},
00585   {"lines", io_lines},
00586   {"open", io_open},
00587   {"output", io_output},
00588   {"popen", io_popen},
00589   {"read", io_read},
00590   {"tmpfile", io_tmpfile},
00591   {"type", io_type},
00592   {"write", io_write},
00593   {NULL, NULL}
00594 };
00595 
00596 
00597 /*
00598 ** methods for file handles
00599 */
00600 static const luaL_Reg flib[] = {
00601   {"close", io_close},
00602   {"flush", f_flush},
00603   {"lines", f_lines},
00604   {"read", f_read},
00605   {"seek", f_seek},
00606   {"setvbuf", f_setvbuf},
00607   {"write", f_write},
00608   {"__gc", f_gc},
00609   {"__tostring", f_tostring},
00610   {NULL, NULL}
00611 };
00612 
00613 
00614 static void createmeta (lua_State *L) {
00615   luaL_newmetatable(L, LUA_FILEHANDLE);  /* create metatable for file handles */
00616   lua_pushvalue(L, -1);  /* push metatable */
00617   lua_setfield(L, -2, "__index");  /* metatable.__index = metatable */
00618   luaL_setfuncs(L, flib, 0);  /* add file methods to new metatable */
00619   lua_pop(L, 1);  /* pop new metatable */
00620 }
00621 
00622 
00623 /*
00624 ** function to (not) close the standard files stdin, stdout, and stderr
00625 */
00626 static int io_noclose (lua_State *L) {
00627   LStream *p = tolstream(L);
00628   p->closef = &io_noclose;  /* keep file opened */
00629   lua_pushnil(L);
00630   lua_pushliteral(L, "cannot close standard file");
00631   return 2;
00632 }
00633 
00634 
00635 static void createstdfile (lua_State *L, FILE *f, const char *k,
00636                            const char *fname) {
00637   LStream *p = newprefile(L);
00638   p->f = f;
00639   p->closef = &io_noclose;
00640   if (k != NULL) {
00641     lua_pushvalue(L, -1);
00642     lua_setfield(L, LUA_REGISTRYINDEX, k);  /* add file to registry */
00643   }
00644   lua_setfield(L, -2, fname);  /* add file to module */
00645 }
00646 
00647 
00648 LUAMOD_API int luaopen_io (lua_State *L) {
00649   luaL_newlib(L, iolib);  /* new module */
00650   createmeta(L);
00651   /* create (and set) default files */
00652   createstdfile(L, stdin, IO_INPUT, "stdin");
00653   createstdfile(L, stdout, IO_OUTPUT, "stdout");
00654   createstdfile(L, stderr, NULL, "stderr");
00655   return 1;
00656 }
00657 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:03 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs