liolib.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. /*
  2. ** $Id: liolib.c,v 2.73.1.4 2010/05/14 15:33:51 roberto Exp $
  3. ** Standard I/O (and system) library
  4. ** See Copyright Notice in lua.h
  5. */
  6. #include <errno.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #define liolib_c
  11. #define LUA_LIB
  12. #include "lua.h"
  13. #include "lauxlib.h"
  14. #include "lualib.h"
  15. #include "lrotable.h"
  16. #define IO_INPUT 1
  17. #define IO_OUTPUT 2
  18. #define IO_STDERR 0
  19. #if LUA_OPTIMIZE_MEMORY != 2
  20. #define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_ENVIRONINDEX, f)
  21. #define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_ENVIRONINDEX, f)
  22. #else
  23. #define LUA_IO_GETFIELD(f) lua_rawgeti(L, LUA_REGISTRYINDEX, liolib_keys[f])
  24. #define LUA_IO_SETFIELD(f) lua_rawseti(L, LUA_REGISTRYINDEX, liolib_keys[f])
  25. /* "Pseudo-random" keys for the registry */
  26. static const int liolib_keys[] = {(int) &luaL_callmeta, (int) &luaL_typerror, (int) &luaL_argerror};
  27. #endif
  28. static const char *const fnames[] = {"input", "output"};
  29. static int pushresult(lua_State *L, int i, const char *filename)
  30. {
  31. int en = errno; /* calls to Lua API may change this value */
  32. if (i)
  33. {
  34. lua_pushboolean(L, 1);
  35. return 1;
  36. }
  37. else
  38. {
  39. lua_pushnil(L);
  40. if (filename)
  41. lua_pushfstring(L, "%s: %s", filename, strerror(en));
  42. else
  43. lua_pushfstring(L, "%s", strerror(en));
  44. lua_pushinteger(L, en);
  45. return 3;
  46. }
  47. }
  48. static void fileerror(lua_State *L, int arg, const char *filename)
  49. {
  50. lua_pushfstring(L, "%s: %s", filename, strerror(errno));
  51. luaL_argerror(L, arg, lua_tostring(L, -1));
  52. }
  53. #define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE))
  54. static int io_type(lua_State *L)
  55. {
  56. void *ud;
  57. luaL_checkany(L, 1);
  58. ud = lua_touserdata(L, 1);
  59. lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE);
  60. if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1))
  61. lua_pushnil(L); /* not a file */
  62. else if (*((FILE **)ud) == NULL)
  63. lua_pushliteral(L, "closed file");
  64. else
  65. lua_pushliteral(L, "file");
  66. return 1;
  67. }
  68. static FILE *tofile(lua_State *L)
  69. {
  70. FILE **f = tofilep(L);
  71. if (*f == NULL)
  72. luaL_error(L, "attempt to use a closed file");
  73. return *f;
  74. }
  75. /*
  76. ** When creating file handles, always creates a `closed' file handle
  77. ** before opening the actual file; so, if there is a memory error, the
  78. ** file is not left opened.
  79. */
  80. static FILE **newfile(lua_State *L)
  81. {
  82. FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *));
  83. *pf = NULL; /* file handle is currently `closed' */
  84. luaL_getmetatable(L, LUA_FILEHANDLE);
  85. lua_setmetatable(L, -2);
  86. return pf;
  87. }
  88. #if LUA_OPTIMIZE_MEMORY != 2
  89. /*
  90. ** function to (not) close the standard files stdin, stdout, and stderr
  91. */
  92. static int io_noclose(lua_State *L)
  93. {
  94. lua_pushnil(L);
  95. lua_pushliteral(L, "cannot close standard file");
  96. return 2;
  97. }
  98. /*
  99. ** function to close 'popen' files
  100. */
  101. static int io_pclose(lua_State *L)
  102. {
  103. FILE **p = tofilep(L);
  104. int ok = lua_pclose(L, *p);
  105. *p = NULL;
  106. return pushresult(L, ok, NULL);
  107. }
  108. /*
  109. ** function to close regular files
  110. */
  111. static int io_fclose(lua_State *L)
  112. {
  113. FILE **p = tofilep(L);
  114. int ok = (fclose(*p) == 0);
  115. *p = NULL;
  116. return pushresult(L, ok, NULL);
  117. }
  118. #endif
  119. static int aux_close(lua_State *L)
  120. {
  121. #if LUA_OPTIMIZE_MEMORY != 2
  122. lua_getfenv(L, 1);
  123. lua_getfield(L, -1, "__close");
  124. return (lua_tocfunction(L, -1))(L);
  125. #else
  126. FILE **p = tofilep(L);
  127. if (*p == stdin || *p == stdout || *p == stderr)
  128. {
  129. lua_pushnil(L);
  130. lua_pushliteral(L, "cannot close standard file");
  131. return 2;
  132. }
  133. int ok = (fclose(*p) == 0);
  134. *p = NULL;
  135. return pushresult(L, ok, NULL);
  136. #endif
  137. }
  138. static int io_close(lua_State *L)
  139. {
  140. if (lua_isnone(L, 1))
  141. LUA_IO_GETFIELD(IO_OUTPUT);
  142. tofile(L); /* make sure argument is a file */
  143. return aux_close(L);
  144. }
  145. static int io_gc(lua_State *L)
  146. {
  147. FILE *f = *tofilep(L);
  148. /* ignore closed files */
  149. if (f != NULL)
  150. aux_close(L);
  151. return 0;
  152. }
  153. static int io_tostring(lua_State *L)
  154. {
  155. FILE *f = *tofilep(L);
  156. if (f == NULL)
  157. lua_pushliteral(L, "file (closed)");
  158. else
  159. lua_pushfstring(L, "file (%p)", f);
  160. return 1;
  161. }
  162. static int io_open(lua_State *L)
  163. {
  164. const char *filename = luaL_checkstring(L, 1);
  165. const char *mode = luaL_optstring(L, 2, "r");
  166. FILE **pf = newfile(L);
  167. *pf = fopen(filename, mode);
  168. return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
  169. }
  170. /*
  171. ** this function has a separated environment, which defines the
  172. ** correct __close for 'popen' files
  173. */
  174. static int io_popen(lua_State *L)
  175. {
  176. const char *filename = luaL_checkstring(L, 1);
  177. const char *mode = luaL_optstring(L, 2, "r");
  178. FILE **pf = newfile(L);
  179. *pf = lua_popen(L, filename, mode);
  180. return (*pf == NULL) ? pushresult(L, 0, filename) : 1;
  181. }
  182. static int io_tmpfile(lua_State *L)
  183. {
  184. FILE **pf = newfile(L);
  185. *pf = tmpfile();
  186. return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;
  187. }
  188. static FILE *getiofile(lua_State *L, int findex)
  189. {
  190. FILE *f;
  191. LUA_IO_GETFIELD(findex);
  192. f = *(FILE **)lua_touserdata(L, -1);
  193. if (f == NULL)
  194. luaL_error(L, "standard %s file is closed", fnames[findex - 1]);
  195. return f;
  196. }
  197. static int g_iofile(lua_State *L, int f, const char *mode)
  198. {
  199. if (!lua_isnoneornil(L, 1))
  200. {
  201. const char *filename = lua_tostring(L, 1);
  202. if (filename)
  203. {
  204. FILE **pf = newfile(L);
  205. *pf = fopen(filename, mode);
  206. if (*pf == NULL)
  207. fileerror(L, 1, filename);
  208. }
  209. else
  210. {
  211. tofile(L); /* check that it's a valid file handle */
  212. lua_pushvalue(L, 1);
  213. }
  214. LUA_IO_SETFIELD(f);
  215. }
  216. /* return current value */
  217. LUA_IO_GETFIELD(f);
  218. return 1;
  219. }
  220. static int io_input(lua_State *L)
  221. {
  222. return g_iofile(L, IO_INPUT, "r");
  223. }
  224. static int io_output(lua_State *L)
  225. {
  226. return g_iofile(L, IO_OUTPUT, "w");
  227. }
  228. static int io_readline(lua_State *L);
  229. static void aux_lines(lua_State *L, int idx, int toclose)
  230. {
  231. lua_pushvalue(L, idx);
  232. lua_pushboolean(L, toclose); /* close/not close file when finished */
  233. lua_pushcclosure(L, io_readline, 2);
  234. }
  235. static int f_lines(lua_State *L)
  236. {
  237. tofile(L); /* check that it's a valid file handle */
  238. aux_lines(L, 1, 0);
  239. return 1;
  240. }
  241. static int io_lines(lua_State *L)
  242. {
  243. if (lua_isnoneornil(L, 1)) /* no arguments? */
  244. {
  245. /* will iterate over default input */
  246. LUA_IO_GETFIELD(IO_INPUT);
  247. return f_lines(L);
  248. }
  249. else
  250. {
  251. const char *filename = luaL_checkstring(L, 1);
  252. FILE **pf = newfile(L);
  253. *pf = fopen(filename, "r");
  254. if (*pf == NULL)
  255. fileerror(L, 1, filename);
  256. aux_lines(L, lua_gettop(L), 1);
  257. return 1;
  258. }
  259. }
  260. /*
  261. ** {======================================================
  262. ** READ
  263. ** =======================================================
  264. */
  265. static int read_number(lua_State *L, FILE *f)
  266. {
  267. lua_Number d;
  268. if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1)
  269. {
  270. lua_pushnumber(L, d);
  271. return 1;
  272. }
  273. else
  274. {
  275. lua_pushnil(L); /* "result" to be removed */
  276. return 0; /* read fails */
  277. }
  278. }
  279. static int test_eof(lua_State *L, FILE *f)
  280. {
  281. int c = getc(f);
  282. ungetc(c, f);
  283. lua_pushlstring(L, NULL, 0);
  284. return (c != EOF);
  285. }
  286. static int read_line(lua_State *L, FILE *f)
  287. {
  288. luaL_Buffer b;
  289. luaL_buffinit(L, &b);
  290. for (;;)
  291. {
  292. size_t l;
  293. char *p = luaL_prepbuffer(&b);
  294. if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) /* eof? */
  295. {
  296. luaL_pushresult(&b); /* close buffer */
  297. return (lua_objlen(L, -1) > 0); /* check whether read something */
  298. }
  299. l = strlen(p);
  300. if (l == 0 || p[l - 1] != '\n')
  301. luaL_addsize(&b, l);
  302. else
  303. {
  304. luaL_addsize(&b, l - 1); /* do not include `eol' */
  305. luaL_pushresult(&b); /* close buffer */
  306. return 1; /* read at least an `eol' */
  307. }
  308. }
  309. }
  310. static int read_chars(lua_State *L, FILE *f, size_t n)
  311. {
  312. size_t rlen; /* how much to read */
  313. size_t nr; /* number of chars actually read */
  314. luaL_Buffer b;
  315. luaL_buffinit(L, &b);
  316. rlen = LUAL_BUFFERSIZE; /* try to read that much each time */
  317. do
  318. {
  319. char *p = luaL_prepbuffer(&b);
  320. if (rlen > n) rlen = n; /* cannot read more than asked */
  321. nr = fread(p, sizeof(char), rlen, f);
  322. luaL_addsize(&b, nr);
  323. n -= nr; /* still have to read `n' chars */
  324. }
  325. while (n > 0 && nr == rlen); /* until end of count or eof */
  326. luaL_pushresult(&b); /* close buffer */
  327. return (n == 0 || lua_objlen(L, -1) > 0);
  328. }
  329. static int g_read(lua_State *L, FILE *f, int first)
  330. {
  331. int nargs = lua_gettop(L) - 1;
  332. int success;
  333. int n;
  334. clearerr(f);
  335. if (nargs == 0) /* no arguments? */
  336. {
  337. success = read_line(L, f);
  338. n = first + 1; /* to return 1 result */
  339. }
  340. else /* ensure stack space for all results and for auxlib's buffer */
  341. {
  342. luaL_checkstack(L, nargs + LUA_MINSTACK, "too many arguments");
  343. success = 1;
  344. for (n = first; nargs-- && success; n++)
  345. {
  346. if (lua_type(L, n) == LUA_TNUMBER)
  347. {
  348. size_t l = (size_t)lua_tointeger(L, n);
  349. success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
  350. }
  351. else
  352. {
  353. const char *p = lua_tostring(L, n);
  354. luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
  355. switch (p[1])
  356. {
  357. case 'n': /* number */
  358. success = read_number(L, f);
  359. break;
  360. case 'l': /* line */
  361. success = read_line(L, f);
  362. break;
  363. case 'a': /* file */
  364. read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */
  365. success = 1; /* always success */
  366. break;
  367. default:
  368. return luaL_argerror(L, n, "invalid format");
  369. }
  370. }
  371. }
  372. }
  373. if (ferror(f))
  374. return pushresult(L, 0, NULL);
  375. if (!success)
  376. {
  377. lua_pop(L, 1); /* remove last result */
  378. lua_pushnil(L); /* push nil instead */
  379. }
  380. return n - first;
  381. }
  382. static int io_read(lua_State *L)
  383. {
  384. return g_read(L, getiofile(L, IO_INPUT), 1);
  385. }
  386. static int f_read(lua_State *L)
  387. {
  388. return g_read(L, tofile(L), 2);
  389. }
  390. static int io_readline(lua_State *L)
  391. {
  392. FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1));
  393. int sucess;
  394. if (f == NULL) /* file is already closed? */
  395. luaL_error(L, "file is already closed");
  396. sucess = read_line(L, f);
  397. if (ferror(f))
  398. return luaL_error(L, "%s", strerror(errno));
  399. if (sucess) return 1;
  400. else /* EOF */
  401. {
  402. if (lua_toboolean(L, lua_upvalueindex(2))) /* generator created file? */
  403. {
  404. lua_settop(L, 0);
  405. lua_pushvalue(L, lua_upvalueindex(1));
  406. aux_close(L); /* close it */
  407. }
  408. return 0;
  409. }
  410. }
  411. /* }====================================================== */
  412. static int g_write(lua_State *L, FILE *f, int arg)
  413. {
  414. int nargs = lua_gettop(L) - 1;
  415. int status = 1;
  416. for (; nargs--; arg++)
  417. {
  418. if (lua_type(L, arg) == LUA_TNUMBER)
  419. {
  420. /* optimization: could be done exactly as for strings */
  421. status = status &&
  422. fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
  423. }
  424. else
  425. {
  426. size_t l;
  427. const char *s = luaL_checklstring(L, arg, &l);
  428. status = status && (fwrite(s, sizeof(char), l, f) == l);
  429. }
  430. }
  431. return pushresult(L, status, NULL);
  432. }
  433. static int io_write(lua_State *L)
  434. {
  435. return g_write(L, getiofile(L, IO_OUTPUT), 1);
  436. }
  437. static int f_write(lua_State *L)
  438. {
  439. return g_write(L, tofile(L), 2);
  440. }
  441. static int f_seek(lua_State *L)
  442. {
  443. static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
  444. static const char *const modenames[] = {"set", "cur", "end", NULL};
  445. FILE *f = tofile(L);
  446. int op = luaL_checkoption(L, 2, "cur", modenames);
  447. long offset = luaL_optlong(L, 3, 0);
  448. op = fseek(f, offset, mode[op]);
  449. if (op)
  450. return pushresult(L, 0, NULL); /* error */
  451. else
  452. {
  453. lua_pushinteger(L, ftell(f));
  454. return 1;
  455. }
  456. }
  457. static int f_setvbuf(lua_State *L)
  458. {
  459. static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
  460. static const char *const modenames[] = {"no", "full", "line", NULL};
  461. FILE *f = tofile(L);
  462. int op = luaL_checkoption(L, 2, NULL, modenames);
  463. lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
  464. int res = setvbuf(f, NULL, mode[op], sz);
  465. return pushresult(L, res == 0, NULL);
  466. }
  467. static int io_flush(lua_State *L)
  468. {
  469. return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
  470. }
  471. static int f_flush(lua_State *L)
  472. {
  473. return pushresult(L, fflush(tofile(L)) == 0, NULL);
  474. }
  475. #define MIN_OPT_LEVEL 2
  476. #include "lrodefs.h"
  477. #if LUA_OPTIMIZE_MEMORY == 2
  478. const LUA_REG_TYPE iolib_funcs[] =
  479. {
  480. #else
  481. const LUA_REG_TYPE iolib[] =
  482. {
  483. #endif
  484. {LSTRKEY("close"), LFUNCVAL(io_close)},
  485. {LSTRKEY("flush"), LFUNCVAL(io_flush)},
  486. {LSTRKEY("input"), LFUNCVAL(io_input)},
  487. {LSTRKEY("lines"), LFUNCVAL(io_lines)},
  488. {LSTRKEY("open"), LFUNCVAL(io_open)},
  489. {LSTRKEY("output"), LFUNCVAL(io_output)},
  490. {LSTRKEY("popen"), LFUNCVAL(io_popen)},
  491. {LSTRKEY("read"), LFUNCVAL(io_read)},
  492. {LSTRKEY("tmpfile"), LFUNCVAL(io_tmpfile)},
  493. {LSTRKEY("type"), LFUNCVAL(io_type)},
  494. {LSTRKEY("write"), LFUNCVAL(io_write)},
  495. {LNILKEY, LNILVAL}
  496. };
  497. #if LUA_OPTIMIZE_MEMORY == 2
  498. static int luaL_index(lua_State *L)
  499. {
  500. return luaR_findfunction(L, iolib_funcs);
  501. }
  502. const luaL_Reg iolib[] =
  503. {
  504. {"__index", luaL_index},
  505. {NULL, NULL}
  506. };
  507. #endif
  508. #undef MIN_OPT_LEVEL
  509. #define MIN_OPT_LEVEL 1
  510. #include "lrodefs.h"
  511. const LUA_REG_TYPE flib[] =
  512. {
  513. {LSTRKEY("close") , LFUNCVAL(io_close) },
  514. {LSTRKEY("flush") , LFUNCVAL(f_flush) },
  515. {LSTRKEY("lines") , LFUNCVAL(f_lines) },
  516. {LSTRKEY("read") , LFUNCVAL(f_read) },
  517. {LSTRKEY("seek") , LFUNCVAL(f_seek) },
  518. {LSTRKEY("setvbuf") , LFUNCVAL(f_setvbuf) },
  519. {LSTRKEY("write") , LFUNCVAL(f_write) },
  520. {LSTRKEY("__gc") , LFUNCVAL(io_gc) },
  521. {LSTRKEY("__tostring"), LFUNCVAL(io_tostring)},
  522. #if LUA_OPTIMIZE_MEMORY > 0
  523. {LSTRKEY("__index") , LROVAL(flib) },
  524. #endif
  525. {LNILKEY, LNILVAL}
  526. };
  527. static void createmeta(lua_State *L)
  528. {
  529. #if LUA_OPTIMIZE_MEMORY == 0
  530. luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
  531. lua_pushvalue(L, -1); /* push metatable */
  532. lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
  533. luaL_register(L, NULL, flib); /* file methods */
  534. #else
  535. luaL_rometatable(L, LUA_FILEHANDLE, (void *)flib); /* create metatable for file handles */
  536. #endif
  537. }
  538. static void createstdfile(lua_State *L, FILE *f, int k, const char *fname)
  539. {
  540. *newfile(L) = f;
  541. #if LUA_OPTIMIZE_MEMORY != 2
  542. if (k > 0)
  543. {
  544. lua_pushvalue(L, -1);
  545. lua_rawseti(L, LUA_ENVIRONINDEX, k);
  546. }
  547. lua_pushvalue(L, -2); /* copy environment */
  548. lua_setfenv(L, -2); /* set it */
  549. lua_setfield(L, -3, fname);
  550. #else
  551. lua_pushvalue(L, -1);
  552. lua_rawseti(L, LUA_REGISTRYINDEX, liolib_keys[k]);
  553. lua_setfield(L, -2, fname);
  554. #endif
  555. }
  556. #if LUA_OPTIMIZE_MEMORY != 2
  557. static void newfenv(lua_State *L, lua_CFunction cls)
  558. {
  559. lua_createtable(L, 0, 1);
  560. lua_pushcfunction(L, cls);
  561. lua_setfield(L, -2, "__close");
  562. }
  563. #endif
  564. LUALIB_API int luaopen_io(lua_State *L)
  565. {
  566. createmeta(L);
  567. #if LUA_OPTIMIZE_MEMORY != 2
  568. /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */
  569. newfenv(L, io_fclose);
  570. lua_replace(L, LUA_ENVIRONINDEX);
  571. /* open library */
  572. luaL_register(L, LUA_IOLIBNAME, iolib);
  573. newfenv(L, io_noclose); /* close function for default files */
  574. #else
  575. luaL_register_light(L, LUA_IOLIBNAME, iolib);
  576. lua_pushvalue(L, -1);
  577. lua_setmetatable(L, -2);
  578. #endif
  579. /* create (and set) default files */
  580. createstdfile(L, stdin, IO_INPUT, "stdin");
  581. createstdfile(L, stdout, IO_OUTPUT, "stdout");
  582. createstdfile(L, stderr, IO_STDERR, "stderr");
  583. #if LUA_OPTIMIZE_MEMORY != 2
  584. lua_pop(L, 1); /* pop environment for default files */
  585. lua_getfield(L, -1, "popen");
  586. newfenv(L, io_pclose); /* create environment for 'popen' */
  587. lua_setfenv(L, -2); /* set fenv for 'popen' */
  588. lua_pop(L, 1); /* pop 'popen' */
  589. #endif
  590. return 1;
  591. }