diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/lua/liolibext.c')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/liolibext.c | 891 |
1 files changed, 312 insertions, 579 deletions
diff --git a/Build/source/texk/web2c/luatexdir/lua/liolibext.c b/Build/source/texk/web2c/luatexdir/lua/liolibext.c index 630562228d9..e910139c2ce 100644 --- a/Build/source/texk/web2c/luatexdir/lua/liolibext.c +++ b/Build/source/texk/web2c/luatexdir/lua/liolibext.c @@ -15,18 +15,13 @@ License for more details. You should have received a copy of the GNU General Public License along - with LuaTeX; if not, see <http://www.gnu.org/licenses/>. */ + with LuaTeX; if not, see <http://www.gnu.org/licenses/>. -/* This extension only replaces one function: io.popen() and two - metatable entries: f:read() and f:lines() but unfortunately - it has to copy quite a bunch of lines from the original liolib.c - to do so. */ #include "ptexlib.h" #include "lua/luatex-api.h" - #ifdef LuajitTeX #include "lua/lauxlib_bridge.h" #else @@ -36,6 +31,10 @@ +#ifdef LuajitTeX +/* luajit has its own way for io, which is a mix of */ +/* lua 5.1 and lua 5.2 . We use the stock luajit. */ +#else /* ** {====================================================== ** lua_popen spawns a new process connected to the current @@ -46,17 +45,17 @@ #if defined(_WIN32) #ifdef _MSC_VER -#define lua_popen(L,c,m) ((void)L, win32_popen(c,m)) -#define lua_pclose(L,file) ((void)L, win32_pclose(file)) +#define lua_popen(L,c,m) ((void)L, win32_popen(c,m)) +#define lua_pclose(L,file) ((void)L, win32_pclose(file)) #else -#define lua_popen(L,c,m) ((void)L, _popen(c,m)) -#define lua_pclose(L,file) ((void)L, _pclose(file)) +#define lua_popen(L,c,m) ((void)L, _popen(c,m)) +#define lua_pclose(L,file) ((void)L, _pclose(file)) #endif #else -#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) -#define lua_pclose(L,file) ((void)L, pclose(file)) +#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) +#define lua_pclose(L,file) ((void)L, pclose(file)) #endif @@ -65,17 +64,17 @@ #if defined(LUA_USE_POSIX) -#define l_fseek(f,o,w) fseeko(f,o,w) -#define l_ftell(f) ftello(f) -#define l_seeknum off_t +#define l_fseek(f,o,w) fseeko(f,o,w) +#define l_ftell(f) ftello(f) +#define l_seeknum off_t #elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ && defined(_MSC_VER) && (_MSC_VER >= 1400) /* Windows (but not DDK) and Visual C++ 2005 or higher */ -#define l_fseek(f,o,w) _fseeki64(f,o,w) -#define l_ftell(f) _ftelli64(f) -#define l_seeknum __int64 +#define l_fseek(f,o,w) _fseeki64(f,o,w) +#define l_ftell(f) _ftelli64(f) +#define l_seeknum __int64 #elif defined(__MINGW32__) @@ -85,637 +84,371 @@ #else -#define l_fseek(f,o,w) fseek(f,o,w) -#define l_ftell(f) ftell(f) -#define l_seeknum long +#define l_fseek(f,o,w) fseek(f,o,w) +#define l_ftell(f) ftell(f) +#define l_seeknum long #endif -#define IO_PREFIX "_IO_" -#define IO_INPUT (IO_PREFIX "input") -#define IO_OUTPUT (IO_PREFIX "output") - -typedef luaL_Stream LStream; - -#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) - -#define isclosed(p) ((p)->closef == NULL) +#endif/* #ifdef LuajitTeX */ -static int io_type (lua_State *L) { - LStream *p; - luaL_checkany(L, 1); - p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); - if (p == NULL) - lua_pushnil(L); /* not a file */ - else if (isclosed(p)) - lua_pushliteral(L, "closed file"); - else - lua_pushliteral(L, "file"); - return 1; -} -static int f_tostring (lua_State *L) { - LStream *p = tolstream(L); - if (isclosed(p)) - lua_pushliteral(L, "file (closed)"); - else - lua_pushfstring(L, "file (%p)", p->f); - return 1; -} static FILE *tofile (lua_State *L) { - LStream *p = tolstream(L); - if (isclosed(p)) - luaL_error(L, "attempt to use a closed file"); - lua_assert(p->f); - return p->f; +#ifdef LuajitTeX + FILE **f = luaL_checkudata(L,1,LUA_FILEHANDLE); + if (*f == NULL) + luaL_error(L,"attempt to use a closed file"); + return *f; +#else + luaL_Stream *p = ((luaL_Stream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)); + if ((p)->closef == NULL) + luaL_error(L, "attempt to use a closed file"); + lua_assert(p->f); + return p->f; +#endif } - /* -** 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. + HH: A few helpers to avoid reading numbers as strings. For now we put them in their + own namespace. We also have a few helpers that can make io functions tex friendly. */ -static LStream *newprefile (lua_State *L) { - LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); - p->closef = NULL; /* mark file handle as 'closed' */ - luaL_setmetatable(L, LUA_FILEHANDLE); - return p; -} - - -static int aux_close (lua_State *L) { - LStream *p = tolstream(L); - lua_CFunction cf = p->closef; - p->closef = NULL; /* mark stream as closed */ - return (*cf)(L); /* close it */ -} - -static int io_close (lua_State *L) { - if (lua_isnone(L, 1)) /* no argument? */ - lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ - tofile(L); /* make sure argument is an open stream */ - return aux_close(L); +static int readcardinal1(lua_State *L) { + FILE *f = tofile(L); + int a = getc(f); + if (a == EOF) + lua_pushnil(L); + else + lua_pushinteger(L, a); + return 1; } -static int f_gc (lua_State *L) { - LStream *p = tolstream(L); - if (!isclosed(p) && p->f != NULL) - aux_close(L); /* ignore closed and incompletely open files */ - return 0; +static int readcardinal2(lua_State *L) { + FILE *f = tofile(L); + int a = getc(f); + int b = getc(f); + if (b == EOF) + lua_pushnil(L); + else + /* (a<<8) | b */ + lua_pushinteger(L, 0x100 * a + b); + return 1; } - -/* -** function to close regular files -*/ -static int io_fclose (lua_State *L) { - LStream *p = tolstream(L); - int res = fclose(p->f); - return luaL_fileresult(L, (res == 0), NULL); +static int readcardinal3(lua_State *L) { + FILE *f = tofile(L); + int a = getc(f); + int b = getc(f); + int c = getc(f); + if (c == EOF) + lua_pushnil(L); + else + /* (a<<16) | (b<<8) | c */ + lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); + return 1; } - -static LStream *newfile (lua_State *L) { - LStream *p = newprefile(L); - p->f = NULL; - p->closef = &io_fclose; - return p; +static int readcardinal4(lua_State *L) { + FILE *f = tofile(L); + int a = getc(f); + int b = getc(f); + int c = getc(f); + int d = getc(f); + if (d == EOF) + lua_pushnil(L); + else + /* (a<<24) | (b<<16) | (c<<8) | d */ + lua_pushinteger(L,0x1000000 * a + 0x10000 * b + 0x100 * c + d); + return 1; } - -static void opencheck (lua_State *L, const char *fname, const char *mode) { - LStream *p = newfile(L); - p->f = fopen(fname, mode); - if (p->f == NULL) { - luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno)); - } else { -#ifdef WIN32 - _setmode (fileno (p->f), _O_BINARY); -#endif - if (mode[0]=='r') - recorder_record_input(fname); +static int readinteger1(lua_State *L) { + FILE *f = tofile(L); + int a = getc(f); + if (a == EOF) + lua_pushnil(L); + else if (a >= 0x80) + lua_pushinteger(L, a - 0x100); else - recorder_record_output(fname); - } + lua_pushinteger(L, a); + return 1; } - -static int io_open (lua_State *L) { - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - LStream *p = newfile(L); - int i = 0; - /* check whether 'mode' matches '[rwa]%+?b?' */ - if (!(mode[i] != '\0' && strchr("rwa", mode[i++]) != NULL && - (mode[i] != '+' || ++i) && /* skip if char is '+' */ - (mode[i] != 'b' || ++i) && /* skip if char is 'b' */ - (mode[i] == '\0'))) - return luaL_error(L, "invalid mode " LUA_QS - " (should match " LUA_QL("[rwa]%%+?b?") ")", mode); - p->f = fopen(filename, mode); - if (p->f == NULL) { - return luaL_fileresult(L, 0, filename) ; - } else { -#ifdef WIN32 - _setmode (fileno (p->f), _O_BINARY); -#endif - if (mode[0]=='r') - recorder_record_input(filename); - else - recorder_record_output(filename); - return 1; - } +static int readinteger2(lua_State *L) { + FILE *f = tofile(L); + int a = getc(f); + int b = getc(f); + if (b == EOF) + lua_pushnil(L); + else if (a >= 0x80) + lua_pushinteger(L, 0x100 * a + b - 0x10000); + else + lua_pushinteger(L, 0x100 * a + b); + return 1; } -/* -** function to close 'popen' files -*/ -static int io_pclose (lua_State *L) { - LStream *p = tolstream(L); - return luaL_execresult(L, lua_pclose(L, p->f)); +static int readinteger3(lua_State *L) { + FILE *f = tofile(L); + int a = getc(f); + int b = getc(f); + int c = getc(f); + if (c == EOF) + lua_pushnil(L); + else if (a >= 0x80) + lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000); + else + lua_pushinteger(L, 0x10000 * a + 0x100 * b + c); + return 1; } -static int io_popen(lua_State * L) -{ - int ret = 1; - char *safecmd = NULL; - char *cmdname = NULL; - int allow = 0; - const char *filename = luaL_checkstring(L, 1); - const char *mode = luaL_optstring(L, 2, "r"); - LStream *p = newprefile(L); - - if (shellenabledp <= 0) { +static int readinteger4(lua_State *L) { + FILE *f = tofile(L); + int a = getc(f); + int b = getc(f); + int c = getc(f); + int d = getc(f); + if (d == EOF) lua_pushnil(L); - lua_pushliteral(L, "All command execution is disabled"); - return 2; - } - /* If restrictedshell == 0, any command is allowed. */ - if (restrictedshell == 0) - allow = 1; + else if (a >= 0x80) + lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000); else - allow = shell_cmd_is_allowed(filename, &safecmd, &cmdname); - - if (allow == 1) { - p->f = lua_popen(L, filename, mode); - p->closef = &io_pclose; - ret = (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; - } else if (allow == 2) { - p->f = lua_popen(L, safecmd, mode); - p->closef = &io_pclose; - ret = (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; - } else if (allow == 0) { - lua_pushnil(L); - lua_pushliteral(L, "Command execution disabled via shell_escape='p'"); - ret = 2; - } else { - lua_pushnil(L); - lua_pushliteral(L, "Bad command line quoting"); - ret = 2; - } - return ret; + lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d); + return 1; } - -static int io_tmpfile (lua_State *L) { - LStream *p = newfile(L); - p->f = tmpfile(); - return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; +static int readfixed2(lua_State *L) { + FILE *f = tofile(L); + int a = getc(f); + int b = getc(f); + if (b == EOF) + lua_pushnil(L); + else if (a >= 0x80) + lua_pushinteger(L, a + b/0xFFFF - 0x100); + else + lua_pushinteger(L, a + b/0xFFFF); + return 1; } - -static FILE *getiofile (lua_State *L, const char *findex) { - LStream *p; - lua_getfield(L, LUA_REGISTRYINDEX, findex); - p = (LStream *)lua_touserdata(L, -1); - if (isclosed(p)) - luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX)); - return p->f; +static int readfixed4(lua_State *L) { + FILE *f = tofile(L); + int a = getc(f); + int b = getc(f); + int c = getc(f); + int d = getc(f); + if (d == EOF) + lua_pushnil(L); + else if (a >= 0x80) + lua_pushnumber(L, (0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000)/65536.0); + else + lua_pushnumber(L, (0x1000000 * a + 0x10000 * b + 0x100 * c + d)/65536.0); + /* from ff */ + /* int n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d; */ + /* lua_pushnumber(L,(real) (n>>16) + ((n&0xffff)/65536.0)); */ + return 1; } - -static int g_iofile (lua_State *L, const char *f, const char *mode) { - if (!lua_isnoneornil(L, 1)) { - const char *filename = lua_tostring(L, 1); - if (filename) - opencheck(L, filename, mode); - else { - tofile(L); /* check that it's a valid file handle */ - lua_pushvalue(L, 1); +static int read2dot14(lua_State *L) { + FILE *f = tofile(L); + int a = getc(f); + int b = getc(f); + if (b == EOF) { + lua_pushnil(L); + } else { + int n = 0x100 * a + b; + /* from ff */ + lua_pushnumber(L,(real) ((n<<16)>>(16+14)) + ((n&0x3fff)/16384.0)); } - lua_setfield(L, LUA_REGISTRYINDEX, f); - } - /* return current value */ - lua_getfield(L, LUA_REGISTRYINDEX, f); - return 1; + return 1; } - -static int io_input (lua_State *L) { - return g_iofile(L, IO_INPUT, "r"); +static int getposition(lua_State *L) { + FILE *f = tofile(L); + long p = ftell(f); + if (p<0) + lua_pushnil(L); + else + lua_pushinteger(L, p); + return 1; } - -static int io_output (lua_State *L) { - return g_iofile(L, IO_OUTPUT, "w"); +static int setposition(lua_State *L) { + FILE *f = tofile(L); + long p = lua_tointeger(L,2); + p = fseek(f,p,SEEK_SET); + if (p<0) + lua_pushnil(L); + else + lua_pushinteger(L, p); + return 1; } - -static int io_readline (lua_State *L); - - -static void aux_lines (lua_State *L, int toclose) { - int i; - int n = lua_gettop(L) - 1; /* number of arguments to read */ - /* ensure that arguments will fit here and into 'io_readline' stack */ - luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options"); - lua_pushvalue(L, 1); /* file handle */ - lua_pushinteger(L, n); /* number of arguments to read */ - lua_pushboolean(L, toclose); /* close/not close file when finished */ - for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1); /* copy arguments */ - lua_pushcclosure(L, io_readline, 3 + n); +static int skipposition(lua_State *L) { + FILE *f = tofile(L); + long p = lua_tointeger(L,2); + p = fseek(f,ftell(f)+p,SEEK_SET); + if (p<0) + lua_pushnil(L); + else + lua_pushinteger(L, p); + return 1; } - -static int f_lines (lua_State *L) { - tofile(L); /* check that it's a valid file handle */ - aux_lines(L, 0); - return 1; +static int readbytetable(lua_State *L) { + FILE *f = tofile(L); + int n = lua_tointeger(L,2); + int i ; + lua_createtable(L, n, 0); + for (i=1;i<=n;i++) { + int a = getc(f); + if (a == EOF) { + break; + } else { + /* + lua_pushinteger(L, i); + lua_pushinteger(L, a); + lua_rawset(L, -3); + */ + lua_pushinteger(L, a); + lua_rawseti(L,-2,i); + } + } + return 1; } - -static int io_lines (lua_State *L) { - int toclose; - if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ - if (lua_isnil(L, 1)) { /* no file name? */ - lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ - lua_replace(L, 1); /* put it at index 1 */ - tofile(L); /* check that it's a valid file handle */ - toclose = 0; /* do not close it after iteration */ - } - else { /* open a new file */ - const char *filename = luaL_checkstring(L, 1); - opencheck(L, filename, "r"); - lua_replace(L, 1); /* put file at index 1 */ - toclose = 1; /* close it after iteration */ - } - aux_lines(L, toclose); - return 1; +static int readbytes(lua_State *L) { + FILE *f = tofile(L); + int n = lua_tointeger(L,2); + int i = 0; + for (i=1;i<=n;i++) { + int a = getc(f); + if (a == EOF) { + return i-1; + } else { + lua_pushinteger(L, a); + } + } + return n; } -/* -** {====================================================== -** 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); /* integer or float */ - return 1; - } - else { - lua_pushnil(L); /* "result" to be removed */ - return 0; /* read fails */ - } +static int recordfilename(lua_State *L) +{ + const char *fname = luaL_checkstring(L, 1); + const char *ftype = lua_tostring(L, 2); + if (fname != NULL && ftype != NULL) { + switch (ftype[1]) { + case 'r': + recorder_record_input(fname); + break; + case 'w': + recorder_record_output(fname); + break; + default: + /* silently ignore */ + break; + } + } else { + /* silently ignore */ + } + return 0; } - -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 checkpermission(lua_State *L) +{ + const char *filename = luaL_checkstring(L, 1); + if (filename == NULL) { + lua_pushboolean(L,0); + lua_pushliteral(L,"no command name given"); + } else if (shellenabledp <= 0) { + lua_pushboolean(L,0); + lua_pushliteral(L,"all command execution is disabled"); + } else if (restrictedshell == 0) { + lua_pushboolean(L,1); + lua_pushliteral(L,"all commands are permitted"); + } else { + char *safecmd = NULL; + char *cmdname = NULL; + switch (shell_cmd_is_allowed(filename, &safecmd, &cmdname)) { + case 0: + lua_pushboolean(L,0); + lua_pushliteral(L, "specific command execution disabled"); + break; + case 1: + lua_pushboolean(L,1); + lua_pushstring(L,filename); + break; + case 2: + lua_pushboolean(L,1); + lua_pushstring(L,safecmd); + break; + default: + lua_pushboolean(L,0); + lua_pushliteral(L, "bad command line quoting"); + break; + } + } + return 2; } -/* this version does not care wether the file has - line endings using an 'alien' convention */ - -static int read_line(lua_State * L, FILE * f, int chop) +static int readline(lua_State *L) { luaL_Buffer buf; int c, d; + FILE *f = tofile(L); luaL_buffinit(L, &buf); while (1) { c = fgetc(f); if (c == EOF) { - luaL_pushresult(&buf); /* close buffer */ - return (lua_rawlen(L, -1) > 0); /* check whether read something */ - }; - if (c == '\n') { - if (!chop) - luaL_addchar(&buf, c); - break; + luaL_pushresult(&buf); + if (lua_rawlen(L, -1) == 0) { + lua_pop(L, 1); + lua_pushnil(L); + } + return 1; + } else if (c == '\n') { + luaL_pushresult(&buf); + return 1; } else if (c == '\r') { - if (!chop) - luaL_addchar(&buf, c); d = fgetc(f); if (d != EOF && d != '\n') { ungetc(d, f); - } else if (!chop) { - luaL_addchar(&buf, d); - } - break; + } + luaL_pushresult(&buf); + return 1; } else { luaL_addchar(&buf, c); } } - luaL_pushresult(&buf); /* close buffer */ - return 1; -} - -#define MAX_SIZE_T (~(size_t)0) - -static void read_all (lua_State *L, FILE *f) { - size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ - l_seeknum old, nrlen = 0; /* for testing file size */ - luaL_Buffer b; - luaL_buffinit(L, &b); - /* speed up loading of not too large files: */ - old = l_ftell(f); - if ((l_fseek(f, 0, SEEK_END) >= 0) && - ((nrlen = l_ftell(f)) > 0) && nrlen < 1000 * 1000 * 100) { - rlen = nrlen; - } - l_fseek(f, old, SEEK_SET); - for (;;) { - char *p = luaL_prepbuffsize(&b, rlen); - size_t nr = fread(p, sizeof(char), rlen, f); - luaL_addsize(&b, nr); - if (nr < rlen) break; /* eof? */ - else if (rlen <= (MAX_SIZE_T / 4)) /* avoid buffers too large */ - rlen *= 2; /* double buffer size at each iteration */ - } - luaL_pushresult(&b); /* close buffer */ -} - - -static int read_chars (lua_State *L, FILE *f, size_t n) { - size_t nr; /* number of chars actually read */ - char *p; - luaL_Buffer b; - luaL_buffinit(L, &b); - p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ - nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ - luaL_addsize(&b, nr); - luaL_pushresult(&b); /* close buffer */ - return (nr > 0); /* true iff read something */ -} - - -static int g_read (lua_State *L, FILE *f, int first) { - int nargs = lua_gettop(L) - 1; - int success; - int n; - clearerr(f); - if (nargs == 0) { /* no arguments? */ - success = read_line(L, f, 1); - 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_tointeger(L, n); - success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); - } - else { - const char *p = lua_tostring(L, n); - luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); - switch (p[1]) { - case 'n': /* number */ - success = read_number(L, f); - break; - case 'l': /* line */ - success = read_line(L, f, 1); - break; - case 'L': /* line with end-of-line */ - success = read_line(L, f, 0); - break; - case 'a': /* file */ - read_all(L, f); /* read entire file */ - success = 1; /* always success */ - break; - default: - return luaL_argerror(L, n, "invalid format"); - } - } - } - } - if (ferror(f)) - return luaL_fileresult(L, 0, NULL); - if (!success) { - lua_pop(L, 1); /* remove last result */ - lua_pushnil(L); /* push nil instead */ - } - return n - first; -} - - -static int io_read (lua_State *L) { - return g_read(L, getiofile(L, IO_INPUT), 1); -} - -static int f_read (lua_State *L) { - return g_read(L, tofile(L), 2); -} - - -static int io_readline (lua_State *L) { - LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); - int i; - int n = (int)lua_tointeger(L, lua_upvalueindex(2)); - if (isclosed(p)) /* file is already closed? */ - return luaL_error(L, "file is already closed"); - lua_settop(L , 1); - for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ - lua_pushvalue(L, lua_upvalueindex(3 + i)); - n = g_read(L, p->f, 2); /* 'n' is number of results */ - lua_assert(n > 0); /* should return at least a nil */ - if (!lua_isnil(L, -n)) /* read at least one value? */ - return n; /* return them */ - else { /* first result is nil: EOF or error */ - if (n > 1) { /* is there error information? */ - /* 2nd result is error message */ - return luaL_error(L, "%s", lua_tostring(L, -n + 1)); - } - if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ - lua_settop(L, 0); - lua_pushvalue(L, lua_upvalueindex(1)); - aux_close(L); /* close it */ - } - return 0; - } } -/* }====================================================== */ - - -static int g_write (lua_State *L, FILE *f, int arg) { - int nargs = lua_gettop(L) - arg; - int status = 1; - for (; nargs--; arg++) { - if (lua_type(L, arg) == LUA_TNUMBER) { - /* optimization: could be done exactly as for strings */ - status = status && - fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; - } - else { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - status = status && (fwrite(s, sizeof(char), l, f) == l); - } - } - if (status) return 1; /* file handle already on stack top */ - else return luaL_fileresult(L, status, NULL); -} - - -static int io_write (lua_State *L) { - return g_write(L, getiofile(L, IO_OUTPUT), 1); -} - - -static int f_write (lua_State *L) { - FILE *f = tofile(L); - lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ - return g_write(L, f, 2); -} - - -static int f_seek (lua_State *L) { - static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; - static const char *const modenames[] = {"set", "cur", "end", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, "cur", modenames); - lua_Number p3 = luaL_optnumber(L, 3, 0); - l_seeknum offset = (l_seeknum)p3; - luaL_argcheck(L, (lua_Number)offset == p3, 3, - "not an integer in proper range"); - op = l_fseek(f, offset, mode[op]); - if (op) - return luaL_fileresult(L, 0, NULL); /* error */ - else { - lua_pushinteger(L, (lua_Number)l_ftell(f)); - return 1; - } -} - - -static int f_setvbuf (lua_State *L) { - int res; - static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; - static const char *const modenames[] = {"no", "full", "line", NULL}; - FILE *f = tofile(L); - int op = luaL_checkoption(L, 2, NULL, modenames); - lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); - if(sz == 0) - res = setvbuf(f, NULL, _IONBF, sz); - else - res = setvbuf(f, NULL, mode[op], sz); - return luaL_fileresult(L, res == 0, NULL); -} - - - -static int io_flush (lua_State *L) { - return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); -} - - -static int f_flush (lua_State *L) { - return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); -} - - -/* -** functions for 'io' library -*/ -static const luaL_Reg iolib[] = { - {"close", io_close}, - {"flush", io_flush}, - {"input", io_input}, - {"lines", io_lines}, - {"open", io_open}, - {"output", io_output}, - {"popen", io_popen}, - {"read", io_read}, - {"tmpfile", io_tmpfile}, - {"type", io_type}, - {"write", io_write}, - {NULL, NULL} -}; - - -/* -** methods for file handles -*/ -static const luaL_Reg flib[] = { - {"close", io_close}, - {"flush", f_flush}, - {"lines", f_lines}, - {"read", f_read}, - {"seek", f_seek}, - {"setvbuf", f_setvbuf}, - {"write", f_write}, - {"__gc", f_gc}, - {"__tostring", f_tostring}, - {NULL, NULL} +static const luaL_Reg fiolib[] = { + /* helpers */ + { "readcardinal1", readcardinal1 }, + { "readcardinal2", readcardinal2 }, + { "readcardinal3", readcardinal3 }, + { "readcardinal4", readcardinal4 }, + { "readinteger1", readinteger1 }, + { "readinteger2", readinteger2 }, + { "readinteger3", readinteger3 }, + { "readinteger4", readinteger4 }, + { "readfixed2", readfixed2 }, + { "readfixed4", readfixed4 }, + { "read2dot14", read2dot14 }, + { "setposition", setposition }, + { "getposition", getposition }, + { "skipposition", skipposition }, + { "readbytes", readbytes }, + { "readbytetable", readbytetable }, + { "readline", readline }, + /* extras */ + { "recordfilename", recordfilename }, + { "checkpermission", checkpermission }, + /* done */ + {NULL, NULL} }; - -#ifndef LuajitTeX -static void createmeta (lua_State *L) { - luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ - lua_pushvalue(L, -1); /* push metatable */ - lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ - luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ - lua_pop(L, 1); /* pop new metatable */ -} - - -/* -** function to (not) close the standard files stdin, stdout, and stderr -*/ -static int io_noclose (lua_State *L) { - LStream *p = tolstream(L); - p->closef = &io_noclose; /* keep file opened */ - lua_pushnil(L); - lua_pushliteral(L, "cannot close standard file"); - return 2; -} - - -static void createstdfile (lua_State *L, FILE *f, const char *k, - const char *fname) { - LStream *p = newprefile(L); - p->f = f; - p->closef = &io_noclose; - if (k != NULL) { - lua_pushvalue(L, -1); - lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ - } - lua_setfield(L, -2, fname); /* add file to module */ -} -#endif - -int open_iolibext (lua_State *L) { -#ifdef LuajitTeX - return luaopen_io(L); -#else - luaL_newlib(L, iolib); /* new module */ - createmeta(L); - /* create (and set) default files */ - createstdfile(L, stdin, IO_INPUT, "stdin"); - createstdfile(L, stdout, IO_OUTPUT, "stdout"); - createstdfile(L, stderr, NULL, "stderr"); - return 1; -#endif +int luaopen_fio(lua_State *L) { + luaL_register(L, "fio", fiolib); + return 1; } |