diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/lua/luastuff.w')
-rw-r--r-- | Build/source/texk/web2c/luatexdir/lua/luastuff.w | 493 |
1 files changed, 493 insertions, 0 deletions
diff --git a/Build/source/texk/web2c/luatexdir/lua/luastuff.w b/Build/source/texk/web2c/luatexdir/lua/luastuff.w new file mode 100644 index 00000000000..06547bc4de9 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luastuff.w @@ -0,0 +1,493 @@ +% luastuff.w + +% Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org> + +% This file is part of LuaTeX. + +% LuaTeX is free software; you can redistribute it and/or modify it under +% the terms of the GNU General Public License as published by the Free +% Software Foundation; either version 2 of the License, or (at your +% option) any later version. + +% LuaTeX is distributed in the hope that it will be useful, but WITHOUT +% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +% License for more details. + +% You should have received a copy of the GNU General Public License along +% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +@ @c +static const char _svn_version[] = + "$Id: luastuff.w 3583 2010-04-02 17:40:44Z hhenkel $ " + "$URL: http://foundry.supelec.fr/svn/luatex/tags/beta-0.60.0/source/texk/web2c/luatexdir/lua/luastuff.w $"; + +#include "lua/luatex-api.h" +#include "ptexlib.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 *getfunc, + const char *setfunc) +{ + /* make the table *//* |[{<tex>}]| */ + lua_pushstring(L, tab); /* |[{<tex>},"dimen"]| */ + lua_newtable(L); /* |[{<tex>},"dimen",{}]| */ + lua_settable(L, -3); /* |[{<tex>}]| */ + /* fetch it back */ + lua_pushstring(L, tab); /* |[{<tex>},"dimen"]| */ + lua_gettable(L, -2); /* |[{<tex>},{<dimen>}]| */ + /* make the meta entries */ + luaL_newmetatable(L, tab); /* |[{<tex>},{<dimen>},{<dimen_m>}]| */ + lua_pushstring(L, "__index"); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index"]| */ + lua_pushstring(L, getfunc); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index","getdimen"]| */ + lua_gettable(L, -5); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index",<tex.getdimen>]| */ + lua_settable(L, -3); /* |[{<tex>},{<dimen>},{<dimen_m>}]| */ + lua_pushstring(L, "__newindex"); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex"]| */ + lua_pushstring(L, setfunc); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex","setdimen"]| */ + lua_gettable(L, -5); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex",<tex.setdimen>]| */ + lua_settable(L, -3); /* |[{<tex>},{<dimen>},{<dimen_m>}]| */ + lua_setmetatable(L, -2); /* |[{<tex>},{<dimen>}]| : assign the metatable */ + lua_pop(L, 1); /* |[{<tex>}]| : clean the stack */ +} + +@ @c +static +const char *getS(lua_State * L, void *ud, size_t * size) +{ + LoadS *ls = (LoadS *) ud; + (void) L; + if (ls->size == 0) + return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + +@ @c +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 +static const luaL_Reg lualibs[] = { + {"", luaopen_base}, + {"package", luaopen_package}, + {"table", luaopen_table}, + {"io", luaopen_io}, + {"os", luaopen_os}, + {"string", luaopen_string}, + {"math", luaopen_math}, + {"debug", luaopen_debug}, + {"unicode", luaopen_unicode}, + {"zip", luaopen_zip}, + {"lpeg", luaopen_lpeg}, + {"md5", luaopen_md5}, + {"lfs", luaopen_lfs}, + {"profiler", luaopen_profiler}, + {NULL, NULL} +}; + + +@ @c +static void do_openlibs(lua_State * L) +{ + const luaL_Reg *lib = lualibs; + for (; lib->func; lib++) { + lua_pushcfunction(L, lib->func); + lua_pushstring(L, lib->name); + lua_call(L, 1, 0); + } +} + +@ @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) { + const char *fname = luaL_optstring(L, 1, NULL); + 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> "); + } + } + return load_aux(L, luaL_loadfile(L, fname)); +} + +@ @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); + 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); + + /* 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_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); + + /* |luaopen_img(L);| */ + lua_pushcfunction(L, luaopen_img); + lua_pushstring(L, "img"); + lua_call(L, 1, 0); + + /* |luaopen_epdf(L);| */ + lua_pushcfunction(L, luaopen_epdf); + lua_pushstring(L, "epdf"); + 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_getfield(L, LUA_GLOBALSINDEX, "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) +{ + LoadS ls; + int i, l; + char *lua_id; + char *s = NULL; + + if (Luas == NULL) { + luainterpreter(); + } + 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); + } else if (nameptr < 0) { + char *tmp = get_lua_name((nameptr + 65536)); + if (tmp != NULL) + lua_id = xstrdup(tmp); + else + lua_id = xstrdup("\\latelua "); + } else { + lua_id = xmalloc(20); + snprintf((char *) lua_id, 20, "\\latelua "); + } + + i = lua_load(Luas, getS, &ls, lua_id); + 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(lua_id); + } + lua_active--; +} + +@ @c +void late_lua(PDF pdf, halfword p) +{ + (void) pdf; + expand_macros_in_tokenlist(p); /* sets |def_ref| */ + luacall(def_ref, late_lua_name(p)); + flush_list(def_ref); +} + +@ @c +void luatokencall(int p, int nameptr) +{ + 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); + } else if (nameptr < 0) { + char *tmp = get_lua_name((nameptr + 65536)); + if (tmp != NULL) + lua_id = xstrdup(tmp); + else + lua_id = xstrdup("\\directlua "); + } else { + lua_id = xstrdup("\\directlua "); + } + i = lua_load(Luas, getS, &ls, lua_id); + 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)); + } + } + xfree(lua_id); + } + lua_active--; +} + +@ @c +lua_State *luatex_error(lua_State * L, int is_fatal) +{ + + const char *luaerr; + size_t len = 0; + char *err = NULL; + if (lua_isstring(L, -1)) { + luaerr = lua_tolstring(L, -1, &len); + err = (char *) xmalloc((unsigned) (len + 1)); + len = (size_t) snprintf(err, (len + 1), "%s", luaerr); + } + 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 */ + lua_fatal_error(err); + /* never reached */ + xfree(err); + lua_close(L); + return (lua_State *) NULL; + } else { + lua_norm_error(err); + xfree(err); + return L; + } +} + +@ @c +void preset_environment(lua_State * L, const parm_struct * p) +{ + int i; + assert(L != NULL); + lua_newtable(L); /* t */ + for (i = 1, ++p; p->name != NULL; i++, p++) { + assert(i == p->idx); + lua_pushstring(L, p->name); /* k t */ + lua_pushinteger(L, p->idx); /* v k t */ + lua_settable(L, -3); /* t */ + } + lua_replace(L, LUA_ENVIRONINDEX); /* - */ +} |