From 2e657baa195eb8a5011a0f08eeb32bd3396ea1bf Mon Sep 17 00:00:00 2001 From: Hans Hagen Date: Thu, 25 Jun 2020 12:13:32 +0200 Subject: 2020-06-25 10:58:00 --- tex/context/base/mkii/cont-new.mkii | 2 +- tex/context/base/mkii/context.mkii | 2 +- tex/context/base/mkiv/anch-pos.lua | 1104 +++++++++++--------- tex/context/base/mkiv/back-res.lua | 1 - tex/context/base/mkiv/buff-ini.lua | 37 +- tex/context/base/mkiv/buff-ver.lua | 2 +- tex/context/base/mkiv/buff-ver.mkiv | 4 + tex/context/base/mkiv/cldf-ini.lua | 508 +++------ tex/context/base/mkiv/cldf-int.lua | 28 +- tex/context/base/mkiv/cldf-lmt.lua | 144 ++- tex/context/base/mkiv/cldf-scn.lua | 53 +- tex/context/base/mkiv/colo-ini.mkxl | 4 +- tex/context/base/mkiv/cont-new.mkiv | 2 +- tex/context/base/mkiv/context.mkiv | 2 +- tex/context/base/mkiv/context.mkxl | 2 +- tex/context/base/mkiv/file-mod.lua | 6 +- tex/context/base/mkiv/font-ctx.lua | 612 +++++------ tex/context/base/mkiv/grph-chk.lua | 10 +- tex/context/base/mkiv/lpdf-ini.lua | 21 +- tex/context/base/mkiv/luat-ini.mkiv | 14 +- tex/context/base/mkiv/luat-usr.lua | 17 - tex/context/base/mkiv/publ-aut.lua | 6 +- tex/context/base/mkiv/status-files.pdf | Bin 27756 -> 27704 bytes tex/context/base/mkiv/status-lua.pdf | Bin 253681 -> 254484 bytes tex/context/base/mkiv/strc-itm.mklx | 42 +- tex/context/base/mkiv/strc-itm.mkvi | 42 +- tex/context/base/mkiv/syst-aux.mkxl | 6 +- tex/context/base/mkiv/syst-lua.lua | 10 +- tex/context/base/mkiv/toks-ini.lua | 4 + tex/context/base/mkiv/toks-scn.lua | 211 ++-- tex/context/base/mkiv/util-str.lua | 86 +- tex/generic/context/luatex/luatex-fonts-merged.lua | 45 +- 32 files changed, 1522 insertions(+), 1505 deletions(-) (limited to 'tex') diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii index 242fe472a..380edf717 100644 --- a/tex/context/base/mkii/cont-new.mkii +++ b/tex/context/base/mkii/cont-new.mkii @@ -11,7 +11,7 @@ %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. -\newcontextversion{2020.06.20 13:33} +\newcontextversion{2020.06.25 10:55} %D This file is loaded at runtime, thereby providing an %D excellent place for hacks, patches, extensions and new diff --git a/tex/context/base/mkii/context.mkii b/tex/context/base/mkii/context.mkii index bbe1f8fca..0cf1b1e6c 100644 --- a/tex/context/base/mkii/context.mkii +++ b/tex/context/base/mkii/context.mkii @@ -20,7 +20,7 @@ %D your styles an modules. \edef\contextformat {\jobname} -\edef\contextversion{2020.06.20 13:33} +\edef\contextversion{2020.06.25 10:55} %D For those who want to use this: diff --git a/tex/context/base/mkiv/anch-pos.lua b/tex/context/base/mkiv/anch-pos.lua index 2788c9d1a..da95eeb1a 100644 --- a/tex/context/base/mkiv/anch-pos.lua +++ b/tex/context/base/mkiv/anch-pos.lua @@ -13,16 +13,19 @@ more efficient.

