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
);
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 ** =======================================================
249 static int read_number (lua_State
*L
, int *f
) {
250 char buf
[10]; /* Maximum uint32 value is 10 chars long */
253 /* Rather hackish, but we don't have fscanf.
254 Was: fscanf(f, LUA_NUMBER_SCAN, &d); */
256 rb
->read(*f
, buf
, 10);
257 while(isdigit(buf
[i
]) && i
< 10)
261 rb
->lseek(*f
, i
-10, SEEK_CUR
);
263 lua_pushnumber(L
, d
);
269 static int test_eof (lua_State
*L
, int *f
) {
270 ssize_t s
= rb
->lseek(*f
, 0, SEEK_CUR
);
271 lua_pushlstring(L
, NULL
, 0);
272 return s
!= rb
->filesize(*f
);
276 /* Rockbox already defines read_line() */
277 static int _read_line (lua_State
*L
, int *f
) {
279 luaL_buffinit(L
, &b
);
283 char *p
= luaL_prepbuffer(&b
);
284 r
= rb
->read_line(*f
, p
, LUAL_BUFFERSIZE
);
286 if (l
== 0 || p
[l
-1] != '\n')
289 luaL_addsize(&b
, l
- 1); /* do not include `eol' */
290 luaL_pushresult(&b
); /* close buffer */
291 return 1; /* read at least an `eol' */
293 if (r
< LUAL_BUFFERSIZE
) { /* eof? */
294 luaL_pushresult(&b
); /* close buffer */
295 return (lua_objlen(L
, -1) > 0); /* check whether read something */
301 static int read_chars (lua_State
*L
, int *f
, size_t n
) {
302 size_t rlen
; /* how much to read */
303 size_t nr
; /* number of chars actually read */
305 luaL_buffinit(L
, &b
);
306 rlen
= LUAL_BUFFERSIZE
; /* try to read that much each time */
308 char *p
= luaL_prepbuffer(&b
);
309 if (rlen
> n
) rlen
= n
; /* cannot read more than asked */
310 nr
= rb
->read(*f
, p
, rlen
);
311 luaL_addsize(&b
, nr
);
312 n
-= nr
; /* still have to read `n' chars */
313 } while (n
> 0 && nr
== rlen
); /* until end of count or eof */
314 luaL_pushresult(&b
); /* close buffer */
315 return (n
== 0 || lua_objlen(L
, -1) > 0);
319 static int g_read (lua_State
*L
, int *f
, int first
) {
320 int nargs
= lua_gettop(L
) - 1;
323 if (nargs
== 0) { /* no arguments? */
324 success
= _read_line(L
, f
);
325 n
= first
+1; /* to return 1 result */
327 else { /* ensure stack space for all results and for auxlib's buffer */
328 luaL_checkstack(L
, nargs
+LUA_MINSTACK
, "too many arguments");
330 for (n
= first
; nargs
-- && success
; n
++) {
331 if (lua_type(L
, n
) == LUA_TNUMBER
) {
332 size_t l
= (size_t)lua_tointeger(L
, n
);
333 success
= (l
== 0) ? test_eof(L
, f
) : read_chars(L
, f
, l
);
336 const char *p
= lua_tostring(L
, n
);
337 luaL_argcheck(L
, p
&& p
[0] == '*', n
, "invalid option");
339 case 'n': /* number */
340 success
= read_number(L
, f
);
343 success
= _read_line(L
, f
);
346 read_chars(L
, f
, ~((size_t)0)); /* read MAX_SIZE_T chars */
347 success
= 1; /* always success */
350 return luaL_argerror(L
, n
, "invalid format");
356 lua_pop(L
, 1); /* remove last result */
357 lua_pushnil(L
); /* push nil instead */
363 static int io_read (lua_State
*L
) {
364 return g_read(L
, getiofile(L
, IO_INPUT
), 1);
368 static int f_read (lua_State
*L
) {
369 return g_read(L
, tofile(L
), 2);
373 static int io_readline (lua_State
*L
) {
374 int *f
= (int *) lua_touserdata(L
, lua_upvalueindex(1));
376 if (*f
< 0) /* file is already closed? */
377 luaL_error(L
, "file is already closed");
378 sucess
= _read_line(L
, f
);
379 if (sucess
) return 1;
381 if (lua_toboolean(L
, lua_upvalueindex(2))) { /* generator created file? */
383 lua_pushvalue(L
, lua_upvalueindex(1));
384 aux_close(L
); /* close it */
390 /* }====================================================== */
393 static int g_write (lua_State
*L
, int *f
, int arg
) {
394 int nargs
= lua_gettop(L
) - 1;
396 for (; nargs
--; arg
++) {
397 if (lua_type(L
, arg
) == LUA_TNUMBER
) {
398 /* optimization: could be done exactly as for strings */
400 rb
->fdprintf(*f
, LUA_NUMBER_FMT
, lua_tonumber(L
, arg
)) > 0;
404 const char *s
= luaL_checklstring(L
, arg
, &l
);
405 status
= status
&& (rb
->write(*f
, s
, l
) == (ssize_t
)l
);
408 return pushresult(L
, status
, NULL
);
412 static int io_write (lua_State
*L
) {
413 return g_write(L
, getiofile(L
, IO_OUTPUT
), 1);
417 static int f_write (lua_State
*L
) {
418 return g_write(L
, tofile(L
), 2);
422 static int f_seek (lua_State
*L
) {
423 static const int mode
[] = {SEEK_SET
, SEEK_CUR
, SEEK_END
};
424 static const char *const modenames
[] = {"set", "cur", "end", NULL
};
426 int op
= luaL_checkoption(L
, 2, "cur", modenames
);
427 long offset
= luaL_optlong(L
, 3, 0);
428 op
= rb
->lseek(f
, offset
, mode
[op
]);
430 return pushresult(L
, 0, NULL
); /* error */
432 lua_pushinteger(L
, rb
->lseek(f
, 0, SEEK_CUR
));
438 static const luaL_Reg iolib
[] = {
443 {"output", io_output
},
451 static const luaL_Reg flib
[] = {
458 {"__tostring", io_tostring
},
463 static void createmeta (lua_State
*L
) {
464 luaL_newmetatable(L
, LUA_FILEHANDLE
); /* create metatable for file handles */
465 lua_pushvalue(L
, -1); /* push metatable */
466 lua_setfield(L
, -2, "__index"); /* metatable.__index = metatable */
467 luaL_register(L
, NULL
, flib
); /* file methods */
471 LUALIB_API
int luaopen_io (lua_State
*L
) {
473 lua_replace(L
, LUA_ENVIRONINDEX
);
475 luaL_register(L
, LUA_IOLIBNAME
, iolib
);
476 /* create (and set) default files */
477 lua_pop(L
, 1); /* pop environment for default files */