aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-03-20 16:13:45 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2000-03-20 16:13:45 -0300
commit67592998809bf5816e2256409b384a712270c7b2 (patch)
tree440bddae0ed82280b4f17096242141964b7e6657
parentda7eb34cd621325066df3e99a9af39fa0d036a85 (diff)
downloadlua-67592998809bf5816e2256409b384a712270c7b2.tar.gz
lua-67592998809bf5816e2256409b384a712270c7b2.tar.bz2
lua-67592998809bf5816e2256409b384a712270c7b2.zip
new implementation for handling I/O tags + setglobal TM for tracing
changes in _INPUT/_OUTPUT
-rw-r--r--liolib.c256
1 files changed, 136 insertions, 120 deletions
diff --git a/liolib.c b/liolib.c
index b65d5ae4..829469e6 100644
--- a/liolib.c
+++ b/liolib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: liolib.c,v 1.57 2000/02/08 16:34:31 roberto Exp roberto $ 2** $Id: liolib.c,v 1.58 2000/03/03 14:58:26 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*/
@@ -35,16 +35,6 @@
35#endif 35#endif
36 36
37 37
38#define IOTAG 1
39
40#define FIRSTARG 2 /* 1st is upvalue */
41
42#define CLOSEDTAG(L, tag) ((tag)-1) /* assume that CLOSEDTAG = iotag-1 */
43
44
45#define FINPUT "_INPUT"
46#define FOUTPUT "_OUTPUT"
47
48 38
49#ifdef POPEN 39#ifdef POPEN
50/* FILE *popen(); 40/* FILE *popen();
@@ -57,6 +47,42 @@ int pclose(); */
57#endif 47#endif
58 48
59 49
50#define INFILE 0
51#define OUTFILE 1
52
53typedef struct IOCtrl {
54 FILE *file[2]; /* values of _INPUT and _OUTPUT */
55 int iotag; /* tag for file handles */
56 int closedtag; /* tag for closed handles */
57} IOCtrl;
58
59
60
61static const char *const filenames[] = {"_INPUT", "_OUTPUT", NULL};
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_pushobject(L, newvalue);
77 lua_rawsetglobal(L, varname);
78}
79
80
81static void ctrl_collect (lua_State *L) {
82 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
83 free(ctrl);
84}
85
60 86
61static void pushresult (lua_State *L, int i) { 87static void pushresult (lua_State *L, int i) {
62 if (i) 88 if (i)
@@ -75,18 +101,13 @@ static void pushresult (lua_State *L, int i) {
75** ======================================================= 101** =======================================================
76*/ 102*/
77 103
78static int gettag (lua_State *L) {
79 return (int)lua_getnumber(L, lua_getparam(L, IOTAG));
80}
81
82 104
83static FILE *gethandle (lua_State *L, lua_Object f) { 105static FILE *gethandle (lua_State *L, IOCtrl *ctrl, lua_Object f) {
84 if (lua_isuserdata(L, f)) { 106 if (lua_isuserdata(L, f)) {
85 int ftag = lua_tag(L, f); 107 int ftag = lua_tag(L, f);
86 int iotag = gettag(L); 108 if (ftag == ctrl->iotag)
87 if (ftag == iotag)
88 return (FILE *)lua_getuserdata(L, f); 109 return (FILE *)lua_getuserdata(L, f);
89 if (ftag == CLOSEDTAG(L, iotag)) 110 else if (ftag == ctrl->closedtag)
90 lua_error(L, "cannot access a closed file"); 111 lua_error(L, "cannot access a closed file");
91 /* else go through */ 112 /* else go through */
92 } 113 }
@@ -94,127 +115,110 @@ static FILE *gethandle (lua_State *L, lua_Object f) {
94} 115}
95 116
96 117
97static FILE *getfilebyname (lua_State *L, const char *name) { 118static FILE *getnonullfile (lua_State *L, IOCtrl *ctrl, int arg) {
98 FILE *handle = gethandle(L, lua_rawgetglobal(L, name)); 119 FILE *f = gethandle(L, ctrl, lua_getparam(L, arg));
99 if (!handle)
100 luaL_verror(L, "`%.50s' is not a file handle", name);
101 return handle;
102}
103
104
105static FILE *getfile (lua_State *L, int arg) {
106 return gethandle(L, lua_getparam(L, arg));
107}
108
109
110static FILE *getnonullfile (lua_State *L, int arg) {
111 FILE *f = getfile(L, arg);
112 luaL_arg_check(L, f, arg, "invalid file handle"); 120 luaL_arg_check(L, f, arg, "invalid file handle");
113 return f; 121 return f;
114} 122}
115 123
116 124
117static FILE *getfileparam (lua_State *L, const char *name, int *arg) { 125static FILE *getfileparam (lua_State *L, IOCtrl *ctrl, int *arg, int inout) {
118 FILE *f = getfile(L, *arg); 126 FILE *f = gethandle(L, ctrl, lua_getparam(L, *arg));
119 if (f) { 127 if (f) {
120 (*arg)++; 128 (*arg)++;
121 return f; 129 return f;
122 } 130 }
123 else 131 else
124 return getfilebyname(L, name); 132 return ctrl->file[inout];
125} 133}
126 134
127 135
128static int closefile (lua_State *L, FILE *f) { 136static void setfilebyname (lua_State *L, IOCtrl *ctrl, FILE *f,
129 if (f == stdin || f == stdout) 137 const char *name) {
130 return 1; 138 lua_pushusertag(L, f, ctrl->iotag);
131 else { 139 lua_setglobal(L, name);
132 int tag = gettag(L);
133 lua_pushusertag(L, f, tag);
134 lua_settag(L, CLOSEDTAG(L, tag));
135 return (CLOSEFILE(L, f) == 0);
136 }
137} 140}
138 141
139 142
140static void io_close (lua_State *L) { 143static void setfile (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) {
141 pushresult(L, closefile(L, getnonullfile(L, FIRSTARG))); 144 ctrl->file[inout] = f;
145 lua_pushusertag(L, f, ctrl->iotag);
146 lua_setglobal(L, filenames[inout]);
142} 147}
143 148
144 149
145static void gc_close (lua_State *L) { 150static void setreturn (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) {
146 FILE *f = getnonullfile(L, FIRSTARG); 151 if (f == NULL)
147 if (f != stdin && f != stdout && f != stderr) { 152 pushresult(L, 0);
148 CLOSEFILE(L, f); 153 else {
154 setfile(L, ctrl, f, inout);
155 lua_pushusertag(L, f, ctrl->iotag);
149 } 156 }
150} 157}
151 158
152 159
153static void io_open (lua_State *L) { 160static int closefile (lua_State *L, IOCtrl *ctrl, FILE *f) {
154 FILE *f = fopen(luaL_check_string(L, FIRSTARG), luaL_check_string(L, FIRSTARG+1)); 161 if (f == stdin || f == stdout)
155 if (f) lua_pushusertag(L, f, gettag(L)); 162 return 1;
156 else pushresult(L, 0); 163 else {
164 if (f == ctrl->file[INFILE])
165 setfile(L, ctrl, stdin, INFILE);
166 else if (f == ctrl->file[OUTFILE])
167 setfile(L, ctrl, stdout, OUTFILE);
168 lua_pushusertag(L, f, ctrl->iotag);
169 lua_settag(L, ctrl->closedtag);
170 return (CLOSEFILE(L, f) == 0);
171 }
157} 172}
158 173
159 174
160static void setfile (lua_State *L, FILE *f, const char *name, int tag) { 175static void io_close (lua_State *L) {
161 lua_pushusertag(L, f, tag); 176 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
162 lua_setglobal(L, name); 177 pushresult(L, closefile(L, ctrl, getnonullfile(L, ctrl, 2)));
163} 178}
164 179
165 180
166static void setreturn (lua_State *L, FILE *f, const char *name) { 181static void io_open (lua_State *L) {
167 if (f == NULL) 182 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
168 pushresult(L, 0); 183 FILE *f = fopen(luaL_check_string(L, 2), luaL_check_string(L, 3));
169 else { 184 if (f) lua_pushusertag(L, f, ctrl->iotag);
170 int tag = gettag(L); 185 else pushresult(L, 0);
171 setfile(L, f, name, tag);
172 lua_pushusertag(L, f, tag);
173 }
174} 186}
175 187
176 188
177static void io_readfrom (lua_State *L) { 189
190static void io_fromto (lua_State *L, int inout, const char *mode) {
191 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
192 lua_Object f = lua_getparam(L, 2);
178 FILE *current; 193 FILE *current;
179 lua_Object f = lua_getparam(L, FIRSTARG);
180 if (f == LUA_NOOBJECT) { 194 if (f == LUA_NOOBJECT) {
181 if (closefile(L, getfilebyname(L, FINPUT))) 195 pushresult(L, closefile(L, ctrl, ctrl->file[inout]));
182 current = stdin; 196 return;
183 else
184 current = NULL; /* to signal error */
185 } 197 }
186 else if (lua_tag(L, f) == gettag(L)) /* deprecated option */ 198 else if (lua_tag(L, f) == ctrl->iotag) /* deprecated option */
187 current = (FILE *)lua_getuserdata(L, f); 199 current = (FILE *)lua_getuserdata(L, f);
188 else { 200 else {
189 const char *s = luaL_check_string(L, FIRSTARG); 201 const char *s = luaL_check_string(L, 2);
190 current = (*s == '|') ? popen(s+1, "r") : fopen(s, "r"); 202 current = (*s == '|') ? popen(s+1, mode) : fopen(s, mode);
191 } 203 }
192 setreturn(L, current, FINPUT); 204 setreturn(L, ctrl, current, inout);
205}
206
207
208static void io_readfrom (lua_State *L) {
209 io_fromto(L, INFILE, "r");
193} 210}
194 211
195 212
196static void io_writeto (lua_State *L) { 213static void io_writeto (lua_State *L) {
197 FILE *current; 214 io_fromto(L, OUTFILE, "w");
198 lua_Object f = lua_getparam(L, FIRSTARG);
199 if (f == LUA_NOOBJECT) {
200 if (closefile(L, getfilebyname(L, FOUTPUT)))
201 current = stdout;
202 else
203 current = NULL; /* to signal error */
204 }
205 else if (lua_tag(L, f) == gettag(L)) /* deprecated option */
206 current = (FILE *)lua_getuserdata(L, f);
207 else {
208 const char *s = luaL_check_string(L, FIRSTARG);
209 current = (*s == '|') ? popen(s+1,"w") : fopen(s, "w");
210 }
211 setreturn(L, current, FOUTPUT);
212} 215}
213 216
214 217
215static void io_appendto (lua_State *L) { 218static void io_appendto (lua_State *L) {
216 FILE *current = fopen(luaL_check_string(L, FIRSTARG), "a"); 219 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
217 setreturn(L, current, FOUTPUT); 220 FILE *current = fopen(luaL_check_string(L, 2), "a");
221 setreturn(L, ctrl, current, OUTFILE);
218} 222}
219 223
220 224
@@ -348,8 +352,9 @@ static int read_chars (lua_State *L, FILE *f, int n) {
348 352
349 353
350static void io_read (lua_State *L) { 354static void io_read (lua_State *L) {
351 int arg = FIRSTARG; 355 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
352 FILE *f = getfileparam(L, FINPUT, &arg); 356 int arg = 2;
357 FILE *f = getfileparam(L, ctrl, &arg, INFILE);
353 lua_Object op = lua_getparam(L, arg); 358 lua_Object op = lua_getparam(L, arg);
354 do { /* repeat for each part */ 359 do { /* repeat for each part */
355 long l; 360 long l;
@@ -393,8 +398,9 @@ static void io_read (lua_State *L) {
393 398
394 399
395static void io_write (lua_State *L) { 400static void io_write (lua_State *L) {
396 int arg = FIRSTARG; 401 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
397 FILE *f = getfileparam(L, FOUTPUT, &arg); 402 int arg = 2;
403 FILE *f = getfileparam(L, ctrl, &arg, OUTFILE);
398 int status = 1; 404 int status = 1;
399 lua_Object o; 405 lua_Object o;
400 while ((o = lua_getparam(L, arg)) != LUA_NOOBJECT) { 406 while ((o = lua_getparam(L, arg)) != LUA_NOOBJECT) {
@@ -416,10 +422,11 @@ static void io_write (lua_State *L) {
416static void io_seek (lua_State *L) { 422static void io_seek (lua_State *L) {
417 static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; 423 static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
418 static const char *const modenames[] = {"set", "cur", "end", NULL}; 424 static const char *const modenames[] = {"set", "cur", "end", NULL};
419 FILE *f = getnonullfile(L, FIRSTARG); 425 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
420 int op = luaL_findstring(luaL_opt_string(L, FIRSTARG+1, "cur"), modenames); 426 FILE *f = getnonullfile(L, ctrl, 2);
421 long offset = luaL_opt_long(L, FIRSTARG+2, 0); 427 int op = luaL_findstring(luaL_opt_string(L, 3, "cur"), modenames);
422 luaL_arg_check(L, op != -1, FIRSTARG+1, "invalid mode"); 428 long offset = luaL_opt_long(L, 4, 0);
429 luaL_arg_check(L, op != -1, 3, "invalid mode");
423 op = fseek(f, offset, mode[op]); 430 op = fseek(f, offset, mode[op]);
424 if (op) 431 if (op)
425 pushresult(L, 0); /* error */ 432 pushresult(L, 0); /* error */
@@ -429,9 +436,10 @@ static void io_seek (lua_State *L) {
429 436
430 437
431static void io_flush (lua_State *L) { 438static void io_flush (lua_State *L) {
432 FILE *f = getfile(L, FIRSTARG); 439 IOCtrl *ctrl = (IOCtrl *)lua_getuserdata(L, lua_getparam(L, 1));
433 luaL_arg_check(L, f || lua_getparam(L, FIRSTARG) == LUA_NOOBJECT, FIRSTARG, 440 lua_Object of = lua_getparam(L, 2);
434 "invalid file handle"); 441 FILE *f = gethandle(L, ctrl, of);
442 luaL_arg_check(L, f || of == LUA_NOOBJECT, 2, "invalid file handle");
435 pushresult(L, fflush(f) == 0); 443 pushresult(L, fflush(f) == 0);
436} 444}
437 445
@@ -604,30 +612,38 @@ static const struct luaL_reg iolibtag[] = {
604}; 612};
605 613
606 614
607static void openwithtags (lua_State *L) { 615static void openwithcontrol (lua_State *L) {
616 IOCtrl *ctrl = (IOCtrl *)malloc(sizeof(IOCtrl));
608 unsigned int i; 617 unsigned int i;
609 int iotag = lua_newtag(L); 618 int ctrltag = lua_newtag(L);
610 lua_newtag(L); /* alloc CLOSEDTAG: assume that CLOSEDTAG = iotag-1 */ 619 ctrl->iotag = lua_newtag(L);
620 ctrl->closedtag = lua_newtag(L);
611 for (i=0; i<sizeof(iolibtag)/sizeof(iolibtag[0]); i++) { 621 for (i=0; i<sizeof(iolibtag)/sizeof(iolibtag[0]); i++) {
612 /* put iotag as upvalue for these functions */ 622 /* put `ctrl' as upvalue for these functions */
613 lua_pushnumber(L, iotag); 623 lua_pushusertag(L, ctrl, ctrltag);
614 lua_pushcclosure(L, iolibtag[i].func, 1); 624 lua_pushcclosure(L, iolibtag[i].func, 1);
615 lua_setglobal(L, iolibtag[i].name); 625 lua_setglobal(L, iolibtag[i].name);
616 } 626 }
617 /* predefined file handles */ 627 /* predefined file handles */
618 setfile(L, stdin, FINPUT, iotag); 628 ctrl->file[INFILE] = stdin;
619 setfile(L, stdout, FOUTPUT, iotag); 629 setfile(L, ctrl, stdin, INFILE);
620 setfile(L, stdin, "_STDIN", iotag); 630 ctrl->file[OUTFILE] = stdout;
621 setfile(L, stdout, "_STDOUT", iotag); 631 setfile(L, ctrl, stdout, OUTFILE);
622 setfile(L, stderr, "_STDERR", iotag); 632 setfilebyname(L, ctrl, stdin, "_STDIN");
623 /* close file when collected */ 633 setfilebyname(L, ctrl, stdout, "_STDOUT");
624 lua_pushnumber(L, iotag); 634 setfilebyname(L, ctrl, stderr, "_STDERR");
625 lua_pushcclosure(L, gc_close, 1); 635 /* change file when assigned */
626 lua_settagmethod(L, iotag, "gc"); 636 lua_pushusertag(L, ctrl, ctrltag);
637 lua_pushcclosure(L, atribTM, 1);
638 lua_settagmethod(L, ctrl->iotag, "setglobal");
639 /* delete `ctrl' when collected */
640 lua_pushusertag(L, ctrl, ctrltag);
641 lua_pushcclosure(L, ctrl_collect, 1);
642 lua_settagmethod(L, ctrltag, "gc");
627} 643}
628 644
629void lua_iolibopen (lua_State *L) { 645void lua_iolibopen (lua_State *L) {
630 luaL_openl(L, iolib); 646 luaL_openl(L, iolib);
631 openwithtags(L); 647 openwithcontrol(L);
632} 648}
633 649