texlive[65866] trunk: new "late special" feature by Phelype

commits+lscarso at tug.org commits+lscarso at tug.org
Sat Feb 18 00:30:18 CET 2023


Revision: 65866
          http://tug.org/svn/texlive?view=revision&revision=65866
Author:   lscarso
Date:     2023-02-18 00:30:17 +0100 (Sat, 18 Feb 2023)
Log Message:
-----------
new "late special" feature by Phelype Oleinik,heavily adapted by H.Hagen.

Modified Paths:
--------------
    trunk/Build/source/texk/web2c/luatexdir/ChangeLog
    trunk/Build/source/texk/web2c/luatexdir/dvi/dvigen.c
    trunk/Build/source/texk/web2c/luatexdir/lua/lnewtokenlib.c
    trunk/Build/source/texk/web2c/luatexdir/lua/lnodelib.c
    trunk/Build/source/texk/web2c/luatexdir/lua/ltexlib.c
    trunk/Build/source/texk/web2c/luatexdir/lua/luanode.c
    trunk/Build/source/texk/web2c/luatexdir/lua/luatex-api.h
    trunk/Build/source/texk/web2c/luatexdir/lua/luatoken.c
    trunk/Build/source/texk/web2c/luatexdir/luatex_svnversion.h
    trunk/Build/source/texk/web2c/luatexdir/pdf/pdflistout.c
    trunk/Build/source/texk/web2c/luatexdir/pdf/pdfliteral.c
    trunk/Build/source/texk/web2c/luatexdir/pdf/pdftables.c
    trunk/Build/source/texk/web2c/luatexdir/tex/backend.c
    trunk/Build/source/texk/web2c/luatexdir/tex/commands.c
    trunk/Build/source/texk/web2c/luatexdir/tex/commands.h
    trunk/Build/source/texk/web2c/luatexdir/tex/extensions.c
    trunk/Build/source/texk/web2c/luatexdir/tex/extensions.h
    trunk/Build/source/texk/web2c/luatexdir/tex/maincontrol.c
    trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.c
    trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.h
    trunk/Master/texmf-dist/doc/luatex/base/luatex-modifications.tex
    trunk/Master/texmf-dist/doc/luatex/base/luatex-nodes.tex
    trunk/Master/texmf-dist/doc/luatex/base/luatex.pdf

Modified: trunk/Build/source/texk/web2c/luatexdir/ChangeLog
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/ChangeLog	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/ChangeLog	2023-02-17 23:30:17 UTC (rev 65866)
@@ -1,3 +1,8 @@
+2023-02-18  Luigi Scarso <luigi.scarso at gmail.com> 
+    * new "late special" feature by Phelype Oleinik,
+      heavily adapted by H.Hagen.
+
+
 2023-02-05  Luigi Scarso <luigi.scarso at gmail.com> 
     *  Fix typos (thanks to J. Friedrich) 
 

Modified: trunk/Build/source/texk/web2c/luatexdir/dvi/dvigen.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/dvi/dvigen.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/dvi/dvigen.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -1324,11 +1324,21 @@
     int old_setting;
     /*tex index into |cur_string| */
     unsigned k;
+    halfword h; 
     synch_dvi_with_pos(pdf->posstruct->pos);
     old_setting = selector;
+    if (subtype(p) == late_special_node ) {
+        expand_macros_in_tokenlist(special_tokens(p));
+        h = token_link(def_ref); 
+    } else { 
+        h = token_link(special_tokens(p));
+    }
     selector = new_string;
-    show_token_list(token_link(write_tokens(p)), null, -1);
+    show_token_list(h, null, -1);
     selector = old_setting;
+    if (subtype(p) == late_special_node ) {
+        flush_list(def_ref);
+    }
     if (cur_length < 256) {
         dvi_out(xxx1);
         dvi_out(cur_length);

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/lnewtokenlib.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/lnewtokenlib.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/lnewtokenlib.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -124,6 +124,41 @@
     return NULL;
 }
 
+/* moved here */
+
+int token_from_lua(lua_State * L)
+{
+    int cmd, chr;
+    int cs = 0;
+    size_t len;
+    lua_token *p;
+    if (lua_type(L, -1) == LUA_TTABLE) {
+        len = lua_rawlen(L, -1);
+        if (len == 3 || len == 2) {
+            lua_rawgeti(L, -1, 1);
+            cmd = (int) lua_tointeger(L, -1);
+            lua_rawgeti(L, -2, 2);
+            chr = (int) lua_tointeger(L, -1);
+            if (len == 3) {
+                lua_rawgeti(L, -3, 3);
+                cs = (int) lua_tointeger(L, -1);
+            }
+            lua_pop(L, (int) len);
+            if (cs == 0) {
+                return token_val(cmd, chr);
+            } else {
+                return cs_token_flag + cs;
+            }
+        }
+    } else { 
+        p = check_istoken(L, -1);
+        if (p) {
+            return token_info(p->token);
+        }
+    }
+    return -1;
+}
+
 /* token library functions */
 
 static void make_new_token(lua_State * L, int cmd, int chr, int cs)

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/lnodelib.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/lnodelib.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/lnodelib.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -150,7 +150,7 @@
 
 #define nodelib_setattr(L, s, n)     reassign_attribute(n,nodelib_getlist(L,s))
 
-#define nodelib_gettoks(L,a)   tokenlist_from_lua(L)
+#define nodelib_gettoks(L,a)   tokenlist_from_lua(L, a)
 
 #define nodelib_getspec        nodelib_getlist
 #define nodelib_getaction      nodelib_getlist
