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