00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #if !defined(_FILE_OFFSET_BITS)
00014 #define _FILE_OFFSET_BITS 64
00015 #endif
00016
00017
00018 #include <errno.h>
00019 #include <stdio.h>
00020 #include <stdlib.h>
00021 #include <string.h>
00022
00023 #define liolib_c
00024 #define LUA_LIB
00025
00026 #include "lua.h"
00027
00028 #include "lauxlib.h"
00029 #include "lualib.h"
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #if !defined(lua_popen)
00041
00042 #if defined(LUA_USE_POPEN)
00043
00044 #define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m))
00045 #define lua_pclose(L,file) ((void)L, pclose(file))
00046
00047 #elif defined(LUA_WIN)
00048
00049 #define lua_popen(L,c,m) ((void)L, _popen(c,m))
00050 #define lua_pclose(L,file) ((void)L, _pclose(file))
00051
00052
00053 #else
00054
00055 #define lua_popen(L,c,m) ((void)((void)c, m), \
00056 luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
00057 #define lua_pclose(L,file) ((void)((void)L, file), -1)
00058
00059
00060 #endif
00061
00062 #endif
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #if !defined(lua_fseek)
00074
00075 #if defined(LUA_USE_POSIX)
00076
00077 #define l_fseek(f,o,w) fseeko(f,o,w)
00078 #define l_ftell(f) ftello(f)
00079 #define l_seeknum off_t
00080
00081 #elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \
00082 && defined(_MSC_VER) && (_MSC_VER >= 1400)
00083
00084
00085 #define l_fseek(f,o,w) _fseeki64(f,o,w)
00086 #define l_ftell(f) _ftelli64(f)
00087 #define l_seeknum __int64
00088
00089 #else
00090
00091 #define l_fseek(f,o,w) fseek(f,o,w)
00092 #define l_ftell(f) ftell(f)
00093 #define l_seeknum long
00094
00095 #endif
00096
00097 #endif
00098
00099
00100
00101
00102 #define IO_PREFIX "_IO_"
00103 #define IO_INPUT (IO_PREFIX "input")
00104 #define IO_OUTPUT (IO_PREFIX "output")
00105
00106
00107 typedef luaL_Stream LStream;
00108
00109
00110 #define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
00111
00112 #define isclosed(p) ((p)->closef == NULL)
00113
00114
00115 static int io_type (lua_State *L) {
00116 LStream *p;
00117 luaL_checkany(L, 1);
00118 p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
00119 if (p == NULL)
00120 lua_pushnil(L);
00121 else if (isclosed(p))
00122 lua_pushliteral(L, "closed file");
00123 else
00124 lua_pushliteral(L, "file");
00125 return 1;
00126 }
00127
00128
00129 static int f_tostring (lua_State *L) {
00130 LStream *p = tolstream(L);
00131 if (isclosed(p))
00132 lua_pushliteral(L, "file (closed)");
00133 else
00134 lua_pushfstring(L, "file (%p)", p->f);
00135 return 1;
00136 }
00137
00138
00139 static FILE *tofile (lua_State *L) {
00140 LStream *p = tolstream(L);
00141 if (isclosed(p))
00142 luaL_error(L, "attempt to use a closed file");
00143 lua_assert(p->f);
00144 return p->f;
00145 }
00146
00147
00148
00149
00150
00151
00152
00153 static LStream *newprefile (lua_State *L) {
00154 LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
00155 p->closef = NULL;
00156 luaL_setmetatable(L, LUA_FILEHANDLE);
00157 return p;
00158 }
00159
00160
00161 static int aux_close (lua_State *L) {
00162 LStream *p = tolstream(L);
00163 lua_CFunction cf = p->closef;
00164 p->closef = NULL;
00165 return (*cf)(L);
00166 }
00167
00168
00169 static int io_close (lua_State *L) {
00170 if (lua_isnone(L, 1))
00171 lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT);
00172 tofile(L);
00173 return aux_close(L);
00174 }
00175
00176
00177 static int f_gc (lua_State *L) {
00178 LStream *p = tolstream(L);
00179 if (!isclosed(p) && p->f != NULL)
00180 aux_close(L);
00181 return 0;
00182 }
00183
00184
00185
00186
00187
00188 static int io_fclose (lua_State *L) {
00189 LStream *p = tolstream(L);
00190 int res = fclose(p->f);
00191 return luaL_fileresult(L, (res == 0), NULL);
00192 }
00193
00194
00195 static LStream *newfile (lua_State *L) {
00196 LStream *p = newprefile(L);
00197 p->f = NULL;
00198 p->closef = &io_fclose;
00199 return p;
00200 }
00201
00202
00203 static void opencheck (lua_State *L, const char *fname, const char *mode) {
00204 LStream *p = newfile(L);
00205 p->f = fopen(fname, mode);
00206 if (p->f == NULL)
00207 luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno));
00208 }
00209
00210
00211 static int io_open (lua_State *L) {
00212 const char *filename = luaL_checkstring(L, 1);
00213 const char *mode = luaL_optstring(L, 2, "r");
00214 LStream *p = newfile(L);
00215 int i = 0;
00216
00217 if (!(mode[i] != '\0' && strchr("rwa", mode[i++]) != NULL &&
00218 (mode[i] != '+' || ++i) &&
00219 (mode[i] != 'b' || ++i) &&
00220 (mode[i] == '\0')))
00221 return luaL_error(L, "invalid mode " LUA_QS
00222 " (should match " LUA_QL("[rwa]%%+?b?") ")", mode);
00223 p->f = fopen(filename, mode);
00224 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
00225 }
00226
00227
00228
00229
00230
00231 static int io_pclose (lua_State *L) {
00232 LStream *p = tolstream(L);
00233 return luaL_execresult(L, lua_pclose(L, p->f));
00234 }
00235
00236
00237 static int io_popen (lua_State *L) {
00238 const char *filename = luaL_checkstring(L, 1);
00239 const char *mode = luaL_optstring(L, 2, "r");
00240 LStream *p = newprefile(L);
00241 p->f = lua_popen(L, filename, mode);
00242 p->closef = &io_pclose;
00243 return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
00244 }
00245
00246
00247 static int io_tmpfile (lua_State *L) {
00248 LStream *p = newfile(L);
00249 p->f = tmpfile();
00250 return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
00251 }
00252
00253
00254 static FILE *getiofile (lua_State *L, const char *findex) {
00255 LStream *p;
00256 lua_getfield(L, LUA_REGISTRYINDEX, findex);
00257 p = (LStream *)lua_touserdata(L, -1);
00258 if (isclosed(p))
00259 luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX));
00260 return p->f;
00261 }
00262
00263
00264 static int g_iofile (lua_State *L, const char *f, const char *mode) {
00265 if (!lua_isnoneornil(L, 1)) {
00266 const char *filename = lua_tostring(L, 1);
00267 if (filename)
00268 opencheck(L, filename, mode);
00269 else {
00270 tofile(L);
00271 lua_pushvalue(L, 1);
00272 }
00273 lua_setfield(L, LUA_REGISTRYINDEX, f);
00274 }
00275
00276 lua_getfield(L, LUA_REGISTRYINDEX, f);
00277 return 1;
00278 }
00279
00280
00281 static int io_input (lua_State *L) {
00282 return g_iofile(L, IO_INPUT, "r");
00283 }
00284
00285
00286 static int io_output (lua_State *L) {
00287 return g_iofile(L, IO_OUTPUT, "w");
00288 }
00289
00290
00291 static int io_readline (lua_State *L);
00292
00293
00294 static void aux_lines (lua_State *L, int toclose) {
00295 int i;
00296 int n = lua_gettop(L) - 1;
00297
00298 luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options");
00299 lua_pushvalue(L, 1);
00300 lua_pushinteger(L, n);
00301 lua_pushboolean(L, toclose);
00302 for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1);
00303 lua_pushcclosure(L, io_readline, 3 + n);
00304 }
00305
00306
00307 static int f_lines (lua_State *L) {
00308 tofile(L);
00309 aux_lines(L, 0);
00310 return 1;
00311 }
00312
00313
00314 static int io_lines (lua_State *L) {
00315 int toclose;
00316 if (lua_isnone(L, 1)) lua_pushnil(L);
00317 if (lua_isnil(L, 1)) {
00318 lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT);
00319 lua_replace(L, 1);
00320 tofile(L);
00321 toclose = 0;
00322 }
00323 else {
00324 const char *filename = luaL_checkstring(L, 1);
00325 opencheck(L, filename, "r");
00326 lua_replace(L, 1);
00327 toclose = 1;
00328 }
00329 aux_lines(L, toclose);
00330 return 1;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 static int read_number (lua_State *L, FILE *f) {
00342 lua_Number d;
00343 if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
00344 lua_pushnumber(L, d);
00345 return 1;
00346 }
00347 else {
00348 lua_pushnil(L);
00349 return 0;
00350 }
00351 }
00352
00353
00354 static int test_eof (lua_State *L, FILE *f) {
00355 int c = getc(f);
00356 ungetc(c, f);
00357 lua_pushlstring(L, NULL, 0);
00358 return (c != EOF);
00359 }
00360
00361
00362 static int read_line (lua_State *L, FILE *f, int chop) {
00363 luaL_Buffer b;
00364 luaL_buffinit(L, &b);
00365 for (;;) {
00366 size_t l;
00367 char *p = luaL_prepbuffer(&b);
00368 if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {
00369 luaL_pushresult(&b);
00370 return (lua_rawlen(L, -1) > 0);
00371 }
00372 l = strlen(p);
00373 if (l == 0 || p[l-1] != '\n')
00374 luaL_addsize(&b, l);
00375 else {
00376 luaL_addsize(&b, l - chop);
00377 luaL_pushresult(&b);
00378 return 1;
00379 }
00380 }
00381 }
00382
00383
00384 #define MAX_SIZE_T (~(size_t)0)
00385
00386 static void read_all (lua_State *L, FILE *f) {
00387 size_t rlen = LUAL_BUFFERSIZE;
00388 luaL_Buffer b;
00389 luaL_buffinit(L, &b);
00390 for (;;) {
00391 char *p = luaL_prepbuffsize(&b, rlen);
00392 size_t nr = fread(p, sizeof(char), rlen, f);
00393 luaL_addsize(&b, nr);
00394 if (nr < rlen) break;
00395 else if (rlen <= (MAX_SIZE_T / 4))
00396 rlen *= 2;
00397 }
00398 luaL_pushresult(&b);
00399 }
00400
00401
00402 static int read_chars (lua_State *L, FILE *f, size_t n) {
00403 size_t nr;
00404 char *p;
00405 luaL_Buffer b;
00406 luaL_buffinit(L, &b);
00407 p = luaL_prepbuffsize(&b, n);
00408 nr = fread(p, sizeof(char), n, f);
00409 luaL_addsize(&b, nr);
00410 luaL_pushresult(&b);
00411 return (nr > 0);
00412 }
00413
00414
00415 static int g_read (lua_State *L, FILE *f, int first) {
00416 int nargs = lua_gettop(L) - 1;
00417 int success;
00418 int n;
00419 clearerr(f);
00420 if (nargs == 0) {
00421 success = read_line(L, f, 1);
00422 n = first+1;
00423 }
00424 else {
00425 luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
00426 success = 1;
00427 for (n = first; nargs-- && success; n++) {
00428 if (lua_type(L, n) == LUA_TNUMBER) {
00429 size_t l = (size_t)lua_tointeger(L, n);
00430 success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
00431 }
00432 else {
00433 const char *p = lua_tostring(L, n);
00434 luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
00435 switch (p[1]) {
00436 case 'n':
00437 success = read_number(L, f);
00438 break;
00439 case 'l':
00440 success = read_line(L, f, 1);
00441 break;
00442 case 'L':
00443 success = read_line(L, f, 0);
00444 break;
00445 case 'a':
00446 read_all(L, f);
00447 success = 1;
00448 break;
00449 default:
00450 return luaL_argerror(L, n, "invalid format");
00451 }
00452 }
00453 }
00454 }
00455 if (ferror(f))
00456 return luaL_fileresult(L, 0, NULL);
00457 if (!success) {
00458 lua_pop(L, 1);
00459 lua_pushnil(L);
00460 }
00461 return n - first;
00462 }
00463
00464
00465 static int io_read (lua_State *L) {
00466 return g_read(L, getiofile(L, IO_INPUT), 1);
00467 }
00468
00469
00470 static int f_read (lua_State *L) {
00471 return g_read(L, tofile(L), 2);
00472 }
00473
00474
00475 static int io_readline (lua_State *L) {
00476 LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
00477 int i;
00478 int n = (int)lua_tointeger(L, lua_upvalueindex(2));
00479 if (isclosed(p))
00480 return luaL_error(L, "file is already closed");
00481 lua_settop(L , 1);
00482 for (i = 1; i <= n; i++)
00483 lua_pushvalue(L, lua_upvalueindex(3 + i));
00484 n = g_read(L, p->f, 2);
00485 lua_assert(n > 0);
00486 if (!lua_isnil(L, -n))
00487 return n;
00488 else {
00489 if (n > 1) {
00490
00491 return luaL_error(L, "%s", lua_tostring(L, -n + 1));
00492 }
00493 if (lua_toboolean(L, lua_upvalueindex(3))) {
00494 lua_settop(L, 0);
00495 lua_pushvalue(L, lua_upvalueindex(1));
00496 aux_close(L);
00497 }
00498 return 0;
00499 }
00500 }
00501
00502
00503
00504
00505 static int g_write (lua_State *L, FILE *f, int arg) {
00506 int nargs = lua_gettop(L) - arg;
00507 int status = 1;
00508 for (; nargs--; arg++) {
00509 if (lua_type(L, arg) == LUA_TNUMBER) {
00510
00511 status = status &&
00512 fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
00513 }
00514 else {
00515 size_t l;
00516 const char *s = luaL_checklstring(L, arg, &l);
00517 status = status && (fwrite(s, sizeof(char), l, f) == l);
00518 }
00519 }
00520 if (status) return 1;
00521 else return luaL_fileresult(L, status, NULL);
00522 }
00523
00524
00525 static int io_write (lua_State *L) {
00526 return g_write(L, getiofile(L, IO_OUTPUT), 1);
00527 }
00528
00529
00530 static int f_write (lua_State *L) {
00531 FILE *f = tofile(L);
00532 lua_pushvalue(L, 1);
00533 return g_write(L, f, 2);
00534 }
00535
00536
00537 static int f_seek (lua_State *L) {
00538 static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
00539 static const char *const modenames[] = {"set", "cur", "end", NULL};
00540 FILE *f = tofile(L);
00541 int op = luaL_checkoption(L, 2, "cur", modenames);
00542 lua_Number p3 = luaL_optnumber(L, 3, 0);
00543 l_seeknum offset = (l_seeknum)p3;
00544 luaL_argcheck(L, (lua_Number)offset == p3, 3,
00545 "not an integer in proper range");
00546 op = l_fseek(f, offset, mode[op]);
00547 if (op)
00548 return luaL_fileresult(L, 0, NULL);
00549 else {
00550 lua_pushnumber(L, (lua_Number)l_ftell(f));
00551 return 1;
00552 }
00553 }
00554
00555
00556 static int f_setvbuf (lua_State *L) {
00557 static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
00558 static const char *const modenames[] = {"no", "full", "line", NULL};
00559 FILE *f = tofile(L);
00560 int op = luaL_checkoption(L, 2, NULL, modenames);
00561 lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
00562 int res = setvbuf(f, NULL, mode[op], sz);
00563 return luaL_fileresult(L, res == 0, NULL);
00564 }
00565
00566
00567
00568 static int io_flush (lua_State *L) {
00569 return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
00570 }
00571
00572
00573 static int f_flush (lua_State *L) {
00574 return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
00575 }
00576
00577
00578
00579
00580
00581 static const luaL_Reg iolib[] = {
00582 {"close", io_close},
00583 {"flush", io_flush},
00584 {"input", io_input},
00585 {"lines", io_lines},
00586 {"open", io_open},
00587 {"output", io_output},
00588 {"popen", io_popen},
00589 {"read", io_read},
00590 {"tmpfile", io_tmpfile},
00591 {"type", io_type},
00592 {"write", io_write},
00593 {NULL, NULL}
00594 };
00595
00596
00597
00598
00599
00600 static const luaL_Reg flib[] = {
00601 {"close", io_close},
00602 {"flush", f_flush},
00603 {"lines", f_lines},
00604 {"read", f_read},
00605 {"seek", f_seek},
00606 {"setvbuf", f_setvbuf},
00607 {"write", f_write},
00608 {"__gc", f_gc},
00609 {"__tostring", f_tostring},
00610 {NULL, NULL}
00611 };
00612
00613
00614 static void createmeta (lua_State *L) {
00615 luaL_newmetatable(L, LUA_FILEHANDLE);
00616 lua_pushvalue(L, -1);
00617 lua_setfield(L, -2, "__index");
00618 luaL_setfuncs(L, flib, 0);
00619 lua_pop(L, 1);
00620 }
00621
00622
00623
00624
00625
00626 static int io_noclose (lua_State *L) {
00627 LStream *p = tolstream(L);
00628 p->closef = &io_noclose;
00629 lua_pushnil(L);
00630 lua_pushliteral(L, "cannot close standard file");
00631 return 2;
00632 }
00633
00634
00635 static void createstdfile (lua_State *L, FILE *f, const char *k,
00636 const char *fname) {
00637 LStream *p = newprefile(L);
00638 p->f = f;
00639 p->closef = &io_noclose;
00640 if (k != NULL) {
00641 lua_pushvalue(L, -1);
00642 lua_setfield(L, LUA_REGISTRYINDEX, k);
00643 }
00644 lua_setfield(L, -2, fname);
00645 }
00646
00647
00648 LUAMOD_API int luaopen_io (lua_State *L) {
00649 luaL_newlib(L, iolib);
00650 createmeta(L);
00651
00652 createstdfile(L, stdin, IO_INPUT, "stdin");
00653 createstdfile(L, stdout, IO_OUTPUT, "stdout");
00654 createstdfile(L, stderr, NULL, "stderr");
00655 return 1;
00656 }
00657