2 ** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $
3 ** Standard I/O (and system) library
4 ** See Copyright Notice in lua.h
27 static const char *const fnames
[] = {"input", "output"};
30 static int pushresult (lua_State
*L
, int i
, const char *filename
) {
33 lua_pushboolean(L
, 1);
39 lua_pushfstring(L
, "%s: %s", filename
, strerror(en
));
41 lua_pushfstring(L
, "%s", strerror(en
));
42 lua_pushinteger(L
, 0);
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));
54 static int io_type (lua_State
*L
) {
57 ud
= lua_touserdata(L
, 1);
58 lua_getfield(L
, LUA_REGISTRYINDEX
, LUA_FILEHANDLE
);
59 if (ud
== NULL
|| !lua_getmetatable(L
, 1) || !lua_rawequal(L
, -2, -1))
60 lua_pushnil(L
); /* not a file */
61 else if (*((int *)ud
) < 0)
62 lua_pushliteral(L
, "closed file");
64 lua_pushliteral(L
, "file");
69 static int* tofile (lua_State
*L
) {
70 int *f
= (int*) luaL_checkudata(L
, 1, LUA_FILEHANDLE
);
72 luaL_error(L
, "attempt to use a closed file");
79 ** When creating file handles, always creates a `closed' file handle
80 ** before opening the actual file; so, if there is a memory error, the
81 ** file is not left opened.
83 static int* newfile (lua_State
*L
) {
84 int *pf
= (int *)lua_newuserdata(L
, sizeof(int));
85 *pf
= -1; /* file handle is currently `closed' */
86 luaL_getmetatable(L
, LUA_FILEHANDLE
);
87 lua_setmetatable(L
, -2);
93 ** function to close regular files
95 static int io_fclose (lua_State
*L
) {
97 int ok
= (rb
->close(*p
) == 0);
99 return pushresult(L
, ok
, NULL
);
103 static inline int aux_close (lua_State
*L
) {
108 static int io_close (lua_State
*L
) {
109 if (lua_isnone(L
, 1))
110 lua_rawgeti(L
, LUA_ENVIRONINDEX
, IO_OUTPUT
);
111 tofile(L
); /* make sure argument is a file */
116 static int io_gc (lua_State
*L
) {
117 int f
= *(int*) luaL_checkudata(L
, 1, LUA_FILEHANDLE
);
118 /* ignore closed files */
125 static int io_tostring (lua_State
*L
) {
126 int f
= *(int*) luaL_checkudata(L
, 1, LUA_FILEHANDLE
);
128 lua_pushliteral(L
, "file (closed)");
130 lua_pushfstring(L
, "file (%d)", f
);
135 static int io_open (lua_State
*L
) {
136 const char *filename
= luaL_checkstring(L
, 1);
137 const char *mode
= luaL_optstring(L
, 2, "r");
138 int *pf
= newfile(L
);
140 if(*(mode
+1) == '+') {
144 flags
|= O_TRUNC
; break;
146 flags
|= O_APPEND
; break;
152 flags
= O_RDONLY
; break;
154 flags
= O_WRONLY
| O_TRUNC
; break;
156 flags
= O_WRONLY
| O_APPEND
; break;
159 if((*mode
== 'w' || *mode
== 'a') && !rb
->file_exists(filename
))
161 *pf
= rb
->open(filename
, flags
, 0666);
162 return (*pf
< 0) ? pushresult(L
, 0, filename
) : 1;
166 static int* getiofile (lua_State
*L
, int findex
) {
168 lua_rawgeti(L
, LUA_ENVIRONINDEX
, findex
);
169 f
= (int *)lua_touserdata(L
, -1);
170 if (f
== NULL
|| *f
< 0)
171 luaL_error(L
, "standard %s file is closed", fnames
[findex
- 1]);
176 static int g_iofile (lua_State
*L
, int f
, int flags
) {
177 if (!lua_isnoneornil(L
, 1)) {
178 const char *filename
= lua_tostring(L
, 1);
180 int *pf
= newfile(L
);
181 *pf
= rb
->open(filename
, flags
);
183 fileerror(L
, 1, filename
);
186 tofile(L
); /* check that it's a valid file handle */
189 lua_rawseti(L
, LUA_ENVIRONINDEX
, f
);
191 /* return current value */
192 lua_rawgeti(L
, LUA_ENVIRONINDEX
, f
);
197 static int io_input (lua_State
*L
) {
198 return g_iofile(L
, IO_INPUT
, O_RDONLY
);
202 static int io_output (lua_State
*L
) {
203 return g_iofile(L
, IO_OUTPUT
, O_WRONLY
);
207 static int io_readline (lua_State
*L
);
210 static void aux_lines (lua_State
*L
, int idx
, int toclose
) {
211 lua_pushvalue(L
, idx
);
212 lua_pushboolean(L
, toclose
); /* close/not close file when finished */
213 lua_pushcclosure(L
, io_readline
, 2);
217 static int f_lines (lua_State
*L
) {
218 tofile(L
); /* check that it's a valid file handle */
224 static int io_lines (lua_State
*L
) {
225 if (lua_isnoneornil(L
, 1)) { /* no arguments? */
226 /* will iterate over default input */
227 lua_rawgeti(L
, LUA_ENVIRONINDEX
, IO_INPUT
);
231 const char *filename
= luaL_checkstring(L
, 1);
232 int *pf
= newfile(L
);
233 *pf
= rb
->open(filename
, O_RDONLY
);
235 fileerror(L
, 1, filename
);
236 aux_lines(L
, lua_gettop(L
), 1);
243 ** {======================================================
245 ** =======================================================
248 static int read_number (lua_State
*L
, int *f
) {
250 if (PREFIX(fscanf
)(*f
, LUA_NUMBER_SCAN
, &d
) == 1) {
251 lua_pushnumber(L
, d
);
254 else return 0; /* read fails */
258 static int test_eof (lua_State
*L
, int *f
) {
259 ssize_t s
= rb
->lseek(*f
, 0, SEEK_CUR
);
260 lua_pushlstring(L
, NULL
, 0);
261 return s
!= rb
->filesize(*f
);
265 /* Rockbox already defines read_line() */
266 static int _read_line (lua_State
*L
, int *f
) {
268 luaL_buffinit(L
, &b
);
272 char *p
= luaL_prepbuffer(&b
);
273 r
= rb
->read_line(*f
, p
, LUAL_BUFFERSIZE
);
275 if (l
== 0 || p
[l
-1] != '\n')
278 luaL_addsize(&b
, l
- 1); /* do not include `eol' */
279 luaL_pushresult(&b
); /* close buffer */
280 return 1; /* read at least an `eol' */
282 if (r
< LUAL_BUFFERSIZE
) { /* eof? */
283 luaL_pushresult(&b
); /* close buffer */
284 return (lua_objlen(L
, -1) > 0); /* check whether read something */
290 static int read_chars (lua_State
*L
, int *f
, size_t n
) {
291 size_t rlen
; /* how much to read */
292 size_t nr
; /* number of chars actually read */
294 luaL_buffinit(L
, &b
);
295 rlen
= LUAL_BUFFERSIZE
; /* try to read that much each time */
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 */
303 luaL_pushresult(&b
); /* close buffer */
304 return (n
== 0 || lua_objlen(L
, -1) > 0);
308 static int g_read (lua_State
*L
, int *f
, int first
) {
309 int nargs
= lua_gettop(L
) - 1;
312 if (nargs
== 0) { /* no arguments? */
313 success
= _read_line(L
, f
);
314 n
= first
+1; /* to return 1 result */
316 else { /* ensure stack space for all results and for auxlib's buffer */
317 luaL_checkstack(L
, nargs
+LUA_MINSTACK
, "too many arguments");
319 for (n
= first
; nargs
-- && success
; n
++) {
320 if (lua_type(L
, n
) == LUA_TNUMBER
) {
321 size_t l
= (size_t)lua_tointeger(L
, n
);
322 success
= (l
== 0) ? test_eof(L
, f
) : read_chars(L
, f
, l
);
325 const char *p
= lua_tostring(L
, n
);
326 luaL_argcheck(L
, p
&& p
[0] == '*', n
, "invalid option");
328 case 'n': /* number */
329 success
= read_number(L
, f
);
332 success
= _read_line(L
, f
);
335 read_chars(L
, f
, ~((size_t)0)); /* read MAX_SIZE_T chars */
336 success
= 1; /* always success */
339 return luaL_argerror(L
, n
, "invalid format");
345 lua_pop(L
, 1); /* remove last result */
346 lua_pushnil(L
); /* push nil instead */
352 static int io_read (lua_State
*L
) {
353 return g_read(L
, getiofile(L
, IO_INPUT
), 1);
357 static int f_read (lua_State
*L
) {
358 return g_read(L
, tofile(L
), 2);
362 static int io_readline (lua_State
*L
) {
363 int *f
= (int *) lua_touserdata(L
, lua_upvalueindex(1));
365 if (*f
< 0) /* file is already closed? */
366 luaL_error(L
, "file is already closed");
367 sucess
= _read_line(L
, f
);
368 if (sucess
) return 1;
370 if (lua_toboolean(L
, lua_upvalueindex(2))) { /* generator created file? */
372 lua_pushvalue(L
, lua_upvalueindex(1));
373 aux_close(L
); /* close it */
379 /* }====================================================== */
382 static int g_write (lua_State
*L
, int *f
, int arg
) {
383 int nargs
= lua_gettop(L
) - 1;
385 for (; nargs
--; arg
++) {
386 if (lua_type(L
, arg
) == LUA_TNUMBER
) {
387 /* optimization: could be done exactly as for strings */
389 rb
->fdprintf(*f
, LUA_NUMBER_FMT
, lua_tonumber(L
, arg
)) > 0;
393 const char *s
= luaL_checklstring(L
, arg
, &l
);
394 status
= status
&& (rb
->write(*f
, s
, l
) == (ssize_t
)l
);
397 return pushresult(L
, status
, NULL
);
401 static int io_write (lua_State
*L
) {
402 return g_write(L
, getiofile(L
, IO_OUTPUT
), 1);
406 static int f_write (lua_State
*L
) {
407 return g_write(L
, tofile(L
), 2);
411 static int f_seek (lua_State
*L
) {
412 static const int mode
[] = {SEEK_SET
, SEEK_CUR
, SEEK_END
};
413 static const char *const modenames
[] = {"set", "cur", "end", NULL
};
415 int op
= luaL_checkoption(L
, 2, "cur", modenames
);
416 long offset
= luaL_optlong(L
, 3, 0);
417 op
= rb
->lseek(f
, offset
, mode
[op
]);
419 return pushresult(L
, 0, NULL
); /* error */
421 lua_pushinteger(L
, rb
->lseek(f
, 0, SEEK_CUR
));
427 static const luaL_Reg iolib
[] = {
432 {"output", io_output
},
440 static const luaL_Reg flib
[] = {
447 {"__tostring", io_tostring
},
452 static void createmeta (lua_State
*L
) {
453 luaL_newmetatable(L
, LUA_FILEHANDLE
); /* create metatable for file handles */
454 lua_pushvalue(L
, -1); /* push metatable */
455 lua_setfield(L
, -2, "__index"); /* metatable.__index = metatable */
456 luaL_register(L
, NULL
, flib
); /* file methods */
460 LUALIB_API
int luaopen_io (lua_State
*L
) {
462 lua_replace(L
, LUA_ENVIRONINDEX
);
464 luaL_register(L
, LUA_IOLIBNAME
, iolib
);
465 /* create (and set) default files */
466 lua_pop(L
, 1); /* pop environment for default files */