From 0b5550c241229764120d133af80a0cbab5937ddd Mon Sep 17 00:00:00 2001 From: Martin Schröder Date: Mon, 24 Mar 2008 15:47:15 +0000 Subject: First step of importing luatex (up to r1121) git-svn-id: svn://tug.org/texlive/trunk@7124 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/texk/web2c/luatexdir/lua/.indent.pro | 12 + .../source/texk/web2c/luatexdir/lua/lcallbacklib.c | 463 + Build/source/texk/web2c/luatexdir/lua/lfontlib.c | 213 + Build/source/texk/web2c/luatexdir/lua/limglib.c | 714 + Build/source/texk/web2c/luatexdir/lua/lkpselib.c | 272 + Build/source/texk/web2c/luatexdir/lua/llanglib.c | 219 + Build/source/texk/web2c/luatexdir/lua/llualib.c | 229 + Build/source/texk/web2c/luatexdir/lua/lmplib.c | 1251 + Build/source/texk/web2c/luatexdir/lua/lnodelib.c | 1967 ++ Build/source/texk/web2c/luatexdir/lua/loslibext.c | 627 + Build/source/texk/web2c/luatexdir/lua/lpdflib.c | 127 + Build/source/texk/web2c/luatexdir/lua/lstatslib.c | 211 + Build/source/texk/web2c/luatexdir/lua/ltexiolib.c | 117 + Build/source/texk/web2c/luatexdir/lua/ltexlib.c | 820 + Build/source/texk/web2c/luatexdir/lua/ltokenlib.c | 263 + Build/source/texk/web2c/luatexdir/lua/luainit.c | 520 + Build/source/texk/web2c/luatexdir/lua/luanode.c | 200 + Build/source/texk/web2c/luatexdir/lua/luastuff.c | 310 + Build/source/texk/web2c/luatexdir/lua/luatex.c | 343 + Build/source/texk/web2c/luatexdir/lua/luatoken.c | 548 + Build/source/texk/web2c/luatexdir/lua/mp.w | 26173 +++++++++++++++++++ Build/source/texk/web2c/luatexdir/lua/psout.w | 5697 ++++ Build/source/texk/web2c/luatexdir/lua/texluac.c | 199 + 23 files changed, 41495 insertions(+) create mode 100644 Build/source/texk/web2c/luatexdir/lua/.indent.pro create mode 100644 Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/lfontlib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/limglib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/lkpselib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/llanglib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/llualib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/lmplib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/lnodelib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/loslibext.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/lpdflib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/lstatslib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/ltexiolib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/ltexlib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/ltokenlib.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/luainit.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/luanode.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/luastuff.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/luatex.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/luatoken.c create mode 100644 Build/source/texk/web2c/luatexdir/lua/mp.w create mode 100644 Build/source/texk/web2c/luatexdir/lua/psout.w create mode 100644 Build/source/texk/web2c/luatexdir/lua/texluac.c (limited to 'Build/source/texk/web2c/luatexdir/lua') diff --git a/Build/source/texk/web2c/luatexdir/lua/.indent.pro b/Build/source/texk/web2c/luatexdir/lua/.indent.pro new file mode 100644 index 00000000000..e9e690f1ba8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/.indent.pro @@ -0,0 +1,12 @@ +/* $Id$ */ +--k-and-r-style +--blank-lines-after-procedures +--line-length 80 +--procnames-start-lines +--no-space-after-function-call-names +--dont-break-procedure-type +--space-after-cast +/* this does not work in indent 2.2.6 :-( */ +--no-tabs +/* this is new in indent 2.2.9 */ +--preprocessor-indentation 2 diff --git a/Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c b/Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c new file mode 100644 index 00000000000..fa207420dfb --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lcallbacklib.c @@ -0,0 +1,463 @@ +/* $Id: lcallbacklib.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + +extern int do_run_callback (int special, char *values, va_list vl); + +int callback_set[total_callbacks] = {0}; + +static const char *const callbacknames[] = { + "", /* empty on purpose */ + "find_write_file", + "find_output_file", + "find_image_file", + "find_format_file", + "find_read_file", "open_read_file", + "find_ocp_file", "read_ocp_file", + "find_vf_file", "read_vf_file", + "find_data_file", "read_data_file", + "find_font_file", "read_font_file", + "find_map_file", "read_map_file", + "find_enc_file", "read_enc_file", + "find_type1_file", "read_type1_file", + "find_truetype_file", "read_truetype_file", + "find_opentype_file", "read_opentype_file", + "find_sfd_file", "read_sfd_file", + "find_pk_file", "read_pk_file", + "show_error_hook", + "process_input_buffer", + "start_page_number", "stop_page_number", + "start_run", "stop_run", + "define_font", + "token_filter", + "pre_output_filter", + "buildpage_filter", + "hpack_filter", "vpack_filter", + "char_exists", + "hyphenate", + "ligaturing", + "kerning", + "pre_linebreak_filter", + "linebreak_filter", + "post_linebreak_filter", + NULL }; + +int callback_callbacks_id = 0; + +void +get_lua_boolean (char *table, char *name, boolean *target) { + int stacktop; + stacktop = lua_gettop(Luas[0]); + luaL_checkstack(Luas[0],2,"out of stack space"); + lua_getglobal(Luas[0],table); + if (lua_istable(Luas[0],-1)) { + lua_getfield(Luas[0],-1,name); + if (lua_isboolean(Luas[0],-1)) { + *target = (lua_toboolean(Luas[0],-1)); + } else if (lua_isnumber(Luas[0],-1)) { + *target = (lua_tonumber(Luas[0],-1)==0 ? 0 : 1); + } + } + lua_settop(Luas[0],stacktop); + return; +} + +void +get_saved_lua_boolean (int r, char *name, boolean *target) { + int stacktop; + stacktop = lua_gettop(Luas[0]); + luaL_checkstack(Luas[0],2,"out of stack space"); + lua_rawgeti(Luas[0],LUA_REGISTRYINDEX,r); + if (lua_istable(Luas[0],-1)) { + lua_getfield(Luas[0],-1,name); + if (lua_isboolean(Luas[0],-1)) { + *target = lua_toboolean(Luas[0],-1); + } else if (lua_isnumber(Luas[0],-1)) { + *target = (lua_tonumber(Luas[0],-1)==0 ? 0 : 1); + } + } + lua_settop(Luas[0],stacktop); + return; +} + +void +get_lua_number (char *table, char *name, integer *target) { + int stacktop; + stacktop = lua_gettop(Luas[0]); + luaL_checkstack(Luas[0],2,"out of stack space"); + lua_getglobal(Luas[0],table); + if (lua_istable(Luas[0],-1)) { + lua_getfield(Luas[0],-1,name); + if (lua_isnumber(Luas[0],-1)) { + *target = lua_tonumber(Luas[0],-1); + } + } + lua_settop(Luas[0],stacktop); + return; +} + +void +get_saved_lua_number (int r, char *name, integer *target) { + int stacktop; + stacktop = lua_gettop(Luas[0]); + luaL_checkstack(Luas[0],2,"out of stack space"); + lua_rawgeti(Luas[0],LUA_REGISTRYINDEX,r); + if (lua_istable(Luas[0],-1)) { + lua_getfield(Luas[0],-1,name); + if (lua_isnumber(Luas[0],-1)) { + *target = lua_tonumber(Luas[0],-1); + } + } + lua_settop(Luas[0],stacktop); + return; +} + + +void +get_lua_string (char *table, char *name, char **target) { + int stacktop; + stacktop = lua_gettop(Luas[0]); + luaL_checkstack(Luas[0],2,"out of stack space"); + lua_getglobal(Luas[0],table); + if (lua_istable(Luas[0],-1)) { + lua_getfield(Luas[0],-1,name); + if (lua_isstring(Luas[0],-1)) { + *target = (char *)lua_tostring(Luas[0],-1); + } + } + lua_settop(Luas[0],stacktop); + return; +} + +void +get_saved_lua_string (int r, char *name, char **target) { + int stacktop; + stacktop = lua_gettop(Luas[0]); + luaL_checkstack(Luas[0],2,"out of stack space"); + lua_rawgeti(Luas[0],LUA_REGISTRYINDEX,r); + if (lua_istable(Luas[0],-1)) { + lua_getfield(Luas[0],-1,name); + if (lua_isstring(Luas[0],-1)) { + *target = (char *)lua_tostring(Luas[0],-1); + } + } + lua_settop(Luas[0],stacktop); + return; +} + + +#define CALLBACK_BOOLEAN 'b' +#define CALLBACK_INTEGER 'd' +#define CALLBACK_LINE 'l' +#define CALLBACK_STRNUMBER 's' +#define CALLBACK_STRING 'S' +#define CALLBACK_CHARNUM 'c' + +int +run_saved_callback (int r, char *name, char *values, ...) { + va_list args; + int ret = 0; + lua_State *L = Luas[0]; + int stacktop = lua_gettop(L); + va_start(args,values); + luaL_checkstack(L,2,"out of stack space"); + lua_rawgeti(L,LUA_REGISTRYINDEX,r); + lua_pushstring(L,name); + lua_rawget(L,-2); + if (lua_isfunction(L,-1)) { + ret = do_run_callback(2,values,args); + } + va_end(args); + lua_settop(L,stacktop); + return ret; +} + + +int +run_and_save_callback (int i, char *values, ...) { + va_list args; + int ret = 0; + lua_State *L = Luas[0]; + int stacktop = lua_gettop(L); + va_start(args,values); + luaL_checkstack(L,2,"out of stack space"); + lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); + lua_rawgeti(L,-1,i); + if (lua_isfunction(L,-1)) { + ret = do_run_callback(1,values,args); + } + va_end(args); + if (ret>0) { + ret = luaL_ref(L,LUA_REGISTRYINDEX); + } + lua_settop(L,stacktop); + return ret; +} + + +int +run_callback (int i, char *values, ...) { + va_list args; + int ret = 0; + lua_State *L = Luas[0]; + int stacktop = lua_gettop(L); + va_start(args,values); + luaL_checkstack(L,2,"out of stack space"); + lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); + lua_rawgeti(L,-1, i); + if (lua_isfunction(L,-1)) { + ret = do_run_callback(0,values,args); + } + va_end(args); + lua_settop(L,stacktop); + return ret; +} + +int +do_run_callback (int special, char *values, va_list vl) { + int ret, len; + int narg,nres; + char *s; + char cs; + int *bufloc; + char *ss = NULL; + int retval = 0; + lua_State *L = Luas[0]; + if (special==2) { /* copy the enclosing table */ + luaL_checkstack(L,1,"out of stack space"); + lua_pushvalue(L,-2); + } + for (narg = 0; *values; narg++) { + luaL_checkstack(L,1,"out of stack space"); + switch (*values++) { + case CALLBACK_CHARNUM: /* an ascii char! */ + cs = (char)va_arg(vl, int); + lua_pushlstring(L,&cs, 1); + break; + case CALLBACK_STRING: /* C string */ + s = va_arg(vl, char *); + lua_pushstring(L, s); + break; + case CALLBACK_INTEGER: /* int */ + lua_pushnumber(L, va_arg(vl, int)); + break; + case CALLBACK_STRNUMBER: /* TeX string */ + s = makeclstring(va_arg(vl, int),&len); + lua_pushlstring(L, s,len); + break; + case CALLBACK_BOOLEAN: /* boolean */ + lua_pushboolean(L, va_arg(vl, int)); + break; + case CALLBACK_LINE: /* a buffer section, with implied start */ + lua_pushlstring(L, (char *)(buffer+first), va_arg(vl, int)); + break; + case '-': + narg--; + break; + case '>': + goto ENDARGS; + default : + ; + } + } + ENDARGS: + nres = strlen(values); + if (special==1) { + nres++; + } + if (special==2) { + narg++; + } + if(lua_pcall(L,narg,nres,0) != 0) { + /* Can't be more precise here, could be called before + * TeX initialization is complete + */ + fprintf(stderr,"This went wrong: %s\n",lua_tostring(L,-1)); + error(); + return 0; + }; + if (nres==0) { + return 1; + } + nres = -nres; + while (*values) { + switch (*values++) { + case CALLBACK_BOOLEAN: + if (!lua_isboolean(L,nres)) { + fprintf(stderr,"Expected a boolean, not: %s\n", lua_typename(L,lua_type(L,nres))); + goto EXIT; + } + int b = lua_toboolean(L,nres); + *va_arg(vl, boolean *) = (boolean)b; + break; + case CALLBACK_INTEGER: + if (!lua_isnumber(L,nres)) { + fprintf(stderr,"Expected a number, not: %s\n", lua_typename(L,lua_type(L,nres))); + goto EXIT; + } + b = lua_tonumber(L,nres); + *va_arg(vl, int *) = b; + break; + case CALLBACK_LINE: /* TeX line */ + if (!lua_isstring(L,nres)) { + if (!lua_isnil(L,nres)) + fprintf(stderr,"Expected a string for (l), not: %s\n", + lua_typename(L,lua_type(L,nres))); + goto EXIT; + } + s = (char *)lua_tolstring(L,nres, (size_t *)&len); + if (s!=NULL) { /* |len| can be zero */ + bufloc = va_arg(vl, int *); + ret = *bufloc; + check_buffer_overflow (ret+len); + while (len--) { + buffer[(*bufloc)++] = *s++; + } + while ((*bufloc)-1>ret && buffer[(*bufloc)-1] == ' ') + (*bufloc)--; + } else { + bufloc = 0; + } + break; + case CALLBACK_STRNUMBER: /* TeX string */ + if (!lua_isstring(L,nres)) { + if (!lua_isnil(L,nres)) { + fprintf(stderr,"Expected a string for (s), not: %s\n", + lua_typename(L,lua_type(L,nres))); + goto EXIT; + } + } + s = (char *)lua_tolstring(L,nres,(size_t *)&len); + if (s==NULL) /* |len| can be zero */ + *va_arg(vl, int *) = 0; + else { + *va_arg(vl, int *) = maketexlstring(s,len); + } + break; + case CALLBACK_STRING: /* C string aka buffer */ + if (!lua_isstring(L,nres)) { + if (!lua_isnil(L,nres)) { + fprintf(stderr,"Expected a string for (S), not: %s\n", + lua_typename(L,lua_type(L,nres))); + goto EXIT; + } + } + s = (char *)lua_tolstring(L,nres,(size_t *)&len); + + if (s==NULL) /* |len| can be zero */ + *va_arg(vl, int *) = 0; + else { + ss = xmalloc(len+1); + (void)memcpy(ss,s,(len+1)); + *va_arg(vl, char **) = ss; + } + break; + default: + fprintf(stdout,"invalid return value type"); + goto EXIT; + } + nres++; + } + retval = 1; + EXIT: + return retval; +} + +void +destroy_saved_callback (int i) { + luaL_unref(Luas[0],LUA_REGISTRYINDEX,i); +} + +static int callback_register (lua_State *L) { + int cb; + char *s; + if (!lua_isstring(L,1) || + ((!lua_isfunction(L,2)) && !lua_isnil(L,2))) { + lua_pushnil(L); + lua_pushstring(L,"Invalid arguments to callback.register."); + return 2; + } + s = (char *)lua_tostring(L,1); + for(cb=0;cb +#include "nodes.h" + +/* this function is in vfovf.c for the moment */ +extern int make_vf_table(lua_State *L, char *name, scaled s); + +static int +font_read_tfm (lua_State *L) { + internalfontnumber f; + scaled s; + int k; + char *cnom; + if(lua_isstring(L, 1)) { + cnom = (char *)lua_tostring(L, 1); + if(lua_isnumber(L, 2)) { + s = (integer)lua_tonumber(L,2); + if (strlen(cnom)) { + f = new_font(); + if (read_tfm_info(f, cnom, "", s)) { + k = font_to_lua(L,f); + delete_font(f); + return k; + } else { + delete_font(f); + lua_pushstring(L, "font loading failed"); + lua_error(L); + } + } else { + lua_pushstring(L, "expected tfm name as first argument"); + lua_error(L); + } + } else { + lua_pushstring(L, "expected an integer size as second argument"); + lua_error(L); + } + } else { + lua_pushstring(L, "expected tfm name as first argument"); + lua_error(L); + } + return 2; /* not reached */ +} + + +static int +font_read_vf (lua_State *L) { + scaled s; + char *cnom; + if(lua_isstring(L, 1)) { + cnom = (char *)lua_tostring(L, 1); + if (strlen(cnom)) { + if(lua_isnumber(L, 2)) { + s = lua_tonumber(L,2); + return make_vf_table(L,cnom,s); + } else { + lua_pushstring(L, "expected an integer size as second argument"); + lua_error(L); + return 2; + } + } + } + lua_pushstring(L, "expected vf name as first argument"); + lua_error(L); + return 2; /* not reached */ +} + +static int +tex_current_font (lua_State *L) { + int i; + i = (int)luaL_optinteger(L,1,0); + if (i>0) { + if (is_valid_font(i)) { + zset_cur_font(i); + return 0; + } else { + lua_pushstring(L, "expected a valid font id"); + lua_error(L); + return 2; /* not reached */ + } + } else { + lua_pushnumber(L,get_cur_font()); + return 1; + } +} + +static int +tex_max_font (lua_State *L) { + lua_pushnumber(L,max_font_id()); + return 1; +} + + +static int +tex_each_font_next (lua_State *L) { + int i,m; /* id */ + m = lua_tonumber(L,1); + i = lua_tonumber(L,2); + i++; + while(i<=m && !is_valid_font(i)) + i++; + if (i>m) { + lua_pushnil(L); + return 1; + } else { + lua_pushnumber(L, i); + font_to_lua (L, i); + return 2; + } +} + +static int +tex_each_font (lua_State *L) { + lua_pushcclosure(L, tex_each_font_next, 0); + lua_pushnumber(L, max_font_id()); + lua_pushnumber(L, 0); + return 3; +} + +static int +frozenfont (lua_State *L) { + int i; + i = (int)luaL_checkinteger(L,1); + if (i) { + if (is_valid_font(i)) { + if (font_touched(i) || font_used(i)) { + lua_pushboolean(L,1); + } else { + lua_pushboolean(L,0); + } + } else { + lua_pushnil(L); + } + return 1; + } else { + lua_pushstring(L, "expected an integer argument"); + lua_error(L); + } + return 0; /* not reached */ +} + + +static int +setfont (lua_State *L) { + int i; + i = (int)luaL_checkinteger(L,-2); + if (i) { + luaL_checktype(L,-1,LUA_TTABLE); + if (is_valid_font(i)) { + if (! (font_touched(i) || font_used(i))) { + font_from_lua (L,i) ; + } else { + lua_pushstring(L, "that font has been accessed already, changing it is forbidden"); + lua_error(L); + } + } else { + lua_pushstring(L, "that integer id is not a valid font"); + lua_error(L); + } + } + return 0; +} + + +static int +deffont (lua_State *L) { + int i; + luaL_checktype(L,-1,LUA_TTABLE); + + i = new_font(); + if(font_from_lua (L,i)) { + lua_pushnumber(L,i); + return 1; + } else { + lua_pop(L,1); /* pop the broken table */ + delete_font(i); + lua_pushstring(L, "font creation failed"); + lua_error(L); + } + return 0; /* not reached */ +} + +static int +getfont (lua_State *L) { + int i; + i = (int)luaL_checkinteger(L,-1); + if (i && is_valid_font(i) && font_to_lua (L, i)) + return 1; + lua_pushnil(L); + return 1; +} + + +static const struct luaL_reg fontlib [] = { + {"read_tfm", font_read_tfm}, + {"read_vf", font_read_vf}, + {"current", tex_current_font}, + {"max", tex_max_font}, + {"each", tex_each_font}, + {"getfont", getfont}, + {"setfont", setfont}, + {"define", deffont}, + {"frozen", frozenfont}, + {NULL, NULL} /* sentinel */ +}; + +int luaopen_font (lua_State *L) +{ + luaL_register(L, "font", fontlib); + make_table(L,"fonts","getfont","setfont"); + return 1; +} diff --git a/Build/source/texk/web2c/luatexdir/lua/limglib.c b/Build/source/texk/web2c/luatexdir/lua/limglib.c new file mode 100644 index 00000000000..fd75e49799a --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/limglib.c @@ -0,0 +1,714 @@ +/* $Id: limglib.c 1098 2008-03-09 10:28:19Z hhenkel $ */ + +#include +#include +#include +#include <../lua51/lua.h> +#include <../lua51/lauxlib.h> +#include +#include "../image/image.h" +#include "../luatex-api.h" + +/**********************************************************************/ + +#ifdef DEBUG +static void stackDump(lua_State * L, char *s) +{ + int i; + int top = lua_gettop(L); + printf("\n=== stackDump <%s>: ", s); + for (i = 1; i <= top; i++) { /* repeat for each level */ + int t = lua_type(L, i); + printf("%d: ", i); + switch (t) { + case LUA_TSTRING: /* strings */ + printf("`%s'", lua_tostring(L, i)); + break; + case LUA_TBOOLEAN: /* booleans */ + printf(lua_toboolean(L, i) ? "true" : "false"); + break; + case LUA_TNUMBER: /* numbers */ + printf("%g", lua_tonumber(L, i)); + break; + default: /* other values */ + printf("%s", lua_typename(L, t)); + break; + } + printf(" "); /* put a separator */ + } + printf("\n"); +} +#endif + +/**********************************************************************/ + +typedef enum { P__ZERO, P_ATTR, P_COLORDEPTH, P_COLORSPACE, P_DEPTH, P_FILENAME, + P_FILEPATH, P_HEIGHT, P_IMAGETYPE, P_INDEX, P_OBJNUM, P_PAGE, P_PAGEBOX, + P_TOTALPAGES, P_TRANSFORM, P_WIDTH, P_XRES, P_XSIZE, P_YRES, P_YSIZE, + P__SENTINEL +} parm_idx; + +typedef struct { + const char *name; /* parameter name */ + parm_idx idx; /* index within img_parms array */ +} parm_struct; + +parm_struct img_parms[] = { + {NULL, P__ZERO}, /* dummy; lua indices run from 1 */ + {"attr", P_ATTR}, + {"colordepth", P_COLORDEPTH}, + {"colorspace", P_COLORSPACE}, + {"depth", P_DEPTH}, + {"filename", P_FILENAME}, + {"filepath", P_FILEPATH}, + {"height", P_HEIGHT}, + {"imagetype", P_IMAGETYPE}, + {"index", P_INDEX}, + {"objnum", P_OBJNUM}, + {"page", P_PAGE}, + {"pagebox", P_PAGEBOX}, + {"pages", P_TOTALPAGES}, + {"transform", P_TRANSFORM}, + {"width", P_WIDTH}, + {"xres", P_XRES}, + {"xsize", P_XSIZE}, + {"yres", P_YRES}, + {"ysize", P_YSIZE}, + {NULL, P__SENTINEL} +}; + +#define imgtype_max 4 +const char *imgtype_s[] = { "none", "pdf", "png", "jpg", "jbig2", NULL }; + +#define pagebox_max 5 +const char *pdfboxspec_s[] = + { "none", "media", "crop", "bleed", "trim", "art", NULL }; + +/**********************************************************************/ + +static void image_to_lua(lua_State * L, image * a) +{ /* key user ... */ + int i, j; + image_dict *d = img_dict(a); + assert(d != NULL); + lua_pushvalue(L, -1); /* k k u ... */ + lua_gettable(L, LUA_ENVIRONINDEX); /* i? k u ... */ + if (!lua_isnumber(L, -1)) /* !i k u ... */ + luaL_error(L, "image_to_lua not a valid image key: %s", + lua_tostring(L, -2)); + i = lua_tointeger(L, -1); /* i k u ... */ + lua_pop(L, 2); /* u ... */ + switch (i) { + case P_WIDTH: + if (is_wd_running(a)) + lua_pushnil(L); + else + lua_pushinteger(L, img_width(a)); + break; + case P_HEIGHT: + if (is_ht_running(a)) + lua_pushnil(L); + else + lua_pushinteger(L, img_height(a)); + break; + case P_DEPTH: + if (is_dp_running(a)) + lua_pushnil(L); + else + lua_pushinteger(L, img_depth(a)); + break; + case P_TRANSFORM: + lua_pushinteger(L, img_transform(a)); + break; + /* now follow all image_dict entries */ + case P_FILENAME: + if (img_filename(d) == NULL || strlen(img_filename(d)) == 0) + lua_pushnil(L); + else + lua_pushstring(L, img_filename(d)); + break; + case P_FILEPATH: + if (img_filepath(d) == NULL || strlen(img_filepath(d)) == 0) + lua_pushnil(L); + else + lua_pushstring(L, img_filepath(d)); + break; + case P_ATTR: + if (img_attr(d) == NULL || strlen(img_attr(d)) == 0) + lua_pushnil(L); + else + lua_pushstring(L, img_attr(d)); + break; + case P_PAGE: + if (img_pagename(d) != NULL && strlen(img_pagename(d)) != 0) + lua_pushstring(L, img_pagename(d)); + else + lua_pushinteger(L, img_pagenum(d)); + break; + case P_TOTALPAGES: + lua_pushinteger(L, img_totalpages(d)); + break; + case P_XSIZE: + lua_pushinteger(L, img_xsize(d)); + break; + case P_YSIZE: + lua_pushinteger(L, img_ysize(d)); + break; + case P_XRES: + lua_pushinteger(L, img_xres(d)); + break; + case P_YRES: + lua_pushinteger(L, img_yres(d)); + break; + case P_COLORSPACE: + if (img_colorspace(d) == 0) + lua_pushnil(L); + else + lua_pushinteger(L, img_colorspace(d)); + break; + case P_COLORDEPTH: + if (img_colordepth(d) == 0) + lua_pushnil(L); + else + lua_pushinteger(L, img_colordepth(d)); + break; + case P_IMAGETYPE: + j = img_type(d); + if (j >= 0 && j <= imgtype_max) { + if (j == IMAGE_TYPE_NONE) + lua_pushnil(L); + else + lua_pushstring(L, imgtype_s[j]); + } else + assert(0); + break; + case P_PAGEBOX: + j = img_pagebox(d); + if (j >= 0 && j <= pagebox_max) { + if (j == PDF_BOX_SPEC_NONE) + lua_pushnil(L); + else + lua_pushstring(L, pdfboxspec_s[j]); + } else + assert(0); + break; + case P_OBJNUM: + if (img_objnum(d) == 0) + lua_pushnil(L); + else + lua_pushinteger(L, img_objnum(d)); + break; + case P_INDEX: + if (img_index(d) == 0) + lua_pushnil(L); + else + lua_pushinteger(L, img_index(d)); + break; + default: + assert(0); + } /* v u ... */ +} + +static void lua_to_image(lua_State * L, image * a) +{ /* value key table ... */ + int i; + image_dict *d = img_dict(a); + assert(d != NULL); + lua_pushvalue(L, -2); /* k v k t ... */ + lua_gettable(L, LUA_ENVIRONINDEX); /* i? v k t ... */ + if (!lua_isnumber(L, -1)) /* !i v k t ... */ + luaL_error(L, "lua_to_image not a valid image key: %s", + lua_tostring(L, -3)); + i = lua_tointeger(L, -1); /* i v k t ... */ + lua_pop(L, 1); /* v k t ... */ + switch (i) { + case P_WIDTH: + if (img_is_refered(a)) + luaL_error(L, "image.width is now read-only"); + if (lua_isnil(L, -1)) + set_wd_running(a); + else if (lua_type(L, -1) == LUA_TNUMBER) + img_width(a) = lua_tointeger(L, -1); + else if (lua_type(L, -1) == LUA_TSTRING) + img_width(a) = dimen_to_number(L, (char *) lua_tostring(L, -1)); + else + luaL_error(L, + "image.width needs integer or nil value or dimension string"); + img_unset_scaled(a); + break; + case P_HEIGHT: + if (img_is_refered(a)) + luaL_error(L, "image.height is now read-only"); + if (lua_isnil(L, -1)) + set_ht_running(a); + else if (lua_type(L, -1) == LUA_TNUMBER) + img_height(a) = lua_tointeger(L, -1); + else if (lua_type(L, -1) == LUA_TSTRING) + img_height(a) = dimen_to_number(L, (char *) lua_tostring(L, -1)); + else + luaL_error(L, + "image.height needs integer or nil value or dimension string"); + img_unset_scaled(a); + break; + case P_DEPTH: + if (img_is_refered(a)) + luaL_error(L, "image.depth is now read-only"); + if (lua_isnil(L, -1)) + set_dp_running(a); + else if (lua_type(L, -1) == LUA_TNUMBER) + img_depth(a) = lua_tointeger(L, -1); + else if (lua_type(L, -1) == LUA_TSTRING) + img_depth(a) = dimen_to_number(L, (char *) lua_tostring(L, -1)); + else + luaL_error(L, + "image.depth needs integer or nil value or dimension string"); + img_unset_scaled(a); + break; + case P_TRANSFORM: + if (img_is_refered(a)) + luaL_error(L, "image.transform is now read-only"); + if (lua_isnumber(L, -1)) + img_transform(a) = lua_tointeger(L, -1); + else + luaL_error(L, "image.transform needs integer value"); + img_unset_scaled(a); + break; + /* now follow all image_dict entries */ + case P_FILENAME: + if (img_state(d) >= DICT_FILESCANNED) + luaL_error(L, "image.filename is now read-only"); + if (lua_isstring(L, -1)) { + if (img_filename(d) != NULL) + xfree(img_filename(d)); + img_filename(d) = xstrdup(lua_tostring(L, -1)); + } else + luaL_error(L, "image.filename needs string value"); + break; + case P_ATTR: + if (img_state(d) >= DICT_FILESCANNED) + luaL_error(L, "image.attr is now read-only"); + if (lua_isstring(L, -1) || lua_isnil(L, -1)) { + if (img_attr(d) != NULL) + xfree(img_attr(d)); + if (lua_isstring(L, -1)) + img_attr(d) = xstrdup(lua_tostring(L, -1)); + } else + luaL_error(L, "image.attr needs string or nil value"); + break; + case P_PAGE: + if (img_state(d) >= DICT_FILESCANNED) + luaL_error(L, "image.page is now read-only"); + if (lua_type(L, -1) == LUA_TSTRING) { + if (img_pagename(d) != NULL) + xfree(img_pagename(d)); + img_pagename(d) = xstrdup(lua_tostring(L, -1)); + img_pagenum(d) = 0; + } else if (lua_type(L, -1) == LUA_TNUMBER) { + img_pagenum(d) = lua_tointeger(L, -1); + if (img_pagename(d) != NULL) + xfree(img_pagename(d)); + img_pagename(d) = NULL; + } else + luaL_error(L, "image.page needs integer or string value"); + break; + case P_COLORSPACE: + if (img_state(d) >= DICT_FILESCANNED) + luaL_error(L, "image.colorspace is now read-only"); + if (lua_isnil(L, -1)) + img_colorspace(d) = 0; + else if (lua_isnumber(L, -1)) + img_colorspace(d) = lua_tointeger(L, -1); + else + luaL_error(L, "image.colorspace needs integer or nil value"); + break; + case P_PAGEBOX: + if (img_state(d) >= DICT_FILESCANNED) + luaL_error(L, "image.pagebox is now read-only"); + if (lua_isnil(L, -1)) + img_pagebox(d) = PDF_BOX_SPEC_NONE; + else if (lua_isstring(L, -1)) + img_pagebox(d) = luaL_checkoption(L, -1, "none", pdfboxspec_s); + else + luaL_error(L, "image.pagebox needs string or nil value"); + break; + case P_FILEPATH: + case P_TOTALPAGES: + case P_XSIZE: + case P_YSIZE: + case P_XRES: + case P_YRES: + case P_IMAGETYPE: + case P_OBJNUM: + case P_INDEX: + case P_COLORDEPTH: + luaL_error(L, "image.%s is a read-only variable", img_parms[i].name); + break; + default: + assert(0); + } /* v k t ... */ +} + +/**********************************************************************/ + +void fix_image_size(lua_State * L, image * a) +{ + if (!img_is_scaled(a) || is_wd_running(a) || is_ht_running(a) + || is_dp_running(a)) { + if (img_is_refered(a)) + luaL_error(L, "image is read-only"); + scale_img(a); + } +} + +void copy_image(lua_State * L, lua_Number scale) +{ + image *a, **aa, *b, **bb; + if (lua_gettop(L) != 1) + luaL_error(L, "img.copy() needs exactly 1 argument"); + aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* a */ + lua_pop(L, 1); /* - */ + a = *aa; + bb = (image **) lua_newuserdata(L, sizeof(image *)); /* b */ + luaL_getmetatable(L, TYPE_IMG); /* m b */ + lua_setmetatable(L, -2); /* b */ + b = *bb = new_image(); + if (!is_wd_running(a)) + img_width(b) = zround(img_width(a) * scale); + if (!is_ht_running(a)) + img_height(b) = zround(img_height(a) * scale); + if (!is_dp_running(a)) + img_depth(b) = zround(img_depth(a) * scale); + img_transform(b) = img_transform(a); + img_dict(b) = img_dict(a); + if (img_dictref(a) != LUA_NOREF) { + lua_rawgeti(L, LUA_GLOBALSINDEX, img_dictref(a)); /* ad b */ + img_dictref(b) = luaL_ref(L, LUA_GLOBALSINDEX); /* b */ + } else + assert(img_state(img_dict(a)) >= DICT_REFERED); +} + +/**********************************************************************/ + +static int l_new_image(lua_State * L) +{ + image *a, **aa; + if (lua_gettop(L) > 1) + luaL_error(L, "img.new() needs maximum 1 argument"); + if (lua_gettop(L) == 1 && !lua_istable(L, 1)) + luaL_error(L, "img.new() needs table as optional argument"); /* (t) */ + aa = (image **) lua_newuserdata(L, sizeof(image *)); /* i (t) */ + luaL_getmetatable(L, TYPE_IMG); /* m i (t) */ + lua_setmetatable(L, -2); /* i (t) */ + a = *aa = new_image(); + image_dict **add = (image_dict **) lua_newuserdata(L, sizeof(image_dict *)); /* ad i (t) */ + luaL_getmetatable(L, TYPE_IMG_DICT); /* m ad i (t) */ + lua_setmetatable(L, -2); /* ad i (t) */ + img_dict(a) = *add = new_image_dict(); + img_dictref(a) = luaL_ref(L, LUA_GLOBALSINDEX); /* i (t) */ + if (lua_gettop(L) != 1) { /* i t, else just i */ + lua_insert(L, -2); /* t i */ + lua_pushnil(L); /* n t i (1st key for iterator) */ + while (lua_next(L, -2) != 0) { /* v k t i */ + lua_to_image(L, a); /* v k t i */ + lua_pop(L, 1); /* k t i */ + } /* t i */ + lua_pop(L, 1); /* i */ + } /* i */ + return 1; /* i */ +} + +static int l_copy_image(lua_State * L) +{ + if (lua_gettop(L) != 1) + luaL_error(L, "img.copy() needs exactly 1 argument"); + if (lua_istable(L, 1)) + l_new_image(L); /* image --- if everything worked well */ + else + copy_image(L, 1.0); /* image */ + return 1; /* image */ +} + +static int l_scan_image(lua_State * L) +{ + image *a, **aa; + if (lua_gettop(L) != 1) + luaL_error(L, "img.scan() needs exactly 1 argument"); + if (lua_istable(L, 1)) + l_new_image(L); /* image --- if everything worked well */ + aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* image */ + a = *aa; + image_dict *ad = img_dict(a); + if (img_state(ad) == DICT_NEW) { + read_img(ad, get_pdf_minor_version(), get_pdf_inclusion_errorlevel()); + img_unset_scaled(a); + } + fix_image_size(L, a); + return 1; /* image */ +} + +/* these should go into some header file... */ +#define obj_type_ximage 8 +#define obj_aux(a) obj_tab[a].int4 /* auxiliary pointer */ +#define obj_data_ptr obj_aux /* pointer to |pdf_mem| */ + +static halfword img_to_node(image * a, integer ref) +{ + image_dict *ad = img_dict(a); + assert(ad != NULL); + assert(img_objnum(ad) != 0); + halfword n = new_node(whatsit_node, pdf_refximage_node); + pdf_ximage_ref(n) = ref; + pdf_width(n) = img_width(a); + pdf_height(n) = img_height(a); + pdf_depth(n) = img_depth(a); + return n; +} + +typedef enum { WR_WRITE, WR_IMMEDIATEWRITE, WR_NODE } wrtype_e; +const char *wrtype_s[] = + { "img.write()", "img.immediatewrite()", "img.node()" }; + +extern void lua_nodelib_push_fast(lua_State * L, halfword n); + +static void write_image_or_node(lua_State * L, wrtype_e writetype) +{ + image *a, **aa; + halfword n; + if (lua_gettop(L) != 1) + luaL_error(L, "%s needs exactly 1 argument", wrtype_s[writetype]); + if (lua_istable(L, 1)) + l_new_image(L); /* image --- if everything worked well */ + aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* image */ + a = *aa; + image_dict *ad = img_dict(a); + assert(ad != NULL); + if (img_state(ad) == DICT_NEW) { + read_img(ad, get_pdf_minor_version(), get_pdf_inclusion_errorlevel()); + img_unset_scaled(a); + } + fix_image_size(L, a); + check_pdfoutput(maketexstring(wrtype_s[writetype]), true); + flush_str(last_tex_string); + integer ref = img_to_array(a); + if (img_objnum(ad) == 0) { /* not strictly needed here, could be delayed until out_image() */ + pdf_ximage_count++; + pdf_create_obj(obj_type_ximage, pdf_ximage_count); + img_objnum(ad) = obj_ptr; + img_index(ad) = pdf_ximage_count; + obj_data_ptr(obj_ptr) = ref; + } + switch (writetype) { + case WR_WRITE: + n = img_to_node(a, ref); + new_tail_append(n); + break; /* image */ + case WR_IMMEDIATEWRITE: + check_pdfminorversion(); /* does initialization stuff */ + pdf_begin_dict(img_objnum(ad), 0); + write_img(ad); + break; /* image */ + case WR_NODE: /* image */ + lua_pop(L, 1); /* - */ + n = img_to_node(a, ref); + lua_nodelib_push_fast(L, n); + break; /* node */ + default: + assert(0); + } + if (img_state(ad) < DICT_REFERED) + img_state(ad) = DICT_REFERED; + img_set_refered(a); /* now image may not be freed by gc */ +} + +static int l_write_image(lua_State * L) +{ + write_image_or_node(L, WR_WRITE); + return 1; /* image */ +} + +static int l_immediatewrite_image(lua_State * L) +{ + write_image_or_node(L, WR_IMMEDIATEWRITE); + return 1; /* image */ +} + +static int l_image_node(lua_State * L) +{ + write_image_or_node(L, WR_NODE); + return 1; /* node */ +} + +static int l_image_keys(lua_State * L) +{ + parm_struct *p = img_parms + 1; + if (lua_gettop(L) != 0) + luaL_error(L, "img.keys() goes without argument"); + lua_newtable(L); /* t */ + for (; p->name != NULL; p++) { + lua_pushinteger(L, (int) p->idx); /* k t */ + lua_pushstring(L, p->name); /* v k t */ + lua_settable(L, -3); /* t */ + } + return 1; +} + +static int l_image_types(lua_State * L) +{ + int i; + char **p; + if (lua_gettop(L) != 0) + luaL_error(L, "img.types() goes without argument"); + lua_newtable(L); /* t */ + for (i = 1, p = (char **) (imgtype_s + 1); *p != NULL; p++, i++) { + lua_pushinteger(L, (int) i); /* k t */ + lua_pushstring(L, *p); /* v k t */ + lua_settable(L, -3); /* t */ + } + return 1; +} + +static int l_image_boxes(lua_State * L) +{ + int i; + char **p; + if (lua_gettop(L) != 0) + luaL_error(L, "img.boxes() goes without argument"); + lua_newtable(L); /* t */ + for (i = 1, p = (char **) (pdfboxspec_s + 1); *p != NULL; p++, i++) { + lua_pushinteger(L, (int) i); /* k t */ + lua_pushstring(L, *p); /* v k t */ + lua_settable(L, -3); /* t */ + } + return 1; +} + +static const struct luaL_Reg imglib[] = { + {"new", l_new_image}, + {"copy", l_copy_image}, + {"scan", l_scan_image}, + {"write", l_write_image}, + {"immediatewrite", l_immediatewrite_image}, + {"node", l_image_node}, + {"keys", l_image_keys}, + {"types", l_image_types}, + {"boxes", l_image_boxes}, + {NULL, NULL} /* sentinel */ +}; + +/**********************************************************************/ +/* Metamethods for image */ + +static int m_img_get(lua_State * L) +{ + image **aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* k u */ + image_to_lua(L, *aa); /* v u */ + return 1; +} + +static int m_img_set(lua_State * L) +{ + image **aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* value key user */ + lua_to_image(L, *aa); /* v k u */ + return 0; +} + +static int m_img_mul(lua_State * L) +{ + image **aa; + lua_Number scale; + if (lua_isnumber(L, 1)) { /* u? n */ + aa = (image **) luaL_checkudata(L, 2, TYPE_IMG); /* u n */ + lua_insert(L, -2); /* n a */ + } else if (lua_isnumber(L, 2)) { /* n u? */ + aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); /* n a */ + } /* n a */ + scale = lua_tonumber(L, 2); /* n a */ + lua_pop(L, 1); /* a */ + copy_image(L, scale); /* b */ + return 1; +} + +static int m_img_print(lua_State * L) +{ + image **aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); + image_dict *d = img_dict(*aa); + if (img_pagename(d) != NULL && strlen(img_pagename(d)) != 0) + lua_pushfstring(L, "", + img_filename(d), img_pagename(d)); + else + lua_pushfstring(L, "", img_filename(d), + img_pagenum(d)); + return 1; +} + +static int m_img_gc(lua_State * L) +{ + image *a, **aa; + aa = (image **) luaL_checkudata(L, 1, TYPE_IMG); + a = *aa; +#ifdef DEBUG + printf("\n===== IMG GC ===== a=%d ad=%d\n", a, img_dict(a)); +#endif + luaL_unref(L, LUA_GLOBALSINDEX, img_dictref(a)); + if (!img_is_refered(a)) + xfree(a); + return 0; +} + +static const struct luaL_Reg img_m[] = { + {"__index", m_img_get}, + {"__newindex", m_img_set}, + {"__mul", m_img_mul}, + {"__tostring", m_img_print}, + {"__gc", m_img_gc}, /* finalizer */ + {NULL, NULL} /* sentinel */ +}; + +/**********************************************************************/ +/* Metamethods for image_dict */ + +static int m_img_dict_gc(lua_State * L) +{ + image_dict *ad, **add; + add = (image_dict **) luaL_checkudata(L, 1, TYPE_IMG_DICT); + ad = *add; +#ifdef DEBUG + printf("\n===== IMG_DICT GC FREE ===== ad=%d\n", ad); +#endif + if (img_state(ad) < DICT_REFERED) + free_image_dict(ad); + return 0; +} + +static const struct luaL_Reg img_dict_m[] = { + {"__gc", m_img_dict_gc}, /* finalizer */ + {NULL, NULL} /* sentinel */ +}; + +/**********************************************************************/ + +void preset_environment(lua_State * L, parm_struct * p) +{ + int i; + lua_newtable(L); /* t */ + for (i = 1, ++p; p->name != NULL; i++, p++) { + assert(i == (int) p->idx); + lua_pushstring(L, p->name); /* k t */ + lua_pushinteger(L, (int) p->idx); /* v k t */ + lua_settable(L, -3); /* t */ + } + lua_replace(L, LUA_ENVIRONINDEX); /* - */ +} + +int luaopen_img(lua_State * L) +{ + preset_environment(L, img_parms); + luaL_newmetatable(L, TYPE_IMG); + luaL_register(L, NULL, img_m); + luaL_newmetatable(L, TYPE_IMG_DICT); + luaL_register(L, NULL, img_dict_m); + luaL_register(L, "img", imglib); + return 1; +} + +/**********************************************************************/ diff --git a/Build/source/texk/web2c/luatexdir/lua/lkpselib.c b/Build/source/texk/web2c/luatexdir/lua/lkpselib.c new file mode 100644 index 00000000000..5ec4dfed869 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lkpselib.c @@ -0,0 +1,272 @@ +/* $Id: lkpselib.c 1061 2008-02-20 09:51:04Z taco $ */ + +#include "luatex-api.h" +#include +#include +#include +#include +#include + +static const int filetypes[] = { + kpse_gf_format, + kpse_pk_format, + kpse_any_glyph_format, + kpse_tfm_format, + kpse_afm_format, + kpse_base_format, + kpse_bib_format, + kpse_bst_format, + kpse_cnf_format, + kpse_db_format, + kpse_fmt_format, + kpse_fontmap_format, + kpse_mem_format, + kpse_mf_format, + kpse_mfpool_format, + kpse_mft_format, + kpse_mp_format, + kpse_mppool_format, + kpse_mpsupport_format, + kpse_ocp_format, + kpse_ofm_format, + kpse_opl_format, + kpse_otp_format, + kpse_ovf_format, + kpse_ovp_format, + kpse_pict_format, + kpse_tex_format, + kpse_texdoc_format, + kpse_texpool_format, + kpse_texsource_format, + kpse_tex_ps_header_format, + kpse_troff_font_format, + kpse_type1_format, + kpse_vf_format, + kpse_dvips_config_format, + kpse_ist_format, + kpse_truetype_format, + kpse_type42_format, + kpse_web2c_format, + kpse_program_text_format, + kpse_program_binary_format, + kpse_miscfonts_format, + kpse_web_format, + kpse_cweb_format, + kpse_enc_format, + kpse_cmap_format, + kpse_sfd_format, + kpse_opentype_format, + kpse_pdftex_config_format, + kpse_lig_format, + kpse_texmfscripts_format }; + +static const char *const filetypenames[] = { + "gf", + "pk", + "bitmap font", + "tfm", + "afm", + "base", + "bib", + "bst", + "cnf", + "ls-R", + "fmt", + "map", + "mem", + "mf", + "mfpool", + "mft", + "mp", + "mppool", + "MetaPost support", + "ocp", + "ofm", + "opl", + "otp", + "ovf", + "ovp", + "graphic/figure", + "tex", + "TeX system documentation", + "texpool", + "TeX system sources", + "PostScript header", + "Troff fonts", + "type1 fonts", + "vf", + "dvips config", + "ist", + "truetype fonts", + "type42 fonts", + "web2c files", + "other text files", + "other binary files", + "misc fonts", + "web", + "cweb", + "enc files", + "cmap files", + "subfont definition files", + "opentype fonts", + "pdftex config", + "lig files", + "texmfscripts", + NULL }; + +/* set to 1 by the |program_name| function */ + +int program_name_set = 0; + +#define TEST_PROGRAM_NAME_SET do { \ + if (! program_name_set) { \ + lua_pushstring(L, "Please call kpse.set_program_name() before using the library"); \ + return lua_error(L); \ + } \ + } while (0) + +static int find_file (lua_State *L) { + int i; + char *st; + int ftype = kpse_tex_format; + int mexist = 0; + TEST_PROGRAM_NAME_SET; + if (!lua_isstring(L,1)) { + lua_pushstring(L, "not a file name"); + lua_error(L); + } + st = (char *)lua_tostring(L,1); + i = lua_gettop(L); + while (i>1) { + if (lua_isboolean (L,i)) { + mexist = lua_toboolean (L,i); + } else if (lua_isnumber (L,i)) { + mexist = lua_tonumber (L,i) ; + } else if (lua_isstring(L,i)) { + int op = luaL_checkoption(L, i, NULL, filetypenames); + ftype = filetypes[op]; + } + i--; + } + if (ftype==kpse_pk_format || + ftype==kpse_gf_format || + ftype==kpse_any_glyph_format) { + /* ret.format, ret.name, ret.dpi */ + kpse_glyph_file_type ret; + lua_pushstring(L, kpse_find_glyph (st,mexist, ftype, &ret)); + } else { + if (mexist>0) + mexist = 1; + if (mexist<0) + mexist = 0; + lua_pushstring(L, kpse_find_file (st,ftype,mexist)); + } + return 1; +} + +static int show_path (lua_State *L) { + int op = luaL_checkoption(L, -1, "tex", filetypenames); + int user_format = filetypes[op]; + TEST_PROGRAM_NAME_SET; + if (!kpse_format_info[user_format].type) /* needed if arg was numeric */ + kpse_init_format (user_format); + lua_pushstring (L, kpse_format_info[user_format].path); + return 1; +} + + +static int expand_path (lua_State *L) { + const char *st = luaL_checkstring(L,1); + TEST_PROGRAM_NAME_SET; + lua_pushstring(L, kpse_path_expand(st)); + return 1; +} + +static int expand_braces (lua_State *L) { + const char *st = luaL_checkstring(L,1); + TEST_PROGRAM_NAME_SET; + lua_pushstring(L, kpse_brace_expand(st)); + return 1; +} + +static int expand_var (lua_State *L) { + const char *st = luaL_checkstring(L,1); + TEST_PROGRAM_NAME_SET; + lua_pushstring(L, kpse_var_expand(st)); + return 1; +} + +static int var_value (lua_State *L) { + const char *st = luaL_checkstring(L,1); + TEST_PROGRAM_NAME_SET; + lua_pushstring(L, kpse_var_value(st)); + return 1; +} + +/* Engine support is a bit of a problem, because we do not want + * to interfere with the normal format discovery of |luatex|. + * Current approach: run |os.setenv()| if you have to. + */ + +extern int luainit; + +static int set_program_name (lua_State *L) { + const char *exe_name = luaL_checkstring(L,1); + const char *prog_name = luaL_optstring(L,2,exe_name); + if (! program_name_set) { + kpse_set_program_name(exe_name, prog_name); + program_name_set = 1; + } else { + kpse_reset_program_name(prog_name); + } + /* fix up the texconfig entry */ + lua_checkstack(L,3); + lua_getglobal(L,"texconfig"); + if (lua_istable(L,-1)) { + lua_pushstring(L,"kpse_init"); + lua_pushboolean(L,0); + lua_rawset(L,-3); + } + lua_pop(L,1); + return 0; +} + +static int init_prog (lua_State *L) { + const char *prefix = luaL_checkstring(L,1); + unsigned dpi = luaL_checkinteger(L,2); + const char *mode = luaL_checkstring(L,3); + const char *fallback = luaL_optstring(L,4,NULL); + TEST_PROGRAM_NAME_SET; + kpse_init_prog(prefix,dpi,mode,fallback); + return 0; +} + +static int readable_file (lua_State *L) { + const char *name = luaL_checkstring(L,1); + TEST_PROGRAM_NAME_SET; + lua_pushstring(L,(char *)kpse_readable_file (name)); + return 1; +} + + +static const struct luaL_reg kpselib [] = { + {"set_program_name", set_program_name}, + {"init_prog", init_prog}, + {"readable_file", readable_file}, + {"find_file", find_file}, + {"expand_path", expand_path}, + {"expand_var", expand_var}, + {"expand_braces",expand_braces}, + {"var_value",var_value}, + {"show_path",show_path}, + {NULL, NULL} /* sentinel */ +}; + + +int +luaopen_kpse (lua_State *L) +{ + luaL_register(L,"kpse",kpselib); + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/llanglib.c b/Build/source/texk/web2c/luatexdir/lua/llanglib.c new file mode 100644 index 00000000000..63e8c45dec8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/llanglib.c @@ -0,0 +1,219 @@ +/* +Copyright (c) 2007 Taco Hoekwater + +This file is part of luatex. + +luatex is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +luatex is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with luatex; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +This is llanglib.c +*/ + +#include "luatex-api.h" +#include + +#include "nodes.h" + +#define LANG_METATABLE "luatex.lang" + +#define check_islang(L,b) (struct tex_language **)luaL_checkudata(L,b,LANG_METATABLE) + +static int +lang_new (lua_State *L) { + struct tex_language **lang; + if (lua_gettop(L)==0) { + lang = lua_newuserdata(L, sizeof(struct tex_language *)); + *lang = new_language(); + if (!*lang) { + lua_pushstring(L,"lang.new(): no room for a new language"); + return lua_error(L); + } + } else { + lang = lua_newuserdata(L, sizeof(struct tex_language *)); + *lang = get_language(lua_tonumber(L,1)); + } + luaL_getmetatable(L,LANG_METATABLE); + lua_setmetatable(L,-2); + return 1; +} + +static int +lang_id (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + lua_pushnumber(L,(*lang_ptr)->id); + return 1; +} + +static int +lang_patterns (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + if (lua_gettop(L)!=1) { + if (!lua_isstring(L,2)) { + lua_pushstring(L,"lang.patterns(): argument should be a string"); + return lua_error(L); + } + load_patterns(*lang_ptr, (unsigned char *)lua_tostring(L,2)); + return 0; + } else { + if ((*lang_ptr)->patterns!=NULL) { + lua_pushstring(L,(char *)hnj_serialize((*lang_ptr)->patterns)); + } else { + lua_pushnil(L); + } + return 1; + } +} + +static int +lang_clear_patterns (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + clear_patterns(*lang_ptr); + return 0; +} + + +static int +lang_hyphenation (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + if (lua_gettop(L)!=1) { + if(!lua_isstring(L,2)) { + lua_pushstring(L,"lang.hyphenation(): argument should be a string"); + return lua_error(L); + } + load_hyphenation(*lang_ptr,(unsigned char *)lua_tostring(L,2)); + return 0; + } else { + if ((*lang_ptr)->exceptions!=0) { + lua_pushstring(L,exception_strings(*lang_ptr)); + } else { + lua_pushnil(L); + } + return 1; + } +} + +static int +lang_pre_hyphen_char (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + if (lua_gettop(L)!=1) { + if(!lua_isnumber(L,2)) { + lua_pushstring(L,"lang.prehyphenchar(): argument should be a character number"); + return lua_error(L); + } + (*lang_ptr)->pre_hyphen_char = lua_tonumber(L,2); + return 0; + } else { + lua_pushnumber(L,(*lang_ptr)->pre_hyphen_char); + return 1; + } +} + +static int +lang_post_hyphen_char (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + if (lua_gettop(L)!=1) { + if(!lua_isnumber(L,2)) { + lua_pushstring(L,"lang.posthyphenchar(): argument should be a character number"); + return lua_error(L); + } + (*lang_ptr)->post_hyphen_char = lua_tonumber(L,2); + return 0; + } else { + lua_pushnumber(L,(*lang_ptr)->post_hyphen_char); + return 1; + } +} + +static int +lang_clear_hyphenation (lua_State *L) { + struct tex_language **lang_ptr; + lang_ptr = check_islang(L,1); + clear_hyphenation(*lang_ptr); + return 0; +} + + +static int +do_lang_clean (lua_State *L) { + char *cleaned; + if (!lua_isstring(L,1)) { + lua_pushstring(L,"lang.clean(): argument should be a string"); + return lua_error(L); + } + (void)clean_hyphenation((char *)lua_tostring(L,1),&cleaned); + lua_pushstring(L,cleaned); + return 1; +} + +static int +do_lang_hyphenate (lua_State *L) { + halfword *h,*t; + h = check_isnode(L,1); + if (lua_isuserdata(L,2)) { + t = check_isnode(L,2); + lua_pop(L,1); + } else { + t = h; + while (vlink(*t)!=null) + *t = vlink(*t); + } + hnj_hyphenation(*h,*t); + lua_pushboolean(L,1); + return 1; +} + + +static const struct luaL_reg langlib_d [] = { + {"clear_patterns", lang_clear_patterns}, + {"clear_hyphenation", lang_clear_hyphenation}, + {"patterns", lang_patterns}, + {"hyphenation", lang_hyphenation}, + {"prehyphenchar", lang_pre_hyphen_char}, + {"posthyphenchar", lang_post_hyphen_char}, + {"id", lang_id}, + {NULL, NULL} /* sentinel */ +}; + + +static const struct luaL_reg langlib[] = { + {"clear_patterns", lang_clear_patterns}, + {"clear_hyphenation", lang_clear_hyphenation}, + {"patterns", lang_patterns}, + {"hyphenation", lang_hyphenation}, + {"prehyphenchar", lang_pre_hyphen_char}, + {"posthyphenchar", lang_post_hyphen_char}, + {"id", lang_id}, + {"clean", do_lang_clean}, + {"hyphenate", do_lang_hyphenate}, + {"new", lang_new}, + {NULL, NULL} /* sentinel */ +}; + + +int +luaopen_lang (lua_State *L) { + luaL_newmetatable(L,LANG_METATABLE); + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, langlib_d); /* dict methods */ + luaL_register(L, "lang", langlib); + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/llualib.c b/Build/source/texk/web2c/luatexdir/lua/llualib.c new file mode 100644 index 00000000000..0d13500a9b7 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/llualib.c @@ -0,0 +1,229 @@ + +/* $Id: llualib.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + +#define LOAD_BUF_SIZE 256 +#define UINT_MAX32 0xFFFFFFFF + +typedef struct { + unsigned char* buf; + int size; + int done; + int alloc; +} bytecode; + +static bytecode *lua_bytecode_registers = NULL; + +int luabytecode_max = -1; +unsigned int luabytecode_bytes = 0; + +void dump_luac_registers (void) { + int k,n; + bytecode b; + dump_int(luabytecode_max); + if (lua_bytecode_registers != NULL) { + n = 0; + for (k=0;k<=luabytecode_max;k++) { + if (lua_bytecode_registers[k].size != 0) + n++; + } + dump_int(n); + for (k=0;k<=luabytecode_max;k++) { + b = lua_bytecode_registers[k]; + if (b.size != 0) { + dump_int(k); + dump_int(b.size); + do_zdump ((char *)b.buf,1,(b.size), DUMP_FILE); + } + } + } +} + +void undump_luac_registers (void) { + int k,n; + unsigned int i; + bytecode b; + undump_int(luabytecode_max); + if (luabytecode_max>=0) { + i = (luabytecode_max+1); + if ((int)(UINT_MAX32/sizeof(bytecode)+1)<=i) { + lua_fatal_error("Corrupt format file"); + } + lua_bytecode_registers = xmalloc(i*sizeof(bytecode)); + luabytecode_bytes = i*sizeof(bytecode); + for (i=0;i<=luabytecode_max;i++) { + lua_bytecode_registers[i].done = 0; + lua_bytecode_registers[i].size = 0; + lua_bytecode_registers[i].buf = NULL; + } + undump_int(n); + for (i=0;isize + size > buf->alloc) { + buf->buf = xrealloc(buf->buf,buf->alloc+size+LOAD_BUF_SIZE); + buf->alloc = buf->alloc+size+LOAD_BUF_SIZE; + } + memcpy(buf->buf+buf->size, b, size); + buf->size += size; + luabytecode_bytes += size; + return 0; +} + +const char* reader(lua_State* L, void* ud, size_t* size) { + bytecode* buf = (bytecode*)ud; + if (buf->done == buf->size) { + *size = 0; + buf->done = 0; + return NULL; + } + *size = buf->size; + buf->done = buf->size; + return (const char*)buf->buf; +} + +int get_bytecode (lua_State *L) { + int k; + k = (int)luaL_checkinteger(L,-1); + if (k<0) { + lua_pushnil(L); + } else if (!bytecode_register_shadow_get(L,k)) { + if (k<=luabytecode_max && lua_bytecode_registers[k].buf != NULL) { + if(lua_load(L,reader,(void *)(lua_bytecode_registers+k),"bytecode")) { + lua_error(L); + lua_pushnil(L); + } else { + lua_pushvalue(L,-1); + bytecode_register_shadow_set(L,k); + } + } else { + lua_pushnil(L); + } + } + return 1; +} + +int set_bytecode (lua_State *L) { + int k, ltype; + unsigned int i; + k = (int)luaL_checkinteger(L,-2); + i = k+1; + if ((int)(UINT_MAX32/sizeof(bytecode)+1)luabytecode_max) { + i = sizeof(bytecode)*(k+1); + lua_bytecode_registers = xrealloc(lua_bytecode_registers,i); + if (luabytecode_max==-1) { + luabytecode_bytes += sizeof(bytecode)*(k+1); + } else { + luabytecode_bytes += sizeof(bytecode)*(k+1-luabytecode_max); + } + for (i=(luabytecode_max+1);i<=k;i++) { + lua_bytecode_registers[i].buf=NULL; + lua_bytecode_registers[i].size=0; + lua_bytecode_registers[i].done=0; + } + luabytecode_max = k; + } + if (lua_bytecode_registers[k].buf != NULL) { + xfree(lua_bytecode_registers[k].buf); + luabytecode_bytes -= lua_bytecode_registers[k].size; + lua_bytecode_registers[k].buf = NULL; + lua_bytecode_registers[k].size=0; + lua_bytecode_registers[k].done=0; + lua_pushnil(L); + bytecode_register_shadow_set(L,k); + } + if (ltype == LUA_TFUNCTION) { + lua_bytecode_registers[k].buf=xmalloc(LOAD_BUF_SIZE); + lua_bytecode_registers[k].alloc = LOAD_BUF_SIZE; + memset(lua_bytecode_registers[k].buf, 0, LOAD_BUF_SIZE); + lua_dump(L,writer,(void *)(lua_bytecode_registers+k)); + } + lua_pop(L,1); + return 0; +} + +static const struct luaL_reg lualib [] = { + {"getbytecode", get_bytecode}, + {"setbytecode", set_bytecode}, + {NULL, NULL} /* sentinel */ +}; + +int luaopen_lua (lua_State *L, int n, char *fname) +{ + luaL_register(L, "lua", lualib); + make_table(L,"bytecode","getbytecode","setbytecode"); + lua_newtable(L); + lua_setfield(L, LUA_REGISTRYINDEX, "bytecode_shadow"); + lua_pushinteger(L, n); + lua_setfield(L, -2, "id"); + lua_pushstring(L, "0.1"); + lua_setfield(L, -2, "version"); + if (fname == NULL) { + lua_pushnil(L); + } else { + lua_pushstring(L, fname); + } + lua_setfield(L, -2, "startupfile"); + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/lmplib.c b/Build/source/texk/web2c/luatexdir/lua/lmplib.c new file mode 100644 index 00000000000..a194f9a55d8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lmplib.c @@ -0,0 +1,1251 @@ +/* $Id$ */ + +#include +#include +#include + +#ifndef pdfTeX +#include +#include +#include +#else +#include <../lua51/lua.h> +#include <../lua51/lauxlib.h> +#include <../lua51/lualib.h> +#endif + +#include "mplib.h" +#include "mpmp.h" +#include "mppsout.h" /* for mp_edge_object */ + +#define MPLIB_METATABLE "MPlib" +#define MPLIB_FIG_METATABLE "MPlib.fig" +#define MPLIB_GR_METATABLE "MPlib.gr" + +#define mplib_init_S(a) do { \ + lua_pushliteral(L,#a); \ + mplib_##a##_ptr = (char *)lua_tostring(L,-1); \ + mplib_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \ + } while (0) + +#define mplib_push_S(a) do { \ + lua_rawgeti(L,LUA_REGISTRYINDEX,mplib_##a##_index); \ + } while (0) + +#define mplib_is_S(a,i) (mplib_##a##_ptr==(char *)lua_tostring(L,i)) + +#define mplib_make_S(a) \ + static int mplib_##a##_index = 0; \ + static char *mplib_##a##_ptr = NULL + +static int mplib_type_Ses[mp_special_code+1] = {0}; /* [0] is not used */ + +mplib_make_S(fill); +mplib_make_S(outline); +mplib_make_S(text); +mplib_make_S(special); +mplib_make_S(start_bounds); +mplib_make_S(stop_bounds); +mplib_make_S(start_clip); +mplib_make_S(stop_clip); + +mplib_make_S(left_type); +mplib_make_S(right_type); +mplib_make_S(x_coord); +mplib_make_S(y_coord); +mplib_make_S(left_x); +mplib_make_S(left_y); +mplib_make_S(right_x); +mplib_make_S(right_y); + +mplib_make_S(color); +mplib_make_S(dash); +mplib_make_S(depth); +mplib_make_S(dsize); +mplib_make_S(font); +mplib_make_S(height); +mplib_make_S(htap); +mplib_make_S(linecap); +mplib_make_S(linejoin); +mplib_make_S(miterlimit); +mplib_make_S(path); +mplib_make_S(pen); +mplib_make_S(postscript); +mplib_make_S(prescript); +mplib_make_S(transform); +mplib_make_S(type); +mplib_make_S(width); + +void mplib_init_Ses(lua_State *L) { + mplib_init_S(fill); + mplib_init_S(outline); + mplib_init_S(text); + mplib_init_S(start_bounds); + mplib_init_S(stop_bounds); + mplib_init_S(start_clip); + mplib_init_S(stop_clip); + mplib_init_S(special); + + mplib_type_Ses[mp_fill_code] = mplib_fill_index; + mplib_type_Ses[mp_stroked_code] = mplib_outline_index; + mplib_type_Ses[mp_text_code] = mplib_text_index; + mplib_type_Ses[mp_start_bounds_code] = mplib_start_bounds_index; + mplib_type_Ses[mp_stop_bounds_code] = mplib_stop_bounds_index; + mplib_type_Ses[mp_start_clip_code] = mplib_start_clip_index; + mplib_type_Ses[mp_stop_clip_code] = mplib_stop_clip_index; + mplib_type_Ses[mp_special_code] = mplib_special_index; + + mplib_init_S(left_type); + mplib_init_S(right_type); + mplib_init_S(x_coord); + mplib_init_S(y_coord); + mplib_init_S(left_x); + mplib_init_S(left_y); + mplib_init_S(right_x); + mplib_init_S(right_y); + + mplib_init_S(color); + mplib_init_S(dash); + mplib_init_S(depth); + mplib_init_S(dsize); + mplib_init_S(font); + mplib_init_S(height); + mplib_init_S(htap); + mplib_init_S(linecap); + mplib_init_S(linejoin); + mplib_init_S(miterlimit); + mplib_init_S(path); + mplib_init_S(pen); + mplib_init_S(postscript); + mplib_init_S(prescript); + mplib_init_S(transform); + mplib_init_S(type); + mplib_init_S(width); +} + + + + +#define xfree(A) if ((A)!=NULL) { free((A)); A = NULL; } + +#define is_mp(L,b) (MP *)luaL_checkudata(L,b,MPLIB_METATABLE) +#define is_fig(L,b) (struct mp_edge_object **)luaL_checkudata(L,b,MPLIB_FIG_METATABLE) +#define is_gr_object(L,b) (struct mp_graphic_object **)luaL_checkudata(L,b,MPLIB_GR_METATABLE) + +/* Enumeration string arrays */ + +static const char *interaction_options[] = + { "unknown","batch","nonstop","scroll","errorstop", NULL}; + +static const char *mplib_filetype_names[] = + {"term", "error", "mp", "log", "ps", "mem", "tfm", "map", "pfb", "enc", NULL}; + +/* only "endpoint" and "explicit" actually happen in paths, + as well as "open" in elliptical pens */ + +static const char *knot_type_enum[] = + { "endpoint", "explicit", "given", "curl", "open", "end_cycle" }; + +/* object fields */ + +static const char *fill_fields[] = + { "type", "path", "htap", "pen", "color", "linejoin", "miterlimit", + "prescript", "postscript", NULL }; + +static const char *stroked_fields[] = + { "type", "path", "pen", "color", "linejoin", "miterlimit", "linecap", "dash", + "prescript", "postscript", NULL }; + +static const char *text_fields[] = + { "type", "text", "dsize", "font", "color", "width", "height", "depth", "transform", + "prescript", "postscript", NULL }; + +static const char *special_fields[] = + { "type", "prescript", NULL }; + +static const char *start_bounds_fields[] = + { "type", "path", NULL }; + +static const char *start_clip_fields[] = + { "type", "path", NULL }; + +static const char *stop_bounds_fields[] = + { "type", NULL }; + +static const char *stop_clip_fields[] = + { "type", NULL }; + +static const char *no_fields[] = + { NULL }; + +typedef enum { + P_ERROR_LINE, P_HALF_LINE, P_MAX_LINE, P_MAIN_MEMORY, + P_HASH_SIZE, P_HASH_PRIME, P_PARAM_SIZE, P_IN_OPEN, P_RANDOM_SEED, + P_INTERACTION, P_INI_VERSION, P_TROFF_MODE, P_PRINT_NAMES, P_MEM_NAME, + P_JOB_NAME, P_FIND_FILE, P__SENTINEL +} mplib_parm_idx; + +typedef struct { + const char *name; /* parameter name */ + mplib_parm_idx idx; /* parameter index */ +} mplib_parm_struct; + +static mplib_parm_struct mplib_parms[] = { + {"error_line", P_ERROR_LINE }, + {"half_error_line", P_HALF_LINE }, + {"max_print_line", P_MAX_LINE }, + {"main_memory", P_MAIN_MEMORY }, + {"hash_size", P_HASH_SIZE }, + {"hash_prime", P_HASH_PRIME }, + {"param_size", P_PARAM_SIZE }, + {"max_in_open", P_IN_OPEN }, + {"random_seed", P_RANDOM_SEED }, + {"interaction", P_INTERACTION }, + {"ini_version", P_INI_VERSION }, + {"troff_mode", P_TROFF_MODE }, + {"print_found_names", P_PRINT_NAMES }, + {"mem_name", P_MEM_NAME }, + {"job_name", P_JOB_NAME }, + {"find_file", P_FIND_FILE }, + {NULL, P__SENTINEL } +}; + +typedef struct _FILE_ITEM { + FILE *f; +} _FILE_ITEM ; + +typedef struct _FILE_ITEM File; + +#define make_stream_buf(A) char *A; size_t A##_size; size_t A##_used + +#define free_stream_buf(A) xfree(mplib_data->A); mplib_data->A##_size = 0; mplib_data->A##_used = 0 + +typedef struct _MPLIB_INSTANCE_DATA { + void *term_file_ptr; + void *err_file_ptr; + void *log_file_ptr; + void *ps_file_ptr; + make_stream_buf(term_out); + make_stream_buf(error_out); + make_stream_buf(log_out); + make_stream_buf(ps_out); + char *input_data; + char *input_data_ptr; + size_t input_data_len; + struct mp_edge_object *edges ; + lua_State *LL; +} _MPLIB_INSTANCE_DATA; + +typedef struct _MPLIB_INSTANCE_DATA mplib_instance; + +static mplib_instance *mplib_get_data (MP mp) { + return (mplib_instance *)mp->userdata; +} + +static mplib_instance *mplib_make_data (void) { + mplib_instance *mplib_data = malloc(sizeof(mplib_instance)); + memset(mplib_data,0,sizeof(mplib_instance)); + return mplib_data ; +} + + +/* Start by defining all the callback routines for the library + * except |run_make_mpx| and |run_editor|. + */ + + +char *mplib_find_file (MP mp, const char *fname, const char *fmode, int ftype) { + mplib_instance *mplib_data = mplib_get_data(mp); + lua_State *L = mplib_data->LL; + lua_checkstack(L,4); + lua_getfield(L,LUA_REGISTRYINDEX,"mplib_file_finder"); + if (lua_isfunction(L,-1)) { + char *s = NULL, *x = NULL; + lua_pushstring(L, fname); + lua_pushstring(L, fmode); + if (ftype >= mp_filetype_text) { + lua_pushnumber(L, ftype-mp_filetype_text); + } else { + lua_pushstring(L, mplib_filetype_names[ftype]); + } + if(lua_pcall(L,3,1,0) != 0) { + fprintf(stdout,"Error in mp.find_file: %s\n", (char *)lua_tostring(L,-1)); + return NULL; + } + x = (char *)lua_tostring(L,-1); + if (x!=NULL) + s = strdup(x); + lua_pop(L,1); /* pop the string */ + return s; + } else { + lua_pop(L,1); + } + if (fmode[0] != 'r' || (! access (fname,R_OK)) || ftype) { + return strdup(fname); + } + return NULL; +} + +static int +mplib_find_file_function (lua_State *L) { + if (! (lua_isfunction(L,-1)|| lua_isnil(L,-1) )) { + return 1; /* error */ + } + lua_pushstring(L, "mplib_file_finder"); + lua_pushvalue(L,-2); + lua_rawset(L,LUA_REGISTRYINDEX); + return 0; +} + +void *mplib_open_file(MP mp, const char *fname, const char *fmode, int ftype) { + File *ff = malloc(sizeof (File)); + if (ff) { + mplib_instance *mplib_data = mplib_get_data(mp); + ff->f = NULL; + if (ftype==mp_filetype_terminal) { + if (fmode[0] == 'r') { + ff->f = stdin; + } else { + xfree(mplib_data->term_file_ptr); + ff->f = malloc(1); + mplib_data->term_file_ptr = ff->f; + } + } else if (ftype==mp_filetype_error) { + xfree(mplib_data->err_file_ptr); + ff->f = malloc(1); + mplib_data->err_file_ptr = ff->f; + } else if (ftype == mp_filetype_log) { + xfree(mplib_data->log_file_ptr); + ff->f = malloc(1); + mplib_data->log_file_ptr = ff->f; + } else if (ftype == mp_filetype_postscript) { + xfree(mplib_data->ps_file_ptr); + ff->f = malloc(1); + mplib_data->ps_file_ptr = ff->f; + } else { + char realmode[3]; + char *f = mplib_find_file(mp, fname,fmode,ftype); + if (f==NULL) + return NULL; + realmode[0] = *fmode; + realmode[1] = 'b'; + realmode[2] = 0; + ff->f = fopen(f, realmode); + if ((fmode[0] == 'r') && (ff->f == NULL)) { + free(ff); + return NULL; + } + } + return ff; + } + return NULL; +} + +static int +mplib_get_char (void *f, mplib_instance *mplib_data) { + int c; + if (f==stdin && mplib_data->input_data != NULL) { + if (mplib_data->input_data_len==0) { + if (mplib_data->input_data_ptr!=NULL) + mplib_data->input_data_ptr = NULL; + else + mplib_data->input_data = NULL; + c = EOF; + } else { + mplib_data->input_data_len--; + c = *(mplib_data->input_data_ptr)++; + } + } else { + c = fgetc(f); + } + return c; +} + +static void +mplib_unget_char (void *f, mplib_instance *mplib_data, int c) { + if (f==stdin && mplib_data->input_data_ptr != NULL) { + mplib_data->input_data_len++; + mplib_data->input_data_ptr--; + } else { + ungetc(c,f); + } +} + + +char *mplib_read_ascii_file (MP mp, void *ff, size_t *size) { + char *s = NULL; + if (ff!=NULL) { + int c; + size_t len = 0, lim = 128; + mplib_instance *mplib_data = mplib_get_data(mp); + FILE *f = ((File *)ff)->f; + if (f==NULL) + return NULL; + *size = 0; + c = mplib_get_char(f,mplib_data); + if (c==EOF) + return NULL; + s = malloc(lim); + if (s==NULL) return NULL; + while (c!=EOF && c!='\n' && c!='\r') { + if (len==lim) { + s =realloc(s, (lim+(lim>>2))); + if (s==NULL) return NULL; + lim+=(lim>>2); + } + s[len++] = c; + c = mplib_get_char(f,mplib_data); + } + if (c=='\r') { + c = mplib_get_char(f,mplib_data); + if (c!=EOF && c!='\n') + mplib_unget_char(f,mplib_data,c); + } + s[len] = 0; + *size = len; + } + return s; +} + +#define APPEND_STRING(a,b) do { \ + if ((mplib_data->a##_used+strlen(b))>=mplib_data->a##_size) { \ + mplib_data->a##_size += 256+(mplib_data->a##_size)/5+strlen(b); \ + mplib_data->a = realloc(mplib_data->a,mplib_data->a##_size); \ + } \ + (void)strcpy(mplib_data->a+mplib_data->a##_used,b); \ + mplib_data->a##_used += strlen(b); \ + } while (0) + +void mplib_write_ascii_file (MP mp, void *ff, const char *s) { + if (ff!=NULL) { + void *f = ((File *)ff)->f; + mplib_instance *mplib_data = mplib_get_data(mp); + if (f!=NULL) { + if (f==mplib_data->term_file_ptr) { + APPEND_STRING(term_out,s); + } else if (f==mplib_data->err_file_ptr) { + APPEND_STRING(error_out,s); + } else if (f==mplib_data->log_file_ptr) { + APPEND_STRING(log_out,s); + } else if (f==mplib_data->ps_file_ptr) { + APPEND_STRING(ps_out,s); + } else { + fprintf((FILE *)f,s); + } + } + } +} + +void mplib_read_binary_file (MP mp, void *ff, void **data, size_t *size) { + (void)mp; + if (ff!=NULL) { + size_t len = 0; + FILE *f = ((File *)ff)->f; + if (f!=NULL) + len = fread(*data,1,*size,f); + *size = len; + } +} + +void mplib_write_binary_file (MP mp, void *ff, void *s, size_t size) { + (void)mp; + if (ff!=NULL) { + FILE *f = ((File *)ff)->f; + if (f!=NULL) + fwrite(s,size,1,f); + } +} + + +void mplib_close_file (MP mp, void *ff) { + if (ff!=NULL) { + mplib_instance *mplib_data = mplib_get_data(mp); + void *f = ((File *)ff)->f; + if (f != NULL && f != mplib_data->term_file_ptr && f != mplib_data->err_file_ptr + && f != mplib_data->log_file_ptr && f != mplib_data->ps_file_ptr) { + fclose(f); + } + free(ff); + } +} + +int mplib_eof_file (MP mp, void *ff) { + if (ff!=NULL) { + mplib_instance *mplib_data = mplib_get_data(mp); + FILE *f = ((File *)ff)->f; + if (f==NULL) + return 1; + if (f==stdin && mplib_data->input_data != NULL) { + return (mplib_data->input_data_len==0); + } + return feof(f); + } + return 1; +} + +void mplib_flush_file (MP mp, void *ff) { + (void)mp; + (void)ff; + return ; +} + +#define APPEND_TO_EDGES(a) do { \ + if (mplib_data->edges==NULL) { \ + mplib_data->edges = hh; \ + } else { \ + struct mp_edge_object *p = mplib_data->edges; \ + while (p->_next!=NULL) { p = p->_next; } \ + p->_next = hh; \ + } \ +} while (0) + +void mplib_shipout_backend (MP mp, int h) { + struct mp_edge_object *hh = mp_gr_export(mp, h); + if (hh) { + mplib_instance *mplib_data = mplib_get_data(mp); + APPEND_TO_EDGES(hh); + } +} + + +static void +mplib_setup_file_ops(struct MP_options * options) { + options->find_file = mplib_find_file; + options->open_file = mplib_open_file; + options->close_file = mplib_close_file; + options->eof_file = mplib_eof_file; + options->flush_file = mplib_flush_file; + options->write_ascii_file = mplib_write_ascii_file; + options->read_ascii_file = mplib_read_ascii_file; + options->write_binary_file = mplib_write_binary_file; + options->read_binary_file = mplib_read_binary_file; + options->shipout_backend = mplib_shipout_backend; +} + +static int +mplib_new (lua_State *L) { + MP *mp_ptr; + mp_ptr = lua_newuserdata(L, sizeof(MP *)); + if (mp_ptr) { + int i; + mplib_instance *mplib_data; + struct MP_options * options; /* instance options */ + options = mp_options(); + mplib_setup_file_ops(options); + mplib_data = mplib_make_data(); + mplib_data->LL = L; + options->userdata = (void *)mplib_data; + options->noninteractive = 1; /* required ! */ + options->print_found_names = 0; + if (lua_type(L,1)==LUA_TTABLE) { + for (i=0;mplib_parms[i].name!=NULL;i++) { + lua_getfield(L,1,mplib_parms[i].name); + if (lua_isnil(L,-1)) { + lua_pop(L,1); + continue; /* skip unset */ + } + switch(mplib_parms[i].idx) { + case P_ERROR_LINE: + options->error_line = lua_tointeger(L,-1); + break; + case P_HALF_LINE: + options->half_error_line = lua_tointeger(L,-1); + break; + case P_MAX_LINE: + options->max_print_line = lua_tointeger(L,-1); + break; + case P_MAIN_MEMORY: + options->main_memory = lua_tointeger(L,-1); + break; + case P_HASH_SIZE: + options->hash_size = lua_tointeger(L,-1); + break; + case P_HASH_PRIME: + options->hash_prime = lua_tointeger(L,-1); + break; + case P_PARAM_SIZE: + options->param_size = lua_tointeger(L,-1); + break; + case P_IN_OPEN: + options->max_in_open = lua_tointeger(L,-1); + break; + case P_RANDOM_SEED: + options->random_seed = lua_tointeger(L,-1); + break; + case P_INTERACTION: + options->interaction = luaL_checkoption(L,-1,"errorstopmode", interaction_options); + break; + case P_INI_VERSION: + options->ini_version = lua_toboolean(L,-1); + break; + case P_TROFF_MODE: + options->troff_mode = lua_toboolean(L,-1); + break; + case P_PRINT_NAMES: + options->print_found_names = lua_toboolean(L,-1); + break; + /* + case P_COMMAND_LINE: + options->command_line = strdup((char *)lua_tostring(L,-1)); + break; + */ + case P_MEM_NAME: + options->mem_name = strdup((char *)lua_tostring(L,-1)); + break; + case P_JOB_NAME: + options->job_name = strdup((char *)lua_tostring(L,-1)); + break; + case P_FIND_FILE: + if(mplib_find_file_function(L)) { /* error here */ + fprintf(stdout,"Invalid arguments to mp.new({find_file=...})\n"); + } + break; + default: + break; + } + lua_pop(L,1); + } + } + *mp_ptr = mp_new(options); + xfree(options->command_line); + xfree(options->mem_name); + xfree(options->job_name); + free(options); + if (*mp_ptr) { + luaL_getmetatable(L,MPLIB_METATABLE); + lua_setmetatable(L,-2); + return 1; + } + } + lua_pushnil(L); + return 1; +} + +static int +mplib_collect (lua_State *L) { + MP *mp_ptr = is_mp(L,1); + xfree(*mp_ptr); + return 0; +} + +static int +mplib_tostring (lua_State *L) { + MP *mp_ptr = is_mp(L,1); + if (*mp_ptr!=NULL) { + lua_pushfstring(L,"",*mp_ptr); + return 1; + } + return 0; +} + +static int +mplib_wrapresults(lua_State *L, mplib_instance *mplib_data, int h) { + lua_checkstack(L,5); + lua_newtable(L); + if (mplib_data->term_out != NULL) { + lua_pushstring(L,mplib_data->term_out); + lua_setfield(L,-2,"term"); + free_stream_buf(term_out); + } + if (mplib_data->error_out != NULL) { + lua_pushstring(L,mplib_data->error_out); + lua_setfield(L,-2,"error"); + free_stream_buf(error_out); + } + if (mplib_data->log_out != NULL ) { + lua_pushstring(L,mplib_data->log_out); + lua_setfield(L,-2,"log"); + free_stream_buf(log_out); + } + if (mplib_data->edges != NULL ) { + struct mp_edge_object **v; + struct mp_edge_object *p = mplib_data->edges; + int i = 1; + lua_newtable(L); + while (p!=NULL) { + v = lua_newuserdata (L, sizeof(struct mp_edge_object *)); + *v = p; + luaL_getmetatable(L,MPLIB_FIG_METATABLE); + lua_setmetatable(L,-2); + lua_rawseti(L,-2,i); i++; + p = p->_next; + } + lua_setfield(L,-2,"fig"); + mplib_data->edges = NULL; + } + lua_pushnumber(L,h); + lua_setfield(L,-2,"status"); + return 1; +} + +static int +mplib_execute (lua_State *L) { + MP *mp_ptr = is_mp(L,1); + if (*mp_ptr!=NULL && lua_isstring(L,2)) { + int h; + mplib_instance *mplib_data = mplib_get_data(*mp_ptr); + mplib_data->input_data = (char *)lua_tolstring(L,2, &(mplib_data->input_data_len)); + mplib_data->input_data_ptr = mplib_data->input_data; + if ((*mp_ptr)->run_state==0) { + h = mp_initialize(*mp_ptr); + } + h = mp_execute(*mp_ptr); + if (mplib_data->input_data_len!=0) { + mplib_data->input_data = NULL; + mplib_data->input_data_ptr = NULL; + mplib_data->input_data_len=0; + } + return mplib_wrapresults(L, mplib_data, h); + } else { + lua_pushnil(L); + } + return 1; +} + +static int +mplib_finish (lua_State *L) { + MP *mp_ptr = is_mp(L,1); + if (*mp_ptr!=NULL) { + mplib_instance *mplib_data = mplib_get_data(*mp_ptr); + int h = mp_finish(*mp_ptr); + return mplib_wrapresults(L, mplib_data, h); + } else { + lua_pushnil(L); + } + return 1; +} + +static int +mplib_statistics (lua_State *L) { + MP *mp_ptr = is_mp(L,1); + if (*mp_ptr!=NULL) { + lua_newtable(L); + lua_pushnumber(L, mp_memory_usage (*mp_ptr)); + lua_setfield(L,-2,"main_memory"); + lua_pushnumber(L, mp_hash_usage (*mp_ptr)); + lua_setfield(L,-2,"hash_size"); + lua_pushnumber(L, mp_param_usage (*mp_ptr)); + lua_setfield(L,-2,"param_size"); + lua_pushnumber(L, mp_open_usage (*mp_ptr)); + lua_setfield(L,-2,"max_in_open"); + } else { + lua_pushnil(L); + } + return 1; +} + + +/* figure methods */ + +static int +mplib_fig_collect (lua_State *L) { + struct mp_edge_object **hh = is_fig(L,1); + if (*hh!=NULL) { + mp_gr_toss_objects (*hh); + *hh=NULL; + } + return 0; +} + +static int +mplib_fig_body (lua_State *L) { + int i = 1; + struct mp_graphic_object **v; + struct mp_graphic_object *p; + struct mp_edge_object **hh = is_fig(L,1); + lua_newtable(L); + p = (*hh)->body; + while (p!=NULL) { + v = lua_newuserdata (L, sizeof(struct mp_graphic_object *)); + *v = p; + luaL_getmetatable(L,MPLIB_GR_METATABLE); + lua_setmetatable(L,-2); + lua_rawseti(L,-2,i); i++; + p = p->_link_field; + } + (*hh)->body = NULL; /* prevent double free */ + return 1; +} + +static int +mplib_fig_copy_body (lua_State *L) { + int i = 1; + struct mp_graphic_object **v; + struct mp_graphic_object *p; + struct mp_edge_object **hh = is_fig(L,1); + lua_newtable(L); + p = (*hh)->body; + while (p!=NULL) { + v = lua_newuserdata (L, sizeof(struct mp_graphic_object *)); + *v = mp_gr_copy_object((*hh)->_parent,p); + luaL_getmetatable(L,MPLIB_GR_METATABLE); + lua_setmetatable(L,-2); + lua_rawseti(L,-2,i); i++; + p = p->_link_field; + } + return 1; +} + + +static int +mplib_fig_tostring (lua_State *L) { + struct mp_edge_object **hh = is_fig(L,1); + lua_pushfstring(L,"
",*hh); + return 1; +} + + + +static int +mp_wrapped_shipout (struct mp_edge_object *hh, int prologues, int procset) { + MP mp = hh->_parent; + if (setjmp(mp->jump_buf)) { + return 0; + } + mp_gr_ship_out(hh,prologues,procset); + return 1; +} + +static int +mplib_fig_postscript (lua_State *L) { + struct mp_edge_object **hh = is_fig(L,1); + int prologues = luaL_optnumber(L,2,-1); + int procset = luaL_optnumber(L,3,-1); + mplib_instance *mplib_data = mplib_get_data((*hh)->_parent); + if (mplib_data->ps_out == NULL) { + if (mp_wrapped_shipout(*hh,prologues, procset)) { + if (mplib_data->ps_out!=NULL ) { + lua_pushstring(L, mplib_data->ps_out); + free_stream_buf(ps_out); + } else { + lua_pushnil(L); + } + return 1; + } else { + lua_pushnil(L); + lua_pushstring(L,mplib_data->log_out); + xfree(mplib_data->ps_out); + return 2; + } + } + lua_pushnil(L); + return 1; +} + +static int +mplib_fig_filename (lua_State *L) { + struct mp_edge_object **hh = is_fig(L,1); + if (*hh!= NULL) { + char *s = (*hh)->_filename; + lua_pushstring(L,s); + } else { + lua_pushnil(L); + } + return 1; +} + + +static int +mplib_fig_bb (lua_State *L) { + struct mp_edge_object **hh = is_fig(L,1); + lua_newtable(L); + lua_pushnumber(L, (double)(*hh)->_minx/65536.0); + lua_rawseti(L,-2,1); + lua_pushnumber(L, (double)(*hh)->_miny/65536.0); + lua_rawseti(L,-2,2); + lua_pushnumber(L, (double)(*hh)->_maxx/65536.0); + lua_rawseti(L,-2,3); + lua_pushnumber(L, (double)(*hh)->_maxy/65536.0); + lua_rawseti(L,-2,4); + return 1; +} + +/* object methods */ + +static int +mplib_gr_collect (lua_State *L) { + struct mp_graphic_object **hh = is_gr_object(L,1); + if (*hh!=NULL) { + mp_gr_toss_object(*hh); + *hh=NULL; + } + return 0; +} + +static int +mplib_gr_tostring (lua_State *L) { + struct mp_graphic_object **hh = is_gr_object(L,1); + lua_pushfstring(L,"",*hh); + return 1; +} + + +static int +mplib_gr_fields (lua_State *L) { + const char **fields; + const char *f; + int i = 1; + struct mp_graphic_object **hh = is_gr_object(L,1); + if (*hh) { + switch ((*hh)->_type_field) { + case mp_fill_code: fields = fill_fields; break; + case mp_stroked_code: fields = stroked_fields; break; + case mp_text_code: fields = text_fields; break; + case mp_special_code: fields = special_fields; break; + case mp_start_clip_code: fields = start_clip_fields; break; + case mp_start_bounds_code: fields = start_bounds_fields; break; + case mp_stop_clip_code: fields = stop_clip_fields; break; + case mp_stop_bounds_code: fields = stop_bounds_fields; break; + default: fields = no_fields; + } + lua_newtable(L); + for (f = *fields; f != NULL; f++) { + lua_pushstring(L,f); + lua_rawseti(L,-2,i); i++; + } + } else { + lua_pushnil(L); + } + return 1; +} + + +#define mplib_push_number(L,x) lua_pushnumber(L,(lua_Number)(x)/65536.0) + +#define MPLIB_PATH 0 +#define MPLIB_PEN 1 + +static void +mplib_push_path (lua_State *L, struct mp_knot *h, int is_pen) { + struct mp_knot *p; /* for scanning the path */ + int i=1; + p=h; + if (p!=NULL) { + lua_newtable(L); + do { + lua_createtable(L,0,6); + if (!is_pen) { + if (p->left_type_field != mp_explicit) { + mplib_push_S(left_type); + lua_pushstring(L,knot_type_enum[p->left_type_field]); + lua_rawset(L,-3); + } + if (p->right_type_field != mp_explicit) { + mplib_push_S(right_type); + lua_pushstring(L,knot_type_enum[p->right_type_field]); + lua_rawset(L,-3); + } + } + mplib_push_S(x_coord); + mplib_push_number(L,p->x_coord_field); + lua_rawset(L,-3); + mplib_push_S(y_coord); + mplib_push_number(L,p->y_coord_field); + lua_rawset(L,-3); + mplib_push_S(left_x); + mplib_push_number(L,p->left_x_field); + lua_rawset(L,-3); + mplib_push_S(left_y); + mplib_push_number(L,p->left_y_field); + lua_rawset(L,-3); + mplib_push_S(right_x); + mplib_push_number(L,p->right_x_field); + lua_rawset(L,-3); + mplib_push_S(right_y); + mplib_push_number(L,p->right_y_field); + lua_rawset(L,-3); + lua_rawseti(L,-2,i); i++; + if ( p->right_type_field==mp_endpoint ) { + return; + } + p=p->next_field; + } while (p!=h) ; + } else { + lua_pushnil(L); + } +} + +#define set_color_objects(pq) \ + object_color_model = pq->color_model_field; \ + object_color_a = pq->color_field._a_val; \ + object_color_b = pq->color_field._b_val; \ + object_color_c = pq->color_field._c_val; \ + object_color_d = pq->color_field._d_val; + + +static void +mplib_push_color (lua_State *L, struct mp_graphic_object *p ) { + int object_color_model; + int object_color_a, object_color_b, object_color_c, object_color_d ; + if (p!=NULL) { + if (p->_type_field == mp_fill_code) { + mp_fill_object *h = (mp_fill_object *)p; + set_color_objects(h); + } else if (p->_type_field == mp_stroked_code) { + mp_stroked_object *h = (mp_stroked_object *)p; + set_color_objects(h); + } else { + mp_text_object *h = (mp_text_object *)p; + set_color_objects(h); + } + lua_newtable(L); + if (object_color_model >= mp_grey_model) { + mplib_push_number(L,object_color_a); + lua_rawseti(L,-2,1); + if (object_color_model >= mp_rgb_model) { + mplib_push_number(L,object_color_b); + lua_rawseti(L,-2,2); + mplib_push_number(L,object_color_c); + lua_rawseti(L,-2,3); + if (object_color_model == mp_cmyk_model) { + mplib_push_number(L,object_color_d); + lua_rawseti(L,-2,4); + } + } + } + } else { + lua_pushnil(L); + } +} + +/* the dash scale is not exported, the field has no external value */ +static void +mplib_push_dash (lua_State *L, struct mp_stroked_object *h ) { + mp_dash_object *d; + if (h!=NULL && h->dash_p_field != NULL) { + d = h->dash_p_field; + lua_newtable(L); + mplib_push_number(L,d->offset_field); + lua_setfield(L,-2,"offset"); + if (d->array_field!=NULL ) { + int i = 0; + lua_newtable(L); + while (*(d->array_field+i) != -1) { + mplib_push_number(L, *(d->array_field+1)); + i++; + lua_rawseti(L,-2,i); + } + lua_setfield(L,-2,"dashes"); + } + } else { + lua_pushnil(L); + } +} + +static void +mplib_push_transform (lua_State *L, struct mp_text_object *h ) { + int i = 1; + if (h!=NULL) { + lua_createtable(L,6,0); + mplib_push_number(L,h->tx_field); + lua_rawseti(L,-2,i); i++; + mplib_push_number(L,h->ty_field); + lua_rawseti(L,-2,i); i++; + mplib_push_number(L,h->txx_field); + lua_rawseti(L,-2,i); i++; + mplib_push_number(L,h->tyx_field); + lua_rawseti(L,-2,i); i++; + mplib_push_number(L,h->txy_field); + lua_rawseti(L,-2,i); i++; + mplib_push_number(L,h->tyy_field); + lua_rawseti(L,-2,i); i++; + } else { + lua_pushnil(L); + } +} + +#define FIELD(A) (mplib_is_S(A,2)) + +static void +mplib_fill_field (lua_State *L, struct mp_fill_object *h) { + if (FIELD(path)) { + mplib_push_path(L, h->path_p_field, MPLIB_PATH); + } else if (FIELD(htap)) { + mplib_push_path(L, h->htap_p_field, MPLIB_PATH); + } else if (FIELD(pen)) { + mplib_push_path(L, h->pen_p_field, MPLIB_PEN); + } else if (FIELD(color)) { + mplib_push_color(L,(mp_graphic_object *)h); + } else if (FIELD(linejoin)) { + lua_pushnumber(L,h->ljoin_field); + } else if (FIELD(miterlimit)) { + mplib_push_number(L,h->miterlim_field); + } else if (FIELD(prescript)) { + lua_pushstring(L,h->pre_script_field); + } else if (FIELD(postscript)) { + lua_pushstring(L,h->post_script_field); + } else { + lua_pushnil(L); + } +} + +static void +mplib_stroked_field (lua_State *L, struct mp_stroked_object *h) { + if (FIELD(path)) { + mplib_push_path(L, h->path_p_field, MPLIB_PATH); + } else if (FIELD(pen)) { + mplib_push_path(L, h->pen_p_field, MPLIB_PEN); + } else if (FIELD(color)) { + mplib_push_color(L, (mp_graphic_object *)h); + } else if (FIELD(dash)) { + mplib_push_dash(L,h); + } else if (FIELD(linecap)) { + lua_pushnumber(L,h->lcap_field); + } else if (FIELD(linejoin)) { + lua_pushnumber(L,h->ljoin_field); + } else if (FIELD(miterlimit)) { + mplib_push_number(L,h->miterlim_field); + } else if (FIELD(prescript)) { + lua_pushstring(L,h->pre_script_field); + } else if (FIELD(postscript)) { + lua_pushstring(L,h->post_script_field); + } else { + lua_pushnil(L); + } +} + +static void +mplib_text_field (lua_State *L, struct mp_text_object *h) { + if (FIELD(text)) { + lua_pushstring(L,h->text_p_field); + } else if (FIELD(dsize)) { + mplib_push_number(L,(h->font_dsize_field/16)); + } else if (FIELD(font)) { + lua_pushstring(L,h->font_name_field); + } else if (FIELD(color)) { + mplib_push_color(L,(mp_graphic_object *)h); + } else if (FIELD(width)) { + mplib_push_number(L,h->width_field); + } else if (FIELD(height)) { + mplib_push_number(L,h->height_field); + } else if (FIELD(depth)) { + mplib_push_number(L,h->depth_field); + } else if (FIELD(transform)) { + mplib_push_transform(L,h); + } else if (FIELD(prescript)) { + lua_pushstring(L,h->pre_script_field); + } else if (FIELD(postscript)) { + lua_pushstring(L,h->post_script_field); + } else { + lua_pushnil(L); + } +} + +static void +mplib_special_field (lua_State *L, struct mp_special_object *h) { + if (FIELD(prescript)) { + lua_pushstring(L,h->pre_script_field); + } else { + lua_pushnil(L); + } +} + +static void +mplib_start_bounds_field (lua_State *L, struct mp_bounds_object *h) { + if (FIELD(path)) { + mplib_push_path(L,h->path_p_field, MPLIB_PATH); + } else { + lua_pushnil(L); + } +} + +static void +mplib_start_clip_field (lua_State *L, struct mp_clip_object *h) { + if (FIELD(path)) { + mplib_push_path(L,h->path_p_field, MPLIB_PATH); + } else { + lua_pushnil(L); + } +} + +static int +mplib_gr_index (lua_State *L) { + struct mp_graphic_object **hh = is_gr_object(L,1); + if (*hh) { + struct mp_graphic_object *h = *hh; + if (mplib_is_S(type,2)) { + lua_rawgeti(L,LUA_REGISTRYINDEX,mplib_type_Ses[h->_type_field]); + } else { + switch (h->_type_field) { + case mp_fill_code: mplib_fill_field(L,(mp_fill_object *)h); break; + case mp_stroked_code: mplib_stroked_field(L,(mp_stroked_object *)h); break; + case mp_text_code: mplib_text_field(L,(mp_text_object *)h); break; + case mp_special_code: mplib_special_field(L,(mp_special_object *)h); break; + case mp_start_clip_code: mplib_start_clip_field(L,(mp_clip_object *)h); break; + case mp_start_bounds_code: mplib_start_bounds_field(L,(mp_bounds_object *)h); break; + /* case mp_stop_clip_code: */ + /* case mp_stop_bounds_code: */ + default: lua_pushnil(L); + } + } + } else { + lua_pushnil(L); + } + return 1; +} + + +static const struct luaL_reg mplib_meta[] = { + {"__gc", mplib_collect}, + {"__tostring", mplib_tostring}, + {NULL, NULL} /* sentinel */ +}; + +static const struct luaL_reg mplib_fig_meta[] = { + {"__gc", mplib_fig_collect }, + {"__tostring", mplib_fig_tostring }, + {"objects", mplib_fig_body }, + {"copy_objects", mplib_fig_copy_body }, + {"filename", mplib_fig_filename }, + {"postscript", mplib_fig_postscript }, + {"boundingbox", mplib_fig_bb }, + {NULL, NULL} /* sentinel */ +}; + +static const struct luaL_reg mplib_gr_meta[] = { + {"__gc", mplib_gr_collect }, + {"__tostring", mplib_gr_tostring }, + {"__index", mplib_gr_index }, + {"fields", mplib_gr_fields }, + {NULL, NULL} /* sentinel */ +}; + + +static const struct luaL_reg mplib_d [] = { + {"execute", mplib_execute }, + {"finish", mplib_finish }, + {"statistics", mplib_statistics }, + {NULL, NULL} /* sentinel */ +}; + + +static const struct luaL_reg mplib_m[] = { + {"new", mplib_new}, + {NULL, NULL} /* sentinel */ +}; + + +int +luaopen_mp (lua_State *L) { + mplib_init_Ses(L); + luaL_newmetatable(L,MPLIB_GR_METATABLE); + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, mplib_gr_meta); /* object meta methods */ + lua_pop(L,1); + + luaL_newmetatable(L,MPLIB_FIG_METATABLE); + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, mplib_fig_meta); /* figure meta methods */ + lua_pop(L,1); + + luaL_newmetatable(L,MPLIB_METATABLE); + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, mplib_meta); /* meta methods */ + luaL_register(L, NULL, mplib_d); /* dict methods */ + luaL_register(L, "mplib", mplib_m); /* module functions */ + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/lnodelib.c b/Build/source/texk/web2c/luatexdir/lua/lnodelib.c new file mode 100644 index 00000000000..de269d5d9c8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lnodelib.c @@ -0,0 +1,1967 @@ +/* $Id: lnodelib.c 1056 2008-02-19 15:42:17Z taco $ */ + +#include "luatex-api.h" +#include + +#include "nodes.h" + +#define init_luaS_index(a) do { \ + lua_pushliteral(L,#a); \ + luaS_##a##_ptr = (char *)lua_tostring(L,-1); \ + luaS_##a##_index = luaL_ref (L,LUA_REGISTRYINDEX); \ + } while (0) + +#define make_luaS_index(a) \ + static int luaS_##a##_index = 0; \ + static char * luaS_##a##_ptr = NULL + +#define luaS_index(a) luaS_##a##_index + +#define luaS_ptr_eq(a,b) (a==luaS_##b##_ptr) + +#define NODE_METATABLE "luatex_node" + +make_luaS_index(luatex_node); + +halfword *check_isnode (lua_State *L, int ud) { + register halfword *p = lua_touserdata(L, ud); + if (p != NULL) { + if (lua_getmetatable(L, ud)) { + lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(luatex_node)); + lua_gettable(L, LUA_REGISTRYINDEX); + if (lua_rawequal(L, -1, -2)) { + lua_pop(L, 2); + return p; + } + } + } + luaL_typerror(L, ud, NODE_METATABLE); + return NULL; +} + +/* This routine finds the numerical value of a string (or number) at + lua stack index |n|. If it is not a valid node type, returns -1 */ + +static +int do_get_node_type_id (lua_State *L, int n, node_info *data) { + register int j; + if (lua_type(L,n)==LUA_TSTRING) { + char *s = (char *)lua_tostring(L,n); + for (j=0;data[j].id!=-1;j++) { + if (strcmp(s,data[j].name)==0) + return j; + } + } else if (lua_type(L,n)==LUA_TNUMBER) { + register int i = lua_tointeger(L,n); + if (data[i].id==i) + return i; + for (j=0;data[j].id!=-1;j++) { + if (data[j].id==i) + return j; + } + } + return -1; +} + +#define get_node_type_id(L,n) do_get_node_type_id(L,n,node_data) +#define get_node_subtype_id(L,n) do_get_node_type_id(L,n,whatsit_node_data) + +static +int get_valid_node_type_id (lua_State *L, int n) { + int i = get_node_type_id(L,n); + if (i==-1) { + if (lua_type(L,n)==LUA_TSTRING) { + lua_pushfstring(L, "Invalid node type id: %s",(char *)lua_tostring(L,n)); + } else { + lua_pushfstring(L, "Invalid node type id: %d",(int)lua_tonumber(L,n)); + } + return lua_error(L); + } + return i; +} + +static +int get_valid_node_subtype_id (lua_State *L, int n) { + int i = get_node_subtype_id(L,n); + if (i==-1) { + if (lua_type(L,n)==LUA_TSTRING) { + lua_pushfstring(L, "Invalid whatsit node id: %s",(char *)lua_tostring(L,n)); + } else { + lua_pushfstring(L, "Invalid whatsit node id: %d",(int)lua_tonumber(L,n)); + } + return lua_error(L); + } + return i; +} + + + +/* Creates a userdata object for a number found at the stack top, + if it is representing a node (i.e. an pointer into |varmem|). + It replaces the stack entry with the new userdata, or pushes + |nil| if the number is |null|, or if the index is definately out of + range. This test could be improved. +*/ + +void +lua_nodelib_push(lua_State *L) { + halfword n; + halfword *a; + n = -1; + if (lua_isnumber(L,-1)) { + n = lua_tointeger(L,-1); + } + lua_pop(L,1); + if ((n==null) || (n<0) || (n>var_mem_max)) { + lua_pushnil(L); + } else { + a = lua_newuserdata(L, sizeof(halfword)); + *a = n; + lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(luatex_node)); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_setmetatable(L,-2); + } + return; +} + +void +lua_nodelib_push_fast(lua_State *L, halfword n) { + halfword *a; + a = lua_newuserdata(L, sizeof(halfword)); + *a = n; + lua_rawgeti(L,LUA_REGISTRYINDEX,luaS_index(luatex_node)); + lua_gettable(L, LUA_REGISTRYINDEX); + lua_setmetatable(L,-2); + return; +} + + +/* converts type strings to type ids */ + +static int +lua_nodelib_id (lua_State *L) { + integer i = get_node_type_id(L,1); + if (i>=0) { + lua_pushnumber(L,i); + } else { + lua_pushnil(L); + } + return 1; +} + + +static int +lua_nodelib_subtype (lua_State *L) { + integer i = get_node_subtype_id(L,1); + if (i>=0) { + lua_pushnumber(L,i); + } else { + lua_pushnil(L); + } + return 1; +} + +/* converts id numbers to type names */ + +static int +lua_nodelib_type (lua_State *L) { + integer i = get_node_type_id(L,1); + if (i>=0) { + lua_pushstring(L,node_data[i].name); + } else { + lua_pushnil(L); + } + return 1; +} + + +/* allocate a new node */ + +static int +lua_nodelib_new(lua_State *L) { + int i,j; + halfword n = null; + i = get_valid_node_type_id(L,1); + + if (i==whatsit_node) { + j = -1; + if (lua_gettop(L)>1) { j = get_valid_node_subtype_id(L,2); } + if (j<0) { + lua_pushstring(L, "Creating a whatsit requires the subtype number as a second argument"); + lua_error(L); + } + } else { + j = 0; + if (lua_gettop(L)>1) { j = lua_tointeger(L,2); } + } + n = new_node(i,j); + lua_nodelib_push_fast(L,n); + return 1; +} + + +/* Free a node. + This function returns the 'next' node, because that may be helpful */ + +static int +lua_nodelib_free(lua_State *L) { + halfword *n; + halfword p; + if (lua_gettop(L)<1) { + lua_pushnil(L); + return 1; + } else if(lua_isnil(L,1)) { + return 1; /* the nil itself */ + } + n = check_isnode(L,1); + p = vlink(*n); + flush_node(*n); + lua_pushnumber(L,p); + lua_nodelib_push(L); + return 1; +} + +/* Free a node list */ + +static int +lua_nodelib_flush_list(lua_State *L) { + halfword *n_ptr; + if ((lua_gettop(L)<1) || lua_isnil(L,1)) + return 0; + n_ptr = check_isnode(L,1); + flush_node_list(*n_ptr); + return 0; +} + +/* find prev, and fix backlinks */ + +#define set_t_to_prev(head,current) \ + t = head; \ + while (vlink(t)!=current && t != null) { \ + if (vlink(t)!=null) \ + alink(vlink(t)) = t; \ + t = vlink(t); \ + } + +/* remove a node from a list */ + + +static int +lua_nodelib_remove (lua_State *L) { + halfword head, current, t; + if (lua_gettop(L)<2) { + lua_pushstring(L,"Not enough arguments for node.remove()"); + lua_error(L); + } + head = *(check_isnode(L,1)); + if (lua_isnil(L,2)) { + return 2; /* the arguments, as they are */ + } + current = *(check_isnode(L,2)); + + if (head == current) { + if (alink(head)!=null && vlink(current)!=null) { + alink(vlink(current)) = alink(head); + } + head = vlink(current); + current = head; + } else { /* head != current */ + t = alink(current); + if (t==null || vlink(t)!=current) { + set_t_to_prev(head,current); + if (t==null) { /* error! */ + lua_pushstring(L,"Attempt to node.remove() a non-existing node"); + lua_error(L); + } + } + /* t is now the previous node */ + vlink(t) = vlink(current); + if (vlink(current)!=null) { + alink(vlink(current)) = t; + } + current = vlink(current); + } + lua_pushnumber(L,head); + lua_nodelib_push(L); + lua_pushnumber(L,current); + lua_nodelib_push(L); + return 2; +} + +/* Insert a node in a list */ + +static int +lua_nodelib_insert_before (lua_State *L) { + halfword head, current, n, t; + if (lua_gettop(L)<3) { + lua_pushstring(L,"Not enough arguments for node.insert_before()"); + lua_error(L); + } + if (lua_isnil(L,3)) { + lua_pop(L,1); + return 2; + } else { + n = *(check_isnode(L,3)); + } + if (lua_isnil(L,1)) { /* no head */ + vlink(n) = null; + alink(n) = null; + lua_nodelib_push_fast(L,n); + lua_pushvalue(L,-1); + return 2; + } else { + head = *(check_isnode(L,1)); + } + if (lua_isnil(L,2)) { + current = tail_of_list(head); + } else { + current = *(check_isnode(L,2)); + } + t = alink(current); + if (t==null || vlink(t)!=current) { + set_t_to_prev(head,current); + if (t==null) { /* error! */ + lua_pushstring(L,"Attempt to node.insert_before() a non-existing node"); + lua_error(L); + } + } + couple_nodes(t,n); + couple_nodes(n,current); + if (head==current) { + lua_nodelib_push_fast(L,n); + } else { + lua_nodelib_push_fast(L,head); + } + lua_nodelib_push_fast(L,n); + return 2; +} + + +static int +lua_nodelib_insert_after (lua_State *L) { + halfword head, current, n; + if (lua_gettop(L)<3) { + lua_pushstring(L,"Not enough arguments for node.insert_after()"); + lua_error(L); + } + if (lua_isnil(L,3)) { + lua_pop(L,1); + return 2; + } else { + n = *(check_isnode(L,3)); + } + if (lua_isnil(L,1)) { /* no head */ + vlink(n) = null; + alink(n) = null; + lua_nodelib_push_fast(L,n); + lua_pushvalue(L,-1); + return 2; + } else { + head = *(check_isnode(L,1)); + } + if (lua_isnil(L,2)) { + current = head; + while (vlink(current)!=null) + current = vlink(current); + } else { + current = *(check_isnode(L,2)); + } + try_couple_nodes(n,vlink(current)); + couple_nodes(current, n); + + lua_pop(L,2); + lua_nodelib_push_fast(L,n); + return 2; +} + + +/* Copy a node list */ + +static int +lua_nodelib_copy_list (lua_State *L) { + halfword *n; + halfword m; + if (lua_isnil(L,1)) + return 1; /* the nil itself */ + n = check_isnode(L,1); + m = copy_node_list(*n); + lua_nodelib_push_fast(L,m); + return 1; +} + +/* (Deep) copy a node */ + +static int +lua_nodelib_copy(lua_State *L) { + halfword *n; + halfword m; + if (lua_isnil(L,1)) + return 1; /* the nil itself */ + n = check_isnode(L,1); + m = copy_node(*n); + lua_nodelib_push_fast(L,m); + return 1; +} + +/* output (write) a node to tex's processor */ + +static int +lua_nodelib_append(lua_State *L) { + halfword *n; + halfword m; + int i, j; + j = lua_gettop(L); + for (i=1;i<=j;i++) { + n = check_isnode(L,i); + m = copy_node_list(*n); + new_tail_append(m); + while (vlink(m)!= null) { + m = vlink(m); + new_tail_append(m); + } + } + return 0; +} + +static int +lua_nodelib_last_node(lua_State *L) { + halfword m; + m = pop_tail(); + lua_pushnumber(L,m); + lua_nodelib_push(L); + return 1; +} + + + +/* build a hbox */ + +static int +lua_nodelib_hpack(lua_State *L) { + halfword n, p; + char *s; + integer w = 0; + int m = 1; + n = *(check_isnode(L,1)); + if (lua_gettop(L)>1) { + w = lua_tointeger(L,2); + if (lua_gettop(L)>2 && lua_type(L,3)==LUA_TSTRING) { + s = (char *)lua_tostring(L,3); + if (strcmp(s,"additional")==0) { + m = 1; + } else { + m = lua_tonumber(L,3); + } + } + } + p = hpack(n,w,m); + lua_nodelib_push_fast(L,p); + return 1; +} + +/* This function is similar to |get_node_type_id|, for field + identifiers. It has to do some more work, because not all + identifiers are valid for all types of nodes. +*/ + +/* this inlining is an optimisation trick. it would be even faster to + compare string pointers on the lua stack, but that would require a + lot of code reworking that I don't have time for right now. +*/ + + +make_luaS_index(id); +make_luaS_index(next); +make_luaS_index(char); +make_luaS_index(font); +make_luaS_index(attr); +make_luaS_index(prev); +make_luaS_index(lang); +make_luaS_index(subtype); +make_luaS_index(left); +make_luaS_index(right); +make_luaS_index(uchyph); +make_luaS_index(components); +make_luaS_index(xoffset); +make_luaS_index(yoffset); + + +void initialize_luaS_indexes(lua_State *L) { + init_luaS_index(id); + init_luaS_index(next); + init_luaS_index(char); + init_luaS_index(font); + init_luaS_index(attr); + init_luaS_index(prev); + init_luaS_index(lang); + init_luaS_index(subtype); + init_luaS_index(left); + init_luaS_index(right); + init_luaS_index(uchyph); + init_luaS_index(components); + init_luaS_index(xoffset); + init_luaS_index(yoffset); +} + +static int +get_node_field_id (lua_State *L, int n, int node ) { + register int t = type(node); + register char *s = (char *)lua_tostring(L,n); + if (luaS_ptr_eq(s,next)) { return 0; } + else if (luaS_ptr_eq(s,id)) { return 1; } + else if (luaS_ptr_eq(s,attr) && + nodetype_has_attributes(t)) { return 3 ; } + else if (t==glyph_node) { + if (luaS_ptr_eq(s,subtype)) { return 2; } + else if (luaS_ptr_eq(s,font)) { return 5; } + else if (luaS_ptr_eq(s,char)) { return 4; } + else if (luaS_ptr_eq(s,prev)) { return -1; } + else if (luaS_ptr_eq(s,lang)) { return 6; } + else if (luaS_ptr_eq(s,left)) { return 7; } + else if (luaS_ptr_eq(s,right)) { return 8; } + else if (luaS_ptr_eq(s,uchyph)) { return 9; } + else if (luaS_ptr_eq(s,components)) { return 10; } + else if (luaS_ptr_eq(s,xoffset)) { return 11; } + else if (luaS_ptr_eq(s,yoffset)) { return 12; } + } + else if (luaS_ptr_eq(s,prev)) { return -1; } + else if (luaS_ptr_eq(s,subtype)) { return 2; } + else { + int j; + char **fields = node_data[t].fields; + if (t==whatsit_node) + fields = whatsit_node_data[subtype(node)].fields; + for (j=0;fields[j]!=NULL;j++) { + if (strcmp(s,fields[j])==0) { + return j+3; + } + } + } + return -2; +} + + +static int +get_valid_node_field_id (lua_State *L, int n, int node ) { + int i = get_node_field_id(L,n,node); + if (i==-2) { + char *s = (char *)lua_tostring(L,n); + lua_pushfstring(L, "Invalid field id %s for node type %s (%d)" , s, node_data[type(node)].name,subtype(node)); + lua_error(L); + } + return i; +} + +static int +lua_nodelib_has_field (lua_State *L) { + int i= -2; + if (!lua_isnil(L,1)) { + i = get_node_field_id(L,2,*(check_isnode(L,1))); + } + lua_pushboolean(L,(i!=-2)); + return 1; +} + + +/* fetch the list of valid node types */ + +static int +do_lua_nodelib_types (lua_State *L, node_info *data) { + int i; + lua_newtable(L); + for (i=0;data[i].id!=-1;i++) { + lua_pushstring(L,data[i].name); + lua_rawseti(L,-2,data[i].id); + } + return 1; +} + +static int +lua_nodelib_types (lua_State *L) { + return do_lua_nodelib_types (L, node_data); +} + +static int +lua_nodelib_whatsits (lua_State *L) { + return do_lua_nodelib_types (L, whatsit_node_data); +} + + +/* fetch the list of valid fields */ + +static int +lua_nodelib_fields (lua_State *L) { + int i = -1; + char ** fields; + int t = get_valid_node_type_id(L,1); + if (t==whatsit_node ) { + t = get_valid_node_subtype_id(L,2); + fields = whatsit_node_data[t].fields; + } else { + fields = node_data[t].fields; + } + lua_checkstack(L,2); + lua_newtable(L); + lua_pushstring(L,"next"); + lua_rawseti(L,-2,0); + lua_pushstring(L,"id"); + lua_rawseti(L,-2,1); + lua_pushstring(L,"subtype"); + lua_rawseti(L,-2,2); + if (fields!=NULL) { + lua_pushstring(L,"prev"); + lua_rawseti(L,-2,-1); + for (i=0;fields[i]!=NULL;i++) { + lua_pushstring(L,fields[i]); + lua_rawseti(L,-2,(i+3)); + } + } + return 1; +} + +/* find the end of a list */ + +static int +lua_nodelib_tail (lua_State *L) { + halfword *n; + halfword t; + if (lua_isnil(L,1)) + return 1; /* the nil itself */ + n = check_isnode(L,1); + t=*n; + if (t==null) + return 1; /* the old userdata */ + alink(t) = null; + while (vlink(t)!=null) { + alink(vlink(t)) = t; + t = vlink(t); + } + lua_nodelib_push_fast(L,t); + return 1; +} + +/* a few utility functions for attribute stuff */ + +static int +lua_nodelib_has_attribute (lua_State *L) { + halfword *n; + int i, val ; + if (lua_isnil(L,1)) + return 1; /* the nil itself */ + n = check_isnode(L,1); + i = lua_tointeger(L,2); + val = luaL_optinteger(L,3,-1); + if((val = has_attribute(*n,i,val))>=0) { + lua_pushnumber(L,val); + } else { + lua_pushnil(L); + } + return 1; +} + +static int +lua_nodelib_set_attribute (lua_State *L) { + halfword *n; + int i, val; + if (lua_gettop(L)==3) { + i = lua_tointeger(L,2); + val = lua_tointeger(L,3); + n = check_isnode(L,1); + if (val<0) { + (void)unset_attribute(*n,i,val); + } else { + set_attribute(*n,i,val); + } + } else { + lua_pushstring(L,"incorrect number of arguments"); + lua_error(L); + } + return 0; +} + + +static int +lua_nodelib_unset_attribute (lua_State *L) { + halfword *n; + int i, val, ret; + if (lua_gettop(L)<=3) { + i = luaL_checknumber(L,2); + val = luaL_optnumber(L,3,-1); + n = check_isnode(L,1); + ret = unset_attribute(*n,i,val); + if(ret>=0) { + lua_pushnumber(L,ret); + } else { + lua_pushnil(L); + } + return 1; + } else { + lua_pushstring(L,"incorrect number of arguments"); + return lua_error(L); + } +} + + +/* iteration */ + +static int nodelib_aux_nil (lua_State *L) { + lua_pushnil(L); + return 1; +} + +static int +nodelib_aux_next_filtered (lua_State *L) { + register halfword t; /* traverser */ + register int i = lua_tointeger(L,lua_upvalueindex(1)); + if (lua_isnil(L,2)) { /* first call */ + t = *check_isnode(L,1); + } else { + t = *check_isnode(L,2); + t = vlink(t); + } + while (t!=null && type(t)!=i) { t = vlink(t); } + if (t==null) { + lua_pushnil(L); + } else { + lua_nodelib_push_fast(L,t); + } + return 1; +} + + +static int +lua_nodelib_traverse_filtered (lua_State *L) { + halfword n; + if (lua_isnil(L,2)) { + lua_pushcclosure(L, nodelib_aux_nil, 0); + return 1; + } + n = *(check_isnode(L,2)); + lua_pop(L,1); /* the node, integer remains */ + lua_pushcclosure(L, nodelib_aux_next_filtered, 1); + lua_nodelib_push_fast(L,n); + lua_pushnil(L); + return 3; +} + +static int +nodelib_aux_next (lua_State *L) { + register halfword t; /* traverser */ + if (lua_isnil(L,2)) { /* first call */ + t = *check_isnode(L,1); + } else { + t = *check_isnode(L,2); + t = vlink(t); + } + if (t==null) { + lua_pushnil(L); + } else { + lua_nodelib_push_fast(L,t); + } + return 1; +} + +static int +lua_nodelib_traverse (lua_State *L) { + halfword n; + if (lua_isnil(L,1)) { + lua_pushcclosure(L, nodelib_aux_nil, 0); + return 1; + } + n = *(check_isnode(L,1)); + lua_pushcclosure(L, nodelib_aux_next, 0); + lua_nodelib_push_fast(L,n); + lua_pushnil(L); + return 3; +; +} + + + +static int +do_lua_nodelib_count (lua_State *L, halfword match, int i, halfword first) { + int count = 0; + int t = first; + while (t!=match) { + if (i<0 || type(t)==i) { count++; } + t = vlink(t); + } + lua_pushnumber(L,count); + return 1; +} + +static int lua_nodelib_length (lua_State *L) { + halfword n; + halfword m = null; + if (lua_isnil(L,1)) { + lua_pushnumber(L,0); + return 1; + } + n = *(check_isnode(L,1)); + if (lua_gettop(L)==2) { + m = *(check_isnode(L,2)); + } + return do_lua_nodelib_count(L,m,-1,n); +} + + +static int lua_nodelib_count (lua_State *L) { + halfword n; + halfword m = null; + int i = -1; + i = lua_tointeger(L,1); + if (lua_isnil(L,2)) { + lua_pushnumber(L,0); + return 1; + } + n = *(check_isnode(L,2)); + if (lua_gettop(L)==3) + m = *(check_isnode(L,3)); + return do_lua_nodelib_count(L,m,i,n); +} + +/* fetching a field from a node */ + +#define nodelib_pushlist(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } +#define nodelib_pushattr(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } +#define nodelib_pushspec(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } +#define nodelib_pushaction(L,n) { lua_pushnumber(L,n); lua_nodelib_push(L); } +#define nodelib_pushstring(L,n) { lua_pushstring(L,makecstring(n)); } + +static void +lua_nodelib_getfield_whatsit (lua_State *L, int n, int field) { + if (field==2) { + lua_pushnumber(L,subtype(n)); + } else { + switch (subtype(n)) { + case open_node: + switch (field) { + case 4: lua_pushnumber(L,write_stream(n)); break; + case 5: nodelib_pushstring(L,open_name(n)); break; + case 6: nodelib_pushstring(L,open_area(n)); break; + case 7: nodelib_pushstring(L,open_ext(n)); break; + default: lua_pushnil(L); + } + break; + case write_node: + switch (field) { + case 4: lua_pushnumber(L,write_stream(n)); break; + case 5: tokenlist_to_lua(L,write_tokens(n)); break; + default: lua_pushnil(L); + } + break; + case close_node: + switch (field) { + case 4: lua_pushnumber(L,write_stream(n)); break; + default: lua_pushnil(L); + } + break; + case special_node: + switch (field) { + case 4: tokenlist_to_luastring(L,write_tokens(n)); break; + default: lua_pushnil(L); + } + break; + case local_par_node: + switch (field) { + case 4: lua_pushnumber(L,local_pen_inter(n)); break; + case 5: lua_pushnumber(L,local_pen_broken(n)); break; + case 6: lua_pushnumber(L,local_par_dir(n)); break; + case 7: nodelib_pushlist(L,local_box_left(n)); break; + case 8: lua_pushnumber(L,local_box_left_width(n)); break; + case 9: nodelib_pushlist(L,local_box_right(n)); break; + case 10: lua_pushnumber(L,local_box_right_width(n)); break; + default: lua_pushnil(L); + } + break; + case dir_node: + switch (field) { + case 4: lua_pushnumber(L,dir_dir(n)); break; + case 5: lua_pushnumber(L,dir_level(n)); break; + case 6: lua_pushnumber(L,dir_dvi_ptr(n)); break; + case 7: lua_pushnumber(L,dir_dvi_h(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_literal_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_literal_mode(n)); break; + case 5: tokenlist_to_luastring(L,pdf_literal_data(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_refobj_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_obj_objnum(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_refxform_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_width(n)); break; + case 5: lua_pushnumber(L,pdf_height(n)); break; + case 6: lua_pushnumber(L,pdf_depth(n)); break; + case 7: lua_pushnumber(L,pdf_xform_objnum(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_refximage_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_width(n)); break; + case 5: lua_pushnumber(L,pdf_height(n)); break; + case 6: lua_pushnumber(L,pdf_depth(n)); break; + case 7: lua_pushnumber(L,pdf_ximage_objnum(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_annot_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_width(n)); break; + case 5: lua_pushnumber(L,pdf_height(n)); break; + case 6: lua_pushnumber(L,pdf_depth(n)); break; + case 7: lua_pushnumber(L,pdf_annot_objnum(n)); break; + case 8: tokenlist_to_luastring(L,pdf_annot_data(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_start_link_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_width(n)); break; + case 5: lua_pushnumber(L,pdf_height(n)); break; + case 6: lua_pushnumber(L,pdf_depth(n)); break; + case 7: lua_pushnumber(L,pdf_link_objnum(n)); break; + case 8: tokenlist_to_luastring(L,pdf_link_attr(n)); break; + case 9: nodelib_pushaction(L,pdf_link_action(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_dest_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_width(n)); break; + case 5: lua_pushnumber(L,pdf_height(n)); break; + case 6: lua_pushnumber(L,pdf_depth(n)); break; + case 7: lua_pushnumber(L,pdf_dest_named_id(n)); break; + case 8: if (pdf_dest_named_id(n) == 1) + tokenlist_to_luastring(L,pdf_dest_id(n)); + else + lua_pushnumber(L,pdf_dest_id(n)); break; + case 9: lua_pushnumber(L,pdf_dest_type(n)); break; + case 10: lua_pushnumber(L,pdf_dest_xyz_zoom(n)); break; + case 11: lua_pushnumber(L,pdf_dest_objnum(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_thread_node: + case pdf_start_thread_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_width(n)); break; + case 5: lua_pushnumber(L,pdf_height(n)); break; + case 6: lua_pushnumber(L,pdf_depth(n)); break; + case 7: lua_pushnumber(L,pdf_thread_named_id(n)); break; + case 8: if (pdf_thread_named_id(n) == 1) + tokenlist_to_luastring(L,pdf_thread_id(n)); + else + lua_pushnumber(L,pdf_thread_id(n)); break; + case 9: tokenlist_to_luastring(L,pdf_thread_attr(n)); break; + default: lua_pushnil(L); + } + break; + case late_lua_node: + switch (field) { + case 4: lua_pushnumber(L,late_lua_reg(n)); break; + case 5: tokenlist_to_luastring(L,late_lua_data(n)); break; + default: lua_pushnil(L); + } + break; + case close_lua_node: + switch (field) { + case 4: lua_pushnumber(L,late_lua_reg(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_colorstack_node: + switch (field) { + case 4: lua_pushnumber(L,pdf_colorstack_stack(n)); break; + case 5: lua_pushnumber(L,pdf_colorstack_cmd(n)); break; + case 6: tokenlist_to_luastring(L,pdf_colorstack_data(n)); break; + default: lua_pushnil(L); + } + break; + case pdf_setmatrix_node: + switch (field) { + case 4: tokenlist_to_luastring(L,pdf_setmatrix_data(n)); break; + default: lua_pushnil(L); + } + break; + case user_defined_node: + switch (field) { + case 4: lua_pushnumber(L,user_node_id(n)); break; + case 5: lua_pushnumber(L,user_node_type(n)); break; + case 6: + switch (user_node_type(n)) { + case 'a': nodelib_pushlist(L,user_node_value(n)); break; + case 'd': lua_pushnumber(L,user_node_value(n)); break; + case 'n': nodelib_pushlist(L,user_node_value(n)); break; + case 's': nodelib_pushstring(L,user_node_value(n)); break; + case 't': tokenlist_to_lua(L,user_node_value(n)); break; + default: lua_pushnumber(L,user_node_value(n)); break; + } break; + default: lua_pushnil(L); + } + break; + default: + lua_pushnil(L); + break; + } + } +} + + +static int +lua_nodelib_getfield (lua_State *L) { + halfword *n_ptr, n; + int field; + if (lua_isnil(L,1)) + return 1; /* a nil */ + n_ptr = check_isnode(L,1); + n = *n_ptr; + field = get_valid_node_field_id(L,2, n); + + if (field<-1) + return 0; + if (field==0) { + lua_pushnumber(L,vlink(n)); + lua_nodelib_push(L); + } else if (field==1) { + lua_pushnumber(L,type(n)); + } else if (field==-1) { + lua_pushnumber(L,alink(n)); + lua_nodelib_push(L); + } else if (field==3 && nodetype_has_attributes(type(n))) { + nodelib_pushattr(L,node_attr(n)); + } else { + switch (type(n)) { + case hlist_node: + case vlist_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: lua_pushnumber(L,width(n)); break; + case 5: lua_pushnumber(L,depth(n)); break; + case 6: lua_pushnumber(L,height(n)); break; + case 7: lua_pushnumber(L,box_dir(n)); break; + case 8: lua_pushnumber(L,shift_amount(n)); break; + case 9: lua_pushnumber(L,glue_order(n)); break; + case 10: lua_pushnumber(L,glue_sign(n)); break; + case 11: lua_pushnumber(L,(double)glue_set(n)); break; + case 12: nodelib_pushlist(L,list_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case unset_node: + switch (field) { + case 2: lua_pushnumber(L,0); break; + case 4: lua_pushnumber(L,width(n)); break; + case 5: lua_pushnumber(L,depth(n)); break; + case 6: lua_pushnumber(L,height(n)); break; + case 7: lua_pushnumber(L,box_dir(n)); break; + case 8: lua_pushnumber(L,glue_shrink(n)); break; + case 9: lua_pushnumber(L,glue_order(n)); break; + case 10: lua_pushnumber(L,glue_sign(n)); break; + case 11: lua_pushnumber(L,glue_stretch(n)); break; + case 12: lua_pushnumber(L,span_count(n)); break; + case 13: nodelib_pushlist(L,list_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case rule_node: + switch (field) { + case 2: lua_pushnumber(L,0); break; + case 4: lua_pushnumber(L,width(n)); break; + case 5: lua_pushnumber(L,depth(n)); break; + case 6: lua_pushnumber(L,height(n)); break; + case 7: lua_pushnumber(L,rule_dir(n)); break; + default: lua_pushnil(L); + } + break; + case ins_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: lua_pushnumber(L,float_cost(n)); break; + case 5: lua_pushnumber(L,depth(n)); break; + case 6: lua_pushnumber(L,height(n)); break; + case 7: nodelib_pushspec(L,split_top_ptr(n)); break; + case 8: nodelib_pushlist(L,ins_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case mark_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: lua_pushnumber(L,mark_class(n)); break; + case 5: tokenlist_to_lua(L,mark_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case adjust_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: nodelib_pushlist(L,adjust_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case disc_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: nodelib_pushlist(L,vlink(pre_break(n))); break; + case 5: nodelib_pushlist(L,vlink(post_break(n))); break; + case 6: nodelib_pushlist(L,vlink(no_break(n))); break; + default: lua_pushnil(L); + } + break; + case math_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: lua_pushnumber(L,surround(n)); break; + default: lua_pushnil(L); + } + break; + case glue_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: nodelib_pushspec(L,glue_ptr(n)); break; + case 5: nodelib_pushlist(L,leader_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case glue_spec_node: + switch (field) { + case 2: lua_pushnumber(L,0); break; + case 3: lua_pushnumber(L,width(n)); break; + case 4: lua_pushnumber(L,stretch(n)); break; + case 5: lua_pushnumber(L,shrink(n)); break; + case 6: lua_pushnumber(L,stretch_order(n)); break; + case 7: lua_pushnumber(L,shrink_order(n)); break; + case 8: lua_pushnumber(L,glue_ref_count(n)); break; + default: lua_pushnil(L); + } + break; + case kern_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: lua_pushnumber(L,width(n)); break; + default: lua_pushnil(L); + } + break; + case penalty_node: + switch (field) { + case 2: lua_pushnumber(L,0); break; + case 4: lua_pushnumber(L,penalty(n)); break; + default: lua_pushnil(L); + } + break; + case glyph_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 4: lua_pushnumber(L,character(n)); break; + case 5: lua_pushnumber(L,font(n)); break; + case 6: lua_pushnumber(L,char_lang(n)); break; + case 7: lua_pushnumber(L,char_lhmin(n)); break; + case 8: lua_pushnumber(L,char_rhmin(n)); break; + case 9: lua_pushnumber(L,char_uchyph(n)); break; + case 10: nodelib_pushlist(L,lig_ptr(n)); break; + case 11: lua_pushnumber(L,x_displace(n)); break; + case 12: lua_pushnumber(L,y_displace(n)); break; + default: lua_pushnil(L); + } + break; + case inserting_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 3: nodelib_pushlist(L,last_ins_ptr(n)); break; + case 4: nodelib_pushlist(L,best_ins_ptr(n)); break; + default: lua_pushnil(L); + } + break; + case split_up_node: + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 3: nodelib_pushlist(L,last_ins_ptr(n)); break; + case 4: nodelib_pushlist(L,best_ins_ptr(n)); break; + case 5: nodelib_pushlist(L,broken_ptr(n)); break; + case 6: nodelib_pushlist(L,broken_ins(n)); break; + default: lua_pushnil(L); + } + break; + case margin_kern_node : + switch (field) { + case 2: lua_pushnumber(L,subtype(n)); break; + case 3: lua_pushnumber(L,width(n)); break; + case 4: nodelib_pushlist(L,margin_char(n)); break; + default: lua_pushnil(L); + } + break; + case action_node: + switch (field) { + case 2: lua_pushnil(L); /* dummy subtype */ break; + case 3: lua_pushnumber(L,pdf_action_type(n)); break; + case 4: lua_pushnumber(L,pdf_action_named_id(n)); break; + case 5: if (pdf_action_named_id(n)==1) { + tokenlist_to_luastring(L,pdf_action_id(n)); + } else { + lua_pushnumber(L,pdf_action_id(n)); + } break; + case 6: tokenlist_to_luastring(L,pdf_action_file(n)); break; + case 7: lua_pushnumber(L,pdf_action_new_window(n)); break; + case 8: tokenlist_to_luastring(L,pdf_action_tokens(n));break; + case 9: lua_pushnumber(L,pdf_action_refcount(n)); break; + default: lua_pushnil(L); + } + break; + case attribute_list_node : + switch (field) { + case 2: lua_pushnumber(L,0); break; + default: lua_pushnil(L); + } + break; + case attribute_node : + switch (field) { + case 2: lua_pushnumber(L,0); break; + case 3: lua_pushnumber(L,attribute_id(n)); break; + case 4: lua_pushnumber(L,attribute_value(n)); break; + default: lua_pushnil(L); + } + break; + case whatsit_node: + lua_nodelib_getfield_whatsit(L,n,field); + break; + default: + lua_pushnil(L); + break; + } + } + return 1; +} + + +static int nodelib_getlist(lua_State *L, int n) { + halfword *m; + if (lua_isuserdata(L,n)) { + m = check_isnode(L,n); + return *m; + } else { + return null ; + } +} + +#define nodelib_getspec nodelib_getlist +#define nodelib_getaction nodelib_getlist + + +static str_number +nodelib_getstring(lua_State *L, int a) { + size_t k; + char *s=(char *)lua_tolstring(L,a, &k); + return maketexlstring(s,k); +} + +#define nodelib_gettoks(L,a) tokenlist_from_lua(L) + +static void nodelib_setattr (lua_State *L, int stackindex, halfword n) { + halfword p; + p = nodelib_getlist(L,stackindex); + if (node_attr(n) != p) { + if (node_attr(n)!=null) + delete_attribute_ref(node_attr(n)); + node_attr(n) = p; + attr_list_ref(p)++; + } +} + +static int nodelib_cantset (lua_State *L, int field, int n) { + lua_pushfstring(L,"You cannot set field %d in a node of type %s", + field, node_data[type(n)].name); + lua_error(L); + return 0; +} + +static int +lua_nodelib_setfield_whatsit(lua_State *L, int n, int field) { + switch (subtype(n)) { + case open_node: + switch (field) { + case 4: write_stream(n) = lua_tointeger(L,3); break; + case 5: open_name(n) = nodelib_getstring(L,3); break; + case 6: open_area(n) = nodelib_getstring(L,3); break; + case 7: open_ext(n) = nodelib_getstring(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case write_node: + switch (field) { + case 4: write_stream(n) = lua_tointeger(L,3); break; + case 5: write_tokens(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case close_node: + switch (field) { + case 4: write_stream(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case special_node: + switch (field) { + case 4: write_tokens(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case local_par_node: + switch (field) { + case 4: local_pen_inter(n) = lua_tointeger(L,3); break; + case 5: local_pen_broken(n) = lua_tointeger(L,3); break; + case 6: local_par_dir(n) = lua_tointeger(L,3); break; + case 7: local_box_left(n) = nodelib_getlist(L,3); break; + case 8: local_box_left_width(n) = lua_tointeger(L,3); break; + case 9: local_box_right(n) = nodelib_getlist(L,3); break; + case 10: local_box_right_width(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case dir_node: + switch (field) { + case 4: dir_dir(n) = lua_tointeger(L,3); break; + case 5: dir_level(n) = lua_tointeger(L,3); break; + case 6: dir_dvi_ptr(n) = lua_tointeger(L,3); break; + case 7: dir_dvi_h(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_literal_node: + switch (field) { + case 4: pdf_literal_mode(n) = lua_tointeger(L,3); break; + case 5: pdf_literal_data(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_refobj_node: + switch (field) { + case 4: pdf_obj_objnum(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_refxform_node: + switch (field) { + case 4: pdf_width(n) = lua_tointeger(L,3); break; + case 5: pdf_height(n) = lua_tointeger(L,3); break; + case 6: pdf_depth(n) = lua_tointeger(L,3); break; + case 7: pdf_xform_objnum(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_refximage_node: + switch (field) { + case 4: pdf_width(n) = lua_tointeger(L,3); break; + case 5: pdf_height(n) = lua_tointeger(L,3); break; + case 6: pdf_depth(n) = lua_tointeger(L,3); break; + case 7: pdf_ximage_objnum(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_annot_node: + switch (field) { + case 4: pdf_width(n) = lua_tointeger(L,3); break; + case 5: pdf_height(n) = lua_tointeger(L,3); break; + case 6: pdf_depth(n) = lua_tointeger(L,3); break; + case 7: pdf_annot_objnum(n) = lua_tointeger(L,3); break; + case 8: pdf_annot_data(n) = nodelib_getstring(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_start_link_node: + switch (field) { + case 4: pdf_width(n) = lua_tointeger(L,3); break; + case 5: pdf_height(n) = lua_tointeger(L,3); break; + case 6: pdf_depth(n) = lua_tointeger(L,3); break; + case 7: pdf_link_objnum(n) = lua_tointeger(L,3); break; + case 8: pdf_link_attr(n) = nodelib_getstring(L,3); break; + case 9: pdf_link_action(n) = nodelib_getaction(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_end_link_node: + switch (field) { + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_dest_node: + switch (field) { + case 4: pdf_width(n) = lua_tointeger(L,3); break; + case 5: pdf_height(n) = lua_tointeger(L,3); break; + case 6: pdf_depth(n) = lua_tointeger(L,3); break; + case 7: pdf_dest_named_id(n) = lua_tointeger(L,3); break; + case 8: if (pdf_dest_named_id(n)==1) + pdf_dest_id(n) = nodelib_gettoks(L,3); + else + pdf_dest_id(n) = lua_tointeger(L,3); break; + case 9: pdf_dest_type(n) = lua_tointeger(L,3); break; + case 10: pdf_dest_xyz_zoom(n) = lua_tointeger(L,3); break; + case 11: pdf_dest_objnum(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_thread_node: + case pdf_start_thread_node: + switch (field) { + case 4: pdf_width(n) = lua_tointeger(L,3); break; + case 5: pdf_height(n) = lua_tointeger(L,3); break; + case 6: pdf_depth(n) = lua_tointeger(L,3); break; + case 7: pdf_thread_named_id(n) = lua_tointeger(L,3); break; + case 8: if (pdf_thread_named_id(n)==1) + pdf_thread_id(n) = nodelib_gettoks(L,3); + else + pdf_thread_id(n) = lua_tointeger(L,3); break; + case 9: pdf_thread_attr(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_end_thread_node: + case pdf_save_pos_node: + return nodelib_cantset(L,field,n); + break; + case late_lua_node: + switch (field) { + case 4: late_lua_reg(n) = lua_tointeger(L,3); break; + case 5: late_lua_data(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case close_lua_node: + switch (field) { + case 4: late_lua_reg(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_colorstack_node: + switch (field) { + case 4: pdf_colorstack_stack(n) = lua_tointeger(L,3); break; + case 5: pdf_colorstack_cmd(n) = lua_tointeger(L,3); break; + case 6: pdf_colorstack_data(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_setmatrix_node: + switch (field) { + case 4: pdf_setmatrix_data(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case pdf_save_node: + case pdf_restore_node: + case cancel_boundary_node: + return nodelib_cantset(L,field,n); + break; + case user_defined_node: + switch (field) { + case 4: user_node_id(n) = lua_tointeger(L,3); break; + case 5: user_node_type(n) = lua_tointeger(L,3); break; + case 6: + switch(user_node_type(n)) { + case 'a': user_node_value(n) = nodelib_getlist(L,3); break; + case 'd': user_node_value(n) = lua_tointeger(L,3); break; + case 'n': user_node_value(n) = nodelib_getlist(L,3); break; + case 's': user_node_value(n) = nodelib_getstring(L,3); break; + case 't': user_node_value(n) = nodelib_gettoks(L,3); break; + default: user_node_value(n) = lua_tointeger(L,3); break; + } break; + default: return nodelib_cantset(L,field,n); + } + break; + default: + /* do nothing */ + break; + } + return 0; +} + +static int +lua_nodelib_setfield (lua_State *L) { + register halfword n; + register int field; + n = *check_isnode(L,1); + field = get_valid_node_field_id(L,2,n); + if (field<-1) + return 0; + if (field==0) { + vlink(n) = nodelib_getlist(L,3); + } else if (field==-1) { + alink(n) = nodelib_getlist(L,3); + } else if (field==3 && nodetype_has_attributes(type(n))) { + nodelib_setattr(L,3,n); + } else if (type(n)==glyph_node) { + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: character(n) = lua_tointeger(L,3); break; + case 5: font(n) = lua_tointeger(L,3); break; + case 6: set_char_lang(n,lua_tointeger(L,3)); break; + case 7: set_char_lhmin(n,lua_tointeger(L,3)); break; + case 8: set_char_rhmin(n,lua_tointeger(L,3)); break; + case 9: set_char_uchyph(n,lua_tointeger(L,3)); break; + case 10: lig_ptr(n) = nodelib_getlist(L,3); break; + case 11: x_displace(n) = lua_tointeger(L,3); break; + case 12: y_displace(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + } else { + switch (type(n)) { + case hlist_node: + case vlist_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: width(n) = lua_tointeger(L,3); break; + case 5: depth(n) = lua_tointeger(L,3); break; + case 6: height(n) = lua_tointeger(L,3); break; + case 7: box_dir(n) = lua_tointeger(L,3); break; + case 8: shift_amount(n) = lua_tointeger(L,3); break; + case 9: glue_order(n) = lua_tointeger(L,3); break; + case 10: glue_sign(n) = lua_tointeger(L,3); break; + case 11: glue_set(n) = (double)lua_tonumber(L,3); break; + case 12: list_ptr(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case unset_node: + switch (field) { + case 2: /* dummy subtype */ break; + case 4: width(n) = lua_tointeger(L,3); break; + case 5: depth(n) = lua_tointeger(L,3); break; + case 6: height(n) = lua_tointeger(L,3); break; + case 7: box_dir(n) = lua_tointeger(L,3); break; + case 8: glue_shrink(n) = lua_tointeger(L,3); break; + case 9: glue_order(n) = lua_tointeger(L,3); break; + case 10: glue_sign(n) = lua_tointeger(L,3); break; + case 11: glue_stretch(n) = lua_tointeger(L,3); break; + case 12: span_count(n) = lua_tointeger(L,3); break; + case 13: list_ptr(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case rule_node: + switch (field) { + case 2: /* dummy subtype */ break; + case 4: width(n) = lua_tointeger(L,3); break; + case 5: depth(n) = lua_tointeger(L,3); break; + case 6: height(n) = lua_tointeger(L,3); break; + case 7: rule_dir(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case ins_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: float_cost(n) = lua_tointeger(L,3); break; + case 5: depth(n) = lua_tointeger(L,3); break; + case 6: height(n) = lua_tointeger(L,3); break; + case 7: split_top_ptr(n) = nodelib_getspec(L,3); break; + case 8: ins_ptr(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case mark_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: mark_class(n) = lua_tointeger(L,3); break; + case 5: mark_ptr(n) = nodelib_gettoks(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case adjust_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: adjust_ptr(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case disc_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: set_disc_field(pre_break(n),nodelib_getlist(L,3)); break; + case 5: set_disc_field(post_break(n),nodelib_getlist(L,3)); break; + case 6: set_disc_field(no_break(n),nodelib_getlist(L,3)); break; + default: return nodelib_cantset(L,field,n); + } + break; + case math_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: surround(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case glue_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: glue_ptr(n) = nodelib_getspec(L,3); break; + case 5: leader_ptr(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case glue_spec_node: + switch (field) { + case 2: /* dummy subtype */ break; + case 3: width(n) = lua_tointeger(L,3); break; + case 4: stretch(n) = lua_tointeger(L,3); break; + case 5: shrink(n) = lua_tointeger(L,3); break; + case 6: stretch_order(n) = lua_tointeger(L,3); break; + case 7: shrink_order(n) = lua_tointeger(L,3); break; + case 8: glue_ref_count(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case kern_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 4: width(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case penalty_node: + switch (field) { + case 2: /* dummy subtype */ break; + case 4: penalty(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case action_node: + switch (field) { + case 2: /* dummy subtype */ break; + case 3: pdf_action_type(n) = lua_tointeger(L,3); break; + case 4: pdf_action_named_id(n) = lua_tointeger(L,3); break; + case 5: if (pdf_action_named_id(n)==1) { + pdf_action_id(n) = nodelib_gettoks(L,3); + } else { + pdf_action_id(n) = lua_tointeger(L,3); + } break; + case 6: pdf_action_file(n) = nodelib_gettoks(L,3); break; + case 7: pdf_action_new_window(n) = lua_tointeger(L,3); break; + case 8: pdf_action_tokens(n) = nodelib_gettoks(L,3); break; + case 9: pdf_action_refcount(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case margin_kern_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 3: width(n) = lua_tointeger(L,3); break; + case 4: margin_char(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case inserting_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 3: last_ins_ptr(n) = nodelib_getlist(L,3); break; + case 4: best_ins_ptr(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case split_up_node: + switch (field) { + case 2: subtype(n) = lua_tointeger(L,3); break; + case 3: last_ins_ptr(n) = nodelib_getlist(L,3); break; + case 4: best_ins_ptr(n) = nodelib_getlist(L,3); break; + case 5: broken_ptr(n) = nodelib_getlist(L,3); break; + case 6: broken_ins(n) = nodelib_getlist(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case attribute_list_node: + switch (field) { + case 2: /* dummy subtype */ break; + default: return nodelib_cantset(L,field,n); + } + break; + case attribute_node: + switch (field) { + case 2: /* dummy subtype */ break; + case 3: attribute_id(n) = lua_tointeger(L,3); break; + case 4: attribute_value(n) = lua_tointeger(L,3); break; + default: return nodelib_cantset(L,field,n); + } + break; + case whatsit_node: + lua_nodelib_setfield_whatsit(L,n,field); + break; + default: + /* do nothing */ + break; + } + } + return 0; +} + +static int +lua_nodelib_print (lua_State *L) { + char *msg; + char a[7] = {' ',' ',' ', 'n', 'i', 'l', 0}; + char v[7] = {' ',' ',' ', 'n', 'i', 'l', 0}; + halfword *n; + n = check_isnode(L,1); + msg = xmalloc(256); + if (alink(*n)!=null) + snprintf(a,7,"%6d",(int)alink(*n)); + if (vlink(*n)!=null) + snprintf(v,7,"%6d",(int)vlink(*n)); + snprintf(msg,255," %s : %s %d>", a, (int)*n, v, node_data[type(*n)].name, subtype(*n)); + lua_pushstring(L,msg); + free(msg); + return 1; +} + + +static int +lua_nodelib_equal (lua_State *L) { + halfword n, m; + n = *(check_isnode(L,1)); + m = *(check_isnode(L,2)); + lua_pushboolean(L,(n==m)); + return 1; +} + +static int +font_tex_ligaturing (lua_State *L) { + /* on the stack are two nodes and a direction */ + halfword tmp_head; + halfword *h; + halfword t =null; + if (lua_gettop(L)<1) { + lua_pushnil(L); + lua_pushboolean(L,0); + return 2; + } + h = check_isnode(L,1); + if (lua_gettop(L)>1) { + t = *(check_isnode(L,2)); + } + tmp_head = new_node(nesting_node,1); + couple_nodes(tmp_head,*h); + tlink(tmp_head)=t; + t = handle_ligaturing(tmp_head,t); + lua_pushnumber(L,vlink(tmp_head)); + flush_node(tmp_head); + lua_nodelib_push(L); + lua_pushnumber(L,t); + lua_nodelib_push(L); + lua_pushboolean(L,1); + return 3; +} + +static int +font_tex_kerning (lua_State *L) { + /* on the stack are two nodes and a direction */ + + halfword tmp_head; + halfword *h; + halfword t =null; + if (lua_gettop(L)<1) { + lua_pushnil(L); + lua_pushboolean(L,0); + return 2; + } + h = check_isnode(L,1); + if (lua_gettop(L)>1) { + t = *(check_isnode(L,2)); + } + tmp_head = new_node(nesting_node,1); + couple_nodes(tmp_head,*h); + tlink(tmp_head)=t; + t = handle_kerning(tmp_head,t); + lua_pushnumber(L,vlink(tmp_head)); + flush_node(tmp_head); + lua_nodelib_push(L); + lua_pushnumber(L,t); + lua_nodelib_push(L); + lua_pushboolean(L,1); + return 3; +} + +static int +lua_nodelib_protect_glyphs (lua_State *L) { + int t = 0; + halfword head = *(check_isnode(L,1)); + while (head!=null) { + if (type(head)==glyph_node) { + register int s = subtype(head); + if (s<256) { + t = 1; + subtype(head) = ((s&0xFE) << 8); + } + } + head = vlink(head); + } + lua_pushboolean(L,t); + lua_pushvalue(L,1); + return 2; +} + +static int +lua_nodelib_unprotect_glyphs (lua_State *L) { + int t = 0; + halfword head = *(check_isnode(L,1)); + while (head!=null) { + if (type(head)==glyph_node) { + register int s = subtype(head); + if (s>=256) { + t = 1; + subtype(head) = (s >> 8); + } + } + head = vlink(head); + } + lua_pushboolean(L,t); + lua_pushvalue(L,1); + return 2; +} + + +static int +lua_nodelib_first_character (lua_State *L) { + /* on the stack are two nodes and a direction */ + halfword h, savetail = null, t = null; + if (lua_gettop(L)<1) { + lua_pushnil(L); + lua_pushboolean(L,0); + return 2; + } + h = *(check_isnode(L,1)); + if (lua_gettop(L)>1) { + t = *(check_isnode(L,2)); + savetail = vlink(t); + vlink(t) = null; + } + while (h!=null && !is_simple_character(h)) { + h = vlink(h); + } + if (savetail!=null) { vlink(t) = savetail; } + lua_pushnumber(L,h); + lua_nodelib_push(L); + lua_pushboolean(L,(h==null? 0 : 1)); + return 2; +} + + +/* this is too simplistic, but it helps Hans to get going */ + +halfword +do_ligature_n (halfword prev, halfword stop, halfword lig) { + vlink(lig) = vlink(stop); + vlink(stop) = null; + lig_ptr(lig) = vlink(prev); + vlink(prev) = lig; + return lig; +} + + + +/* node.do_ligature_n(node prev, node last, node lig) */ +static int +lua_nodelib_do_ligature_n (lua_State *L) { + halfword n, m, o, p, tmp_head; + n = *(check_isnode(L,1)); + m = *(check_isnode(L,2)); + o = *(check_isnode(L,3)); + if (alink(n)==null || vlink(alink(n))!=n) { + tmp_head = new_node(temp_node,0); + couple_nodes(tmp_head,n); + p = do_ligature_n(tmp_head,m,o); + flush_node(tmp_head); + } else { + p = do_ligature_n(alink(n),m,o); + } + lua_pushnumber(L,p); + lua_nodelib_push(L); + return 1; +} + +extern halfword list_node_mem_usage (void) ; + +static int +lua_nodelib_usedlist (lua_State *L) { + lua_pushnumber(L,list_node_mem_usage()); + lua_nodelib_push(L); + return 1; +} + + +static const struct luaL_reg nodelib_f [] = { + {"id", lua_nodelib_id}, + {"subtype", lua_nodelib_subtype}, + {"type", lua_nodelib_type}, + {"new", lua_nodelib_new}, + {"length", lua_nodelib_length}, + {"count", lua_nodelib_count}, + {"traverse", lua_nodelib_traverse}, + {"traverse_id", lua_nodelib_traverse_filtered}, + {"slide", lua_nodelib_tail}, + {"types", lua_nodelib_types}, + {"whatsits", lua_nodelib_whatsits}, + {"fields", lua_nodelib_fields}, + {"has_field", lua_nodelib_has_field}, + {"free", lua_nodelib_free}, + {"flush_list", lua_nodelib_flush_list}, + {"remove", lua_nodelib_remove}, + {"insert_before", lua_nodelib_insert_before}, + {"insert_after", lua_nodelib_insert_after}, + {"write", lua_nodelib_append}, + {"last_node", lua_nodelib_last_node}, + {"copy", lua_nodelib_copy}, + {"copy_list", lua_nodelib_copy_list}, + {"hpack", lua_nodelib_hpack}, + {"has_attribute", lua_nodelib_has_attribute}, + {"set_attribute", lua_nodelib_set_attribute}, + {"unset_attribute", lua_nodelib_unset_attribute}, + {"do_ligature_n", lua_nodelib_do_ligature_n}, + {"ligaturing", font_tex_ligaturing}, + {"kerning", font_tex_kerning}, + {"first_character", lua_nodelib_first_character}, + {"usedlist", lua_nodelib_usedlist}, + {"protect_glyphs", lua_nodelib_protect_glyphs}, + {"unprotect_glyphs", lua_nodelib_unprotect_glyphs}, + {NULL, NULL} /* sentinel */ +}; + +static const struct luaL_reg nodelib_m [] = { + {"__index", lua_nodelib_getfield}, + {"__newindex", lua_nodelib_setfield}, + {"__tostring", lua_nodelib_print}, + {"__eq", lua_nodelib_equal}, + {NULL, NULL} /* sentinel */ +}; + + + +int +luaopen_node (lua_State *L) +{ + luaL_newmetatable(L,NODE_METATABLE); + luaL_register(L, NULL, nodelib_m); + luaL_register(L, "node", nodelib_f); + init_luaS_index(luatex_node); + initialize_luaS_indexes(L); + return 1; +} + +void +nodelist_to_lua (lua_State *L, int n) { + lua_pushnumber(L,n); + lua_nodelib_push(L); +} + +int +nodelist_from_lua (lua_State *L) { + halfword *n; + if (lua_isnil(L,-1)) + return null; + n = check_isnode(L,-1); + return *n; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/loslibext.c b/Build/source/texk/web2c/luatexdir/lua/loslibext.c new file mode 100644 index 00000000000..003b031f627 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/loslibext.c @@ -0,0 +1,627 @@ +/* $Id: loslibext.c 1066 2008-02-23 10:52:51Z taco $ */ + +#include "luatex-api.h" +#include + +#include +#include +#include + +/* An attempt to figure out the basic platform, does not + care about niceties like version numbers yet, + and ignores platforms where luatex is unlikely to + successfully compile without major prorting effort + (amiga|mac|os2|vms) */ + +#if defined(_WIN32) || defined(WIN32) || defined(__NT__) +#define OS_PLATTYPE "windows" +#define OS_PLATNAME "windows" +#elif defined(__GO32__) || defined(__DJGPP__) || defined(__DOS__) +#define OS_PLATTYPE "msdos" +#define OS_PLATNAME "msdos" +#else /* assume everything else is unix-y */ +#define OS_PLATTYPE "unix" +/* this is just a first guess */ +#if defined(__BSD__) + #define OS_PLATNAME "bsd" +#elif defined(__SYSV__) + #define OS_PLATNAME "sysv" +#else + #define OS_PLATNAME "generic" +#endif +/* attempt to be more precise */ +#if defined(__LINUX__) || defined (__linux) + #undef OS_PLATNAME + #define OS_PLATNAME "linux" +#elif defined(__FREEBSD__) || defined(__FreeBSD) + #undef OS_PLATNAME + #define OS_PLATNAME "freebsd" +#elif defined(__OPENBSD__) || defined(__OpenBSD) + #undef OS_PLATNAME + #define OS_PLATNAME "openbsd" +#elif defined(__SOLARIS__) + #undef OS_PLATNAME + #define OS_PLATNAME "solaris" +#elif defined(__SUNOS__) || defined(__SUN__) || defined(sun) + #undef OS_PLATNAME + #define OS_PLATNAME "sunos" +#elif defined(HPUX) || defined(__hpux) + #undef OS_PLATNAME + #define OS_PLATNAME "hpux" +#elif defined(__sgi) + #undef OS_PLATNAME + #define OS_PLATNAME "irix" +#elif defined(__MACH__) && defined(__APPLE__) + #undef OS_PLATNAME + #define OS_PLATNAME "macosx" +#endif +#endif + + + + + +/* there could be more platforms that don't have these two, + * but win32 and sunos are for sure. + * gettimeofday() for win32 is using an alternative definition + */ + +#if (! defined(WIN32)) && (! defined(__SUNOS__)) +#include /* gettimeofday() */ +#include /* times() */ +#include +#endif + +/* set this to one for spawn instead of exec on windows */ + +#define DONT_REALLY_EXIT 1 + +#ifdef WIN32 +#include +#define spawn_command(a,b,c) _spawnvpe(_P_WAIT,(const char *)a,(const char* const*)b,(const char* const*)c) +#if DONT_REALLY_EXIT +#define exec_command(a,b,c) exit(spawn_command((a),(b),(c))) +#else +#define exec_command(a,b,c) _execvpe((const char *)a,(const char* const*)b,(const char* const*)c) +#endif +#else +#include +#define DEFAULT_PATH "/bin:/usr/bin:." + +static int +exec_command(const char *file, char *const *argv, char *const *envp) +{ + char path[PATH_MAX]; + const char *searchpath, *esp; + size_t prefixlen, filelen, totallen; + + if (strchr(file, '/')) /* Specific path */ + return execve(file, argv, envp); + + filelen = strlen(file); + + searchpath = getenv("PATH"); + if (!searchpath) + searchpath = DEFAULT_PATH; + + errno = ENOENT; /* Default errno, if execve() doesn't change it */ + + do { + esp = strchr(searchpath, ':'); + if (esp) + prefixlen = esp - searchpath; + else + prefixlen = strlen(searchpath); + + if (prefixlen == 0 || searchpath[prefixlen - 1] == '/') { + totallen = prefixlen + filelen; + if (totallen >= PATH_MAX) + continue; + memcpy(path, searchpath, prefixlen); + memcpy(path + prefixlen, file, filelen); + } else { + totallen = prefixlen + filelen + 1; + if (totallen >= PATH_MAX) + continue; + memcpy(path, searchpath, prefixlen); + path[prefixlen] = '/'; + memcpy(path + prefixlen + 1, file, filelen); + } + path[totallen] = '\0'; + + execve(path, argv, envp); + if (errno == E2BIG || errno == ENOEXEC || + errno == ENOMEM || errno == ETXTBSY) + break; /* Report this as an error, no more search */ + + searchpath = esp + 1; + } while (esp); + + return -1; +} + +/* + It is not possible to mimic |spawnve()| completely. The main problem is + that the |fork|--|waitpid| combination cannot really do identical error + reporting to the parent process, because it has to pass all the possible + error conditions as well as the actual process return status through a + single 8-bit value. + + The current implementation tries to give back meaningful results for |execve()| + errors in the child, for the cases that could also be returned by |spawnve()|, + and for |ETXTBSY|, because that can be triggered by our path searching routine. + + This implementation does not differentiate abnormal status conditions reported + by |waitpid()|, but will simply return a single error indication value. + + For all this, hyjacking a bunch of numbers in the range 1...255 is needed. + The chance of collisions is hopefully diminished by using a rather random + range in the 8-bit section. +*/ + +#define INVALID_RET_E2BIG 143 +#define INVALID_RET_ENOENT 144 +#define INVALID_RET_ENOEXEC 145 +#define INVALID_RET_ENOMEM 146 +#define INVALID_RET_ETXTBSY 147 +#define INVALID_RET_UNKNOWN 148 +#define INVALID_RET_INTR 149 + +static int +spawn_command(const char *file, char *const *argv, char *const *envp) +{ + pid_t pid, wait_pid; + int status; + pid = fork(); + if (pid<0) { + return -1; /* fork failed */ + } + if (pid>0) { /* parent */ + status = 0; + wait_pid = waitpid (pid, &status,0); + if (wait_pid == pid) { + if (WIFEXITED(status)) + return WEXITSTATUS(status); + else + return INVALID_RET_INTR; + } else { + return -1; /* some waitpid error */ + } + } else { + int f; + /* somewhat random upper limit. ignore errors on purpose */ + for (f = 0; f<256; f++) + (void)fsync(f); + + if (exec_command(file, argv, envp)) { + /* let's hope no-one uses these values */ + switch (errno) { + case E2BIG: exit(INVALID_RET_E2BIG); + case ETXTBSY: exit(INVALID_RET_ETXTBSY); + case ENOENT: exit(INVALID_RET_ENOENT); + case ENOEXEC: exit(INVALID_RET_ENOEXEC); + case ENOMEM: exit(INVALID_RET_ENOMEM); + default: exit(INVALID_RET_UNKNOWN); + } + return -1; + } + } +} + +#endif + +extern char **environ; + +static char ** +do_split_command(char *maincmd) +{ + char *piece, *start_piece; + char *cmd; + char **cmdline = NULL; + unsigned int i, j; + int ret = 0; + int in_string = 0; + int quoted = 0; + if (strlen(maincmd) == 0) + return NULL; + /* allocate the array of options first. it will probably be + be a little bit too big, but better too much than to little */ + j=2; + for (i = 0; i < strlen(maincmd); i++) { if (maincmd[i]==' ') j++; } + cmdline = malloc(sizeof(char *) * j); + for (i = 0; i < j; i++) { cmdline[i] = NULL; } + cmd = maincmd; + i = 0; + while (cmd[i] == ' ') i++; /* skip leading spaces */ + start_piece = malloc(strlen(cmd)+1); /* a buffer */ + piece = start_piece; + for (; i <= strlen(maincmd); i++) { + if (cmd[i]=='\\' && + (cmd[i+1] == '\\' || cmd[i+1] == '\'' || cmd[i+1] == '"')) { + quoted =1; + continue; + } + if (in_string && cmd[i] == in_string && !quoted) { + in_string = 0; + continue; + } + if ((cmd[i] == '"' || cmd[i] == '\'')&& !quoted) { + in_string = cmd[i]; + continue; + } + if ((in_string==0 && cmd[i] == ' ') || cmd[i]==0) { + *piece = 0; + cmdline[ret++] = xstrdup(start_piece); + piece = start_piece; + while (i < strlen(maincmd) && cmd[(i + 1)] == ' ') + i++; + continue; + } + *piece++ = cmd[i]; + quoted=0; + } + xfree(start_piece); + return cmdline; +} + +static char ** +do_flatten_command(lua_State *L, char **runcmd) { + unsigned int i, j ; + char *s; + char **cmdline = NULL; + *runcmd = NULL; + + for (j = 1;;j++) { + lua_rawgeti(L,-1,j); + if (lua_isnil(L,-1)) { + lua_pop(L,1); + break; + } + lua_pop(L,1); + } + if (j == 1) + return NULL; + cmdline = malloc(sizeof(char *) * (j+1)); + for (i = 1; i <= j; i++) { + cmdline[i] = NULL; + lua_rawgeti(L,-1,i); + if (lua_isnil(L,-1) || (s=(char *)lua_tostring(L,-1))==NULL) { + lua_pop(L,1); + if (i==1) { + xfree(cmdline) ; + return NULL; + } else { + break; + } + } else { + lua_pop(L,1); + cmdline[(i-1)] = xstrdup(s); + } + } + cmdline[i] = NULL; + + lua_rawgeti(L,-1,0); + if (lua_isnil(L,-1) || (s=(char *)lua_tostring(L,-1))==NULL) { + *runcmd = cmdline[0]; + } else { + *runcmd = xstrdup(s); + } + lua_pop(L,1); + + return cmdline; +} + + +static int os_exec (lua_State *L) { + char * maincmd, * runcmd; + char ** cmdline = NULL; + + if (lua_gettop(L)!=1) { + lua_pushnil(L); + lua_pushliteral(L,"invalid arguments passed"); + return 2; + } + if (lua_type(L,1)==LUA_TSTRING) { + maincmd = (char *)lua_tostring(L, 1); + cmdline = do_split_command(maincmd); + runcmd = cmdline[0]; + } else if (lua_type(L,1)==LUA_TTABLE) { + cmdline = do_flatten_command(L, & runcmd); + } + if (cmdline!=NULL) { +#if defined(WIN32) && DONT_REALLY_EXIT + exec_command(runcmd, cmdline, environ); +#else + if (exec_command(runcmd, cmdline, environ)==-1) { + lua_pushnil(L); + lua_pushfstring(L,"%s: %s",runcmd, strerror(errno)); + lua_pushnumber(L, errno); + return 3; + } +#endif + } + lua_pushnil(L); + lua_pushliteral(L,"invalid command line passed"); + return 2; +} + +#define do_error_return(A,B) do { \ + lua_pushnil(L); \ + lua_pushfstring(L,"%s: %s",runcmd,(A)); \ + lua_pushnumber(L, B); \ + return 3; \ + } while (0) + +static int os_spawn (lua_State *L) { + char * maincmd, * runcmd; + char ** cmdline = NULL; + int i; + + if (lua_gettop(L)!=1) { + lua_pushnil(L); + lua_pushliteral(L,"invalid arguments passed"); + return 2; + } + if (lua_type(L,1)==LUA_TSTRING) { + maincmd = (char *)lua_tostring(L, 1); + cmdline = do_split_command(maincmd); + runcmd = cmdline[0]; + } else if (lua_type(L,1)==LUA_TTABLE) { + cmdline = do_flatten_command(L, &runcmd); + } + if (cmdline!=NULL) { + i = spawn_command(runcmd, cmdline, environ); + if (i==0) { + lua_pushnumber(L, i); + return 1; + } else if (i==-1) { + /* this branch covers WIN32 as well as fork() and waitpid() errors */ + do_error_return(strerror(errno),errno); +#ifndef WIN32 + } else if (i==INVALID_RET_E2BIG) { do_error_return(strerror(E2BIG),i); + } else if (i==INVALID_RET_ENOENT) { do_error_return(strerror(ENOENT),i); + } else if (i==INVALID_RET_ENOEXEC) { do_error_return(strerror(ENOEXEC),i); + } else if (i==INVALID_RET_ENOMEM) { do_error_return(strerror(ENOMEM),i); + } else if (i==INVALID_RET_ETXTBSY) { do_error_return(strerror(ETXTBSY),i); + } else if (i==INVALID_RET_UNKNOWN) { do_error_return("execution failed",i); + } else if (i==INVALID_RET_INTR) { do_error_return("execution interrupted",i); +#endif + } else { + lua_pushnumber(L, i); + return 1; + } + } + lua_pushnil(L); + lua_pushliteral(L,"invalid command line passed"); + return 2; +} + +/* Hans wants to set env values */ + +static int os_setenv (lua_State *L) { + char *value, *key, *val; + key = (char *)luaL_optstring(L, 1, NULL); + val = (char *)luaL_optstring(L, 2, NULL); + if (key) { + if (val) { + value = xmalloc(strlen(key)+strlen(val)+2); + sprintf(value,"%s=%s",key,val); + if (putenv(value)) { + return luaL_error(L, "unable to change environment"); + } + } else { +#if defined(WIN32) || defined(__sun__) + value = xmalloc(strlen(key)+2); + sprintf(value,"%s=",key); + if (putenv(value)) { + return luaL_error(L, "unable to change environment"); + } +#else + (void)unsetenv(key); +#endif + } + } + lua_pushboolean (L, 1); + return 1; +} + + +void find_env (lua_State *L){ + char *envitem, *envitem_orig; + char *envkey; + char **envpointer; + envpointer = environ; + lua_getglobal(L,"os"); + if (envpointer!=NULL && lua_istable(L,-1)) { + luaL_checkstack(L,2,"out of stack space"); + lua_pushstring(L,"env"); + lua_newtable(L); + while (*envpointer) { + /* TODO: perhaps a memory leak here */ + luaL_checkstack(L,2,"out of stack space"); + envitem = xstrdup(*envpointer); + envitem_orig = envitem; + envkey=envitem; + while (*envitem != '=') { + envitem++; + } + *envitem=0; + envitem++; + lua_pushstring(L,envkey); + lua_pushstring(L,envitem); + lua_rawset(L,-3); + envpointer++; + free(envitem_orig); + } + lua_rawset(L,-3); + } + lua_pop(L,1); +} + +static int ex_sleep(lua_State *L) +{ + lua_Number interval = luaL_checknumber(L, 1); + lua_Number units = luaL_optnumber(L, 2, 1); +#ifdef WIN32 + Sleep(1e3 * interval / units); +#else /* assumes posix or bsd */ + usleep(1e6 * interval / units); +#endif + return 0; +} + +#if (! defined (WIN32)) && (! defined (__SUNOS__)) +static int os_times (lua_State *L) { + struct tms r; + (void)times(&r); + lua_newtable(L); + lua_pushnumber(L, ((lua_Number)(r.tms_utime))/(lua_Number)sysconf(_SC_CLK_TCK)); + lua_setfield(L,-2,"utime"); + lua_pushnumber(L, ((lua_Number)(r.tms_stime))/(lua_Number)sysconf(_SC_CLK_TCK)); + lua_setfield(L,-2,"stime"); + lua_pushnumber(L, ((lua_Number)(r.tms_cutime))/(lua_Number)sysconf(_SC_CLK_TCK)); + lua_setfield(L,-2,"cutime"); + lua_pushnumber(L, ((lua_Number)(r.tms_cstime))/(lua_Number)sysconf(_SC_CLK_TCK)); + lua_setfield(L,-2,"cstime"); + return 1; +} +#endif + +#if ! defined (__SUNOS__) + +#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) + #define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 +#else + #define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL +#endif + +static int os_gettimeofday (lua_State *L) { + double v; +#ifndef WIN32 + struct timeval tv; + gettimeofday(&tv, NULL); + v = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0; +#else + FILETIME ft; + unsigned __int64 tmpres = 0; + + GetSystemTimeAsFileTime(&ft); + + tmpres |= ft.dwHighDateTime; + tmpres <<= 32; + tmpres |= ft.dwLowDateTime; + tmpres /= 10; + tmpres -= DELTA_EPOCH_IN_MICROSECS; /*converting file time to unix epoch*/ + v = (double)tmpres / 1000000.0; +#endif + lua_pushnumber(L, v); + return 1; +} +#endif + +static const char repl[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + +static int dirs_made = 0; + +#define MAXTRIES 36*36*36 + +char * +do_mkdtemp (char *tmpl) +{ + int count ; + int value ; + char *xes = &tmpl[strlen (tmpl) - 6]; + /* this is not really all that random, but it will do */ + if (dirs_made==0) { + srand(time(NULL)); + } + value = rand(); + for (count = 0; count < MAXTRIES; value += 8413, ++count) { + int v = value; + xes[0] = repl[v % 36]; v /= 36; + xes[1] = repl[v % 36]; v /= 36; + xes[2] = repl[v % 36]; v /= 36; + xes[3] = repl[v % 36]; v /= 36; + xes[4] = repl[v % 36]; v /= 36; + xes[5] = repl[v % 36]; + if (mkdir (tmpl, S_IRUSR | S_IWUSR | S_IXUSR) >= 0) { + dirs_made++; + return tmpl; + } else if (errno != EEXIST) { + return NULL; + } + } + return NULL; +} + +static int os_tmpdir (lua_State *L) { + char *s, *tempdir; + char *tmp = (char *)luaL_optstring(L, 1, "luatex.XXXXXX"); + if (tmp==NULL || + strlen(tmp)<6 || + (strcmp(tmp+strlen(tmp)-6,"XXXXXX") != 0)) { + lua_pushnil(L); + lua_pushstring(L, "Invalid argument to os.tmpdir()"); + return 2; + } else { + tempdir = xstrdup(tmp); + } +#ifdef HAVE_MKDTEMP + s = mkdtemp(tempdir); +#else + s = do_mkdtemp(tempdir); +#endif + if (s==NULL) { + int en = errno; /* calls to Lua API may change this value */ + lua_pushnil(L); + lua_pushfstring(L, "%s", strerror(en)); + return 2; + } else { + lua_pushstring(L,s); + return 1; + } +} + + +void +open_oslibext (lua_State *L, int safer_option) { + + find_env(L); + + lua_getglobal(L,"os"); + lua_pushcfunction(L, ex_sleep); + lua_setfield(L,-2,"sleep"); + lua_getglobal(L,"os"); + lua_pushliteral(L, OS_PLATTYPE); + lua_setfield(L,-2,"type"); + lua_getglobal(L,"os"); + lua_pushliteral(L, OS_PLATNAME); + lua_setfield(L,-2,"name"); +#if (! defined (WIN32)) && (! defined (__SUNOS__)) + lua_getglobal(L,"os"); + lua_pushcfunction(L, os_times); + lua_setfield(L,-2,"times"); +#endif +#if ! defined (__SUNOS__) + lua_getglobal(L,"os"); + lua_pushcfunction(L, os_gettimeofday); + lua_setfield(L,-2,"gettimeofday"); +#endif + if (!safer_option) { + lua_getglobal(L,"os"); + lua_pushcfunction(L, os_setenv); + lua_setfield(L,-2,"setenv"); + lua_getglobal(L,"os"); + lua_pushcfunction(L, os_exec); + lua_setfield(L,-2,"exec"); + lua_getglobal(L,"os"); + lua_pushcfunction(L, os_spawn); + lua_setfield(L,-2,"spawn"); + lua_getglobal(L,"os"); + lua_pushcfunction(L, os_tmpdir); + lua_setfield(L,-2,"tmpdir"); + + } + + +} diff --git a/Build/source/texk/web2c/luatexdir/lua/lpdflib.c b/Build/source/texk/web2c/luatexdir/lua/lpdflib.c new file mode 100644 index 00000000000..9cf847c84c8 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lpdflib.c @@ -0,0 +1,127 @@ +/* $Id: lpdflib.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + + +static int +findcurv (lua_State *L) { + int j; + j = get_cur_v(); + lua_pushnumber(L, j); + return 1; +} + +static int +findcurh (lua_State *L) { + int j; + j = get_cur_h(); + lua_pushnumber(L, j); + return 1; +} + + +typedef enum { set_origin, direct_page, direct_always } pdf_lit_mode; + +int luapdfprint(lua_State * L) +{ + int n; + unsigned i, len; + const char *outputstr, *st; + pdf_lit_mode literal_mode; + n = lua_gettop(L); + if (!lua_isstring(L, -1)) { + lua_pushstring(L, "no string to print"); + lua_error(L); + } + literal_mode = set_origin; + if (n == 2) { + if (!lua_isstring(L, -2)) { + lua_pushstring(L, "invalid argument for print literal mode"); + lua_error(L); + } else { + outputstr = (char *) lua_tostring(L, -2); + if (strcmp(outputstr, "direct") == 0) + literal_mode = direct_always; + else if (strcmp(outputstr, "page") == 0) + literal_mode = direct_page; + else { + lua_pushstring(L, + "invalid argument for print literal mode"); + lua_error(L); + } + } + } else { + if (n != 1) { + lua_pushstring(L, "invalid number of arguments"); + lua_error(L); + } + } + switch (literal_mode) { + case (set_origin): + pdf_end_text(); + pdf_set_origin(cur_h, cur_v); + break; + case (direct_page): + pdf_end_text(); + break; + case (direct_always): + pdf_end_string_nl(); + break; + default: + assert(0); + } + st = lua_tolstring(L, n,&len); + for (i = 0; i < len; i++) { + if (i%16 == 0) + pdfroom(16); + pdf_buf[pdf_ptr++] = st[i]; + } + return 0; +} + +static int +getpdf (lua_State *L) { + char *st; + if (lua_isstring(L,2)) { + st = (char *)lua_tostring(L,2); + if (st && *st) { + if (*st == 'h') + return findcurh(L); + else if (*st == 'v') + return findcurv(L); + } + } + lua_pushnil(L); + return 1; +} + +static int +setpdf (lua_State *L) { + return (L==NULL ? 0 : 0); /* for -Wall */ +} + +static const struct luaL_reg pdflib[] = { + {"print", luapdfprint}, + {NULL, NULL} /* sentinel */ +}; + + +int +luaopen_pdf (lua_State *L) { + luaL_register(L, "pdf", pdflib); + /* build meta table */ + luaL_newmetatable(L,"pdf_meta"); + lua_pushstring(L, "__index"); + lua_pushcfunction(L, getpdf); + /* do these later, NYI */ + if (0) { + lua_settable(L, -3); + lua_pushstring(L, "__newindex"); + lua_pushcfunction(L, setpdf); + } + lua_settable(L, -3); + lua_setmetatable(L,-2); /* meta to itself */ + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/lstatslib.c b/Build/source/texk/web2c/luatexdir/lua/lstatslib.c new file mode 100644 index 00000000000..025e851e775 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/lstatslib.c @@ -0,0 +1,211 @@ +/* $Id: lstatslib.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + +typedef struct statistic { + const char *name; + char type; + void *value; +} statistic ; + +extern char *ptexbanner; +/* extern string getcurrentfilenamestring; */ + +typedef char * (*charfunc)(void); +typedef integer (*intfunc)(void); + +char *getbanner (void) { + return ptexbanner; +} + +/* hack, I really should implement the makecstring */ +char *getfilename (void) { + integer t; + t = get_current_name(); + if (t>(1<<21)) + return makecstring(t); + else + return xstrdup (""); +} + +char *getlasterror (void) { + return makecstring(last_error); +} + + +extern int luabytecode_max; +extern int luabytecode_bytes; +extern int luastate_max; +extern int luastate_bytes; + +static struct statistic stats[] = { + { "pdf_gone", 'g', &pdf_gone }, + { "pdf_ptr", 'g', &pdf_ptr }, + { "dvi_gone", 'g', &dvi_offset }, + { "dvi_ptr", 'g', &dvi_ptr }, + { "total_pages", 'g', &total_pages }, + { "output_file_name", 's', &output_file_name }, + { "log_name", 's', &texmf_log_name }, /* weird */ + { "banner", 'S', &getbanner }, + { "pdftex_banner", 's', &pdftex_banner }, + /* + * mem stat + */ + { "var_used", 'g', &var_used }, + { "dyn_used", 'g', &dyn_used }, + /* + * traditional tex stats + */ + { "str_ptr", 'g', &str_ptr }, + { "init_str_ptr", 'g', &init_str_ptr }, + { "max_strings", 'g', &max_strings }, + { "pool_ptr", 'g', &pool_ptr }, + { "init_pool_ptr", 'g', &init_pool_ptr }, + { "pool_size", 'g', &pool_size }, + { "var_mem_max", 'g', &var_mem_max }, + { "node_mem_usage", 'S', &sprint_node_mem_usage }, + { "fix_mem_max", 'g', &fix_mem_max }, + { "fix_mem_min", 'g', &fix_mem_min }, + { "fix_mem_end", 'g', &fix_mem_end }, + { "cs_count", 'g', &cs_count }, + { "hash_size", 'G', &get_hash_size }, + { "hash_extra", 'g', &hash_extra }, + { "font_ptr", 'G', &max_font_id }, + { "max_in_stack", 'g', &max_in_stack }, + { "max_nest_stack", 'g', &max_nest_stack }, + { "max_param_stack", 'g', &max_param_stack }, + { "max_buf_stack", 'g', &max_buf_stack }, + { "max_save_stack", 'g', &max_save_stack }, + { "stack_size", 'g', &stack_size }, + { "nest_size", 'g', &nest_size }, + { "param_size", 'g', ¶m_size }, + { "buf_size", 'g', &buf_size }, + { "save_size", 'g', &save_size }, + /* pdf stats */ + { "obj_ptr", 'g', &obj_ptr }, + { "obj_tab_size", 'g', &obj_tab_size }, + { "pdf_os_cntr", 'g', &pdf_os_cntr }, + { "pdf_os_objidx", 'g', &pdf_os_objidx }, + { "pdf_dest_names_ptr", 'g', &pdf_dest_names_ptr }, + { "dest_names_size", 'g', &dest_names_size }, + { "pdf_mem_ptr", 'g', &pdf_mem_ptr }, + { "pdf_mem_size", 'g', &pdf_mem_size }, + + { "largest_used_mark", 'g', &biggest_used_mark }, + + { "filename", 'S', &getfilename }, + { "inputid", 'G', &get_current_name }, + { "linenumber", 'g', &line }, + { "lasterrorstring", 'S', &getlasterror }, + + { "luabytecodes", 'g', &luabytecode_max }, + { "luabytecode_bytes", 'g', &luabytecode_bytes }, + { "luastates", 'g', &luastate_max }, + { "luastate_bytes", 'g', &luastate_bytes }, + + { "output_active", 'b', &output_active }, + + { NULL, 0 , 0 } }; + + +static int stats_name_to_id (char *name) { + int i; + for (i=0; stats[i].name!=NULL; i++) { + if (strcmp(stats[i].name, name) == 0) + return i; + } + return 0; +} + +static int do_getstat (lua_State *L,int i) { + int t; + char *st; + charfunc f; + intfunc g; + int str; + t = stats[i].type; + switch(t) { + case 'S': + f = stats[i].value; + st = f(); + lua_pushstring(L,st); + break; + case 's': + str = *(integer *)(stats[i].value); + if (str) { + lua_pushstring(L,makecstring(str)); + } else { + lua_pushnil(L); + } + break; + case 'G': + g = stats[i].value; + lua_pushnumber(L,g()); + break; + case 'g': + lua_pushnumber(L,*(integer *)(stats[i].value)); + break; + case 'B': + g = stats[i].value; + lua_pushboolean(L,g()); + break; + case 'b': + lua_pushboolean(L,*(integer *)(stats[i].value)); + break; + default: + lua_pushnil(L); + } + return 1; +} + +static int getstats (lua_State *L) { + char *st; + int i; + if (lua_isstring(L,-1)) { + st = (char *)lua_tostring(L,-1); + i = stats_name_to_id(st); + if (i>0) { + return do_getstat(L,i); + } + } + return 0; +} + +static int setstats (lua_State *L) { + return 0; +} + +static int statslist (lua_State *L) { + int i; + luaL_checkstack(L,1,"out of stack space"); + lua_newtable(L); + for (i=0; stats[i].name!=NULL; i++) { + luaL_checkstack(L,2,"out of stack space"); + lua_pushstring(L,stats[i].name); + do_getstat(L,i); + lua_rawset(L,-3); + } + return 1; +} + + + +static const struct luaL_reg statslib [] = { + {"list",statslist}, + {NULL, NULL} /* sentinel */ +}; + +int luaopen_stats (lua_State *L) +{ + luaL_register(L, "status", statslib); + luaL_newmetatable(L,"stats_meta"); + lua_pushstring(L, "__index"); + lua_pushcfunction(L, getstats); + lua_settable(L, -3); + lua_pushstring(L, "__newindex"); + lua_pushcfunction(L, setstats); + lua_settable(L, -3); + lua_setmetatable(L,-2); /* meta to itself */ + return 1; +} diff --git a/Build/source/texk/web2c/luatexdir/lua/ltexiolib.c b/Build/source/texk/web2c/luatexdir/lua/ltexiolib.c new file mode 100644 index 00000000000..a61409b2943 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/ltexiolib.c @@ -0,0 +1,117 @@ +/* $Id: ltexiolib.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + +typedef void (*texio_printer) (strnumber s); + +static char *loggable_info = NULL; + +static int +do_texio_print (lua_State *L, texio_printer printfunction) { + strnumber texs,u; + char *s; + char save_selector; + int n,i; + size_t k; + u = 0; + n = lua_gettop(L); + if (n==0 || !lua_isstring(L, -1)) { + lua_pushstring(L, "no string to print"); + lua_error(L); + } + save_selector = selector; + i = 1; + if (n>1) { + s=(char *)lua_tostring(L, 1); + if (strcmp(s,"log") == 0) { i++; selector = log_only; } + else if (strcmp(s,"term") == 0) { i++; selector = term_only; } + else if (strcmp(s,"term and log") == 0) { i++; selector = term_and_log; } + } + if (selector!=log_only && selector!=term_only && selector != term_and_log) { + normalize_selector(); /* sets selector */ + } + /* just in case there is a string in progress */ + if (str_start[str_ptr-0x200000]1) { + s=(char *)lua_tostring(L, 1); + if (strcmp(s,"log") == 0) { i++; l = 1; } + else if (strcmp(s,"term") == 0) { i++; l = 2; } + else if (strcmp(s,"term and log") == 0) { i++; l = 3; } + } + for (;i<=n;i++) { + if(lua_isstring(L, i)) { + s = (char *)lua_tostring(L, i); + if (l==2||l==3) + fprintf(stdout,"%s%s", extra, s); + if (l==1||l==3) { + if (loggable_info==NULL) { + loggable_info = strdup(s); + } else { + char *v = concat3 (loggable_info,extra,s); + free(loggable_info); + loggable_info = v; + } + } + } + } +} + +static int +texio_print (lua_State *L) { + if (ready_already!=314159 || pool_ptr==0 || job_name==0) { + do_texio_ini_print(L,""); + return 0; + } + return do_texio_print(L,zprint); +} + +static int +texio_printnl (lua_State *L) { + if (ready_already!=314159 || pool_ptr==0 || job_name==0) { + do_texio_ini_print(L,"\n"); + return 0; + } + return do_texio_print(L,zprint_nl); +} + +/* at the point this function is called, the selector is log_only */ +void flush_loggable_info (void) { + if (loggable_info!=NULL) { + fprintf(log_file,"%s\n",loggable_info); + free(loggable_info); + loggable_info=NULL; + } +} + + +static const struct luaL_reg texiolib [] = { + {"write", texio_print}, + {"write_nl", texio_printnl}, + {NULL, NULL} /* sentinel */ +}; + +int +luaopen_texio (lua_State *L) { + luaL_register(L,"texio",texiolib); + return 1; +} diff --git a/Build/source/texk/web2c/luatexdir/lua/ltexlib.c b/Build/source/texk/web2c/luatexdir/lua/ltexlib.c new file mode 100644 index 00000000000..f2258010136 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/ltexlib.c @@ -0,0 +1,820 @@ +/* $Id: ltexlib.c 1087 2008-03-07 23:52:35Z hhenkel $ */ + +#include "luatex-api.h" +#include +#include "nodes.h" + +typedef struct { + char *text; + unsigned int tsize; + void *next; + unsigned char partial; + int cattable; +} rope; + +typedef struct { + rope *head; + rope *tail; + char complete; /* currently still writing ? */ +} spindle; + +#define PARTIAL_LINE 1 +#define FULL_LINE 0 + +#define NO_CAT_TABLE -2 +#define DEFAULT_CAT_TABLE -1 + +#define write_spindle spindles[spindle_index] +#define read_spindle spindles[(spindle_index-1)] + +static int spindle_size = 0; +static spindle *spindles = NULL; +static int spindle_index = 0; + + +static int +do_luacprint (lua_State * L, int partial, int deftable) { + int i, n; + size_t tsize; + char *st, *sttemp; + rope *rn; + int cattable = deftable; + int startstrings = 1; + n = lua_gettop(L); + if (cattable != NO_CAT_TABLE) { + if (lua_type(L,1)==LUA_TNUMBER && n>1) { + cattable = lua_tonumber(L, 1); + startstrings = 2; + } + } + for (i = startstrings; i <= n; i++) { + if (!lua_isstring(L, i)) { + lua_pushstring(L, "no string to print"); + lua_error(L); + } + sttemp = (char *)lua_tolstring(L, i,&tsize); + st = xmalloc((tsize+1)); + memcpy(st,sttemp,(tsize+1)); + if (st) { + /* fprintf(stderr,"W[%d]:=%s\n",spindle_index,st);*/ + luacstrings++; + rn = (rope *)xmalloc(sizeof(rope)); /* valgrind says we leak here */ + rn->text = st; + rn->tsize = tsize; + rn->partial = partial; + rn->cattable = cattable; + rn->next = NULL; + if (write_spindle.head == NULL) { + assert(write_spindle.tail == NULL); + write_spindle.head = rn; + } else { + write_spindle.tail->next = rn; + } + write_spindle.tail = rn; + write_spindle.complete = 0; + } + } + return 0; +} + +int luacwrite(lua_State * L) { + return do_luacprint(L,FULL_LINE,NO_CAT_TABLE); +} + +int luacprint(lua_State * L) { + return do_luacprint(L,FULL_LINE,DEFAULT_CAT_TABLE); +} + +int luacsprint(lua_State * L) { + return do_luacprint(L,PARTIAL_LINE,DEFAULT_CAT_TABLE); +} + +int +luacstring_detokenized (void) { + return (read_spindle.tail->cattable == NO_CAT_TABLE); +} + +int +luacstring_defaultcattable (void) { + return (read_spindle.tail->cattable == DEFAULT_CAT_TABLE); +} + +integer +luacstring_cattable (void) { + return (integer)read_spindle.tail->cattable; +} + +int +luacstring_simple (void) { + return (read_spindle.tail->partial == PARTIAL_LINE); +} + +int +luacstring_penultimate (void) { + return (read_spindle.tail->next == NULL); +} + +int +luacstring_input (void) { + char *st; + int ret; + rope *t = read_spindle.head; + if (!read_spindle.complete) { + read_spindle.complete =1; + read_spindle.tail = NULL; + } + if (t == NULL) { + if(read_spindle.tail != NULL) + free(read_spindle.tail); + read_spindle.tail = NULL; + return 0; + } + if (t->text != NULL) { + st = t->text; + /* put that thing in the buffer */ + last = first; + ret = last; + check_buffer_overflow (last + t->tsize); + while (t->tsize-->0) + buffer[last++] = *st++; + if (!t->partial) { + while (last-1>ret && buffer[last-1] == ' ') + last--; + } + free (t->text); + t->text = NULL; + } + if (read_spindle.tail != NULL) { /* not a one-liner */ + free(read_spindle.tail); + } + read_spindle.tail = t; + read_spindle.head = t->next; + return 1; +} + +/* open for reading, and make a new one for writing */ +void +luacstring_start (int n) { + spindle_index++; + if(spindle_size == spindle_index) { /* add a new one */ + spindles = xrealloc(spindles,sizeof(spindle)*(spindle_size+1)); + spindles[spindle_index].head = NULL; + spindles[spindle_index].tail = NULL; + spindles[spindle_index].complete = 0; + spindle_size++; + } +} + +/* close for reading */ + +void +luacstring_close (int n) { + rope *next, *t; + next = read_spindle.head; + while (next != NULL) { + if (next->text != NULL) + free(next->text); + t = next; + next = next->next; + free(t); + } + read_spindle.head = NULL; + if(read_spindle.tail != NULL) + free(read_spindle.tail); + read_spindle.tail = NULL; + read_spindle.complete = 0; + spindle_index--; +} + +/* local (static) versions */ + +#define width_offset 1 +#define depth_offset 2 +#define height_offset 3 + +#define check_index_range(j) \ + if (j<0 || j > 65535) { \ + lua_pushstring(L, "incorrect index value"); \ + lua_error(L); } + + +int dimen_to_number (lua_State *L,char *s){ + double v; + char *d; + int j; + v = strtod(s,&d); + if (strcmp (d,"in") == 0) { j = (int)(((v*7227)/100) *65536); } + else if (strcmp (d,"pc") == 0) { j = (int)((v*12) *65536); } + else if (strcmp (d,"cm") == 0) { j = (int)(((v*7227)/254) *65536); } + else if (strcmp (d,"mm") == 0) { j = (int)(((v*7227)/2540) *65536); } + else if (strcmp (d,"bp") == 0) { j = (int)(((v*7227)/7200) *65536); } + else if (strcmp (d,"dd") == 0) { j = (int)(((v*1238)/1157) *65536); } + else if (strcmp (d,"cc") == 0) { j = (int)(((v*14856)/1157) *65536); } + else if (strcmp (d,"nd") == 0) { j = (int)(((v*21681)/20320)*65536); } + else if (strcmp (d,"nc") == 0) { j = (int)(((v*65043)/5080) *65536); } + else if (strcmp (d,"pt") == 0) { j = (int)(v *65536); } + else if (strcmp (d,"sp") == 0) { j = (int)(v); } + else { + lua_pushstring(L, "unknown dimension specifier"); + lua_error(L); + j = 0; + } + return j; +} + +int setdimen (lua_State *L) { + int i,j; + size_t k; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + j = 0; + /* find the value*/ + if (!lua_isnumber(L,i)) + if (lua_isstring(L,i)) { + j = dimen_to_number(L,(char *)lua_tostring(L,i)); + } else { + lua_pushstring(L, "unsupported value type"); + lua_error(L); + } + else + j = (int)lua_tonumber(L,i); + /* find the index*/ + if (lua_type(L,i-1)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i-1, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + k = zget_equiv(cur_cs)-get_scaled_base(); + } else { + k = (int)luaL_checkinteger(L,i-1); + } + check_index_range(k); + if(set_tex_dimen_register(k,j)) { + lua_pushstring(L, "incorrect value"); + lua_error(L); + } + return 0; +} + +int getdimen (lua_State *L) { + int i,j; + size_t k; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + if (lua_type(L,i)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + if (is_undefined_cs(cur_cs)) { + lua_pushnil(L); + return 1; + } + k = zget_equiv(cur_cs)-get_scaled_base(); + } else { + k = (int)luaL_checkinteger(L,i); + } + check_index_range(k); + j = get_tex_dimen_register(k); + lua_pushnumber(L, j); + return 1; +} + +int setcount (lua_State *L) { + int i,j; + size_t k; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + j = (int)luaL_checkinteger(L,i); + if (lua_type(L,i-1)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i-1,&k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + k = zget_equiv(cur_cs)-get_count_base(); + } else { + k = (int)luaL_checkinteger(L,i-1); + } + check_index_range(k); + if (set_tex_count_register(k,j)) { + lua_pushstring(L, "incorrect value"); + lua_error(L); + } + return 0; +} + +int getcount (lua_State *L) { + int i, j; + size_t k; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + if (lua_type(L,i)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + if (is_undefined_cs(cur_cs)) { + lua_pushnil(L); + return 1; + } + k = zget_equiv(cur_cs)-get_count_base(); + } else { + k = (int)luaL_checkinteger(L,i); + } + check_index_range(k); + j = get_tex_count_register(k); + lua_pushnumber(L, j); + return 1; +} + + +int setattribute (lua_State *L) { + int i,j; + size_t k; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + j = (int)luaL_checkinteger(L,i); + if (lua_type(L,i-1)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i-1, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + k = zget_equiv(cur_cs)-get_attribute_base(); + } else { + k = (int)luaL_checkinteger(L,i-1); + } + check_index_range(k); + if (set_tex_attribute_register(k,j)) { + lua_pushstring(L, "incorrect value"); + lua_error(L); + } + return 0; +} + +int getattribute (lua_State *L) { + int i, j; + size_t k; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + if (lua_type(L,i)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + if (is_undefined_cs(cur_cs)) { + lua_pushnil(L); + return 1; + } + k = zget_equiv(cur_cs)-get_attribute_base(); + } else { + k = (int)luaL_checkinteger(L,i); + } + check_index_range(k); + j = get_tex_attribute_register(k); + lua_pushnumber(L, j); + return 1; +} + +int settoks (lua_State *L) { + int i,j; + size_t k,len; + int cur_cs; + int texstr; + char *s, *st; + i = lua_gettop(L); + if (!lua_isstring(L,i)) { + lua_pushstring(L, "unsupported value type"); + lua_error(L); + } + st = (char *)lua_tolstring(L,i,&len); + + if (lua_type(L,i-1)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i-1, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + k = zget_equiv(cur_cs)-get_toks_base(); + } else { + k = (int)luaL_checkinteger(L,i-1); + } + check_index_range(k); + j = maketexlstring(st,len); + + if(zset_tex_toks_register(k,j)) { + flush_str(j); + lua_pushstring(L, "incorrect value"); + lua_error(L); + } + return 0; +} + +int gettoks (lua_State *L) { + int i; + size_t k; + strnumber t; + int cur_cs; + int texstr; + char *s; + i = lua_gettop(L); + if (lua_type(L,i)==LUA_TSTRING) { + s = (char *)lua_tolstring(L,i, &k); + texstr = maketexlstring(s,k); + cur_cs = string_lookup(texstr); + flush_str(texstr); + if (is_undefined_cs(cur_cs)) { + lua_pushnil(L); + return 1; + } + k = zget_equiv(cur_cs)-get_toks_base(); + } else { + k = (int)luaL_checkinteger(L,i); + } + + check_index_range(k); + t = get_tex_toks_register(k); + lua_pushstring(L, makecstring(t)); + flush_str(t); + return 1; +} + +int getbox (lua_State *L) { + int k, t; + k = (int)luaL_checkinteger(L,-1); + check_index_range(k); + t = get_tex_box_register(k); + nodelist_to_lua(L,t); + return 1; +} + +int setbox (lua_State *L) { + int i,j,k; + + + + k = (int)luaL_checkinteger(L,-2); + check_index_range(k); + i = get_tex_box_register(k); + if (lua_isboolean(L,-1)) { + j = lua_toboolean(L,-1); + if (j==0) + j = null; + else + return 0; + } else { + j = nodelist_from_lua(L); + } + if(set_tex_box_register(k,j)) { + lua_pushstring(L, "incorrect value"); + lua_error(L); + } + return 0; +} + + +static int getboxdim (lua_State *L, int whichdim) { + int i, j; + i = lua_gettop(L); + j = (int)lua_tonumber(L,(i)); + lua_settop(L,(i-2)); /* table at -1 */ + if (j<0 || j > 65535) { + lua_pushstring(L, "incorrect index"); + lua_error(L); + } + switch (whichdim) { + case width_offset: + lua_pushnumber(L, get_tex_box_width(j)); + break; + case height_offset: + lua_pushnumber(L, get_tex_box_height(j)); + break; + case depth_offset: + lua_pushnumber(L, get_tex_box_depth(j)); + } + return 1; +} + +int getboxwd (lua_State *L) { + return getboxdim (L, width_offset); +} + +int getboxht (lua_State *L) { + return getboxdim (L, height_offset); +} + +int getboxdp (lua_State *L) { + return getboxdim (L, depth_offset); +} + +static int setboxdim (lua_State *L, int whichdim) { + int i,j,k,err; + i = lua_gettop(L); + if (!lua_isnumber(L,i)) { + j = dimen_to_number(L,(char *)lua_tostring(L,i)); + } else { + j = (int)lua_tonumber(L,i); + } + k = (int)lua_tonumber(L,(i-1)); + lua_settop(L,(i-3)); /* table at -2 */ + if (k<0 || k > 65535) { + lua_pushstring(L, "incorrect index"); + lua_error(L); + } + err = 0; + switch (whichdim) { + case width_offset: + err = set_tex_box_width(k,j); + break; + case height_offset: + err = set_tex_box_height(k,j); + break; + case depth_offset: + err = set_tex_box_depth(k,j); + } + if (err) { + lua_pushstring(L, "not a box"); + lua_error(L); + } + return 0; +} + +int setboxwd (lua_State *L) { + return setboxdim(L,width_offset); +} + +int setboxht (lua_State *L) { + return setboxdim(L,height_offset); +} + +int setboxdp (lua_State *L) { + return setboxdim(L,depth_offset); +} + +int settex (lua_State *L) { + char *st; + int i,j,texstr; + size_t k; + int cur_cs, cur_cmd; + j = 0; + i = lua_gettop(L); + if (lua_isstring(L,(i-1))) { + st = (char *)lua_tolstring(L,(i-1), &k); + texstr = maketexlstring(st,k); + if (zis_primitive(texstr)) { + cur_cs = string_lookup(texstr); + flush_str(texstr); + cur_cmd = zget_eq_type(cur_cs); + if (is_int_assign(cur_cmd)) { + if (lua_isnumber(L,i)) { + assign_internal_int(zget_equiv(cur_cs),lua_tonumber(L,i)); + } else { + lua_pushstring(L, "unsupported value type"); + lua_error(L); + } + } else if (is_dim_assign(cur_cmd)) { + if (!lua_isnumber(L,i)) + if (lua_isstring(L,i)) { + j = dimen_to_number(L,(char *)lua_tostring(L,i)); + } else { + lua_pushstring(L, "unsupported value type"); + lua_error(L); + } + else + j = (int)lua_tonumber(L,i); + assign_internal_dim(zget_equiv(cur_cs),j); + } else { + lua_pushstring(L, "unsupported tex internal assignment"); + lua_error(L); + } + } else { + lua_rawset(L,(i-2)); + } + } else { + lua_rawset(L,(i-2)); + } + return 0; +} + +char * +get_something_internal (int cur_cmd, int cur_code) { + int texstr; + char *str; + int save_cur_val,save_cur_val_level; + save_cur_val = cur_val; + save_cur_val_level = cur_val_level; + zscan_something_simple(cur_cmd,cur_code); + texstr = the_scanned_result(); + cur_val = save_cur_val; + cur_val_level = save_cur_val_level; + str = makecstring(texstr); + flush_str(texstr); + return str; +} + +char * +get_convert (int cur_code) { + int texstr; + char *str = NULL; + texstr = the_convert_string(cur_code); + if (texstr) { + str = makecstring(texstr); + flush_str(texstr); + } + return str; +} + + +int +gettex (lua_State *L) { + char *st; + int i,texstr; + size_t k; + char *str; + int cur_cs, cur_cmd, cur_code; + i = lua_gettop(L); + if (lua_isstring(L,i)) { + st = (char *)lua_tolstring(L,i, &k); + texstr = maketexlstring(st,k); + cur_cs = zprim_lookup(texstr); + flush_str(texstr); + if (cur_cs) { + cur_cmd = zget_prim_eq_type(cur_cs); + cur_code = zget_prim_equiv(cur_cs); + if (is_convert(cur_cmd)) + str = get_convert(cur_code); + else + str = get_something_internal(cur_cmd,cur_code); + if (str) + lua_pushstring(L,str); + else + lua_pushnil(L); + return 1; + } else { + lua_rawget(L,(i-1)); + return 1; + } + } else { + lua_rawget(L,(i-1)); + return 1; + } + return 0; /* not reached */ +} + + +int +getlist (lua_State *L) { + char *str; + if (lua_isstring(L,2)) { + str = (char *)lua_tostring(L,2); + if (strcmp(str,"page_ins_head")==0) { + lua_pushnumber(L,page_ins_head); lua_nodelib_push(L); + } else if (strcmp(str,"contrib_head")==0) { + lua_pushnumber(L,contrib_head); lua_nodelib_push(L); + } else if (strcmp(str,"page_head")==0) { + lua_pushnumber(L,page_head); lua_nodelib_push(L); + } else if (strcmp(str,"temp_head")==0) { + lua_pushnumber(L,temp_head); lua_nodelib_push(L); + } else if (strcmp(str,"hold_head")==0) { + lua_pushnumber(L,hold_head); lua_nodelib_push(L); + } else if (strcmp(str,"adjust_head")==0) { + lua_pushnumber(L,adjust_head); lua_nodelib_push(L); + } else if (strcmp(str,"pre_adjust_head")==0) { + lua_pushnumber(L,pre_adjust_head); lua_nodelib_push(L); + } else if (strcmp(str,"align_head")==0) { + lua_pushnumber(L,align_head); lua_nodelib_push(L); + } else { + lua_pushnil(L); + } + } else { + lua_pushnil(L); + } + return 1; +} + +int +setlist (lua_State *L) { + return 0; +} + +#define infinity 2147483647 + +static int +do_integer_error(double m) { + char *help[] = {"I can only go up to 2147483647='17777777777=""7FFFFFFF,", + "so I'm using that number instead of yours.", + NULL } ; + tex_error("Number too big",help); + return (m>0.0 ? infinity : -infinity); +} + + +static int +tex_roundnumber (lua_State *L) { + double m = lua_tonumber(L, 1)+0.5; + if (abs(m)>(double)infinity) + lua_pushnumber(L,do_integer_error(m)); + else + lua_pushnumber(L,floor(m)); + return 1; +} + +static int +tex_scaletable (lua_State *L) { + double delta = luaL_checknumber(L, 2); + if (lua_istable(L,1)) { + lua_newtable(L); /* the new table is at index 3 */ + lua_pushnil(L); + while (lua_next(L,1)!= 0 ) { /* numeric value */ + lua_pushvalue(L,-2); + lua_insert(L,-2); + if (lua_isnumber(L,-1)) { + double m = lua_tonumber(L,-1)*delta + 0.5; + lua_pop(L,1); + if (abs(m)>(double)infinity) + lua_pushnumber(L,do_integer_error(m)); + else + lua_pushnumber(L,floor(m)); + } + lua_rawset(L,3); + } + } else if (lua_isnumber(L,1)) { + double m = lua_tonumber(L,1)*delta + 0.5; + if (abs(m)>(double)infinity) + lua_pushnumber(L,do_integer_error(m)); + else + lua_pushnumber(L,floor(m)); + } else { + lua_pushnil(L); + } + return 1; +} + +static const struct luaL_reg texlib [] = { + {"write", luacwrite}, + {"print", luacprint}, + {"sprint", luacsprint}, + {"setdimen", setdimen}, + {"getdimen", getdimen}, + {"setattribute", setattribute}, + {"getattribute", getattribute}, + {"setcount", setcount}, + {"getcount", getcount}, + {"settoks", settoks}, + {"gettoks", gettoks}, + {"setbox", setbox}, + {"getbox", getbox}, + {"setlist", setlist}, + {"getlist", getlist}, + {"setboxwd", setboxwd}, + {"getboxwd", getboxwd}, + {"setboxht", setboxht}, + {"getboxht", getboxht}, + {"setboxdp", setboxdp}, + {"getboxdp", getboxdp}, + {"round", tex_roundnumber}, + {"scale", tex_scaletable}, + {NULL, NULL} /* sentinel */ +}; + +int luaopen_tex (lua_State *L) +{ + luaL_register(L, "tex", texlib); + make_table(L,"attribute","getattribute","setattribute"); + make_table(L,"dimen","getdimen","setdimen"); + make_table(L,"count","getcount","setcount"); + make_table(L,"toks","gettoks","settoks"); + make_table(L,"box","getbox","setbox"); + make_table(L,"lists","getlist","setlist"); + make_table(L,"wd","getboxwd","setboxwd"); + make_table(L,"ht","getboxht","setboxht"); + make_table(L,"dp","getboxdp","setboxdp"); + /* make the meta entries */ + /* fetch it back */ + luaL_newmetatable(L,"tex_meta"); + lua_pushstring(L, "__index"); + lua_pushcfunction(L, gettex); + lua_settable(L, -3); + lua_pushstring(L, "__newindex"); + lua_pushcfunction(L, settex); + lua_settable(L, -3); + lua_setmetatable(L,-2); /* meta to itself */ + /* initialize the I/O stack: */ + spindles = xmalloc(sizeof(spindle)); + spindle_index = 0; + spindles[0].head = NULL; + spindles[0].tail = NULL; + spindle_size = 1; + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/ltokenlib.c b/Build/source/texk/web2c/luatexdir/lua/ltokenlib.c new file mode 100644 index 00000000000..582779623cf --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/ltokenlib.c @@ -0,0 +1,263 @@ +/* $Id: ltokenlib.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + + +extern int get_command_id (char *); + +static int max_command = 0; +static int hash_base = 0; +static int active_base = 0; +static int null_cs = 0; + +#define protected_token 0x1C00001 + +#define is_valid_token(L,i) (lua_istable(L,i) && lua_objlen(L,i)==3) +#define get_token_cmd(L,i) lua_rawgeti(L,i,1) +#define get_token_chr(L,i) lua_rawgeti(L,i,2) +#define get_token_cs(L,i) lua_rawgeti(L,i,3) + +static int +test_expandable (lua_State *L) { + integer cmd = -1; + if (is_valid_token(L,-1)) { + get_token_cmd(L,-1); + if (lua_isnumber(L,-1)) { + cmd = lua_tointeger(L,-1); + } else if (lua_isstring(L,-1)) { + cmd = get_command_id((char *)lua_tostring(L,-1)); + } + if (cmd>max_command) { + lua_pushboolean(L,1); + } else { + lua_pushboolean(L,0); + } + } else { + lua_pushnil(L); + } + return 1; +} + + +static int +test_protected (lua_State *L) { + integer chr = -1; + if (is_valid_token(L,-1)) { + get_token_chr(L,-1); + if (lua_isnumber(L,-1)) { + chr = lua_tointeger(L,-1); + } else if (lua_isstring(L,-1)) { + chr = get_command_id((char *)lua_tostring(L,-1)); + } + if (fixmem[fixmem[chr].hhrh].hhlh==protected_token) { + lua_pushboolean(L,1); + } else { + lua_pushboolean(L,0); + } + } else { + lua_pushnil(L); + } + return 1; +} + +static int +test_activechar (lua_State *L) { + integer cmd = -1; + if (is_valid_token(L,-1)) { + get_token_chr(L,-1); + if (lua_isnumber(L,-1)) { + cmd = lua_tointeger(L,-1); + } + if (cmd>0 && cmd==protected_token) { + lua_pushboolean(L,1); + } else { + lua_pushboolean(L,0); + } + } else { + lua_pushnil(L); + } + return 1; +} + + +static int +run_get_command_name (lua_State *L) { + int cs; + if (is_valid_token(L,-1)) { + get_token_cmd(L,-1); + if (lua_isnumber(L,-1)) { + cs = lua_tointeger(L,-1); + lua_pushstring(L,command_names[cs].cmd_name); + } else { + lua_pushstring(L,""); + } + } else { + lua_pushnil(L); + } + return 1; +} + +static int +run_get_csname_name (lua_State *L) { + int cs,cmd,n; + char *s; + + if (is_valid_token(L,-1)) { + get_token_cmd(L,-1); + if (lua_isnumber(L,-1)) { + cmd = lua_tointeger(L,-1); + } + lua_pop(L,1); + cs = 0; + get_token_cs(L,-1); + if (lua_isnumber(L,-1)) { + cs = lua_tointeger(L,-1); + } + lua_pop(L,1); + + if (cs != 0 && (n = zget_cs_text(cs)) && n>=0) { + s = makecstring(n); + lua_pushstring(L,s); + } else { + lua_pushstring(L,""); + } + } else { + lua_pushnil(L); + } + return 1; +} + +static int +run_get_command_id (lua_State *L) { + int cs = -1; + if (lua_isstring(L,-1)) { + cs = get_command_id((char *)lua_tostring(L,-1)); + } + lua_pushnumber(L,cs); + return 1; +} + + +static int +run_get_csname_id (lua_State *L) { + int texstr; + char *s; + size_t k,cs = 0; + if (lua_isstring(L,-1)) { + s = (char *)lua_tolstring(L,-1, &k); + texstr = maketexlstring(s,k); + cs = string_lookup(texstr); + flush_str(texstr); + } + lua_pushnumber(L,cs); + return 1; +} + + +void +make_token_table (lua_State *L, int cmd, int chr, int cs) { + lua_createtable(L,3,0); + lua_pushnumber(L,cmd); + lua_rawseti(L,-2,1); + lua_pushnumber(L,chr); + lua_rawseti(L,-2,2); + lua_pushnumber(L,cs); + lua_rawseti(L,-2,3); +} + +static int +run_get_next (lua_State *L) { + int save_nncs; + save_nncs = no_new_control_sequence; + no_new_control_sequence = 0; + get_next(); + no_new_control_sequence = save_nncs; + make_token_table(L,cur_cmd,cur_chr,cur_cs); + return 1; +} + +static int +run_expand (lua_State *L) { + expand(); + return 0; +} + + +static int +run_lookup (lua_State *L) { + char *s; + size_t l; + str_number t; + integer cs,cmd,chr; + int save_nncs; + if (lua_isstring(L,-1)) { + s = (char *)lua_tolstring(L,-1,&l); + if (l>0) { + save_nncs = no_new_control_sequence; + no_new_control_sequence = true; + cs = id_lookup((last+1),l); /* cleans up the lookup buffer */ + t = maketexlstring(s,l); + cs = string_lookup(t); + flush_str(t); + cmd = zget_eq_type(cs); + chr = zget_equiv(cs); + make_token_table(L,cmd,chr,cs); + no_new_control_sequence = save_nncs; + return 1; + } + } + lua_newtable(L); + return 1; +} + +static int +run_build (lua_State *L) { + integer cmd,chr,cs; + if (lua_isnumber(L,1)) { + cs =0; + chr = lua_tointeger(L,1); + cmd = luaL_optinteger(L,2,zget_char_cat_code(chr)); + if (cmd==0 || cmd == 9 || cmd == 14 || cmd == 15) { + fprintf(stdout, "\n\nluatex error: not a good token.\nCatcode %i can not be returned, so I replaced it by 12 (other)",(int)cmd); + error(); + cmd=12; + } + if (cmd == 13) { + cs=chr+active_base; + cmd=zget_eq_type(cs); + chr=zget_equiv(cs); + } + make_token_table(L,cmd,chr,cs); + return 1; + } else { + return run_lookup(L); + } +} + + +static const struct luaL_reg tokenlib [] = { + {"get_next", run_get_next}, + {"expand", run_expand}, + {"lookup", run_lookup}, + {"create", run_build}, + {"is_expandable",test_expandable}, + {"is_activechar",test_activechar}, + {"is_protected", test_protected}, + {"csname_id", run_get_csname_id}, + {"csname_name", run_get_csname_name}, + {"command_name", run_get_command_name}, + {"command_id", run_get_command_id}, + {NULL, NULL} /* sentinel */ +}; + +int luaopen_token (lua_State *L) +{ + luaL_register(L, "token", tokenlib); + max_command = get_max_command(); + hash_base = get_hash_base(); + active_base = get_active_base(); + null_cs = get_nullcs(); + return 1; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/luainit.c b/Build/source/texk/web2c/luatexdir/lua/luainit.c new file mode 100644 index 00000000000..c76b676c0f4 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luainit.c @@ -0,0 +1,520 @@ +#include + +#include "luatex-api.h" +#include + +#include + +#ifndef program_invocation_name +/* char *program_invocation_name = NULL; */ +#endif + +extern void parse_src_specials_option (char *n) ; + +const_string LUATEX_IHELP[] = { + "Usage: luatex --lua=FILE [OPTION]... [TEXNAME[.tex]] [COMMANDS]", + " or: luatex --lua=FILE [OPTION]... \\FIRST-LINE", + " or: luatex --lua=FILE [OPTION]... &FMT ARGS", + " Run luaTeX on TEXNAME, usually creating TEXNAME.pdf.", + " Any remaining COMMANDS are processed as luatex input, after TEXNAME is read.", + "", + " Alternatively, if the first non-option argument begins with a backslash,", + " interpret all non-option arguments as a line of luatex input.", + "", + " Alternatively, if the first non-option argument begins with a &, the", + " next word is taken as the FMT to read, overriding all else. Any", + " remaining arguments are processed as above.", + "", + " If no arguments or options are specified, prompt for input.", + "", + " --lua=FILE the lua initialization file", + " --safer disable some easily exploitable lua commands", + " --fmt=FORMAT load the format file FORMAT", + " --ini be initex, for dumping formats", + " --help display this help and exit", + " --version output version information and exit", + "", + " Alternate behaviour models can be obtained by special switches", + "", + " --luaonly run a lua file, then exit", + " --luaconly byte-compile a lua file, then exit", + NULL +}; + +static void +prepare_cmdline(lua_State * L, char **argv, int argc, int zero_offset) +{ + int i; + luaL_checkstack(L, argc + 3, "too many arguments to script"); + lua_createtable(L, 0, 0); + for (i = 0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, (i-zero_offset)); + } + lua_setglobal(L, "arg"); + return; +} + +extern string dump_name; +extern const_string c_job_name; +extern boolean srcspecialsoption; +extern char *last_source_name; +extern int last_lineno; + +string input_name = NULL; + +static string user_progname = NULL; + +extern char *ptexbanner; +extern int program_name_set; /* in lkpselib.c */ + +/* for topenin() */ +extern char **argv; +extern int argc; + +char *startup_filename = NULL; +int lua_only = 0; +int lua_offset = 0; + +int safer_option = 0; + +/* Reading the options. */ + +/* Test whether getopt found an option ``A''. + Assumes the option index is in the variable `option_index', and the + option table in a variable `long_options'. */ +#define ARGUMENT_IS(a) STREQ (long_options[option_index].name, a) + +/* SunOS cc can't initialize automatic structs, so make this static. */ +static struct option long_options[] + = { { "fmt", 1, 0, 0}, + { "lua", 1, 0, 0}, + { "luaonly", 0, 0, 0}, + { "safer", 0, &safer_option, 1}, + { "help", 0, 0, 0 }, + { "ini", 0, &ini_version, 1 }, + { "interaction", 1, 0, 0 }, + { "halt-on-error", 0, &haltonerrorp, 1 }, + { "kpathsea-debug", 1, 0, 0 }, + { "progname", 1, 0, 0 }, + { "version", 0, 0, 0 }, + { "recorder", 0, &recorder_enabled, 1 }, + { "etex", 0, 0, 0 }, + { "output-comment", 1, 0, 0 }, + { "output-directory", 1, 0, 0 }, + { "draftmode", 0, 0, 0 }, + { "output-format", 1, 0, 0 }, + { "shell-escape", 0, &shellenabledp, 1 }, + { "no-shell-escape", 0, &shellenabledp, -1 }, + { "debug-format", 0, &debug_format_file, 1 }, + { "src-specials", 2, 0, 0 }, + { "file-line-error-style", 0, &filelineerrorstylep, 1 }, + { "no-file-line-error-style", 0, &filelineerrorstylep, -1 }, + /* Shorter option names for the above. */ + { "file-line-error", 0, &filelineerrorstylep, 1 }, + { "no-file-line-error", 0, &filelineerrorstylep, -1 }, + { "jobname", 1, 0, 0 }, + { "parse-first-line", 0, &parsefirstlinep, 1 }, + { "no-parse-first-line", 0, &parsefirstlinep, -1 }, + { "translate-file", 1, 0, 0 }, + { "default-translate-file", 1, 0, 0 }, + { "8bit", 0, 0, 0 }, + { "mktex", 1, 0, 0 }, + { "no-mktex", 1, 0, 0 }, +{0, 0, 0, 0} +}; + +static void +parse_options(int argc, char **argv) +{ + int g; /* `getopt' return code. */ + int option_index; + char *firstfile = NULL; + opterr = 0; /* dont whine */ + for (;;) { + g = getopt_long_only(argc, argv, "+", long_options, &option_index); + + if (g == -1) /* End of arguments, exit the loop. */ + break; + if (g == '?') /* Unknown option. */ + continue; + + assert(g == 0); /* We have no short option names. */ + + if (ARGUMENT_IS("luaonly")) { + lua_only = 1; + lua_offset = optind; + luainit = 1 ; + } else if (ARGUMENT_IS("lua")) { + startup_filename = optarg; + lua_offset = (optind-1); + luainit = 1 ; + + } else if (ARGUMENT_IS ("kpathsea-debug")) { + kpathsea_debug |= atoi (optarg); + + } else if (ARGUMENT_IS("progname")) { + user_progname = optarg; + + } else if (ARGUMENT_IS ("jobname")) { + c_job_name = optarg; + + } else if (ARGUMENT_IS("fmt")) { + dump_name = optarg; + + } else if (ARGUMENT_IS ("output-directory")) { + output_directory = optarg; + + } else if (ARGUMENT_IS ("output-comment")) { + unsigned len = strlen (optarg); + if (len < 256) { + output_comment = optarg; + } else { + WARNING2 ("Comment truncated to 255 characters from %d. (%s)", + len, optarg); + output_comment = (string)xmalloc (256); + strncpy (output_comment, optarg, 255); + output_comment[255] = 0; + } + + } else if (ARGUMENT_IS ("src-specials")) { + last_source_name = xstrdup(""); + /* Option `--src" without any value means `auto' mode. */ + if (optarg == NULL) { + insertsrcspecialeverypar = true; + insertsrcspecialauto = true; + srcspecialsoption = true; + srcspecialsp = true; + } else { + parse_src_specials_option(optarg); + } + + } else if (ARGUMENT_IS ("output-format")) { + pdf_output_option = 1; + if (strcmp(optarg, "dvi") == 0) { + pdf_output_value = 0; + } else if (strcmp(optarg, "pdf") == 0) { + pdf_output_value = 2; + } else { + WARNING1 ("Ignoring unknown value `%s' for --output-format", optarg); + pdf_output_option = 0; + } + + } else if (ARGUMENT_IS ("draftmode")) { + pdf_draftmode_option = 1; + pdf_draftmode_value = 1; + + } else if (ARGUMENT_IS ("mktex")) { + kpse_maketex_option (optarg, true); + + } else if (ARGUMENT_IS ("no-mktex")) { + kpse_maketex_option (optarg, false); + + } else if (ARGUMENT_IS ("interaction")) { + /* These numbers match @d's in *.ch */ + if (STREQ (optarg, "batchmode")) { + interactionoption = 0; + } else if (STREQ (optarg, "nonstopmode")) { + interactionoption = 1; + } else if (STREQ (optarg, "scrollmode")) { + interactionoption = 2; + } else if (STREQ (optarg, "errorstopmode")) { + interactionoption = 3; + } else { + WARNING1 ("Ignoring unknown argument `%s' to --interaction", optarg); + } + + } else if (ARGUMENT_IS("help")) { + usagehelp(LUATEX_IHELP, BUG_ADDRESS); + + } else if (ARGUMENT_IS("version")) { + char *versions; + initversionstring(&versions); + print_version_banner(); + + puts( +"\n\nLuaTeX merges and builds upon (parts of) the code from these projects:\n\n" +"tex by Donald Knuth\n" +"etex by Peter Breitenlohner, Phil Taylor and friends\n" +"omega by John Plaice and Yannis Haralambous\n" +"aleph by Giuseppe Bilotta\n" +"pdftex by Han The Thanh and friends\n" +"kpathsea by Karl Berry, Olaf Weber and others\n" +"lua by Roberto Ierusalimschy, Waldemar Celes,\n" +" Luiz Henrique de Figueiredo\n" +"metapost by John Hobby, Taco Hoekwater and friends.\n" +"xpdf by Derek Noonberg (partial)\n" +"fontforge by George Williams (partial)\n\n" +"Some extensions to lua and additional lua libraries are used, as well as\n" +"libraries for graphic inclusion. More details can be found in the source.\n" +"Code development was sponsored by a grant from Colorado State University\n" +"via the 'oriental tex' project, the TeX User Groups, and donations.\n\n" +"The LuaTeX team is Hans Hagen, Hartmut Henkel, Taco Hoekwater.\n\n" +"There is NO warranty. Redistribution of this software is covered by\n" +"the terms of the GNU General Public License, version 2. For more\n" +"information about these matters, see the file named COPYING and\n" +"the LuaTeX source.\n\n" +"Copyright 2008 Taco Hoekwater, the LuaTeX Team.\n"); + + puts(versions); + uexit(0); + } + } + /* attempt to find dump_name */ + if (argv[optind] && argv[optind][0] == '&') { + dump_name = strdup(argv[optind] + 1); + } else if (argv[optind] && argv[optind][0] != '\\') { + if (argv[optind][0] == '*') { + input_name = strdup(argv[optind] + 1); + } else { + firstfile = strdup(argv[optind]); + if (lua_only) { + startup_filename = firstfile; + } else { + if ((strstr(firstfile,".lua") == firstfile+strlen(firstfile)-4) || + (strstr(firstfile,".luc") == firstfile+strlen(firstfile)-4) || + (strstr(firstfile,".LUA") == firstfile+strlen(firstfile)-4) || + (strstr(firstfile,".LUC") == firstfile+strlen(firstfile)-4) || + (strstr(argv[0],"luatexlua") != NULL) || + (strstr(argv[0],"texlua") != NULL)) { + startup_filename = firstfile; + lua_only = 1; + lua_offset = optind; + luainit = 1 ; + } else { + input_name = firstfile; + } + } + } + } else { + if ((strstr(argv[0],"luatexlua") != NULL)|| + (strstr(argv[0],"texlua") != NULL)) { + lua_only = 1; + luainit = 1 ; + } + } +} + +/* test for readability */ +#define is_readable(a) (stat(a,&finfo)==0) && S_ISREG(finfo.st_mode) && \ + (f=fopen(a,"r")) != NULL && !fclose(f) + +char * +find_filename(char *name, char *envkey) +{ + struct stat finfo; + char *dirname = NULL; + char *filename = NULL; + FILE *f; + if (is_readable(name)) { + return name; + } else { + dirname = getenv(envkey); + if ((dirname != NULL) && strlen(dirname)) { + dirname = strdup(getenv(envkey)); + if (*(dirname + strlen(dirname) - 1) == '/') { + *(dirname + strlen(dirname) - 1) = 0; + } + filename = xmalloc(strlen(dirname) + strlen(name) + 2); + filename = concat3(dirname, "/", name); + if (is_readable(filename)) { + xfree(dirname); + return filename; + } + xfree(filename); + } + } + return NULL; +} + + +void +init_kpse (void) { + + if (!user_progname) { + user_progname = dump_name; + } else if (!dump_name) { + dump_name = user_progname; + } + if (!user_progname) { + if (ini_version) { + user_progname = input_name; + } else { + if(!startup_filename) { + if (!dump_name) { + dump_name = strdup(argv[0]); + user_progname = dump_name; + } + } + } + } + if (!user_progname) { + fprintf(stdout, + "kpathsea mode needs a --progname or --fmt switch\n"); + exit(1); + } + kpse_set_program_name(argv[0], user_progname); + program_name_set=1; +} + +void +fix_dumpname (void) { + int dist; + if (dump_name) { + /* adjust array for Pascal and provide extension, if needed */ + dist = strlen(dump_name) - strlen(DUMP_EXT); + if (strstr(dump_name, DUMP_EXT) == dump_name + dist) + DUMP_VAR = concat(" ", dump_name); + else + DUMP_VAR = concat3(" ", dump_name, DUMP_EXT); + DUMP_LENGTH_VAR = strlen(DUMP_VAR + 1); + } else { + /* For dump_name to be NULL is a bug. */ + if (!ini_version) + abort(); + } +} + +void +lua_initialize(int ac, char **av) +{ + + char *given_file = NULL; + int kpse_init; + int tex_table_id; + int pdf_table_id; + int token_table_id; + int node_table_id; + /* Save to pass along to topenin. */ + argc = ac; + argv = av; + + ptexbanner = BANNER; + program_invocation_name = argv[0]; + + /* be 'luac' */ + if (argc>1 && + (STREQ(argv[0],"texluac") || + STREQ(argv[1],"--luaconly") || + STREQ(argv[1],"--luac"))) { + exit(luac_main(ac,av)); + } + + /* Must be initialized before options are parsed. */ + interactionoption = 4; + dump_name = NULL; + /* parse commandline */ + parse_options(ac, av); + + /* make sure that the locale is 'sane' (for lua) */ + putenv("LC_CTYPE=C"); + putenv("LC_COLLATE=C"); + putenv("LC_NUMERIC=C"); + + /* this is sometimes needed */ + putenv("engine=luatex"); + + luainterpreter(0); + + prepare_cmdline(Luas[0], argv, argc, lua_offset); /* collect arguments */ + + if (startup_filename != NULL) { + given_file = xstrdup(startup_filename); + startup_filename = find_filename(startup_filename, "LUATEXDIR"); + } + /* now run the file */ + if (startup_filename != NULL) { + /* hide the 'tex' and 'pdf' table */ + tex_table_id = hide_lua_table(Luas[0], "tex"); + token_table_id = hide_lua_table(Luas[0], "token"); + node_table_id = hide_lua_table(Luas[0], "node"); + pdf_table_id = hide_lua_table(Luas[0], "pdf"); + + if (luaL_loadfile(Luas[0], startup_filename)) { + fprintf(stdout, "%s\n",lua_tostring(Luas[0], -1)); + exit(1); + } + if (lua_pcall(Luas[0], 0, 0, 0)) { + fprintf(stdout, "%s\n",lua_tostring(Luas[0], -1)); + exit(1); + } + /* no filename? quit now! */ + if (!input_name) { + get_lua_string("texconfig", "jobname", &input_name); + } + if (!dump_name) { + get_lua_string("texconfig", "formatname", &dump_name); + } + if ((lua_only) || ((!input_name) && (!dump_name))) { + exit(0); + } + /* unhide the 'tex' and 'pdf' table */ + unhide_lua_table(Luas[0], "tex", tex_table_id); + unhide_lua_table(Luas[0], "pdf", pdf_table_id); + unhide_lua_table(Luas[0], "token", token_table_id); + unhide_lua_table(Luas[0], "node", node_table_id); + + /* kpse_init */ + kpse_init = -1; + get_lua_boolean("texconfig", "kpse_init", &kpse_init); + + if (kpse_init != 0) { + init_kpse(); + } + /* prohibit_file_trace (boolean) */ + tracefilenames = 1; + get_lua_boolean("texconfig", "trace_file_names", &tracefilenames); + + /* src_special_xx */ + insertsrcspecialauto = insertsrcspecialeverypar = + insertsrcspecialeveryparend = insertsrcspecialeverycr = + insertsrcspecialeverymath = insertsrcspecialeveryhbox = + insertsrcspecialeveryvbox = insertsrcspecialeverydisplay = + false; + get_lua_boolean("texconfig", "src_special_auto", + &insertsrcspecialauto); + get_lua_boolean("texconfig", "src_special_everypar", + &insertsrcspecialeverypar); + get_lua_boolean("texconfig", "src_special_everyparend", + &insertsrcspecialeveryparend); + get_lua_boolean("texconfig", "src_special_everycr", + &insertsrcspecialeverycr); + get_lua_boolean("texconfig", "src_special_everymath", + &insertsrcspecialeverymath); + get_lua_boolean("texconfig", "src_special_everyhbox", + &insertsrcspecialeveryhbox); + get_lua_boolean("texconfig", "src_special_everyvbox", + &insertsrcspecialeveryvbox); + get_lua_boolean("texconfig", "src_special_everydisplay", + &insertsrcspecialeverydisplay); + + srcspecialsp = insertsrcspecialauto | insertsrcspecialeverypar | + insertsrcspecialeveryparend | insertsrcspecialeverycr | + insertsrcspecialeverymath | insertsrcspecialeveryhbox | + insertsrcspecialeveryvbox | insertsrcspecialeverydisplay; + + /* file_line_error */ + filelineerrorstylep = false; + get_lua_boolean("texconfig", "file_line_error", + &filelineerrorstylep); + + /* halt_on_error */ + haltonerrorp = false; + get_lua_boolean("texconfig", "halt_on_error", &haltonerrorp); + + fix_dumpname(); + } else { + if (luainit) { + if (given_file) { + fprintf(stdout, "%s file %s not found\n", (lua_only ? "Script" : "Configuration"), given_file); + } else { + fprintf(stdout, "No %s file given\n", (lua_only ? "script" : "configuration")); + } + exit(1); + } else { + /* init */ + init_kpse(); + fix_dumpname(); + } + } +} diff --git a/Build/source/texk/web2c/luatexdir/lua/luanode.c b/Build/source/texk/web2c/luatexdir/lua/luanode.c new file mode 100644 index 00000000000..17c8e7be8e2 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luanode.c @@ -0,0 +1,200 @@ +/* $Id: luanode.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include +#include "nodes.h" + +#undef link /* defined by cpascal.h */ +#define info(a) fixmem[(a)].hhlh +#define link(a) fixmem[(a)].hhrh + + +static char *group_code_names[] = { + "", + "simple", + "hbox", + "adjusted_hbox", + "vbox", + "vtop", + "align", + "no_align", + "output", + "math", + "disc", + "insert", + "vcenter", + "math_choice", + "semi_simple", + "math_shift", + "math_left", + "local_box" , + "split_off", + "split_keep", + "preamble", + "align_set", + "fin_row"}; + +char *pack_type_name[] = { "exactly", "additional"}; + + +void +lua_node_filter_s (int filterid, char *extrainfo, halfword head_node, halfword *tail_node) { + halfword ret; + int a; + lua_State *L = Luas[0]; + int callback_id = callback_defined(filterid); + if (head_node==null || vlink(head_node)==null || callback_id==0) + return; + lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); + lua_rawgeti(L,-1, callback_id); + if (!lua_isfunction(L,-1)) { + lua_pop(L,2); + return; + } + nodelist_to_lua(L,vlink(head_node)); /* arg 1 */ + lua_pushstring(L,extrainfo); /* arg 2 */ + if (lua_pcall(L,2,1,0) != 0) { /* no arg, 1 result */ + fprintf(stdout,"error: %s\n",lua_tostring(L,-1)); + lua_pop(L,2); + error(); + return; + } + if (lua_isboolean(L,-1)) { + if (lua_toboolean(L,-1)!=1) { + flush_node_list(vlink(head_node)); + vlink(head_node) = null; + } + } else { + a = nodelist_from_lua(L); + vlink(head_node)= a; + } + lua_pop(L,2); /* result and callback container table */ + if (fix_node_lists) + fix_node_list(head_node); + ret = vlink(head_node); + if (ret!=null) { + while (vlink(ret)!=null) + ret=vlink(ret); + *tail_node=ret; + } else { + *tail_node=head_node; + } + return ; +} + +void +lua_node_filter (int filterid, int extrainfo, halfword head_node, halfword *tail_node) { + lua_node_filter_s(filterid, group_code_names[extrainfo], head_node, tail_node); + return ; +} + + + +halfword +lua_hpack_filter (halfword head_node, scaled size, int pack_type, int extrainfo) { + halfword ret; + lua_State *L = Luas[0]; + int callback_id = callback_defined(hpack_filter_callback); + if (head_node==null || callback_id == 0) + return head_node; + lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); + lua_rawgeti(L,-1, callback_id); + if (!lua_isfunction(L,-1)) { + lua_pop(L,2); + return head_node; + } + + nodelist_to_lua(L,head_node); + lua_pushstring(L,group_code_names[extrainfo]); + lua_pushnumber(L,size); + lua_pushstring(L,pack_type_name[pack_type]); + if (lua_pcall(L,4,1,0) != 0) { /* no arg, 1 result */ + fprintf(stdout,"error: %s\n",lua_tostring(L,-1)); + lua_pop(L,2); + error(); + return head_node; + } + ret = head_node; + if (lua_isboolean(L,-1)) { + if (lua_toboolean(L,-1)!=1) { + flush_node_list(head_node); + ret = null; + } + } else { + ret = nodelist_from_lua(L); + } + lua_pop(L,2); /* result and callback container table */ + /* lua_gc(L,LUA_GCSTEP, LUA_GC_STEP_SIZE);*/ + if (fix_node_lists) + fix_node_list(ret); + return ret; +} + +halfword +lua_vpack_filter (halfword head_node, scaled size, int pack_type, scaled maxd, int extrainfo) { + halfword ret; + integer callback_id ; + lua_State *L = Luas[0]; + if (head_node==null) + return head_node; + if (strcmp("output",group_code_names[extrainfo])==0) { + callback_id = callback_defined(pre_output_filter_callback); + } else { + callback_id = callback_defined(vpack_filter_callback); + } + if (callback_id==0) { + return head_node; + } + lua_rawgeti(L,LUA_REGISTRYINDEX,callback_callbacks_id); + lua_rawgeti(L,-1, callback_id); + if (!lua_isfunction(L,-1)) { + lua_pop(L,2); + return head_node; + } + nodelist_to_lua(L,head_node); + lua_pushstring(L,group_code_names[extrainfo]); + lua_pushnumber(L,size); + lua_pushstring(L,pack_type_name[pack_type]); + lua_pushnumber(L,maxd); + if (lua_pcall(L,5,1,0) != 0) { /* no arg, 1 result */ + fprintf(stdout,"error: %s\n",lua_tostring(L,-1)); + lua_pop(L,2); + error(); + return head_node; + } + ret = head_node; + if (lua_isboolean(L,-1)) { + if (lua_toboolean(L,-1)!=1) { + flush_node_list(head_node); + ret = null; + } + } else { + ret = nodelist_from_lua(L); + } + lua_pop(L,2); /* result and callback container table */ + /* lua_gc(L,LUA_GCSTEP, LUA_GC_STEP_SIZE);*/ + 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. + */ + +int +visible_last_node_type (int n) { + int i = type(n); + if ((i!=math_node) && (i<=unset_node)) + return i+1; + if (i==glyph_node) + return -1; + if (i==whatsit_node && subtype(n)==local_par_node) + return -1; + if (i==255) + return -1 ; /* this is not right, probably dir nodes! */ + return last_known_node +1 ; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/luastuff.c b/Build/source/texk/web2c/luatexdir/lua/luastuff.c new file mode 100644 index 00000000000..f48bfdb0171 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luastuff.c @@ -0,0 +1,310 @@ +/* $Id: luastuff.c 1079 2008-03-05 15:34:41Z taco $ */ + +#include "luatex-api.h" +#include + +lua_State *Luas[65536]; + +extern char *startup_filename; +extern int safer_option; + +int luastate_max = 0; +int luastate_bytes = 0; + +void +make_table (lua_State *L, char *tab, char *getfunc, char *setfunc) { + /* make the table */ /* [{}] */ + lua_pushstring(L,tab); /* [{},"dimen"] */ + lua_newtable(L); /* [{},"dimen",{}] */ + lua_settable(L, -3); /* [{}] */ + /* fetch it back */ + lua_pushstring(L,tab); /* [{},"dimen"] */ + lua_gettable(L, -2); /* [{},{}] */ + /* make the meta entries */ + luaL_newmetatable(L,tab); /* [{},{},{}] */ + lua_pushstring(L, "__index"); /* [{},{},{},"__index"] */ + lua_pushstring(L, getfunc); /* [{},{},{},"__index","getdimen"] */ + lua_gettable(L, -5); /* [{},{},{},"__index",] */ + lua_settable(L, -3); /* [{},{},{}] */ + lua_pushstring(L, "__newindex");/* [{},{},{},"__newindex"] */ + lua_pushstring(L, setfunc); /* [{},{},{},"__newindex","setdimen"] */ + lua_gettable(L, -5); /* [{},{},{},"__newindex",] */ + lua_settable(L, -3); /* [{},{},{}] */ + lua_setmetatable(L,-2); /* [{},{}] : assign the metatable */ + lua_pop(L,1); /* [{}] : clean the stack */ +} + +static +const char *getS(lua_State * L, void *ud, size_t * size) { + LoadS *ls = (LoadS *) ud; + (void) L; + if (ls->size == 0) + return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + +void *my_luaalloc (void *ud, void *ptr, size_t osize, size_t nsize) { + void *ret = NULL; + if (nsize == 0) + free(ptr); + else + ret = realloc(ptr, nsize); + luastate_bytes += (nsize-osize); + return ret; +} + +static int my_luapanic (lua_State *L) { + (void)L; /* to avoid warnings */ + fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; +} + + +void +luainterpreter (int n) { + lua_State *L; + L = lua_newstate(my_luaalloc, NULL); + if (L==NULL) { + fprintf(stderr,"Can't create a new Lua state (%d).",n); + return; + } + lua_atpanic(L, &my_luapanic); + + luastate_max++; + luaL_openlibs(L); + + open_oslibext(L,safer_option); + + lua_getglobal(L,"package"); + lua_pushstring(L,""); + lua_setfield(L,-2,"cpath"); + lua_pop(L,1); /* pop the table */ + + /*luaopen_unicode(L);*/ + lua_pushcfunction(L, luaopen_unicode); + lua_pushstring(L, "unicode"); + lua_call(L, 1, 0); + + /*luaopen_zip(L);*/ + lua_pushcfunction(L, luaopen_zip); + lua_pushstring(L, "zip"); + lua_call(L, 1, 0); + + /*luaopen_lpeg(L);*/ + lua_pushcfunction(L, luaopen_lpeg); + lua_pushstring(L, "lpeg"); + lua_call(L, 1, 0); + + /*luaopen_md5(L);*/ + lua_pushcfunction(L, luaopen_md5); + lua_pushstring(L, "md5"); + lua_call(L, 1, 0); + + /*luaopen_lfs(L);*/ + lua_pushcfunction(L, luaopen_lfs); + lua_pushstring(L, "lfs"); + lua_call(L, 1, 0); + + /* zlib. slightly odd calling convention */ + luaopen_zlib(L); + lua_setglobal(L,"zlib"); + luaopen_gzip(L); + /* fontforge */ + luaopen_ff(L); + + luaopen_pdf(L); + luaopen_tex(L); + luaopen_token(L); + luaopen_node(L); + luaopen_texio(L); + luaopen_kpse(L); + if (n==0) { + luaopen_callback(L); + lua_createtable(L, 0, 0); + lua_setglobal(L, "texconfig"); + } + luaopen_lua(L,n,startup_filename); + luaopen_stats(L); + luaopen_font(L); + luaopen_lang(L); + + /* luaopen_img(L); */ + lua_pushcfunction(L, luaopen_img); + lua_pushstring(L, "img"); + lua_call(L, 1, 0); + + luaopen_mp(L); + + if (safer_option) { + /* disable some stuff if --safer */ + (void)hide_lua_value(L, "os","execute"); + (void)hide_lua_value(L, "os","rename"); + (void)hide_lua_value(L, "os","remove"); + (void)hide_lua_value(L, "io","popen"); + /* make io.open only read files */ + luaL_checkstack(L,2,"out of stack space"); + lua_getglobal(L,"io"); + lua_getfield(L,-1,"open_ro"); + lua_setfield(L,-2,"open"); + (void)hide_lua_value(L, "io","tmpfile"); + (void)hide_lua_value(L, "io","output"); + (void)hide_lua_value(L, "lfs","chdir"); + (void)hide_lua_value(L, "lfs","lock"); + (void)hide_lua_value(L, "lfs","touch"); + (void)hide_lua_value(L, "lfs","rmdir"); + (void)hide_lua_value(L, "lfs","mkdir"); + } + Luas[n] = L; +} + +int hide_lua_table(lua_State *L, char *name) { + int r=0; + lua_getglobal(L,name); + if(lua_istable(L,-1)) { + r = luaL_ref(L,LUA_REGISTRYINDEX); + lua_pushnil(L); + lua_setglobal(L,name); + } + return r; +} + +void unhide_lua_table(lua_State *L, char *name, int r) { + lua_rawgeti(L,LUA_REGISTRYINDEX,r); + lua_setglobal(L,name); + luaL_unref(L,LUA_REGISTRYINDEX,r); +} + +int hide_lua_value(lua_State *L, char *name, char *item) { + int r=0; + lua_getglobal(L,name); + if(lua_istable(L,-1)) { + lua_getfield(L,-1,item); + r = luaL_ref(L,LUA_REGISTRYINDEX); + lua_pushnil(L); + lua_setfield(L,-2,item); + } + return r; +} + +void unhide_lua_value(lua_State *L, char *name, char *item, int r) { + lua_getglobal(L,name); + if(lua_istable(L,-1)) { + lua_rawgeti(L,LUA_REGISTRYINDEX,r); + lua_setfield(L,-2,item); + luaL_unref(L,LUA_REGISTRYINDEX,r); + } +} + + +void +luacall(int n, int s) { + LoadS ls; + int i ; + char lua_id[12]; + if (Luas[n] == NULL) { + luainterpreter(n); + } + luatex_load_init(s,&ls); + if (ls.size>0) { + snprintf((char *)lua_id,12,"luas[%d]",n); + i = lua_load(Luas[n], getS, &ls, lua_id); + if (i != 0) { + Luas[n] = luatex_error(Luas[n],(i == LUA_ERRSYNTAX ? 0 : 1)); + } else { + i = lua_pcall(Luas[n], 0, 0, 0); + if (i != 0) { + Luas[n] = luatex_error(Luas[n],(i == LUA_ERRRUN ? 0 : 1)); + } + } + } +} + +void +luatokencall(int n, int p) { + LoadS ls; + int i, l; + char *s=NULL; + char lua_id[12]; + if (Luas[n] == NULL) { + luainterpreter(n); + } + l = 0; + s = tokenlist_to_cstring(p,1,&l); + ls.s = s; + ls.size = l; + if (ls.size>0) { + snprintf((char *)lua_id,12,"luas[%d]",n); + i = lua_load(Luas[n], getS, &ls, lua_id); + xfree(s); + if (i != 0) { + Luas[n] = luatex_error(Luas[n],(i == LUA_ERRSYNTAX ? 0 : 1)); + } else { + i = lua_pcall(Luas[n], 0, 0, 0); + if (i != 0) { + Luas[n] = luatex_error(Luas[n],(i == LUA_ERRRUN ? 0 : 1)); + } + } + } +} + + + +void +closelua(int n) { + if (n!=0 && Luas[n] != NULL) { + lua_close(Luas[n]); + luastate_max--; + Luas[n] = NULL; + } +} + + +void +luatex_load_init (int s, LoadS *ls) { + ls->s = (const char *)&(str_pool[str_start[s]]); + ls->size = str_start[s + 1] - str_start[s]; +} + +lua_State * +luatex_error (lua_State * L, int is_fatal) { + + size_t len; + char *err; + strnumber s; + const char *luaerr = lua_tolstring(L, -1,&len); + err = (char *)xmalloc(len+1); + len = snprintf(err,(len+1),"%s",luaerr); + if (is_fatal>0) { + /* Normally a memory error from lua. + The pool may overflow during the maketexlstring(), but we + are crashing anyway so we may as well abort on the pool size */ + s = maketexlstring(err, len); + lua_fatal_error(s); + /* never reached */ + xfree (err); + lua_close(L); + luastate_max--; + return (lua_State *)NULL; + } else { + /* Here, the pool could be full already, but we can possibly escape from that + * condition, since the lua chunk that caused the error is the current string. + */ + s = str_ptr-0x200000; + /* fprintf(stderr,"poolinfo: %d: %d,%d out of %d\n",s,pool_ptr,str_start[(s-1)],pool_size);*/ + pool_ptr = str_start[(s-1)]; + str_start[s] = pool_ptr; + if (pool_ptr+len>=pool_size) { + lua_norm_error(' '); + } else { + s = maketexlstring(err,len); + lua_norm_error(s); + flush_str(s); + } + xfree (err); + return L; + } +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/luatex.c b/Build/source/texk/web2c/luatexdir/lua/luatex.c new file mode 100644 index 00000000000..5172ca24292 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luatex.c @@ -0,0 +1,343 @@ +/* $Id: luatex.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include +#include + +/* do this aleph stuff here, for now */ + +void +b_test_in(void) +{ + string fname = kpse_find_file ((char *)(nameoffile + 1), + kpse_program_binary_format, true); + + if (fname) { + libcfree(nameoffile); + nameoffile = xmalloc(2+strlen(fname)); + namelength = strlen(fname); + strcpy((char *)nameoffile+1, fname); + } + else { + libcfree(nameoffile); + nameoffile = xmalloc(2); + namelength = 0; + nameoffile[0] = 0; + nameoffile[1] = 0; + } +} + + +int **ocp_tables; +static int ocp_entries = 0; + +void +allocate_ocp_table P2C(int, ocp_number, int, ocp_size) +{ + int i; + if (ocp_entries==0) { + ocp_tables = (int **) xmalloc(256*sizeof(int**)); + ocp_entries=256; + } else if ((ocp_number==256)&&(ocp_entries==256)) { + ocp_tables = xrealloc(ocp_tables, 65536); + ocp_entries=65536; + } + ocp_tables[ocp_number] = + (int *) xmalloc((1+ocp_size)*sizeof(int)); + ocp_tables[ocp_number][0] = ocp_size; + for (i=1; i<=ocp_size; i++) { + ocp_tables[ocp_number][i] = 0; + } +} + +void +dump_ocp_table P1C(int, ocp_number) +{ + dump_things(ocp_tables[ocp_number][0], ocp_tables[ocp_number][0]+1); +} + +void +undump_ocp_table P1C(int, ocp_number) +{ + int sizeword; + if (ocp_entries==0) { + ocp_tables = (int **) xmalloc(256*sizeof(int**)); + ocp_entries=256; + } else if ((ocp_number==256)&&(ocp_entries==256)) { + ocp_tables = xrealloc(ocp_tables, 65536); + ocp_entries=65536; + } + undump_things(sizeword,1); + ocp_tables[ocp_number] = + (int *) xmalloc((1+sizeword)*sizeof(int)); + ocp_tables[ocp_number][0] = sizeword; + undump_things(ocp_tables[ocp_number][1], sizeword); +} + + +void +run_external_ocp P1C(string, external_ocp_name) +{ + char *in_file_name; + char *out_file_name; + FILE *in_file; + FILE *out_file; + char command_line[400]; + int i; + unsigned c; + int c_in; +#ifdef WIN32 + char *tempenv; + +#define null_string(s) ((s == NULL) || (*s == '\0')) + + tempenv = getenv("TMPDIR"); + if (null_string(tempenv)) + tempenv = getenv("TEMP"); + if (null_string(tempenv)) + tempenv = getenv("TMP"); + if (null_string(tempenv)) + tempenv = "c:/tmp"; /* "/tmp" is not good if we are on a CD-ROM */ + in_file_name = concat(tempenv, "/__aleph__in__XXXXXX"); + mktemp(in_file_name); +#else + in_file_name = strdup("/tmp/__aleph__in__XXXXXX"); + mkstemp(in_file_name); +#endif /* WIN32 */ + + in_file = fopen(in_file_name, FOPEN_WBIN_MODE); + + for (i=1; i<=otp_input_end; i++) { + c = otp_input_buf[i]; + if (c>0xffff) { + fprintf(stderr, "Aleph does not currently support 31-bit chars\n"); + exit(1); + } + if (c>0x4000000) { + fputc(0xfc | ((c>>30) & 0x1), in_file); + fputc(0x80 | ((c>>24) & 0x3f), in_file); + fputc(0x80 | ((c>>18) & 0x3f), in_file); + fputc(0x80 | ((c>>12) & 0x3f), in_file); + fputc(0x80 | ((c>>6) & 0x3f), in_file); + fputc(0x80 | (c & 0x3f), in_file); + } else if (c>0x200000) { + fputc(0xf8 | ((c>>24) & 0x3), in_file); + fputc(0x80 | ((c>>18) & 0x3f), in_file); + fputc(0x80 | ((c>>12) & 0x3f), in_file); + fputc(0x80 | ((c>>6) & 0x3f), in_file); + fputc(0x80 | (c & 0x3f), in_file); + } else if (c>0x10000) { + fputc(0xf0 | ((c>>18) & 0x7), in_file); + fputc(0x80 | ((c>>12) & 0x3f), in_file); + fputc(0x80 | ((c>>6) & 0x3f), in_file); + fputc(0x80 | (c & 0x3f), in_file); + } else if (c>0x800) { + fputc(0xe0 | ((c>>12) & 0xf), in_file); + fputc(0x80 | ((c>>6) & 0x3f), in_file); + fputc(0x80 | (c & 0x3f), in_file); + } else if (c>0x80) { + fputc(0xc0 | ((c>>6) & 0x1f), in_file); + fputc(0x80 | (c & 0x3f), in_file); + } else { + fputc(c & 0x7f, in_file); + } + } + fclose(in_file); + +#define advance_cin if ((c_in = fgetc(out_file)) == -1) { \ + fprintf(stderr, "File contains bad char\n"); \ + goto end_of_while; \ + } + +#ifdef WIN32 + out_file_name = concat(tempenv, "/__aleph__out__XXXXXX"); + mktemp(out_file_name); +#else + out_file_name = strdup("/tmp/__aleph__out__XXXXXX"); + mkstemp(out_file_name); +#endif + + sprintf(command_line, "%s <%s >%s\n", + external_ocp_name+1, in_file_name, out_file_name); + system(command_line); + out_file = fopen(out_file_name, FOPEN_RBIN_MODE); + otp_output_end = 0; + otp_output_buf[otp_output_end] = 0; + while ((c_in = fgetc(out_file)) != -1) { + if (c_in>=0xfc) { + c = (c_in & 0x1) << 30; + {advance_cin} + c |= (c_in & 0x3f) << 24; + {advance_cin} + c |= (c_in & 0x3f) << 18; + {advance_cin} + c |= (c_in & 0x3f) << 12; + {advance_cin} + c |= (c_in & 0x3f) << 6; + {advance_cin} + c |= c_in & 0x3f; + } else if (c_in>=0xf8) { + c = (c_in & 0x3) << 24; + {advance_cin} + c |= (c_in & 0x3f) << 18; + {advance_cin} + c |= (c_in & 0x3f) << 12; + {advance_cin} + c |= (c_in & 0x3f) << 6; + {advance_cin} + c |= c_in & 0x3f; + } else if (c_in>=0xf0) { + c = (c_in & 0x7) << 18; + {advance_cin} + c |= (c_in & 0x3f) << 12; + {advance_cin} + c |= (c_in & 0x3f) << 6; + {advance_cin} + c |= c_in & 0x3f; + } else if (c_in>=0xe0) { + c = (c_in & 0xf) << 12; + {advance_cin} + c |= (c_in & 0x3f) << 6; + {advance_cin} + c |= c_in & 0x3f; + } else if (c_in>=0x80) { + c = (c_in & 0x1f) << 6; + {advance_cin} + c |= c_in & 0x3f; + } else { + c = c_in & 0x7f; + } + otp_output_buf[++otp_output_end] = c; + } + +end_of_while: + remove(in_file_name); + remove(out_file_name); +} + +/* Read and write dump files through zlib */ + +/* Earlier versions recast *f from FILE * to gzFile, but there is + * no guarantee that these have the same size, so a static variable + * is needed. + */ + +static gzFile gz_fmtfile = NULL; + +void +do_zdump (char *p, int item_size, int nitems, FILE *out_file) +{ + int err; + if (nitems==0) + return; + if (gzwrite (gz_fmtfile,(void *)p, item_size*nitems) != item_size*nitems) + { + fprintf (stderr, "! Could not write %d %d-byte item(s): %s.\n", + nitems, item_size, gzerror(gz_fmtfile,&err)); + uexit (1); + } +} + +void +do_zundump (char *p, int item_size, int nitems, FILE *in_file) +{ + int err; + if (nitems==0) + return; + if (gzread (gz_fmtfile,(void *)p, item_size*nitems) <= 0) + { + fprintf (stderr, "Could not undump %d %d-byte item(s): %s.\n", + nitems, item_size, gzerror(gz_fmtfile,&err)); + uexit (1); + } +} + +#define COMPRESSION "R3" + +boolean +zopen_w_input (FILE **f, int format, const_string fopen_mode) { + int callbackid; + int res; + char *fnam; + callbackid = callback_defined(find_format_file_callback); + if (callbackid>0) { + res = run_callback(callbackid,"S->S",(nameoffile+1),&fnam); + if (res && fnam && strlen(fnam)>0) { + xfree (nameoffile); + nameoffile = xmalloc (strlen(fnam)+2); + memcpy((nameoffile+1),fnam,strlen(fnam)); + *(nameoffile+strlen(fnam)+1)=0; + *f = xfopen(fnam,fopen_mode); + if (*f == NULL) { + return 0; + } + } else { + return 0; + } + } else { + res = open_input(f,format,fopen_mode); + } + if (res) { + gz_fmtfile = gzdopen(fileno(*f),"rb" COMPRESSION); + } + return res; +} + +boolean +zopen_w_output (FILE **f, const_string fopen_mode) { + int res = 1; + if (luainit) { + *f = fopen((nameoffile+1),fopen_mode); + if (*f == NULL) { + return 0; + } + } else { + res = open_output(f,fopen_mode); + } + if (res) { + gz_fmtfile = gzdopen(fileno(*f),"wb" COMPRESSION); + } + return res; +} + +void +zwclose (FILE *f) { + gzclose(gz_fmtfile); +} + +/* create the dvi or pdf file */ + +int +open_outfile(FILE **f, char *name, char *mode) { + FILE *res; + res = fopen(name,mode); + if (res != NULL) { + *f = res; + return 1; + } + return 0; +} + + +/* the caller sets tfm_buffer=NULL and tfm_size=0 */ + +int +readbinfile (FILE *f, unsigned char **tfm_buffer, integer *tfm_size) { + void *buf; + int size; + if (fseek(f, 0, SEEK_END)==0) { + size = ftell(f); + if (size>0) { + buf = xmalloc(size); + if(fseek(f, 0, SEEK_SET)==0) { + if(fread((void *)buf,size,1,f)==1) { + *tfm_buffer=(unsigned char *)buf; + *tfm_size=(integer)size; + return 1; + } + } + } + } /* seek failed, or zero-sized file */ + return 0; +} + 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..23d9ca82150 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/luatoken.c @@ -0,0 +1,548 @@ +/* $Id: luatoken.c 1013 2008-02-14 00:09:02Z oneiros $ */ + +#include "luatex-api.h" +#include + +#include "tokens.h" + +command_item command_names[] = + { { "relax", 0, NULL }, + { "left_brace", 0 , NULL }, + { "right_brace", 0 , NULL }, + { "math_shift", 0 , NULL }, + { "tab_mark", 0 , NULL }, + { "car_ret", 0 , NULL }, + { "mac_param", 0 , NULL }, + { "sup_mark", 0 , NULL }, + { "sub_mark", 0 , NULL }, + { "endv", 0 , NULL }, + { "spacer", 0 , NULL }, + { "letter", 0 , NULL }, + { "other_char", 0 , NULL }, + { "par_end", 0 , NULL }, + { "stop", 0 , NULL }, + { "delim_num", 0 , NULL }, + { "char_num", 0 , NULL }, + { "math_char_num", 0 , NULL }, + { "mark", 0 , NULL }, + { "xray", 0 , NULL }, + { "make_box", 0 , NULL }, + { "hmove", 0 , NULL }, + { "vmove", 0 , NULL }, + { "un_hbox", 0 , NULL }, + { "un_vbox", 0 , NULL }, + { "remove_item", 0 , NULL }, + { "hskip", 0 , NULL }, + { "vskip", 0 , NULL }, + { "mskip", 0 , NULL }, + { "kern", 0 , NULL }, + { "mkern", 0 , NULL }, + { "leader_ship", 0 , NULL }, + { "halign", 0 , NULL }, + { "valign", 0 , NULL }, + { "no_align", 0 , NULL }, + { "vrule", 0 , NULL }, + { "hrule", 0 , NULL }, + { "insert", 0 , NULL }, + { "vadjust", 0 , NULL }, + { "ignore_spaces", 0 , NULL }, + { "after_assignment", 0 , NULL }, + { "after_group", 0 , NULL }, + { "break_penalty", 0 , NULL }, + { "start_par", 0 , NULL }, + { "ital_corr", 0 , NULL }, + { "accent", 0 , NULL }, + { "math_accent", 0 , NULL }, + { "discretionary", 0 , NULL }, + { "eq_no", 0 , NULL }, + { "left_right", 0 , NULL }, + { "math_comp", 0 , NULL }, + { "limit_switch", 0 , NULL }, + { "above", 0 , NULL }, + { "math_style", 0 , NULL }, + { "math_choice", 0 , NULL }, + { "non_script", 0 , NULL }, + { "vcenter", 0 , NULL }, + { "case_shift", 0 , NULL }, + { "message", 0 , NULL }, + { "extension", 0 , NULL }, + { "in_stream", 0 , NULL }, + { "begin_group", 0 , NULL }, + { "end_group", 0 , NULL }, + { "omit", 0 , NULL }, + { "ex_space", 0 , NULL }, + { "no_boundary", 0 , NULL }, + { "radical", 0 , NULL }, + { "end_cs_name", 0 , NULL }, + { "char_ghost", 0 , NULL }, + { "assign_local_box", 0 , NULL }, + { "char_given", 0 , NULL }, + { "math_given", 0 , NULL }, + { "omath_given", 0 , NULL }, + { "last_item", 0 , NULL }, + { "toks_register", 0 , NULL }, + { "assign_toks", 0, NULL }, + { "assign_int", 0, NULL }, + { "assign_dimen", 0 , NULL }, + { "assign_glue", 0 ,NULL }, + { "assign_mu_glue", 0 , NULL }, + { "assign_font_dimen", 0 , NULL }, + { "assign_font_int", 0 , NULL }, + { "set_aux", 0 , NULL }, + { "set_prev_graf", 0 , NULL }, + { "set_page_dimen", 0 , NULL }, + { "set_page_int", 0 , NULL }, + { "set_box_dimen", 0 , NULL }, + { "set_shape", 0, NULL }, + { "def_code", 0 , NULL }, + { "extdef_code", 0 , NULL }, + { "def_family", 0 , NULL }, + { "set_font", 0 , NULL }, + { "def_font", 0 , NULL }, + { "register", 0 , NULL }, + { "assign_box_dir", 0 , NULL }, + { "assign_dir", 0 , NULL }, + { "advance", 0 , NULL }, + { "multiply", 0 , NULL }, + { "divide", 0 , NULL }, + { "prefix", 0 , NULL }, + { "let", 0 , NULL }, /* 100 */ + { "shorthand_def", 0 , NULL }, + { "read_to_cs", 0 , NULL }, + { "def", 0 , NULL }, + { "set_box", 0 , NULL }, + { "hyph_data", 0 , NULL }, + { "set_interaction", 0 , NULL }, + { "letterspace_font", 0 , NULL }, + { "set_ocp", 0 , NULL }, + { "def_ocp", 0 , NULL }, + { "set_ocp_list", 0 , NULL }, /* 110 */ + { "def_ocp_list", 0 , NULL }, + { "clear_ocp_lists", 0 , NULL }, + { "push_ocp_list", 0 , NULL }, + { "pop_ocp_list", 0 , NULL }, + { "ocp_list_op", 0 , NULL }, + { "ocp_trace_level", 0 , NULL}, + { "undefined_cs", 0 , NULL }, + { "expand_after", 0 , NULL }, + { "no_expand", 0 , NULL }, + { "input", 0 , NULL }, /* 120 */ + { "if_test", 0 , NULL }, + { "fi_or_else", 0 , NULL }, + { "cs_name", 0 , NULL }, + { "convert", 0 , NULL }, + { "the", 0 , NULL }, + { "top_bot_mark", 0 , NULL }, + { "call", 0 , NULL }, + { "long_call", 0 , NULL }, + { "outer_call", 0 , NULL }, + { "long_outer_call", 0 , NULL }, /* 130 */ + { "end_template", 0 , NULL }, + { "dont_expand", 0, NULL }, + { "glue_ref", 0 , NULL }, + { "shape_ref", 0 , NULL }, + { "box_ref", 0 , NULL }, + { "data", 0 , NULL }, + { NULL, 0, NULL } }; + + +int get_command_id (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; + cur_cs = 0; + int len = lua_objlen(L,-1); + if (len==3 || len==2) { + r = 1; + lua_rawgeti(L,-1,1); + cur_cmd = lua_tointeger(L,-1); + lua_rawgeti(L,-2,2); + cur_chr = lua_tointeger(L,-1); + if (len==3) { + lua_rawgeti(L,-3,3); + cur_cs = lua_tointeger(L,-1); + } + lua_pop(L,len); + if (cur_cs==0) + cur_tok=(cur_cmd*string_offset)+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; + int len = lua_objlen(L,-1); + if (len==3 || len==2) { + lua_rawgeti(L,-1,1); + cmd = lua_tointeger(L,-1); + lua_rawgeti(L,-2,2); + chr = lua_tointeger(L,-1); + if (len==3) { + lua_rawgeti(L,-3,3); + cs = lua_tointeger(L,-1); + } + lua_pop(L,len); + if (cs==0) { + return (cmd*string_offset)+chr; + } else { + return cs_token_flag+cs; + } + } + return -1; +} + +static int +get_cur_cs (lua_State *L) { + char *s; + unsigned j; + size_t l; + integer cs; + int save_nncs; + int ret; + ret = 0; + cur_cs = 0; + lua_getfield(L,-1,"name"); + if (lua_isstring(L,-1)) { + s = (char *)lua_tolstring(L,-1,&l); + if (l>0) { + if (last+l>buf_size) + check_buffer_overflow(last+l); + for (j=0;jalloci) { \ + ret = xrealloc(ret,alloci+64); \ + alloci = alloci + 64; } \ + ret[i++] = a; } + +#define Print_char(a) append_i_byte(a) + +#define Print_uchar(s) { \ + if (s<=0x7F) { \ + Print_char(s); \ + } else if (s<=0x7FF) { \ + Print_char(0xC0 + (s / 0x40)); \ + Print_char(0x80 + (s % 0x40)); \ + } else if (s<=0xFFFF) { \ + Print_char(0xE0 + (s / 0x1000)); \ + Print_char(0x80 + ((s % 0x1000) / 0x40)); \ + Print_char(0x80 + ((s % 0x1000) % 0x40)); \ + } else if (s>=0x10FF00) { \ + Print_char(s-0x10FF00); \ + } else { \ + Print_char(0xF0 + (s / 0x40000)); \ + Print_char(0x80 + ((s % 0x40000) / 0x1000)); \ + Print_char(0x80 + (((s % 0x40000) % 0x1000) / 0x40)); \ + Print_char(0x80 + (((s % 0x40000) % 0x1000) % 0x40)); \ + } } + + +#define Print_esc(b) { if (e>0 && e=0xF0))|| \ + ((length(a)==3)&&(str_pool[str_start_macro(a)]>=0xE0))|| \ + ((length(a)==2)&&(str_pool[str_start_macro(a)]>=0xC0)) + +#define is_cat_letter(a) \ + (get_char_cat_code(pool_to_unichar(str_start_macro(a))) == 11) + +static int active_base = 0; +static int hash_base = 0; +static int eqtb_size = 0; +static int null_cs = 0; +static int undefined_control_sequence; + +char * +tokenlist_to_cstring ( int p , int inhibit_par, int *siz) { + integer m, c ; + integer q; + char *s; + int e; + char *ret=NULL; + int match_chr = '#'; + int n = '0'; + int alloci = 0; + int i = 0; + if (p==null || link(p)==null) { + if (siz!=NULL) + *siz = 0; + return NULL; + } + p = link(p); /* skip refcount */ + if (active_base==0) { + active_base = get_active_base(); + hash_base = get_hash_base(); + null_cs = get_nullcs(); + eqtb_size = get_eqtb_size(); + undefined_control_sequence = get_undefined_control_sequence(); + } + e = get_escape_char(); + while ( p != null ) { + if (p < fix_mem_min || p > fix_mem_end ) { + Print_esc ("CLOBBERED.") ; + break; + } + if (info(p)>=cs_token_flag) { + if ( ! (inhibit_par && info(p)==par_token) ) { + q = info(p) - cs_token_flag; + if (q=undefined_control_sequence)&&((q<=eqtb_size))||(q>eqtb_size+hash_extra)) { + Print_esc("IMPOSSIBLE."); + } else if ((zget_cs_text(q)<0)||(zget_cs_text(q)>=str_ptr)) { + Print_esc("NONEXISTENT."); + } else { + Print_uchar (e); + s = makecstring(zget_cs_text(q)); + while (*s) { Print_char(*s); s++; } + if ((! single_letter(zget_cs_text(q))) || is_cat_letter(zget_cs_text(q))) { + Print_char(' '); + } + } + } + } else { + m=info(p) / string_offset; + c=info(p) % string_offset; + if ( info(p) < 0 ) { + Print_esc ( "BAD.") ; + } else { + switch ( m ) { + case 6 : /* falls through */ + Print_uchar ( c ) ; + case 1 : + case 2 : + case 3 : + case 4 : + case 7 : + case 8 : + case 10 : + case 11 : + case 12 : + Print_uchar ( c ) ; + break ; + case 5 : + Print_uchar ( match_chr ) ; + if ( c <= 9 ) { + Print_char ( c + '0') ; + } else { + Print_char ( '!' ) ; + return NULL; + } + break ; + case 13 : + match_chr = c ; + Print_uchar ( c ) ; + incr ( n ) ; + Print_char ( n ) ; + if ( n > '9' ) + return NULL; + break ; + case 14 : + if ( c == 0 ) { + Print_char ('-'); + Print_char ('>') ; + } + break ; + default: + Print_esc ( "BAD.") ; + break ; + } + } + } + p = link(p); + } + ret[i]=0; + if (siz!=NULL) + *siz = i; + 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 < fix_mem_end) { i++; v = link(v); } + i = 1; + lua_createtable(L,i,0); + while (p!=null&& p < fix_mem_end) { + if (info(p)>=cs_token_flag) { + cs=info(p)-cs_token_flag; + cmd = zget_eq_type(cs); + chr = zget_equiv(cs); + make_token_table(L,cmd,chr,cs); + } else { + cmd=info(p) / string_offset; + chr=info(p) % string_offset; + make_token_table(L,cmd,chr,0); + } + lua_rawseti(L,-2,i++); + p = 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,l); +} + + +int +tokenlist_from_lua(lua_State *L) { + char *s; + int tok,i; + size_t j; + halfword p,q,r; + r = get_avail(); + info(r)=0; /* ref count */ + link(r)=null; + p = r; + if (lua_istable(L,-1)) { + j = lua_objlen(L,-1); + if (j>0) { + for (i=1;i<=j;i++) { + lua_rawgeti(L,-1,i); + tok = token_from_lua(L); + if (tok>=0) { + store_new_token(tok); + } + lua_pop(L,1); + }; + } + return r; + } else if (lua_isstring(L,-1)) { + s = (char *)lua_tolstring(L,-1,&j); + for (i=0;i0) { + for (i=1;i<=j;i++) { + lua_rawgeti(L,-1,i); + if (get_cur_cmd(L) || get_cur_cs(L)) { + store_new_token(cur_tok); + } + lua_pop(L,1); + } + } + if (p!=r) { + p = link(r); + free_avail(r); + begin_token_list(p, inserted); + cur_input.nofilter_field=true; + get_next(); + lua_pop(L,1); + break; + } else { + fprintf(stdout,"error: illegal or empty token list returned\n"); + lua_pop(L,2); + error(); + return; + } + } else { + lua_pop(L,1); + if (get_cur_cmd(L) || get_cur_cs(L)) { + lua_pop(L,1); + break; + } else { + lua_pop(L,2); + continue; + } + } + } else { + lua_pop(L,1); + continue; + } + } + lua_pop(L,1); /* callback container */ + return; +} + diff --git a/Build/source/texk/web2c/luatexdir/lua/mp.w b/Build/source/texk/web2c/luatexdir/lua/mp.w new file mode 100644 index 00000000000..a459cc48fe1 --- /dev/null +++ b/Build/source/texk/web2c/luatexdir/lua/mp.w @@ -0,0 +1,26173 @@ +% $Id: mp.web,v 1.8 2005/08/24 10:54:02 taco Exp $ +% MetaPost, by John Hobby. Public domain. + +% Much of this program was copied with permission from MF.web Version 1.9 +% It interprets a language very similar to D.E. Knuth's METAFONT, but with +% changes designed to make it more suitable for PostScript output. + +% TeX is a trademark of the American Mathematical Society. +% METAFONT is a trademark of Addison-Wesley Publishing Company. +% PostScript is a trademark of Adobe Systems Incorporated. + +% Here is TeX material that gets inserted after \input webmac +\def\hang{\hangindent 3em\noindent\ignorespaces} +\def\textindent#1{\hangindent2.5em\noindent\hbox to2.5em{\hss#1 }\ignorespaces} +\def\ps{PostScript} +\def\psqrt#1{\sqrt{\mathstrut#1}} +\def\k{_{k+1}} +\def\pct!{{\char`\%}} % percent sign in ordinary text +\font\tenlogo=logo10 % font used for the METAFONT logo +\font\logos=logosl10 +\def\MF{{\tenlogo META}\-{\tenlogo FONT}} +\def\MP{{\tenlogo META}\-{\tenlogo POST}} +\def\[#1]{\ignorespaces} % left over from pascal web +\def\<#1>{$\langle#1\rangle$} +\def\section{\mathhexbox278} +\let\swap=\leftrightarrow +\def\round{\mathop{\rm round}\nolimits} +\mathchardef\vb="026A % synonym for `\|' + +\def\(#1){} % this is used to make section names sort themselves better +\def\9#1{} % this is used for sort keys in the index via @@:sort key}{entry@@> +\def\title{MetaPost} +\pdfoutput=1 +\pageno=3 + +@* \[1] Introduction. + +This is \MP, a graphics-language processor based on D. E. Knuth's \MF. + +The main purpose of the following program is to explain the algorithms of \MP\ +as clearly as possible. However, the program has been written so that it +can be tuned to run efficiently in a wide variety of operating environments +by making comparatively few changes. Such flexibility is possible because +the documentation that follows is written in the \.{WEB} language, which is +at a higher level than C. + +A large piece of software like \MP\ has inherent complexity that cannot +be reduced below a certain level of difficulty, although each individual +part is fairly simple by itself. The \.{WEB} language is intended to make +the algorithms as readable as possible, by reflecting the way the +individual program pieces fit together and by providing the +cross-references that connect different parts. Detailed comments about +what is going on, and about why things were done in certain ways, have +been liberally sprinkled throughout the program. These comments explain +features of the implementation, but they rarely attempt to explain the +\MP\ language itself, since the reader is supposed to be familiar with +{\sl The {\logos METAFONT\/}book} as well as the manual +@.WEB@> +@:METAFONTbook}{\sl The {\logos METAFONT\/}book@> +{\sl A User's Manual for MetaPost}, Computing Science Technical Report 162, +AT\AM T Bell Laboratories. + +@ The present implementation is a preliminary version, but the possibilities +for new features are limited by the desire to remain as nearly compatible +with \MF\ as possible. + +On the other hand, the \.{WEB} description can be extended without changing +the core of the program, and it has been designed so that such +extensions are not extremely difficult to make. +The |banner| string defined here should be changed whenever \MP\ +undergoes any modifications, so that it will be clear which version of +\MP\ might be the guilty party when a problem arises. +@^extensions to \MP@> +@^system dependencies@> + +@d banner "This is MetaPost, Version 1.003" /* printed when \MP\ starts */ +@d metapost_version "1.003" +@d mplib_version "0.30" +@d version_string " (Cweb version 0.30)" + +@d true 1 +@d false 0 + +@ The external library header for \MP\ is |mplib.h|. It contains a +few typedefs and the header defintions for the externally used +fuctions. + +The most important of the typedefs is the definition of the structure +|MP_options|, that acts as a small, configurable front-end to the fairly +large |MP_instance| structure. + +@(mplib.h@>= +typedef struct MP_instance * MP; +@ +typedef struct MP_options { + @