diff --git a/manual/luatex-lua.tex b/manual/luatex-lua.tex
index f9107fa1f960ae654df469bb195986c9c2cff617..625334c1b8a4e260bad92a2abf3b65ca4d4cfdf7 100644
--- a/manual/luatex-lua.tex
+++ b/manual/luatex-lua.tex
@@ -608,6 +608,10 @@ in addition to the regular \type {io} library functions.
 \NC \type{readbytetable(f,n)}       \NC \type {n} bytes\NC \NR
 \stoptabulate
 
+There are eight additional little endian variants for the \type {cardinal[1-4]}
+and \type {integer[1-4]} readers: \type {cardinal[1-4]le} and \type
+{integer[1-4]le}.
+
 \stopsubsection
 
 \startsubsection[title={Binary input from strings with \type {sio}}]
diff --git a/manual/luatex-math.tex b/manual/luatex-math.tex
index b4a2d4b05d55f7a120ff38779858412f66086385..89c0836ba76281641e405dff8af004121cd3570d 100644
--- a/manual/luatex-math.tex
+++ b/manual/luatex-math.tex
@@ -1331,6 +1331,9 @@ For Latin Modern the result looks as follows:
     \stoptabulate
 \stop
 
+The keyword \type {norule} will hide the rule with the above variants while
+keeping the rule related spacing.
+
 \subsection {Delimiters: \type{\Uleft}, \prm {Umiddle} and \prm {Uright}}
 
 \topicindex {math+delimiters}
diff --git a/manual/luatex-modifications.tex b/manual/luatex-modifications.tex
index 747945f55f7ae82fef5a96dadf2b7f6931928345..bf4233165b921329f8856099e18112604d7477a7 100644
--- a/manual/luatex-modifications.tex
+++ b/manual/luatex-modifications.tex
@@ -615,6 +615,8 @@ primitives (for as far their functionality is still around) you now can do this:
 \protected\def\pdfmapline             {\pdfextension mapline }
 \protected\def\pdftrailer             {\pdfextension trailer }
 \protected\def\pdfglyphtounicode      {\pdfextension glyphtounicode }
+\protected\def\pdfrunninglinkoff      {\pdfextension linkstate 1 }
+\protected\def\pdfrunninglinkon       {\pdfextension linkstate 0 }
 \stoptyping
 
 The introspective primitives can be defined as:
diff --git a/manual/luatex-tex.tex b/manual/luatex-tex.tex
index dacaec0cb92df69694dbb4113f9a1222ed3aac45..34aa3754d2c5a894fa5f4072d743c046bfa65140 100644
--- a/manual/luatex-tex.tex
+++ b/manual/luatex-tex.tex
@@ -249,7 +249,8 @@ readable (like \prm {tracingcommands} and \prm {parindent}).
 
 \topicindex{parameters+internal}
 
-\libindex{set}           \libindex{get}
+\libindex{set}
+\libindex{get}
 
 For all the parameters in this section, it is possible to access them directly
 using their names as index in the \type {tex} table, or by using one of the
@@ -357,6 +358,10 @@ These are read|-|only:
 tex.deadcycles
 tex.insertpenalties
 tex.parshape
+tex.interlinepenalties
+tex.clubpenalties
+tex.widowpenalties
+tex.displaywidowpenalties
 tex.prevgraf
 tex.spacefactor
 \stoptyping
@@ -605,6 +610,8 @@ tex.currentifbranch
 
 \libindex{scantoks}
 
+\libindex{getmark}
+
 \TEX's attributes (\lpr {attribute}), counters (\prm {count}), dimensions (\prm
 {dimen}), skips (\prm {skip}, \prm {muskip}) and token (\prm {toks}) registers
 can be accessed and written to using two times five virtual sub|-|tables of the
@@ -741,6 +748,12 @@ tex.scantoks("global",0,"$\int\limits^1_2$")
 In the function|-|based interface, it is possible to define values globally by
 using the string \type {global} as the first function argument.
 
+There is a dedicated getter for marks: \type {getmark} that takes two arguments.
+The first argument is one of \type {top}, \type {bottom}, \type {first}, \type
+{splitbottom} or \type {splitfirst}, and the second argument is a marks class
+number. When no arguments are given the current maximum number of classes is
+returned.
+
 \stopsubsection
 
 \startsubsection[title={Character code registers: \type {[get|set]*code[s]}}]
@@ -2063,8 +2076,7 @@ most intriguing.
 \NC \type{scan_toks}      \NC definer, expand    \NC returns a table of tokens tokens \NC \NR
 \NC \type{scan_code}      \NC bitset             \NC returns a character if its category is in the given bitset (representing catcodes) \NC \NR
 \NC \type{scan_string}    \NC                    \NC returns a string given between \type {{}}, as \type {\macro} or as sequence of characters with catcode 11 or 12 \NC \NR
