summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/lua/liolibext.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/lua/liolibext.c')
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/liolibext.c891
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;
}