Lua 5.1.4: liolib.c
L0001 /*
L0002 ** $Id: liolib.c,v 2.73.1.3 2008年01月18日 17:47:43 roberto Exp $
L0003 ** Standard I/O (and system) library
L0004 ** See Copyright Notice in lua.h
L0005 */
L0006
L0007
L0008 #include <errno.h>
L0009 #include <stdio.h>
L0010 #include <stdlib.h>
L0011 #include <string.h>
L0012
L0013 #define liolib_c
L0014 #define LUA_LIB
L0015
L0016 #include "lua.h"
L0017
L0018 #include "lauxlib.h"
L0019 #include "lualib.h"
L0020
L0021
L0022
L0023 #define IO_INPUT 1
L0024 #define IO_OUTPUT 2
L0025
L0026
L0027 static const char *const fnames[] = {"input", "output"};
L0028
L0029
L0030 static int pushresult (lua_State *L, int i, const char *filename) {
L0031 int en = errno; /* calls to Lua API may change this value */
L0032 if (i) {
L0033 lua_pushboolean(L, 1);
L0034 return 1;
L0035 }
L0036 else {
L0037 lua_pushnil(L);
L0038 if (filename)
L0039 lua_pushfstring(L, "%s: %s", filename, strerror(en));
L0040 else
L0041 lua_pushfstring(L, "%s", strerror(en));
L0042 lua_pushinteger(L, en);
L0043 return 3;
L0044 }
L0045 }
L0046
L0047
L0048 static void fileerror (lua_State *L, int arg, const char *filename) {
L0049 lua_pushfstring(L, "%s: %s", filename, strerror(errno));
L0050 luaL_argerror(L, arg, lua_tostring(L, -1));
L0051 }
L0052
L0053
L0054 #define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
L0055
L0056
L0057 static int io_type (lua_State *L) {
L0058 void *ud;
L0059 luaL_checkany(L, 1);
L0060 ud = lua_touserdata(L, 1);
L0061 lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
L0062 if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
L0063 lua_pushnil(L); /* not a file */
L0064 else if (*((FILE **)ud) == NULL)
L0065 lua_pushliteral(L, "closed file");
L0066 else
L0067 lua_pushliteral(L, "file");
L0068 return 1;
L0069 }
L0070
L0071
L0072 static FILE *tofile (lua_State *L) {
L0073 FILE **f = tofilep(L);
L0074 if (*f == NULL)
L0075 luaL_error(L, "attempt to use a closed file");
L0076 return *f;
L0077 }
L0078
L0079
L0080
L0081 /*
L0082 ** When creating file handles, always creates a `closed' file handle
L0083 ** before opening the actual file; so, if there is a memory error, the
L0084 ** file is not left opened.
L0085 */
L0086 static FILE **newfile (lua_State *L) {
L0087 FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
L0088 *pf = NULL; /* file handle is currently `closed' */
L0089 luaL_getmetatable(L, LUA_FILEHANDLE);
L0090 lua_setmetatable(L, -2);
L0091 return pf;
L0092 }
L0093
L0094
L0095 /*
L0096 ** function to (not) close the standard files stdin, stdout, and stderr
L0097 */
L0098 static int io_noclose (lua_State *L) {
L0099 lua_pushnil(L);
L0100 lua_pushliteral(L, "cannot close standard file");
L0101 return 2;
L0102 }
L0103
L0104
L0105 /*
L0106 ** function to close 'popen' files
L0107 */
L0108 static int io_pclose (lua_State *L) {
L0109 FILE **p = tofilep(L);
L0110 int ok = lua_pclose(L, *p);
L0111 *p = NULL;
L0112 return pushresult(L, ok, NULL);
L0113 }
L0114
L0115
L0116 /*
L0117 ** function to close regular files
L0118 */
L0119 static int io_fclose (lua_State *L) {
L0120 FILE **p = tofilep(L);
L0121 int ok = (fclose(*p) == 0);
L0122 *p = NULL;
L0123 return pushresult(L, ok, NULL);
L0124 }
L0125
L0126
L0127 static int aux_close (lua_State *L) {
L0128 lua_getfenv(L, 1);
L0129 lua_getfield(L, -1, "__close");
L0130 return (lua_tocfunction(L, -1))(L);
L0131 }
L0132
L0133
L0134 static int io_close (lua_State *L) {
L0135 if (lua_isnone(L, 1))
L0136 lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT);
L0137 tofile(L); /* make sure argument is a file */
L0138 return aux_close(L);
L0139 }
L0140
L0141
L0142 static int io_gc (lua_State *L) {
L0143 FILE *f = *tofilep(L);
L0144 /* ignore closed files */
L0145 if (f != NULL)
L0146 aux_close(L);
L0147 return 0;
L0148 }
L0149
L0150
L0151 static int io_tostring (lua_State *L) {
L0152 FILE *f = *tofilep(L);
L0153 if (f == NULL)
L0154 lua_pushliteral(L, "file (closed)");
L0155 else
L0156 lua_pushfstring(L, "file (%p)", f);
L0157 return 1;
L0158 }
L0159
L0160
L0161 static int io_open (lua_State *L) {
L0162 const char *filename = luaL_checkstring(L, 1);
L0163 const char *mode = luaL_optstring(L, 2, "r");
L0164 FILE **pf = newfile(L);
L0165 *pf = fopen(filename, mode);
L0166 return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
L0167 }
L0168
L0169
L0170 /*
L0171 ** this function has a separated environment, which defines the
L0172 ** correct __close for 'popen' files
L0173 */
L0174 static int io_popen (lua_State *L) {
L0175 const char *filename = luaL_checkstring(L, 1);
L0176 const char *mode = luaL_optstring(L, 2, "r");
L0177 FILE **pf = newfile(L);
L0178 *pf = lua_popen(L, filename, mode);
L0179 return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
L0180 }
L0181
L0182
L0183 static int io_tmpfile (lua_State *L) {
L0184 FILE **pf = newfile(L);
L0185 *pf = tmpfile();
L0186 return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
L0187 }
L0188
L0189
L0190 static FILE *getiofile (lua_State *L, int findex) {
L0191 FILE *f;
L0192 lua_rawgeti(L, LUA_ENVIRONINDEX, findex);
L0193 f = *(FILE **)lua_touserdata(L, -1);
L0194 if (f == NULL)
L0195 luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
L0196 return f;
L0197 }
L0198
L0199
L0200 static int g_iofile (lua_State *L, int f, const char *mode) {
L0201 if (!lua_isnoneornil(L, 1)) {
L0202 const char *filename = lua_tostring(L, 1);
L0203 if (filename) {
L0204 FILE **pf = newfile(L);
L0205 *pf = fopen(filename, mode);
L0206 if (*pf == NULL)
L0207 fileerror(L, 1, filename);
L0208 }
L0209 else {
L0210 tofile(L); /* check that it's a valid file handle */
L0211 lua_pushvalue(L, 1);
L0212 }
L0213 lua_rawseti(L, LUA_ENVIRONINDEX, f);
L0214 }
L0215 /* return current value */
L0216 lua_rawgeti(L, LUA_ENVIRONINDEX, f);
L0217 return 1;
L0218 }
L0219
L0220
L0221 static int io_input (lua_State *L) {
L0222 return g_iofile(L, IO_INPUT, "r");
L0223 }
L0224
L0225
L0226 static int io_output (lua_State *L) {
L0227 return g_iofile(L, IO_OUTPUT, "w");
L0228 }
L0229
L0230
L0231 static int io_readline (lua_State *L);
L0232
L0233
L0234 static void aux_lines (lua_State *L, int idx, int toclose) {
L0235 lua_pushvalue(L, idx);
L0236 lua_pushboolean(L, toclose); /* close/not close file when finished */
L0237 lua_pushcclosure(L, io_readline, 2);
L0238 }
L0239
L0240
L0241 static int f_lines (lua_State *L) {
L0242 tofile(L); /* check that it's a valid file handle */
L0243 aux_lines(L, 1, 0);
L0244 return 1;
L0245 }
L0246
L0247
L0248 static int io_lines (lua_State *L) {
L0249 if (lua_isnoneornil(L, 1)) { /* no arguments? */
L0250 /* will iterate over default input */
L0251 lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT);
L0252 return f_lines(L);
L0253 }
L0254 else {
L0255 const char *filename = luaL_checkstring(L, 1);
L0256 FILE **pf = newfile(L);
L0257 *pf = fopen(filename, "r");
L0258 if (*pf == NULL)
L0259 fileerror(L, 1, filename);
L0260 aux_lines(L, lua_gettop(L), 1);
L0261 return 1;
L0262 }
L0263 }
L0264
L0265
L0266 /*
L0267 ** {======================================================
L0268 ** READ
L0269 ** =======================================================
L0270 */
L0271
L0272
L0273 static int read_number (lua_State *L, FILE *f) {
L0274 lua_Number d;
L0275 if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
L0276 lua_pushnumber(L, d);
L0277 return 1;
L0278 }
L0279 else return 0; /* read fails */
L0280 }
L0281
L0282
L0283 static int test_eof (lua_State *L, FILE *f) {
L0284 int c = getc(f);
L0285 ungetc(c, f);
L0286 lua_pushlstring(L, NULL, 0);
L0287 return (c != EOF);
L0288 }
L0289
L0290
L0291 static int read_line (lua_State *L, FILE *f) {
L0292 luaL_Buffer b;
L0293 luaL_buffinit(L, &b);
L0294 for (;;) {
L0295 size_t l;
L0296 char *p = luaL_prepbuffer(&b);
L0297 if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */
L0298 luaL_pushresult(&b); /* close buffer */
L0299 return (lua_objlen(L, -1) > 0); /* check whether read something */
L0300 }
L0301 l = strlen(p);
L0302 if (l == 0 || p[l-1] != '\n')
L0303 luaL_addsize(&b, l);
L0304 else {
L0305 luaL_addsize(&b, l - 1); /* do not include `eol' */
L0306 luaL_pushresult(&b); /* close buffer */
L0307 return 1; /* read at least an `eol' */
L0308 }
L0309 }
L0310 }
L0311
L0312
L0313 static int read_chars (lua_State *L, FILE *f, size_t n) {
L0314 size_t rlen; /* how much to read */
L0315 size_t nr; /* number of chars actually read */
L0316 luaL_Buffer b;
L0317 luaL_buffinit(L, &b);
L0318 rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
L0319 do {
L0320 char *p = luaL_prepbuffer(&b);
L0321 if (rlen > n) rlen = n; /* cannot read more than asked */
L0322 nr = fread(p, sizeof(char), rlen, f);
L0323 luaL_addsize(&b, nr);
L0324 n -= nr; /* still have to read `n' chars */
L0325 } while (n > 0 && nr == rlen); /* until end of count or eof */
L0326 luaL_pushresult(&b); /* close buffer */
L0327 return (n == 0 || lua_objlen(L, -1) > 0);
L0328 }
L0329
L0330
L0331 static int g_read (lua_State *L, FILE *f, int first) {
L0332 int nargs = lua_gettop(L) - 1;
L0333 int success;
L0334 int n;
L0335 clearerr(f);
L0336 if (nargs == 0) { /* no arguments? */
L0337 success = read_line(L, f);
L0338 n = first+1; /* to return 1 result */
L0339 }
L0340 else { /* ensure stack space for all results and for auxlib's buffer */
L0341 luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
L0342 success = 1;
L0343 for (n = first; nargs-- && success; n++) {
L0344 if (lua_type(L, n) == LUA_TNUMBER) {
L0345 size_t l = (size_t)lua_tointeger(L, n);
L0346 success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
L0347 }
L0348 else {
L0349 const char *p = lua_tostring(L, n);
L0350 luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
L0351 switch (p[1]) {
L0352 case 'n': /* number */
L0353 success = read_number(L, f);
L0354 break;
L0355 case 'l': /* line */
L0356 success = read_line(L, f);
L0357 break;
L0358 case 'a': /* file */
L0359 read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */
L0360 success = 1; /* always success */
L0361 break;
L0362 default:
L0363 return luaL_argerror(L, n, "invalid format");
L0364 }
L0365 }
L0366 }
L0367 }
L0368 if (ferror(f))
L0369 return pushresult(L, 0, NULL);
L0370 if (!success) {
L0371 lua_pop(L, 1); /* remove last result */
L0372 lua_pushnil(L); /* push nil instead */
L0373 }
L0374 return n - first;
L0375 }
L0376
L0377
L0378 static int io_read (lua_State *L) {
L0379 return g_read(L, getiofile(L, IO_INPUT), 1);
L0380 }
L0381
L0382
L0383 static int f_read (lua_State *L) {
L0384 return g_read(L, tofile(L), 2);
L0385 }
L0386
L0387
L0388 static int io_readline (lua_State *L) {
L0389 FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
L0390 int sucess;
L0391 if (f == NULL) /* file is already closed? */
L0392 luaL_error(L, "file is already closed");
L0393 sucess = read_line(L, f);
L0394 if (ferror(f))
L0395 return luaL_error(L, "%s", strerror(errno));
L0396 if (sucess) return 1;
L0397 else { /* EOF */
L0398 if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */
L0399 lua_settop(L, 0);
L0400 lua_pushvalue(L, lua_upvalueindex(1));
L0401 aux_close(L); /* close it */
L0402 }
L0403 return 0;
L0404 }
L0405 }
L0406
L0407 /* }====================================================== */
L0408
L0409
L0410 static int g_write (lua_State *L, FILE *f, int arg) {
L0411 int nargs = lua_gettop(L) - 1;
L0412 int status = 1;
L0413 for (; nargs--; arg++) {
L0414 if (lua_type(L, arg) == LUA_TNUMBER) {
L0415 /* optimization: could be done exactly as for strings */
L0416 status = status &&
L0417 fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
L0418 }
L0419 else {
L0420 size_t l;
L0421 const char *s = luaL_checklstring(L, arg, &l);
L0422 status = status && (fwrite(s, sizeof(char), l, f) == l);
L0423 }
L0424 }
L0425 return pushresult(L, status, NULL);
L0426 }
L0427
L0428
L0429 static int io_write (lua_State *L) {
L0430 return g_write(L, getiofile(L, IO_OUTPUT), 1);
L0431 }
L0432
L0433
L0434 static int f_write (lua_State *L) {
L0435 return g_write(L, tofile(L), 2);
L0436 }
L0437
L0438
L0439 static int f_seek (lua_State *L) {
L0440 static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
L0441 static const char *const modenames[] = {"set", "cur", "end", NULL};
L0442 FILE *f = tofile(L);
L0443 int op = luaL_checkoption(L, 2, "cur", modenames);
L0444 long offset = luaL_optlong(L, 3, 0);
L0445 op = fseek(f, offset, mode[op]);
L0446 if (op)
L0447 return pushresult(L, 0, NULL); /* error */
L0448 else {
L0449 lua_pushinteger(L, ftell(f));
L0450 return 1;
L0451 }
L0452 }
L0453
L0454
L0455 static int f_setvbuf (lua_State *L) {
L0456 static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
L0457 static const char *const modenames[] = {"no", "full", "line", NULL};
L0458 FILE *f = tofile(L);
L0459 int op = luaL_checkoption(L, 2, NULL, modenames);
L0460 lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
L0461 int res = setvbuf(f, NULL, mode[op], sz);
L0462 return pushresult(L, res == 0, NULL);
L0463 }
L0464
L0465
L0466
L0467 static int io_flush (lua_State *L) {
L0468 return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
L0469 }
L0470
L0471
L0472 static int f_flush (lua_State *L) {
L0473 return pushresult(L, fflush(tofile(L)) == 0, NULL);
L0474 }
L0475
L0476
L0477 static const luaL_Reg iolib[] = {
L0478 {"close", io_close},
L0479 {"flush", io_flush},
L0480 {"input", io_input},
L0481 {"lines", io_lines},
L0482 {"open", io_open},
L0483 {"output", io_output},
L0484 {"popen", io_popen},
L0485 {"read", io_read},
L0486 {"tmpfile", io_tmpfile},
L0487 {"type", io_type},
L0488 {"write", io_write},
L0489 {NULL, NULL}
L0490 };
L0491
L0492
L0493 static const luaL_Reg flib[] = {
L0494 {"close", io_close},
L0495 {"flush", f_flush},
L0496 {"lines", f_lines},
L0497 {"read", f_read},
L0498 {"seek", f_seek},
L0499 {"setvbuf", f_setvbuf},
L0500 {"write", f_write},
L0501 {"__gc", io_gc},
L0502 {"__tostring", io_tostring},
L0503 {NULL, NULL}
L0504 };
L0505
L0506
L0507 static void createmeta (lua_State *L) {
L0508 luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
L0509 lua_pushvalue(L, -1); /* push metatable */
L0510 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
L0511 luaL_register(L, NULL, flib); /* file methods */
L0512 }
L0513
L0514
L0515 static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) {
L0516 *newfile(L) = f;
L0517 if (k > 0) {
L0518 lua_pushvalue(L, -1);
L0519 lua_rawseti(L, LUA_ENVIRONINDEX, k);
L0520 }
L0521 lua_pushvalue(L, -2); /* copy environment */
L0522 lua_setfenv(L, -2); /* set it */
L0523 lua_setfield(L, -3, fname);
L0524 }
L0525
L0526
L0527 static void newfenv (lua_State *L, lua_CFunction cls) {
L0528 lua_createtable(L, 0, 1);
L0529 lua_pushcfunction(L, cls);
L0530 lua_setfield(L, -2, "__close");
L0531 }
L0532
L0533
L0534 LUALIB_API int luaopen_io (lua_State *L) {
L0535 createmeta(L);
L0536 /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
L0537 newfenv(L, io_fclose);
L0538 lua_replace(L, LUA_ENVIRONINDEX);
L0539 /* open library */
L0540 luaL_register(L, LUA_IOLIBNAME, iolib);
L0541 /* create (and set) default files */
L0542 newfenv(L, io_noclose); /* close function for default files */
L0543 createstdfile(L, stdin, IO_INPUT, "stdin");
L0544 createstdfile(L, stdout, IO_OUTPUT, "stdout");
L0545 createstdfile(L, stderr, 0, "stderr");
L0546 lua_pop(L, 1); /* pop environment for default files */
L0547 lua_getfield(L, -1, "popen");
L0548 newfenv(L, io_pclose); /* create environment for 'popen' */
L0549 lua_setfenv(L, -2); /* set fenv for 'popen' */
L0550 lua_pop(L, 1); /* pop 'popen' */
L0551 return 1;
L0552 }
L0553
Generated by
pretty.lua