@@ -1584,6 +1584,7 @@
 
 #define set_pdf_literal_direct_token(L,n,i) do { \
     pdf_literal_data(n) = nodelib_gettoks(L, i); \
+    pdf_literal_type(n) = normal; \
 } while (0)
 
 #define cleanup_late_lua(n) do {                               \
@@ -1652,7 +1653,7 @@
 #define get_write_direct_value(L,n) do {  \
     int l; \
     char *s; \
-    expand_macros_in_tokenlist(n); \
+    expand_macros_in_tokenlist(write_tokens(n)); \
     s = tokenlist_to_cstring(def_ref, 1, &l); \
     lua_pushlstring(L, s, (size_t) l); \
     free(s); \
@@ -1689,7 +1690,7 @@
             halfword s = subtype(n);
             if (s == user_defined_node) {
                 get_user_node_direct_value(L, n);
-            } else if (s == pdf_literal_node) {
+            } else if (s == pdf_literal_node || s == pdf_late_literal_node) {
                 get_pdf_literal_direct_value(L, n);
                 /*tex A bonus. */
                 lua_pushinteger(L,pdf_literal_mode(n));
@@ -1698,7 +1699,7 @@
                 get_late_lua_direct_value(L, n);
             } else if (s == pdf_setmatrix_node) {
                 get_pdf_setmatrix_direct_value(L, n);
-            } else if (s == special_node) {
+            } else if (s == special_node || s == late_special_node) {
                 get_special_direct_value(L, n);
             } else if (s == write_node) {
                 get_write_direct_value(L, n);
@@ -1725,17 +1726,21 @@
             halfword s = subtype(n);
             if (s == user_defined_node) {
                 set_user_node_direct_value(L, n, 2);
-            } else if (s == pdf_literal_node) {
-                set_pdf_literal_direct_normal(L, n, 2);
-                if (lua_type(L,2) == LUA_TNUMBER) {
+            } else if (s == pdf_literal_node || s == pdf_late_literal_node) {
+                if (lua_type(L,2) == LUA_TTABLE) {
+                    set_pdf_literal_direct_token(L, n, 2);
+                } else { 
+                    set_pdf_literal_direct_normal(L, n, 2);
+                }
+                if (lua_type(L,3) == LUA_TNUMBER) {
                     /*tex A bonus. */
-                    pdf_literal_mode(n) = lua_tointeger(L,2);
+                    pdf_literal_mode(n) = lua_tointeger(L,3);
                 }
             } else if (s == late_lua_node) {
                 set_late_lua_direct_normal(L, n, 2);
             } else if (s == pdf_setmatrix_node) {
                 set_pdf_setmatrix_direct_value(L, n, 2);
-            } else if (s == special_node) {
+            } else if (s == special_node || s == late_special_node) {
                 set_special_direct_value(L, n, 2);
             } else if (s == write_node) {
                 set_write_direct_value(L,n,2);
@@ -3200,7 +3205,8 @@
         else if (t == fence_noad)               subtypes = node_subtypes_fence;
         /* backend */
         else if (t == pdf_dest_node)            subtypes = node_values_pdf_destination;
-        else if (t == pdf_literal_node)         subtypes = node_values_pdf_literal;
+        else if((t == pdf_literal_node)
+             || (t == pdf_late_literal_node))   subtypes = node_values_pdf_literal;
     }
     if (subtypes != NULL) {
         lua_checkstack(L, 2);
@@ -4435,7 +4441,7 @@
         } else {
             lua_pushnil(L);
         }
-    } else if (t == pdf_literal_node) {
+    } else if (t == pdf_literal_node || t == pdf_late_literal_node) {
         /*tex The |string| key is obsolete. */
         if (lua_key_eq(s, mode)) {
             lua_pushinteger(L, pdf_literal_mode(n));
@@ -4520,7 +4526,7 @@
         } else {
             lua_pushnil(L);
         }
-    } else if (t == special_node) {
+    } else if (t == special_node || t == late_special_node) {
         if (lua_key_eq(s, data)) {
             get_special_direct_value(L,n);
         } else {
@@ -5215,7 +5221,7 @@
         } else {
             lua_pushnil(L);
         }
-    } else if (t == pdf_literal_node) {
+    } else if (t == pdf_literal_node || t == pdf_late_literal_node) {
         /*tex The |string| key is obsolete. */
         if (lua_key_eq(s, mode)) {
             lua_pushinteger(L, pdf_literal_mode(n));
@@ -5300,7 +5306,7 @@
         } else {
             lua_pushnil(L);
         }
-    } else if (t == special_node) {
+    } else if (t == special_node || t == late_special_node) {
         if (lua_key_eq(s, data)) {
             get_special_direct_value(L,n);
         } else {
@@ -6580,7 +6586,7 @@
 {
     int t = subtype(n);
 
-    if (t == pdf_literal_node) {
+    if (t == pdf_literal_node || t == pdf_late_literal_node) {
         /*tex The |string| key is obsolete. */
         if (lua_key_eq(s, mode)) {
             pdf_literal_mode(n) = (quarterword) lua_tointeger(L, 3);
@@ -6772,7 +6778,7 @@
         } else {
             return nodelib_cantset(L, n, s);
         }
-    } else if (t == special_node) {
+    } else if (t == special_node || t == late_special_node) {
         if (lua_key_eq(s, data)) {
             set_special_direct_value(L,n,3);
         } else {
@@ -7362,7 +7368,7 @@
 static int lua_nodelib_direct_setfield_whatsit(lua_State * L, int n, const char *s)
 {
     int t = subtype(n);
-    if (t == pdf_literal_node) {
+    if (t == pdf_literal_node || t == pdf_late_literal_node) {
         /*tex The |string| key is obsolete. */
         if (lua_key_eq(s, mode)) {
             pdf_literal_mode(n) = (quarterword) lua_tointeger(L, 3);
@@ -7527,7 +7533,7 @@
         } else {
             return nodelib_cantset(L, n, s);
         }
-    } else if (t == special_node) {
+    } else if (t == special_node || t == late_special_node) {
         if (lua_key_eq(s, data)) {
             set_special_direct_value(L, n, 3);
         } else {

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/ltexlib.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/ltexlib.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/ltexlib.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -1790,13 +1790,12 @@
                 }
             } else if (is_toks_assign(cur_cmd1)) {
                 if (lua_type(L,i) == LUA_TSTRING) {
-                    j = tokenlist_from_lua(L);  /* uses stack -1 */
+                    j = tokenlist_from_lua(L, -1);  /* uses stack -1 */
                     assign_internal_value((isglobal ? 4 : 0), equiv(cur_cs1), j);
 
                 } else {
                     luaL_error(L, "unsupported value type");
                 }
-
             } else if (lua_istable(L, (i - 2))) {
                 /*
                     people may want to add keys that are also primitives |tex.wd| for example)

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/luanode.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/luanode.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/luanode.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -418,7 +418,10 @@
 void show_pdf_literal(pointer p)
 {
     int t = pdf_literal_type(p);
-    tprint_esc("pdfliteral");
+    if (subtype(p)==pdf_late_literal_node)
+        tprint_esc("pdflateliteral");
+    else 
+        tprint_esc("pdfliteral");
     switch (pdf_literal_mode(p)) {
         case set_origin:
             tprint(" origin");

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/luatex-api.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/luatex-api.h	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/luatex-api.h	2023-02-17 23:30:17 UTC (rev 65866)
@@ -162,7 +162,8 @@
 extern int luaopen_token(lua_State * L);
 extern void tokenlist_to_lua(lua_State * L, int p);
 extern void tokenlist_to_luastring(lua_State * L, int p);
-extern int tokenlist_from_lua(lua_State * L);
+extern int tokenlist_from_lua(lua_State * L, int i);
+extern int token_from_lua(lua_State * L);
 
 extern void lua_nodelib_push(lua_State * L);
 extern int nodelib_getdir(lua_State * L, int n);
@@ -1017,6 +1018,7 @@
 make_lua_key(pdf_link_data);\
 make_lua_key(pdf_link_state);\
 make_lua_key(pdf_literal);\
+make_lua_key(pdf_late_literal);\
 make_lua_key(pdf_refobj);\
 make_lua_key(pdf_restore);\
 make_lua_key(pdf_save);\
@@ -1125,6 +1127,7 @@
 make_lua_key(span);\
 make_lua_key(spec);\
 make_lua_key(special);\
+make_lua_key(late_special);\
 make_lua_key(split_discards_head);\
 make_lua_key(split_insert);\
 make_lua_key(split_keep);\
@@ -1721,6 +1724,7 @@
 init_lua_key(pdf_link_data);\
 init_lua_key(pdf_link_state);\
 init_lua_key(pdf_literal);\
+init_lua_key(pdf_late_literal);\
 init_lua_key(pdf_refobj);\
 init_lua_key(pdf_restore);\
 init_lua_key(pdf_save);\
@@ -1825,6 +1829,7 @@
 init_lua_key(span);\
 init_lua_key(spec);\
 init_lua_key(special);\
+init_lua_key(late_special);\
 init_lua_key(split_discards_head);\
 init_lua_key(split_insert);\
 init_lua_key(split_keep);\
@@ -2492,6 +2497,7 @@
 use_lua_key(pdf_link_data);
 use_lua_key(pdf_link_state);
 use_lua_key(pdf_literal);
+use_lua_key(pdf_late_literal);
 use_lua_key(pdf_refobj);
 use_lua_key(pdf_restore);
 use_lua_key(pdf_save);
@@ -2600,6 +2606,7 @@
 use_lua_key(span);
 use_lua_key(spec);
 use_lua_key(special);
+use_lua_key(late_special);
 use_lua_key(split_discards_head);
 use_lua_key(split_insert);
 use_lua_key(split_keep);

Modified: trunk/Build/source/texk/web2c/luatexdir/lua/luatoken.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/lua/luatoken.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/lua/luatoken.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -386,30 +386,6 @@
 }
 */
 
-static int token_from_lua(lua_State * L)
-{
-    int cmd, chr;
-    int cs = 0;
-    size_t len = lua_rawlen(L, -1);
-    if (len == 3 || len == 2) {
-        lua_rawgeti(L, -1, 1);
-        cmd = (int) lua_tointeger(L, -1);
-        lua_rawgeti(L, -2, 2);
-        chr = (int) lua_tointeger(L, -1);
-        if (len == 3) {
-            lua_rawgeti(L, -3, 3);
-            cs = (int) lua_tointeger(L, -1);
-        }
-        lua_pop(L, (int) len);
-        if (cs == 0) {
-            return token_val(cmd, chr);
-        } else {
-            return cs_token_flag + cs;
-        }
-    }
-    return -1;
-}
-
 /*
 static int get_cur_cs(lua_State * L)
 {
@@ -482,7 +458,7 @@
     free(s);
 }
 
-int tokenlist_from_lua(lua_State * L)
+int tokenlist_from_lua(lua_State * L, int index)
 {
     const char *s;
     int tok, t;
@@ -492,12 +468,12 @@
     token_info(r) = 0;
     token_link(r) = null;
     p = r;
-    t = lua_type(L, -1);
+    t = lua_type(L, index);
     if (t == LUA_TTABLE) {
-        j = lua_rawlen(L, -1);
+        j = lua_rawlen(L, index);
         if (j > 0) {
             for (i = 1; i <= j; i++) {
-                lua_rawgeti(L, -1, (int) i);
+                lua_rawgeti(L, index, (int) i);
                 tok = token_from_lua(L);
                 if (tok >= 0) {
                     store_new_token(tok);
@@ -507,7 +483,7 @@
         }
         return r;
     } else if (t == LUA_TSTRING) {
-        s = lua_tolstring(L, -1, &j);
+        s = lua_tolstring(L, index, &j);
         for (i = 0; i < j; i++) {
             if (s[i] == 32) {
                 tok = token_val(10, s[i]);

Modified: trunk/Build/source/texk/web2c/luatexdir/luatex_svnversion.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/luatex_svnversion.h	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/luatex_svnversion.h	2023-02-17 23:30:17 UTC (rev 65866)
@@ -1,4 +1,4 @@
 #ifndef luatex_svn_revision_h
 #define luatex_svn_revision_h
-#define luatex_svn_revision 7558
+#define luatex_svn_revision 7559
 #endif

Modified: trunk/Build/source/texk/web2c/luatexdir/pdf/pdflistout.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/pdf/pdflistout.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/pdf/pdflistout.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -274,6 +274,7 @@
     if (output_mode_used == OMODE_PDF) {
         switch (subtype(p)) {
             case pdf_literal_node:
+            case pdf_late_literal_node:
             case pdf_save_node:
             case pdf_restore_node:
             case pdf_setmatrix_node:
@@ -730,6 +731,7 @@
                                 wrapup_leader(p);
                                 break;
                             case special_node:
+                            case late_special_node:
                                 /*tex |pdf_special(pdf, p)| */
                             case late_lua_node:
                                 /*tex |late_lua(pdf, p)| */
@@ -1103,6 +1105,7 @@
                             wrapup_leader(p);
                             break;
                         case special_node:
+                        case late_special_node:
                             /*tex |pdf_special(pdf, p)|; */
                         case late_lua_node:
                             /*tex |late_lua(pdf, p)|; */

Modified: trunk/Build/source/texk/web2c/luatexdir/pdf/pdfliteral.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/pdf/pdfliteral.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/pdf/pdfliteral.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -21,16 +21,32 @@
 
 #include "ptexlib.h"
 
+/* 
+    With these (new) late nodes we operate on write_tokens which happens to be 
+    equivalent to pdf_literal_data so it is somewhat confusing but cleaning this 
+    up now is asking for troubles. 
+*/
+
 void pdf_special(PDF pdf, halfword p)
 {
     int old_setting = selector;
     str_number s;
+    halfword h; 
+    if (subtype(p) == late_special_node) {
+        expand_macros_in_tokenlist(pdf_literal_data(p));
+        h = token_link(def_ref); 
+    } else { 
+        h = token_link(pdf_literal_data(p));
+    }
     selector = new_string;
-    show_token_list(token_link(write_tokens(p)), null, -1);
+    show_token_list(h, null, -1);
     selector = old_setting;
     s = make_string();
     pdf_literal(pdf, s, scan_special, true);
     flush_str(s);
+    if (subtype(p) == late_special_node) {
+        flush_list(def_ref);
+    }
 }
 
 /*tex
@@ -47,15 +63,25 @@
     int old_setting;
     str_number s;
     int t = pdf_literal_type(p);
+    halfword h; 
     pdfstructure *ps = pdf->pstruct;
     if (t == normal) {
         old_setting = selector;
+        if (subtype(p) == pdf_late_literal_node) {
+            expand_macros_in_tokenlist(pdf_literal_data(p));
+            h = token_link(def_ref); 
+        } else { 
+            h = token_link(pdf_literal_data(p));
+        }
         selector = new_string;
-        show_token_list(token_link(pdf_literal_data(p)), null, -1);
+        show_token_list(h, null, -1);
         selector = old_setting;
         s = make_string();
         pdf_literal(pdf, s, pdf_literal_mode(p), false);
         flush_str(s);
+        if (subtype(p) == pdf_late_literal_node) {
+            flush_list(def_ref);
+        }
     } else if (t == lua_refid_literal) {
         switch (pdf_literal_mode(p)) {
             case set_origin:

Modified: trunk/Build/source/texk/web2c/luatexdir/pdf/pdftables.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/pdf/pdftables.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/pdf/pdftables.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -231,6 +231,8 @@
     passed to |set_rect_dimens| and have control per feature, maybe even under parameter control.
 */
 
+halfword calculate_width_to_endlink(halfword p, halfword this_box, halfword *leftskip, halfword *rightskip);
+
 void set_rect_dimens(PDF pdf, halfword p, halfword parent_box, scaledpos cur, scaled_whd alt_rule)
 {
     /*tex 

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/backend.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/backend.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/backend.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -32,7 +32,10 @@
     p->node_fu[rule_node] = &pdf_place_rule;
     p->node_fu[glyph_node] = &pdf_place_glyph;
     p->whatsit_fu[special_node] = &pdf_special;
+    p->whatsit_fu[late_special_node] = &pdf_special;
+    p->whatsit_fu[late_lua_node] = &late_lua;
     p->whatsit_fu[pdf_literal_node] = &pdf_out_literal;
+    p->whatsit_fu[pdf_late_literal_node] = &pdf_out_literal;
     p->whatsit_fu[pdf_refobj_node] = &pdf_ref_obj;
     p->whatsit_fu[pdf_annot_node] = &do_annot;
     p->whatsit_fu[pdf_start_link_node] = &do_link;
@@ -40,7 +43,6 @@
     p->whatsit_fu[pdf_dest_node] = &do_dest;
     p->whatsit_fu[pdf_thread_node] = &do_thread;
     p->whatsit_fu[pdf_end_thread_node] = &end_thread;
-    p->whatsit_fu[late_lua_node] = &late_lua;
     p->whatsit_fu[pdf_colorstack_node] = &pdf_out_colorstack;
     p->whatsit_fu[pdf_setmatrix_node] = &pdf_out_setmatrix;
     p->whatsit_fu[pdf_save_node] = &pdf_out_save;
@@ -63,6 +65,7 @@
     p->node_fu[rule_node] = &dvi_place_rule;
     p->node_fu[glyph_node] = &dvi_place_glyph;
     p->whatsit_fu[special_node] = &dvi_special;
+    p->whatsit_fu[late_special_node] = &dvi_special;
     p->whatsit_fu[late_lua_node] = &late_lua;
     p->control_fu[backend_control_push_list] = &dvi_push_list;
     p->control_fu[backend_control_pop_list] = &dvi_pop_list;

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/commands.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/commands.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/commands.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -714,7 +714,8 @@
     primitive_tex("special", extension_cmd, special_code, 0);
     cs_text(frozen_special) = maketexstring("special");
     eqtb[frozen_special] = eqtb[cur_val];
-    primitive_tex("immediate", extension_cmd, immediate_code, 0);
+    primitive_tex("immediate", extension_cmd, reserved_immediate_code, 0);
+    primitive_tex("deferred", extension_cmd, reserved_deferred_code, 0);
     primitive_luatex("localinterlinepenalty", assign_int_cmd, int_base + local_inter_line_penalty_code, int_base);
     primitive_luatex("localbrokenpenalty", assign_int_cmd, int_base + local_broken_penalty_code, int_base);
     primitive_luatex("pagedir", assign_dir_cmd, int_base + page_direction_code, dir_base);

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/commands.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/commands.h	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/commands.h	2023-02-17 23:30:17 UTC (rev 65866)
@@ -352,7 +352,8 @@
     gp_code_base = 7
 } font_codes ;
 
-#  define immediate_code 4      /* command modifier for \.{\\immediate} */
+#  define immediate_code 4   /* reserved_immediate_code */  /* command modifier for \.{\\immediate} */
+#  define deferred_code  5   /* reserved_deferred_code  */  /* command modifier for \.{\\deferred} */
 
 extern void initialize_commands(void);
 extern void initialize_etex_commands(void);

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/extensions.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/extensions.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/extensions.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -116,38 +116,60 @@
 int last_saved_box_index ;
 scaledpos last_position = { 0, 0 };
 
-static void do_extension_dvi(int immediate)
+static void do_extension_dvi_literal(int deferred)
 {
+    new_whatsit(deferred ? late_special_node : special_node);
+    write_stream(tail) = null;
+    scan_toks(false, ! deferred);
+    write_tokens(tail) = def_ref;
+}
+
+static void do_extension_dvi(int immediate, int deferred)
+{
     if (scan_keyword("literal")) {
-        new_whatsit(special_node);
-        write_stream(tail) = null;
-        scan_toks(false, true);
-        write_tokens(tail) = def_ref;
+        /* immediate is the default here */
+        if (scan_keyword("shipout")) { 
+            deferred = 1;
+        }
+        do_extension_dvi_literal(deferred);
+    } else if (scan_keyword("lateliteral")) {
+        do_extension_dvi_literal(1);
     } else {
         tex_error("unexpected use of \\dviextension",null);
     }
 }
 
-static void do_extension_pdf(int immediate)
+static void do_extension_pdf_literal(int deferred)
 {
+    new_whatsit(deferred ? pdf_late_literal_node : pdf_literal_node);
+    if (scan_keyword("direct"))
+        set_pdf_literal_mode(tail, direct_always);
+    else if (scan_keyword("page"))
+        set_pdf_literal_mode(tail, direct_page);
+    else if (scan_keyword("text"))
+        set_pdf_literal_mode(tail, direct_text);
+    else if (scan_keyword("raw"))
+        set_pdf_literal_mode(tail, direct_raw);
+    else if (scan_keyword("origin"))
+        set_pdf_literal_mode(tail, set_origin);
+    else
+        set_pdf_literal_mode(tail, set_origin);
+    scan_toks(false, ! deferred);
+    set_pdf_literal_type(tail, normal);
+    set_pdf_literal_data(tail, def_ref);
+}
+
+static void do_extension_pdf(int immediate, int deferred)
+{
     int i;
     if (scan_keyword("literal")) {
-        new_whatsit(pdf_literal_node);
-        if (scan_keyword("direct"))
-            set_pdf_literal_mode(tail, direct_always);
-        else if (scan_keyword("page"))
-            set_pdf_literal_mode(tail, direct_page);
-        else if (scan_keyword("text"))
-            set_pdf_literal_mode(tail, direct_text);
-        else if (scan_keyword("raw"))
-            set_pdf_literal_mode(tail, direct_raw);
-        else if (scan_keyword("origin"))
-            set_pdf_literal_mode(tail, set_origin);
-        else
-            set_pdf_literal_mode(tail, set_origin);
-        scan_toks(false, true);
-        set_pdf_literal_type(tail, normal);
-        set_pdf_literal_data(tail, def_ref);
+        /* immediate is the default here */
+        if (scan_keyword("shipout")) { 
+            deferred = 1;
+        }
+        do_extension_pdf_literal(deferred);
+    } else if (scan_keyword("lateliteral")) {
+        do_extension_pdf_literal(1);
     } else if (scan_keyword("dest")) {
         scan_pdfdest(static_pdf);
     } else if (scan_keyword("annot")) {
@@ -341,7 +363,7 @@
 
     The extensions are backend related. The next subroutine uses |cur_chr| to
     decide what sort of whatsit is involved, and also inserts a |write_stream|
-    number.
+    number. 
 
 */
 
@@ -363,10 +385,17 @@
     write_stream(tail) = cur_val;
 }
 
-void do_extension(int immediate)
+/* 
+    Specials and literals are immediate by default but can be deferred as well. We have two prefixes that 
+    don't accumulate but trigger a next token pickup. Writes and resources are deferred by default. The 
+    (wish for a) shipout key scanner comes from similar features in the other engines. So, we're 
+    compatible but also conceptually a bit more consistent by introducing a |\deferred| prefix. 
+*/
+
+void do_extension(int immediate, int deferred)
 {
     /*tex All-purpose pointers. */
-    halfword k,p;
+    halfword k, p;
     if (cur_cmd == extension_cmd) {
         /*tex These have their own range starting at 0. */
         switch (cur_chr) {
@@ -431,18 +460,26 @@
                 /*tex
 
                     When `\.{\\special\{...\}}' appears, we expand the macros in
-                    the token list as in \.{\\xdef} and \.{\\mark}.
+                    the token list as in \.{\\xdef} and \.{\\mark}.  When marked with \.{shipout}, we keep
+                    tokens unexpanded for now.
 
                 */
-                new_whatsit(special_node);
+                if (scan_keyword("shipout")) {
+                    deferred = 1;
+                } 
+                new_whatsit(deferred ? late_special_node : special_node);
                 write_stream(tail) = null;
-                p = scan_toks(false, true);
+                p = scan_toks(false, ! deferred);
                 write_tokens(tail) = def_ref;
                 break;
-            case immediate_code:
+            case reserved_immediate_code:
                 get_x_token();
-                do_extension(1);
+                do_extension(1, 0);
                 break;
+            case reserved_deferred_code:
+                get_x_token();
+                do_extension(0, 1);
+                break;
             case end_local_code:
                 if (tracing_nesting_par > 2) {
                     local_control_message("leaving token scanner");
@@ -467,11 +504,11 @@
             /*tex Backend extensions have their own range starting at 32. */
             case dvi_extension_code:
                 if (get_o_mode() == OMODE_DVI)
-                    do_extension_dvi(immediate);
+                    do_extension_dvi(immediate, deferred);
                 break;
             case pdf_extension_code:
                 if (get_o_mode() == OMODE_PDF)
-                    do_extension_pdf(immediate);
+                    do_extension_pdf(immediate, deferred);
                 break;
             /*tex Done. */
             default:
@@ -523,7 +560,7 @@
     token_link(q) = r;
     token_info(r) = end_write_token;
     begin_token_list(q, inserted);
-    begin_token_list(write_tokens(p), write_text);
+    begin_token_list(p, write_text);
     q = get_avail();
     token_info(q) = left_brace_token + '{';
     begin_token_list(q, inserted);
@@ -573,7 +610,7 @@
     lstring *s = NULL;
     int callback_id;
     int lua_retval;
-    expand_macros_in_tokenlist(p);
+    expand_macros_in_tokenlist(write_tokens(p));
     old_setting = selector;
     j = write_stream(p);
     if (file_can_be_written(j)) {

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/extensions.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/extensions.h	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/extensions.h	2023-02-17 23:30:17 UTC (rev 65866)
@@ -42,7 +42,7 @@
 
 extern halfword write_loc;
 
-extern void do_extension(int immediate);
+extern void do_extension(int immediate, int deferred);
 
 /*
 User defined whatsits can be inserted into node lists to pass data
@@ -130,6 +130,7 @@
     close_code,
     reserved_extension_code, // 3: we moved special below immediate //
     reserved_immediate_code, // 4: same number as main codes, expected value //
+    reserved_deferred_code,
     /* backend specific implementations */
     special_code,
     save_box_resource_code,

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/maincontrol.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/maincontrol.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/maincontrol.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -624,7 +624,7 @@
 }
 
 static void run_extension (void) {
-    do_extension(0);
+    do_extension(0, 0);
 }
 
 static void run_normal (void) {

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.c
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.c	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.c	2023-02-17 23:30:17 UTC (rev 65866)
@@ -961,6 +961,7 @@
     { write_node,            write_node_size,          NULL, node_fields_whatsit_write,            NULL, -1, 0 },
     { close_node,            close_node_size,          NULL, node_fields_whatsit_close,            NULL, -1, 0 },
     { special_node,          special_node_size,        NULL, node_fields_whatsit_special,          NULL, -1, 0 },
+    { late_special_node,     special_node_size,        NULL, node_fields_whatsit_special,          NULL, -1, 0 },
     { fake_node,             fake_node_size,           NULL, NULL,                                 NULL, -1, 0 },
     { fake_node,             fake_node_size,           NULL, NULL,                                 NULL, -1, 0 },
     { save_pos_node,         save_pos_node_size,       NULL, node_fields_whatsit_save_pos,         NULL, -1, 0 },
@@ -972,7 +973,6 @@
     { fake_node,             fake_node_size,           NULL, NULL,                                 NULL, -1, 0 },
     { fake_node,             fake_node_size,           NULL, NULL,                                 NULL, -1, 0 },
     { fake_node,             fake_node_size,           NULL, NULL,                                 NULL, -1, 0 },
-    { fake_node,             fake_node_size,           NULL, NULL,                                 NULL, -1, 0 },
 
     /*tex Here starts the \DVI\ backend section, todo: a separate list. */
 
@@ -980,7 +980,8 @@
 
     /*tex Here starts the \PDF\ backend section, todo: a separate list.  */
 
-    { pdf_literal_node,      write_node_size,          NULL, node_fields_whatsit_pdf_literal,      NULL, -1, 0 },
+    { pdf_literal_node,      literal_node_size,        NULL, node_fields_whatsit_pdf_literal,      NULL, -1, 0 },
+    { pdf_late_literal_node, literal_node_size,        NULL, node_fields_whatsit_pdf_literal,      NULL, -1, 0 },
     { pdf_refobj_node,       pdf_refobj_node_size,     NULL, node_fields_whatsit_pdf_refobj,       NULL, -1, 0 },
     { pdf_annot_node,        pdf_annot_node_size,      NULL, node_fields_whatsit_pdf_annot,        NULL, -1, 0 },
     { pdf_start_link_node,   pdf_annot_node_size,      NULL, node_fields_whatsit_pdf_start_link,   NULL, -1, 0 },
@@ -1009,6 +1010,7 @@
     init_node_key(whatsit_node_data, write_node,        write)
     init_node_key(whatsit_node_data, close_node,        close)
     init_node_key(whatsit_node_data, special_node,      special)
+    init_node_key(whatsit_node_data, late_special_node, late_special)
     init_node_key(whatsit_node_data, save_pos_node,     save_pos)
     init_node_key(whatsit_node_data, late_lua_node,     late_lua)
     init_node_key(whatsit_node_data, user_defined_node, user_defined)
@@ -1050,6 +1052,7 @@
     init_field_nop(node_fields_whatsit_write, 3);
 
     init_node_key(whatsit_node_data, pdf_literal_node,     pdf_literal)
+    init_node_key(whatsit_node_data, pdf_late_literal_node,pdf_late_literal)
     init_node_key(whatsit_node_data, pdf_refobj_node,      pdf_refobj)
     init_node_key(whatsit_node_data, pdf_annot_node,       pdf_annot)
     init_node_key(whatsit_node_data, pdf_start_link_node,  pdf_start_link)
@@ -1942,6 +1945,7 @@
     switch (subtype(p)) {
         case write_node:
         case special_node:
+        case late_special_node:
             add_token_ref(write_tokens(p));
             break;
         case late_lua_node:
@@ -1980,6 +1984,7 @@
 {
     switch(subtype(p)) {
         case pdf_literal_node:
+        case pdf_late_literal_node:
             copy_pdf_literal(r, p);
             break;
         case pdf_colorstack_node:
@@ -2201,6 +2206,7 @@
         case save_pos_node:
             break;
         case special_node:
+        case late_special_node:
             delete_token_ref(write_tokens(p));
             break;
         case late_lua_node:
@@ -2257,6 +2263,7 @@
         case pdf_end_thread_node:
             break;
         case pdf_literal_node:
+        case pdf_late_literal_node:
             free_pdf_literal(p);
             break;
         case pdf_colorstack_node:
@@ -2481,6 +2488,7 @@
     switch (subtype(p)) {
         /*tex Frontend code. */
         case special_node:
+        case late_special_node:
             check_token_ref(p);
             break;
         case user_defined_node:
@@ -2519,6 +2527,7 @@
 {
     switch (subtype(p)) {
         case pdf_literal_node:
+        case pdf_late_literal_node:
             if (pdf_literal_type(p) == normal)
                 check_token_ref(p);
             break;
@@ -3475,6 +3484,10 @@
             tprint_esc("special");
             print_mark(write_tokens(p));
             break;
+        case late_special_node:
+            tprint_esc("latespecial");
+            print_mark(write_tokens(p));
+            break;
         case late_lua_node:
             show_late_lua(p);
             break;
@@ -3518,6 +3531,7 @@
 {
     switch (subtype(p)) {
         case pdf_literal_node:
+        case pdf_late_literal_node:
             show_pdf_literal(p);
             break;
         case pdf_colorstack_node:

Modified: trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.h
===================================================================
--- trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.h	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Build/source/texk/web2c/luatexdir/tex/texnodes.h	2023-02-17 23:30:17 UTC (rev 65866)
@@ -710,6 +710,7 @@
     write_node,
     close_node,
     special_node,
+    late_special_node,          /* done a la pdftex, more natural is to use special with a flag instead */
     use_box_resource_node,
     use_image_resource_node,
     save_pos_node,
@@ -719,6 +720,7 @@
     dvi_literal_node = 15,
     /* pdf backend */
     pdf_literal_node = 16,
+    pdf_late_literal_node,   /* done a la pdftex, more natural is to use special with a flag instead */
     pdf_refobj_node,
     pdf_annot_node,
     pdf_start_link_node,
@@ -737,16 +739,19 @@
     pdf_link_state_node,
 } whatsit_types;
 
-#  define first_common_whatsit      0
+#  define first_common_whatsit      open_node
 #  define last_common_whatsit       user_defined_node
-#  define backend_first_dvi_whatsit 15
-#  define backend_last_dvi_whatsit  15
-#  define backend_first_pdf_whatsit 16
-#  define backend_last_pdf_whatsit  32
+#  define backend_first_dvi_whatsit dvi_literal_node
+#  define backend_last_dvi_whatsit  dvi_literal_node 
+#  define backend_first_pdf_whatsit pdf_literal_node 
+#  define backend_last_pdf_whatsit  pdf_link_state_node  /* Don't forget to adapt this when extending! */
 
-/* add some slack for the future */
+/* 
+    We add quite some slack for future usage because who knows how we need to be compatible with 
+    other engines. 
+*/
 
-#  define MAX_WHATSIT_TYPE 34
+#  define MAX_WHATSIT_TYPE 48
 
 #  define known_whatsit_type(i) ( \
     (i >= first_common_whatsit      && i <= last_common_whatsit) || \
@@ -810,8 +815,6 @@
 #  define boundary_node_size 3
 #  define boundary_value(a) vinfo((a)+2)
 
-#  define special_node_size 3
-
 typedef enum {
     normal_dir = 0,
     cancel_dir,
@@ -826,10 +829,14 @@
 #  define dir_cur_v(a)     vlink((a)+4)
 
 #  define write_node_size 3
+#  define literal_node_size 3
+#  define special_node_size 3
 #  define close_node_size 3
 #  define write_tokens(a)  vlink(a+2)
 #  define write_stream(a)  vinfo(a+2)
 
+#  define special_tokens write_tokens
+
 #  define open_node_size 4
 #  define open_name(a)   vlink((a)+2)
 #  define open_area(a)   vinfo((a)+3)

Modified: trunk/Master/texmf-dist/doc/luatex/base/luatex-modifications.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/base/luatex-modifications.tex	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Master/texmf-dist/doc/luatex/base/luatex-modifications.tex	2023-02-17 23:30:17 UTC (rev 65866)
@@ -600,6 +600,7 @@
 
 \starttyping
 \protected\def\pdfliteral             {\pdfextension literal}
+\protected\def\pdflateliteral         {\pdfextension lateliteral}
 \protected\def\pdfcolorstack          {\pdfextension colorstack}
 \protected\def\pdfsetmatrix           {\pdfextension setmatrix}
 \protected\def\pdfsave                {\pdfextension save\relax}
@@ -747,11 +748,12 @@
 
 Although we started from a merge of \PDFTEX\ and \ALEPH, by now the code base as
 well as functionality has diverted from those parents. Here we show the options
-that can be passed to the extensions.
+that can be passed to the extensions. The \type {shipout} option is a compatibility
+feature. Instead one can use the \type {deferred} prefix.
 
 \starttexsyntax
 \pdfextension literal
-    [ direct | page | raw ] { tokens }
+    [shipout] [ direct | page | raw ] { tokens }
 \stoptexsyntax
 
 \starttexsyntax

Modified: trunk/Master/texmf-dist/doc/luatex/base/luatex-nodes.tex
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/base/luatex-nodes.tex	2023-02-17 22:52:48 UTC (rev 65865)
+++ trunk/Master/texmf-dist/doc/luatex/base/luatex-nodes.tex	2023-02-17 23:30:17 UTC (rev 65866)
@@ -1,4 +1,4 @@
-% language=uk
+% language=us engine=luatex runpath=texruns:manuals/luatex
 
 \environment luatex-style
 
@@ -893,7 +893,6 @@
 When a function is used, it gets called with as first argument the node that triggers
 the call.
 
-
 \stopsection
 
 \startsection[title={\DVI\ backend whatsits}]
@@ -915,7 +914,7 @@
 
 \startsection[title={\PDF\ backend whatsits}]
 
-\subsection{\whs {pdf_literal}}
+\subsection{\whs {pdf_literal} and \whs {pdf_late_literal}}
 
 \starttabulate[|l|l|p|]
 \DB field        \BC type   \BC explanation \NC \NR
@@ -1020,10 +1019,13 @@
 \TB
 \NC \type{action_type} \NC number           \NC the kind of action involved \NC \NR
 \NC \type{action_id}   \NC number or string \NC token list reference or string \NC \NR
+%NC \type{named_id}    \NC number           \NC the index of the destination \NC \NR
+% a strange key but needed for latex; a probably downward incompable patch instead of a fix
 \NC \type{named_id}    \NC number           \NC are \type {dest_id} and \type {struct_id} string values? \NC \NR
 \NC \type{file}        \NC string           \NC the target filename \NC \NR
 \NC \type{new_window}  \NC number           \NC the window state of the target \NC \NR
 \NC \type{data}        \NC string           \NC the name of the destination \NC \NR
+% needed for latex and therefore equivalent to pdftex
 \NC \type{struct_id}   \NC nil              \NC the action does not reference a structure destination \NC \NR
 \NC                    \NC number           \NC id of the referenced structure destination \NC \NR
 \NC                    \NC string           \NC name of the referenced structure destination \NC \NR

Modified: trunk/Master/texmf-dist/doc/luatex/base/luatex.pdf
===================================================================
(Binary files differ)



More information about the tex-live-commits mailing list.