Lua 5.1.4: liolib.c
L0001
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;
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);
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
L0086 static FILE **newfile (lua_State *L) {
L0087 FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
L0088 *pf = NULL;
L0089 luaL_getmetatable(L, LUA_FILEHANDLE);
L0090 lua_setmetatable(L, -2);
L0091 return pf;
L0092 }
L0093
L0094
L0095
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
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
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);
L0138 return aux_close(L);
L0139 }
L0140
L0141
L0142 static int io_gc (lua_State *L) {
L0143 FILE *f = *tofilep(L);
L0144
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
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);
L0211 lua_pushvalue(L, 1);
L0212 }
L0213 lua_rawseti(L, LUA_ENVIRONINDEX, f);
L0214 }
L0215
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);
L0237 lua_pushcclosure(L, io_readline, 2);
L0238 }
L0239
L0240
L0241 static int f_lines (lua_State *L) {
L0242 tofile(L);
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)) {
L0250
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
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;
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) {
L0298 luaL_pushresult(&b);
L0299 return (lua_objlen(L, -1) > 0);
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);
L0306 luaL_pushresult(&b);
L0307 return 1;
L0308 }
L0309 }
L0310 }
L0311
L0312
L0313 static int read_chars (lua_State *L, FILE *f, size_t n) {
L0314 size_t rlen;
L0315 size_t nr;
L0316 luaL_Buffer b;
L0317 luaL_buffinit(L, &b);
L0318 rlen = LUAL_BUFFERSIZE;
L0319 do {
L0320 char *p = luaL_prepbuffer(&b);
L0321 if (rlen > n) rlen = n;
L0322 nr = fread(p, sizeof(char), rlen, f);
L0323 luaL_addsize(&b, nr);
L0324 n -= nr;
L0325 } while (n > 0 && nr == rlen);
L0326 luaL_pushresult(&b);
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) {
L0337 success = read_line(L, f);
L0338 n = first+1;
L0339 }
L0340 else {
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':
L0353 success = read_number(L, f);
L0354 break;
L0355 case 'l':
L0356 success = read_line(L, f);
L0357 break;
L0358 case 'a':
L0359 read_chars(L, f, ~((size_t)0));
L0360 success = 1;
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);
L0372 lua_pushnil(L);
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)
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 {
L0398 if (lua_toboolean(L, lua_upvalueindex(2))) {
L0399 lua_settop(L, 0);
L0400 lua_pushvalue(L, lua_upvalueindex(1));
L0401 aux_close(L);
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
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);
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);
L0509 lua_pushvalue(L, -1);
L0510 lua_setfield(L, -2, "__index");
L0511 luaL_register(L, NULL, flib);
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);
L0522 lua_setfenv(L, -2);
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
L0537 newfenv(L, io_fclose);
L0538 lua_replace(L, LUA_ENVIRONINDEX);
L0539
L0540 luaL_register(L, LUA_IOLIBNAME, iolib);
L0541
L0542 newfenv(L, io_noclose);
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);
L0547 lua_getfield(L, -1, "popen");
L0548 newfenv(L, io_pclose);
L0549 lua_setfenv(L, -2);
L0550 lua_pop(L, 1);
L0551 return 1;
L0552 }
L0553
Generated by pretty.lua