From fff0f2637579a3259e5da3e8c36436f0ab89aa23 Mon Sep 17 00:00:00 2001
From: Hans Hagen <pragma@wxs.nl>
Date: Sat, 21 Sep 2013 13:53:00 +0200
Subject: beta 2013.09.21 13:53

---
 tex/context/base/buff-ini.lua                      |   1 +
 tex/context/base/catc-sym.mkiv                     |   3 +-
 tex/context/base/char-ini.lua                      |  13 +-
 tex/context/base/cont-new.mkiv                     |   2 +-
 tex/context/base/context-version.pdf               | Bin 4110 -> 4108 bytes
 tex/context/base/context.mkiv                      |   2 +-
 tex/context/base/data-vir.lua                      |   1 +
 tex/context/base/page-pst.lua                      |   1 +
 tex/context/base/page-pst.mkiv                     |   1 +
 tex/context/base/s-inf-03.pdf                      | Bin 0 -> 1981 bytes
 tex/context/base/status-files.pdf                  | Bin 24764 -> 24761 bytes
 tex/context/base/status-lua.log                    |  79 +++
 tex/context/base/status-lua.pdf                    | Bin 221990 -> 0 bytes
 tex/generic/context/luatex/luatex-fonts-merged.lua | 668 +++++++++++----------
 14 files changed, 454 insertions(+), 317 deletions(-)
 create mode 100644 tex/context/base/s-inf-03.pdf
 create mode 100644 tex/context/base/status-lua.log
 delete mode 100644 tex/context/base/status-lua.pdf

diff --git a/tex/context/base/buff-ini.lua b/tex/context/base/buff-ini.lua
index 9d0aa0a6f..a8c101b61 100644
--- a/tex/context/base/buff-ini.lua
+++ b/tex/context/base/buff-ini.lua
@@ -377,6 +377,7 @@ end
 function commands.getbuffer(name)
     local str = getcontent(name)
     if str ~= "" then
+     -- characters.showstring(str)
         context.viafile(str,formatters["buffer.%s"](validstring(name,"noname")))
     end
 end
diff --git a/tex/context/base/catc-sym.mkiv b/tex/context/base/catc-sym.mkiv
index 82169d994..425a5393c 100644
--- a/tex/context/base/catc-sym.mkiv
+++ b/tex/context/base/catc-sym.mkiv
@@ -71,7 +71,8 @@
 
 \normalprotected\def\uncatcodespacetokens
   {\catcode\spaceasciicode    \spacecatcode
-   \catcode\formfeedasciicode \ignorecatcode
+   \catcode\tabasciicode      \spacecatcode
+   \catcode\formfeedasciicode \endoflinecatcode
    \catcode\endoflineasciicode\endoflinecatcode
    \catcode\delasciicode      \ignorecatcode}
 
