summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/luatexdir/lua
diff options
context:
space:
mode:
authorLuigi Scarso <luigi.scarso@gmail.com>2017-03-11 00:31:06 +0000
committerLuigi Scarso <luigi.scarso@gmail.com>2017-03-11 00:31:06 +0000
commit7fa7e2984ec7346b13ce8d3a84826552d30f00ea (patch)
treef177da03ee3839977b28ee4f149cb612666eddde /Build/source/texk/web2c/luatexdir/lua
parentdedac2fcc2339e6d9cddef8edb046fd0e04c397e (diff)
sync with luatex r.6287 and mpost r.2125
git-svn-id: svn://tug.org/texlive/trunk@43454 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/lua')
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/helpers.w26
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lauxlib_bridge.h22
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lepdflib.cc5
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/limglib.c3
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/liolibext.c891
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lnewtokenlib.c49
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/loslibext.c27
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lstatslib.c50
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/lstrlibext.c249
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/luainit.w2248
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/luastuff.w1242
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/luatex-api.h18
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/luatex-core.c253
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/luatex-core.lua209
-rw-r--r--Build/source/texk/web2c/luatexdir/lua/mplibstuff.w93
15 files changed, 2978 insertions, 2407 deletions
diff --git a/Build/source/texk/web2c/luatexdir/lua/helpers.w b/Build/source/texk/web2c/luatexdir/lua/helpers.w
new file mode 100644
index 00000000000..d12e476909d
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/helpers.w
@@ -0,0 +1,26 @@
+% helpers.w
+%
+% Copyright 2017 LuaTeX team <bugs@@luatex.org>
+%
+% This file is part of LuaTeX.
+%
+% LuaTeX is free software; you can redistribute it and/or modify it under
+% the terms of the GNU General Public License as published by the Free
+% Software Foundation; either version 2 of the License, or (at your
+% option) any later version.
+%
+% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
+% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+% 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/>.
+
+@ We will move here some helpers common to code that are now in weird places,
+probably organized in texhelpers, luahelpers, pdfhelpers.
+
+
+
+@c
+/* to fill... */
diff --git a/Build/source/texk/web2c/luatexdir/lua/lauxlib_bridge.h b/Build/source/texk/web2c/luatexdir/lua/lauxlib_bridge.h
index 9f54ffe9103..d71a6786845 100644
--- a/Build/source/texk/web2c/luatexdir/lua/lauxlib_bridge.h
+++ b/Build/source/texk/web2c/luatexdir/lua/lauxlib_bridge.h
@@ -23,10 +23,6 @@
/* http://lua.2524044.n2.nabble.com/converting-modules-in-written-in-C-for-Lua-5-1-to-Lua-5-2-td7642941.html */
#define luaL_setmetatable(L, tname) luaL_getmetatable(L, tname);lua_setmetatable(L, -2);
-/* see http://comments.gmane.org/gmane.comp.programming.swig/18673 */
-/*
-# define lua_rawlen lua_objlen
-*/
LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname);
@@ -39,23 +35,7 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op);
#define lua_unlock(L) ((void) 0)
#endif
-#define luaL_newlibtable(L,l) \
- lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
-
+#define luaL_newlibtable(L,l) lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1)
#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0))
-/* Is this ok as replacement for lua_copy of lua 5.2.4 ? */
-/*
-#if defined(LUAJIT)
-LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) {
- TValue *fr, *to;
- lua_lock(L);
- fr = index2adr(L, fromidx);
- to = index2adr(L, toidx);
- api_checkvalidindex(L, to);
- copyTV(L,to,fr);
- lua_unlock(L);
-}
-#endif
-*/
#endif
diff --git a/Build/source/texk/web2c/luatexdir/lua/lepdflib.cc b/Build/source/texk/web2c/luatexdir/lua/lepdflib.cc
index 00e27863a2c..7250ffd1863 100644
--- a/Build/source/texk/web2c/luatexdir/lua/lepdflib.cc
+++ b/Build/source/texk/web2c/luatexdir/lua/lepdflib.cc
@@ -3484,11 +3484,6 @@ int luaopen_epdf(lua_State * L)
setfuncs_meta(TextSpan);
setfuncs_meta(XRef);
setfuncs_meta(XRefEntry);
-
-#ifdef LuajitTeX
luaL_register(L, "epdf", epdflib_f);
-#else
- luaL_newlib(L, epdflib_f);
-#endif
return 1;
}
diff --git a/Build/source/texk/web2c/luatexdir/lua/limglib.c b/Build/source/texk/web2c/luatexdir/lua/limglib.c
index e82bf9d5184..6010bfd8500 100644
--- a/Build/source/texk/web2c/luatexdir/lua/limglib.c
+++ b/Build/source/texk/web2c/luatexdir/lua/limglib.c
@@ -761,12 +761,11 @@ int luaopen_img(lua_State * L)
luaL_register(L, NULL, img_m);
luaL_newmetatable(L, TYPE_IMG_DICT);
luaL_register(L, NULL, img_dict_m);
- luaL_register(L, "img", imglib_f);
#else
luaL_setfuncs(L, img_m, 0);
luaL_newmetatable(L, TYPE_IMG_DICT);
luaL_setfuncs(L, img_dict_m, 0);
- luaL_newlib(L, imglib_f);
#endif
+ luaL_register(L, "img", imglib_f);
return 1;
}
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;
}
diff --git a/Build/source/texk/web2c/luatexdir/lua/lnewtokenlib.c b/Build/source/texk/web2c/luatexdir/lua/lnewtokenlib.c
index 373f2d98382..a891c59bcbb 100644
--- a/Build/source/texk/web2c/luatexdir/lua/lnewtokenlib.c
+++ b/Build/source/texk/web2c/luatexdir/lua/lnewtokenlib.c
@@ -797,6 +797,53 @@ static int run_scan_token(lua_State * L)
/* TODO: check for a quick way to set a macro to empty (HH) */
+static int get_meaning(lua_State * L)
+{
+ const char *name = null;
+ size_t lname = 0;
+ int cs, cmd;
+ if (lua_type(L, 1) == LUA_TSTRING) {
+ name = lua_tolstring(L, 1, &lname);
+ cs = string_lookup(name, lname);
+ cmd = eq_type(cs);
+ if (cmd >= call_cmd) {
+ int chr = equiv(cs);
+ char *str = tokenlist_to_cstring(chr, true, NULL);
+ lua_pushstring(L, str);
+ free(str);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int get_macro(lua_State * L)
+{
+ const char *name = null;
+ size_t lname = 0;
+ int cs, cmd;
+ if (lua_type(L, 1) == LUA_TSTRING) {
+ name = lua_tolstring(L, 1, &lname);
+ cs = string_lookup(name, lname);
+ cmd = eq_type(cs);
+ if (cmd >= call_cmd) {
+ /*
+ Expanding would expand in-place, unless we make a copy which we don't want to
+ do. So, we just pass the meaning i.e. no: expand_macros_in_tokenlist(chr).
+
+ Actually it would be nice to adapt tokenlist_to_cstring with an extra argument
+ indicating that we are not interested in the before -> part.
+ */
+ int chr = equiv(cs);
+ char *str = tokenlist_to_xstring(chr, true, NULL);
+ lua_pushstring(L, str);
+ free(str);
+ return 1;
+ }
+ }
+ return 0;
+}
+
static int set_macro(lua_State * L)
{
const char *name = null;
@@ -950,6 +997,8 @@ static const struct luaL_Reg tokenlib[] = {
{ "get_protected", lua_tokenlib_get_protected },
/* maybe more setters */
{ "set_macro", set_macro },
+ { "get_macro", get_macro },
+ { "get_meaning", get_meaning },
/* probably never */
/* {"expand", run_expand}, */ /* does not work yet! */
/* {"csname_id", run_get_csname_id}, */ /* yes or no */
diff --git a/Build/source/texk/web2c/luatexdir/lua/loslibext.c b/Build/source/texk/web2c/luatexdir/lua/loslibext.c
index 76dd527c0bf..309d636c4f6 100644
--- a/Build/source/texk/web2c/luatexdir/lua/loslibext.c
+++ b/Build/source/texk/web2c/luatexdir/lua/loslibext.c
@@ -894,11 +894,11 @@ static int os_gettimeofday(lua_State * L)
}
#endif
-static const char repl[] = "0123456789abcdefghijklmnopqrstuvwxyz";
#define MAXTRIES 36*36*36
#ifndef HAVE_MKDTEMP
+static const char repl[] = "0123456789abcdefghijklmnopqrstuvwxyz";
static int dirs_made = 0;
static char *do_mkdtemp(char *tmpl)
@@ -1014,7 +1014,7 @@ static int os_execute(lua_State * L)
}
-void open_oslibext(lua_State * L, int safer)
+void open_oslibext(lua_State * L)
{
find_env(L);
@@ -1037,17 +1037,16 @@ void open_oslibext(lua_State * L, int safer)
lua_setfield(L, -2, "gettimeofday");
#endif
- if (!safer) {
- lua_pushcfunction(L, os_setenv);
- lua_setfield(L, -2, "setenv");
- lua_pushcfunction(L, os_exec);
- lua_setfield(L, -2, "exec");
- lua_pushcfunction(L, os_spawn);
- lua_setfield(L, -2, "spawn");
- lua_pushcfunction(L, os_execute);
- lua_setfield(L, -2, "execute");
- lua_pushcfunction(L, os_tmpdir);
- lua_setfield(L, -2, "tmpdir");
- }
+ lua_pushcfunction(L, os_setenv);
+ lua_setfield(L, -2, "setenv");
+ lua_pushcfunction(L, os_exec);
+ lua_setfield(L, -2, "exec");
+ lua_pushcfunction(L, os_spawn);
+ lua_setfield(L, -2, "spawn");
+ lua_pushcfunction(L, os_execute);
+ lua_setfield(L, -2, "execute");
+ lua_pushcfunction(L, os_tmpdir);
+ lua_setfield(L, -2, "tmpdir");
+
lua_pop(L, 1); /* pop the table */
}
diff --git a/Build/source/texk/web2c/luatexdir/lua/lstatslib.c b/Build/source/texk/web2c/luatexdir/lua/lstatslib.c
index 7473ca214a4..d055dc35cea 100644
--- a/Build/source/texk/web2c/luatexdir/lua/lstatslib.c
+++ b/Build/source/texk/web2c/luatexdir/lua/lstatslib.c
@@ -121,6 +121,21 @@ static const char *getenginename(void)
return engine_name;
}
+static const char * get_lc_ctype(void)
+{
+ return lc_ctype;
+}
+
+static const char * get_lc_collate(void)
+{
+ return lc_collate;
+}
+
+static const char * get_lc_numeric(void)
+{
+ return lc_numeric;
+}
+
static lua_Number get_luatexhashchars(void)
@@ -216,14 +231,36 @@ static int get_hash_size(void)
static lua_Number shell_escape_state(void)
{
if (shellenabledp <= 0) {
+ /* No shell at all. */
return (lua_Number) 0;
} else if (restrictedshell == 0) {
+ /* Shell has no restriction. */
+ return (lua_Number) 2;
+ } else {
+ /* Shell has restrictions, see cnf file. */
+ return (lua_Number) 1;
+ }
+}
+
+static lua_Number safer_option_state(void)
+{
+ if (safer_option == 0) {
+ return (lua_Number) 0;
+ } else {
+ return (lua_Number) 1;
+ }
+}
+
+static lua_Number kpse_used_state(void)
+{
+ if (kpse_init == 1) {
return (lua_Number) 1;
} else {
- return (lua_Number) 2;
+ return (lua_Number) 0;
}
}
+
/* temp, for backward compat */
static int init_pool_ptr = 0;
@@ -255,14 +292,16 @@ static struct statistic stats[] = {
{"log_name", 'S', (void *) &getlogname},
{"banner", 'S', (void *) &getbanner},
{"luatex_version", 'G', &get_luatexversion},
- {"luatex_revision", 'S', (void *) &luatexrevision},
+ {"luatex_revision", 'S', (void *) &luatexrevision},
{"luatex_hashtype", 'S', (void *) &get_luatexhashtype},
{"luatex_hashchars", 'N', &get_luatexhashchars},
{"luatex_engine", 'S', (void *) &getenginename},
{"ini_version", 'b', &ini_version},
- {"shell_escape", 'N', &shell_escape_state}, /* be easy on old time usage */
+ {"shell_escape", 'N', &shell_escape_state},
+ {"safer_option", 'N', &safer_option_state},
+ {"kpse_used", 'N', &kpse_used_state},
/*
* mem stat
*/
@@ -310,8 +349,13 @@ static struct statistic stats[] = {
{"luabytecode_bytes", 'g', &luabytecode_bytes},
{"luastate_bytes", 'g', &luastate_bytes},
{"callbacks", 'g', &callback_count},
+
{"indirect_callbacks", 'g', &saved_callback_count},
+ {"lc_ctype", 'S', (void *) &get_lc_ctype},
+ {"lc_collate", 'S', (void *) &get_lc_collate},
+ {"lc_numeric",'S', (void *) &get_lc_numeric},
+
{NULL, 0, 0}
};
diff --git a/Build/source/texk/web2c/luatexdir/lua/lstrlibext.c b/Build/source/texk/web2c/luatexdir/lua/lstrlibext.c
index 8a474fd09c9..5d5c0d723ac 100644
--- a/Build/source/texk/web2c/luatexdir/lua/lstrlibext.c
+++ b/Build/source/texk/web2c/luatexdir/lua/lstrlibext.c
@@ -1,5 +1,5 @@
/* lstrlibext.c
-
+
Copyright 2012 Taco Hoekwater <taco@luatex.org>
This file is part of LuaTeX.
@@ -25,100 +25,71 @@
#define LUA_CORE
#include "lua.h"
+#ifdef LuajitTeX
+#include "lauxlib.h"
+#include "lualib.h"
+#else
#include "luaconf.h"
#include "lapi.h"
#include "lundump.h"
+#endif
-
-static int str_split (lua_State *L) {
- size_t l;
- size_t i;
- int n;
- char *q, *p, *orig;
- int mult = 0;
- const char *s = luaL_checklstring(L, 1, &l);
- const char *joiner = luaL_optstring(L, 2, " +");
- lua_newtable(L);
- if (l == 0) {
- lua_pushvalue(L,1);
- lua_rawseti(L,-2,1);
- return 1;
- }
- orig = p = malloc(l+1);
- if (p==NULL) {
- fprintf(stderr, "fatal: memory exhausted (malloc of %u bytes).\n",(int)(l+1));
- exit(EXIT_FAILURE);
- }
- strcpy(p,s);
- n = 1;
- q = p;
-
- if (*joiner == 0) {
- for (i=0;i<l;i++) {
- lua_pushlstring(L,q,1); q++;
- lua_rawseti(L,-2,n); n++;
- }
- free(orig);
- return 1;
- }
- if (*(joiner+1) == '+') {
- mult = 1;
- while(*p==*joiner) {
- p++;
- l--;
+static int bytepairs_aux (lua_State *L) {
+ size_t ls;
+ unsigned char i;
+ const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
+ int ind = lua_tointeger(L, lua_upvalueindex(2));
+ if (ind<(int)ls) {
+ if (ind+1<(int)ls) {
+ lua_pushinteger(L, (ind+2)); /* iterator */
+ } else {
+ lua_pushinteger(L, (ind+1)); /* iterator */
}
- q = p;
- }
- for (i=0;i<l;i++) {
- if (*(p+i)==*joiner) {
- *(p+i) = 0;
- lua_pushlstring(L,q,((p+i)-q));
- lua_rawseti(L,-2,n); n++;
- if (mult) {
- while(*(p+i+1)==*joiner) {
- i++;
- }
- }
- q = p+i+1;
+ lua_replace(L, lua_upvalueindex(2));
+ i = (unsigned char)*(s+ind);
+ lua_pushinteger(L, i); /* byte one */
+ if (ind+1<(int)ls) {
+ i = (unsigned char)*(s+ind+1);
+ lua_pushinteger(L, i); /* byte two */
+ } else {
+ lua_pushnil(L); /* odd string length */
}
+ return 2;
}
- if (mult && q==(p+l)) {
- free(orig);
- return 1;
- }
- if(q<=(p+l)) {
- lua_pushlstring(L,q,strlen(q));
- lua_rawseti(L,-2,n);
- }
- free(orig);
+ return 0; /* string ended */
+}
+
+static int str_bytepairs (lua_State *L) {
+ luaL_checkstring(L, 1);
+ lua_settop(L, 1);
+ lua_pushinteger(L, 0);
+ lua_pushcclosure(L, bytepairs_aux, 2);
return 1;
-}
+}
-static int characters_aux (lua_State *L) {
+static int bytes_aux (lua_State *L) {
size_t ls;
- char b[2];
+ unsigned char i;
const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
- int ind = lua_tointeger(L, lua_upvalueindex(2));
+ int ind = lua_tointeger(L, lua_upvalueindex(2));
if (ind<(int)ls) {
lua_pushinteger(L, (ind+1)); /* iterator */
lua_replace(L, lua_upvalueindex(2));
- b[0] = *(s+ind); b[1] = 0;
- lua_pushlstring(L, b, 1);
+ i = (unsigned char)*(s+ind);
+ lua_pushinteger(L, i); /* byte */
return 1;
}
return 0; /* string ended */
}
-
-static int str_characters (lua_State *L) {
+static int str_bytes (lua_State *L) {
luaL_checkstring(L, 1);
lua_settop(L, 1);
lua_pushinteger(L, 0);
- lua_pushcclosure(L, characters_aux, 2);
+ lua_pushcclosure(L, bytes_aux, 2);
return 1;
}
-
static int utf_failed(lua_State *L, int new_ind) {
static char fffd [3] = {0xEF,0xBF,0xBD};
lua_pushinteger(L, new_ind); /* iterator */
@@ -152,8 +123,7 @@ static int utfcharacters_aux (lua_State *L) {
}
}
return utf_failed(L,ind+1); /* we found a follow byte! */
-}
-
+}
static int str_utfcharacters (lua_State *L) {
luaL_checkstring(L, 1);
@@ -163,7 +133,6 @@ static int str_utfcharacters (lua_State *L) {
return 1;
}
-
static int utfvalues_aux (lua_State *L) {
size_t ls;
unsigned char i = 0;
@@ -180,7 +149,7 @@ static int utfvalues_aux (lua_State *L) {
if (i<0x80) {
v = i;
} else if (i>=0xF0) {
- if ((ind+3)<(int)ls && ((unsigned)*(s+ind+1))>=0x80
+ if ((ind+3)<(int)ls && ((unsigned)*(s+ind+1))>=0x80
&& ((unsigned)*(s+ind+2))>=0x80 && ((unsigned)*(s+ind+3))>=0x80) {
numbytes = 4;
j = ((unsigned)*(s+ind+1))-128;
@@ -211,7 +180,6 @@ static int utfvalues_aux (lua_State *L) {
return 0; /* string ended */
}
-
static int str_utfvalues (lua_State *L) {
luaL_checkstring(L, 1);
lua_settop(L, 1);
@@ -220,8 +188,6 @@ static int str_utfvalues (lua_State *L) {
return 1;
}
-
-
static int characterpairs_aux (lua_State *L) {
size_t ls;
char b[2];
@@ -237,7 +203,7 @@ static int characterpairs_aux (lua_State *L) {
b[0] = *(s+ind); b[1] = 0;
lua_pushlstring(L, b, 1);
if (ind+1<(int)ls) {
- b[0] = *(s+ind+1);
+ b[0] = *(s+ind+1);
lua_pushlstring(L, b, 1);
} else {
lua_pushlstring(L, b+1, 0);
@@ -247,7 +213,6 @@ static int characterpairs_aux (lua_State *L) {
return 0; /* string ended */
}
-
static int str_characterpairs (lua_State *L) {
luaL_checkstring(L, 1);
lua_settop(L, 1);
@@ -256,65 +221,96 @@ static int str_characterpairs (lua_State *L) {
return 1;
}
-static int bytes_aux (lua_State *L) {
+static int characters_aux (lua_State *L) {
size_t ls;
- unsigned char i;
+ char b[2];
const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
- int ind = lua_tointeger(L, lua_upvalueindex(2));
+ int ind = lua_tointeger(L, lua_upvalueindex(2));
if (ind<(int)ls) {
lua_pushinteger(L, (ind+1)); /* iterator */
lua_replace(L, lua_upvalueindex(2));
- i = (unsigned char)*(s+ind);
- lua_pushinteger(L, i); /* byte */
+ b[0] = *(s+ind); b[1] = 0;
+ lua_pushlstring(L, b, 1);
return 1;
}
return 0; /* string ended */
}
-static int str_bytes (lua_State *L) {
+static int str_characters (lua_State *L) {
luaL_checkstring(L, 1);
lua_settop(L, 1);
lua_pushinteger(L, 0);
- lua_pushcclosure(L, bytes_aux, 2);
+ lua_pushcclosure(L, characters_aux, 2);
return 1;
}
-static int bytepairs_aux (lua_State *L) {
- size_t ls;
- unsigned char i;
- const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls);
- int ind = lua_tointeger(L, lua_upvalueindex(2));
- if (ind<(int)ls) {
- if (ind+1<(int)ls) {
- lua_pushinteger(L, (ind+2)); /* iterator */
- } else {
- lua_pushinteger(L, (ind+1)); /* iterator */
+static int str_split (lua_State *L) {
+ size_t l;
+ size_t i;
+ int n;
+ char *q, *p, *orig;
+ int mult = 0;
+ const char *s = luaL_checklstring(L, 1, &l);
+ const char *joiner = luaL_optstring(L, 2, " +");
+ lua_newtable(L);
+ if (l == 0) {
+ lua_pushvalue(L,1);
+ lua_rawseti(L,-2,1);
+ return 1;
+ }
+ orig = p = malloc(l+1);
+ if (p==NULL) {
+ fprintf(stderr, "fatal: memory exhausted (malloc of %u bytes).\n",(int)(l+1));
+ exit(EXIT_FAILURE);
+ }
+ strcpy(p,s);
+ n = 1;
+ q = p;
+
+ if (*joiner == 0) {
+ for (i=0;i<l;i++) {
+ lua_pushlstring(L,q,1); q++;
+ lua_rawseti(L,-2,n); n++;
}
- lua_replace(L, lua_upvalueindex(2));
- i = (unsigned char)*(s+ind);
- lua_pushinteger(L, i); /* byte one */
- if (ind+1<(int)ls) {
- i = (unsigned char)*(s+ind+1);
- lua_pushinteger(L, i); /* byte two */
- } else {
- lua_pushnil(L); /* odd string length */
+ free(orig);
+ return 1;
+ }
+ if (*(joiner+1) == '+') {
+ mult = 1;
+ while(*p==*joiner) {
+ p++;
+ l--;
}
- return 2;
+ q = p;
}
- return 0; /* string ended */
-}
-
-
-static int str_bytepairs (lua_State *L) {
- luaL_checkstring(L, 1);
- lua_settop(L, 1);
- lua_pushinteger(L, 0);
- lua_pushcclosure(L, bytepairs_aux, 2);
+ for (i=0;i<l;i++) {
+ if (*(p+i)==*joiner) {
+ *(p+i) = 0;
+ lua_pushlstring(L,q,((p+i)-q));
+ lua_rawseti(L,-2,n); n++;
+ if (mult) {
+ while(*(p+i+1)==*joiner) {
+ i++;
+ }
+ }
+ q = p+i+1;
+ }
+ }
+ if (mult && q==(p+l)) {
+ free(orig);
+ return 1;
+ }
+ if(q<=(p+l)) {
+ lua_pushlstring(L,q,strlen(q));
+ lua_rawseti(L,-2,n);
+ }
+ free(orig);
return 1;
}
-
-
+#ifdef LuajitTeX
+ /* dump is built in */
+#else
static int writer (lua_State *L, const void* b, size_t size, void* B) {
(void)L;
luaL_addlstring((luaL_Buffer*) B, (const char *)b, size);
@@ -349,8 +345,19 @@ static int str_dump (lua_State *L) {
luaL_pushresult(&b);
return 1;
}
-
-
+#endif /*ifdef LuajitTeX*/
+
+static int str_bytetable (lua_State *L) {
+ size_t l;
+ int i;
+ const char *s = luaL_checklstring(L, 1, &l);
+ lua_createtable(L,l,0);
+ for (i=0;i<l;i++) {
+ lua_pushinteger(L,(unsigned char)*(s+i));
+ lua_rawseti(L,-2,i+1);
+ }
+ return 1;
+}
static const luaL_Reg strlibext[] = {
{"utfvalues", str_utfvalues},
@@ -359,8 +366,13 @@ static const luaL_Reg strlibext[] = {
{"characterpairs", str_characterpairs},
{"bytes", str_bytes},
{"bytepairs", str_bytepairs},
+ {"bytetable", str_bytetable},
{"explode", str_split},
+#ifdef LuajitTeX
+ /* luajit has dump built in */
+#else
{"dump", str_dump},
+#endif
{NULL, NULL}
};
@@ -374,4 +386,3 @@ void open_strlibext(lua_State * L)
}
lua_pop(L,1);
}
-
diff --git a/Build/source/texk/web2c/luatexdir/lua/luainit.w b/Build/source/texk/web2c/luatexdir/lua/luainit.w
index fe0c3de5eb0..de2bf47cc46 100644
--- a/Build/source/texk/web2c/luatexdir/lua/luainit.w
+++ b/Build/source/texk/web2c/luatexdir/lua/luainit.w
@@ -1,1095 +1,1153 @@
-% luainit.w
-%
-% Copyright 2006-2017 Taco Hoekwater <taco@@luatex.org>
-%
-% This file is part of LuaTeX.
-%
-% LuaTeX is free software; you can redistribute it and/or modify it under
-% the terms of the GNU General Public License as published by the Free
-% Software Foundation; either version 2 of the License, or (at your
-% option) any later version.
-%
-% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
-% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-% 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/>.
-
-@ @c
-
-#include "ptexlib.h"
-
-#include <kpathsea/c-stat.h>
-
-#include "lua/luatex-api.h"
-
-/* internalized strings: see luatex-api.h */
-set_make_keys;
-
-@
-This file is getting a bit messy, but it is not simple to fix unilaterally.
-
-Better to wait until Karl has some time (after texlive 2008) so we can
-synchronize with kpathsea. One problem, for instance, is that I would
-like to resolve the full executable path. |kpse_set_program_name()| does
-that, indirectly (by setting SELFAUTOLOC in the environment), but it
-does much more, making it hard to use for our purpose.
-
-In fact, it sets three C variables:
-
- |kpse_invocation_name| |kpse_invocation_short_name| |kpse->program_name|
-
-and five environment variables:
-
- SELFAUTOLOC SELFAUTODIR SELFAUTOPARENT SELFAUTOGRANDPARENT progname
-
-@c
-const_string LUATEX_IHELP[] = {
- "Usage: " my_name " --lua=FILE [OPTION]... [TEXNAME[.tex]] [COMMANDS]",
- " or: " my_name " --lua=FILE [OPTION]... \\FIRST-LINE",
- " or: " my_name " --lua=FILE [OPTION]... &FMT ARGS",
- " Run " MyName " on TEXNAME, usually creating TEXNAME.pdf.",
- " Any remaining COMMANDS are processed as luatex input, after TEXNAME is read.",
- "",
- " Alternatively, if the first non-option argument begins with a backslash,",
- " " my_name " interprets all non-option arguments as an input line.",
- "",
- " Alternatively, if the first non-option argument begins with a &, the",
- " next word is taken as the FMT to read, overriding all else. Any",
- " remaining arguments are processed as above.",
- "",
- " If no arguments or options are specified, prompt for input.",
- "",
- " The following regular options are understood: ",
- "",
- " --credits display credits and exit",
- " --debug-format enable format debugging",
- " --draftmode switch on draft mode (generates no output PDF)",
- " --[no-]file-line-error disable/enable file:line:error style messages",
- " --[no-]file-line-error-style aliases of --[no-]file-line-error",
- " --fmt=FORMAT load the format file FORMAT",
- " --halt-on-error stop processing at the first error",
- " --help display help and exit",
- " --ini be ini" my_name ", for dumping formats",
- " --interaction=STRING set interaction mode (STRING=batchmode/nonstopmode/scrollmode/errorstopmode)",
- " --jobname=STRING set the job name to STRING",
- " --kpathsea-debug=NUMBER set path searching debugging flags according to the bits of NUMBER",
- " --lua=FILE load and execute a lua initialization script",
- " --[no-]mktex=FMT disable/enable mktexFMT generation (FMT=tex/tfm)",
- " --nosocket disable the lua socket library",
- " --output-comment=STRING use STRING for DVI file comment instead of date (no effect for PDF)",
- " --output-directory=DIR use existing DIR as the directory to write files in",
- " --output-format=FORMAT use FORMAT for job output; FORMAT is 'dvi' or 'pdf'",
- " --progname=STRING set the program name to STRING",
- " --recorder enable filename recorder",
- " --safer disable easily exploitable lua commands",
- " --[no-]shell-escape disable/enable system commands",
- " --shell-restricted restrict system commands to a list of commands given in texmf.cnf",
- " --synctex=NUMBER enable synctex",
- " --utc init time to UTC",
- " --version display version and exit",
- "",
- "Alternate behaviour models can be obtained by special switches",
- "",
- " --luaonly run a lua file, then exit",
- " --luaconly byte-compile a lua file, then exit",
- " --luahashchars the bits used by current Lua interpreter for strings hashing",
-#ifdef LuajitTeX
- " --jiton turns the JIT compiler on (default off)",
- " --jithash=STRING choose the hash function for the lua strings (lua51|luajit20: default lua51)",
-#endif
- "",
- "See the reference manual for more information about the startup process.",
- NULL
-};
-
-/*
- " --8bit ignored, input is assumed to be in UTF-8 encoding",
- " --default-translate-file=FILE ignored, input is assumed to be in UTF-8 encoding",
- " --etex ignored, the etex extensions are always active",
- " --disable-write18 disable \\write18{SHELL COMMAND}",
- " --enable-write18 enable \\write18{SHELL COMMAND}",
- " --[no-]parse-first-line ignored",
- " --translate-file=FILE ignored, input is assumed to be in UTF-8 encoding",
-*/
-
-@ The return value will be the directory of the executable, e.g.: \.{c:/TeX/bin}
-@c
-static char *ex_selfdir(char *argv0)
-{
-#if defined(WIN32)
-#if defined(__MINGW32__)
- char path[PATH_MAX], *fp;
-
- /* SearchPath() always gives back an absolute directory */
- if (SearchPath(NULL, argv0, ".exe", PATH_MAX, path, NULL) == 0)
- FATAL1("Can't determine where the executable %s is.\n", argv0);
- /* slashify the dirname */
- for (fp = path; fp && *fp; fp++)
- if (IS_DIR_SEP(*fp))
- *fp = DIR_SEP;
-#else /* __MINGW32__ */
-#define PATH_MAX 512
- char short_path[PATH_MAX], path[PATH_MAX], *fp;
-
- /* SearchPath() always gives back an absolute directory */
- if (SearchPath(NULL, argv0, ".exe", PATH_MAX, short_path, &fp) == 0)
- FATAL1("Can't determine where the executable %s is.\n", argv0);
- if (getlongpath(path, short_path, sizeof(path)) == 0) {
- FATAL1("This path points to an invalid file : %s\n", short_path);
- }
-#endif /* __MINGW32__ */
- return xdirname(path);
-#else /* WIN32 */
- return kpse_selfdir(argv0);
-#endif
-}
-
-@ @c
-static void prepare_cmdline(lua_State * L, char **av, int ac, int zero_offset)
-{
- int i;
- char *s;
- luaL_checkstack(L, ac + 3, "too many arguments to script");
- lua_createtable(L, 0, 0);
- for (i = 0; i < ac; i++) {
- lua_pushstring(L, av[i]);
- lua_rawseti(L, -2, (i - zero_offset));
- }
- lua_setglobal(L, "arg");
- lua_getglobal(L, "os");
- s = ex_selfdir(argv[0]);
- lua_pushstring(L, s);
- xfree(s);
- lua_setfield(L, -2, "selfdir");
- return;
-}
-
-
-@ @c
-int kpse_init = -1;
-
-@ @c
-string input_name = NULL;
-
-static string user_progname = NULL;
-
-char *startup_filename = NULL;
-int lua_only = 0;
-int lua_offset = 0;
-unsigned char show_luahashchars = 0;
-
-#ifdef LuajitTeX
-int luajiton = 0;
-char *jithash_hashname = NULL;
-#endif
-
-int safer_option = 0;
-int nosocket_option = 0;
-int utc_option = 0;
-
-@ Reading the options.
-
-@ Test whether getopt found an option ``A''.
-Assumes the option index is in the variable |option_index|, and the
-option table in a variable |long_options|.
-
-@c
-#define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a)
-
-/*
- SunOS cc can't initialize automatic structs, so make this static.
-*/
-
-/*
- Nota Bene: we still intercept some options that other engines handle
- so that existing scripted usage will not fail.
-*/
-
-static struct option long_options[] = {
- {"fmt", 1, 0, 0},
- {"lua", 1, 0, 0},
- {"luaonly", 0, 0, 0},
- {"luahashchars", 0, 0, 0},
-#ifdef LuajitTeX
- {"jiton", 0, 0, 0},
- {"jithash", 1, 0, 0},
-#endif
- {"safer", 0, &safer_option, 1},
- {"utc", 0, &utc_option, 1},
- {"nosocket", 0, &nosocket_option, 1},
- {"help", 0, 0, 0},
- {"ini", 0, &ini_version, 1},
- {"interaction", 1, 0, 0},
- {"halt-on-error", 0, &haltonerrorp, 1},
- {"kpathsea-debug", 1, 0, 0},
- {"progname", 1, 0, 0},
- {"version", 0, 0, 0},
- {"credits", 0, 0, 0},
- {"recorder", 0, 0, 0},
- {"etex", 0, 0, 0},
- {"output-comment", 1, 0, 0},
- {"output-directory", 1, 0, 0},
- {"draftmode", 0, 0, 0},
- {"output-format", 1, 0, 0},
- {"shell-escape", 0, &shellenabledp, 1},
- {"no-shell-escape", 0, &shellenabledp, -1},
- {"enable-write18", 0, &shellenabledp, 1},
- {"disable-write18", 0, &shellenabledp, -1},
- {"shell-restricted", 0, 0, 0},
- {"debug-format", 0, &debug_format_file, 1},
- {"file-line-error-style", 0, &filelineerrorstylep, 1},
- {"no-file-line-error-style", 0, &filelineerrorstylep, -1},
-
- /* Shorter option names for the above. */
-
- {"file-line-error", 0, &filelineerrorstylep, 1},
- {"no-file-line-error", 0, &filelineerrorstylep, -1},
- {"jobname", 1, 0, 0},
- {"parse-first-line", 0, &parsefirstlinep, 1},
- {"no-parse-first-line", 0, &parsefirstlinep, -1},
- {"translate-file", 1, 0, 0},
- {"default-translate-file", 1, 0, 0},
- {"8bit", 0, 0, 0},
- {"mktex", 1, 0, 0},
- {"no-mktex", 1, 0, 0},
-
- /* Synchronization: just like "interaction" above */
-
- {"synctex", 1, 0, 0},
- {0, 0, 0, 0}
-};
-
-@ @c
-int lua_numeric_field_by_index(lua_State * L, int name_index, int dflt)
-{
- register int i = dflt;
- lua_rawgeti(L, LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */
- lua_rawget(L, -2);
- if (lua_type(L, -1) == LUA_TNUMBER) {
- i = lua_roundnumber(L, -1);
- }
- lua_pop(L, 1);
- return i;
-}
-
-@ @c
-unsigned int lua_unsigned_numeric_field_by_index(lua_State * L, int name_index, int dflt)
-{
- register unsigned int i = dflt;
- lua_rawgeti(L, LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */
- lua_rawget(L, -2);
- if (lua_type(L, -1) == LUA_TNUMBER) {
- i = lua_uroundnumber(L, -1);
- }
- lua_pop(L, 1);
- return i;
-}
-
-@ @c
-static int recorderoption = 0;
-
-static void parse_options(int ac, char **av)
-{
-#ifdef WIN32
-/* save argc and argv */
- int sargc = argc;
- char **sargv = argv;
-#endif
- int g; /* `getopt' return code. */
- int option_index;
- char *firstfile = NULL;
- opterr = 0; /* dont whine */
-#ifdef LuajitTeX
- if ((strstr(argv[0], "luajittexlua") != NULL) ||
- (strstr(argv[0], "texluajit") != NULL)) {
-#else
- if ((strstr(argv[0], "luatexlua") != NULL) ||
- (strstr(argv[0], "texlua") != NULL)) {
-#endif
- lua_only = 1;
- luainit = 1;
- }
- for (;;) {
- g = getopt_long_only(ac, av, "+", long_options, &option_index);
-
- if (g == -1) /* End of arguments, exit the loop. */
- break;
- if (g == '?') { /* Unknown option. */
- if (!luainit)
- fprintf(stderr,"%s: unrecognized option '%s'\n", argv[0], argv[optind-1]);
- continue;
- }
-
- assert(g == 0); /* We have no short option names. */
-
- if (ARGUMENT_IS("luaonly")) {
- lua_only = 1;
- lua_offset = optind;
- luainit = 1;
- } else if (ARGUMENT_IS("lua")) {
- startup_filename = optarg;
- lua_offset = (optind - 1);
- luainit = 1;
-#ifdef LuajitTeX
- } else if (ARGUMENT_IS("jiton")) {
- luajiton = 1;
- } else if (ARGUMENT_IS("jithash")) {
- size_t len = strlen(optarg);
- if (len<16) {
- jithash_hashname = optarg;
- } else {
- WARNING2("hash name truncated to 15 characters from %d. (%s)", (int) len, optarg);
- jithash_hashname = (string) xmalloc(16);
- strncpy(jithash_hashname, optarg, 15);
- jithash_hashname[15] = 0;
- }
-#endif
- } else if (ARGUMENT_IS("luahashchars")) {
- show_luahashchars = 1;
- } else if (ARGUMENT_IS("kpathsea-debug")) {
- kpathsea_debug |= atoi(optarg);
- } else if (ARGUMENT_IS("progname")) {
- user_progname = optarg;
- } else if (ARGUMENT_IS("jobname")) {
- c_job_name = optarg;
- } else if (ARGUMENT_IS("fmt")) {
- dump_name = optarg;
- } else if (ARGUMENT_IS("output-directory")) {
- output_directory = optarg;
- } else if (ARGUMENT_IS("output-comment")) {
- size_t len = strlen(optarg);
- if (len < 256) {
- output_comment = optarg;
- } else {
- WARNING2("Comment truncated to 255 characters from %d. (%s)", (int) len, optarg);
- output_comment = (string) xmalloc(256);
- strncpy(output_comment, optarg, 255);
- output_comment[255] = 0;
- }
- } else if (ARGUMENT_IS("shell-restricted")) {
- shellenabledp = 1;
- restrictedshell = 1;
- } else if (ARGUMENT_IS("output-format")) {
- output_mode_option = 1;
- if (strcmp(optarg, "dvi") == 0) {
- output_mode_value = 0;
- } else if (strcmp(optarg, "pdf") == 0) {
- output_mode_value = 1;
- } else {
- WARNING1("Ignoring unknown value `%s' for --output-format",optarg);
- output_mode_option = 0;
- }
- } else if (ARGUMENT_IS("draftmode")) {
- draft_mode_option = 1;
- draft_mode_value = 1;
- } else if (ARGUMENT_IS("mktex")) {
- kpse_maketex_option(optarg, true);
- } else if (ARGUMENT_IS("no-mktex")) {
- kpse_maketex_option(optarg, false);
- } else if (ARGUMENT_IS("interaction")) {
- /* These numbers match CPP defines */
- if (STREQ(optarg, "batchmode")) {
- interactionoption = 0;
- } else if (STREQ(optarg, "nonstopmode")) {
- interactionoption = 1;
- } else if (STREQ(optarg, "scrollmode")) {
- interactionoption = 2;
- } else if (STREQ(optarg, "errorstopmode")) {
- interactionoption = 3;
- } else {
- WARNING1("Ignoring unknown argument `%s' to --interaction", optarg);
- }
- } else if (ARGUMENT_IS("synctex")) {
- /* Synchronize TeXnology: catching the command line option as a long */
- synctexoption = (int) strtol(optarg, NULL, 0);
- } else if (ARGUMENT_IS("recorder")) {
- recorderoption = 1 ;
- } else if (ARGUMENT_IS("help")) {
- usagehelp(LUATEX_IHELP, BUG_ADDRESS);
- } else if (ARGUMENT_IS("version")) {
- print_version_banner();
- /* *INDENT-OFF* */
- puts("\n\nExecute '" my_name " --credits' for credits and version details.\n\n"
- "There is NO warranty. Redistribution of this software is covered by\n"
- "the terms of the GNU General Public License, version 2 or (at your option)\n"
- "any later version. For more information about these matters, see the file\n"
- "named COPYING and the LuaTeX source.\n\n"
- "LuaTeX is Copyright 2017 Taco Hoekwater and the LuaTeX Team.\n");
- /* *INDENT-ON* */
- uexit(0);
- } else if (ARGUMENT_IS("credits")) {
- char *versions;
- initversionstring(&versions);
- print_version_banner();
- /* *INDENT-OFF* */
- puts("\n\nThe LuaTeX team is Hans Hagen, Hartmut Henkel, Taco Hoekwater, Luigi Scarso.\n\n"
- MyName " merges and builds upon (parts of) the code from these projects:\n\n"
- "tex : Donald Knuth\n"
- "etex : Peter Breitenlohner, Phil Taylor and friends\n"
- "omega : John Plaice and Yannis Haralambous\n"
- "aleph : Giuseppe Bilotta\n"
- "pdftex : Han The Thanh and friends\n"
- "kpathsea : Karl Berry, Olaf Weber and others\n"
- "lua : Roberto Ierusalimschy, Waldemar Celes and Luiz Henrique de Figueiredo\n"
- "metapost : John Hobby, Taco Hoekwater and friends\n"
- "poppler : Derek Noonburg, Kristian H\\ogsberg (partial)\n"
- "fontforge : George Williams (partial)\n"
- "luajit : Mike Pall (used in LuajitTeX)\n");
- /* *INDENT-ON* */
- puts(versions);
- uexit(0);
- }
- }
- /* attempt to find |input_name| / |dump_name| */
- if (lua_only) {
- if (argv[optind]) {
- startup_filename = xstrdup(argv[optind]);
- lua_offset = optind;
- }
- } else if (argv[optind] && argv[optind][0] == '&') {
- dump_name = xstrdup(argv[optind] + 1);
- } else if (argv[optind] && argv[optind][0] != '\\') {
- if (argv[optind][0] == '*') {
- input_name = xstrdup(argv[optind] + 1);
- } else {
- firstfile = xstrdup(argv[optind]);
- if ((strstr(firstfile, ".lua") ==
- firstfile + strlen(firstfile) - 4)
- || (strstr(firstfile, ".luc") ==
- firstfile + strlen(firstfile) - 4)
- || (strstr(firstfile, ".LUA") ==
- firstfile + strlen(firstfile) - 4)
- || (strstr(firstfile, ".LUC") ==
- firstfile + strlen(firstfile) - 4)) {
- if (startup_filename == NULL) {
- startup_filename = firstfile;
- lua_offset = optind;
- lua_only = 1;
- luainit = 1;
- }
- } else {
- input_name = firstfile;
- }
- }
-#ifdef WIN32
- } else if (sargc > 1 && sargv[sargc-1] && sargv[sargc-1][0] != '-' &&
- sargv[sargc-1][0] != '\\') {
- if (sargv[sargc-1][0] == '&')
- dump_name = xstrdup(sargv[sargc-1] + 1);
- else {
- if (sargv[sargc-1][0] == '*')
- input_name = xstrdup(sargv[sargc-1] + 1);
- else
- input_name = xstrdup(sargv[sargc-1]);
- sargv[sargc-1] = normalize_quotes(input_name, "argument");
- }
- if (safer_option) /* --safer implies --nosocket */
- nosocket_option = 1;
- return;
-#endif
- }
- if (safer_option) /* --safer implies --nosocket */
- nosocket_option = 1;
- /* Finalize the input filename. */
- if (input_name != NULL) {
- argv[optind] = normalize_quotes(input_name, "argument");
- }
-}
-
-@ test for readability
-@c
-#define is_readable(a) (stat(a,&finfo)==0) && S_ISREG(finfo.st_mode) && \
- (f=fopen(a,"r")) != NULL && !fclose(f)
-
-@ @c
-static char *find_filename(char *name, const char *envkey)
-{
- struct stat finfo;
- char *dirname = NULL;
- char *filename = NULL;
- FILE *f;
- if (is_readable(name)) {
- return name;
- } else {
- dirname = getenv(envkey);
- if ((dirname != NULL) && strlen(dirname)) {
- dirname = xstrdup(getenv(envkey));
- if (*(dirname + strlen(dirname) - 1) == '/') {
- *(dirname + strlen(dirname) - 1) = 0;
- }
- filename = xmalloc((unsigned) (strlen(dirname) + strlen(name) + 2));
- filename = concat3(dirname, "/", name);
- xfree(dirname);
- if (is_readable(filename)) {
- return filename;
- }
- xfree(filename);
- }
- }
- return NULL;
-}
-
-@ @c
-
-static void init_kpse(void)
-{
- if (!user_progname) {
- user_progname = dump_name;
- } else if (!dump_name) {
- dump_name = user_progname;
- }
- if (!user_progname) {
- if (ini_version) {
- if (input_name) {
- char *p = input_name + strlen(input_name) - 1;
- while (p >= input_name) {
- if (IS_DIR_SEP (*p)) {
- p++;
- input_name = p;
- break;
- }
- p--;
- }
- user_progname = remove_suffix (input_name);
- }
- if (!user_progname) {
- user_progname = kpse_program_basename(argv[0]);
- }
- } else {
- if (!dump_name) {
- dump_name = kpse_program_basename(argv[0]);
- }
- user_progname = dump_name;
- }
- }
- kpse_set_program_enabled(kpse_fmt_format, MAKE_TEX_FMT_BY_DEFAULT,
- kpse_src_compile);
-
- kpse_set_program_name(argv[0], user_progname);
- init_shell_escape(); /* set up 'restrictedshell' */
- init_start_time();
- program_name_set = 1 ;
- if (recorderoption) {
- recorder_enabled = 1;
- }
-}
-
-@ @c
-static void fix_dumpname(void)
-{
- int dist;
- if (dump_name) {
- /* adjust array for Pascal and provide extension, if needed */
- dist = (int) (strlen(dump_name) - strlen(DUMP_EXT));
- if (strstr(dump_name, DUMP_EXT) == dump_name + dist)
- TEX_format_default = dump_name;
- else
- TEX_format_default = concat(dump_name, DUMP_EXT);
- } else {
- /* For |dump_name| to be NULL is a bug. */
- if (!ini_version) {
- fprintf(stdout, "no format given, quitting\n");
- exit(1);
- }
- }
-}
-
-@ lua require patch
-
-@ Auxiliary function for kpse search
-
-@c
-static const char *luatex_kpse_find_aux(lua_State *L, const char *name,
- kpse_file_format_type format, const char *errname)
-{
- const char *filename;
- const char *altname;
- altname = luaL_gsub(L, name, ".", "/"); /* Lua convention */
- filename = kpse_find_file(altname, format, false);
- if (filename == NULL) {
- filename = kpse_find_file(name, format, false);
- }
- if (filename == NULL) {
- lua_pushfstring(L, "\n\t[kpse %s searcher] file not found: " LUA_QS, errname, name);
- }
- return filename;
-}
-
-@ The lua search function.
-
-When kpathsea is not initialized, then it runs the
-normal lua function that is saved in the registry, otherwise
-it uses kpathsea.
-
-two registry ref variables are needed: one for the actual lua
-function, the other for its environment .
-
-@c
-static int lua_loader_function = 0;
-
-static int luatex_kpse_lua_find(lua_State * L)
-{
- const char *filename;
- const char *name;
- name = luaL_checkstring(L, 1);
- if (program_name_set == 0) {
- lua_rawgeti(L, LUA_REGISTRYINDEX, lua_loader_function);
- lua_pushvalue(L, -2);
- lua_call(L, 1, 1);
- return 1;
- }
- filename = luatex_kpse_find_aux(L, name, kpse_lua_format, "lua");
- if (filename == NULL)
- return 1; /* library not found in this path */
- if (luaL_loadfile(L, filename) != 0) {
- luaL_error(L, "error loading module %s from file %s:\n\t%s",
- lua_tostring(L, 1), filename, lua_tostring(L, -1));
- }
- return 1; /* library loaded successfully */
-}
-
-@ @c
-static int clua_loader_function = 0;
-extern int searcher_C_luatex (lua_State *L, const char *name, const char *filename);
-
-static int luatex_kpse_clua_find(lua_State * L)
-{
- const char *filename;
- const char *name;
- if (safer_option) {
- lua_pushliteral(L, "\n\t[C searcher disabled in safer mode]");
- return 1; /* library not found in this path */
- }
- name = luaL_checkstring(L, 1);
- if (program_name_set == 0) {
- lua_rawgeti(L, LUA_REGISTRYINDEX, clua_loader_function);
- lua_pushvalue(L, -2);
- lua_call(L, 1, 1);
- return 1;
- } else {
- const char *path_saved;
- char *prefix, *postfix, *p, *total;
- char *extensionless;
- char *temp_name;
- int j;
- filename = luatex_kpse_find_aux(L, name, kpse_clua_format, "C");
- if (filename == NULL)
- return 1; /* library not found in this path */
- extensionless = strdup(filename);
- if (!extensionless)
- return 1; /* allocation failure */
- /* Fix Issue 850: replace '.' with LUA_DIRSEP */
- temp_name = strdup(name);
- for(j=0; ; j++){
- if ((unsigned char)temp_name[j]=='\0') {
- break;
- }
- if ((unsigned char)temp_name[j]=='.'){
- temp_name[j]=LUA_DIRSEP[0];
- }
- }
- p = strstr(extensionless, temp_name);
- if (!p) return 1; /* this would be exceedingly weird */
- *p = '\0';
- prefix = strdup(extensionless);
- if (!prefix) return 1; /* allocation failure */
- postfix = strdup(p+strlen(name));
- if (!postfix) return 1; /* allocation failure */
- total = malloc(strlen(prefix)+strlen(postfix)+2);
- if (!total) return 1; /* allocation failure */
- snprintf(total,strlen(prefix)+strlen(postfix)+2, "%s?%s", prefix, postfix);
- /* save package.path */
- lua_getglobal(L,"package");
- lua_getfield(L,-1,"cpath");
- path_saved = lua_tostring(L,-1);
- lua_pop(L,1);
- /* set package.path = "?" */
- lua_pushstring(L,total);
- lua_setfield(L,-2,"cpath");
- lua_pop(L,1); /* pop "package" */
- /* run function */
- lua_rawgeti(L, LUA_REGISTRYINDEX, clua_loader_function);
- lua_pushstring(L, name);
- lua_call(L, 1, 1);
- /* restore package.path */
- lua_getglobal(L,"package");
- lua_pushstring(L,path_saved);
- lua_setfield(L,-2,"cpath");
- lua_pop(L,1); /* pop "package" */
- free(extensionless);
- free(total);
- free(temp_name);
- return 1;
- }
-}
-
-@ Setting up the new search functions.
-
-This replaces package.searchers[2] and package.searchers[3] with the
-functions defined above.
-
-@c
-static void setup_lua_path(lua_State * L)
-{
- lua_getglobal(L, "package");
-#ifdef LuajitTeX
- lua_getfield(L, -1, "loaders");
-#else
- lua_getfield(L, -1, "searchers");
-#endif
- lua_rawgeti(L, -1, 2); /* package.searchers[2] */
- lua_loader_function = luaL_ref(L, LUA_REGISTRYINDEX);
- lua_pushcfunction(L, luatex_kpse_lua_find);
- lua_rawseti(L, -2, 2); /* replace the normal lua loader */
-
- lua_rawgeti(L, -1, 3); /* package.searchers[3] */
- clua_loader_function = luaL_ref(L, LUA_REGISTRYINDEX);
- lua_pushcfunction(L, luatex_kpse_clua_find);
- lua_rawseti(L, -2, 3); /* replace the normal lua lib loader */
-
- lua_pop(L, 2); /* pop the array and table */
-}
-
-@ helper variables for the safe keeping of table ids
-
-@c
-int tex_table_id;
-int pdf_table_id;
-int token_table_id;
-int node_table_id;
-
-@ @c
-int l_pack_type_index [PACK_TYPE_SIZE] ;
-int l_group_code_index [GROUP_CODE_SIZE];
-int l_local_par_index [LOCAL_PAR_SIZE];
-int l_math_style_name_index [MATH_STYLE_NAME_SIZE];
-int l_dir_par_index [DIR_PAR_SIZE];
-int l_dir_text_index [DIR_TEXT_SIZE];
-
-int img_parms [img_parms_max];
-int img_pageboxes [img_pageboxes_max];
-
-int lua_show_valid_list(lua_State *L, const char **list, int max)
-{
- int i;
- lua_newtable(L);
- for (i = 0; i < max; i++) {
- lua_pushinteger(L,i+1);
- lua_pushstring(L, list[i]);
- lua_settable(L, -3);
- }
- return 1;
-}
-
-int lua_show_valid_keys(lua_State *L, int *list, int max)
-{
- int i;
- lua_newtable(L);
- for (i = 0; i < max; i++) {
- lua_pushinteger(L,i+1);
- lua_rawgeti(L, LUA_REGISTRYINDEX, list[i]);
- lua_settable(L, -3);
- }
- return 1;
-}
-
-#if defined(WIN32) || defined(__MINGW32__) || defined(__CYGWIN__)
-char **suffixlist;
-
-# define EXE_SUFFIXES ".com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh;.ws;.tcl;.py;.pyw"
-
-@ @c
-static void mk_suffixlist(void)
-{
- char **p;
- char *q, *r, *v;
- int n;
-
-# if defined(__CYGWIN__)
- v = xstrdup(EXE_SUFFIXES);
-# else
- v = (char *) getenv("PATHEXT");
- if (v) /* strlwr() exists also in MingW */
- v = (char *) strlwr(xstrdup(v));
- else
- v = xstrdup(EXE_SUFFIXES);
-# endif
-
- q = v;
- n = 0;
-
- while ((r = strchr(q, ';')) != NULL) {
- n++;
- r++;
- q = r;
- }
- if (*q)
- n++;
- suffixlist = (char **) xmalloc((n + 2) * sizeof(char *));
- p = suffixlist;
- *p = xstrdup(".dll");
- p++;
- q = v;
- while ((r = strchr(q, ';')) != NULL) {
- *r = '\0';
- *p = xstrdup(q);
- p++;
- r++;
- q = r;
- }
- if (*q) {
- *p = xstrdup(q);
- p++;
- }
- *p = NULL;
- free(v);
-}
-#endif
-
-@ @c
-void lua_initialize(int ac, char **av)
-{
- char *given_file = NULL;
- char *banner;
- /*int kpse_init;*/
- size_t len;
- int starttime;
- int utc;
- static char LC_CTYPE_C[] = "LC_CTYPE=C";
- static char LC_COLLATE_C[] = "LC_COLLATE=C";
- static char LC_NUMERIC_C[] = "LC_NUMERIC=C";
- static char engine_luatex[] = "engine=" my_name;
- /* Save to pass along to topenin. */
- const char *fmt = "This is " MyName ", Version %s" WEB2CVERSION;
- argc = ac;
- argv = av;
- len = strlen(fmt) + strlen(luatex_version_string) ;
- banner = xmalloc(len);
- sprintf(banner, fmt, luatex_version_string);
- luatex_banner = banner;
- kpse_invocation_name = kpse_program_basename(argv[0]);
-
- /* be 'luac' */
- if (argc >1) {
-#ifdef LuajitTeX
- if (FILESTRCASEEQ(kpse_invocation_name, "texluajitc"))
- exit(luac_main(ac, av));
- if (STREQ(argv[1], "--luaconly") || STREQ(argv[1], "--luac")) {
- char *argv1 = xmalloc (strlen ("luajittex") + 1);
- av[1] = argv1;
- strcpy (av[1], "luajittex");
- exit(luac_main(--ac, ++av));
- }
-#else
- if (FILESTRCASEEQ(kpse_invocation_name, "texluac"))
- exit(luac_main(ac, av));
- if (STREQ(argv[1], "--luaconly") || STREQ(argv[1], "--luac")) {
- strcpy(av[1], "luatex");
- exit(luac_main(--ac, ++av));
- }
-#endif
- }
-#if defined(WIN32) || defined(__MINGW32__) || defined(__CYGWIN__)
- mk_suffixlist();
-#endif
-
- /* Must be initialized before options are parsed. */
- interactionoption = 4;
- dump_name = NULL;
-
- /* 0 means "disable Synchronize TeXnology".
- synctexoption is a *.web variable.
- We initialize it to a weird value to catch the -synctex command line flag
- At runtime, if synctexoption is not |INT_MAX|, then it contains the command line option provided,
- otherwise no such option was given by the user. */
-#define SYNCTEX_NO_OPTION INT_MAX
- synctexoption = SYNCTEX_NO_OPTION;
-
- /* parse commandline */
- parse_options(ac, av);
- if (lua_only)
- shellenabledp = true;
-
- /* make sure that the locale is 'sane' (for lua) */
-
- putenv(LC_CTYPE_C);
- putenv(LC_COLLATE_C);
- putenv(LC_NUMERIC_C);
-
- /* this is sometimes needed */
- putenv(engine_luatex);
-
- luainterpreter();
-
- /* init internalized strings */
- set_init_keys;
-
- lua_pushstring(Luas,"lua.functions");
- lua_newtable(Luas);
- lua_settable(Luas,LUA_REGISTRYINDEX);
-
- /* here start the key definitions */
- set_l_pack_type_index;
- set_l_group_code_index;
- set_l_local_par_index;
- set_l_math_style_name_index;
- set_l_dir_par_index;
- set_l_dir_text_index;
-
- set_l_img_keys_index;
- set_l_img_pageboxes_index;
-
- prepare_cmdline(Luas, argv, argc, lua_offset); /* collect arguments */
- setup_lua_path(Luas);
-
- if (startup_filename != NULL) {
- given_file = xstrdup(startup_filename);
- if (lua_only) {
- xfree(startup_filename);
- }
- startup_filename = find_filename(given_file, "LUATEXDIR");
- }
- /* now run the file */
- if (startup_filename != NULL) {
- char *v1;
- /* hide the 'tex' and 'pdf' table */
- tex_table_id = hide_lua_table(Luas, "tex");
- token_table_id = hide_lua_table(Luas, "token");
- node_table_id = hide_lua_table(Luas, "node");
- pdf_table_id = hide_lua_table(Luas, "pdf");
-
- if (luaL_loadfile(Luas, startup_filename)) {
- fprintf(stdout, "%s\n", lua_tostring(Luas, -1));
- exit(1);
- }
- /* */
- init_tex_table(Luas);
- if (lua_pcall(Luas, 0, 0, 0)) {
- fprintf(stdout, "%s\n", lua_tostring(Luas, -1));
- lua_traceback(Luas);
- exit(1);
- }
- /* no filename? quit now! */
- if (!input_name) {
- get_lua_string("texconfig", "jobname", &input_name);
- }
- if (!dump_name) {
- get_lua_string("texconfig", "formatname", &dump_name);
- }
- if (lua_only) {
- if (given_file)
- free(given_file);
- /* this is not strictly needed but it pleases valgrind */
- lua_close(Luas);
- exit(0);
- }
- /* unhide the 'tex' and 'pdf' table */
- unhide_lua_table(Luas, "tex", tex_table_id);
- unhide_lua_table(Luas, "pdf", pdf_table_id);
- unhide_lua_table(Luas, "token", token_table_id);
- unhide_lua_table(Luas, "node", node_table_id);
-
- /* |kpse_init| */
- kpse_init = -1;
- get_lua_boolean("texconfig", "kpse_init", &kpse_init);
-
- if (kpse_init != 0) {
- luainit = 0; /* re-enable loading of texmf.cnf values, see luatex.ch */
- init_kpse();
- }
- /* |prohibit_file_trace| (boolean) */
- tracefilenames = 1;
- get_lua_boolean("texconfig", "trace_file_names", &tracefilenames);
-
- /* |file_line_error| */
- filelineerrorstylep = false;
- get_lua_boolean("texconfig", "file_line_error", &filelineerrorstylep);
-
- /* |halt_on_error| */
- haltonerrorp = false;
- get_lua_boolean("texconfig", "halt_on_error", &haltonerrorp);
-
- /* |restrictedshell| */
- v1 = NULL;
- get_lua_string("texconfig", "shell_escape", &v1);
- if (v1) {
- if (*v1 == 't' || *v1 == 'y' || *v1 == '1') {
- shellenabledp = 1;
- } else if (*v1 == 'p') {
- shellenabledp = 1;
- restrictedshell = 1;
- }
- free(v1);
- }
- /* If shell escapes are restricted, get allowed cmds from cnf. */
- if (shellenabledp && restrictedshell == 1) {
- v1 = NULL;
- get_lua_string("texconfig", "shell_escape_commands", &v1);
- if (v1) {
- mk_shellcmdlist(v1);
- free(v1);
- }
- }
-
- starttime = -1 ;
- get_lua_number("texconfig", "start_time", &starttime);
- if (starttime < 0) {
- /*
- We provide this one for compatibility reasons and therefore also in
- uppercase.
- */
- get_lua_number("texconfig", "SOURCE_DATE_EPOCH", &starttime);
- }
- if (starttime >= 0) {
- set_start_time(starttime);
- }
-
- utc = -1 ;
- get_lua_boolean("texconfig", "use_utc_time", &utc);
- if (utc >= 0 && utc <= 1) {
- utc_option = utc;
- }
-
- fix_dumpname();
- } else {
- if (luainit) {
- if (given_file) {
- fprintf(stdout, "%s file %s not found\n", (lua_only ? "Script" : "Configuration"), given_file);
- free(given_file);
- } else {
- fprintf(stdout, "No %s file given\n", (lua_only ? "script" : "configuration"));
- }
- exit(1);
- } else {
- /* init */
- init_kpse();
- fix_dumpname();
- }
- }
- /* Maybe we can extend this way to the others tables, using luac. */
- if ( safer_option || ((shellenabledp == 0) || (shellenabledp == 1 && restrictedshell == 1)) ) {
- (void) luaL_dostring(Luas,"ffi=require[[ffi]]; for k,_ in pairs(ffi) do if k~='gc' then ffi[k]=nil end; end; ffi=nil;");
- }
-}
-
-@ @c
-void check_texconfig_init(void)
-{
- if (Luas != NULL) {
- lua_getglobal(Luas, "texconfig");
- if (lua_istable(Luas, -1)) {
- lua_getfield(Luas, -1, "init");
- if (lua_isfunction(Luas, -1)) {
- int i = lua_pcall(Luas, 0, 0, 0);
- if (i != 0) {
- /* Can't be more precise here, called before TeX initialization */
- fprintf(stderr, "This went wrong: %s\n", lua_tostring(Luas, -1));
- error();
- }
- }
- }
- }
-}
+% luainit.w
+%
+% Copyright 2006-2017 Taco Hoekwater <taco@@luatex.org>
+%
+% This file is part of LuaTeX.
+%
+% LuaTeX is free software; you can redistribute it and/or modify it under
+% the terms of the GNU General Public License as published by the Free
+% Software Foundation; either version 2 of the License, or (at your
+% option) any later version.
+%
+% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
+% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+% 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/>.
+
+@ @c
+
+#include "ptexlib.h"
+
+#include <kpathsea/c-stat.h>
+
+#include "lua/luatex-api.h"
+
+#include <locale.h>
+
+extern int load_luatex_core_lua (lua_State * L);
+
+/* internalized strings: see luatex-api.h */
+set_make_keys;
+
+@
+This file is getting a bit messy, but it is not simple to fix unilaterally.
+
+Better to wait until Karl has some time (after texlive 2008) so we can
+synchronize with kpathsea. One problem, for instance, is that I would
+like to resolve the full executable path. |kpse_set_program_name()| does
+that, indirectly (by setting SELFAUTOLOC in the environment), but it
+does much more, making it hard to use for our purpose.
+
+In fact, it sets three C variables:
+
+ |kpse_invocation_name| |kpse_invocation_short_name| |kpse->program_name|
+
+and five environment variables:
+
+ SELFAUTOLOC SELFAUTODIR SELFAUTOPARENT SELFAUTOGRANDPARENT progname
+
+@c
+const_string LUATEX_IHELP[] = {
+ "Usage: " my_name " --lua=FILE [OPTION]... [TEXNAME[.tex]] [COMMANDS]",
+ " or: " my_name " --lua=FILE [OPTION]... \\FIRST-LINE",
+ " or: " my_name " --lua=FILE [OPTION]... &FMT ARGS",
+ " Run " MyName " on TEXNAME, usually creating TEXNAME.pdf.",
+ " Any remaining COMMANDS are processed as luatex input, after TEXNAME is read.",
+ "",
+ " Alternatively, if the first non-option argument begins with a backslash,",
+ " " my_name " interprets all non-option arguments as an input line.",
+ "",
+ " Alternatively, if the first non-option argument begins with a &, the",
+ " next word is taken as the FMT to read, overriding all else. Any",
+ " remaining arguments are processed as above.",
+ "",
+ " If no arguments or options are specified, prompt for input.",
+ "",
+ " The following regular options are understood: ",
+ "",
+ " --credits display credits and exit",
+ " --debug-format enable format debugging",
+ " --draftmode switch on draft mode (generates no output PDF)",
+ " --[no-]file-line-error disable/enable file:line:error style messages",
+ " --[no-]file-line-error-style aliases of --[no-]file-line-error",
+ " --fmt=FORMAT load the format file FORMAT",
+ " --halt-on-error stop processing at the first error",
+ " --help display help and exit",
+ " --ini be ini" my_name ", for dumping formats",
+ " --interaction=STRING set interaction mode (STRING=batchmode/nonstopmode/scrollmode/errorstopmode)",
+ " --jobname=STRING set the job name to STRING",
+ " --kpathsea-debug=NUMBER set path searching debugging flags according to the bits of NUMBER",
+ " --lua=FILE load and execute a lua initialization script",
+ " --[no-]mktex=FMT disable/enable mktexFMT generation (FMT=tex/tfm)",
+ " --nosocket disable the lua socket library",
+ " --output-comment=STRING use STRING for DVI file comment instead of date (no effect for PDF)",
+ " --output-directory=DIR use existing DIR as the directory to write files in",
+ " --output-format=FORMAT use FORMAT for job output; FORMAT is 'dvi' or 'pdf'",
+ " --progname=STRING set the program name to STRING",
+ " --recorder enable filename recorder",
+ " --safer disable easily exploitable lua commands",
+ " --[no-]shell-escape disable/enable system commands",
+ " --shell-restricted restrict system commands to a list of commands given in texmf.cnf",
+ " --synctex=NUMBER enable synctex",
+ " --utc init time to UTC",
+ " --version display version and exit",
+ "",
+ "Alternate behaviour models can be obtained by special switches",
+ "",
+ " --luaonly run a lua file, then exit",
+ " --luaconly byte-compile a lua file, then exit",
+ " --luahashchars the bits used by current Lua interpreter for strings hashing",
+#ifdef LuajitTeX
+ " --jiton turns the JIT compiler on (default off)",
+ " --jithash=STRING choose the hash function for the lua strings (lua51|luajit20: default lua51)",
+#endif
+ "",
+ "See the reference manual for more information about the startup process.",
+ NULL
+};
+
+@ Later we will put on environment |LC_CTYPE|, |LC_COLLATE| and
+|LC_NUMERIC| set to |C|, so we need a place where to store the old values.
+@c
+const char *lc_ctype;
+const char *lc_collate;
+const char *lc_numeric;
+
+/*
+ " --8bit ignored, input is assumed to be in UTF-8 encoding",
+ " --default-translate-file=FILE ignored, input is assumed to be in UTF-8 encoding",
+ " --etex ignored, the etex extensions are always active",
+ " --disable-write18 disable \\write18{SHELL COMMAND}",
+ " --enable-write18 enable \\write18{SHELL COMMAND}",
+ " --[no-]parse-first-line ignored",
+ " --translate-file=FILE ignored, input is assumed to be in UTF-8 encoding",
+*/
+
+@ The return value will be the directory of the executable, e.g.: \.{c:/TeX/bin}
+@c
+static char *ex_selfdir(char *argv0)
+{
+#if defined(WIN32)
+#if defined(__MINGW32__)
+ char path[PATH_MAX], *fp;
+
+ /* SearchPath() always gives back an absolute directory */
+ if (SearchPath(NULL, argv0, ".exe", PATH_MAX, path, NULL) == 0)
+ FATAL1("Can't determine where the executable %s is.\n", argv0);
+ /* slashify the dirname */
+ for (fp = path; fp && *fp; fp++)
+ if (IS_DIR_SEP(*fp))
+ *fp = DIR_SEP;
+#else /* __MINGW32__ */
+#define PATH_MAX 512
+ char short_path[PATH_MAX], path[PATH_MAX], *fp;
+
+ /* SearchPath() always gives back an absolute directory */
+ if (SearchPath(NULL, argv0, ".exe", PATH_MAX, short_path, &fp) == 0)
+ FATAL1("Can't determine where the executable %s is.\n", argv0);
+ if (getlongpath(path, short_path, sizeof(path)) == 0) {
+ FATAL1("This path points to an invalid file : %s\n", short_path);
+ }
+#endif /* __MINGW32__ */
+ return xdirname(path);
+#else /* WIN32 */
+ return kpse_selfdir(argv0);
+#endif
+}
+
+@ @c
+static void prepare_cmdline(lua_State * L, char **av, int ac, int zero_offset)
+{
+ int i;
+ char *s;
+ luaL_checkstack(L, ac + 3, "too many arguments to script");
+ lua_createtable(L, 0, 0);
+ for (i = 0; i < ac; i++) {
+ lua_pushstring(L, av[i]);
+ lua_rawseti(L, -2, (i - zero_offset));
+ }
+ lua_setglobal(L, "arg");
+ lua_getglobal(L, "os");
+ s = ex_selfdir(argv[0]);
+ lua_pushstring(L, s);
+ xfree(s);
+ lua_setfield(L, -2, "selfdir");
+ return;
+}
+
+
+@ @c
+int kpse_init = -1;
+
+@ @c
+string input_name = NULL;
+
+static string user_progname = NULL;
+
+char *startup_filename = NULL;
+int lua_only = 0;
+int lua_offset = 0;
+unsigned char show_luahashchars = 0;
+
+#ifdef LuajitTeX
+int luajiton = 0;
+char *jithash_hashname = NULL;
+#endif
+
+int safer_option = 0;
+int nosocket_option = 0;
+int utc_option = 0;
+
+@ Reading the options.
+
+@ Test whether getopt found an option ``A''.
+Assumes the option index is in the variable |option_index|, and the
+option table in a variable |long_options|.
+
+@c
+#define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a)
+
+/*
+ SunOS cc can't initialize automatic structs, so make this static.
+*/
+
+/*
+ Nota Bene: we still intercept some options that other engines handle
+ so that existing scripted usage will not fail.
+*/
+
+static struct option long_options[] = {
+ {"fmt", 1, 0, 0},
+ {"lua", 1, 0, 0},
+ {"luaonly", 0, 0, 0},
+ {"luahashchars", 0, 0, 0},
+#ifdef LuajitTeX
+ {"jiton", 0, 0, 0},
+ {"jithash", 1, 0, 0},
+#endif
+ {"safer", 0, &safer_option, 1},
+ {"utc", 0, &utc_option, 1},
+ {"nosocket", 0, &nosocket_option, 1},
+ {"help", 0, 0, 0},
+ {"ini", 0, &ini_version, 1},
+ {"interaction", 1, 0, 0},
+ {"halt-on-error", 0, &haltonerrorp, 1},
+ {"kpathsea-debug", 1, 0, 0},
+ {"progname", 1, 0, 0},
+ {"version", 0, 0, 0},
+ {"credits", 0, 0, 0},
+ {"recorder", 0, 0, 0},
+ {"etex", 0, 0, 0},
+ {"output-comment", 1, 0, 0},
+ {"output-directory", 1, 0, 0},
+ {"draftmode", 0, 0, 0},
+ {"output-format", 1, 0, 0},
+ {"shell-escape", 0, &shellenabledp, 1},
+ {"no-shell-escape", 0, &shellenabledp, -1},
+ {"enable-write18", 0, &shellenabledp, 1},
+ {"disable-write18", 0, &shellenabledp, -1},
+ {"shell-restricted", 0, 0, 0},
+ {"debug-format", 0, &debug_format_file, 1},
+ {"file-line-error-style", 0, &filelineerrorstylep, 1},
+ {"no-file-line-error-style", 0, &filelineerrorstylep, -1},
+
+ /* Shorter option names for the above. */
+
+ {"file-line-error", 0, &filelineerrorstylep, 1},
+ {"no-file-line-error", 0, &filelineerrorstylep, -1},
+ {"jobname", 1, 0, 0},
+ {"parse-first-line", 0, &parsefirstlinep, 1},
+ {"no-parse-first-line", 0, &parsefirstlinep, -1},
+ {"translate-file", 1, 0, 0},
+ {"default-translate-file", 1, 0, 0},
+ {"8bit", 0, 0, 0},
+ {"mktex", 1, 0, 0},
+ {"no-mktex", 1, 0, 0},
+
+ /* Synchronization: just like "interaction" above */
+
+ {"synctex", 1, 0, 0},
+ {0, 0, 0, 0}
+};
+
+@ @c
+int lua_numeric_field_by_index(lua_State * L, int name_index, int dflt)
+{
+ register int i = dflt;
+ lua_rawgeti(L, LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */
+ lua_rawget(L, -2);
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ i = lua_roundnumber(L, -1);
+ }
+ lua_pop(L, 1);
+ return i;
+}
+
+@ @c
+unsigned int lua_unsigned_numeric_field_by_index(lua_State * L, int name_index, int dflt)
+{
+ register unsigned int i = dflt;
+ lua_rawgeti(L, LUA_REGISTRYINDEX, name_index); /* fetch the stringptr */
+ lua_rawget(L, -2);
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ i = lua_uroundnumber(L, -1);
+ }
+ lua_pop(L, 1);
+ return i;
+}
+
+@ @c
+static int recorderoption = 0;
+
+static void parse_options(int ac, char **av)
+{
+#ifdef WIN32
+/* save argc and argv */
+ int sargc = argc;
+ char **sargv = argv;
+#endif
+ int g; /* `getopt' return code. */
+ int option_index;
+ char *firstfile = NULL;
+ opterr = 0; /* dont whine */
+#ifdef LuajitTeX
+ if ((strstr(argv[0], "luajittexlua") != NULL) ||
+ (strstr(argv[0], "texluajit") != NULL)) {
+#else
+ if ((strstr(argv[0], "luatexlua") != NULL) ||
+ (strstr(argv[0], "texlua") != NULL)) {
+#endif
+ lua_only = 1;
+ luainit = 1;
+ }
+
+ for (;;) {
+ g = getopt_long_only(ac, av, "+", long_options, &option_index);
+ if (g == -1) /* End of arguments, exit the loop. */
+ break;
+ if (g == '?') { /* Unknown option. */
+ if (!luainit)
+ fprintf(stderr,"%s: unrecognized option '%s'\n", argv[0], argv[optind-1]);
+ continue;
+ }
+
+ assert(g == 0); /* We have no short option names. */
+
+ if (ARGUMENT_IS("luaonly")) {
+ lua_only = 1;
+ lua_offset = optind;
+ luainit = 1;
+ } else if (ARGUMENT_IS("lua")) {
+ startup_filename = optarg;
+ lua_offset = (optind - 1);
+ luainit = 1;
+#ifdef LuajitTeX
+ } else if (ARGUMENT_IS("jiton")) {
+ luajiton = 1;
+ } else if (ARGUMENT_IS("jithash")) {
+ size_t len = strlen(optarg);
+ if (len<16) {
+ jithash_hashname = optarg;
+ } else {
+ WARNING2("hash name truncated to 15 characters from %d. (%s)", (int) len, optarg);
+ jithash_hashname = (string) xmalloc(16);
+ strncpy(jithash_hashname, optarg, 15);
+ jithash_hashname[15] = 0;
+ }
+#endif
+ } else if (ARGUMENT_IS("luahashchars")) {
+ show_luahashchars = 1;
+ } else if (ARGUMENT_IS("kpathsea-debug")) {
+ kpathsea_debug |= atoi(optarg);
+ } else if (ARGUMENT_IS("progname")) {
+ user_progname = optarg;
+ } else if (ARGUMENT_IS("jobname")) {
+ c_job_name = optarg;
+ } else if (ARGUMENT_IS("fmt")) {
+ dump_name = optarg;
+ } else if (ARGUMENT_IS("output-directory")) {
+ output_directory = optarg;
+ } else if (ARGUMENT_IS("output-comment")) {
+ size_t len = strlen(optarg);
+ if (len < 256) {
+ output_comment = optarg;
+ } else {
+ WARNING2("Comment truncated to 255 characters from %d. (%s)", (int) len, optarg);
+ output_comment = (string) xmalloc(256);
+ strncpy(output_comment, optarg, 255);
+ output_comment[255] = 0;
+ }
+ } else if (ARGUMENT_IS("shell-restricted")) {
+ shellenabledp = 1;
+ restrictedshell = 1;
+ } else if (ARGUMENT_IS("output-format")) {
+ output_mode_option = 1;
+ if (strcmp(optarg, "dvi") == 0) {
+ output_mode_value = 0;
+ } else if (strcmp(optarg, "pdf") == 0) {
+ output_mode_value = 1;
+ } else {
+ WARNING1("Ignoring unknown value `%s' for --output-format",optarg);
+ output_mode_option = 0;
+ }
+ } else if (ARGUMENT_IS("draftmode")) {
+ draft_mode_option = 1;
+ draft_mode_value = 1;
+ } else if (ARGUMENT_IS("mktex")) {
+ kpse_maketex_option(optarg, true);
+ } else if (ARGUMENT_IS("no-mktex")) {
+ kpse_maketex_option(optarg, false);
+ } else if (ARGUMENT_IS("interaction")) {
+ /* These numbers match CPP defines */
+ if (STREQ(optarg, "batchmode")) {
+ interactionoption = 0;
+ } else if (STREQ(optarg, "nonstopmode")) {
+ interactionoption = 1;
+ } else if (STREQ(optarg, "scrollmode")) {
+ interactionoption = 2;
+ } else if (STREQ(optarg, "errorstopmode")) {
+ interactionoption = 3;
+ } else {
+ WARNING1("Ignoring unknown argument `%s' to --interaction", optarg);
+ }
+ } else if (ARGUMENT_IS("synctex")) {
+ /* Synchronize TeXnology: catching the command line option as a long */
+ synctexoption = (int) strtol(optarg, NULL, 0);
+ } else if (ARGUMENT_IS("recorder")) {
+ recorderoption = 1 ;
+ } else if (ARGUMENT_IS("help")) {
+ usagehelp(LUATEX_IHELP, BUG_ADDRESS);
+ } else if (ARGUMENT_IS("version")) {
+ print_version_banner();
+ /* *INDENT-OFF* */
+ puts("\n\nExecute '" my_name " --credits' for credits and version details.\n\n"
+ "There is NO warranty. Redistribution of this software is covered by\n"
+ "the terms of the GNU General Public License, version 2 or (at your option)\n"
+ "any later version. For more information about these matters, see the file\n"
+ "named COPYING and the LuaTeX source.\n\n"
+ "LuaTeX is Copyright 2017 Taco Hoekwater and the LuaTeX Team.\n");
+ /* *INDENT-ON* */
+ uexit(0);
+ } else if (ARGUMENT_IS("credits")) {
+ char *versions;
+ initversionstring(&versions);
+ print_version_banner();
+ /* *INDENT-OFF* */
+ puts("\n\nThe LuaTeX team is Hans Hagen, Hartmut Henkel, Taco Hoekwater, Luigi Scarso.\n\n"
+ MyName " merges and builds upon (parts of) the code from these projects:\n\n"
+ "tex : Donald Knuth\n"
+ "etex : Peter Breitenlohner, Phil Taylor and friends\n"
+ "omega : John Plaice and Yannis Haralambous\n"
+ "aleph : Giuseppe Bilotta\n"
+ "pdftex : Han The Thanh and friends\n"
+ "kpathsea : Karl Berry, Olaf Weber and others\n"
+ "lua : Roberto Ierusalimschy, Waldemar Celes and Luiz Henrique de Figueiredo\n"
+ "metapost : John Hobby, Taco Hoekwater and friends\n"
+ "poppler : Derek Noonburg, Kristian H\\ogsberg (partial)\n"
+ "fontforge : George Williams (partial)\n"
+ "luajit : Mike Pall (used in LuajitTeX)\n");
+ /* *INDENT-ON* */
+ puts(versions);
+ uexit(0);
+ }
+ }
+ /* attempt to find |input_name| / |dump_name| */
+ if (lua_only) {
+ if (argv[optind]) {
+ startup_filename = xstrdup(argv[optind]);
+ lua_offset = optind;
+ }
+ } else if (argv[optind] && argv[optind][0] == '&') {
+ dump_name = xstrdup(argv[optind] + 1);
+ } else if (argv[optind] && argv[optind][0] != '\\') {
+ if (argv[optind][0] == '*') {
+ input_name = xstrdup(argv[optind] + 1);
+ } else {
+ firstfile = xstrdup(argv[optind]);
+ if ((strstr(firstfile, ".lua") ==
+ firstfile + strlen(firstfile) - 4)
+ || (strstr(firstfile, ".luc") ==
+ firstfile + strlen(firstfile) - 4)
+ || (strstr(firstfile, ".LUA") ==
+ firstfile + strlen(firstfile) - 4)
+ || (strstr(firstfile, ".LUC") ==
+ firstfile + strlen(firstfile) - 4)) {
+ if (startup_filename == NULL) {
+ startup_filename = firstfile;
+ lua_offset = optind;
+ lua_only = 1;
+ luainit = 1;
+ }
+ } else {
+ input_name = firstfile;
+ }
+ }
+#ifdef WIN32
+ } else if (sargc > 1 && sargv[sargc-1] && sargv[sargc-1][0] != '-' &&
+ sargv[sargc-1][0] != '\\') {
+ if (sargv[sargc-1][0] == '&')
+ dump_name = xstrdup(sargv[sargc-1] + 1);
+ else {
+ if (sargv[sargc-1][0] == '*')
+ input_name = xstrdup(sargv[sargc-1] + 1);
+ else
+ input_name = xstrdup(sargv[sargc-1]);
+ sargv[sargc-1] = normalize_quotes(input_name, "argument");
+ }
+ if (safer_option) /* --safer implies --nosocket */
+ nosocket_option = 1;
+ return;
+#endif
+ }
+ if (safer_option) /* --safer implies --nosocket */
+ nosocket_option = 1;
+ /* Finalize the input filename. */
+ if (input_name != NULL) {
+ argv[optind] = normalize_quotes(input_name, "argument");
+ }
+}
+
+@ test for readability
+@c
+#define is_readable(a) (stat(a,&finfo)==0) && S_ISREG(finfo.st_mode) && \
+ (f=fopen(a,"r")) != NULL && !fclose(f)
+
+@ @c
+static char *find_filename(char *name, const char *envkey)
+{
+ struct stat finfo;
+ char *dirname = NULL;
+ char *filename = NULL;
+ FILE *f;
+ if (is_readable(name)) {
+ return name;
+ } else {
+ dirname = getenv(envkey);
+ if ((dirname != NULL) && strlen(dirname)) {
+ dirname = xstrdup(getenv(envkey));
+ if (*(dirname + strlen(dirname) - 1) == '/') {
+ *(dirname + strlen(dirname) - 1) = 0;
+ }
+ filename = xmalloc((unsigned) (strlen(dirname) + strlen(name) + 2));
+ filename = concat3(dirname, "/", name);
+ xfree(dirname);
+ if (is_readable(filename)) {
+ return filename;
+ }
+ xfree(filename);
+ }
+ }
+ return NULL;
+}
+
+@ @c
+
+static void init_kpse(void)
+{
+ if (!user_progname) {
+ user_progname = dump_name;
+ } else if (!dump_name) {
+ dump_name = user_progname;
+ }
+ if (!user_progname) {
+ if (ini_version) {
+ if (input_name) {
+ char *p = input_name + strlen(input_name) - 1;
+ while (p >= input_name) {
+ if (IS_DIR_SEP (*p)) {
+ p++;
+ input_name = p;
+ break;
+ }
+ p--;
+ }
+ user_progname = remove_suffix (input_name);
+ }
+ if (!user_progname) {
+ user_progname = kpse_program_basename(argv[0]);
+ }
+ } else {
+ if (!dump_name) {
+ dump_name = kpse_program_basename(argv[0]);
+ }
+ user_progname = dump_name;
+ }
+ }
+ kpse_set_program_enabled(kpse_fmt_format, MAKE_TEX_FMT_BY_DEFAULT,
+ kpse_src_compile);
+
+ kpse_set_program_name(argv[0], user_progname);
+ init_shell_escape(); /* set up 'restrictedshell' */
+ init_start_time();
+ program_name_set = 1 ;
+ if (recorderoption) {
+ recorder_enabled = 1;
+ }
+}
+
+@ @c
+static void fix_dumpname(void)
+{
+ int dist;
+ if (dump_name) {
+ /* adjust array for Pascal and provide extension, if needed */
+ dist = (int) (strlen(dump_name) - strlen(DUMP_EXT));
+ if (strstr(dump_name, DUMP_EXT) == dump_name + dist)
+ TEX_format_default = dump_name;
+ else
+ TEX_format_default = concat(dump_name, DUMP_EXT);
+ } else {
+ /* For |dump_name| to be NULL is a bug. */
+ if (!ini_version) {
+ fprintf(stdout, "no format given, quitting\n");
+ exit(1);
+ }
+ }
+}
+
+@ lua require patch
+
+@ Auxiliary function for kpse search
+
+@c
+static const char *luatex_kpse_find_aux(lua_State *L, const char *name,
+ kpse_file_format_type format, const char *errname)
+{
+ const char *filename;
+ const char *altname;
+ altname = luaL_gsub(L, name, ".", "/"); /* Lua convention */
+ filename = kpse_find_file(altname, format, false);
+ if (filename == NULL) {
+ filename = kpse_find_file(name, format, false);
+ }
+ if (filename == NULL) {
+ lua_pushfstring(L, "\n\t[kpse %s searcher] file not found: " LUA_QS, errname, name);
+ }
+ return filename;
+}
+
+@ The lua search function.
+
+When kpathsea is not initialized, then it runs the
+normal lua function that is saved in the registry, otherwise
+it uses kpathsea.
+
+two registry ref variables are needed: one for the actual lua
+function, the other for its environment .
+
+@c
+static int lua_loader_function = 0;
+
+static int luatex_kpse_lua_find(lua_State * L)
+{
+ const char *filename;
+ const char *name;
+ name = luaL_checkstring(L, 1);
+ if (program_name_set == 0) {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, lua_loader_function);
+ lua_pushvalue(L, -2);
+ lua_call(L, 1, 1);
+ return 1;
+ }
+ filename = luatex_kpse_find_aux(L, name, kpse_lua_format, "lua");
+ if (filename == NULL)
+ return 1; /* library not found in this path */
+ if (luaL_loadfile(L, filename) != 0) {
+ luaL_error(L, "error loading module %s from file %s:\n\t%s",
+ lua_tostring(L, 1), filename, lua_tostring(L, -1));
+ }
+ return 1; /* library loaded successfully */
+}
+
+@ @c
+static int clua_loader_function = 0;
+extern int searcher_C_luatex (lua_State *L, const char *name, const char *filename);
+
+static int luatex_kpse_clua_find(lua_State * L)
+{
+ const char *filename;
+ const char *name;
+ if (safer_option) {
+ lua_pushliteral(L, "\n\t[C searcher disabled in safer mode]");
+ return 1; /* library not found in this path */
+ }
+ name = luaL_checkstring(L, 1);
+ if (program_name_set == 0) {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, clua_loader_function);
+ lua_pushvalue(L, -2);
+ lua_call(L, 1, 1);
+ return 1;
+ } else {
+ const char *path_saved;
+ char *prefix, *postfix, *p, *total;
+ char *extensionless;
+ char *temp_name;
+ int j;
+ filename = luatex_kpse_find_aux(L, name, kpse_clua_format, "C");
+ if (filename == NULL)
+ return 1; /* library not found in this path */
+ extensionless = strdup(filename);
+ if (!extensionless)
+ return 1; /* allocation failure */
+ /* Fix Issue 850: replace '.' with LUA_DIRSEP */
+ temp_name = strdup(name);
+ for(j=0; ; j++){
+ if ((unsigned char)temp_name[j]=='\0') {
+ break;
+ }
+ if ((unsigned char)temp_name[j]=='.'){
+ temp_name[j]=LUA_DIRSEP[0];
+ }
+ }
+ p = strstr(extensionless, temp_name);
+ if (!p) return 1; /* this would be exceedingly weird */
+ *p = '\0';
+ prefix = strdup(extensionless);
+ if (!prefix) return 1; /* allocation failure */
+ postfix = strdup(p+strlen(name));
+ if (!postfix) return 1; /* allocation failure */
+ total = malloc(strlen(prefix)+strlen(postfix)+2);
+ if (!total) return 1; /* allocation failure */
+ snprintf(total,strlen(prefix)+strlen(postfix)+2, "%s?%s", prefix, postfix);
+ /* save package.path */
+ lua_getglobal(L,"package");
+ lua_getfield(L,-1,"cpath");
+ path_saved = lua_tostring(L,-1);
+ lua_pop(L,1);
+ /* set package.path = "?" */
+ lua_pushstring(L,total);
+ lua_setfield(L,-2,"cpath");
+ lua_pop(L,1); /* pop "package" */
+ /* run function */
+ lua_rawgeti(L, LUA_REGISTRYINDEX, clua_loader_function);
+ lua_pushstring(L, name);
+ lua_call(L, 1, 1);
+ /* restore package.path */
+ lua_getglobal(L,"package");
+ lua_pushstring(L,path_saved);
+ lua_setfield(L,-2,"cpath");
+ lua_pop(L,1); /* pop "package" */
+ free(extensionless);
+ free(total);
+ free(temp_name);
+ return 1;
+ }
+}
+
+@ Setting up the new search functions.
+
+This replaces package.searchers[2] and package.searchers[3] with the
+functions defined above.
+
+@c
+static void setup_lua_path(lua_State * L)
+{
+ lua_getglobal(L, "package");
+#ifdef LuajitTeX
+ lua_getfield(L, -1, "loaders");
+#else
+ lua_getfield(L, -1, "searchers");
+#endif
+ lua_rawgeti(L, -1, 2); /* package.searchers[2] */
+ lua_loader_function = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_pushcfunction(L, luatex_kpse_lua_find);
+ lua_rawseti(L, -2, 2); /* replace the normal lua loader */
+
+ lua_rawgeti(L, -1, 3); /* package.searchers[3] */
+ clua_loader_function = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_pushcfunction(L, luatex_kpse_clua_find);
+ lua_rawseti(L, -2, 3); /* replace the normal lua lib loader */
+
+ lua_pop(L, 2); /* pop the array and table */
+}
+
+@ helper variables for the safe keeping of table ids
+
+@c
+int tex_table_id;
+int pdf_table_id;
+int token_table_id;
+int node_table_id;
+
+@ @c
+int l_pack_type_index [PACK_TYPE_SIZE] ;
+int l_group_code_index [GROUP_CODE_SIZE];
+int l_local_par_index [LOCAL_PAR_SIZE];
+int l_math_style_name_index [MATH_STYLE_NAME_SIZE];
+int l_dir_par_index [DIR_PAR_SIZE];
+int l_dir_text_index [DIR_TEXT_SIZE];
+
+int img_parms [img_parms_max];
+int img_pageboxes [img_pageboxes_max];
+
+int lua_show_valid_list(lua_State *L, const char **list, int max)
+{
+ int i;
+ lua_newtable(L);
+ for (i = 0; i < max; i++) {
+ lua_pushinteger(L,i+1);
+ lua_pushstring(L, list[i]);
+ lua_settable(L, -3);
+ }
+ return 1;
+}
+
+int lua_show_valid_keys(lua_State *L, int *list, int max)
+{
+ int i;
+ lua_newtable(L);
+ for (i = 0; i < max; i++) {
+ lua_pushinteger(L,i+1);
+ lua_rawgeti(L, LUA_REGISTRYINDEX, list[i]);
+ lua_settable(L, -3);
+ }
+ return 1;
+}
+
+#if defined(WIN32) || defined(__MINGW32__) || defined(__CYGWIN__)
+char **suffixlist;
+
+# define EXE_SUFFIXES ".com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh;.ws;.tcl;.py;.pyw"
+
+@ @c
+static void mk_suffixlist(void)
+{
+ char **p;
+ char *q, *r, *v;
+ int n;
+
+# if defined(__CYGWIN__)
+ v = xstrdup(EXE_SUFFIXES);
+# else
+ v = (char *) getenv("PATHEXT");
+ if (v) /* strlwr() exists also in MingW */
+ v = (char *) strlwr(xstrdup(v));
+ else
+ v = xstrdup(EXE_SUFFIXES);
+# endif
+
+ q = v;
+ n = 0;
+
+ while ((r = strchr(q, ';')) != NULL) {
+ n++;
+ r++;
+ q = r;
+ }
+ if (*q)
+ n++;
+ suffixlist = (char **) xmalloc((n + 2) * sizeof(char *));
+ p = suffixlist;
+ *p = xstrdup(".dll");
+ p++;
+ q = v;
+ while ((r = strchr(q, ';')) != NULL) {
+ *r = '\0';
+ *p = xstrdup(q);
+ p++;
+ r++;
+ q = r;
+ }
+ if (*q) {
+ *p = xstrdup(q);
+ p++;
+ }
+ *p = NULL;
+ free(v);
+}
+#endif
+
+@ @c
+void lua_initialize(int ac, char **av)
+{
+ char *given_file = NULL;
+ char *banner;
+ /*int kpse_init;*/
+ size_t len;
+ int starttime;
+ int utc;
+ static char LC_CTYPE_C[] = "LC_CTYPE=C";
+ static char LC_COLLATE_C[] = "LC_COLLATE=C";
+ static char LC_NUMERIC_C[] = "LC_NUMERIC=C";
+ static char engine_luatex[] = "engine=" my_name;
+ char *old_locale = NULL;
+ char *env_locale = NULL;
+ char *tmp = NULL;
+ /* Save to pass along to topenin. */
+ const char *fmt = "This is " MyName ", Version %s" WEB2CVERSION;
+ argc = ac;
+ argv = av;
+ len = strlen(fmt) + strlen(luatex_version_string) ;
+ banner = xmalloc(len);
+ sprintf(banner, fmt, luatex_version_string);
+ luatex_banner = banner;
+ kpse_invocation_name = kpse_program_basename(argv[0]);
+
+ /* be 'luac' */
+ if (argc >1) {
+#ifdef LuajitTeX
+ if (FILESTRCASEEQ(kpse_invocation_name, "texluajitc"))
+ exit(luac_main(ac, av));
+ if (STREQ(argv[1], "--luaconly") || STREQ(argv[1], "--luac")) {
+ char *argv1 = xmalloc (strlen ("luajittex") + 1);
+ av[1] = argv1;
+ strcpy (av[1], "luajittex");
+ exit(luac_main(--ac, ++av));
+ }
+#else
+ if (FILESTRCASEEQ(kpse_invocation_name, "texluac"))
+ exit(luac_main(ac, av));
+ if (STREQ(argv[1], "--luaconly") || STREQ(argv[1], "--luac")) {
+ strcpy(av[1], "luatex");
+ exit(luac_main(--ac, ++av));
+ }
+#endif
+ }
+#if defined(WIN32) || defined(__MINGW32__) || defined(__CYGWIN__)
+ mk_suffixlist();
+#endif
+
+ /* Must be initialized before options are parsed. */
+ interactionoption = 4;
+ dump_name = NULL;
+
+ /* 0 means "disable Synchronize TeXnology".
+ synctexoption is a *.web variable.
+ We initialize it to a weird value to catch the -synctex command line flag
+ At runtime, if synctexoption is not |INT_MAX|, then it contains the command line option provided,
+ otherwise no such option was given by the user. */
+#define SYNCTEX_NO_OPTION INT_MAX
+ synctexoption = SYNCTEX_NO_OPTION;
+
+ /* parse commandline */
+ parse_options(ac, av);
+ if (lua_only) {
+ /* Shell has no restrictions. */
+ shellenabledp = true;
+ restrictedshell = false;
+ safer_option = 0;
+ }
+ /* Get the current locale (it should be C ) */
+ /* and save LC_CTYPE, LC_COLLATE and LC_NUMERIC. */
+ /* Later luainterpreter() will consciously use them. */
+ old_locale = setlocale (LC_ALL, NULL);
+ lc_ctype = NULL;
+ lc_collate = NULL;
+ lc_numeric = NULL;
+ if (old_locale) {
+ /* If setlocale fails here, then the state */
+ /* could be compromised, and we exit. */
+ env_locale = setlocale (LC_ALL, "");
+ if (!env_locale) {
+ fprintf(stderr,"Unable to read environment locale:exit now.\n");
+ exit(1);
+ }
+ tmp = setlocale (LC_CTYPE, NULL);
+ if (tmp) {
+ lc_ctype = xstrdup(tmp);
+ }
+ tmp = setlocale (LC_COLLATE, NULL);
+ if (tmp){
+ lc_collate = xstrdup(tmp);
+ }
+ tmp = setlocale (LC_NUMERIC, NULL);
+ if (tmp){
+ lc_numeric = xstrdup(tmp);
+ }
+ /* Back to the previous locale if possible, */
+ /* otherwise it's a serious error and we exit:*/
+ /* we can't ensure a 'sane' locale for lua. */
+ env_locale = setlocale (LC_ALL, old_locale);
+ if (!env_locale) {
+ fprintf(stderr,"Unable to restore original locale:exit now.\n");
+ exit(1);
+ }
+ } else {
+ fprintf(stderr,"Unable to store environment locale.\n");
+ }
+
+ /* make sure that the locale is 'sane' (for lua) */
+ putenv(LC_CTYPE_C);
+ putenv(LC_COLLATE_C);
+ putenv(LC_NUMERIC_C);
+
+ /* this is sometimes needed */
+ putenv(engine_luatex);
+
+ luainterpreter();
+
+ /* init internalized strings */
+ set_init_keys;
+
+ lua_pushstring(Luas,"lua.functions");
+ lua_newtable(Luas);
+ lua_settable(Luas,LUA_REGISTRYINDEX);
+
+ /* here start the key definitions */
+ set_l_pack_type_index;
+ set_l_group_code_index;
+ set_l_local_par_index;
+ set_l_math_style_name_index;
+ set_l_dir_par_index;
+ set_l_dir_text_index;
+
+ set_l_img_keys_index;
+ set_l_img_pageboxes_index;
+
+ prepare_cmdline(Luas, argv, argc, lua_offset); /* collect arguments */
+ setup_lua_path(Luas);
+
+ if (startup_filename != NULL) {
+ given_file = xstrdup(startup_filename);
+ if (lua_only) {
+ xfree(startup_filename);
+ }
+ startup_filename = find_filename(given_file, "LUATEXDIR");
+ }
+ /* now run the file */
+ if (startup_filename != NULL) {
+ char *v1;
+ /* hide the 'tex' and 'pdf' table */
+ tex_table_id = hide_lua_table(Luas, "tex");
+ token_table_id = hide_lua_table(Luas, "token");
+ node_table_id = hide_lua_table(Luas, "node");
+ pdf_table_id = hide_lua_table(Luas, "pdf");
+
+ if (luaL_loadfile(Luas, startup_filename)) {
+ fprintf(stdout, "%s\n", lua_tostring(Luas, -1));
+ exit(1);
+ }
+ /* */
+ init_tex_table(Luas);
+ if (lua_pcall(Luas, 0, 0, 0)) {
+ fprintf(stdout, "%s\n", lua_tostring(Luas, -1));
+ lua_traceback(Luas);
+ exit(1);
+ }
+ /* no filename? quit now! */
+ if (!input_name) {
+ get_lua_string("texconfig", "jobname", &input_name);
+ }
+ if (!dump_name) {
+ get_lua_string("texconfig", "formatname", &dump_name);
+ }
+ if (lua_only) {
+ if (given_file)
+ free(given_file);
+ /* this is not strictly needed but it pleases valgrind */
+ lua_close(Luas);
+ exit(0);
+ }
+ /* unhide the 'tex' and 'pdf' table */
+ unhide_lua_table(Luas, "tex", tex_table_id);
+ unhide_lua_table(Luas, "pdf", pdf_table_id);
+ unhide_lua_table(Luas, "token", token_table_id);
+ unhide_lua_table(Luas, "node", node_table_id);
+
+ /* |kpse_init| */
+ kpse_init = -1;
+ get_lua_boolean("texconfig", "kpse_init", &kpse_init);
+
+ if (kpse_init != 0) {
+ luainit = 0; /* re-enable loading of texmf.cnf values, see luatex.ch */
+ init_kpse();
+ kpse_init = 1;
+ }
+ /* |prohibit_file_trace| (boolean) */
+ tracefilenames = 1;
+ get_lua_boolean("texconfig", "trace_file_names", &tracefilenames);
+
+ /* |file_line_error| */
+ filelineerrorstylep = false;
+ get_lua_boolean("texconfig", "file_line_error", &filelineerrorstylep);
+
+ /* |halt_on_error| */
+ haltonerrorp = false;
+ get_lua_boolean("texconfig", "halt_on_error", &haltonerrorp);
+
+ /* |restrictedshell| */
+ v1 = NULL;
+ get_lua_string("texconfig", "shell_escape", &v1);
+ if (v1) {
+ if (*v1 == 't' || *v1 == 'y' || *v1 == '1') {
+ shellenabledp = 1;
+ } else if (*v1 == 'p') {
+ shellenabledp = 1;
+ restrictedshell = 1;
+ }
+ free(v1);
+ }
+ /* If shell escapes are restricted, get allowed cmds from cnf. */
+ if (shellenabledp && restrictedshell == 1) {
+ v1 = NULL;
+ get_lua_string("texconfig", "shell_escape_commands", &v1);
+ if (v1) {
+ mk_shellcmdlist(v1);
+ free(v1);
+ }
+ }
+
+ starttime = -1 ;
+ get_lua_number("texconfig", "start_time", &starttime);
+ if (starttime < 0) {
+ /*
+ We provide this one for compatibility reasons and therefore also in
+ uppercase.
+ */
+ get_lua_number("texconfig", "SOURCE_DATE_EPOCH", &starttime);
+ }
+ if (starttime >= 0) {
+ set_start_time(starttime);
+ }
+
+ utc = -1 ;
+ get_lua_boolean("texconfig", "use_utc_time", &utc);
+ if (utc >= 0 && utc <= 1) {
+ utc_option = utc;
+ }
+
+ fix_dumpname();
+ } else {
+ if (luainit) {
+ if (given_file) {
+ fprintf(stdout, "%s file %s not found\n", (lua_only ? "Script" : "Configuration"), given_file);
+ free(given_file);
+ } else {
+ fprintf(stdout, "No %s file given\n", (lua_only ? "script" : "configuration"));
+ }
+ exit(1);
+ } else {
+ /* init */
+ init_kpse();
+ kpse_init = 1;
+ fix_dumpname();
+ }
+ }
+
+ /* Here we load luatex-core.lua which takes care of some protection on demand. */
+ if (load_luatex_core_lua(Luas))
+ fprintf(stderr, "Error in execution of luatex-core.lua .\n");
+ /* Done. */
+}
+
+@ @c
+void check_texconfig_init(void)
+{
+ if (Luas != NULL) {
+ lua_getglobal(Luas, "texconfig");
+ if (lua_istable(Luas, -1)) {
+ lua_getfield(Luas, -1, "init");
+ if (lua_isfunction(Luas, -1)) {
+ int i = lua_pcall(Luas, 0, 0, 0);
+ if (i != 0) {
+ /* Can't be more precise here, called before TeX initialization */
+ fprintf(stderr, "This went wrong: %s\n", lua_tostring(Luas, -1));
+ error();
+ }
+ }
+ }
+ }
+}
diff --git a/Build/source/texk/web2c/luatexdir/lua/luastuff.w b/Build/source/texk/web2c/luatexdir/lua/luastuff.w
index d9743ba4f21..6f57e8ee845 100644
--- a/Build/source/texk/web2c/luatexdir/lua/luastuff.w
+++ b/Build/source/texk/web2c/luatexdir/lua/luastuff.w
@@ -1,563 +1,679 @@
-% luastuff.w
-%
-% Copyright 2006-2013 Taco Hoekwater <taco@@luatex.org>
-%
-% This file is part of LuaTeX.
-%
-% LuaTeX is free software; you can redistribute it and/or modify it under
-% the terms of the GNU General Public License as published by the Free
-% Software Foundation; either version 2 of the License, or (at your
-% option) any later version.
-%
-% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
-% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
-% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
-% 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/>.
-
-@ @c
-#include "ptexlib.h"
-#include "lua/luatex-api.h"
-
-@ @c
-lua_State *Luas = NULL;
-
-int luastate_bytes = 0;
-int lua_active = 0;
-
-@ @c
-void make_table(lua_State * L, const char *tab, const char *mttab, const char *getfunc,
- const char *setfunc)
-{
- /* make the table *//* |[{<tex>}]| */
- lua_pushstring(L, tab); /* |[{<tex>},"dimen"]| */
- lua_newtable(L); /* |[{<tex>},"dimen",{}]| */
- lua_settable(L, -3); /* |[{<tex>}]| */
- /* fetch it back */
- lua_pushstring(L, tab); /* |[{<tex>},"dimen"]| */
- lua_gettable(L, -2); /* |[{<tex>},{<dimen>}]| */
- /* make the meta entries */
- luaL_newmetatable(L, mttab); /* |[{<tex>},{<dimen>},{<dimen_m>}]| */
- lua_pushstring(L, "__index"); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index"]| */
- lua_pushstring(L, getfunc); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index","getdimen"]| */
- lua_gettable(L, -5); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index",<tex.getdimen>]| */
- lua_settable(L, -3); /* |[{<tex>},{<dimen>},{<dimen_m>}]| */
- lua_pushstring(L, "__newindex"); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex"]| */
- lua_pushstring(L, setfunc); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex","setdimen"]| */
- lua_gettable(L, -5); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex",<tex.setdimen>]| */
- lua_settable(L, -3); /* |[{<tex>},{<dimen>},{<dimen_m>}]| */
- lua_setmetatable(L, -2); /* |[{<tex>},{<dimen>}]| : assign the metatable */
- lua_pop(L, 1); /* |[{<tex>}]| : clean the stack */
-}
-
-@ @c
-static const char *getS(lua_State * L, void *ud, size_t * size)
-{
- LoadS *ls = (LoadS *) ud;
- (void) L;
- if (ls->size == 0)
- return NULL;
- *size = ls->size;
- ls->size = 0;
- return ls->s;
-}
-
-@ @c
-static void *my_luaalloc(void *ud, void *ptr, size_t osize, size_t nsize)
-{
- void *ret = NULL;
- (void) ud; /* for -Wunused */
- if (nsize == 0)
- free(ptr);
- else
- ret = realloc(ptr, nsize);
- luastate_bytes += (int) (nsize - osize);
- return ret;
-}
-
-@ @c
-static int my_luapanic(lua_State * L)
-{
- (void) L; /* to avoid warnings */
- fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1));
- return 0;
-}
-
-@ @c
-void luafunctioncall(int slot)
-{
- int i ;
- int stacktop = lua_gettop(Luas);
- lua_active++;
- lua_rawgeti(Luas, LUA_REGISTRYINDEX, lua_key_index(lua_functions));
- lua_gettable(Luas, LUA_REGISTRYINDEX);
- lua_rawgeti(Luas, -1,slot);
- if (lua_isfunction(Luas,-1)) {
- int base = lua_gettop(Luas); /* function index */
- lua_pushinteger(Luas, slot);
- lua_pushcfunction(Luas, lua_traceback); /* push traceback function */
- lua_insert(Luas, base); /* put it under chunk */
- i = lua_pcall(Luas, 1, 0, base);
- lua_remove(Luas, base); /* remove traceback function */
- if (i != 0) {
- lua_gc(Luas, LUA_GCCOLLECT, 0);
- Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
- }
- }
- lua_settop(Luas,stacktop);
- lua_active--;
-}
-
-@ @c
-static const luaL_Reg lualibs[] = {
- {"", luaopen_base},
- {"package", luaopen_package},
- {"coroutine", luaopen_coroutine},
- {"table", luaopen_table},
- {"io", open_iolibext},
- {"os", luaopen_os},
- {"string", luaopen_string},
- {"math", luaopen_math},
- {"debug", luaopen_debug},
- {"unicode", luaopen_unicode},
- {"zip", luaopen_zip},
- {"bit32", luaopen_bit32},
- {"md5", luaopen_md5},
- {"ffi", luaopen_ffi},
- {"lfs", luaopen_lfs},
- {"profiler", luaopen_profiler},
- {"lpeg", luaopen_lpeg},
- {NULL, NULL}
-};
-
-@ @c
-static void do_openlibs(lua_State * L)
-{
- const luaL_Reg *lib;
- for (lib = lualibs; lib->func; lib++) {
- luaL_requiref(L, lib->name, lib->func, 1);
- lua_pop(L, 1); /* remove lib */
- }
-}
-
-@ @c
-static int load_aux (lua_State *L, int status) {
- if (status == 0) /* OK? */
- return 1;
- else {
- lua_pushnil(L);
- lua_insert(L, -2); /* put before error message */
- return 2; /* return nil plus error message */
- }
-}
-
-@ @c
-static int luatex_loadfile (lua_State *L) {
- int status = 0;
- const char *fname = luaL_optstring(L, 1, NULL);
- const char *mode = luaL_optstring(L, 2, NULL);
- int env = !lua_isnone(L, 3); /* 'env' parameter? */
- if (!lua_only && !fname && interaction == batch_mode) {
- lua_pushnil(L);
- lua_pushstring(L, "reading from stdin is disabled in batch mode");
- return 2; /* return nil plus error message */
- }
- status = luaL_loadfilex(L, fname, mode);
- if (status == LUA_OK) {
- recorder_record_input(fname);
- if (env) { /* 'env' parameter? */
- lua_pushvalue(L, 3);
- lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */
- }
- }
- return load_aux(L, status);
-}
-
-@ @c
-static int luatex_dofile (lua_State *L) {
- const char *fname = luaL_optstring(L, 1, NULL);
- int n = lua_gettop(L);
- if (!lua_only && !fname) {
- if (interaction == batch_mode) {
- lua_pushnil(L);
- lua_pushstring(L, "reading from stdin is disabled in batch mode");
- return 2; /* return nil plus error message */
- } else {
- tprint_nl("lua> ");
- }
- }
- if (luaL_loadfile(L, fname) != 0) lua_error(L);
- recorder_record_input(fname);
- lua_call(L, 0, LUA_MULTRET);
- return lua_gettop(L) - n;
-}
-
-@ @c
-void luainterpreter(void)
-{
- lua_State *L;
- L = lua_newstate(my_luaalloc, NULL);
- if (L == NULL) {
- fprintf(stderr, "Can't create the Lua state.\n");
- return;
- }
- lua_atpanic(L, &my_luapanic);
-
- do_openlibs(L); /* does all the 'simple' libraries */
-
- lua_pushcfunction(L,luatex_dofile);
- lua_setglobal(L, "dofile");
- lua_pushcfunction(L,luatex_loadfile);
- lua_setglobal(L, "loadfile");
-
- luatex_md5_lua_open(L);
-
- open_oslibext(L, safer_option);
-/*
- open_iolibext(L);
-*/
- open_strlibext(L);
- open_lfslibext(L);
-
-
- /* luasockets */
- /* socket and mime are a bit tricky to open because
- they use a load-time dependency that has to be
- worked around for luatex, where the C module is
- loaded way before the lua module.
- */
- if (!nosocket_option) {
- lua_getglobal(L, "package");
- lua_getfield(L, -1, "loaded");
- if (!lua_istable(L, -1)) {
- lua_newtable(L);
- lua_setfield(L, -2, "loaded");
- lua_getfield(L, -1, "loaded");
- }
- luaopen_socket_core(L);
- lua_setfield(L, -2, "socket.core");
- lua_pushnil(L);
- lua_setfield(L, -2, "socket"); /* package.loaded.socket = nil */
-
- luaopen_mime_core(L);
- lua_setfield(L, -2, "mime.core");
- lua_pushnil(L);
- lua_setfield(L, -2, "mime"); /* package.loaded.mime = nil */
- lua_pop(L, 2); /* pop the tables */
-
- luatex_socketlua_open(L); /* preload the pure lua modules */
- }
- /* zlib. slightly odd calling convention */
- luaopen_zlib(L);
- lua_setglobal(L, "zlib");
- luaopen_gzip(L);
-
- /* our own libraries */
- luaopen_ff(L);
- luaopen_tex(L);
- luaopen_token(L);
- luaopen_node(L);
- luaopen_texio(L);
- luaopen_kpse(L);
- luaopen_callback(L);
- luaopen_lua(L, startup_filename);
- luaopen_stats(L);
- luaopen_font(L);
- luaopen_lang(L);
- luaopen_mplib(L);
- luaopen_vf(L);
-
- /* |luaopen_pdf(L);| */
- /* environment table at |LUA_ENVIRONINDEX| needs to load this way: */
- lua_pushcfunction(L, luaopen_pdf);
- lua_pushstring(L, "pdf");
- lua_call(L, 1, 0);
-
- if (!lua_only) {
- luaL_requiref(L, "img", luaopen_img, 1);
- lua_pop(L, 1);
- }
-
- luaL_requiref(L, "epdf", luaopen_epdf, 1);
- lua_pop(L, 1);
-
- /* |luaopen_pdfscanner(L);| */
- lua_pushcfunction(L, luaopen_pdfscanner);
- lua_pushstring(L, "pdfscanner");
- lua_call(L, 1, 0);
-
- lua_createtable(L, 0, 0);
- lua_setglobal(L, "texconfig");
-
- if (safer_option) {
- /* disable some stuff if --safer */
- (void) hide_lua_value(L, "os", "execute");
- (void) hide_lua_value(L, "os", "rename");
- (void) hide_lua_value(L, "os", "remove");
- (void) hide_lua_value(L, "io", "popen");
- /* make io.open only read files */
- luaL_checkstack(L, 2, "out of stack space");
- lua_getglobal(L, "io");
- lua_getfield(L, -1, "open_ro");
- lua_setfield(L, -2, "open");
- (void) hide_lua_value(L, "io", "tmpfile");
- (void) hide_lua_value(L, "io", "output");
- (void) hide_lua_value(L, "lfs", "chdir");
- (void) hide_lua_value(L, "lfs", "lock");
- (void) hide_lua_value(L, "lfs", "touch");
- (void) hide_lua_value(L, "lfs", "rmdir");
- (void) hide_lua_value(L, "lfs", "mkdir");
- }
- Luas = L;
-}
-
-@ @c
-int hide_lua_table(lua_State * L, const char *name)
-{
- int r = 0;
- lua_getglobal(L, name);
- if (lua_istable(L, -1)) {
- r = luaL_ref(L, LUA_REGISTRYINDEX);
- lua_pushnil(L);
- lua_setglobal(L, name);
- }
- return r;
-}
-
-@ @c
-void unhide_lua_table(lua_State * L, const char *name, int r)
-{
- lua_rawgeti(L, LUA_REGISTRYINDEX, r);
- lua_setglobal(L, name);
- luaL_unref(L, LUA_REGISTRYINDEX, r);
-}
-
-@ @c
-int hide_lua_value(lua_State * L, const char *name, const char *item)
-{
- int r = 0;
- lua_getglobal(L, name);
- if (lua_istable(L, -1)) {
- lua_getfield(L, -1, item);
- r = luaL_ref(L, LUA_REGISTRYINDEX);
- lua_pushnil(L);
- lua_setfield(L, -2, item);
- }
- return r;
-}
-
-@ @c
-void unhide_lua_value(lua_State * L, const char *name, const char *item, int r)
-{
- lua_getglobal(L, name);
- if (lua_istable(L, -1)) {
- lua_rawgeti(L, LUA_REGISTRYINDEX, r);
- lua_setfield(L, -2, item);
- luaL_unref(L, LUA_REGISTRYINDEX, r);
- }
-}
-
-@ @c
-int lua_traceback(lua_State * L)
-{
- lua_getglobal(L, "debug");
- if (!lua_istable(L, -1)) {
- lua_pop(L, 1);
- return 1;
- }
- lua_getfield(L, -1, "traceback");
- if (!lua_isfunction(L, -1)) {
- lua_pop(L, 2);
- return 1;
- }
- lua_pushvalue(L, 1); /* pass error message */
- lua_pushinteger(L, 2); /* skip this function and traceback */
- lua_call(L, 2, 1); /* call debug.traceback */
- return 1;
-}
-
-@ @c
-static void luacall(int p, int nameptr, boolean is_string) /* hh-ls: optimized lua_id resolving */
-{
- LoadS ls;
- int i;
- size_t ll = 0;
- char *lua_id;
- char *s = NULL;
-
- if (Luas == NULL) {
- luainterpreter();
- }
- lua_active++;
- if (is_string) {
- const char *ss = NULL;
- lua_rawgeti(Luas, LUA_REGISTRYINDEX, p);
- if (lua_isfunction(Luas,-1)) {
- int base = lua_gettop(Luas); /* function index */
- lua_checkstack(Luas, 1);
- lua_pushcfunction(Luas, lua_traceback); /* push traceback function */
- lua_insert(Luas, base); /* put it under chunk */
- i = lua_pcall(Luas, 0, 0, base);
- lua_remove(Luas, base); /* remove traceback function */
- if (i != 0) {
- lua_gc(Luas, LUA_GCCOLLECT, 0);
- Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
- }
- lua_active--;
- return ;
- }
- ss = lua_tolstring(Luas, -1, &ll);
- s = xmalloc(ll+1);
- memcpy(s,ss,ll+1);
- lua_pop(Luas,1);
- } else {
- int l = 0;
- s = tokenlist_to_cstring(p, 1, &l);
- ll = (size_t)l;
- }
- ls.s = s;
- ls.size = ll;
- if (ls.size > 0) {
- if (nameptr > 0) {
- int l = 0; /* not used */
- lua_id = tokenlist_to_cstring(nameptr, 1, &l);
- i = lua_load(Luas, getS, &ls, lua_id, NULL);
- xfree(lua_id);
- } else if (nameptr < 0) {
- lua_id = get_lua_name((nameptr + 65536));
- if (lua_id != NULL) {
- i = lua_load(Luas, getS, &ls, lua_id, NULL);
- } else {
- i = lua_load(Luas, getS, &ls, "=[\\latelua]", NULL);
- }
- } else {
- i = lua_load(Luas, getS, &ls, "=[\\latelua]", NULL);
- }
- if (i != 0) {
- Luas = luatex_error(Luas, (i == LUA_ERRSYNTAX ? 0 : 1));
- } else {
- int base = lua_gettop(Luas); /* function index */
- lua_checkstack(Luas, 1);
- lua_pushcfunction(Luas, lua_traceback); /* push traceback function */
- lua_insert(Luas, base); /* put it under chunk */
- i = lua_pcall(Luas, 0, 0, base);
- lua_remove(Luas, base); /* remove traceback function */
- if (i != 0) {
- lua_gc(Luas, LUA_GCCOLLECT, 0);
- Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
- }
- }
- xfree(ls.s);
- }
- lua_active--;
-}
-
-@ @c
-void late_lua(PDF pdf, halfword p)
-{
- (void) pdf;
- if (late_lua_type(p)==normal) {
- expand_macros_in_tokenlist(p); /* sets |def_ref| */
- luacall(def_ref, late_lua_name(p), false);
- flush_list(def_ref);
- } else {
- luacall(late_lua_data(p), late_lua_name(p), true);
- }
-}
-
-@ @c
-void luatokencall(int p, int nameptr) /* hh-ls: optimized lua_id resolving */
-{
- LoadS ls;
- int i, l;
- char *s = NULL;
- char *lua_id;
- assert(Luas);
- l = 0;
- lua_active++;
- s = tokenlist_to_cstring(p, 1, &l);
- ls.s = s;
- ls.size = (size_t) l;
- if (ls.size > 0) {
- if (nameptr > 0) {
- lua_id = tokenlist_to_cstring(nameptr, 1, &l);
- i = lua_load(Luas, getS, &ls, lua_id, NULL);
- xfree(lua_id);
- } else if (nameptr < 0) {
- lua_id = get_lua_name((nameptr + 65536));
- if (lua_id != NULL) {
- i = lua_load(Luas, getS, &ls, lua_id, NULL);
- } else {
- i = lua_load(Luas, getS, &ls, "=[\\directlua]", NULL);
- }
- } else {
- i = lua_load(Luas, getS, &ls, "=[\\directlua]", NULL);
- }
- xfree(s);
- if (i != 0) {
- Luas = luatex_error(Luas, (i == LUA_ERRSYNTAX ? 0 : 1));
- } else {
- int base = lua_gettop(Luas); /* function index */
- lua_checkstack(Luas, 1);
- lua_pushcfunction(Luas, lua_traceback); /* push traceback function */
- lua_insert(Luas, base); /* put it under chunk */
- i = lua_pcall(Luas, 0, 0, base);
- lua_remove(Luas, base); /* remove traceback function */
- if (i != 0) {
- lua_gc(Luas, LUA_GCCOLLECT, 0);
- Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
- }
- }
- }
- lua_active--;
-}
-
-@ @c
-lua_State *luatex_error(lua_State * L, int is_fatal)
-{
-
- const_lstring luaerr;
- char *err = NULL;
- if (lua_type(L, -1) == LUA_TSTRING) {
- luaerr.s = lua_tolstring(L, -1, &luaerr.l);
- /* free last one ? */
- err = (char *) xmalloc((unsigned) (luaerr.l + 1));
- snprintf(err, (luaerr.l + 1), "%s", luaerr.s);
- last_lua_error = err; /* hm, what if we have several .. not freed */
- }
- if (is_fatal > 0) {
- /* Normally a memory error from lua.
- The pool may overflow during the |maketexlstring()|, but we
- are crashing anyway so we may as well abort on the pool size */
- normal_error("lua",err);
- /* never reached */
- lua_close(L);
- return (lua_State *) NULL;
- } else {
- normal_warning("lua",err);
- return L;
- }
-}
-
-@ @c
-void preset_environment(lua_State * L, const parm_struct * p, const char *s)
-{
- int i;
- assert(L != NULL);
- /* double call with same s gives assert(0) */
- lua_pushstring(L, s); /* s */
- lua_gettable(L, LUA_REGISTRYINDEX); /* t */
- assert(lua_isnil(L, -1));
- lua_pop(L, 1); /* - */
- lua_pushstring(L, s); /* s */
- lua_newtable(L); /* t s */
- for (i = 1, ++p; p->name != NULL; i++, p++) {
- assert(i == p->idx);
- lua_pushstring(L, p->name); /* k t s */
- lua_pushinteger(L, p->idx); /* v k t s */
- lua_settable(L, -3); /* t s */
- }
- lua_settable(L, LUA_REGISTRYINDEX); /* - */
-}
+% luastuff.w
+%
+% Copyright 2006-2013 Taco Hoekwater <taco@@luatex.org>
+%
+% This file is part of LuaTeX.
+%
+% LuaTeX is free software; you can redistribute it and/or modify it under
+% the terms of the GNU General Public License as published by the Free
+% Software Foundation; either version 2 of the License, or (at your
+% option) any later version.
+%
+% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
+% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+% 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/>.
+
+@ @c
+#include "ptexlib.h"
+#include "lua/luatex-api.h"
+#ifdef LuajitTeX
+#include "lua/lauxlib_bridge.h"
+#endif
+
+@ @c
+lua_State *Luas = NULL;
+
+int luastate_bytes = 0;
+int lua_active = 0;
+
+#ifdef LuajitTeX
+#define Luas_load(Luas,getS,ls,lua_id) \
+ lua_load(Luas,getS,ls,lua_id);
+#define Luas_open(name,luaopen_lib) \
+ lua_pushcfunction(L, luaopen_lib); \
+ lua_pushstring(L, name); \
+ lua_call(L, 1, 0);
+#else
+#define Luas_load(Luas,getS,ls,lua_id) \
+ lua_load(Luas,getS,ls,lua_id,NULL);
+#define Luas_open(name,luaopen_lib) \
+ luaL_requiref(L, name, luaopen_lib, 1); \
+ lua_pop(L, 1);
+#endif
+
+@ @c
+void make_table(lua_State * L, const char *tab, const char *mttab, const char *getfunc, const char *setfunc)
+{
+ /* make the table *//* |[{<tex>}]| */
+ lua_pushstring(L, tab); /* |[{<tex>},"dimen"]| */
+ lua_newtable(L); /* |[{<tex>},"dimen",{}]| */
+ lua_settable(L, -3); /* |[{<tex>}]| */
+ /* fetch it back */
+ lua_pushstring(L, tab); /* |[{<tex>},"dimen"]| */
+ lua_gettable(L, -2); /* |[{<tex>},{<dimen>}]| */
+ /* make the meta entries */
+ luaL_newmetatable(L, mttab); /* |[{<tex>},{<dimen>},{<dimen_m>}]| */
+ lua_pushstring(L, "__index"); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index"]| */
+ lua_pushstring(L, getfunc); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index","getdimen"]| */
+ lua_gettable(L, -5); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index",<tex.getdimen>]| */
+ lua_settable(L, -3); /* |[{<tex>},{<dimen>},{<dimen_m>}]| */
+ lua_pushstring(L, "__newindex"); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex"]| */
+ lua_pushstring(L, setfunc); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex","setdimen"]| */
+ lua_gettable(L, -5); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex",<tex.setdimen>]| */
+ lua_settable(L, -3); /* |[{<tex>},{<dimen>},{<dimen_m>}]| */
+ lua_setmetatable(L, -2); /* |[{<tex>},{<dimen>}]| : assign the metatable */
+ lua_pop(L, 1); /* |[{<tex>}]| : clean the stack */
+}
+
+@ @c
+static const char *getS(lua_State * L, void *ud, size_t * size)
+{
+ LoadS *ls = (LoadS *) ud;
+ (void) L;
+ if (ls->size == 0)
+ return NULL;
+ *size = ls->size;
+ ls->size = 0;
+ return ls->s;
+}
+
+@ @c
+#ifdef LuajitTeX
+ /* Luatex has its own memory allocator, LuajitTeX uses the */
+ /* standard one from the stock. We left this space as */
+ /* reference, but be careful: memory allocator is a key */
+ /* component in luajit, it's easy to get sub-optimal */
+ /* performances. */
+#else
+static void *my_luaalloc(void *ud, void *ptr, size_t osize, size_t nsize)
+{
+ void *ret = NULL;
+ (void) ud; /* for -Wunused */
+ if (nsize == 0)
+ free(ptr);
+ else
+ ret = realloc(ptr, nsize);
+ luastate_bytes += (int) (nsize - osize);
+ return ret;
+}
+#endif
+
+@ @c
+static int my_luapanic(lua_State * L)
+{
+ (void) L; /* to avoid warnings */
+ fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", lua_tostring(L, -1));
+ return 0;
+}
+
+@ @c
+void luafunctioncall(int slot)
+{
+ int i ;
+ int stacktop = lua_gettop(Luas);
+ lua_active++;
+ lua_rawgeti(Luas, LUA_REGISTRYINDEX, lua_key_index(lua_functions));
+ lua_gettable(Luas, LUA_REGISTRYINDEX);
+ lua_rawgeti(Luas, -1,slot);
+ if (lua_isfunction(Luas,-1)) {
+ int base = lua_gettop(Luas); /* function index */
+ lua_pushinteger(Luas, slot);
+ lua_pushcfunction(Luas, lua_traceback); /* push traceback function */
+ lua_insert(Luas, base); /* put it under chunk */
+ i = lua_pcall(Luas, 1, 0, base);
+ lua_remove(Luas, base); /* remove traceback function */
+ if (i != 0) {
+ lua_gc(Luas, LUA_GCCOLLECT, 0);
+ Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
+ }
+ }
+ lua_settop(Luas,stacktop);
+ lua_active--;
+}
+
+@ @c
+static const luaL_Reg lualibs[] = {
+ /* standard lua libraries */
+ { "_G", luaopen_base },
+ { "package", luaopen_package },
+ { "table", luaopen_table },
+ { "io", luaopen_io },
+ { "os", luaopen_os },
+ { "string", luaopen_string },
+ { "math", luaopen_math },
+ { "debug", luaopen_debug },
+ { "lpeg", luaopen_lpeg },
+ { "bit32", luaopen_bit32 },
+#ifdef LuajitTeX
+ /* bit is only in luajit, */
+ /* coroutine is loaded in a special way */
+ { "bit", luaopen_bit },
+#else
+ { "coroutine", luaopen_coroutine },
+#endif
+ /* additional (public) libraries */
+ { "unicode", luaopen_unicode },
+ { "zip", luaopen_zip },
+ { "md5", luaopen_md5 },
+ { "lfs", luaopen_lfs },
+ /* extra standard lua libraries */
+#ifdef LuajitTeX
+ { "jit", luaopen_jit },
+#endif
+ { "ffi", luaopen_ffi },
+ /* obsolete, undocumented and for oru own testing only */
+ /*{ "profiler", luaopen_profiler }, */
+ /* more libraries will be loaded later */
+ { NULL, NULL }
+};
+
+@ @c
+static void do_openlibs(lua_State * L)
+{
+ const luaL_Reg *lib = lualibs;
+ for (; lib->func; lib++) {
+ Luas_open(lib->name,lib->func);
+ }
+}
+
+@ @c
+#ifdef LuajitTeX
+ /* in luajit load_aux is not used.*/
+#else
+static int load_aux (lua_State *L, int status) {
+ if (status == 0) /* OK? */
+ return 1;
+ else {
+ lua_pushnil(L);
+ lua_insert(L, -2); /* put before error message */
+ return 2; /* return nil plus error message */
+ }
+}
+#endif
+
+@ @c
+static int luatex_loadfile (lua_State *L) {
+ int status = 0;
+ const char *fname = luaL_optstring(L, 1, NULL);
+ const char *mode = luaL_optstring(L, 2, NULL);
+#ifdef LuajitTeX
+ /* 5.1 */
+#else
+ int env = !lua_isnone(L, 3); /* 'env' parameter? */
+#endif
+ if (!lua_only && !fname && interaction == batch_mode) {
+ lua_pushnil(L);
+ lua_pushstring(L, "reading from stdin is disabled in batch mode");
+ return 2; /* return nil plus error message */
+ }
+ status = luaL_loadfilex(L, fname, mode);
+ if (status == LUA_OK) {
+ recorder_record_input(fname);
+#ifdef LuajitTeX
+ /* 5.1 */
+#else
+ if (env) { /* 'env' parameter? */
+ lua_pushvalue(L, 3);
+ lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */
+ }
+#endif
+ }
+#ifdef LuajitTeX
+ return RESERVED_load_aux_JIT(L, status,3);
+#else
+ return load_aux(L, status);
+#endif
+}
+
+@ @c
+static int luatex_dofile (lua_State *L) {
+ const char *fname = luaL_optstring(L, 1, NULL);
+ int n = lua_gettop(L);
+ if (!lua_only && !fname) {
+ if (interaction == batch_mode) {
+ lua_pushnil(L);
+ lua_pushstring(L, "reading from stdin is disabled in batch mode");
+ return 2; /* return nil plus error message */
+ } else {
+ tprint_nl("lua> ");
+ }
+ }
+ if (luaL_loadfile(L, fname) != 0)
+ lua_error(L);
+ recorder_record_input(fname);
+ lua_call(L, 0, LUA_MULTRET);
+ return lua_gettop(L) - n;
+}
+
+@ @c
+void luainterpreter(void)
+{
+ lua_State *L;
+#ifdef LuajitTeX
+ if (jithash_hashname == NULL) {
+ /* default lua51 */
+ luajittex_choose_hash_function = 0;
+ jithash_hashname = (char *) xmalloc(strlen("lua51") + 1);
+ jithash_hashname = strcpy ( jithash_hashname, "lua51");
+ } else if (strcmp((const char*)jithash_hashname,"lua51") == 0) {
+ luajittex_choose_hash_function = 0;
+ } else if (strcmp((const char*)jithash_hashname,"luajit20") == 0) {
+ luajittex_choose_hash_function = 1;
+ } else {
+ /* default lua51 */
+ luajittex_choose_hash_function = 0;
+ jithash_hashname = strcpy ( jithash_hashname, "lua51");
+ }
+ L = luaL_newstate() ;
+#else
+ L = lua_newstate(my_luaalloc, NULL);
+#endif
+ if (L == NULL) {
+ fprintf(stderr, "Can't create the Lua state.\n");
+ return;
+ }
+ lua_atpanic(L, &my_luapanic);
+
+ do_openlibs(L); /* does all the 'simple' libraries */
+#ifdef LuajitTeX
+ if (luajiton){
+ luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE|LUAJIT_MODE_ON);
+ }
+ else {
+ luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE|LUAJIT_MODE_OFF);
+ }
+#endif
+
+ lua_pushcfunction(L,luatex_dofile);
+ lua_setglobal(L, "dofile");
+ lua_pushcfunction(L,luatex_loadfile);
+ lua_setglobal(L, "loadfile");
+
+ open_oslibext(L);
+ open_strlibext(L);
+ open_lfslibext(L);
+
+ /*
+ The socket and mime libraries are a bit tricky to open because they use a load-time
+ dependency that has to be worked around for luatex, where the C module is loaded
+ way before the lua module.
+ */
+
+ if (!nosocket_option) {
+ /* todo: move this to common */
+ lua_getglobal(L, "package");
+ lua_getfield(L, -1, "loaded");
+ if (!lua_istable(L, -1)) {
+ lua_newtable(L);
+ lua_setfield(L, -2, "loaded");
+ lua_getfield(L, -1, "loaded");
+ }
+ luaopen_socket_core(L);
+ lua_setfield(L, -2, "socket.core");
+ lua_pushnil(L);
+ lua_setfield(L, -2, "socket"); /* package.loaded.socket = nil */
+
+ luaopen_mime_core(L);
+ lua_setfield(L, -2, "mime.core");
+ lua_pushnil(L);
+ lua_setfield(L, -2, "mime"); /* package.loaded.mime = nil */
+ lua_pop(L, 2); /* pop the tables */
+
+ luatex_socketlua_open(L); /* preload the pure lua modules */
+ }
+
+ /* zlib. slightly odd calling convention */
+ luaopen_zlib(L);
+ lua_setglobal(L, "zlib");
+
+ luaopen_gzip(L);
+
+ /* our own libraries register themselves */
+
+ luaopen_fio(L);
+ luaopen_ff(L);
+ luaopen_tex(L);
+ luaopen_token(L);
+ luaopen_node(L);
+ luaopen_texio(L);
+ luaopen_kpse(L);
+ luaopen_callback(L);
+
+ luaopen_lua(L, startup_filename);
+
+ luaopen_stats(L);
+ luaopen_font(L);
+ luaopen_lang(L);
+ luaopen_mplib(L);
+ luaopen_vf(L);
+ luaopen_pdf(L);
+ luaopen_epdf(L);
+ luaopen_pdfscanner(L);
+
+ if (!lua_only) {
+ luaopen_img(L);
+ }
+
+ lua_createtable(L, 0, 0);
+ lua_setglobal(L, "texconfig");
+
+ Luas = L;
+}
+
+@ @c
+int hide_lua_table(lua_State * L, const char *name)
+{
+ int r = 0;
+ lua_getglobal(L, name);
+ if (lua_istable(L, -1)) {
+ r = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_pushnil(L);
+ lua_setglobal(L, name);
+ }
+ return r;
+}
+
+@ @c
+void unhide_lua_table(lua_State * L, const char *name, int r)
+{
+ lua_rawgeti(L, LUA_REGISTRYINDEX, r);
+ lua_setglobal(L, name);
+ luaL_unref(L, LUA_REGISTRYINDEX, r);
+}
+
+@ @c
+int hide_lua_value(lua_State * L, const char *name, const char *item)
+{
+ int r = 0;
+ lua_getglobal(L, name);
+ if (lua_istable(L, -1)) {
+ lua_getfield(L, -1, item);
+ r = luaL_ref(L, LUA_REGISTRYINDEX);
+ lua_pushnil(L);
+ lua_setfield(L, -2, item);
+ }
+ return r;
+}
+
+@ @c
+void unhide_lua_value(lua_State * L, const char *name, const char *item, int r)
+{
+ lua_getglobal(L, name);
+ if (lua_istable(L, -1)) {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, r);
+ lua_setfield(L, -2, item);
+ luaL_unref(L, LUA_REGISTRYINDEX, r);
+ }
+}
+
+@ @c
+int lua_traceback(lua_State * L)
+{
+ lua_getglobal(L, "debug");
+ if (!lua_istable(L, -1)) {
+ lua_pop(L, 1);
+ return 1;
+ }
+ lua_getfield(L, -1, "traceback");
+ if (!lua_isfunction(L, -1)) {
+ lua_pop(L, 2);
+ return 1;
+ }
+ lua_pushvalue(L, 1); /* pass error message */
+ lua_pushinteger(L, 2); /* skip this function and traceback */
+ lua_call(L, 2, 1); /* call debug.traceback */
+ return 1;
+}
+
+@ @c
+static void luacall(int p, int nameptr, boolean is_string) /* hh-ls: optimized lua_id resolving */
+{
+ LoadS ls;
+ int i;
+ size_t ll = 0;
+ char *lua_id;
+ char *s = NULL;
+
+ if (Luas == NULL) {
+ luainterpreter();
+ }
+ lua_active++;
+ if (is_string) {
+ const char *ss = NULL;
+ lua_rawgeti(Luas, LUA_REGISTRYINDEX, p);
+ if (lua_isfunction(Luas,-1)) {
+ int base = lua_gettop(Luas); /* function index */
+ lua_checkstack(Luas, 1);
+ lua_pushcfunction(Luas, lua_traceback); /* push traceback function */
+ lua_insert(Luas, base); /* put it under chunk */
+ i = lua_pcall(Luas, 0, 0, base);
+ lua_remove(Luas, base); /* remove traceback function */
+ if (i != 0) {
+ lua_gc(Luas, LUA_GCCOLLECT, 0);
+ Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
+ }
+ lua_active--;
+ return ;
+ }
+ ss = lua_tolstring(Luas, -1, &ll);
+ s = xmalloc(ll+1);
+ memcpy(s,ss,ll+1);
+ lua_pop(Luas,1);
+ } else {
+ int l = 0;
+ s = tokenlist_to_cstring(p, 1, &l);
+ ll = (size_t)l;
+ }
+ ls.s = s;
+ ls.size = ll;
+ if (ls.size > 0) {
+ if (nameptr > 0) {
+ int l = 0; /* not used */
+ lua_id = tokenlist_to_cstring(nameptr, 1, &l);
+ i = Luas_load(Luas, getS, &ls, lua_id);
+ xfree(lua_id);
+ } else if (nameptr < 0) {
+ lua_id = get_lua_name((nameptr + 65536));
+ if (lua_id != NULL) {
+ i = Luas_load(Luas, getS, &ls, lua_id);
+ } else {
+ i = Luas_load(Luas, getS, &ls, "=[\\latelua]");
+ }
+ } else {
+ i = Luas_load(Luas, getS, &ls, "=[\\latelua]");
+ }
+ if (i != 0) {
+ Luas = luatex_error(Luas, (i == LUA_ERRSYNTAX ? 0 : 1));
+ } else {
+ int base = lua_gettop(Luas); /* function index */
+ lua_checkstack(Luas, 1);
+ lua_pushcfunction(Luas, lua_traceback); /* push traceback function */
+ lua_insert(Luas, base); /* put it under chunk */
+ i = lua_pcall(Luas, 0, 0, base);
+ lua_remove(Luas, base); /* remove traceback function */
+ if (i != 0) {
+ lua_gc(Luas, LUA_GCCOLLECT, 0);
+ Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
+ }
+ }
+ xfree(ls.s);
+ }
+ lua_active--;
+}
+
+@ @c
+void late_lua(PDF pdf, halfword p)
+{
+ (void) pdf;
+ if (late_lua_type(p)==normal) {
+ expand_macros_in_tokenlist(p); /* sets |def_ref| */
+ luacall(def_ref, late_lua_name(p), false);
+ flush_list(def_ref);
+ } else {
+ luacall(late_lua_data(p), late_lua_name(p), true);
+ }
+}
+
+@ @c
+void luatokencall(int p, int nameptr) /* hh-ls: optimized lua_id resolving */
+{
+ LoadS ls;
+ int i, l;
+ char *s = NULL;
+ char *lua_id;
+ assert(Luas);
+ l = 0;
+ lua_active++;
+ s = tokenlist_to_cstring(p, 1, &l);
+ ls.s = s;
+ ls.size = (size_t) l;
+ if (ls.size > 0) {
+ if (nameptr > 0) {
+ lua_id = tokenlist_to_cstring(nameptr, 1, &l);
+ i = Luas_load(Luas, getS, &ls, lua_id);
+ xfree(lua_id);
+ } else if (nameptr < 0) {
+ lua_id = get_lua_name((nameptr + 65536));
+ if (lua_id != NULL) {
+ i = Luas_load(Luas, getS, &ls, lua_id);
+ } else {
+ i = Luas_load(Luas, getS, &ls, "=[\\directlua]");
+ }
+ } else {
+ i = Luas_load(Luas, getS, &ls, "=[\\directlua]");
+ }
+ xfree(s);
+ if (i != 0) {
+ Luas = luatex_error(Luas, (i == LUA_ERRSYNTAX ? 0 : 1));
+ } else {
+ int base = lua_gettop(Luas); /* function index */
+ lua_checkstack(Luas, 1);
+ lua_pushcfunction(Luas, lua_traceback); /* push traceback function */
+ lua_insert(Luas, base); /* put it under chunk */
+ i = lua_pcall(Luas, 0, 0, base);
+ lua_remove(Luas, base); /* remove traceback function */
+ if (i != 0) {
+ lua_gc(Luas, LUA_GCCOLLECT, 0);
+ Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1));
+ }
+ }
+ }
+ lua_active--;
+}
+
+@ @c
+lua_State *luatex_error(lua_State * L, int is_fatal)
+{
+
+ const_lstring luaerr;
+ char *err = NULL;
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ luaerr.s = lua_tolstring(L, -1, &luaerr.l);
+ /* free last one ? */
+ err = (char *) xmalloc((unsigned) (luaerr.l + 1));
+ snprintf(err, (luaerr.l + 1), "%s", luaerr.s);
+ last_lua_error = err; /* hm, what if we have several .. not freed */
+ }
+ if (is_fatal > 0) {
+ /* Normally a memory error from lua.
+ The pool may overflow during the |maketexlstring()|, but we
+ are crashing anyway so we may as well abort on the pool size */
+ normal_error("lua",err);
+ /* never reached */
+ lua_close(L);
+ return (lua_State *) NULL;
+ } else {
+ normal_warning("lua",err);
+ return L;
+ }
+}
+
+@ @c
+void preset_environment(lua_State * L, const parm_struct * p, const char *s)
+{
+ int i;
+ assert(L != NULL);
+ /* double call with same s gives assert(0) */
+ lua_pushstring(L, s); /* s */
+ lua_gettable(L, LUA_REGISTRYINDEX); /* t */
+ assert(lua_isnil(L, -1));
+ lua_pop(L, 1); /* - */
+ lua_pushstring(L, s); /* s */
+ lua_newtable(L); /* t s */
+ for (i = 1, ++p; p->name != NULL; i++, p++) {
+ assert(i == p->idx);
+ lua_pushstring(L, p->name); /* k t s */
+ lua_pushinteger(L, p->idx); /* v k t s */
+ lua_settable(L, -3); /* t s */
+ }
+ lua_settable(L, LUA_REGISTRYINDEX); /* - */
+}
+
+
+@ @c
+/*
+ luajit compatibility layer for luatex lua5.2
+*/
+#ifdef LuajitTeX
+LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) {
+ void *p = lua_touserdata(L, ud);
+ if (p != NULL) { /* value is a userdata? */
+ if (lua_getmetatable(L, ud)) { /* does it have a metatable? */
+ luaL_getmetatable(L, tname); /* get correct metatable */
+ if (!lua_rawequal(L, -1, -2)) /* not the same? */
+ p = NULL; /* value is a userdata with wrong metatable */
+ lua_pop(L, 2); /* remove both metatables */
+ return p;
+ }
+ }
+ return NULL; /* value is not a userdata with a metatable */
+}
+
+@ @c
+/* It's not ok. See lua-users.org/wiki/CompatibilityWithLuaFive for another solution */
+LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) {
+ /*luaL_checkversion(L);*/
+ luaL_checkstack(L, nup, "too many upvalues");
+ for (; l->name != NULL; l++) { /* fill the table with given functions */
+ int i;
+ for (i = 0; i < nup; i++) /* copy upvalues to the top */
+ lua_pushvalue(L, -nup);
+ lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */
+ lua_setfield(L, -(nup + 2), l->name);
+ }
+ lua_pop(L, nup); /* remove upvalues */
+}
+
+@ @c
+LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) {
+ lua_State *L = B->L;
+ if (sz > LUAL_BUFFERSIZE )
+ luaL_error(L, "buffer too large");
+ return luaL_prepbuffer(B) ;
+}
+
+@ @c
+LUA_API int lua_compare (lua_State *L, int o1, int o2, int op) {
+ /*StkId o1, o2;*/
+ int i = 0;
+ lua_lock(L); /* may call tag method */
+ /* o1 = index2addr(L, index1); */
+ /* o2 = index2addr(L, index2); */
+ /*if (isvalid(o1) && isvalid(o2)) {*/
+ switch (op) {
+ case LUA_OPEQ: i = lua_equal(L, o1, o2); break;
+ case LUA_OPLT: i = lua_lessthan(L, o1, o2); break;
+ case LUA_OPLE: i = (lua_lessthan(L, o1, o2) || lua_equal(L, o1, o2)) ; break;
+ default: luaL_error(L, "invalid option");
+ }
+ /*}*/
+ lua_unlock(L);
+ return i;
+}
+
+@ @c
+#endif
diff --git a/Build/source/texk/web2c/luatexdir/lua/luatex-api.h b/Build/source/texk/web2c/luatexdir/lua/luatex-api.h
index f7c612ce204..7d34607b9e0 100644
--- a/Build/source/texk/web2c/luatexdir/lua/luatex-api.h
+++ b/Build/source/texk/web2c/luatexdir/lua/luatex-api.h
@@ -105,9 +105,9 @@ extern int l_new_image(lua_State * L);
extern int luaopen_epdf(lua_State * L);
extern int luaopen_pdfscanner(lua_State * L);
extern int luaopen_mplib(lua_State * L);
+extern int luaopen_fio(lua_State * L);
-extern void open_oslibext(lua_State * L, int safer_option);
-extern int open_iolibext(lua_State * L);
+extern void open_oslibext(lua_State * L);
extern void open_strlibext(lua_State * L);
extern void open_lfslibext(lua_State * L);
@@ -154,6 +154,12 @@ extern void dump_luac_registers(void);
extern void undump_luac_registers(void);
extern int lua_only;
+extern const char *lc_ctype;
+extern const char *lc_collate;
+extern const char *lc_numeric;
+
+
+
#ifdef LuajitTeX
extern int luajiton;
extern char *jithash_hashname ;
@@ -1246,10 +1252,10 @@ init_lua_key_alias(term_and_log,"term and log")
} \
} while(0)
-#ifdef __MINGW32__
-extern FILE *_cairo_win32_tmpfile( void );
-#define tmpfile() _cairo_win32_tmpfile()
-#endif /* __MINGW32__ */
+#ifdef _WIN32
+extern FILE *_cairo_win_tmpfile( void );
+#define tmpfile() _cairo_win_tmpfile()
+#endif /* _WIN32 */
#endif /* LUATEX_API_H */
diff --git a/Build/source/texk/web2c/luatexdir/lua/luatex-core.c b/Build/source/texk/web2c/luatexdir/lua/luatex-core.c
new file mode 100644
index 00000000000..c5426b2c90e
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/luatex-core.c
@@ -0,0 +1,253 @@
+/* generated from and by luatex-core.lua */
+
+#include "lua.h"
+#include "lauxlib.h"
+
+int load_luatex_core_lua (lua_State * L);
+
+int load_luatex_core_lua (lua_State * L)
+{
+ static unsigned char luatex_core_lua[] = {
+ 0x2d, 0x2d, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65,
+ 0x73, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x3d,
+ 0x20, 0x7b, 0x20, 0x7d, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x6d, 0x6f, 0x64, 0x75, 0x6c, 0x65, 0x73,
+ 0x20, 0x5b, 0x27, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x78, 0x2d, 0x63, 0x6f, 0x72, 0x65, 0x27, 0x5d,
+ 0x20, 0x3d, 0x20, 0x7b, 0x0a, 0x2d, 0x2d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x76, 0x65, 0x72, 0x73,
+ 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x30, 0x31, 0x2c, 0x0a, 0x2d,
+ 0x2d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x20, 0x20,
+ 0x3d, 0x20, 0x27, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20,
+ 0x6c, 0x75, 0x61, 0x74, 0x65, 0x78, 0x27, 0x2c, 0x0a, 0x2d, 0x2d, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x27, 0x48, 0x61, 0x6e,
+ 0x73, 0x20, 0x48, 0x61, 0x67, 0x65, 0x6e, 0x20, 0x26, 0x20, 0x4c, 0x75, 0x69, 0x67, 0x69, 0x20,
+ 0x53, 0x63, 0x61, 0x72, 0x73, 0x6f, 0x27, 0x2c, 0x0a, 0x2d, 0x2d, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x63, 0x6f, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x3d, 0x20, 0x27, 0x4c, 0x75, 0x61,
+ 0x54, 0x65, 0x58, 0x20, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74, 0x20,
+ 0x54, 0x65, 0x61, 0x6d, 0x27, 0x2c, 0x0a, 0x2d, 0x2d, 0x20, 0x7d, 0x0a, 0x0a, 0x4c, 0x55, 0x41,
+ 0x54, 0x45, 0x58, 0x43, 0x4f, 0x52, 0x45, 0x56, 0x45, 0x52, 0x53, 0x49, 0x4f, 0x4e, 0x20, 0x3d,
+ 0x20, 0x31, 0x2e, 0x30, 0x30, 0x32, 0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20,
+ 0x66, 0x69, 0x6c, 0x65, 0x20, 0x6f, 0x76, 0x65, 0x72, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x20, 0x73,
+ 0x6f, 0x6d, 0x65, 0x20, 0x4c, 0x75, 0x61, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e,
+ 0x73, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x72, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x20,
+ 0x76, 0x61, 0x72, 0x69, 0x61, 0x6e, 0x74, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65,
+ 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x0a, 0x2d, 0x2d, 0x20, 0x66, 0x75, 0x6e,
+ 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x69, 0x74, 0x79, 0x20, 0x61, 0x73, 0x20, 0x4c, 0x75,
+ 0x61, 0x54, 0x65, 0x58, 0x20, 0x3c, 0x3d, 0x20, 0x31, 0x2e, 0x30, 0x34, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x64, 0x6f, 0x69, 0x6e, 0x67, 0x20, 0x69, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x77,
+ 0x61, 0x79, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x74, 0x73, 0x20, 0x75, 0x73, 0x20, 0x74, 0x6f,
+ 0x20, 0x6b, 0x65, 0x65, 0x70, 0x20, 0x74, 0x68, 0x65, 0x0a, 0x2d, 0x2d, 0x20, 0x6f, 0x72, 0x69,
+ 0x67, 0x69, 0x6e, 0x61, 0x6c, 0x20, 0x69, 0x6f, 0x20, 0x6c, 0x69, 0x62, 0x72, 0x61, 0x72, 0x69,
+ 0x65, 0x73, 0x20, 0x63, 0x6c, 0x65, 0x61, 0x6e, 0x2e, 0x20, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72,
+ 0x6d, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x62, 0x61, 0x62, 0x6c,
+ 0x79, 0x20, 0x65, 0x76, 0x65, 0x6e, 0x20, 0x61, 0x20, 0x62, 0x69, 0x74, 0x20, 0x62, 0x65, 0x74,
+ 0x74, 0x65, 0x72, 0x20, 0x6e, 0x6f, 0x77, 0x2e, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20,
+ 0x74, 0x79, 0x70, 0x65, 0x2c, 0x20, 0x6e, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x67, 0x65, 0x74, 0x6d,
+ 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72,
+ 0x65, 0x20, 0x3d, 0x20, 0x74, 0x79, 0x70, 0x65, 0x2c, 0x20, 0x6e, 0x65, 0x78, 0x74, 0x2c, 0x20,
+ 0x67, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x20, 0x72, 0x65,
+ 0x71, 0x75, 0x69, 0x72, 0x65, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x69, 0x6e, 0x64,
+ 0x2c, 0x20, 0x67, 0x73, 0x75, 0x62, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e,
+ 0x66, 0x69, 0x6e, 0x64, 0x2c, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x67, 0x73, 0x75,
+ 0x62, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6f, 0x5f, 0x6f, 0x70, 0x65, 0x6e,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x69,
+ 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x69, 0x6f, 0x5f,
+ 0x70, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x3d, 0x20, 0x69, 0x6f, 0x2e, 0x70, 0x6f, 0x70, 0x65, 0x6e, 0x0a, 0x6c, 0x6f, 0x63, 0x61,
+ 0x6c, 0x20, 0x69, 0x6f, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x69, 0x6f, 0x2e, 0x6c, 0x69, 0x6e, 0x65, 0x73,
+ 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x69, 0x6f, 0x5f, 0x72, 0x65, 0x61, 0x64,
+ 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x66, 0x69,
+ 0x6f, 0x2e, 0x72, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x20, 0x66, 0x69, 0x6f, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73,
+ 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x20, 0x66, 0x69, 0x6f, 0x2e, 0x63, 0x68, 0x65, 0x63, 0x6b,
+ 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x20, 0x66, 0x69, 0x6f, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x66, 0x69, 0x6c, 0x65, 0x6e,
+ 0x61, 0x6d, 0x65, 0x20, 0x20, 0x3d, 0x20, 0x66, 0x69, 0x6f, 0x2e, 0x72, 0x65, 0x63, 0x6f, 0x72,
+ 0x64, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x20, 0x6d, 0x74, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x67, 0x65, 0x74, 0x6d, 0x65, 0x74, 0x61, 0x74, 0x61,
+ 0x62, 0x6c, 0x65, 0x28, 0x69, 0x6f, 0x2e, 0x73, 0x74, 0x64, 0x65, 0x72, 0x72, 0x29, 0x0a, 0x6c,
+ 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6d, 0x74, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x6d, 0x74, 0x2e, 0x6c, 0x69,
+ 0x6e, 0x65, 0x73, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x61, 0x66, 0x65, 0x72, 0x6f,
+ 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20,
+ 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x73, 0x61, 0x66, 0x65, 0x72, 0x5f, 0x6f, 0x70, 0x74,
+ 0x69, 0x6f, 0x6e, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x65,
+ 0x73, 0x63, 0x61, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20,
+ 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x5f, 0x65, 0x73, 0x63,
+ 0x61, 0x70, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x30, 0x20, 0x28, 0x64, 0x69,
+ 0x73, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x29, 0x20, 0x31, 0x20, 0x28, 0x72, 0x65, 0x73, 0x74, 0x72,
+ 0x69, 0x63, 0x74, 0x65, 0x64, 0x29, 0x20, 0x32, 0x20, 0x28, 0x65, 0x76, 0x65, 0x72, 0x79, 0x74,
+ 0x68, 0x69, 0x6e, 0x67, 0x29, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6b, 0x70, 0x73, 0x65,
+ 0x75, 0x73, 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x3d, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x6b, 0x70, 0x73, 0x65, 0x5f, 0x75, 0x73,
+ 0x65, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x30, 0x20, 0x31,
+ 0x0a, 0x0a, 0x69, 0x6f, 0x2e, 0x73, 0x61, 0x76, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x69, 0x6f,
+ 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x20, 0x2d, 0x2d, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65,
+ 0x20, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x0a, 0x69, 0x6f, 0x2e, 0x73, 0x61,
+ 0x76, 0x65, 0x64, 0x5f, 0x70, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x69, 0x6f, 0x5f, 0x70, 0x6f, 0x70, 0x65, 0x6e, 0x20,
+ 0x2d, 0x2d, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x65, 0x63,
+ 0x74, 0x65, 0x64, 0x0a, 0x69, 0x6f, 0x2e, 0x73, 0x61, 0x76, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x6e,
+ 0x65, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20,
+ 0x69, 0x6f, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x2d, 0x2d, 0x20, 0x61, 0x6c, 0x77, 0x61,
+ 0x79, 0x73, 0x20, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x0a, 0x6d, 0x74, 0x2e, 0x73,
+ 0x61, 0x76, 0x65, 0x64, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x6d, 0x74, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x73,
+ 0x20, 0x2d, 0x2d, 0x20, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x20, 0x72, 0x65, 0x61, 0x64, 0x6f,
+ 0x6e, 0x6c, 0x79, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x6f, 0x5f, 0x6f, 0x70,
+ 0x65, 0x6e, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x68, 0x6f, 0x77, 0x29, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x3d, 0x20, 0x27,
+ 0x72, 0x27, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c,
+ 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x20, 0x3d, 0x20, 0x69, 0x6f, 0x5f, 0x6f, 0x70, 0x65, 0x6e,
+ 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x68, 0x6f, 0x77, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69,
+ 0x66, 0x20, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x69, 0x66, 0x20, 0x74, 0x79, 0x70, 0x65, 0x28, 0x68, 0x6f, 0x77, 0x29, 0x20, 0x3d, 0x3d,
+ 0x20, 0x27, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x27, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x69,
+ 0x6e, 0x64, 0x28, 0x68, 0x6f, 0x77, 0x2c, 0x27, 0x77, 0x27, 0x29, 0x20, 0x74, 0x68, 0x65, 0x6e,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x69, 0x6f,
+ 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28,
+ 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x27, 0x77, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x65, 0x6c, 0x73, 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x66, 0x69, 0x6f, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x66, 0x69, 0x6c,
+ 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x27, 0x72, 0x27, 0x29, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66,
+ 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x6f, 0x5f, 0x6f,
+ 0x70, 0x65, 0x6e, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x28, 0x6e, 0x61, 0x6d,
+ 0x65, 0x2c, 0x68, 0x6f, 0x77, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x68, 0x6f,
+ 0x77, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68,
+ 0x6f, 0x77, 0x20, 0x3d, 0x20, 0x27, 0x72, 0x27, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6c, 0x73,
+ 0x65, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x3d, 0x20,
+ 0x67, 0x73, 0x75, 0x62, 0x28, 0x68, 0x6f, 0x77, 0x2c, 0x27, 0x5b, 0x5e, 0x72, 0x62, 0x5d, 0x27,
+ 0x2c, 0x27, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
+ 0x68, 0x6f, 0x77, 0x20, 0x3d, 0x3d, 0x20, 0x27, 0x27, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x68, 0x6f, 0x77, 0x20, 0x3d,
+ 0x20, 0x27, 0x72, 0x27, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63,
+ 0x61, 0x6c, 0x20, 0x66, 0x20, 0x3d, 0x20, 0x69, 0x6f, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x28, 0x6e,
+ 0x61, 0x6d, 0x65, 0x2c, 0x68, 0x6f, 0x77, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20,
+ 0x66, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66,
+ 0x69, 0x6f, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d,
+ 0x65, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x27, 0x72, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66,
+ 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63,
+ 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x6f, 0x5f, 0x70,
+ 0x6f, 0x70, 0x65, 0x6e, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x2e, 0x2e, 0x2e, 0x29, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x6f, 0x6b, 0x61, 0x79, 0x2c, 0x20, 0x66,
+ 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x3d, 0x20, 0x66, 0x69, 0x6f, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b,
+ 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x29,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6f, 0x6b, 0x61, 0x79, 0x20, 0x61, 0x6e, 0x64,
+ 0x20, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x69, 0x6f, 0x5f, 0x70, 0x6f,
+ 0x70, 0x65, 0x6e, 0x28, 0x66, 0x6f, 0x75, 0x6e, 0x64, 0x2c, 0x2e, 0x2e, 0x2e, 0x29, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61,
+ 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x75, 0x61, 0x74, 0x65,
+ 0x78, 0x5f, 0x69, 0x6f, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x29,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x20, 0x3d, 0x20, 0x69,
+ 0x6f, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x28, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x27, 0x72, 0x27, 0x29,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x66, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75,
+ 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x69, 0x6f, 0x5f,
+ 0x72, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x28, 0x66, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a,
+ 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x6f, 0x5f, 0x72, 0x65,
+ 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x28, 0x66, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65,
+ 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x29, 0x0a,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66,
+ 0x69, 0x6f, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x6c, 0x69, 0x6e, 0x65, 0x28, 0x66, 0x29, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x69, 0x6f, 0x2e, 0x6c,
+ 0x69, 0x6e, 0x65, 0x73, 0x20, 0x3d, 0x20, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x6f,
+ 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x0a, 0x6d, 0x74, 0x2e, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20,
+ 0x3d, 0x20, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x6f, 0x5f, 0x72, 0x65, 0x61, 0x64,
+ 0x6c, 0x69, 0x6e, 0x65, 0x0a, 0x0a, 0x2d, 0x2d, 0x20, 0x57, 0x65, 0x20, 0x61, 0x73, 0x73, 0x75,
+ 0x6d, 0x65, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20, 0x74, 0x6f,
+ 0x20, 0x62, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20,
+ 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x20,
+ 0x6f, 0x66, 0x20, 0x6b, 0x70, 0x73, 0x65, 0x2e, 0x20, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73,
+ 0x20, 0x74, 0x68, 0x65, 0x0a, 0x2d, 0x2d, 0x20, 0x63, 0x61, 0x73, 0x65, 0x20, 0x69, 0x6e, 0x20,
+ 0x43, 0x6f, 0x6e, 0x54, 0x65, 0x58, 0x74, 0x2e, 0x0a, 0x0a, 0x69, 0x66, 0x20, 0x6b, 0x70, 0x73,
+ 0x65, 0x75, 0x73, 0x65, 0x64, 0x20, 0x3d, 0x3d, 0x20, 0x31, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x20, 0x3d, 0x20,
+ 0x6c, 0x75, 0x61, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x6f, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x0a, 0x20,
+ 0x20, 0x20, 0x20, 0x69, 0x6f, 0x2e, 0x70, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x6c, 0x75,
+ 0x61, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x6f, 0x5f, 0x70, 0x6f, 0x70, 0x65, 0x6e, 0x0a, 0x0a, 0x65,
+ 0x6e, 0x64, 0x0a, 0x0a, 0x69, 0x66, 0x20, 0x73, 0x61, 0x66, 0x65, 0x72, 0x6f, 0x70, 0x74, 0x69,
+ 0x6f, 0x6e, 0x20, 0x3d, 0x3d, 0x20, 0x31, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x6f, 0x73, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x20, 0x3d, 0x20, 0x6e,
+ 0x69, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x73, 0x2e, 0x73, 0x70, 0x61, 0x77, 0x6e, 0x20,
+ 0x20, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x73, 0x2e, 0x65,
+ 0x78, 0x65, 0x63, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x6f, 0x73, 0x2e, 0x73, 0x65, 0x74, 0x65, 0x6e, 0x76, 0x20, 0x20, 0x3d, 0x20, 0x6e, 0x69,
+ 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x73, 0x2e, 0x74, 0x65, 0x6d, 0x70, 0x64, 0x69, 0x72,
+ 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6f, 0x2e, 0x70,
+ 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x69, 0x6f, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x6e, 0x69,
+ 0x6c, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x73, 0x2e, 0x72, 0x65, 0x6e, 0x61, 0x6d, 0x65,
+ 0x20, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x73, 0x2e, 0x72,
+ 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x69, 0x6f, 0x2e, 0x74, 0x6d, 0x70, 0x66, 0x69, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0x6e,
+ 0x69, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6f, 0x2e, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74,
+ 0x20, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x66, 0x73,
+ 0x2e, 0x63, 0x68, 0x64, 0x69, 0x72, 0x20, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x6c, 0x66, 0x73, 0x2e, 0x6c, 0x6f, 0x63, 0x6b, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x6e,
+ 0x69, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x66, 0x73, 0x2e, 0x74, 0x6f, 0x75, 0x63, 0x68,
+ 0x20, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x66, 0x73, 0x2e,
+ 0x72, 0x6d, 0x64, 0x69, 0x72, 0x20, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x6c, 0x66, 0x73, 0x2e, 0x6d, 0x6b, 0x64, 0x69, 0x72, 0x20, 0x20, 0x3d, 0x20, 0x6e, 0x69,
+ 0x6c, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x6f, 0x2e, 0x73, 0x61, 0x76, 0x65, 0x64, 0x5f,
+ 0x70, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x69, 0x6f, 0x2e, 0x73, 0x61, 0x76, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x20, 0x20, 0x3d,
+ 0x20, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x78, 0x5f, 0x69, 0x6f, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x5f,
+ 0x72, 0x65, 0x61, 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x0a, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x69,
+ 0x66, 0x20, 0x73, 0x61, 0x66, 0x65, 0x72, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x3d, 0x3d,
+ 0x20, 0x31, 0x20, 0x6f, 0x72, 0x20, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x63, 0x61, 0x70,
+ 0x65, 0x20, 0x7e, 0x3d, 0x20, 0x32, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x66, 0x66, 0x69, 0x20, 0x3d, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x28, 0x27,
+ 0x66, 0x66, 0x69, 0x27, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x6b, 0x2c,
+ 0x20, 0x76, 0x20, 0x69, 0x6e, 0x20, 0x6e, 0x65, 0x78, 0x74, 0x2c, 0x20, 0x66, 0x66, 0x69, 0x20,
+ 0x64, 0x6f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x66, 0x20, 0x6b, 0x20,
+ 0x7e, 0x3d, 0x20, 0x27, 0x67, 0x63, 0x27, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x66, 0x69, 0x5b, 0x6b, 0x5d, 0x20,
+ 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e,
+ 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x66,
+ 0x69, 0x20, 0x3d, 0x20, 0x6e, 0x69, 0x6c, 0x0a, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x2d, 0x2d, 0x20,
+ 0x6f, 0x73, 0x2e, 0x5b, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x7c, 0x6f, 0x73, 0x2e, 0x73,
+ 0x70, 0x61, 0x77, 0x6e, 0x7c, 0x6f, 0x73, 0x2e, 0x65, 0x78, 0x65, 0x63, 0x5d, 0x20, 0x61, 0x6c,
+ 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x61, 0x72, 0x65, 0x20, 0x73, 0x68, 0x65, 0x6c, 0x6c, 0x65,
+ 0x73, 0x63, 0x61, 0x70, 0x65, 0x20, 0x61, 0x77, 0x61, 0x72, 0x65, 0x29, 0x0a, 0x0a, 0x0a, 0x69,
+ 0x66, 0x20, 0x6d, 0x64, 0x35, 0x20, 0x74, 0x68, 0x65, 0x6e, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20, 0x73, 0x75, 0x6d, 0x20, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x6d,
+ 0x64, 0x35, 0x2e, 0x73, 0x75, 0x6d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x20, 0x67, 0x73, 0x75, 0x62, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+ 0x2e, 0x67, 0x73, 0x75, 0x62, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x20,
+ 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x2e,
+ 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6c, 0x6f, 0x63, 0x61, 0x6c,
+ 0x20, 0x62, 0x79, 0x74, 0x65, 0x20, 0x20, 0x20, 0x3d, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
+ 0x2e, 0x62, 0x79, 0x74, 0x65, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74,
+ 0x69, 0x6f, 0x6e, 0x20, 0x6d, 0x64, 0x35, 0x2e, 0x73, 0x75, 0x6d, 0x68, 0x65, 0x78, 0x61, 0x28,
+ 0x6b, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72,
+ 0x6e, 0x20, 0x28, 0x67, 0x73, 0x75, 0x62, 0x28, 0x73, 0x75, 0x6d, 0x28, 0x6b, 0x29, 0x2c, 0x20,
+ 0x22, 0x2e, 0x22, 0x2c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x63, 0x29,
+ 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74,
+ 0x75, 0x72, 0x6e, 0x20, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x28, 0x22, 0x25, 0x30, 0x32, 0x78,
+ 0x22, 0x2c, 0x62, 0x79, 0x74, 0x65, 0x28, 0x63, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64,
+ 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6d,
+ 0x64, 0x35, 0x2e, 0x73, 0x75, 0x6d, 0x48, 0x45, 0x58, 0x41, 0x28, 0x6b, 0x29, 0x0a, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x28, 0x67, 0x73,
+ 0x75, 0x62, 0x28, 0x73, 0x75, 0x6d, 0x28, 0x6b, 0x29, 0x2c, 0x20, 0x22, 0x2e, 0x22, 0x2c, 0x20,
+ 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x28, 0x63, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x20, 0x66,
+ 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x28, 0x22, 0x25, 0x30, 0x32, 0x58, 0x22, 0x2c, 0x62, 0x79, 0x74,
+ 0x65, 0x28, 0x63, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e,
+ 0x64, 0x29, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x65, 0x6e, 0x64, 0x0a, 0x0a, 0x65, 0x6e, 0x64,
+ 0x0a, 0x0a, 0x00
+ };
+ return luaL_dostring(L, (const char*) luatex_core_lua);
+} \ No newline at end of file
diff --git a/Build/source/texk/web2c/luatexdir/lua/luatex-core.lua b/Build/source/texk/web2c/luatexdir/lua/luatex-core.lua
new file mode 100644
index 00000000000..704e44c2400
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/luatex-core.lua
@@ -0,0 +1,209 @@
+-- if not modules then modules = { } end modules ['luatex-core'] = {
+-- version = 1.001,
+-- comment = 'companion to luatex',
+-- author = 'Hans Hagen & Luigi Scarso',
+-- copyright = 'LuaTeX Development Team',
+-- }
+
+LUATEXCOREVERSION = 1.002
+
+-- This file overloads some Lua functions. The readline variants provide the same
+-- functionality as LuaTeX <= 1.04 and doing it this way permits us to keep the
+-- original io libraries clean. Performance is probably even a bit better now.
+
+local type, next, getmetatable, require = type, next, getmetatable, require
+local find, gsub = string.find, string.gsub
+
+local io_open = io.open
+local io_popen = io.popen
+local io_line = io.lines
+
+local fio_readline = fio.readline
+local fio_checkpermission = fio.checkpermission
+local fio_recordfilename = fio.recordfilename
+
+local mt = getmetatable(io.stderr)
+local mt_lines = mt.lines
+local saferoption = status.safer_option
+local shellescape = status.shell_escape -- 0 (disabled) 1 (restricted) 2 (everything)
+local kpseused = status.kpse_used -- 0 1
+
+io.saved_open = io_open -- can be protected
+io.saved_popen = io_popen -- can be protected
+io.saved_lines = io_lines -- always readonly
+mt.saved_lines = mt_lines -- always readonly
+
+local function luatex_io_open(name,how)
+ if not how then
+ how = 'r'
+ end
+ local f = io_open(name,how)
+ if f then
+ if type(how) == 'string' and find(how,'w') then
+ fio_recordfilename(name,'w')
+ else
+ fio_recordfilename(name,'r')
+ end
+ end
+ return f
+end
+
+local function luatex_io_open_readonly(name,how)
+ if how then
+ how = 'r'
+ else
+ how = gsub(how,'[^rb]','')
+ if how == '' then
+ how = 'r'
+ end
+ end
+ local f = io_open(name,how)
+ if f then
+ fio_recordfilename(name,'r')
+ end
+ return f
+end
+
+local function luatex_io_popen(name,...)
+ local okay, found = fio_checkpermission(name)
+ if okay and found then
+ return io_popen(found,...)
+ end
+end
+
+local function luatex_io_lines(name)
+ local f = io_open(name,'r')
+ if f then
+ return function()
+ return fio_readline(f)
+ end
+ end
+end
+
+local function luatex_io_readline(f)
+ return function()
+ return fio_readline(f)
+ end
+end
+
+io.lines = luatex_io_lines
+mt.lines = luatex_io_readline
+
+-- We assume management to be provided by the replacement of kpse. This is the
+-- case in ConTeXt.
+
+if kpseused == 1 then
+
+ io.open = luatex_io_open
+ io.popen = luatex_io_popen
+
+end
+
+if saferoption == 1 then
+
+ os.execute = nil
+ os.spawn = nil
+ os.exec = nil
+ os.setenv = nil
+ os.tempdir = nil
+
+ io.popen = nil
+ io.open = nil
+
+ os.rename = nil
+ os.remove = nil
+
+ io.tmpfile = nil
+ io.output = nil
+
+ lfs.chdir = nil
+ lfs.lock = nil
+ lfs.touch = nil
+ lfs.rmdir = nil
+ lfs.mkdir = nil
+
+ io.saved_popen = nil
+ io.saved_open = luatex_io_open_readonly
+
+end
+
+if saferoption == 1 or shellescape ~= 2 then
+
+ ffi = require('ffi')
+ for k, v in next, ffi do
+ if k ~= 'gc' then
+ ffi[k] = nil
+ end
+ end
+ ffi = nil
+end
+
+-- os.[execute|os.spawn|os.exec] already are shellescape aware)
+
+
+if md5 then
+
+ local sum = md5.sum
+ local gsub = string.gsub
+ local format = string.format
+ local byte = string.byte
+
+ function md5.sumhexa(k)
+ return (gsub(sum(k), ".", function(c)
+ return format("%02x",byte(c))
+ end))
+ end
+
+ function md5.sumHEXA(k)
+ return (gsub(sum(k), ".", function(c)
+ return format("%02X",byte(c))
+ end))
+ end
+
+end
+
+if utilities and utilities.merger and utilities.merger.compact then
+
+ local byte, format, gmatch = string.byte, string.format, string.gmatch
+ local concat = table.concat
+
+ local data = gsub(io.loaddata('luatex-core.lua'),'if%s+utilities.*','')
+ local t = { }
+ local r = { }
+ local n = 0
+ local d = gsub(data,'\r\n','\n') -- be nice for unix
+ local s = utilities.merger.compact(d) -- no comments and less spaces
+
+ t[#t+1] = '/* generated from and by luatex-core.lua */'
+ t[#t+1] = ''
+ -- t[#t+1] = format('/*\n\n%s\n\n*/',d)
+ -- t[#t+1] = ''
+ t[#t+1] = '#include "lua.h"'
+ t[#t+1] = '#include "lauxlib.h"'
+ t[#t+1] = ''
+ t[#t+1] = 'int load_luatex_core_lua (lua_State * L);'
+ t[#t+1] = ''
+ t[#t+1] = 'int load_luatex_core_lua (lua_State * L)'
+ t[#t+1] = '{'
+ t[#t+1] = ' static unsigned char luatex_core_lua[] = {'
+ for c in gmatch(d,'.') do
+ if n == 16 then
+ n = 1
+ t[#t+1] = ' ' .. concat(r,', ') .. ','
+ else
+ n = n + 1
+ end
+ r[n] = format('0x%02x',byte(c))
+ end
+ n = n + 1
+ r[n] = '0x00'
+ t[#t+1] = ' ' .. concat(r,', ',1,n)
+ t[#t+1] = ' };'
+ -- t[#t+1] = format('unsigned int luatex_core_lua_len = 0x%x;',#d+1)
+ t[#t+1] = ' return luaL_dostring(L, (const char*) luatex_core_lua);'
+ t[#t+1] = '}'
+
+ io.savedata('luatex-core.c',concat(t,'\n'))
+ io.savedata('luatex-core-stripped.lua',s)
+
+end
diff --git a/Build/source/texk/web2c/luatexdir/lua/mplibstuff.w b/Build/source/texk/web2c/luatexdir/lua/mplibstuff.w
new file mode 100644
index 00000000000..3104a287007
--- /dev/null
+++ b/Build/source/texk/web2c/luatexdir/lua/mplibstuff.w
@@ -0,0 +1,93 @@
+% mplibstuff.w
+%
+% Copyright 2017 LuaTeX team <bugs@@luatex.org>
+%
+% This file is part of LuaTeX.
+%
+% LuaTeX is free software; you can redistribute it and/or modify it under
+% the terms of the GNU General Public License as published by the Free
+% Software Foundation; either version 2 of the License, or (at your
+% option) any later version.
+%
+% LuaTeX is distributed in the hope that it will be useful, but WITHOUT
+% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+% 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/>.
+
+@ PNG and SVG backends are not available in \LuaTeX, because it's complex
+to manage the math formulas at run time. In this respect |PostScript| and the highlevel |objects|
+are better, and they are the standard way. Another problem is how to emit the warning:
+the |normal\_warning| function is not available when \LuaTeX\ is called as LUA only.
+
+
+
+@c
+#include <stdio.h>
+
+extern void normal_warning(const char *t, const char *p);
+extern int lua_only;
+#define mplibstuff_message(BACKEND) do { \
+ if (lua_only) { \
+ fprintf(stdout,"mplib: " #BACKEND " backend not available.\n"); \
+ } else { \
+ normal_warning("mplib", #BACKEND " backend not available."); \
+ } \
+} while (0)
+
+
+@ @c
+void mp_png_backend_initialize (void *mp);
+void mp_png_backend_free (void *mp);
+int mp_png_gr_ship_out (void *hh, void *options, int standalone);
+int mp_png_ship_out (void *hh, const char *options);
+
+@ @c
+void mp_svg_backend_initialize (void *mp);
+void mp_svg_backend_free (void *mp);
+int mp_svg_ship_out (void *hh, int prologues);
+int mp_svg_gr_ship_out (void *hh, int qprologues, int standalone);
+
+@ @c
+void mp_png_backend_initialize (void *mp) {return; } /*{mplibstuff_message(1png);return;}*/
+void mp_png_backend_free (void *mp) {return; } /*{mplibstuff_message(png);return;}*/
+int mp_png_gr_ship_out (void *hh, void *options, int standalone) {mplibstuff_message(png);return 1;}
+int mp_png_ship_out (void *hh, const char *options) {mplibstuff_message(png);return 1;}
+
+@ @c
+void mp_svg_backend_initialize (void *mp) {return;} /*{mplibstuff_message(svg);return;}*/
+void mp_svg_backend_free (void *mp) {return;} /*{mplibstuff_message(svg);return;}*/
+int mp_svg_ship_out (void *hh, int prologues) {mplibstuff_message(svg);return 1;}
+int mp_svg_gr_ship_out (void *hh, int qprologues, int standalone) {mplibstuff_message(svg);return 1;}
+
+@ @c
+const char*
+cairo_version_string (void);
+const char*
+pixman_version_string (void);
+#define CAIRO_VERSION_STRING "CAIRO NOT AVAILABLE"
+const char *COMPILED_CAIRO_VERSION_STRING = CAIRO_VERSION_STRING;
+#define PIXMAN_VERSION_STRING "PIXMAN NOT AVAILABLE"
+const char *COMPILED_PIXMAN_VERSION_STRING = PIXMAN_VERSION_STRING;
+
+const char*
+cairo_version_string (void)
+{
+ return CAIRO_VERSION_STRING;
+}
+
+const char*
+pixman_version_string (void)
+{
+ return PIXMAN_VERSION_STRING;
+}
+
+
+
+
+
+@ @c
+char png_libpng_ver[] = "PNG NOT AVAILABLE";
+