diff options
Diffstat (limited to 'apps/plugins/lua/liolib.c')
-rw-r--r-- | apps/plugins/lua/liolib.c | 536 |
1 files changed, 156 insertions, 380 deletions
diff --git a/apps/plugins/lua/liolib.c b/apps/plugins/lua/liolib.c index a282dd1ac0..7a43915f20 100644 --- a/apps/plugins/lua/liolib.c +++ b/apps/plugins/lua/liolib.c | |||
@@ -1,21 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: liolib.c,v 2.112.1.1 2013/04/12 18:48:47 roberto Exp $ | 2 | ** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ |
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 | */ |
6 | 6 | ||
7 | 7 | ||
8 | /* | ||
9 | ** This definition must come before the inclusion of 'stdio.h'; it | ||
10 | ** should not affect non-POSIX systems | ||
11 | */ | ||
12 | #if !defined(_FILE_OFFSET_BITS) | ||
13 | #define _LARGEFILE_SOURCE 1 | ||
14 | #define _FILE_OFFSET_BITS 64 | ||
15 | #endif | ||
16 | |||
17 | |||
18 | #include <errno.h> | ||
19 | #include <stdio.h> | 8 | #include <stdio.h> |
20 | #include <stdlib.h> | 9 | #include <stdlib.h> |
21 | #include <string.h> | 10 | #include <string.h> |
@@ -30,111 +19,46 @@ | |||
30 | #include "rocklibc.h" | 19 | #include "rocklibc.h" |
31 | 20 | ||
32 | 21 | ||
33 | #if !defined(lua_checkmode) | ||
34 | |||
35 | /* | ||
36 | ** Check whether 'mode' matches '[rwa]%+?b?'. | ||
37 | ** Change this macro to accept other modes for 'fopen' besides | ||
38 | ** the standard ones. | ||
39 | */ | ||
40 | #define lua_checkmode(mode) \ | ||
41 | (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \ | ||
42 | (*mode != '+' || ++mode) && /* skip if char is '+' */ \ | ||
43 | (*mode != 'b' || ++mode) && /* skip if char is 'b' */ \ | ||
44 | (*mode == '\0')) | ||
45 | |||
46 | #endif | ||
47 | |||
48 | /* | ||
49 | ** {====================================================== | ||
50 | ** lua_popen spawns a new process connected to the current | ||
51 | ** one through the file streams. | ||
52 | ** ======================================================= | ||
53 | */ | ||
54 | |||
55 | #if !defined(lua_popen) /* { */ | ||
56 | |||
57 | #if defined(LUA_USE_POPEN) /* { */ | ||
58 | |||
59 | #define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) | ||
60 | #define lua_pclose(L,file) ((void)L, pclose(file)) | ||
61 | |||
62 | #elif defined(LUA_WIN) /* }{ */ | ||
63 | |||
64 | #define lua_popen(L,c,m) ((void)L, _popen(c,m)) | ||
65 | #define lua_pclose(L,file) ((void)L, _pclose(file)) | ||
66 | |||
67 | |||
68 | #else /* }{ */ | ||
69 | |||
70 | #define lua_popen(L,c,m) ((void)((void)c, m), \ | ||
71 | luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) | ||
72 | #define lua_pclose(L,file) ((void)((void)L, file), -1) | ||
73 | |||
74 | |||
75 | #endif /* } */ | ||
76 | |||
77 | #endif /* } */ | ||
78 | |||
79 | /* }====================================================== */ | ||
80 | |||
81 | |||
82 | /* | ||
83 | ** {====================================================== | ||
84 | ** lua_fseek: configuration for longer offsets | ||
85 | ** ======================================================= | ||
86 | */ | ||
87 | |||
88 | #if !defined(lua_fseek) && !defined(LUA_ANSI) /* { */ | ||
89 | |||
90 | #if defined(LUA_USE_POSIX) /* { */ | ||
91 | |||
92 | #define l_fseek(f,o,w) fseeko(f,o,w) | ||
93 | #define l_ftell(f) ftello(f) | ||
94 | #define l_seeknum off_t | ||
95 | |||
96 | #elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ | ||
97 | && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */ | ||
98 | /* Windows (but not DDK) and Visual C++ 2005 or higher */ | ||
99 | |||
100 | #define l_fseek(f,o,w) _fseeki64(f,o,w) | ||
101 | #define l_ftell(f) _ftelli64(f) | ||
102 | #define l_seeknum __int64 | ||
103 | |||
104 | #endif /* } */ | ||
105 | 22 | ||
106 | #endif /* } */ | 23 | #define IO_INPUT 1 |
107 | 24 | #define IO_OUTPUT 2 | |
108 | |||
109 | #if !defined(l_fseek) /* default definitions */ | ||
110 | #define l_fseek(f,o,w) fseek(f,o,w) | ||
111 | #define l_ftell(f) ftell(f) | ||
112 | #define l_seeknum long | ||
113 | #endif | ||
114 | |||
115 | /* }====================================================== */ | ||
116 | 25 | ||
117 | 26 | ||
118 | #define IO_PREFIX "_IO_" | 27 | static const char *const fnames[] = {"input", "output"}; |
119 | #define IO_INPUT (IO_PREFIX "input") | ||
120 | #define IO_OUTPUT (IO_PREFIX "output") | ||
121 | 28 | ||
122 | 29 | ||
123 | typedef luaL_Stream LStream; | 30 | static int pushresult (lua_State *L, int i, const char *filename) { |
124 | 31 | int en = errno; | |
32 | if (i) { | ||
33 | lua_pushboolean(L, 1); | ||
34 | return 1; | ||
35 | } | ||
36 | else { | ||
37 | lua_pushnil(L); | ||
38 | if (filename) | ||
39 | lua_pushfstring(L, "%s: %s", filename, strerror(en)); | ||
40 | else | ||
41 | lua_pushfstring(L, "%s", strerror(en)); | ||
42 | lua_pushinteger(L, 0); | ||
43 | return 3; | ||
44 | } | ||
45 | } | ||
125 | 46 | ||
126 | #define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) | ||
127 | 47 | ||
128 | #define isclosed(p) ((p)->closef == NULL) | 48 | static void fileerror (lua_State *L, int arg, const char *filename) { |
49 | lua_pushfstring(L, "%s: %s", filename, strerror(errno)); | ||
50 | luaL_argerror(L, arg, lua_tostring(L, -1)); | ||
51 | } | ||
129 | 52 | ||
130 | 53 | ||
131 | static int io_type (lua_State *L) { | 54 | static int io_type (lua_State *L) { |
132 | LStream *p; | 55 | void *ud; |
133 | luaL_checkany(L, 1); | 56 | luaL_checkany(L, 1); |
134 | p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); | 57 | ud = lua_touserdata(L, 1); |
135 | if (p == NULL) | 58 | lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); |
59 | if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) | ||
136 | lua_pushnil(L); /* not a file */ | 60 | lua_pushnil(L); /* not a file */ |
137 | else if (isclosed(p)) | 61 | else if (*((int *)ud) < 0) |
138 | lua_pushliteral(L, "closed file"); | 62 | lua_pushliteral(L, "closed file"); |
139 | else | 63 | else |
140 | lua_pushliteral(L, "file"); | 64 | lua_pushliteral(L, "file"); |
@@ -142,97 +66,76 @@ static int io_type (lua_State *L) { | |||
142 | } | 66 | } |
143 | 67 | ||
144 | 68 | ||
145 | static int f_tostring (lua_State *L) { | 69 | static int* tofile (lua_State *L) { |
146 | LStream *p = tolstream(L); | 70 | int *f = (int*) luaL_checkudata(L, 1, LUA_FILEHANDLE); |
147 | if (isclosed(p)) | 71 | if (*f < 0) |
148 | lua_pushliteral(L, "file (closed)"); | ||
149 | else | ||
150 | lua_pushfstring(L, "file (%p)", p->f); | ||
151 | return 1; | ||
152 | } | ||
153 | |||
154 | |||
155 | static FILE *tofile (lua_State *L) { | ||
156 | LStream *p = tolstream(L); | ||
157 | if (isclosed(p)) | ||
158 | luaL_error(L, "attempt to use a closed file"); | 72 | luaL_error(L, "attempt to use a closed file"); |
159 | lua_assert(p->f); | 73 | return f; |
160 | return p->f; | ||
161 | } | 74 | } |
162 | 75 | ||
163 | 76 | ||
77 | |||
164 | /* | 78 | /* |
165 | ** When creating file handles, always creates a `closed' file handle | 79 | ** When creating file handles, always creates a `closed' file handle |
166 | ** before opening the actual file; so, if there is a memory error, the | 80 | ** before opening the actual file; so, if there is a memory error, the |
167 | ** file is not left opened. | 81 | ** file is not left opened. |
168 | */ | 82 | */ |
169 | static LStream *newprefile (lua_State *L) { | 83 | static int* newfile (lua_State *L) { |
170 | LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); | 84 | int *pf = (int *)lua_newuserdata(L, sizeof(int)); |
171 | p->closef = NULL; /* mark file handle as 'closed' */ | 85 | *pf = -1; /* file handle is currently `closed' */ |
172 | luaL_setmetatable(L, LUA_FILEHANDLE); | 86 | luaL_getmetatable(L, LUA_FILEHANDLE); |
173 | return p; | 87 | lua_setmetatable(L, -2); |
88 | return pf; | ||
174 | } | 89 | } |
175 | 90 | ||
176 | 91 | ||
177 | static int aux_close (lua_State *L) { | 92 | /* |
178 | LStream *p = tolstream(L); | 93 | ** function to close regular files |
179 | lua_CFunction cf = p->closef; | 94 | */ |
180 | p->closef = NULL; /* mark stream as closed */ | 95 | static int io_fclose (lua_State *L) { |
181 | return (*cf)(L); /* close it */ | 96 | int *p = tofile(L); |
97 | int ok = (rb->close(*p) == 0); | ||
98 | *p = -1; | ||
99 | return pushresult(L, ok, NULL); | ||
182 | } | 100 | } |
183 | 101 | ||
184 | 102 | ||
185 | static int io_close (lua_State *L) { | 103 | static inline int aux_close (lua_State *L) { |
186 | if (lua_isnone(L, 1)) /* no argument? */ | 104 | return io_fclose(L); |
187 | lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ | ||
188 | tofile(L); /* make sure argument is an open stream */ | ||
189 | return aux_close(L); | ||
190 | } | 105 | } |
191 | 106 | ||
192 | 107 | ||
193 | static int f_gc (lua_State *L) { | 108 | static int io_close (lua_State *L) { |
194 | LStream *p = tolstream(L); | 109 | if (lua_isnone(L, 1)) |
195 | if (!isclosed(p) && p->f != NULL) | 110 | lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); |
196 | aux_close(L); /* ignore closed and incompletely open files */ | 111 | tofile(L); /* make sure argument is a file */ |
197 | return 0; | 112 | return aux_close(L); |
198 | } | ||
199 | |||
200 | |||
201 | /* | ||
202 | ** function to close regular files | ||
203 | */ | ||
204 | static int io_fclose (lua_State *L) { | ||
205 | LStream *p = tolstream(L); | ||
206 | int res = rb->close((int)p->f); | ||
207 | return luaL_fileresult(L, (res == 0), NULL); | ||
208 | } | 113 | } |
209 | 114 | ||
210 | 115 | ||
211 | static LStream *newfile (lua_State *L) { | 116 | static int io_gc (lua_State *L) { |
212 | LStream *p = newprefile(L); | 117 | int f = *(int*) luaL_checkudata(L, 1, LUA_FILEHANDLE); |
213 | p->f = NULL; | 118 | /* ignore closed files */ |
214 | p->closef = &io_fclose; | 119 | if (f >= 0) |
215 | return p; | 120 | aux_close(L); |
121 | return 0; | ||
216 | } | 122 | } |
217 | 123 | ||
218 | 124 | ||
219 | static void opencheck (lua_State *L, const char *fname, const char *mode) { | 125 | static int io_tostring (lua_State *L) { |
220 | LStream *p = newfile(L); | 126 | int f = *(int*) luaL_checkudata(L, 1, LUA_FILEHANDLE); |
221 | int flags = O_RDONLY; | 127 | if (f < 0) |
222 | if (strcmp(mode, "w") == 0) | 128 | lua_pushliteral(L, "file (closed)"); |
223 | flags = O_WRONLY; | 129 | else |
224 | p->f = (FILE*)rb->open(fname, flags); | 130 | lua_pushfstring(L, "file (%d)", f); |
225 | if (p->f == NULL) | 131 | return 1; |
226 | luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno)); | ||
227 | } | 132 | } |
228 | 133 | ||
229 | 134 | ||
230 | static int io_open (lua_State *L) { | 135 | static int io_open (lua_State *L) { |
231 | const char *filename = luaL_checkstring(L, 1); | 136 | const char *filename = luaL_checkstring(L, 1); |
232 | const char *mode = luaL_optstring(L, 2, "r"); | 137 | const char *mode = luaL_optstring(L, 2, "r"); |
233 | LStream *p = newfile(L); | 138 | int *pf = newfile(L); |
234 | const char *md = mode; /* to traverse/check mode */ | ||
235 | luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode"); | ||
236 | int flags = 0; | 139 | int flags = 0; |
237 | if(*(mode+1) == '+') { | 140 | if(*(mode+1) == '+') { |
238 | flags = O_RDWR; | 141 | flags = O_RDWR; |
@@ -255,117 +158,84 @@ static int io_open (lua_State *L) { | |||
255 | } | 158 | } |
256 | if((*mode == 'w' || *mode == 'a') && !rb->file_exists(filename)) | 159 | if((*mode == 'w' || *mode == 'a') && !rb->file_exists(filename)) |
257 | flags |= O_CREAT; | 160 | flags |= O_CREAT; |
258 | int pf = rb->open(filename, flags, 0666); | 161 | *pf = rb->open(filename, flags, 0666); |
259 | p->f = (FILE*)pf; | 162 | return (*pf < 0) ? pushresult(L, 0, filename) : 1; |
260 | return (pf < 0) ? luaL_fileresult(L, 0, filename) : 1; | ||
261 | } | 163 | } |
262 | 164 | ||
263 | 165 | ||
264 | #if 0 | 166 | static int* getiofile (lua_State *L, int findex) { |
265 | /* | 167 | int *f; |
266 | ** function to close 'popen' files | 168 | lua_rawgeti(L, LUA_ENVIRONINDEX, findex); |
267 | */ | 169 | f = (int *)lua_touserdata(L, -1); |
268 | static int io_pclose (lua_State *L) { | 170 | if (f == NULL || *f < 0) |
269 | LStream *p = tolstream(L); | 171 | luaL_error(L, "standard %s file is closed", fnames[findex - 1]); |
270 | return luaL_execresult(L, lua_pclose(L, p->f)); | 172 | return f; |
271 | } | 173 | } |
272 | 174 | ||
273 | 175 | ||
274 | static int io_popen (lua_State *L) { | 176 | static int g_iofile (lua_State *L, int f, int flags) { |
275 | const char *filename = luaL_checkstring(L, 1); | ||
276 | const char *mode = luaL_optstring(L, 2, "r"); | ||
277 | LStream *p = newprefile(L); | ||
278 | p->f = lua_popen(L, filename, mode); | ||
279 | p->closef = &io_pclose; | ||
280 | return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; | ||
281 | } | ||
282 | |||
283 | |||
284 | static int io_tmpfile (lua_State *L) { | ||
285 | LStream *p = newfile(L); | ||
286 | p->f = tmpfile(); | ||
287 | return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; | ||
288 | } | ||
289 | #endif | ||
290 | |||
291 | |||
292 | static FILE *getiofile (lua_State *L, const char *findex) { | ||
293 | LStream *p; | ||
294 | lua_getfield(L, LUA_REGISTRYINDEX, findex); | ||
295 | p = (LStream *)lua_touserdata(L, -1); | ||
296 | if (isclosed(p)) | ||
297 | luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX)); | ||
298 | return p->f; | ||
299 | } | ||
300 | |||
301 | |||
302 | static int g_iofile (lua_State *L, const char *f, const char *mode) { | ||
303 | if (!lua_isnoneornil(L, 1)) { | 177 | if (!lua_isnoneornil(L, 1)) { |
304 | const char *filename = lua_tostring(L, 1); | 178 | const char *filename = lua_tostring(L, 1); |
305 | if (filename) | 179 | if (filename) { |
306 | opencheck(L, filename, mode); | 180 | int *pf = newfile(L); |
181 | *pf = rb->open(filename, flags); | ||
182 | if (*pf < 0) | ||
183 | fileerror(L, 1, filename); | ||
184 | } | ||
307 | else { | 185 | else { |
308 | tofile(L); /* check that it's a valid file handle */ | 186 | tofile(L); /* check that it's a valid file handle */ |
309 | lua_pushvalue(L, 1); | 187 | lua_pushvalue(L, 1); |
310 | } | 188 | } |
311 | lua_setfield(L, LUA_REGISTRYINDEX, f); | 189 | lua_rawseti(L, LUA_ENVIRONINDEX, f); |
312 | } | 190 | } |
313 | /* return current value */ | 191 | /* return current value */ |
314 | lua_getfield(L, LUA_REGISTRYINDEX, f); | 192 | lua_rawgeti(L, LUA_ENVIRONINDEX, f); |
315 | return 1; | 193 | return 1; |
316 | } | 194 | } |
317 | 195 | ||
318 | 196 | ||
319 | static int io_input (lua_State *L) { | 197 | static int io_input (lua_State *L) { |
320 | return g_iofile(L, IO_INPUT, "r"); | 198 | return g_iofile(L, IO_INPUT, O_RDONLY); |
321 | } | 199 | } |
322 | 200 | ||
323 | 201 | ||
324 | static int io_output (lua_State *L) { | 202 | static int io_output (lua_State *L) { |
325 | return g_iofile(L, IO_OUTPUT, "w"); | 203 | return g_iofile(L, IO_OUTPUT, O_WRONLY); |
326 | } | 204 | } |
327 | 205 | ||
328 | 206 | ||
329 | static int io_readline (lua_State *L); | 207 | static int io_readline (lua_State *L); |
330 | 208 | ||
331 | 209 | ||
332 | static void aux_lines (lua_State *L, int toclose) { | 210 | static void aux_lines (lua_State *L, int idx, int toclose) { |
333 | int i; | 211 | lua_pushvalue(L, idx); |
334 | int n = lua_gettop(L) - 1; /* number of arguments to read */ | ||
335 | /* ensure that arguments will fit here and into 'io_readline' stack */ | ||
336 | luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options"); | ||
337 | lua_pushvalue(L, 1); /* file handle */ | ||
338 | lua_pushinteger(L, n); /* number of arguments to read */ | ||
339 | lua_pushboolean(L, toclose); /* close/not close file when finished */ | 212 | lua_pushboolean(L, toclose); /* close/not close file when finished */ |
340 | for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1); /* copy arguments */ | 213 | lua_pushcclosure(L, io_readline, 2); |
341 | lua_pushcclosure(L, io_readline, 3 + n); | ||
342 | } | 214 | } |
343 | 215 | ||
344 | 216 | ||
345 | static int f_lines (lua_State *L) { | 217 | static int f_lines (lua_State *L) { |
346 | tofile(L); /* check that it's a valid file handle */ | 218 | tofile(L); /* check that it's a valid file handle */ |
347 | aux_lines(L, 0); | 219 | aux_lines(L, 1, 0); |
348 | return 1; | 220 | return 1; |
349 | } | 221 | } |
350 | 222 | ||
351 | 223 | ||
352 | static int io_lines (lua_State *L) { | 224 | static int io_lines (lua_State *L) { |
353 | int toclose; | 225 | if (lua_isnoneornil(L, 1)) { /* no arguments? */ |
354 | if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ | 226 | /* will iterate over default input */ |
355 | if (lua_isnil(L, 1)) { /* no file name? */ | 227 | lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); |
356 | lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ | 228 | return f_lines(L); |
357 | lua_replace(L, 1); /* put it at index 1 */ | ||
358 | tofile(L); /* check that it's a valid file handle */ | ||
359 | toclose = 0; /* do not close it after iteration */ | ||
360 | } | 229 | } |
361 | else { /* open a new file */ | 230 | else { |
362 | const char *filename = luaL_checkstring(L, 1); | 231 | const char *filename = luaL_checkstring(L, 1); |
363 | opencheck(L, filename, "r"); | 232 | int *pf = newfile(L); |
364 | lua_replace(L, 1); /* put file at index 1 */ | 233 | *pf = rb->open(filename, O_RDONLY); |
365 | toclose = 1; /* close it after iteration */ | 234 | if (*pf < 0) |
235 | fileerror(L, 1, filename); | ||
236 | aux_lines(L, lua_gettop(L), 1); | ||
237 | return 1; | ||
366 | } | 238 | } |
367 | aux_lines(L, toclose); | ||
368 | return 1; | ||
369 | } | 239 | } |
370 | 240 | ||
371 | 241 | ||
@@ -375,89 +245,72 @@ static int io_lines (lua_State *L) { | |||
375 | ** ======================================================= | 245 | ** ======================================================= |
376 | */ | 246 | */ |
377 | 247 | ||
378 | 248 | static int read_number (lua_State *L, int *f) { | |
379 | static int read_number (lua_State *L, FILE *f) { | ||
380 | lua_Number d; | 249 | lua_Number d; |
381 | if (PREFIX(fscanf)(f, LUA_NUMBER_SCAN, &d) == 1) { | 250 | if (PREFIX(fscanf)(*f, LUA_NUMBER_SCAN, &d) == 1) { |
382 | lua_pushnumber(L, d); | 251 | lua_pushnumber(L, d); |
383 | return 1; | 252 | return 1; |
384 | } | 253 | } |
385 | else { | 254 | else return 0; /* read fails */ |
386 | lua_pushnil(L); /* "result" to be removed */ | ||
387 | return 0; /* read fails */ | ||
388 | } | ||
389 | } | 255 | } |
390 | 256 | ||
391 | 257 | ||
392 | static int test_eof (lua_State *L, FILE *f) { | 258 | static int test_eof (lua_State *L, int *f) { |
393 | ssize_t s = rb->lseek((int)f, 0, SEEK_CUR); | 259 | ssize_t s = rb->lseek(*f, 0, SEEK_CUR); |
394 | lua_pushlstring(L, NULL, 0); | 260 | lua_pushlstring(L, NULL, 0); |
395 | return s != rb->filesize((int)f); | 261 | return s != rb->filesize(*f); |
396 | } | 262 | } |
397 | 263 | ||
398 | 264 | ||
399 | /* Rockbox already defines read_line() */ | 265 | /* Rockbox already defines read_line() */ |
400 | static int _read_line (lua_State *L, FILE *f, int chop) { | 266 | static int _read_line (lua_State *L, int *f) { |
401 | luaL_Buffer b; | 267 | luaL_Buffer b; |
402 | luaL_buffinit(L, &b); | 268 | luaL_buffinit(L, &b); |
403 | for (;;) { | 269 | for (;;) { |
404 | size_t l; | 270 | size_t l; |
405 | size_t r; | 271 | size_t r; |
406 | char *p = luaL_prepbuffer(&b); | 272 | char *p = luaL_prepbuffer(&b); |
407 | r = rb->read_line((int)f, p, LUAL_BUFFERSIZE); | 273 | r = rb->read_line(*f, p, LUAL_BUFFERSIZE); |
408 | l = strlen(p); | 274 | l = strlen(p); |
409 | if (l == 0 || p[l-1] != '\n') | 275 | if (l == 0 || p[l-1] != '\n') |
410 | luaL_addsize(&b, l); | 276 | luaL_addsize(&b, l); |
411 | else { | 277 | else { |
412 | luaL_addsize(&b, l - chop); /* chop 'eol' if needed */ | 278 | luaL_addsize(&b, l - 1); /* do not include `eol' */ |
413 | luaL_pushresult(&b); /* close buffer */ | 279 | luaL_pushresult(&b); /* close buffer */ |
414 | return 1; /* read at least an `eol' */ | 280 | return 1; /* read at least an `eol' */ |
415 | } | 281 | } |
416 | if (r < LUAL_BUFFERSIZE) { /* eof? */ | 282 | if (r < LUAL_BUFFERSIZE) { /* eof? */ |
417 | luaL_pushresult(&b); /* close buffer */ | 283 | luaL_pushresult(&b); /* close buffer */ |
418 | return (lua_rawlen(L, -1) > 0); /* check whether read something */ | 284 | return (lua_objlen(L, -1) > 0); /* check whether read something */ |
419 | } | 285 | } |
420 | } | 286 | } |
421 | } | 287 | } |
422 | 288 | ||
423 | 289 | ||
424 | #define MAX_SIZE_T (~(size_t)0) | 290 | static int read_chars (lua_State *L, int *f, size_t n) { |
425 | 291 | size_t rlen; /* how much to read */ | |
426 | static void read_all (lua_State *L, FILE *f) { | ||
427 | size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ | ||
428 | luaL_Buffer b; | ||
429 | luaL_buffinit(L, &b); | ||
430 | for (;;) { | ||
431 | char *p = luaL_prepbuffsize(&b, rlen); | ||
432 | size_t nr = rb->read((int)f, p, rlen); | ||
433 | luaL_addsize(&b, nr); | ||
434 | if (nr < rlen) break; /* eof? */ | ||
435 | else if (rlen <= (MAX_SIZE_T / 4)) /* avoid buffers too large */ | ||
436 | rlen *= 2; /* double buffer size at each iteration */ | ||
437 | } | ||
438 | luaL_pushresult(&b); /* close buffer */ | ||
439 | } | ||
440 | |||
441 | |||
442 | static int read_chars (lua_State *L, FILE *f, size_t n) { | ||
443 | size_t nr; /* number of chars actually read */ | 292 | size_t nr; /* number of chars actually read */ |
444 | char *p; | ||
445 | luaL_Buffer b; | 293 | luaL_Buffer b; |
446 | luaL_buffinit(L, &b); | 294 | luaL_buffinit(L, &b); |
447 | p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ | 295 | rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ |
448 | nr = rb->read((int)f, p, n); /* try to read 'n' chars */ | 296 | do { |
449 | luaL_addsize(&b, nr); | 297 | char *p = luaL_prepbuffer(&b); |
298 | if (rlen > n) rlen = n; /* cannot read more than asked */ | ||
299 | nr = rb->read(*f, p, rlen); | ||
300 | luaL_addsize(&b, nr); | ||
301 | n -= nr; /* still have to read `n' chars */ | ||
302 | } while (n > 0 && nr == rlen); /* until end of count or eof */ | ||
450 | luaL_pushresult(&b); /* close buffer */ | 303 | luaL_pushresult(&b); /* close buffer */ |
451 | return (nr > 0); /* true iff read something */ | 304 | return (n == 0 || lua_objlen(L, -1) > 0); |
452 | } | 305 | } |
453 | 306 | ||
454 | 307 | ||
455 | static int g_read (lua_State *L, FILE *f, int first) { | 308 | static int g_read (lua_State *L, int *f, int first) { |
456 | int nargs = lua_gettop(L) - 1; | 309 | int nargs = lua_gettop(L) - 1; |
457 | int success; | 310 | int success; |
458 | int n; | 311 | int n; |
459 | if (nargs == 0) { /* no arguments? */ | 312 | if (nargs == 0) { /* no arguments? */ |
460 | success = _read_line(L, f, 1); | 313 | success = _read_line(L, f); |
461 | n = first+1; /* to return 1 result */ | 314 | n = first+1; /* to return 1 result */ |
462 | } | 315 | } |
463 | else { /* ensure stack space for all results and for auxlib's buffer */ | 316 | else { /* ensure stack space for all results and for auxlib's buffer */ |
@@ -476,13 +329,10 @@ static int g_read (lua_State *L, FILE *f, int first) { | |||
476 | success = read_number(L, f); | 329 | success = read_number(L, f); |
477 | break; | 330 | break; |
478 | case 'l': /* line */ | 331 | case 'l': /* line */ |
479 | success = _read_line(L, f, 1); | 332 | success = _read_line(L, f); |
480 | break; | ||
481 | case 'L': /* line with end-of-line */ | ||
482 | success = _read_line(L, f, 0); | ||
483 | break; | 333 | break; |
484 | case 'a': /* file */ | 334 | case 'a': /* file */ |
485 | read_all(L, f); /* read entire file */ | 335 | read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ |
486 | success = 1; /* always success */ | 336 | success = 1; /* always success */ |
487 | break; | 337 | break; |
488 | default: | 338 | default: |
@@ -510,24 +360,14 @@ static int f_read (lua_State *L) { | |||
510 | 360 | ||
511 | 361 | ||
512 | static int io_readline (lua_State *L) { | 362 | static int io_readline (lua_State *L) { |
513 | LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); | 363 | int *f = (int *) lua_touserdata(L, lua_upvalueindex(1)); |
514 | int i; | 364 | int sucess; |
515 | int n = (int)lua_tointeger(L, lua_upvalueindex(2)); | 365 | if (*f < 0) /* file is already closed? */ |
516 | if (isclosed(p)) /* file is already closed? */ | 366 | luaL_error(L, "file is already closed"); |
517 | return luaL_error(L, "file is already closed"); | 367 | sucess = _read_line(L, f); |
518 | lua_settop(L , 1); | 368 | if (sucess) return 1; |
519 | for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ | 369 | else { /* EOF */ |
520 | lua_pushvalue(L, lua_upvalueindex(3 + i)); | 370 | if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ |
521 | n = g_read(L, p->f, 2); /* 'n' is number of results */ | ||
522 | lua_assert(n > 0); /* should return at least a nil */ | ||
523 | if (!lua_isnil(L, -n)) /* read at least one value? */ | ||
524 | return n; /* return them */ | ||
525 | else { /* first result is nil: EOF or error */ | ||
526 | if (n > 1) { /* is there error information? */ | ||
527 | /* 2nd result is error message */ | ||
528 | return luaL_error(L, "%s", lua_tostring(L, -n + 1)); | ||
529 | } | ||
530 | if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ | ||
531 | lua_settop(L, 0); | 371 | lua_settop(L, 0); |
532 | lua_pushvalue(L, lua_upvalueindex(1)); | 372 | lua_pushvalue(L, lua_upvalueindex(1)); |
533 | aux_close(L); /* close it */ | 373 | aux_close(L); /* close it */ |
@@ -539,23 +379,22 @@ static int io_readline (lua_State *L) { | |||
539 | /* }====================================================== */ | 379 | /* }====================================================== */ |
540 | 380 | ||
541 | 381 | ||
542 | static int g_write (lua_State *L, FILE *f, int arg) { | 382 | static int g_write (lua_State *L, int *f, int arg) { |
543 | int nargs = lua_gettop(L) - arg; | 383 | int nargs = lua_gettop(L) - 1; |
544 | int status = 1; | 384 | int status = 1; |
545 | for (; nargs--; arg++) { | 385 | for (; nargs--; arg++) { |
546 | if (lua_type(L, arg) == LUA_TNUMBER) { | 386 | if (lua_type(L, arg) == LUA_TNUMBER) { |
547 | /* optimization: could be done exactly as for strings */ | 387 | /* optimization: could be done exactly as for strings */ |
548 | status = status && | 388 | status = status && |
549 | rb->fdprintf((int)f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; | 389 | rb->fdprintf(*f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; |
550 | } | 390 | } |
551 | else { | 391 | else { |
552 | size_t l; | 392 | size_t l; |
553 | const char *s = luaL_checklstring(L, arg, &l); | 393 | const char *s = luaL_checklstring(L, arg, &l); |
554 | status = status && (rb->write((int)f, s, l) == (ssize_t)l); | 394 | status = status && (rb->write(*f, s, l) == (ssize_t)l); |
555 | } | 395 | } |
556 | } | 396 | } |
557 | if (status) return 1; /* file handle already on stack top */ | 397 | return pushresult(L, status, NULL); |
558 | else return luaL_fileresult(L, status, NULL); | ||
559 | } | 398 | } |
560 | 399 | ||
561 | 400 | ||
@@ -565,86 +404,47 @@ static int io_write (lua_State *L) { | |||
565 | 404 | ||
566 | 405 | ||
567 | static int f_write (lua_State *L) { | 406 | static int f_write (lua_State *L) { |
568 | FILE *f = tofile(L); | 407 | return g_write(L, tofile(L), 2); |
569 | lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ | ||
570 | return g_write(L, f, 2); | ||
571 | } | 408 | } |
572 | 409 | ||
573 | 410 | ||
574 | static int f_seek (lua_State *L) { | 411 | static int f_seek (lua_State *L) { |
575 | static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; | 412 | static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; |
576 | static const char *const modenames[] = {"set", "cur", "end", NULL}; | 413 | static const char *const modenames[] = {"set", "cur", "end", NULL}; |
577 | FILE *f = tofile(L); | 414 | int f = *tofile(L); |
578 | int op = luaL_checkoption(L, 2, "cur", modenames); | 415 | int op = luaL_checkoption(L, 2, "cur", modenames); |
579 | lua_Number p3 = luaL_optnumber(L, 3, 0); | 416 | long offset = luaL_optlong(L, 3, 0); |
580 | l_seeknum offset = (l_seeknum)p3; | 417 | op = rb->lseek(f, offset, mode[op]); |
581 | luaL_argcheck(L, (lua_Number)offset == p3, 3, | ||
582 | "not an integer in proper range"); | ||
583 | op = rb->lseek((int)f, offset, mode[op]); | ||
584 | if (op) | 418 | if (op) |
585 | return luaL_fileresult(L, 0, NULL); /* error */ | 419 | return pushresult(L, 0, NULL); /* error */ |
586 | else { | 420 | else { |
587 | lua_pushnumber(L, (lua_Number)rb->lseek((int)f, 0, SEEK_CUR)); | 421 | lua_pushinteger(L, rb->lseek(f, 0, SEEK_CUR)); |
588 | return 1; | 422 | return 1; |
589 | } | 423 | } |
590 | } | 424 | } |
591 | 425 | ||
592 | #if 0 | ||
593 | static int f_setvbuf (lua_State *L) { | ||
594 | static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; | ||
595 | static const char *const modenames[] = {"no", "full", "line", NULL}; | ||
596 | FILE *f = tofile(L); | ||
597 | int op = luaL_checkoption(L, 2, NULL, modenames); | ||
598 | lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); | ||
599 | int res = setvbuf(f, NULL, mode[op], sz); | ||
600 | return luaL_fileresult(L, res == 0, NULL); | ||
601 | } | ||
602 | |||
603 | 426 | ||
604 | |||
605 | static int io_flush (lua_State *L) { | ||
606 | return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); | ||
607 | } | ||
608 | |||
609 | |||
610 | static int f_flush (lua_State *L) { | ||
611 | return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); | ||
612 | } | ||
613 | #endif | ||
614 | |||
615 | |||
616 | /* | ||
617 | ** functions for 'io' library | ||
618 | */ | ||
619 | static const luaL_Reg iolib[] = { | 427 | static const luaL_Reg iolib[] = { |
620 | {"close", io_close}, | 428 | {"close", io_close}, |
621 | /*{"flush", io_flush},*/ | ||
622 | {"input", io_input}, | 429 | {"input", io_input}, |
623 | {"lines", io_lines}, | 430 | {"lines", io_lines}, |
624 | {"open", io_open}, | 431 | {"open", io_open}, |
625 | {"output", io_output}, | 432 | {"output", io_output}, |
626 | /*{"popen", io_popen},*/ | ||
627 | {"read", io_read}, | 433 | {"read", io_read}, |
628 | /*{"tmpfile", io_tmpfile},*/ | ||
629 | {"type", io_type}, | 434 | {"type", io_type}, |
630 | {"write", io_write}, | 435 | {"write", io_write}, |
631 | {NULL, NULL} | 436 | {NULL, NULL} |
632 | }; | 437 | }; |
633 | 438 | ||
634 | 439 | ||
635 | /* | ||
636 | ** methods for file handles | ||
637 | */ | ||
638 | static const luaL_Reg flib[] = { | 440 | static const luaL_Reg flib[] = { |
639 | {"close", io_close}, | 441 | {"close", io_close}, |
640 | /*{"flush", f_flush},*/ | ||
641 | {"lines", f_lines}, | 442 | {"lines", f_lines}, |
642 | {"read", f_read}, | 443 | {"read", f_read}, |
643 | {"seek", f_seek}, | 444 | {"seek", f_seek}, |
644 | /*{"setvbuf", f_setvbuf},*/ | ||
645 | {"write", f_write}, | 445 | {"write", f_write}, |
646 | {"__gc", f_gc}, | 446 | {"__gc", io_gc}, |
647 | {"__tostring", f_tostring}, | 447 | {"__tostring", io_tostring}, |
648 | {NULL, NULL} | 448 | {NULL, NULL} |
649 | }; | 449 | }; |
650 | 450 | ||
@@ -653,40 +453,16 @@ static void createmeta (lua_State *L) { | |||
653 | luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ | 453 | luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ |
654 | lua_pushvalue(L, -1); /* push metatable */ | 454 | lua_pushvalue(L, -1); /* push metatable */ |
655 | lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ | 455 | lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ |
656 | luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ | 456 | luaL_register(L, NULL, flib); /* file methods */ |
657 | lua_pop(L, 1); /* pop new metatable */ | ||
658 | } | 457 | } |
659 | 458 | ||
660 | 459 | ||
661 | /* | 460 | LUALIB_API int luaopen_io (lua_State *L) { |
662 | ** function to (not) close the standard files stdin, stdout, and stderr | ||
663 | */ | ||
664 | #if 0 | ||
665 | static int io_noclose (lua_State *L) { | ||
666 | LStream *p = tolstream(L); | ||
667 | p->closef = &io_noclose; /* keep file opened */ | ||
668 | lua_pushnil(L); | ||
669 | lua_pushliteral(L, "cannot close standard file"); | ||
670 | return 2; | ||
671 | } | ||
672 | |||
673 | |||
674 | static void createstdfile (lua_State *L, FILE *f, const char *k, | ||
675 | const char *fname) { | ||
676 | LStream *p = newprefile(L); | ||
677 | p->f = f; | ||
678 | p->closef = &io_noclose; | ||
679 | if (k != NULL) { | ||
680 | lua_pushvalue(L, -1); | ||
681 | lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ | ||
682 | } | ||
683 | lua_setfield(L, -2, fname); /* add file to module */ | ||
684 | } | ||
685 | #endif | ||
686 | |||
687 | LUAMOD_API int luaopen_io (lua_State *L) { | ||
688 | luaL_newlib(L, iolib); /* new module */ | ||
689 | createmeta(L); | 461 | createmeta(L); |
462 | lua_replace(L, LUA_ENVIRONINDEX); | ||
463 | /* open library */ | ||
464 | luaL_register(L, LUA_IOLIBNAME, iolib); | ||
690 | /* create (and set) default files */ | 465 | /* create (and set) default files */ |
466 | lua_pop(L, 1); /* pop environment for default files */ | ||
691 | return 1; | 467 | return 1; |
692 | } | 468 | } |