diff --git a/tex/context/base/char-ini.lua b/tex/context/base/char-ini.lua
index 625996033..7548650e6 100644
--- a/tex/context/base/char-ini.lua
+++ b/tex/context/base/char-ini.lua
@@ -10,7 +10,7 @@ if not modules then modules = { } end modules ['char-ini'] = {
 
 -- we can remove the tag range starting at 0xE0000 (special applications)
 
-local utfchar, utfbyte, utfvalues, ustring = utf.char, utf.byte, utf.values, utf.ustring
+local utfchar, utfbyte, utfvalues, ustring, utotable = utf.char, utf.byte, utf.values, utf.ustring, utf.totable
 local concat, unpack, tohash = table.concat, table.unpack, table.tohash
 local next, tonumber, type, rawget, rawset = next, tonumber, type, rawget, rawset
 local format, lower, gsub, match, gmatch = string.format, string.lower, string.gsub, string.match, string.match, string.gmatch
@@ -948,8 +948,19 @@ end
 local tracedchars = utilities.strings.tracers
 
 tracedchars[0x00] = "[signal]"
+tracedchars[0x0A] = "[linefeed]"
+tracedchars[0x0B] = "[tab]"
+tracedchars[0x0C] = "[formfeed]"
+tracedchars[0x0D] = "[return]"
 tracedchars[0x20] = "[space]"
 
+function characters.showstring(str)
+    local list = utotable(str)
+    for i=1,#list do
+        report_defining("split % 3i : %C",i,list[i])
+    end
+end
+
 -- the following code will move to char-tex.lua
 
 -- tex
diff --git a/tex/context/base/cont-new.mkiv b/tex/context/base/cont-new.mkiv
index dfac919dd..5cfb7b5de 100644
--- a/tex/context/base/cont-new.mkiv
+++ b/tex/context/base/cont-new.mkiv
@@ -11,7 +11,7 @@
 %C therefore copyrighted by \PRAGMA. See mreadme.pdf for
 %C details.
 
-\newcontextversion{2013.09.21 10:50}
+\newcontextversion{2013.09.21 13:53}
 
 %D This file is loaded at runtime, thereby providing an excellent place for
 %D hacks, patches, extensions and new features.
diff --git a/tex/context/base/context-version.pdf b/tex/context/base/context-version.pdf
index 1e62693f1..dcef079b9 100644
Binary files a/tex/context/base/context-version.pdf and b/tex/context/base/context-version.pdf differ
diff --git a/tex/context/base/context.mkiv b/tex/context/base/context.mkiv
index e13588f8a..9209790b5 100644
--- a/tex/context/base/context.mkiv
+++ b/tex/context/base/context.mkiv
@@ -25,7 +25,7 @@
 %D up and the dependencies are more consistent.
 
 \edef\contextformat {\jobname}
-\edef\contextversion{2013.09.21 10:50}
+\edef\contextversion{2013.09.21 13:53}
 \edef\contextkind   {beta}
 
 %D For those who want to use this:
diff --git a/tex/context/base/data-vir.lua b/tex/context/base/data-vir.lua
index e5bf35fa7..48fec54e0 100644
--- a/tex/context/base/data-vir.lua
+++ b/tex/context/base/data-vir.lua
@@ -58,6 +58,7 @@ function openers.virtual(specification)
         end
         data[original] = nil -- when we comment this we can have error messages
         -- With utf-8 we signal that no regime is to be applied!
+     -- characters.showstring(d)
         return openers.helpers.textopener("virtual",original,d,"utf-8")
     else
         if trace_virtual then
diff --git a/tex/context/base/page-pst.lua b/tex/context/base/page-pst.lua
index 2fc400a14..50580ae33 100644
--- a/tex/context/base/page-pst.lua
+++ b/tex/context/base/page-pst.lua
@@ -24,6 +24,7 @@ local function flush(page)
     local c = cache[page]
     if c then
         for i=1,#c do
+         -- characters.showstring(c[i])
             context.viafile(c[i],format("page.%s",validstring(page,"nopage")))
         end
         cache[page] = nil
diff --git a/tex/context/base/page-pst.mkiv b/tex/context/base/page-pst.mkiv
index 7f8a39ca6..704289246 100644
--- a/tex/context/base/page-pst.mkiv
+++ b/tex/context/base/page-pst.mkiv
@@ -78,6 +78,7 @@
   %\flushrestfloats
    \page_floats_flush_page_floats
    \setnormalcatcodes                 % postponing in verbatim
+   \uncatcodespacetokens              % postponing in startlines
    \restoreglobalbodyfont             % otherwise problems inside split verbatim
    \ctxcommand{flushpostponedblocks()}%
    \relax
diff --git a/tex/context/base/s-inf-03.pdf b/tex/context/base/s-inf-03.pdf
new file mode 100644
index 000000000..30df291ed
Binary files /dev/null and b/tex/context/base/s-inf-03.pdf differ
diff --git a/tex/context/base/status-files.pdf b/tex/context/base/status-files.pdf
index 4d97aa52c..7324eec33 100644
Binary files a/tex/context/base/status-files.pdf and b/tex/context/base/status-files.pdf differ
diff --git a/tex/context/base/status-lua.log b/tex/context/base/status-lua.log
new file mode 100644
index 000000000..125142be3
--- /dev/null
+++ b/tex/context/base/status-lua.log
@@ -0,0 +1,79 @@
+(cont-yes.mkiv
+
+ConTeXt  ver: 2013.09.21 13:53 MKIV beta  fmt: 2013.9.21  int: english/english
+
+system          > 'cont-new.mkiv' loaded
+(cont-new.mkiv)
+system          > 'cont-loc.mkiv' loaded
+(c:/data/develop/context/sources/cont-loc.mkiv
+!!!!            > testing prevdepth across page
+)
+system          > 'cont-exp.mkiv' loaded
+interface       > macros > processed mkvi file 'c:/data/develop/context/sources/cont-exp.mkiv', delta 0
+interface       > macros > processed mkvi file 'c:/data/develop/context/sources/cont-exp.mkiv', delta 0
+(c:/data/develop/context/sources/cont-exp.mkiv)
+system          > files > jobname 's-inf-03', input './s-inf-03.mkiv', result 'status-lua.pdf'
+fonts           > latin modern fonts are not preloaded
+languages       > language 'en' is active
+(c:/data/develop/context/texmf/tex/context/base/s-inf-03.mkiv (c:/data/develop/context/sources/type-loc.mkiv) (type-imp-dejavu.mkiv) (type-imp-xits.mkiv (type-imp-texgyre.mkiv)){c:/data/develop/tex-context/tex/texmf-context/fonts/map/pdftex/context/mkiv-base.map} (virtual://buffer.noname.1
+references      > unknown reference '[][]'
+references      > unknown reference '[][attributes]'
+references      > unknown reference '[][backends]'
+references      > unknown reference '[][bibtex]'
+references      > unknown reference '[][bit32]'
+references      > unknown reference '[][blobs]'
+references      > unknown reference '[][boolean]'
+references      > unknown reference '[][buffers]'
+references      > unknown reference '[][builders]'
+references      > unknown reference '[][caches]'
+references      > unknown reference '[][callback]'
+references      > unknown reference '[][callbacks]'
+references      > unknown reference '[][catcodes]'
+references      > unknown reference '[][characters]'
+references      > unknown reference '[][chemistry]'
+references      > unknown reference '[][commands]'
+references      > unknown reference '[][containers]'
+references      > unknown reference '[][context]'
+references      > unknown reference '[][converters]'
+references      > unknown reference '[][coroutine]'
+references      > unknown reference '[][ctxrunner]'
+references      > unknown reference '[][debug]'
+references      > unknown reference '[][dir]'
+references      > unknown reference '[][directives]'
+references      > unknown reference '[][document]'
+references      > unknown reference '[][documentdata]'
+references      > unknown reference '[][environment]'
+references      > unknown reference '[][epdf]'
+references      > unknown reference '[][experiments]'
+references      > unknown reference '[][figures]'
+references      > unknown reference '[][file]'
+references      > unknown reference '[][floats]'
+references      > unknown reference '[][font]'
+references      > unknown reference '[][fontloader]'
+references      > unknown reference '[][fonts]'
+references      > unknown reference '[][functions]'
+references      > unknown reference '[][graphics]'
+references      > unknown reference '[][gzip]'
+references      > unknown reference '[][img]'
+references      > unknown reference '[][interactions]'
+references      > unknown reference '[][interfaces]'
+references      > unknown reference '[][io]'
+references      > unknown reference '[][job]'
+references      > unknown reference '[][lang]'
+references      > unknown reference '[][languages]'
+references      > unknown reference '[][layouts]'
+references      > unknown reference '[][lfs]'
+references      > unknown reference '[][libraries]'
+references      > unknown reference '[][lmx]'
+references      > unknown reference '[][logs]'
+references      > unknown reference '[][lpdf]'
+references      > unknown reference '[][lpeg]'
+references      > unknown reference '[][ltn12]'
+references      > unknown reference '[][lua]'
+references      > unknown reference '[][luatex]'
+references      > unknown reference '[][lxml]'
+references      > unknown reference '[][math]'
+references      > unknown reference '[][mathematics]'
+references      > unknown reference '[][mbox]'
+references      > unknown reference '[][md5]'
+references      > unknown reference '[][metapost
\ No newline at end of file
diff --git a/tex/context/base/status-lua.pdf b/tex/context/base/status-lua.pdf
deleted file mode 100644
index 7906584df..000000000
Binary files a/tex/context/base/status-lua.pdf and /dev/null differ
diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua
index 6e1a9c44c..810538a7f 100644
--- a/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
 -- merged file : luatex-fonts-merged.lua
 -- parent file : luatex-fonts.lua
--- merge date  : 09/21/13 11:52:58
+-- merge date  : 09/21/13 13:53:05
 
 do -- begin closure to overcome local limits and interference
 
@@ -8770,11 +8770,24 @@ local injections=nodes.injections
 local nodecodes=nodes.nodecodes
 local glyph_code=nodecodes.glyph
 local kern_code=nodecodes.kern
-local nodepool=nodes.pool
+local nuts=nodes.nuts
+local nodepool=nuts.pool
 local newkern=nodepool.kern
-local traverse_id=node.traverse_id
-local insert_node_before=node.insert_before
-local insert_node_after=node.insert_after
+local tonode=nuts.tonode
+local tonut=nuts.tonut
+local getfield=nuts.getfield
+local getnext=nuts.getnext
+local getprev=nuts.getprev
+local getid=nuts.getid
+local getattr=nuts.getattr
+local getfont=nuts.getfont
+local getsubtype=nuts.getsubtype
+local getchar=nuts.getchar
+local setfield=nuts.setfield
+local setattr=nuts.setattr
+local traverse_id=nuts.traverse_id
+local insert_node_before=nuts.insert_before
+local insert_node_after=nuts.insert_after
 local a_kernpair=attributes.private('kernpair')
 local a_ligacomp=attributes.private('ligacomp')
 local a_markbase=attributes.private('markbase')
@@ -8793,21 +8806,21 @@ function injections.setcursive(start,nxt,factor,rlmode,exit,entry,tfmstart,tfmne
   local dx,dy=factor*(exit[1]-entry[1]),factor*(exit[2]-entry[2])
   local ws,wn=tfmstart.width,tfmnext.width
   local bound=#cursives+1
-  start[a_cursbase]=bound
-  nxt[a_curscurs]=bound
+  setattr(start,a_cursbase,bound)
+  setattr(nxt,a_curscurs,bound)
   cursives[bound]={ rlmode,dx,dy,ws,wn }
   return dx,dy,bound
 end
 function injections.setpair(current,factor,rlmode,r2lflag,spec,tfmchr)
   local x,y,w,h=factor*spec[1],factor*spec[2],factor*spec[3],factor*spec[4]
   if x~=0 or w~=0 or y~=0 or h~=0 then
-    local bound=current[a_kernpair]
+    local bound=getattr(current,a_kernpair)
     if bound then
       local kb=kerns[bound]
       kb[2],kb[3],kb[4],kb[5]=(kb[2] or 0)+x,(kb[3] or 0)+y,(kb[4] or 0)+w,(kb[5] or 0)+h
     else
       bound=#kerns+1
-      current[a_kernpair]=bound
+      setattr(current,a_kernpair,bound)
       kerns[bound]={ rlmode,x,y,w,h,r2lflag,tfmchr.width }
     end
     return x,y,w,h,bound
@@ -8818,7 +8831,7 @@ function injections.setkern(current,factor,rlmode,x,tfmchr)
   local dx=factor*x
   if dx~=0 then
     local bound=#kerns+1
-    current[a_kernpair]=bound
+    setattr(current,a_kernpair,bound)
     kerns[bound]={ rlmode,dx }
     return dx,bound
   else
@@ -8827,25 +8840,25 @@ function injections.setkern(current,factor,rlmode,x,tfmchr)
 end
 function injections.setmark(start,base,factor,rlmode,ba,ma,index,baseismark) 
   local dx,dy=factor*(ba[1]-ma[1]),factor*(ba[2]-ma[2])   
-  local bound=base[a_markbase]          
+  local bound=getattr(base,a_markbase)          
   local index=1
   if bound then
     local mb=marks[bound]
     if mb then
       index=#mb+1
       mb[index]={ dx,dy,rlmode }
-      start[a_markmark]=bound
-      start[a_markdone]=index
+      setattr(start,a_markmark,bound)
+      setattr(start,a_markdone,index)
       return dx,dy,bound
     else
-      report_injections("possible problem, %U is base mark without data (id %a)",base.char,bound)
+      report_injections("possible problem, %U is base mark without data (id %a)",getchar(base),bound)
     end
   end
   index=index or 1
   bound=#marks+1
-  base[a_markbase]=bound
-  start[a_markmark]=bound
-  start[a_markdone]=index
+  setattr(base,a_markbase,bound)
+  setattr(start,a_markmark,bound)
+  setattr(start,a_markdone,index)
   marks[bound]={ [index]={ dx,dy,rlmode,baseismark } }
   return dx,dy,bound
 end
@@ -8855,15 +8868,15 @@ end
 local function trace(head)
   report_injections("begin run")
   for n in traverse_id(glyph_code,head) do
-    if n.subtype<256 then
-      local kp=n[a_kernpair]
-      local mb=n[a_markbase]
-      local mm=n[a_markmark]
-      local md=n[a_markdone]
-      local cb=n[a_cursbase]
-      local cc=n[a_curscurs]
-      local char=n.char
-      report_injections("font %s, char %U, glyph %c",n.font,char,char)
+    if getsubtype(n)<256 then
+      local kp=getattr(n,a_kernpair)
+      local mb=getattr(n,a_markbase)
+      local mm=getattr(n,a_markmark)
+      local md=getattr(n,a_markdone)
+      local cb=getattr(n,a_cursbase)
+      local cc=getattr(n,a_curscurs)
+      local char=getchar(n)
+      report_injections("font %s, char %U, glyph %c",getfont(n),char,char)
       if kp then
         local k=kerns[kp]
         if k[3] then
@@ -8904,21 +8917,23 @@ local function show_result(head)
   local current=head
   local skipping=false
   while current do
-    local id=current.id
+    local id=getid(current)
     if id==glyph_code then
-      report_injections("char: %C, width %p, xoffset %p, yoffset %p",current.char,current.width,current.xoffset,current.yoffset)
+      report_injections("char: %C, width %p, xoffset %p, yoffset %p",
+        getchar(current),getfield(current,"width"),getfield(current,"xoffset"),getfield(current,"yoffset"))
       skipping=false
     elseif id==kern_code then
-      report_injections("kern: %p",current.kern)
+      report_injections("kern: %p",getfield(current,"kern"))
       skipping=false
     elseif not skipping then
       report_injections()
       skipping=true
     end
-    current=current.next
+    current=getnext(current)
   end
 end
 function injections.handler(head,where,keep)
+  head=tonut(head)
   local has_marks,has_cursives,has_kerns=next(marks),next(cursives),next(kerns)
   if has_marks or has_cursives then
     if trace_injections then
@@ -8928,17 +8943,18 @@ function injections.handler(head,where,keep)
     if has_kerns then 
       local nf,tm=nil,nil
       for n in traverse_id(glyph_code,head) do 
-        if n.subtype<256 then
+        if getsubtype(n)<256 then
           nofvalid=nofvalid+1
           valid[nofvalid]=n
-          if n.font~=nf then
-            nf=n.font
-            tm=fontdata[nf].resources.marks
+          local f=getfont(n)
+          if f~=nf then
+            nf=f
+            tm=fontdata[nf].resources.marks 
           end
           if tm then
-            mk[n]=tm[n.char]
+            mk[n]=tm[getchar(n)]
           end
-          local k=n[a_kernpair]
+          local k=getattr(n,a_kernpair)
           if k then
             local kk=kerns[k]
             if kk then
@@ -8958,15 +8974,16 @@ function injections.handler(head,where,keep)
     else
       local nf,tm=nil,nil
       for n in traverse_id(glyph_code,head) do
-        if n.subtype<256 then
+        if getsubtype(n)<256 then
           nofvalid=nofvalid+1
           valid[nofvalid]=n
-          if n.font~=nf then
-            nf=n.font
-            tm=fontdata[nf].resources.marks
+          local f=getfont(n)
+          if f~=nf then
+            nf=f
+            tm=fontdata[nf].resources.marks 
           end
           if tm then
-            mk[n]=tm[n.char]
+            mk[n]=tm[getchar(n)]
           end
         end
       end
@@ -8975,7 +8992,7 @@ function injections.handler(head,where,keep)
       local cx={}
       if has_kerns and next(ky) then
         for n,k in next,ky do
-          n.yoffset=k
+          setfield(n,"yoffset",k)
         end
       end
       if has_cursives then
@@ -8984,9 +9001,9 @@ function injections.handler(head,where,keep)
         for i=1,nofvalid do 
           local n=valid[i]
           if not mk[n] then
-            local n_cursbase=n[a_cursbase]
+            local n_cursbase=getattr(n,a_cursbase)
             if p_cursbase then
-              local n_curscurs=n[a_curscurs]
+              local n_curscurs=getattr(n,a_curscurs)
               if p_cursbase==n_curscurs then
                 local c=cursives[n_curscurs]
                 if c then
@@ -9009,20 +9026,20 @@ function injections.handler(head,where,keep)
                 end
               end
             elseif maxt>0 then
-              local ny=n.yoffset
+              local ny=getfield(n,"yoffset")
               for i=maxt,1,-1 do
                 ny=ny+d[i]
                 local ti=t[i]
-                ti.yoffset=ti.yoffset+ny
+                setfield(ti,"yoffset",getfield(ti,"yoffset")+ny)
               end
               maxt=0
             end
             if not n_cursbase and maxt>0 then
-              local ny=n.yoffset
+              local ny=getfield(n,"yoffset")
               for i=maxt,1,-1 do
                 ny=ny+d[i]
                 local ti=t[i]
-                ti.yoffset=ny
+                setfield(ti,"yoffset",ny)
               end
               maxt=0
             end
@@ -9030,11 +9047,11 @@ function injections.handler(head,where,keep)
           end
         end
         if maxt>0 then
-          local ny=n.yoffset
+          local ny=getfield(n,"yoffset")
           for i=maxt,1,-1 do
             ny=ny+d[i]
             local ti=t[i]
-            ti.yoffset=ny
+            setfield(ti,"yoffset",ny)
           end
           maxt=0
         end
@@ -9045,57 +9062,66 @@ function injections.handler(head,where,keep)
       if has_marks then
         for i=1,nofvalid do
           local p=valid[i]
-          local p_markbase=p[a_markbase]
+          local p_markbase=getattr(p,a_markbase)
           if p_markbase then
             local mrks=marks[p_markbase]
             local nofmarks=#mrks
-            for n in traverse_id(glyph_code,p.next) do
-              local n_markmark=n[a_markmark]
+            for n in traverse_id(glyph_code,getnext(p)) do
+              local n_markmark=getattr(n,a_markmark)
               if p_markbase==n_markmark then
-                local index=n[a_markdone] or 1
+                local index=getattr(n,a_markdone) or 1
                 local d=mrks[index]
                 if d then
                   local rlmode=d[3]
                   local k=wx[p]
+                  local px=getfield(p,"xoffset")
+                  local ox=0
                   if k then
                     local x=k[2]
                     local w=k[4]
                     if w then
                       if rlmode and rlmode>=0 then
-                        n.xoffset=p.xoffset-p.width+d[1]-(w-x)
+                        ox=px-getfield(p,"width")+d[1]-(w-x)
                       else
-                        n.xoffset=p.xoffset-d[1]-x
+                        ox=px-d[1]-x
                       end
                     else
                       if rlmode and rlmode>=0 then
-                        n.xoffset=p.xoffset-p.width+d[1]
+                        ox=px-getfield(p,"width")+d[1]
                       else
-                        n.xoffset=p.xoffset-d[1]-x
+                        ox=px-d[1]-x
                       end
                     end
                   else
+                    local wp=getfield(p,"width")
+                    local wn=getfield(n,"width") 
                     if rlmode and rlmode>=0 then
-                      n.xoffset=p.xoffset-p.width+d[1]
+                      ox=px-wp+d[1]
                     else
-                      n.xoffset=p.xoffset-d[1]
+                      ox=px-d[1]
                     end
-                    local w=n.width
-                    if w~=0 then
-                      insert_node_before(head,n,newkern(-w/2))
-                      insert_node_after(head,n,newkern(-w/2))
+                    if wn~=0 then
+                      insert_node_before(head,n,newkern(-wn/2))
+                      insert_node_after(head,n,newkern(-wn/2))
                     end
                   end
+                  setfield(n,"xoffset",ox)
+                  local py=getfield(p,"yoffset")
+                  local oy=0
                   if mk[p] then
-                    n.yoffset=p.yoffset+d[2]
+                    oy=py+d[2]
                   else
-                    n.yoffset=n.yoffset+p.yoffset+d[2]
+                    oy=getfield(n,"yoffset")+py+d[2]
                   end
+                  setfield(n,"yoffset",oy)
                   if nofmarks==1 then
                     break
                   else
                     nofmarks=nofmarks-1
                   end
                 end
+              elseif not n_markmark then
+                break 
               else
               end
             end
@@ -9147,6 +9173,7 @@ function injections.handler(head,where,keep)
       if not keep then
         kerns={}
       end
+head=tonode(head)
       return head,true
     elseif not keep then
       kerns,cursives,marks={},{},{}
@@ -9156,14 +9183,14 @@ function injections.handler(head,where,keep)
       trace(head)
     end
     for n in traverse_id(glyph_code,head) do
-      if n.subtype<256 then
-        local k=n[a_kernpair]
+      if getsubtype(n)<256 then
+        local k=getattr(n,a_kernpair)
         if k then
           local kk=kerns[k]
           if kk then
             local rl,x,y,w=kk[1],kk[2] or 0,kk[3],kk[4]
             if y and y~=0 then
-              n.yoffset=y 
+              setfield(n,"yoffset",y) 
             end
             if w then
               local wx=w-x
@@ -9194,10 +9221,10 @@ function injections.handler(head,where,keep)
     if not keep then
       kerns={}
     end
-    return head,true
+    return tonode(head),true
   else
   end
-  return head,false
+  return tonode(head),false
 end
 
 end -- closure
@@ -9612,12 +9639,25 @@ registertracker("otf.positions","otf.marks,otf.kerns,otf.cursive")
 registertracker("otf.actions","otf.replacements,otf.positions")
 registertracker("otf.injections","nodes.injections")
 registertracker("*otf.sample","otf.steps,otf.actions,otf.analyzing")
-local insert_node_after=node.insert_after
-local delete_node=nodes.delete
-local copy_node=node.copy
-local find_node_tail=node.tail or node.slide
-local flush_node_list=node.flush_list
-local end_of_math=node.end_of_math
+local nuts=nodes.nuts
+local tonode=nuts.tonode
+local tonut=nuts.tonut
+local getfield=nuts.getfield
+local getnext=nuts.getnext
+local getprev=nuts.getprev
+local getid=nuts.getid
+local getattr=nuts.getattr
+local getfont=nuts.getfont
+local getsubtype=nuts.getsubtype
+local getchar=nuts.getchar
+local setfield=nuts.setfield
+local setattr=nuts.setattr
+local insert_node_after=nuts.insert_after
+local delete_node=nuts.delete
+local copy_node=nuts.copy
+local find_node_tail=nuts.tail
+local flush_node_list=nuts.flush_list
+local end_of_math=nuts.end_of_math
 local setmetatableindex=table.setmetatableindex
 local zwnj=0x200C
 local zwj=0x200D
@@ -9726,83 +9766,83 @@ local function pref(kind,lookupname)
   return formatters["feature %a, lookup %a"](kind,lookupname)
 end
 local function copy_glyph(g) 
-  local components=g.components
+  local components=getfield(g,"components")
   if components then
-    g.components=nil
+    setfield(g,"components",nil)
     local n=copy_node(g)
-    g.components=components
+    setfield(g,"components",components)
     return n
   else
     return copy_node(g)
   end
 end
 local function markstoligature(kind,lookupname,head,start,stop,char)
-  if start==stop and start.char==char then
+  if start==stop and getchar(start)==char then
     return head,start
   else
-    local prev=start.prev
-    local next=stop.next
-    start.prev=nil
-    stop.next=nil
+    local prev=getprev(start)
+    local next=getnext(stop)
+    setfield(start,"prev",nil)
+    setfield(stop,"next",nil)
     local base=copy_glyph(start)
     if head==start then
       head=base
     end
-    base.char=char
-    base.subtype=ligature_code
-    base.components=start
+    setfield(base,"char",char)
+    setfield(base,"subtype",ligature_code)
+    setfield(base,"components",start)
     if prev then
-      prev.next=base
+      setfield(prev,"next",base)
     end
     if next then
-      next.prev=base
+      setfield(next,"prev",base)
     end
-    base.next=next
-    base.prev=prev
+    setfield(base,"next",next)
+    setfield(base,"prev",prev)
     return head,base
   end
 end
 local function getcomponentindex(start)
-  if start.id~=glyph_code then
+  if getid(start)~=glyph_code then
     return 0
-  elseif start.subtype==ligature_code then
+  elseif getsubtype(start)==ligature_code then
     local i=0
-    local components=start.components
+    local components=getfield(start,"components")
     while components do
       i=i+getcomponentindex(components)
-      components=components.next
+      components=getnext(components)
     end
     return i
-  elseif not marks[start.char] then
+  elseif not marks[getchar(start)] then
     return 1
   else
     return 0
   end
 end
 local function toligature(kind,lookupname,head,start,stop,char,markflag,discfound) 
-  if start==stop and start.char==char then
-    start.char=char
+  if start==stop and getchar(start)==char then
+    setfield(start,"char",char)
     return head,start
   end
-  local prev=start.prev
-  local next=stop.next
-  start.prev=nil
-  stop.next=nil
+  local prev=getprev(start)
+  local next=getnext(stop)
+  setfield(start,"prev",nil)
+  setfield(stop,"next",nil)
   local base=copy_glyph(start)
   if start==head then
     head=base
   end
-  base.char=char
-  base.subtype=ligature_code
-  base.components=start 
+  setfield(base,"char",char)
+  setfield(base,"subtype",ligature_code)
+  setfield(base,"components",start) 
   if prev then
-    prev.next=base
+    setfield(prev,"next",base)
   end
   if next then
-    next.prev=base
+    setfield(next,"prev",base)
   end
-  base.next=next
-  base.prev=prev
+  setfield(base,"next",next)
+  setfield(base,"prev",prev)
   if not discfound then
     local deletemarks=markflag~="mark"
     local components=start
@@ -9811,42 +9851,42 @@ local function toligature(kind,lookupname,head,start,stop,char,markflag,discfoun
     local head=base
     local current=base
     while start do
-      local char=start.char
+      local char=getchar(start)
       if not marks[char] then
         baseindex=baseindex+componentindex
         componentindex=getcomponentindex(start)
       elseif not deletemarks then 
-        start[a_ligacomp]=baseindex+(start[a_ligacomp] or componentindex)
+        setattr(start,a_ligacomp,baseindex+(getattr(start,a_ligacomp) or componentindex))
         if trace_marks then
-          logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp])
+          logwarning("%s: keep mark %s, gets index %s",pref(kind,lookupname),gref(char),getattr(start,a_ligacomp))
         end
         head,current=insert_node_after(head,current,copy_node(start)) 
       elseif trace_marks then
         logwarning("%s: delete mark %s",pref(kind,lookupname),gref(char))
       end
-      start=start.next
+      start=getnext(start)
     end
-    local start=current.next
-    while start and start.id==glyph_code do
-      local char=start.char
+    local start=getnext(current)
+    while start and getid(start)==glyph_code do
+      local char=getchar(start)
       if marks[char] then
-        start[a_ligacomp]=baseindex+(start[a_ligacomp] or componentindex)
+        setattr(start,a_ligacomp,baseindex+(getattr(start,a_ligacomp) or componentindex))
         if trace_marks then
-          logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),start[a_ligacomp])
+          logwarning("%s: set mark %s, gets index %s",pref(kind,lookupname),gref(char),getattr(start,a_ligacomp))
         end
       else
         break
       end
-      start=start.next
+      start=getnext(start)
     end
   end
   return head,base
 end
 function handlers.gsub_single(head,start,kind,lookupname,replacement)
   if trace_singles then
-    logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(start.char),gref(replacement))
+    logprocess("%s: replacing %s by single %s",pref(kind,lookupname),gref(getchar(start)),gref(replacement))
   end
-  start.char=replacement
+  setfield(start,"char",replacement)
   return head,start,true
 end
 local function get_alternative_glyph(start,alternatives,value,trace_alternatives)
@@ -9872,7 +9912,7 @@ local function get_alternative_glyph(start,alternatives,value,trace_alternatives
         return false,trace_alternatives and formatters["invalid value %a, %s"](value,"out of range")
       end
     elseif value==0 then
-      return start.char,trace_alternatives and formatters["invalid value %a, %s"](value,"no change")
+      return getchar(start),trace_alternatives and formatters["invalid value %a, %s"](value,"no change")
     elseif value<1 then
       return alternatives[1],trace_alternatives and formatters["invalid value %a, taking %a"](value,1)
     else
@@ -9883,25 +9923,25 @@ end
 local function multiple_glyphs(head,start,multiple) 
   local nofmultiples=#multiple
   if nofmultiples>0 then
-    start.char=multiple[1]
+    setfield(start,"char",multiple[1])
     if nofmultiples>1 then
-      local sn=start.next
+      local sn=getnext(start)
       for k=2,nofmultiples do 
         local n=copy_node(start) 
-        n.char=multiple[k]
-        n.next=sn
-        n.prev=start
+        setfield(n,"char",multiple[k])
+        setfield(n,"next",sn)
+        setfield(n,"prev",start)
         if sn then
-          sn.prev=n
+          setfield(sn,"prev",n)
         end
-        start.next=n
+        setfield(start,"next",n)
         start=n
       end
     end
     return head,start,true
   else
     if trace_multiples then
-      logprocess("no multiple for %s",gref(start.char))
+      logprocess("no multiple for %s",gref(getchar(start)))
     end
     return head,start,false
   end
@@ -9911,34 +9951,34 @@ function handlers.gsub_alternate(head,start,kind,lookupname,alternative,sequence
   local choice,comment=get_alternative_glyph(start,alternative,value,trace_alternatives)
   if choice then
     if trace_alternatives then
-      logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(start.char),choice,gref(choice),comment)
+      logprocess("%s: replacing %s by alternative %a to %s, %s",pref(kind,lookupname),gref(getchar(start)),choice,gref(choice),comment)
     end
-    start.char=choice
+    setfield(start,"char",choice)
   else
     if trace_alternatives then
-      logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(start.char),comment)
+      logwarning("%s: no variant %a for %s, %s",pref(kind,lookupname),value,gref(getchar(start)),comment)
     end
   end
   return head,start,true
 end
 function handlers.gsub_multiple(head,start,kind,lookupname,multiple)
   if trace_multiples then
-    logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(start.char),gref(multiple))
+    logprocess("%s: replacing %s by multiple %s",pref(kind,lookupname),gref(getchar(start)),gref(multiple))
   end
   return multiple_glyphs(head,start,multiple)
 end
 function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