-\NC \type{scan_argument}  \NC                    \NC this one is simular to \type {scanstring} but also accepts a \type {\cs}
-                                                     (which then get expanded) \NC \NR
+\NC \type{scan_argument}  \NC boolean            \NC this one is simular to \type {scanstring} but also accepts a \type {\cs} \NC \NR
 \NC \type{scan_word}      \NC                    \NC returns a sequence of characters with catcode 11 or 12 as string \NC \NR
 \NC \type{scan_csname}    \NC                    \NC returns \type {foo} after scanning \type {\foo} \NC \NR
 \NC \type{scan_list}      \NC                    \NC picks up a box specification and returns a \type {[h|v]list} node \NC \NR
@@ -2080,6 +2092,11 @@ macro, in which case the result will also provide information about what
 arguments are expected and in the result this is separated from the meaning by a
 separator token. The \type {expand} flag determines if the list will be expanded.
 
+The \type {scan_argument} function expands the given argument. When a braced
+argument is scanned, expansion can be prohibited by passing \type {false}
+(default is \type {true}). In case of a control sequence passing \type {false}
+will result in a one|-|level expansion (the meaning of the macro).
+
 The string scanner scans for something between curly braces and expands on the
 way, or when it sees a control sequence it will return its meaning. Otherwise it
 will scan characters with catcode \type {letter} or \type {other}. So, given the
@@ -2292,6 +2309,9 @@ accepts a string and returns a boolean:
 local okay = token.is_defined("foo")
 \stoptyping
 
+When a second argument to \type {is_defined} is \type {true} the check is for an
+undefined control sequence (only), otherwise any undefined command gives true.
+
 The largest character possible is returned by \type {biggest_char}, just in case you
 need to know that boundary condition.
 
diff --git a/manual/luatex.pdf b/manual/luatex.pdf
index a41eeca7e10bee9921d8f51d43e8ff787a681245..18840cc366608387f928f663ff4a335f8f011807 100644
Binary files a/manual/luatex.pdf and b/manual/luatex.pdf differ
diff --git a/source/texk/web2c/lib/ChangeLog b/source/texk/web2c/lib/ChangeLog
index 754f164b4d15f13bb53a53213968d45c92ba57e6..be05b6cdceeb173b2ab19b565b53633a955b044f 100644
--- a/source/texk/web2c/lib/ChangeLog
+++ b/source/texk/web2c/lib/ChangeLog
@@ -1,3 +1,7 @@
+2021-01-01  Akira Kakuto  <kakuto@w32tex.org>
+
+	* printversion.c: Update copyright year.
+
 2020-12-10  Akira Kakuto  <kakuto@w32tex.org>
 
 	* lib.h: Definition of eof() contradicts corecrt_io.h
diff --git a/source/texk/web2c/lib/printversion.c b/source/texk/web2c/lib/printversion.c
index b34825a939c1c5332af8b16273028577806f7221..8716e6db9946bfc9004fa2c632360452da1738d5 100644
--- a/source/texk/web2c/lib/printversion.c
+++ b/source/texk/web2c/lib/printversion.c
@@ -56,7 +56,7 @@ printversionandexit (const_string banner,
 #endif
 
   if (copyright_holder) {
-    printf ("Copyright 2020 %s.\n", copyright_holder);
+    printf ("Copyright 2021 %s.\n", copyright_holder);
     if (!author)
       author = copyright_holder;
   }
diff --git a/source/texk/web2c/luatexdir/ChangeLog b/source/texk/web2c/luatexdir/ChangeLog
index b18c96f90f390b1d46c64add438dfa1daf41bfef..93bdcaf7da0e7c3c45b1f18a039666cc6b0dff5b 100644
--- a/source/texk/web2c/luatexdir/ChangeLog
+++ b/source/texk/web2c/luatexdir/ChangeLog
@@ -1,3 +1,6 @@
+2021-01-13 Luigi Scarso <luigi.scarso@gmail.com> 
+    * pdftex compatibility hack (H. Hagen)
+
 2020-12-13 Luigi Scarso <luigi.scarso@gmail.com> 
     * fixed Hyphenation issue regarding frozen glyph nodes (M.F. Krüger)
 
diff --git a/source/texk/web2c/luatexdir/lua/lnodelib.c b/source/texk/web2c/luatexdir/lua/lnodelib.c
index 7e76746037b26c591ce1d8ac0fdc44f6a1a716e5..0cd6803841537360474a7d08f73b2a210d77be7b 100644
--- a/source/texk/web2c/luatexdir/lua/lnodelib.c
+++ b/source/texk/web2c/luatexdir/lua/lnodelib.c
@@ -6772,6 +6772,12 @@ static int lua_nodelib_setfield_whatsit(lua_State * L, int n, const char *s)
         } else {
             return nodelib_cantset(L, n, s);
         }
