summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv
diff options
context:
space:
mode:
authorHans Hagen <pragma@wxs.nl>2021-06-24 19:37:45 +0200
committerContext Git Mirror Bot <phg@phi-gamma.net>2021-06-24 19:37:45 +0200
commit820657bb1e9acfb36f24dfa8801526b0d5f2b464 (patch)
treefc93fd3936e84b9b0a6402719e185d35e332eee9 /tex/context/base/mkiv
parent4272a26c49cbfee8917e5272fc0f964cbcfc4b03 (diff)
downloadcontext-820657bb1e9acfb36f24dfa8801526b0d5f2b464.tar.gz
2021-06-24 18:52:00
Diffstat (limited to 'tex/context/base/mkiv')
-rw-r--r--tex/context/base/mkiv/back-exp.lua2
-rw-r--r--tex/context/base/mkiv/cldf-ini.lua16
-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-dec.lua56
-rw-r--r--tex/context/base/mkiv/data-tar.lua236
-rw-r--r--tex/context/base/mkiv/data-use.lua4
-rw-r--r--tex/context/base/mkiv/data-zip.lua4
-rw-r--r--tex/context/base/mkiv/font-cff.lua18
-rw-r--r--tex/context/base/mkiv/font-imp-math.lua3
-rw-r--r--tex/context/base/mkiv/font-imp-tweaks.lua115
-rw-r--r--tex/context/base/mkiv/font-osd.lua111
-rw-r--r--tex/context/base/mkiv/font-otc.lua353
-rw-r--r--tex/context/base/mkiv/font-otl.lua2
-rw-r--r--tex/context/base/mkiv/font-otr.lua2
-rw-r--r--tex/context/base/mkiv/grph-img.lua2
-rw-r--r--tex/context/base/mkiv/l-gzip.lua174
-rw-r--r--tex/context/base/mkiv/l-lpeg.lua12
-rw-r--r--tex/context/base/mkiv/l-os.lua2
-rw-r--r--tex/context/base/mkiv/lang-ini.lua15
-rw-r--r--tex/context/base/mkiv/luat-cnf.lua2
-rw-r--r--tex/context/base/mkiv/luat-cod.lua54
-rw-r--r--tex/context/base/mkiv/luat-lib.mkiv3
-rw-r--r--tex/context/base/mkiv/luat-run.lua2
-rw-r--r--tex/context/base/mkiv/luat-sto.lua2
-rw-r--r--tex/context/base/mkiv/lxml-ini.lua1
-rw-r--r--tex/context/base/mkiv/lxml-tex.lua8
-rw-r--r--tex/context/base/mkiv/mult-low.lua10
-rw-r--r--tex/context/base/mkiv/mult-prm.lua15
-rw-r--r--tex/context/base/mkiv/node-res.lua2
-rw-r--r--tex/context/base/mkiv/node-syn.lua7
-rw-r--r--tex/context/base/mkiv/status-files.pdfbin23588 -> 23600 bytes
-rw-r--r--tex/context/base/mkiv/status-lua.pdfbin246757 -> 248139 bytes
-rw-r--r--tex/context/base/mkiv/supp-box.lua2
-rw-r--r--tex/context/base/mkiv/util-fil.lua18
-rw-r--r--tex/context/base/mkiv/util-sac.lua23
-rw-r--r--tex/context/base/mkiv/util-tar.lua359
-rw-r--r--tex/context/base/mkiv/util-zip.lua201
38 files changed, 1333 insertions, 507 deletions
diff --git a/tex/context/base/mkiv/back-exp.lua b/tex/context/base/mkiv/back-exp.lua
index 5928da538..51c32ec1d 100644
--- a/tex/context/base/mkiv/back-exp.lua
+++ b/tex/context/base/mkiv/back-exp.lua
@@ -1640,7 +1640,7 @@ do
d.__i__ = n
data[n] = d
elseif content == " " or content == "" then
- if di.tg == "mspace" then
+ if d.tg == "mspace" then
-- we append or prepend a space to a preceding or following mtext
local parent = di.__p__
local index = di.__i__ -- == i
diff --git a/tex/context/base/mkiv/cldf-ini.lua b/tex/context/base/mkiv/cldf-ini.lua
index f95ac301c..a69b2d707 100644
--- a/tex/context/base/mkiv/cldf-ini.lua
+++ b/tex/context/base/mkiv/cldf-ini.lua
@@ -400,19 +400,22 @@ local registerscanner if CONTEXTLMTXMODE > 0 then
-- always permanent but we can consider to obey permanent==false
+ -- todo: make bitset instead of keys (nil is skipped anyway)
+
local function toflags(specification)
- local protected = specification.protected and "protected" -- or ""
+ local protected = specification.protected and "protected"
+ local untraced = specification.untraced and "untraced"
local usage = specification.usage
if usage == "value" then
- return "global", "value", "permanent", protected
+ return "global", "value", "permanent", "untraced", protected
elseif usage == "condition" then
- return "global", "conditional", "permanent", protected
+ return "global", "conditional", "permanent", "untraced", protected
elseif specification.frozen then
- return "global", "frozen", protected
+ return "global", "frozen", untraced, protected
elseif specification.permanent == false or specification.onlyonce then -- for now onlyonce here
- return "global", protected
+ return "global", untraced, protected
else
- return "global", "permanent", protected
+ return "global", "permanent", untraced, protected
end
end
@@ -422,6 +425,7 @@ local registerscanner if CONTEXTLMTXMODE > 0 then
storedscanners[name] = n
namesofscanners[n] = name
name = specification.public and name or (privatenamespace .. name)
+ -- print(name,n,toflags(specification))
setluatoken(name,n,toflags(specification))
end
diff --git a/tex/context/base/mkiv/cont-new.mkiv b/tex/context/base/mkiv/cont-new.mkiv
index 29bb55997..5ae1a881c 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{2021.06.14 17:06}
+\newcontextversion{2021.06.24 18:50}
%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 4e6e0dcb9..20d33af39 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{2021.06.14 17:06}
+\edef\contextversion{2021.06.24 18:50}
%D Kind of special:
diff --git a/tex/context/base/mkiv/data-dec.lua b/tex/context/base/mkiv/data-dec.lua
new file mode 100644
index 000000000..2a62b7dd9
--- /dev/null
+++ b/tex/context/base/mkiv/data-dec.lua
@@ -0,0 +1,56 @@
+if not modules then modules = { } end modules ['data-dec'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local loaddata = io.loaddata
+local suffix = file.suffix
+local resultof = os.resultof
+
+local decompressors = { }
+resolvers.decompressors = decompressors
+
+local decompresslzma = nil
+local decompressgzip = gzip.decompress
+
+local function decompressed(k)
+ local s = suffix(k)
+ if s == "xz" then
+ if decompresslzma == nil then
+ local lzma = require(resolvers.findfile("libs-imp-lzma.lmt"))
+ if lzma then
+ local decompress = lzma.decompress
+ decompresslzma = function(name)
+ return decompress(loaddata(k))
+ end
+ else
+ decompresslzma = function(name)
+ -- todo: use a proper runner
+ return resultof("xz -d -c -q -q " .. name)
+ end
+ end
+ end
+ return decompresslzma(k)
+ elseif s == "gz" then
+ return decompressgzip(loaddata(k))
+ end
+end
+
+local cache = table.setmetatableindex(function(t,k)
+ local v = decompressed(k) or false
+ t[k] = v
+ return v
+end)
+
+decompressors.decompress = decompress
+
+function decompressors.register(filename)
+ return cache[filename]
+end
+
+function decompressors.unregister(filename)
+ cache[filename] = nil
+end
diff --git a/tex/context/base/mkiv/data-tar.lua b/tex/context/base/mkiv/data-tar.lua
new file mode 100644
index 000000000..45de749b6
--- /dev/null
+++ b/tex/context/base/mkiv/data-tar.lua
@@ -0,0 +1,236 @@
+if not modules then modules = { } end modules ['data-tar'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local format, find, match = string.format, string.find, string.match
+
+local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
+
+local report_tar = logs.reporter("resolvers","tar")
+
+--[[ldx--
+<p>We use a url syntax for accessing the tar file itself and file in it:</p>
+
+<typing>
+tar:///oeps.tar?name=bla/bla.tex
+tar:///oeps.tar?tree=tex/texmf-local
+</typing>
+--ldx]]--
+
+local resolvers = resolvers
+local findfile = resolvers.findfile
+local registerfile = resolvers.registerfile
+local splitmethod = resolvers.splitmethod
+local starttiming = resolvers.starttiming
+local stoptiming = resolvers.stoptiming
+
+local urlquery = url.query
+
+--- hm, zip sits in the global namespace, but tar doesn't
+
+local tar = utilities.tar or { }
+utilities.tar = tar -- not needed
+
+local archives = tar.archives or { }
+tar.archives = archives
+
+local registeredfiles = tar.registeredfiles or { }
+tar.registeredfiles = registeredfiles
+
+-- foo.tar.xz : done
+-- foo.tar.gz : todo
+-- foo.tar : done
+
+local hashtar, fetchtar, wipetar do
+
+ local suffix = file.suffix -- hassuffix .. no need to split
+
+ local tarfiles = utilities.tar.file
+ local tarstrings = utilities.tar.string
+
+ local hashtarfile = tar.files.hash
+ local fetchtarfile = tar.files.fetch
+
+ local hashtarstring = tar.strings.hash
+ local fetchtarstring = tar.strings.fetch
+
+ local register = resolvers.decompressors.register
+
+ hashtar = function(archive,strip)
+ local a = register(archive)
+ if a then
+ return hashtarstring(a,archive)
+ else
+ return hashtarfile(archive,archive)
+ end
+ end
+
+ fetchtar = function(archive,filename,list)
+ local a = register(archive)
+ if a then
+ return fetchtarstring(a,filename,list)
+ else
+ return fetchtarfile(archive,filename,list)
+ end
+ end
+
+ wipetar = resolvers.decompressors.unregister
+
+end
+
+local function validfile(archive,name)
+ return archive[name]
+end
+
+local function openarchive(name)
+ if not name or name == "" then
+ return nil
+ else
+ local arch = archives[name]
+ if not arch then
+ local full = findfile(name) or ""
+ arch = full ~= "" and hashtar(full,name) or false
+ archives[name] = arch
+ end
+ return arch
+ end
+end
+
+local function closearchive(name)
+ if not name or (name == "" and archives[name]) then
+ archives[name] = nil
+ wipetar(name)
+ end
+end
+
+tar.openarchive = openarchive
+tar.closearchive = closearchive
+
+function resolvers.locators.tar(specification)
+ local archive = specification.filename
+ local tarfile = archive and archive ~= "" and openarchive(archive)
+ if trace_locating then
+ if tarfile then
+ report_tar("locator: archive %a found",archive)
+ else
+ report_tar("locator: archive %a not found",archive)
+ end
+ end
+end
+
+function resolvers.concatinators.tar(tarfile,path,name) -- ok ?
+ if not path or path == "" then
+ return format('%s?name=%s',tarfile,name)
+ else
+ return format('%s?name=%s/%s',tarfile,path,name)
+ end
+end
+
+local finders = resolvers.finders
+local notfound = finders.notfound
+
+function finders.tar(specification)
+ local original = specification.original
+ local archive = specification.filename
+ if archive then
+ local query = urlquery(specification.query)
+ local queryname = query.name
+ if queryname then
+ local tfile = openarchive(archive)
+ if tfile then
+ if trace_locating then
+ report_tar("finder: archive %a found",archive)
+ end
+ if validfile(tfile,queryname) then
+ if trace_locating then
+ report_tar("finder: file %a found",queryname)
+ end
+ return specification.original
+ elseif trace_locating then
+ report_tar("finder: file %a not found",queryname)
+ end
+ elseif trace_locating then
+ report_tar("finder: unknown archive %a",archive)
+ end
+ end
+ end
+ if trace_locating then
+ report_tar("finder: %a not found",original)
+ end
+ return notfound()
+end
+
+local openers = resolvers.openers
+local notfound = openers.notfound
+local textopener = openers.helpers.textopener
+
+function openers.tar(specification)
+ local original = specification.original
+ local archive = specification.filename
+ if archive then
+ local query = urlquery(specification.query)
+ local queryname = query.name
+ if queryname then
+ local tfile = openarchive(archive)
+ if tfile then
+ if trace_locating then
+ report_tar("opener; archive %a opened",archive)
+ end
+ local data = fetchtar(archive,queryname,tfile)
+ if data then
+ if trace_locating then
+ report_tar("opener: file %a found",queryname)
+ end
+ return textopener('tar',original,data) -- a string handle
+ elseif trace_locating then
+ report_tar("opener: file %a not found",queryname)
+ end
+ elseif trace_locating then
+ report_tar("opener: unknown archive %a",archive)
+ end
+ end
+ end
+ if trace_locating then
+ report_tar("opener: %a not found",original)
+ end
+ return notfound()
+end
+
+loaders = resolvers.loaders
+local notfound = loaders.notfound
+
+function loaders.tar(specification)
+ local original = specification.original
+ local archive = specification.filename
+ if archive then
+ local query = urlquery(specification.query)
+ local queryname = query.name
+ if queryname then
+ local tfile = openarchive(archive)
+ if tfile then
+ if trace_locating then
+ report_tar("loader: archive %a opened",archive)
+ end
+ local data = fetchtar(archive,queryname,tfile)
+ if data then
+ if trace_locating then
+ report_tar("loader; file %a loaded",original)
+ end
+ return true, data, #data
+ elseif trace_locating then
+ report_tar("loader: file %a not found",queryname)
+ end
+ elseif trace_locating then
+ report_tar("loader; unknown archive %a",archive)
+ end
+ end
+ end
+ if trace_locating then
+ report_tar("loader: %a not found",original)
+ end
+ return notfound()
+end
diff --git a/tex/context/base/mkiv/data-use.lua b/tex/context/base/mkiv/data-use.lua
index a7ca2389e..168b62201 100644
--- a/tex/context/base/mkiv/data-use.lua
+++ b/tex/context/base/mkiv/data-use.lua
@@ -82,14 +82,14 @@ function statistics.savefmtstatus(texname,formatbanner,sourcefile,banner) -- tex
functionality = LUATEXFUNCTIONALITY,
}
io.savedata(luvname,table.serialize(luvdata,true))
- lua.registerfinalizer(function()
+ lua.registerinitexfinalizer(function()
if jit then
logs.report("format banner","%s lua: %s jit",banner,LUAVERSION)
else
logs.report("format banner","%s lua: %s",banner,LUAVERSION)
end
logs.newline()
- end)
+ end, "show banner")
end
end
diff --git a/tex/context/base/mkiv/data-zip.lua b/tex/context/base/mkiv/data-zip.lua
index 8d914b842..1a9310f17 100644
--- a/tex/context/base/mkiv/data-zip.lua
+++ b/tex/context/base/mkiv/data-zip.lua
@@ -70,10 +70,10 @@ if zipfiles then
local readstring = streams.readstring
local streamsize = streams.size
- local metatable = {
+ local metatable = { -- irrelevant as the streams proivide the methods .. a leftover?
close = streams.close,
read = function(stream,n)
- readstring(stream,n == "*a" and streamsize(stream) or n)
+ readstring(stream,n == "*a" and streamsize(stream) or n) -- no return ?
end
}
diff --git a/tex/context/base/mkiv/font-cff.lua b/tex/context/base/mkiv/font-cff.lua
index ff87292ba..8b01d92b7 100644
--- a/tex/context/base/mkiv/font-cff.lua
+++ b/tex/context/base/mkiv/font-cff.lua
@@ -572,6 +572,11 @@ do
stack[top] = -(byte(b0)-251)*256 - byte(b1) - 108
end
+ -- local p_float = P("\255") * C(1) * C(1) * C(1) * C(1) / function(b0,b1,b2,b3)
+ -- top = top + 1
+ -- stack[top] = 0
+ -- end
+
local p_short = P("\28") * C(1) * C(1) / function(b1,b2)
-- -32768 .. +32767 : b1<<8 | b2
top = top + 1
@@ -607,6 +612,7 @@ do
+ p_nibbles
+ p_single
+ p_double
+ -- + p_float
+ p_unsupported
)^1
@@ -1825,13 +1831,13 @@ do
stack[top] = -t*256 + 64148 - tab[i+1]
i = i + 2
else
- -- a 16.16 float
- local n = 0x100 * tab[i+1] + tab[i+2]
- if n >= 0x8000 then
- stack[top] = n - 0x10000 + (0x100 * tab[i+3] + tab[i+4])/0xFFFF
- else
- stack[top] = n + (0x100 * tab[i+3] + tab[i+4])/0xFFFF
+ -- a 16.16 float (used for italic but pretty unreliable)
+ local n1 = 0x100 * tab[i+1] + tab[i+2]
+ local n2 = 0x100 * tab[i+3] + tab[i+4]
+ if n1 >= 0x8000 then
+ n1 = n1 - 0x10000
end
+ stack[top] = n1 + n2/0xFFFF
i = i + 5
end
elseif t == 28 then
diff --git a/tex/context/base/mkiv/font-imp-math.lua b/tex/context/base/mkiv/font-imp-math.lua
index d2294e93c..c0185ca34 100644
--- a/tex/context/base/mkiv/font-imp-math.lua
+++ b/tex/context/base/mkiv/font-imp-math.lua
@@ -108,7 +108,8 @@ function fonts.helpers.mathscriptslots(tfmdata,textcode)
end
end
end
-local function initialize(tfmdata,key,value)
+
+local function initialize(tfmdata,value)
if value then
local rawdata = tfmdata.shared.rawdata
local rawresources = rawdata and rawdata.resources
diff --git a/tex/context/base/mkiv/font-imp-tweaks.lua b/tex/context/base/mkiv/font-imp-tweaks.lua
index 9cbda97fa..6d522e48b 100644
--- a/tex/context/base/mkiv/font-imp-tweaks.lua
+++ b/tex/context/base/mkiv/font-imp-tweaks.lua
@@ -10,10 +10,15 @@ if not context then return end
local addfeature = fonts.handlers.otf.addfeature
+-- The mapping directives avoids a check and copying of the (kind of special code
+-- mapping tables.
+
addfeature {
name = "uppercasing",
type = "substitution",
prepend = true,
+ mapping = true,
+ -- valid = function() return true end,
data = characters.uccodes
}
@@ -21,5 +26,115 @@ addfeature {
name = "lowercasing",
type = "substitution",
prepend = true,
+ mapping = true,
+ -- valid = function() return true end,
data = characters.lccodes
}
+
+if CONTEXTLMTXMODE > 0 then
+
+ local nuts = nodes.nuts
+ local isnextchar = nuts.isnextchar
+ local getdisc = nuts.getdisc
+ local setchar = nuts.setchar
+
+ local disc_code = nodes.nodecodes.disc
+
+ local lccodes = characters.lccodes
+ local uccodes = characters.uccodes
+
+ function fonts.handlers.otf.handlers.ctx_camelcasing(head,dataset,sequence,initialrl,font,dynamic)
+ local first = false
+ local current = head
+ -- local scale = 1000
+ -- local xscale = 1000
+ -- local yscale = 1000
+ local function check(current)
+ while current do
+ -- scale, xscale, yscale = getscales(current)
+ local nxt, char, id = isnextchar(current,font,dynamic) -- ,scale,xscale,yscale)
+ if char then
+ if first then
+ local lower = lccodes[char]
+ if lower ~= char then
+ setchar(current,lower)
+ end
+ else
+ local upper = uccodes[char]
+ if upper ~= char then
+ setchar(current,upper)
+ end
+ first = true
+ end
+ elseif id == disc_code then
+ local pre, post, replace = getdisc(current)
+ if pre then
+ check(pre)
+ end
+ if post then
+ check(post)
+ end
+ if replace then
+ check(replace)
+ end
+ else
+ first = false
+ end
+ current = nxt
+ end
+ end
+ check(current)
+ return head
+ end
+
+ addfeature {
+ nocheck = true,
+ name = "camelcasing",
+ type = "ctx_camelcasing",
+ prepend = true,
+ data = "action",
+ }
+
+end
+
+do -- for the moment this is mostly a demo feature
+
+ local digit = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" }
+ local single = { "'" }
+ local double = { '"' }
+
+ local singleprime = 0x2032 -- "′"
+ local doubleprime = 0x2033 -- "″"
+
+ addfeature {
+ -- nocheck = true,
+ name = "primes",
+ type = "chainsubstitution",
+ lookups = {
+ {
+ type = "substitution",
+ data = { ["'"] = singleprime },
+ },
+ {
+ type = "substitution",
+ data = { ["'"] = doubleprime },
+ },
+ },
+ data = {
+ rules = {
+ {
+ before = { digit },
+ current = { single },
+ after = { digit },
+ lookups = { 1 },
+ },
+ {
+ before = { digit },
+ current = { single, single },
+ lookups = { 2, 0 }, -- zero: gsub_remove
+ },
+ },
+ },
+ }
+
+end
diff --git a/tex/context/base/mkiv/font-osd.lua b/tex/context/base/mkiv/font-osd.lua
index 2d0e685c1..a9ea878c0 100644
--- a/tex/context/base/mkiv/font-osd.lua
+++ b/tex/context/base/mkiv/font-osd.lua
@@ -118,7 +118,7 @@ local setstate = nuts.setstate
local ischar = nuts.ischar
-local insertnodeafter = nuts.insertafter
+local insertnodeafter = nuts.insertafter
local copy_node = nuts.copy
local remove_node = nuts.remove
local flushlist = nuts.flushlist
@@ -130,7 +130,8 @@ local unsetvalue = attributes.unsetvalue
local fontdata = fonts.hashes.identifiers
-local a_syllabe = attributes.private('syllabe')
+local a_syllabe = "syllable" -- attributes.private('syllabe') -- can be just a property key
+local a_reordered = "reordered" -- attributes.private('reordered') -- can be just a property key
local dotted_circle = 0x25CC
local c_nbsp = 0x00A0
@@ -1332,7 +1333,7 @@ local function reorder_one(head,start,stop,font,attr,nbspaces)
if getchar(base) == c_nbsp then
nbspaces = nbspaces - 1
if base == stop then
- stop = getprev(stop)
+ stop = getprev(stop)
end
head = remove_node(head,base)
flushnode(base)
@@ -1514,7 +1515,7 @@ function handlers.devanagari_reorder_reph(head,start)
start = startnext
startattr = getprop(start,a_syllabe)
break
- elseif not c and ( vowel_modifier[char] or stress_tone_mark[char] ) then
+ elseif not c and (vowel_modifier[char] or stress_tone_mark[char]) then
c = current
end
current = getnext(current)
@@ -1616,10 +1617,8 @@ end
-- return head, start, done
-- end
-local reordered_pre_base_reordering_consonants = { } -- shared ? not reset ?
-
function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
- if reordered_pre_base_reordering_consonants[start] then
+ if getprop(start,a_reordered) then
return head, start, true
end
local current = start -- we could cache attributes here
@@ -1643,7 +1642,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
setlink(start,next)
setlink(current,start)
-- setlink(current,start,next) -- maybe
- reordered_pre_base_reordering_consonants[start] = true
+ setprop(start,"reordered",true)
start = startnext
return head, start, true
-- elseif consonant[char] and (not getstate(current) or getstate(current,s_init)) then
@@ -1679,7 +1678,7 @@ function handlers.devanagari_reorder_pre_base_reordering_consonants(head,start)
setlink(getprev(current),start)
setlink(start,current)
end
- reordered_pre_base_reordering_consonants[start] = true
+ setprop(start,"reordered",true)
start = startnext
break
end
@@ -2251,20 +2250,20 @@ local function analyze_next_chars_one(c,font,variant) -- skip one dependent vowe
local already_below_mark -- = false
local already_post_mark -- = false
while dependent_vowel[v] do
- local vowels = twopart_mark[v] or { v }
- for k, v in next, vowels do
- if pre_mark[v] and not already_pre_mark then
- already_pre_mark = true
- elseif above_mark[v] and not already_above_mark then
- already_above_mark = true
- elseif below_mark[v] and not already_below_mark then
- already_below_mark = true
- elseif post_mark[v] and not already_post_mark then
- already_post_mark = true
- else
- return c
- end
- end
+ local vowels = twopart_mark[v] or { v }
+ for k, v in next, vowels do
+ if pre_mark[v] and not already_pre_mark then
+ already_pre_mark = true
+ elseif above_mark[v] and not already_above_mark then
+ already_above_mark = true
+ elseif below_mark[v] and not already_below_mark then
+ already_below_mark = true
+ elseif post_mark[v] and not already_post_mark then
+ already_post_mark = true
+ else
+ return c
+ end
+ end
c = getnext(c)
n = getnext(c)
if not n then
@@ -2440,21 +2439,21 @@ local function analyze_next_chars_two(c,font)
local already_above_mark -- = false
local already_below_mark -- = false
local already_post_mark -- = false
- while dependent_vowel[v] do
- local vowels = twopart_mark[v] or { v }
- for k, v in next, vowels do
- if pre_mark[v] and not already_pre_mark then
- already_pre_mark = true
- elseif above_mark[v] and not already_above_mark then
- already_above_mark = true
- elseif below_mark[v] and not already_below_mark then
- already_below_mark = true
- elseif post_mark[v] and not already_post_mark then
- already_post_mark = true
- else
- return c
- end
- end
+ while dependent_vowel[v] do
+ local vowels = twopart_mark[v] or { v }
+ for k, v in next, vowels do
+ if pre_mark[v] and not already_pre_mark then
+ already_pre_mark = true
+ elseif above_mark[v] and not already_above_mark then
+ already_above_mark = true
+ elseif below_mark[v] and not already_below_mark then
+ already_below_mark = true
+ elseif post_mark[v] and not already_post_mark then
+ already_post_mark = true
+ else
+ return c
+ end
+ end
c = n
n = getnext(c)
if not n then
@@ -2731,15 +2730,15 @@ local function method_one(head,font,attr)
while current do
local char = ischar(current,font)
if char then
- if n == 0 and not getstate(current) then
- setstate(current,s_init)
- end
- n = n + 1
- else
- n = 0
- end
- current = getnext(current)
- end
+ if n == 0 and not getstate(current) then
+ setstate(current,s_init)
+ end
+ n = n + 1
+ else
+ n = 0
+ end
+ current = getnext(current)
+ end
return head, done
end
@@ -2841,15 +2840,15 @@ local function method_two(head,font,attr)
while current do
local char = ischar(current,font)
if char then
- if n == 0 and not getstate(current) then -- state can also be init
- setstate(current,s_init)
- end
- n = n + 1
- else
- n = 0
- end
- current = getnext(current)
- end
+ if n == 0 and not getstate(current) then -- state can also be init
+ setstate(current,s_init)
+ end
+ n = n + 1
+ else
+ n = 0
+ end
+ current = getnext(current)
+ end
return head, done
end
diff --git a/tex/context/base/mkiv/font-otc.lua b/tex/context/base/mkiv/font-otc.lua
index 2643d022a..2c955dbce 100644
--- a/tex/context/base/mkiv/font-otc.lua
+++ b/tex/context/base/mkiv/font-otc.lua
@@ -102,8 +102,9 @@ local function validspecification(specification,name)
specification = { dataset = dataset }
else
dataset = { { data = specification.data } }
- specification.data = nil
- specification.dataset = dataset
+ specification.data = nil
+ specification.coverage = dataset
+ specification.dataset = dataset
end
local first = dataset[1]
if first then
@@ -232,6 +233,7 @@ local function addfeature(data,feature,specifications)
local unicode = tounicode(code)
local description = descriptions[unicode]
if not nocheck and not description then
+ -- todo: trace !
skip = skip + 1
else
if type(replacement) == "table" then
@@ -436,7 +438,30 @@ local function addfeature(data,feature,specifications)
local prepare_single = prepare_pair -- we could have a better test on the spec
- local function prepare_chain(list,featuretype,sublookups)
+ local function hassteps(lookups)
+ if lookups then
+ for i=1,#lookups do
+ local l = lookups[i]
+ if l then
+ for j=1,#l do
+ local l = l[j]
+ if l then
+ local n = l.nofsteps
+ if not n then
+ -- gsub_remove
+ return true
+ elseif n > 0 then
+ return true
+ end
+ end
+ end
+ end
+ end
+ end
+ return false
+ end
+
+ local function prepare_chain(list,featuretype,sublookups,nocheck)
-- todo: coveractions
local rules = list.rules
local coverage = { }
@@ -473,6 +498,7 @@ local function addfeature(data,feature,specifications)
local lookups = rule.lookups or false
local subtype = nil
if lookups and sublookups then
+ local l = { }
for k, v in sortedhash(lookups) do
local t = type(v)
if t == "table" then
@@ -483,58 +509,66 @@ local function addfeature(data,feature,specifications)
v[i] = { vi }
end
end
+ l[k] = v
elseif t == "number" then
local lookup = sublookups[v]
if lookup then
- lookups[k] = { lookup }
+ l[k] = { lookup }
if not subtype then
subtype = lookup.type
end
elseif v == 0 then
- lookups[k] = { { type = "gsub_remove" } }
+ l[k] = { { type = "gsub_remove", nosteps = true } }
else
- lookups[k] = false -- { false } -- new
+ l[k] = false -- { false } -- new
end
else
- lookups[k] = false -- { false } -- new
+ l[k] = false -- { false } -- new
end
end
+ if nocheck then
+ -- fragile
+ rule.lookups = l --no, because checking can spoil it
+ end
+ lookups = l
end
if nofsequences > 0 then -- we merge coverage into one
-- we copy as we can have different fonts
- local hashed = { }
- for i=1,nofsequences do
- local t = { }
- local s = sequence[i]
- for i=1,#s do
- local u = tounicode(s[i])
- if u then
- t[u] = true
+ if hassteps(lookups) then
+ local hashed = { }
+ for i=1,nofsequences do
+ local t = { }
+ local s = sequence[i]
+ for i=1,#s do
+ local u = tounicode(s[i])
+ if u then
+ t[u] = true
+ end
end
+ hashed[i] = t
end
- hashed[i] = t
- end
- sequence = hashed
- -- now we create the rule
- rulesize = rulesize + 1
- rulehash[rulesize] = {
- nofrules, -- 1
- lookuptype, -- 2
- sequence, -- 3
- start, -- 4
- stop, -- 5
- lookups, -- 6 (6/7 also signal of what to do)
- replacements, -- 7
- subtype, -- 8
- }
--- for unic in next, sequence[start] do
- for unic in sortedhash(sequence[start]) do
- local cu = coverage[unic]
- if not cu then
- coverage[unic] = rulehash -- can now be done cleaner i think
+ sequence = hashed
+ rulesize = rulesize + 1
+ rulehash[rulesize] = {
+ nofrules, -- 1
+ lookuptype, -- 2
+ sequence, -- 3
+ start, -- 4
+ stop, -- 5
+ lookups, -- 6 (6/7 also signal of what to do)
+ replacements, -- 7
+ subtype, -- 8
+ }
+ for unic in sortedhash(sequence[start]) do
+ local cu = coverage[unic]
+ if not cu then
+ coverage[unic] = rulehash -- can now be done cleaner i think
+ end
end
+ sequence.n = nofsequences
+ else
+ -- report_otf("no steps for %a",lookuptype) -- e.g. in primes feature
end
- sequence.n = nofsequences
end
end
rulehash.n = rulesize
@@ -626,133 +660,164 @@ local function addfeature(data,feature,specifications)
end
local askedfeatures = specification.features or everywhere
local askedsteps = specification.steps or specification.subtables or { specification.data } or { }
- local featuretype = normalized[specification.type or "substitution"] or "substitution"
+ local featuretype = specification.type or "substitution"
+ local featureaction = false
local featureflags = specification.flags or noflags
local nocheck = specification.nocheck
+ local mapping = specification.mapping
local featureorder = specification.order or { feature }
local featurechain = (featuretype == "chainsubstitution" or featuretype == "chainposition") and 1 or 0
local nofsteps = 0
local steps = { }
local sublookups = specification.lookups
local category = nil
+ local steptype = nil
+ local sequence = nil
+ --
+ if fonts.handlers.otf.handlers[featuretype] then
+ featureaction = true -- function based
+ else
+ featuretype = normalized[specification.type or "substitution"] or "substitution"
+ end
--
checkflags(specification,resources)
--
- if sublookups then
- local s = { }
- for i=1,#sublookups do
- local specification = sublookups[i]
- 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 nofsteps = 0
- local steps = { }
- for i=1,#askedsteps do
- local list = askedsteps[i]
- local coverage = nil
- local format = nil
- if featuretype == "substitution" then
- coverage = prepare_substitution(list,featuretype,nocheck)
- elseif featuretype == "ligature" then
- coverage = prepare_ligature(list,featuretype,nocheck)
- elseif featuretype == "alternate" then
- coverage = prepare_alternate(list,featuretype,nocheck)
- elseif featuretype == "multiple" then
- coverage = prepare_multiple(list,featuretype,nocheck)
- elseif featuretype == "kern" or featuretype == "move" then
- format = featuretype
- coverage = prepare_kern(list,featuretype)
- elseif featuretype == "pair" then
- format = "pair"
- coverage = prepare_pair(list,featuretype)
- elseif featuretype == "single" then
- format = "single"
- coverage = prepare_single(list,featuretype)
- end
- if coverage and next(coverage) then
- nofsteps = nofsteps + 1
- steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ for k, v in next, askedfeatures do
+ if v[1] then
+ askedfeatures[k] = tohash(v)
+ end
+ end
+ --
+ if featureflags[1] then featureflags[1] = "mark" end
+ if featureflags[2] then featureflags[2] = "ligature" end
+ if featureflags[3] then featureflags[3] = "base" end
+ --
+ if featureaction then
+
+ category = "gsub"
+ sequence = {
+ features = { [feature] = askedfeatures },
+ flags = featureflags,
+ name = feature, -- redundant
+ order = featureorder,
+ type = featuretype,
+ -- steps = { },
+ nofsteps = 0, -- just in case we test for that
+ }
+
+ else
+
+ if sublookups then
+ local s = { }
+ for i=1,#sublookups do
+ local specification = sublookups[i]
+ 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 nofsteps = 0
+ local steps = { }
+ for i=1,#askedsteps do
+ local list = askedsteps[i]
+ local coverage = nil
+ local format = nil
+ if featuretype == "substitution" then
+ coverage = prepare_substitution(list,featuretype,nocheck)
+ elseif featuretype == "ligature" then
+ coverage = prepare_ligature(list,featuretype,nocheck)
+ elseif featuretype == "alternate" then
+ coverage = prepare_alternate(list,featuretype,nocheck)
+ elseif featuretype == "multiple" then
+ coverage = prepare_multiple(list,featuretype,nocheck)
+ elseif featuretype == "kern" or featuretype == "move" then
+ format = featuretype
+ coverage = prepare_kern(list,featuretype)
+ elseif featuretype == "pair" then
+ format = "pair"
+ coverage = prepare_pair(list,featuretype)
+ elseif featuretype == "single" then
+ format = "single"
+ coverage = prepare_single(list,featuretype)
+ end
+ if coverage and next(coverage) then
+ nofsteps = nofsteps + 1
+ steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
end
+ --
+ checkmerge(specification)
+ checksteps(specification)
+ --
+ s[i] = {
+ [stepkey] = steps,
+ nofsteps = nofsteps,
+ flags = featureflags,
+ type = types[featuretype],
+ }
+ end
+ sublookups = s
+ end
+
+ for i=1,#askedsteps do
+ local list = askedsteps[i]
+ local coverage = nil
+ local format = nil
+ if featuretype == "substitution" then
+ -- see font-imp-tweaks: we directly pass a mapping so no checks done
+ category = "gsub"
+ coverage = (mapping and list) or prepare_substitution(list,featuretype,nocheck)
+ elseif featuretype == "ligature" then
+ category = "gsub"
+ coverage = prepare_ligature(list,featuretype,nocheck)
+ elseif featuretype == "alternate" then
+ category = "gsub"
+ coverage = prepare_alternate(list,featuretype,nocheck)
+ elseif featuretype == "multiple" then
+ category = "gsub"
+ coverage = prepare_multiple(list,featuretype,nocheck)
+ elseif featuretype == "kern" or featuretype == "move" then
+ category = "gpos"
+ format = featuretype
+ coverage = prepare_kern(list,featuretype)
+ elseif featuretype == "pair" then
+ category = "gpos"
+ format = "pair"
+ coverage = prepare_pair(list,featuretype)
+ elseif featuretype == "single" then
+ category = "gpos"
+ format = "single"
+ coverage = prepare_single(list,featuretype)
+ elseif featuretype == "chainsubstitution" then
+ category = "gsub"
+ coverage = prepare_chain(list,featuretype,sublookups,nocheck)
+ elseif featuretype == "chainposition" then
+ category = "gpos"
+ coverage = prepare_chain(list,featuretype,sublookups,nocheck)
+ else
+ report_otf("not registering feature %a, unknown category",feature)
+ return
end
- --
- checkmerge(specification)
- checksteps(specification)
- --
- s[i] = {
+ if coverage and next(coverage) then
+ nofsteps = nofsteps + 1
+ steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
+ end
+ end
+
+ if nofsteps > 0 then
+ sequence = {
+ chain = featurechain,
+ features = { [feature] = askedfeatures },
+ flags = featureflags,
+ name = feature, -- redundant
+ order = featureorder,
[stepkey] = steps,
nofsteps = nofsteps,
- flags = featureflags,
type = types[featuretype],
}
end
- sublookups = s
end
- for i=1,#askedsteps do
- local list = askedsteps[i]
- local coverage = nil
- local format = nil
- if featuretype == "substitution" then
- category = "gsub"
- coverage = prepare_substitution(list,featuretype,nocheck)
- elseif featuretype == "ligature" then
- category = "gsub"
- coverage = prepare_ligature(list,featuretype,nocheck)
- elseif featuretype == "alternate" then
- category = "gsub"
- coverage = prepare_alternate(list,featuretype,nocheck)
- elseif featuretype == "multiple" then
- category = "gsub"
- coverage = prepare_multiple(list,featuretype,nocheck)
- elseif featuretype == "kern" or featuretype == "move" then
- category = "gpos"
- format = featuretype
- coverage = prepare_kern(list,featuretype)
- elseif featuretype == "pair" then
- category = "gpos"
- format = "pair"
- coverage = prepare_pair(list,featuretype)
- elseif featuretype == "single" then
- category = "gpos"
- format = "single"
- coverage = prepare_single(list,featuretype)
- elseif featuretype == "chainsubstitution" then
- category = "gsub"
- coverage = prepare_chain(list,featuretype,sublookups)
- elseif featuretype == "chainposition" then
- category = "gpos"
- coverage = prepare_chain(list,featuretype,sublookups)
- else
- report_otf("not registering feature %a, unknown category",feature)
- return
- end
- if coverage and next(coverage) then
- nofsteps = nofsteps + 1
- steps[nofsteps] = register(coverage,featuretype,format,feature,nofsteps,descriptions,resources)
- end
- end
- if nofsteps > 0 then
+
+ if sequence then
-- script = { lang1, lang2, lang3 } or script = { lang1 = true, ... }
- for k, v in next, askedfeatures do
- if v[1] then
- askedfeatures[k] = tohash(v)
- end
- end
- --
- if featureflags[1] then featureflags[1] = "mark" end
- if featureflags[2] then featureflags[2] = "ligature" end
- if featureflags[3] then featureflags[3] = "base" end
- local steptype = types[featuretype]
- local sequence = {
- chain = featurechain,
- features = { [feature] = askedfeatures },
- flags = featureflags,
- name = feature, -- redundant
- order = featureorder,
- [stepkey] = steps,
- nofsteps = nofsteps,
- type = steptype,
- }
- --
checkflags(sequence,resources)
checkmerge(sequence)
checksteps(sequence)
@@ -782,11 +847,13 @@ local function addfeature(data,feature,specifications)
end
end
end
+
end
end
if trace_loading then
report_otf("registering feature %a, affected glyphs %a, skipped glyphs %a",feature,done,skip)
end
+
end
otf.enhancers.addfeature = addfeature
diff --git a/tex/context/base/mkiv/font-otl.lua b/tex/context/base/mkiv/font-otl.lua
index 6b564e4c1..eadf05890 100644
--- a/tex/context/base/mkiv/font-otl.lua
+++ b/tex/context/base/mkiv/font-otl.lua
@@ -314,7 +314,7 @@ local function copytotfm(data,cache_id)
local properties = derivetable(data.properties)
local descriptions = derivetable(data.descriptions)
local goodies = derivetable(data.goodies)
- local characters = { }
+ local characters = { } -- newtable if we knwo how many
local parameters = { }
local mathparameters = { }
--
diff --git a/tex/context/base/mkiv/font-otr.lua b/tex/context/base/mkiv/font-otr.lua
index 4b154b256..2f8934508 100644
--- a/tex/context/base/mkiv/font-otr.lua
+++ b/tex/context/base/mkiv/font-otr.lua
@@ -1250,7 +1250,7 @@ readers.post = function(f,fontdata,specification)
local version = readulong(f)
fontdata.postscript = {
version = version,
- italicangle = round(1000*readfixed(f))/1000,
+ italicangle = readfixed(f),
underlineposition = readfword(f),
underlinethickness = readfword(f),
monospaced = readulong(f),
diff --git a/tex/context/base/mkiv/grph-img.lua b/tex/context/base/mkiv/grph-img.lua
index 0dc5efa70..a982965ff 100644
--- a/tex/context/base/mkiv/grph-img.lua
+++ b/tex/context/base/mkiv/grph-img.lua
@@ -16,7 +16,7 @@ local round = math.round
local concat = table.concat
local suffixonly = file.suffix
-local newreader = io.newreader
+local newreader = io.newreader -- needs checking 0/1 based
local setmetatableindex = table.setmetatableindex
local setmetatablecall = table.setmetatablecall
diff --git a/tex/context/base/mkiv/l-gzip.lua b/tex/context/base/mkiv/l-gzip.lua
index f141b5ebb..aadb781da 100644
--- a/tex/context/base/mkiv/l-gzip.lua
+++ b/tex/context/base/mkiv/l-gzip.lua
@@ -5,176 +5,4 @@ if not modules then modules = { } end modules ['l-gzip'] = {
license = "see context related readme files"
}
--- We only have a few official methods here:
---
--- local decompressed = gzip.load (filename)
--- local resultsize = gzip.save (filename,compresslevel)
--- local compressed = gzip.compress (str,compresslevel)
--- local decompressed = gzip.decompress (str)
--- local iscompressed = gzip.compressed (str)
--- local suffix, okay = gzip.suffix (filename)
---
--- In LuaMetaTeX we have only xzip which implements a very few methods:
---
--- compress (str,level,method,window,memory,strategy)
--- decompress (str,window)
--- adler32 (str,checksum)
--- crc32 (str,checksum)
---
--- Special window values are:
---
--- flate : - 15
--- zlib : 15
--- gzip : 15 | 16
--- auto : 15 | 32
-
-gzip = gzip or { } -- so in luatex we keep the old ones too
-
-if not zlib then
- zlib = xzip -- in luametatex we shadow the old one
-elseif not xzip then
- xzip = zlib
-end
-
-if zlib then
-
- local suffix = file.suffix
- local suffixes = file.suffixes
- local find = string.find
- local openfile = io.open
-
- local gzipwindow = 15 + 16 -- +16: gzip, +32: gzip|zlib
- local gziplevel = 3
- local identifier = "^\x1F\x8B\x08"
-
- local compress = zlib.compress
- local decompress = zlib.decompress
-
- function gzip.load(filename)
- local f = openfile(filename,"rb")
- if not f then
- -- invalid file
- else
- local data = f:read("*all")
- f:close()
- if data and data ~= "" then
- if suffix(filename) == "gz" then
- data = decompress(data,gzipwindow)
- end
- return data
- end
- end
- end
-
- function gzip.save(filename,data,level)
- if suffix(filename) ~= "gz" then
- filename = filename .. ".gz"
- end
- local f = openfile(filename,"wb")
- if f then
- data = compress(data or "",level or gziplevel,nil,gzipwindow)
- f:write(data)
- f:close()
- return #data
- end
- end
-
- function gzip.suffix(filename)
- local suffix, extra = suffixes(filename)
- local gzipped = extra == "gz"
- return suffix, gzipped
- end
-
- function gzip.compressed(s)
- return s and find(s,identifier)
- end
-
- function gzip.compress(s,level)
- if s and not find(s,identifier) then -- the find check might go away
- if not level then
- level = gziplevel
- elseif level <= 0 then
- return s
- elseif level > 9 then
- level = 9
- end
- return compress(s,level or gziplevel,nil,gzipwindow) or s
- end
- end
-
- function gzip.decompress(s)
- if s and find(s,identifier) then
- return decompress(s,gzipwindow)
- else
- return s
- end
- end
-
-end
-
--- In luametatex we can use this one but it doesn't look like there wil be stream
--- support so for now we still use zlib (the performance difference is not that
--- spectacular in our usage.
-
--- if flate then
---
--- local type = type
--- local find = string.find
---
--- local compress = flate.gz_compress
--- local decompress = flate.gz_decompress
---
--- local absmax = 128*1024*1024
--- local initial = 64*1024
--- local identifier = "^\x1F\x8B\x08"
---
--- function gzip.compressed(s)
--- return s and find(s,identifier)
--- end
---
--- function gzip.compress(s,level)
--- if s and not find(s,identifier) then -- the find check might go away
--- if not level then
--- level = 3
--- elseif level <= 0 then
--- return s
--- elseif level > 9 then
--- level = 9
--- end
--- return compress(s,level) or s
--- end
--- end
---
--- function gzip.decompress(s,size,iterate)
--- if s and find(s,identifier) then
--- if type(size) ~= "number" then
--- size = initial
--- end
--- if size > absmax then
--- size = absmax
--- end
--- if type(iterate) == "number" then
--- max = size * iterate
--- elseif iterate == nil or iterate == true then
--- iterate = true
--- max = absmax
--- end
--- if max > absmax then
--- max = absmax
--- end
--- while true do
--- local d = decompress(s,size)
--- if d then
--- return d
--- end
--- size = 2 * size
--- if not iterate or size > max then
--- return false
--- end
--- end
--- else
--- return s
--- end
--- end
---
--- end
+-- now in util-zip
diff --git a/tex/context/base/mkiv/l-lpeg.lua b/tex/context/base/mkiv/l-lpeg.lua
index 50306e4ab..77e5cf12d 100644
--- a/tex/context/base/mkiv/l-lpeg.lua
+++ b/tex/context/base/mkiv/l-lpeg.lua
@@ -665,12 +665,12 @@ end
-- lpeg.print(lpeg.P("a","b","c"))
-- lpeg.print(lpeg.S("a","b","c"))
--- print(lpeg.count("äáàa",lpeg.P("á") + lpeg.P("à")))
--- print(lpeg.count("äáàa",lpeg.UP("áà")))
--- print(lpeg.count("äáàa",lpeg.US("àá")))
--- print(lpeg.count("äáàa",lpeg.UR("aá")))
--- print(lpeg.count("äáàa",lpeg.UR("àá")))
--- print(lpeg.count("äáàa",lpeg.UR(0x0000,0xFFFF)))
+-- print(lpeg.counter("äáàa",lpeg.P("á") + lpeg.P("à")))
+-- print(lpeg.counter("äáàa",lpeg.UP("áà")))
+-- print(lpeg.counter("äáàa",lpeg.US("àá")))
+-- print(lpeg.counter("äáàa",lpeg.UR("aá")))
+-- print(lpeg.counter("äáàa",lpeg.UR("àá")))
+-- print(lpeg.counter("äáàa",lpeg.UR(0x0000,0xFFFF)))
function lpeg.is_lpeg(p)
return p and lpegtype(p) == "pattern"
diff --git a/tex/context/base/mkiv/l-os.lua b/tex/context/base/mkiv/l-os.lua
index c7584ccce..06cc35a79 100644
--- a/tex/context/base/mkiv/l-os.lua
+++ b/tex/context/base/mkiv/l-os.lua
@@ -187,7 +187,7 @@ local execute = os.execute
local iopopen = io.popen
local function resultof(command)
- local handle = iopopen(command,"r") -- already has flush
+ local handle = iopopen(command,"rb") -- already has flush, b is new !
if handle then
local result = handle:read("*all") or ""
handle:close()
diff --git a/tex/context/base/mkiv/lang-ini.lua b/tex/context/base/mkiv/lang-ini.lua
index c8b5ee158..e286233bc 100644
--- a/tex/context/base/mkiv/lang-ini.lua
+++ b/tex/context/base/mkiv/lang-ini.lua
@@ -158,11 +158,16 @@ local function sethjcodes(instance,loaded,what,factor)
loaded.codehash = h
end
--
- local function setcode(l)
- local u = uccodes[l]
+ local function setcode(code)
+ local l = lccodes[code] -- just in case we get a mixture
+ local u = uccodes[code] -- just in case we get a mixture
local s = l
+ if type(s) ~= "number" then
+ l = code
+ s = code
+ end
if hjcounts then
- local c = hjcounts[l]
+ local c = hjcounts[s]
if c then
c = c.count
if not c then
@@ -183,14 +188,14 @@ local function sethjcodes(instance,loaded,what,factor)
h[l] = s
if u ~= l and type(u) == "number" then
sethjcode(instance,u,s)
- h[u] = lccodes[l]
+ h[u] = s
end
end
--
local s = tex.savinghyphcodes
tex.savinghyphcodes = 0
if type(c) == "table" then
- for l in next, c do
+ for l in sortedhash(c) do
setcode(utfbyte(l))
end
else
diff --git a/tex/context/base/mkiv/luat-cnf.lua b/tex/context/base/mkiv/luat-cnf.lua
index 550fa5892..7bb70ce20 100644
--- a/tex/context/base/mkiv/luat-cnf.lua
+++ b/tex/context/base/mkiv/luat-cnf.lua
@@ -261,4 +261,4 @@ local function makestub()
logs.newline()
end
-lua.registerfinalizer(makestub,"create stub file")
+lua.registerinitexfinalizer(makestub,"create stub file")
diff --git a/tex/context/base/mkiv/luat-cod.lua b/tex/context/base/mkiv/luat-cod.lua
index 25c716eeb..6175302a3 100644
--- a/tex/context/base/mkiv/luat-cod.lua
+++ b/tex/context/base/mkiv/luat-cod.lua
@@ -90,28 +90,6 @@ function lua.registercode(filename,options)
end
end
-local finalizers = { }
-
-function lua.registerfinalizer(f,comment)
- comment = comment or "unknown"
- if type(f) == "function" then
- finalizers[#finalizers+1] = { action = f, comment = comment }
- else
- print(format("\nfatal error: invalid finalizer, action: %s\n",comment))
- os.exit()
- end
-end
-
-function lua.finalize(logger)
- for i=1,#finalizers do
- local finalizer = finalizers[i]
- finalizer.action()
- if logger then
- logger("finalize action: %s",finalizer.comment)
- end
- end
-end
-
-- A first start with environments. This will be overloaded later.
environment = environment or { }
@@ -168,6 +146,38 @@ environment.jitsupported = JITSUPPORTED
environment.initex = INITEXMODE
environment.initexmode = INITEXMODE
+if INITEXMODE then
+
+ local finalizers = { }
+
+ function lua.registerinitexfinalizer(f,comment)
+ comment = comment or "unknown"
+ if type(f) == "function" then
+ finalizers[#finalizers+1] = { action = f, comment = comment }
+ else
+ print(format("\nfatal error: invalid finalizer, action: %s\n",comment))
+ os.exit()
+ end
+ end
+
+ function lua.finalizeinitex(logger)
+ for i=1,#finalizers do
+ local finalizer = finalizers[i]
+ finalizer.action()
+ if logger then
+ logger("finalize action: %s",finalizer.comment)
+ end
+ end
+ end
+
+else
+
+ function lua.registerinitexfinalizer() end
+ function lua.finalizeinitex () end
+
+end
+
+
if not environment.luafilechunk then
function environment.luafilechunk(filename)
diff --git a/tex/context/base/mkiv/luat-lib.mkiv b/tex/context/base/mkiv/luat-lib.mkiv
index f6bab870b..2879ca62a 100644
--- a/tex/context/base/mkiv/luat-lib.mkiv
+++ b/tex/context/base/mkiv/luat-lib.mkiv
@@ -53,13 +53,14 @@
\registerctxluafile{data-res}{}
\registerctxluafile{data-inp}{}
\registerctxluafile{data-out}{}
-\registerctxluafile{data-fil}{} % opener gets overloaded in data-tex
+\registerctxluafile{data-fil}{autosuffix} % opener gets overloaded in data-tex
\registerctxluafile{data-pre}{} % after data-res
\registerctxluafile{data-bin}{} % before data-tex
\registerctxluafile{data-tex}{} % after data-pre
\registerctxluafile{data-vir}{}
\registerctxluafile{data-zip}{}
+%registerctxluafile{data-tar}{}
%registerctxluafile{data-crl}{}
\registerctxluafile{data-sch}{}
\registerctxluafile{data-tre}{}
diff --git a/tex/context/base/mkiv/luat-run.lua b/tex/context/base/mkiv/luat-run.lua
index 874287ee1..c778ad094 100644
--- a/tex/context/base/mkiv/luat-run.lua
+++ b/tex/context/base/mkiv/luat-run.lua
@@ -106,7 +106,7 @@ local function pre_dump_actions()
for i=1,#dumpactions do
dumpactions[i]()
end
- lua.finalize(trace_lua_dump and report_lua or nil)
+ lua.finalizeinitex(trace_lua_dump and report_lua or nil)
end
local function wrapup_synctex()
diff --git a/tex/context/base/mkiv/luat-sto.lua b/tex/context/base/mkiv/luat-sto.lua
index feb546400..be5134b84 100644
--- a/tex/context/base/mkiv/luat-sto.lua
+++ b/tex/context/base/mkiv/luat-sto.lua
@@ -90,7 +90,7 @@ if environment.initex then
storage.max = max
end
- lua.registerfinalizer(dump,"dump storage")
+ lua.registerinitexfinalizer(dump,"dump storage")
end
diff --git a/tex/context/base/mkiv/lxml-ini.lua b/tex/context/base/mkiv/lxml-ini.lua
index 6524670fc..980a83f1a 100644
--- a/tex/context/base/mkiv/lxml-ini.lua
+++ b/tex/context/base/mkiv/lxml-ini.lua
@@ -205,7 +205,6 @@ if CONTEXTLMTXMODE > 0 then
end
}
-
implement {
name = "ifxmlempty",
public = true,
diff --git a/tex/context/base/mkiv/lxml-tex.lua b/tex/context/base/mkiv/lxml-tex.lua
index 148484f51..95fafafac 100644
--- a/tex/context/base/mkiv/lxml-tex.lua
+++ b/tex/context/base/mkiv/lxml-tex.lua
@@ -2085,11 +2085,11 @@ do
local e = getid(id)
if e then
local at = e.at
- if at and at[a] ~= "" then
- return true
- end
+ att = at and at[a] or ""
+ else
+ att = ""
end
- return false
+ return att == ""
end
function lxml.refatt(id,a)
diff --git a/tex/context/base/mkiv/mult-low.lua b/tex/context/base/mkiv/mult-low.lua
index 2b2173ae9..8132c6094 100644
--- a/tex/context/base/mkiv/mult-low.lua
+++ b/tex/context/base/mkiv/mult-low.lua
@@ -97,6 +97,12 @@ return {
"mmodeifcode", "innerifcode", "voidifcode", "hboxifcode", "vboxifcode", "xifcode", "eofifcode",
"trueifcode", "falseifcode", "caseifcode", "definedifcode", "csnameifcode", "fontcharifcode",
--
+ "overrulemathcontrolcode", "underrulemathcontrolcode", "radicalrulemathcontrolcode", "fractionrulemathcontrolcode",
+ "accentskewhalfmathcontrolcode", "accentskewapplymathcontrolcode", "accentitalickernmathcontrolcode",
+ "delimiteritalickernmathcontrolcode", "orditalickernmathcontrolcode", "charitalicwidthmathcontrolcode",
+ "charitalicnoreboxmathcontrolcode", "boxednoitalickernmathcontrolcode", "nostaircasekernmathcontrolcode",
+ "textitalickernmathcontrolcode",
+ --
"fontslantperpoint", "fontinterwordspace", "fontinterwordstretch", "fontinterwordshrink",
"fontexheight", "fontemwidth", "fontextraspace", "slantperpoint",
"mathexheight", "mathemwidth",
@@ -177,6 +183,8 @@ return {
"frozenflagcode", "tolerantflagcode", "protectedflagcode", "primitiveflagcode", "permanentflagcode", "noalignedflagcode", "immutableflagcode", "mutableflagcode",
"globalflagcode", "overloadedflagcode", "immediateflagcode", "conditionalflagcode", "valueflagcode", "instanceflagcode",
--
+ "ordflattencode", "binflattencode", "relflattencode", "punctflattencode", "innerflattencode",
+ --
"prewordcode", "postwordcode",
--
"continuewhenlmtxmode"
@@ -563,6 +571,8 @@ return {
--
"suggestedalias",
--
+ "showboxhere",
+ --
"newlocalcount", "newlocaldimen", "newlocalskip", "newlocalmuskip", "newlocaltoks", "newlocalbox",
"newlocalwrite", "newlocalread",
"setnewlocalcount", "setnewlocaldimen", "setnewlocalskip", "setnewlocalmuskip", "setnewlocaltoks", "setnewlocalbox",
diff --git a/tex/context/base/mkiv/mult-prm.lua b/tex/context/base/mkiv/mult-prm.lua
index 6338bff40..2cb38e8a3 100644
--- a/tex/context/base/mkiv/mult-prm.lua
+++ b/tex/context/base/mkiv/mult-prm.lua
@@ -32,14 +32,11 @@ return {
"iffontchar",
"interactionmode",
"interlinepenalties",
- "lastchkdim",
- "lastchknum",
"lastlinefit",
"lastnodetype",
"marks",
"muexpr",
"mutoglue",
- "numericscale",
"numexpr",
"pagediscards",
"parshapedimen",
@@ -120,6 +117,10 @@ return {
"Umathdelimiterovervariant",
"Umathdelimiterundervariant",
"Umathdenominatorvariant",
+ "Umathextrasubpreshift",
+ "Umathextrasubshift",
+ "Umathextrasuppreshift",
+ "Umathextrasupshift",
"Umathfractiondelsize",
"Umathfractiondenomdown",
"Umathfractiondenomvgap",
@@ -318,9 +319,11 @@ return {
"explicithyphenpenalty",
"firstvalidlanguage",
"fontid",
+ "fontmathcontrol",
"fontspecifiedsize",
"formatname",
"frozen",
+ "futurecsname",
"futuredef",
"futureexpand",
"futureexpandis",
@@ -396,6 +399,8 @@ return {
"instance",
"integerdef",
"lastarguments",
+ "lastchkdim",
+ "lastchknum",
"lastnamedcs",
"lastnodesubtype",
"leftmarginkern",
@@ -423,11 +428,13 @@ return {
"luatexbanner",
"luatexrevision",
"luatexversion",
+ "mathcontrolmode",
"mathdelimitersmode",
"mathdirection",
"mathdisplayskipmode",
"matheqnogapstep",
"mathflattenmode",
+ "mathfontcontrol",
"mathitalicsmode",
"mathnolimitsmode",
"mathpenaltiesmode",
@@ -450,6 +457,7 @@ return {
"normalizelinemode",
"nospaces",
"novrule",
+ "numericscale",
"orelse",
"orunless",
"outputbox",
@@ -492,6 +500,7 @@ return {
"undent",
"unletfrozen",
"unletprotected",
+ "untraced",
"vpack",
"wordboundary",
"wrapuppar",
diff --git a/tex/context/base/mkiv/node-res.lua b/tex/context/base/mkiv/node-res.lua
index 408f8ea47..5c669f9da 100644
--- a/tex/context/base/mkiv/node-res.lua
+++ b/tex/context/base/mkiv/node-res.lua
@@ -590,7 +590,7 @@ statistics.register("node memory usage", function() -- comes after cleanup !
end
end)
-lua.registerfinalizer(cleanup, "cleanup reserved nodes")
+lua.registerinitexfinalizer(cleanup, "cleanup reserved nodes")
-- experiment
diff --git a/tex/context/base/mkiv/node-syn.lua b/tex/context/base/mkiv/node-syn.lua
index 8b8b628dd..4014445b0 100644
--- a/tex/context/base/mkiv/node-syn.lua
+++ b/tex/context/base/mkiv/node-syn.lua
@@ -231,8 +231,8 @@ local blockedsuffixes = {
-- lfg = true,
}
-local sttags = table.setmetatableindex(function(t,name)
- name = collapsepath(name)
+local sttags = table.setmetatableindex(function(t,fullname)
+ local name = collapsepath(fullname)
if blockedsuffixes[suffixonly(name)] then
-- Just so that I don't get the ones on my development tree.
nofblocked = nofblocked + 1
@@ -248,6 +248,9 @@ local sttags = table.setmetatableindex(function(t,name)
else
noftags = noftags + 1
t[name] = noftags
+ if name ~= fullname then
+ t[fullname] = noftags
+ end
stnums[noftags] = name
return noftags
end
diff --git a/tex/context/base/mkiv/status-files.pdf b/tex/context/base/mkiv/status-files.pdf
index 2558e805e..4c0c46993 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 dcbc15681..ca29ed3a5 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/supp-box.lua b/tex/context/base/mkiv/supp-box.lua
index 4b9322ba7..2e7ca5924 100644
--- a/tex/context/base/mkiv/supp-box.lua
+++ b/tex/context/base/mkiv/supp-box.lua
@@ -171,7 +171,7 @@ implement {
arguments = "integer",
actions = function(n)
-- we just hyphenate (as we pass a hpack) .. a bit too much casting but ...
- local l = languages.hyphenators.handler(tonode(checkedlist(n)))
+ local l = languages.hyphenators.handler(checkedlist(n))
report_hyphenation("show: %s",listtoutf(l,false,true))
end
}
diff --git a/tex/context/base/mkiv/util-fil.lua b/tex/context/base/mkiv/util-fil.lua
index 183f7bea8..0b20264ec 100644
--- a/tex/context/base/mkiv/util-fil.lua
+++ b/tex/context/base/mkiv/util-fil.lua
@@ -203,23 +203,23 @@ function files.readinteger4le(f)
end
function files.readfixed2(f)
- local a, b = byte(f:read(2),1,2)
- if a >= 0x80 then
- tonumber((a - 0x100) .. "." .. b)
- else
- tonumber(( a ) .. "." .. b)
+ local n1, n2 = byte(f:read(2),1,2)
+ if n1 >= 0x80 then
+ n1 = n1 - 0x100
end
+ return n1 + n2/0xFF
end
-- (real) (n>>16) + ((n&0xffff)/65536.0)) but no cast in lua (we could use unpack)
function files.readfixed4(f)
local a, b, c, d = byte(f:read(4),1,4)
- if a >= 0x80 then
- tonumber((0x100 * a + b - 0x10000) .. "." .. (0x100 * c + d))
- else
- tonumber((0x100 * a + b ) .. "." .. (0x100 * c + d))
+ local n1 = 0x100 * a + b
+ local n2 = 0x100 * c + d
+ if n1 >= 0x8000 then
+ n1 = n1 - 0x10000
end
+ return n1 + n2/0xFFFF
end
-- (real) ((n<<16)>>(16+14)) + ((n&0x3fff)/16384.0))
diff --git a/tex/context/base/mkiv/util-sac.lua b/tex/context/base/mkiv/util-sac.lua
index 522b0bc08..796a620ba 100644
--- a/tex/context/base/mkiv/util-sac.lua
+++ b/tex/context/base/mkiv/util-sac.lua
@@ -262,12 +262,11 @@ function streams.readfixed2(f)
local i = f[2]
local j = i + 1
f[2] = j + 1
- local a, b = byte(f[1],i,j)
- if a >= 0x80 then
- return tonumber((a - 0x100) .. "." .. b) or 0
- else
- return tonumber((a ) .. "." .. b) or 0
+ local n1, n2 = byte(f[1],i,j)
+ if n1 >= 0x80 then
+ n1 = n1 - 0x100
end
+ return n1 + n2/0xFF
end
function streams.readfixed4(f)
@@ -275,11 +274,12 @@ function streams.readfixed4(f)
local j = i + 3
f[2] = j + 1
local a, b, c, d = byte(f[1],i,j)
- if a >= 0x80 then
- return tonumber((0x100 * a + b - 0x10000) .. "." .. (0x100 * c + d)) or 0
- else
- return tonumber((0x100 * a + b ) .. "." .. (0x100 * c + d)) or 0
+ local n1 = 0x100 * a + b
+ local n2 = 0x100 * c + d
+ if n1 >= 0x8000 then
+ n1 = n1 - 0x10000
end
+ return n1 + n2/0xFFFF
end
if bit32 then
@@ -507,10 +507,10 @@ do
function io.newreader(str,method)
local f, m
if method == "string" then
- f = openstring(str)
+ f = openstring(str,true)
m = streams
elseif method == "stream" then
- f = openstream(str)
+ f = openstream(str,true)
m = streams
else
f = openfile(str,"rb")
@@ -522,6 +522,7 @@ do
__index = function(t,k)
local r = m[k]
if k == "close" then
+ -- maybe use __toclose
if f then
m.close(f)
f = nil
diff --git a/tex/context/base/mkiv/util-tar.lua b/tex/context/base/mkiv/util-tar.lua
new file mode 100644
index 000000000..0368a7db5
--- /dev/null
+++ b/tex/context/base/mkiv/util-tar.lua
@@ -0,0 +1,359 @@
+if not modules then modules = { } end modules ['util-tar'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local type, tonumber = type, tonumber
+local gsub, escapedpattern = string.gsub, string.escapedpattern
+local nameonly, dirname, makedirs = file.nameonly, file.dirname, dir.makedirs
+local savedata = io.savedata
+local newreader = io.newreader
+
+local report = logs.reporter("tar")
+
+local types = {
+ ["0"] = "file",
+ ["\0"] = "regular",
+ ["1"] = "link",
+ ["2"] = "symbolic", -- reserved
+ ["3"] = "character",
+ ["4"] = "block",
+ ["5"] = "directory",
+ ["6"] = "fifo",
+ ["7"] = "continuation", -- reserved
+ ["x"] = "extended", -- header
+}
+
+local function asstring(str)
+ return str and gsub(str,"[\0 ]+$","") or nil
+end
+
+local function asnumber(str)
+ str = gsub(str,"\0$","")
+ return tonumber(str,8)
+end
+
+local function opentar(whatever,filename)
+ local f = newreader(filename,whatever)
+ if f then
+ f.metadata = {
+ nofpaths = 0,
+ noffiles = 0,
+ noflinks = 0,
+ nofbytes = 0,
+ }
+ return f
+ end
+end
+
+local function readheader(t)
+ -- checksum
+ local p = t:getposition()
+ local h = t:readbytetable(512)
+ t:setposition(p)
+ for i=149,156 do -- nasty, one less
+ h[i] = 0
+ end
+ local c = 256
+ for i=1,512 do
+ c = c + h[i]
+ end
+ --
+ local header = {
+ name = asstring(t:readstring(100)), -- 0
+ mode = asnumber(t:readstring( 8)), -- 100 -- when we write: 0775 octal
+ uid = asnumber(t:readstring( 8)), -- 108
+ gid = asnumber(t:readstring( 8)), -- 116
+ size = asnumber(t:readstring( 12)), -- 124
+ mtime = asnumber(t:readstring( 12)), -- 136
+ checksum = asnumber(t:readstring( 6)), -- 148 -- actually 6 with space and \0
+ dummy = t:skip (2) ,
+ typeflag = t:readstring( 1) , -- 156
+ linkname = asstring(t:readstring(100)), -- 157
+ -- magic = asstring(t:readstring( 6)), -- 257 -- ustar\0
+ -- version = 2 -- 263
+ -- uname = 32 -- 265
+ -- gname = 32 -- 297
+ -- devmajor = 8 -- 329
+ -- devminor = 8 -- 337
+ -- prefix = 155 -- 345
+ padding = t:skip (255) , -- 500
+ }
+ local typeflag = header.typeflag
+ if typeflag then
+ header.filetype = types[typeflag]
+ if c == header.checksum then
+ return header
+ end
+ end
+end
+
+local readers = {
+
+ directory = function(t,h)
+ local metadata = t.metadata
+ local filename = h.name
+ if metadata.verbose then
+ report("%8s %s","",filename)
+ end
+ metadata.nofpaths = metadata.nofpaths + 1
+ return true
+ end,
+
+ file = function(t,h)
+ local metadata = t.metadata
+ local filename = h.name
+ local filesize = h.size
+ local pathname = dirname(filename)
+ if metadata.verbose then
+ report("% 8i : %s",filesize,filename)
+ end
+ if makedirs(pathname) then
+ savedata(filename,t:readstring(filesize))
+ else
+ t.skip(filesize)
+ end
+ local position = t:getposition()
+ local target = position + (512 - position % 512) % 512
+ t:setposition(target)
+ metadata.noffiles = metadata.noffiles + 1
+ metadata.nofbytes = metadata.nofbytes + filesize
+ return true
+ end,
+
+ link = function(t,h)
+ local metadata = t.metadata
+ local filename = h.name
+ local linkname = h.linkname
+ if metadata.verbose then
+ report("%8s %s => %s","",linkname,filename)
+ end
+ metadata.noflinks = metadata.noflinks + 1
+ return true
+ end,
+
+}
+
+local skippers = {
+
+ directory = function(t,h)
+ return true
+ end,
+
+ file = function(t,h)
+ local filesize = h.size
+ local fileoffset = t:getposition()
+ local position = filesize + fileoffset
+ local target = position + (512 - position % 512) % 512
+ t:setposition(target)
+ return fileoffset
+ end,
+
+ link = function(t,h)
+ return true
+ end,
+
+}
+
+local writers = {
+ -- nothing here (yet)
+}
+
+local function saveheader(t,h)
+ local filetype = h.filetype
+ local reader = readers[filetype]
+ if reader then
+ return filetype, reader(t,h)
+ else
+ report("no reader for %s",filetype)
+ end
+end
+
+local function skipheader(t,h)
+ local filetype = h.filetype
+ local skipper = skippers[filetype]
+ if skipper then
+ return filetype, skipper(t,h)
+ else
+ report("no skipper for %s",filetype)
+ end
+end
+
+local function unpacktar(whatever,filename,verbose)
+ local t = opentar(whatever,filename)
+ if t then
+ local metadata = t.metadata
+ statistics.starttiming(metadata)
+ if verbose then
+ if whatever == "string" then
+ report("unpacking: %i bytes",#filename)
+ else
+ report("unpacking: %s",filename)
+ end
+ report("")
+ metadata.verbose = verbose
+ end
+ while true do
+ local h = readheader(t)
+ if not h then
+ break
+ else
+ local filetype, saved = saveheader(t,h)
+ if not saved then
+ break
+ end
+ end
+ end
+ statistics.stoptiming(metadata)
+ metadata.runtime = statistics.elapsed(metadata)
+ if verbose then
+ report("")
+ report("number of paths : %i",metadata.nofpaths)
+ report("number of files : %i",metadata.noffiles)
+ report("number of links : %i",metadata.noflinks)
+ report("number of bytes : %i",metadata.nofbytes)
+ report("")
+ report("runtime needed : %s",statistics.elapsedseconds(metadata))
+ report("")
+ end
+ t.close()
+ return metadata
+ end
+end
+
+local function listtar(whatever,filename,onlyfiles)
+ local t = opentar(whatever,filename)
+ if t then
+ local list, n = { }, 0
+ while true do
+ local h = readheader(t)
+ if not h then
+ break
+ else
+ local filetype, offset = skipheader(t,h)
+ if not offset then
+ break
+ elseif filetype == "file" then
+ n = n + 1 ; list[n] = { filetype, h.name, h.size }
+ elseif filetype == "link" then
+ n = n + 1 ; list[n] = { filetype, h.name, h.linkfile }
+ elseif not onlyfiles then
+ n = n + 1 ; list[n] = { filetype, h.name }
+ end
+ end
+ end
+ t.close()
+ -- can be an option
+ table.sort(list,function(a,b) return a[2] < b[2] end)
+ return list
+ end
+end
+
+local function hashtar(whatever,filename,strip)
+ local t = opentar(whatever,filename)
+ if t then
+ local list = { }
+ if strip then
+ strip = "^" .. escapedpattern(nameonly(nameonly(strip))) .. "/"
+ end
+ while true do
+ local h = readheader(t)
+ if not h then
+ break
+ else
+ local filetype, offset = skipheader(t,h)
+ if not offset then
+ break
+ else
+ local name = h.name
+ if strip then
+ name = gsub(name,strip,"")
+ end
+ if filetype == "file" then
+ list[name] = { offset, h.size }
+ elseif filetype == "link" then
+ list[name] = h.linkname
+ end
+ end
+ end
+ end
+ t.close()
+ return list
+ end
+end
+
+-- weak table ?
+
+local function fetchtar(whatever,archive,filename,list)
+ if not list then
+ list = hashtar(whatever,archive)
+ end
+ if list then
+ local what = list[filename]
+ if type(what) == "string" then
+ what = list[what] -- a link
+ end
+ if what then
+ local t = opentar(whatever,archive)
+ if t then
+ t:setposition(what[1])
+ return t:readstring(what[2])
+ end
+ end
+ end
+end
+
+local function packtar(whatever,filename,verbose)
+ report("packing will be implemented when we need it")
+end
+
+local tar = {
+ files = {
+ unpack = function(...) return unpacktar("file", ...) end,
+ pack = function(...) return packtar ("file", ...) end,
+ list = function(...) return listtar ("file", ...) end,
+ hash = function(...) return hashtar ("file", ...) end,
+ fetch = function(...) return fetchtar ("file", ...) end,
+ },
+ strings = {
+ unpack = function(...) return unpacktar("string",...) end,
+ pack = function(...) return packtar ("string",...) end,
+ list = function(...) return listtar ("string",...) end,
+ hash = function(...) return hashtar ("string",...) end,
+ fetch = function(...) return fetchtar ("string",...) end,
+ },
+ streams = {
+ unpack = function(...) return unpacktar("stream",...) end,
+ pack = function(...) return packtar ("stream",...) end,
+ list = function(...) return listtar ("stream",...) end,
+ hash = function(...) return hashtar ("stream",...) end,
+ fetch = function(...) return fetchtar ("stream",...) end,
+ },
+}
+
+utilities.tar = tar
+
+-- tar.files .unpack("e:/luatex/luametatex-source.tar",true)
+-- tar.streams.unpack("e:/luatex/luametatex-source.tar",true)
+-- tar.strings.unpack(io.loaddata("e:/luatex/luametatex-source.tar"),true)
+
+-- inspect(tar.files .unpack("e:/luatex/luametatex-source.tar"))
+-- inspect(tar.streams.unpack("e:/luatex/luametatex-source.tar"))
+-- inspect(tar.strings.unpack(io.loaddata("e:/luatex/luametatex-source.tar")))
+
+-- inspect(tar.files .list("e:/luatex/luametatex-source.tar",true))
+-- inspect(tar.streams.list("e:/luatex/luametatex-source.tar",true))
+-- inspect(tar.strings.list(io.loaddata("e:/luatex/luametatex-source.tar"),true))
+
+-- local c = os.clock()
+-- local l = tar.files.hash("e:/luatex/luametatex-source.tar")
+-- for i=1,500 do
+-- local s = tar.files.fetch("e:/luatex/luametatex-source.tar", "luametatex-source/source/tex/texbuildpage.c", l)
+-- local s = tar.files.fetch( "e:/luatex/luametatex-source.tar","luametatex-source/source/lua/lmtlibrary.c", l)
+-- end
+-- print(os.clock()-c)
+
+return tar
diff --git a/tex/context/base/mkiv/util-zip.lua b/tex/context/base/mkiv/util-zip.lua
index e97f3a065..67c1a715f 100644
--- a/tex/context/base/mkiv/util-zip.lua
+++ b/tex/context/base/mkiv/util-zip.lua
@@ -21,6 +21,14 @@ local ioopen = io.open
local loaddata, savedata = io.loaddata, io.savedata
local filejoin, isdir, dirname, mkdirs = file.join, lfs.isdir, file.dirname, dir.mkdirs
+gzip = gzip or { } -- so in luatex we keep the old ones too
+
+if not zlib then
+ zlib = xzip -- in luametatex we shadow the old one
+elseif not xzip then
+ xzip = zlib
+end
+
local files = utilities.files
local openfile = files.open
local closefile = files.close
@@ -497,48 +505,157 @@ if xzip then -- flate then do
end
-zipfiles.gunzipfile = gzip.load
+if not gzip.compress then
+
+ -- todo: compress/decompress that work with offset in string
+
+ -- We only have a few official methods here:
+ --
+ -- local decompressed = gzip.load (filename)
+ -- local resultsize = gzip.save (filename,compresslevel)
+ -- local compressed = gzip.compress (str,compresslevel)
+ -- local decompressed = gzip.decompress (str)
+ -- local iscompressed = gzip.compressed (str)
+ -- local suffix, okay = gzip.suffix (filename)
+ --
+ -- In LuaMetaTeX we have only xzip which implements a very few methods:
+ --
+ -- compress (str,level,method,window,memory,strategy)
+ -- decompress (str,window)
+ -- adler32 (str,checksum)
+ -- crc32 (str,checksum)
+ --
+ -- Special window values are:
+ --
+ -- flate : - 15
+ -- zlib : 15
+ -- gzip : - 15
+
+ local suffix = file.suffix
+ local suffixes = file.suffixes
+ local find = string.find
+ local concat = table.concat
+ local openfile = io.open
+
+ local gzipwindow = -15 -- miniz needs this
+ local gziplevel = 3
+ local identifier = "\x1F\x8B"
+ local pattern = "^\x1F\x8B\x08"
+
+ local compress = zlib.compress
+ local decompress = zlib.decompress
+ local crc32 = zlib.crc32
+
+ local streams = utilities.streams
+ local openstream = streams.openstring
+ local closestream = streams.close
+ local getposition = streams.getposition
+ local readbyte = streams.readbyte
+ local readcardinal4 = streams.readcardinal4le
+ local readcardinal2 = streams.readcardinal2le
+ local readstring = streams.readstring
+ local readcstring = streams.readcstring
+ local skipbytes = streams.skip
+
+ local tocardinal1 = streams.tocardinal1
+ local tocardinal4 = streams.tocardinal4le
+
+ local function getdecompressed(str)
+ local s = openstream(str)
+ local identifier = readstring(s,2)
+ local method = readbyte(s,1)
+ local flags = readbyte(s,1)
+ local timestamp = readcardinal4(s)
+ local compression = readbyte(s,1)
+ local operating = readbyte(s,1)
+ local isjusttext = (flags & 0x01 ~= 0) and true or false
+ local extrasize = (flags & 0x04 ~= 0) and readcardinal2(s) or 0
+ local filename = (flags & 0x08 ~= 0) and readcstring(s) or ""
+ local comment = (flags & 0x10 ~= 0) and readcstring(s) or ""
+ local checksum = (flags & 0x02 ~= 0) and readcardinal2(s) or 0
+ local compressed = readstring(s,#str)
+ local data = decompress(compressed,gzipwindow) -- pass offset
+ return data
+ end
--- if flate then
---
--- local streams = utilities.streams
--- local openfile = streams.open
--- local closestream = streams.close
--- local setposition = streams.setposition
--- local getsize = streams.size
--- local readcardinal4 = streams.readcardinal4le
--- local getstring = streams.getstring
--- local decompress = flate.gz_decompress
---
--- -- id1=1 id2=1 method=1 flags=1 mtime=4(le) extra=1 os=1
--- -- flags:8 comment=...<nul> flags:4 name=...<nul> flags:2 extra=...<nul> flags:1 crc=2
--- -- data:?
--- -- crc=4 size=4
---
--- function zipfiles.gunzipfile(filename)
--- local strm = openfile(filename)
--- if strm then
--- setposition(strm,getsize(strm) - 4 + 1)
--- local size = readcardinal4(strm)
--- local data = decompress(getstring(strm),size)
--- closestream(strm)
--- return data
--- end
--- end
---
--- elseif gzip then
---
--- local openfile = gzip.open
---
--- function zipfiles.gunzipfile(filename)
--- local g = openfile(filename,"rb")
--- if g then
--- local d = g:read("*a")
--- d:close()
--- return d
--- end
--- end
---
--- end
+ local function putcompressed(str,level,originalname)
+ return concat {
+ identifier, -- 2 identifier
+ tocardinal1(0x08), -- 1 method
+ tocardinal1(0x08), -- 1 flags
+ tocardinal4(os.time()), -- 4 mtime
+ tocardinal1(0x02), -- 1 compression (2 or 4)
+ tocardinal1(0xFF), -- 1 operating
+ (originalname or "unknownname") .. "\0",
+ compress(str,level,nil,gzipwindow),
+ tocardinal4(crc32(str)), -- 4
+ tocardinal4(#str), -- 4
+ }
+ end
+
+ function gzip.load(filename)
+ local f = openfile(filename,"rb")
+ if not f then
+ -- invalid file
+ else
+ local data = f:read("*all")
+ f:close()
+ if data and data ~= "" then
+ if suffix(filename) == "gz" then
+ data = getdecompressed(data)
+ end
+ return data
+ end
+ end
+ end
+
+ function gzip.save(filename,data,level,originalname)
+ if suffix(filename) ~= "gz" then
+ filename = filename .. ".gz"
+ end
+ local f = openfile(filename,"wb")
+ if f then
+ data = putcompressed(data or "",level or gziplevel,originalname)
+ f:write(data)
+ f:close()
+ return #data
+ end
+ end
+
+ function gzip.suffix(filename)
+ local suffix, extra = suffixes(filename)
+ local gzipped = extra == "gz"
+ return suffix, gzipped
+ end
+
+ function gzip.compressed(s)
+ return s and find(s,identifier)
+ end
+
+ function gzip.compress(s,level)
+ if s and not find(s,identifier) then -- the find check might go away
+ if not level then
+ level = gziplevel
+ elseif level <= 0 then
+ return s
+ elseif level > 9 then
+ level = 9
+ end
+ return putcompressed(s,level or gziplevel) or s
+ end
+ end
+
+ function gzip.decompress(s)
+ if s and find(s,identifier) then
+ return getdecompressed(s)
+ else
+ return s
+ end
+ end
+
+
+end
+
+zipfiles.gunzipfile = gzip.load
return zipfiles