-  local s,stop,discfound=start.next,nil,false
-  local startchar=start.char
+  local s,stop,discfound=getnext(start),nil,false
+  local startchar=getchar(start)
   if marks[startchar] then
     while s do
-      local id=s.id
-      if id==glyph_code and s.font==currentfont and s.subtype<256 then
-        local lg=ligature[s.char]
+      local id=getid(s)
+      if id==glyph_code and getfont(s)==currentfont and getsubtype(s)<256 then
+        local lg=ligature[getchar(s)]
         if lg then
           stop=s
           ligature=lg
-          s=s.next
+          s=getnext(s)
         else
           break
         end
@@ -9950,9 +9990,9 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
       local lig=ligature.ligature
       if lig then
         if trace_ligatures then
-          local stopchar=stop.char
+          local stopchar=getchar(stop)
           head,start=markstoligature(kind,lookupname,head,start,stop,lig)
-          logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char))
+          logprocess("%s: replacing %s upto %s by ligature %s case 1",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start)))
         else
           head,start=markstoligature(kind,lookupname,head,start,stop,lig)
         end
@@ -9963,18 +10003,18 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
   else
     local skipmark=sequence.flags[1]
     while s do
-      local id=s.id
-      if id==glyph_code and s.subtype<256 then
-        if s.font==currentfont then
-          local char=s.char
+      local id=getid(s)
+      if id==glyph_code and getsubtype(s)<256 then
+        if getfont(s)==currentfont then
+          local char=getchar(s)
           if skipmark and marks[char] then
