summaryrefslogtreecommitdiff
path: root/apps/plugins/lua/liolib.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/lua/liolib.c')
-rw-r--r--apps/plugins/lua/liolib.c536
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_" 27static const char *const fnames[] = {"input", "output"};
119#define IO_INPUT (IO_PREFIX "input")
120#define IO_OUTPUT (IO_PREFIX "output")
121 28
122 29
123typedef luaL_Stream LStream; 30static 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) 48static 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
131static int io_type (lua_State *L) { 54static 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
145static int f_tostring (lua_State *L) { 69static 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
155static 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*/
169static LStream *newprefile (lua_State *L) { 83static 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
177static 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 */ 95static 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
185static int io_close (lua_State *L) { 103static 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
193static int f_gc (lua_State *L) { 108static 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*/
204static 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
211static LStream *newfile (lua_State *L) { 116static 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
219static void opencheck (lua_State *L, const char *fname, const char *mode) { 125static 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
230static int io_open (lua_State *L) { 135static 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 166static 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);
268static 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
274static int io_popen (lua_State *L) { 176static 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
284static 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
292static 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
302static 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
319static int io_input (lua_State *L) { 197static 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
324static int io_output (lua_State *L) { 202static 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
329static int io_readline (lua_State *L); 207static int io_readline (lua_State *L);
330 208
331 209
332static void aux_lines (lua_State *L, int toclose) { 210static 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
345static int f_lines (lua_State *L) { 217static 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
352static int io_lines (lua_State *L) { 224static 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 248static int read_number (lua_State *L, int *f) {
379static 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
392static int test_eof (lua_State *L, FILE *f) { 258static 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() */
400static int _read_line (lua_State *L, FILE *f, int chop) { 266static 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) 290static int read_chars (lua_State *L, int *f, size_t n) {
425 291 size_t rlen; /* how much to read */
426static 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
442static 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
455static int g_read (lua_State *L, FILE *f, int first) { 308static 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
512static int io_readline (lua_State *L) { 362static 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
542static int g_write (lua_State *L, FILE *f, int arg) { 382static 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
567static int f_write (lua_State *L) { 406static 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
574static int f_seek (lua_State *L) { 411static 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
593static 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
605static int io_flush (lua_State *L) {
606 return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
607}
608
609
610static 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*/
619static const luaL_Reg iolib[] = { 427static 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*/
638static const luaL_Reg flib[] = { 440static 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/* 460LUALIB_API int luaopen_io (lua_State *L) {
662** function to (not) close the standard files stdin, stdout, and stderr
663*/
664#if 0
665static 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
674static 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
687LUAMOD_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}