00001 /* 00002 ** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ 00003 ** Standard I/O (and system) library 00004 ** See Copyright Notice in lua.h 00005 */ 00006 00007 00008 #include <errno.h> 00009 #include <stdio.h> 00010 #include <stdlib.h> 00011 #include <string.h> 00012 00013 #define liolib_c 00014 #define LUA_LIB 00015 00016 #include "lua.h" 00017 00018 #include "lauxlib.h" 00019 #include "lualib.h" 00020 00021 00022 00023 #define IO_INPUT 1 00024 #define IO_OUTPUT 2 00025 00026 00027 static const char *const fnames[] = {"input", "output"}; 00028 00029 00030 static int pushresult (lua_State *L, int i, const char *filename) { 00031 int en = errno; /* calls to Lua API may change this value */ 00032 if (i) { 00033 lua_pushboolean(L, 1); 00034 return 1; 00035 } 00036 else { 00037 lua_pushnil(L); 00038 if (filename) 00039 lua_pushfstring(L, "%s: %s", filename, strerror(en)); 00040 else 00041 lua_pushfstring(L, "%s", strerror(en)); 00042 lua_pushinteger(L, en); 00043 return 3; 00044 } 00045 } 00046 00047 00048 static void fileerror (lua_State *L, int arg, const char *filename) { 00049 lua_pushfstring(L, "%s: %s", filename, strerror(errno)); 00050 luaL_argerror(L, arg, lua_tostring(L, -1)); 00051 } 00052 00053 00054 #define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) 00055 00056 00057 static int io_type (lua_State *L) { 00058 void *ud; 00059 luaL_checkany(L, 1); 00060 ud = lua_touserdata(L, 1); 00061 lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); 00062 if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) 00063 lua_pushnil(L); /* not a file */ 00064 else if (*((FILE **)ud) == NULL) 00065 lua_pushliteral(L, "closed file"); 00066 else 00067 lua_pushliteral(L, "file"); 00068 return 1; 00069 } 00070 00071 00072 static FILE *tofile (lua_State *L) { 00073 FILE **f = tofilep(L); 00074 if (*f == NULL) 00075 luaL_error(L, "attempt to use a closed file"); 00076 return *f; 00077 } 00078 00079 00080 00081 /* 00082 ** When creating file handles, always creates a `closed' file handle 00083 ** before opening the actual file; so, if there is a memory error, the 00084 ** file is not left opened. 00085 */ 00086 static FILE **newfile (lua_State *L) { 00087 FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); 00088 *pf = NULL; /* file handle is currently `closed' */ 00089 luaL_getmetatable(L, LUA_FILEHANDLE); 00090 lua_setmetatable(L, -2); 00091 return pf; 00092 } 00093 00094 00095 /* 00096 ** function to (not) close the standard files stdin, stdout, and stderr 00097 */ 00098 static int io_noclose (lua_State *L) { 00099 lua_pushnil(L); 00100 lua_pushliteral(L, "cannot close standard file"); 00101 return 2; 00102 } 00103 00104 00105 /* 00106 ** function to close 'popen' files 00107 */ 00108 static int io_pclose (lua_State *L) { 00109 FILE **p = tofilep(L); 00110 int ok = lua_pclose(L, *p); 00111 *p = NULL; 00112 return pushresult(L, ok, NULL); 00113 } 00114 00115 00116 /* 00117 ** function to close regular files 00118 */ 00119 static int io_fclose (lua_State *L) { 00120 FILE **p = tofilep(L); 00121 int ok = (fclose(*p) == 0); 00122 *p = NULL; 00123 return pushresult(L, ok, NULL); 00124 } 00125 00126 00127 static int aux_close (lua_State *L) { 00128 lua_getfenv(L, 1); 00129 lua_getfield(L, -1, "__close"); 00130 return (lua_tocfunction(L, -1))(L); 00131 } 00132 00133 00134 static int io_close (lua_State *L) { 00135 if (lua_isnone(L, 1)) 00136 lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); 00137 tofile(L); /* make sure argument is a file */ 00138 return aux_close(L); 00139 } 00140 00141 00142 static int io_gc (lua_State *L) { 00143 FILE *f = *tofilep(L); 00144 /* ignore closed files */ 00145 if (f != NULL) 00146 aux_close(L); 00147 return 0; 00148 } 00149 00150 00151 static int io_tostring (lua_State *L) { 00152 FILE *f = *tofilep(L); 00153 if (f == NULL) 00154 lua_pushliteral(L, "file (closed)"); 00155 else 00156 lua_pushfstring(L, "file (%p)", f); 00157 return 1; 00158 } 00159 00160 00161 static int io_open (lua_State *L) { 00162 const char *filename = luaL_checkstring(L, 1); 00163 const char *mode = luaL_optstring(L, 2, "r"); 00164 FILE **pf = newfile(L); 00165 *pf = fopen(filename, mode); 00166 return (*pf == NULL) ? pushresult(L, 0, filename) : 1; 00167 } 00168 00169 00170 /* 00171 ** this function has a separated environment, which defines the 00172 ** correct __close for 'popen' files 00173 */ 00174 static int io_popen (lua_State *L) { 00175 const char *filename = luaL_checkstring(L, 1); 00176 const char *mode = luaL_optstring(L, 2, "r"); 00177 FILE **pf = newfile(L); 00178 *pf = (FILE *) lua_popen(L, filename, mode); 00179 return (*pf == NULL) ? pushresult(L, 0, filename) : 1; 00180 } 00181 00182 00183 static int io_tmpfile (lua_State *L) { 00184 FILE **pf = newfile(L); 00185 *pf = tmpfile(); 00186 return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; 00187 } 00188 00189 00190 static FILE *getiofile (lua_State *L, int findex) { 00191 FILE *f; 00192 lua_rawgeti(L, LUA_ENVIRONINDEX, findex); 00193 f = *(FILE **)lua_touserdata(L, -1); 00194 if (f == NULL) 00195 luaL_error(L, "standard %s file is closed", fnames[findex - 1]); 00196 return f; 00197 } 00198 00199 00200 static int g_iofile (lua_State *L, int f, const char *mode) { 00201 if (!lua_isnoneornil(L, 1)) { 00202 const char *filename = lua_tostring(L, 1); 00203 if (filename) { 00204 FILE **pf = newfile(L); 00205 *pf = fopen(filename, mode); 00206 if (*pf == NULL) 00207 fileerror(L, 1, filename); 00208 } 00209 else { 00210 tofile(L); /* check that it's a valid file handle */ 00211 lua_pushvalue(L, 1); 00212 } 00213 lua_rawseti(L, LUA_ENVIRONINDEX, f); 00214 } 00215 /* return current value */ 00216 lua_rawgeti(L, LUA_ENVIRONINDEX, f); 00217 return 1; 00218 } 00219 00220 00221 static int io_input (lua_State *L) { 00222 return g_iofile(L, IO_INPUT, "r"); 00223 } 00224 00225 00226 static int io_output (lua_State *L) { 00227 return g_iofile(L, IO_OUTPUT, "w"); 00228 } 00229 00230 00231 static int io_readline (lua_State *L); 00232 00233 00234 static void aux_lines (lua_State *L, int idx, int toclose) { 00235 lua_pushvalue(L, idx); 00236 lua_pushboolean(L, toclose); /* close/not close file when finished */ 00237 lua_pushcclosure(L, io_readline, 2); 00238 } 00239 00240 00241 static int f_lines (lua_State *L) { 00242 tofile(L); /* check that it's a valid file handle */ 00243 aux_lines(L, 1, 0); 00244 return 1; 00245 } 00246 00247 00248 static int io_lines (lua_State *L) { 00249 if (lua_isnoneornil(L, 1)) { /* no arguments? */ 00250 /* will iterate over default input */ 00251 lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); 00252 return f_lines(L); 00253 } 00254 else { 00255 const char *filename = luaL_checkstring(L, 1); 00256 FILE **pf = newfile(L); 00257 *pf = fopen(filename, "r"); 00258 if (*pf == NULL) 00259 fileerror(L, 1, filename); 00260 aux_lines(L, lua_gettop(L), 1); 00261 return 1; 00262 } 00263 } 00264 00265 00266 /* 00267 ** {====================================================== 00268 ** READ 00269 ** ======================================================= 00270 */ 00271 00272 00273 static int read_number (lua_State *L, FILE *f) { 00274 lua_Number d; 00275 if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { 00276 lua_pushnumber(L, d); 00277 return 1; 00278 } 00279 else return 0; /* read fails */ 00280 } 00281 00282 00283 static int test_eof (lua_State *L, FILE *f) { 00284 int c = getc(f); 00285 ungetc(c, f); 00286 lua_pushlstring(L, NULL, 0); 00287 return (c != EOF); 00288 } 00289 00290 00291 static int read_line (lua_State *L, FILE *f) { 00292 luaL_Buffer b; 00293 luaL_buffinit(L, &b); 00294 for (;;) { 00295 size_t l; 00296 char *p = luaL_prepbuffer(&b); 00297 if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ 00298 luaL_pushresult(&b); /* close buffer */ 00299 return (lua_objlen(L, -1) > 0); /* check whether read something */ 00300 } 00301 l = strlen(p); 00302 if (l == 0 || p[l-1] != '\n') 00303 luaL_addsize(&b, l); 00304 else { 00305 luaL_addsize(&b, l - 1); /* do not include `eol' */ 00306 luaL_pushresult(&b); /* close buffer */ 00307 return 1; /* read at least an `eol' */ 00308 } 00309 } 00310 } 00311 00312 00313 static int read_chars (lua_State *L, FILE *f, size_t n) { 00314 size_t rlen; /* how much to read */ 00315 size_t nr; /* number of chars actually read */ 00316 luaL_Buffer b; 00317 luaL_buffinit(L, &b); 00318 rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ 00319 do { 00320 char *p = luaL_prepbuffer(&b); 00321 if (rlen > n) rlen = n; /* cannot read more than asked */ 00322 nr = fread(p, sizeof(char), rlen, f); 00323 luaL_addsize(&b, nr); 00324 n -= nr; /* still have to read `n' chars */ 00325 } while (n > 0 && nr == rlen); /* until end of count or eof */ 00326 luaL_pushresult(&b); /* close buffer */ 00327 return (n == 0 || lua_objlen(L, -1) > 0); 00328 } 00329 00330 00331 static int g_read (lua_State *L, FILE *f, int first) { 00332 int nargs = lua_gettop(L) - 1; 00333 int success; 00334 int n; 00335 clearerr(f); 00336 if (nargs == 0) { /* no arguments? */ 00337 success = read_line(L, f); 00338 n = first+1; /* to return 1 result */ 00339 } 00340 else { /* ensure stack space for all results and for auxlib's buffer */ 00341 luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); 00342 success = 1; 00343 for (n = first; nargs-- && success; n++) { 00344 if (lua_type(L, n) == LUA_TNUMBER) { 00345 size_t l = (size_t)lua_tointeger(L, n); 00346 success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); 00347 } 00348 else { 00349 const char *p = lua_tostring(L, n); 00350 luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); 00351 switch (p[1]) { 00352 case 'n': /* number */ 00353 success = read_number(L, f); 00354 break; 00355 case 'l': /* line */ 00356 success = read_line(L, f); 00357 break; 00358 case 'a': /* file */ 00359 read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ 00360 success = 1; /* always success */ 00361 break; 00362 default: 00363 return luaL_argerror(L, n, "invalid format"); 00364 } 00365 } 00366 } 00367 } 00368 if (ferror(f)) 00369 return pushresult(L, 0, NULL); 00370 if (!success) { 00371 lua_pop(L, 1); /* remove last result */ 00372 lua_pushnil(L); /* push nil instead */ 00373 } 00374 return n - first; 00375 } 00376 00377 00378 static int io_read (lua_State *L) { 00379 return g_read(L, getiofile(L, IO_INPUT), 1); 00380 } 00381 00382 00383 static int f_read (lua_State *L) { 00384 return g_read(L, tofile(L), 2); 00385 } 00386 00387 00388 static int io_readline (lua_State *L) { 00389 FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); 00390 int sucess; 00391 if (f == NULL) /* file is already closed? */ 00392 luaL_error(L, "file is already closed"); 00393 sucess = read_line(L, f); 00394 if (ferror(f)) 00395 return luaL_error(L, "%s", strerror(errno)); 00396 if (sucess) return 1; 00397 else { /* EOF */ 00398 if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ 00399 lua_settop(L, 0); 00400 lua_pushvalue(L, lua_upvalueindex(1)); 00401 aux_close(L); /* close it */ 00402 } 00403 return 0; 00404 } 00405 } 00406 00407 /* }====================================================== */ 00408 00409 00410 static int g_write (lua_State *L, FILE *f, int arg) { 00411 int nargs = lua_gettop(L) - 1; 00412 int status = 1; 00413 for (; nargs--; arg++) { 00414 if (lua_type(L, arg) == LUA_TNUMBER) { 00415 /* optimization: could be done exactly as for strings */ 00416 status = status && 00417 fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; 00418 } 00419 else { 00420 size_t l; 00421 const char *s = luaL_checklstring(L, arg, &l); 00422 status = status && (fwrite(s, sizeof(char), l, f) == l); 00423 } 00424 } 00425 return pushresult(L, status, NULL); 00426 } 00427 00428 00429 static int io_write (lua_State *L) { 00430 return g_write(L, getiofile(L, IO_OUTPUT), 1); 00431 } 00432 00433 00434 static int f_write (lua_State *L) { 00435 return g_write(L, tofile(L), 2); 00436 } 00437 00438 00439 static int f_seek (lua_State *L) { 00440 static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; 00441 static const char *const modenames[] = {"set", "cur", "end", NULL}; 00442 FILE *f = tofile(L); 00443 int op = luaL_checkoption(L, 2, "cur", modenames); 00444 long offset = luaL_optlong(L, 3, 0); 00445 op = fseek(f, offset, mode[op]); 00446 if (op) 00447 return pushresult(L, 0, NULL); /* error */ 00448 else { 00449 lua_pushinteger(L, ftell(f)); 00450 return 1; 00451 } 00452 } 00453 00454 00455 static int f_setvbuf (lua_State *L) { 00456 static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; 00457 static const char *const modenames[] = {"no", "full", "line", NULL}; 00458 FILE *f = tofile(L); 00459 int op = luaL_checkoption(L, 2, NULL, modenames); 00460 lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); 00461 int res = setvbuf(f, NULL, mode[op], sz); 00462 return pushresult(L, res == 0, NULL); 00463 } 00464 00465 00466 00467 static int io_flush (lua_State *L) { 00468 return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); 00469 } 00470 00471 00472 static int f_flush (lua_State *L) { 00473 return pushresult(L, fflush(tofile(L)) == 0, NULL); 00474 } 00475 00476 00477 static const luaL_Reg iolib[] = { 00478 {"close", io_close}, 00479 {"flush", io_flush}, 00480 {"input", io_input}, 00481 {"lines", io_lines}, 00482 {"open", io_open}, 00483 {"output", io_output}, 00484 {"popen", io_popen}, 00485 {"read", io_read}, 00486 {"tmpfile", io_tmpfile}, 00487 {"type", io_type}, 00488 {"write", io_write}, 00489 {NULL, NULL} 00490 }; 00491 00492 00493 static const luaL_Reg flib[] = { 00494 {"close", io_close}, 00495 {"flush", f_flush}, 00496 {"lines", f_lines}, 00497 {"read", f_read}, 00498 {"seek", f_seek}, 00499 {"setvbuf", f_setvbuf}, 00500 {"write", f_write}, 00501 {"__gc", io_gc}, 00502 {"__tostring", io_tostring}, 00503 {NULL, NULL} 00504 }; 00505 00506 00507 static void createmeta (lua_State *L) { 00508 luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ 00509 lua_pushvalue(L, -1); /* push metatable */ 00510 lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ 00511 luaL_register(L, NULL, flib); /* file methods */ 00512 } 00513 00514 00515 static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { 00516 *newfile(L) = f; 00517 if (k > 0) { 00518 lua_pushvalue(L, -1); 00519 lua_rawseti(L, LUA_ENVIRONINDEX, k); 00520 } 00521 lua_pushvalue(L, -2); /* copy environment */ 00522 lua_setfenv(L, -2); /* set it */ 00523 lua_setfield(L, -3, fname); 00524 } 00525 00526 00527 static void newfenv (lua_State *L, lua_CFunction cls) { 00528 lua_createtable(L, 0, 1); 00529 lua_pushcfunction(L, cls); 00530 lua_setfield(L, -2, "__close"); 00531 } 00532 00533 00534 LUALIB_API int luaopen_io (lua_State *L) { 00535 createmeta(L); 00536 /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ 00537 newfenv(L, io_fclose); 00538 lua_replace(L, LUA_ENVIRONINDEX); 00539 /* open library */ 00540 luaL_register(L, LUA_IOLIBNAME, iolib); 00541 /* create (and set) default files */ 00542 newfenv(L, io_noclose); /* close function for default files */ 00543 createstdfile(L, stdin, IO_INPUT, "stdin"); 00544 createstdfile(L, stdout, IO_OUTPUT, "stdout"); 00545 createstdfile(L, stderr, 0, "stderr"); 00546 lua_pop(L, 1); /* pop environment for default files */ 00547 lua_getfield(L, -1, "popen"); 00548 newfenv(L, io_pclose); /* create environment for 'popen' */ 00549 lua_setfenv(L, -2); /* set fenv for 'popen' */ 00550 lua_pop(L, 1); /* pop 'popen' */ 00551 return 1; 00552 } 00553
ContextLogger2—ContextLogger2 Logger Daemon Internals—Generated on Mon May 2 13:49:54 2011 by Doxygen 1.6.1