-            s=s.next
+            s=getnext(s)
           else
             local lg=ligature[char]
             if lg then
               stop=s
               ligature=lg
-              s=s.next
+              s=getnext(s)
             else
               break
             end
@@ -9984,7 +10024,7 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
         end
       elseif id==disc_code then
         discfound=true
-        s=s.next
+        s=getnext(s)
       else
         break
       end
@@ -9993,9 +10033,9 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
       local lig=ligature.ligature
       if lig then
         if trace_ligatures then
-          local stopchar=stop.char
+          local stopchar=getchar(stop)
           head,start=toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound)
-          logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(start.char))
+          logprocess("%s: replacing %s upto %s by ligature %s case 2",pref(kind,lookupname),gref(startchar),gref(stopchar),gref(getchar(start)))
         else
           head,start=toligature(kind,lookupname,head,start,stop,lig,skipmark,discfound)
         end
@@ -10007,16 +10047,16 @@ function handlers.gsub_ligature(head,start,kind,lookupname,ligature,sequence)
   return head,start,false
 end
 function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence)
-  local markchar=start.char
+  local markchar=getchar(start)
   if marks[markchar] then
-    local base=start.prev 
-    if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
-      local basechar=base.char
+    local base=getprev(start) 
+    if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+      local basechar=getchar(base)
       if marks[basechar] then
         while true do
