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

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