+    } else if (t == pdf_link_state_node) {
+        if (lua_key_eq(s, value)) {
+            pdf_link_state(n) = (halfword) lua_tointeger(L, 3);
+        } else {
+            return nodelib_cantset(L, n, s);
+        }
     } else if ((t == pdf_end_link_node) || (t == pdf_end_thread_node) || (t == save_pos_node) ||
                (t == pdf_save_node)     || (t == pdf_restore_node)) {
         return nodelib_cantset(L, n, s);
diff --git a/source/texk/web2c/luatexdir/lua/ltexlib.c b/source/texk/web2c/luatexdir/lua/ltexlib.c
index deb7755517892343fab0ed63179d8d637c6e3660..6e19e0727bcfc7dcee473c7bb94b1616aa273c73 100644
--- a/source/texk/web2c/luatexdir/lua/ltexlib.c
+++ b/source/texk/web2c/luatexdir/lua/ltexlib.c
@@ -2668,10 +2668,21 @@ static int tex_hashpairs(lua_State * L)
     while (cs < hash_size) {
         s = hash_text(cs);
         if (s > 0) {
+            halfword n = cs_next(cs);
             char *ss = makecstring(s);
             lua_pushstring(L, ss);
             free(ss);
             lua_rawseti(L, -2, ++nt);
+            while (n) {
+                s = cs_text(n);
+                if (s) {
+                    ss = makecstring(s);
+                    lua_pushstring(L, ss);
+                    free(ss);
+                    lua_rawseti(L, -2, ++nt);
+                }
+                n = cs_next(n);
+            }
         }
         cs++;
     }
diff --git a/source/texk/web2c/luatexdir/lua/luatex-api.h b/source/texk/web2c/luatexdir/lua/luatex-api.h
index 06692cb020204ea4eb4409145339e9e854c931b8..5f42bd5895c310db81bf93d80d38687747ba258c 100644
--- a/source/texk/web2c/luatexdir/lua/luatex-api.h
+++ b/source/texk/web2c/luatexdir/lua/luatex-api.h
@@ -1014,6 +1014,7 @@ make_lua_key(pdf_destination);\
 make_lua_key(pdf_end_link);\
 make_lua_key(pdf_end_thread);\
 make_lua_key(pdf_link_data);\
+make_lua_key(pdf_link_state);\
 make_lua_key(pdf_literal);\
 make_lua_key(pdf_refobj);\
 make_lua_key(pdf_restore);\
@@ -1715,6 +1716,7 @@ init_lua_key(pdf_destination);\
 init_lua_key(pdf_end_link);\
 init_lua_key(pdf_end_thread);\
 init_lua_key(pdf_link_data);\
+init_lua_key(pdf_link_state);\
 init_lua_key(pdf_literal);\
 init_lua_key(pdf_refobj);\
 init_lua_key(pdf_restore);\
@@ -2483,6 +2485,7 @@ use_lua_key(pdf_destination);
 use_lua_key(pdf_end_link);
 use_lua_key(pdf_end_thread);
 use_lua_key(pdf_link_data);
+use_lua_key(pdf_link_state);
 use_lua_key(pdf_literal);
 use_lua_key(pdf_refobj);
 use_lua_key(pdf_restore);
diff --git a/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/psread.c b/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/psread.c
index b54cbac638d9e7e400c57e3676bff288860916b2..96cf5c30d4c835d708547008f1226b70fafd040a 100644
--- a/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/psread.c
+++ b/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/psread.c
@@ -531,7 +531,7 @@ return( pt_number );
 	    }
 	} else {
 	    *val = strtod(tokbuf,&end);
-	    if ( !finite(*val) ) {
+	    if ( !isfinite(*val) ) {
 /* GT: NaN is a concept in IEEE floating point which means "Not a Number" */
 /* GT: it is used to represent errors like 0/0 or sqrt(-1). */
 		LogError( _("Bad number, infinity or nan: %s\n"), tokbuf );
@@ -677,14 +677,14 @@ return( sp );
 }
 
 static void CheckMakeB(BasePoint *test, BasePoint *good) {
-    if ( !finite(test->x) || test->x>100000 || test->x<-100000 ) {
+    if ( !isfinite(test->x) || test->x>100000 || test->x<-100000 ) {
 	LogError( _("Value out of bounds in spline.\n") );
 	if ( good!=NULL )
 	    test->x = good->x;
 	else
 	    test->x = 0;
     }
-    if ( !finite(test->y) || test->y>100000 || test->y<-100000 ) {
+    if ( !isfinite(test->y) || test->y>100000 || test->y<-100000 ) {
 	LogError( _("Value out of bounds in spline.\n") );
 	if ( good!=NULL )
 	    test->y = good->y;
diff --git a/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/splinerefigure.c b/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/splinerefigure.c
index b651a241960caaec7d81dd5fddd0b66d29f7b51b..9d7694de739915515238b48f215c6ba417680785 100644
--- a/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/splinerefigure.c
+++ b/source/texk/web2c/luatexdir/luafontloader/fontforge/fontforge/splinerefigure.c
@@ -75,7 +75,7 @@ void SplineRefigure3(Spline *spline) {
 	if ( ysp->a==0 && xsp->a==0 && ysp->b==0 && xsp->b==0 )
 	    spline->islinear = true;	/* This seems extremely unlikely... */
     }
-    if ( !finite(ysp->a) || !finite(xsp->a) || !finite(ysp->c) || !finite(xsp->c) || !finite(ysp->d) || !finite(xsp->d))
+    if ( !isfinite(ysp->a) || !isfinite(xsp->a) || !isfinite(ysp->c) || !isfinite(xsp->c) || !isfinite(ysp->d) || !isfinite(xsp->d))
 	IError("NaN value in spline creation");
     LinearApproxFree(spline->approx);
     spline->approx = NULL;
diff --git a/source/texk/web2c/luatexdir/luatex_svnversion.h b/source/texk/web2c/luatexdir/luatex_svnversion.h
index 13e060d557e35b9ddbe834dd637b1d06d0ff0f8e..0eb59f10988741c4f1cd865e6f2dd7125d5d11ba 100644
--- a/source/texk/web2c/luatexdir/luatex_svnversion.h
+++ b/source/texk/web2c/luatexdir/luatex_svnversion.h
@@ -1 +1 @@
-#define luatex_svn_revision 7393
+#define luatex_svn_revision 7397
diff --git a/source/texk/web2c/luatexdir/pdf/pdfgen.c b/source/texk/web2c/luatexdir/pdf/pdfgen.c
index 63736787ec572b03a210e762b56c3fae3fa3f673..ce610cb4925f69799c6634c7c8b4773075c2d16f 100644
--- a/source/texk/web2c/luatexdir/pdf/pdfgen.c
+++ b/source/texk/web2c/luatexdir/pdf/pdfgen.c
@@ -916,6 +916,7 @@ void pdf_print_toks(PDF pdf, halfword p)
     xfree(s);
 }
 
+/*
 void pdf_add_rect_spec(PDF pdf, halfword r)
 {
     pdf_add_bp(pdf, pdf_ann_left(r));
@@ -923,6 +924,16 @@ void pdf_add_rect_spec(PDF pdf, halfword r)
     pdf_add_bp(pdf, pdf_ann_right(r));
     pdf_add_bp(pdf, pdf_ann_top(r));
 }
+*/
+
+void pdf_add_rect_spec(PDF pdf, halfword r)
+{
+    /* the check is now here */
+    pdf_add_bp(pdf, pdf_ann_left(r)   < pdf_ann_right(r) ? pdf_ann_left(r)   : pdf_ann_right(r));
+    pdf_add_bp(pdf, pdf_ann_bottom(r) < pdf_ann_top(r)   ? pdf_ann_bottom(r) : pdf_ann_top(r));
+    pdf_add_bp(pdf, pdf_ann_left(r)   < pdf_ann_right(r) ? pdf_ann_right(r)  : pdf_ann_left(r));
+    pdf_add_bp(pdf, pdf_ann_bottom(r) < pdf_ann_top(r)   ? pdf_ann_top(r)    : pdf_ann_bottom(r));
+}
 
 void pdf_rectangle(PDF pdf, halfword r)
 {
diff --git a/source/texk/web2c/luatexdir/pdf/pdflink.c b/source/texk/web2c/luatexdir/pdf/pdflink.c
index 55521b176922aeff3ee1249020118a546212039d..77b950adf253f0305ab0e98af52de728947ec2f7 100644
--- a/source/texk/web2c/luatexdir/pdf/pdflink.c
+++ b/source/texk/web2c/luatexdir/pdf/pdflink.c
@@ -29,6 +29,16 @@ with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
 
 */
 
+void pdf_out_link_state(PDF pdf, halfword p)
+{
+    if (pdf_link_state(p) >= 0 && pdf_link_state(p) <= 1) {
+        pdf->link_state = pdf_link_state(p);
+    } else {
+        /* ignores so one can use them for whatever purpose */
+    }
+}
+
+
 void push_link_level(PDF pdf, halfword p)
 {
     if (pdf->link_stack_ptr >= pdf_max_link_level)
diff --git a/source/texk/web2c/luatexdir/pdf/pdflink.h b/source/texk/web2c/luatexdir/pdf/pdflink.h
index 5b3d2042a80b5e692ea880f7e1b0e6e898035f2b..ed96beab3dce27820425e46f5a401e53af14ea88 100644
--- a/source/texk/web2c/luatexdir/pdf/pdflink.h
+++ b/source/texk/web2c/luatexdir/pdf/pdflink.h
@@ -28,6 +28,7 @@
 extern void push_link_level(PDF pdf, halfword p);
 extern void pop_link_level(PDF pdf);
 extern void do_link(PDF pdf, halfword p, halfword parent_box, scaledpos cur);
+extern void pdf_out_link_state(PDF pdf, halfword p);
 extern void end_link(PDF pdf, halfword p);
 extern void append_link(PDF pdf, halfword parent_box, scaledpos cur, small_number i);
 extern void scan_startlink(PDF pdf);
diff --git a/source/texk/web2c/luatexdir/pdf/pdflistout.c b/source/texk/web2c/luatexdir/pdf/pdflistout.c
index 86567c1dc4e8c1780f8f2baf5491e40cfec5e9d6..02c7025c3301e223574bb8560f278d05df51fbcf 100644
--- a/source/texk/web2c/luatexdir/pdf/pdflistout.c
+++ b/source/texk/web2c/luatexdir/pdf/pdflistout.c
@@ -177,6 +177,7 @@ static void handle_backend_whatsit(PDF pdf, halfword p, halfword parent_box, sca
             case pdf_refobj_node:
             case pdf_end_link_node:
             case pdf_end_thread_node:
+            case pdf_link_state_node:
                 backend_out_whatsit[subtype(p)](pdf, p);
                 break;
             case pdf_annot_node:
@@ -254,8 +255,20 @@ void hlist_out(PDF pdf, halfword this_box, int rule_callback_id)
     cur_s++;
     backend_out_control[backend_control_push_list](pdf,&saved_pos,&saved_loc);
     for (i = 1; i <= pdf->link_stack_ptr; i++) {
-        if (pdf->link_stack[i].nesting_level == cur_s)
+        if (pdf->link_state == 1) {
+            /*
+                We ignore this link. This is a compatibility-with-pdftex feature needed for latex. It
+                is suboptimal in the sense that when the whatsit is set, the next box is influenced,
+                so there there can be side effects when used in the middle of a line, when using
+                vadjust, etc. But we can assume that tha macro package knows when and where this
+                mechanism is triggered, so a more sophisticated solution is not needed (and would be
+                confusing in its own anyway.)
+
+                I would not be surprised of we have some leak here but it's harmless.
+           */
+        } else if (pdf->link_stack[i].nesting_level == cur_s) {
             append_link(pdf, this_box, cur, (small_number) i);
+        }
     }
     if (synctex) {
         synctexhlist(this_box);
diff --git a/source/texk/web2c/luatexdir/pdf/pdftables.c b/source/texk/web2c/luatexdir/pdf/pdftables.c
index a97d0e39e853f3e139cc76900fcb77b0027c2f75..2a02dcd98ec53a1484eeee0ee5301417e1bf7c04 100644
--- a/source/texk/web2c/luatexdir/pdf/pdftables.c
+++ b/source/texk/web2c/luatexdir/pdf/pdftables.c
@@ -224,8 +224,7 @@ void check_obj_type(PDF pdf, int t, int objnum)
 void set_rect_dimens(PDF pdf, halfword p, halfword parent_box, scaledpos cur, scaled_whd alt_rule, scaled margin)
 {
     /*tex The positions relative to cur: */
-    scaledpos ll, ur;
-    scaledpos pos_ll, pos_ur, tmp;
+    scaledpos ll, ur, pos_ll, pos_ur;
     posstructure localpos;
     localpos.dir = pdf->posstruct->dir;
     /*tex |pdf| contains current point on page: */
@@ -246,16 +245,11 @@ void set_rect_dimens(PDF pdf, halfword p, halfword parent_box, scaledpos cur, sc
     pos_ll = localpos.pos;
     synch_pos_with_cur(&localpos, pdf->posstruct, ur);
     pos_ur = localpos.pos;
-    if (pos_ll.h > pos_ur.h) {
-        tmp.h = pos_ll.h;
-        pos_ll.h = pos_ur.h;
-        pos_ur.h = tmp.h;
-    }
-    if (pos_ll.v > pos_ur.v) {
-        tmp.v = pos_ll.v;
-        pos_ll.v = pos_ur.v;
-        pos_ur.v = tmp.v;
-    }
+    /*
+        The test for swapping has been moved to the moment we write the rectangle. This has to
+        do with the fact that we have code dealing with directions and that the |pdf_ann_*|
+        horizontal edges get recalculated in some places.
+    */
     if (global_shipping_mode == SHIPPING_PAGE && matrixused()) {
         matrixtransformrect(pos_ll.h, pos_ll.v, pos_ur.h, pos_ur.v);
         pos_ll.h = getllx();
diff --git a/source/texk/web2c/luatexdir/pdf/pdftypes.h b/source/texk/web2c/luatexdir/pdf/pdftypes.h
index 67ffcbecb2261d2cf307ab68a391d5184d802c5a..ad2465f528367e75cd384f23ab963407c6dbbd0e 100644
--- a/source/texk/web2c/luatexdir/pdf/pdftypes.h
+++ b/source/texk/web2c/luatexdir/pdf/pdftypes.h
@@ -371,6 +371,7 @@ typedef struct pdf_output_file_ {
     /* the pdf link stack */
     pdf_link_stack_record link_stack[(pdf_max_link_level + 1)];
     int link_stack_ptr;
+    int link_state;
     /* the thread data */
     int last_thread;            /* pointer to the last thread */
     scaled_whd thread;
diff --git a/source/texk/web2c/luatexdir/tex/backend.c b/source/texk/web2c/luatexdir/tex/backend.c
index d8c7daed251de97e68589677f231b32d09a7094b..3115a88a7e37296dea715ee7ab4fba9d55d596f1 100644
--- a/source/texk/web2c/luatexdir/tex/backend.c
+++ b/source/texk/web2c/luatexdir/tex/backend.c
@@ -45,6 +45,7 @@ static void init_pdf_backend_functions(void)
     p->whatsit_fu[pdf_setmatrix_node] = &pdf_out_setmatrix;
     p->whatsit_fu[pdf_save_node] = &pdf_out_save;
     p->whatsit_fu[pdf_restore_node] = &pdf_out_restore;
+    p->whatsit_fu[pdf_link_state_node] = &pdf_out_link_state;
     p->control_fu[backend_control_push_list] = &pdf_push_list;
     p->control_fu[backend_control_pop_list] = &pdf_pop_list;
     p->control_fu[backend_control_begin_page] = &pdf_begin_page;
diff --git a/source/texk/web2c/luatexdir/tex/dumpdata.c b/source/texk/web2c/luatexdir/tex/dumpdata.c
index 215cd686fd2a1abe03fab6616be3ffc83871f5d8..e7d53050b296d5deeda1e18b70a7af8669c4e897 100644
--- a/source/texk/web2c/luatexdir/tex/dumpdata.c
+++ b/source/texk/web2c/luatexdir/tex/dumpdata.c
@@ -32,7 +32,7 @@ with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
 
 */
 
-#define FORMAT_ID (907+53)
+#define FORMAT_ID (907+54)
 #if ((FORMAT_ID>=0) && (FORMAT_ID<=256))
 #error Wrong value for FORMAT_ID.
 #endif
diff --git a/source/texk/web2c/luatexdir/tex/errors.c b/source/texk/web2c/luatexdir/tex/errors.c
index 19be65703790da9a7188d9b4cab919521fc9b130..ce80df99e7e6b621e8f82e328863d77a6916d299 100644
--- a/source/texk/web2c/luatexdir/tex/errors.c
+++ b/source/texk/web2c/luatexdir/tex/errors.c
@@ -290,7 +290,8 @@ static int Isspace (char c)
 __attribute__ ((noreturn))
 static void luatex_calledit (int baseptr, int linenumber)
 {
-    char *temp, *command, *fullcmd;
+    char *temp, *command;
+    char *fullcmd = NULL; /* avoid compiler warning */
     char c;
     int sdone, ddone, i;
     char *filename = makecstring(input_stack[base_ptr].name_field);
@@ -442,7 +443,7 @@ void error(void)
         /*tex Get user's advice and |return|. */
         while (1) {
           CONTINUE:
-            /*tex  
+            /*tex
              Original reports:
 
              https://tex.stackexchange.com/questions/551313/
@@ -455,7 +456,7 @@ void error(void)
             selector from 16 to 15 in term_input, due to the lack of this check in
             recursive error() call.
             */
-            if (interaction !=error_stop_mode) 
+            if (interaction !=error_stop_mode)
                 return;
             clear_for_error_prompt();
             prompt_input("? ");
@@ -986,7 +987,7 @@ void normal_warning(const char *t, const char *p)
         new_line_char_par = 10;
         report_id = callback_defined(show_lua_error_hook_callback);
         if (report_id == 0) {
-	    if (p != NULL) 
+	    if (p != NULL)
 	      tprint(p);
             help2(
                 "The lua interpreter ran into a problem, so the",
diff --git a/source/texk/web2c/luatexdir/tex/extensions.c b/source/texk/web2c/luatexdir/tex/extensions.c
index 60deb747a85696dd964c3c3e188a6ca9fd720ac6..19d4e44417361de265bb9a0c79ae30d2667418c7 100644
--- a/source/texk/web2c/luatexdir/tex/extensions.c
+++ b/source/texk/web2c/luatexdir/tex/extensions.c
@@ -156,6 +156,10 @@ static void do_extension_pdf(int immediate)
         new_whatsit(pdf_save_node);
     } else if (scan_keyword("restore")) {
         new_whatsit(pdf_restore_node);
+    } else if (scan_keyword("linkstate")) {
+        new_whatsit(pdf_link_state_node);
+        scan_int();
+        pdf_link_state(tail) = cur_val;
     } else if (scan_keyword("setmatrix")) {
         new_whatsit(pdf_setmatrix_node);
         scan_toks(false, true);
diff --git a/source/texk/web2c/luatexdir/tex/texnodes.c b/source/texk/web2c/luatexdir/tex/texnodes.c
index 0d7bcd5dec23c222f4baa3859b9e7c5a040f476b..02e117a876b885cb9cc6e2bb2de732ce62fd81b9 100644
--- a/source/texk/web2c/luatexdir/tex/texnodes.c
+++ b/source/texk/web2c/luatexdir/tex/texnodes.c
@@ -136,12 +136,14 @@ field_info node_fields_whatsit_pdf_end_thread[2];
 field_info node_fields_whatsit_pdf_literal[4];
 field_info node_fields_whatsit_pdf_refobj[3];
 field_info node_fields_whatsit_pdf_restore[2];
+field_info node_fields_whatsit_pdf_link_state[3];
 field_info node_fields_whatsit_pdf_save[2];
 field_info node_fields_whatsit_pdf_setmatrix[3];
 field_info node_fields_whatsit_pdf_start_link[8];
 field_info node_fields_whatsit_pdf_start_thread[8];
 field_info node_fields_whatsit_pdf_thread[8];
 
+
 /*tex The values of fields. */
 
 subtype_info node_values_dir[] = {
@@ -997,6 +999,7 @@ node_info whatsit_node_data[] = {
     { pdf_setmatrix_node,    pdf_setmatrix_node_size,  NULL, node_fields_whatsit_pdf_setmatrix,    NULL, -1, 0 },
     { pdf_save_node,         pdf_save_node_size,       NULL, node_fields_whatsit_pdf_save,         NULL, -1, 0 },
     { pdf_restore_node,      pdf_restore_node_size,    NULL, node_fields_whatsit_pdf_restore,      NULL, -1, 0 },
+    { pdf_link_state_node,   pdf_link_state_node_size, NULL, node_fields_whatsit_pdf_link_state,   NULL, -1, 0 },
 
     /*tex That's it. */
 
@@ -1065,6 +1068,7 @@ void l_set_whatsit_data(void) {
     init_node_key(whatsit_node_data, pdf_setmatrix_node,   pdf_setmatrix)
     init_node_key(whatsit_node_data, pdf_save_node,        pdf_save)
     init_node_key(whatsit_node_data, pdf_restore_node,     pdf_restore)
+    init_node_key(whatsit_node_data, pdf_link_state_node,  pdf_link_state)
 
     init_node_key(node_values_pdf_destination, 0, xyz)
     init_node_key(node_values_pdf_destination, 1, fit)
@@ -1133,6 +1137,10 @@ void l_set_whatsit_data(void) {
     init_field_key(node_fields_whatsit_pdf_end_link, 0, attr);
     init_field_nop(node_fields_whatsit_pdf_end_link, 1);
 
+    init_field_key(node_fields_whatsit_pdf_link_state, 0, attr);
+    init_field_key(node_fields_whatsit_pdf_link_state, 1, value);
+    init_field_nop(node_fields_whatsit_pdf_link_state, 2);
+
     init_field_key(node_fields_whatsit_pdf_end_thread, 0, attr);
     init_field_nop(node_fields_whatsit_pdf_end_thread, 1);
 
@@ -2257,6 +2265,7 @@ void flush_node_wrapup_pdf(halfword p)
     switch(subtype(p)) {
         case pdf_save_node:
         case pdf_restore_node:
+        case pdf_link_state_node:
         case pdf_refobj_node:
         case pdf_end_link_node:
         case pdf_end_thread_node:
@@ -2559,6 +2568,7 @@ void check_node_wrapup_pdf(halfword p)
             break;
         case pdf_save_node:
         case pdf_restore_node:
+        case pdf_link_state_node:
         case pdf_refobj_node:
         case pdf_end_link_node:
         case pdf_end_thread_node:
@@ -3550,21 +3560,21 @@ void show_node_wrapup_pdf(int p)
             tprint_esc("pdfcolorstack ");
             print_int(pdf_colorstack_stack(p));
             switch (pdf_colorstack_cmd(p)) {
-            case colorstack_set:
-                tprint(" set ");
-                break;
-            case colorstack_push:
-                tprint(" push ");
-                break;
-            case colorstack_pop:
-                tprint(" pop");
-                break;
-            case colorstack_current:
-                tprint(" current");
-                break;
-            default:
-                confusion("colorstack");
-                break;
+                case colorstack_set:
+                    tprint(" set ");
+                    break;
+                case colorstack_push:
+                    tprint(" push ");
+                    break;
+                case colorstack_pop:
+                    tprint(" pop");
+                    break;
+                case colorstack_current:
+                    tprint(" current");
+                    break;
+                default:
+                    confusion("colorstack");
+                    break;
             }
             if (pdf_colorstack_cmd(p) <= colorstack_data)
                 print_mark(pdf_colorstack_data(p));
@@ -3579,6 +3589,10 @@ void show_node_wrapup_pdf(int p)
         case pdf_restore_node:
             tprint_esc("pdfrestore");
             break;
+        case pdf_link_state_node:
+            tprint_esc("pdflinkstate ");
+            print_int(pdf_link_state(p));
+            break;
         case pdf_refobj_node:
             tprint_esc("pdfrefobj");
             if (obj_obj_is_stream(static_pdf, pdf_obj_objnum(p))) {
diff --git a/source/texk/web2c/luatexdir/tex/texnodes.h b/source/texk/web2c/luatexdir/tex/texnodes.h
index 121511bc09841e7a5f93cd0783cab9f807a9f51c..9742ca4966c207e9d728a1da56136b94a63df576 100644
--- a/source/texk/web2c/luatexdir/tex/texnodes.h
+++ b/source/texk/web2c/luatexdir/tex/texnodes.h
@@ -734,6 +734,7 @@ typedef enum {
     pdf_setmatrix_node,
     pdf_save_node,
     pdf_restore_node,
+    pdf_link_state_node,
 } whatsit_types;
 
 #  define first_common_whatsit      0
@@ -741,9 +742,11 @@ typedef enum {
 #  define backend_first_dvi_whatsit 15
 #  define backend_last_dvi_whatsit  15
 #  define backend_first_pdf_whatsit 16
-#  define backend_last_pdf_whatsit  31
+#  define backend_last_pdf_whatsit  32
 
-#  define MAX_WHATSIT_TYPE 32
+/* add some slack for the future */
+
+#  define MAX_WHATSIT_TYPE 34
 
 #  define known_whatsit_type(i) ( \
     (i >= first_common_whatsit      && i <= last_common_whatsit) || \
@@ -920,6 +923,10 @@ typedef enum {
 #  define pdf_save_node_size        3
 #  define pdf_restore_node_size     3
 
+#  define pdf_link_state_node_size  3
+
+#  define pdf_link_state(a) vinfo((a) + 2)
+
 #  define pdf_colorstack_node_size  4
 #  define pdf_colorstack_stack(a)   vlink((a)+2)
 #  define pdf_colorstack_cmd(a)     vinfo((a)+2)
diff --git a/source/utils/README b/source/utils/README
index d55ea345cf678cb84c2add71d39432bd04b7cc52..13c83712dd98bd41cc7e8f1dddde323c4d89cf82 100644
--- a/source/utils/README
+++ b/source/utils/README
@@ -1,10 +1,10 @@
-$Id: README 56819 2020-10-31 04:55:57Z kakuto $
+$Id: README 57291 2021-01-02 16:31:31Z karl $
 Public domain.  Originally written 2005 by Karl Berry.
 
 Extra utilities we (optionally) compile for TeX Live.
 See comments in ../texk/README.
 
-asymptote 2.65 - checked 26mar20
+asymptote 2.68 - checked 2jan21
   update to TL from CTAN, to include prebuilt doc.
   see http://tug.org/texlive/build.html#asymptote
   and tlpkg/bin/tl-update-asy