-          base=base.prev
-          if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
-            basechar=base.char
+          base=getprev(base)
+          if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+            basechar=getchar(base)
             if not marks[basechar] then
               break
             end
@@ -10065,16 +10105,16 @@ function handlers.gpos_mark2base(head,start,kind,lookupname,markanchors,sequence
   return head,start,false
 end
 function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequence)
-  local markchar=start.char
+  local markchar=getchar(start)
   if marks[markchar] then
-    local base=start.prev 
-    if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
-      local basechar=base.char
+    local base=getprev(start) 
+    if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+      local basechar=getchar(base)
       if marks[basechar] then
         while true do
-          base=base.prev
-          if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
-            basechar=base.char
+          base=getprev(base)
+          if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+            basechar=getchar(base)
             if not marks[basechar] then
               break
             end
@@ -10086,7 +10126,7 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ
           end
         end
       end
-      local index=start[a_ligacomp]
+      local index=getattr(start,a_ligacomp)
       local baseanchors=descriptions[basechar]
       if baseanchors then
         baseanchors=baseanchors.anchors
@@ -10131,22 +10171,22 @@ function handlers.gpos_mark2ligature(head,start,kind,lookupname,markanchors,sequ
   return head,start,false
 end
 function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence)
-  local markchar=start.char
+  local markchar=getchar(start)
   if marks[markchar] then
-    local base=start.prev 
-    local slc=start[a_ligacomp]
+    local base=getprev(start) 
+    local slc=getattr(start,a_ligacomp)
     if slc then 
       while base do
-        local blc=base[a_ligacomp]
+        local blc=getattr(base,a_ligacomp)
         if blc and blc~=slc then
-          base=base.prev
+          base=getprev(base)
         else
           break
         end
       end
     end
-    if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then 
-      local basechar=base.char
+    if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then 
+      local basechar=getchar(base)
       local baseanchors=descriptions[basechar]
       if baseanchors then
         baseanchors=baseanchors.anchors
@@ -10184,20 +10224,20 @@ function handlers.gpos_mark2mark(head,start,kind,lookupname,markanchors,sequence
   return head,start,false
 end
 function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence) 
-  local alreadydone=cursonce and start[a_cursbase]
+  local alreadydone=cursonce and getattr(start,a_cursbase)
   if not alreadydone then
     local done=false
-    local startchar=start.char
+    local startchar=getchar(start)
     if marks[startchar] then
       if trace_cursive then
         logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
       end
     else
-      local nxt=start.next
-      while not done and nxt and nxt.id==glyph_code and nxt.font==currentfont and nxt.subtype<256 do
-        local nextchar=nxt.char
+      local nxt=getnext(start)
+      while not done and nxt and getid(nxt)==glyph_code and getfont(nxt)==currentfont and getsubtype(nxt)<256 do
+        local nextchar=getchar(nxt)
         if marks[nextchar] then
-          nxt=nxt.next
+          nxt=getnext(nxt)
         else
           local entryanchors=descriptions[nextchar]
           if entryanchors then
@@ -10231,13 +10271,13 @@ function handlers.gpos_cursive(head,start,kind,lookupname,exitanchors,sequence)
     return head,start,done
   else
     if trace_cursive and trace_details then
-      logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone)
+      logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone)
     end
     return head,start,false
   end
 end
 function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence)
