From 7fa7e2984ec7346b13ce8d3a84826552d30f00ea Mon Sep 17 00:00:00 2001 From: Luigi Scarso Date: Sat, 11 Mar 2017 00:31:06 +0000 Subject: sync with luatex r.6287 and mpost r.2125 git-svn-id: svn://tug.org/texlive/trunk@43454 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/texk/web2c/luatexdir/lua/helpers.w | 26 + .../texk/web2c/luatexdir/lua/lauxlib_bridge.h | 22 +- Build/source/texk/web2c/luatexdir/lua/lepdflib.cc | 5 - Build/source/texk/web2c/luatexdir/lua/limglib.c | 3 +- Build/source/texk/web2c/luatexdir/lua/liolibext.c | 891 +++----- .../source/texk/web2c/luatexdir/lua/lnewtokenlib.c | 49 + Build/source/texk/web2c/luatexdir/lua/loslibext.c | 27 +- Build/source/texk/web2c/luatexdir/lua/lstatslib.c | 50 +- Build/source/texk/web2c/luatexdir/lua/lstrlibext.c | 249 +-- Build/source/texk/web2c/luatexdir/lua/luainit.w | 2248 ++++++++++---------- Build/source/texk/web2c/luatexdir/lua/luastuff.w | 1242 ++++++----- Build/source/texk/web2c/luatexdir/lua/luatex-api.h | 18 +- .../source/texk/web2c/luatexdir/lua/luatex-core.c | 253 +++ .../texk/web2c/luatexdir/lua/luatex-core.lua | 209 ++ Build/source/texk/web2c/luatexdir/lua/mplibstuff.w | 93 + 15 files changed, 2978 insertions(+), 2407 deletions(-) create mode 100644 Build/source/texk/web2c/luatexdir/lua/helpers.w create mode 100644 Build/source/texk/web2c/luatexdir/lua/luatex-core.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/luatex-core.lua create mode 100644 Build/source/texk/web2c/luatexdir/lua/mplibstuff.w (limited to 'Build/source/texk/web2c/luatexdir/lua') 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 +% +% 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 . + +@ 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 . */ + with LuaTeX; if not, see . -/* 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 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=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 -% -% 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 . - -@ @c - -#include "ptexlib.h" - -#include - -#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 +% +% 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 . + +@ @c + +#include "ptexlib.h" + +#include + +#include "lua/luatex-api.h" + +#include + +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 -% -% 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 . - -@ @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 *//* |[{}]| */ - lua_pushstring(L, tab); /* |[{},"dimen"]| */ - lua_newtable(L); /* |[{},"dimen",{}]| */ - lua_settable(L, -3); /* |[{}]| */ - /* fetch it back */ - lua_pushstring(L, tab); /* |[{},"dimen"]| */ - lua_gettable(L, -2); /* |[{},{}]| */ - /* make the meta entries */ - luaL_newmetatable(L, mttab); /* |[{},{},{}]| */ - lua_pushstring(L, "__index"); /* |[{},{},{},"__index"]| */ - lua_pushstring(L, getfunc); /* |[{},{},{},"__index","getdimen"]| */ - lua_gettable(L, -5); /* |[{},{},{},"__index",]| */ - lua_settable(L, -3); /* |[{},{},{}]| */ - lua_pushstring(L, "__newindex"); /* |[{},{},{},"__newindex"]| */ - lua_pushstring(L, setfunc); /* |[{},{},{},"__newindex","setdimen"]| */ - lua_gettable(L, -5); /* |[{},{},{},"__newindex",]| */ - lua_settable(L, -3); /* |[{},{},{}]| */ - lua_setmetatable(L, -2); /* |[{},{}]| : assign the metatable */ - lua_pop(L, 1); /* |[{}]| : 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 +% +% 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 . + +@ @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 *//* |[{}]| */ + lua_pushstring(L, tab); /* |[{},"dimen"]| */ + lua_newtable(L); /* |[{},"dimen",{}]| */ + lua_settable(L, -3); /* |[{}]| */ + /* fetch it back */ + lua_pushstring(L, tab); /* |[{},"dimen"]| */ + lua_gettable(L, -2); /* |[{},{}]| */ + /* make the meta entries */ + luaL_newmetatable(L, mttab); /* |[{},{},{}]| */ + lua_pushstring(L, "__index"); /* |[{},{},{},"__index"]| */ + lua_pushstring(L, getfunc); /* |[{},{},{},"__index","getdimen"]| */ + lua_gettable(L, -5); /* |[{},{},{},"__index",]| */ + lua_settable(L, -3); /* |[{},{},{}]| */ + lua_pushstring(L, "__newindex"); /* |[{},{},{},"__newindex"]| */ + lua_pushstring(L, setfunc); /* |[{},{},{},"__newindex","setdimen"]| */ + lua_gettable(L, -5); /* |[{},{},{},"__newindex",]| */ + lua_settable(L, -3); /* |[{},{},{}]| */ + lua_setmetatable(L, -2); /* |[{},{}]| : assign the metatable */ + lua_pop(L, 1); /* |[{}]| : 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 +% +% 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 . + +@ 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 + +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"; + -- cgit v1.2.3