--ldx]]-- -- plus (extra) is obsolete but we will keep it for a while - +-- -- maybe replace texsp by our own converter (stay at the lua end) -- eventually mp will have large numbers so we can use sp there too - --- this is one of the first modules using scanners and we need to replace --- it by implement and friends - +-- +-- this is one of the first modules using scanners and we need to replace it by +-- implement and friends +-- -- we could have namespaces, like p, page, region, columnarea, textarea but then -- we need virtual table accessors as well as have tag/id accessors ... we don't -- save much here (at least not now) +-- +-- This was the last module that got rid of directly setting scanners, with a little +-- performance degradation but not that noticeable. local tostring, next, setmetatable, tonumber = tostring, next, setmetatable, tonumber local sort = table.sort @@ -38,8 +41,7 @@ local scanstring = scanners.string local scaninteger = scanners.integer local scandimen = scanners.dimen -local compilescanner = tokens.compile -local scanners = interfaces.scanners +local implement = interfaces.implement local commands = commands local context = context @@ -124,9 +126,9 @@ local nofregular = 0 local nofspecial = 0 local splitter = lpeg.splitat(":",true) -local pagedata = { } -local columndata = setmetatableindex("table") -- per page -local freedata = setmetatableindex("table") -- per page +local pagedata = { } +local columndata = setmetatableindex("table") -- per page +local freedata = setmetatableindex("table") -- per page local function initializer() tobesaved = jobpositions.tobesaved @@ -376,19 +378,22 @@ jobpositions.set = set jobpositions.setspec = setspec jobpositions.get = get -scanners.dosaveposition = compilescanner { +implement { + name = "dosaveposition", + arguments = { "string", "integer", "dimen", "dimen" }, actions = setall, -- name p x y - arguments = { "string", "integer", "dimen", "dimen" } } -scanners.dosavepositionwhd = compilescanner { -- somehow fails +implement { + name = "dosavepositionwhd", + arguments = { "string", "integer", "dimen", "dimen", "dimen", "dimen", "dimen" }, actions = setall, -- name p x y w h d - arguments = { "string", "integer", "dimen", "dimen", "dimen", "dimen", "dimen" } } -scanners.dosavepositionplus = compilescanner { +implement { + name = "dosavepositionplus", + arguments = { "string", "integer", "dimen", "dimen", "dimen", "dimen", "dimen", "string" }, actions = setall, -- name p x y w h d extra - arguments = { "string", "integer", "dimen", "dimen", "dimen", "dimen", "dimen", "string" } } -- will become private table (could also become attribute driven but too nasty @@ -424,29 +429,41 @@ end jobpositions.b_column = b_column jobpositions.e_column = e_column -scanners.bposcolumn = function() -- tag - local tag = scanstring() - insert(columns,tag) - column = tag -end +implement { + name = "bposcolumn", + arguments = "string", + actions = function(tag) + insert(columns,tag) + column = tag + end +} -scanners.bposcolumnregistered = function() -- tag - local tag = scanstring() - insert(columns,tag) - column = tag - ctx_latelua { action = b_column, tag = tag } -end +implement { + name = "bposcolumnregistered", + arguments = "string", + actions = function(tag) + insert(columns,tag) + column = tag + ctx_latelua { action = b_column, tag = tag } + end +} -scanners.eposcolumn = function() - remove(columns) - column = columns[#columns] -end +implement { + name = "eposcolumn", + actions = function() + remove(columns) + column = columns[#columns] + end +} -scanners.eposcolumnregistered = function() - ctx_latelua { action = e_column } - remove(columns) - column = columns[#columns] -end +implement { + name = "eposcolumnregistered", + actions = function() + ctx_latelua { action = e_column } + remove(columns) + column = columns[#columns] + end +} -- regions @@ -551,167 +568,181 @@ end local nofparagraphs = 0 -scanners.parpos = function() - nofparagraphs = nofparagraphs + 1 - texsetcount("global","c_anch_positions_paragraph",nofparagraphs) - local box = getbox("strutbox") - local w, h, d = getwhd(box) - local t = { - p = true, - c = true, - r = true, - x = true, - y = true, - h = h, - d = d, - hs = texget("hsize"), -- never 0 - } - local leftskip = texget("leftskip",false) - local rightskip = texget("rightskip",false) - local hangindent = texget("hangindent") - local hangafter = texget("hangafter") - local parindent = texget("parindent") - local parshape = texget("parshape") - if leftskip ~= 0 then - t.ls = leftskip - end - if rightskip ~= 0 then - t.rs = rightskip - end - if hangindent ~= 0 then - t.hi = hangindent - end - if hangafter ~= 1 and hangafter ~= 0 then -- can not be zero .. so it needs to be 1 if zero - t.ha = hangafter - end - if parindent ~= 0 then - t.pi = parindent - end - if parshape and #parshape > 0 then - t.ps = parshape +implement { + name = "parpos", + actions = function() + nofparagraphs = nofparagraphs + 1 + texsetcount("global","c_anch_positions_paragraph",nofparagraphs) + local box = getbox("strutbox") + local w, h, d = getwhd(box) + local t = { + p = true, + c = true, + r = true, + x = true, + y = true, + h = h, + d = d, + hs = texget("hsize"), -- never 0 + } + local leftskip = texget("leftskip",false) + local rightskip = texget("rightskip",false) + local hangindent = texget("hangindent") + local hangafter = texget("hangafter") + local parindent = texget("parindent") + local parshape = texget("parshape") + if leftskip ~= 0 then + t.ls = leftskip + end + if rightskip ~= 0 then + t.rs = rightskip + end + if hangindent ~= 0 then + t.hi = hangindent + end + if hangafter ~= 1 and hangafter ~= 0 then -- can not be zero .. so it needs to be 1 if zero + t.ha = hangafter + end + if parindent ~= 0 then + t.pi = parindent + end + if parshape and #parshape > 0 then + t.ps = parshape + end + local name = f_p_tag(nofparagraphs) + tobesaved[name] = t + ctx_latelua { action = enhance, specification = t } end - local name = f_p_tag(nofparagraphs) - tobesaved[name] = t - ctx_latelua { action = enhance, specification = t } -end +} -scanners.dosetposition = function() -- name - local name = scanstring() - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetcount("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } -end +implement { + name = "dosetposition", + arguments = "string", + actions = function(name) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetcount("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end +} -scanners.dosetpositionwhd = function() -- name w h d extra - local name = scanstring() - local w = scandimen() - local h = scandimen() - local d = scandimen() - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - w = w ~= 0 and w or nil, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetcount("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } -end +implement { + name = "dosetpositionwhd", + arguments = { "string", "dimen", "dimen", "dimen" }, + actions = function(name,w,h,d) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + w = w ~= 0 and w or nil, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetcount("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end +} -scanners.dosetpositionbox = function() -- name box - local name = scanstring() - local box = getbox(scaninteger()) - local w, h, d = getwhd(box) - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - w = w ~= 0 and w or nil, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetcount("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } -end +implement { + name = "dosetpositionbox", + arguments = { "string", "integer" }, + actions = function(name,n) + local box = getbox(n) + local w, h, d = getwhd(box) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + w = w ~= 0 and w or nil, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetcount("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end +} -scanners.dosetpositionplus = function() -- name w h d extra - local name = scanstring() - local w = scandimen() - local h = scandimen() - local d = scandimen() - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - w = w ~= 0 and w or nil, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - e = scanstring(), - r2l = texgetcount("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } -end +implement { + name = "dosetpositionplus", + arguments = { "string", "dimen", "dimen", "dimen" }, + actions = function(name,w,h,d) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + w = w ~= 0 and w or nil, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + e = scanstring(), + r2l = texgetcount("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end +} -scanners.dosetpositionstrut = function() -- name - local name = scanstring() - local box = getbox("strutbox") - local w, h, d = getwhd(box) - local spec = { - p = true, - c = column, - r = true, - x = true, - y = true, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetcount("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } -end +implement { + name = "dosetpositionstrut", + arguments = "string", + actions = function(name) + local box = getbox("strutbox") + local w, h, d = getwhd(box) + local spec = { + p = true, + c = column, + r = true, + x = true, + y = true, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetcount("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end +} -scanners.dosetpositionstrutkind = function() -- name - local name = scanstring() - local kind = scaninteger() - local box = getbox("strutbox") - local w, h, d = getwhd(box) - local spec = { - k = kind, - p = true, - c = column, - r = true, - x = true, - y = true, - h = h ~= 0 and h or nil, - d = d ~= 0 and d or nil, - n = nofparagraphs > 0 and nofparagraphs or nil, - r2l = texgetcount("inlinelefttoright") == 1 or nil, - } - tobesaved[name] = spec - ctx_latelua { action = enhance, specification = spec } -end +implement { + name = "dosetpositionstrutkind", + arguments = { "string", "integer" }, + actions = function(name,kind) + local box = getbox("strutbox") + local w, h, d = getwhd(box) + local spec = { + k = kind, + p = true, + c = column, + r = true, + x = true, + y = true, + h = h ~= 0 and h or nil, + d = d ~= 0 and d or nil, + n = nofparagraphs > 0 and nofparagraphs or nil, + r2l = texgetcount("inlinelefttoright") == 1 or nil, + } + tobesaved[name] = spec + ctx_latelua { action = enhance, specification = spec } + end +} function jobpositions.getreserved(tag,n) if tag == v_column then @@ -990,166 +1021,222 @@ jobpositions.columnofpos = columnofpos -- interface -scanners.replacepospxywhd = function() -- name page x y w h d - collected[scanstring()] = { - p = scaninteger(), - x = scandimen(), - y = scandimen(), - w = scandimen(), - h = scandimen(), - d = scandimen(), - } -end +implement { + name = "replacepospxywhd", + arguments = { "string", "integer", "dimen", "dimen", "dimen", "dimen", "dimen" }, + actions = function(name,page,x,y,w,h,d) + collected[name] = { + p = page, + x = x, + y = y, + w = w, + h = h, + d = d, + } + end +} -scanners.copyposition = function() -- target source - collected[scanstring()] = collected[scanstring()] -end +implement { + name = "copyposition", + arguments = "2 strings", + actions = function(target,source) + collected[target] = collected[source] + end +} -scanners.MPp = function() -- name - local jpi = collected[scanstring()] - if jpi then - local p = jpi.p - if p and p ~= true then - context(p) - return +implement { + name = "MPp", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + local p = jpi.p + if p and p ~= true then + context(p) + return + end end + context('0') end - context('0') -end +} -scanners.MPx = function() -- name - local jpi = collected[scanstring()] - if jpi then - local x = jpi.x - if x and x ~= true and x ~= 0 then - context("%.5Fpt",x*pt) - return +implement { + name = "MPx", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + local x = jpi.x + if x and x ~= true and x ~= 0 then + context("%.5Fpt",x*pt) + return + end end + context('0pt') end - context('0pt') -end +} -scanners.MPy = function() -- name - local jpi = collected[scanstring()] - if jpi then - local y = jpi.y - if y and y ~= true and y ~= 0 then - context("%.5Fpt",y*pt) - return +implement { + name = "MPy", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + local y = jpi.y + if y and y ~= true and y ~= 0 then + context("%.5Fpt",y*pt) + return + end end + context('0pt') end - context('0pt') -end +} -scanners.MPw = function() -- name - local jpi = collected[scanstring()] - if jpi then - local w = jpi.w - if w and w ~= 0 then - context("%.5Fpt",w*pt) - return +implement { + name = "MPw", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + local w = jpi.w + if w and w ~= 0 then + context("%.5Fpt",w*pt) + return + end end + context('0pt') end - context('0pt') -end +} -scanners.MPh = function() -- name - local jpi = collected[scanstring()] - if jpi then - local h = jpi.h - if h and h ~= 0 then - context("%.5Fpt",h*pt) - return +implement { + name = "MPh", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + local h = jpi.h + if h and h ~= 0 then + context("%.5Fpt",h*pt) + return + end end + context('0pt') end - context('0pt') -end +} -scanners.MPd = function() -- name - local jpi = collected[scanstring()] - if jpi then - local d = jpi.d - if d and d ~= 0 then - context("%.5Fpt",d*pt) - return +implement { + name = "MPd", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + local d = jpi.d + if d and d ~= 0 then + context("%.5Fpt",d*pt) + return + end end + context('0pt') end - context('0pt') -end +} -scanners.MPxy = function() -- name - local jpi = collected[scanstring()] - if jpi then - context('(%.5Fpt,%.5Fpt)', - jpi.x*pt, - jpi.y*pt - ) - else - context('(0,0)') +implement { + name = "MPxy", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + context('(%.5Fpt,%.5Fpt)', + jpi.x*pt, + jpi.y*pt + ) + else + context('(0,0)') + end end -end +} -scanners.MPwhd = function() -- name - local jpi = collected[scanstring()] - if jpi then - local w = jpi.w or 0 - local h = jpi.h or 0 - local d = jpi.d or 0 - if w ~= 0 or h ~= 0 or d ~= 0 then - context("%.5Fpt,%.5Fpt,%.5Fpt",w*pt,h*pt,d*pt) - return +implement { + name = "MPwhd", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + local w = jpi.w or 0 + local h = jpi.h or 0 + local d = jpi.d or 0 + if w ~= 0 or h ~= 0 or d ~= 0 then + context("%.5Fpt,%.5Fpt,%.5Fpt",w*pt,h*pt,d*pt) + return + end end + context('0pt,0pt,0pt') end - context('0pt,0pt,0pt') -end +} -scanners.MPll = function() -- name - local jpi = collected[scanstring()] - if jpi then - context('(%.5Fpt,%.5Fpt)', - jpi.x *pt, - (jpi.y-jpi.d)*pt - ) - else - context('(0,0)') -- for mp only +implement { + name = "MPll", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + context('(%.5Fpt,%.5Fpt)', + jpi.x *pt, + (jpi.y-jpi.d)*pt + ) + else + context('(0,0)') -- for mp only + end end -end +} -scanners.MPlr = function() -- name - local jpi = collected[scanstring()] - if jpi then - context('(%.5Fpt,%.5Fpt)', - (jpi.x + jpi.w)*pt, - (jpi.y - jpi.d)*pt - ) - else - context('(0,0)') -- for mp only +implement { + name = "MPlr", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + context('(%.5Fpt,%.5Fpt)', + (jpi.x + jpi.w)*pt, + (jpi.y - jpi.d)*pt + ) + else + context('(0,0)') -- for mp only + end end -end +} -scanners.MPur = function() -- name - local jpi = collected[scanstring()] - if jpi then - context('(%.5Fpt,%.5Fpt)', - (jpi.x + jpi.w)*pt, - (jpi.y + jpi.h)*pt - ) - else - context('(0,0)') -- for mp only +implement { + name = "MPur", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + context('(%.5Fpt,%.5Fpt)', + (jpi.x + jpi.w)*pt, + (jpi.y + jpi.h)*pt + ) + else + context('(0,0)') -- for mp only + end end -end +} -scanners.MPul = function() -- name - local jpi = collected[scanstring()] - if jpi then - context('(%.5Fpt,%.5Fpt)', - jpi.x *pt, - (jpi.y + jpi.h)*pt - ) - else - context('(0,0)') -- for mp only +implement { + name = "MPul", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + context('(%.5Fpt,%.5Fpt)', + jpi.x *pt, + (jpi.y + jpi.h)*pt + ) + else + context('(0,0)') -- for mp only + end end -end +} local function MPpos(id) local jpi = collected[id] @@ -1170,53 +1257,67 @@ local function MPpos(id) context('0,0,0,0,0,0') -- for mp only end -scanners.MPpos = function() -- name - MPpos(scanstring()) -end +implement { + name = "MPpos", + arguments = "string", + actions = MPpos +} -scanners.MPn = function() -- name - local jpi = collected[scanstring()] - if jpi then - local n = jpi.n - if n then - context(n) - return +implement { + name = "MPn", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + local n = jpi.n + if n then + context(n) + return + end end + context(0) end - context(0) -end +} -scanners.MPc = function() -- name - local jpi = collected[scanstring()] - if jpi then - local c = jpi.c - if c and c ~= true then - context(c) - return +implement { + name = "MPc", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + local c = jpi.c + if c and c ~= true then + context(c) + return + end end + context('0') -- okay ? end - context('0') -- okay ? -end +} -scanners.MPr = function() -- name - local jpi = collected[scanstring()] - if jpi then - local r = jpi.r - if r and r ~= true then - context(r) - return - end - local p = jpi.p - if p then - context("page:" .. p) +implement { + name = "MPr", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + local r = jpi.r + if r and r ~= true then + context(r) + return + end + local p = jpi.p + if p then + context("page:" .. p) + end end end -end +} -local function MPpardata(n) - local t = collected[n] +local function MPpardata(id) + local t = collected[id] if not t then - local tag = f_p_tag(n) + local tag = f_p_tag(id) t = collected[tag] end if t then @@ -1233,157 +1334,213 @@ local function MPpardata(n) end end -scanners.MPpardata = function() -- name - MPpardata(scanstring()) -end +implement { + name = "MPpardata", + arguments = "string", + actions = MPpardata +} -scanners.MPposset = function() -- name (special helper, used in backgrounds) - local name = scanstring() - local b = f_b_tag(name) - local e = f_e_tag(name) - local w = f_w_tag(name) - local p = f_p_tag(getparagraph(b)) - MPpos(b) context(",") MPpos(e) context(",") MPpos(w) context(",") MPpos(p) context(",") MPpardata(p) -end +implement { + name = "MPposset", + arguments = "string", + actions = function(name) + local b = f_b_tag(name) + local e = f_e_tag(name) + local w = f_w_tag(name) + local p = f_p_tag(getparagraph(b)) + MPpos(b) context(",") MPpos(e) context(",") MPpos(w) context(",") MPpos(p) context(",") MPpardata(p) + end +} -scanners.MPls = function() -- name - local jpi = collected[scanstring()] - if jpi then - context("%.5Fpt",jpi.ls*pt) - else - context("0pt") +implement { + name = "MPls", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + context("%.5Fpt",jpi.ls*pt) + else + context("0pt") + end end -end +} -scanners.MPrs = function() -- name - local jpi = collected[scanstring()] - if jpi then - context("%.5Fpt",jpi.rs*pt) - else - context("0pt") +implement { + name = "MPrs", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + context("%.5Fpt",jpi.rs*pt) + else + context("0pt") + end end -end +} local splitter = lpeg.tsplitat(",") -scanners.MPplus = function() -- name n default - local jpi = collected[scanstring()] - local n = scaninteger() - local default = scanstring() - if jpi then - local e = jpi.e - if e then - local split = jpi.split - if not split then - split = lpegmatch(splitter,jpi.e) - jpi.split = split +implement { + name = "MPplus", + arguments = { "string", "integer", "string" }, + actions = function(name,n,default) + local jpi = collected[name] + if jpi then + local e = jpi.e + if e then + local split = jpi.split + if not split then + split = lpegmatch(splitter,jpi.e) + jpi.split = split + end + context(split[n] or default) + return end - context(split[n] or default) - return end + context(default) end - context(default) -end +} -scanners.MPrest = function() -- name default - local jpi = collected[scanstring()] - local default = scanstring() - context(jpi and jpi.e or default) -end +implement { + name = "MPrest", + arguments = { "string", "string" }, + actions = function(name,default) + local jpi = collected[name] + context(jpi and jpi.e or default) + end +} -scanners.MPxywhd = function() -- name - local jpi = collected[scanstring()] - if jpi then - context("%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt", - jpi.x*pt, - jpi.y*pt, - jpi.w*pt, - jpi.h*pt, - jpi.d*pt - ) - else - context("0,0,0,0,0") -- for mp only +implement { + name = "MPxywhd", + arguments = "string", + actions = function(name) + local jpi = collected[name] + if jpi then + context("%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt,%.5Fpt", + jpi.x*pt, + jpi.y*pt, + jpi.w*pt, + jpi.h*pt, + jpi.d*pt + ) + else + context("0,0,0,0,0") -- for mp only + end end -end +} local doif = commands.doif local doifelse = commands.doifelse -scanners.doifelseposition = function() -- name - doifelse(collected[scanstring()]) -end - -scanners.doifposition = function() -- name - doif(collected[scanstring()]) -end +implement { + name = "doifelseposition", + arguments = "string", + actions = function(name) + doifelse(collected[name]) + end +} --- local ctx_iftrue = context.protected.cs.iftrue --- local ctx_iffalse = context.protected.cs.iffalse --- --- scanners.ifknownposition = function() -- name --- (collected[scanstring()] and ctx_iftrue or ctx_iffalse)() --- end - -scanners.doifelsepositiononpage = function() -- name page -- probably always realpageno - local c = collected[scanstring()] - local p = scaninteger() - doifelse(c and c.p == p) -end +implement { + name = "doifposition", + arguments = "string", + actions = function(name) + doif(collected[name]) + end +} -scanners.doifelseoverlapping = function() -- one two - doifelse(overlapping(scanstring(),scanstring())) -end +implement { + name = "doifelsepositiononpage", + arguments = { "string", "integer" }, + actions = function(name,p) + local c = collected[name] + doifelse(c and c.p == p) + end +} -scanners.doifelsepositionsonsamepage = function() -- list - doifelse(onsamepage(scanstring())) -end +implement { + name = "doifelseoverlapping", + arguments = { "string", "string" }, + actions = function(one,two) + doifelse(overlapping(one,two)) + end +} -scanners.doifelsepositionsonthispage = function() -- list - doifelse(onsamepage(scanstring(),tostring(texgetcount("realpageno")))) -end +implement { + name = "doifelsepositionsonsamepage", + arguments = "string", + actions = function(list) + doifelse(onsamepage(list)) + end +} --- scanners.columnofpos = function() --- context(columnofpos(scaninteger(),scandimen()) --- end +implement { + name = "doifelsepositionsonthispage", + arguments = "string", + actions = function(list) + doifelse(onsamepage(list,tostring(texgetcount("realpageno")))) + end +} -scanners.doifelsepositionsused = function() - doifelse(next(collected)) -end +implement { + name = "doifelsepositionsused", + actions = function() + doifelse(next(collected)) + end +} -scanners.markregionbox = function() -- box - markregionbox(scaninteger()) -end +implement { + name = "markregionbox", + arguments = "integer", + actions = markregionbox +} -scanners.setregionbox = function() -- box - setregionbox(scaninteger()) -end +implement { + name = "setregionbox", + arguments = "integer", + actions = setregionbox +} -scanners.markregionboxtagged = function() -- box tag - markregionbox(scaninteger(),scanstring()) -end +implement { + name = "markregionboxtagged", + arguments = { "integer", "string" }, + actions = markregionbox +} -scanners.markregionboxtaggedn = function() -- box tag n - markregionbox(scaninteger(),scanstring(),nil, - nil,nil,nil,nil,nil,scaninteger()) -end +implement { + name = "markregionboxtaggedn", + arguments = { "integer", "string", "integer" }, + actions = function(box,tag,n) + markregionbox(box,tag,nil,nil,nil,nil,nil,nil,n) + end +} -scanners.setregionboxtagged = function() -- box tag - setregionbox(scaninteger(),scanstring()) -end +implement { + name = "setregionboxtagged", + arguments = { "integer", "string" }, + actions = setregionbox +} -scanners.markregionboxcorrected = function() -- box tag - markregionbox(scaninteger(),scanstring(),true) -end +implement { + name = "markregionboxcorrected", + arguments = { "integer", "string", true }, + actions = markregionbox +} -scanners.markregionboxtaggedkind = function() -- box tag kind - markregionbox(scaninteger(),scanstring(),nil, - scaninteger(),scandimen(),scandimen(),scandimen(),scandimen()) -end +implement { + name = "markregionboxtaggedkind", + arguments = { "integer", "string", "integer", "dimen", "dimen", "dimen", "dimen" }, + actions = function(box,tag,n,d1,d2,d3,d4) + markregionbox(box,tag,nil,n,d1,d2,d3,d4) + end +} -scanners.reservedautoregiontag = function() - nofregions = nofregions + 1 - context(f_region(nofregions)) -end +implement { + name = "reservedautoregiontag", + actions = function() + nofregions = nofregions + 1 + context(f_region(nofregions)) + end +} -- statistics (at least for the moment, when testing) @@ -1409,7 +1566,6 @@ end) -- We support the low level positional commands too: local newsavepos = nodes.pool.savepos -local implement = interfaces.implement implement { name = "savepos", actions = function() context(newsavepos()) end } implement { name = "lastxpos", actions = function() context(gethpos()) end } diff --git a/tex/context/base/mkiv/back-res.lua b/tex/context/base/mkiv/back-res.lua index 2ca4a5ac8..4ee6d15d3 100644 --- a/tex/context/base/mkiv/back-res.lua +++ b/tex/context/base/mkiv/back-res.lua @@ -19,7 +19,6 @@ local scandimension = scanners.dimension local scanword = scanners.word local scanwhd = scanners.whd -local scanners = interfaces.scanners local implement = interfaces.implement local constants = interfaces.constants local variables = interfaces.variables diff --git a/tex/context/base/mkiv/buff-ini.lua b/tex/context/base/mkiv/buff-ini.lua index e4f01c03f..b4290f8b1 100644 --- a/tex/context/base/mkiv/buff-ini.lua +++ b/tex/context/base/mkiv/buff-ini.lua @@ -46,8 +46,6 @@ local getcommand = token.get_command local getcsname = token.get_csname local getnextchar = token.get_next_char -local scanners = interfaces.scanners - local variables = interfaces.variables local settings_to_array = utilities.parsers.settings_to_array local formatters = string.formatters @@ -623,21 +621,26 @@ end tokens.pickup = pickup -scanners.pickupbuffer = function() - local name = scanstring() - local start = scanstring() - local stop = scanstring() - local finish = scanstring() - local catcodes = scaninteger() - local doundent = scanboolean() - local data = pickup(start,stop) - if doundent or (autoundent and doundent == nil) then - data = undent(data) - end - buffers.assign(name,data,catcodes) - -- context[finish]() - context(finish) -end +implement { + name = "pickupbuffer", + actions = function() + -- let's pickup all here (no arguments) + local name = scanstring() + local start = scanstring() + local stop = scanstring() + local finish = scanstring() + local catcodes = scaninteger() + local doundent = scanboolean() + -- could be a scanner: + local data = pickup(start,stop) + if doundent or (autoundent and doundent == nil) then + data = undent(data) + end + buffers.assign(name,data,catcodes) + -- context[finish]() + context(finish) + end +} local function savebuffer(list,name,prefix) -- name is optional if not list or list == "" then diff --git a/tex/context/base/mkiv/buff-ver.lua b/tex/context/base/mkiv/buff-ver.lua index 2bf663704..ccb8ab0df 100644 --- a/tex/context/base/mkiv/buff-ver.lua +++ b/tex/context/base/mkiv/buff-ver.lua @@ -588,7 +588,7 @@ end local function realign(lines,strip) -- "yes", local n if strip == v_yes then - n = math.huge + n = 0xFFFF for i=1, #lines do local spaces = find(lines[i],"%S") -- can be lpeg if not spaces then diff --git a/tex/context/base/mkiv/buff-ver.mkiv b/tex/context/base/mkiv/buff-ver.mkiv index 24aaa57d3..a3c27977f 100644 --- a/tex/context/base/mkiv/buff-ver.mkiv +++ b/tex/context/base/mkiv/buff-ver.mkiv @@ -1016,4 +1016,8 @@ \stopcontextdefinitioncode +%D This is \type {\asciimode} without the double comment hackery: + +\unexpanded\def\literalmode{\setcatcodetable\txtcatcodes} + \protect \endinput diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua index 8e2d6f051..9569cf357 100644 --- a/tex/context/base/mkiv/cldf-ini.lua +++ b/tex/context/base/mkiv/cldf-ini.lua @@ -26,7 +26,7 @@ if not modules then modules = { } end modules ['cldf-ini'] = { -- 0.651 local foo = getcount("ctxcatcodes") -- 0.408 local foo = getcount(ctxcatcodes) -- local ctxcatcodes = tex.iscount("ctxcatcodes") --- maybe:  (escape) or 0x2061 (apply function) or 0x2394 (software function ⎔) +-- maybe:  (escape) or 0x2061 (apply function) or 0x2394 (software function ⎔) (old) -- note : tex.print == line with endlinechar appended -- todo : context("%bold{total: }%s",total) -- todo : context.documentvariable("title") @@ -58,6 +58,20 @@ if not modules then modules = { } end modules ['cldf-ini'] = { -- time (for the better or worse). There have been no fundamental changes for many years -- and performance has not changed much either. +-- The code here has evolved over time, and was already present in the early versions of +-- mkiv. However, it got adapted when feature were added to luatex, like the ability to +-- "print" nodes and later tokens. We use to have control over the method used (if only +-- for testing) but the older code has been removed now. The history is in the archives. +-- These were the controls: + +-- local tokenflushmode = true +-- local nodeflushmode = true +-- local scannerdefmode = true +-- local maxflushnodeindex = 0x10FFFF - 1 + +-- In earlier experiments a function tables was referred to as lua.calls and the primitive +-- \luafunctions was \luacall and we used our own implementation of a function table (more +-- indirectness). local format, stripstring = string.format, string.strip local next, type, tostring, tonumber, unpack, select, rawset = next, type, tostring, tonumber, unpack, select, rawset @@ -85,9 +99,6 @@ local texprint = tex.print -- each arg a separate line (not last in ----- texwrite = tex.write -- all 'space' and 'character' local texgetcount = tex.getcount --- local function texsprint(...) print("sprint",...) tex.sprint(...) end --- local function texprint (...) print("print", ...) tex.print (...) end - local isnode = node.is_node local writenode = node.write local copynodelist = node.copy_list @@ -118,19 +129,6 @@ local report_cld = logs.reporter("cld","stack") local processlines = true -- experiments.register("context.processlines", function(v) processlines = v end) -local tokenflushmode = true -local nodeflushmode = true -local scannerdefmode = true -local maxflushnodeindex = 0x10FFFF - 1 - --- tokenflushmode = false --- nodeflushmode = false --- scannerdefmode = false - --- In earlier experiments a function tables was referred to as lua.calls and the --- primitive \luafunctions was \luacall and we used our own implementation of --- a function table (more indirectness). - local trialtypesettingstate = createtoken("trialtypesettingstate").index function context.trialtypesetting() @@ -142,7 +140,9 @@ local showstackusage = false trackers.register("context.stack",function(v) showstackusage = v end) -local freed, nofused, noffreed = { }, 0, 0 +local freed = { } +local nofused = 0 +local noffreed = 0 local usedstack = function() return nofused, noffreed @@ -208,11 +208,11 @@ local initex = environment.initex storage.register("storage/storedfunctions", storedfunctions, "storage.storedfunctions") local f_resolve = nil -local p_resolve = ((1-lpegP("."))^1 / function(s) f_resolve = f_resolve[s] end * lpegP(".")^0)^1 +local p_resolve = ((1-lpegP("."))^1 / function(s) f_resolve = f_resolve[s] end * lpegP(".")^0)^1 local function resolvestoredfunction(str) if type(str) == "string" then - f_resolve = global + f_resolve = global -- namespace lpegmatch(p_resolve,str) return f_resolve else @@ -257,9 +257,11 @@ else end end -local registerfunction = function(f,direct) -- either f=code or f=namespace,direct=name - local slot, func - if noffreed > 0 then +local registerfunction = function(f,direct,slot) -- either f=code or f=namespace,direct=name + local func + if slot then + -- already used + elseif noffreed > 0 then slot = freed[noffreed] freed[noffreed] = nil noffreed = noffreed - 1 @@ -269,12 +271,8 @@ local registerfunction = function(f,direct) -- either f=code or f=namespace,dire end if direct then if initex then - func = function(...) - expose(slot,f,...) - end - if initex then - storedfunctions[slot] = f - end + func = function(...) expose(slot,f,...) end + storedfunctions[slot] = f else func = resolvestoredfunction(f) end @@ -357,73 +355,46 @@ do end --- so far - --- The next hack is a convenient way to define scanners at the Lua end and --- get them available at the TeX end. There is some dirty magic needed to --- prevent overload during format loading. +-- The next hack is a convenient way to define scanners at the Lua end and get them +-- available at the TeX end. There is some dirty magic needed to prevent overload +-- during format loading. Nowadays we prefer to use the slightly less efficient way +-- of defining interfaces using the implementer. There is a little more overhead in +-- defining as well as runtime overhead, but we accept that. -- interfaces.scanners.foo = function() context("[%s]",tokens.scanners.string()) end : \scan_foo -interfaces.storedscanners = interfaces.storedscanners or { } -local storedscanners = interfaces.storedscanners +local storedscanners = interfaces.storedscanners or { } +local interfacescanners = { } +local privatenamespace = "clf_" -storage.register("interfaces/storedscanners", storedscanners, "interfaces.storedscanners") +interfaces.storedscanners = storedscanners -local interfacescanners = setmetatablenewindex(function(t,k,v) - rawset(t,k,v) - if storedscanners[k] then - -- report_cld("warning: scanner %a is already set (mode 1a)",k) - -- os.exit() - -- \scan_ is already in the format - -- report_cld("using interface scanner: %s",k) - elseif scannerdefmode then - -- report_cld("installing interface scanner: %s (mode 1b)",k) - -- local n = registerfunction(interfaces.scanners[k],true) - local n = registerfunction("interfaces.scanners."..k,true) - storedscanners[k] = n - local name = "clf_" .. k - setluatoken(name,n,"global") -- todo : protected and "protected" or "" - else - -- report_cld("installing interface scanner: %s (mode 1c)",k) - storedscanners[k] = true - context("\\installctxscanner{clf_%s}{interfaces.scanners.%s}",k,k) - end - -- rawset(t,k,v) -end) +storage.register("interfaces/storedscanners", storedscanners, "interfaces.storedscanners") -function interfaces.registerscanner(name,action,protected,public,value) +local function registerscanner(name,action,protected,public,value) rawset(interfacescanners,name,action) - if storedscanners[name] then - -- report_cld("warning: scanner %a is already set (mode 2a)",name) - -- os.exit() - -- \scan_ is already in the format - -- report_cld("using interface scanner: %s",k) - elseif scannerdefmode then - -- report_cld("installing interface scanner: %s (mode 2b)",name) - -- local n = registerfunction(action,true) -- todo - local n = registerfunction("interfaces.scanners."..name,true) - storedscanners[name] = n - local name = public and name or ("clf_" .. name) - setluatoken(name,n,"global",protected and "protected" or "",value and "value" or "") - else - storedscanners[name] = true - -- report_cld("installing interface scanner: %s (mode 2c)",name) - context("\\install%sctxscanner{%s%s}{interfaces.scanners.%s}", - protected and "protected" or "", - public and "" or "clf_", - name, - name - ) - end - -- rawset(interfacescanners,name,action) + local n = storedscanners[name] + n = registerfunction("interfaces.scanners."..name,true,n) + storedscanners[name] = n + name = public and name or (privatenamespace .. name) + setluatoken(name,n,"global",protected and "protected" or "",value and "value" or "") end +interfaces.registerscanner = registerscanner + +function interfaces.knownscanner(name) + return interfacescanners[name] +end + +setmetatablenewindex(interfacescanners, function(t,k,v) + report_cld("don't register scanner %a directly",k) + -- registerscanner(k,v) +end) + interfaces.scanners = storage.mark(interfacescanners) -interfaces._ = interfaces.scanners context.functions = { - register = registerfunction, + register = function(qualifiedname) return registerfunction(qualifiedname) end, -- only one argument unregister = unregisterfunction, reserve = reservefunction, known = knownfunctions, @@ -448,7 +419,7 @@ function commands.ctxresetter(name) -- to be checked return function() if storedscanners[name] then rawset(interfacescanners,name,dummy) - context.resetctxscanner("clf_" .. name) + context.resetctxscanner(privatenamespace .. name) end end end @@ -540,25 +511,11 @@ local endstripper = beginstripper * lpegP(-1) local justaspace = space * lpegCc("") local justanewline = newline * lpegCc("") -local function n_content(s) - flush(contentcatcodes,s) -end - -local function n_verbose(s) - flush(vrbcatcodes,s) -end - -local function n_endofline() - flush(currentcatcodes," \r") -end - -local function n_emptyline() - flushdirect(currentcatcodes,"\r") -end - -local function n_simpleline() - flush(currentcatcodes," \r") -end +local function n_content (s) flush (contentcatcodes,s ) end +local function n_verbose (s) flush (vrbcatcodes, s ) end +local function n_endofline () flush (currentcatcodes," \r") end +local function n_emptyline () flushdirect(currentcatcodes,"\r" ) end +local function n_simpleline() flush (currentcatcodes," \r") end local n_exception = "" @@ -646,7 +603,7 @@ function context.newverbosehandler(specification) -- a special variant for e.g. specification = specification or { } -- local f_line = specification.line or function() flushdirect("\r") end - local f_space = specification.space or function() flush(" ") end + local f_space = specification.space or function() flush (" ") end local f_content = specification.content or n_verbose local f_before = specification.before local f_after = specification.after @@ -700,20 +657,6 @@ function context.printlines(str,raw) -- todo: see if via file is useable end end --- function context.printtable(t,separator) -- todo: see if via file is useable --- if separator == nil or separator == true then --- separator = "\r" --- elseif separator == "" then --- separator = false --- end --- for i=1,#t do --- context(t[i]) -- we need to go through catcode handling --- if separator then --- context(separator) --- end --- end --- end - function context.printtable(t,separator) -- todo: see if via file is useable if separator == nil or separator == true then separator = "\r" @@ -730,22 +673,6 @@ end local containseol = patterns.containseol -local s_cldl_option_b = "[\\cldl" -local s_cldl_option_f = "[\\cldl" -- add space (not needed) -local s_cldl_option_e = "]" -local s_cldl_option_s = "\\cldl" ------ s_cldl_option_d = "\\cldd" -local s_cldl_option_d = s_cldl_option_s -local s_cldl_argument_b = "{\\cldl" -local s_cldl_argument_f = "{\\cldl " -local s_cldl_argument_e = "}" - --- local s_cldl_option_b = "[" --- local s_cldl_option_f = "" -- add space (not needed) --- local s_cldl_option_s = "" --- local s_cldl_argument_b = "{" --- local s_cldl_argument_f = "{ " - local t_cldl_luafunction = newtoken("luafunctioncall",0) local lua_expandable_call_token_code = token.command_id and token.command_id("lua_expandable_call") @@ -756,17 +683,12 @@ directives.register("context.sorthash",function(v) end) local function writer(parent,command,...) -- already optimized before call - if type(command) == "string" then -- for now flush(currentcatcodes,command) -- todo: ctx|prt|texcatcodes else flush(command) -- todo: ctx|prt|texcatcodes end - local direct = false - -- local t = { ... } - -- for i=1,#t do - -- local ti = t[i] for i=1,select("#",...) do local ti = select(i,...) if direct then @@ -849,15 +771,7 @@ local function writer(parent,command,...) -- already optimized before call local tj = ti[1] if type(tj) == "function" then tj = storefunction(tj) - if tokenflushmode then - -- if newtoken then - flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_token_code),"]") - -- else - -- flush(currentcatcodes,"[",t_cldl_luafunction,tj,"]") - -- end - else - flush(currentcatcodes,s_cldl_option_b,tj,s_cldl_option_e) - end + flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_token_code),"]") else flush(currentcatcodes,"[",tj,"]") end @@ -867,15 +781,7 @@ local function writer(parent,command,...) -- already optimized before call local tj = ti[j] if type(tj) == "function" then tj = storefunction(tj) - if tokenflushmode then - -- if newtoken then - flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_token_code),j == tn and "]" or ",") - -- else - -- flush(currentcatcodes,"[",t_cldl_luafunction,tj,j == tn and "]" or ",") - -- end - else - flush(currentcatcodes,s_cldl_option_s,tj,j == tn and "]" or ",") - end + flush(currentcatcodes,"[",newtoken(tj,lua_expandable_call_token_code),j == tn and "]" or ",") else if j == tn then flush(currentcatcodes,tj,"]") @@ -888,15 +794,7 @@ local function writer(parent,command,...) -- already optimized before call elseif typ == "function" then -- todo: ctx|prt|texcatcodes ti = storefunction(ti) - if tokenflushmode then - -- if newtoken then - flush(currentcatcodes,"{",newtoken(ti,lua_expandable_call_token_code),"}") - -- else - -- flush(currentcatcodes,"{",t_cldl_luafunction,ti,"}") - -- end - else - flush(currentcatcodes,s_cldl_argument_f,ti,s_cldl_argument_e) - end + flush(currentcatcodes,"{",newtoken(ti,lua_expandable_call_token_code),"}") elseif typ == "boolean" then if ti then flushdirect(currentcatcodes,"\r") @@ -906,16 +804,7 @@ local function writer(parent,command,...) -- already optimized before call elseif typ == "thread" then report_context("coroutines not supported as we cannot yield across boundaries") elseif isnode(ti) then -- slow | why {} here ? - if nodeflushmode then - local n = tonut(ti) - if n <= maxflushnodeindex then - flush(currentcatcodes,"{",ti,"}") - else - flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e) - end - else - flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e) - end + flush(currentcatcodes,"{",ti,"}") else local s = tostring(ti) if s then @@ -924,109 +813,47 @@ local function writer(parent,command,...) -- already optimized before call report_context("error: %a gets a weird argument %a",command,ti) end end --- else --- local n = isnode(ti) --- if n then --- if nodeflushmode and n <= maxflushnodeindex then --- flush(ti) --- else --- flush(currentcatcodes,s_cldl_argument_b,storenode(ti),s_cldl_argument_e) --- end --- else --- report_context("error: %a gets a weird argument %a",command,ti) --- end --- end + -- else + -- local n = isnode(ti) + -- if n then + -- flush(ti) + -- else + -- report_context("error: %a gets a weird argument %a",command,ti) + -- end end end end -local core +local toks = tokens.cache +context.tokenizedcs = toks -if tokenflushmode then -- combine them - - local toks = tokens.cache - - context.tokenizedcs = toks - - core = setmetatableindex(function(parent,k) - local t - local f = function(first,...) - if not t then - t = toks[k] - end - if first == nil then - flush(t) - else - return writer(context,t,first,...) - end +local core = setmetatableindex(function(parent,k) + local t + local f = function(first,...) + if not t then + t = toks[k] end - parent[k] = f - return f - end) - --- core = setmetatableindex(function(parent,k) --- local t --- local f = function(first,...) --- if not t then --- t = toks[k] --- end --- local f = function(first,...) --- if first == nil then --- flush(t) --- else --- return writer(context,t,first,...) --- end --- end --- parent[k] = f --- if first == nil then --- flush(t) --- else --- return writer(context,t,first,...) --- end --- end --- parent[k] = f --- return f --- end) - - core.cs = setmetatableindex(function(parent,k) - local t - local f = function() - if not t then - t = toks[k] - end + if first == nil then flush(t) + else + return writer(context,t,first,...) end - parent[k] = f - return f - end) - -else - - context.tokenizedcs = false - - core = setmetatableindex(function(parent,k) - local c = "\\" .. k - local f = function(first,...) - if first == nil then - flush(currentcatcodes,c) - else - return writer(context,c,first,...) - end - end - parent[k] = f - return f - end) + end + parent[k] = f + return f +end) - core.cs = setmetatableindex(function(parent,k) - local c = "\\" .. k -- tostring(k) - local f = function() - flush(currentcatcodes,c) +core.cs = setmetatableindex(function(parent,k) + local t + local f = function() + if not t then + t = toks[k] end - parent[k] = f - return f - end) - -end + flush(t) + end + parent[k] = f + return f +end) local indexer = function(parent,k) if type(k) == "string" then @@ -1122,15 +949,7 @@ local caller = function(parent,f,a,...) elseif typ == "function" then -- ignored: a ... f = storefunction(f) - if tokenflushmode then - -- if newtoken then - flush(currentcatcodes,"{",newtoken(f,lua_expandable_call_token_code),"}") - -- else - -- flush(currentcatcodes,"{",t_cldl_luafunction,f,"}") - -- end - else - flush(currentcatcodes,s_cldl_argument_b,f,s_cldl_argument_e) -- todo: ctx|prt|texcatcodes - end + flush(currentcatcodes,"{",newtoken(f,lua_expandable_call_token_code),"}") elseif typ == "boolean" then if f then if a ~= nil then @@ -1149,16 +968,7 @@ local caller = function(parent,f,a,...) elseif typ == "thread" then report_context("coroutines not supported as we cannot yield across boundaries") elseif isnode(f) then -- slow - if nodeflushmode then - local n = tonut(f) - if n <= maxflushnodeindex then - flush(f) - else - flush(currentcatcodes,s_cldl_option_s,storenode(f)," ") - end - else - flush(currentcatcodes,s_cldl_option_s,storenode(f)," ") - end + flush(f) else local s = tostring(f) if s then @@ -1167,29 +977,20 @@ local caller = function(parent,f,a,...) report_context("error: %a gets a weird argument %a","context",f) end end --- else --- local n = isnode(f) --- if n then --- if nodeflushmode and n <= maxflushnodeindex then --- flush(f) --- else --- flush(currentcatcodes,s_cldl_option_s,storenode(f)," ") --- end --- else --- report_context("error: %a gets a weird argument %a","context",f) --- end --- end + -- else + -- local n = isnode(f) + -- if n then + -- flush(f) + -- else + -- report_context("error: %a gets a weird argument %a","context",f) + -- end end end context.nodes = { -- todo store = storenode, flush = function(n) - if nodeflushmode and tonut(n) <= maxflushnodeindex then - flush(n) - else - flush(currentcatcodes,d and s_cldl_option_d or s_cldl_option_s,storenode(n)," ") - end + flush(n) end, } @@ -1198,11 +999,7 @@ context.nuts = { -- todo return storenode(tonut(n)) end, flush = function(n,d) - if nodeflushmode and n <= maxflushnodeindex then - flush(tonode(n)) - else - flush(currentcatcodes,d and s_cldl_option_d or s_cldl_option_s,storenode(tonode(n))," ") - end + flush(tonode(n)) end, } @@ -1640,22 +1437,7 @@ function context.newindexer(catcodes,cmdcodes) contentcatcodes = savedcatcodes end - if tokenflushmode then - - handler.cs = core.cs - - else - - handler.cs = setmetatableindex(function(parent,k) - local c = "\\" .. k -- tostring(k) - local f = function() - flush(cmdcodes,c) - end - parent[k] = f - return f - end) - - end + handler.cs = core.cs setmetatableindex(handler,indexer) setmetatablecall (handler,caller) @@ -1675,23 +1457,6 @@ do -- formatted.command([catcodes,]format[,...]) --- local function formattedflush(parent,c,catcodes,fmt,...) --- if type(catcodes) == "number" then --- if fmt then --- local result --- pushcatcodes(catcodes) --- result = writer(parent,c,formatters[fmt](...)) --- popcatcodes() --- return result --- else --- -- no need to change content catcodes --- return writer(parent,c) --- end --- else --- return writer(parent,c,formatters[catcodes](fmt,...)) --- end --- end - local function formattedflush(parent,c,catcodes,fmt,...) if not catcodes then return writer(parent,c) @@ -1708,51 +1473,26 @@ do end end - local indexer - - if tokenflushmode then -- combine them - - local toks = tokens.cache + local toks = tokens.cache - indexer = function(parent,k) - if type(k) == "string" then - local t - local f = function(first,...) - if not t then - t = toks[k] - end - if first == nil then - flush(t) - else - return formattedflush(parent,t,first,...) - end + local indexer = function(parent,k) + if type(k) == "string" then + local t + local f = function(first,...) + if not t then + t = toks[k] end - parent[k] = f - return f - else - return context -- catch - end - end - - else - - indexer = function(parent,k) - if type(k) == "string" then - local c = "\\" .. k - local f = function(first,...) - if first == nil then - flush(currentcatcodes,c) - else - return formattedflush(parent,c,first,...) - end + if first == nil then + flush(t) + else + return formattedflush(parent,t,first,...) end - parent[k] = f - return f - else - return context -- catch end + parent[k] = f + return f + else + return context -- catch end - end -- formatted([catcodes,]format[,...]) diff --git a/tex/context/base/mkiv/cldf-int.lua b/tex/context/base/mkiv/cldf-int.lua index 86420f422..d869f3154 100644 --- a/tex/context/base/mkiv/cldf-int.lua +++ b/tex/context/base/mkiv/cldf-int.lua @@ -313,18 +313,22 @@ else end function interfaces.tolist(t) - local r = { } - for i=1,#t do - r[i] = t[i] - end - local n = #r - for k,v in table.sortedhash(t) do - if type(k) ~= "number" then - n = n + 1 - r[n] = k .. "=" .. v + if t then + local r = { } + for i=1,#t do + r[i] = t[i] + end + local n = #r + for k,v in table.sortedhash(t) do + if type(k) ~= "number" then + n = n + 1 + r[n] = k .. "=" .. v + end end + return concat(r,", ") + else + return "" end - return concat(r,", ") end -- \startluacode @@ -358,9 +362,9 @@ end -- context.startnarrower() -- end -- --- local function stopmore(opt_1) +-- local function stopmore() -- context.stopnarrower() --- context("stop more, options: %s",interfaces.tolist(opt_1)) +-- context("stop more") -- context.stopnarrower() -- end -- diff --git a/tex/context/base/mkiv/cldf-lmt.lua b/tex/context/base/mkiv/cldf-lmt.lua index ab25f962e..4855372fa 100644 --- a/tex/context/base/mkiv/cldf-lmt.lua +++ b/tex/context/base/mkiv/cldf-lmt.lua @@ -8,8 +8,9 @@ if not modules then modules = { } end modules ['cldf-lmt'] = { local next, load = next, load -local setmetatableindex = table.setmetatableindex -local serialize = table.serialize +local setmetatableindex = table.setmetatableindex +local setmetatablenewindex = table.setmetatablenewindex +local serialize = table.serialize local random = math.random local randomseed = math.randomseed @@ -30,8 +31,12 @@ local scancardinal = scanners.luacardinal local scannumber = scanners.luanumber local scanargument = scanners.argument local scantoken = scanners.token +local scancsname = scanners.csname + local getindex = token.get_index + local texsetdimen = tex.setdimen +local texget = tex.get local values = tokens.values local none_code = values.none @@ -57,7 +62,7 @@ implement { value = true, actions = function(b) local n = scanword() - if b then + if b == "value" then context("%.99g",floats[n] or 0) else floats[n] = scannumber(true) @@ -72,7 +77,7 @@ implement { value = true, actions = function(b) local n = scanword() - if b then + if b == "value" then context("%i",integers[n] or 0) else integers[n] = scaninteger(true) @@ -86,7 +91,7 @@ implement { value = true, actions = function(b) local n = scanword() - if b then + if b == "value" then return integer_code, integers[n] or 0 else integers[n] = scancount(true) @@ -100,7 +105,7 @@ implement { value = true, actions = function(b) local n = scanword() - if b then + if b == "value" then return dimension_code, integers[n] or 0 else integers[n] = scandimen(false,false,true) @@ -114,8 +119,8 @@ implement { value = true, actions = function(b) local n = scanword() - if b then - context("%d",cardinals[n] or 0) + if b == "value" then + context("%1.0f",cardinals[n] or 0) else cardinals[n] = scancardinal(true) end @@ -128,8 +133,8 @@ implement { value = true, actions = function(b) local n = scanword() - if b then - context("%d",floats[n] or integers[n] or cardinals[n] or 0) + if b == "value" then + context("%N",floats[n] or integers[n] or cardinals[n] or 0) -- maybe %N else -- floats[n] = scanfloat(true) floats[n] = scannumber(true) @@ -142,7 +147,7 @@ implement { public = true, value = true, actions = function(b) - if b then + if b == "value" then return integer_code, random(scaninteger(),scaninteger()) else randomseed(scaninteger(true)) @@ -243,7 +248,7 @@ implement { d = d[scaninteger()] end local x = scaninteger() - if b then + if b == "value" then local code = a.code if code == float_code then context("%.99g",d[x]) @@ -258,7 +263,6 @@ implement { end, } - implement { name = "arrayequals", public = true, @@ -275,7 +279,7 @@ implement { d = d[scaninteger()] end local x = scaninteger() - if b then + if b == "value" then return boolean_code, a.scanner() == d[x] end end @@ -299,7 +303,7 @@ implement { d = d[scaninteger()] end local x = scaninteger() - if b then + if b == "value" then local v = a.scanner() local d = d[x] if d < v then @@ -379,7 +383,7 @@ implement { public = true, value = true, actions = function(b) - if b then + if b == "value" then local how = scanword() local what = scandimen() if how then @@ -417,7 +421,7 @@ local setdata = tokens.setdata local report = logs.reporter("lua table") ------ ctxsprint = context.sprint +local ctxsprint = context.sprint -- we could have an extra one that collects all end of grouped actions -- so that we dispose more in one go but it doesn's pay off @@ -607,3 +611,109 @@ context.luatables = { inspect = inspectluatable, show = showluatables, } + +-- Here's another mechanism ... + +local tables = { } +local stack = setmetatableindex("table") + +interfaces.implement { + name = "droptablegroup", + public = true, + actions = function() + local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel() + local s = stack[g] + if s then + for t, data in next, s do + for k, v in next, data do + t[k] = v + end + end + stack[g] = { } + end + end, +} + +local ctx_atendofgroup = context.core.cs.atendofgroup +local ctx_droptablegroup = context.core.cs.droptablegroup + +local function handletable(t,b,array) + if b == "value" then + local k = array and scaninteger() or scanargument() + local v = t[k] + if v then + context(v) + end + else + local data = scanargument() + data = load("return {" .. data .. "}") + if data then + data = data() + if data then + local l = t.level + local g = texget("currentgrouplevel") -- todo: tex.getgrouplevel() + local s = stack[g] + local d = s[t] + if not d then + d = { } + s[t] = d + ctx_atendofgroup() + ctx_droptablegroup() + end + for k, v in next, data do + if not d[k] then + d[k] = t[k] + end + t[k] = v + end + if b == "global" then + for k, v in next, stack do + local t = s[t] + if t then + for k, v in next, data do + if t[k] then + t[k] = nil + end + end + end + end + end + end + end + end +end + +local function newtable(array) + local name = scancsname(true) + if not tables[name] then + local t = { } + tables[name] = t + interfaces.implement { + name = name, + public = true, + value = true, + actions = function(b) + handletable(t,b,array) + end, + } + else + -- already defined + end +end + +implement { + name = "newhashedtable", + protected = true, + public = true, + actions = newtable, +} + +implement { + name = "newindexedtable", + protected = true, + public = true, + actions = function() newtable(true) end, +} + +context.hashedtables = setmetatableindex(function(t,k) return tables[k] end) +context.indexedtables = context.hashedtables diff --git a/tex/context/base/mkiv/cldf-scn.lua b/tex/context/base/mkiv/cldf-scn.lua index 1e5fe221d..fc4ea1e4a 100644 --- a/tex/context/base/mkiv/cldf-scn.lua +++ b/tex/context/base/mkiv/cldf-scn.lua @@ -8,32 +8,35 @@ if not modules then modules = { } end modules ['cldf-scn'] = { local load, type, tostring = load, type, tostring -local formatters = string.formatters -local char = string.char -local concat = table.concat +local formatters = string.formatters +local char = string.char +local concat = table.concat -local lpegmatch = lpeg.match -local p_unquoted = lpeg.Cs(lpeg.patterns.unquoted) +local lpegmatch = lpeg.match +local p_unquoted = lpeg.Cs(lpeg.patterns.unquoted) -local f_action_f = formatters["action%s(%s)"] -local f_action_s = formatters["local action%s = action[%s]"] -local f_command = formatters["local action = tokens._action\n%\nt\nreturn function(%s) return %s end"] +local f_action_f = formatters["action%s(%s)"] +local f_action_s = formatters["local action%s = action[%s]"] +local f_command = formatters["local action = tokens._action\n%\nt\nreturn function(%s) return %s end"] -local interfaces = interfaces -local commands = commands -local scanners = interfaces.scanners -local register = interfaces.registerscanner +local interfaces = interfaces +local commands = commands +local register = interfaces.registerscanner +local knownscanner = interfaces.knownscanner -local compile = tokens.compile or function() end -local presets = tokens.presets +local compile = tokens.compile or function() end +local presets = tokens.presets -local dummy = function() end +local dummy = function() end -local report = logs.reporter("interfaces","implementor") +local report = logs.reporter("interfaces","implementor") function interfaces.implement(specification) + local name = specification.name + if name == "" then + name = nil + end local actions = specification.actions - local name = specification.name local arguments = specification.arguments local private = specification.scope == "private" local onlyonce = specification.onlyonce @@ -45,9 +48,6 @@ function interfaces.implement(specification) end return end - if name == "" then - name = nil - end local p = arguments and presets[arguments] if p then arguments = p @@ -74,8 +74,8 @@ function interfaces.implement(specification) if not name then return scanner end - if scanners[name] and not specification.overload then - report("warning: 'scanners.%s' is redefined",name) + if knownscanner(name) and not specification.overload then + report("warning: interface scanner %a is overloaded",name) end register(name,scanner,specification.protected,specification.public,specification.value) if private then @@ -160,12 +160,3 @@ interfaces.defined = tokens.defined interfaces.setmacro = tokens.setters.macro interfaces.setcount = tokens.setters.count interfaces.setdimen = tokens.setters.dimen - -interfaces.strings = table.setmetatableindex(function(t,k) - local v = { } - for i=1,k do - v[i] = "string" - end - t[k] = v - return v -end) diff --git a/tex/context/base/mkiv/colo-ini.mkxl b/tex/context/base/mkiv/colo-ini.mkxl index 63d29d0a6..724316629 100644 --- a/tex/context/base/mkiv/colo-ini.mkxl +++ b/tex/context/base/mkiv/colo-ini.mkxl @@ -250,8 +250,8 @@ %D The following command is obsolete: -\unexpanded\def\startcolorpage {\startcolor[\ifempty\maintextcolor\defaulttextcolor\else\maintextcolor\fi]} -\unexpanded\def\stopcolorpage {\stopcolor} +\unexpanded\def\startcolorpage{\startcolor[\ifempty\maintextcolor\defaulttextcolor\else\maintextcolor\fi]} +\unexpanded\def\stopcolorpage {\stopcolor} \unexpanded\def\getcolorattributevalue#1#2% obsolete, use \thecolorattribute instead ... {\begingroup diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv index bdee367d1..3b01c297e 100644 --- a/tex/context/base/mkiv/cont-new.mkiv +++ b/tex/context/base/mkiv/cont-new.mkiv @@ -13,7 +13,7 @@ % \normalend % uncomment this to get the real base runtime -\newcontextversion{2020.06.20 13:33} +\newcontextversion{2020.06.25 10:55} %D This file is loaded at runtime, thereby providing an excellent place for hacks, %D patches, extensions and new features. There can be local overloads in cont-loc diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv index f5d02a708..bbefc17e6 100644 --- a/tex/context/base/mkiv/context.mkiv +++ b/tex/context/base/mkiv/context.mkiv @@ -45,7 +45,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2020.06.20 13:33} +\edef\contextversion{2020.06.25 10:55} \edef\contextkind {beta} %D Kind of special: diff --git a/tex/context/base/mkiv/context.mkxl b/tex/context/base/mkiv/context.mkxl index e69d387f2..45a8e2f2f 100644 --- a/tex/context/base/mkiv/context.mkxl +++ b/tex/context/base/mkiv/context.mkxl @@ -29,7 +29,7 @@ %D {YYYY.MM.DD HH:MM} format. \edef\contextformat {\jobname} -\edef\contextversion{2020.06.20 13:33} +\edef\contextversion{2020.06.25 10:55} \edef\contextkind {beta} %D Kind of special: diff --git a/tex/context/base/mkiv/file-mod.lua b/tex/context/base/mkiv/file-mod.lua index 10a187178..c10e557c7 100644 --- a/tex/context/base/mkiv/file-mod.lua +++ b/tex/context/base/mkiv/file-mod.lua @@ -246,18 +246,16 @@ function environment.useluamodule(list) end end -local strings = interfaces.strings - implement { name = "usemodules", actions = environment.usemodules, - arguments = strings[2] + arguments = "2 strings", } implement { name = "doifelseolderversion", actions = function(one,two) commands.doifelse(comparedversion(one,two) >= 0) end, - arguments = strings[2] + arguments = "2 strings" } implement { diff --git a/tex/context/base/mkiv/font-ctx.lua b/tex/context/base/mkiv/font-ctx.lua index 9e59c66bc..3b2676667 100644 --- a/tex/context/base/mkiv/font-ctx.lua +++ b/tex/context/base/mkiv/font-ctx.lua @@ -1168,69 +1168,56 @@ local specifiers = { } do -- else too many locals - ----- ctx_setdefaultfontname = context.fntsetdefname - ----- ctx_setsomefontname = context.fntsetsomename - ----- ctx_setemptyfontsize = context.fntsetnopsize - ----- ctx_setsomefontsize = context.fntsetsomesize - ----- ctx_letvaluerelax = context.letvaluerelax + local starttiming = statistics.starttiming + local stoptiming = statistics.stoptiming - local starttiming = statistics.starttiming - local stoptiming = statistics.stoptiming + local setmacro = tokens.setters.macro - local scanners = tokens.scanners - local scanstring = scanners.string - local scaninteger = scanners.integer - local scannumber = scanners.number - local scanboolean = scanners.boolean - - local setmacro = tokens.setters.macro - local scanners = interfaces.scanners - - -- function commands.definefont_one(str) - - scanners.definefont_one = function() - local str = scanstring() - - starttiming(fonts) - if trace_defining then - report_defining("memory usage before: %s",statistics.memused()) - report_defining("start stage one: %s",str) - end - local fullname, size = lpegmatch(splitpattern,str) - local lookup, name, sub, method, detail = getspecification(fullname) - if not name then - report_defining("strange definition %a",str) - -- ctx_setdefaultfontname() - elseif name == "unknown" then - -- ctx_setdefaultfontname() - else - -- ctx_setsomefontname(name) - setmacro("somefontname",name,"global") - end - -- we can also use a count for the size - if size and size ~= "" then - local mode, size = lpegmatch(sizepattern,size) - if size and mode then - texsetcount("scaledfontmode",mode) - -- ctx_setsomefontsize(size) - setmacro("somefontsize",size) + implement { + name = "definefont_one", + arguments = "string", + actions = function(str) + starttiming(fonts) + if trace_defining then + report_defining("memory usage before: %s",statistics.memused()) + report_defining("start stage one: %s",str) + end + local fullname, size = lpegmatch(splitpattern,str) + local lookup, name, sub, method, detail = getspecification(fullname) + if not name then + report_defining("strange definition %a",str) + -- ctx_setdefaultfontname() + elseif name == "unknown" then + -- ctx_setdefaultfontname() + else + -- ctx_setsomefontname(name) + setmacro("somefontname",name,"global") + end + -- we can also use a count for the size + if size and size ~= "" then + local mode, size = lpegmatch(sizepattern,size) + if size and mode then + texsetcount("scaledfontmode",mode) + -- ctx_setsomefontsize(size) + setmacro("somefontsize",size) + else + texsetcount("scaledfontmode",0) + -- ctx_setemptyfontsize() + end + elseif true then + -- so we don't need to check in tex + texsetcount("scaledfontmode",2) + -- ctx_setemptyfontsize() else texsetcount("scaledfontmode",0) -- ctx_setemptyfontsize() end - elseif true then - -- so we don't need to check in tex - texsetcount("scaledfontmode",2) - -- ctx_setemptyfontsize() - else - texsetcount("scaledfontmode",0) - -- ctx_setemptyfontsize() - end - specification = definers.makespecification(str,lookup,name,sub,method,detail,size) - if trace_defining then - report_defining("stop stage one") + specification = definers.makespecification(str,lookup,name,sub,method,detail,size) + if trace_defining then + report_defining("stop stage one") + end end - end + } local function nice_cs(cs) return (gsub(cs,".->", "")) @@ -1244,179 +1231,228 @@ do -- else too many locals combinefeatures = v end) - scanners.definefont_two = function() - local global = scanboolean() -- \ifx\fontclass\empty\s!false\else\s!true\fi - local cs = scanstring () -- {#csname}% - local str = scanstring () -- \somefontfile - local size = scaninteger() -- \d_font_scaled_font_size - local inheritancemode = scaninteger() -- \c_font_feature_inheritance_mode - local classfeatures = scanstring () -- \m_font_class_features - local fontfeatures = scanstring () -- \m_font_features - local classfallbacks = scanstring () -- \m_font_class_fallbacks - local fontfallbacks = scanstring () -- \m_font_fallbacks - local mathsize = scaninteger() -- \fontface - local textsize = scaninteger() -- \d_font_scaled_text_face - local relativeid = scaninteger() -- \relativefontid - local classgoodies = scanstring () -- \m_font_class_goodies - local goodies = scanstring () -- \m_font_goodies - local classdesignsize = scanstring () -- \m_font_class_designsize - local fontdesignsize = scanstring () -- \m_font_designsize - local scaledfontmode = scaninteger() -- \scaledfontmode - - if trace_defining then - report_defining("start stage two: %s, size %s, features %a & %a, mode %a",str,size,classfeatures,fontfeatures,inheritancemode) - end - -- name is now resolved and size is scaled cf sa/mo - local lookup, name, sub, method, detail = getspecification(str or "") - -- new (todo: inheritancemode) - local designsize = fontdesignsize ~= "" and fontdesignsize or classdesignsize or "" - local designname = designsizefilename(name,designsize,size) - if designname and designname ~= "" then - if trace_defining or trace_designsize then - report_defining("remapping name %a, specification %a, size %a, designsize %a",name,designsize,size,designname) - end - -- we don't catch detail here - local o_lookup, o_name, o_sub, o_method, o_detail = getspecification(designname) - if o_lookup and o_lookup ~= "" then lookup = o_lookup end - if o_method and o_method ~= "" then method = o_method end - if o_detail and o_detail ~= "" then detail = o_detail end - name = o_name - sub = o_sub - end - -- so far - -- some settings can have been overloaded - if lookup and lookup ~= "" then - specification.lookup = lookup - end - if relativeid and relativeid ~= "" then -- experimental hook - local id = tonumber(relativeid) or 0 - specification.relativeid = id > 0 and id - end - -- - specification.name = name - specification.size = size - specification.sub = (sub and sub ~= "" and sub) or specification.sub - specification.mathsize = mathsize - specification.textsize = textsize - specification.goodies = goodies - specification.cs = cs - specification.global = global - specification.scalemode = scaledfontmode -- context specific - if detail and detail ~= "" then - specification.method = method or "*" - specification.detail = detail - elseif specification.detail and specification.detail ~= "" then - -- already set - elseif inheritancemode == 0 then - -- nothing - elseif inheritancemode == 1 then - -- fontonly - if fontfeatures and fontfeatures ~= "" then - specification.method = "*" - specification.detail = fontfeatures - end - if fontfallbacks and fontfallbacks ~= "" then - specification.fallbacks = fontfallbacks - end - elseif inheritancemode == 2 then - -- classonly - if classfeatures and classfeatures ~= "" then - specification.method = "*" - specification.detail = classfeatures - end - if classfallbacks and classfallbacks ~= "" then - specification.fallbacks = classfallbacks - end - elseif inheritancemode == 3 then - -- fontfirst - if combinefeatures then - if classfeatures and classfeatures ~= "" then - specification.method = "*" - if fontfeatures and fontfeatures ~= "" and fontfeatures ~= classfeatures then - specification.detail = classfeatures .. "," .. fontfeatures - else - specification.detail = classfeatures - end - elseif fontfeatures and fontfeatures ~= "" then - specification.method = "*" - specification.detail = fontfeatures + + + + + + implement { + name = "definefont_two", + arguments = { + "boolean", "string", "string", "integer", "integer", "string", "string", "string", "string", + "integer", "integer", "integer", "string", "string", "string", "string", "integer", + }, + actions = function ( + global, -- \ifx\fontclass\empty\s!false\else\s!true\fi + cs, -- {#csname}% + str, -- \somefontfile + size, -- \d_font_scaled_font_size + inheritancemode, -- \c_font_feature_inheritance_mode + classfeatures, -- \m_font_class_features + fontfeatures, -- \m_font_features + classfallbacks, -- \m_font_class_fallbacks + fontfallbacks, -- \m_font_fallbacks + mathsize, -- \fontface + textsize, -- \d_font_scaled_text_face + relativeid, -- \relativefontid + classgoodies, -- \m_font_class_goodies + goodies, -- \m_font_goodies + classdesignsize, -- \m_font_class_designsize + fontdesignsize, -- \m_font_designsize + scaledfontmode -- \scaledfontmode + ) + + if trace_defining then + report_defining("start stage two: %s, size %s, features %a & %a, mode %a",str,size,classfeatures,fontfeatures,inheritancemode) + end + -- name is now resolved and size is scaled cf sa/mo + local lookup, name, sub, method, detail = getspecification(str or "") + -- new (todo: inheritancemode) + local designsize = fontdesignsize ~= "" and fontdesignsize or classdesignsize or "" + local designname = designsizefilename(name,designsize,size) + if designname and designname ~= "" then + if trace_defining or trace_designsize then + report_defining("remapping name %a, specification %a, size %a, designsize %a",name,designsize,size,designname) end - else + -- we don't catch detail here + local o_lookup, o_name, o_sub, o_method, o_detail = getspecification(designname) + if o_lookup and o_lookup ~= "" then lookup = o_lookup end + if o_method and o_method ~= "" then method = o_method end + if o_detail and o_detail ~= "" then detail = o_detail end + name = o_name + sub = o_sub + end + -- so far + -- some settings can have been overloaded + if lookup and lookup ~= "" then + specification.lookup = lookup + end + if relativeid and relativeid ~= "" then -- experimental hook + local id = tonumber(relativeid) or 0 + specification.relativeid = id > 0 and id + end + -- + specification.name = name + specification.size = size + specification.sub = (sub and sub ~= "" and sub) or specification.sub + specification.mathsize = mathsize + specification.textsize = textsize + specification.goodies = goodies + specification.cs = cs + specification.global = global + specification.scalemode = scaledfontmode -- context specific + if detail and detail ~= "" then + specification.method = method or "*" + specification.detail = detail + elseif specification.detail and specification.detail ~= "" then + -- already set + elseif inheritancemode == 0 then + -- nothing + elseif inheritancemode == 1 then + -- fontonly if fontfeatures and fontfeatures ~= "" then specification.method = "*" specification.detail = fontfeatures - elseif classfeatures and classfeatures ~= "" then + end + if fontfallbacks and fontfallbacks ~= "" then + specification.fallbacks = fontfallbacks + end + elseif inheritancemode == 2 then + -- classonly + if classfeatures and classfeatures ~= "" then specification.method = "*" specification.detail = classfeatures end - end - if fontfallbacks and fontfallbacks ~= "" then - specification.fallbacks = fontfallbacks - elseif classfallbacks and classfallbacks ~= "" then - specification.fallbacks = classfallbacks - end - elseif inheritancemode == 4 then - -- classfirst - if combinefeatures then - if fontfeatures and fontfeatures ~= "" then - specification.method = "*" - if classfeatures and classfeatures ~= "" and classfeatures ~= fontfeatures then - specification.detail = fontfeatures .. "," .. classfeatures - else + if classfallbacks and classfallbacks ~= "" then + specification.fallbacks = classfallbacks + end + elseif inheritancemode == 3 then + -- fontfirst + if combinefeatures then + if classfeatures and classfeatures ~= "" then + specification.method = "*" + if fontfeatures and fontfeatures ~= "" and fontfeatures ~= classfeatures then + specification.detail = classfeatures .. "," .. fontfeatures + else + specification.detail = classfeatures + end + elseif fontfeatures and fontfeatures ~= "" then + specification.method = "*" specification.detail = fontfeatures end - elseif classfeatures and classfeatures ~= "" then - specification.method = "*" - specification.detail = classfeatures + else + if fontfeatures and fontfeatures ~= "" then + specification.method = "*" + specification.detail = fontfeatures + elseif classfeatures and classfeatures ~= "" then + specification.method = "*" + specification.detail = classfeatures + end end - else - if classfeatures and classfeatures ~= "" then - specification.method = "*" - specification.detail = classfeatures - elseif fontfeatures and fontfeatures ~= "" then - specification.method = "*" - specification.detail = fontfeatures + if fontfallbacks and fontfallbacks ~= "" then + specification.fallbacks = fontfallbacks + elseif classfallbacks and classfallbacks ~= "" then + specification.fallbacks = classfallbacks + end + elseif inheritancemode == 4 then + -- classfirst + if combinefeatures then + if fontfeatures and fontfeatures ~= "" then + specification.method = "*" + if classfeatures and classfeatures ~= "" and classfeatures ~= fontfeatures then + specification.detail = fontfeatures .. "," .. classfeatures + else + specification.detail = fontfeatures + end + elseif classfeatures and classfeatures ~= "" then + specification.method = "*" + specification.detail = classfeatures + end + else + if classfeatures and classfeatures ~= "" then + specification.method = "*" + specification.detail = classfeatures + elseif fontfeatures and fontfeatures ~= "" then + specification.method = "*" + specification.detail = fontfeatures + end + end + if classfallbacks and classfallbacks ~= "" then + specification.fallbacks = classfallbacks + elseif fontfallbacks and fontfallbacks ~= "" then + specification.fallbacks = fontfallbacks end end - if classfallbacks and classfallbacks ~= "" then - specification.fallbacks = classfallbacks - elseif fontfallbacks and fontfallbacks ~= "" then - specification.fallbacks = fontfallbacks - end - end - -- - local tfmdata = definers.read(specification,size) -- id not yet known (size in spec?) - -- - local lastfontid = 0 - local tfmtype = type(tfmdata) - if tfmtype == "table" then - -- setting the extra characters will move elsewhere - local characters = tfmdata.characters - local parameters = tfmdata.parameters - local properties = tfmdata.properties - -- we use char0 as signal; cf the spec pdf can handle this (no char in slot) - characters[0] = nil - -- characters[0x00A0] = { width = parameters.space } - -- characters[0x2007] = { width = characters[0x0030] and characters[0x0030].width or parameters.space } -- figure - -- characters[0x2008] = { width = characters[0x002E] and characters[0x002E].width or parameters.space } -- period -- - local fallbacks = specification.fallbacks or "" - local mathsize = (mathsize == 1 or mathsize == 2 or mathsize == 3) and mathsize or nil -- can be unset so we test 1 2 3 - if fallbacks ~= "" and mathsize and not busy then - busy = true - -- We need this ugly hack in order to resolve fontnames (at the \TEX end). Originally - -- math was done in Lua after loading (plugged into aftercopying). + local tfmdata = definers.read(specification,size) -- id not yet known (size in spec?) + -- + local lastfontid = 0 + local tfmtype = type(tfmdata) + if tfmtype == "table" then + -- setting the extra characters will move elsewhere + local characters = tfmdata.characters + local parameters = tfmdata.parameters + local properties = tfmdata.properties + -- we use char0 as signal; cf the spec pdf can handle this (no char in slot) + characters[0] = nil + -- characters[0x00A0] = { width = parameters.space } + -- characters[0x2007] = { width = characters[0x0030] and characters[0x0030].width or parameters.space } -- figure + -- characters[0x2008] = { width = characters[0x002E] and characters[0x002E].width or parameters.space } -- period -- - -- After tl 2017 I'll also do text fallbacks this way (although backups there are done - -- in a completely different way.) - if trace_defining then - report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a", - name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,1) - end - mathematics.resolvefallbacks(tfmdata,specification,fallbacks) - context(function() - busy = false - mathematics.finishfallbacks(tfmdata,specification,fallbacks) + local fallbacks = specification.fallbacks or "" + local mathsize = (mathsize == 1 or mathsize == 2 or mathsize == 3) and mathsize or nil -- can be unset so we test 1 2 3 + if fallbacks ~= "" and mathsize and not busy then + busy = true + -- We need this ugly hack in order to resolve fontnames (at the \TEX end). Originally + -- math was done in Lua after loading (plugged into aftercopying). + -- + -- After tl 2017 I'll also do text fallbacks this way (although backups there are done + -- in a completely different way.) + if trace_defining then + report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a", + name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,1) + end + mathematics.resolvefallbacks(tfmdata,specification,fallbacks) + context(function() + busy = false + mathematics.finishfallbacks(tfmdata,specification,fallbacks) + local id = definefont(tfmdata) + csnames[id] = specification.cs + properties.id = id + definers.register(tfmdata,id) -- to be sure, normally already done + texdefinefont(global,cs,id) + constructors.cleanuptable(tfmdata) + constructors.finalize(tfmdata) + if trace_defining then + report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a", + name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,2) + end + -- resolved (when designsize is used): + local size = round(tfmdata.parameters.size or 655360) + setmacro("somefontsize",size.."sp") + -- ctx_setsomefontsize(size .. "sp") + texsetcount("scaledfontsize",size) + lastfontid = id + -- + if trace_defining then + report_defining("memory usage after: %s",statistics.memused()) + report_defining("stop stage two") + end + -- + texsetcount("global","lastfontid",lastfontid) + specifiers[lastfontid] = { str, size } + if not mathsize then + -- forget about it (can't happen here) + elseif mathsize == 0 then + -- can't happen (here) + else + -- maybe only 1 2 3 (we already test for this) + lastmathids[mathsize] = lastfontid + end + stoptiming(fonts) + end) + return + else local id = definefont(tfmdata) csnames[id] = specification.cs properties.id = id @@ -1426,7 +1462,7 @@ do -- else too many locals constructors.finalize(tfmdata) if trace_defining then report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a", - name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,2) + name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,"-") end -- resolved (when designsize is used): local size = round(tfmdata.parameters.size or 655360) @@ -1434,102 +1470,78 @@ do -- else too many locals -- ctx_setsomefontsize(size .. "sp") texsetcount("scaledfontsize",size) lastfontid = id - -- - if trace_defining then - report_defining("memory usage after: %s",statistics.memused()) - report_defining("stop stage two") - end - -- - texsetcount("global","lastfontid",lastfontid) - specifiers[lastfontid] = { str, size } - if not mathsize then - -- forget about it (can't happen here) - elseif mathsize == 0 then - -- can't happen (here) - else - -- maybe only 1 2 3 (we already test for this) - lastmathids[mathsize] = lastfontid - end - stoptiming(fonts) - end) - return - else - local id = definefont(tfmdata) - csnames[id] = specification.cs - properties.id = id - definers.register(tfmdata,id) -- to be sure, normally already done - texdefinefont(global,cs,id) - constructors.cleanuptable(tfmdata) - constructors.finalize(tfmdata) + end + elseif tfmtype == "number" then if trace_defining then - report_defining("defining %a, id %a, target %a, features %a / %a, fallbacks %a / %a, step %a", - name,id,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,"-") + report_defining("reusing %s, id %a, target %a, features %a / %a, fallbacks %a / %a, goodies %a / %a, designsize %a / %a", + name,tfmdata,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,classgoodies,goodies,classdesignsize,fontdesignsize) end + csnames[tfmdata] = specification.cs + texdefinefont(global,cs,tfmdata) -- resolved (when designsize is used): - local size = round(tfmdata.parameters.size or 655360) - setmacro("somefontsize",size.."sp") + local size = round(fontdata[tfmdata].parameters.size or 0) -- ctx_setsomefontsize(size .. "sp") + setmacro("somefontsize",size.."sp") texsetcount("scaledfontsize",size) - lastfontid = id + lastfontid = tfmdata + else + report_defining("unable to define %a as %a",name,nice_cs(cs)) + lastfontid = -1 + texsetcount("scaledfontsize",0) + -- ctx_letvaluerelax(cs) -- otherwise the current definition takes the previous one end - elseif tfmtype == "number" then if trace_defining then - report_defining("reusing %s, id %a, target %a, features %a / %a, fallbacks %a / %a, goodies %a / %a, designsize %a / %a", - name,tfmdata,nice_cs(cs),classfeatures,fontfeatures,classfallbacks,fontfallbacks,classgoodies,goodies,classdesignsize,fontdesignsize) - end - csnames[tfmdata] = specification.cs - texdefinefont(global,cs,tfmdata) - -- resolved (when designsize is used): - local size = round(fontdata[tfmdata].parameters.size or 0) - -- ctx_setsomefontsize(size .. "sp") - setmacro("somefontsize",size.."sp") - texsetcount("scaledfontsize",size) - lastfontid = tfmdata - else - report_defining("unable to define %a as %a",name,nice_cs(cs)) - lastfontid = -1 - texsetcount("scaledfontsize",0) - -- ctx_letvaluerelax(cs) -- otherwise the current definition takes the previous one - end - if trace_defining then - report_defining("memory usage after: %s",statistics.memused()) - report_defining("stop stage two") - end - -- - texsetcount("global","lastfontid",lastfontid) - specifiers[lastfontid] = { str, size } - if not mathsize then - -- forget about it - elseif mathsize == 0 then - -- can't happen (here) - else - -- maybe only 1 2 3 - lastmathids[mathsize] = lastfontid + report_defining("memory usage after: %s",statistics.memused()) + report_defining("stop stage two") + end + -- + texsetcount("global","lastfontid",lastfontid) + specifiers[lastfontid] = { str, size } + if not mathsize then + -- forget about it + elseif mathsize == 0 then + -- can't happen (here) + else + -- maybe only 1 2 3 + lastmathids[mathsize] = lastfontid + end + -- + stoptiming(fonts) end - -- - stoptiming(fonts) - end + } - function scanners.specifiedfontspec() - local f = specifiers[scaninteger()] - if f then - context(f[1]) - end - end - function scanners.specifiedfontsize() - local f = specifiers[scaninteger()] - if f then - context(f[2]) + implement { + name = "specifiedfontspec", + arguments = "integer", + actions = function(id) + local f = specifiers[id] + if f then + context(f[1]) + end end - end - function scanners.specifiedfont() - local f = specifiers[scaninteger()] - local s = scannumber() - if f and s then - context("%s at %0.2p",f[1],s * f[2]) -- we round to 2 decimals (as at the tex end) + } + + implement { + name = "specifiedfontsize", + arguments = "integer", + actions = function(id) + local f = specifiers[id] + if f then + context(f[2]) + end end - end + } + implement { + name = "specifiedfont", + arguments = { "integer", "number" }, + actions = function(id,size) + local f = specifiers[id] + if f and size then + context("%s at %0.2p",f[1],size * f[2]) -- we round to 2 decimals (as at the tex end) + end + end + } -- local function define(specification) diff --git a/tex/context/base/mkiv/grph-chk.lua b/tex/context/base/mkiv/grph-chk.lua index ed78b856c..0688f46ef 100644 --- a/tex/context/base/mkiv/grph-chk.lua +++ b/tex/context/base/mkiv/grph-chk.lua @@ -127,9 +127,9 @@ function checkers.pdf(data) return genericchecker(data) end -local function wrappedidentify(identify,filename) +local function wrappedidentify(identify,filename,filetype) local wrapup = function() report_inclusion("fatal error reading %a",filename) end - local _, result = xpcall(identify,wrapup,filename) + local _, result = xpcall(identify,wrapup,filename,filetype) if result then local xsize = result.xsize or 0 local ysize = result.ysize or 0 @@ -166,7 +166,7 @@ function checkers.jpg(data) local inject = lpdf.injectors.jpg local found = false request.scanimage = function(t) - local result = wrappedidentify(identify,t.filename) + local result = wrappedidentify(identify,t.filename,"jpg") found = not result.error return { filename = result.filename, @@ -202,7 +202,7 @@ function checkers.jp2(data) -- idem as jpg local inject = lpdf.injectors.jp2 local found = false request.scanimage = function(t) - local result = wrappedidentify(identify,t.filename) + local result = wrappedidentify(identify,t.filename,"jp2") found = not result.error return { filename = result.filename, @@ -238,7 +238,7 @@ function checkers.png(data) -- same as jpg (for now) local inject = lpdf.injectors.png -- currently pdf specific local found = false request.scanimage = function(t) - local result = wrappedidentify(identify,t.filename) + local result = wrappedidentify(identify,t.filename,"png") found = not result.error return { filename = result.filename, diff --git a/tex/context/base/mkiv/lpdf-ini.lua b/tex/context/base/mkiv/lpdf-ini.lua index 2163e8748..c6dd4765e 100644 --- a/tex/context/base/mkiv/lpdf-ini.lua +++ b/tex/context/base/mkiv/lpdf-ini.lua @@ -25,7 +25,6 @@ local report_finalizing = logs.reporter("backend","finalizing") local report_blocked = logs.reporter("backend","blocked") local implement = interfaces.implement -local two_strings = interfaces.strings[2] local context = context @@ -1553,16 +1552,16 @@ end -- interface implement { name = "lpdf_collectedresources", actions = { lpdf.collectedresources, context } } -implement { name = "lpdf_addtocatalog", arguments = two_strings, actions = lpdf.addtocatalog } -implement { name = "lpdf_addtoinfo", arguments = two_strings, actions = function(a,b,c) lpdf.addtoinfo(a,b,c) end } -- gets adapted -implement { name = "lpdf_addtonames", arguments = two_strings, actions = lpdf.addtonames } -implement { name = "lpdf_addtopageattributes", arguments = two_strings, actions = lpdf.addtopageattributes } -implement { name = "lpdf_addtopagesattributes", arguments = two_strings, actions = lpdf.addtopagesattributes } -implement { name = "lpdf_addtopageresources", arguments = two_strings, actions = lpdf.addtopageresources } -implement { name = "lpdf_adddocumentextgstate", arguments = two_strings, actions = function(a,b) lpdf.adddocumentextgstate (a,pdfverbose(b)) end } -implement { name = "lpdf_adddocumentcolorspace", arguments = two_strings, actions = function(a,b) lpdf.adddocumentcolorspace(a,pdfverbose(b)) end } -implement { name = "lpdf_adddocumentpattern", arguments = two_strings, actions = function(a,b) lpdf.adddocumentpattern (a,pdfverbose(b)) end } -implement { name = "lpdf_adddocumentshade", arguments = two_strings, actions = function(a,b) lpdf.adddocumentshade (a,pdfverbose(b)) end } +implement { name = "lpdf_addtocatalog", arguments = "2 strings", actions = lpdf.addtocatalog } +implement { name = "lpdf_addtoinfo", arguments = "2 strings", actions = function(a,b,c) lpdf.addtoinfo(a,b,c) end } -- gets adapted +implement { name = "lpdf_addtonames", arguments = "2 strings", actions = lpdf.addtonames } +implement { name = "lpdf_addtopageattributes", arguments = "2 strings", actions = lpdf.addtopageattributes } +implement { name = "lpdf_addtopagesattributes", arguments = "2 strings", actions = lpdf.addtopagesattributes } +implement { name = "lpdf_addtopageresources", arguments = "2 strings", actions = lpdf.addtopageresources } +implement { name = "lpdf_adddocumentextgstate", arguments = "2 strings", actions = function(a,b) lpdf.adddocumentextgstate (a,pdfverbose(b)) end } +implement { name = "lpdf_adddocumentcolorspace", arguments = "2 strings", actions = function(a,b) lpdf.adddocumentcolorspace(a,pdfverbose(b)) end } +implement { name = "lpdf_adddocumentpattern", arguments = "2 strings", actions = function(a,b) lpdf.adddocumentpattern (a,pdfverbose(b)) end } +implement { name = "lpdf_adddocumentshade", arguments = "2 strings", actions = function(a,b) lpdf.adddocumentshade (a,pdfverbose(b)) end } -- more helpers: copy from lepd to lpdf diff --git a/tex/context/base/mkiv/luat-ini.mkiv b/tex/context/base/mkiv/luat-ini.mkiv index d1d829be9..f059d2b85 100644 --- a/tex/context/base/mkiv/luat-ini.mkiv +++ b/tex/context/base/mkiv/luat-ini.mkiv @@ -121,13 +121,13 @@ %D \edef\luaescapestring#1{\!!bs#1\!!es} %D \stoptyping -\def\setdocumentfilename #1#2{\clf_setdocumentfilename\numexpr#1\relax{#2}} -\def\setdocumentargument #1#2{\clf_setdocumentargument{#1}{#2}} -\def\setdocumentargumentdefault#1#2{\clf_setdocumentdefaultargument{#1}{#2}} -\def\getdocumentfilename #1{\clf_getdocumentfilename\numexpr#1\relax} -\def\getdocumentargument #1{\clf_getdocumentargument{#1}{}} -\def\setdocumentargument #1#2{\clf_setdocumentargument{#1}{#2}} -\def\getdocumentargumentdefault#1#2{\clf_getdocumentargument{#1}{#2}} +\normalprotected\def\setdocumentfilename #1#2{\clf_setdocumentfilename\numexpr#1\relax{#2}} +\normalprotected\def\setdocumentargument #1#2{\clf_setdocumentargument{#1}{#2}} +\normalprotected\def\setdocumentargumentdefault#1#2{\clf_setdocumentdefaultargument{#1}{#2}} + \def\getdocumentfilename #1{\clf_getdocumentfilename\numexpr#1\relax} + \def\getdocumentargument #1{\clf_getdocumentargument{#1}{}} +\normalprotected\def\setdocumentargument #1#2{\clf_setdocumentargument{#1}{#2}} + \def\getdocumentargumentdefault#1#2{\clf_getdocumentargument{#1}{#2}} % seldom used so no need for speedy variants: diff --git a/tex/context/base/mkiv/luat-usr.lua b/tex/context/base/mkiv/luat-usr.lua index b49379bbf..1756bb198 100644 --- a/tex/context/base/mkiv/luat-usr.lua +++ b/tex/context/base/mkiv/luat-usr.lua @@ -102,23 +102,6 @@ interfaces.implement { arguments = "2 strings", } --- local scanners = interfaces.scanners --- --- local function ctxscanner(name) --- local scanner = scanners[name] --- if scanner then --- scanner() --- else --- report("unknown scanner: %s",name) --- end --- end --- --- interfaces.implement { --- name = "clfscanner", --- actions = ctxscanner, --- arguments = "string", --- } - local function registername(name,message) if not name or name == "" then report_instance("no valid name given") diff --git a/tex/context/base/mkiv/publ-aut.lua b/tex/context/base/mkiv/publ-aut.lua index e74c7ee18..123a67009 100644 --- a/tex/context/base/mkiv/publ-aut.lua +++ b/tex/context/base/mkiv/publ-aut.lua @@ -530,9 +530,9 @@ implement { name = "btxauthor", actions = btxauthor, arguments = { - "string", - "string", - "string", + "argument", + "argument", + "argument", { { "combiner" }, { "kind" }, diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf index 374d3b695..26777bb6d 100644 Binary files a/tex/context/base/mkiv/status-files.pdf and b/tex/context/base/mkiv/status-files.pdf differ diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf index a39f37412..ad3136f2a 100644 Binary files a/tex/context/base/mkiv/status-lua.pdf and b/tex/context/base/mkiv/status-lua.pdf differ diff --git a/tex/context/base/mkiv/strc-itm.mklx b/tex/context/base/mkiv/strc-itm.mklx index 2f3cc8425..3d1861d12 100644 --- a/tex/context/base/mkiv/strc-itm.mklx +++ b/tex/context/base/mkiv/strc-itm.mklx @@ -1321,6 +1321,7 @@ \letvalue{\??itemgroupstart\v!ran }\strc_itemgroups_start_edge \letvalue{\??itemgroupstart\v!its }\strc_itemgroups_start_items \letvalue{\??itemgroupstart\v!mar }\strc_itemgroups_start_margin +\letvalue{\??itemgroupstart\v!txt }\strc_itemgroups_start_text \def\optimizelistitemsbreak {\ifcase\c_strc_itemgroups_column_depth @@ -1578,6 +1579,11 @@ \appendtoks \let\item \strc_itemgroups_start_do_item + \let\sub \strc_itemgroups_start_subitem + \let\sym \strc_itemgroups_start_symbol + \let\ran \strc_itemgroups_start_edge + \let\its \strc_itemgroups_start_items + \let\mar \strc_itemgroups_start_margin \let\noitem \strc_itemgroups_start_no_item \let\itm \strc_itemgroups_start_do_item \let\but \strc_itemgroups_start_button @@ -1588,27 +1594,29 @@ \let\startitem \startitemgroupitem \let\stopitem \stopitemgroupitem \let\starthead \startitemgrouphead - \let\stophead \stopitemgroupitemhead + \let\stophead \stopitemgrouphead \let\startspecialitem\startspecialitemgroupitem \let\stopspecialitem \stopspecialitemgroupitem \to \itemgroupcommands -\ifx\currentinterface \v!english \else - - \appendtoks - \expandafter\let\csname\v!item \endcsname\strc_itemgroups_start_do_item - \expandafter\let\csname\v!sub \endcsname\strc_itemgroups_start_subitem - \expandafter\let\csname\v!sym \endcsname\strc_itemgroups_start_symbol - \expandafter\let\csname\v!ran \endcsname\strc_itemgroups_start_edge - \expandafter\let\csname\v!head \endcsname\strc_itemgroups_head - \expandafter\let\csname\v!its \endcsname\strc_itemgroups_start_items - \expandafter\let\csname\v!mar \endcsname\strc_itemgroups_start_margin - \expandafter\let\csname\v!txt \endcsname\strc_itemgroups_start_text - \expandafter\let\csname\e!start\v!item\endcsname\startitemgroupitem - \expandafter\let\csname\e!stop \v!item\endcsname\stopitemgroupitem - \expandafter\let\csname\e!start\v!head\endcsname\startitemgrouphead - \expandafter\let\csname\e!stop \v!head\endcsname\stopitemgrouphead - \to \itemgroupcommands +\ifx\currentinterface \s!english \else + + \def\next#1#2{\ifcsname#1\endcsname\else\let\csname#1\endcsname#2\fi} + + \etoksapp\itemgroupcommands{% + \next{\v!item }\strc_itemgroups_start_do_item + \next{\v!sub }\strc_itemgroups_start_subitem + \next{\v!sym }\strc_itemgroups_start_symbol + \next{\v!ran }\strc_itemgroups_start_edge + \next{\v!head }\strc_itemgroups_head + \next{\v!its }\strc_itemgroups_start_items + \next{\v!mar }\strc_itemgroups_start_margin + \next{\v!txt }\strc_itemgroups_start_text + \next{\e!start\v!item}\startitemgroupitem + \next{\e!stop \v!item}\stopitemgroupitem + \next{\e!start\v!head}\startitemgrouphead + \next{\e!stop \v!head}\stopitemgrouphead + } \fi diff --git a/tex/context/base/mkiv/strc-itm.mkvi b/tex/context/base/mkiv/strc-itm.mkvi index cbbefd5db..1b306fe18 100644 --- a/tex/context/base/mkiv/strc-itm.mkvi +++ b/tex/context/base/mkiv/strc-itm.mkvi @@ -1321,6 +1321,7 @@ \letvalue{\??itemgroupstart\v!ran }\strc_itemgroups_start_edge \letvalue{\??itemgroupstart\v!its }\strc_itemgroups_start_items \letvalue{\??itemgroupstart\v!mar }\strc_itemgroups_start_margin +\letvalue{\??itemgroupstart\v!txt }\strc_itemgroups_start_text \def\optimizelistitemsbreak {\ifcase\c_strc_itemgroups_column_depth \ifconditional\c_strc_itemgroups_optimize @@ -1577,6 +1578,11 @@ \appendtoks \let\item \strc_itemgroups_start_do_item + \let\sub \strc_itemgroups_start_subitem + \let\sym \strc_itemgroups_start_symbol + \let\ran \strc_itemgroups_start_edge + \let\its \strc_itemgroups_start_items + \let\mar \strc_itemgroups_start_margin \let\noitem \strc_itemgroups_start_no_item \let\itm \strc_itemgroups_start_do_item \let\but \strc_itemgroups_start_button @@ -1587,27 +1593,29 @@ \let\startitem \startitemgroupitem \let\stopitem \stopitemgroupitem \let\starthead \startitemgrouphead - \let\stophead \stopitemgroupitemhead + \let\stophead \stopitemgrouphead \let\startspecialitem\startspecialitemgroupitem \let\stopspecialitem \stopspecialitemgroupitem \to \itemgroupcommands -\ifx\currentinterface \v!english \else - - \appendtoks - \expandafter\let\csname\v!item \endcsname\strc_itemgroups_start_do_item - \expandafter\let\csname\v!sub \endcsname\strc_itemgroups_start_subitem - \expandafter\let\csname\v!sym \endcsname\strc_itemgroups_start_symbol - \expandafter\let\csname\v!ran \endcsname\strc_itemgroups_start_edge - \expandafter\let\csname\v!head \endcsname\strc_itemgroups_head - \expandafter\let\csname\v!its \endcsname\strc_itemgroups_start_items - \expandafter\let\csname\v!mar \endcsname\strc_itemgroups_start_margin - \expandafter\let\csname\v!txt \endcsname\strc_itemgroups_start_text - \expandafter\let\csname\e!start\v!item\endcsname\startitemgroupitem - \expandafter\let\csname\e!stop \v!item\endcsname\stopitemgroupitem - \expandafter\let\csname\e!start\v!head\endcsname\startitemgrouphead - \expandafter\let\csname\e!stop \v!head\endcsname\stopitemgrouphead - \to \itemgroupcommands +\ifx\currentinterface \s!english \else + + \def\next#1#2{\ifcsname#1\endcsname\else\let\csname#1\endcsname#2\fi} + + \etoksapp\itemgroupcommands{% + \next{\v!item }\strc_itemgroups_start_do_item + \next{\v!sub }\strc_itemgroups_start_subitem + \next{\v!sym }\strc_itemgroups_start_symbol + \next{\v!ran }\strc_itemgroups_start_edge + \next{\v!head }\strc_itemgroups_head + \next{\v!its }\strc_itemgroups_start_items + \next{\v!mar }\strc_itemgroups_start_margin + \next{\v!txt }\strc_itemgroups_start_text + \next{\e!start\v!item}\startitemgroupitem + \next{\e!stop \v!item}\stopitemgroupitem + \next{\e!start\v!head}\startitemgrouphead + \next{\e!stop \v!head}\stopitemgrouphead + } \fi diff --git a/tex/context/base/mkiv/syst-aux.mkxl b/tex/context/base/mkiv/syst-aux.mkxl index 956d43f89..2c84fe2c6 100644 --- a/tex/context/base/mkiv/syst-aux.mkxl +++ b/tex/context/base/mkiv/syst-aux.mkxl @@ -634,9 +634,9 @@ %D These are normally only used for keywords, i.e.\ strings so we can delegate %D the work to \LUA: -\unexpanded\def\doifelseinset#1#2{\clf_doifelseinset{#1}{#2}} -\unexpanded\def\doifinset #1#2{\clf_doifinset {#1}{#2}} -\unexpanded\def\doifnotinset #1#2{\clf_doifnotinset {#1}{#2}} +%unexpanded\def\doifelseinset#1#2{\clf_doifelseinset{#1}{#2}} +%unexpanded\def\doifinset #1#2{\clf_doifinset {#1}{#2}} +%unexpanded\def\doifnotinset #1#2{\clf_doifnotinset {#1}{#2}} % % \let\firstinset \clf_firstinset % These don't accept spaces after commas: diff --git a/tex/context/base/mkiv/syst-lua.lua b/tex/context/base/mkiv/syst-lua.lua index 77960def7..5976e077f 100644 --- a/tex/context/base/mkiv/syst-lua.lua +++ b/tex/context/base/mkiv/syst-lua.lua @@ -20,11 +20,9 @@ local ctx_secondoftwoarguments = context.secondoftwoarguments local ctx_firstofoneargument = context.firstofoneargument local ctx_gobbleoneargument = context.gobbleoneargument -local two_strings = interfaces.strings[2] - implement { -- will be overloaded later name = "writestatus", - arguments = two_strings, + arguments = "2 strings", actions = logs.status, } @@ -123,7 +121,7 @@ implement { implement { name = "doifelsesame", - arguments = two_strings, + arguments = "2 strings", actions = function(a,b) if a == b then ctx_firstoftwoarguments() @@ -135,7 +133,7 @@ implement { implement { name = "doifsame", - arguments = two_strings, + arguments = "2 strings", actions = function(a,b) if a == b then ctx_firstofoneargument() @@ -147,7 +145,7 @@ implement { implement { name = "doifnotsame", - arguments = two_strings, + arguments = "2 strings", actions = function(a,b) if a == b then ctx_gobbleoneargument() diff --git a/tex/context/base/mkiv/toks-ini.lua b/tex/context/base/mkiv/toks-ini.lua index 0ac5dcc50..184a17489 100644 --- a/tex/context/base/mkiv/toks-ini.lua +++ b/tex/context/base/mkiv/toks-ini.lua @@ -43,6 +43,7 @@ end local scan_toks = token.scan_toks local scan_string = token.scan_string local scan_argument = token.scan_argument +local scan_delimited = token.scan_delimited local scan_tokenlist = token.scan_tokenlist local scan_int = token.scan_int local scan_code = token.scan_code @@ -55,6 +56,7 @@ local scan_keyword_cs = token.scan_keyword_cs or scan_keyword local scan_token = token.scan_token local scan_box = token.scan_box local scan_word = token.scan_word +local scan_letters = token.scan_letters or scan_word -- lmtx local scan_key = token.scan_key local scan_value = token.scan_value local scan_char = token.scan_char @@ -191,11 +193,13 @@ tokens.scanners = { -- these expand count = scan_int, string = scan_string, argument = scan_argument, + delimited = scan_delimited, tokenlist = scan_tokenlist, verbatim = scan_verbatim, -- detokenize code = scan_code, tokencode = scan_token_code, word = scan_word, + letters = scan_letters, key = scan_key, value = scan_value, char = scan_char, diff --git a/tex/context/base/mkiv/toks-scn.lua b/tex/context/base/mkiv/toks-scn.lua index 09c3e13b2..7ef4ce603 100644 --- a/tex/context/base/mkiv/toks-scn.lua +++ b/tex/context/base/mkiv/toks-scn.lua @@ -22,13 +22,16 @@ local tokenbits = tokens.bits local scanstring = scanners.string local scanargument = scanners.argument +local scandelimited = scanners.delimited -- lmtx local scanverbatim = scanners.verbatim local scantokenlist = scanners.tokenlist +local scantoks = scanners.toks local scaninteger = scanners.integer local scannumber = scanners.number local scankeyword = scanners.keyword local scankeywordcs = scanners.keywordcs local scanword = scanners.word +local scanletters = scanners.letters local scankey = scanners.key local scancode = scanners.code local scanboolean = scanners.boolean @@ -113,23 +116,24 @@ local function scantable(t,data) if not data then data = { } end - local wrapped = scanopen() - while true do --- local key = scanword() - local key = scanword(true) - if key then - local get = t[key] - if get then - data[key] = get() + if t then + local wrapped = scanopen() + while true do + local key = scanword(true) + if key then + local get = t[key] + if get then + data[key] = get() + else + -- catch all we can get + end else - -- catch all we can get + break end - else - break end - end - if wrapped then - scanclose() + if wrapped then + scanclose() + end end return data end @@ -166,42 +170,84 @@ function scanners.whd() end end +-- begin lmtx + +local l = utf.byte("[") +local r = utf.byte("]") + +local function scanbracketed() + local s = scandelimited(l, r) + if s then + return s + else + report_scan("missing argument in line %i of %a", status.linenumber, status.filename) + return "" + end +end + +local function scanoptional() + return scandelimited(l, r) or "" +end + +local function scanbracketedasis() + return scandelimited(l, r, false) +end + +local function scanargumentasis() + return scanargument(false) +end + +scanners.bracketed = scanbracketed +scanners.optional = scanoptional +scanners.bracketedasis = scanbracketedasis +scanners.argumentasis = scanargumentasis + +-- end lmtx + local shortcuts = { - tokens = tokens, - bits = tokenbits, - open = open, - close = close, - scanners = scanners, - scanstring = scanstring, - scanargument = scanargument, - scanverbatim = scanverbatim, - scantokenlist = scantokenlist, - scaninteger = scaninteger, - scannumber = scannumber, - scantable = scantable, - scankeyword = scankeyword, - scankeywordcs = scankeywordcs, - scanword = scanword, - -- scankey = scankey, - scancode = scancode, - scanboolean = scanboolean, - scandimen = scandimen, - scandimension = scandimen, - scanbox = scanners.box, - scanhbox = scanners.hbox, - scanvbox = scanners.vbox, - scanvtop = scanners.vtop, - scanconditional = scanconditional, - scanopen = scanopen, - scanclose = scanclose, - scanlist = scanlist, - scancsname = scancsname, - todimen = todimen, - tonumber = tonumber, - tostring = tostring, - toboolean = toboolean, - inspect = inspect, - report = report_scan, + tokens = tokens, + bits = tokenbits, + open = open, + close = close, + scanners = scanners, + scanstring = scanstring, + scanargument = scanargument, + scanverbatim = scanverbatim, + scantokenlist = scantokenlist, + scantoks = scantoks, + scaninteger = scaninteger, + scannumber = scannumber, + scantable = scantable, -- not directly useable + scankeyword = scankeyword, + scankeywordcs = scankeywordcs, + scanword = scanword, + scanletters = scanletters, + -- scankey = scankey, + scancode = scancode, + scanboolean = scanboolean, + scandimen = scandimen, + scandimension = scandimen, + scanbox = scanners.box, + scanhbox = scanners.hbox, + scanvbox = scanners.vbox, + scanvtop = scanners.vtop, + scanconditional = scanconditional, + scanopen = scanopen, + scanclose = scanclose, + scanlist = scanlist, + scancsname = scancsname, + todimen = todimen, + tonumber = tonumber, + tostring = tostring, + toboolean = toboolean, + inspect = inspect, + report = report_scan, + -- lmtx + scandelimited = scandelimited, -- not directly useable + scanbracketed = scanbracketed, + scanoptional = scanoptional, + scanbracketedasis = scanbracketedasis, + scanargumentasis = scanargumentasis, } tokens.shortcuts = shortcuts @@ -222,25 +268,28 @@ tokens.converters = { toglue = "todimen", } --- We could just pickup a keyword but then we really need to make sure --- that no number follows it when that is the assignment and adding --- an optional = defeats the gain in speed. Currently we have sources --- with no spaces (\startcontextdefinitioncode ...) so it fails there. +-- We could just pickup a keyword but then we really need to make sure that no number +-- follows it when that is the assignment and adding an optional = defeats the gain +-- in speed. Currently we have sources with no spaces (\startcontextdefinitioncode +-- ...) so it fails there. -- --- Another drawback is that we then need to use { } instead of ending --- with \relax (as we can do now) but that is no big deal. It's just --- that I then need to check the TeX end. More pain than gain and a bit --- risky too. +-- Another drawback is that we then need to use { } instead of ending with \relax (as +-- we can do now) but that is no big deal. It's just that I then need to check the TeX +-- end. More pain than gain and a bit risky too. Using scanletters works better, but +-- the gain is only some 10 percent but if we don't have keywords with numbers it might +-- make sense in the end, some day. local f_if = formatters[ " if scankeywordcs('%s') then data['%s'] = scan%s()"] local f_elseif = formatters[" elseif scankeywordcs('%s') then data['%s'] = scan%s()"] ------ f_if = formatters[" local key = scanword() if key == '' then break elseif key == '%s' then data['%s'] = scan%s()"] ------ f_elseif = formatters[" elseif key == '%s' then data['%s'] = scan%s()"] - ----- f_if_x = formatters[ " if not data['%s'] and scankeywordcs('%s') then data['%s'] = scan%s()"] ----- f_elseif_x = formatters[" elseif not data['%s'] and scankeywordcs('%s') then data['%s'] = scan%s()"] +-- if CONTEXTLMTXMODE > 0 then +-- f_if = formatters[" local key = scanletters() if key == '' then break elseif key == '%s' then data['%s'] = scan%s()"] +-- f_elseif = formatters[" elseif key == '%s' then data['%s'] = scan%s()"] +-- end + local f_local = formatters["local scan%s = scanners.%s"] local f_scan = formatters["scan%s()"] local f_shortcut = formatters["local %s = scanners.converters.%s"] @@ -250,9 +299,11 @@ local f_elseif_c = formatters[" elseif scankeywordcs('%s') then data['%s'] = %s local f_scan_c = formatters["%s(scan%s())"] -- see above --- ------ f_if_c = formatters[" local key = scanword() if key == '' then break elseif key == '%s' then data['%s'] = %s(scan%s())"] ------ f_elseif_c = formatters[" elseif k == '%s' then data['%s'] = %s(scan%s())"] + +-- if CONTEXTLMTXMODE > 0 then +-- f_if_c = formatters[" local key = scanletters() if key == '' then break elseif key == '%s' then data['%s'] = %s(scan%s())"] +-- f_elseif_c = formatters[" elseif k == '%s' then data['%s'] = %s(scan%s())"] +-- end local f_any = formatters[" else local key = scanword(true) if key then data[key] = scan%s() else break end end"] local f_any_c = formatters[" else local key = scanword(true) if key then data[key] = %s(scan%s()) else break end end"] @@ -270,33 +321,6 @@ local f_action_f = formatters["action%s(%s)"] local f_action_s = formatters["local action%s = tokens._action[%s]"] local f_nested = formatters["local function scan%s()\n local data = { }\n%s\n return data\nend\n"] --- local f_check = formatters[ [[ --- local wrapped = false --- while true do --- local c = scancode(open) --- if c == 123 then --- wrapped = true --- break --- elseif c ~= 32 then --- break --- end --- end --- while true do --- ]] .. "%\nt\n" .. [[ --- %s --- end --- if wrapped then --- while true do --- local c = scancode(close) --- if c == 125 then --- break --- elseif c ~= 32 then --- break --- end --- end --- end --- ]] ] - local f_check = formatters[ [[ local wrapped = scanopen() while true do @@ -319,6 +343,11 @@ local presets = { ["6 strings"] = { "string", "string", "string", "string", "string", "string" }, ["7 strings"] = { "string", "string", "string", "string", "string", "string", "string" }, ["8 strings"] = { "string", "string", "string", "string", "string", "string", "string", "string" }, + + ["1 argument" ] = { "argument" }, + ["2 arguments"] = { "argument", "argument" }, + ["3 arguments"] = { "argument", "argument", "argument" }, + ["4 arguments"] = { "argument", "argument", "argument", "argument" }, } tokens.presets = presets @@ -542,7 +571,7 @@ end -- { "nature", "boolean" }, -- { "escape", "string" }, -- { "escape" }, --- } +-- }, -- "boolean", -- } -- diff --git a/tex/context/base/mkiv/util-str.lua b/tex/context/base/mkiv/util-str.lua index aba7859c3..2d3f4d669 100644 --- a/tex/context/base/mkiv/util-str.lua +++ b/tex/context/base/mkiv/util-str.lua @@ -1057,76 +1057,44 @@ local format_rest = function(s) return format("%q",s) -- catches " and \n and such end --- local format_extension = function(extensions,f,name) --- local extension = extensions[name] or "tostring(%s)" --- local f = tonumber(f) or 1 --- local w = find(extension,"%.%.%.") --- if f == 0 then --- if w then --- extension = gsub(extension,"%.%.%.","") --- end --- return extension --- elseif f == 1 then --- if w then --- extension = gsub(extension,"%.%.%.","%%s") --- end --- n = n + 1 --- local a = "a" .. n --- return format(extension,a,a) -- maybe more times? --- elseif f < 0 then --- local a = "a" .. (n + f + 1) --- return format(extension,a,a) --- else --- if w then --- extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s") --- end --- -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we --- -- cache we don't save much and there are hardly any extensions anyway --- local t = { } --- for i=1,f do --- n = n + 1 --- -- t[#t+1] = "a" .. n --- t[i] = "a" .. n --- end --- return format(extension,unpack(t)) --- end --- end - local format_extension = function(extensions,f,name) local extension = extensions[name] or "tostring(%s)" local f = tonumber(f) or 1 local w = find(extension,"%.%.%.") - if w then - -- we have a wildcard - if f == 0 then + if f == 0 then + if w then extension = gsub(extension,"%.%.%.","") - return extension - elseif f == 1 then + end + return extension + elseif f == 1 then + if w then extension = gsub(extension,"%.%.%.","%%s") - n = n + 1 - local a = "a" .. n - return format(extension,a,a) -- maybe more times? - elseif f < 0 then + end + n = n + 1 + local a = "a" .. n + return format(extension,a,a) -- maybe more times? + elseif f < 0 then + if w then + -- not supported + extension = gsub(extension,"%.%.%.","") + return extension + else local a = "a" .. (n + f + 1) return format(extension,a,a) - else - extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s") - -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we - -- cache we don't save much and there are hardly any extensions anyway - local t = { } - for i=1,f do - n = n + 1 - -- t[#t+1] = "a" .. n - t[i] = "a" .. n - end - return format(extension,unpack(t)) end else - extension = gsub(extension,"%%s",function() + if w then + extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s") + end + -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we + -- cache we don't save much and there are hardly any extensions anyway + local t = { } + for i=1,f do n = n + 1 - return "a" .. n - end) - return extension + -- t[#t+1] = "a" .. n + t[i] = "a" .. n + end + return format(extension,unpack(t)) end end diff --git a/tex/generic/context/luatex/luatex-fonts-merged.lua b/tex/generic/context/luatex/luatex-fonts-merged.lua index 68b47494a..471d32d1b 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 : c:/data/develop/context/sources/luatex-fonts-merged.lua -- parent file : c:/data/develop/context/sources/luatex-fonts.lua --- merge date : 2020-06-20 13:33 +-- merge date : 2020-06-25 10:55 do -- begin closure to overcome local limits and interference @@ -3761,33 +3761,36 @@ local format_extension=function(extensions,f,name) local extension=extensions[name] or "tostring(%s)" local f=tonumber(f) or 1 local w=find(extension,"%.%.%.") - if w then - if f==0 then + if f==0 then + if w then extension=gsub(extension,"%.%.%.","") - return extension - elseif f==1 then + end + return extension + elseif f==1 then + if w then extension=gsub(extension,"%.%.%.","%%s") - n=n+1 - local a="a"..n - return format(extension,a,a) - elseif f<0 then + end + n=n+1 + local a="a"..n + return format(extension,a,a) + elseif f<0 then + if w then + extension=gsub(extension,"%.%.%.","") + return extension + else local a="a"..(n+f+1) return format(extension,a,a) - else - extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s") - local t={} - for i=1,f do - n=n+1 - t[i]="a"..n - end - return format(extension,unpack(t)) end else - extension=gsub(extension,"%%s",function() + if w then + extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s") + end + local t={} + for i=1,f do n=n+1 - return "a"..n - end) - return extension + t[i]="a"..n + end + return format(extension,unpack(t)) end end local builder=Cs { "start", -- cgit v1.2.3