diff options
Diffstat (limited to 'Build/source/texk/web2c/luatexdir/lua')
16 files changed, 5368 insertions, 2344 deletions
diff --git a/Build/source/texk/web2c/luatexdir/lua/helpers.c b/Build/source/texk/web2c/luatexdir/lua/helpers.c new file mode 100644 index 00000000000..e7be7a2c2fe --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/helpers.c @@ -0,0 +1,29 @@ +/* + +helpers.w + +Copyright 2017 LuaTeX team <bugs@@luatex.org> + +This file is part of LuaTeX. + +LuaTeX is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. + +LuaTeX is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU General Public License along +with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +*/ + +/*tex + +We might move here some helpers common to code that are now in weird places, +probably organized in texhelpers, luahelpers, pdfhelpers. + +*/ diff --git a/Build/source/texk/web2c/luatexdir/lua/helpers.w b/Build/source/texk/web2c/luatexdir/lua/helpers.w deleted file mode 100644 index d12e476909d..00000000000 --- a/Build/source/texk/web2c/luatexdir/lua/helpers.w +++ /dev/null @@ -1,26 +0,0 @@ -% helpers.w -% -% Copyright 2017 LuaTeX team <bugs@@luatex.org> -% -% This file is part of LuaTeX. -% -% LuaTeX is free software; you can redistribute it and/or modify it under -% the terms of the GNU General Public License as published by the Free -% Software Foundation; either version 2 of the License, or (at your -% option) any later version. -% -% LuaTeX is distributed in the hope that it will be useful, but WITHOUT -% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -% License for more details. -% -% You should have received a copy of the GNU General Public License along -% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -@ We will move here some helpers common to code that are now in weird places, -probably organized in texhelpers, luahelpers, pdfhelpers. - - - -@c -/* to fill... */ diff --git a/Build/source/texk/web2c/luatexdir/lua/llfslibext.c b/Build/source/texk/web2c/luatexdir/lua/llfslibext.c deleted file mode 100644 index eba5778dfc7..00000000000 --- a/Build/source/texk/web2c/luatexdir/lua/llfslibext.c +++ /dev/null @@ -1,171 +0,0 @@ -/* llfslibext.c - - Copyright 2010-2011 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/>. */ - -#include "ptexlib.h" -#include "lua/luatex-api.h" - -#include <kpathsea/c-stat.h> -#include <kpathsea/c-dir.h> -#include <time.h> - - -#ifdef _WIN32 -# include <windows.h> -#else -#endif - -#ifdef _WIN32 - -static int get_short_name(lua_State * L) -{ - long length = 0; - TCHAR *buffer = NULL; - const char *lpszPath = luaL_checkstring(L, 1); - length = GetShortPathName(lpszPath, NULL, 0); - if (length == 0) { - lua_pushnil(L); - lua_pushfstring(L, "operating system error: %d", (int) GetLastError()); - return 2; - } - buffer = (TCHAR *) xmalloc(length * sizeof(TCHAR)); - length = GetShortPathName(lpszPath, buffer, length); - if (length == 0) { - lua_pushnil(L); - lua_pushfstring(L, "operating system error: %d", (int) GetLastError()); - return 2; - } - lua_pushlstring(L, (const char *) buffer, (size_t) length); - return 1; -} - -static int read_link(lua_State * L) -{ - lua_pushboolean(L, 0); - lua_pushliteral(L, "readlink not supported on this platform"); - return 2; -} - -#else - -static int pusherror(lua_State * L, const char *info) -{ - lua_pushnil(L); - if (info == NULL) - lua_pushstring(L, strerror(errno)); - else - lua_pushfstring(L, "%s: %s", info, strerror(errno)); - lua_pushinteger(L, errno); - return 3; -} - -static int Preadlink(lua_State * L) -{ -/** readlink(path) */ - const char *path = luaL_checkstring(L, 1); - char *b = NULL; - int allocated = 128; - int n; - while (1) { - b = malloc(allocated); - if (!b) - return pusherror(L, path); - n = readlink(path, b, allocated); - if (n == -1) { - free(b); - return pusherror(L, path); - } - if (n < allocated) - break; - /* Not enough room, try bigger */ - allocated *= 2; - free(b); - } - lua_pushlstring(L, b, n); - free(b); - return 1; -} - - -static int read_link(lua_State * L) -{ - return Preadlink(L); -} - -static int get_short_name(lua_State * L __attribute__ ((unused))) -{ - /* simply do nothing */ - return 1; -} -#endif - - -/* -** Get file information -*/ -static int file_is_directory(lua_State * L) -{ - struct stat info; - const char *file = luaL_checkstring(L, 1); - - if (stat(file, &info)) { - lua_pushnil(L); - lua_pushfstring(L, "cannot obtain information from file `%s'", file); - return 2; - } - if (S_ISDIR(info.st_mode)) - lua_pushboolean(L, 1); - else - lua_pushboolean(L, 0); - - return 1; -} - -static int file_is_file(lua_State * L) -{ - struct stat info; - const char *file = luaL_checkstring(L, 1); - - if (stat(file, &info)) { - lua_pushnil(L); - lua_pushfstring(L, "cannot obtain information from file `%s'", file); - return 2; - } - if (S_ISREG(info.st_mode)) - lua_pushboolean(L, 1); - else - lua_pushboolean(L, 0); - - return 1; -} - - -void open_lfslibext(lua_State * L) -{ - - lua_getglobal(L, "lfs"); - lua_pushcfunction(L, file_is_directory); - lua_setfield(L, -2, "isdir"); - lua_pushcfunction(L, file_is_file); - lua_setfield(L, -2, "isfile"); - lua_pushcfunction(L, read_link); - lua_setfield(L, -2, "readlink"); - lua_pushcfunction(L, get_short_name); - lua_setfield(L, -2, "shortname"); - lua_pop(L, 1); /* pop the table */ -} diff --git a/Build/source/texk/web2c/luatexdir/lua/lpdfelib.c b/Build/source/texk/web2c/luatexdir/lua/lpdfelib.c new file mode 100644 index 00000000000..31fad9f632d --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lpdfelib.c @@ -0,0 +1,1666 @@ +/*tex + + This file will host the encapsulated \PDF\ support code used for inclusion + and access from \LUA. + +*/ + +#include "ptexlib.h" + +/*tex + + We need to avoid collision with some defines in |cpascal.h|. + +*/ + +#undef lpdfelib_orig_input +#undef lpdfelib_orig_output + +#ifdef input +#define lpdfelib_orig_input input +#undef input +#endif + +#ifdef output +#define lpdfelib_orig_output output +#undef output +#endif + +#include "luapplib/pplib.h" + +#include "image/epdf.h" + +#ifdef lpdfelib_orig_input +#define input lpdfelib_orig_input +#undef lpdfelib_orig_input +#endif + +#ifdef lpdfelib_orig_output +#define output lpdfelib_orig_output +#undef lpdfelib_orig_output +#endif + +#include "lua/luatex-api.h" + +/*tex + + We start with some housekeeping. Dictionaries, arrays, streams and references + get userdata, while strings, names, integers, floats and booleans become regular + \LUA\ objects. We need to define a few metatable identifiers too. + +*/ + +#define PDFE_METATABLE "luatex.pdfe" +#define PDFE_METATABLE_DICTIONARY "luatex.pdfe.dictionary" +#define PDFE_METATABLE_ARRAY "luatex.pdfe.array" +#define PDFE_METATABLE_STREAM "luatex.pdfe.stream" +#define PDFE_METATABLE_REFERENCE "luatex.pdfe.reference" + +typedef struct { + ppdoc *document; + boolean open; + boolean isfile; + char *memstream; + int pages; + int index; +} pdfe_document ; + +typedef struct { + ppdict *dictionary; + ppref *ref; +} pdfe_dictionary; + +typedef struct { + pparray *array; + ppref *ref; +} pdfe_array; + +typedef struct { + ppstream *stream; + ppref *ref; + int decode; + int open; +} pdfe_stream; + +typedef struct { + ppref *reference; +} pdfe_reference; + +/*tex + + We need to check if we have the right userdata. A similar warning is issued + when encounter a problem. We don't exit. + +*/ + +static void pdfe_invalid_object_warning(const char * detail) +{ + formatted_warning("pdfe lib","lua <pdfe %s> expected",detail); +} + +static pdfe_document *check_isdocument(lua_State * L, int n) +{ + pdfe_document *p = (pdfe_document *)lua_touserdata(L, n); + if (p != NULL && lua_getmetatable(L, n)) { + lua_get_metatablelua(luatex_pdfe); + if (!lua_rawequal(L, -1, -2)) { + p = NULL; + } + lua_pop(L, 2); + if (p != NULL) { + return p; + } + } + pdfe_invalid_object_warning("document"); + return NULL; +} + +static pdfe_dictionary *check_isdictionary(lua_State * L, int n) +{ + pdfe_dictionary *p = (pdfe_dictionary *)lua_touserdata(L, n); + if (p != NULL && lua_getmetatable(L, n)) { + lua_get_metatablelua(luatex_pdfe_dictionary); + if (!lua_rawequal(L, -1, -2)) { + p = NULL; + } + lua_pop(L, 2); + if (p != NULL) { + return p; + } + } + pdfe_invalid_object_warning("dictionary"); + return NULL; +} + +static pdfe_array *check_isarray(lua_State * L, int n) +{ + pdfe_array *p = (pdfe_array *)lua_touserdata(L, n); + if (p != NULL && lua_getmetatable(L, n)) { + lua_get_metatablelua(luatex_pdfe_array); + if (!lua_rawequal(L, -1, -2)) { + p = NULL; + } + lua_pop(L, 2); + if (p != NULL) { + return p; + } + } + pdfe_invalid_object_warning("array"); + return NULL; +} + +static pdfe_stream *check_isstream(lua_State * L, int n) +{ + pdfe_stream *p = (pdfe_stream *)lua_touserdata(L, n); + if (p != NULL && lua_getmetatable(L, n)) { + lua_get_metatablelua(luatex_pdfe_stream); + if (!lua_rawequal(L, -1, -2)) { + p = NULL; + } + lua_pop(L, 2); + if (p != NULL) { + return p; + } + } + pdfe_invalid_object_warning("stream"); + return NULL; +} + +static pdfe_reference *check_isreference(lua_State * L, int n) +{ + pdfe_reference *p = (pdfe_reference *)lua_touserdata(L, n); + if (p != NULL && lua_getmetatable(L, n)) { + lua_get_metatablelua(luatex_pdfe_reference); + if (!lua_rawequal(L, -1, -2)) { + p = NULL; + } + lua_pop(L, 2); + if (p != NULL) { + return p; + } + } + pdfe_invalid_object_warning("reference"); + return NULL; +} + +/*tex + + Reporting the type of a userdata is just a sequence of tests till we find the + right one. We return nothing is it is no pdfe type. + + \starttyping + t = pdfe.type(<pdfe document|dictionary|array|reference|stream>) + \stoptyping + +*/ + +#define check_type(field,meta,name) do { \ + lua_get_metatablelua(luatex_##meta); \ + if (lua_rawequal(L, -1, -2)) { \ + lua_pushstring(L,name); \ + return 1; \ + } \ + lua_pop(L, 1); \ +} while (0) + +static int pdfelib_type(lua_State * L) +{ + void *p = lua_touserdata(L, 1); + if (p != NULL && lua_getmetatable(L, 1)) { + check_type(document, pdfe, "pdfe"); + check_type(dictionary,pdfe_dictionary,"pdfe.dictionary"); + check_type(array, pdfe_array, "pdfe.array"); + check_type(reference, pdfe_reference, "pdfe.reference"); + check_type(stream, pdfe_stream, "pdfe.stream"); + } + return 0; +} + +/*tex + + The \type {tostring} metamethods are similar and report a pdfe type plus a + pointer value, as is rather usual in \LUA. + +*/ + +#define define_to_string(field,what) \ +static int pdfelib_tostring_##field(lua_State * L) { \ + pdfe_##field *p = check_is##field(L, 1); \ + if (p != NULL) { \ + lua_pushfstring(L, "<" what " %p>", (ppdoc *) p->field); \ + return 1; \ + } \ + return 0; \ +} + +define_to_string(document, "pdfe") +define_to_string(dictionary,"pdfe.dictionary") +define_to_string(array, "pdfe.array") +define_to_string(reference, "pdfe.reference") +define_to_string(stream, "pdfe.stream") + +/*tex + + The pushers look rather similar. We have two variants, one that just pushes + the object, and another that also pushes some extra information. + +*/ + +#define pdfe_push_dictionary do { \ + pdfe_dictionary *d = (pdfe_dictionary *)lua_newuserdata(L, sizeof(pdfe_dictionary)); \ + luaL_getmetatable(L, PDFE_METATABLE_DICTIONARY); \ + lua_setmetatable(L, -2); \ + d->dictionary = dictionary; \ +} while(0) + +static int pushdictionary(lua_State * L, ppdict *dictionary) +{ + if (dictionary != NULL) { + pdfe_push_dictionary; + lua_pushinteger(L,dictionary->size); + return 2; + } + return 0; +} + +static int pushdictionaryonly(lua_State * L, ppdict *dictionary) +{ + if (dictionary != NULL) { + pdfe_push_dictionary; + return 1; + } + return 0; +} + +#define pdfe_push_array do { \ + pdfe_array *a = (pdfe_array *)lua_newuserdata(L, sizeof(pdfe_array)); \ + luaL_getmetatable(L, PDFE_METATABLE_ARRAY); \ + lua_setmetatable(L, -2); \ + a->array = array; \ + } while (0) + +static int pusharray(lua_State * L, pparray * array) +{ + if (array != NULL) { + pdfe_push_array; + lua_pushinteger(L,array->size); + return 2; + } + return 0; +} + +static int pusharrayonly(lua_State * L, pparray * array) +{ + if (array != NULL) { + pdfe_push_array; + return 1; + } + return 0; +} + +#define pdfe_push_stream do { \ + pdfe_stream *s = (pdfe_stream *)lua_newuserdata(L, sizeof(pdfe_stream)); \ + luaL_getmetatable(L, PDFE_METATABLE_STREAM); \ + lua_setmetatable(L, -2); \ + s->stream = stream; \ + s->open = 0; \ + s->decode = 0; \ +} while(0) + +static int pushstream(lua_State * L, ppstream * stream) +{ + if (stream != NULL) { + pdfe_push_stream; + if (pushdictionary(L, stream->dict) > 0) + return 3; + else + return 1; + } + return 0; +} + +static int pushstreamonly(lua_State * L, ppstream * stream) +{ + if (stream != NULL) { + pdfe_push_stream; + if (pushdictionaryonly(L, stream->dict) > 0) + return 2; + else + return 1; + } + return 0; +} + +#define pdfe_push_reference do { \ + pdfe_reference *r = (pdfe_reference *)lua_newuserdata(L, sizeof(pdfe_reference)); \ + luaL_getmetatable(L, PDFE_METATABLE_REFERENCE); \ + lua_setmetatable(L, -2); \ + r->reference = reference; \ + } while (0) + +static int pushreference(lua_State * L, ppref * reference) +{ + if (reference != NULL) { + pdfe_push_reference; + lua_pushinteger(L,reference->number); + return 2; + } + return 0; +} + +/*tex + + The next function checks for the type and then pushes the matching data on + the stack. + + \starttabulate[|c|l|l|l|] + \BC type \BC meaning \BC value \BC detail \NC \NR + \NC \type {0} \NC none \NC nil \NC \NC \NR + \NC \type {1} \NC null \NC nil \NC \NC \NR + \NC \type {2} \NC boolean \NC boolean \NC \NC \NR + \NC \type {3} \NC boolean \NC integer \NC \NC \NR + \NC \type {4} \NC number \NC float \NC \NC \NR + \NC \type {5} \NC name \NC string \NC \NC \NR + \NC \type {6} \NC string \NC string \NC type \NC \NR + \NC \type {7} \NC array \NC arrayobject \NC size \NC \NR + \NC \type {8} \NC dictionary \NC dictionaryobject \NC size \NC \NR + \NC \type {9} \NC stream \NC streamobject \NC dictionary size \NC \NR + \NC \type {10} \NC reference \NC integer \NC \NC \NR + \LL + \stoptabulate + + A name and string can be distinguished by the extra type value that a string + has. + +*/ + +static int pushvalue(lua_State * L, ppobj *object) +{ + switch (object->type) { + case PPNONE: + case PPNULL: + lua_pushnil(L); + return 1; + break; + case PPBOOL: + lua_pushboolean(L,object->integer); + return 1; + break; + case PPINT: + lua_pushinteger(L, object-> integer); + return 1; + break; + case PPNUM: + lua_pushnumber(L, object->number); + return 1; + break; + case PPNAME: + lua_pushstring(L, (const char *) ppname_decoded(object->name)); + return 1; + break; + case PPSTRING: + lua_pushlstring(L,(const char *) object->string, ppstring_size((void *)object->string)); + lua_pushboolean(L, ppstring_hex((void *)object->string)); + return 2; + break; + case PPARRAY: + return pusharray(L, object->array); + break; + case PPDICT: + return pushdictionary(L, object->dict); + break; + case PPSTREAM: + return pushstream(L, object->stream); + break; + case PPREF: + return pushreference(L, object->ref); + break; + } + return 0; +} + +/*tex + + We need to start someplace when we traverse a document's tree. There are + three places: + + \starttyping + catalogdictionary = getcatalog(documentobject) + trailerdictionary = gettrailer(documentobject) + infodictionary = getinfo (documentobject) + \stoptyping + +*/ + +static int pdfelib_getcatalog(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p == NULL) + return 0; + return pushdictionaryonly(L,ppdoc_catalog(p->document)); +} + +static int pdfelib_gettrailer(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p == NULL) + return 0; + return pushdictionaryonly(L,ppdoc_trailer(p->document)); +} + +static int pdfelib_getinfo(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p == NULL) + return 0; + return pushdictionaryonly(L,ppdoc_info(p->document)); +} + +/*tex + + We have three more helpers. + + \starttyping + [key,] type, value, detail = getfromdictionary(dictionaryobject,name|index) + type, value, detail = getfromarray (arrayobject,index) + [key,] type, value, detail = getfromstream (streamobject,name|index) + \stoptyping + +*/ + +static int pdfelib_getfromarray(lua_State * L) +{ + pdfe_array *a = check_isarray(L, 1); + if (a != NULL) { + int index = luaL_checkint(L, 2) - 1; + if (index < a->array->size) { + ppobj *object = pparray_at(a->array,index); + lua_pushinteger(L,(int) object->type); + return 1 + pushvalue(L,object); + } + } + return 0; +} + +static int pdfelib_getfromdictionary(lua_State * L) +{ + pdfe_dictionary *d = check_isdictionary(L, 1); + if (d != NULL) { + if (lua_type(L,2) == LUA_TSTRING) { + const char *name = luaL_checkstring(L, 2); + ppobj *object = ppdict_get_obj(d->dictionary,name); + if (object != NULL) { + lua_pushinteger(L,(int) object->type); + return 1 + pushvalue(L,object); + } + } else { + int index = luaL_checkint(L, 2) - 1; + if (index < d->dictionary->size) { + ppobj *object = ppdict_at(d->dictionary,index); + ppname key = ppdict_key(d->dictionary,index); + lua_pushstring(L,(const char *) key); + lua_pushinteger(L,(int) object->type); + return 2 + pushvalue(L,object); + } + } + } + return 0; +} + +static int pdfelib_getfromstream(lua_State * L) +{ + pdfe_stream *s = (pdfe_stream *)lua_touserdata(L, 1); + if (s != NULL) { + ppdict *d = s->stream->dict; + if (lua_type(L,2) == LUA_TSTRING) { + const char *name = luaL_checkstring(L, 2); + ppobj *object = ppdict_get_obj(d,name); + if (object != NULL) { + lua_pushinteger(L,(int) object->type); + return 1 + pushvalue(L,object); + } + } else { + int index = luaL_checkint(L, 2) - 1; + if (index < d->size) { + ppobj *object = ppdict_at(d,index); + ppname key = ppdict_key(d,index); + lua_pushstring(L,(const char *) key); + lua_pushinteger(L,(int) object->type); + return 2 + pushvalue(L,object); + } + } + } + return 0; +} + +/*tex + + An indexed table with all entries in an array can be fetched with:: + + \starttyping + t = arraytotable(arrayobject) + \stoptyping + + An hashed table with all entries in an dictionary can be fetched with:: + + \starttyping + t = dictionarytotable(arrayobject) + \stoptyping + +*/ + +static void pdfelib_totable(lua_State * L, ppobj * object, int flat) +{ + int n = pushvalue(L,object); + if (flat && n < 2) { + return; + } + /* [value] [extra] [more] */ + lua_createtable(L,n+1,0); + if (n == 1) { + /* value { nil, nil } */ + lua_insert(L,-2); + /* { nil, nil } value */ + lua_rawseti(L,-2,2); + /* { nil , value } */ + } else if (n == 2) { + /* value extra { nil, nil, nil } */ + lua_insert(L,-3); + /* { nil, nil, nil } value extra */ + lua_rawseti(L,-3,3); + /* { nil, nil, extra } value */ + lua_rawseti(L,-2,2); + /* { nil, value, extra } */ + } else if (n == 3) { + /* value extra more { nil, nil, nil, nil } */ + lua_insert(L,-4); + /* { nil, nil, nil, nil, nil } value extra more */ + lua_rawseti(L,-4,4); + /* { nil, nil, nil, more } value extra */ + lua_rawseti(L,-3,3); + /* { nil, nil, extra, more } value */ + lua_rawseti(L,-2,2); + /* { nil, value, extra, more } */ + } + lua_pushinteger(L,(int) object->type); + /* { nil, [value], [extra], [more] } type */ + lua_rawseti(L,-2,1); + /* { type, [value], [extra], [more] } */ + return; +} + +static int pdfelib_arraytotable(lua_State * L) +{ + pdfe_array *a = check_isarray(L, 1); + if (a != NULL) { + int flat = lua_isboolean(L,2); + int i = 0; + lua_createtable(L,i,0); + /* table */ + for (i=0;i<a->array->size;i++) { + ppobj *object = pparray_at(a->array,i); + pdfelib_totable(L,object,flat); + /* table { type, [value], [extra], [more] } */ + lua_rawseti(L,-2,i+1); + /* table[i] = { type, [value], [extra], [more] } */ + } + return 1; + } + return 0; +} + +static int pdfelib_dictionarytotable(lua_State * L) +{ + pdfe_dictionary *d = check_isdictionary(L, 1); + if (d != NULL) { + int flat = lua_isboolean(L,2); + int i = 0; + lua_createtable(L,0,i); + /* table */ + for (i=0;i<d->dictionary->size;i++) { + ppobj *object = ppdict_at(d->dictionary,i); + ppname key = ppdict_key(d->dictionary,i); + lua_pushstring(L,(const char *) key); + /* table key */ + pdfelib_totable(L,object,flat); + /* table key { type, [value], [extra], [more] } */ + lua_rawset(L,-3); + /* table[key] = { type, [value], [extra] } */ + } + return 1; + } + return 0; +} + +/*tex + + All pages are collected with: + + \starttyping + { { dict, size, objnum }, ... } = pagestotable(document) + \stoptyping + +*/ + +static int pdfelib_pagestotable(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p != NULL) { + ppdoc *d = p->document; + ppref *r = NULL; + int i = 0; + lua_createtable(L,ppdoc_page_count(d),0); + /* pages[1..n] */ + for (r = ppdoc_first_page(d), i = 1; r != NULL; r = ppdoc_next_page(d), ++i) { + lua_createtable(L,3,0); + pushdictionary(L,ppref_obj(r)->dict); + /* table dictionary n */ + lua_rawseti(L,-3,2); + /* table dictionary */ + lua_rawseti(L,-2,1); + /* table */ + lua_pushinteger(L,r->number); + /* table reference */ + lua_rawseti(L,-2,3); + /* table */ + lua_rawseti(L,-2,i); + /* pages[i] = { dictionary, size, objnum } */ + } + return 1; + } + return 0; +} + +/*tex + + Streams can be fetched on one go: + + \starttyping + string, n = readwholestream(streamobject,decode) + \stoptyping + +*/ + +static int pdfelib_readwholestream(lua_State * L) +{ + pdfe_stream *s = check_isstream(L, 1); + if (s != NULL) { + uint8_t *b = NULL; + int decode = 0; + size_t n = 0; + if (s->open > 0) { + ppstream_done(s->stream); + s->open = 0; + s->decode = 0; + } + if (lua_gettop(L) > 1 && lua_isboolean(L, 2)) { + decode = lua_toboolean(L, 2); + } + b = ppstream_all(s->stream,&n,decode); + lua_pushlstring(L, (const char *) b, n); + lua_pushinteger(L, (int) n); + ppstream_done(s->stream); + return 2; + } + return 0; +} + +/*tex + + Alternatively streams can be fetched stepwise: + + okay = openstream(streamobject,[decode]) + string, n = readfromstream(streamobject) + closestream(streamobject) + +*/ + +static int pdfelib_openstream(lua_State * L) +{ + pdfe_stream *s = check_isstream(L, 1); + if (s != NULL) { + if (s->open == 0) { + if (lua_gettop(L) > 1) { + s->decode = lua_isboolean(L, 2); + } + s->open = 1; + } + lua_pushboolean(L,1); + return 1; + } + return 0; +} + +static int pdfelib_closestream(lua_State * L) +{ + pdfe_stream *s = check_isstream(L, 1); + if (s != NULL) { + if (s->open >0) { + ppstream_done(s->stream); + s->open = 0; + s->decode = 0; + } + } + return 0; +} + +static int pdfelib_readfromstream(lua_State * L) +{ + pdfe_stream *s = check_isstream(L, 1); + if (s != NULL) { + size_t n = 0; + uint8_t *d = NULL; + if (s->open == 1) { + d = ppstream_first(s->stream,&n,s->decode); + s->open = 2; + } else if (s->open == 2) { + d = ppstream_next(s->stream,&n); + } else { + return 0; + } + lua_pushlstring(L, (const char *) d, n); + lua_pushinteger(L, (int) n); + return 2; + } + return 0; +} + +/*tex + + There are two methods for opening a document: files and strings. + + \starttyping + documentobject = open(filename) + documentobject = new(string,length) + \stoptyping + + Closing happens with: + + \starttyping + close(documentobject) + \stoptyping + + When the \type {new} function gets a peudo filename as third argument, + no user data will be created but the stream is accessible as image. + +*/ + +static int pdfelib_open(lua_State * L) +{ + const char *filename = luaL_checkstring(L, 1); + ppdoc *d = ppdoc_load(filename); + if (d == NULL) { + formatted_warning("pdfe lib","no valid pdf file '%s'",filename); + } else { + pdfe_document *p = (pdfe_document *) lua_newuserdata(L, sizeof(pdfe_document)); + luaL_getmetatable(L, PDFE_METATABLE); + lua_setmetatable(L, -2); + p->document = d; + p->open = true; + p->isfile = true; + p->memstream = NULL; + return 1; + } + return 0; +} + +static int pdfelib_new(lua_State * L) +{ + const char *docstream = NULL; + char *memstream = NULL ; + unsigned long long streamsize; + switch (lua_type(L, 1)) { + case LUA_TSTRING: + /* stream as Lua string */ + docstream = luaL_checkstring(L, 1); + break; + case LUA_TLIGHTUSERDATA: + /* stream as sequence of bytes */ + docstream = (const char *) lua_touserdata(L, 1); + break; + default: + luaL_error(L, "bad <pdfe> argument: string or lightuserdata expected"); + break; + } + if (docstream == NULL) { + luaL_error(L, "bad <pdfe> document"); + } + /* size of the stream */ + streamsize = (unsigned long long) luaL_checkint(L, 2); + memstream = xmalloc((unsigned) (streamsize + 1)); + if (! memstream) { + luaL_error(L, "no room for <pdfe> stream"); + } + memcpy(memstream, docstream, (streamsize + 1)); + memstream[streamsize]='\0'; + if (lua_gettop(L) == 2) { + /* we stay at the lua end */ + ppdoc *d = ppdoc_mem(memstream, streamsize); + if (d == NULL) { + normal_warning("pdfe lib","no valid pdf mem stream"); + } else { + pdfe_document *p = (pdfe_document *) lua_newuserdata(L, sizeof(pdfe_document)); + luaL_getmetatable(L, PDFE_METATABLE); + lua_setmetatable(L, -2); + p->document = d; + p->open = true; + p->isfile = false; + p->memstream = memstream; + return 1; + } + } else { + /* pseudo file name */ + PdfDocument *pdf_doc; + const char *file_id = luaL_checkstring(L, 3); + if (file_id == NULL) { + luaL_error(L, "<pdfe> stream has an invalid id"); + } + if (strlen(file_id) > STREAM_FILE_ID_LEN ) { + /* a limit to the length of the string */ + luaL_error(L, "<pdfe> stream has a too long id"); + } + pdf_doc = refMemStreamPdfDocument(memstream, streamsize, file_id); + if (pdf_doc != NULL) { + lua_pushstring(L,pdf_doc->file_path); + return 1; + } else { + /* pplib does this: xfree(memstream); */ + } + } + return 0; +} + +/* + + There is no garbage collection needed as the library itself manages the + objects. Normally objects don't take much space. Streams use buffers so (I + assume) that they are not persistent. The only collector is in the parent + object (the document). + +*/ + +static int pdfelib_free(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p != NULL && p->open) { + if (p->document != NULL) { + ppdoc_free(p->document); + p->document = NULL; + } + if (p->memstream != NULL) { + /* pplib does this: xfree(p->memstream); */ + p->memstream = NULL; + } + p->open = false; + } + return 0; +} + +static int pdfelib_close(lua_State * L) +{ + return pdfelib_free(L); +} + +/*tex + + A document is can be uncrypted with: + + \starttyping + status = unencrypt(documentobject,user,owner) + \stoptyping + + Instead of a password \type {nil} can be passed, so there are three possible + useful combinations. + +*/ + +static int pdfelib_unencrypt(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p != NULL) { + size_t u = 0; + size_t o = 0; + const char* user = NULL; + const char* owner = NULL; + int top = lua_gettop(L); + if (top > 1) { + if (lua_type(L,2) == LUA_TSTRING) { + user = lua_tolstring(L, 2, &u); + } else { + /*tex we're not too picky but normally it will be nil or false */ + } + if (top > 2) { + if (lua_type(L,3) == LUA_TSTRING) { + owner = lua_tolstring(L, 3, &o); + } else { + /*tex we're not too picky but normally it will be nil or false */ + } + } + lua_pushinteger(L, (int) ppdoc_crypt_pass(p->document,user,u,owner,o)); + return 1; + } + } + lua_pushinteger(L, (int) PPCRYPT_FAIL); + return 1; +} + +/*tex + + There are a couple of ways to get information about the document: + + \starttyping + n = getsize (documentobject) + major, minor = getversion (documentobject) + status = getstatus (documentobject) + n = getnofobjects (documentobject) + n = getnofpages (documentobject) + bytes, waste = getmemoryusage(documentobject) + \stoptyping + +*/ + +static int pdfelib_getsize(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p == NULL) + return 0; + lua_pushinteger(L,(int) ppdoc_file_size(p->document)); + return 1; +} + + +static int pdfelib_getversion(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p == NULL) { + return 0; + } else { + int minor; + int major = ppdoc_version_number(p->document, &minor); + lua_pushinteger(L,(int) major); + lua_pushinteger(L,(int) minor); + return 2; + } +} + +static int pdfelib_getstatus(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p == NULL) + return 0; + lua_pushinteger(L,(int) ppdoc_crypt_status(p->document)); + return 1; +} + +static int pdfelib_getnofobjects(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p == NULL) + return 0; + lua_pushinteger(L,(int) ppdoc_objects(p->document)); + return 1; +} + +static int pdfelib_getnofpages(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p == NULL) + return 0; + lua_pushinteger(L,(int) ppdoc_page_count(p->document)); + return 1; +} + +static int pdfelib_getmemoryusage(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p != NULL) { + size_t w = 0; + size_t m = ppdoc_memory(p->document,&w); + lua_pushinteger(L,(int) m); + lua_pushinteger(L,(int) w); + return 2; + } + return 0; +} + +/* + A specific page dictionary can be filtered with the next command. So, there + is no need to parse the document page tree (with these \type {kids} arrays). + + \starttyping + dictionaryobject = getpage(documentobject,pagenumber) + \stoptyping + +*/ + +static int pushpage(lua_State * L, ppdoc * d, int page) +{ + if (page <= 0 || page > ppdoc_page_count(d)) { + return 0; + } else { + ppref *pp = ppdoc_page(d,page); + return pushdictionaryonly(L, ppref_obj(pp)->dict); + } +} + +static int pdfelib_getpage(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p == NULL) { + return 0; + } else { + return pushpage(L, p->document, luaL_checkint(L, 2)); + } +} + +static int pushpages(lua_State * L, ppdoc * d) +{ + int i = 0; + ppref *r; + lua_createtable(L,ppdoc_page_count(d),0); + /* pages[1..n] */ + for (r = ppdoc_first_page(d), i = 1; r != NULL; r = ppdoc_next_page(d), ++i) { + pushdictionaryonly(L,ppref_obj(r)->dict); + lua_rawseti(L,-2,i); + } + return 1 ; +} + +static int pdfelib_getpages(lua_State * L) +{ + pdfe_document *p = check_isdocument(L, 1); + if (p == NULL) { + return 0; + } else { + return pushpages(L, p->document); + } +} + +/*tex + + The boundingbox (\type {MediaBox) and similar boxes can be available in a + (page) doctionary but also in a parent object. Therefore a helper is + available that does the (backtracked) lookup. + + \starttyping + { lx, ly, rx, ry } = getbox(dictionaryobject) + \stoptyping + +*/ + +static int pdfelib_getbox(lua_State * L) +{ + if (lua_gettop(L) > 1 && lua_type(L,2) == LUA_TSTRING) { + pdfe_dictionary *p = check_isdictionary(L, 1); + if (p != NULL) { + const char *key = lua_tostring(L,2); + pprect box; + pprect *r; + box.lx = box.rx = box.ly = box.ry = 0; + r = ppdict_get_box(p->dictionary,key,&box); + if (r != NULL) { + lua_createtable(L,4,0); + lua_pushnumber(L,r->lx); + lua_rawseti(L,-2,1); + lua_pushnumber(L,r->ly); + lua_rawseti(L,-2,2); + lua_pushnumber(L,r->rx); + lua_rawseti(L,-2,3); + lua_pushnumber(L,r->ry); + lua_rawseti(L,-2,4); + return 1; + } + } + } + return 0; +} + +/*tex + + This one is needed when you use the detailed getters and run into an + object reference. The regular getters resolve this automatically. + + \starttyping + [dictionary|array|stream]object = getfromreference(referenceobject) + \stoptyping + +*/ + +static int pdfelib_getfromreference(lua_State * L) +{ + pdfe_reference *r = check_isreference(L, 1); + if (r != NULL) { + ppobj *o = ppref_obj(r->reference); + lua_pushinteger(L,o->type); + return 1 + pushvalue(L,o); + } + return 0; +} + +/*tex + + Here are some convenient getters: + + \starttyping + <string> = getstring (array|dict|ref,index|key) + <integer> = getinteger (array|dict|ref,index|key) + <number> = getnumber (array|dict|ref,index|key) + <boolan> = getboolean (array|dict|ref,index|key) + <string> = getname (array|dict|ref,index|key) + <dictionary> = getdictionary(array|dict|ref,index|key) + <array> = getarray (array|dict|ref,index|key) + <stream>, <dict> = getstream (array|dict|ref,index|key) + \stoptyping + + We report issues when reasonable but are silent when it makes sense. We don't + error on this because we expect the user code to act reasonable on a return + value. + +*/ + +#define pdfelib_get_value_check_1 do { \ + if (p == NULL) { \ + if (t == LUA_TSTRING) { \ + normal_warning("pdfe lib","lua <pdfe dictionary> expected"); \ + } else if (t == LUA_TNUMBER) { \ + normal_warning("pdfe lib","lua <pdfe array> expected"); \ + } else { \ + normal_warning("pdfe lib","invalid arguments"); \ + } \ + return 0; \ + } else if (! lua_getmetatable(L, 1)) { \ + normal_warning("pdfe lib","first argument should be a <pde array> or <pde dictionary>"); \ + } \ +} while (0) + +#define pdfelib_get_value_check_2 \ + normal_warning("pdfe lib","second argument should be integer or string"); + +/*tex + + The direct fetcher returns the result or |NULL| when there is nothing + found. + +*/ + +#define pdfelib_get_value_direct(get_d,get_a) do { \ + int t = lua_type(L,2); \ + void *p = lua_touserdata(L, 1); \ + pdfelib_get_value_check_1; \ + if (t == LUA_TSTRING) { \ + const char *key = lua_tostring(L,-2); \ + lua_get_metatablelua(luatex_pdfe_dictionary); \ + if (lua_rawequal(L, -1, -2)) { \ + value = get_d(((pdfe_dictionary *) p)->dictionary, key); \ + } else { \ + lua_pop(L,1); \ + lua_get_metatablelua(luatex_pdfe_reference); \ + if (lua_rawequal(L, -1, -2)) { \ + ppobj * o = ppref_obj((ppref *) (((pdfe_reference *) p)->reference)); \ + if (o != NULL && o->type == PPDICT) { \ + value = get_d((ppdict *)o->dict, key); \ + } \ + } \ + } \ + } else if (t == LUA_TNUMBER) { \ + size_t index = lua_tointeger(L,-2); \ + lua_get_metatablelua(luatex_pdfe_array); \ + if (lua_rawequal(L, -1, -2)) { \ + value = get_a(((pdfe_array *) p)->array, index); \ + } else { \ + lua_pop(L,1); \ + lua_get_metatablelua(luatex_pdfe_reference); \ + if (lua_rawequal(L, -1, -2)) { \ + ppobj * o = ppref_obj((ppref *) (((pdfe_reference *) p)->reference)); \ + if (o != NULL && o->type == PPARRAY) { \ + value = get_a((pparray *) o->array, index); \ + } \ + } \ + } \ + } else { \ + pdfelib_get_value_check_2; \ + } \ +} while (0) + +/*tex + + The indirect fetcher passes a pointer to the target variable and returns + success state. + +*/ + +#define pdfelib_get_value_indirect(get_d,get_a) do { \ + int t = lua_type(L,2); \ + void *p = lua_touserdata(L, 1); \ + pdfelib_get_value_check_1; \ + if (t == LUA_TSTRING) { \ + const char *key = lua_tostring(L,-2); \ + lua_get_metatablelua(luatex_pdfe_dictionary); \ + if (lua_rawequal(L, -1, -2)) { \ + okay = get_d(((pdfe_dictionary *) p)->dictionary, key, &value); \ + } else { \ + lua_pop(L,1); \ + lua_get_metatablelua(luatex_pdfe_reference); \ + if (lua_rawequal(L, -1, -2)) { \ + ppobj * o = ppref_obj((ppref *) (((pdfe_reference *) p)->reference)); \ + if (o != NULL && o->type == PPDICT) \ + okay = get_d(o->dict, key, &value); \ + } \ + } \ + } else if (t == LUA_TNUMBER) { \ + size_t index = lua_tointeger(L,-2); \ + lua_get_metatablelua(luatex_pdfe_array); \ + if (lua_rawequal(L, -1, -2)) { \ + okay = get_a(((pdfe_array *) p)->array, index, &value); \ + } else { \ + lua_pop(L,1); \ + lua_get_metatablelua(luatex_pdfe_reference); \ + if (lua_rawequal(L, -1, -2)) { \ + ppobj * o = ppref_obj((ppref *) (((pdfe_reference *) p)->reference)); \ + if (o != NULL && o->type == PPARRAY) \ + okay = get_a(o->array, index, &value); \ + } \ + } \ + } else { \ + pdfelib_get_value_check_2; \ + } \ +} while (0) + +static int pdfelib_getstring(lua_State * L) +{ + if (lua_gettop(L) > 1) { + ppstring value = NULL; + pdfelib_get_value_direct(ppdict_rget_string,pparray_rget_string); + if (value != NULL) { + lua_pushstring(L,(const char *) value); + return 1; + } + } + return 0; +} + +static int pdfelib_getinteger(lua_State * L) +{ + if (lua_gettop(L) > 1) { + ppint value = 0; + int okay = 0; + pdfelib_get_value_indirect(ppdict_rget_int,pparray_rget_int); + if (okay) { + lua_pushinteger(L,(int) value); + return 1; + } + } + return 0; +} + +static int pdfelib_getnumber(lua_State * L) +{ + if (lua_gettop(L) > 1) { + ppnum value = 0; + int okay = 0; + pdfelib_get_value_indirect(ppdict_rget_num,pparray_rget_num); + if (okay) { + lua_pushnumber(L,value); + return 1; + } + } + return 0; +} + +static int pdfelib_getboolean(lua_State * L) +{ + if (lua_gettop(L) > 1) { + int value = 0; + int okay = 0; + pdfelib_get_value_indirect(ppdict_rget_bool,pparray_rget_bool); + if (okay) { + lua_pushboolean(L,value); + return 1; + } + } + return 0; +} + +static int pdfelib_getname(lua_State * L) +{ + if (lua_gettop(L) > 1) { + ppname value = NULL; + pdfelib_get_value_direct(ppdict_rget_name,pparray_rget_name); + if (value != NULL) { + lua_pushstring(L,(const char *) ppname_decoded(value)); + return 1; + } + } + return 0; +} + +static int pdfelib_getdictionary(lua_State * L) +{ + if (lua_gettop(L) > 1) { + ppdict * value = NULL; + pdfelib_get_value_direct(ppdict_rget_dict,pparray_rget_dict); + if (value != NULL) { + return pushdictionaryonly(L,value); + } + } + return 0; +} + +static int pdfelib_getarray(lua_State * L) +{ + if (lua_gettop(L) > 1) { + pparray * value = NULL; + pdfelib_get_value_direct(ppdict_rget_array,pparray_rget_array); + if (value != NULL) { + return pusharrayonly(L,value); + } + } + return 0; +} + +static int pdfelib_getstream(lua_State * L) +{ + if (lua_gettop(L) > 1) { + ppobj * value = NULL; + pdfelib_get_value_direct(ppdict_rget_obj,pparray_rget_obj); + if (value != NULL && value->type == PPSTREAM) { + return pushstreamonly(L,(ppstream *) value->stream); + } + } + return 0; +} + +/*tex + + The generic pushed that does a similar job as the previous getters acts upon + the type. + +*/ + +static int pdfelib_pushvalue(lua_State * L, ppobj *object) +{ + switch (object->type) { + case PPNONE: + case PPNULL: + lua_pushnil(L); + break; + case PPBOOL: + lua_pushboolean(L, object->integer); + break; + case PPINT: + lua_pushinteger(L, object->integer); + break; + case PPNUM: + lua_pushnumber(L, object->number); + break; + case PPNAME: + lua_pushstring(L, (const char *) ppname_decoded(object->name)); + break; + case PPSTRING: + lua_pushlstring(L,(const char *) object->string, ppstring_size((void *)object->string)); + break; + case PPARRAY: + return pusharrayonly(L, object->array); + break; + case PPDICT: + return pushdictionary(L, object->dict); + break; + case PPSTREAM: + return pushstream(L, object->stream); + break; + case PPREF: + pushreference(L, object->ref); + break; + default: + lua_pushnil(L); + break; + } + return 1; +} + +/*tex + + Finally we arrived at the acessors for the userdata objects. The use + previously defined helpers. + +*/ + +static int pdfelib_access(lua_State * L) +{ + if (lua_type(L,2) == LUA_TSTRING) { + pdfe_document *p = (pdfe_document *)lua_touserdata(L, 1); + const char *s = lua_tostring(L,2); + if (lua_key_eq(s,catalog) || lua_key_eq(s,Catalog)) { + return pushdictionaryonly(L,ppdoc_catalog(p->document)); + } else if (lua_key_eq(s,info) || lua_key_eq(s,Info)) { + return pushdictionaryonly(L,ppdoc_info(p->document)); + } else if (lua_key_eq(s,trailer) || lua_key_eq(s,Trailer)) { + return pushdictionaryonly(L,ppdoc_trailer(p->document)); + } else if (lua_key_eq(s,pages) || lua_key_eq(s,Pages)) { + return pushpages(L,p->document); + } + } + return 0; +} + +static int pdfelib_array_access(lua_State * L) +{ + if (lua_type(L,2) == LUA_TNUMBER) { + pdfe_array *p = (pdfe_array *)lua_touserdata(L, 1); + ppint index = lua_tointeger(L,2) - 1; + ppobj *o = pparray_rget_obj(p->array,index); + if (o != NULL) { + return pdfelib_pushvalue(L,o); + } + } + return 0; +} + +static int pdfelib_dictionary_access(lua_State * L) +{ + pdfe_dictionary *p = (pdfe_dictionary *)lua_touserdata(L, 1); + if (lua_type(L,2) == LUA_TSTRING) { + const char *key = lua_tostring(L,2); + ppobj *o = ppdict_rget_obj(p->dictionary,key); + if (o != NULL) { + return pdfelib_pushvalue(L,o); + } + } else if (lua_type(L,2) == LUA_TNUMBER) { + ppint index = lua_tointeger(L,2) - 1; + ppobj *o = ppdict_at(p->dictionary,index); + if (o != NULL) { + return pdfelib_pushvalue(L,o); + } + } + return 0; +} + +static int pdfelib_stream_access(lua_State * L) +{ + pdfe_stream *p = (pdfe_stream *)lua_touserdata(L, 1); + if (lua_type(L,2) == LUA_TSTRING) { + const char *key = lua_tostring(L,2); + ppobj *o = ppdict_rget_obj(p->stream->dict,key); + if (o != NULL) { + return pdfelib_pushvalue(L,o); + } + } else if (lua_type(L,2) == LUA_TNUMBER) { + ppint index = lua_tointeger(L,2) - 1; + ppobj *o = ppdict_at(p->stream->dict,index); + if (o != NULL) { + return pdfelib_pushvalue(L,o); + } + } + return 0; +} + +/*tex + + The length metamethods are defined last. + +*/ + +static int pdfelib_array_size(lua_State * L) +{ + pdfe_array *p = (pdfe_array *)lua_touserdata(L, 1); + lua_pushinteger(L,p->array->size); + return 1; +} + +static int pdfelib_dictionary_size(lua_State * L) +{ + pdfe_dictionary *p = (pdfe_dictionary *)lua_touserdata(L, 1); + lua_pushinteger(L,p->dictionary->size); + return 1; +} + +static int pdfelib_stream_size(lua_State * L) +{ + pdfe_stream *p = (pdfe_stream *)lua_touserdata(L, 1); + lua_pushinteger(L,p->stream->dict->size); + return 1; +} + +/*tex + + We now initialize the main interface. We might aa few more + informational helpers but this is it. + +*/ + +static const struct luaL_Reg pdfelib[] = { + /* management */ + { "type", pdfelib_type }, + { "open", pdfelib_open }, + { "new", pdfelib_new }, + { "close", pdfelib_close }, + { "unencrypt", pdfelib_unencrypt }, + /* statistics */ + { "getversion", pdfelib_getversion }, + { "getstatus", pdfelib_getstatus }, + { "getsize", pdfelib_getsize }, + { "getnofobjects", pdfelib_getnofobjects }, + { "getnofpages", pdfelib_getnofpages }, + { "getmemoryusage", pdfelib_getmemoryusage }, + /* getters */ + { "getcatalog", pdfelib_getcatalog }, + { "gettrailer", pdfelib_gettrailer }, + { "getinfo", pdfelib_getinfo }, + { "getpage", pdfelib_getpage }, + { "getpages", pdfelib_getpages }, + { "getbox", pdfelib_getbox }, + { "getfromreference", pdfelib_getfromreference }, + { "getfromdictionary", pdfelib_getfromdictionary }, + { "getfromarray", pdfelib_getfromarray }, + { "getfromstream", pdfelib_getfromstream }, + /* collectors */ + { "dictionarytotable", pdfelib_dictionarytotable }, + { "arraytotable", pdfelib_arraytotable }, + { "pagestotable", pdfelib_pagestotable }, + /* more getters */ + { "getstring", pdfelib_getstring }, + { "getinteger", pdfelib_getinteger }, + { "getnumber", pdfelib_getnumber }, + { "getboolean", pdfelib_getboolean }, + { "getname", pdfelib_getname }, + { "getdictionary", pdfelib_getdictionary }, + { "getarray", pdfelib_getarray }, + { "getstream", pdfelib_getstream }, + /* streams */ + { "readwholestream", pdfelib_readwholestream }, + /* not really needed */ + { "openstream", pdfelib_openstream }, + { "readfromstream", pdfelib_readfromstream }, + { "closestream", pdfelib_closestream }, + /* done */ + { NULL, NULL} +}; + +/*tex + + The user data metatables are defined as follows. Watch how only the + document needs a garbage collector. + +*/ + +static const struct luaL_Reg pdfelib_m[] = { + { "__tostring", pdfelib_tostring_document }, + { "__gc", pdfelib_free }, + { "__index", pdfelib_access }, + { NULL, NULL} +}; + +static const struct luaL_Reg pdfelib_m_dictionary[] = { + { "__tostring", pdfelib_tostring_dictionary }, + { "__index", pdfelib_dictionary_access }, + { "__len", pdfelib_dictionary_size }, + { NULL, NULL} +}; + +static const struct luaL_Reg pdfelib_m_array[] = { + { "__tostring", pdfelib_tostring_array }, + { "__index", pdfelib_array_access }, + { "__len", pdfelib_array_size }, + { NULL, NULL} +}; + +static const struct luaL_Reg pdfelib_m_stream[] = { + { "__tostring", pdfelib_tostring_stream }, + { "__index", pdfelib_stream_access }, + { "__len", pdfelib_stream_size }, + { "__call", pdfelib_readwholestream }, + { NULL, NULL} +}; + +static const struct luaL_Reg pdfelib_m_reference[] = { + { "__tostring", pdfelib_tostring_reference }, + { NULL, NULL} +}; + +/*tex + + Finally we hav earrived at the main initialiser that will be called as part + of \LUATEX's initializer. + +*/ + +/*tex + + Here we hook in the error handler. + +*/ + +static void pdfelib_message(const char *message, void *alien) +{ + normal_warning("pdfe",message); +} + +int luaopen_pdfe(lua_State * L) +{ + /*tex First the four userdata object get their metatables defined. */ + + luaL_newmetatable(L, PDFE_METATABLE_DICTIONARY); + luaL_openlib(L, NULL, pdfelib_m_dictionary, 0); + + luaL_newmetatable(L, PDFE_METATABLE_ARRAY); + luaL_openlib(L, NULL, pdfelib_m_array, 0); + + luaL_newmetatable(L, PDFE_METATABLE_STREAM); + luaL_openlib(L, NULL, pdfelib_m_stream, 0); + + luaL_newmetatable(L, PDFE_METATABLE_REFERENCE); + luaL_openlib(L, NULL, pdfelib_m_reference, 0); + + /*tex Then comes the main (document) metatable: */ + + luaL_newmetatable(L, PDFE_METATABLE); + luaL_openlib(L, NULL, pdfelib_m, 0); + + /*tex Last the library opens up itself to the world. */ + + luaL_openlib(L, "pdfe", pdfelib, 0); + + pplog_callback(pdfelib_message, stderr); + + return 1; +} diff --git a/Build/source/texk/web2c/luatexdir/lua/lpdfscannerlib.c b/Build/source/texk/web2c/luatexdir/lua/lpdfscannerlib.c new file mode 100644 index 00000000000..6c3bc8876ee --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lpdfscannerlib.c @@ -0,0 +1,1110 @@ +/* lpdfscannerlib.c + + Copyright 2013 Taco Hoekwater <taco@luatex.org> + + This file is part of LuaTeX. + + LuaTeX is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your + option) any later version. + + LuaTeX is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + License for more details. + + You should have received a copy of the GNU General Public License along + with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +*/ + +/*tex + + The scanner can read from a string or stream. Streams can be given directly as + |ppstream| object or as a |pparray| of streams. Here is an example of usage: + + \starttyping + local operatortable = { } + + operatortable.Do = function(scanner,info) + local resources = info.resources + if resources then + local val = scanner:pop() + local name = val[2] + local xobject = resources.XObject + print(info.space .. "Uses XObject " .. name) + local resources = xobject.Resources + if resources then + local newinfo = { + space = info.space .. " ", + resources = resources, + } + pdfscanner.scan(entry, operatortable, newinfo) + end + end + end + + local function Analyze(filename) + local doc = pdfe.open(filename) + if doc then + local pages = doc.Pages + for i=1,#pages do + local page = pages[i] + local info = { + space = " " , + resources = page.Resources, + } + print("Page " .. i) + pdfscanner.scan(page.Contents,operatortable,info) + pdfscanner.scan(page.Contents(),operatortable,info) + end + end + end + + Analyze("foo.pdf") + \stoptyping + +*/ + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <assert.h> +#include <math.h> + +#include <lua.h> +#include <lauxlib.h> +#include <lualib.h> + +#include "luapplib/pplib.h" + +#include <lua/luatex-api.h> + +#define SCANNER "pdfscanner" + +#define MAXOPERANDS 1000 + +typedef enum { + pdf_integer = 1, + pdf_real, + pdf_boolean, + pdf_name, + pdf_operator, + pdf_string, + pdf_startarray, + pdf_stoparray, + pdf_startdict, + pdf_stopdict, +} pdf_token_type; + +typedef struct Token { + pdf_token_type type; + double value; + char *string; +} Token; + +typedef struct ObjectList { + struct ObjectList *next; + ppstream *stream; +} ObjectList; + +typedef struct scannerdata { + int _ininlineimage; + int _nextoperand; + Token **_operandstack; + ppstream *_stream; + ObjectList *_streams; + const char *buffer; + size_t position; + size_t size; + int uses_stream; +} scannerdata; + +#define PDFE_METATABLE_ARRAY "luatex.pdfe.array" +#define PDFE_METATABLE_STREAM "luatex.pdfe.stream" + +typedef struct { + void *d; + /*tex reference to |PdfDocument|, or |NULL| */ + void *pd; + /*tex counter to detect |PDFDoc| change */ + unsigned long pc; +} udstruct; + +static void clear_operand_stack(scannerdata * self, int from); +static Token *_parseToken(scannerdata * self, int c); +static void push_token(lua_State * L, scannerdata * self); + +static void *priv_xmalloc(size_t size) +{ + void *new_mem = (void *) malloc(size); + if (new_mem == NULL) { + luaL_error(Luas, "no room for <pdfscanned> stream"); + } + return new_mem; +} + +static void *priv_xrealloc(void *old_ptr, size_t size) +{ + void *new_mem = (void *) realloc(old_ptr, size); + if (new_mem == NULL) { + luaL_error(Luas, "no room for <pdfscanned> stream"); + } + return new_mem; +} + +#define xreallocarray(ptr,type,size) ((type*)priv_xrealloc(ptr,(size+1)*sizeof(type))) + +#define INITBUFSIZE 64 + +#define define_buffer(a) \ + char *a = (char *)priv_xmalloc (INITBUFSIZE); \ + int a##_size = INITBUFSIZE; \ + int a##index = 0; \ + memset (a,0,INITBUFSIZE) + +#define check_overflow(a, wsize) do { \ + if (wsize >= a##_size) { \ + int nsize = a##_size + a##_size / 4; \ + a = (char *) xreallocarray(a, char, (unsigned) nsize); \ + memset (a+a##_size, 0, a##_size / 4); \ + a##_size = nsize; \ + } \ +} while (0) + + +static scannerdata *scanner_push(lua_State * L) +{ + scannerdata *a = (scannerdata *) lua_newuserdata(L, sizeof(scannerdata)); + luaL_getmetatable(L, SCANNER); + lua_setmetatable(L, -2); + return a; +} + +static scannerdata *scanner_check(lua_State * L, int index) +{ + scannerdata *bar; + luaL_checktype(L, index, LUA_TUSERDATA); + bar = (scannerdata *) luaL_checkudata(L, index, SCANNER); + if (bar == NULL) + luaL_argerror(L, index, SCANNER " expected"); + return bar; +} + +static void free_token(Token * token) +{ + if (token->string) { + free(token->string); + } + free(token); +} + +static void clear_operand_stack(scannerdata * self, int from) +{ + int i = self->_nextoperand - 1; + while (i >= from) { + if (self->_operandstack[i]) { + free_token(self->_operandstack[i]); + self->_operandstack[i] = NULL; + } + i--; + } + self->_nextoperand = from; +} + +static void push_operand(scannerdata * self, Token * token) +{ + if (self->_nextoperand + 1 > MAXOPERANDS) { + fprintf(stderr, "out of operand stack space"); + exit(1); + } + self->_operandstack[self->_nextoperand++] = token; +} + +static Token *new_operand(pdf_token_type c) +{ + Token *token = (Token *) priv_xmalloc(sizeof(Token)); + memset(token, 0, sizeof(Token)); + token->type = c; + return token; +} + +static void _nextStream(scannerdata * self) +{ + ObjectList *rover = NULL; + if (self->uses_stream && self->buffer != NULL) { + if (self->uses_stream) { + ppstream_done(self->_stream); + } else { + free(self->_stream); + } + } + rover = self->_streams; + self->_stream = rover->stream; + if (self->uses_stream) { + self->buffer = (const char *) ppstream_all(self->_stream, &self->size, 1); + } + self->position = 0; + self->_streams = rover->next; + free(rover); +} + +static int streamGetChar(scannerdata * self) +{ + int i = EOF; + if (self->position < self->size) { + const char c = self->buffer[self->position]; + ++self->position; + i = (int) c; + } + if (i < 0 && self->_streams) { + _nextStream(self); + i = streamGetChar(self); + } + return i; +} + +static int streamLookChar(scannerdata * self) +{ + int i = EOF; + if (self->position < self->size) { + const char c = self->buffer[self->position]; + /*not |++self->position;| */ + i = (int) c; + } + if (i < 0 && self->_streams) { + _nextStream(self); + i = streamGetChar(self); + } + return i; +} + +static void streamReset(scannerdata * self) +{ + if (self->uses_stream) { + self->buffer = (const char *) ppstream_all(self->_stream, &self->size, 1); + } + self->position = 0; +} + +static void streamClose(scannerdata * self) +{ + if (self->uses_stream) { + ppstream_done(self->_stream); + } else { + free(self->_stream); + } + self->buffer = NULL; + self->_stream = NULL; +} + +/*tex end of stream interface */ + +static Token *_parseSpace(scannerdata * self) +{ + return _parseToken(self, streamGetChar(self)); +} + +static Token *_parseString(scannerdata * self, int c) +{ + int level; + Token *token = NULL; + define_buffer(found); + level = 1; + while (1) { + c = streamGetChar(self); + if (c == '(') { + level = level + 1; + } else if (c == ')') { + level = level - 1; + if (level < 1) + break; + } else if (c == '\\') { + int next = streamGetChar(self); + if (next == '(' || next == ')' || next == '\\') { + c = next; + } else if (next == '\n' || next == '\r') { + c = '\0'; + } else if (next == 'n') { + c = '\n'; + } else if (next == 'r') { + c = '\r'; + } else if (next == 't') { + c = '\t'; + } else if (next == 'b') { + c = '\b'; + } else if (next == 'f') { + c = '\f'; + } else if (next >= '0' && next <= '7') { + int next2; + next = next - '0'; + next2 = streamLookChar(self); + if (next2 >= '0' && next2 <= '7') { + int next3; + next2 = streamGetChar(self); + next2 = next2 - '0'; + next3 = streamLookChar(self); + if (next3 >= '0' && next3 <= '7') { + next3 = streamGetChar(self); + next3 = next3 - '0'; + c = (next * 64 + next2 * 8 + next3); + } else { + c = (next * 8 + next2); + } + } else { + c = next; + } + } else { + c = next; + } + } + check_overflow(found, foundindex); + if (c >= 0) { + found[foundindex++] = c; + } + } + token = new_operand(pdf_string); + token->value = foundindex; + token->string = found; + return token; +} + +static Token *_parseNumber(scannerdata * self, int c) +{ + double value = 0; + pdf_token_type type = pdf_integer; + int isfraction = 0; + int isnegative = 0; + int i = 0; + Token *token = NULL; + if (c == '-') { + isnegative = 1; + c = streamGetChar(self); + } + if (c == '.') { + type = pdf_real; + isfraction = 1; + } else { + value = c - '0'; + } + c = streamLookChar(self); + if ((c >= '0' && c <= '9') || c == '.') { + c = streamGetChar(self); + while (1) { + if (c == '.') { + type = pdf_real; + isfraction = 1; + } else { + i = c - '0'; + if (isfraction > 0) { + value = value + (i / (pow(10.0, isfraction))); + isfraction = isfraction + 1; + } else { + value = (value * 10) + i; + } + } + c = streamLookChar(self); + if (!((c >= '0' && c <= '9') || c == '.')) + break; + c = streamGetChar(self); + } + } + if (isnegative) { + value = -value; + } + token = new_operand(type); + token->value = value; + return token; +} + +static Token *_parseName(scannerdata * self, int c) +{ + Token *token = NULL; + define_buffer(found); + c = streamGetChar(self); + while (1) { + check_overflow(found, foundindex); + found[foundindex++] = c; + c = streamLookChar(self); + if (c == ' ' || c == '\n' || c == '\r' || c == '\t' || + c == '/' || c == '[' || c == '(' || c == '<') + break; + c = streamGetChar(self); + } + token = new_operand(pdf_name); + token->string = found; + token->value = strlen(found); + return token; +} + +#define hexdigit(c) \ + (c>= '0' && c<= '9') ? (c - '0') : ((c>= 'A' && c<= 'F') ? (c - 'A' + 10) : (c - 'a' + 10)) + +static Token *_parseHexstring(scannerdata * self, int c) +{ + int isodd = 1; + int hexval = 0; + Token *token = NULL; + define_buffer(found); + while (c != '>') { + if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f')) { + if (isodd == 1) { + int v = hexdigit(c); + hexval = 16 * v; + } else { + hexval += hexdigit(c); + check_overflow(found, foundindex); + found[foundindex++] = hexval; + } + isodd = (isodd == 1 ? 0 : 1); + } + c = streamGetChar(self); + } + token = new_operand(pdf_string); + token->value = foundindex; + token->string = found; + return token; +} + +#define pdf_isspace(a) (a == '\0' || a == ' ' || a == '\n' || a == '\r' || a == '\t' || a == '\v') + +/*tex this is rather horrible */ + +static Token *_parseInlineImage(scannerdata * self, int c) +{ + Token *token = NULL; + define_buffer(found); + if (c == ' ') { + /*tex first space can be ignored */ + c = streamGetChar(self); + } + check_overflow(found, foundindex); + found[foundindex++] = c; + while (1) { + c = streamLookChar(self); + if (c == 'E' + && (found[foundindex - 1] == '\n' + || found[foundindex - 1] == '\r')) { + c = streamGetChar(self); + check_overflow(found, foundindex); + found[foundindex++] = c; + c = streamLookChar(self); + if (c == 'I') { + c = streamGetChar(self); + check_overflow(found, foundindex); + found[foundindex++] = c; + c = streamLookChar(self); + if (pdf_isspace(c)) { + /*tex |I| */ + found[--foundindex] = '\0'; + /*tex |E| */ + found[--foundindex] = '\0'; + /*tex remove end-of-line before |EI| */ + if (found[foundindex - 1] == '\n') { + found[--foundindex] = '\0'; + } + if (found[foundindex - 1] == '\r') { + found[--foundindex] = '\0'; + } + break; + } else { + c = streamGetChar(self); + check_overflow(found, foundindex); + found[foundindex++] = c; + } + } else { + c = streamGetChar(self); + check_overflow(found, foundindex); + found[foundindex++] = c; + } + } else { + c = streamGetChar(self); + check_overflow(found, foundindex); + found[foundindex++] = c; + } + } + token = new_operand(pdf_string); + token->value = foundindex; + token->string = found; + return token; +} + +static Token *_parseOperator(scannerdata * self, int c) +{ + define_buffer(found); + while (1) { + check_overflow(found, foundindex); + found[foundindex++] = c; + c = streamLookChar(self); + if ((c < 0) || (c == ' ' || c == '\n' || c == '\r' || c == '\t' || + c == '/' || c == '[' || c == '(' || c == '<')) + break; + c = streamGetChar(self); + } + /*tex |print| (found) */ + if (strcmp(found, "ID") == 0) { + self->_ininlineimage = 1; + } + if (strcmp(found, "false") == 0) { + Token *token = new_operand(pdf_boolean); + token->value = 0; + free(found); + return token; + } else if (strcmp(found, "true") == 0) { + Token *token = new_operand(pdf_boolean); + token->value = 1.0; + free(found); + return token; + } else { + Token *token = new_operand(pdf_operator); + token->string = found; + return token; + } +} + +static Token *_parseComment(scannerdata * self, int c) +{ + do { + c = streamGetChar(self); + } while (c != '\n' && c != '\r' && c != -1); + return _parseToken(self, streamGetChar(self)); +} + +static Token *_parseLt(scannerdata * self, int c) +{ + c = streamGetChar(self); + if (c == '<') { + return new_operand(pdf_startdict); + } else { + return _parseHexstring(self, c); + } +} + +static Token *_parseGt(scannerdata * self, int c) +{ + c = streamGetChar(self); + if (c == '>') { + return new_operand(pdf_stopdict); + } else { + fprintf(stderr, "stray > in stream"); + return NULL; + } +} + +static Token *_parseError(int c) +{ + fprintf(stderr, "stray %c [%d] in stream", c, c); + return NULL; +} + +static Token *_parseStartarray(void) +{ + return new_operand(pdf_startarray); +} + +static Token *_parseStoparray(void) +{ + return new_operand(pdf_stoparray); +} + +static Token *_parseToken(scannerdata * self, int c) +{ + if (self->_ininlineimage == 1) { + self->_ininlineimage = 2; + return _parseInlineImage(self, c); + } else if (self->_ininlineimage == 2) { + Token *token = NULL; + self->_ininlineimage = 0; + token = new_operand(pdf_operator); + token->string = strdup("EI"); + return token; + } + if (c < 0) + return NULL; + switch (c) { + case '(': + return _parseString(self, c); + break; + case ')': + return _parseError(c); + break; + case '[': + return _parseStartarray(); + break; + case ']': + return _parseStoparray(); + break; + case '/': + return _parseName(self, c); + break; + case '<': + return _parseLt(self, c); + break; + case '>': + return _parseGt(self, c); + break; + case '%': + return _parseComment(self, c); + break; + case ' ': + case '\r': + case '\n': + case '\t': + return _parseSpace(self); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '-': + case '.': + return _parseNumber(self, c); + break; + default: + if (c <= 127) { + return _parseOperator(self, c); + } else { + return _parseError(c); + } + } +} + +static int scanner_scan(lua_State * L) +{ + Token *token; + scannerdata *self; + if (lua_gettop(L) != 3) { + return 0; + } + luaL_checktype(L, 2, LUA_TTABLE); + luaL_checktype(L, 3, LUA_TTABLE); + self = scanner_push(L); + memset(self, 0, sizeof(scannerdata)); + self->_operandstack = (Token **) priv_xmalloc(MAXOPERANDS * sizeof(Token)); + memset(self->_operandstack, 0, (MAXOPERANDS * sizeof(Token))); + /*tex stack slot 4 = self */ + self->uses_stream = 1; + if (lua_type(L, 1) == LUA_TSTRING) { + /*tex + We could make a temporary copy on the stack (or in the registry) + which saves memory. + */ + char *buf = NULL; + const char *s = lua_tolstring(L, 1, &self->size); + if (s==NULL){ + fprintf(stderr,"fatal: cannot convert the token to string."); + exit(1); + } + buf = priv_xmalloc(self->size+1); + buf[self->size]='\0'; + self->uses_stream = 0; + memcpy(buf,s,self->size); + self->buffer = buf; + } else if (lua_type(L, 1) == LUA_TTABLE) { + udstruct *uin; + void *ud; + int i = 1; + while (1) { + lua_rawgeti(L, 1, i); + if (lua_type(L, -1) == LUA_TUSERDATA) { + ud = luaL_checkudata(L, -1, PDFE_METATABLE_STREAM); + if (ud != NULL) { + ObjectList *rover = NULL; + ObjectList *item = NULL; + uin = (udstruct *) ud; + rover = self->_streams; + item = (ObjectList *) priv_xmalloc(sizeof(ObjectList)); + item->stream = ((ppstream *) uin->d); + item->next = NULL; + if (!rover) { + rover = item; + self->_streams = rover; + } else { + while (rover->next) + rover = rover->next; + rover->next = item; + } + } + } else { + ObjectList *rover = self->_streams; + self->_stream = rover->stream; + self->_streams = rover->next; + free(rover); + lua_pop(L, 1); + break; + } + lua_pop(L, 1); + i++; + } + } else { + udstruct *uin; + void *ud; + luaL_checktype(L, 1, LUA_TUSERDATA); + ud = luaL_checkudata(L, 1, PDFE_METATABLE_STREAM); + if (ud != NULL) { + uin = (udstruct *) ud; + self->_stream = ((ppstream *) uin->d); + } else { + ud = luaL_checkudata(L, 1, PDFE_METATABLE_ARRAY); + if (ud != NULL) { + ObjectList *rover = NULL; + pparray *array = NULL; + int count; + int i; + uin = (udstruct *) ud; + array = (pparray *) uin->d; + count = array->size; + for (i = 0; i < count; i++) { + ppobj *obj = pparray_at(array, i); + if (obj->type == PPSTREAM) { + ObjectList *rover = self->_streams; + ObjectList *item = + (ObjectList *) + priv_xmalloc(sizeof(ObjectList)); + item->stream = obj->stream; + item->next = NULL; + if (!rover) { + rover = item; + self->_streams = rover; + } else { + while (rover->next) + rover = rover->next; + rover->next = item; + } + } + } + rover = self->_streams; + self->_stream = rover->stream; + self->_streams = rover->next; + } + } + } + streamReset(self); + token = _parseToken(self, streamGetChar(self)); + while (token) { + if (token->type == pdf_operator) { + lua_pushstring(L, token->string); + free_token(token); + /*tex fetch operator table */ + lua_rawget(L, 2); + if (lua_isfunction(L, -1)) { + lua_pushvalue(L, 4); + lua_pushvalue(L, 3); + (void) lua_call(L, 2, 0); + } else { + /*tex nil */ + lua_pop(L, 1); + } + clear_operand_stack(self, 0); + } else { + push_operand(self, token); + } + if (self->uses_stream) { + if (!self->_stream) { + break; + } + } else { + if (self->buffer == NULL) { + break; + } + } + token = _parseToken(self, streamGetChar(self)); + } + /*tex wrap up */ + if (self->_stream) { + streamClose(self); + } + clear_operand_stack(self, 0); + free(self->_operandstack); + return 0; +} + +static int scanner_done(lua_State * L) +{ + int c; + scannerdata *self = scanner_check(L, 1); + while ((c = streamGetChar(self)) >= 0); + return 0; +} + +/*tex here are the stack popping functions, and their helpers */ + +static void operandstack_backup(scannerdata * self) +{ + int i = self->_nextoperand - 1; + int balance = 0; + int backupstart = 0; + int backupstop = self->_operandstack[i]->type; + if (backupstop == pdf_stopdict) { + backupstart = pdf_startdict; + } else if (backupstop == pdf_stoparray) { + backupstart = pdf_startarray; + } else { + return; + } + for (; i >= 0; i--) { + if (self->_operandstack[i]->type == backupstop) { + balance++; + } else if (self->_operandstack[i]->type == backupstart) { + balance--; + } + if (balance == 0) { + break; + } + } + self->_nextoperand = i + 1; +} + +static void push_array(lua_State * L, scannerdata * self) +{ + /*tex nesting tracking */ + int balance = 1; + /*tex \LUA\ array index */ + int index = 1; + Token *token = self->_operandstack[self->_nextoperand++]; + lua_newtable(L); + while (token) { + if (token->type == pdf_stoparray) + balance--; + if (token->type == pdf_startarray) + balance++; + if (!balance) { + break; + } else { + push_token(L, self); + lua_rawseti(L, -2, index++); + } + token = self->_operandstack[self->_nextoperand++]; + } +} + + +static void push_dict(lua_State * L, scannerdata * self) +{ + /*tex nesting tracking */ + int balance = 1; + /*tex toggle between \LUA\ value and \LUA\ key */ + int needskey = 1; + Token *token = self->_operandstack[self->_nextoperand++]; + lua_newtable(L); + while (token) { + if (token->type == pdf_stopdict) + balance--; + if (token->type == pdf_startdict) + balance++; + if (!balance) { + break; + } else if (needskey) { + lua_pushlstring(L, token->string, token->value); + needskey = 0; + } else { + push_token(L, self); + needskey = 1; + lua_rawset(L, -3); + } + token = self->_operandstack[self->_nextoperand++]; + } +} + +const char *typenames[pdf_stopdict + 1] = { + "unknown", "integer", "real", "boolean", "name", "operator", + "string", "array", "array", "dict", "dict" +}; + +static void push_token(lua_State * L, scannerdata * self) +{ + Token *token = self->_operandstack[self->_nextoperand - 1]; + lua_createtable(L, 2, 0); + lua_pushstring(L, typenames[token->type]); + lua_rawseti(L, -2, 1); + if (token->type == pdf_string || token->type == pdf_name) { + lua_pushlstring(L, token->string, token->value); + } else if (token->type == pdf_real || token->type == pdf_integer) { + /*tex This is an integer or float. */ + lua_pushnumber(L, token->value); + } else if (token->type == pdf_boolean) { + lua_pushboolean(L, (int) token->value); + } else if (token->type == pdf_startarray) { + push_array(L, self); + } else if (token->type == pdf_startdict) { + push_dict(L, self); + } else { + lua_pushnil(L); + } + lua_rawseti(L, -2, 2); +} + +static int scanner_popsingular(lua_State * L, int token_type) +{ + Token *token = NULL; + /*tex this keeps track of how much of the operand stack needs deleting: */ + int clear = 0; + scannerdata *self = scanner_check(L, 1); + if (self->_nextoperand == 0) { + return 0; + } + clear = self->_nextoperand - 1; + token = self->_operandstack[self->_nextoperand - 1]; + if (token == NULL || (token->type != token_type)) { + return 0; + } + /*tex + The simple cases can be written out directly, but dicts and + arrays are better done via the recursive function. + */ + if (token_type == pdf_stoparray || token_type == pdf_stopdict) { + operandstack_backup(self); + clear = self->_nextoperand - 1; + push_token(L, self); + lua_rawgeti(L, -1, 2); + } else if (token_type == pdf_real || token_type == pdf_integer) { + /*tex the number can be an integer or float */ + lua_pushnumber(L, token->value); + } else if (token_type == pdf_boolean) { + lua_pushboolean(L, (int) token->value); + } else if (token_type == pdf_name || token_type == pdf_string) { + lua_pushlstring(L, token->string, token->value); + } else { + return 0; + } + clear_operand_stack(self, clear); + return 1; +} + +static int scanner_popanything(lua_State * L) +{ + Token *token = NULL; + /*tex how much of the operand stack needs deleting: */ + int clear = 0; + int token_type; + scannerdata *self = scanner_check(L, 1); + if (self->_nextoperand == 0) { + return 0; + } + clear = self->_nextoperand - 1; + token = self->_operandstack[self->_nextoperand - 1]; + if (token == NULL) { + return 0; + } + token_type = token->type; + /*tex + The simple cases can be written out directly, but dicts and + arrays are better done via the recursive function. + */ + if (token_type == pdf_stoparray || token_type == pdf_stopdict) { + operandstack_backup(self); + clear = self->_nextoperand - 1; + push_token(L, self); + } else { + push_token(L, self); + } + clear_operand_stack(self, clear); + return 1; +} + +static int scanner_popnumber(lua_State * L) +{ + if (scanner_popsingular(L, pdf_real)) + return 1; + if (scanner_popsingular(L, pdf_integer)) + return 1; + lua_pushnil(L); + return 1; +} + +static int scanner_popboolean(lua_State * L) +{ + if (scanner_popsingular(L, pdf_boolean)) + return 1; + lua_pushnil(L); + return 1; +} + +static int scanner_popstring(lua_State * L) +{ + if (scanner_popsingular(L, pdf_string)) + return 1; + lua_pushnil(L); + return 1; +} + +static int scanner_popname(lua_State * L) +{ + if (scanner_popsingular(L, pdf_name)) + return 1; + lua_pushnil(L); + return 1; +} + +static int scanner_poparray(lua_State * L) +{ + if (scanner_popsingular(L, pdf_stoparray)) + return 1; + lua_pushnil(L); + return 1; +} + +static int scanner_popdictionary(lua_State * L) +{ + if (scanner_popsingular(L, pdf_stopdict)) + return 1; + lua_pushnil(L); + return 1; +} + +static int scanner_popany(lua_State * L) +{ + if (scanner_popanything(L)) + return 1; + lua_pushnil(L); + return 1; +} + +static const luaL_Reg scannerlib_meta[] = { + {0, 0} +}; + +static const struct luaL_Reg scannerlib_m[] = { + { "done", scanner_done }, + { "pop", scanner_popany }, + { "popnumber", scanner_popnumber }, + { "popname", scanner_popname }, + { "popstring", scanner_popstring }, + { "poparray", scanner_poparray }, + { "popdictionary", scanner_popdictionary }, + { "popboolean", scanner_popboolean }, + /*tex For old times sake: */ + { "popNumber", scanner_popnumber }, + { "popName", scanner_popname }, + { "popString", scanner_popstring }, + { "popArray", scanner_poparray }, + { "popDict", scanner_popdictionary }, + { "popBool", scanner_popboolean }, + /*tex Sentinel: */ + { NULL, NULL } +}; + +static const luaL_Reg scannerlib[] = { + { "scan", scanner_scan }, + /*tex Sentinel: */ + { NULL, NULL } +}; + +LUALIB_API int luaopen_pdfscanner(lua_State * L) +{ + luaL_newmetatable(L, SCANNER); + luaL_openlib(L, 0, scannerlib_meta, 0); + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + luaL_openlib(L, NULL, scannerlib_m, 0); + luaL_openlib(L, "pdfscanner", scannerlib, 0); + return 1; +} diff --git a/Build/source/texk/web2c/luatexdir/lua/luainit.w b/Build/source/texk/web2c/luatexdir/lua/luainit.c index dec76b0216b..60c654aa0a0 100644 --- a/Build/source/texk/web2c/luatexdir/lua/luainit.w +++ b/Build/source/texk/web2c/luatexdir/lua/luainit.c @@ -1,23 +1,25 @@ -% luainit.w -% -% Copyright 2006-2018 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 +/* + +luainit.w + +Copyright 2006-2018 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/>. + +*/ #include "ptexlib.h" @@ -29,27 +31,23 @@ extern int load_luatex_core_lua (lua_State * L); -/* internalized strings: see luatex-api.h */ -set_make_keys; +/*tex internalized strings: see luatex-api.h */ -@ -This file is getting a bit messy, but it is not simple to fix unilaterally. +set_make_keys; -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. +/*tex -In fact, it sets three C variables: +This file is getting a bit messy, but it is not simple to fix unilaterally. In +fact, it sets three C variables: - |kpse_invocation_name| |kpse_invocation_short_name| |kpse->program_name| + |kpse_invocation_name| |kpse_invocation_short_name| |kpse->program_name| and five environment variables: - SELFAUTOLOC SELFAUTODIR SELFAUTOPARENT SELFAUTOGRANDPARENT progname + |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", @@ -109,9 +107,13 @@ const_string LUATEX_IHELP[] = { 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 +/*tex + +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. + +*/ + const char *lc_ctype; const char *lc_collate; const char *lc_numeric; @@ -126,26 +128,28 @@ const char *lc_numeric; " --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 +/*tex + +The return value will be the directory of the executable, e.g.: \.{c:/TeX/bin} + +*/ + static char *ex_selfdir(char *argv0) { #if defined(WIN32) #if defined(__MINGW32__) char path[PATH_MAX], *fp; - - /* SearchPath() always gives back an absolute directory */ + /*tex 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 */ + /*tex 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 */ + /*tex 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) { @@ -158,7 +162,6 @@ static char *ex_selfdir(char *argv0) #endif } -@ @c static void prepare_cmdline(lua_State * L, char **av, int ac, int zero_offset) { int i; @@ -178,11 +181,8 @@ static void prepare_cmdline(lua_State * L, char **av, int ac, int zero_offset) return; } - -@ @c int kpse_init = -1; -@ @c string input_name = NULL; static string user_progname = NULL; @@ -201,22 +201,20 @@ int safer_option = 0; int nosocket_option = 0; int utc_option = 0; -@ Reading the options. +/*tex -@ 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|. +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. */ -/* +#define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a) + +/*tex Nota Bene: we still intercept some options that other engines handle so that existing scripted usage will not fail. + + SunOS cc can't initialize automatic structs, so make this static. */ static struct option long_options[] = { @@ -253,9 +251,7 @@ static struct option long_options[] = { {"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. */ - + /*tex Shorter option names for the above. */ {"file-line-error", 0, &filelineerrorstylep, 1}, {"no-file-line-error", 0, &filelineerrorstylep, -1}, {"jobname", 1, 0, 0}, @@ -266,18 +262,16 @@ static struct option long_options[] = { {"8bit", 0, 0, 0}, {"mktex", 1, 0, 0}, {"no-mktex", 1, 0, 0}, - - /* Synchronization: just like "interaction" above */ - + /*tex 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 */ + /*tex fetch the stringptr */ + lua_rawgeti(L, LUA_REGISTRYINDEX, name_index); lua_rawget(L, -2); if (lua_type(L, -1) == LUA_TNUMBER) { i = lua_roundnumber(L, -1); @@ -286,11 +280,11 @@ int lua_numeric_field_by_index(lua_State * L, int name_index, int dflt) 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 */ + /*tex fetch the stringptr */ + lua_rawgeti(L, LUA_REGISTRYINDEX, name_index); lua_rawget(L, -2); if (lua_type(L, -1) == LUA_TNUMBER) { i = lua_uroundnumber(L, -1); @@ -299,20 +293,21 @@ unsigned int lua_unsigned_numeric_field_by_index(lua_State * L, int name_index, return i; } -@ @c static int recorderoption = 0; static void parse_options(int ac, char **av) { #ifdef WIN32 -/* save argc and argv */ + /*tex We save |argc| and |argv|. */ int sargc = argc; char **sargv = argv; #endif - int g; /* `getopt' return code. */ + /*tex The `getopt' return code. */ + int g; int option_index; char *firstfile = NULL; - opterr = 0; /* dont whine */ + /*tex Dont whine. */ + opterr = 0; #ifdef LuajitTeX if ((strstr(argv[0], "luajittexlua") != NULL) || (strstr(argv[0], "texluajit") != NULL)) { @@ -326,37 +321,39 @@ static void parse_options(int ac, char **av) for (;;) { g = getopt_long_only(ac, av, "+", long_options, &option_index); - if (g == -1) /* End of arguments, exit the loop. */ + if (g == -1) { + /*tex 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 (g == '?') { + /*tex Unknown option. */ + if (!luainit) + fprintf(stderr,"%s: unrecognized option '%s'\n", argv[0], argv[optind-1]); + continue; + } + /* We have no short option names. */ + assert(g == 0); if (ARGUMENT_IS("luaonly")) { lua_only = 1; lua_offset = optind; luainit = 1; } else if (ARGUMENT_IS("lua")) { - startup_filename = xstrdup(optarg); + 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; - } + 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; @@ -414,7 +411,7 @@ static void parse_options(int ac, char **av) WARNING1("Ignoring unknown argument `%s' to --interaction", optarg); } } else if (ARGUMENT_IS("synctex")) { - /* Synchronize TeXnology: catching the command line option as a long */ + /*tex Synchronize TeXnology: catching the command line option as a long */ synctexoption = (int) strtol(optarg, NULL, 0); } else if (ARGUMENT_IS("recorder")) { recorderoption = 1 ; @@ -445,8 +442,8 @@ static void parse_options(int ac, char **av) "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 Hogsberg (partial)\n" + "metapost : John Hobby, Taco Hoekwater, Luigi Scarso, Hans Hagen and friends\n" + "pplib : Paweł Jackowski\n" "fontforge : George Williams (partial)\n" "luajit : Mike Pall (used in LuajitTeX)\n"); /* *INDENT-ON* */ @@ -454,7 +451,7 @@ static void parse_options(int ac, char **av) uexit(0); } } - /* attempt to find |input_name| / |dump_name| */ + /*tex attempt to find |input_name| and |dump_name| */ if (lua_only) { if (argv[optind]) { startup_filename = xstrdup(argv[optind]); @@ -502,20 +499,23 @@ static void parse_options(int ac, char **av) return; #endif } - if (safer_option) /* --safer implies --nosocket */ + /*tex |--safer| implies |--nosocket| */ + if (safer_option) nosocket_option = 1; - /* Finalize the input filename. */ + /*tex 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) +/*tex + Test for readability. +*/ + +#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; @@ -543,8 +543,6 @@ static char *find_filename(char *name, const char *envkey) return NULL; } -@ @c - static void init_kpse(void) { if (!user_progname) { @@ -576,11 +574,10 @@ static void init_kpse(void) user_progname = dump_name; } } - kpse_set_program_enabled(kpse_fmt_format, MAKE_TEX_FMT_BY_DEFAULT, - kpse_src_compile); - + 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' */ + /*tex set up 'restrictedshell' */ + init_shell_escape(); init_start_time(); program_name_set = 1 ; if (recorderoption) { @@ -588,19 +585,18 @@ static void init_kpse(void) } } -@ @c static void fix_dumpname(void) { int dist; if (dump_name) { - /* adjust array for Pascal and provide extension, if needed */ + /*tex 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. */ + /*tex For |dump_name| to be NULL is a bug. */ if (!ini_version) { fprintf(stdout, "no format given, quitting\n"); exit(1); @@ -608,17 +604,17 @@ static void fix_dumpname(void) } } -@ lua require patch - -@ Auxiliary function for kpse search +/*tex + 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) + kpse_file_format_type format, const char *errname) { const char *filename; const char *altname; - altname = luaL_gsub(L, name, ".", "/"); /* Lua convention */ + /*tex Lua convention */ + altname = luaL_gsub(L, name, ".", "/"); filename = kpse_find_file(altname, format, false); if (filename == NULL) { filename = kpse_find_file(name, format, false); @@ -629,16 +625,17 @@ static const char *luatex_kpse_find_aux(lua_State *L, const char *name, return filename; } -@ The lua search function. +/*tex + + Here comes 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. -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 . -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) @@ -653,16 +650,18 @@ static int luatex_kpse_lua_find(lua_State * L) 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 (filename == NULL) { + /*tex library not found in this path */ + return 1; + } 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)); + lua_tostring(L, 1), filename, lua_tostring(L, -1)); } - return 1; /* library loaded successfully */ + /*tex library loaded successfully */ + return 1; } -@ @c static int clua_loader_function = 0; extern int searcher_C_luatex (lua_State *L, const char *name, const char *filename); @@ -671,8 +670,9 @@ static int luatex_kpse_clua_find(lua_State * L) const char *filename; const char *name; if (safer_option) { + /*tex library not found in this path */ lua_pushliteral(L, "\n\t[C searcher disabled in safer mode]"); - return 1; /* library not found in this path */ + return 1; } name = luaL_checkstring(L, 1); if (program_name_set == 0) { @@ -687,12 +687,16 @@ static int luatex_kpse_clua_find(lua_State * L) 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 */ + if (filename == NULL) { + /*tex library not found in this path */ + return 1; + } extensionless = strdup(filename); - if (!extensionless) - return 1; /* allocation failure */ - /* Fix Issue 850: replace '.' with LUA_DIRSEP */ + if (!extensionless) { + /*tex allocation failure */ + return 1; + } + /*tex Replace '.' with |LUA_DIRSEP| */ temp_name = strdup(name); for(j=0; ; j++){ if ((unsigned char)temp_name[j]=='\0') { @@ -703,33 +707,44 @@ static int luatex_kpse_clua_find(lua_State * L) } } p = strstr(extensionless, temp_name); - if (!p) return 1; /* this would be exceedingly weird */ + if (!p) { + /*tex this would be exceedingly weird */ + return 1; + } *p = '\0'; prefix = strdup(extensionless); - if (!prefix) return 1; /* allocation failure */ + if (!prefix) { + /*tex allocation failure */ + return 1; + } postfix = strdup(p+strlen(name)); - if (!postfix) return 1; /* allocation failure */ + if (!postfix) { + /*tex allocation failure */ + return 1; + } 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 */ + /*tex 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 = "?" */ + /*tex set package.path = "?" */ lua_pushstring(L,total); lua_setfield(L,-2,"cpath"); - lua_pop(L,1); /* pop "package" */ - /* run function */ + /*tex pop ``package'' */ + lua_pop(L,1); + /*tex run function */ lua_rawgeti(L, LUA_REGISTRYINDEX, clua_loader_function); lua_pushstring(L, name); lua_call(L, 1, 1); - /* restore package.path */ + /*tex restore package.path */ lua_getglobal(L,"package"); lua_pushstring(L,path_saved); lua_setfield(L,-2,"cpath"); - lua_pop(L,1); /* pop "package" */ + /*tex pop ``package'' */ + lua_pop(L,1); free(extensionless); free(total); free(temp_name); @@ -737,12 +752,13 @@ static int luatex_kpse_clua_find(lua_State * L) } } -@ Setting up the new search functions. +/*tex + + Setting up the new search functions. This replaces package.searchers[2] and + package.searchers[3] with the functions defined above. -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"); @@ -751,46 +767,45 @@ static void setup_lua_path(lua_State * L) #else lua_getfield(L, -1, "searchers"); #endif - lua_rawgeti(L, -1, 2); /* package.searchers[2] */ + /*tex package.searchers[2] */ + lua_rawgeti(L, -1, 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] */ + /*tex replace the normal lua loader */ + lua_rawseti(L, -2, 2); + /*tex package.searchers[3] */ + lua_rawgeti(L, -1, 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 */ + /*tex replace the normal lua lib loader */ + lua_rawseti(L, -2, 3); + /*tex pop the array and table */ + lua_pop(L, 2); } -@ helper variables for the safe keeping of table ids +/*tex + + 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 l_dir_text_index_normal [DIR_TEXT_SIZE]; +int l_dir_text_index_cancel [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 lua_show_valid_list(lua_State *L, const char **list, int offset, int max) { int i; lua_newtable(L); for (i = 0; i < max; i++) { - lua_pushinteger(L,i+1); + lua_pushinteger(L,i+offset); lua_pushstring(L, list[i]); lua_settable(L, -3); } @@ -812,28 +827,31 @@ int lua_show_valid_keys(lua_State *L, int *list, int max) #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" +/* Why do we add script stuff to this weird incomplete. Let's go more minimal. */ + +/* + #define EXE_SUFFIXES ".com;.exe;.bat;.cmd;.vbs;.vbe;.js;.jse;.wsf;.wsh;.ws;.tcl;.py;.pyw" +*/ + +#define EXE_SUFFIXES ".com;.exe;.bat;.cmd" -@ @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 */ + /*tex strlwr() exists also in MingW */ + if (v) v = (char *) strlwr(xstrdup(v)); else v = xstrdup(EXE_SUFFIXES); # endif - q = v; n = 0; - while ((r = strchr(q, ';')) != NULL) { n++; r++; @@ -862,12 +880,10 @@ static void mk_suffixlist(void) } #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; @@ -878,7 +894,7 @@ void lua_initialize(int ac, char **av) char *old_locale = NULL; char *env_locale = NULL; char *tmp = NULL; - /* Save to pass along to topenin. */ + /*tex Save to pass along to topenin. */ const char *fmt = "This is " MyName ", Version %s" WEB2CVERSION; argc = ac; argv = av; @@ -887,8 +903,7 @@ void lua_initialize(int ac, char **av) sprintf(banner, fmt, luatex_version_string); luatex_banner = banner; kpse_invocation_name = kpse_program_basename(argv[0]); - - /* be 'luac' */ + /*tex be `luac' */ if (argc >1) { #ifdef LuajitTeX if (FILESTRCASEEQ(kpse_invocation_name, "texluajitc")) @@ -911,106 +926,104 @@ void lua_initialize(int ac, char **av) #if defined(WIN32) || defined(__MINGW32__) || defined(__CYGWIN__) mk_suffixlist(); #endif - - /* Must be initialized before options are parsed. */ + /*tex 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. */ + /*tex + In the next option 0 means ``disable Synchronize TeXnology''. The + |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 */ + /*tex parse commandline */ parse_options(ac, av); if (lua_only) { - /* Shell has no restrictions. */ + /*tex 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. */ + /*tex + 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 = xstrdup(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. */ + /*tex + If |setlocale| fails here, then the state could be compromised, and + we exit. + */ env_locale = setlocale (LC_ALL, ""); - if (!env_locale && !lua_only) { - fprintf(stderr,"Unable to read environment locale: exit now.\n"); - exit(1); - } + if (!env_locale && !lua_only) { + fprintf(stderr,"Unable to read environment locale: exit now.\n"); + exit(1); + } tmp = setlocale (LC_CTYPE, NULL); - if (tmp) { - lc_ctype = xstrdup(tmp); + if (tmp) { + lc_ctype = xstrdup(tmp); } - tmp = setlocale (LC_COLLATE, NULL); - if (tmp){ - lc_collate = xstrdup(tmp); + tmp = setlocale (LC_COLLATE, NULL); + if (tmp) { + lc_collate = xstrdup(tmp); } - tmp = setlocale (LC_NUMERIC, NULL); - if (tmp){ - lc_numeric = xstrdup(tmp); + tmp = setlocale (LC_NUMERIC, NULL); + if (tmp) { + lc_numeric = xstrdup(tmp); + } + /*tex + Return 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 %s: exit now.\n",old_locale); + exit(1); } - /* 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 %s: exit now.\n",old_locale); - exit(1); - } xfree(old_locale); } else { fprintf(stderr,"Unable to store environment locale.\n"); } - - /* make sure that the locale is 'sane' (for lua) */ + /*tex 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 */ + /*tex this is sometimes needed */ putenv(engine_luatex); - luainterpreter(); - - /* init internalized strings */ + /*tex init internalized strings */ set_init_keys; - lua_pushstring(Luas,"lua.functions"); lua_newtable(Luas); lua_settable(Luas,LUA_REGISTRYINDEX); - - /* here start the key definitions */ + /*tex 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; - + l_set_node_data(); + l_set_whatsit_data(); + l_set_token_data(); set_l_img_keys_index; set_l_img_pageboxes_index; - - prepare_cmdline(Luas, argv, argc, lua_offset); /* collect arguments */ + /*tex collect arguments */ + prepare_cmdline(Luas, argv, argc, lua_offset); setup_lua_path(Luas); - if (startup_filename != NULL) { given_file = xstrdup(startup_filename); if (lua_only) { - xfree(startup_filename); + xfree(startup_filename); } startup_filename = find_filename(given_file, "LUATEXDIR"); } - /* now run the file */ + /*tex now run the file */ if (startup_filename != NULL) { char *v1; int tex_table_id = hide_lua_table(Luas, "tex"); @@ -1018,7 +1031,7 @@ void lua_initialize(int ac, char **av) int node_table_id = hide_lua_table(Luas, "node"); int pdf_table_id = hide_lua_table(Luas, "pdf"); if (lua_only) { - /* hide the 'tex' and 'pdf' table */ + /*tex hide the 'tex' and 'pdf' table */ if (load_luatex_core_lua(Luas)) { fprintf(stderr, "Error in execution of luatex-core.lua .\n"); } @@ -1026,20 +1039,20 @@ void lua_initialize(int ac, char **av) fprintf(stdout, "%s\n", lua_tostring(Luas, -1)); exit(1); } - init_tex_table(Luas); /* needed ? */ + init_tex_table(Luas); if (lua_pcall(Luas, 0, 0, 0)) { fprintf(stdout, "%s\n", lua_tostring(Luas, -1)); lua_traceback(Luas); - /* lua_close(Luas); */ + /*tex lua_close(Luas); */ exit(1); } else { if (given_file) free(given_file); - /* lua_close(Luas); */ + /*tex lua_close(Luas); */ exit(0); } } - /* a normal tex run */ + /*tex a normal tex run */ init_tex_table(Luas); unhide_lua_table(Luas, "tex", tex_table_id); unhide_lua_table(Luas, "pdf", pdf_table_id); @@ -1060,28 +1073,25 @@ void lua_initialize(int ac, char **av) if (!dump_name) { get_lua_string("texconfig", "formatname", &dump_name); } - /* |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 */ + /*tex re-enable loading of texmf.cnf values, see luatex.ch */ + luainit = 0; init_kpse(); kpse_init = 1; } - /* |prohibit_file_trace| (boolean) */ + /*tex |prohibit_file_trace| (boolean) */ tracefilenames = 1; get_lua_boolean("texconfig", "trace_file_names", &tracefilenames); - - /* |file_line_error| */ + /*tex |file_line_error| */ filelineerrorstylep = false; get_lua_boolean("texconfig", "file_line_error", &filelineerrorstylep); - - /* |halt_on_error| */ + /*tex |halt_on_error| */ haltonerrorp = false; get_lua_boolean("texconfig", "halt_on_error", &haltonerrorp); - - /* |restrictedshell| */ + /*tex |restrictedshell| */ v1 = NULL; get_lua_string("texconfig", "shell_escape", &v1); if (v1) { @@ -1093,7 +1103,7 @@ void lua_initialize(int ac, char **av) } free(v1); } - /* If shell escapes are restricted, get allowed cmds from cnf. */ + /*tex If shell escapes are restricted, get allowed cmds from cnf. */ if (shellenabledp && restrictedshell == 1) { v1 = NULL; get_lua_string("texconfig", "shell_escape_commands", &v1); @@ -1102,11 +1112,10 @@ void lua_initialize(int ac, char **av) free(v1); } } - starttime = -1 ; get_lua_number("texconfig", "start_time", &starttime); if (starttime < 0) { - /* + /*tex We provide this one for compatibility reasons and therefore also in uppercase. */ @@ -1115,38 +1124,32 @@ void lua_initialize(int ac, char **av) 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 if (luainit) { + if (given_file) { + fprintf(stdout, "%s file %s not found\n", (lua_only ? "Script" : "Configuration"), given_file); + free(given_file); } else { - /* init */ - init_kpse(); - kpse_init = 1; - fix_dumpname(); + fprintf(stdout, "No %s file given\n", (lua_only ? "script" : "configuration")); } + exit(1); + } else { + /* init */ + init_kpse(); + kpse_init = 1; + fix_dumpname(); + } + /*tex 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"); } - - /* 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) { @@ -1156,7 +1159,10 @@ void check_texconfig_init(void) 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 */ + /*tex + We can't be more precise hereas it's called before \TEX\ + initialization happens. + */ fprintf(stderr, "This went wrong: %s\n", lua_tostring(Luas, -1)); error(); } diff --git a/Build/source/texk/web2c/luatexdir/lua/luanode.w b/Build/source/texk/web2c/luatexdir/lua/luanode.c index ef2f0b92655..3182b609773 100644 --- a/Build/source/texk/web2c/luatexdir/lua/luanode.w +++ b/Build/source/texk/web2c/luatexdir/lua/luanode.c @@ -1,33 +1,32 @@ -% luanode.w -% -% Copyright 2006-2008 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/>. +/* -/* hh-ls: we make sure that lua never sees prev of head but also that when -nodes are removed or inserted, temp nodes don't interfere */ +luanode.w -@ @c +Copyright 2006-2008 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/>. + +*/ #include "ptexlib.h" #include "lua/luatex-api.h" -@ @c void lua_node_filter_s(int filterid, int extrainfo) { + int i; int callback_id = callback_defined(filterid); int s_top = lua_gettop(Luas); if (callback_id <= 0) { @@ -38,20 +37,20 @@ void lua_node_filter_s(int filterid, int extrainfo) lua_settop(Luas, s_top); return; } - lua_push_string_by_index(Luas,extrainfo); /* arg 1 */ - if (lua_pcall(Luas, 1, 0, 0) != 0) { - fprintf(stdout, "error: %s\n", lua_tostring(Luas, -1)); + lua_push_string_by_index(Luas,extrainfo); + if ((i=lua_pcall(Luas, 1, 0, 0)) != 0) { + formatted_warning("node filter","error: %s", lua_tostring(Luas, -1)); lua_settop(Luas, s_top); - error(); + luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); return; } lua_settop(Luas, s_top); return; } -@ @c void lua_node_filter(int filterid, int extrainfo, halfword head_node, halfword * tail_node) { + int i; halfword start_node, start_done, last_node; int s_top = lua_gettop(Luas); int callback_id = callback_defined(filterid); @@ -59,45 +58,45 @@ void lua_node_filter(int filterid, int extrainfo, halfword head_node, halfword * lua_settop(Luas, s_top); return; } - /* we start after head */ + /*tex We start after head. */ start_node = vlink(head_node); if (start_node == null || !get_callback(Luas, callback_id)) { lua_settop(Luas, s_top); return; } - /* we make sure we have no prev */ + /*tex We make sure we have no prev */ alink(start_node) = null ; - /* the action */ + /*tex the action */ nodelist_to_lua(Luas, start_node); lua_push_group_code(Luas,extrainfo); - if (lua_pcall(Luas, 2, 1, 0) != 0) { - fprintf(stdout, "error: %s\n", lua_tostring(Luas, -1)); + if ((i=lua_pcall(Luas, 2, 1, 0)) != 0) { + formatted_warning("node filter", "error: %s\n", lua_tostring(Luas, -1)); lua_settop(Luas, s_top); - error(); + luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); return; } - /* the result */ + /*tex the result */ if (lua_isboolean(Luas, -1)) { if (lua_toboolean(Luas, -1) != 1) { - /* discard */ + /*tex discard */ flush_node_list(start_node); vlink(head_node) = null; } else { - /* keep */ + /*tex keep */ } } else { - /* append to old head */ - start_done = nodelist_from_lua(Luas); + /*tex append to old head */ + start_done = nodelist_from_lua(Luas,-1); try_couple_nodes(head_node,start_done); } - /* redundant as we set top anyway */ + /*tex redundant as we set top anyway */ lua_pop(Luas, 2); - /* find tail in order to update tail */ + /*tex find tail in order to update tail */ start_node = vlink(head_node); if (start_node != null) { - /* maybe just always slide (harmless and fast) */ + /*tex maybe just always slide (harmless and fast) */ if (fix_node_lists) { - /* slides and returns last node */ + /*tex slides and returns last node */ *tail_node = fix_node_list(start_node); } else { last_node = vlink(start_node); @@ -105,24 +104,23 @@ void lua_node_filter(int filterid, int extrainfo, halfword head_node, halfword * start_node = last_node; last_node = vlink(start_node); } - /* we're at the end now */ + /*tex we're at the end now */ *tail_node = start_node; } } else { - /* we're already at the end */ + /*tex we're already at the end */ *tail_node = head_node; } - /* clean up */ + /*tex clean up */ lua_settop(Luas, s_top); return; } -@ @c int lua_linebreak_callback(int is_broken, halfword head_node, halfword * new_head) { - int a; + int a, i; register halfword *p; - int ret = 0; /* failure */ + int ret = 0; int s_top = lua_gettop(Luas); int callback_id = callback_defined(linebreak_filter_callback); if (head_node == null || vlink(head_node) == null || callback_id <= 0) { @@ -130,32 +128,33 @@ int lua_linebreak_callback(int is_broken, halfword head_node, halfword * new_hea return ret; } if (!get_callback(Luas, callback_id)) { - lua_settop(Luas, s_top); + lua_settop(Luas, s_top); return ret; } - alink(vlink(head_node)) = null ; /* hh-ls */ - nodelist_to_lua(Luas, vlink(head_node)); /* arg 1 */ - lua_pushboolean(Luas, is_broken); /* arg 2 */ - if (lua_pcall(Luas, 2, 1, 0) != 0) { /* no arg, 1 result */ - fprintf(stdout, "error: %s\n", lua_tostring(Luas, -1)); + alink(vlink(head_node)) = null ; + nodelist_to_lua(Luas, vlink(head_node)); + lua_pushboolean(Luas, is_broken); + if ((i=lua_pcall(Luas, 2, 1, 0)) != 0) { + formatted_warning("linebreak", "error: %s", lua_tostring(Luas, -1)); lua_settop(Luas, s_top); - error(); + luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); return ret; } + lua_settop(Luas, s_top); p = lua_touserdata(Luas, -1); if (p != NULL) { - a = nodelist_from_lua(Luas); + a = nodelist_from_lua(Luas,-1); try_couple_nodes(*new_head,a); ret = 1; } - lua_settop(Luas, s_top); return ret; } -@ @c -int lua_appendtovlist_callback(halfword box, int location, halfword prev_depth, boolean is_mirrored, halfword * result, int * next_depth, boolean * prev_set) +int lua_appendtovlist_callback(halfword box, int location, halfword prev_depth, + boolean is_mirrored, halfword * result, int * next_depth, boolean * prev_set) { register halfword *p; + int i; int s_top = lua_gettop(Luas); int callback_id = callback_defined(append_to_vlist_filter_callback); if (box == null || callback_id <= 0) { @@ -170,10 +169,10 @@ int lua_appendtovlist_callback(halfword box, int location, halfword prev_depth, lua_push_string_by_index(Luas,location); lua_pushinteger(Luas, (int) prev_depth); lua_pushboolean(Luas, is_mirrored); - if (lua_pcall(Luas, 4, 2, 0) != 0) { - fprintf(stdout, "error: %s\n", lua_tostring(Luas, -1)); + if ((i=lua_pcall(Luas, 4, 2, 0)) != 0) { + formatted_warning("append to vlist","error: %s", lua_tostring(Luas, -1)); lua_settop(Luas, s_top); - error(); + luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); return 0; } if (lua_type(Luas,-1) == LUA_TNUMBER) { @@ -187,13 +186,13 @@ int lua_appendtovlist_callback(halfword box, int location, halfword prev_depth, p = check_isnode(Luas, -1); *result = *p; } - lua_settop(Luas, s_top); return 1; } -@ @c -halfword lua_hpack_filter(halfword head_node, scaled size, int pack_type, int extrainfo, int pack_direction, halfword attr) +halfword lua_hpack_filter(halfword head_node, scaled size, int pack_type, int extrainfo, + int pack_direction, halfword attr) { + int i; halfword ret; int s_top = lua_gettop(Luas); int callback_id = callback_defined(hpack_filter_callback); @@ -205,7 +204,7 @@ halfword lua_hpack_filter(halfword head_node, scaled size, int pack_type, int ex lua_settop(Luas, s_top); return head_node; } - alink(head_node) = null ; /* hh-ls */ + alink(head_node) = null ; nodelist_to_lua(Luas, head_node); lua_push_group_code(Luas,extrainfo); lua_pushinteger(Luas, size); @@ -220,10 +219,10 @@ halfword lua_hpack_filter(halfword head_node, scaled size, int pack_type, int ex } else { lua_pushnil(Luas); } - if (lua_pcall(Luas, 6, 1, 0) != 0) { - fprintf(stdout, "error: %s\n", lua_tostring(Luas, -1)); + if ((i=lua_pcall(Luas, 6, 1, 0)) != 0) { + formatted_warning("hpack filter", "error: %s\n", lua_tostring(Luas, -1)); lua_settop(Luas, s_top); - error(); + luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); return head_node; } ret = head_node; @@ -233,29 +232,26 @@ halfword lua_hpack_filter(halfword head_node, scaled size, int pack_type, int ex ret = null; } } else { - ret = nodelist_from_lua(Luas); + ret = nodelist_from_lua(Luas,-1); } lua_settop(Luas, s_top); -#if 0 - lua_gc(Luas,LUA_GCSTEP, LUA_GC_STEP_SIZE); -#endif if (fix_node_lists) fix_node_list(ret); return ret; } -@ @c halfword lua_vpack_filter(halfword head_node, scaled size, int pack_type, scaled maxd, - int extrainfo, int pack_direction, halfword attr) + int extrainfo, int pack_direction, halfword attr) { halfword ret; + int i; int callback_id; int s_top = lua_gettop(Luas); if (head_node == null) { lua_settop(Luas, s_top); return head_node; } - if (extrainfo == 8) { /* output */ + if (extrainfo == 8) { callback_id = callback_defined(pre_output_filter_callback); } else { callback_id = callback_defined(vpack_filter_callback); @@ -268,7 +264,7 @@ halfword lua_vpack_filter(halfword head_node, scaled size, int pack_type, scaled lua_settop(Luas, s_top); return head_node; } - alink(head_node) = null ; /* hh-ls */ + alink(head_node) = null ; nodelist_to_lua(Luas, head_node); lua_push_group_code(Luas, extrainfo); lua_pushinteger(Luas, size); @@ -284,10 +280,10 @@ halfword lua_vpack_filter(halfword head_node, scaled size, int pack_type, scaled } else { lua_pushnil(Luas); } - if (lua_pcall(Luas, 7, 1, 0) != 0) { - fprintf(stdout, "error: %s\n", lua_tostring(Luas, -1)); + if ((i=lua_pcall(Luas, 7, 1, 0)) != 0) { + formatted_warning("vpack filter", "error: %s", lua_tostring(Luas, -1)); lua_settop(Luas, s_top); - error(); + luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); return head_node; } ret = head_node; @@ -297,76 +293,84 @@ halfword lua_vpack_filter(halfword head_node, scaled size, int pack_type, scaled ret = null; } } else { - ret = nodelist_from_lua(Luas); + ret = nodelist_from_lua(Luas,-1); } lua_settop(Luas, s_top); -#if 0 - lua_gc(Luas,LUA_GCSTEP, LUA_GC_STEP_SIZE); -#endif if (fix_node_lists) fix_node_list(ret); return ret; } -@ This is a quick hack to fix etex's \.{\\lastnodetype} now that - there are many more visible node types. TODO: check the - eTeX manual for the expected return values. +/*tex + + This is a quick hack to fix \ETEX's \.{\\lastnodetype} now that there are many + more visible node types. + +*/ -@c int visible_last_node_type(int n) { int i = type(n); if (i != glyph_node) { return get_etex_code(i); } else if (is_ligature(n)) { - return 7; /* old ligature value */ + /*tex old ligature value */ + return 7; } else { - return 0; /* old character value */ + /*tex old character value */ + return 0; } } -@ @c -void lua_pdf_literal(PDF pdf, int i) +void lua_pdf_literal(PDF pdf, int i, int noline) { const char *s = NULL; size_t l = 0; lua_rawgeti(Luas, LUA_REGISTRYINDEX, i); s = lua_tolstring(Luas, -1, &l); - pdf_out_block(pdf, s, l); - pdf_out(pdf, 10); /* |pdf_print_nl| */ + if (noline) { + pdf_check_space(pdf); + pdf_out_block(pdf, s, l); + pdf_set_space(pdf); + } else { + pdf_out_block(pdf, s, l); + pdf_out(pdf, 10); + } lua_pop(Luas, 1); } -@ @c void copy_pdf_literal(pointer r, pointer p) { - pdf_literal_type(r) = pdf_literal_type(p); + int t = pdf_literal_type(p); + pdf_literal_type(r) = t; pdf_literal_mode(r) = pdf_literal_mode(p); - if (pdf_literal_type(p) == normal) { + if (t == normal) { pdf_literal_data(r) = pdf_literal_data(p); add_token_ref(pdf_literal_data(p)); - } else { + } else if (t == lua_refid_literal) { lua_rawgeti(Luas, LUA_REGISTRYINDEX, pdf_literal_data(p)); pdf_literal_data(r) = luaL_ref(Luas, LUA_REGISTRYINDEX); + } else { + /* maybe something user, we don't support a call here but best keep it sane anyway. */ + pdf_literal_data(r) = pdf_literal_data(p); } } -@ @c void copy_late_lua(pointer r, pointer p) { - late_lua_type(r) = late_lua_type(p); + int t = late_lua_type(p); + late_lua_type(r) = t; if (late_lua_name(p) > 0) add_token_ref(late_lua_name(p)); - if (late_lua_type(p) == normal) { + if (t == normal) { late_lua_data(r) = late_lua_data(p); add_token_ref(late_lua_data(p)); - } else { + } else if (t == lua_refid_literal) { lua_rawgeti(Luas, LUA_REGISTRYINDEX, late_lua_data(p)); late_lua_data(r) = luaL_ref(Luas, LUA_REGISTRYINDEX); } } -@ @c void copy_user_lua(pointer r, pointer p) { if (user_node_value(p) != 0) { @@ -375,28 +379,28 @@ void copy_user_lua(pointer r, pointer p) } } -@ @c void free_pdf_literal(pointer p) { - if (pdf_literal_type(p) == normal) { + int t = pdf_literal_type(p); + if (t == normal) { delete_token_ref(pdf_literal_data(p)); - } else { + } else if (t == lua_refid_literal) { luaL_unref(Luas, LUA_REGISTRYINDEX, pdf_literal_data(p)); } } void free_late_lua(pointer p) { + int t = late_lua_type(p); if (late_lua_name(p) > 0) delete_token_ref(late_lua_name(p)); - if (late_lua_type(p) == normal) { + if (t == normal) { delete_token_ref(late_lua_data(p)); - } else { + } else if (t == lua_refid_literal) { luaL_unref(Luas, LUA_REGISTRYINDEX, late_lua_data(p)); } } -@ @c void free_user_lua(pointer p) { if (user_node_value(p) != 0) { @@ -404,9 +408,9 @@ void free_user_lua(pointer p) } } -@ @c void show_pdf_literal(pointer p) { + int t = pdf_literal_type(p); tprint_esc("pdfliteral"); switch (pdf_literal_mode(p)) { case set_origin: @@ -422,30 +426,36 @@ void show_pdf_literal(pointer p) tprint(" raw"); break; default: - confusion("literal2"); + tprint(" <invalid mode>"); break; } - if (pdf_literal_type(p) == normal) { + if (t == normal) { print_mark(pdf_literal_data(p)); + } else if (t == lua_refid_literal) { + tprint(" <lua data reference "); + print_int(pdf_literal_data(p)); + tprint(">"); } else { - lua_rawgeti(Luas, LUA_REGISTRYINDEX, pdf_literal_data(p)); - tprint("\""); - tprint(lua_tostring(Luas, -1)); - tprint("\""); - lua_pop(Luas, 1); + tprint(" <invalid data>"); } } -@ @c void show_late_lua(pointer p) { + int t = late_lua_type(p); tprint_esc("latelua"); print_int(late_lua_reg(p)); - if (late_lua_type(p) == normal) { + if (t == normal) { print_mark(late_lua_data(p)); - } else { - tprint(" <function "); + } else if (t == lua_refid_literal) { + tprint(" <function reference "); print_int(late_lua_data(p)); tprint(">"); + } else if (t == lua_refid_call) { + tprint(" <functioncall reference "); + print_int(late_lua_data(p)); + tprint(">"); + } else { + tprint(" <invalid data>"); } } diff --git a/Build/source/texk/web2c/luatexdir/lua/luastuff.w b/Build/source/texk/web2c/luatexdir/lua/luastuff.c index a2b1dd14327..0d9342223df 100644 --- a/Build/source/texk/web2c/luatexdir/lua/luastuff.w +++ b/Build/source/texk/web2c/luatexdir/lua/luastuff.c @@ -1,30 +1,32 @@ -% luastuff.w -% -% Copyright 2006-2013 Taco Hoekwater <taco@@luatex.org> -% -% This file is part of LuaTeX. -% -% LuaTeX is free software; you can redistribute it and/or modify it under -% the terms of the GNU General Public License as published by the Free -% Software Foundation; either version 2 of the License, or (at your -% option) any later version. -% -% LuaTeX is distributed in the hope that it will be useful, but WITHOUT -% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -% License for more details. -% -% You should have received a copy of the GNU General Public License along -% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -@ @c +/* + +luastuff.w + +Copyright 2006-2013 Taco Hoekwater <taco@@luatex.org> + +This file is part of LuaTeX. + +LuaTeX is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. + +LuaTeX is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU General Public License along +with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +*/ + #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; @@ -45,31 +47,44 @@ int lua_active = 0; lua_pop(L, 1); #endif -@ @c void make_table(lua_State * L, const char *tab, const char *mttab, const char *getfunc, const char *setfunc) { - /* make the table *//* |[{<tex>}]| */ - lua_pushstring(L, tab); /* |[{<tex>},"dimen"]| */ - lua_newtable(L); /* |[{<tex>},"dimen",{}]| */ - lua_settable(L, -3); /* |[{<tex>}]| */ - /* fetch it back */ - lua_pushstring(L, tab); /* |[{<tex>},"dimen"]| */ - lua_gettable(L, -2); /* |[{<tex>},{<dimen>}]| */ - /* make the meta entries */ - luaL_newmetatable(L, mttab); /* |[{<tex>},{<dimen>},{<dimen_m>}]| */ - lua_pushstring(L, "__index"); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index"]| */ - lua_pushstring(L, getfunc); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index","getdimen"]| */ - lua_gettable(L, -5); /* |[{<tex>},{<dimen>},{<dimen_m>},"__index",<tex.getdimen>]| */ - lua_settable(L, -3); /* |[{<tex>},{<dimen>},{<dimen_m>}]| */ - lua_pushstring(L, "__newindex"); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex"]| */ - lua_pushstring(L, setfunc); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex","setdimen"]| */ - lua_gettable(L, -5); /* |[{<tex>},{<dimen>},{<dimen_m>},"__newindex",<tex.setdimen>]| */ - lua_settable(L, -3); /* |[{<tex>},{<dimen>},{<dimen_m>}]| */ - lua_setmetatable(L, -2); /* |[{<tex>},{<dimen>}]| : assign the metatable */ - lua_pop(L, 1); /* |[{<tex>}]| : clean the stack */ + /*tex make the table *//* |[{<tex>}]| */ + /*tex |[{<tex>},"dimen"]| */ + lua_pushstring(L, tab); + /*tex |[{<tex>},"dimen",{}]| */ + lua_newtable(L); + /*tex |[{<tex>}]| */ + lua_settable(L, -3); + /*tex fetch it back */ + /*tex |[{<tex>},"dimen"]| */ + lua_pushstring(L, tab); + /*tex |[{<tex>},{<dimen>}]| */ + lua_gettable(L, -2); + /*tex make the meta entries */ + /*tex |[{<tex>},{<dimen>},{<dimen_m>}]| */ + luaL_newmetatable(L, mttab); + /*tex |[{<tex>},{<dimen>},{<dimen_m>},"__index"]| */ + lua_pushstring(L, "__index"); + /*tex |[{<tex>},{<dimen>},{<dimen_m>},"__index","getdimen"]| */ + lua_pushstring(L, getfunc); + /*tex |[{<tex>},{<dimen>},{<dimen_m>},"__index",<tex.getdimen>]| */ + lua_gettable(L, -5); + /*tex |[{<tex>},{<dimen>},{<dimen_m>}]| */ + lua_settable(L, -3); + lua_pushstring(L, "__newindex"); /*tex |[{<tex>},{<dimen>},{<dimen_m>},"__newindex"]| */ + /*tex |[{<tex>},{<dimen>},{<dimen_m>},"__newindex","setdimen"]| */ + lua_pushstring(L, setfunc); + /*tex |[{<tex>},{<dimen>},{<dimen_m>},"__newindex",<tex.setdimen>]| */ + lua_gettable(L, -5); + /*tex |[{<tex>},{<dimen>},{<dimen_m>}]| */ + lua_settable(L, -3); + /*tex |[{<tex>},{<dimen>}]| : assign the metatable */ + lua_setmetatable(L, -2); + /*tex |[{<tex>}]| : clean the stack */ + lua_pop(L, 1); } -@ @c static const char *getS(lua_State * L, void *ud, size_t * size) { LoadS *ls = (LoadS *) ud; @@ -81,18 +96,19 @@ static const char *getS(lua_State * L, void *ud, size_t * size) 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. */ + /* + \LUATEX\ has its own memory allocator, \LUAJIITEX\ 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 */ + /*tex define |ud| for -Wunused */ + (void) ud; if (nsize == 0) free(ptr); else @@ -102,15 +118,14 @@ static void *my_luaalloc(void *ud, void *ptr, size_t osize, size_t nsize) } #endif -@ @c static int my_luapanic(lua_State * L) { - (void) L; /* to avoid warnings */ + /*tex define |L| to avoid warnings */ + (void) L; 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 ; @@ -120,12 +135,17 @@ void luafunctioncall(int slot) lua_gettable(Luas, LUA_REGISTRYINDEX); lua_rawgeti(Luas, -1,slot); if (lua_isfunction(Luas,-1)) { - int base = lua_gettop(Luas); /* function index */ + /*tex function index */ + int base = lua_gettop(Luas); lua_pushinteger(Luas, slot); - lua_pushcfunction(Luas, lua_traceback); /* push traceback function */ - lua_insert(Luas, base); /* put it under chunk */ + /* push traceback function */ + lua_pushcfunction(Luas, lua_traceback); + /*tex put it under chunk */ + lua_insert(Luas, base); + ++function_callback_count; i = lua_pcall(Luas, 1, 0, base); - lua_remove(Luas, base); /* remove traceback function */ + /*tex remove traceback function */ + lua_remove(Luas, base); if (i != 0) { lua_gc(Luas, LUA_GCCOLLECT, 0); Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); @@ -135,9 +155,8 @@ void luafunctioncall(int slot) lua_active--; } -@ @c static const luaL_Reg lualibs[] = { - /* standard lua libraries */ + /*tex standard \LUA\ libraries */ { "_G", luaopen_base }, { "package", luaopen_package }, { "table", luaopen_table }, @@ -149,32 +168,30 @@ static const luaL_Reg lualibs[] = { { "lpeg", luaopen_lpeg }, { "bit32", luaopen_bit32 }, #ifdef LuajitTeX - /* bit is only in luajit, */ - /* coroutine is loaded in a special way */ - { "bit", luaopen_bit }, + /*tex |bit| is only in \LUAJIT */ + /*tex |coroutine| is loaded in a special way */ + { "bit", luaopen_bit }, #else #if LUA_VERSION_NUM == 503 { "utf8", luaopen_utf8 }, #endif { "coroutine", luaopen_coroutine }, #endif - /* additional (public) libraries */ + /*tex additional (public) libraries */ { "unicode", luaopen_unicode }, { "zip", luaopen_zip }, { "md5", luaopen_md5 }, + { "sha2", luaopen_sha2 }, { "lfs", luaopen_lfs }, - /* extra standard lua libraries */ + /*tex 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 */ + /*tex more libraries will be loaded later */ { NULL, NULL } }; -@ @c static void do_openlibs(lua_State * L) { const luaL_Reg *lib = lualibs; @@ -183,22 +200,23 @@ static void do_openlibs(lua_State * L) } } -@ @c #ifdef LuajitTeX - /* in luajit load_aux is not used.*/ + /*tex in \LUAJIT\ |load_aux| is not used.*/ #else static int load_aux (lua_State *L, int status) { - if (status == 0) /* OK? */ + if (status == 0) + /*tex okay */ return 1; else { + /*tex return nil plus error message */ lua_pushnil(L); - lua_insert(L, -2); /* put before error message */ - return 2; /* return nil plus error message */ + /*tex put before error message */ + lua_insert(L, -2); + return 2; } } #endif -@ @c static int luatex_loadfile (lua_State *L) { int status = 0; const char *fname = luaL_optstring(L, 1, NULL); @@ -206,12 +224,14 @@ static int luatex_loadfile (lua_State *L) { #ifdef LuajitTeX /* 5.1 */ #else - int env = !lua_isnone(L, 3); /* 'env' parameter? */ + /*tex the |env| parameter */ + int env = !lua_isnone(L, 3); #endif if (!lua_only && !fname && interaction == batch_mode) { + /*tex return |nil| plus error message */ lua_pushnil(L); lua_pushstring(L, "reading from stdin is disabled in batch mode"); - return 2; /* return nil plus error message */ + return 2; } status = luaL_loadfilex(L, fname, mode); if (status == LUA_OK) { @@ -219,9 +239,11 @@ static int luatex_loadfile (lua_State *L) { #ifdef LuajitTeX /* 5.1 */ #else - if (env) { /* 'env' parameter? */ + if (env) { + /*tex the |env| parameter */ lua_pushvalue(L, 3); - lua_setupvalue(L, -2, 1); /* set it as 1st upvalue of loaded chunk */ + /*tex set it as first upvalue of loaded chunk */ + lua_setupvalue(L, -2, 1); } #endif } @@ -232,15 +254,15 @@ static int luatex_loadfile (lua_State *L) { #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) { + /*tex return |nil| plus error message */ lua_pushnil(L); lua_pushstring(L, "reading from stdin is disabled in batch mode"); - return 2; /* return nil plus error message */ + return 2; } else { tprint_nl("lua> "); } @@ -252,13 +274,12 @@ static int luatex_dofile (lua_State *L) { return lua_gettop(L) - n; } -@ @c void luainterpreter(void) { lua_State *L; #ifdef LuajitTeX if (jithash_hashname == NULL) { - /* default lua51 */ + /*tex default lua51 */ luajittex_choose_hash_function = 0; jithash_hashname = (char *) xmalloc(strlen("lua51") + 1); jithash_hashname = strcpy ( jithash_hashname, "lua51"); @@ -267,7 +288,7 @@ void luainterpreter(void) } else if (strcmp((const char*)jithash_hashname,"luajit20") == 0) { luajittex_choose_hash_function = 1; } else { - /* default lua51 */ + /*tex default lua51 */ luajittex_choose_hash_function = 0; jithash_hashname = strcpy ( jithash_hashname, "lua51"); } @@ -280,8 +301,8 @@ void luainterpreter(void) return; } lua_atpanic(L, &my_luapanic); - - do_openlibs(L); /* does all the 'simple' libraries */ + /*tex This initializes all the `simple' libraries: */ + do_openlibs(L); #ifdef LuajitTeX if (luajiton){ luaJIT_setmode(L, 0, LUAJIT_MODE_ENGINE|LUAJIT_MODE_ON); @@ -290,22 +311,17 @@ void luainterpreter(void) 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. + /*tex + 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"); @@ -315,28 +331,26 @@ void luainterpreter(void) lua_setfield(L, -2, "loaded"); lua_getfield(L, -1, "loaded"); } + /*tex |package.loaded.socket = nil| */ luaopen_socket_core(L); lua_setfield(L, -2, "socket.core"); lua_pushnil(L); - lua_setfield(L, -2, "socket"); /* package.loaded.socket = nil */ - + lua_setfield(L, -2, "socket"); + /*tex |package.loaded.mime = 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 */ + lua_setfield(L, -2, "mime"); + /*tex pop the tables */ + lua_pop(L, 2); + /*tex preload the pure \LUA\ modules */ + luatex_socketlua_open(L); } - - /* zlib. slightly odd calling convention */ + /*tex |zlib|'s slightly odd calling convention */ luaopen_zlib(L); lua_setglobal(L, "zlib"); - luaopen_gzip(L); - - /* our own libraries register themselves */ - + /*tex our own libraries register themselves */ luaopen_fio(L); luaopen_ff(L); luaopen_tex(L); @@ -345,29 +359,25 @@ void luainterpreter(void) luaopen_texio(L); luaopen_kpse(L); luaopen_callback(L); - + /*tex now we plug in extra \LUA\ startup code */ luaopen_lua(L, startup_filename); - + /*tex and open some \TEX\ ones */ luaopen_stats(L); luaopen_font(L); luaopen_lang(L); luaopen_mplib(L); luaopen_vf(L); luaopen_pdf(L); - luaopen_epdf(L); + luaopen_pdfe(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; @@ -380,7 +390,6 @@ int hide_lua_table(lua_State * L, const char *name) return r; } -@ @c void unhide_lua_table(lua_State * L, const char *name, int r) { lua_rawgeti(L, LUA_REGISTRYINDEX, r); @@ -388,7 +397,6 @@ void unhide_lua_table(lua_State * L, const char *name, int r) luaL_unref(L, LUA_REGISTRYINDEX, r); } -@ @c int hide_lua_value(lua_State * L, const char *name, const char *item) { int r = 0; @@ -402,7 +410,6 @@ int hide_lua_value(lua_State * L, const char *name, const char *item) return r; } -@ @c void unhide_lua_value(lua_State * L, const char *name, const char *item, int r) { lua_getglobal(L, name); @@ -413,7 +420,6 @@ void unhide_lua_value(lua_State * L, const char *name, const char *item, int r) } } -@ @c int lua_traceback(lua_State * L) { lua_getglobal(L, "debug"); @@ -426,21 +432,23 @@ int lua_traceback(lua_State * L) 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 */ + /*tex pass error message */ + lua_pushvalue(L, 1); + /*tex skip this function and traceback */ + lua_pushinteger(L, 2); + /*tex call |debug.traceback| */ + lua_call(L, 2, 1); return 1; } -@ @c -static void luacall(int p, int nameptr, boolean is_string) /* hh-ls: optimized lua_id resolving */ +static void luacall(int p, int nameptr, boolean is_string) { LoadS ls; int i; size_t ll = 0; char *lua_id; char *s = NULL; - + int stacktop = lua_gettop(Luas); if (Luas == NULL) { luainterpreter(); } @@ -449,16 +457,22 @@ static void luacall(int p, int nameptr, boolean is_string) /* hh-ls: optimized l const char *ss = NULL; lua_rawgeti(Luas, LUA_REGISTRYINDEX, p); if (lua_isfunction(Luas,-1)) { - int base = lua_gettop(Luas); /* function index */ + /*tex function index */ + int base = lua_gettop(Luas); lua_checkstack(Luas, 1); - lua_pushcfunction(Luas, lua_traceback); /* push traceback function */ - lua_insert(Luas, base); /* put it under chunk */ + /*tex push traceback function */ + lua_pushcfunction(Luas, lua_traceback); + /*tex put it under chunk */ + lua_insert(Luas, base); + ++late_callback_count; i = lua_pcall(Luas, 0, 0, base); - lua_remove(Luas, base); /* remove traceback function */ + /*tex remove traceback function */ + lua_remove(Luas, base); if (i != 0) { lua_gc(Luas, LUA_GCCOLLECT, 0); Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); } + lua_settop(Luas,stacktop); lua_active--; return ; } @@ -475,7 +489,8 @@ static void luacall(int p, int nameptr, boolean is_string) /* hh-ls: optimized l ls.size = ll; if (ls.size > 0) { if (nameptr > 0) { - int l = 0; /* not used */ + /*tex |l| is not used */ + int l = 0; lua_id = tokenlist_to_cstring(nameptr, 1, &l); i = Luas_load(Luas, getS, &ls, lua_id); xfree(lua_id); @@ -492,12 +507,17 @@ static void luacall(int p, int nameptr, boolean is_string) /* hh-ls: optimized l if (i != 0) { Luas = luatex_error(Luas, (i == LUA_ERRSYNTAX ? 0 : 1)); } else { - int base = lua_gettop(Luas); /* function index */ + /*tex function index */ + int base = lua_gettop(Luas); lua_checkstack(Luas, 1); - lua_pushcfunction(Luas, lua_traceback); /* push traceback function */ - lua_insert(Luas, base); /* put it under chunk */ + /*tex push traceback function */ + lua_pushcfunction(Luas, lua_traceback); + /*tex put it under chunk */ + lua_insert(Luas, base); + ++late_callback_count; i = lua_pcall(Luas, 0, 0, base); - lua_remove(Luas, base); /* remove traceback function */ + /*tex remove traceback function */ + lua_remove(Luas, base); if (i != 0) { lua_gc(Luas, LUA_GCCOLLECT, 0); Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); @@ -505,31 +525,99 @@ static void luacall(int p, int nameptr, boolean is_string) /* hh-ls: optimized l } xfree(ls.s); } + lua_settop(Luas,stacktop); + lua_active--; +} + +void luacall_vf(int p, int f, int c) +{ + int i; + int stacktop = lua_gettop(Luas); + if (Luas == NULL) { + luainterpreter(); + } + lua_active++; + lua_rawgeti(Luas, LUA_REGISTRYINDEX, p); + if (lua_isfunction(Luas,-1)) { + /*tex function index */ + int base = lua_gettop(Luas); + lua_checkstack(Luas, 1); + /*tex push traceback function */ + lua_pushcfunction(Luas, lua_traceback); + /*tex put it under chunk */ + lua_insert(Luas, base); + lua_pushinteger(Luas, f); + lua_pushinteger(Luas, c); + ++late_callback_count; + i = lua_pcall(Luas, 2, 0, base); + /*tex remove traceback function */ + lua_remove(Luas, base); + if (i != 0) { + lua_gc(Luas, LUA_GCCOLLECT, 0); + Luas = luatex_error(Luas, (i == LUA_ERRRUN ? 0 : 1)); + } + } else { + LoadS ls; + size_t ll = 0; + char *s = NULL; + const char *ss = NULL; + ss = lua_tolstring(Luas, -1, &ll); + s = xmalloc(ll+1); + memcpy(s,ss,ll+1); + lua_pop(Luas,1); + ls.s = s; + ls.size = ll; + if (ls.size > 0) { + i = Luas_load(Luas, getS, &ls, "=[vf command]"); + 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 */ + ++late_callback_count; + 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_settop(Luas,stacktop); lua_active--; } -@ @c void late_lua(PDF pdf, halfword p) { + halfword t; (void) pdf; - if (late_lua_type(p)==normal) { - expand_macros_in_tokenlist(p); /* sets |def_ref| */ + t = late_lua_type(p); + if (t == normal) { + /*tex sets |def_ref| */ + expand_macros_in_tokenlist(p); luacall(def_ref, late_lua_name(p), false); flush_list(def_ref); - } else { + } else if (t == lua_refid_call) { + luafunctioncall(late_lua_data(p)); + } else if (t == lua_refid_literal) { luacall(late_lua_data(p), late_lua_name(p), true); + } else { + /*tex Let's just ignore it, could be some user specific thing. */ } } -@ @c -void luatokencall(int p, int nameptr) /* hh-ls: optimized lua_id resolving */ +void luatokencall(int p, int nameptr) { LoadS ls; - int i, l; + int i; + int l = 0; char *s = NULL; char *lua_id; - assert(Luas); - l = 0; + int stacktop = lua_gettop(Luas); lua_active++; s = tokenlist_to_cstring(p, 1, &l); ls.s = s; @@ -538,7 +626,7 @@ void luatokencall(int p, int nameptr) /* hh-ls: optimized lua_id resolving */ if (nameptr > 0) { lua_id = tokenlist_to_cstring(nameptr, 1, &l); i = Luas_load(Luas, getS, &ls, lua_id); - xfree(lua_id); + xfree(lua_id); } else if (nameptr < 0) { lua_id = get_lua_name((nameptr + 65536)); if (lua_id != NULL) { @@ -553,40 +641,53 @@ void luatokencall(int p, int nameptr) /* hh-ls: optimized lua_id resolving */ if (i != 0) { Luas = luatex_error(Luas, (i == LUA_ERRSYNTAX ? 0 : 1)); } else { - int base = lua_gettop(Luas); /* function index */ + /*tex function index */ + int base = lua_gettop(Luas); lua_checkstack(Luas, 1); - lua_pushcfunction(Luas, lua_traceback); /* push traceback function */ - lua_insert(Luas, base); /* put it under chunk */ + /*tex push traceback function */ + lua_pushcfunction(Luas, lua_traceback); + /*tex put it under chunk */ + lua_insert(Luas, base); + ++direct_callback_count; i = lua_pcall(Luas, 0, 0, base); - lua_remove(Luas, base); /* remove traceback function */ + /*tex remove traceback function */ + lua_remove(Luas, base); 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 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 ? */ + /*tex + Free the 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 */ + /*tex + What if we have several .. not freed? + */ + last_lua_error = err; } 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 */ + /* + 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 */ + /*tex + This is never reached. + */ lua_close(L); return (lua_State *) NULL; } else { @@ -595,35 +696,41 @@ lua_State *luatex_error(lua_State * L, int is_fatal) } } -@ @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 */ + /*tex double call with same s gives assert(0) */ + lua_pushstring(L, s); + /*tex state: s */ + lua_gettable(L, LUA_REGISTRYINDEX); + /*tex state: t */ assert(lua_isnil(L, -1)); - lua_pop(L, 1); /* - */ - lua_pushstring(L, s); /* s */ - lua_newtable(L); /* t s */ + lua_pop(L, 1); + /*tex state: - */ + lua_pushstring(L, s); + /*tex state: s */ + lua_newtable(L); + /*tex state: 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_pushstring(L, p->name); + /*tex state: k t s */ + lua_pushinteger(L, p->idx); + /*tex state: v k t s */ + lua_settable(L, -3); + /*tex state: t s */ } - lua_settable(L, LUA_REGISTRYINDEX); /* - */ + lua_settable(L, LUA_REGISTRYINDEX); + /* tex state: - */ } - -@ @c -/* - luajit compatibility layer for luatex lua5.2 +/*tex + Here comes a \LUAJIT\ compatibility layer for \LUATEX\ \LUA5.2: */ + #ifdef LuajitTeX -@ @c LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { lua_State *L = B->L; if (sz > LUAL_BUFFERSIZE ) @@ -631,24 +738,22 @@ LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { 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)) {*/ + /* 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/luatoken.c b/Build/source/texk/web2c/luatexdir/lua/luatoken.c new file mode 100644 index 00000000000..fb197b68f7b --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luatoken.c @@ -0,0 +1,585 @@ +/* + +luatoken.w + +Copyright 2006-2012 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/>. + +*/ + +#include "ptexlib.h" +#include "lua/luatex-api.h" + +command_item command_names[] = { + { relax_cmd, NULL, 0}, + { left_brace_cmd, NULL, 0}, + { right_brace_cmd, NULL, 0}, + { math_shift_cmd, NULL, 0}, + { tab_mark_cmd, NULL, 0}, + { car_ret_cmd, NULL, 0}, + { mac_param_cmd, NULL, 0}, + { sup_mark_cmd, NULL, 0}, + { sub_mark_cmd, NULL, 0}, + { endv_cmd, NULL, 0}, + { spacer_cmd, NULL, 0}, + { letter_cmd, NULL, 0}, + { other_char_cmd, NULL, 0}, + { par_end_cmd, NULL, 0}, + { stop_cmd, NULL, 0}, + { delim_num_cmd, NULL, 0}, + { char_num_cmd, NULL, 0}, + { math_char_num_cmd, NULL, 0}, + { mark_cmd, NULL, 0}, + { node_cmd, NULL, 0}, + { xray_cmd, NULL, 0}, + { make_box_cmd, NULL, 0}, + { hmove_cmd, NULL, 0}, + { vmove_cmd, NULL, 0}, + { un_hbox_cmd, NULL, 0}, + { un_vbox_cmd, NULL, 0}, + { remove_item_cmd, NULL, 0}, + { hskip_cmd, NULL, 0}, + { vskip_cmd, NULL, 0}, + { mskip_cmd, NULL, 0}, + { kern_cmd, NULL, 0}, + { mkern_cmd, NULL, 0}, + { leader_ship_cmd, NULL, 0}, + { halign_cmd, NULL, 0}, + { valign_cmd, NULL, 0}, + { no_align_cmd, NULL, 0}, + { no_vrule_cmd, NULL, 0}, + { no_hrule_cmd, NULL, 0}, + { vrule_cmd, NULL, 0}, + { hrule_cmd, NULL, 0}, + { insert_cmd, NULL, 0}, + { vadjust_cmd, NULL, 0}, + { ignore_spaces_cmd, NULL, 0}, + { after_assignment_cmd, NULL, 0}, + { after_group_cmd, NULL, 0}, + { break_penalty_cmd, NULL, 0}, + { start_par_cmd, NULL, 0}, + { ital_corr_cmd, NULL, 0}, + { accent_cmd, NULL, 0}, + { math_accent_cmd, NULL, 0}, + { discretionary_cmd, NULL, 0}, + { eq_no_cmd, NULL, 0}, + { left_right_cmd, NULL, 0}, + { math_comp_cmd, NULL, 0}, + { limit_switch_cmd, NULL, 0}, + { above_cmd, NULL, 0}, + { math_style_cmd, NULL, 0}, + { math_choice_cmd, NULL, 0}, + { non_script_cmd, NULL, 0}, + { vcenter_cmd, NULL, 0}, + { case_shift_cmd, NULL, 0}, + { message_cmd, NULL, 0}, + { normal_cmd, NULL, 0}, + { extension_cmd, NULL, 0}, + { option_cmd, NULL, 0}, + { lua_function_call_cmd, NULL, 0}, + { lua_bytecode_call_cmd, NULL, 0}, + { lua_call_cmd, NULL, 0}, + { in_stream_cmd, NULL, 0}, + { begin_group_cmd, NULL, 0}, + { end_group_cmd, NULL, 0}, + { omit_cmd, NULL, 0}, + { ex_space_cmd, NULL, 0}, + { boundary_cmd, NULL, 0}, + { radical_cmd, NULL, 0}, + { super_sub_script_cmd, NULL, 0}, + { no_super_sub_script_cmd, NULL, 0}, + { math_shift_cs_cmd, NULL, 0}, + { end_cs_name_cmd, NULL, 0}, + { char_ghost_cmd, NULL, 0}, + { assign_local_box_cmd, NULL, 0}, + { char_given_cmd, NULL, 0}, + { math_given_cmd, NULL, 0}, + { xmath_given_cmd, NULL, 0}, + { last_item_cmd, NULL, 0}, + { toks_register_cmd, NULL, 0}, + { assign_toks_cmd, NULL, 0}, + { assign_int_cmd, NULL, 0}, + { assign_attr_cmd, NULL, 0}, + { assign_dimen_cmd, NULL, 0}, + { assign_glue_cmd, NULL, 0}, + { assign_mu_glue_cmd, NULL, 0}, + { assign_font_dimen_cmd, NULL, 0}, + { assign_font_int_cmd, NULL, 0}, + { assign_hang_indent_cmd, NULL, 0}, + { set_aux_cmd, NULL, 0}, + { set_prev_graf_cmd, NULL, 0}, + { set_page_dimen_cmd, NULL, 0}, + { set_page_int_cmd, NULL, 0}, + { set_box_dimen_cmd, NULL, 0}, + { set_tex_shape_cmd, NULL, 0}, + { set_etex_shape_cmd, NULL, 0}, + { def_char_code_cmd, NULL, 0}, + { def_del_code_cmd, NULL, 0}, + { extdef_math_code_cmd, NULL, 0}, + { extdef_del_code_cmd, NULL, 0}, + { def_family_cmd, NULL, 0}, + { set_math_param_cmd, NULL, 0}, + { set_font_cmd, NULL, 0}, + { def_font_cmd, NULL, 0}, + { register_cmd, NULL, 0}, + { assign_box_direction_cmd, NULL, 0}, + { assign_box_dir_cmd, NULL, 0}, + { assign_direction_cmd, NULL, 0}, + { assign_dir_cmd, NULL, 0}, + { advance_cmd, NULL, 0}, + { multiply_cmd, NULL, 0}, + { divide_cmd, NULL, 0}, + { prefix_cmd, NULL, 0}, + { let_cmd, NULL, 0}, + { shorthand_def_cmd, NULL, 0}, + { def_lua_call_cmd, NULL, 0}, + { read_to_cs_cmd, NULL, 0}, + { def_cmd, NULL, 0}, + { set_box_cmd, NULL, 0}, + { hyph_data_cmd, NULL, 0}, + { set_interaction_cmd, NULL, 0}, + { letterspace_font_cmd, NULL, 0}, + { expand_font_cmd, NULL, 0}, + { copy_font_cmd, NULL, 0}, + { set_font_id_cmd, NULL, 0}, + { undefined_cs_cmd, NULL, 0}, + { expand_after_cmd, NULL, 0}, + { no_expand_cmd, NULL, 0}, + { input_cmd, NULL, 0}, + { lua_expandable_call_cmd, NULL, 0}, + { lua_local_call_cmd, NULL, 0}, + { if_test_cmd, NULL, 0}, + { fi_or_else_cmd, NULL, 0}, + { cs_name_cmd, NULL, 0}, + { convert_cmd, NULL, 0}, + { variable_cmd, NULL, 0}, + { feedback_cmd, NULL, 0}, + { the_cmd, NULL, 0}, + { combine_toks_cmd, NULL, 0}, + { top_bot_mark_cmd, NULL, 0}, + { call_cmd, NULL, 0}, + { long_call_cmd, NULL, 0}, + { outer_call_cmd, NULL, 0}, + { long_outer_call_cmd, NULL, 0}, + { end_template_cmd, NULL, 0}, + { dont_expand_cmd, NULL, 0}, + { glue_ref_cmd, NULL, 0}, + { shape_ref_cmd, NULL, 0}, + { box_ref_cmd, NULL, 0}, + { data_cmd, NULL, 0}, + { -1, NULL, 0} +}; + +# define init_token_key(target,n,key) \ + target[n].lua = luaS_##key##_index; \ + target[n].name = luaS_##key##_ptr; + +void l_set_token_data(void) +{ + init_token_key(command_names, relax_cmd, relax); + init_token_key(command_names, left_brace_cmd, left_brace); + init_token_key(command_names, right_brace_cmd, right_brace); + init_token_key(command_names, math_shift_cmd, math_shift); + init_token_key(command_names, tab_mark_cmd, tab_mark); + init_token_key(command_names, car_ret_cmd, car_ret); + init_token_key(command_names, mac_param_cmd, mac_param); + init_token_key(command_names, sup_mark_cmd, sup_mark); + init_token_key(command_names, sub_mark_cmd, sub_mark); + init_token_key(command_names, endv_cmd, endv); + init_token_key(command_names, spacer_cmd, spacer); + init_token_key(command_names, letter_cmd, letter); + init_token_key(command_names, other_char_cmd, other_char); + init_token_key(command_names, par_end_cmd, par_end); + init_token_key(command_names, stop_cmd, stop); + init_token_key(command_names, delim_num_cmd, delim_num); + init_token_key(command_names, char_num_cmd, char_num); + init_token_key(command_names, math_char_num_cmd, math_char_num); + init_token_key(command_names, mark_cmd, mark); + init_token_key(command_names, node_cmd, node); + init_token_key(command_names, xray_cmd, xray); + init_token_key(command_names, make_box_cmd, make_box); + init_token_key(command_names, hmove_cmd, hmove); + init_token_key(command_names, vmove_cmd, vmove); + init_token_key(command_names, un_hbox_cmd, un_hbox); + init_token_key(command_names, un_vbox_cmd, un_vbox); + init_token_key(command_names, remove_item_cmd, remove_item); + init_token_key(command_names, hskip_cmd, hskip); + init_token_key(command_names, vskip_cmd, vskip); + init_token_key(command_names, mskip_cmd, mskip); + init_token_key(command_names, kern_cmd, kern); + init_token_key(command_names, mkern_cmd, mkern); + init_token_key(command_names, leader_ship_cmd, leader_ship); + init_token_key(command_names, halign_cmd, halign); + init_token_key(command_names, valign_cmd, valign); + init_token_key(command_names, no_align_cmd, no_align); + init_token_key(command_names, vrule_cmd, vrule); + init_token_key(command_names, hrule_cmd, hrule); + init_token_key(command_names, no_vrule_cmd, novrule); + init_token_key(command_names, no_hrule_cmd, nohrule); + init_token_key(command_names, insert_cmd, insert); + init_token_key(command_names, vadjust_cmd, vadjust); + init_token_key(command_names, ignore_spaces_cmd, ignore_spaces); + init_token_key(command_names, after_assignment_cmd, after_assignment); + init_token_key(command_names, after_group_cmd, after_group); + init_token_key(command_names, break_penalty_cmd, break_penalty); + init_token_key(command_names, start_par_cmd, start_par); + init_token_key(command_names, ital_corr_cmd, ital_corr); + init_token_key(command_names, accent_cmd, accent); + init_token_key(command_names, math_accent_cmd, math_accent); + init_token_key(command_names, discretionary_cmd, discretionary); + init_token_key(command_names, eq_no_cmd, eq_no); + init_token_key(command_names, left_right_cmd, left_right); + init_token_key(command_names, math_comp_cmd, math_comp); + init_token_key(command_names, limit_switch_cmd, limit_switch); + init_token_key(command_names, above_cmd, above); + init_token_key(command_names, math_style_cmd, math_style); + init_token_key(command_names, math_choice_cmd, math_choice); + init_token_key(command_names, non_script_cmd, non_script); + init_token_key(command_names, vcenter_cmd, vcenter); + init_token_key(command_names, case_shift_cmd, case_shift); + init_token_key(command_names, message_cmd, message); + init_token_key(command_names, normal_cmd, normal); + init_token_key(command_names, extension_cmd, extension); + init_token_key(command_names, option_cmd, option); + init_token_key(command_names, lua_function_call_cmd, lua_function_call); + init_token_key(command_names, lua_bytecode_call_cmd, lua_bytecode_call); + init_token_key(command_names, lua_call_cmd, lua_call); + init_token_key(command_names, in_stream_cmd, in_stream); + init_token_key(command_names, begin_group_cmd, begin_group); + init_token_key(command_names, end_group_cmd, end_group); + init_token_key(command_names, omit_cmd, omit); + init_token_key(command_names, ex_space_cmd, ex_space); + init_token_key(command_names, boundary_cmd, boundary); + init_token_key(command_names, radical_cmd, radical); + init_token_key(command_names, super_sub_script_cmd, super_sub_script); + init_token_key(command_names, no_super_sub_script_cmd, no_super_sub_script); + init_token_key(command_names, math_shift_cs_cmd, math_shift_cs); + init_token_key(command_names, end_cs_name_cmd, end_cs_name); + init_token_key(command_names, char_ghost_cmd, char_ghost); + init_token_key(command_names, assign_local_box_cmd, assign_local_box); + init_token_key(command_names, char_given_cmd, char_given); + init_token_key(command_names, math_given_cmd, math_given); + init_token_key(command_names, xmath_given_cmd, xmath_given); + init_token_key(command_names, last_item_cmd, last_item); + init_token_key(command_names, toks_register_cmd, toks_register); + init_token_key(command_names, assign_toks_cmd, assign_toks); + init_token_key(command_names, assign_int_cmd, assign_int); + init_token_key(command_names, assign_attr_cmd, assign_attr); + init_token_key(command_names, assign_dimen_cmd, assign_dimen); + init_token_key(command_names, assign_glue_cmd, assign_glue); + init_token_key(command_names, assign_mu_glue_cmd, assign_mu_glue); + init_token_key(command_names, assign_font_dimen_cmd, assign_font_dimen); + init_token_key(command_names, assign_font_int_cmd, assign_font_int); + init_token_key(command_names, assign_hang_indent_cmd, assign_hang_indent); + init_token_key(command_names, set_aux_cmd, set_aux); + init_token_key(command_names, set_prev_graf_cmd, set_prev_graf); + init_token_key(command_names, set_page_dimen_cmd, set_page_dimen); + init_token_key(command_names, set_page_int_cmd, set_page_int); + init_token_key(command_names, set_box_dimen_cmd, set_box_dimen); + init_token_key(command_names, set_tex_shape_cmd, set_tex_shape); + init_token_key(command_names, set_etex_shape_cmd, set_etex_shape); + init_token_key(command_names, def_char_code_cmd, def_char_code); + init_token_key(command_names, def_del_code_cmd, def_del_code); + init_token_key(command_names, extdef_math_code_cmd, extdef_math_code); + init_token_key(command_names, extdef_del_code_cmd, extdef_del_code); + init_token_key(command_names, def_family_cmd, def_family); + init_token_key(command_names, set_math_param_cmd, set_math_param); + init_token_key(command_names, set_font_cmd, set_font); + init_token_key(command_names, def_font_cmd, def_font); + init_token_key(command_names, def_lua_call_cmd, def_lua_call); + init_token_key(command_names, register_cmd, register); + init_token_key(command_names, assign_box_direction_cmd, assign_box_direction); + init_token_key(command_names, assign_box_dir_cmd, assign_box_dir); + init_token_key(command_names, assign_direction_cmd, assign_direction); + init_token_key(command_names, assign_dir_cmd, assign_dir); + init_token_key(command_names, advance_cmd, advance); + init_token_key(command_names, multiply_cmd, multiply); + init_token_key(command_names, divide_cmd, divide); + init_token_key(command_names, prefix_cmd, prefix); + init_token_key(command_names, let_cmd, let); + init_token_key(command_names, shorthand_def_cmd, shorthand_def); + init_token_key(command_names, read_to_cs_cmd, read_to_cs); + init_token_key(command_names, def_cmd, def); + init_token_key(command_names, set_box_cmd, set_box); + init_token_key(command_names, hyph_data_cmd, hyph_data); + init_token_key(command_names, set_interaction_cmd, set_interaction); + init_token_key(command_names, letterspace_font_cmd, letterspace_font); + init_token_key(command_names, expand_font_cmd, expand_font); + init_token_key(command_names, copy_font_cmd, copy_font); + init_token_key(command_names, set_font_id_cmd, set_font_id); + init_token_key(command_names, undefined_cs_cmd, undefined_cs); + init_token_key(command_names, expand_after_cmd, expand_after); + init_token_key(command_names, no_expand_cmd, no_expand); + init_token_key(command_names, input_cmd, input); + init_token_key(command_names, lua_expandable_call_cmd, lua_expandable_call); + init_token_key(command_names, lua_local_call_cmd, lua_local_call); + init_token_key(command_names, if_test_cmd, if_test); + init_token_key(command_names, fi_or_else_cmd, fi_or_else); + init_token_key(command_names, cs_name_cmd, cs_name); + init_token_key(command_names, convert_cmd, convert); + init_token_key(command_names, variable_cmd, variable); + init_token_key(command_names, feedback_cmd, feedback); + init_token_key(command_names, the_cmd, the); + init_token_key(command_names, combine_toks_cmd, combinetoks); + init_token_key(command_names, top_bot_mark_cmd, top_bot_mark); + init_token_key(command_names, call_cmd, call); + init_token_key(command_names, long_call_cmd, long_call); + init_token_key(command_names, outer_call_cmd, outer_call); + init_token_key(command_names, long_outer_call_cmd, long_outer_call); + init_token_key(command_names, end_template_cmd, end_template); + init_token_key(command_names, dont_expand_cmd, dont_expand); + init_token_key(command_names, glue_ref_cmd, glue_ref); + init_token_key(command_names, shape_ref_cmd, shape_ref); + init_token_key(command_names, box_ref_cmd, box_ref); + init_token_key(command_names, data_cmd, data); +} + +int get_command_id(const char *s) +{ + int i; + for (i = 0; command_names[i].id != -1; i++) { + if (s == command_names[i].name) + return i; + } + return -1; +} + +/* +static int get_cur_cmd(lua_State * L) +{ + int r = 0; + size_t len = lua_rawlen(L, -1); + cur_cs = 0; + if (len == 3 || len == 2) { + r = 1; + lua_rawgeti(L, -1, 1); + cur_cmd = (int) lua_tointeger(L, -1); + lua_rawgeti(L, -2, 2); + cur_chr = (halfword) lua_tointeger(L, -1); + if (len == 3) { + lua_rawgeti(L, -3, 3); + cur_cs = (halfword) lua_tointeger(L, -1); + } + lua_pop(L, (int) len); + if (cur_cs == 0) + cur_tok = token_val(cur_cmd, cur_chr); + else + cur_tok = cs_token_flag + cur_cs; + } + return r; +} +*/ + +static int token_from_lua(lua_State * L) +{ + int cmd, chr; + int cs = 0; + size_t len = lua_rawlen(L, -1); + if (len == 3 || len == 2) { + lua_rawgeti(L, -1, 1); + cmd = (int) lua_tointeger(L, -1); + lua_rawgeti(L, -2, 2); + chr = (int) lua_tointeger(L, -1); + if (len == 3) { + lua_rawgeti(L, -3, 3); + cs = (int) lua_tointeger(L, -1); + } + lua_pop(L, (int) len); + if (cs == 0) { + return token_val(cmd, chr); + } else { + return cs_token_flag + cs; + } + } + return -1; +} + +/* +static int get_cur_cs(lua_State * L) +{ + const char *s; + unsigned j; + size_t l; + int cs; + int save_nncs; + int ret; + ret = 0; + cur_cs = 0; + lua_getfield(L, -1, "name"); + if (lua_type(L, -1) == LUA_TSTRING) { + s = lua_tolstring(L, -1, &l); + if (l > 0) { + if ((last + (int) l) > buf_size) + check_buffer_overflow((last + (int) l)); + for (j = 0; j < l; j++) { + buffer[(unsigned) last + 1 + j] = (packed_ASCII_code) * s++; + } + save_nncs = no_new_control_sequence; + no_new_control_sequence = false; + cs = id_lookup((last + 1), (int) l); + cur_tok = cs_token_flag + cs; + cur_cmd = eq_type(cs); + cur_chr = equiv(cs); + no_new_control_sequence = save_nncs; + ret = 1; + } + } + lua_pop(L, 1); + return ret; +} +*/ + +void tokenlist_to_lua(lua_State * L, int p) +{ + int cmd, chr, cs; + int v; + int i = 1; + v = p; + while (v != null && v < (int) fix_mem_end) { + i++; + v = token_link(v); + } + i = 1; + lua_createtable(L, i, 0); + while (p != null && p < (int) fix_mem_end) { + if (token_info(p) >= cs_token_flag) { + cs = token_info(p) - cs_token_flag; + cmd = eq_type(cs); + chr = equiv(cs); + make_token_table(L, cmd, chr, cs); + } else { + cmd = token_cmd(token_info(p)); + chr = token_chr(token_info(p)); + make_token_table(L, cmd, chr, 0); + } + lua_rawseti(L, -2, i++); + p = token_link(p); + } +} + +void tokenlist_to_luastring(lua_State * L, int p) +{ + int l; + char *s; + s = tokenlist_to_cstring(p, 1, &l); + lua_pushlstring(L, s, (size_t) l); + free(s); +} + +int tokenlist_from_lua(lua_State * L) +{ + const char *s; + int tok, t; + size_t i, j; + halfword p, q, r; + r = get_avail(); + token_info(r) = 0; + token_link(r) = null; + p = r; + t = lua_type(L, -1); + if (t == LUA_TTABLE) { + j = lua_rawlen(L, -1); + if (j > 0) { + for (i = 1; i <= j; i++) { + lua_rawgeti(L, -1, (int) i); + tok = token_from_lua(L); + if (tok >= 0) { + store_new_token(tok); + } + lua_pop(L, 1); + }; + } + return r; + } else if (t == LUA_TSTRING) { + s = lua_tolstring(L, -1, &j); + for (i = 0; i < j; i++) { + if (s[i] == 32) { + tok = token_val(10, s[i]); + } else { + int j1 = (int) str2uni((const unsigned char *) (s + i)); + i = i + (size_t) (utf8_size(j1) - 1); + tok = token_val(12, j1); + } + store_new_token(tok); + } + return r; + } else { + free_avail(r); + return null; + } +} + +/* +static void do_get_token_lua(int callback_id) +{ + while (1) { + if (!get_callback(Luas, callback_id)) { + get_next(); + lua_pop(Luas, 2); + break; + } + if (lua_pcall(Luas, 0, 1, 0) != 0) { + tex_error(lua_tostring(Luas, -1), NULL); + lua_pop(Luas, 2); + break; + } + if (lua_istable(Luas, -1)) { + lua_rawgeti(Luas, -1, 1); + if (lua_istable(Luas, -1)) { + int p, q, r; + size_t i, j; + lua_pop(Luas, 1); + r = get_avail(); + p = r; + j = lua_rawlen(Luas, -1); + if (j > 0) { + for (i = 1; i <= j; i++) { + lua_rawgeti(Luas, -1, (int) i); + if (get_cur_cmd(Luas) || get_cur_cs(Luas)) { + store_new_token(cur_tok); + } + lua_pop(Luas, 1); + } + } + if (p != r) { + p = token_link(r); + free_avail(r); + begin_token_list(p, inserted); + cur_input.nofilter_field = true; + get_next(); + } else { + tex_error("error: illegal or empty token list returned", NULL); + } + lua_pop(Luas, 2); + break; + } else { + lua_pop(Luas, 1); + if (get_cur_cmd(Luas) || get_cur_cs(Luas)) { + lua_pop(Luas, 2); + break; + } else { + lua_pop(Luas, 2); + continue; + } + } + } else { + lua_pop(Luas, 2); + } + } + return; +} +*/ diff --git a/Build/source/texk/web2c/luatexdir/lua/luatoken.w b/Build/source/texk/web2c/luatexdir/lua/luatoken.w deleted file mode 100644 index e9740ffc676..00000000000 --- a/Build/source/texk/web2c/luatexdir/lua/luatoken.w +++ /dev/null @@ -1,424 +0,0 @@ -% luatoken.w -% -% Copyright 2006-2012 Taco Hoekwater <taco@@luatex.org> -% -% This file is part of LuaTeX. -% -% LuaTeX is free software; you can redistribute it and/or modify it under -% the terms of the GNU General Public License as published by the Free -% Software Foundation; either version 2 of the License, or (at your -% option) any later version. -% -% LuaTeX is distributed in the hope that it will be useful, but WITHOUT -% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -% License for more details. -% -% You should have received a copy of the GNU General Public License along -% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -@ @c - -#include "ptexlib.h" -#include "lua/luatex-api.h" - -@ @c -command_item command_names[] = { - {"relax", relax_cmd, NULL}, - {"left_brace", left_brace_cmd, NULL}, - {"right_brace", right_brace_cmd, NULL}, - {"math_shift", math_shift_cmd, NULL}, - {"tab_mark", tab_mark_cmd, NULL}, - {"car_ret", car_ret_cmd, NULL}, - {"mac_param", mac_param_cmd, NULL}, - {"sup_mark", sup_mark_cmd, NULL}, - {"sub_mark", sub_mark_cmd, NULL}, - {"endv", endv_cmd, NULL}, - {"spacer", spacer_cmd, NULL}, - {"letter", letter_cmd, NULL}, - {"other_char", other_char_cmd, NULL}, - {"par_end", par_end_cmd, NULL}, - {"stop", stop_cmd, NULL}, - {"delim_num", delim_num_cmd, NULL}, - {"char_num", char_num_cmd, NULL}, - {"math_char_num", math_char_num_cmd, NULL}, - {"mark", mark_cmd, NULL}, - {"xray", xray_cmd, NULL}, - {"make_box", make_box_cmd, NULL}, - {"hmove", hmove_cmd, NULL}, - {"vmove", vmove_cmd, NULL}, - {"un_hbox", un_hbox_cmd, NULL}, - {"un_vbox", un_vbox_cmd, NULL}, - {"remove_item", remove_item_cmd, NULL}, - {"hskip", hskip_cmd, NULL}, - {"vskip", vskip_cmd, NULL}, - {"mskip", mskip_cmd, NULL}, - {"kern", kern_cmd, NULL}, - {"mkern", mkern_cmd, NULL}, - {"leader_ship", leader_ship_cmd, NULL}, - {"halign", halign_cmd, NULL}, - {"valign", valign_cmd, NULL}, - {"no_align", no_align_cmd, NULL}, - {"novrule", no_vrule_cmd, NULL}, - {"nohrule", no_hrule_cmd, NULL}, - {"vrule", vrule_cmd, NULL}, - {"hrule", hrule_cmd, NULL}, - {"insert", insert_cmd, NULL}, - {"vadjust", vadjust_cmd, NULL}, - {"ignore_spaces", ignore_spaces_cmd, NULL}, - {"after_assignment", after_assignment_cmd, NULL}, - {"after_group", after_group_cmd, NULL}, - {"break_penalty", break_penalty_cmd, NULL}, - {"start_par", start_par_cmd, NULL}, - {"ital_corr", ital_corr_cmd, NULL}, - {"accent", accent_cmd, NULL}, - {"math_accent", math_accent_cmd, NULL}, - {"discretionary", discretionary_cmd, NULL}, - {"eq_no", eq_no_cmd, NULL}, - {"left_right", left_right_cmd, NULL}, - {"math_comp", math_comp_cmd, NULL}, - {"limit_switch", limit_switch_cmd, NULL}, - {"above", above_cmd, NULL}, - {"math_style", math_style_cmd, NULL}, - {"math_choice", math_choice_cmd, NULL}, - {"non_script", non_script_cmd, NULL}, - {"vcenter", vcenter_cmd, NULL}, - {"case_shift", case_shift_cmd, NULL}, - {"message", message_cmd, NULL}, - {"normal", normal_cmd, NULL}, - {"extension", extension_cmd, NULL}, - {"option", option_cmd, NULL}, - {"in_stream", in_stream_cmd, NULL}, - {"begin_group", begin_group_cmd, NULL}, - {"end_group", end_group_cmd, NULL}, - {"omit", omit_cmd, NULL}, - {"ex_space", ex_space_cmd, NULL}, - {"boundary", boundary_cmd, NULL}, - {"radical", radical_cmd, NULL}, - {"super_sub_script", super_sub_script_cmd, NULL}, - {"no_super_sub_script", no_super_sub_script_cmd, NULL}, - {"math_shift_cs", math_shift_cs_cmd, NULL}, - {"end_cs_name", end_cs_name_cmd, NULL}, - {"char_ghost", char_ghost_cmd, NULL}, - {"assign_local_box", assign_local_box_cmd, NULL}, - {"char_given", char_given_cmd, NULL}, - {"math_given", math_given_cmd, NULL}, - {"xmath_given", xmath_given_cmd, NULL}, - {"last_item", last_item_cmd, NULL}, - {"toks_register", toks_register_cmd, NULL}, - {"assign_toks", assign_toks_cmd, NULL}, - {"assign_int", assign_int_cmd, NULL}, - {"assign_attr", assign_attr_cmd, NULL}, - {"assign_dimen", assign_dimen_cmd, NULL}, - {"assign_glue", assign_glue_cmd, NULL}, - {"assign_mu_glue", assign_mu_glue_cmd, NULL}, - {"assign_font_dimen", assign_font_dimen_cmd, NULL}, - {"assign_font_int", assign_font_int_cmd, NULL}, - {"assign_hang_indent", assign_hang_indent_cmd, NULL}, - {"set_aux", set_aux_cmd, NULL}, - {"set_prev_graf", set_prev_graf_cmd, NULL}, - {"set_page_dimen", set_page_dimen_cmd, NULL}, - {"set_page_int", set_page_int_cmd, NULL}, - {"set_box_dimen", set_box_dimen_cmd, NULL}, - {"set_tex_shape", set_tex_shape_cmd, NULL}, - {"set_etex_shape", set_etex_shape_cmd, NULL}, - {"def_char_code", def_char_code_cmd, NULL}, - {"def_del_code", def_del_code_cmd, NULL}, - {"extdef_math_code", extdef_math_code_cmd, NULL}, - {"extdef_del_code", extdef_del_code_cmd, NULL}, - {"def_family", def_family_cmd, NULL}, - {"set_math_param", set_math_param_cmd, NULL}, - {"set_font", set_font_cmd, NULL}, - {"def_font", def_font_cmd, NULL}, - {"register", register_cmd, NULL}, - {"assign_box_dir", assign_box_dir_cmd, NULL}, - {"assign_dir", assign_dir_cmd, NULL}, - {"advance", advance_cmd, NULL}, - {"multiply", multiply_cmd, NULL}, - {"divide", divide_cmd, NULL}, - {"prefix", prefix_cmd, NULL}, - {"let", let_cmd, NULL}, - {"shorthand_def", shorthand_def_cmd, NULL}, - {"read_to_cs", read_to_cs_cmd, NULL}, - {"def", def_cmd, NULL}, - {"set_box", set_box_cmd, NULL}, - {"hyph_data", hyph_data_cmd, NULL}, - {"set_interaction", set_interaction_cmd, NULL}, - {"letterspace_font", letterspace_font_cmd, NULL}, - {"expand_font",expand_font_cmd, NULL}, - {"copy_font", copy_font_cmd, NULL}, - {"set_font_id", set_font_id_cmd, NULL}, - {"undefined_cs", undefined_cs_cmd, NULL}, - {"expand_after", expand_after_cmd, NULL}, - {"no_expand", no_expand_cmd, NULL}, - {"input", input_cmd, NULL}, - {"if_test", if_test_cmd, NULL}, - {"fi_or_else", fi_or_else_cmd, NULL}, - {"cs_name", cs_name_cmd, NULL}, - {"convert", convert_cmd, NULL}, - {"variable", variable_cmd, NULL}, - {"feedback", feedback_cmd, NULL}, - {"the", the_cmd, NULL}, - {"combinetoks", combine_toks_cmd, NULL}, - {"top_bot_mark", top_bot_mark_cmd, NULL}, - {"call", call_cmd, NULL}, - {"long_call", long_call_cmd, NULL}, - {"outer_call", outer_call_cmd, NULL}, - {"long_outer_call", long_outer_call_cmd, NULL}, - {"end_template", end_template_cmd, NULL}, - {"dont_expand", dont_expand_cmd, NULL}, - {"glue_ref", glue_ref_cmd, NULL}, - {"shape_ref", shape_ref_cmd, NULL}, - {"box_ref", box_ref_cmd, NULL}, - {"data", data_cmd, NULL}, - {NULL, 0, NULL} -}; - - -@ @c -int get_command_id(const char *s) -{ - int i; - int cmd = -1; - for (i = 0; command_names[i].cmd_name != NULL; i++) { - if (strcmp(s, command_names[i].cmd_name) == 0) - break; - } - if (command_names[i].cmd_name != NULL) { - cmd = i; - } - return cmd; -} - -/* -static int get_cur_cmd(lua_State * L) -{ - int r = 0; - size_t len = lua_rawlen(L, -1); - cur_cs = 0; - if (len == 3 || len == 2) { - r = 1; - lua_rawgeti(L, -1, 1); - cur_cmd = (int) lua_tointeger(L, -1); - lua_rawgeti(L, -2, 2); - cur_chr = (halfword) lua_tointeger(L, -1); - if (len == 3) { - lua_rawgeti(L, -3, 3); - cur_cs = (halfword) lua_tointeger(L, -1); - } - lua_pop(L, (int) len); - if (cur_cs == 0) - cur_tok = token_val(cur_cmd, cur_chr); - else - cur_tok = cs_token_flag + cur_cs; - } - return r; -} -*/ - -@ @c -static int token_from_lua(lua_State * L) -{ - int cmd, chr; - int cs = 0; - size_t len = lua_rawlen(L, -1); - if (len == 3 || len == 2) { - lua_rawgeti(L, -1, 1); - cmd = (int) lua_tointeger(L, -1); - lua_rawgeti(L, -2, 2); - chr = (int) lua_tointeger(L, -1); - if (len == 3) { - lua_rawgeti(L, -3, 3); - cs = (int) lua_tointeger(L, -1); - } - lua_pop(L, (int) len); - if (cs == 0) { - return token_val(cmd, chr); - } else { - return cs_token_flag + cs; - } - } - return -1; -} - -/* -static int get_cur_cs(lua_State * L) -{ - const char *s; - unsigned j; - size_t l; - int cs; - int save_nncs; - int ret; - ret = 0; - cur_cs = 0; - lua_getfield(L, -1, "name"); - if (lua_type(L, -1) == LUA_TSTRING) { - s = lua_tolstring(L, -1, &l); - if (l > 0) { - if ((last + (int) l) > buf_size) - check_buffer_overflow((last + (int) l)); - for (j = 0; j < l; j++) { - buffer[(unsigned) last + 1 + j] = (packed_ASCII_code) * s++; - } - save_nncs = no_new_control_sequence; - no_new_control_sequence = false; - cs = id_lookup((last + 1), (int) l); - cur_tok = cs_token_flag + cs; - cur_cmd = eq_type(cs); - cur_chr = equiv(cs); - no_new_control_sequence = save_nncs; - ret = 1; - } - } - lua_pop(L, 1); - return ret; -} -*/ - -@ @c -void tokenlist_to_lua(lua_State * L, int p) -{ - int cmd, chr, cs; - int v; - int i = 1; - v = p; - while (v != null && v < (int) fix_mem_end) { - i++; - v = token_link(v); - } - i = 1; - lua_createtable(L, i, 0); - while (p != null && p < (int) fix_mem_end) { - if (token_info(p) >= cs_token_flag) { - cs = token_info(p) - cs_token_flag; - cmd = eq_type(cs); - chr = equiv(cs); - make_token_table(L, cmd, chr, cs); - } else { - cmd = token_cmd(token_info(p)); - chr = token_chr(token_info(p)); - make_token_table(L, cmd, chr, 0); - } - lua_rawseti(L, -2, i++); - p = token_link(p); - } -} - -@ @c -void tokenlist_to_luastring(lua_State * L, int p) -{ - int l; - char *s; - s = tokenlist_to_cstring(p, 1, &l); - lua_pushlstring(L, s, (size_t) l); - free(s); -} - - -@ @c -int tokenlist_from_lua(lua_State * L) -{ - const char *s; - int tok, t; - size_t i, j; - halfword p, q, r; - r = get_avail(); - token_info(r) = 0; /* ref count */ - token_link(r) = null; - p = r; - t = lua_type(L, -1); - if (t == LUA_TTABLE) { - j = lua_rawlen(L, -1); - if (j > 0) { - for (i = 1; i <= j; i++) { - lua_rawgeti(L, -1, (int) i); - tok = token_from_lua(L); - if (tok >= 0) { - store_new_token(tok); - } - lua_pop(L, 1); - }; - } - return r; - } else if (t == LUA_TSTRING) { - s = lua_tolstring(L, -1, &j); - for (i = 0; i < j; i++) { - if (s[i] == 32) { - tok = token_val(10, s[i]); - } else { - int j1 = (int) str2uni((const unsigned char *) (s + i)); - i = i + (size_t) (utf8_size(j1) - 1); - tok = token_val(12, j1); - } - store_new_token(tok); - } - return r; - } else { - free_avail(r); - return null; - } -} - -/* - -static void do_get_token_lua(int callback_id) -{ - while (1) { - if (!get_callback(Luas, callback_id)) { - get_next(); - lua_pop(Luas, 2); - break; - } - if (lua_pcall(Luas, 0, 1, 0) != 0) { - tex_error(lua_tostring(Luas, -1), NULL); - lua_pop(Luas, 2); - break; - } - if (lua_istable(Luas, -1)) { - lua_rawgeti(Luas, -1, 1); - if (lua_istable(Luas, -1)) { - int p, q, r; - size_t i, j; - lua_pop(Luas, 1); - r = get_avail(); - p = r; - j = lua_rawlen(Luas, -1); - if (j > 0) { - for (i = 1; i <= j; i++) { - lua_rawgeti(Luas, -1, (int) i); - if (get_cur_cmd(Luas) || get_cur_cs(Luas)) { - store_new_token(cur_tok); - } - lua_pop(Luas, 1); - } - } - if (p != r) { - p = token_link(r); - free_avail(r); - begin_token_list(p, inserted); - cur_input.nofilter_field = true; - get_next(); - } else { - tex_error("error: illegal or empty token list returned", NULL); - } - lua_pop(Luas, 2); - break; - } else { - lua_pop(Luas, 1); - if (get_cur_cmd(Luas) || get_cur_cs(Luas)) { - lua_pop(Luas, 2); - break; - } else { - lua_pop(Luas, 2); - continue; - } - } - } else { - lua_pop(Luas, 2); - } - } - return; -} - -*/ diff --git a/Build/source/texk/web2c/luatexdir/lua/mplibstuff.c b/Build/source/texk/web2c/luatexdir/lua/mplibstuff.c new file mode 100644 index 00000000000..f1713ae0e6e --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/mplibstuff.c @@ -0,0 +1,115 @@ +/* + +mplibstuff.w + +Copyright 2017 LuaTeX team <bugs@@luatex.org> + +This file is part of LuaTeX. + +LuaTeX is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2 of the License, or (at your +option) any later version. + +LuaTeX is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +License for more details. + +You should have received a copy of the GNU General Public License along +with LuaTeX; if not, see <http://www.gnu.org/licenses/>. + +*/ + +/*tex + +The \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. + +*/ + +#include <stdio.h> + +extern void normal_warning(const char *t, const char *p); + +extern int lua_only; + +#define mplibstuff_message(MSG) do { \ + if (lua_only) { \ + fprintf(stdout,"mplib: " #MSG " not available.\n"); \ + } else { \ + normal_warning("mplib", #MSG " not available."); \ + } \ +} while (0) + +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); + +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); + +void *mp_initialize_binary_math(void *mp); + + +void mp_png_backend_initialize (void *mp) { return; } +void mp_png_backend_free (void *mp) { return; } +int mp_png_gr_ship_out (void *hh, void *options, int standalone) { mplibstuff_message(png backend); return 1; } +int mp_png_ship_out (void *hh, const char *options) { mplibstuff_message(png backend); return 1; } + +void mp_svg_backend_initialize (void *mp) { return; } +void mp_svg_backend_free (void *mp) { return; } +int mp_svg_ship_out (void *hh, int prologues) { mplibstuff_message(svg bakend); return 1; } +int mp_svg_gr_ship_out (void *hh, int qprologues, int standalone) { mplibstuff_message(svg backend); return 1; } + + +void *mp_initialize_binary_math(void *mp) {mplibstuff_message(math binary);return NULL; } + +const char* cairo_version_string (void); +const char* mpfr_get_version(void); +const char* pixman_version_string (void); + + +#define CAIRO_VERSION_STRING "CAIRO NOT AVAILABLE" +const char *COMPILED_CAIRO_VERSION_STRING = CAIRO_VERSION_STRING; + +#define MPFR_VERSION_STRING "MPFR NOT AVAILABLE" +const char *COMPILED_MPFR_VERSION_STRING = MPFR_VERSION_STRING; + + +#define __GNU_MP_VERSION -1 +#define __GNU_MP_VERSION_MINOR -1 +#define __GNU_MP_VERSION_PATCHLEVEL -1 +int COMPILED__GNU_MP_VERSION = __GNU_MP_VERSION ; +int COMPILED__GNU_MP_VERSION_MINOR = __GNU_MP_VERSION_MINOR ; +int COMPILED__GNU_MP_VERSION_PATCHLEVEL = __GNU_MP_VERSION_PATCHLEVEL ; +const char * const COMPILED_gmp_version="GMP NOT AVAILABLE"; + +#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* mpfr_get_version(void) +{ + return MPFR_VERSION_STRING; +} + +const char* pixman_version_string (void) +{ + return PIXMAN_VERSION_STRING; +} + +char png_libpng_ver[] = "PNG NOT AVAILABLE"; + + + diff --git a/Build/source/texk/web2c/luatexdir/lua/mplibstuff.w b/Build/source/texk/web2c/luatexdir/lua/mplibstuff.w deleted file mode 100644 index 3104a287007..00000000000 --- a/Build/source/texk/web2c/luatexdir/lua/mplibstuff.w +++ /dev/null @@ -1,93 +0,0 @@ -% mplibstuff.w -% -% Copyright 2017 LuaTeX team <bugs@@luatex.org> -% -% This file is part of LuaTeX. -% -% LuaTeX is free software; you can redistribute it and/or modify it under -% the terms of the GNU General Public License as published by the Free -% Software Foundation; either version 2 of the License, or (at your -% option) any later version. -% -% LuaTeX is distributed in the hope that it will be useful, but WITHOUT -% ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -% FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -% License for more details. -% -% You should have received a copy of the GNU General Public License along -% with LuaTeX; if not, see <http://www.gnu.org/licenses/>. - -@ PNG and SVG backends are not available in \LuaTeX, because it's complex -to manage the math formulas at run time. In this respect |PostScript| and the highlevel |objects| -are better, and they are the standard way. Another problem is how to emit the warning: -the |normal\_warning| function is not available when \LuaTeX\ is called as LUA only. - - - -@c -#include <stdio.h> - -extern void normal_warning(const char *t, const char *p); -extern int lua_only; -#define mplibstuff_message(BACKEND) do { \ - if (lua_only) { \ - fprintf(stdout,"mplib: " #BACKEND " backend not available.\n"); \ - } else { \ - normal_warning("mplib", #BACKEND " backend not available."); \ - } \ -} while (0) - - -@ @c -void mp_png_backend_initialize (void *mp); -void mp_png_backend_free (void *mp); -int mp_png_gr_ship_out (void *hh, void *options, int standalone); -int mp_png_ship_out (void *hh, const char *options); - -@ @c -void mp_svg_backend_initialize (void *mp); -void mp_svg_backend_free (void *mp); -int mp_svg_ship_out (void *hh, int prologues); -int mp_svg_gr_ship_out (void *hh, int qprologues, int standalone); - -@ @c -void mp_png_backend_initialize (void *mp) {return; } /*{mplibstuff_message(1png);return;}*/ -void mp_png_backend_free (void *mp) {return; } /*{mplibstuff_message(png);return;}*/ -int mp_png_gr_ship_out (void *hh, void *options, int standalone) {mplibstuff_message(png);return 1;} -int mp_png_ship_out (void *hh, const char *options) {mplibstuff_message(png);return 1;} - -@ @c -void mp_svg_backend_initialize (void *mp) {return;} /*{mplibstuff_message(svg);return;}*/ -void mp_svg_backend_free (void *mp) {return;} /*{mplibstuff_message(svg);return;}*/ -int mp_svg_ship_out (void *hh, int prologues) {mplibstuff_message(svg);return 1;} -int mp_svg_gr_ship_out (void *hh, int qprologues, int standalone) {mplibstuff_message(svg);return 1;} - -@ @c -const char* -cairo_version_string (void); -const char* -pixman_version_string (void); -#define CAIRO_VERSION_STRING "CAIRO NOT AVAILABLE" -const char *COMPILED_CAIRO_VERSION_STRING = CAIRO_VERSION_STRING; -#define PIXMAN_VERSION_STRING "PIXMAN NOT AVAILABLE" -const char *COMPILED_PIXMAN_VERSION_STRING = PIXMAN_VERSION_STRING; - -const char* -cairo_version_string (void) -{ - return CAIRO_VERSION_STRING; -} - -const char* -pixman_version_string (void) -{ - return PIXMAN_VERSION_STRING; -} - - - - - -@ @c -char png_libpng_ver[] = "PNG NOT AVAILABLE"; - diff --git a/Build/source/texk/web2c/luatexdir/lua/texluac.c b/Build/source/texk/web2c/luatexdir/lua/texluac.c new file mode 100644 index 00000000000..61016cfdb5b --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/texluac.c @@ -0,0 +1,532 @@ +/* + +texluac.w + +Copyright (C) 1994-2007 Lua.org, PUC-Rio. All rights reserved. +Copyright 2006-2013 Taco Hoekwater <taco@@luatex.org> + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +This file is part of LuaTeX. + +*/ + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define luac_c +#define LUA_CORE + +#include "lua.h" +#include "lauxlib.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstring.h" +#include "lundump.h" + +#include "lua/luatex-api.h" + +static void PrintFunction(const Proto* f, int full); + +#define luaU_print PrintFunction + +/*tex A fix for non-gcc compilation: */ + +#if !defined(__GNUC__) || (__GNUC__ < 2) +# define __attribute__(x) +#endif + +/*tex default program name */ + +#define PROGNAME "texluac" + +/*tex default output file */ + +#define OUTPUT PROGNAME ".out" + +/*tex list bytecodes? */ + +static int listing = 0; + +/*tex dump bytecodes? */ + +static int dumping = 1; + +/*tex strip debug information? */ + +static int stripping = 0; + +/*tex default output file name */ + +static char Output[] = { OUTPUT }; + +/*tex actual output file name */ + +static const char *output = Output; + +/*tex actual program name */ + +static const char *progname = PROGNAME; + +__attribute__ ((noreturn)) +static void fatal(const char *message) { + fprintf(stderr,"%s: %s\n",progname,message); + exit(EXIT_FAILURE); +} + +__attribute__ ((noreturn)) +static void cannot(const char *what) { + fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); + exit(EXIT_FAILURE); +} + +__attribute__ ((noreturn)) +static void usage(const char* message) +{ + if (*message=='-') + fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); + else + fprintf(stderr,"%s: %s\n",progname,message); + fprintf(stderr, + "usage: %s [options] [filenames]\n" + "Available options are:\n" + " -l list (use -l -l for full listing)\n" + " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" + " -p parse only\n" + " -s strip debug information\n" + " -v show version information\n" + " -- stop handling options\n" + " - stop handling options and process stdin\n" + ,progname,Output); + exit(EXIT_FAILURE); +} + +#define IS(s) (strcmp(argv[i],s)==0) + +static int doargs(int argc, char* argv[]) +{ + int i; + int version=0; + if (argv[0]!=NULL && *argv[0]!=0) + progname=argv[0]; + for (i=1; i<argc; i++) { + if (*argv[i]!='-') { + /* end of options; keep it */ + break; + } else if (IS("--")) { + /* end of options; skip it */ + ++i; + if (version) ++version; + break; + } else if (IS("-")) { + /* end of options; use stdin */ + break; + } else if (IS("-l")) { + /* list */ + ++listing; + } else if (IS("-o")) { + /* output file */ + output=argv[++i]; + if (output==NULL || *output==0 || (*output=='-' && output[1]!=0)) + usage(LUA_QL("-o") " needs argument"); + if (IS("-")) + output=NULL; + } else if (IS("-p")) { + /* parse only */ + dumping=0; + } else if (IS("-s")) { + /* strip debug information */ + stripping=1; + } else if (IS("-v")) { + /* show version */ + ++version; + } else { + /* unknown option */ + usage(argv[i]); + } + } + if (i==argc && (listing || !dumping)) { + dumping=0; + argv[--i]=Output; + } + if (version) { + printf("%s\n",LUA_COPYRIGHT); + if (version==argc-1) + exit(EXIT_SUCCESS); + } + return i; +} + +#define FUNCTION "(function()end)();" + +static const char* reader(lua_State *L, void *ud, size_t *size) +{ + UNUSED(L); + if ((*(int*)ud)--) { + *size=sizeof(FUNCTION)-1; + return FUNCTION; + } else { + *size=0; + return NULL; + } +} + +#define toproto(L,i) getproto(L->top+(i)) + +static const Proto* combine(lua_State* L, int n) +{ + if (n==1) { + return toproto(L,-1); + } else { + Proto* f; + int i=n; + if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) + fatal(lua_tostring(L,-1)); + f=toproto(L,-1); + for (i=0; i<n; i++) { + f->p[i]=toproto(L,i-n-1); + if (f->p[i]->sizeupvalues>0) + f->p[i]->upvalues[0].instack=0; + } + f->sizelineinfo=0; + return f; + } +} + +static int writer(lua_State* L, const void* p, size_t size, void* u) +{ + UNUSED(L); + return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); +} + +static int pmain(lua_State* L) +{ + int argc=(int)lua_tointeger(L,1); + char** argv=(char**)lua_touserdata(L,2); + const Proto* f; + int i; + if (!lua_checkstack(L,argc)) + fatal("too many input files"); + /*tex + Open standard libraries: we need to to this to keep the symbol + |luaL_openlibs|. + */ + luaL_checkversion(L); + /*tex stop collector during initialization */ + lua_gc(L, LUA_GCSTOP, 0); + /*tex open libraries */ + luaL_openlibs(L); + lua_gc(L, LUA_GCRESTART, 0); + for (i=0; i<argc; i++) { + const char* filename=IS("-") ? NULL : argv[i]; + if (luaL_loadfile(L,filename)!=LUA_OK) + fatal(lua_tostring(L,-1)); + } + f=combine(L,argc); + if (listing) + luaU_print(f,listing>1); + if (dumping) { + FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); + if (D==NULL) + cannot("open"); + lua_lock(L); + luaU_dump(L,f,writer,D,stripping); + lua_unlock(L); + if (ferror(D)) + cannot("write"); + if (fclose(D)) + cannot("close"); + } + return 0; +} + +int luac_main(int ac, char *av[]) +{ + lua_State *L; + int i = doargs(ac, av); + ac -= i; + av += i; + if (ac <= 0) + usage("no input files given"); + L=luaL_newstate(); + if (L == NULL) + fatal("not enough memory for state"); + lua_pushcfunction(L,&pmain); + lua_pushinteger(L,ac); + lua_pushlightuserdata(L,av); + if (lua_pcall(L,2,0,0)!=LUA_OK) + fatal(lua_tostring(L,-1)); + lua_close(L); + return EXIT_SUCCESS; +} + +/* + See Copyright Notice in |lua.h|. +*/ + +#define VOID(p) ((const void*)(p)) + +#if (defined(LuajitTeX)) || (LUA_VERSION_NUM == 502) +#define TSVALUE(o) rawtsvalue(o) +#endif +#if (LUA_VERSION_NUM == 503) +#define TSVALUE(o) tsvalue(o) +#endif + +static void PrintString(const TString* ts) +{ + const char* s=getstr(ts); + size_t i,n; +#if (defined(LuajitTeX)) || (LUA_VERSION_NUM == 502) + n=ts->tsv.len; +#endif +#if (LUA_VERSION_NUM == 503) + n=(ts->tt == LUA_TSHRSTR ? ts->shrlen : ts->u.lnglen); +#endif + printf("%c",'"'); + for (i=0; i<n; i++) { + int c=(int)(unsigned char)s[i]; + switch (c) { + case '"': + printf("\\\""); + break; + case '\\': + printf("\\\\"); + break; + case '\a': + printf("\\a"); + break; + case '\b': + printf("\\b"); + break; + case '\f': + printf("\\f"); + break; + case '\n': + printf("\\n"); + break; + case '\r': + printf("\\r"); + break; + case '\t': + printf("\\t"); + break; + case '\v': + printf("\\v"); + break; + default : + if (isprint(c)) + printf("%c",c); + else + printf("\\%03d",c); + break; + } + } + printf("%c",'"'); +} + +static void PrintConstant(const Proto* f, int i) +{ + const TValue* o=&f->k[i]; + switch (ttype(o)) { + case LUA_TNIL: + printf("nil"); + break; + case LUA_TBOOLEAN: + printf(bvalue(o) ? "true" : "false"); + break; + case LUA_TNUMBER: + printf(LUA_NUMBER_FMT,nvalue(o)); + break; + case LUA_TSTRING: + PrintString(TSVALUE(o)); + break; + default: + /*tex This cannot happen. */ + printf("? type=%d",ttype(o)); + break; + } +} + +#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") +#define MYK(x) (-1-(x)) + +static void PrintCode(const Proto* f) +{ + const Instruction* code=f->code; + int pc,n=f->sizecode; + for (pc=0; pc<n; pc++) { + Instruction i=code[pc]; + OpCode o=GET_OPCODE(i); + int a=GETARG_A(i); + int b=GETARG_B(i); + int c=GETARG_C(i); + int ax=GETARG_Ax(i); + int bx=GETARG_Bx(i); + int sbx=GETARG_sBx(i); + int line=getfuncline(f,pc); + printf("\t%d\t",pc+1); + if (line>0) + printf("[%d]\t",line); + else + printf("[-]\t"); + printf("%-9s\t",luaP_opnames[o]); + switch (getOpMode(o)) { + case iABC: + printf("%d",a); + if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b); + if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); + break; + case iABx: + printf("%d",a); + if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); + if (getBMode(o)==OpArgU) printf(" %d",bx); + break; + case iAsBx: + printf("%d %d",a,sbx); + break; + case iAx: + printf("%d",MYK(ax)); + break; + } + switch (o) { + case OP_LOADK: + printf("\t; "); PrintConstant(f,bx); + break; + case OP_GETUPVAL: + case OP_SETUPVAL: + printf("\t; %s",UPVALNAME(b)); + break; + case OP_GETTABUP: + printf("\t; %s",UPVALNAME(b)); + if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABUP: + printf("\t; %s",UPVALNAME(a)); + if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } + if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } + break; + case OP_GETTABLE: + case OP_SELF: + if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABLE: + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: + case OP_POW: + case OP_EQ: + case OP_LT: + case OP_LE: + if (ISK(b) || ISK(c)) { + printf("\t; "); + if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); + printf(" "); + if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); + } + break; + case OP_JMP: + case OP_FORLOOP: + case OP_FORPREP: + case OP_TFORLOOP: + printf("\t; to %d",sbx+pc+2); + break; + case OP_CLOSURE: + printf("\t; %p",VOID(f->p[bx])); + break; + case OP_SETLIST: + if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); + break; + case OP_EXTRAARG: + printf("\t; "); PrintConstant(f,ax); + break; + default: + break; + } + printf("\n"); + } +} + +#define SS(x) ((x==1)?"":"s") +#define S(x) (int)(x),SS(x) + +static void PrintHeader(const Proto* f) +{ + const char* s=f->source ? getstr(f->source) : "=?"; + if (*s=='@' || *s=='=') + s++; + else if (*s==LUA_SIGNATURE[0]) + s="(bstring)"; + else + s="(string)"; + printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", + (f->linedefined==0)?"main":"function",s, + f->linedefined,f->lastlinedefined, + S(f->sizecode),VOID(f)); + printf("%d%s param%s, %d slot%s, %d upvalue%s, ", + (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), + S(f->maxstacksize),S(f->sizeupvalues)); + printf("%d local%s, %d constant%s, %d function%s\n", + S(f->sizelocvars),S(f->sizek),S(f->sizep)); +} + +static void PrintDebug(const Proto* f) +{ + int i,n; + n=f->sizek; + printf("constants (%d) for %p:\n",n,VOID(f)); + for (i=0; i<n; i++) { + printf("\t%d\t",i+1); + PrintConstant(f,i); + printf("\n"); + } + n=f->sizelocvars; + printf("locals (%d) for %p:\n",n,VOID(f)); + for (i=0; i<n; i++) { + printf("\t%d\t%s\t%d\t%d\n", + i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); + } + n=f->sizeupvalues; + printf("upvalues (%d) for %p:\n",n,VOID(f)); + for (i=0; i<n; i++) { + printf("\t%d\t%s\t%d\t%d\n", + i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx); + } +} + +static void PrintFunction(const Proto* f, int full) +{ + int i,n=f->sizep; + PrintHeader(f); + PrintCode(f); + if (full) + PrintDebug(f); + for (i=0; i<n; i++) + PrintFunction(f->p[i],full); +} diff --git a/Build/source/texk/web2c/luatexdir/lua/texluac.w b/Build/source/texk/web2c/luatexdir/lua/texluac.w deleted file mode 100644 index 424c74c77fd..00000000000 --- a/Build/source/texk/web2c/luatexdir/lua/texluac.w +++ /dev/null @@ -1,495 +0,0 @@ -% texluac.w -% -% Copyright (C) 1994-2007 Lua.org, PUC-Rio. All rights reserved. -% Copyright 2006-2013 Taco Hoekwater <taco@@luatex.org> -% -% Permission is hereby granted, free of charge, to any person obtaining -% a copy of this software and associated documentation files (the -% "Software"), to deal in the Software without restriction, including -% without limitation the rights to use, copy, modify, merge, publish, -% distribute, sublicense, and/or sell copies of the Software, and to -% permit persons to whom the Software is furnished to do so, subject to -% the following conditions: -% -% The above copyright notice and this permission notice shall be -% included in all copies or substantial portions of the Software. -% -% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -% IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -% CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -% TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -% SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -% -% This file is part of LuaTeX. - -@ @c - - -#include <ctype.h> -#include <errno.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#define luac_c -#define LUA_CORE - -#include "lua.h" -#include "lauxlib.h" - -#include "ldebug.h" -#include "ldo.h" -#include "lfunc.h" -#include "lmem.h" -#include "lobject.h" -#include "lopcodes.h" -#include "lstring.h" -#include "lundump.h" - -#include "lua/luatex-api.h" - -static void PrintFunction(const Proto* f, int full); -#define luaU_print PrintFunction - -@ @c -/* fix for non-gcc compilation: */ -#if !defined(__GNUC__) || (__GNUC__ < 2) -# define __attribute__(x) -#endif /* !defined(__GNUC__) || (__GNUC__ < 2) */ - -@ @c -#define PROGNAME "texluac" /* default program name */ -#define OUTPUT PROGNAME ".out" /* default output file */ - -static int listing=0; /* list bytecodes? */ -static int dumping = 1; /* dump bytecodes? */ -static int stripping = 0; /* strip debug information? */ -static char Output[] = { OUTPUT }; /* default output file name */ - -static const char *output = Output; /* actual output file name */ -static const char *progname = PROGNAME; /* actual program name */ - -@ @c -__attribute__ ((noreturn)) -static void fatal(const char *message) -{ - fprintf(stderr,"%s: %s\n",progname,message); - exit(EXIT_FAILURE); -} - -@ @c -__attribute__ ((noreturn)) -static void cannot(const char *what) -{ - fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); - exit(EXIT_FAILURE); -} - -@ @c -__attribute__ ((noreturn)) -static void usage(const char* message) -{ - if (*message=='-') - fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); - else - fprintf(stderr,"%s: %s\n",progname,message); - fprintf(stderr, - "usage: %s [options] [filenames]\n" - "Available options are:\n" - " -l list (use -l -l for full listing)\n" - " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" - " -p parse only\n" - " -s strip debug information\n" - " -v show version information\n" - " -- stop handling options\n" - " - stop handling options and process stdin\n" - ,progname,Output); - exit(EXIT_FAILURE); -} - -@ @c -#define IS(s) (strcmp(argv[i],s)==0) - -static int doargs(int argc, char* argv[]) -{ - int i; - int version=0; - if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; - for (i=1; i<argc; i++) - { - if (*argv[i]!='-') /* end of options; keep it */ - break; - else if (IS("--")) /* end of options; skip it */ - { - ++i; - if (version) ++version; - break; - } - else if (IS("-")) /* end of options; use stdin */ - break; - else if (IS("-l")) /* list */ - ++listing; - else if (IS("-o")) /* output file */ - { - output=argv[++i]; - if (output==NULL || *output==0 || (*output=='-' && output[1]!=0)) - usage(LUA_QL("-o") " needs argument"); - if (IS("-")) output=NULL; - } - else if (IS("-p")) /* parse only */ - dumping=0; - else if (IS("-s")) /* strip debug information */ - stripping=1; - else if (IS("-v")) /* show version */ - ++version; - else /* unknown option */ - usage(argv[i]); - } - if (i==argc && (listing || !dumping)) - { - dumping=0; - argv[--i]=Output; - } - if (version) - { - printf("%s\n",LUA_COPYRIGHT); - if (version==argc-1) exit(EXIT_SUCCESS); - } - return i; -} - -@ @c -#define FUNCTION "(function()end)();" - -static const char* reader(lua_State *L, void *ud, size_t *size) -{ - UNUSED(L); - if ((*(int*)ud)--) - { - *size=sizeof(FUNCTION)-1; - return FUNCTION; - } - else - { - *size=0; - return NULL; - } -} - -#define toproto(L,i) getproto(L->top+(i)) - -static const Proto* combine(lua_State* L, int n) -{ - if (n==1) - return toproto(L,-1); - else - { - Proto* f; - int i=n; - if (lua_load(L,reader,&i,"=(" PROGNAME ")",NULL)!=LUA_OK) fatal(lua_tostring(L,-1)); - f=toproto(L,-1); - for (i=0; i<n; i++) - { - f->p[i]=toproto(L,i-n-1); - if (f->p[i]->sizeupvalues>0) f->p[i]->upvalues[0].instack=0; - } - f->sizelineinfo=0; - return f; - } -} - -@ @c -static int writer(lua_State* L, const void* p, size_t size, void* u) -{ - UNUSED(L); - return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); -} - -static int pmain(lua_State* L) -{ - int argc=(int)lua_tointeger(L,1); - char** argv=(char**)lua_touserdata(L,2); - const Proto* f; - int i; - if (!lua_checkstack(L,argc)) fatal("too many input files"); - /* open standard libraries: */ - /* we need to to this to keep */ - /* the symbol luaL_openlibs */ - luaL_checkversion(L); - lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ - luaL_openlibs(L); /* open libraries */ - lua_gc(L, LUA_GCRESTART, 0); - for (i=0; i<argc; i++) - { - const char* filename=IS("-") ? NULL : argv[i]; - if (luaL_loadfile(L,filename)!=LUA_OK) fatal(lua_tostring(L,-1)); - } - f=combine(L,argc); - if (listing) luaU_print(f,listing>1); - if (dumping) - { - FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); - if (D==NULL) cannot("open"); - lua_lock(L); - luaU_dump(L,f,writer,D,stripping); - lua_unlock(L); - if (ferror(D)) cannot("write"); - if (fclose(D)) cannot("close"); - } - return 0; -} - -@ @c -int luac_main(int ac, char *av[]) -{ - lua_State *L; - int i = doargs(ac, av); - ac -= i; - av += i; - if (ac <= 0) - usage("no input files given"); - L=luaL_newstate(); - if (L == NULL) - fatal("not enough memory for state"); - lua_pushcfunction(L,&pmain); - lua_pushinteger(L,ac); - lua_pushlightuserdata(L,av); - if (lua_pcall(L,2,0,0)!=LUA_OK) - fatal(lua_tostring(L,-1)); - lua_close(L); - return EXIT_SUCCESS; -} - -/* -** print bytecodes -** See Copyright Notice in lua.h -*/ - -#define VOID(p) ((const void*)(p)) - -#if (defined(LuajitTeX)) || (LUA_VERSION_NUM == 502) -#define TSVALUE(o) rawtsvalue(o) -#endif -#if (LUA_VERSION_NUM == 503) -#define TSVALUE(o) tsvalue(o) -#endif - - -static void PrintString(const TString* ts) -{ - const char* s=getstr(ts); - size_t i,n; -#if (defined(LuajitTeX)) || (LUA_VERSION_NUM == 502) - n=ts->tsv.len; -#endif -#if (LUA_VERSION_NUM == 503) - n=(ts->tt == LUA_TSHRSTR ? ts->shrlen : ts->u.lnglen); -#endif - printf("%c",'"'); - for (i=0; i<n; i++) - { - int c=(int)(unsigned char)s[i]; - switch (c) - { - case '"': printf("\\\""); break; - case '\\': printf("\\\\"); break; - case '\a': printf("\\a"); break; - case '\b': printf("\\b"); break; - case '\f': printf("\\f"); break; - case '\n': printf("\\n"); break; - case '\r': printf("\\r"); break; - case '\t': printf("\\t"); break; - case '\v': printf("\\v"); break; - default: if (isprint(c)) - printf("%c",c); - else - printf("\\%03d",c); - } - } - printf("%c",'"'); -} - -static void PrintConstant(const Proto* f, int i) -{ - const TValue* o=&f->k[i]; - switch (ttype(o)) - { - case LUA_TNIL: - printf("nil"); - break; - case LUA_TBOOLEAN: - printf(bvalue(o) ? "true" : "false"); - break; - case LUA_TNUMBER: - printf(LUA_NUMBER_FMT,nvalue(o)); - break; - case LUA_TSTRING: - PrintString(TSVALUE(o)); - break; - default: /* cannot happen */ - printf("? type=%d",ttype(o)); - break; - } -} - -#define UPVALNAME(x) ((f->upvalues[x].name) ? getstr(f->upvalues[x].name) : "-") -#define MYK(x) (-1-(x)) - -static void PrintCode(const Proto* f) -{ - const Instruction* code=f->code; - int pc,n=f->sizecode; - for (pc=0; pc<n; pc++) - { - Instruction i=code[pc]; - OpCode o=GET_OPCODE(i); - int a=GETARG_A(i); - int b=GETARG_B(i); - int c=GETARG_C(i); - int ax=GETARG_Ax(i); - int bx=GETARG_Bx(i); - int sbx=GETARG_sBx(i); - int line=getfuncline(f,pc); - printf("\t%d\t",pc+1); - if (line>0) printf("[%d]\t",line); else printf("[-]\t"); - printf("%-9s\t",luaP_opnames[o]); - switch (getOpMode(o)) - { - case iABC: - printf("%d",a); - if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (MYK(INDEXK(b))) : b); - if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (MYK(INDEXK(c))) : c); - break; - case iABx: - printf("%d",a); - if (getBMode(o)==OpArgK) printf(" %d",MYK(bx)); - if (getBMode(o)==OpArgU) printf(" %d",bx); - break; - case iAsBx: - printf("%d %d",a,sbx); - break; - case iAx: - printf("%d",MYK(ax)); - break; - } - switch (o) - { - case OP_LOADK: - printf("\t; "); PrintConstant(f,bx); - break; - case OP_GETUPVAL: - case OP_SETUPVAL: - printf("\t; %s",UPVALNAME(b)); - break; - case OP_GETTABUP: - printf("\t; %s",UPVALNAME(b)); - if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } - break; - case OP_SETTABUP: - printf("\t; %s",UPVALNAME(a)); - if (ISK(b)) { printf(" "); PrintConstant(f,INDEXK(b)); } - if (ISK(c)) { printf(" "); PrintConstant(f,INDEXK(c)); } - break; - case OP_GETTABLE: - case OP_SELF: - if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } - break; - case OP_SETTABLE: - case OP_ADD: - case OP_SUB: - case OP_MUL: - case OP_DIV: - case OP_POW: - case OP_EQ: - case OP_LT: - case OP_LE: - if (ISK(b) || ISK(c)) - { - printf("\t; "); - if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); - printf(" "); - if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); - } - break; - case OP_JMP: - case OP_FORLOOP: - case OP_FORPREP: - case OP_TFORLOOP: - printf("\t; to %d",sbx+pc+2); - break; - case OP_CLOSURE: - printf("\t; %p",VOID(f->p[bx])); - break; - case OP_SETLIST: - if (c==0) printf("\t; %d",(int)code[++pc]); else printf("\t; %d",c); - break; - case OP_EXTRAARG: - printf("\t; "); PrintConstant(f,ax); - break; - default: - break; - } - printf("\n"); - } -} - -#define SS(x) ((x==1)?"":"s") -#define S(x) (int)(x),SS(x) - -static void PrintHeader(const Proto* f) -{ - const char* s=f->source ? getstr(f->source) : "=?"; - if (*s=='@@' || *s=='=') - s++; - else if (*s==LUA_SIGNATURE[0]) - s="(bstring)"; - else - s="(string)"; - printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", - (f->linedefined==0)?"main":"function",s, - f->linedefined,f->lastlinedefined, - S(f->sizecode),VOID(f)); - printf("%d%s param%s, %d slot%s, %d upvalue%s, ", - (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), - S(f->maxstacksize),S(f->sizeupvalues)); - printf("%d local%s, %d constant%s, %d function%s\n", - S(f->sizelocvars),S(f->sizek),S(f->sizep)); -} - -static void PrintDebug(const Proto* f) -{ - int i,n; - n=f->sizek; - printf("constants (%d) for %p:\n",n,VOID(f)); - for (i=0; i<n; i++) - { - printf("\t%d\t",i+1); - PrintConstant(f,i); - printf("\n"); - } - n=f->sizelocvars; - printf("locals (%d) for %p:\n",n,VOID(f)); - for (i=0; i<n; i++) - { - printf("\t%d\t%s\t%d\t%d\n", - i,getstr(f->locvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); - } - n=f->sizeupvalues; - printf("upvalues (%d) for %p:\n",n,VOID(f)); - for (i=0; i<n; i++) - { - printf("\t%d\t%s\t%d\t%d\n", - i,UPVALNAME(i),f->upvalues[i].instack,f->upvalues[i].idx); - } -} - -static void PrintFunction(const Proto* f, int full) -{ - int i,n=f->sizep; - PrintHeader(f); - PrintCode(f); - if (full) PrintDebug(f); - for (i=0; i<n; i++) PrintFunction(f->p[i],full); -} diff --git a/Build/source/texk/web2c/luatexdir/lua/texluajitc.c b/Build/source/texk/web2c/luatexdir/lua/texluajitc.c new file mode 100644 index 00000000000..5cac5d65ab1 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/texluajitc.c @@ -0,0 +1,650 @@ +/* + + LuaJIT frontend. Runs commands, scripts, read-eval-print (REPL) etc. + Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h + + Major portions taken verbatim or adapted from the Lua interpreter. + Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h + +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define luajit_c + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" +#include "luajit.h" + +#include "lj_arch.h" + +#if LJ_TARGET_POSIX +#include <unistd.h> +#define lua_stdin_is_tty() isatty(0) +#elif LJ_TARGET_WINDOWS +#include <io.h> +#ifdef __BORLANDC__ +#define lua_stdin_is_tty() isatty(_fileno(stdin)) +#else +#define lua_stdin_is_tty() _isatty(_fileno(stdin)) +#endif +#else +#define lua_stdin_is_tty() 1 +#endif + +#if !LJ_TARGET_CONSOLE +#include <signal.h> +#endif + +#include "lua/luatex-api.h" + +static lua_State *globalL = NULL; +static const char *progname = LUA_PROGNAME; + +#if !LJ_TARGET_CONSOLE + +static void lstop(lua_State *L, lua_Debug *ar) +{ + /*tex Unused arg. */ + (void)ar; + lua_sethook(L, NULL, 0, 0); + /*tex Avoid luaL_error -- a C hook doesn't add an extra frame. */ + luaL_where(L, 0); + lua_pushfstring(L, "%sinterrupted!", lua_tostring(L, -1)); + lua_error(L); +} + +/*tex if another SIGINT happens before lstop, terminate process (default action) */ + +static void laction(int i) +{ + signal(i, SIG_DFL); + lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +} + +#endif + +static void print_usage(void) +{ + fprintf(stderr, + "usage: %s [options]... [script [args]...].\n" + "Available options are:\n" + " -e chunk Execute string " LUA_QL("chunk") ".\n" + " -l name Require library " LUA_QL("name") ".\n" + " -b ... Save or list bytecode.\n" + " -j cmd Perform LuaJIT control command.\n" + " -O[opt] Control LuaJIT optimizations.\n" + " -i Enter interactive mode after executing " LUA_QL("script") ".\n" + " -v Show version information.\n" + " -E Ignore environment variables.\n" + " -- Stop handling options.\n" + " - Execute stdin and stop handling options.\n" + , + progname); + fflush(stderr); +} + +static void l_message(const char *pname, const char *msg) +{ + if (pname) fprintf(stderr, "%s: ", pname); + fprintf(stderr, "%s\n", msg); + fflush(stderr); +} + +static int report(lua_State *L, int status) +{ + if (status && !lua_isnil(L, -1)) { + const char *msg = lua_tostring(L, -1); + if (msg == NULL) + msg = "(error object is not a string)"; + l_message(progname, msg); + lua_pop(L, 1); + } + return status; +} + +static int traceback(lua_State *L) +{ + if (!lua_isstring(L, 1)) { + /*tex Non-string error object? Try metamethod. */ + if (lua_isnoneornil(L, 1) || !luaL_callmeta(L, 1, "__tostring") || !lua_isstring(L, -1)) { + /*tex Return non-string error object. */ + return 1; + } + /*tex Replace object by result of __tostring metamethod. */ + lua_remove(L, 1); + } + luaL_traceback(L, L, lua_tostring(L, 1), 1); + return 1; +} + +static int docall(lua_State *L, int narg, int clear) +{ + int status; + /*tex function index */ + int base = lua_gettop(L) - narg; + /*tex push traceback function */ + lua_pushcfunction(L, traceback); + /*tex put it under chunk and args */ + lua_insert(L, base); +#if !LJ_TARGET_CONSOLE + signal(SIGINT, laction); +#endif + status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); +#if !LJ_TARGET_CONSOLE + signal(SIGINT, SIG_DFL); +#endif + /*tex remove traceback function */ + lua_remove(L, base); + /*tex force a complete garbage collection in case of errors */ + if (status != 0) + lua_gc(L, LUA_GCCOLLECT, 0); + return status; +} + +static void print_version(void) +{ + fputs(LUAJIT_VERSION " -- " LUAJIT_COPYRIGHT ". " LUAJIT_URL "\n", stdout); +} + +static void print_jit_status(lua_State *L) +{ + int n; + const char *s; + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + /*tex Get jit.* module table. */ + lua_getfield(L, -1, "jit"); + lua_remove(L, -2); + lua_getfield(L, -1, "status"); + lua_remove(L, -2); + n = lua_gettop(L); + lua_call(L, 0, LUA_MULTRET); + fputs(lua_toboolean(L, n) ? "JIT: ON" : "JIT: OFF", stdout); + for (n++; (s = lua_tostring(L, n)); n++) { + putc(' ', stdout); + fputs(s, stdout); + } + putc('\n', stdout); +} + +static int getargs(lua_State *L, char **argv, int n) +{ + int narg = 0; + int i; + /*tex count total number of arguments */ + while (argv[argc]) argc++; + /*tex number of arguments to the script */ + narg = argc - (n + 1); + luaL_checkstack(L, narg + 3, "too many arguments to script"); + for (i = n+1; i < argc; i++) { + lua_pushstring(L, argv[i]); + } + lua_createtable(L, narg, n + 1); + for (i = 0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i - n); + } + return narg; +} + +static int dofile(lua_State *L, const char *name) +{ + int status = luaL_loadfile(L, name) || docall(L, 0, 1); + return report(L, status); +} + +static int dostring(lua_State *L, const char *s, const char *name) +{ + int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1); + return report(L, status); +} + +static int dolibrary(lua_State *L, const char *name) +{ + lua_getglobal(L, "require"); + lua_pushstring(L, name); + return report(L, docall(L, 1, 1)); +} + +static void write_prompt(lua_State *L, int firstline) +{ + const char *p; + lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); + p = lua_tostring(L, -1); + if (p == NULL) p = firstline ? LUA_PROMPT : LUA_PROMPT2; + fputs(p, stdout); + fflush(stdout); + /*tex remove global */ + lua_pop(L, 1); +} + +static int incomplete(lua_State *L, int status) +{ + if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(L, -1, &lmsg); + const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1); + if (strstr(msg, LUA_QL("<eof>")) == tp) { + lua_pop(L, 1); + return 1; + } + } + return 0; +} + +static int pushline(lua_State *L, int firstline) +{ + char buf[LUA_MAXINPUT]; + write_prompt(L, firstline); + if (fgets(buf, LUA_MAXINPUT, stdin)) { + size_t len = strlen(buf); + if (len > 0 && buf[len-1] == '\n') + buf[len-1] = '\0'; + if (firstline && buf[0] == '=') + lua_pushfstring(L, "return %s", buf+1); + else + lua_pushstring(L, buf); + return 1; + } + return 0; +} + +static int loadline(lua_State *L) +{ + int status; + lua_settop(L, 0); + if (!pushline(L, 1)) { + /*tex no input */ + return -1; + } + for (;;) { + /*tex repeat until gets a complete line */ + status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); + /*tex cannot try to add lines? */ + if (!incomplete(L, status)) + break; + /*tex no more input? */ + if (!pushline(L, 0)) + return -1; + /*tex add a new line... */ + lua_pushliteral(L, "\n"); + /*tex ...between the two lines */ + lua_insert(L, -2); + /*tex join them */ + lua_concat(L, 3); + } + /*tex remove line */ + lua_remove(L, 1); + return status; +} + +static void dotty(lua_State *L) +{ + int status; + const char *oldprogname = progname; + progname = NULL; + while ((status = loadline(L)) != -1) { + if (status == 0) + status = docall(L, 0, 0); + report(L, status); + if (status == 0 && lua_gettop(L) > 0) { + /*tex any result to print? */ + lua_getglobal(L, "print"); + lua_insert(L, 1); + if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) + l_message(progname, + lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)", + lua_tostring(L, -1))); + } + } + /*tex clear stack */ + lua_settop(L, 0); + fputs("\n", stdout); + fflush(stdout); + progname = oldprogname; +} + +static int handle_script(lua_State *L, char **argv, int n) +{ + int status; + const char *fname; + /*tex collect arguments */ + int narg = getargs(L, argv, n); + lua_setglobal(L, "arg"); + fname = argv[n]; + if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) { + /*tex use stdin */ + fname = NULL; + } + status = luaL_loadfile(L, fname); + lua_insert(L, -(narg+1)); + if (status == 0) + status = docall(L, narg, 0); + else + lua_pop(L, narg); + return report(L, status); +} + +/*tex Load add-on module. */ + +static int loadjitmodule(lua_State *L) +{ + lua_getglobal(L, "require"); + lua_pushliteral(L, "jit."); + lua_pushvalue(L, -3); + lua_concat(L, 2); + if (lua_pcall(L, 1, 1, 0)) { + const char *msg = lua_tostring(L, -1); + if (msg && !strncmp(msg, "module ", 7)) { + err: + l_message(progname, + "unknown luaJIT command or jit.* modules not installed"); + return 1; + } else { + return report(L, 1); + } + } + lua_getfield(L, -1, "start"); + if (lua_isnil(L, -1)) + goto err; + /*tex Drop module table. */ + lua_remove(L, -2); + return 0; +} + +/*tex Run command with options. */ + +static int runcmdopt(lua_State *L, const char *opt) +{ + int narg = 0; + if (opt && *opt) { + /*tex Split arguments. */ + for (;;) { + const char *p = strchr(opt, ','); + narg++; + if (!p) + break; + if (p == opt) + lua_pushnil(L); + else + lua_pushlstring(L, opt, (size_t)(p - opt)); + opt = p + 1; + } + if (*opt) + lua_pushstring(L, opt); + else + lua_pushnil(L); + } + return report(L, lua_pcall(L, narg, 0, 0)); +} + +/*tex JIT engine control command: try jit library first or load add-on module. */ + +static int dojitcmd(lua_State *L, const char *cmd) +{ + const char *opt = strchr(cmd, '='); + lua_pushlstring(L, cmd, opt ? (size_t)(opt - cmd) : strlen(cmd)); + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + /*tex Get jit.* module table. */ + lua_getfield(L, -1, "jit"); + lua_remove(L, -2); + /*tex Lookup library function. */ + lua_pushvalue(L, -2); + lua_gettable(L, -2); + if (!lua_isfunction(L, -1)) { + /*tex Drop non-function and jit.* table, keep module name. */ + lua_pop(L, 2); + if (loadjitmodule(L)) + return 1; + } else { + /*tex Drop jit.* table. */ + lua_remove(L, -2); + } + /*tex Drop module name. */ + lua_remove(L, -2); + return runcmdopt(L, opt ? opt+1 : opt); +} + +/*tex Optimization flags. */ + +static int dojitopt(lua_State *L, const char *opt) +{ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, -1, "jit.opt"); + lua_remove(L, -2); + lua_getfield(L, -1, "start"); + lua_remove(L, -2); + return runcmdopt(L, opt); +} + +/*tex Save or list bytecode. */ + +static int dobytecode(lua_State *L, char **argv) +{ + int narg = 0; + lua_pushliteral(L, "bcsave"); + if (loadjitmodule(L)) + return 1; + if (argv[0][2]) { + narg++; + argv[0][1] = '-'; + lua_pushstring(L, argv[0]+1); + } + for (argv++; *argv != NULL; narg++, argv++) + lua_pushstring(L, *argv); + return report(L, lua_pcall(L, narg, 0, 0)); +} + +/*tex Check that argument has no extra characters at the end */ + +#define notail(x) {if ((x)[2] != '\0') return -1;} + +#define FLAGS_INTERACTIVE 1 +#define FLAGS_VERSION 2 +#define FLAGS_EXEC 4 +#define FLAGS_OPTION 8 +#define FLAGS_NOENV 16 + +static int collectargs(char **argv, int *flags) +{ + int i; + for (i = 1; argv[i] != NULL; i++) { + /*tex Not an option? */ + if (argv[i][0] != '-') + return i; + /*tex Check option. */ + switch (argv[i][1]) { + case '-': + notail(argv[i]); + return (argv[i+1] != NULL ? i+1 : 0); + case '\0': + return i; + case 'i': + notail(argv[i]); + *flags |= FLAGS_INTERACTIVE; + /*tex fallthrough */ + case 'v': + notail(argv[i]); + *flags |= FLAGS_VERSION; + break; + case 'e': + *flags |= FLAGS_EXEC; + case 'j': + /*tex LuaJIT extension */ + case 'l': + *flags |= FLAGS_OPTION; + if (argv[i][2] == '\0') { + i++; + if (argv[i] == NULL) + return -1; + } + break; + case 'O': + /*tex LuaJIT extension */ + break; + case 'b': + /*tex LuaJIT extension */ + if (*flags) return -1; + *flags |= FLAGS_EXEC; + return 0; + case 'E': + *flags |= FLAGS_NOENV; + break; + default: + /*tex invalid option */ + return -1; + } + } + return 0; +} + +static int runargs(lua_State *L, char **argv, int n) +{ + int i; + for (i = 1; i < n; i++) { + if (argv[i] == NULL) + continue; + lua_assert(argv[i][0] == '-'); + switch (argv[i][1]) { + /*tex Options */ + case 'e': { + const char *chunk = argv[i] + 2; + if (*chunk == '\0') + chunk = argv[++i]; + lua_assert(chunk != NULL); + if (dostring(L, chunk, "=(command line)") != 0) + return 1; + break; + } + case 'l': { + const char *filename = argv[i] + 2; + if (*filename == '\0') + filename = argv[++i]; + lua_assert(filename != NULL); + if (dolibrary(L, filename)) { + /*tex stop if file fails */ + return 1; + } + break; + } + case 'j': { + /*tex LuaJIT extension */ + const char *cmd = argv[i] + 2; + if (*cmd == '\0') + cmd = argv[++i]; + lua_assert(cmd != NULL); + if (dojitcmd(L, cmd)) + return 1; + break; + } + case 'O': + /*tex LuaJIT extension */ + if (dojitopt(L, argv[i] + 2)) + return 1; + break; + case 'b': + /*tex LuaJIT extension */ + return dobytecode(L, argv+i); + default: break; + } + } + return 0; +} + +static int handle_luainit(lua_State *L) +{ +#if LJ_TARGET_CONSOLE + const char *init = NULL; +#else + const char *init = getenv(LUA_INIT); +#endif + if (init == NULL) { + /*tex status OK */ + return 0; + } else if (init[0] == 64) { + return dofile(L, init+1); + } else { + return dostring(L, init, "=" LUA_INIT); + } +} + +struct Smain { + char **argv; + int argc; + int status; +}; + +static int pmain(lua_State *L) +{ + struct Smain *s = (struct Smain *)lua_touserdata(L, 1); + char **argv = s->argv; + int script; + int flags = 0; + globalL = L; + if (argv[0] && argv[0][0]) + progname = argv[0]; + /*tex linker-enforced version check */ + LUAJIT_VERSION_SYM(); + script = collectargs(argv, &flags); + if (script < 0) { + /*tex invalid args? */ + print_usage(); + s->status = 1; + return 0; + } + if ((flags & FLAGS_NOENV)) { + lua_pushboolean(L, 1); + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + } + /*tex stop collector during initialization */ + lua_gc(L, LUA_GCSTOP, 0); + /*tex open libraries */ + luaL_openlibs(L); + lua_gc(L, LUA_GCRESTART, -1); + if (!(flags & FLAGS_NOENV)) { + s->status = handle_luainit(L); + if (s->status != 0) return 0; + } + if ((flags & FLAGS_VERSION)) print_version(); + s->status = runargs(L, argv, (script > 0) ? script : s->argc); + if (s->status != 0) return 0; + if (script) { + s->status = handle_script(L, argv, script); + if (s->status != 0) return 0; + } + if ((flags & FLAGS_INTERACTIVE)) { + print_jit_status(L); + dotty(L); + } else if (script == 0 && !(flags & (FLAGS_EXEC|FLAGS_VERSION))) { + if (lua_stdin_is_tty()) { + print_version(); + print_jit_status(L); + dotty(L); + } else { + /*tex executes stdin as a file */ + dofile(L, NULL); + } + } + return 0; +} + +int luac_main(int argc, char **argv) +{ + int status; + struct Smain s; + lua_State *L = lua_open(); /* create state */ + if (L == NULL) { + l_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; + } + s.argc = argc; + s.argv = argv; + status = lua_cpcall(L, pmain, &s); + report(L, status); + lua_close(L); + return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/texluajitc.w b/Build/source/texk/web2c/luatexdir/lua/texluajitc.w deleted file mode 100644 index f54f9c8d4a4..00000000000 --- a/Build/source/texk/web2c/luatexdir/lua/texluajitc.w +++ /dev/null @@ -1,575 +0,0 @@ -/* -** LuaJIT frontend. Runs commands, scripts, read-eval-print (REPL) etc. -** Copyright (C) 2005-2012 Mike Pall. See Copyright Notice in luajit.h -** -** Major portions taken verbatim or adapted from the Lua interpreter. -** Copyright (C) 1994-2008 Lua.org, PUC-Rio. See Copyright Notice in lua.h -*/ - -@ @c -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#define luajit_c - -#include "lua.h" -#include "lauxlib.h" -#include "lualib.h" -#include "luajit.h" - -#include "lj_arch.h" - -#if LJ_TARGET_POSIX -#include <unistd.h> -#define lua_stdin_is_tty() isatty(0) -#elif LJ_TARGET_WINDOWS -#include <io.h> -#ifdef __BORLANDC__ -#define lua_stdin_is_tty() isatty(_fileno(stdin)) -#else -#define lua_stdin_is_tty() _isatty(_fileno(stdin)) -#endif -#else -#define lua_stdin_is_tty() 1 -#endif - -#if !LJ_TARGET_CONSOLE -#include <signal.h> -#endif - -#include "lua/luatex-api.h" - -static lua_State *globalL = NULL; -static const char *progname = LUA_PROGNAME; - -#if !LJ_TARGET_CONSOLE -static void lstop(lua_State *L, lua_Debug *ar) -{ - (void)ar; /* unused arg. */ - lua_sethook(L, NULL, 0, 0); - /* Avoid luaL_error -- a C hook doesn't add an extra frame. */ - luaL_where(L, 0); - lua_pushfstring(L, "%sinterrupted!", lua_tostring(L, -1)); - lua_error(L); -} - -static void laction(int i) -{ - signal(i, SIG_DFL); /* if another SIGINT happens before lstop, - terminate process (default action) */ - lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); -} -#endif - -static void print_usage(void) -{ - fprintf(stderr, - "usage: %s [options]... [script [args]...].\n" - "Available options are:\n" - " -e chunk Execute string " LUA_QL("chunk") ".\n" - " -l name Require library " LUA_QL("name") ".\n" - " -b ... Save or list bytecode.\n" - " -j cmd Perform LuaJIT control command.\n" - " -O[opt] Control LuaJIT optimizations.\n" - " -i Enter interactive mode after executing " LUA_QL("script") ".\n" - " -v Show version information.\n" - " -E Ignore environment variables.\n" - " -- Stop handling options.\n" - " - Execute stdin and stop handling options.\n" - , - progname); - fflush(stderr); -} - -static void l_message(const char *pname, const char *msg) -{ - if (pname) fprintf(stderr, "%s: ", pname); - fprintf(stderr, "%s\n", msg); - fflush(stderr); -} - -static int report(lua_State *L, int status) -{ - if (status && !lua_isnil(L, -1)) { - const char *msg = lua_tostring(L, -1); - if (msg == NULL) msg = "(error object is not a string)"; - l_message(progname, msg); - lua_pop(L, 1); - } - return status; -} - -static int traceback(lua_State *L) -{ - if (!lua_isstring(L, 1)) { /* Non-string error object? Try metamethod. */ - if (lua_isnoneornil(L, 1) || - !luaL_callmeta(L, 1, "__tostring") || - !lua_isstring(L, -1)) - return 1; /* Return non-string error object. */ - lua_remove(L, 1); /* Replace object by result of __tostring metamethod. */ - } - luaL_traceback(L, L, lua_tostring(L, 1), 1); - return 1; -} - -static int docall(lua_State *L, int narg, int clear) -{ - int status; - int base = lua_gettop(L) - narg; /* function index */ - lua_pushcfunction(L, traceback); /* push traceback function */ - lua_insert(L, base); /* put it under chunk and args */ -#if !LJ_TARGET_CONSOLE - signal(SIGINT, laction); -#endif - status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); -#if !LJ_TARGET_CONSOLE - signal(SIGINT, SIG_DFL); -#endif - lua_remove(L, base); /* remove traceback function */ - /* force a complete garbage collection in case of errors */ - if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); - return status; -} - -static void print_version(void) -{ - fputs(LUAJIT_VERSION " -- " LUAJIT_COPYRIGHT ". " LUAJIT_URL "\n", stdout); -} - -static void print_jit_status(lua_State *L) -{ - int n; - const char *s; - lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_getfield(L, -1, "jit"); /* Get jit.* module table. */ - lua_remove(L, -2); - lua_getfield(L, -1, "status"); - lua_remove(L, -2); - n = lua_gettop(L); - lua_call(L, 0, LUA_MULTRET); - fputs(lua_toboolean(L, n) ? "JIT: ON" : "JIT: OFF", stdout); - for (n++; (s = lua_tostring(L, n)); n++) { - putc(' ', stdout); - fputs(s, stdout); - } - putc('\n', stdout); -} - -static int getargs(lua_State *L, char **argv, int n) -{ - int narg; - int i; - int argc = 0; - while (argv[argc]) argc++; /* count total number of arguments */ - narg = argc - (n + 1); /* number of arguments to the script */ - luaL_checkstack(L, narg + 3, "too many arguments to script"); - for (i = n+1; i < argc; i++) - lua_pushstring(L, argv[i]); - lua_createtable(L, narg, n + 1); - for (i = 0; i < argc; i++) { - lua_pushstring(L, argv[i]); - lua_rawseti(L, -2, i - n); - } - return narg; -} - -static int dofile(lua_State *L, const char *name) -{ - int status = luaL_loadfile(L, name) || docall(L, 0, 1); - return report(L, status); -} - -static int dostring(lua_State *L, const char *s, const char *name) -{ - int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1); - return report(L, status); -} - -static int dolibrary(lua_State *L, const char *name) -{ - lua_getglobal(L, "require"); - lua_pushstring(L, name); - return report(L, docall(L, 1, 1)); -} - -static void write_prompt(lua_State *L, int firstline) -{ - const char *p; - lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); - p = lua_tostring(L, -1); - if (p == NULL) p = firstline ? LUA_PROMPT : LUA_PROMPT2; - fputs(p, stdout); - fflush(stdout); - lua_pop(L, 1); /* remove global */ -} - -static int incomplete(lua_State *L, int status) -{ - if (status == LUA_ERRSYNTAX) { - size_t lmsg; - const char *msg = lua_tolstring(L, -1, &lmsg); - const char *tp = msg + lmsg - (sizeof(LUA_QL("<eof>")) - 1); - if (strstr(msg, LUA_QL("<eof>")) == tp) { - lua_pop(L, 1); - return 1; - } - } - return 0; /* else... */ -} - -static int pushline(lua_State *L, int firstline) -{ - char buf[LUA_MAXINPUT]; - write_prompt(L, firstline); - if (fgets(buf, LUA_MAXINPUT, stdin)) { - size_t len = strlen(buf); - if (len > 0 && buf[len-1] == '\n') - buf[len-1] = '\0'; - if (firstline && buf[0] == '=') - lua_pushfstring(L, "return %s", buf+1); - else - lua_pushstring(L, buf); - return 1; - } - return 0; -} - -static int loadline(lua_State *L) -{ - int status; - lua_settop(L, 0); - if (!pushline(L, 1)) - return -1; /* no input */ - for (;;) { /* repeat until gets a complete line */ - status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); - if (!incomplete(L, status)) break; /* cannot try to add lines? */ - if (!pushline(L, 0)) /* no more input? */ - return -1; - lua_pushliteral(L, "\n"); /* add a new line... */ - lua_insert(L, -2); /* ...between the two lines */ - lua_concat(L, 3); /* join them */ - } - lua_remove(L, 1); /* remove line */ - return status; -} - -static void dotty(lua_State *L) -{ - int status; - const char *oldprogname = progname; - progname = NULL; - while ((status = loadline(L)) != -1) { - if (status == 0) status = docall(L, 0, 0); - report(L, status); - if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ - lua_getglobal(L, "print"); - lua_insert(L, 1); - if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) - l_message(progname, - lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)", - lua_tostring(L, -1))); - } - } - lua_settop(L, 0); /* clear stack */ - fputs("\n", stdout); - fflush(stdout); - progname = oldprogname; -} - -static int handle_script(lua_State *L, char **argv, int n) -{ - int status; - const char *fname; - int narg = getargs(L, argv, n); /* collect arguments */ - lua_setglobal(L, "arg"); - fname = argv[n]; - if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) - fname = NULL; /* stdin */ - status = luaL_loadfile(L, fname); - lua_insert(L, -(narg+1)); - if (status == 0) - status = docall(L, narg, 0); - else - lua_pop(L, narg); - return report(L, status); -} - -/* Load add-on module. */ -static int loadjitmodule(lua_State *L) -{ - lua_getglobal(L, "require"); - lua_pushliteral(L, "jit."); - lua_pushvalue(L, -3); - lua_concat(L, 2); - if (lua_pcall(L, 1, 1, 0)) { - const char *msg = lua_tostring(L, -1); - if (msg && !strncmp(msg, "module ", 7)) { - err: - l_message(progname, - "unknown luaJIT command or jit.* modules not installed"); - return 1; - } else { - return report(L, 1); - } - } - lua_getfield(L, -1, "start"); - if (lua_isnil(L, -1)) goto err; - lua_remove(L, -2); /* Drop module table. */ - return 0; -} - -/* Run command with options. */ -static int runcmdopt(lua_State *L, const char *opt) -{ - int narg = 0; - if (opt && *opt) { - for (;;) { /* Split arguments. */ - const char *p = strchr(opt, ','); - narg++; - if (!p) break; - if (p == opt) - lua_pushnil(L); - else - lua_pushlstring(L, opt, (size_t)(p - opt)); - opt = p + 1; - } - if (*opt) - lua_pushstring(L, opt); - else - lua_pushnil(L); - } - return report(L, lua_pcall(L, narg, 0, 0)); -} - -/* JIT engine control command: try jit library first or load add-on module. */ -static int dojitcmd(lua_State *L, const char *cmd) -{ - const char *opt = strchr(cmd, '='); - lua_pushlstring(L, cmd, opt ? (size_t)(opt - cmd) : strlen(cmd)); - lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_getfield(L, -1, "jit"); /* Get jit.* module table. */ - lua_remove(L, -2); - lua_pushvalue(L, -2); - lua_gettable(L, -2); /* Lookup library function. */ - if (!lua_isfunction(L, -1)) { - lua_pop(L, 2); /* Drop non-function and jit.* table, keep module name. */ - if (loadjitmodule(L)) - return 1; - } else { - lua_remove(L, -2); /* Drop jit.* table. */ - } - lua_remove(L, -2); /* Drop module name. */ - return runcmdopt(L, opt ? opt+1 : opt); -} - -/* Optimization flags. */ -static int dojitopt(lua_State *L, const char *opt) -{ - lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); - lua_getfield(L, -1, "jit.opt"); /* Get jit.opt.* module table. */ - lua_remove(L, -2); - lua_getfield(L, -1, "start"); - lua_remove(L, -2); - return runcmdopt(L, opt); -} - -/* Save or list bytecode. */ -static int dobytecode(lua_State *L, char **argv) -{ - int narg = 0; - lua_pushliteral(L, "bcsave"); - if (loadjitmodule(L)) - return 1; - if (argv[0][2]) { - narg++; - argv[0][1] = '-'; - lua_pushstring(L, argv[0]+1); - } - for (argv++; *argv != NULL; narg++, argv++) - lua_pushstring(L, *argv); - return report(L, lua_pcall(L, narg, 0, 0)); -} - -/* check that argument has no extra characters at the end */ -#define notail(x) {if ((x)[2] != '\0') return -1;} - -#define FLAGS_INTERACTIVE 1 -#define FLAGS_VERSION 2 -#define FLAGS_EXEC 4 -#define FLAGS_OPTION 8 -#define FLAGS_NOENV 16 - -static int collectargs(char **argv, int *flags) -{ - int i; - for (i = 1; argv[i] != NULL; i++) { - if (argv[i][0] != '-') /* Not an option? */ - return i; - switch (argv[i][1]) { /* Check option. */ - case '-': - notail(argv[i]); - return (argv[i+1] != NULL ? i+1 : 0); - case '\0': - return i; - case 'i': - notail(argv[i]); - *flags |= FLAGS_INTERACTIVE; - /* fallthrough */ - case 'v': - notail(argv[i]); - *flags |= FLAGS_VERSION; - break; - case 'e': - *flags |= FLAGS_EXEC; - case 'j': /* LuaJIT extension */ - case 'l': - *flags |= FLAGS_OPTION; - if (argv[i][2] == '\0') { - i++; - if (argv[i] == NULL) return -1; - } - break; - case 'O': break; /* LuaJIT extension */ - case 'b': /* LuaJIT extension */ - if (*flags) return -1; - *flags |= FLAGS_EXEC; - return 0; - case 'E': - *flags |= FLAGS_NOENV; - break; - default: return -1; /* invalid option */ - } - } - return 0; -} - -static int runargs(lua_State *L, char **argv, int n) -{ - int i; - for (i = 1; i < n; i++) { - if (argv[i] == NULL) continue; - lua_assert(argv[i][0] == '-'); - switch (argv[i][1]) { /* option */ - case 'e': { - const char *chunk = argv[i] + 2; - if (*chunk == '\0') chunk = argv[++i]; - lua_assert(chunk != NULL); - if (dostring(L, chunk, "=(command line)") != 0) - return 1; - break; - } - case 'l': { - const char *filename = argv[i] + 2; - if (*filename == '\0') filename = argv[++i]; - lua_assert(filename != NULL); - if (dolibrary(L, filename)) - return 1; /* stop if file fails */ - break; - } - case 'j': { /* LuaJIT extension */ - const char *cmd = argv[i] + 2; - if (*cmd == '\0') cmd = argv[++i]; - lua_assert(cmd != NULL); - if (dojitcmd(L, cmd)) - return 1; - break; - } - case 'O': /* LuaJIT extension */ - if (dojitopt(L, argv[i] + 2)) - return 1; - break; - case 'b': /* LuaJIT extension */ - return dobytecode(L, argv+i); - default: break; - } - } - return 0; -} - -static int handle_luainit(lua_State *L) -{ -#if LJ_TARGET_CONSOLE - const char *init = NULL; -#else - const char *init = getenv(LUA_INIT); -#endif - if (init == NULL) - return 0; /* status OK */ - else if (init[0] == 64) - return dofile(L, init+1); - else - return dostring(L, init, "=" LUA_INIT); -} - -struct Smain { - char **argv; - int argc; - int status; -}; - -static int pmain(lua_State *L) -{ - struct Smain *s = (struct Smain *)lua_touserdata(L, 1); - char **argv = s->argv; - int script; - int flags = 0; - globalL = L; - if (argv[0] && argv[0][0]) progname = argv[0]; - LUAJIT_VERSION_SYM(); /* linker-enforced version check */ - script = collectargs(argv, &flags); - if (script < 0) { /* invalid args? */ - print_usage(); - s->status = 1; - return 0; - } - if ((flags & FLAGS_NOENV)) { - lua_pushboolean(L, 1); - lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); - } - lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ - luaL_openlibs(L); /* open libraries */ - lua_gc(L, LUA_GCRESTART, -1); - if (!(flags & FLAGS_NOENV)) { - s->status = handle_luainit(L); - if (s->status != 0) return 0; - } - if ((flags & FLAGS_VERSION)) print_version(); - s->status = runargs(L, argv, (script > 0) ? script : s->argc); - if (s->status != 0) return 0; - if (script) { - s->status = handle_script(L, argv, script); - if (s->status != 0) return 0; - } - if ((flags & FLAGS_INTERACTIVE)) { - print_jit_status(L); - dotty(L); - } else if (script == 0 && !(flags & (FLAGS_EXEC|FLAGS_VERSION))) { - if (lua_stdin_is_tty()) { - print_version(); - print_jit_status(L); - dotty(L); - } else { - dofile(L, NULL); /* executes stdin as a file */ - } - } - return 0; -} - -int luac_main(int argc, char **argv) -{ - int status; - struct Smain s; - lua_State *L = lua_open(); /* create state */ - if (L == NULL) { - l_message(argv[0], "cannot create state: not enough memory"); - return EXIT_FAILURE; - } - s.argc = argc; - s.argv = argv; - status = lua_cpcall(L, pmain, &s); - report(L, status); - lua_close(L); - return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; -} - |