-  local startchar=start.char
+  local startchar=getchar(start)
   local dx,dy,w,h=setpair(start,tfmdata.parameters.factor,rlmode,sequence.flags[4],kerns,characters[startchar])
   if trace_kerns then
     logprocess("%s: shifting single %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),dx,dy,w,h)
@@ -10245,19 +10285,19 @@ function handlers.gpos_single(head,start,kind,lookupname,kerns,sequence)
   return head,start,false
 end
 function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
-  local snext=start.next
+  local snext=getnext(start)
   if not snext then
     return head,start,false
   else
     local prev,done=start,false
     local factor=tfmdata.parameters.factor
     local lookuptype=lookuptypes[lookupname]
-    while snext and snext.id==glyph_code and snext.font==currentfont and snext.subtype<256 do
-      local nextchar=snext.char
+    while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
+      local nextchar=getchar(snext)
       local krn=kerns[nextchar]
       if not krn and marks[nextchar] then
         prev=snext
-        snext=snext.next
+        snext=getnext(snext)
       else
         local krn=kerns[nextchar]
         if not krn then
@@ -10265,14 +10305,14 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
           if lookuptype=="pair" then 
             local a,b=krn[2],krn[3]
             if a and #a>0 then
-              local startchar=start.char
+              local startchar=getchar(start)
               local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
               if trace_kerns then
                 logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
               end
             end
             if b and #b>0 then
-              local startchar=start.char
+              local startchar=getchar(start)
               local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
               if trace_kerns then
                 logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",pref(kind,lookupname),gref(startchar),gref(nextchar),x,y,w,h)
@@ -10285,7 +10325,7 @@ function handlers.gpos_pair(head,start,kind,lookupname,kerns,sequence)
         elseif krn~=0 then
           local k=setkern(snext,factor,rlmode,krn)
           if trace_kerns then
-            logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(prev.char),gref(nextchar))
+            logprocess("%s: inserting kern %s between %s and %s",pref(kind,lookupname),k,gref(getchar(prev)),gref(nextchar))
           end
           done=true
         end
