📄 liolib.c
字号:
/*** $Id: liolib.c,v 2.39a 2003/03/19 21:16:12 roberto Exp $** Standard I/O (and system) library** See Copyright Notice in lua.h*/#include <errno.h>#include <locale.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#define liolib_c#include "lua.h"#include "lauxlib.h"#include "lualib.h"/*** by default, gcc does not get `tmpname'*/#ifndef USE_TMPNAME#ifdef __GNUC__#define USE_TMPNAME 0#else#define USE_TMPNAME 1#endif#endif/*** by default, posix systems get `popen'*/#ifndef USE_POPEN#ifdef _POSIX_C_SOURCE#if _POSIX_C_SOURCE >= 2#define USE_POPEN 1#endif#endif#endif#ifndef USE_POPEN#define USE_POPEN 0#endif/*** {======================================================** FILE Operations** =======================================================*/#if !USE_POPEN#define pclose(f) (-1)#endif#define FILEHANDLE "FILE*"#define IO_INPUT "_input"#define IO_OUTPUT "_output"static int pushresult (lua_State *L, int i, const char *filename) { if (i) { lua_pushboolean(L, 1); return 1; } else { lua_pushnil(L); if (filename) lua_pushfstring(L, "%s: %s", filename, strerror(errno)); else lua_pushfstring(L, "%s", strerror(errno)); lua_pushnumber(L, errno); return 3; }}static FILE **topfile (lua_State *L, int findex) { FILE **f = (FILE **)luaL_checkudata(L, findex, FILEHANDLE); if (f == NULL) luaL_argerror(L, findex, "bad file"); return f;}static int io_type (lua_State *L) { FILE **f = (FILE **)luaL_checkudata(L, 1, FILEHANDLE); if (f == NULL) lua_pushnil(L); else if (*f == NULL) lua_pushliteral(L, "closed file"); else lua_pushliteral(L, "file"); return 1;}static FILE *tofile (lua_State *L, int findex) { FILE **f = topfile(L, findex); if (*f == NULL) luaL_error(L, "attempt to use a closed file"); return *f;}/*** When creating file handles, always creates a `closed' file handle** before opening the actual file; so, if there is a memory error, the** file is not left opened.*/static FILE **newfile (lua_State *L) { FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); *pf = NULL; /* file handle is currently `closed' */ luaL_getmetatable(L, FILEHANDLE); lua_setmetatable(L, -2); return pf;}/*** assumes that top of the stack is the `io' library, and next is** the `io' metatable*/static void registerfile (lua_State *L, FILE *f, const char *name, const char *impname) { lua_pushstring(L, name); *newfile(L) = f; if (impname) { lua_pushstring(L, impname); lua_pushvalue(L, -2); lua_settable(L, -6); /* metatable[impname] = file */ } lua_settable(L, -3); /* io[name] = file */}static int aux_close (lua_State *L) { FILE *f = tofile(L, 1); if (f == stdin || f == stdout || f == stderr) return 0; /* file cannot be closed */ else { int ok = (pclose(f) != -1) || (fclose(f) == 0); if (ok) *(FILE **)lua_touserdata(L, 1) = NULL; /* mark file as closed */ return ok; }}static int io_close (lua_State *L) { if (lua_isnone(L, 1) && lua_type(L, lua_upvalueindex(1)) == LUA_TTABLE) { lua_pushstring(L, IO_OUTPUT); lua_rawget(L, lua_upvalueindex(1)); } return pushresult(L, aux_close(L), NULL);}static int io_gc (lua_State *L) { FILE **f = topfile(L, 1); if (*f != NULL) /* ignore closed files */ aux_close(L); return 0;}static int io_tostring (lua_State *L) { char buff[128]; FILE **f = topfile(L, 1); if (*f == NULL) strcpy(buff, "closed"); else sprintf(buff, "%p", lua_touserdata(L, 1)); lua_pushfstring(L, "file (%s)", buff); return 1;}static int io_open (lua_State *L) { const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); FILE **pf = newfile(L); *pf = fopen(filename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1;}static int io_popen (lua_State *L) {#if !USE_POPEN luaL_error(L, "`popen' not supported"); return 0;#else const char *filename = luaL_checkstring(L, 1); const char *mode = luaL_optstring(L, 2, "r"); FILE **pf = newfile(L); *pf = popen(filename, mode); return (*pf == NULL) ? pushresult(L, 0, filename) : 1;#endif}static int io_tmpfile (lua_State *L) { FILE **pf = newfile(L); *pf = tmpfile(); return (*pf == NULL) ? pushresult(L, 0, NULL) : 1;}static FILE *getiofile (lua_State *L, const char *name) { lua_pushstring(L, name); lua_rawget(L, lua_upvalueindex(1)); return tofile(L, -1);}static int g_iofile (lua_State *L, const char *name, const char *mode) { if (!lua_isnoneornil(L, 1)) { const char *filename = lua_tostring(L, 1); lua_pushstring(L, name); if (filename) { FILE **pf = newfile(L); *pf = fopen(filename, mode); if (*pf == NULL) { lua_pushfstring(L, "%s: %s", filename, strerror(errno)); luaL_argerror(L, 1, lua_tostring(L, -1)); } } else { tofile(L, 1); /* check that it's a valid file handle */ lua_pushvalue(L, 1); } lua_rawset(L, lua_upvalueindex(1)); } /* return current value */ lua_pushstring(L, name); lua_rawget(L, lua_upvalueindex(1)); return 1;}static int io_input (lua_State *L) { return g_iofile(L, IO_INPUT, "r");}static int io_output (lua_State *L) { return g_iofile(L, IO_OUTPUT, "w");}static int io_readline (lua_State *L);static void aux_lines (lua_State *L, int idx, int close) { lua_pushliteral(L, FILEHANDLE); lua_rawget(L, LUA_REGISTRYINDEX); lua_pushvalue(L, idx); lua_pushboolean(L, close); /* close/not close file when finished */ lua_pushcclosure(L, io_readline, 3);}static int f_lines (lua_State *L) { tofile(L, 1); /* check that it's a valid file handle */ aux_lines(L, 1, 0); return 1;}static int io_lines (lua_State *L) { if (lua_isnoneornil(L, 1)) { /* no arguments? */ lua_pushstring(L, IO_INPUT); lua_rawget(L, lua_upvalueindex(1)); /* will iterate over default input */ return f_lines(L); } else { const char *filename = luaL_checkstring(L, 1); FILE **pf = newfile(L); *pf = fopen(filename, "r"); luaL_argcheck(L, *pf, 1, strerror(errno)); aux_lines(L, lua_gettop(L), 1); return 1; }}/*** {======================================================** READ** =======================================================*/static int read_number (lua_State *L, FILE *f) { lua_Number d; if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { lua_pushnumber(L, d); return 1; } else return 0; /* read fails */}static int test_eof (lua_State *L, FILE *f) { int c = getc(f); ungetc(c, f); lua_pushlstring(L, NULL, 0); return (c != EOF);}static int read_line (lua_State *L, FILE *f) { luaL_Buffer b; luaL_buffinit(L, &b); for (;;) { size_t l; char *p = luaL_prepbuffer(&b); if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ luaL_pushresult(&b); /* close buffer */ return (lua_strlen(L, -1) > 0); /* check whether read something */ } l = strlen(p); if (p[l-1] != '\n') luaL_addsize(&b, l); else { luaL_addsize(&b, l - 1); /* do not include `eol' */ luaL_pushresult(&b); /* close buffer */ return 1; /* read at least an `eol' */ } }}static int read_chars (lua_State *L, FILE *f, size_t n) { size_t rlen; /* how much to read */ size_t nr; /* number of chars actually read */ luaL_Buffer b; luaL_buffinit(L, &b); rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ do { char *p = luaL_prepbuffer(&b); if (rlen > n) rlen = n; /* cannot read more than asked */ nr = fread(p, sizeof(char), rlen, f); luaL_addsize(&b, nr); n -= nr; /* still have to read `n' chars */ } while (n > 0 && nr == rlen); /* until end of count or eof */ luaL_pushresult(&b); /* close buffer */ return (n == 0 || lua_strlen(L, -1) > 0);}static int g_read (lua_State *L, FILE *f, int first) { int nargs = lua_gettop(L) - 1; int success; int n; if (nargs == 0) { /* no arguments? */ success = read_line(L, f); n = first+1; /* to return 1 result */ } else { /* ensure stack space for all results and for auxlib's buffer */ luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); success = 1; for (n = first; nargs-- && success; n++) { if (lua_type(L, n) == LUA_TNUMBER) { size_t l = (size_t)lua_tonumber(L, n); success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -