pdftex[890] branches/stable: shipout keyword for delayed expansion of

commits+karl at tug.org commits+karl at tug.org
Sat Jan 21 03:05:59 CET 2023


Revision: 890
          http://tug.org/svn/pdftex?view=revision&revision=890
Author:   karl
Date:     2023-01-21 03:05:59 +0100 (Sat, 21 Jan 2023)
Log Message:
-----------
shipout keyword for delayed expansion of \special and \literal, from phelype

Modified Paths:
--------------
    branches/stable/doc/manual/ChangeLog
    branches/stable/doc/manual/pdftex-t.tex
    branches/stable/doc/manual/pdftex-w.pdf
    branches/stable/source/src/texk/web2c/pdftexdir/ChangeLog
    branches/stable/source/src/texk/web2c/pdftexdir/NEWS
    branches/stable/source/src/texk/web2c/pdftexdir/pdftex.web
    branches/stable/tests/Common.mak

Added Paths:
-----------
    branches/stable/tests/27-late-shipout/
    branches/stable/tests/27-late-shipout/Makefile
    branches/stable/tests/27-late-shipout/test-shipout.pdf
    branches/stable/tests/27-late-shipout/test-shipout.tex
    branches/stable/tests/Makefile

Modified: branches/stable/doc/manual/ChangeLog
===================================================================
--- branches/stable/doc/manual/ChangeLog	2023-01-20 16:39:45 UTC (rev 889)
+++ branches/stable/doc/manual/ChangeLog	2023-01-21 02:05:59 UTC (rev 890)
@@ -1,3 +1,9 @@
+2023-01-20  Karl Berry  <karl at freefriends.org>
+
+	* pdftex-t.tex (\pdfliteral, \special): document new shipout keyword.
+	From Phelype Oleinik <phe.h.o1 at gmail.com>, 16 Jan 2023 20:51:33,
+	mail to latex-team + karl.
+
 2022-12-22  Karl Berry  <karl at freefriends.org>
 
 	* pdftex-t.tex (\pdfomitprocset): document.

Modified: branches/stable/doc/manual/pdftex-t.tex
===================================================================
--- branches/stable/doc/manual/pdftex-t.tex	2023-01-20 16:39:45 UTC (rev 889)
+++ branches/stable/doc/manual/pdftex-t.tex	2023-01-21 02:05:59 UTC (rev 890)
@@ -40,7 +40,8 @@
 
 \svnscan $Id$
 
-\def\currentpdftex{1.40.22}
+\def\versplit#1#2#3{#1.#2#3}% 140 -> 1.40
+\def\currentpdftex{\expandafter\versplit\the\pdftexversion.\pdftexrevision}
 
 %***********************************************************************
 
@@ -1575,11 +1576,6 @@
 }
 
 \Syntax{
-\Something{pdfliteral spec} \Means %
-  \Literal{direct} \Or \Literal{page}
-}
-
-\Syntax{
 \Something{pdfspecial spec} \Means %
   \Lbrace \Optional{\Something{pdfspecial id} %
   \Optional{\Something{pdfspecial modifier}}} %
@@ -3445,7 +3441,7 @@
 annotations have internally hard||coded absolute positions. Again this
 is for the sake of speed optimization. The main disadvantage is that these
 annotations do {\em not} obey transformations issued by \type
-{\pdfliteral}'s.
+{\pdfliteral}s.
 
 The \Something{action spec} specifies the action that should be
 performed when the hyperlink is activated, one of (see the syntax
@@ -3648,33 +3644,39 @@
 \subsection{Literals and specials}
 
 \pdftexprimitive{\Syntax{\Tex{\pdfliteral}
-  \Optional{\Something{pdfliteral spec}}
+  \Optional{\Literal{shipout}}
+  \Optional{\Literal{direct} \Or \Literal{page}}
   \Something{general text}
   \Modelist{h, v, m}
   }}
 \bookmark{\tex{pdfliteral}}
 
-Like \type{\special} in normal \TEX, this command inserts raw
-\PDF\ code into the output. This allows support of color and text
-transformation. This primitive is heavily used in the \METAPOST\
-inclusion macros. Normally \PDFTEX\ ends a text section in the \PDF\
-output and sets the transformation matrix to the current location on the
-page before inserting \Something{general text}\unkern, however this can be
-turned off by giving the optional keyword \Literal{direct}. This command
-appends a whatsit node to the list being built. \Something{general text}
-is expanded when the whatsit node is created and not when it is shipped
-out, as with \type{\special}.
+Analogous to \type{\special} in the original \TEX, this command inserts
+raw \PDF\ code into the output, appending a whatsit node to the list
+being built. This allows support of color and text transformation, among
+other things.
 
-Starting with version 1.30.0, \PDFTEX\ allows to use a new keyword
-\type{page} instead of \type{direct}. Both modify the default behavior
-of \type{\pdfliteral}, avoiding translation of the coordinates space
-before inserting the literal code. The difference is that the \type{page}
+By default, \Something{general text} is expanded immediately, when the
+whatsit node is created, as with \type{\special}. Starting with version
+1.40.25, the optional keyword \Literal{shipout} can be used to delay
+expansion of \Something{general text} until the whatsit node is shipped
+out, as with non-\type{\immediate} \type{\write}.
+
+Normally, \PDFTEX\ ends a text section in the \PDF\ output and sets the
+transformation matrix to the current location on the page before
+inserting \Something{general text}\unkern; this can be turned off by
+giving the optional keyword \Literal{direct}.
+
+Starting with version 1.30.0, \PDFTEX\ supports the keyword \type{page}
+in addition to \type{direct}. Both modify the default behavior of
+\type{\pdfliteral}, avoiding translation of the coordinate space before
+inserting the literal code. The difference is that the \type{page}
 keyword instructs \PDFTEX\ to close a \type{BT ET} text block before
-inserting anything. It means that the literal code inserted refers to the
-origin (lower||left corner of the page) and can be safely enclosed with
-\type{q Q}. Note, that in most cases using \type{q Q} operators inside
-\type{\pdfliteral} with \type{direct} keyword will produce corrupted
-\PDF\ output, as the \PDF\ standard doesn't allow to do anything like
+inserting anything. This means that the literal code inserted refers to
+the \PDF\ origin (lower-left corner of the page) and can be safely
+enclosed with \type{q Q}. In contrast, using \type{q Q} operators inside
+\type{\pdfliteral} with the \type{direct} keyword will produce corrupted
+\PDF\ output, as the \PDF\ standard doesn't allow doing anything like
 this within a \type{BT ET} block.
 
 % HE: \unkern is a kludge here; wanted to have tight "{pdf:"
@@ -3699,6 +3701,20 @@
 This is equivalent to \Syntax{\Tex{\pdfliteral} \Literal{page} \Lbrace
 \Something{text} \Rbrace}.
 
+\pdftexprimitive{\Syntax{\Tex{\special} \Optional{\Literal{shipout}}
+  \Lbrace\unkern \Something{general text} \Rbrace}}
+\bookmark{\tex{special\ shipout}}
+
+Starting with version 1.40.25, \PDFTEX\ extends the \type{\special}
+primitive to support the optional keyword \Literal{shipout}. This delays
+expansion of \Something{general text} until the page is shipped out, as
+with non-\type{\immediate} \type{\write}. By default, \Something{general
+text} is expanded immediately.
+
+\Syntax{\Tex{\special} \Literal{shipout} \Lbrace \unkern\Literal{pdf:}
+\Something{text} \Rbrace} is equivalent to \Syntax{\Tex{\pdfliteral}
+\Literal{shipout} \Lbrace \Something{text} \Rbrace}.
+
 %***********************************************************************
 
 \subsection{Strings}
@@ -4336,11 +4352,10 @@
 depth is higher than the \type{\tracingstacklevels} value.
 
 The intended use of \type{\tracingstacklevels} is not so much to
-truncate logging as to indicate the expansion levels for detailed
-debugging. Thus normally it would be set to a large number
-(\type{\maxdimen}, say), so that everything is fully logged, with the
-addition of the expansion level indication with the number of dots in
-the prefix.
+truncate logging as to indicate expansion levels for detailed debugging.
+Thus normally it would be set to a large number (\type{\maxdimen}, say),
+so that everything is fully logged, with the addition of the expansion
+level indication with the number of dots in the prefix.
 
 The behavior is the same in all \TeX\ engines except the original \TEX\
 and \eTeX, where \type{\tracingstacklevels} remains undefined.
@@ -4352,8 +4367,8 @@
 If this primitive parameter has a value corresponding to an open output
 stream (which has been opened with \type{\openout}), then any
 \type{\show}, \type{\showthe}, \type{\showbox} or \type{\showlists}
-commands do not write output to the terminal, but instead write to only
-the referenced output stream, as if they were written with
+commands do not write output to the terminal, but instead write to the
+referenced output stream only, as if they were written with
 \type{\immediate\write}.
 
 For example:
@@ -4418,11 +4433,9 @@
 \pdftexprimitive{\Syntax{\Tex{\pdftexrevision} \Whatever{expandable}}}
 \bookmark{\tex{pdftexrevision}}
 
-\def\versplit#1#2#3{#1.#2#3}
-
 Returns the revision number of \PDFTEX, \eg\ for \PDFTEX\ version
-\expandafter\versplit\the\pdftexversion.\pdftexrevision\ (used to produce
-this document), it returns the number {\tt \pdftexrevision}.
+\currentpdftex\ (used to produce this document), it returns the number
+{\tt \pdftexrevision}.
 
 
 \pdftexprimitive{\Syntax{\Tex{\pdftexversion} \Whatever{read||only integer}}}
@@ -4429,8 +4442,8 @@
 \bookmark{\tex{pdftexversion}}
 
 Returns the version of \PDFTEX\ multiplied by 100, \eg\ for \PDFTEX\
-version \expandafter\versplit\the\pdftexversion.\pdftexrevision\ (used to
-produce this document), it returns {\tt \number\pdftexversion}.
+version \currentpdftex\ (used to produce this document), it returns {\tt
+\number\pdftexversion}.
 
 %***********************************************************************
 

Modified: branches/stable/doc/manual/pdftex-w.pdf
===================================================================
(Binary files differ)

Modified: branches/stable/source/src/texk/web2c/pdftexdir/ChangeLog
===================================================================
--- branches/stable/source/src/texk/web2c/pdftexdir/ChangeLog	2023-01-20 16:39:45 UTC (rev 889)
+++ branches/stable/source/src/texk/web2c/pdftexdir/ChangeLog	2023-01-21 02:05:59 UTC (rev 890)
@@ -1,3 +1,17 @@
+2023-01-20  Phelype Oleinik  <phe.h.o1 at gmail.com>
+
+	* pdftex.web: implement shipout keyword for delayed expansion
+	with \pdfliteral and \special, like non-\immediate \write.
+	(pdf_out_literal): check for pdf_lateliteral_node.
+	(pdf_special): check for latespecial_node.
+	(latespecial_node): new @d (4)
+	(pdf_lateliteral_node): new @d (pdftex_first_extension_code + 1).
+	(Implement \.{\\special}),
+	(Implement \.{\\pdfliteral}): look for `shipout' keyword.
+	(scan_pdf_ext_late_toks): new procedure.
+	(Display the whatsit) <latespecial_node, <pdf_lateliteral_node>:
+	new cases.
+
 2022-12-28  Thanh Han The  <hanthethanh at gmail.com>
 
 	* pdftex.web (Display the whatsit...) <pdf_dest_node>: indicate

Modified: branches/stable/source/src/texk/web2c/pdftexdir/NEWS
===================================================================
--- branches/stable/source/src/texk/web2c/pdftexdir/NEWS	2023-01-20 16:39:45 UTC (rev 889)
+++ branches/stable/source/src/texk/web2c/pdftexdir/NEWS	2023-01-21 02:05:59 UTC (rev 890)
@@ -1,5 +1,7 @@
 pdfTeX 3.141592653-2.6-1.40.25
 - changes:
+  - new keyword `shipout' for \special and \pdfliteral, delaying
+    expansion until the node is shipped out, like non-\immediate \write.
   - new primitive \pdfinfoomitdict to omit /Info dictionary completely.
   - new primitive \pdfomitprocset to control omitting /ProcSet array;
     /ProcSet is included if this parameter is negative, or if this

Modified: branches/stable/source/src/texk/web2c/pdftexdir/pdftex.web
===================================================================
--- branches/stable/source/src/texk/web2c/pdftexdir/pdftex.web	2023-01-20 16:39:45 UTC (rev 889)
+++ branches/stable/source/src/texk/web2c/pdftexdir/pdftex.web	2023-01-21 02:05:59 UTC (rev 890)
@@ -1,4 +1,4 @@
-% Copyright 1996-2022 Han Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh,
+% Copyright 1996-2023 Han Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh,
 % <thanh@@pdftex.org>
 
 % This file is part of pdfTeX.
@@ -18501,8 +18501,16 @@
 procedure pdf_out_literal(p:pointer);
 var old_setting:0..max_selector; {holds print |selector|}
     s: str_number;
+    @!q,@!r:pointer; {temporary variables for list manipulation}
+    @!old_mode:integer; {saved |mode|}
 begin
-    old_setting:=selector; selector:=new_string;
+    old_setting:=selector;
+    if subtype(p)=pdf_lateliteral_node then
+      begin @<Expand macros in the token list
+        and make |link(def_ref)| point to the result@>;
+      pdf_literal_data(p):=def_ref;
+      end;
+    selector:=new_string;
     show_token_list(link(pdf_literal_data(p)),null,pool_size-pool_ptr);
     selector:=old_setting;
     s := make_string;
@@ -18618,8 +18626,17 @@
 procedure pdf_special(p: pointer);
 var old_setting:0..max_selector; {holds print |selector|}
     s: str_number;
+    @!q,@!r:pointer; {temporary variables for list manipulation}
+    @!old_mode:integer; {saved |mode|}
 begin
-    old_setting:=selector; selector:=new_string;
+    old_setting:=selector;
+    selector:=selector;
+    if subtype(p)=latespecial_node then
+      begin @<Expand macros in the token list
+        and make |link(def_ref)| point to the result@>;
+      write_tokens(p):=def_ref;
+      end;
+    selector:=new_string;
     show_token_list(link(write_tokens(p)),null,pool_size-pool_ptr);
     selector:=old_setting;
     s := make_string;
@@ -33624,7 +33641,8 @@
 @d write_node=1 {|subtype| in whatsits that represent things to \.{\\write}}
 @d close_node=2 {|subtype| in whatsits that represent streams to \.{\\closeout}}
 @d special_node=3 {|subtype| in whatsits that represent \.{\\special} things}
- at d language_node=4 {|subtype| in whatsits that change the current language}
+ at d latespecial_node==4 {|subtype| in whatsits that represent \.{\\special} things expanded during output}
+ at d language_node=5 {|subtype| in whatsits that change the current language}
 @d what_lang(#)==link(#+1) {language number, in the range |0..255|}
 @d what_lhm(#)==type(#+1) {minimum left fragment, in the range |1..63|}
 @d what_rhm(#)==subtype(#+1) {minimum right fragment, in the range |1..63|}
@@ -33651,52 +33669,53 @@
 |extension| with a modifier, whenever possible, so that |main_control|
 stays the same.
 
- at d immediate_code=4 {command modifier for \.{\\immediate}}
- at d set_language_code=5 {command modifier for \.{\\setlanguage}}
- at d pdftex_first_extension_code = 6
+ at d immediate_code=5 {command modifier for \.{\\immediate}}
+ at d set_language_code=6 {command modifier for \.{\\setlanguage}}
+ at d pdftex_first_extension_code = 7
 @d pdf_literal_node            == pdftex_first_extension_code + 0
- at d pdf_obj_code                == pdftex_first_extension_code + 1
- at d pdf_refobj_node             == pdftex_first_extension_code + 2
- at d pdf_xform_code              == pdftex_first_extension_code + 3
- at d pdf_refxform_node           == pdftex_first_extension_code + 4
- at d pdf_ximage_code             == pdftex_first_extension_code + 5
- at d pdf_refximage_node          == pdftex_first_extension_code + 6
- at d pdf_annot_node              == pdftex_first_extension_code + 7
- at d pdf_start_link_node         == pdftex_first_extension_code + 8
- at d pdf_end_link_node           == pdftex_first_extension_code + 9
- at d pdf_outline_code            == pdftex_first_extension_code + 10
- at d pdf_dest_node               == pdftex_first_extension_code + 11
- at d pdf_thread_node             == pdftex_first_extension_code + 12
- at d pdf_start_thread_node       == pdftex_first_extension_code + 13
- at d pdf_end_thread_node         == pdftex_first_extension_code + 14
- at d pdf_save_pos_node           == pdftex_first_extension_code + 15
- at d pdf_info_code               == pdftex_first_extension_code + 16
- at d pdf_catalog_code            == pdftex_first_extension_code + 17
- at d pdf_names_code              == pdftex_first_extension_code + 18
- at d pdf_font_attr_code          == pdftex_first_extension_code + 19
- at d pdf_include_chars_code      == pdftex_first_extension_code + 20
- at d pdf_map_file_code           == pdftex_first_extension_code + 21
- at d pdf_map_line_code           == pdftex_first_extension_code + 22
- at d pdf_trailer_code            == pdftex_first_extension_code + 23
- at d pdf_trailer_id_code         == pdftex_first_extension_code + 24
- at d reset_timer_code            == pdftex_first_extension_code + 25
- at d pdf_font_expand_code        == pdftex_first_extension_code + 26
- at d set_random_seed_code        == pdftex_first_extension_code + 27
- at d pdf_snap_ref_point_node     == pdftex_first_extension_code + 28
- at d pdf_snapy_node              == pdftex_first_extension_code + 29
- at d pdf_snapy_comp_node         == pdftex_first_extension_code + 30
- at d pdf_glyph_to_unicode_code   == pdftex_first_extension_code + 31
- at d pdf_colorstack_node         == pdftex_first_extension_code + 32
- at d pdf_setmatrix_node          == pdftex_first_extension_code + 33
- at d pdf_save_node               == pdftex_first_extension_code + 34
- at d pdf_restore_node            == pdftex_first_extension_code + 35
- at d pdf_nobuiltin_tounicode_code== pdftex_first_extension_code + 36
- at d pdf_interword_space_on_node == pdftex_first_extension_code + 37
- at d pdf_interword_space_off_node== pdftex_first_extension_code + 38
- at d pdf_fake_space_node         == pdftex_first_extension_code + 39
- at d pdf_running_link_off_node   == pdftex_first_extension_code + 40
- at d pdf_running_link_on_node    == pdftex_first_extension_code + 41
- at d pdftex_last_extension_code  == pdftex_first_extension_code + 41
+ at d pdf_lateliteral_node        == pdftex_first_extension_code + 1
+ at d pdf_obj_code                == pdftex_first_extension_code + 2
+ at d pdf_refobj_node             == pdftex_first_extension_code + 3
+ at d pdf_xform_code              == pdftex_first_extension_code + 4
+ at d pdf_refxform_node           == pdftex_first_extension_code + 5
+ at d pdf_ximage_code             == pdftex_first_extension_code + 6
+ at d pdf_refximage_node          == pdftex_first_extension_code + 7
+ at d pdf_annot_node              == pdftex_first_extension_code + 8
+ at d pdf_start_link_node         == pdftex_first_extension_code + 9
+ at d pdf_end_link_node           == pdftex_first_extension_code + 10
+ at d pdf_outline_code            == pdftex_first_extension_code + 11
+ at d pdf_dest_node               == pdftex_first_extension_code + 12
+ at d pdf_thread_node             == pdftex_first_extension_code + 13
+ at d pdf_start_thread_node       == pdftex_first_extension_code + 14
+ at d pdf_end_thread_node         == pdftex_first_extension_code + 15
+ at d pdf_save_pos_node           == pdftex_first_extension_code + 16
+ at d pdf_info_code               == pdftex_first_extension_code + 17
+ at d pdf_catalog_code            == pdftex_first_extension_code + 18
+ at d pdf_names_code              == pdftex_first_extension_code + 19
+ at d pdf_font_attr_code          == pdftex_first_extension_code + 20
+ at d pdf_include_chars_code      == pdftex_first_extension_code + 21
+ at d pdf_map_file_code           == pdftex_first_extension_code + 22
+ at d pdf_map_line_code           == pdftex_first_extension_code + 23
+ at d pdf_trailer_code            == pdftex_first_extension_code + 24
+ at d pdf_trailer_id_code         == pdftex_first_extension_code + 25
+ at d reset_timer_code            == pdftex_first_extension_code + 26
+ at d pdf_font_expand_code        == pdftex_first_extension_code + 27
+ at d set_random_seed_code        == pdftex_first_extension_code + 28
+ at d pdf_snap_ref_point_node     == pdftex_first_extension_code + 29
+ at d pdf_snapy_node              == pdftex_first_extension_code + 30
+ at d pdf_snapy_comp_node         == pdftex_first_extension_code + 31
+ at d pdf_glyph_to_unicode_code   == pdftex_first_extension_code + 32
+ at d pdf_colorstack_node         == pdftex_first_extension_code + 33
+ at d pdf_setmatrix_node          == pdftex_first_extension_code + 34
+ at d pdf_save_node               == pdftex_first_extension_code + 35
+ at d pdf_restore_node            == pdftex_first_extension_code + 36
+ at d pdf_nobuiltin_tounicode_code== pdftex_first_extension_code + 37
+ at d pdf_interword_space_on_node == pdftex_first_extension_code + 38
+ at d pdf_interword_space_off_node== pdftex_first_extension_code + 39
+ at d pdf_fake_space_node         == pdftex_first_extension_code + 40
+ at d pdf_running_link_off_node   == pdftex_first_extension_code + 41
+ at d pdf_running_link_on_node    == pdftex_first_extension_code + 42
+ at d pdftex_last_extension_code  == pdftex_first_extension_code + 42
 
 @<Put each...@>=
 primitive("openout",extension,open_node);@/
@@ -33965,12 +33984,17 @@
 end
 
 @ When `\.{\\special\{...\}}' appears, we expand the macros in the token
-list as in \.{\\xdef} and \.{\\mark}.
+list as in \.{\\xdef} and \.{\\mark}.  When marked with \.{shipout}, we keep
+tokens unexpanded for now.
 
 @<Implement \.{\\special}@>=
+begin if scan_keyword("shipout") then
+begin new_whatsit(latespecial_node,write_node_size); write_stream(tail):=null;
+p:=scan_toks(false,false); write_tokens(tail):=def_ref;
+end else
 begin new_whatsit(special_node,write_node_size); write_stream(tail):=null;
 p:=scan_toks(false,true); write_tokens(tail):=def_ref;
-end
+end; end
 
 @ @<Implement \.{\\pdffontexpand}@>=
     read_expand_font
@@ -34022,6 +34046,11 @@
     call_func(scan_toks(false, true)); {like \.{\\special}}
 end;
 
+procedure scan_pdf_ext_late_toks;
+begin
+    call_func(scan_toks(false, false)); {like \.{\\special}, but doesn't expand}
+end;
+
 procedure compare_strings; {to implement \.{\\pdfstrcmp}}
 label done;
 var s1, s2: str_number;
@@ -34065,7 +34094,9 @@
 @ @<Implement \.{\\pdfliteral}@>=
 begin
     check_pdfoutput("\pdfliteral", true);
-    new_whatsit(pdf_literal_node, write_node_size);
+    if scan_keyword("shipout") then k:=pdf_lateliteral_node
+    else k:=pdf_literal_node;
+    new_whatsit(k, write_node_size);
     if scan_keyword("direct") then
         pdf_literal_mode(tail) := direct_always
     else if scan_keyword("page") then
@@ -34072,7 +34103,8 @@
         pdf_literal_mode(tail) := direct_page
     else
         pdf_literal_mode(tail) := set_origin;
-    scan_pdf_ext_toks;
+    if k=pdf_literal_node then
+      scan_pdf_ext_toks else scan_pdf_ext_late_toks;
     pdf_literal_data(tail) := def_ref;
 end
 
@@ -35406,13 +35438,17 @@
 special_node:begin print_esc("special");
   print_mark(write_tokens(p));
   end;
+latespecial_node:begin print_esc("special"); print(" shipout");
+  print_mark(write_tokens(p));
+  end;
 language_node:begin print_esc("setlanguage");
   print_int(what_lang(p)); print(" (hyphenmin ");
   print_int(what_lhm(p)); print_char(",");
   print_int(what_rhm(p)); print_char(")");
   end;
-pdf_literal_node: begin
+pdf_literal_node,pdf_lateliteral_node: begin
     print_esc("pdfliteral");
+    if subtype(p)=pdf_lateliteral_node then print(" shipout");
     case pdf_literal_mode(p) of
     set_origin:
         do_nothing;
@@ -35620,13 +35656,13 @@
 case subtype(p) of
 open_node: begin r:=get_node(open_node_size); words:=open_node_size;
   end;
-write_node,special_node: begin r:=get_node(write_node_size);
+write_node,special_node,latespecial_node: begin r:=get_node(write_node_size);
   add_token_ref(write_tokens(p)); words:=write_node_size;
   end;
 close_node,language_node: begin r:=get_node(small_node_size);
   words:=small_node_size;
   end;
-pdf_literal_node: begin
+pdf_literal_node,pdf_lateliteral_node: begin
     r := get_node(write_node_size);
     add_token_ref(pdf_literal_data(p));
     words := write_node_size;
@@ -35731,11 +35767,11 @@
 @ @<Wipe out the whatsit...@>=
 begin case subtype(p) of
 open_node: free_node(p,open_node_size);
-write_node,special_node: begin delete_token_ref(write_tokens(p));
+write_node,special_node,latespecial_node: begin delete_token_ref(write_tokens(p));
   free_node(p,write_node_size); goto done;
   end;
 close_node,language_node: free_node(p,small_node_size);
-pdf_literal_node: begin
+pdf_literal_node,pdf_lateliteral_node: begin
     delete_token_ref(pdf_literal_data(p));
     free_node(p, write_node_size);
 end;
@@ -35884,8 +35920,17 @@
 procedure special_out(@!p:pointer);
 var old_setting:0..max_selector; {holds print |selector|}
 @!k:pool_pointer; {index into |str_pool|}
+@!q,@!r:pointer; {temporary variables for list manipulation}
+@!old_mode:integer; {saved |mode|}
 begin synch_h; synch_v;@/
 old_setting:=selector; selector:=new_string;
+selector:=old_setting;
+if subtype(p)=latespecial_node then
+  begin @<Expand macros in the token list
+    and make |link(def_ref)| point to the result@>;
+  write_tokens(p):=def_ref;
+  end;
+selector:=new_string;
 show_token_list(link(write_tokens(p)),null,pool_size-pool_ptr);
 selector:=old_setting;
 str_room(1);
@@ -35972,7 +36017,7 @@
 begin case subtype(p) of
 open_node,write_node,close_node:@<Do some work that has been queued up
   for \.{\\write}@>;
-special_node:special_out(p);
+special_node,latespecial_node:special_out(p);
 language_node:do_nothing;
 pdf_save_pos_node:
   @<Save current position in DVI mode@>;
@@ -36817,7 +36862,7 @@
 
 @ @<Output the whatsit node |p| in |pdf_vlist_out|@>=
 case subtype(p) of
-pdf_literal_node:
+pdf_literal_node,pdf_lateliteral_node:
     pdf_out_literal(p);
 pdf_colorstack_node:
     pdf_out_colorstack(p);
@@ -36848,7 +36893,7 @@
     end_thread;
 pdf_save_pos_node:
     @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>;
-special_node:
+special_node,latespecial_node:
     pdf_special(p);
 pdf_snap_ref_point_node:
     @<Save current position to |pdf_snapx_refpos|, |pdf_snapy_refpos|@>;
@@ -36903,7 +36948,7 @@
 
 @ @<Output the whatsit node |p| in |pdf_hlist_out|@>=
 case subtype(p) of
-pdf_literal_node:
+pdf_literal_node,pdf_lateliteral_node:
     pdf_out_literal(p);
 pdf_colorstack_node:
     pdf_out_colorstack(p);
@@ -36935,7 +36980,7 @@
     pdf_error("ext4", "\pdfendthread ended up in hlist");
 pdf_save_pos_node:
     @<Save current position to |pdf_last_x_pos|, |pdf_last_y_pos|@>;
-special_node:
+special_node,latespecial_node:
     pdf_special(p);
 pdf_snap_ref_point_node:
     @<Save current position to |pdf_snapx_refpos|, |pdf_snapy_refpos|@>;

Added: branches/stable/tests/27-late-shipout/Makefile
===================================================================
--- branches/stable/tests/27-late-shipout/Makefile	                        (rev 0)
+++ branches/stable/tests/27-late-shipout/Makefile	2023-01-21 02:05:59 UTC (rev 890)
@@ -0,0 +1,12 @@
+# $Id$
+# Public domain.
+# Test shipout keyword on \special and \pdfliteral.
+
+include ../Common.mak
+
+test-shipout:
+	$(prog) -etex ./test-shipout.tex
+
+clean:
+	$(clean)
+


Property changes on: branches/stable/tests/27-late-shipout/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Date Author Id Revision
\ No newline at end of property
Added: branches/stable/tests/27-late-shipout/test-shipout.pdf
===================================================================
(Binary files differ)

Index: branches/stable/tests/27-late-shipout/test-shipout.pdf
===================================================================
--- branches/stable/tests/27-late-shipout/test-shipout.pdf	2023-01-20 16:39:45 UTC (rev 889)
+++ branches/stable/tests/27-late-shipout/test-shipout.pdf	2023-01-21 02:05:59 UTC (rev 890)

Property changes on: branches/stable/tests/27-late-shipout/test-shipout.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/pdf
\ No newline at end of property
Added: branches/stable/tests/27-late-shipout/test-shipout.tex
===================================================================
--- branches/stable/tests/27-late-shipout/test-shipout.tex	                        (rev 0)
+++ branches/stable/tests/27-late-shipout/test-shipout.tex	2023-01-21 02:05:59 UTC (rev 890)
@@ -0,0 +1,38 @@
+% $Id$
+% Public domain. Originally by Phelype Oleinik, 2023.
+% Test `shipout' keyword on \special and \pdfliteral to delay expansion.
+
+\catcode`\{=1 \catcode`\}=2
+\output={\global\advance\count0 by 1 \shipout\box255 }
+
+\pdfoutput=1
+\pdfcompresslevel-0
+\pdfobjcompresslevel=0
+\hsize=4.6cm
+  \pdfpagewidth=\hsize
+  \hoffset=-1in
+\topskip=10pt
+\baselineskip=12pt
+\vsize=\dimexpr\topskip+3\baselineskip\relax
+  \pdfpageheight=\vsize
+  \voffset=-1in
+\parindent=0pt
+
+\font\f = cmr10 \f
+
+\def\!{\ifodd\count0 0\else 1\fi}
+\def\0{\pdfliteral {0 g}}
+
+\def\text{%
+  \pdfliteral         direct {\! 1 0 0 k}1hello\01 %
+  \special              {PDF:direct:\! g}2hello\02 %
+  \pdfliteral shipout direct {\! 1 0 0 k}3hello\03 %
+  \special    shipout   {PDF:direct:\! g}4hello\04 %
+}
+
+\text \text \text \text
+\text \text \text \text
+\text \text \text \text
+\text \text \text \text
+
+\end


Property changes on: branches/stable/tests/27-late-shipout/test-shipout.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Date Author Id Revision
\ No newline at end of property
Modified: branches/stable/tests/Common.mak
===================================================================
--- branches/stable/tests/Common.mak	2023-01-20 16:39:45 UTC (rev 889)
+++ branches/stable/tests/Common.mak	2023-01-21 02:05:59 UTC (rev 890)
@@ -4,8 +4,8 @@
 # Common Makefile definitions to run pdftex from test hierarchy,
 # but use support files from an installation.
 
-tl ?= /usr/local/texlive-rel
-tl_dist = $(tl)/texmf-dist
+tm ?= /usr/local/texlive-rel
+tl_dist = $(tm)/texmf-dist
 #
 plain = $(tl_dist)/tex/plain/base
 plain_config = $(tl_dist)/tex/plain/config

Added: branches/stable/tests/Makefile
===================================================================
--- branches/stable/tests/Makefile	                        (rev 0)
+++ branches/stable/tests/Makefile	2023-01-21 02:05:59 UTC (rev 890)
@@ -0,0 +1,15 @@
+# $Id$
+# Public domain. Originally written by Karl Berry.
+# Top-level tests Makefile. Not done.
+
+default:
+	@echo "install to copy tests to TL Master for distribution."
+	@echo "all to try running all tests, but doesn't work."
+
+all:
+	for d in *; do make -C $$d </dev/null || exit 1; done >log 2>&1
+
+dest = /v/texlive/Master/texmf-dist/doc/pdftex/tests
+filelist = /tmp/sat # svn status, numbers, not directories or .
+install:
+	rsync -avR --delete `cat $(filelist)` $(dest)/


Property changes on: branches/stable/tests/Makefile
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:keywords
## -0,0 +1 ##
+Date Author Id Revision
\ No newline at end of property


More information about the pdftex-commits mailing list.