root/lib/lua/liolib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pushresult
  2. fileerror
  3. io_type
  4. tofile
  5. newfile
  6. io_noclose
  7. io_pclose
  8. io_fclose
  9. aux_close
  10. io_close
  11. io_gc
  12. io_tostring
  13. io_open
  14. io_popen
  15. io_tmpfile
  16. getiofile
  17. g_iofile
  18. io_input
  19. io_output
  20. aux_lines
  21. f_lines
  22. io_lines
  23. scan_num
  24. read_number
  25. test_eof
  26. test_eof
  27. read_line
  28. read_chars
  29. g_read
  30. io_read
  31. f_read
  32. io_readline
  33. g_write
  34. io_write
  35. f_write
  36. f_seek
  37. f_setvbuf
  38. io_flush
  39. f_flush
  40. f_getfptr
  41. createmeta
  42. createstdfile
  43. newfenv
  44. luaopen_io

   1 /*
   2 ** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $
   3 ** Standard I/O (and system) library
   4 ** See Copyright Notice in lua.h
   5 */
   6 
   7 #include <errno.h>
   8 #include <stdio.h>
   9 #include <stdlib.h>
  10 #include <string.h>
  11 #include <ctype.h>
  12 
  13 #define liolib_c
  14 #define LUA_LIB
  15 
  16 #include "lua.h"
  17 
  18 #include "lauxlib.h"
  19 #include "lualib.h"
  20 
  21 #define IO_INPUT        1
  22 #define IO_OUTPUT       2
  23 
  24 
  25 static const char *const fnames[] = {"input", "output"};
  26 
  27 
  28 static int pushresult (lua_State *L, int i, const char *filename) {
  29   int en = errno;  /* calls to Lua API may change this value */
  30   if (i) {
  31     lua_pushboolean(L, 1);
  32     return 1;
  33   }
  34   else {
  35     lua_pushnil(L);
  36     if (filename)
  37       lua_pushfstring(L, "%s: %s", filename, strerror(en));
  38     else
  39       lua_pushfstring(L, "%s", strerror(en));
  40     lua_pushinteger(L, en);
  41     return 3;
  42   }
  43 }
  44 
  45 
  46 static void fileerror (lua_State *L, int arg, const char *filename) {
  47   lua_pushfstring(L, "%s: %s", filename, strerror(errno));
  48   luaL_argerror(L, arg, lua_tostring(L, -1));
  49 }
  50 
  51 
  52 #define tofilep(L)      ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
  53 
  54 
  55 static int io_type (lua_State *L) {
  56   void *ud;
  57   luaL_checkany(L, 1);
  58   ud = lua_touserdata(L, 1);
  59   lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
  60   if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
  61     lua_pushnil(L);  /* not a file */
  62   else if (*((FILE **)ud) == NULL)
  63     lua_pushliteral(L, "closed file");
  64   else
  65     lua_pushliteral(L, "file");
  66   return 1;
  67 }
  68 
  69 
  70 static FILE *tofile (lua_State *L) {
  71   FILE **f = tofilep(L);
  72   if (*f == NULL)
  73     luaL_error(L, "attempt to use a closed file");
  74   return *f;
  75 }
  76 
  77 
  78 
  79 /*
  80 ** When creating file handles, always creates a `closed' file handle
  81 ** before opening the actual file; so, if there is a memory error, the
  82 ** file is not left opened.
  83 */
  84 static FILE **newfile (lua_State *L) {
  85   FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
  86   *pf = NULL;  /* file handle is currently `closed' */
  87   luaL_getmetatable(L, LUA_FILEHANDLE);
  88   lua_setmetatable(L, -2);
  89   return pf;
  90 }
  91 
  92 
  93 /*
  94 ** function to (not) close the standard files stdin, stdout, and stderr
  95 */
  96 static int io_noclose (lua_State *L) {
  97   lua_pushnil(L);
  98   lua_pushliteral(L, "cannot close standard file");
  99   return 2;
 100 }
 101 
 102 
 103 // reyalp - no popen
 104 #if 0
 105 /*
 106 ** function to close 'popen' files
 107 */
 108 static int io_pclose (lua_State *L) {
 109   FILE **p = tofilep(L);
 110   int ok = lua_pclose(L, *p);
 111   *p = NULL;
 112   return pushresult(L, ok, NULL);
 113 }
 114 #endif
 115 
 116 
 117 /*
 118 ** function to close regular files
 119 */
 120 static int io_fclose (lua_State *L) {
 121   FILE **p = tofilep(L);
 122   int ok = (fclose(*p) == 0);
 123   *p = NULL;
 124   return pushresult(L, ok, NULL);
 125 }
 126 
 127 
 128 static int aux_close (lua_State *L) {
 129   lua_getfenv(L, 1);
 130   lua_getfield(L, -1, "__close");
 131   return (lua_tocfunction(L, -1))(L);
 132 }
 133 
 134 
 135 static int io_close (lua_State *L) {
 136   if (lua_isnone(L, 1))
 137     lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
 138   tofile(L);  /* make sure argument is a file */
 139   return aux_close(L);
 140 }
 141 
 142 
 143 static int io_gc (lua_State *L) {
 144   FILE *f = *tofilep(L);
 145   /* ignore closed files */
 146   if (f != NULL)
 147     aux_close(L);
 148   return 0;
 149 }
 150 
 151 
 152 static int io_tostring (lua_State *L) {
 153   FILE *f = *tofilep(L);
 154   if (f == NULL)
 155     lua_pushliteral(L, "file (closed)");
 156   else
 157     lua_pushfstring(L, "file (%p)", f);
 158   return 1;
 159 }
 160 
 161 
 162 static int io_open (lua_State *L) {
 163   const char *filename = luaL_checkstring(L, 1);
 164   const char *mode = luaL_optstring(L, 2, "r");
 165   FILE **pf = newfile(L);
 166   *pf = fopen(filename, mode);
 167   return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
 168 }
 169 
 170 
 171 /*
 172 ** this function has a separated environment, which defines the
 173 ** correct __close for 'popen' files
 174 */
 175 #if 0
 176 static int io_popen (lua_State *L) {
 177   const char *filename = luaL_checkstring(L, 1);
 178   const char *mode = luaL_optstring(L, 2, "r");
 179   FILE **pf = newfile(L);
 180   *pf = lua_popen(L, filename, mode);
 181   return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
 182 }
 183 #endif
 184 
 185 
 186 // TODO tmpfile
 187 #if 0
 188 static int io_tmpfile (lua_State *L) {
 189   FILE **pf = newfile(L);
 190   *pf = tmpfile();
 191   return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
 192 }
 193 #endif
 194 
 195 
 196 static FILE *getiofile (lua_State *L, int findex) {
 197   FILE *f;
 198   lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
 199   f = *(FILE **)lua_touserdata(L, -1);
 200   if (f == NULL)
 201     luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
 202   return f;
 203 }
 204 
 205 
 206 static int g_iofile (lua_State *L, int f, const char *mode) {
 207   if (!lua_isnoneornil(L, 1)) {
 208     const char *filename = lua_tostring(L, 1);
 209     if (filename) {
 210       FILE **pf = newfile(L);
 211       *pf = fopen(filename, mode);
 212       if (*pf == NULL)
 213         fileerror(L, 1, filename);
 214     }
 215     else {
 216       tofile(L);  /* check that it's a valid file handle */
 217       lua_pushvalue(L, 1);
 218     }
 219     lua_rawseti(L, LUA_ENVIRONINDEX, f);
 220   }
 221   /* return current value */
 222   lua_rawgeti(L, LUA_ENVIRONINDEX, f);
 223   return 1;
 224 }
 225 
 226 
 227 static int io_input (lua_State *L) {
 228   return g_iofile(L, IO_INPUT, "r");
 229 }
 230 
 231 
 232 static int io_output (lua_State *L) {
 233   return g_iofile(L, IO_OUTPUT, "w");
 234 }
 235 
 236 
 237 static int io_readline (lua_State *L);
 238 
 239 
 240 static void aux_lines (lua_State *L, int idx, int toclose) {
 241   lua_pushvalue(L, idx);
 242   lua_pushboolean(L, toclose);  /* close/not close file when finished */
 243   lua_pushcclosure(L, io_readline, 2);
 244 }
 245 
 246 
 247 static int f_lines (lua_State *L) {
 248   tofile(L);  /* check that it's a valid file handle */
 249   aux_lines(L, 1, 0);
 250   return 1;
 251 }
 252 
 253 
 254 static int io_lines (lua_State *L) {
 255   if (lua_isnoneornil(L, 1)) {  /* no arguments? */
 256     /* will iterate over default input */
 257     lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
 258     return f_lines(L);
 259   }
 260   else {
 261     const char *filename = luaL_checkstring(L, 1);
 262     FILE **pf = newfile(L);
 263     *pf = fopen(filename, "r");
 264     if (*pf == NULL)
 265       fileerror(L, 1, filename);
 266     aux_lines(L, lua_gettop(L), 1);
 267     return 1;
 268   }
 269 }
 270 
 271 
 272 /*
 273 ** {======================================================
 274 ** READ
 275 ** =======================================================
 276 */
 277 
 278 #define SCAN_NUM_MAX_CHARS 11
 279 // reyalp - no fscanf, read a number
 280 // this doesn't exactly replicate fscanf(f,"%d",&r)
 281 // in particular, scanf will eat an indefinite number of digits
 282 static int scan_num(FILE *f,int *r) {
 283   char c;
 284   int count=0;
 285   int neg=0;
 286   char s[SCAN_NUM_MAX_CHARS];
 287   do {
 288     if(fread(&c,1,1,f) != 1) return 0;
 289   } while( isspace(c) );
 290   if(c == '-') {
 291     neg=1;
 292     if(fread(&c,1,1,f) != 1) return 0;
 293   }
 294   while( count < SCAN_NUM_MAX_CHARS ) {
 295     if(isdigit(c)) {
 296       s[count++] = c;
 297     }
 298     else {
 299       fseek(f,-1,SEEK_CUR);
 300       if(count < 1 )
 301         return 0;
 302       else
 303         break;
 304     }
 305     if( fread(&c,1,1,f) != 1 ) break;
 306   }
 307   s[count] = 0;
 308   if(count) {
 309     *r = (neg) ? -atoi(s) : atoi(s);
 310     return 1;
 311   }
 312   return 0;
 313 }
 314 
 315 static int read_number (lua_State *L, FILE *f) {
 316   lua_Number d;
 317 // no fscanf
 318 #if 0
 319   if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
 320 #else
 321   if (scan_num(f,&d) == 1) {
 322 #endif
 323     lua_pushnumber(L, d);
 324     return 1;
 325   }
 326   else {
 327     lua_pushnil(L);  /* "result" to be removed */
 328     return 0;  /* read fails */
 329   }
 330 }
 331 
 332 
 333 #if 0
 334 static int test_eof (lua_State *L, FILE *f) {
 335   int c = getc(f);
 336   ungetc(c, f);
 337   lua_pushlstring(L, NULL, 0);
 338   return (c != EOF);
 339 }
 340 #else
 341 static int test_eof (lua_State *L, FILE *f) {
 342   lua_pushlstring(L, NULL, 0);
 343   // TODO not sure why getc/ungetc was used
 344   return !feof(f);
 345 }
 346 
 347 #endif
 348 
 349 static int read_line (lua_State *L, FILE *f) {
 350   luaL_Buffer b;
 351   luaL_buffinit(L, &b);
 352   for (;;) {
 353     size_t l;
 354     char *p = luaL_prepbuffer(&b);
 355     if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {  /* eof? */
 356       luaL_pushresult(&b);  /* close buffer */
 357       return (lua_objlen(L, -1) > 0);  /* check whether read something */
 358     }
 359     l = strlen(p);
 360     if (l == 0 || p[l-1] != '\n')
 361       luaL_addsize(&b, l);
 362     else {
 363       luaL_addsize(&b, l - 1);  /* do not include `eol' */
 364       luaL_pushresult(&b);  /* close buffer */
 365       return 1;  /* read at least an `eol' */
 366     }
 367   }
 368 }
 369 
 370 
 371 static int read_chars (lua_State *L, FILE *f, size_t n) {
 372   size_t rlen;  /* how much to read */
 373   size_t nr;  /* number of chars actually read */
 374   luaL_Buffer b;
 375   luaL_buffinit(L, &b);
 376   rlen = LUAL_BUFFERSIZE;  /* try to read that much each time */
 377   do {
 378     char *p = luaL_prepbuffer(&b);
 379     if (rlen > n) rlen = n;  /* cannot read more than asked */
 380     nr = fread(p, sizeof(char), rlen, f);
 381     luaL_addsize(&b, nr);
 382     n -= nr;  /* still have to read `n' chars */
 383   } while (n > 0 && nr == rlen);  /* until end of count or eof */
 384   luaL_pushresult(&b);  /* close buffer */
 385   return (n == 0 || lua_objlen(L, -1) > 0);
 386 }
 387 
 388 
 389 static int g_read (lua_State *L, FILE *f, int first) {
 390   int nargs = lua_gettop(L) - 1;
 391   int success;
 392   int n;
 393 // no error state to clear
 394 #if 0
 395   clearerr(f);
 396 #endif
 397   if (nargs == 0) {  /* no arguments? */
 398     success = read_line(L, f);
 399     n = first+1;  /* to return 1 result */
 400   }
 401   else {  /* ensure stack space for all results and for auxlib's buffer */
 402     luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
 403     success = 1;
 404     for (n = first; nargs-- && success; n++) {
 405       if (lua_type(L, n) == LUA_TNUMBER) {
 406         size_t l = (size_t)lua_tointeger(L, n);
 407         success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
 408       }
 409       else {
 410         const char *p = lua_tostring(L, n);
 411         luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
 412         switch (p[1]) {
 413           case 'n':  /* number */
 414             success = read_number(L, f);
 415             break;
 416           case 'l':  /* line */
 417             success = read_line(L, f);
 418             break;
 419           case 'a':  /* file */
 420             read_chars(L, f, ~((size_t)0));  /* read MAX_SIZE_T chars */
 421             success = 1; /* always success */
 422             break;
 423           default:
 424             return luaL_argerror(L, n, "invalid format");
 425         }
 426       }
 427     }
 428   }
 429 // we have no ferror
 430 #if 0
 431   if (ferror(f))
 432     return pushresult(L, 0, NULL);
 433 #endif
 434   if (!success) {
 435     lua_pop(L, 1);  /* remove last result */
 436     lua_pushnil(L);  /* push nil instead */
 437   }
 438   return n - first;
 439 }
 440 
 441 
 442 static int io_read (lua_State *L) {
 443   return g_read(L, getiofile(L, IO_INPUT), 1);
 444 }
 445 
 446 
 447 static int f_read (lua_State *L) {
 448   return g_read(L, tofile(L), 2);
 449 }
 450 
 451 
 452 static int io_readline (lua_State *L) {
 453   FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
 454   int sucess;
 455   if (f == NULL)  /* file is already closed? */
 456     luaL_error(L, "file is already closed");
 457   sucess = read_line(L, f);
 458 // we have no ferror
 459 #if 0
 460   if (ferror(f))
 461     return luaL_error(L, "%s", strerror(errno));
 462 #endif
 463   if (sucess) return 1;
 464   else {  /* EOF */
 465     if (lua_toboolean(L, lua_upvalueindex(2))) {  /* generator created file? */
 466       lua_settop(L, 0);
 467       lua_pushvalue(L, lua_upvalueindex(1));
 468       aux_close(L);  /* close it */
 469     }
 470     return 0;
 471   }
 472 }
 473 
 474 /* }====================================================== */
 475 
 476 
 477 static int g_write (lua_State *L, FILE *f, int arg) {
 478   int nargs = lua_gettop(L) - 1;
 479   int status = 1;
 480   for (; nargs--; arg++) {
 481     if (lua_type(L, arg) == LUA_TNUMBER) {
 482       char s[12];
 483       sprintf(s,LUA_NUMBER_FMT,lua_tonumber(L,arg));
 484       /* optimization: could be done exactly as for strings */
 485       status = status &&
 486 #if 0
 487           fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
 488 #else
 489           fwrite(s, sizeof(char), strlen(s), f);
 490 #endif
 491     }
 492     else {
 493       size_t l;
 494       const char *s = luaL_checklstring(L, arg, &l);
 495       status = status && ((size_t)fwrite(s, sizeof(char), l, f) == l);
 496     }
 497   }
 498   return pushresult(L, status, NULL);
 499 }
 500 
 501 
 502 static int io_write (lua_State *L) {
 503   return g_write(L, getiofile(L, IO_OUTPUT), 1);
 504 }
 505 
 506 
 507 static int f_write (lua_State *L) {
 508   return g_write(L, tofile(L), 2);
 509 }
 510 
 511 
 512 static int f_seek (lua_State *L) {
 513   static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
 514   static const char *const modenames[] = {"set", "cur", "end", NULL};
 515   FILE *f = tofile(L);
 516   int op = luaL_checkoption(L, 2, "cur", modenames);
 517   long offset = luaL_optlong(L, 3, 0);
 518   op = fseek(f, offset, mode[op]);
 519   if (op)
 520     return pushresult(L, 0, NULL);  /* error */
 521   else {
 522     lua_pushinteger(L, ftell(f));
 523     return 1;
 524   }
 525 }
 526 
 527 
 528 #if 0
 529 static int f_setvbuf (lua_State *L) {
 530   static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
 531   static const char *const modenames[] = {"no", "full", "line", NULL};
 532   FILE *f = tofile(L);
 533   int op = luaL_checkoption(L, 2, NULL, modenames);
 534   lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
 535   int res = setvbuf(f, NULL, mode[op], sz);
 536   return pushresult(L, res == 0, NULL);
 537 }
 538 #endif
 539 
 540 
 541 
 542 static int io_flush (lua_State *L) {
 543   return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
 544 }
 545 
 546 
 547 static int f_flush (lua_State *L) {
 548   return pushresult(L, fflush(tofile(L)) == 0, NULL);
 549 }
 550 
 551 static int f_getfptr(lua_State *L) {
 552   FILE *f = tofile(L);
 553   lua_pushinteger(L, (int)f);
 554   return 1;
 555 }
 556 
 557 static const luaL_Reg iolib[] = {
 558   {"close", io_close},
 559   {"flush", io_flush},
 560   {"input", io_input},
 561   {"lines", io_lines},
 562   {"open", io_open},
 563   {"output", io_output},
 564 #if 0
 565   {"popen", io_popen},
 566 #endif
 567   {"read", io_read},
 568   // TODO
 569 #if 0
 570   {"tmpfile", io_tmpfile},
 571 #endif
 572   {"type", io_type},
 573   {"write", io_write},
 574   {NULL, NULL}
 575 };
 576 
 577 
 578 static const luaL_Reg flib[] = {
 579   {"close", io_close},
 580   {"flush", f_flush},
 581   {"lines", f_lines},
 582   {"read", f_read},
 583   {"seek", f_seek},
 584 #if 0
 585   {"setvbuf", f_setvbuf},
 586 #endif
 587   {"write", f_write},
 588   {"_getfptr",f_getfptr}, // debug
 589   {"__gc", io_gc},
 590   {"__tostring", io_tostring},
 591   {NULL, NULL}
 592 };
 593 
 594 
 595 static void createmeta (lua_State *L) {
 596   luaL_newmetatable(L, LUA_FILEHANDLE);  /* create metatable for file handles */
 597   lua_pushvalue(L, -1);  /* push metatable */
 598   lua_setfield(L, -2, "__index");  /* metatable.__index = metatable */
 599   luaL_register(L, NULL, flib);  /* file methods */
 600 }
 601 
 602 
 603 static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
 604   *newfile(L) = f;
 605   if (k > 0) {
 606     lua_pushvalue(L, -1);
 607     lua_rawseti(L, LUA_ENVIRONINDEX, k);
 608   }
 609   lua_pushvalue(L, -2);  /* copy environment */
 610   lua_setfenv(L, -2);  /* set it */
 611   lua_setfield(L, -3, fname);
 612 }
 613 
 614 
 615 static void newfenv (lua_State *L, lua_CFunction cls) {
 616   lua_createtable(L, 0, 1);
 617   lua_pushcfunction(L, cls);
 618   lua_setfield(L, -2, "__close");
 619 }
 620 
 621 
 622 LUALIB_API int luaopen_io (lua_State *L) {
 623   createmeta(L);
 624   /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
 625   newfenv(L, io_fclose);
 626   lua_replace(L, LUA_ENVIRONINDEX);
 627   /* open library */
 628   luaL_register(L, LUA_IOLIBNAME, iolib);
 629   /* create (and set) default files */
 630   newfenv(L, io_noclose);  /* close function for default files */
 631 #ifdef HOST_LUA
 632   createstdfile(L, stdin, IO_INPUT, "stdin");
 633   createstdfile(L, stdout, IO_OUTPUT, "stdout");
 634   createstdfile(L, stderr, 0, "stderr");
 635 #else
 636 // initialize them in the closed state
 637 // stderr/stdout could go to regular files or script console
 638   createstdfile(L, NULL, IO_INPUT, "stdin");
 639   createstdfile(L, NULL, IO_OUTPUT, "stdout");
 640   createstdfile(L, NULL, 0, "stderr");
 641 #endif
 642   lua_pop(L, 1);  /* pop environment for default files */
 643   // reyalp - no popen
 644 #if 0
 645   lua_getfield(L, -1, "popen");
 646   newfenv(L, io_pclose);  /* create environment for 'popen' */
 647   lua_setfenv(L, -2);  /* set fenv for 'popen' */
 648   lua_pop(L, 1);  /* pop 'popen' */
 649 #endif
 650   return 1;
 651 }
 652 

/* [<][>][^][v][top][bottom][index][help] */