liolib.c
上传用户:dzyhzl
上传日期:2019-04-29
资源大小:56270k
文件大小:19k
源码类别:

模拟服务器

开发平台:

C/C++

  1. /*
  2. ** $Id: liolib.c,v 1.91 2000/10/31 13:10:24 roberto Exp $
  3. ** Standard I/O (and system) library
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <ctype.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include <time.h>
  11. #include "../lua.h"
  12. #include "../lauxlib.h"
  13. #include "../luadebug.h"
  14. #include "../lualib.h"
  15. //#include "errno.h"
  16. #ifndef OLD_ANSI
  17. #include <errno.h>
  18. #include <locale.h>
  19. #define realloc(b,s)    ((b) == NULL ? malloc(s) : (realloc)(b, s))
  20. #define free(b)         if (b) (free)(b)
  21. #else
  22. /* no support for locale and for strerror: fake them */
  23. #define setlocale(a,b) ((void)a, strcmp((b),"C")==0?"C":NULL)
  24. #define LC_ALL 0
  25. #define LC_COLLATE 0
  26. #define LC_CTYPE 0
  27. #define LC_MONETARY 0
  28. #define LC_NUMERIC 0
  29. #define LC_TIME 0
  30. #define strerror(e) "generic I/O error"
  31. #define errno (-1)
  32. #endif
  33. //这个define调试时加的,以后要去掉!!!
  34. //#define errno (-1)//Question
  35. #ifdef POPEN
  36. /* FILE *popen();
  37. int pclose(); */
  38. #define CLOSEFILE(L, f)    ((pclose(f) == -1) ? fclose(f) : 0)
  39. #else
  40. /* no support for popen */
  41. #define popen(x,y) NULL  /* that is, popen always fails */
  42. #define CLOSEFILE(L, f)    (fclose(f))
  43. #endif
  44. #define INFILE 0
  45. #define OUTFILE 1
  46. typedef struct IOCtrl {
  47.   int ref[2];  /* ref for strings _INPUT/_OUTPUT */
  48.   int iotag;    /* tag for file handles */
  49.   int closedtag;  /* tag for closed handles */
  50. } IOCtrl;
  51. static const char *const filenames[] = {"_INPUT", "_OUTPUT"};
  52. static int pushresult (lua_State *L, int i) {
  53.   if (i) {
  54.     lua_pushuserdata(L, NULL);
  55.     return 1;
  56.   }
  57.   else {
  58.     lua_pushnil(L);
  59.     lua_pushstring(L, strerror(errno));
  60.     lua_pushnumber(L, errno);
  61.     return 3;;
  62.   }
  63. }
  64. /*
  65. ** {======================================================
  66. ** FILE Operations
  67. ** =======================================================
  68. */
  69. static FILE *gethandle (lua_State *L, IOCtrl *ctrl, int f) {
  70.   void *p = lua_touserdata(L, f);
  71.   if (p != NULL) {  /* is `f' a userdata ? */
  72.     int ftag = lua_tag(L, f);
  73.     if (ftag == ctrl->iotag)  /* does it have the correct tag? */
  74.       return (FILE *)p;
  75.     else if (ftag == ctrl->closedtag)
  76.       lua_error(L, "cannot access a closed file");
  77.     /* else go through */
  78.   }
  79.   return NULL;
  80. }
  81. static FILE *getnonullfile (lua_State *L, IOCtrl *ctrl, int arg) {
  82.   FILE *f = gethandle(L, ctrl, arg);
  83.   luaL_arg_check(L, f, arg, "invalid file handle");
  84.   return f;
  85. }
  86. static FILE *getfilebyref (lua_State *L, IOCtrl *ctrl, int inout) {
  87.   FILE *f;
  88.   lua_getglobals(L);
  89.   lua_getref(L, ctrl->ref[inout]);
  90.   lua_rawget(L, -2);
  91.   f = gethandle(L, ctrl, -1);
  92.   if (f == NULL)
  93.     luaL_verror(L, "global variable `%.10s' is not a file handle",
  94.                 filenames[inout]);
  95.   return f;
  96. }
  97. static void setfilebyname (lua_State *L, IOCtrl *ctrl, FILE *f,
  98.                            const char *name) {
  99.   lua_pushusertag(L, f, ctrl->iotag);
  100.   lua_setglobal(L, name);
  101. }
  102. #define setfile(L,ctrl,f,inout) (setfilebyname(L,ctrl,f,filenames[inout]))
  103. static int setreturn (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) {
  104.   if (f == NULL)
  105.     return pushresult(L, 0);
  106.   else {
  107.     setfile(L, ctrl, f, inout);
  108.     lua_pushusertag(L, f, ctrl->iotag);
  109.     return 1;
  110.   }
  111. }
  112. static int closefile (lua_State *L, IOCtrl *ctrl, FILE *f) {
  113.   if (f == stdin || f == stdout || f == stderr)
  114.     return 1;
  115.   else {
  116.     lua_pushusertag(L, f, ctrl->iotag);
  117.     lua_settag(L, ctrl->closedtag);
  118.     return (CLOSEFILE(L, f) == 0);
  119.   }
  120. }
  121. static int io_close (lua_State *L) {
  122.   IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1);
  123.   lua_pop(L, 1);  /* remove upvalue */
  124.   return pushresult(L, closefile(L, ctrl, getnonullfile(L, ctrl, 1)));
  125. }
  126. static int file_collect (lua_State *L) {
  127.   IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1);
  128.   FILE *f = getnonullfile(L, ctrl, 1);
  129.   if (f != stdin && f != stdout && f != stderr)
  130.     CLOSEFILE(L, f);
  131.   return 0;
  132. }
  133. static int io_open (lua_State *L) {
  134.   IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1);
  135.   FILE *f;
  136.   lua_pop(L, 1);  /* remove upvalue */
  137.   f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2));
  138.   if (f) {
  139.     lua_pushusertag(L, f, ctrl->iotag);
  140.     return 1;
  141.   }
  142.   else
  143.     return pushresult(L, 0);
  144. }
  145. static int io_fromto (lua_State *L, int inout, const char *mode) {
  146.   IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1);
  147.   FILE *current;
  148.   lua_pop(L, 1);  /* remove upvalue */
  149.   if (lua_isnull(L, 1)) {
  150.     closefile(L, ctrl, getfilebyref(L, ctrl, inout));
  151.     current = (inout == 0) ? stdin : stdout;    
  152.   }
  153.   else if (lua_tag(L, 1) == ctrl->iotag)  /* deprecated option */
  154.     current = (FILE *)lua_touserdata(L, 1);
  155.   else {
  156.     const char *s = luaL_check_string(L, 1);
  157.     current = (*s == '|') ? popen(s+1, mode) : fopen(s, mode);
  158.   }
  159.   return setreturn(L, ctrl, current, inout);
  160. }
  161. static int io_readfrom (lua_State *L) {
  162.   return io_fromto(L, INFILE, "r");
  163. }
  164. static int io_writeto (lua_State *L) {
  165.   return io_fromto(L, OUTFILE, "w");
  166. }
  167. static int io_appendto (lua_State *L) {
  168.   IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1);
  169.   FILE *current;
  170.   lua_pop(L, 1);  /* remove upvalue */
  171.   current = fopen(luaL_check_string(L, 1), "a");
  172.   return setreturn(L, ctrl, current, OUTFILE);
  173. }
  174. /*
  175. ** {======================================================
  176. ** READ
  177. ** =======================================================
  178. */
  179. #ifdef LUA_COMPAT_READPATTERN
  180. /*
  181. ** We cannot lookahead without need, because this can lock stdin.
  182. ** This flag signals when we need to read a next char.
  183. */
  184. #define NEED_OTHER (EOF-1)  /* just some flag different from EOF */
  185. static int read_pattern (lua_State *L, FILE *f, const char *p) {
  186.   int inskip = 0;  /* {skip} level */
  187.   int c = NEED_OTHER;
  188.   luaL_Buffer b;
  189.   luaL_buffinit(L, &b);
  190.   while (*p != '') {
  191.     switch (*p) {
  192.       case '{':
  193.         inskip++;
  194.         p++;
  195.         continue;
  196.       case '}':
  197.         if (!inskip) lua_error(L, "unbalanced braces in read pattern");
  198.         inskip--;
  199.         p++;
  200.         continue;
  201.       default: {
  202.         const char *ep = luaI_classend(L, p);  /* get what is next */
  203.         int m;  /* match result */
  204.         if (c == NEED_OTHER) c = getc(f);
  205.         m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
  206.         if (m) {
  207.           if (!inskip) luaL_putchar(&b, c);
  208.           c = NEED_OTHER;
  209.         }
  210.         switch (*ep) {
  211.           case '+':  /* repetition (1 or more) */
  212.             if (!m) goto break_while;  /* pattern fails? */
  213.             /* else go through */
  214.           case '*':  /* repetition (0 or more) */
  215.             while (m) {  /* reads the same item until it fails */
  216.               c = getc(f);
  217.               m = (c==EOF) ? 0 : luaI_singlematch(c, p, ep);
  218.               if (m && !inskip) luaL_putchar(&b, c);
  219.             }
  220.             /* go through to continue reading the pattern */
  221.           case '?':  /* optional */
  222.             p = ep+1;  /* continues reading the pattern */
  223.             continue;
  224.           default:
  225.             if (!m) goto break_while;  /* pattern fails? */
  226.             p = ep;  /* else continues reading the pattern */
  227.         }
  228.       }
  229.     }
  230.   } break_while:
  231.   if (c != NEED_OTHER) ungetc(c, f);
  232.   luaL_pushresult(&b);  /* close buffer */
  233.   return (*p == '');
  234. }
  235. #else
  236. #define read_pattern(L, f, p) (lua_error(L, "read patterns are deprecated"), 0)
  237. #endif
  238. static int read_number (lua_State *L, FILE *f) {
  239.   double d;
  240.   if (fscanf(f, "%lf", &d) == 1) {
  241.     lua_pushnumber(L, d);
  242.     return 1;
  243.   }
  244.   else return 0;  /* read fails */
  245. }
  246. static int read_word (lua_State *L, FILE *f) {
  247.   int c;
  248.   luaL_Buffer b;
  249.   luaL_buffinit(L, &b);
  250.   do { c = fgetc(f); } while (isspace(c));  /* skip spaces */
  251.   while (c != EOF && !isspace(c)) {
  252.     luaL_putchar(&b, c);
  253.     c = fgetc(f);
  254.   }
  255.   ungetc(c, f);
  256.   luaL_pushresult(&b);  /* close buffer */
  257.   return (lua_strlen(L, -1) > 0);
  258. }
  259. static int read_line (lua_State *L, FILE *f) {
  260.   int n = 0;
  261.   luaL_Buffer b;
  262.   luaL_buffinit(L, &b);
  263.   for (;;) {
  264.     char *p = luaL_prepbuffer(&b);
  265.     if (!fgets(p, LUAL_BUFFERSIZE, f))  /* read fails? */
  266.       break;
  267.     n = strlen(p);
  268.     if (p[n-1] != 'n')
  269.       luaL_addsize(&b, n); 
  270.     else {
  271.       luaL_addsize(&b, n-1);  /* do not add the `n' */
  272.       break;
  273.     }
  274.   }
  275.   luaL_pushresult(&b);  /* close buffer */
  276.   return (n > 0);  /* read something? */
  277. }
  278. static void read_file (lua_State *L, FILE *f) {
  279.   size_t len = 0;
  280.   size_t size = BUFSIZ;
  281.   char *buffer = NULL;
  282.   for (;;) {
  283.     char *newbuffer = (char *)realloc(buffer, size);
  284.     if (newbuffer == NULL) {
  285.       free(buffer);
  286.       lua_error(L, "not enough memory to read a file");
  287.     }
  288.     buffer = newbuffer;
  289.     len += fread(buffer+len, sizeof(char), size-len, f);
  290.     if (len < size) break;  /* did not read all it could */
  291.     size *= 2;
  292.   }
  293.   lua_pushlstring(L, buffer, len);
  294.   free(buffer);
  295. }
  296. static int read_chars (lua_State *L, FILE *f, size_t n) {
  297.   char *buffer;
  298.   size_t n1;
  299.   char statbuff[BUFSIZ];
  300.   if (n <= BUFSIZ)
  301.     buffer = statbuff;
  302.   else {
  303.     buffer = (char  *)malloc(n);
  304.     if (buffer == NULL)
  305.       lua_error(L, "not enough memory to read a file");
  306.   }
  307.   n1 = fread(buffer, sizeof(char), n, f);
  308.   lua_pushlstring(L, buffer, n1);
  309.   if (buffer != statbuff) free(buffer);
  310.   return (n1 > 0 || n == 0);
  311. }
  312. static int io_read (lua_State *L) {
  313.   IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1);
  314.   int lastarg = lua_gettop(L) - 1;
  315.   int firstarg = 1;
  316.   FILE *f = gethandle(L, ctrl, firstarg);
  317.   int n;
  318.   if (f) firstarg++;
  319.   else f = getfilebyref(L, ctrl, INFILE);  /* get _INPUT */
  320.   lua_pop(L, 1);
  321.   if (firstarg > lastarg) {  /* no arguments? */
  322.     lua_settop(L, 0);  /* erase upvalue and other eventual garbage */
  323.     firstarg = lastarg = 1;  /* correct indices */
  324.     lua_pushstring(L, "*l");  /* push default argument */
  325.   }
  326.   else  /* ensure stack space for all results and for auxlib's buffer */
  327.     luaL_checkstack(L, lastarg-firstarg+1+LUA_MINSTACK, "too many arguments");
  328.   for (n = firstarg; n<=lastarg; n++) {
  329.     int success;
  330.     if (lua_isnumber(L, n))
  331.       success = read_chars(L, f, (size_t)lua_tonumber(L, n));
  332.     else {
  333.       const char *p = luaL_check_string(L, n);
  334.       if (p[0] != '*')
  335.         success = read_pattern(L, f, p);  /* deprecated! */
  336.       else {
  337.         switch (p[1]) {
  338.           case 'n':  /* number */
  339.             if (!read_number(L, f)) goto endloop;  /* read fails */
  340.             continue;  /* number is already pushed; avoid the "pushstring" */
  341.           case 'l':  /* line */
  342.             success = read_line(L, f);
  343.             break;
  344.           case 'a':  /* file */
  345.             read_file(L, f);
  346.             success = 1; /* always success */
  347.             break;
  348.           case 'w':  /* word */
  349.             success = read_word(L, f);
  350.             break;
  351.           default:
  352.             luaL_argerror(L, n, "invalid format");
  353.             success = 0;  /* to avoid warnings */
  354.         }
  355.       }
  356.     }
  357.     if (!success) {
  358.       lua_pop(L, 1);  /* remove last result */
  359.       break;  /* read fails */
  360.     }
  361.   } endloop:
  362.   return n - firstarg;
  363. }
  364. /* }====================================================== */
  365. static int io_write (lua_State *L) {
  366.   int lastarg = lua_gettop(L) - 1;
  367.   IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1);
  368.   int arg = 1;
  369.   int status = 1;
  370.   FILE *f = gethandle(L, ctrl, arg);
  371.   if (f) arg++;
  372.   else f = getfilebyref(L, ctrl, OUTFILE);  /* get _OUTPUT */
  373.   for (; arg <=  lastarg; arg++) {
  374.     if (lua_type(L, arg) == LUA_TNUMBER) {  /* LUA_NUMBER */
  375.       /* optimization: could be done exactly as for strings */
  376.       status = status && fprintf(f, "%.16g", lua_tonumber(L, arg)) > 0;
  377.     }
  378.     else {
  379.       size_t l;
  380.       const char *s = luaL_check_lstr(L, arg, &l);
  381.       status = status && (fwrite(s, sizeof(char), l, f) == l);
  382.     }
  383.   }
  384.   pushresult(L, status);
  385.   return 1;
  386. }
  387. static int io_seek (lua_State *L) {
  388.   static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
  389.   static const char *const modenames[] = {"set", "cur", "end", NULL};
  390.   IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1);
  391.   FILE *f;
  392.   int op;
  393.   long offset;
  394.   lua_pop(L, 1);  /* remove upvalue */
  395.   f = getnonullfile(L, ctrl, 1);
  396.   op = luaL_findstring(luaL_opt_string(L, 2, "cur"), modenames);
  397.   offset = luaL_opt_long(L, 3, 0);
  398.   luaL_arg_check(L, op != -1, 2, "invalid mode");
  399.   op = fseek(f, offset, mode[op]);
  400.   if (op)
  401.     return pushresult(L, 0);  /* error */
  402.   else {
  403.     lua_pushnumber(L, ftell(f));
  404.     return 1;
  405.   }
  406. }
  407. static int io_flush (lua_State *L) {
  408.   IOCtrl *ctrl = (IOCtrl *)lua_touserdata(L, -1);
  409.   FILE *f;
  410.   lua_pop(L, 1);  /* remove upvalue */
  411.   f = gethandle(L, ctrl, 1);
  412.   luaL_arg_check(L, f || lua_isnull(L, 1), 1, "invalid file handle");
  413.   return pushresult(L, fflush(f) == 0);
  414. }
  415. /* }====================================================== */
  416. /*
  417. ** {======================================================
  418. ** Other O.S. Operations
  419. ** =======================================================
  420. */
  421. static int io_execute (lua_State *L) {
  422.   lua_pushnumber(L, system(luaL_check_string(L, 1)));
  423.   return 1;
  424. }
  425. static int io_remove (lua_State *L) {
  426.   return pushresult(L, remove(luaL_check_string(L, 1)) == 0);
  427. }
  428. static int io_rename (lua_State *L) {
  429.   return pushresult(L, rename(luaL_check_string(L, 1),
  430.                     luaL_check_string(L, 2)) == 0);
  431. }
  432. static int io_tmpname (lua_State *L) {
  433.   lua_pushstring(L, tmpnam(NULL));
  434.   return 1;
  435. }
  436. static int io_getenv (lua_State *L) {
  437.   lua_pushstring(L, getenv(luaL_check_string(L, 1)));  /* if NULL push nil */
  438.   return 1;
  439. }
  440. static int io_clock (lua_State *L) {
  441.   lua_pushnumber(L, ((double)clock())/CLOCKS_PER_SEC);
  442.   return 1;
  443. }
  444. static int io_date (lua_State *L) {
  445.   char b[256];
  446.   const char *s = luaL_opt_string(L, 1, "%c");
  447.   struct tm *stm;
  448.   time_t t;
  449.   time(&t); stm = localtime(&t);
  450.   if (strftime(b, sizeof(b), s, stm))
  451.     lua_pushstring(L, b);
  452.   else
  453.     lua_error(L, "invalid `date' format");
  454.   return 1;
  455. }
  456. static int setloc (lua_State *L) {
  457.   static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY,
  458.                       LC_NUMERIC, LC_TIME};
  459.   static const char *const catnames[] = {"all", "collate", "ctype", "monetary",
  460.      "numeric", "time", NULL};
  461.   int op = luaL_findstring(luaL_opt_string(L, 2, "all"), catnames);
  462.   luaL_arg_check(L, op != -1, 2, "invalid option");
  463.   lua_pushstring(L, setlocale(cat[op], luaL_check_string(L, 1)));
  464.   return 1;
  465. }
  466. static int io_exit (lua_State *L) {
  467.   printf("LUASCRIPT_ERROR!!!!!FROM io_exit!!!!!!111n");
  468.   printf("LUASCRIPT_ERROR!!!!!FROM io_exit!!!!!!111n");
  469.   printf("LUASCRIPT_ERROR!!!!!FROM io_exit!!!!!!111n");
  470. //  exit(luaL_opt_int(L, 1, EXIT_SUCCESS));
  471.   return 0;  /* to avoid warnings */
  472. }
  473. /* }====================================================== */
  474. static int io_debug (lua_State *L) {
  475.   for (;;) {
  476.     char buffer[250];
  477.     fprintf(stderr, "lua_debug> ");
  478.     if (fgets(buffer, sizeof(buffer), stdin) == 0 ||
  479.         strcmp(buffer, "contn") == 0)
  480.       return 0;
  481.     lua_dostring(L, buffer);
  482.     lua_settop(L, 0);  /* remove eventual returns */
  483.   }
  484. }
  485. #define LEVELS1 12 /* size of the first part of the stack */
  486. #define LEVELS2 10 /* size of the second part of the stack */
  487. static int errorfb (lua_State *L) {
  488.   int level = 1;  /* skip level 0 (it's this function) */
  489.   int firstpart = 1;  /* still before eventual `...' */
  490.   lua_Debug ar;
  491.   luaL_Buffer b;
  492.   luaL_buffinit(L, &b);
  493.   luaL_addstring(&b, "error: ");
  494.   luaL_addstring(&b, luaL_check_string(L, 1));
  495.   luaL_addstring(&b, "n");
  496.   while (lua_getstack(L, level++, &ar)) {
  497.     char buff[120];  /* enough to fit following `sprintf's */
  498.     if (level == 2)
  499.       luaL_addstring(&b, "stack traceback:n");
  500.     else if (level > LEVELS1 && firstpart) {
  501.       /* no more than `LEVELS2' more levels? */
  502.       if (!lua_getstack(L, level+LEVELS2, &ar))
  503.         level--;  /* keep going */
  504.       else {
  505.         luaL_addstring(&b, "       ...n");  /* too many levels */
  506.         while (lua_getstack(L, level+LEVELS2, &ar))  /* find last levels */
  507.           level++;
  508.       }
  509.       firstpart = 0;
  510.       continue;
  511.     }
  512.     sprintf(buff, "%4d:  ", level-1);
  513.     luaL_addstring(&b, buff);
  514.     lua_getinfo(L, "Snl", &ar);
  515.     switch (*ar.namewhat) {
  516.       case 'g':  case 'l':  /* global, local */
  517.         sprintf(buff, "function `%.50s'", ar.name);
  518.         break;
  519.       case 'f':  /* field */
  520.         sprintf(buff, "method `%.50s'", ar.name);
  521.         break;
  522.       case 't':  /* tag method */
  523.         sprintf(buff, "`%.50s' tag method", ar.name);
  524.         break;
  525.       default: {
  526.         if (*ar.what == 'm')  /* main? */
  527.           sprintf(buff, "main of %.70s", ar.short_src);
  528.         else if (*ar.what == 'C')  /* C function? */
  529.           sprintf(buff, "%.70s", ar.short_src);
  530.         else
  531.           sprintf(buff, "function <%d:%.70s>", ar.linedefined, ar.short_src);
  532.         ar.source = NULL;  /* do not print source again */
  533.       }
  534.     }
  535.     luaL_addstring(&b, buff);
  536.     if (ar.currentline > 0) {
  537.       sprintf(buff, " at line %d", ar.currentline);
  538.       luaL_addstring(&b, buff);
  539.     }
  540.     if (ar.source) {
  541.       sprintf(buff, " [%.70s]", ar.short_src);
  542.       luaL_addstring(&b, buff);
  543.     }
  544.     luaL_addstring(&b, "n");
  545.   }
  546.   luaL_pushresult(&b);
  547.   lua_getglobal(L, LUA_ALERT);
  548.   if (lua_isfunction(L, -1)) {  /* avoid loop if _ALERT is not defined */
  549.     lua_pushvalue(L, -2);  /* error message */
  550.     lua_rawcall(L, 1, 0);
  551.   }
  552.   return 0;
  553. }
  554. static const struct luaL_reg iolib[] = {
  555.   {LUA_ERRORMESSAGE, errorfb},
  556.   {"clock",     io_clock},
  557.   {"date",     io_date},
  558.   {"debug",    io_debug},
  559.   {"execute",  io_execute},
  560.   {"exit",     io_exit},
  561.   {"getenv",   io_getenv},
  562.   {"remove",   io_remove},
  563.   {"rename",   io_rename},
  564.   {"setlocale", setloc},
  565.   {"tmpname",   io_tmpname}
  566. };
  567. static const struct luaL_reg iolibtag[] = {
  568.   {"appendto", io_appendto},
  569.   {"closefile",   io_close},
  570.   {"flush",     io_flush},
  571.   {"openfile",   io_open},
  572.   {"read",     io_read},
  573.   {"readfrom", io_readfrom},
  574.   {"seek",     io_seek},
  575.   {"write",    io_write},
  576.   {"writeto",  io_writeto}
  577. };
  578. static void openwithcontrol (lua_State *L) {
  579.   IOCtrl *ctrl = (IOCtrl *)lua_newuserdata(L, sizeof(IOCtrl));
  580.   unsigned int i;
  581.   ctrl->iotag = lua_newtag(L);
  582.   ctrl->closedtag = lua_newtag(L);
  583.   for (i=0; i<sizeof(iolibtag)/sizeof(iolibtag[0]); i++) {
  584.     /* put `ctrl' as upvalue for these functions */
  585.     lua_pushvalue(L, -1);
  586.     lua_pushcclosure(L, iolibtag[i].func, 1);
  587.     lua_setglobal(L, iolibtag[i].name);
  588.   }
  589.   /* create references to variable names */
  590.   lua_pushstring(L, filenames[INFILE]);
  591.   ctrl->ref[INFILE] = lua_ref(L, 1);
  592.   lua_pushstring(L, filenames[OUTFILE]);
  593.   ctrl->ref[OUTFILE] = lua_ref(L, 1);
  594.   /* predefined file handles */
  595.   setfile(L, ctrl, stdin, INFILE);
  596.   setfile(L, ctrl, stdout, OUTFILE);
  597.   setfilebyname(L, ctrl, stdin, "_STDIN");
  598.   setfilebyname(L, ctrl, stdout, "_STDOUT");
  599.   setfilebyname(L, ctrl, stderr, "_STDERR");
  600.   /* close files when collected */
  601.   lua_pushcclosure(L, file_collect, 1);  /* pops `ctrl' from stack */
  602.   lua_settagmethod(L, ctrl->iotag, "gc");
  603. }
  604. LUALIB_API void lua_iolibopen (lua_State *L) {
  605.   luaL_openl(L, iolib);
  606.   openwithcontrol(L);
  607. }