@@ -10320,13 +10360,13 @@ function chainmores.chainsub(head,start,stop,kind,chainname,currentcontext,looku
   return head,start,false
 end
 function chainprocs.reversesub(head,start,stop,kind,chainname,currentcontext,lookuphash,replacements)
-  local char=start.char
+  local char=getchar(start)
   local replacement=replacements[char]
   if replacement then
     if trace_singles then
       logprocess("%s: single reverse replacement of %s by %s",cref(kind,chainname),gref(char),gref(replacement))
     end
-    start.char=replacement
+    setfield(start,"char",replacement)
     return head,start,true
   else
     return head,start,false
@@ -10337,9 +10377,9 @@ local function delete_till_stop(start,stop,ignoremarks)
   if start==stop then
   elseif ignoremarks then
     repeat 
-      local next=start.next
-      if not marks[next.char] then
-        local components=next.components
+      local next=getnext(start)
+      if not marks[getchar(next)] then
+        local components=getfield(next,"components")
         if components then 
           flush_node_list(components)
         end
@@ -10349,8 +10389,8 @@ local function delete_till_stop(start,stop,ignoremarks)
     until next==stop
   else 
     repeat
-      local next=start.next
-      local components=next.components
+      local next=getnext(start)
+      local components=getfield(next,"components")
       if components then 
         flush_node_list(components)
       end
@@ -10367,8 +10407,8 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
     logwarning("todo: check if we need to loop over the replacements: %s",concat(subtables," "))
   end
   while current do
-    if current.id==glyph_code then
-      local currentchar=current.char
+    if getid(current)==glyph_code then
+      local currentchar=getchar(current)
       local lookupname=subtables[1] 
       local replacement=lookuphash[lookupname]
       if not replacement then
@@ -10385,14 +10425,14 @@ function chainprocs.gsub_single(head,start,stop,kind,chainname,currentcontext,lo
           if trace_singles then
             logprocess("%s: replacing single %s by %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(currentchar),gref(replacement))
           end
-          current.char=replacement
+          setfield(current,"char",replacement)
         end
       end
       return head,start,true
     elseif current==stop then
       break
     else
-      current=current.next
+      current=getnext(current)
     end
   end
   return head,start,false
@@ -10400,7 +10440,7 @@ end
 chainmores.gsub_single=chainprocs.gsub_single
 function chainprocs.gsub_multiple(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
   delete_till_stop(start,stop) 
-  local startchar=start.char
+  local startchar=getchar(start)
   local subtables=currentlookup.subtables
   local lookupname=subtables[1]
   local replacements=lookuphash[lookupname]
@@ -10429,8 +10469,8 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
   local subtables=currentlookup.subtables
   local value=featurevalue==true and tfmdata.shared.features[kind] or featurevalue
   while current do
-    if current.id==glyph_code then 
-      local currentchar=current.char
+    if getid(current)==glyph_code then 
+      local currentchar=getchar(current)
       local lookupname=subtables[1]
       local alternatives=lookuphash[lookupname]
       if not alternatives then
@@ -10445,7 +10485,7 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
             if trace_alternatives then
               logprocess("%s: replacing %s by alternative %a to %s, %s",cref(kind,chainname,chainlookupname,lookupname),gref(char),choice,gref(choice),comment)
             end
-            start.char=choice
+            setfield(start,"char",choice)
           else
             if trace_alternatives then
               logwarning("%s: no variant %a for %s, %s",cref(kind,chainname,chainlookupname,lookupname),value,gref(char),comment)
@@ -10459,14 +10499,14 @@ function chainprocs.gsub_alternate(head,start,stop,kind,chainname,currentcontext
     elseif current==stop then
       break
     else
-      current=current.next
+      current=getnext(current)
     end
   end
   return head,start,false
 end
 chainmores.gsub_alternate=chainprocs.gsub_alternate
 function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex)
-  local startchar=start.char
+  local startchar=getchar(start)
   local subtables=currentlookup.subtables
   local lookupname=subtables[1]
   local ligatures=lookuphash[lookupname]
@@ -10481,20 +10521,20 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
         logwarning("%s: no ligatures starting with %s",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
       end
     else
-      local s=start.next
+      local s=getnext(start)
       local discfound=false
       local last=stop
       local nofreplacements=0
       local skipmark=currentlookup.flags[1]
       while s do
-        local id=s.id
+        local id=getid(s)
         if id==disc_code then
-          s=s.next
+          s=getnext(s)
           discfound=true
         else
-          local schar=s.char
+          local schar=getchar(s)
           if skipmark and marks[schar] then 
-            s=s.next
+            s=getnext(s)
           else
             local lg=ligatures[schar]
             if lg then
@@ -10502,7 +10542,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
               if s==stop then
                 break
               else
-                s=s.next
+                s=getnext(s)
               end
             else
               break
@@ -10519,7 +10559,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
           if start==stop then
             logprocess("%s: replacing character %s by ligature %s case 3",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(l2))
           else
-            logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char),gref(l2))
+            logprocess("%s: replacing character %s upto %s by ligature %s case 4",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)),gref(l2))
           end
         end
         head,start=toligature(kind,lookupname,head,start,stop,l2,currentlookup.flags[1],discfound)
@@ -10528,7 +10568,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
         if start==stop then
           logwarning("%s: replacing character %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar))
         else
-          logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(stop.char))
+          logwarning("%s: replacing character %s upto %s by ligature fails",cref(kind,chainname,chainlookupname,lookupname,chainindex),gref(startchar),gref(getchar(stop)))
         end
       end
     end
@@ -10537,7 +10577,7 @@ function chainprocs.gsub_ligature(head,start,stop,kind,chainname,currentcontext,
 end
 chainmores.gsub_ligature=chainprocs.gsub_ligature
 function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
-  local markchar=start.char
+  local markchar=getchar(start)
   if marks[markchar] then
     local subtables=currentlookup.subtables
     local lookupname=subtables[1]
@@ -10546,14 +10586,14 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext
       markanchors=markanchors[markchar]
     end
     if markanchors then
-      local base=start.prev 
-      if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
-        local basechar=base.char
+      local base=getprev(start) 
+      if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+        local basechar=getchar(base)
         if marks[basechar] then
           while true do
-            base=base.prev
-            if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
-              basechar=base.char
+            base=getprev(base)
+            if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+              basechar=getchar(base)
               if not marks[basechar] then
                 break
               end
@@ -10600,7 +10640,7 @@ function chainprocs.gpos_mark2base(head,start,stop,kind,chainname,currentcontext
   return head,start,false
 end
 function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
-  local markchar=start.char
+  local markchar=getchar(start)
   if marks[markchar] then
     local subtables=currentlookup.subtables
     local lookupname=subtables[1]
@@ -10609,14 +10649,14 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon
       markanchors=markanchors[markchar]
     end
     if markanchors then
-      local base=start.prev 
-      if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
-        local basechar=base.char
+      local base=getprev(start) 
+      if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+        local basechar=getchar(base)
         if marks[basechar] then
           while true do
-            base=base.prev
-            if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then
-              basechar=base.char
+            base=getprev(base)
+            if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then
+              basechar=getchar(base)
               if not marks[basechar] then
                 break
               end
@@ -10628,7 +10668,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon
             end
           end
         end
-        local index=start[a_ligacomp]
+        local index=getattr(start,a_ligacomp)
         local baseanchors=descriptions[basechar].anchors
         if baseanchors then
           local baseanchors=baseanchors['baselig']
@@ -10667,7 +10707,7 @@ function chainprocs.gpos_mark2ligature(head,start,stop,kind,chainname,currentcon
   return head,start,false
 end
 function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
-  local markchar=start.char
+  local markchar=getchar(start)
   if marks[markchar] then
       local subtables=currentlookup.subtables
       local lookupname=subtables[1]
@@ -10676,20 +10716,20 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext
         markanchors=markanchors[markchar]
       end
       if markanchors then
-        local base=start.prev 
-        local slc=start[a_ligacomp]
+        local base=getprev(start) 
+        local slc=getattr(start,a_ligacomp)
         if slc then 
           while base do
-            local blc=base[a_ligacomp]
+            local blc=getattr(base,a_ligacomp)
             if blc and blc~=slc then
-              base=base.prev
+              base=getprev(base)
             else
               break
             end
           end
         end
-        if base and base.id==glyph_code and base.font==currentfont and base.subtype<256 then 
-          local basechar=base.char
+        if base and getid(base)==glyph_code and getfont(base)==currentfont and getsubtype(base)<256 then 
+          local basechar=getchar(base)
           local baseanchors=descriptions[basechar].anchors
           if baseanchors then
             baseanchors=baseanchors['basemark']
@@ -10725,9 +10765,9 @@ function chainprocs.gpos_mark2mark(head,start,stop,kind,chainname,currentcontext
   return head,start,false
 end
 function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname)
-  local alreadydone=cursonce and start[a_cursbase]
+  local alreadydone=cursonce and getattr(start,a_cursbase)
   if not alreadydone then
-    local startchar=start.char
+    local startchar=getchar(start)
     local subtables=currentlookup.subtables
     local lookupname=subtables[1]
     local exitanchors=lookuphash[lookupname]
@@ -10741,11 +10781,11 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
           logprocess("%s: ignoring cursive for mark %s",pref(kind,lookupname),gref(startchar))
         end
       else
-        local nxt=start.next
-        while not done and nxt and nxt.id==glyph_code and nxt.font==currentfont and nxt.subtype<256 do
-          local nextchar=nxt.char
+        local nxt=getnext(start)
+        while not done and nxt and getid(nxt)==glyph_code and getfont(nxt)==currentfont and getsubtype(nxt)<256 do
+          local nextchar=getchar(nxt)
           if marks[nextchar] then
-            nxt=nxt.next
+            nxt=getnext(nxt)
           else
             local entryanchors=descriptions[nextchar]
             if entryanchors then
@@ -10779,7 +10819,7 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
       return head,start,done
     else
       if trace_cursive and trace_details then
-        logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(start.char),alreadydone)
+        logprocess("%s, cursive %s is already done",pref(kind,lookupname),gref(getchar(start)),alreadydone)
       end
       return head,start,false
     end
@@ -10787,7 +10827,7 @@ function chainprocs.gpos_cursive(head,start,stop,kind,chainname,currentcontext,l
   return head,start,false
 end
 function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
-  local startchar=start.char
+  local startchar=getchar(start)
   local subtables=currentlookup.subtables
   local lookupname=subtables[1]
   local kerns=lookuphash[lookupname]
@@ -10803,9 +10843,9 @@ function chainprocs.gpos_single(head,start,stop,kind,chainname,currentcontext,lo
   return head,start,false
 end
 function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,lookuphash,currentlookup,chainlookupname,chainindex,sequence)
-  local snext=start.next
+  local snext=getnext(start)
   if snext then
-    local startchar=start.char
+    local startchar=getchar(start)
     local subtables=currentlookup.subtables
     local lookupname=subtables[1]
     local kerns=lookuphash[lookupname]
@@ -10815,26 +10855,26 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look
         local lookuptype=lookuptypes[lookupname]
         local prev,done=start,false
         local factor=tfmdata.parameters.factor
-        while snext and snext.id==glyph_code and snext.font==currentfont and snext.subtype<256 do
-          local nextchar=snext.char
+        while snext and getid(snext)==glyph_code and getfont(snext)==currentfont and getsubtype(snext)<256 do
+          local nextchar=getchar(snext)
           local krn=kerns[nextchar]
           if not krn and marks[nextchar] then
             prev=snext
-            snext=snext.next
+            snext=getnext(snext)
           else
             if not krn then
             elseif type(krn)=="table" then
               if lookuptype=="pair" then
                 local a,b=krn[2],krn[3]
                 if a and #a>0 then
-                  local startchar=start.char
+                  local startchar=getchar(start)
                   local x,y,w,h=setpair(start,factor,rlmode,sequence.flags[4],a,characters[startchar])
                   if trace_kerns then
                     logprocess("%s: shifting first of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
                   end
                 end
                 if b and #b>0 then
-                  local startchar=start.char
+                  local startchar=getchar(start)
                   local x,y,w,h=setpair(snext,factor,rlmode,sequence.flags[4],b,characters[nextchar])
                   if trace_kerns then
                     logprocess("%s: shifting second of pair %s and %s by (%p,%p) and correction (%p,%p)",cref(kind,chainname,chainlookupname),gref(startchar),gref(nextchar),x,y,w,h)
@@ -10846,7 +10886,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look
                 if a and a~=0 then
                   local k=setkern(snext,factor,rlmode,a)
                   if trace_kerns then
-                    logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar))
+                    logprocess("%s: inserting first kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
                   end
                 end
                 if b and b~=0 then
@@ -10857,7 +10897,7 @@ function chainprocs.gpos_pair(head,start,stop,kind,chainname,currentcontext,look
             elseif krn~=0 then
               local k=setkern(snext,factor,rlmode,krn)
               if trace_kerns then
-                logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(prev.char),gref(nextchar))
+                logprocess("%s: inserting kern %s between %s and %s",cref(kind,chainname,chainlookupname),k,gref(getchar(prev)),gref(nextchar))
               end
               done=true
             end
@@ -10894,7 +10934,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
     local seq=ck[3]
     local s=#seq
     if s==1 then
-      match=current.id==glyph_code and current.font==currentfont and current.subtype<256 and seq[1][current.char]
+      match=getid(current)==glyph_code and getfont(current)==currentfont and getsubtype(current)<256 and seq[1][getchar(current)]
     else
       local f,l=ck[4],ck[5]
       if f==1 and f==l then
@@ -10902,13 +10942,13 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
         if f==l then
         else
           local n=f+1
-          last=last.next
+          last=getnext(last)
           while n<=l do
             if last then
-              local id=last.id
+              local id=getid(last)
               if id==glyph_code then
-                if last.font==currentfont and last.subtype<256 then
-                  local char=last.char
+                if getfont(last)==currentfont and getsubtype(last)<256 then
+                  local char=getchar(last)
                   local ccd=descriptions[char]
                   if ccd then
                     local class=ccd.class
@@ -10917,10 +10957,10 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
                       if trace_skips then
                         show_skip(kind,chainname,char,ck,class)
                       end
-                      last=last.next
+                      last=getnext(last)
                     elseif seq[n][char] then
                       if n<l then
-                        last=last.next
+                        last=getnext(last)
                       end
                       n=n+1
                     else
@@ -10936,7 +10976,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
                   break
                 end
               elseif id==disc_code then
-                last=last.next
+                last=getnext(last)
               else
                 match=false
                 break
@@ -10949,15 +10989,15 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
         end
       end
       if match and f>1 then
-        local prev=start.prev
+        local prev=getprev(start)
         if prev then
           local n=f-1
           while n>=1 do
             if prev then
-              local id=prev.id
+              local id=getid(prev)
               if id==glyph_code then
-                if prev.font==currentfont and prev.subtype<256 then 
-                  local char=prev.char
+                if getfont(prev)==currentfont and getsubtype(prev)<256 then 
+                  local char=getchar(prev)
                   local ccd=descriptions[char]
                   if ccd then
                     local class=ccd.class
@@ -10987,7 +11027,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
                 match=false
                 break
               end
-              prev=prev.prev
+              prev=getprev(prev)
             elseif seq[n][32] then 
               n=n -1
             else
@@ -11007,15 +11047,15 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
         end
       end
       if match and s>l then
-        local current=last and last.next
+        local current=last and getnext(last)
         if current then
           local n=l+1
           while n<=s do
             if current then
-              local id=current.id
+              local id=getid(current)
               if id==glyph_code then
-                if current.font==currentfont and current.subtype<256 then 
-                  local char=current.char
+                if getfont(current)==currentfont and getsubtype(current)<256 then 
+                  local char=getchar(current)
                   local ccd=descriptions[char]
                   if ccd then
                     local class=ccd.class
@@ -11045,7 +11085,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
                 match=false
                 break
               end
-              current=current.next
+              current=getnext(current)
             elseif seq[n][32] then
               n=n+1
             else
@@ -11068,7 +11108,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
     if match then
       if trace_contexts then
         local rule,lookuptype,f,l=ck[1],ck[2],ck[4],ck[5]
-        local char=start.char
+        local char=getchar(start)
         if ck[9] then
           logwarning("%s: rule %s matches at char %s for (%s,%s,%s) chars, lookuptype %a, %a => %a",
             cref(kind,chainname),rule,gref(char),f-1,l-f+1,s-l,lookuptype,ck[9],ck[10])
@@ -11098,12 +11138,12 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
           repeat
             if skipped then
               while true do
-                local char=start.char
+                local char=getchar(start)
                 local ccd=descriptions[char]
                 if ccd then
                   local class=ccd.class
                   if class==skipmark or class==skipligature or class==skipbase or (markclass and class=="mark" and not markclass[char]) then
-                    start=start.next
+                    start=getnext(start)
                   else
                     break
                   end
@@ -11128,7 +11168,7 @@ local function normal_handle_contextchain(head,start,kind,chainname,contexts,seq
               i=i+1
             end
             if start then
-              start=start.next
+              start=getnext(start)
             else
             end
           until i>nofchainlookups
@@ -11255,6 +11295,7 @@ local function featuresprocessor(head,font,attr)
   if not lookuphash then
     return head,false
   end
+  head=tonut(head)
   if trace_steps then
     checkstep(head)
   end
@@ -11287,10 +11328,10 @@ local function featuresprocessor(head,font,attr)
       local handler=handlers[typ]
       local start=find_node_tail(head) 
       while start do
-        local id=start.id
+        local id=getid(start)
         if id==glyph_code then
-          if start.font==font and start.subtype<256 then
-            local a=start[0]
+          if getfont(start)==font and getsubtype(start)<256 then
+            local a=getattr(start,0)
             if a then
               a=a==attr
             else
@@ -11301,7 +11342,7 @@ local function featuresprocessor(head,font,attr)
                 local lookupname=subtables[i]
                 local lookupcache=lookuphash[lookupname]
                 if lookupcache then
-                  local lookupmatch=lookupcache[start.char]
+                  local lookupmatch=lookupcache[getchar(start)]
                   if lookupmatch then
                     head,start,success=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
                     if success then
@@ -11312,15 +11353,15 @@ local function featuresprocessor(head,font,attr)
                   report_missing_cache(typ,lookupname)
                 end
               end
-              if start then start=start.prev end
+              if start then start=getprev(start) end
             else
-              start=start.prev
+              start=getprev(start)
             end
           else
-            start=start.prev
+            start=getprev(start)
           end
         else
-          start=start.prev
+          start=getprev(start)
         end
       end
     else
@@ -11335,17 +11376,17 @@ local function featuresprocessor(head,font,attr)
           report_missing_cache(typ,lookupname)
         else
           while start do
-            local id=start.id
+            local id=getid(start)
             if id==glyph_code then
-              if start.font==font and start.subtype<256 then
-                local a=start[0]
+              if getfont(start)==font and getsubtype(start)<256 then
+                local a=getattr(start,0)
                 if a then
-                  a=(a==attr) and (not attribute or start[a_state]==attribute)
+                  a=(a==attr) and (not attribute or getattr(start,a_state)==attribute)
                 else
-                  a=not attribute or start[a_state]==attribute
+                  a=not attribute or getattr(start,a_state)==attribute
                 end
                 if a then
-                  local lookupmatch=lookupcache[start.char]
+                  local lookupmatch=lookupcache[getchar(start)]
                   if lookupmatch then
                     local ok
                     head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,1)
@@ -11353,17 +11394,17 @@ local function featuresprocessor(head,font,attr)
                       success=true
                     end
                   end
-                  if start then start=start.next end
+                  if start then start=getnext(start) end
                 else
-                  start=start.next
+                  start=getnext(start)
                 end
               else
-                start=start.next
+                start=getnext(start)
               end
             elseif id==whatsit_code then 
-              local subtype=start.subtype
+              local subtype=getsubtype(start)
               if subtype==dir_code then
-                local dir=start.dir
+                local dir=getfield(start,"dir")
                 if   dir=="+TRT" or dir=="+TLT" then
                   topstack=topstack+1
                   dirstack[topstack]=dir
@@ -11382,7 +11423,7 @@ local function featuresprocessor(head,font,attr)
                   report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
                 end
               elseif subtype==localpar_code then
-                local dir=start.dir
+                local dir=getfield(start,"dir")
                 if dir=="TRT" then
                   rlparmode=-1
                 elseif dir=="TLT" then
@@ -11395,31 +11436,31 @@ local function featuresprocessor(head,font,attr)
                   report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
                 end
               end
-              start=start.next
+              start=getnext(start)
             elseif id==math_code then
-              start=end_of_math(start).next
+              start=getnext(end_of_math(start))
             else
-              start=start.next
+              start=getnext(start)
             end
           end
         end
       else
         while start do
-          local id=start.id
+          local id=getid(start)
           if id==glyph_code then
-            if start.font==font and start.subtype<256 then
-              local a=start[0]
+            if getfont(start)==font and getsubtype(start)<256 then
+              local a=getattr(start,0)
               if a then
-                a=(a==attr) and (not attribute or start[a_state]==attribute)
+                a=(a==attr) and (not attribute or getattr(start,a_state)==attribute)
               else
-                a=not attribute or start[a_state]==attribute
+                a=not attribute or getattr(start,a_state)==attribute
               end
               if a then
                 for i=1,ns do
                   local lookupname=subtables[i]
                   local lookupcache=lookuphash[lookupname]
                   if lookupcache then
-                    local lookupmatch=lookupcache[start.char]
+                    local lookupmatch=lookupcache[getchar(start)]
                     if lookupmatch then
                       local ok
                       head,start,ok=handler(head,start,dataset[4],lookupname,lookupmatch,sequence,lookuphash,i)
@@ -11434,17 +11475,17 @@ local function featuresprocessor(head,font,attr)
                     report_missing_cache(typ,lookupname)
                   end
                 end
-                if start then start=start.next end
+                if start then start=getnext(start) end
               else
-                start=start.next
+                start=getnext(start)
               end
             else
-              start=start.next
+              start=getnext(start)
             end
           elseif id==whatsit_code then
-            local subtype=start.subtype
+            local subtype=getsubtype(start)
             if subtype==dir_code then
-              local dir=start.dir
+              local dir=getfield(start,"dir")
               if   dir=="+TRT" or dir=="+TLT" then
                 topstack=topstack+1
                 dirstack[topstack]=dir
@@ -11463,7 +11504,7 @@ local function featuresprocessor(head,font,attr)
                 report_process("directions after txtdir %a: parmode %a, txtmode %a, # stack %a, new dir %a",dir,rlparmode,rlmode,topstack,newdir)
               end
             elseif subtype==localpar_code then
-              local dir=start.dir
+              local dir=getfield(start,"dir")
               if dir=="TRT" then
                 rlparmode=-1
               elseif dir=="TLT" then
@@ -11476,11 +11517,11 @@ local function featuresprocessor(head,font,attr)
                 report_process("directions after pardir %a: parmode %a, txtmode %a",dir,rlparmode,rlmode)
               end
             end
-            start=start.next
+            start=getnext(start)
           elseif id==math_code then
-            start=end_of_math(start).next
+            start=getnext(end_of_math(start))
           else
-            start=start.next
+            start=getnext(start)
           end
         end
       end
@@ -11492,6 +11533,7 @@ local function featuresprocessor(head,font,attr)
       registerstep(head)
     end
   end
+  head=tonode(head)
   return head,done
 end
 local function generic(lookupdata,lookupname,unicode,lookuphash)
-- 
cgit v1.2.3