diff options
Diffstat (limited to 'liolib.c')
-rw-r--r-- | liolib.c | 112 |
1 files changed, 46 insertions, 66 deletions
@@ -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 | ||
53 | typedef struct IOCtrl { | 53 | typedef 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 | ||
61 | static const char *const filenames[] = {"_INPUT", "_OUTPUT", NULL}; | 61 | static const char *const filenames[] = {"_INPUT", "_OUTPUT"}; |
62 | |||
63 | |||
64 | static 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 | |||
83 | static 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 | ||
89 | static void pushresult (lua_State *L, int i) { | 64 | static void pushresult (lua_State *L, int i) { |
@@ -105,10 +80,11 @@ static void pushresult (lua_State *L, int i) { | |||
105 | 80 | ||
106 | 81 | ||
107 | static FILE *gethandle (lua_State *L, IOCtrl *ctrl, lua_Object f) { | 82 | static 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 | ||
127 | static FILE *getfileparam (lua_State *L, IOCtrl *ctrl, int *arg, int inout) { | 103 | static 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 | ||
145 | static 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 | ||
152 | static void setreturn (lua_State *L, IOCtrl *ctrl, FILE *f, int inout) { | 125 | static 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 | ||
183 | static void file_collect (lua_State *L) { | 152 | static 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) { | |||
368 | static void io_read (lua_State *L) { | 345 | static 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) { | |||
414 | static void io_write (lua_State *L) { | 394 | static 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 | |||
666 | void lua_iolibopen (lua_State *L) { | 646 | void lua_iolibopen (lua_State *L) { |
667 | luaL_openl(L, iolib); | 647 | luaL_openl(L, iolib); |
668 | openwithcontrol(L); | 648 | openwithcontrol(L); |