diff options
author | Luigi Scarso <luigi.scarso@gmail.com> | 2017-03-11 00:31:06 +0000 |
---|---|---|
committer | Luigi Scarso <luigi.scarso@gmail.com> | 2017-03-11 00:31:06 +0000 |
commit | 7fa7e2984ec7346b13ce8d3a84826552d30f00ea (patch) | |
tree | f177da03ee3839977b28ee4f149cb612666eddde /Build/source/texk/web2c/luatexdir/lua | |
parent | dedac2fcc2339e6d9cddef8edb046fd0e04c397e (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.w | 26 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/lauxlib_bridge.h | 22 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/lepdflib.cc | 5 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/limglib.c | 3 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/liolibext.c | 891 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/lnewtokenlib.c | 49 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/loslibext.c | 27 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/lstatslib.c | 50 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/lstrlibext.c | 249 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/luainit.w | 2248 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/luastuff.w | 1242 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/luatex-api.h | 18 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/luatex-core.c | 253 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/luatex-core.lua | 209 | ||||
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/mplibstuff.w | 93 |
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"; + |