summaryrefslogtreecommitdiff
path: root/tex/context/base/mkxl/node-ali.lmt
diff options
context:
space:
mode:
Diffstat (limited to 'tex/context/base/mkxl/node-ali.lmt')
-rw-r--r--tex/context/base/mkxl/node-ali.lmt818
1 files changed, 584 insertions, 234 deletions
diff --git a/tex/context/base/mkxl/node-ali.lmt b/tex/context/base/mkxl/node-ali.lmt
index 0a7cf30ce..ca3c97536 100644
--- a/tex/context/base/mkxl/node-ali.lmt
+++ b/tex/context/base/mkxl/node-ali.lmt
@@ -6,50 +6,75 @@ if not modules then modules = { } end modules ['node-ali'] = {
license = "see context related readme files"
}
-local a_alignchar = attributes.private("aligncharacter")
-
-local nuts = nodes.nuts
-local tonut = nuts.tonut
-local tonode = nuts.tonode
-local getwidth = nuts.getwidth
-local setwidth = nuts.setwidth
-local getid = nuts.getid
-local getattr = nuts.getattr
-local setnext = nuts.setnext
-local getnext = nuts.getnext
-local getprev = nuts.getprev
-local setglue = nuts.setglue
-local getglue = nuts.getglue
-local getlist = nuts.getlist
-local setlist = nuts.setlist
-local setattrlist = nuts.setattrlist
-local getchar = nuts.getchar
-local addmargins = nuts.addmargins
-local findtail = nuts.tail
-local hasglyph = nuts.hasglyph
-local getwordrange = nuts.getwordrange
-local dimensions = nuts.rangedimensions
-local nextrecord = nuts.traversers.alignrecord
-local nextunset = nuts.traversers.unset
-local nextglyph = nuts.traversers.glyph
-local nextglue = nuts.traversers.glue
-local nextnode = nuts.traversers.node
-local prevnode = nuts.treversers.node
-local flushnode = nuts.flush
-local hpack = nuts.hpack
-
-local glyph_code = nodes.nodecodes.glyph
-local glue_code = nodes.nodecodes.glue
-local kern_code = nodes.nodecodes.kern
-local disc_code = nodes.nodecodes.disc
-
-local spaceskip_code = nodes.gluecodes.spaceskip
-local xspaceskip_code = nodes.gluecodes.xspaceskip
-local fontkern_code = nodes.kerncodes.fontkern
-
-local newkern = nuts.pool.kern
-local insertbefore = nuts.insertbefore
-local insertafter = nuts.insertafter
+local setmetatableindex = table.setmetatableindex
+
+local a_alignchar = attributes.private("aligncharacter")
+
+local nuts = nodes.nuts
+local tonut = nuts.tonut
+local tonode = nuts.tonode
+local getwidth = nuts.getwidth
+local setwidth = nuts.setwidth
+local getid = nuts.getid
+local getattr = nuts.getattr
+local setnext = nuts.setnext
+local getnext = nuts.getnext
+local getprev = nuts.getprev
+local setglue = nuts.setglue
+local getglue = nuts.getglue
+local setglue = nuts.setglue
+local getwhd = nuts.getwhd
+local setwhd = nuts.setwhd
+local getlist = nuts.getlist
+local setlist = nuts.setlist
+local setattrlist = nuts.setattrlist
+local setprop = nuts.setprop
+local getfont = nuts.getfont
+local getchar = nuts.getchar
+local addmargins = nuts.addmargins
+local findtail = nuts.tail
+local hasglyph = nuts.hasglyph
+local getwordrange = nuts.getwordrange
+local dimensions = nuts.rangedimensions
+local flushnode = nuts.flush
+local hpack = nuts.hpack
+local repack = nuts.repack
+local insertbefore = nuts.insertbefore
+local insertafter = nuts.insertafter
+local effectiveglue = nuts.effectiveglue
+
+local newkern = nuts.pool.kern
+local newrule = nuts.pool.rule
+local newglue = nuts.pool.glue
+
+local traversers = nuts.traversers
+local nextrecord = traversers.alignrecord
+local nextunset = traversers.unset
+local nextglyph = traversers.glyph
+local nextglue = traversers.glue
+local nextboundary = traversers.boundary
+local nextnode = traversers.node
+local nextlist = traversers.list
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+local glue_code = nodecodes.glue
+local kern_code = nodecodes.kern
+local disc_code = nodecodes.disc
+local unset_code = nodecodes.unset
+local alignrecord_code = nodecodes.alignrecord
+
+local spaceskip_code = nodes.gluecodes.spaceskip
+local xspaceskip_code = nodes.gluecodes.xspaceskip
+local intermathskip_code = nodes.gluecodes.intermathskip
+local fontkern_code = nodes.kerncodes.fontkern
+local row_code = nodes.listcodes.alignment -- should be row
+local cell_code = nodes.listcodes.cell
+local line_code = nodes.listcodes.line
+
+-- local preamble_pass <const> = tex.alignmentcontextcodes.preamble
+-- local preroll_pass <const> = tex.alignmentcontextcodes.preroll
+-- local wrapup_pass <const> = tex.alignmentcontextcodes.wrapup
-- todo statistics and tracing
@@ -57,211 +82,213 @@ local method = 2
local unislots = fonts.hashes.unislots -- todo
local chardata = fonts.hashes.characters
-function nodes.handlers.aligncharacter(head,attr,preamble)
- local attr = getattr(attr,a_alignchar) -- 1 : value doesn't matter (for now)
- if attr then
- local widths = { }
- local data = { }
- local rows = 0
- local cols = 0
- for col in nextrecord, preamble do
- cols = cols + 1
- local w, s = getwidth(col,true)
- widths[cols] = { col, w, s }
- end
- --
- for row in nextunset, head do
- rows = rows + 1
- local c = 0
- local d = { }
- data[rows] = d
- for col in nextunset, getlist(row) do
- c = c + 1
- if widths[c][2] then
- local list = getlist(col)
- -- if method == 1 then
- -- local left = nil
- -- local right = nil
- -- local middle = nil
- -- for g, char in nextglyph, list do
- -- if not left then
- -- left = g
- -- end
- -- if char == getattr(g,a_alignchar) then
- -- middle = g
- -- end
- -- right = g
- -- end
- -- d[c] = middle and { col, left, middle, right, 0, 0, getwidth(middle) } or false
- -- elseif method == 2 then
- local middle = nil
- -- we can either cache unislots or we can cache for this font
- for g, char, font in nextglyph, list do
- local unicode = getattr(g,a_alignchar)
- if unicode then
- if char == unicode then
- middle = g
- elseif unislots[font][char] == unicode then
- middle = g
+function nodes.handlers.aligncharacter(head,where,attr,preamble)
+ if where == "preroll" then
+ local attr = getattr(attr,a_alignchar) -- 1 : value doesn't matter (for now)
+ if attr then
+ local widths = { }
+ local data = { }
+ local rows = 0
+ local cols = 0
+ for col in nextrecord, preamble do
+ cols = cols + 1
+ local w, s = getwidth(col,true)
+ widths[cols] = { col, w, s }
+ end
+ --
+ for row in nextunset, head do
+ rows = rows + 1
+ local c = 0
+ local d = { }
+ data[rows] = d
+ for col in nextunset, getlist(row) do
+ c = c + 1
+ if widths[c][2] then
+ local list = getlist(col)
+ -- if method == 1 then
+ -- local left = nil
+ -- local right = nil
+ -- local middle = nil
+ -- for g, char in nextglyph, list do
+ -- if not left then
+ -- left = g
+ -- end
+ -- if char == getattr(g,a_alignchar) then
+ -- middle = g
+ -- end
+ -- right = g
+ -- end
+ -- d[c] = middle and { col, left, middle, right, 0, 0, getwidth(middle) } or false
+ -- elseif method == 2 then
+ local middle = nil
+ -- we can either cache unislots or we can cache for this font
+ for g, char, font in nextglyph, list do
+ local unicode = getattr(g,a_alignchar)
+ if unicode then
+ if char == unicode then
+ middle = g
+ elseif unislots[font][char] == unicode then
+ middle = g
+ end
end
end
- end
- if middle then
- local left, right = getwordrange(middle) -- not real gain but handy anyway (less code too)
- -- local left = middle
- -- local right = middle
- -- for g, id, subtype in nextnode, middle do
- -- if id == glyph_code or id == disc_code then
- -- right = g
- -- elseif id == kern_code and subtype == fontkern_code then
- -- right = g
- -- else
- -- break
- -- end
- -- end
- -- for g, id, subtype in prevnode, middle do
- -- if id == glyph_code or id == disc_code then
- -- left = g
- -- elseif id == kern_code and subtype == fontkern_code then
- -- left = g
- -- else
- -- break
- -- end
- -- end
- d[c] = { col, left, middle, right, 0, 0, getwidth(middle) }
- else
- d[c] = false
- end
- -- else
- -- local middle = nil
- -- for g, char in nextglyph, list do
- -- if char == getattr(g,a_alignchar) then
- -- middle = g
- -- end
- -- end
- -- if middle then
- -- local left = list
- -- local right = findtail(list)
- -- if getid(left) == glue_code then
- -- left = getnext(left)
- -- end
- -- if getid(right) == glue_code then
- -- right = getprev(right)
- -- end
- -- d[c] = { col, left, middle, right, 0, 0, getwidth(middle) }
- -- else
- -- d[c] = false
- -- end
- -- end
- else
- d[c] = false
+ if middle then
+ local left, right = getwordrange(middle) -- not real gain but handy anyway (less code too)
+ -- local left = middle
+ -- local right = middle
+ -- for g, id, subtype in nextnode, middle do
+ -- if id == glyph_code or id == disc_code then
+ -- right = g
+ -- elseif id == kern_code and subtype == fontkern_code then
+ -- right = g
+ -- else
+ -- break
+ -- end
+ -- end
+ -- for g, id, subtype in prevnode, middle do
+ -- if id == glyph_code or id == disc_code then
+ -- left = g
+ -- elseif id == kern_code and subtype == fontkern_code then
+ -- left = g
+ -- else
+ -- break
+ -- end
+ -- end
+ d[c] = { col, left, middle, right, 0, 0, getwidth(middle) }
+ else
+ d[c] = false
+ end
+ -- else
+ -- local middle = nil
+ -- for g, char in nextglyph, list do
+ -- if char == getattr(g,a_alignchar) then
+ -- middle = g
+ -- end
+ -- end
+ -- if middle then
+ -- local left = list
+ -- local right = findtail(list)
+ -- if getid(left) == glue_code then
+ -- left = getnext(left)
+ -- end
+ -- if getid(right) == glue_code then
+ -- right = getprev(right)
+ -- end
+ -- d[c] = { col, left, middle, right, 0, 0, getwidth(middle) }
+ -- else
+ -- d[c] = false
+ -- end
+ -- end
+ else
+ d[c] = false
+ end
end
end
- end
- --
- for col=1,cols do
- local maxl = 0
- local maxr = 0
- local minm = 0
- local maxm = 0
- local colw = widths[col]
- for row=1,rows do
- local d = data[row][col]
- if d then
- local p = d[1]
- local l = d[2]
- local m = d[3]
- local r = d[4]
- if m then
- local lw = l == m and 0 or dimensions(p,l,m)
- local rw = m == r and 0 or dimensions(p,getnext(m),getnext(r))
- d[5] = lw
- d[6] = rw
- if lw > maxl then
- maxl = lw
- end
- if rw > maxr then
- maxr = rw
- end
- local mw = d[7]
- if maxm == 0 then
- minm = mw
- maxm = mw
- else
- if mw > maxm then
- maxm = mw
+ --
+ for col=1,cols do
+ local maxl = 0
+ local maxr = 0
+ local minm = 0
+ local maxm = 0
+ local colw = widths[col]
+ for row=1,rows do
+ local d = data[row][col]
+ if d then
+ local p = d[1]
+ local l = d[2]
+ local m = d[3]
+ local r = d[4]
+ if m then
+ local lw = l == m and 0 or dimensions(p,l,m)
+ local rw = m == r and 0 or dimensions(p,getnext(m),getnext(r))
+ d[5] = lw
+ d[6] = rw
+ if lw > maxl then
+ maxl = lw
end
- if mw < minm then
+ if rw > maxr then
+ maxr = rw
+ end
+ local mw = d[7]
+ if maxm == 0 then
minm = mw
+ maxm = mw
+ else
+ if mw > maxm then
+ maxm = mw
+ end
+ if mw < minm then
+ minm = mw
+ end
end
end
end
end
- end
- --
- local fixedwidth = colw[3] ~= 0
- --
- local old = colw[2]
- local new = old
- for row=1,rows do
- local d = data[row][col]
- if d then
- local p = d[1]
- local l = d[2]
- local m = d[3]
- local r = d[4]
- if l and m and r then
- local lw = d[5]
- local rw = d[6]
- local mw = d[7]
- dl = maxl - lw
- dr = maxr - rw
- if dl ~= 0 or dr ~= 0 or mw ~= maxm then
- local lst = getlist(p)
- local wid = getwidth(p)
- if dl ~= 0 then
- local k = newkern(dl)
- lst = insertbefore(lst,l,k)
- setattrlist(k,m)
+ --
+ local fixedwidth = colw[3] ~= 0
+ --
+ local old = colw[2]
+ local new = old
+ for row=1,rows do
+ local d = data[row][col]
+ if d then
+ local p = d[1]
+ local l = d[2]
+ local m = d[3]
+ local r = d[4]
+ if l and m and r then
+ local lw = d[5]
+ local rw = d[6]
+ local mw = d[7]
+ dl = maxl - lw
+ dr = maxr - rw
+ if dl ~= 0 or dr ~= 0 or mw ~= maxm then
+ local lst = getlist(p)
+ local wid = getwidth(p)
+ if dl ~= 0 then
+ local k = newkern(dl)
+ lst = insertbefore(lst,l,k)
+ setattrlist(k,m)
+ setlist(p,lst)
+ wid = wid + dl
+ end
+ if dr ~= 0 then
+ local k = newkern(dr)
+ insertafter(lst,r,k)
+ setattrlist(k,m)
+ wid = wid + dr
+ end
+ if mw ~= maxm then
+ local dw = (maxm - mw)
+ local dx = dw / 2
+ addmargins(m,-dx,-dx)
+ wid = wid + dw
+ end
+ setwidth(p,wid)
+ if wid > new then
+ new = wid
+ end
setlist(p,lst)
- wid = wid + dl
- end
- if dr ~= 0 then
- local k = newkern(dr)
- insertafter(lst,r,k)
- setattrlist(k,m)
- wid = wid + dr
- end
- if mw ~= maxm then
- local dw = (maxm - mw)
- local dx = dw / 2
- addmargins(m,-dx,-dx)
- wid = wid + dw
- end
- setwidth(p,wid)
- if wid > new then
- new = wid
- end
- setlist(p,lst)
- -- somewhat fuzzy:
- if fixedwidth then
- local l = hpack(h,getwidth(p),"exactly")
- setglue(p,getglue(l))
- setlist(l)
- flushnode(l)
- else
- setglue(p)
+ -- somewhat fuzzy:
+ if fixedwidth then
+ local l = hpack(h,getwidth(p),"exactly")
+ setglue(p,getglue(l))
+ setlist(l)
+ flushnode(l)
+ else
+ setglue(p)
+ end
+ --
end
- --
end
end
end
- end
- if new > old then
- if fixedwidth then
- -- issue overflow warning
- else
- setwidth(colw[1],new)
+ if new > old then
+ if fixedwidth then
+ -- issue overflow warning
+ else
+ setwidth(colw[1],new)
+ end
end
end
end
@@ -283,3 +310,326 @@ interfaces.implement {
end,
}
+-- Let's put it here (for now):
+
+do
+
+ local getdata = nuts.getdata
+ local removenode = nuts.remove
+ local getwhd = nuts.getwhd
+ local getheight = nuts.getheight
+ local getdepth = nuts.getdepth
+ local setheight = nuts.setheight
+ local setdepth = nuts.setdepth
+ local getglue = nuts.getglue
+ local setoffsets = nuts.setoffsets
+ local setsubtype = nuts.setsubtype
+
+ local baselineskip_code = nodes.gluecodes.baselineskip
+ local lineskip_code = nodes.gluecodes.lineskip
+
+ local alignrecord_code = nodecodes.alignrecord
+ local hlist_code = nodecodes.hlist
+ local unset_code = nodecodes.unset
+
+ local nextnode = nuts.traversers.node
+
+ local texgetdimen = tex.getdimen
+ local texgetglue = tex.getglue
+ local texget = tex.get
+
+ local leftmarker = tex.boundaries.system("c_math_align_l_marker")
+ local rightmarker = tex.boundaries.system("c_math_align_r_marker")
+
+ local a_location = attributes.system("mathnumberlocation")
+ local a_threshold = attributes.system("mathnumberthreshold")
+
+ -- Here:
+
+ local function openup(specification,head)
+ local inbetween = specification.inbetween or 0
+ local height = specification.height or 0
+ local depth = specification.depth or 0
+ local lines = { }
+ for n, id, subtype, list in nextlist, head do
+ lines[#lines+1] = { n, subtype, getwhd(n) }
+ end
+ local t = #lines
+ if t > 0 then
+ local l = 1
+ for n, subtype in nextglue, head do
+ -- one day we can decide what to do with intertext stuff based on the
+ -- subtype but not now ... on our agenda (intertext etc)
+ if subtype == baselineskip_code or subtype == lineskip_code then
+ local amount, stretch, shrink = getglue(n)
+ local prevdp = lines[l] [5]
+ local nextht = lines[l+1][4]
+ local delta = 0
+ if prevdp < depth then
+ setdepth(lines[l][1],depth)
+ delta = delta + (depth - prevdp)
+ end
+ if nextht < height then
+ setheight(lines[l+1][1],height)
+ delta = delta + (height - nextht)
+ end
+ if subtype == lineskip_code then
+ setglue(n,inbetween,stretch,shrink)
+ setsubtype(n,baselineskip_code)
+ else
+ setglue(n,amount+inbetween-delta,stretch,shrink)
+ end
+ l = l + 1
+-- if l > t then
+-- break
+-- end
+ end
+ end
+ local firstht = lines[1][4]
+ local lastdp = lines[t][5]
+ if firstht < height then
+ setheight(lines[1],height)
+ end
+ if lastdp < depth then
+ setdepth(lines[t],depth)
+ end
+ end
+ end
+
+ nuts.openup = openup
+
+ -- When present, the number is after the right marker. We need to move the
+ -- number when we want it at the left.
+ --
+ -- Todo: set a flag in mathalignment and support atttibutes on it so that
+ -- we can check if this is needed.
+
+ -- [dummy] [left -2] [second -1] [number 0]
+
+ -- In the end it makes more sense to just calculate the alignment in lua
+ -- but it is kind of fun to see how we can control alignments.
+
+ local totals = { }
+ local widths = { }
+ local records = { }
+ local deltas = { }
+ local cellwidths = { }
+
+ local a_flushleft <const> = 1
+ local a_centered <const> = 2
+ local a_flushright <const> = 3
+
+ local function first_pass(head,attr,preamble)
+ --
+ local width = 0
+ local hsize = texget("hsize")
+ local count = 0
+ local overflow = false
+totals = { } -- maybe use one table
+widths = { }
+records = { }
+deltas = { }
+ for n in nextrecord, preamble do
+ local wd = getwidth(n)
+ count = count + 1
+ width = width + wd
+ totals [count] = width
+ widths [count] = wd
+ records[count] = n
+ deltas [count] = 0
+ end
+ --
+ local lindex = 0
+ local rindex = 0
+ local lwidth = 0
+ local rwidth = 0
+ local centered = false
+ for row in nextunset, head do
+ local count = 0
+ local anchor = nil
+ local rochan = nil
+ -- local cellwidths = { }
+ for cell in nextunset, getlist(row) do
+ local list = getlist(cell)
+ count = count + 1
+ cellwidths[count] = getwidth(cell)
+ for bound in nextboundary, list do
+ local marker = getdata(bound)
+ if marker == leftmarker then
+ lindex = count
+ anchor = bound
+ rochan = list
+ elseif marker == rightmarker then
+ local n = getnext(bound)
+ if n and getid(n) == hlist_code then
+ local wd, ht, dp = getwhd(n)
+ local lc = getattr(n,a_location)
+ if lc then
+ -- todo: just store align in the outer attribute so once ...
+ local align = lc // 0x10
+ local location = lc % 0x10
+ local threshold = getattr(n,a_threshold)
+ if location == 1 then
+ -- number right
+ local m = 1
+ local s = align == a_centered and 2 or 1
+-- if align == 1 then
+ if align == a_flushleft then
+ -- flushleft
+ rwidth = wd
+-- elseif align == 3 then
+ elseif align == a_flushright then
+ -- flushright
+ rwidth = wd
+ elseif wd > lwidth then
+ lwidth = wd
+ rwidth = wd
+ centered = true
+ end
+ if totals[count-2] + cellwidths[count-1] + s*wd - s*threshold > hsize then
+ local total = ht + dp
+ setdepth(row,getdepth(row) + total)
+ setoffsets(n,0,-total)
+ local pr = records[count-1]
+ local cw = getwidth(pr)
+ if cw - wd > deltas[count-1] then
+ deltas[count-1] = cw - wd
+ end
+ overflow = true
+ end
+ elseif location == 2 then
+ -- number left
+-- if align == 1 then
+ if align == a_flushleft then
+ -- flushleft
+ lwidth = wd
+-- elseif align == 3 then
+ elseif align == a_flushright then
+ -- flushright
+ lwidth = wd
+ end
+ end
+ if location == 2 and anchor then
+ local l, l, n = removenode(list,n)
+ if l ~= list then
+ setlist(cell,l)
+ -- setwidth(cell,0)
+ end
+ insertafter(rochan,anchor,n)
+ end
+ end
+ end
+ rindex = count
+ end
+ end
+ end
+ end
+ --
+ if overflow then
+ if deltas[rindex-1] ~= 0 then
+ setwidth(records[rindex-1],deltas[rindex-1])
+ end
+ end
+ for count=1,#records do
+ if count == lindex then
+ if centered and overflow then
+ lwidth = lwidth - tex.getdimen("d_math_eqalign_number_distance")
+ end
+ setwidth(records[count],lwidth)
+ elseif count == rindex then
+ setwidth(records[count],rwidth)
+ end
+ end
+ end
+
+ local function second_pass(head,attr,preamble)
+ local done = setmetatableindex("table")
+ local glues = { }
+ local okay = false
+ for row, id, subtype in nextlist, head do
+ if id == hlist_code and subtype == row_code then
+ for cell, id, subtype in nextlist, getlist(row) do
+ if id == hlist_code and subtype == cell_code then
+ for n, s in nextglue, getlist(cell) do
+ if s == intermathskip_code then
+ local e = effectiveglue(n,cell)
+ local g = getglue(n)
+ local f = getfont(n)
+ local a = done[f]
+ local d = a[g]
+ glues[n] = g
+ if not d then
+ a[g] = e
+ elseif d > e then
+ a[g] = e
+ okay = true
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+ if okay then
+ for k, v in next, glues do
+ local g = done[getfont(k)][v]
+ if g then
+ setglue(k,g)
+ setprop(k,"fixedmathalign",true)
+ end
+ end
+ for row, id, subtype in nextlist, head do
+ if id == hlist_code and subtype == row_code then
+ for cell, id, subtype, list in nextlist, getlist(row) do
+ if list and id == hlist_code and subtype == cell_code then
+ local wd = getwidth(cell)
+ repack(cell,wd,"exactly")
+ end
+ end
+ end
+ end
+ end
+ end
+
+ local function third_pass(head,attr,preamble)
+ local inbetween, stretch, shrink = texgetglue("s_strc_math_alignment_inbetween")
+ openup({ inbetween = inbetween }, head)
+ end
+
+ -- maybe zero pass: preamble pass
+
+ function nodes.handlers.fixmathalign(head,where,attr,preamble)
+ if where == "preroll" then
+ local signal = getattr(attr,a_location)
+ if signal == 0x20 or signal == 0x40 then
+ first_pass(head,attr,preamble)
+ end
+ elseif where == "wrapup" then
+ local signal = getattr(attr,a_location)
+ if signal == 0x40 then
+ second_pass(head,attr,preamble)
+ end
+ -- maybe also signal
+ third_pass(head,attr,preamble)
+ end
+ end
+end
+
+local report = logs.reporter("alignment","preamble")
+local trace trackers.register("alignments.showstates",function(v) trace = v end)
+
+function nodes.handlers.showpreamble(head,where,attr,preamble)
+ if trace then
+ local c = 0
+ for n, id in nextnode, preamble do
+ if id == unset_code or id == alignrecord_code then
+ c = c + 1
+ report("stage %a, cell %i, width %p",where,c,getwidth(n))
+ elseif id == glue_code then
+ report("stage %a, tabskip %s",where,node.direct.gluetostring(n))
+ else
+ report("stage %a, node %a",where,nodecodes[id])
+ end
+ end
+ end
+end