aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--liolib.c112
1 files changed, 46 insertions, 66 deletions
diff --git a/liolib.c b/liolib.c
index b92e809d..dc432b40 100644
--- a/liolib.c
+++ b/liolib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: liolib.c,v 1.69 2000/08/09 19:16:57 roberto Exp roberto $ 2** $Id: liolib.c,v 1.70 2000/08/14 19:10:14 roberto Exp roberto $
3** Standard I/O (and system) library 3** Standard I/O (and system) library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -51,39 +51,14 @@ int pclose(); */
51#define OUTFILE 1 51#define OUTFILE 1
52 52
53typedef struct IOCtrl { 53typedef struct IOCtrl {
54 FILE *file[2]; /* values of _INPUT and _OUTPUT */ 54 int ref[2]; /* ref for strings _INPUT/_OUTPUT */
55 int iotag; /* tag for file handles */ 55 int iotag; /* tag for file handles */
56 int closedtag; /* tag for closed handles */ 56 int closedtag; /* tag for closed handles */
57} IOCtrl; 57} IOCtrl;
58 58
59 59
60 60
61static const char *const filenames[] = {"_INPUT", "_OUTPUT", NULL}; 61static const char *const filenames[] = {"_INPUT", "_OUTPUT"};
62
63
64static void atribTM (lua_State *L) {
65 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
66 const char *varname = luaL_check_string(L, 2);
67 lua_Object newvalue = lua_getparam(L, 4);
68 int inout;
69 if ((inout = luaL_findstring(varname, filenames)) != -1) {
70 if (lua_tag(L, newvalue) != ctrl->iotag)
71 luaL_verror(L, "%.20s value must be a valid file handle",
72 filenames[inout]);
73 ctrl->file[inout] = (FILE *)lua_getuserdata(L, newvalue);
74 }
75 /* set the actual variable */
76 lua_pushglobals(L);
77 lua_pushstring(L, varname);
78 lua_pushobject(L, newvalue);
79 lua_rawset(L);
80}
81
82
83static void ctrl_collect (lua_State *L) {
84 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
85 free(ctrl);
86}
87 62
88 63
89static void pushresult (lua_State *L, int i) { 64static void pushresult (lua_State *L, int i) {
@@ -105,10 +80,11 @@ static void pushresult (lua_State *L, int i) {
105 80
106 81
107static FILE *gethandle (lua_State *L, IOCtrl *ctrl, lua_Object f) { 82static FILE *gethandle (lua_State *L, IOCtrl *ctrl, lua_Object f) {
108 if (lua_isuserdata(L, f)) { 83 void *p = lua_getuserdata(L, f);
84 if (p != NULL) { /* is `f' a userdata ? */
109 int ftag = lua_tag(L, f); 85 int ftag = lua_tag(L, f);
110 if (ftag == ctrl->iotag) 86 if (ftag == ctrl->iotag) /* does it have the correct tag? */
111 return (FILE *)lua_getuserdata(L, f); 87 return (FILE *)p;
112 else if (ftag == ctrl->closedtag) 88 else if (ftag == ctrl->closedtag)
113 lua_error(L, "cannot access a closed file"); 89 lua_error(L, "cannot access a closed file");
114 /* else go through */ 90 /* else go through */
@@ -124,14 +100,15 @@ static FILE *getnonullfile (lua_State *L, IOCtrl *ctrl, int arg) {
124} 100}
125 101
126 102
127static FILE *getfileparam (lua_State *L, IOCtrl *ctrl, int *arg, int inout) { 103static FILE *getfilebyref (lua_State *L, IOCtrl *ctrl, int inout) {
128 FILE *f = gethandle(L, ctrl, lua_getparam(L, *arg)); 104 FILE *f;
129 if (f) { 105 lua_pushglobals(L);
130 (*arg)++; 106 lua_pushref(L, ctrl->ref[inout]);
131 return f; 107 f = gethandle(L, ctrl, lua_rawget(L));
132 } 108 if (f == NULL)
133 else 109 luaL_verror(L, "global variable `%.10s' is not a file handle",
134 return ctrl->file[inout]; 110 filenames[inout]);
111 return f;
135} 112}
136 113
137 114
@@ -142,11 +119,7 @@ static void setfilebyname (lua_State *L, IOCtrl *ctrl, FILE *f,
142} 119}
143 120
144 121
145static void setfile (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) { 122#define setfile(L,ctrl,f,inout) (setfilebyname(L,ctrl,f,filenames[inout]))
146 ctrl->file[inout] = f;
147 lua_pushusertag(L, f, ctrl->iotag);
148 lua_setglobal(L, filenames[inout]);
149}
150 123
151 124
152static void setreturn (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) { 125static void setreturn (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) {
@@ -163,10 +136,6 @@ static int closefile (lua_State *L, IOCtrl *ctrl, FILE *f) {
163 if (f == stdin || f == stdout || f == stderr) 136 if (f == stdin || f == stdout || f == stderr)
164 return 1; 137 return 1;
165 else { 138 else {
166 if (f == ctrl->file[INFILE])
167 setfile(L, ctrl, stdin, INFILE);
168 else if (f == ctrl->file[OUTFILE])
169 setfile(L, ctrl, stdout, OUTFILE);
170 lua_pushusertag(L, f, ctrl->iotag); 139 lua_pushusertag(L, f, ctrl->iotag);
171 lua_settag(L, ctrl->closedtag); 140 lua_settag(L, ctrl->closedtag);
172 return (CLOSEFILE(L, f) == 0); 141 return (CLOSEFILE(L, f) == 0);
@@ -182,9 +151,17 @@ static void io_close (lua_State *L) {
182 151
183static void file_collect (lua_State *L) { 152static void file_collect (lua_State *L) {
184 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1)); 153 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
185 FILE *f = getnonullfile(L, ctrl, 2); 154 if (ctrl == (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 2))) {
186 if (f != stdin && f != stdout && f != stderr) 155 /* collectig `ctrl' itself */
187 CLOSEFILE(L, f); 156 lua_unref(L, ctrl->ref[INFILE]);
157 lua_unref(L, ctrl->ref[OUTFILE]);
158 free(ctrl);
159 }
160 else { /* collecting a file: Close it */
161 FILE *f = getnonullfile(L, ctrl, 2);
162 if (f != stdin && f != stdout && f != stderr)
163 CLOSEFILE(L, f);
164 }
188} 165}
189 166
190 167
@@ -202,8 +179,8 @@ static void io_fromto (lua_State *L, int inout, const char *mode) {
202 lua_Object f = lua_getparam(L, 2); 179 lua_Object f = lua_getparam(L, 2);
203 FILE *current; 180 FILE *current;
204 if (f == LUA_NOOBJECT) { 181 if (f == LUA_NOOBJECT) {
205 pushresult(L, closefile(L, ctrl, ctrl->file[inout])); 182 closefile(L, ctrl, getfilebyref(L, ctrl, inout));
206 return; 183 current = (inout == 0) ? stdin : stdout;
207 } 184 }
208 else if (lua_tag(L, f) == ctrl->iotag) /* deprecated option */ 185 else if (lua_tag(L, f) == ctrl->iotag) /* deprecated option */
209 current = (FILE *)lua_getuserdata(L, f); 186 current = (FILE *)lua_getuserdata(L, f);
@@ -368,8 +345,11 @@ static int read_chars (lua_State *L, FILE *f, size_t n) {
368static void io_read (lua_State *L) { 345static void io_read (lua_State *L) {
369 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1)); 346 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
370 int arg = 2; 347 int arg = 2;
371 FILE *f = getfileparam(L, ctrl, &arg, INFILE); 348 lua_Object op;
372 lua_Object op = lua_getparam(L, arg); 349 FILE *f = gethandle(L, ctrl, lua_getparam(L, arg));
350 if (f) arg++;
351 else f = getfilebyref(L, ctrl, INFILE); /* get _INPUT */
352 op = lua_getparam(L, arg);
373 do { /* repeat for each part */ 353 do { /* repeat for each part */
374 size_t l; 354 size_t l;
375 int success; 355 int success;
@@ -414,9 +394,11 @@ static void io_read (lua_State *L) {
414static void io_write (lua_State *L) { 394static void io_write (lua_State *L) {
415 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1)); 395 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
416 int arg = 2; 396 int arg = 2;
417 FILE *f = getfileparam(L, ctrl, &arg, OUTFILE);
418 int status = 1; 397 int status = 1;
419 lua_Object o; 398 lua_Object o;
399 FILE *f = gethandle(L, ctrl, lua_getparam(L, arg));
400 if (f) arg++;
401 else f = getfilebyref(L, ctrl, OUTFILE); /* get _OUTPUT */
420 while ((o = lua_getparam(L, arg)) != LUA_NOOBJECT) { 402 while ((o = lua_getparam(L, arg)) != LUA_NOOBJECT) {
421 if (lua_type(L, o)[2] == 'm') { /* nuMber? */ /* LUA_NUMBER */ 403 if (lua_type(L, o)[2] == 'm') { /* nuMber? */ /* LUA_NUMBER */
422 /* optimization: could be done exactly as for strings */ 404 /* optimization: could be done exactly as for strings */
@@ -641,28 +623,26 @@ static void openwithcontrol (lua_State *L) {
641 lua_pushcclosure(L, iolibtag[i].func, 1); 623 lua_pushcclosure(L, iolibtag[i].func, 1);
642 lua_setglobal(L, iolibtag[i].name); 624 lua_setglobal(L, iolibtag[i].name);
643 } 625 }
626 /* create references to variable names */
627 lua_pushstring(L, filenames[INFILE]);
628 ctrl->ref[INFILE] = lua_ref(L, 1);
629 lua_pushstring(L, filenames[OUTFILE]);
630 ctrl->ref[OUTFILE] = lua_ref(L, 1);
644 /* predefined file handles */ 631 /* predefined file handles */
645 ctrl->file[INFILE] = stdin;
646 setfile(L, ctrl, stdin, INFILE); 632 setfile(L, ctrl, stdin, INFILE);
647 ctrl->file[OUTFILE] = stdout;
648 setfile(L, ctrl, stdout, OUTFILE); 633 setfile(L, ctrl, stdout, OUTFILE);
649 setfilebyname(L, ctrl, stdin, "_STDIN"); 634 setfilebyname(L, ctrl, stdin, "_STDIN");
650 setfilebyname(L, ctrl, stdout, "_STDOUT"); 635 setfilebyname(L, ctrl, stdout, "_STDOUT");
651 setfilebyname(L, ctrl, stderr, "_STDERR"); 636 setfilebyname(L, ctrl, stderr, "_STDERR");
652 /* change file when assigned */
653 lua_pushusertag(L, ctrl, ctrltag);
654 lua_pushcclosure(L, atribTM, 1);
655 lua_settagmethod(L, ctrl->iotag, "setglobal");
656 /* delete `ctrl' when collected */ 637 /* delete `ctrl' when collected */
657 lua_pushusertag(L, ctrl, ctrltag); 638 lua_pushusertag(L, ctrl, ctrltag);
658 lua_pushcclosure(L, ctrl_collect, 1); 639 lua_pushcclosure(L, file_collect, 1);
659 lua_settagmethod(L, ctrltag, "gc"); 640 lua_settagmethod(L, ctrltag, "gc");
660 /* close files when collected */ 641 /* close files when collected */
661 lua_pushusertag(L, ctrl, ctrltag); 642 lua_copytagmethods(L, ctrl->iotag, ctrltag);
662 lua_pushcclosure(L, file_collect, 1);
663 lua_settagmethod(L, ctrl->iotag, "gc");
664} 643}
665 644
645
666void lua_iolibopen (lua_State *L) { 646void lua_iolibopen (lua_State *L) {
667 luaL_openl(L, iolib); 647 luaL_openl(L, iolib);
668 openwithcontrol(L); 648 openwithcontrol(L);