summaryrefslogtreecommitdiff
path: root/tex/context/base
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2017-02-23 18:12:36 +0100
committerContext Git Mirror Bot <phg42.2a@gmail.com>2017-02-23 18:12:36 +0100
commitc91d92093b72a73a92c3ae3c641137abe6fb64b9 (patch)
treebfbdc4359ae391d0d96e577fb544023464427e81 /tex/context/base
parente4223677ac0d23e4888e41efda0d2e6aabbe76bf (diff)
downloadcontext-c91d92093b72a73a92c3ae3c641137abe6fb64b9.tar.gz
2017-02-23 17:13:00
Diffstat (limited to 'tex/context/base')
-rw-r--r--tex/context/base/mkii/cont-new.mkii2
-rw-r--r--tex/context/base/mkii/context.mkii2
-rw-r--r--tex/context/base/mkiv/anch-pos.lua2
-rw-r--r--tex/context/base/mkiv/char-fio.lua5
-rw-r--r--tex/context/base/mkiv/char-utf.lua11
-rw-r--r--tex/context/base/mkiv/char-utf.mkiv6
-rw-r--r--tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--tex/context/base/mkiv/context.mkiv2
-rw-r--r--tex/context/base/mkiv/data-ini.lua10
-rw-r--r--tex/context/base/mkiv/font-dsp.lua214
-rw-r--r--tex/context/base/mkiv/font-lib.mkvi1
-rw-r--r--tex/context/base/mkiv/font-lig.lua52
-rw-r--r--tex/context/base/mkiv/font-otc.lua42
-rw-r--r--tex/context/base/mkiv/font-otj.lua2
-rw-r--r--tex/context/base/mkiv/font-otr.lua63
-rw-r--r--tex/context/base/mkiv/font-ots.lua55
-rw-r--r--tex/context/base/mkiv/luat-cnf.lua3
-rw-r--r--tex/context/base/mkiv/node-fin.lua2
-rw-r--r--tex/context/base/mkiv/publ-imp-apa.lua3
-rw-r--r--tex/context/base/mkiv/publ-imp-apa.mkvi8
-rw-r--r--tex/context/base/mkiv/publ-ini.lua29
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin25672 -> 25646 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin372476 -> 373036 bytes
-rw-r--r--tex/context/base/mkiv/trac-deb.lua12
-rw-r--r--tex/context/base/mkiv/util-deb.lua245
-rw-r--r--tex/context/base/mkiv/util-env.lua28
-rw-r--r--tex/context/base/mkiv/util-fil.lua7
-rw-r--r--tex/context/base/mkiv/util-lib.lua284
-rw-r--r--tex/context/base/mkiv/util-str.lua37
29 files changed, 878 insertions, 251 deletions
diff --git a/tex/context/base/mkii/cont-new.mkii b/tex/context/base/mkii/cont-new.mkii
index 0e6e6851f..1c5dfe2d5 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{2017.02.20 17:55}
+\newcontextversion{2017.02.23 17:07}
%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 868227917..a89ce83ff 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{2017.02.20 17:55}
+\edef\contextversion{2017.02.23 17:07}
%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 6a9612d9e..2ba9e2420 100644
--- a/tex/context/base/mkiv/anch-pos.lua
+++ b/tex/context/base/mkiv/anch-pos.lua
@@ -90,8 +90,6 @@ local jobpositions = {
job.positions = jobpositions
-_plib_ = jobpositions -- might go
-
local default = { -- not r and paragraphs etc
__index = {
x = 0, -- x position baseline
diff --git a/tex/context/base/mkiv/char-fio.lua b/tex/context/base/mkiv/char-fio.lua
index ab2555935..fa69d9356 100644
--- a/tex/context/base/mkiv/char-fio.lua
+++ b/tex/context/base/mkiv/char-fio.lua
@@ -42,18 +42,19 @@ local reporting = "no"
-- per line by default
local enforced = {
- ["characters.filters.utf.reorder"] = true,
["characters.filters.utf.collapse"] = true,
["characters.filters.utf.decompose"] = true,
+ ["characters.filters.utf.reorder"] = false,
}
function utffilters.enable()
+ -- only used one time (normally)
for k, v in next, enforced do
if v then
if reporting == "yes" then
report("%a enabled",k)
end
- enableaction(textfileactions,v)
+ enableaction(textfileactions,k)
else
if reporting == "yes" then
report("%a not enabled",k)
diff --git a/tex/context/base/mkiv/char-utf.lua b/tex/context/base/mkiv/char-utf.lua
index ece9d7a76..f4a6d50e1 100644
--- a/tex/context/base/mkiv/char-utf.lua
+++ b/tex/context/base/mkiv/char-utf.lua
@@ -409,8 +409,8 @@ function utffilters.addgrapheme(result,first,second) -- can be U+ 0x string or u
graphemes[first][second] = result
end
local pair = first .. second
- if not composed[pair] then
- composed[pair] = result
+ if not collapsed[pair] then
+ collapsed[pair] = result
p_composed = nil
end
end
@@ -498,7 +498,8 @@ local function prepare()
for k, v in sortedhash(characters.data) do
local combining = v.combining -- v.ordering or v.combining
if combining then
- hash[utfchar(k)] = { utfchar(k), combining, 0 } -- slot 3 can be used in sort
+ local u = utfchar(k)
+ hash[u] = { u, combining, 0 } -- slot 3 can be used in sort
end
end
local e = utfchartabletopattern(exceptions)
@@ -522,7 +523,7 @@ end
-- local collapse = utffilters.collapse
-- local decompose = utffilters.decompose
--- local preprocess = utffilters.preprocess
+-- local reorder = utffilters.reorder
--
-- local c1, c2, c3 = "a", "̂", "̃"
-- local r2, r3 = "â", "ẫ"
@@ -540,7 +541,7 @@ end
-- for i=1,10000 do
-- collapse(data)
-- decompose(data)
--- -- preprocess(data)
+-- -- reorder(data)
-- end
-- print(os.clock()-t,decompose(collapse(data))==okay,decompose(collapse(str)))
-- end
diff --git a/tex/context/base/mkiv/char-utf.mkiv b/tex/context/base/mkiv/char-utf.mkiv
index fe9f402ef..3b77771a7 100644
--- a/tex/context/base/mkiv/char-utf.mkiv
+++ b/tex/context/base/mkiv/char-utf.mkiv
@@ -31,9 +31,9 @@
%D since the source files are rather simple, we postpone the
%D initialization till runtime.
-\appendtoks
- \clf_enableutf % not needed when we create a format so we do it now
-\to \everyjob
+% \appendtoks
+% \clf_enableutf % not needed when we create a format so we do it now
+% \to \everyjob
%D The next one influences input parsing.
%D
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index 4c044c330..c67cf1c25 100644
--- a/tex/context/base/mkiv/cont-new.mkiv
+++ b/tex/context/base/mkiv/cont-new.mkiv
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2017.02.20 17:55}
+\newcontextversion{2017.02.23 17:07}
%D This file is loaded at runtime, thereby providing an excellent place for
%D hacks, patches, extensions and new features.
diff --git a/tex/context/base/mkiv/context.mkiv b/tex/context/base/mkiv/context.mkiv
index 31d79390a..dc66b5564 100644
--- a/tex/context/base/mkiv/context.mkiv
+++ b/tex/context/base/mkiv/context.mkiv
@@ -39,7 +39,7 @@
%D up and the dependencies are more consistent.
\edef\contextformat {\jobname}
-\edef\contextversion{2017.02.20 17:55}
+\edef\contextversion{2017.02.23 17:07}
\edef\contextkind {beta}
%D For those who want to use this:
diff --git a/tex/context/base/mkiv/data-ini.lua b/tex/context/base/mkiv/data-ini.lua
index 5ed2cce26..09357368c 100644
--- a/tex/context/base/mkiv/data-ini.lua
+++ b/tex/context/base/mkiv/data-ini.lua
@@ -217,11 +217,11 @@ end
environment.texroot = file.collapsepath(texroot)
-if type(profiler) == "table" and not jit then
- directives.register("system.profile",function()
- profiler.start("luatex-profile.log")
- end)
-end
+-- if type(profiler) == "table" and not jit then
+-- directives.register("system.profile",function()
+-- profiler.start("luatex-profile.log")
+-- end)
+-- end
-- a forward definition
diff --git a/tex/context/base/mkiv/font-dsp.lua b/tex/context/base/mkiv/font-dsp.lua
index 2d52c23a9..a5a1ae7c0 100644
--- a/tex/context/base/mkiv/font-dsp.lua
+++ b/tex/context/base/mkiv/font-dsp.lua
@@ -72,6 +72,7 @@ local streamreader = readers.streamreader
local setposition = streamreader.setposition
local getposition = streamreader.getposition
local skipshort = streamreader.skipshort
+local skipbytes = streamreader.skip
local readushort = streamreader.readcardinal2 -- 16-bit unsigned integer
local readulong = streamreader.readcardinal4 -- 24-bit unsigned integer
local readshort = streamreader.readinteger2 -- 16-bit signed integer
@@ -79,6 +80,9 @@ local readfword = readshort
local readstring = streamreader.readstring
local readtag = streamreader.readtag
local readbytes = streamreader.readbytes
+local readfixed = streamreader.readfixed4
+local read2dot14 = streamreader.read2dot14
+local readinteger = streamreader.readinteger1
local gsubhandlers = { }
local gposhandlers = { }
@@ -2434,3 +2438,213 @@ function readers.svg(f,fontdata,specification)
fontdata.hascolor = true
end
end
+
+-- This next few are work in progress. I have no fonts that have these tables so it's a
+-- gamble. I'll pick up this thread some day (if needed at all). See font-tst.tex for a
+-- possible test. Something for a rainy day and a stack of fresh cd's.
+
+function readers.fvar(f,fontdata,specification)
+ local datatable = fontdata.tables.fvar
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ local majorversion = readushort(f) -- 1
+ local minorversion = readushort(f) -- 0
+ if majorversion ~= 1 and minorversion ~= 0 then
+ report("table version %a.%a of %a is not supported (yet), maybe font %s is bad",
+ majorversion,minorversion,"fvar",fontdata.filename)
+ return
+ end
+ local offsettoaxis = tableoffset + readushort(f)
+ local nofsizepairs = readushort(f) -- 2 count/size pairs
+ -- pair 1
+ local nofaxis = readushort(f)
+ local sizeofaxis = readushort(f)
+ -- pair 2
+ local nofinstances = readushort(f)
+ local sizeofinstances = readushort(f)
+ --
+ local extras = fontdata.extras
+ local axis = { }
+ local instances = { }
+ --
+ setposition(f,offsettoaxis)
+ --
+ local function readtuple(f)
+ local t = { }
+ for i=1,nofaxis do
+ t[i] = readfixed(f)
+ end
+ return t
+ end
+ --
+ for i=1,nofaxis do
+ axis[i] = {
+ tag = readtag(f), -- ital opsz slnt wdth wght
+ minimum = readfixed(f), -- we get weird values from a test font ... to be checked
+ default = readfixed(f), -- idem
+ maximum = readfixed(f), -- idem
+ flags = readushort(f),
+ nameid = extras[readushort(f)],
+ }
+ local n = sizeofaxis - 20
+ if n > 0 then
+ skipbytes(f,n)
+ elseif n < 0 then
+ -- error
+ end
+ end
+ --
+ for i=1,nofinstances do
+ local subfamid = readushort(f)
+ local flags = readushort(f)
+ local tuple = readtuple(f)
+ local psnameid = false
+ local nofbytes = 2 + 2 + #tuple * 2
+ if nofbytes < sizeofinstances then
+ psnameid = readushort(f)
+ nofbytes = nofbytes + 2
+ end
+ instances[i] = {
+ subfamily = extras[subfamid],
+ flags = flags,
+ tuple = tuple,
+ psname = extras[psnameid] or nil,
+ }
+ if nofbytes > 0 then
+ skipbytes(f,nofbytes)
+ end
+ end
+ --
+ fontdata.variable = {
+ axis = axis,
+ instances = instances,
+ }
+ end
+end
+
+-- function readers.gvar(f,fontdata,specification)
+-- end
+
+-- function readers.hvar(f,fontdata,specification)
+-- end
+
+-- function readers.vvar(f,fontdata,specification)
+-- end
+
+-- We don't need all these dimensions so we only mention those that make
+-- sense. Mapping to some function makes most sense.
+
+local tags = {
+ hasc = "", -- horizontal ascender OS/2.sTypoAscender
+ hdsc = "", -- horizontal descender OS/2.sTypoDescender
+ -- hlgp = "", -- horizontal line gap OS/2.sTypoLineGap
+ -- hcla = "", -- horizontal clipping ascent OS/2.usWinAscent
+ -- hcld = "", -- horizontal clipping descent OS/2.usWinDescent
+ vasc = "", -- vertical ascender vhea.ascent
+ vdsc = "", -- vertical descender vhea.descent
+ vlgp = "", -- vertical line gap vhea.lineGap
+ xhgt = "", -- x height OS/2.sxHeight
+ cpht = "", -- cap height OS/2.sCapHeight
+ -- sbxs = "", -- subscript em x size OS/2.ySubscriptXSize
+ -- sbys = "", -- subscript em y size OS/2.ySubscriptYSize
+ -- sbxo = "", -- subscript em x offset OS/2.ySubscriptXOffset
+ -- sbyo = "", -- subscript em y offset OS/2.ySubscriptYOffset
+ -- spxs = "", -- superscript em x size OS/2.ySuperscriptXSize
+ -- spys = "", -- superscript em y size OS/2.ySuperscriptYSize
+ -- spxo = "", -- superscript em x offset OS/2.ySuperscriptXOffset
+ -- spyo = "", -- superscript em y offset OS/2.ySuperscriptYOffset
+ -- strs = "", -- strikeout size OS/2.yStrikeoutSize
+ -- stro = "", -- strikeout offset OS/2.yStrikeoutPosition
+ -- unds = "", -- underline size post.underlineThickness
+ -- undo = "", -- underline offset post.underlinePosition
+}
+
+function readers.mvar(f,fontdata,specification)
+ local datatable = fontdata.tables.mvar
+ if datatable then
+ local tableoffset = datatable.offset
+ setposition(f,tableoffset)
+ local majorversion = readushort(f) -- 1
+ local minorversion = readushort(f) -- 0
+ if majorversion ~= 1 and minorversion ~= 0 then
+ report("table version %a.%a of %a is not supported (yet), maybe font %s is bad",
+ majorversion,minorversion,"fvar",fontdata.filename)
+ return
+ end
+ --
+ local nofaxis = readushort(f)
+ local recordsize = readushort(f)
+ local nofrecords = readushort(f)
+ local offsettostore = tableoffset + readushort(f)
+ local records = { }
+ local dimensions = { }
+ local store = { }
+ local regions = { }
+ --
+ for i=1,nofrecords do
+ local tag = readtag(f)
+ if tags[tag] then
+ dimensions[tag] = {
+ outer = readushort(f),
+ inner = readushort(f),
+ }
+ else
+ skipshort(f,2)
+ end
+ end
+ --
+ setposition(f,offsettostore)
+ local nofaxis = readushort(f)
+ local nofregions = readushort(f)
+ for i=1,nofregions do
+ local t = { }
+ for i=1,nofaxis do
+ t[i] = {
+ start = read2dot14(f),
+ peak = read2dot14(f),
+ stop = read2dot14(f),
+ }
+ end
+ regions[i] = t
+ end
+ --
+ local format = readushort(f) -- 1
+ local offset = offsettostore + readulong(f)
+ local nofdata = readushort(f)
+ local data = { }
+ for i=1,nofdata do
+ data[i] = readulong(f) + offset
+ end
+ for i=1,nofdata do
+ local offset = data[i]
+ setposition(f,offset)
+ local nofdeltas = readushort(f)
+ local nofshort = readushort(f)
+ local nofregions = readushort(f)
+ local deltas = { }
+ local regions = { }
+ local length = nofshort + nofregions
+ for i=1,nofregions do
+ regions[i] = readushort(f)
+ end
+ for i=1,nofdeltas do
+ local t = { }
+ for i=1,nofshort do
+ t[i] = readushort(f)
+ end
+ for i=1,nofregions do
+ t[nofshort+i] = readinteger(f)
+ end
+ deltas[i] = t
+ end
+ data[i] = {
+ regions = regions,
+ deltas = deltas,
+ }
+ end
+ end
+end
+
+-- function readers.vorg(f,fontdata,specification)
+-- end
diff --git a/tex/context/base/mkiv/font-lib.mkvi b/tex/context/base/mkiv/font-lib.mkvi
index ed7d896c5..316e70019 100644
--- a/tex/context/base/mkiv/font-lib.mkvi
+++ b/tex/context/base/mkiv/font-lib.mkvi
@@ -97,6 +97,7 @@
\registerctxluafile{font-ctx}{1.001} % after def as it overloads
\registerctxluafile{font-ext}{1.001}
+\registerctxluafile{font-lig}{1.001} % only for experiments so try to avoid it
\registerctxluafile{font-fbk}{1.001}
\registerctxluafile{font-aux}{1.001}
diff --git a/tex/context/base/mkiv/font-lig.lua b/tex/context/base/mkiv/font-lig.lua
new file mode 100644
index 000000000..823be9c3b
--- /dev/null
+++ b/tex/context/base/mkiv/font-lig.lua
@@ -0,0 +1,52 @@
+if not modules then modules = { } end modules ['font-lig'] = {
+ version = 1.001,
+ comment = "companion to font-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+}
+
+-- This module is not loaded but generated a file for plain TeX as a substitute
+-- for collapsing the input: "luatex-fonts-lig.lua" with "collapse=yes".
+
+local standalone = not characters
+
+if standalone then
+ require("char-def")
+ require("char-utf")
+ if characters.initialize then
+ characters.initialize()
+ end
+end
+
+local data = { } -- if we ever preload this i'll cache it
+
+for first, seconds in next, characters.graphemes do
+ for second, combined in next, seconds do
+ data[combined] = { first, second }
+ end
+end
+
+-- data['c'] = { 'a', 'b' }
+-- data['d'] = { 'c', 'c' }
+
+local feature = {
+ name = "collapse",
+ type = "ligature",
+ prepend = true,
+ dataset = {
+ { data = data },
+ { data = data },
+ }
+}
+
+if standalone then
+ local filename = "luatex-fonts-lig.lua"
+ local filedata = "-- this file is generated by context\n\n"
+ .. "fonts.handlers.otf.addfeature "
+ .. table.serialize(feature,false)
+ logs.report("fonts","pseudo ligature file %a saved",filename)
+ io.savedata(filename,filedata)
+else
+ fonts.handlers.otf.addfeature(feature)
+end
diff --git a/tex/context/base/mkiv/font-otc.lua b/tex/context/base/mkiv/font-otc.lua
index a55320903..a0dda593d 100644
--- a/tex/context/base/mkiv/font-otc.lua
+++ b/tex/context/base/mkiv/font-otc.lua
@@ -195,13 +195,15 @@ local function addfeature(data,feature,specifications)
local stepkey = coverup.stepkey
local register = coverup.register
- local function prepare_substitution(list,featuretype)
+ local function prepare_substitution(list,featuretype,nocheck)
local coverage = { }
local cover = coveractions[featuretype]
for code, replacement in next, list do
local unicode = tounicode(code)
local description = descriptions[unicode]
- if description then
+ if not nocheck and not description then
+ skip = skip + 1
+ else
if type(replacement) == "table" then
replacement = replacement[1]
end
@@ -212,20 +214,18 @@ local function addfeature(data,feature,specifications)
else
skip = skip + 1
end
- else
- skip = skip + 1
end
end
return coverage
end
- local function prepare_alternate(list,featuretype)
+ local function prepare_alternate(list,featuretype,nocheck)
local coverage = { }
local cover = coveractions[featuretype]
for code, replacement in next, list do
local unicode = tounicode(code)
local description = descriptions[unicode]
- if not description then
+ if not nocheck and not description then
skip = skip + 1
elseif type(replacement) == "table" then
local r = { }
@@ -248,13 +248,13 @@ local function addfeature(data,feature,specifications)
return coverage
end
- local function prepare_multiple(list,featuretype)
+ local function prepare_multiple(list,featuretype,nocheck)
local coverage = { }
local cover = coveractions[featuretype]
for code, replacement in next, list do
local unicode = tounicode(code)
local description = descriptions[unicode]
- if not description then
+ if not nocheck and not description then
skip = skip + 1
elseif type(replacement) == "table" then
local r, n = { }, 0
@@ -281,16 +281,19 @@ local function addfeature(data,feature,specifications)
end
end
end
+ inspect(coverage)
return coverage
end
- local function prepare_ligature(list,featuretype)
+ local function prepare_ligature(list,featuretype,nocheck)
local coverage = { }
local cover = coveractions[featuretype]
for code, ligature in next, list do
local unicode = tounicode(code)
local description = descriptions[unicode]
- if description then
+ if not nocheck and not description then
+ skip = skip + 1
+ else
if type(ligature) == "string" then
ligature = { lpegmatch(splitter,ligature) }
end
@@ -311,8 +314,6 @@ local function addfeature(data,feature,specifications)
else
skip = skip + 1
end
- else
- skip = skip + 1
end
end
return coverage
@@ -552,6 +553,7 @@ local function addfeature(data,feature,specifications)
local askedsteps = specification.steps or specification.subtables or { specification.data } or { }
local featuretype = normalized[specification.type or "substitution"] or "substitution"
local featureflags = specification.flags or noflags
+ local nocheck = specification.nocheck
local featureorder = specification.order or { feature }
local featurechain = (featuretype == "chainsubstitution" or featuretype == "chainposition") and 1 or 0
local nofsteps = 0
@@ -572,13 +574,13 @@ local function addfeature(data,feature,specifications)
local coverage = nil
local format = nil
if featuretype == "substitution" then
- coverage = prepare_substitution(list,featuretype)
+ coverage = prepare_substitution(list,featuretype,nocheck)
elseif featuretype == "ligature" then
- coverage = prepare_ligature(list,featuretype)
+ coverage = prepare_ligature(list,featuretype,nocheck)
elseif featuretype == "alternate" then
- coverage = prepare_alternate(list,featuretype)
+ coverage = prepare_alternate(list,featuretype,nocheck)
elseif featuretype == "multiple" then
- coverage = prepare_multiple(list,featuretype)
+ coverage = prepare_multiple(list,featuretype,nocheck)
elseif featuretype == "kern" then
format = "kern"
coverage = prepare_kern(list,featuretype)
@@ -605,16 +607,16 @@ local function addfeature(data,feature,specifications)
local format = nil
if featuretype == "substitution" then
category = "gsub"
- coverage = prepare_substitution(list,featuretype)
+ coverage = prepare_substitution(list,featuretype,nocheck)
elseif featuretype == "ligature" then
category = "gsub"
- coverage = prepare_ligature(list,featuretype)
+ coverage = prepare_ligature(list,featuretype,nocheck)
elseif featuretype == "alternate" then
category = "gsub"
- coverage = prepare_alternate(list,featuretype)
+ coverage = prepare_alternate(list,featuretype,nocheck)
elseif featuretype == "multiple" then
category = "gsub"
- coverage = prepare_multiple(list,featuretype)
+ coverage = prepare_multiple(list,featuretype,nocheck)
elseif featuretype == "kern" then
category = "gpos"
format = "kern"
diff --git a/tex/context/base/mkiv/font-otj.lua b/tex/context/base/mkiv/font-otj.lua
index fdee3513f..50330cb83 100644
--- a/tex/context/base/mkiv/font-otj.lua
+++ b/tex/context/base/mkiv/font-otj.lua
@@ -25,7 +25,7 @@ if not modules then modules = { } end modules ['font-otj'] = {
if not nodes.properties then return end
-local next, rawget = next, rawget
+local next, rawget, tonumber = next, rawget, tonumber
local fastcopy = table.fastcopy
local registertracker = trackers.register
diff --git a/tex/context/base/mkiv/font-otr.lua b/tex/context/base/mkiv/font-otr.lua
index a9d3a8b29..c5c5d8f32 100644
--- a/tex/context/base/mkiv/font-otr.lua
+++ b/tex/context/base/mkiv/font-otr.lua
@@ -65,11 +65,9 @@ if not modules then modules = { } end modules ['font-otr'] = {
-- require("char-ini")
-- end
-local next, type, unpack = next, type, unpack
-local byte, lower, char, strip, gsub = string.byte, string.lower, string.char, string.strip, string.gsub
-local bittest = bit32.btest
-local concat, remove, unpack, fastcopy = table.concat, table.remov, table.unpack, table.fastcopy
-local floor, abs, sqrt, round = math.floor, math.abs, math.sqrt, math.round
+local next, type = next, type
+local byte, lower, char, gsub = string.byte, string.lower, string.char, string.gsub
+local floor, round = math.floor, math.round
local P, R, S, C, Cs, Cc, Ct, Carg, Cmt = lpeg.P, lpeg.R, lpeg.S, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.Ct, lpeg.Carg, lpeg.Cmt
local lpegmatch = lpeg.match
@@ -120,7 +118,7 @@ local readoffset = readushort
local read2dot14 = streamreader.read2dot14 -- 16-bit signed fixed number with the low 14 bits of fraction (2.14) (F2DOT14)
function streamreader.readtag(f)
- return lower(strip(readstring(f,4)))
+ return lower(stripstring(readstring(f,4)))
end
-- date represented in number of seconds since 12:00 midnight, January 1, 1904. The value is represented as a
@@ -174,6 +172,7 @@ local reservednames = { [0] =
"wwssubfamily",
"lightbackgroundpalette",
"darkbackgroundpalette",
+ "variationspostscriptnameprefix",
}
-- more at: https://www.microsoft.com/typography/otspec/name.htm
@@ -747,7 +746,8 @@ function readers.name(f,fontdata,specification)
local encoding = encodings[encoding]
local language = languages[language]
if encoding and language then
- local name = reservednames[readushort(f)]
+ local index = readushort(f)
+ local name = reservednames[index]
if name then
namelist[#namelist+1] = {
platform = platform,
@@ -758,7 +758,14 @@ function readers.name(f,fontdata,specification)
offset = start + readushort(f),
}
else
- skipshort(f,2)
+namelist[#namelist+1] = {
+ platform = platform,
+ encoding = encoding,
+ language = language,
+ length = readushort(f),
+ offset = start + readushort(f),
+}
+-- skipshort(f,2)
end
else
skipshort(f,3)
@@ -783,8 +790,9 @@ function readers.name(f,fontdata,specification)
--
-- we need to choose one we like, for instance an unicode one
--
- local names = { }
- local done = { }
+ local names = { }
+ local done = { }
+ local extras = { }
--
-- there is quite some logic in ff ... hard to follow so we start simple
-- and extend when we run into it (todo: proper reverse hash) .. we're only
@@ -795,7 +803,7 @@ function readers.name(f,fontdata,specification)
for i=1,#namelist do
local name = namelist[i]
local nametag = name.name
- if not done[nametag] then
+ if not done[nametag or i] then
local encoding = name.encoding
local language = name.language
if (not e or encoding == e) and (not l or language == l) then
@@ -808,13 +816,16 @@ function readers.name(f,fontdata,specification)
if decoder then
content = decoder(content)
end
- names[nametag] = {
- content = content,
- platform = platform,
- encoding = encoding,
- language = language,
- }
- done[nametag] = true
+ if nametag then
+ names[nametag] = {
+ content = content,
+ platform = platform,
+ encoding = encoding,
+ language = language,
+ }
+ end
+ extras[i-1] = content
+ done[nametag or i] = true
end
end
end
@@ -827,7 +838,8 @@ function readers.name(f,fontdata,specification)
filter("macintosh")
filter("unicode")
--
- fontdata.names = names
+ fontdata.names = names
+ fontdata.extras = extras
--
if specification.platformnames then
local collected = { }
@@ -1288,7 +1300,8 @@ local sequence = {
local supported = { }
for i=1,#sequence do
- local sp, se, sf = unpack(sequence[i])
+ local si = sequence[i]
+ local sp, se, sf = si[1], si[2], si[3]
local p = supported[sp]
if not p then
p = { }
@@ -1704,7 +1717,8 @@ function readers.cmap(f,fontdata,specification)
--
local ok = false
for i=1,#sequence do
- local sp, se, sf = unpack(sequence[i])
+ local si = sequence[i]
+ local sp, se, sf = si[1], si[2], si[3]
if checkcmap(f,fontdata,records,sp,se,sf) > 0 then
ok = true
end
@@ -2000,7 +2014,6 @@ local function readdata(f,offset,specification)
end
end
--
- --
readers["os/2"](f,fontdata,specification)
readers["head"](f,fontdata,specification)
readers["maxp"](f,fontdata,specification)
@@ -2023,6 +2036,12 @@ local function readdata(f,offset,specification)
readers["gpos"](f,fontdata,specification)
readers["math"](f,fontdata,specification)
--
+ -- readers["fvar"](f,fontdata,specification)
+ -- readers["hvar"](f,fontdata,specification)
+ -- readers["vvar"](f,fontdata,specification)
+ -- readers["mvar"](f,fontdata,specification)
+ -- readers["vorg"](f,fontdata,specification)
+ --
fontdata.locations = nil
fontdata.tables = nil
fontdata.cidmaps = nil
diff --git a/tex/context/base/mkiv/font-ots.lua b/tex/context/base/mkiv/font-ots.lua
index 22dd082d1..742a0c561 100644
--- a/tex/context/base/mkiv/font-ots.lua
+++ b/tex/context/base/mkiv/font-ots.lua
@@ -125,7 +125,6 @@ local fonts = fonts
local otf = fonts.handlers.otf
local tracers = nodes.tracers
-local trace_lookups = false registertracker("otf.lookups", function(v) trace_lookups = v end)
local trace_singles = false registertracker("otf.singles", function(v) trace_singles = v end)
local trace_multiples = false registertracker("otf.multiples", function(v) trace_multiples = v end)
local trace_alternatives = false registertracker("otf.alternatives", function(v) trace_alternatives = v end)
@@ -738,7 +737,11 @@ end
local function get_alternative_glyph(start,alternatives,value)
local n = #alternatives
- if value == "random" then
+ if n == 1 then
+ -- we could actually change that into a gsub and save some memory in the
+ -- font loader but it makes tracing more messy
+ return alternatives[1], trace_alternatives and "1 (only one present)"
+ elseif value == "random" then
local r = getrandom and getrandom("glyph",1,n) or random(1,n)
return alternatives[r], trace_alternatives and formatters["value %a, taking %a"](value,r)
elseif value == "first" then
@@ -2356,7 +2359,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
size = l - f + 1
if size > 1 then
-- before/current/after | before/current | current/after
- local discfound = nil
+ local discfound -- = nil
local n = f + 1
-- last = getnext(last) -- the second in current (first already matched)
last = startnext -- the second in current (first already matched)
@@ -2485,7 +2488,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
-- sweeptype = nil
end
if prev then
- local discfound = nil
+ local discfound -- = nil
local n = f - 1
while n >= 1 do
if prev then
@@ -2597,7 +2600,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
-- maybe only if match
prev = getprev(prev)
- elseif seq[n][32] and id == glue_code and isspace(prev,threshold,id) then
+ elseif id == glue_code and seq[n][32] and isspace(prev,threshold,id) then
n = n - 1
prev = getprev(prev)
else
@@ -2619,14 +2622,12 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
-- after
if match and s > l then
local current = last and getnext(last)
- if not current then
- if sweeptype == "post" or sweeptype == "replace" then
- current = getnext(sweepnode)
- -- sweeptype = nil
- end
+ if not current and (sweeptype == "post" or sweeptype == "replace") then
+ current = getnext(sweepnode)
+ -- sweeptype = nil
end
if current then
- local discfound = nil
+ local discfound -- = nil
-- removed optimization for s-l == 1, we have to deal with marks anyway
local n = l + 1
while n <= s do
@@ -2731,7 +2732,7 @@ local function handle_contextchain(head,start,dataset,sequence,contexts,rlmode)
end
-- maybe only if match
current = getnext(current)
- elseif seq[n][32] and id == glue_code and isspace(current,threshold,id) then
+ elseif id == glue_code and seq[n][32] and isspace(current,threshold,id) then
n = n + 1
current = getnext(current)
else
@@ -2910,6 +2911,14 @@ do -- overcome local limit
end
+-- Functions like kernrun, comprun etc evolved over time and in the end look rather
+-- complex. It's a bit of a compromis between extensive copying and creating subruns.
+-- The logic has been improved a lot by Kai and Ivo who use complex fonts which
+-- really helped to identify border cases on the one hand and get insight in the diverse
+-- ways fonts implement features (not always that consistent and efficient). At the same
+-- time I tried to keep the code relatively efficient so that the overhead in runtime
+-- stays acceptable.
+
local function report_disc(what,n)
report_run("%s: %s > %s",what,n,languages.serializediscretionary(n))
end
@@ -3014,7 +3023,7 @@ local function kernrun(disc,k_run,font,attr,...)
return nextstart, done
end
--- fonts like ebgaramond do ligatuires this way (less efficient than e.g. dejavu which
+-- fonts like ebgaramond do ligatures this way (less efficient than e.g. dejavu which
-- will do the testrun variant)
local function comprun(disc,c_run,...) -- vararg faster than the whole list
@@ -3741,6 +3750,14 @@ otf.helpers = otf.helpers or { }
otf.helpers.txtdirstate = txtdirstate
otf.helpers.pardirstate = pardirstate
+-- This is the main loop. We run over the node list dealing with a specific font. The
+-- attribute is a context specific thing. We could work on sub start-stop ranges instead
+-- but I wonder if there is that much speed gain (experiments showed that it made not
+-- much sense) and we need to keep track of directions anyway. Also at some point I
+-- want to play with font interactions and then we do need the full sweeps. Apart from
+-- optimizations the principles of processing the features hasn't changed much since
+-- the beginning.
+
local function featuresprocessor(head,font,attr)
local sequences = sequencelists[font] -- temp hack
@@ -3791,11 +3808,6 @@ local function featuresprocessor(head,font,attr)
local dirstack = { } -- could move outside function but we can have local runs
sweephead = { }
- -- We could work on sub start-stop ranges instead but I wonder if there is that
- -- much speed gain (experiments showed that it made not much sense) and we need
- -- to keep track of directions anyway. Also at some point I want to play with
- -- font interactions and then we do need the full sweeps.
-
-- Keeping track of the headnode is needed for devanagari. (I generalized it a bit
-- so that multiple cases are also covered.) We could prepend a temp node.
@@ -3906,6 +3918,9 @@ local function featuresprocessor(head,font,attr)
elseif char == false then
-- whatever glyph
start = getnext(start)
+ elseif id == glue_code then
+ -- happens often
+ start = getnext(start)
elseif id == disc_code then
local ok
if gpossing then
@@ -3977,6 +3992,10 @@ local function featuresprocessor(head,font,attr)
start = getnext(start)
end
elseif char == false then
+ -- whatever glyph
+ start = getnext(start)
+ elseif id == glue_code then
+ -- happens often
start = getnext(start)
elseif id == disc_code then
local ok
diff --git a/tex/context/base/mkiv/luat-cnf.lua b/tex/context/base/mkiv/luat-cnf.lua
index 9d37df7bb..c26b4775b 100644
--- a/tex/context/base/mkiv/luat-cnf.lua
+++ b/tex/context/base/mkiv/luat-cnf.lua
@@ -70,9 +70,8 @@ function texconfig.init()
"epdf", "fontloader", "kpse", "mplib",
},
obsolete = {
- "fontforge", -- can be filled by luat-log
+ "fontloader", -- can be filled by luat-log
"kpse",
- "token",
},
functions = {
"assert", "pcall", "xpcall", "error", "collectgarbage",
diff --git a/tex/context/base/mkiv/node-fin.lua b/tex/context/base/mkiv/node-fin.lua
index 03c8a7607..ffb2ae49e 100644
--- a/tex/context/base/mkiv/node-fin.lua
+++ b/tex/context/base/mkiv/node-fin.lua
@@ -327,7 +327,7 @@ local function selective(namespace,attribute,head,inheritance,default) -- two at
if id == glyph_code then
check = true
elseif id == disc_code then
- check = true -- notneeded when we flatten replace
+ check = true -- not needed when we flatten replace
elseif id == glue_code then
leader = getleader(stack)
if leader then
diff --git a/tex/context/base/mkiv/publ-imp-apa.lua b/tex/context/base/mkiv/publ-imp-apa.lua
index f2e7f11e1..ec46b7f7e 100644
--- a/tex/context/base/mkiv/publ-imp-apa.lua
+++ b/tex/context/base/mkiv/publ-imp-apa.lua
@@ -191,7 +191,7 @@ categories.inbook = {
optional = {
"withauthor", "translator",
"subtitle", "type", "file",
- "booktitle",
+ "booktitle", "subbooktitle",
-- APA ignores this: "chapter",
"editionset", "series",
"month",
@@ -217,6 +217,7 @@ categories.incollection = {
optional = {
"withauthor", "translator",
"subtitle", "type", "file",
+ "subbooktitle",
"editionset", "series",
-- APA ignores this: "chapter",
"month",
diff --git a/tex/context/base/mkiv/publ-imp-apa.mkvi b/tex/context/base/mkiv/publ-imp-apa.mkvi
index 6470bb089..77fcb8995 100644
--- a/tex/context/base/mkiv/publ-imp-apa.mkvi
+++ b/tex/context/base/mkiv/publ-imp-apa.mkvi
@@ -88,6 +88,14 @@
[\c!authorconversion=normalshort]
\definebtx
+ [apa:\s!list:director]
+ [apa:\s!list:author]
+
+\definebtx
+ [apa:\s!list:producer]
+ [apa:\s!list:author]
+
+\definebtx
[apa:\s!list:suffix]
[apa:\s!list]
diff --git a/tex/context/base/mkiv/publ-ini.lua b/tex/context/base/mkiv/publ-ini.lua
index 86dc6cea2..52642c89d 100644
--- a/tex/context/base/mkiv/publ-ini.lua
+++ b/tex/context/base/mkiv/publ-ini.lua
@@ -1984,6 +1984,33 @@ do
arguments = { "string", "string" }
}
+ local function identical(a,b)
+ local na, nb = #a, #b
+ if na ~= nb then
+ return false
+ end
+ if na > 0 then
+ for i=1,na do
+ if not identical(a[i],b[i]) then
+ return false
+ end
+ end
+ return true
+ end
+ local ha, hb = a.hash, b.hash
+ if ha then
+ return ha == hb
+ end
+ for k, v in next, a do
+ if k == "original" or k == "snippets" then
+ -- skip diagnostic info
+ elseif v ~= b[k] then
+ return false
+ end
+ end
+ return true
+ end
+
function lists.sameasprevious(dataset,i,name,order,method)
local rendering = renderings[dataset]
local list = rendering.list
@@ -2030,7 +2057,7 @@ do
if c_casted and c_casted == p_casted then
sameentry = true
elseif type(c_casted) == "table" and type(p_casted) == "table" then
- sameentry = table.identical(c_casted,p_casted)
+ sameentry = identical(c_casted,p_casted)
end
end
if trace_detail then
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index 1441c0e6c..6d7f14ae0 100644
--- a/tex/context/base/mkiv/status-files.pdf
+++ b/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/status-lua.pdf b/tex/context/base/mkiv/status-lua.pdf
index cc2383ec2..189773237 100644
--- a/tex/context/base/mkiv/status-lua.pdf
+++ b/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/tex/context/base/mkiv/trac-deb.lua b/tex/context/base/mkiv/trac-deb.lua
index 782be154f..d1168a3a9 100644
--- a/tex/context/base/mkiv/trac-deb.lua
+++ b/tex/context/base/mkiv/trac-deb.lua
@@ -372,3 +372,15 @@ implement { name = "disableexperiments", actions = experiments.disable, argument
implement { name = "showdebuginfo", actions = lmx.showdebuginfo }
implement { name = "overloaderror", actions = lmx.overloaderror }
implement { name = "showlogcategories", actions = logs.show }
+
+directives.register("system.profile",function()
+ luatex.registerstopactions(function()
+ debugger.disable()
+ debugger.savestats("luatex-profile.log")
+ report_nl()
+ logs.report("system","profiler stopped, log saved in %a","luatex-profile.log")
+ report_nl()
+ end)
+ logs.report("system","profiler started")
+ debugger.enable()
+end)
diff --git a/tex/context/base/mkiv/util-deb.lua b/tex/context/base/mkiv/util-deb.lua
index ee732b3b5..040a7a9cf 100644
--- a/tex/context/base/mkiv/util-deb.lua
+++ b/tex/context/base/mkiv/util-deb.lua
@@ -12,87 +12,236 @@ if not modules then modules = { } end modules ['util-deb'] = {
local debug = require "debug"
-local getinfo = debug.getinfo
+local getinfo, sethook = debug.getinfo, debug.sethook
local type, next, tostring = type, next, tostring
-local format, find = string.format, string.find
-local is_boolean = string.is_boolean
+local format, find, sub, gsub = string.format, string.find, string.sub, string.gsub
+local insert, remove, sort = table.insert, table.remove, table.sort
utilities = utilities or { }
local debugger = utilities.debugger or { }
utilities.debugger = debugger
-local counters = { }
+local report = logs.reporter("debugger")
+
+local ticks = os.gettimeofday or os.clock
+local seconds = function(n) return n or 0 end
+local overhead = 0
+local dummycalls = 10*1000
+local nesting = 0
local names = { }
-local report = logs.reporter("debugger")
+local function initialize()
--- one
+ if FFISUPPORTED and ffi then
-local function hook()
- local f = getinfo(2) -- "nS"
- if f then
- local n = "unknown"
- if f.what == "C" then
- n = f.name or '<anonymous>'
- if not names[n] then
- names[n] = format("%42s",n)
+ if os.type == "windows" then
+ local okay, kernel = pcall(ffi.load,"kernel32")
+ if kernel then
+ local tonumber = ffi.number or tonumber
+ffi.cdef[[
+int QueryPerformanceFrequency(int64_t *lpFrequency);
+int QueryPerformanceCounter(int64_t *lpPerformanceCount);
+]]
+ local target = ffi.new("__int64[1]")
+ ticks = function()
+ if kernel.QueryPerformanceCounter(target) == 1 then
+ return tonumber(target[0])
+ else
+ return 0
+ end
+ end
+ local target = ffi.new("__int64[1]")
+ seconds = function(ticks)
+ if kernel.QueryPerformanceFrequency(target) == 1 then
+ return ticks / tonumber(target[0])
+ else
+ return 0
+ end
+ end
end
- else
- -- source short_src linedefined what name namewhat nups func
- n = f.name or f.namewhat or f.what
- if not n or n == "" then
- n = "?"
+ elseif os.type == "unix" then
+ local C = ffi.C
+ local tonumber = ffi.number or tonumber
+ -- 1 = CLOCK_MONOTONIC
+ -- 2 = CLOCK_PROCESS_CPUTIME_ID
+ffi.cdef [[
+struct timespec { long sec; long nsec; };
+int clock_gettime(int timerid, struct timespec *t);
+ ]]
+ local target = ffi.new("timespec[?]",1)
+ function ticks()
+ C.clock_gettime(2,target)
+ return tonumber(target[0].sec*1000000000 + target[0].nsec)
end
- if not names[n] then
- names[n] = format("%42s : % 5i : %s",n,f.linedefined or 0,f.short_src or "unknown source")
+ seconds = function(ticks)
+ return ticks/1000000000
end
+
end
- counters[n] = (counters[n] or 0) + 1
end
+
+ initialize = false
+
end
-function debugger.showstats(printer,threshold) -- hm, something has changed, rubish now
- printer = printer or report
- threshold = threshold or 0
- local total, grandtotal, functions = 0, 0, 0
- local dataset = { }
- for name, count in next, counters do
- dataset[#dataset+1] = { name, count }
+table.setmetatableindex(names,function(t,name)
+ local v = table.setmetatableindex(function(t,source)
+ local v = table.setmetatableindex(function(t,line)
+ local v = { total = 0, count = 0 }
+ t[line] = v
+ return v
+ end)
+ t[source] = v
+ return v
+ end)
+ t[name] = v
+ return v
+end)
+
+local function hook(where)
+ local f = getinfo(2,"nSl")
+ if f then
+ local source = f.short_src
+ if not source then
+ return
+ end
+ local line = f.linedefined or 0
+ local name = f.name
+ if not name then
+ local what = f.what
+ if what == "C" then
+ name = "<anonymous>"
+ else
+ name = f.namewhat or what or "<unknown>"
+ end
+ end
+ local data = names[name][source][line]
+ if where == "call" then
+ data.count = data.count + 1
+ insert(data,ticks())
+ elseif where == "return" then
+ local t = remove(data)
+ if t then
+ data.total = data.total + ticks() - t
+ end
+ end
end
- table.sort(dataset,function(a,b) return a[2] == b[2] and b[1] > a[1] or a[2] > b[2] end)
- for i=1,#dataset do
- local d = dataset[i]
- local name = d[1]
- local count = d[2]
- if count > threshold and not find(name,"for generator") then -- move up
- printer(format("%8i %s\n", count, names[name]))
- total = total + count
+end
+
+function debugger.showstats(printer)
+ local printer = printer or report
+ local calls = 0
+ local functions = 0
+ local dataset = { }
+ local length = 0
+ local wholetime = 0
+ for name, sources in next, names do
+ for source, lines in next, sources do
+ for line, data in next, lines do
+ if #name > length then
+ length = #name
+ end
+ local total = data.total
+ local count = data.count
+ local real = total
+ if real > 0 then
+ real = total - (count * overhead / dummycalls)
+ if real < 0 then
+ real = 0
+ end
+ wholetime = wholetime + real
+ end
+ if line < 0 then
+ line = 0
+ end
+ dataset[#dataset+1] = { real, total, count, name, source, line }
+ end
+ end
+ end
+ sort(dataset,function(a,b)
+ if a[1] == b[1] then
+ if a[2] == b[2] then
+ if a[3] == b[3] then
+ if a[4] == b[4] then
+ if a[5] == b[5] then
+ return a[6] < b[6]
+ else
+ return a[5] < b[5]
+ end
+ else
+ return a[4] < b[4]
+ end
+ else
+ return b[3] < a[3]
+ end
+ else
+ return b[2] < a[2]
+ end
+ else
+ return b[1] < a[1]
end
- grandtotal = grandtotal + count
+ end)
+ if length > 50 then
+ length = 50
+ end
+ local fmt = string.formatters["%4.9k %4.9k %3.3k %8i %-" .. length .. "s %4i %s"]
+ for i=1,#dataset do
+ local data = dataset[i]
+ local real = data[1]
+ local total = data[2]
+ local count = data[3]
+ local name = data[4]
+ local source = data[5]
+ local line = data[6]
+ local percent = real / wholetime
+ calls = calls + count
functions = functions + 1
+ name = gsub(name,"%s+"," ")
+ if #name > length then
+ name = sub(name,1,length)
+ end
+ printer(fmt(seconds(total),seconds(real),percent,count,name,line,source))
end
- printer("\n")
- printer(format("functions : % 10i\n", functions))
- printer(format("total : % 10i\n", total))
- printer(format("grand total: % 10i\n", grandtotal))
- printer(format("threshold : % 10i\n", threshold))
+ printer("")
+ printer(format("functions : %i", functions))
+ printer(format("calls : %i", calls))
+ printer(format("overhead : %f", seconds(overhead/1000)))
end
-function debugger.savestats(filename,threshold)
+function debugger.savestats(filename)
local f = io.open(filename,'w')
if f then
- debugger.showstats(function(str) f:write(str) end,threshold)
+ debugger.showstats(function(str) f:write(str,"\n") end)
f:close()
end
end
function debugger.enable()
- debug.sethook(hook,"c")
+ if nesting == 0 then
+ running = true
+ if initialize then
+ initialize()
+ end
+ sethook(hook,"cr")
+ local function dummy() end
+ local t = ticks()
+ for i=1,dummycalls do
+ dummy()
+ end
+ overhead = ticks() - t
+ end
+ if nesting > 0 then
+ nesting = nesting + 1
+ end
end
function debugger.disable()
- debug.sethook()
- -- counters[debug.getinfo(2,"f").func] = nil
+ if nesting > 0 then
+ nesting = nesting - 1
+ end
+ if nesting == 0 then
+ sethook()
+ end
end
-- debugger.enable()
diff --git a/tex/context/base/mkiv/util-env.lua b/tex/context/base/mkiv/util-env.lua
index fb3dda41f..0b832e72e 100644
--- a/tex/context/base/mkiv/util-env.lua
+++ b/tex/context/base/mkiv/util-env.lua
@@ -31,15 +31,23 @@ end
-- setlocale(nil,nil)
-- end
--
--- function os.pushlocale(...)
+-- function os.pushlocale(l,...)
-- insert(stack, {
--- collate = setlocale("collate"),
--- ctype = setlocale("ctype"),
--- monetary = setlocale("monetary"),
--- numeric = setlocale("numeric"),
--- time = setlocale("time"),
+-- collate = setlocale(nil,"collate"),
+-- ctype = setlocale(nil,"ctype"),
+-- monetary = setlocale(nil,"monetary"),
+-- numeric = setlocale(nil,"numeric"),
+-- time = setlocale(nil,"time"),
-- })
--- setlocale(...)
+-- if l then
+-- setlocale(l,...)
+-- else
+-- setlocale(status.lc_collate ,"collate"),
+-- setlocale(status.lc_ctype ,"ctype"),
+-- setlocale(status.lc_monetary,"monetary"),
+-- setlocale(status.lc_numeric ,"numeric"),
+-- setlocale(status.lc_time ,"time"),
+-- end
-- end
--
-- function os.poplocale(...)
@@ -51,6 +59,12 @@ end
-- end
-- end
--
+-- function os.setlocale()
+-- -- no way you can mess with it, use push/pop
+-- end
+--
+-- setlocale(nil,nil) -- setlocale("all","C")
+--
-- end
-- dirty tricks (we will replace the texlua call by luatex --luaonly)
diff --git a/tex/context/base/mkiv/util-fil.lua b/tex/context/base/mkiv/util-fil.lua
index cf97d9541..dba3b235c 100644
--- a/tex/context/base/mkiv/util-fil.lua
+++ b/tex/context/base/mkiv/util-fil.lua
@@ -101,9 +101,10 @@ function files.readinteger1(f) -- one byte
end
end
-files.readcardinal1 = files.readbyte -- one byte
-files.readcardinal = files.readcardinal1
-files.readinteger = files.readinteger1
+files.readcardinal1 = files.readbyte -- one byte
+files.readcardinal = files.readcardinal1
+files.readinteger = files.readinteger1
+files.readsignedbyte = files.readinteger1
function files.readcardinal2(f)
local a, b = byte(f:read(2),1,2)
diff --git a/tex/context/base/mkiv/util-lib.lua b/tex/context/base/mkiv/util-lib.lua
index 2601b2e57..e9a968228 100644
--- a/tex/context/base/mkiv/util-lib.lua
+++ b/tex/context/base/mkiv/util-lib.lua
@@ -6,9 +6,6 @@ if not modules then modules = { } end modules ['util-lib'] = {
license = "see context related readme files",
}
--- This is experimental code for Hans and Luigi. Don't depend on it! There
--- will be a plain variant.
-
--[[
The problem with library bindings is manyfold. They are of course platform
@@ -73,29 +70,41 @@ and then without.
]]--
--- seems to be clua in recent texlive
-
-local gsub, find = string.gsub, string.find
-local pathpart, nameonly, joinfile = file.pathpart, file.nameonly, file.join
-local findfile, findfiles = resolvers and resolvers.findfile, resolvers and resolvers.findfiles
-
-local loaded = package.loaded
+local type = type
+local next = next
+local pcall = pcall
+local gsub = string.gsub
+local find = string.find
+local sort = table.sort
+local pathpart = file.pathpart
+local nameonly = file.nameonly
+local joinfile = file.join
+local removesuffix = file.removesuffix
+local findfile = resolvers.findfile
+local findfiles = resolvers.findfiles
+local expandpaths = resolvers.expandedpathlistfromvariable
+local qualifiedpath = file.is_qualified_path
+local isfile = lfs.isfile
-local report_swiglib = logs.reporter("swiglib")
-local trace_swiglib = false trackers.register("resolvers.swiglib", function(v) trace_swiglib = v end)
+local done = false
-- We can check if there are more that one component, and if not, we can
-- append 'core'.
-local done = false
-
-local function requireswiglib(required,version)
- local trace_swiglib = trace_swiglib or package.helpers.trace
- local library = loaded[required]
- if library == nil then
- if trace_swiglib then
- report_swiglib("requiring library %a with version %a",required,version or "any")
+local function locate(required,version,trace,report,action)
+ if type(required) ~= "string" then
+ report("provide a proper library name")
+ return
+ end
+ if trace then
+ report("requiring library %a with version %a",required,version or "any")
+ end
+ local found_library = nil
+ if qualifiedpath(required) then
+ if isfile(required) then
+ found_library = required
end
+ else
-- initialize a few variables
local required_full = gsub(required,"%.","/") -- package.helpers.lualibfile
local required_path = pathpart(required_full)
@@ -104,16 +113,16 @@ local function requireswiglib(required,version)
local version = type(version) == "string" and version ~= "" and version or false
local engine = environment.ownmain or false
--
- if trace_swiglib and not done then
- local list = resolvers.expandedpathlistfromvariable("lib") -- fresh, no reuse
+ if trace and not done then
+ local list = expandpaths("lib") -- fresh, no reuse
for i=1,#list do
- report_swiglib("tds path %i: %s",i,list[i])
+ report("tds path %i: %s",i,list[i])
end
end
-- helpers
local function found(locate,asked_library,how,...)
- if trace_swiglib then
- report_swiglib("checking %s: %a",how,asked_library)
+ if trace then
+ report("checking %s: %a",how,asked_library)
end
return locate(asked_library,...)
end
@@ -121,15 +130,15 @@ local function requireswiglib(required,version)
local found = nil
if version then
local asked_library = joinfile(required_path,version,required_name)
- if trace_swiglib then
- report_swiglib("checking %s: %a","with version",asked_library)
+ if trace then
+ report("checking %s: %a","with version",asked_library)
end
found = locate(asked_library,...)
end
if not found or found == "" then
local asked_library = joinfile(required_path,required_name)
- if trace_swiglib then
- report_swiglib("checking %s: %a","with version",asked_library)
+ if trace then
+ report("checking %s: %a","with version",asked_library)
end
found = locate(asked_library,...)
end
@@ -140,32 +149,32 @@ local function requireswiglib(required,version)
-- match anyway.
local function attempt(checkpattern)
-- check cnf spec using name and version
- if trace_swiglib then
- report_swiglib("checking tds lib paths strictly")
+ if trace then
+ report("checking tds lib paths strictly")
end
local found = findfile and check(findfile,"lib")
if found and (not checkpattern or find(found,checkpattern)) then
return found
end
-- check cnf spec using wildcard
- if trace_swiglib then
- report_swiglib("checking tds lib paths with wildcard")
+ if trace then
+ report("checking tds lib paths with wildcard")
end
local asked_library = joinfile(required_path,".*",required_name)
- if trace_swiglib then
- report_swiglib("checking %s: %a","latest version",asked_library)
+ if trace then
+ report("checking %s: %a","latest version",asked_library)
end
local list = findfiles(asked_library,"lib",true)
if list and #list > 0 then
- table.sort(list)
+ sort(list)
local found = list[#list]
if found and (not checkpattern or find(found,checkpattern)) then
return found
end
end
-- Check lib paths using name and version.
- if trace_swiglib then
- report_swiglib("checking lib paths")
+ if trace then
+ report("checking lib paths")
end
package.extralibpath(environment.ownpath)
local paths = package.libpaths()
@@ -177,59 +186,80 @@ local function requireswiglib(required,version)
end
return false
end
- local found_library = nil
if engine then
- if trace_swiglib then
- report_swiglib("attemp 1, engine %a",engine)
+ if trace then
+ report("attemp 1, engine %a",engine)
end
found_library = attempt("/"..engine.."/")
if not found_library then
- if trace_swiglib then
- report_swiglib("attemp 2, no engine",asked_library)
+ if trace then
+ report("attemp 2, no engine",asked_library)
end
found_library = attempt()
end
else
found_library = attempt()
end
- -- load and initialize when found
- if not found_library then
- if trace_swiglib then
- report_swiglib("not found: %a",required)
- end
- library = false
- else
- local path = pathpart(found_library)
- local base = nameonly(found_library)
- dir.push(path)
- if trace_swiglib then
- report_swiglib("found: %a",found_library)
- end
- local message = nil
- local opener = "luaopen_" .. required_base
- library, message = package.loadlib(found_library,opener)
- local libtype = type(library)
- if libtype == "function" then
- library = library()
- else
- report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library")
- library = false
- end
- dir.pop()
- end
- -- cache result
- if not library then
- report_swiglib("unknown: %a",required)
- elseif trace_swiglib then
- report_swiglib("stored: %a",required)
+ end
+ -- load and initialize when found
+ if not found_library then
+ if trace then
+ report("not found: %a",required)
end
- loaded[required] = library
+ library = false
else
- report_swiglib("reused: %a",required)
+ if trace then
+ report("found: %a",found_library)
+ end
+ local message, result = action(found_library,required_base)
+ if result then
+ library = result
+ else
+ library = false
+ report("load error: message %a, library %a",tostring(message),found_library or "no library")
+ end
+ end
+ if not library then
+ report("unknown: %a",required)
+ elseif trace then
+ report("stored: %a",required)
end
return library
end
+do
+
+ local report_swiglib = logs.reporter("swiglib")
+ local trace_swiglib = false
+ local savedrequire = require
+ local loadedlibs = { }
+
+ trackers.register("resolvers.swiglib", function(v) trace_swiglib = v end)
+
+ function requireswiglib(required,version)
+ local library = loadedlibs[library]
+ if library == nil then
+ local trace_swiglib = trace_swiglib or package.helpers.trace
+ library = locate(required,version,trace_swiglib,report_swiglib,function(name,base)
+ dir.push(pathpart(name))
+ local opener = "luaopen_" .. base
+ local library, message = package.loadlib(name,opener)
+ local libtype = type(library)
+ if libtype == "function" then
+ library = library()
+ message = true
+ else
+ report_swiglib("load error: %a returns %a, message %a, library %a",opener,libtype,(string.gsub(message or "no message","[%s]+$","")),found_library or "no library")
+ library = false
+ end
+ dir.pop()
+ return message, library
+ end)
+ loadedlibs[required] = library or false
+ end
+ return library
+ end
+
--[[
For convenience we make the require loader function swiglib aware. Alternatively
@@ -237,15 +267,13 @@ we could put the specific loader in the global namespace.
]]--
-local savedrequire = require
-
-function require(name,version)
- if find(name,"^swiglib%.") then
- return requireswiglib(name,version)
- else
- return savedrequire(name)
+ function require(name,version)
+ if find(name,"^swiglib%.") then
+ return requireswiglib(name,version)
+ else
+ return savedrequire(name)
+ end
end
-end
--[[
@@ -255,43 +283,87 @@ recommended loader.
]]--
-local swiglibs = { }
-local initializer = "core"
+ local swiglibs = { }
+ local initializer = "core"
-function swiglib(name,version)
- local library = swiglibs[name]
- if not library then
- statistics.starttiming(swiglibs)
- if trace_swiglib then
- report_swiglib("loading %a",name)
- end
- if not find(name,"%." .. initializer .. "$") then
- fullname = "swiglib." .. name .. "." .. initializer
- else
- fullname = "swiglib." .. name
+ function swiglib(name,version)
+ local library = swiglibs[name]
+ if not library then
+ statistics.starttiming(swiglibs)
+ if trace_swiglib then
+ report_swiglib("loading %a",name)
+ end
+ if not find(name,"%." .. initializer .. "$") then
+ fullname = "swiglib." .. name .. "." .. initializer
+ else
+ fullname = "swiglib." .. name
+ end
+ library = requireswiglib(fullname,version)
+ swiglibs[name] = library
+ statistics.stoptiming(swiglibs)
end
- library = requireswiglib(fullname,version)
- swiglibs[name] = library
- statistics.stoptiming(swiglibs)
+ return library
end
- return library
+
+ statistics.register("used swiglibs", function()
+ if next(swiglibs) then
+ return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs))
+ end
+ end)
+
end
-statistics.register("used swiglibs", function()
- if next(swiglibs) then
- return string.format("%s, initial load time %s seconds",table.concat(table.sortedkeys(swiglibs)," "),statistics.elapsedtime(swiglibs))
+if FFISUPPORTED and ffi and ffi.load then
+
+--[[
+
+We use the same lookup logic for ffi loading.
+
+]]--
+
+ local report_ffilib = logs.reporter("ffilib")
+ local trace_ffilib = false
+ local savedffiload = ffi.load
+
+ trackers.register("resolvers.ffilib", function(v) trace_ffilib = v end)
+
+ function ffilib(required,version)
+ return locate(required,version,trace_ffilib,report_ffilib,function(name)
+ local message, library = pcall(savedffiload,removesuffix(name))
+ if type(library) == "userdata" then
+ return message, library
+ else
+ return message, false
+ end
+ end)
end
-end)
+
+ function ffi.load(name)
+ local library = ffilib(name)
+ if type(library) == "userdata" then
+ return library
+ else
+ report_ffilib("trying to load %a using normal loader",name)
+ return savedffiload(name)
+ end
+ end
+
+end
--[[
-So, we now have:
+-- So, we now have:
+
+trackers.enable("resolvers.ffilib")
+trackers.enable("resolvers.swiglib")
local gm = require("swiglib.gmwand.core")
local gm = swiglib("gmwand.core")
local sq = swiglib("mysql.core")
local sq = swiglib("mysql.core","5.6")
-Watch out, the last one is less explicit and lacks the swiglib prefix.
+ffilib("libmysql","5.6.14")
+
+-- Watch out, the last one is less explicit and lacks the swiglib prefix.
]]--
diff --git a/tex/context/base/mkiv/util-str.lua b/tex/context/base/mkiv/util-str.lua
index fb510257a..9e6be9999 100644
--- a/tex/context/base/mkiv/util-str.lua
+++ b/tex/context/base/mkiv/util-str.lua
@@ -449,6 +449,31 @@ function number.sparseexponent(f,n)
return tostring(n)
end
+local hf = { }
+local hs = { }
+
+setmetatable(hf, { __index = function(t,k)
+ local v = "%." .. k .. "f"
+ t[k] = v
+ return v
+end } )
+
+setmetatable(hs, { __index = function(t,k)
+ local v = "%" .. k .. "s"
+ t[k] = v
+ return v
+end } )
+
+function number.formattedfloat(n,b,a)
+ local s = format(hf[a],n)
+ local l = (b or 0) + (a or 0) + 1
+ if #s < l then
+ return format(hs[l],s)
+ else
+ return s
+ end
+end
+
local template = [[
%s
%s
@@ -479,6 +504,7 @@ local autodouble=string.autodouble
local sequenced=table.sequenced
local formattednumber=number.formatted
local sparseexponent=number.sparseexponent
+local formattedfloat=number.formattedfloat
]]
else
@@ -504,6 +530,7 @@ else
sequenced = table.sequenced,
formattednumber = number.formatted,
sparseexponent = number.sparseexponent,
+ formattedfloat = number.formattedfloat
}
end
@@ -521,6 +548,9 @@ setmetatable(arguments, { __index =
})
local prefix_any = C((S("+- .") + R("09"))^0)
+local prefix_sub = (C((S("+-") + R("09"))^0) + Cc(0))
+ * P(".")
+ * (C((S("+-") + R("09"))^0) + Cc(0))
local prefix_tab = P("{") * C((1-P("}"))^0) * P("}") + C((1-R("az","AZ","09","%%"))^0)
-- we've split all cases as then we can optimize them (let's omit the fuzzy u)
@@ -594,6 +624,11 @@ local format_F = function(f) -- beware, no cast to number
end
end
+local format_k = function(b,a) -- slow
+ n = n + 1
+ return format("formattedfloat(a%s,%i,%i)",n,b or 0, a or 0)
+end
+
local format_g = function(f)
n = n + 1
return format("format('%%%sg',a%s)",f,n)
@@ -855,6 +890,7 @@ local builder = Cs { "start",
+ V("S") -- new
+ V("Q") -- new
+ V("N") -- new
+ + V("k") -- new
--
+ V("r")
+ V("h") + V("H") + V("u") + V("U")
@@ -894,6 +930,7 @@ local builder = Cs { "start",
["S"] = (prefix_any * P("S")) / format_S, -- %S => %s (tostring)
["Q"] = (prefix_any * P("Q")) / format_S, -- %Q => %q (tostring)
["N"] = (prefix_any * P("N")) / format_N, -- %N => tonumber (strips leading zeros)
+ ["k"] = (prefix_sub * P("k")) / format_k, -- %k => like f but with n.m
["c"] = (prefix_any * P("c")) / format_c, -- %c => utf character (extension to regular)
["C"] = (prefix_any * P("C")) / format_C, -- %c => U+.... utf character
--