summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/context/lua/luatools.lua380
-rw-r--r--scripts/context/lua/mtxrun.lua332
-rw-r--r--scripts/context/stubs/mswin/luatools.lua380
-rw-r--r--scripts/context/stubs/mswin/mtxrun.lua332
-rwxr-xr-xscripts/context/stubs/unix/luatools380
-rwxr-xr-xscripts/context/stubs/unix/mtxrun332
-rw-r--r--tex/context/base/cont-new.tex2
-rw-r--r--tex/context/base/context.tex2
-rw-r--r--tex/context/base/core-sys.mkiv76
-rw-r--r--tex/context/base/data-res.lua6
-rw-r--r--tex/context/base/font-syn.lua11
-rw-r--r--tex/context/base/lpdf-mis.lua26
-rw-r--r--tex/context/base/node-ref.lua39
-rw-r--r--tex/generic/context/luatex-fonts-merged.lua2
14 files changed, 2038 insertions, 262 deletions
diff --git a/scripts/context/lua/luatools.lua b/scripts/context/lua/luatools.lua
index f0fcd517d..433d1b8dc 100644
--- a/scripts/context/lua/luatools.lua
+++ b/scripts/context/lua/luatools.lua
@@ -265,6 +265,11 @@ function string.tabtospace(str,tab)
return str
end
+function string:compactlong() -- strips newlines and leading spaces
+ self = gsub(self,"[\n\r]+ *","")
+ self = gsub(self,"^ *","")
+ return self
+end
end -- of closure
@@ -407,6 +412,10 @@ function table.strip(tab)
return lst
end
+local function compare(a,b)
+ return (tostring(a) < tostring(b))
+end
+
local function sortedkeys(tab)
local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in next, tab do
@@ -427,7 +436,7 @@ local function sortedkeys(tab)
end
end
if kind == 0 or kind == 3 then
- sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
+ sort(srt,compare)
else
sort(srt)
end
@@ -1058,7 +1067,7 @@ function table.insert_after_value(t,value,str)
end
local function are_equal(a,b,n,m) -- indexed
- if #a == #b then
+ if a and b and #a == #b then
n = n or 1
m = m or #a
for i=n,m do
@@ -1215,6 +1224,7 @@ end
function io.loaddata(filename,textmode)
local f = io.open(filename,(textmode and 'r') or 'rb')
if f then
+ -- collectgarbage("step") -- sometimes makes a big difference in mem consumption
local data = f:read('*all')
-- garbagecollector.check(data)
f:close()
@@ -1451,6 +1461,7 @@ set = set or { }
local nums = { }
local tabs = { }
local concat = table.concat
+local next, type = next, type
set.create = table.tohash
@@ -1458,17 +1469,19 @@ function set.tonumber(t)
if next(t) then
local s = ""
-- we could save mem by sorting, but it slows down
- for k, v in pairs(t) do
+ for k, v in next, t do
if v then
-- why bother about the leading space
s = s .. " " .. k
end
end
- if not nums[s] then
- tabs[#tabs+1] = t
- nums[s] = #tabs
+ local n = nums[s]
+ if not n then
+ n = #tabs + 1
+ tabs[n] = t
+ nums[s] = n
end
- return nums[s]
+ return n
else
return 0
end
@@ -1482,6 +1495,20 @@ function set.totable(n)
end
end
+function set.tolist(n)
+ if n == 0 or not tabs[n] then
+ return ""
+ else
+ local t = { }
+ for k, v in next, tabs[n] do
+ if v then
+ t[#t+1] = k
+ end
+ end
+ return concat(t," ")
+ end
+end
+
function set.contains(n,s)
if type(n) == "table" then
return n[s]
@@ -1678,8 +1705,8 @@ function file.replacesuffix(filename, suffix)
return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
end
-function file.dirname(name)
- return match(name,"^(.+)[/\\].-$") or ""
+function file.dirname(name,default)
+ return match(name,"^(.+)[/\\].-$") or (default or "")
end
function file.basename(name)
@@ -1717,15 +1744,8 @@ function file.join(...)
end
function file.iswritable(name)
- local a = lfs.attributes(name)
- if a and a.permissions:sub(2,2) == "w" then
- return true
- else
- name = file.dirname(name) or "."
- if name == "" then name = "." end
- a = lfs.attributes(name)
- return a and a.permissions:sub(2,2) == "w"
- end
+ local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,"."))
+ return a and a.permissions:sub(2,2) == "w"
end
function file.isreadable(name)
@@ -1893,6 +1913,26 @@ function file.is_rootbased_path(filename)
return rootbased:match(filename)
end
+local slash = lpeg.S("\\/")
+local period = lpeg.P(".")
+local drive = lpeg.C(lpeg.R("az","AZ")) * lpeg.P(":")
+local path = lpeg.C(((1-slash)^0 * slash)^0)
+local suffix = period * lpeg.C(lpeg.P(1-period)^0 * lpeg.P(-1))
+local base = lpeg.C((1-suffix)^0)
+
+local pattern = (drive + lpeg.Cc("")) * (path + lpeg.Cc("")) * (base + lpeg.Cc("")) * (suffix + lpeg.Cc(""))
+
+function file.splitname(str) -- returns drive, path, base, suffix
+ return pattern:match(str)
+end
+
+-- function test(t) for k, v in pairs(t) do print(v, "=>", file.splitname(v)) end end
+--
+-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
+-- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" }
+-- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" }
+-- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" }
+
end -- of closure
@@ -1948,7 +1988,7 @@ function file.checksum(name)
if md5 then
local data = io.loaddata(name)
if data then
- return md5.HEXsum(data)
+ return md5.HEX(data)
end
end
return nil
@@ -2862,6 +2902,235 @@ end -- of closure
do -- create closure to overcome 200 locals limit
+if not modules then modules = { } end modules ['l-aux'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+aux = aux or { }
+
+local concat, format, gmatch = table.concat, string.format, string.gmatch
+local tostring, type = tostring, type
+
+local space = lpeg.P(' ')
+local equal = lpeg.P("=")
+local comma = lpeg.P(",")
+local lbrace = lpeg.P("{")
+local rbrace = lpeg.P("}")
+local nobrace = 1 - (lbrace+rbrace)
+local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace }
+local spaces = space^0
+
+local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
+
+local key = lpeg.C((1-equal-comma)^1)
+local pattern_a = (space+comma)^0 * (key * equal * value + key * lpeg.C(""))
+local pattern_c = (space+comma)^0 * (key * equal * value)
+
+local key = lpeg.C((1-space-equal-comma)^1)
+local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + lpeg.C("")))
+
+-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored
+
+local hash = { }
+
+local function set(key,value) -- using Carg is slower here
+ hash[key] = value
+end
+
+local pattern_a_s = (pattern_a/set)^1
+local pattern_b_s = (pattern_b/set)^1
+local pattern_c_s = (pattern_c/set)^1
+
+aux.settings_to_hash_pattern_a = pattern_a_s
+aux.settings_to_hash_pattern_b = pattern_b_s
+aux.settings_to_hash_pattern_c = pattern_c_s
+
+function aux.make_settings_to_hash_pattern(set,how)
+ if how == "strict" then
+ return (pattern_c/set)^1
+ elseif how == "tolerant" then
+ return (pattern_b/set)^1
+ else
+ return (pattern_a/set)^1
+ end
+end
+
+function aux.settings_to_hash(str)
+ if str and str ~= "" then
+ hash = { }
+ if moretolerant then
+ pattern_b_s:match(str)
+ else
+ pattern_a_s:match(str)
+ end
+ return hash
+ else
+ return { }
+ end
+end
+
+function aux.settings_to_hash_tolerant(str)
+ if str and str ~= "" then
+ hash = { }
+ pattern_b_s:match(str)
+ return hash
+ else
+ return { }
+ end
+end
+
+function aux.settings_to_hash_strict(str)
+ if str and str ~= "" then
+ hash = { }
+ pattern_c_s:match(str)
+ return next(hash) and hash
+ else
+ return nil
+ end
+end
+
+local seperator = comma * space^0
+local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
+local pattern = lpeg.Ct(value*(seperator*value)^0)
+
+-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
+
+aux.settings_to_array_pattern = pattern
+
+function aux.settings_to_array(str)
+ if not str or str == "" then
+ return { }
+ else
+ return pattern:match(str)
+ end
+end
+
+local function set(t,v)
+ t[#t+1] = v
+end
+
+local value = lpeg.P(lpeg.Carg(1)*value) / set
+local pattern = value*(seperator*value)^0 * lpeg.Carg(1)
+
+function aux.add_settings_to_array(t,str)
+ return pattern:match(str, nil, t)
+end
+
+function aux.hash_to_string(h,separator,yes,no,strict,omit)
+ if h then
+ local t, s = { }, table.sortedkeys(h)
+ omit = omit and table.tohash(omit)
+ for i=1,#s do
+ local key = s[i]
+ if not omit or not omit[key] then
+ local value = h[key]
+ if type(value) == "boolean" then
+ if yes and no then
+ if value then
+ t[#t+1] = key .. '=' .. yes
+ elseif not strict then
+ t[#t+1] = key .. '=' .. no
+ end
+ elseif value or not strict then
+ t[#t+1] = key .. '=' .. tostring(value)
+ end
+ else
+ t[#t+1] = key .. '=' .. value
+ end
+ end
+ end
+ return concat(t,separator or ",")
+ else
+ return ""
+ end
+end
+
+function aux.array_to_string(a,separator)
+ if a then
+ return concat(a,separator or ",")
+ else
+ return ""
+ end
+end
+
+function aux.settings_to_set(str,t)
+ t = t or { }
+ for s in gmatch(str,"%s*([^,]+)") do
+ t[s] = true
+ end
+ return t
+end
+
+-- temporary here
+
+function aux.getparameters(self,class,parentclass,settings)
+ local sc = self[class]
+ if not sc then
+ sc = table.clone(self[parent])
+ self[class] = sc
+ end
+ aux.add_settings_to_array(sc, settings)
+end
+
+-- temporary here
+
+local digit = lpeg.R("09")
+local period = lpeg.P(".")
+local zero = lpeg.P("0")
+
+--~ local finish = lpeg.P(-1)
+--~ local nodigit = (1-digit) + finish
+--~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000
+--~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100
+
+local trailingzeros = zero^0 * -digit -- suggested by Roberto R
+local case_1 = period * trailingzeros / ""
+local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "")
+
+local number = digit^1 * (case_1 + case_2)
+local stripper = lpeg.Cs((number + 1)^0)
+
+--~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100"
+--~ collectgarbage("collect")
+--~ str = string.rep(sample,10000)
+--~ local ts = os.clock()
+--~ stripper:match(str)
+--~ print(#str, os.clock()-ts, stripper:match(sample))
+
+function aux.strip_zeros(str)
+ return stripper:match(str)
+end
+
+function aux.definetable(target) -- defines undefined tables
+ local composed, t = nil, { }
+ for name in gmatch(target,"([^%.]+)") do
+ if composed then
+ composed = composed .. "." .. name
+ else
+ composed = name
+ end
+ t[#t+1] = format("%s = %s or { }",composed,composed)
+ end
+ return concat(t,"\n")
+end
+
+function aux.accesstable(target)
+ local t = _G
+ for name in gmatch(target,"([^%.]+)") do
+ t = t[name]
+ end
+ return t
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
if not modules then modules = { } end modules ['trac-tra'] = {
version = 1.001,
comment = "companion to luat-lib.tex",
@@ -3012,7 +3281,11 @@ trackers = trackers or { }
local data, done = { }, { }
local function set(what,value)
- for w in gmatch(lower(what),"[^, ]+") do
+ if type(what) == "string" then
+ what = aux.settings_to_array(what)
+ end
+ for i=1,#what do
+ local w = what[i]
for d, f in next, data do
if done[d] then
-- prevent recursion due to wildcards
@@ -3391,27 +3664,34 @@ statistics.threshold = 0.05
local clock = os.gettimeofday or os.clock
+local notimer
+
function statistics.hastimer(instance)
return instance and instance.starttime
end
function statistics.starttiming(instance)
- if instance then
- local it = instance.timing
- if not it then
- it = 0
- end
- if it == 0 then
- instance.starttime = clock()
- if not instance.loadtime then
- instance.loadtime = 0
- end
+ if not instance then
+ notimer = { }
+ instance = notimer
+ end
+ local it = instance.timing
+ if not it then
+ it = 0
+ end
+ if it == 0 then
+ instance.starttime = clock()
+ if not instance.loadtime then
+ instance.loadtime = 0
end
- instance.timing = it + 1
end
+ instance.timing = it + 1
end
function statistics.stoptiming(instance, report)
+ if not instance then
+ instance = notimer
+ end
if instance then
local it = instance.timing
if it > 1 then
@@ -3435,10 +3715,16 @@ function statistics.stoptiming(instance, report)
end
function statistics.elapsedtime(instance)
+ if not instance then
+ instance = notimer
+ end
return format("%0.3f",(instance and instance.loadtime) or 0)
end
function statistics.elapsedindeed(instance)
+ if not instance then
+ instance = notimer
+ end
local t = (instance and instance.loadtime) or 0
return t > statistics.threshold
end
@@ -3479,6 +3765,7 @@ function statistics.show(reporter)
reporter(s[1],r,n)
end
end
+ texio.write_nl("") -- final newline
statistics.enable = false
end
end
@@ -3536,6 +3823,7 @@ if not modules then modules = { } end modules ['luat-log'] = {
-- this is old code that needs an overhaul
local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format
+local texcount = tex and tex.count
if texlua then
write_nl = print
@@ -3615,10 +3903,8 @@ function logs.tex.line(fmt,...) -- new
end
end
-local texcount = tex and tex.count
-
function logs.tex.start_page_number()
- local real, user, sub = texcount[0], texcount[1], texcount[2]
+ local real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
if real > 0 then
if user > 0 then
if sub > 0 then
@@ -3673,7 +3959,7 @@ function logs.xml.stop_run()
end
function logs.xml.start_page_number()
- write_nl(format("<p real='%s' page='%s' sub='%s'", texcount[0], texcount[1], texcount[2]))
+ write_nl(format("<p real='%s' page='%s' sub='%s'", texcount.realpageno, texcount.userpageno, texcount.subpageno))
end
function logs.xml.stop_page_number()
@@ -3908,7 +4194,7 @@ formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' }
formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' }
formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' }
formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' }
-formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc' }
+formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' }
formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' }
formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' }
@@ -3930,6 +4216,7 @@ alternatives['fea files'] = 'fea'
alternatives['opentype fonts'] = 'otf'
alternatives['truetype fonts'] = 'ttf'
alternatives['truetype collections'] = 'ttc'
+alternatives['truetype dictionary'] = 'dfont'
alternatives['type1 fonts'] = 'pfb'
-- obscure ones
@@ -4046,12 +4333,12 @@ local function reset_hashes()
end
local function check_configuration() -- not yet ok, no time for debugging now
- local ie = instance.environment
+ local ie, iv = instance.environment, instance.variables
local function fix(varname,default)
local proname = varname .. "." .. instance.progname or "crap"
- local p, v = ie[proname], ie[varname]
+ local p, v = ie[proname], ie[varname] or iv[varname]
if not ((p and p ~= "") or (v and v ~= "")) then
- instance.variables[varname] = default -- or environment?
+ iv[varname] = default -- or environment?
end
end
local name = os.name
@@ -5890,10 +6177,6 @@ caches.paths = caches.paths or nil
caches.force = false
caches.defaults = { "TEXMFCACHE", "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
-function caches.cleanname(name)
- return (gsub(lower(name),"[^%w%d]+","-"))
-end
-
function caches.temp()
local cachepath = nil
local function check(list,isenv)
@@ -5990,7 +6273,9 @@ function caches.loaddata(path,name)
local tmaname, tmcname = caches.setluanames(path,name)
local loader = loadfile(tmcname) or loadfile(tmaname)
if loader then
- return loader()
+ loader = loader()
+ collectgarbage("step")
+ return loader
else
return false
end
@@ -6132,7 +6417,7 @@ function containers.define(category, subcategory, version, enabled)
enabled = enabled,
version = version or 1.000,
trace = false,
- path = caches and caches.setpath(category,subcategory),
+ path = caches and caches.setpath and caches.setpath(category,subcategory),
}
c[subcategory] = s
end
@@ -6191,6 +6476,10 @@ function containers.content(container,name)
return container.storage[name]
end
+function containers.cleanname(name)
+ return (gsub(lower(name),"[^%w%d]+","-"))
+end
+
end -- of closure
@@ -6585,6 +6874,7 @@ own.libs = { -- todo: check which ones are really needed
'l-unicode.lua',
'l-math.lua',
'l-utils.lua',
+ 'l-aux.lua',
'trac-tra.lua',
'luat-env.lua',
'trac-inf.lua',
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index aba22a16e..82d1edecb 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -421,6 +421,10 @@ function table.strip(tab)
return lst
end
+local function compare(a,b)
+ return (tostring(a) < tostring(b))
+end
+
local function sortedkeys(tab)
local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in next, tab do
@@ -441,7 +445,7 @@ local function sortedkeys(tab)
end
end
if kind == 0 or kind == 3 then
- sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
+ sort(srt,compare)
else
sort(srt)
end
@@ -1072,7 +1076,7 @@ function table.insert_after_value(t,value,str)
end
local function are_equal(a,b,n,m) -- indexed
- if #a == #b then
+ if a and b and #a == #b then
n = n or 1
m = m or #a
for i=n,m do
@@ -1229,6 +1233,7 @@ end
function io.loaddata(filename,textmode)
local f = io.open(filename,(textmode and 'r') or 'rb')
if f then
+ -- collectgarbage("step") -- sometimes makes a big difference in mem consumption
local data = f:read('*all')
-- garbagecollector.check(data)
f:close()
@@ -1465,6 +1470,7 @@ set = set or { }
local nums = { }
local tabs = { }
local concat = table.concat
+local next, type = next, type
set.create = table.tohash
@@ -1472,17 +1478,19 @@ function set.tonumber(t)
if next(t) then
local s = ""
-- we could save mem by sorting, but it slows down
- for k, v in pairs(t) do
+ for k, v in next, t do
if v then
-- why bother about the leading space
s = s .. " " .. k
end
end
- if not nums[s] then
- tabs[#tabs+1] = t
- nums[s] = #tabs
+ local n = nums[s]
+ if not n then
+ n = #tabs + 1
+ tabs[n] = t
+ nums[s] = n
end
- return nums[s]
+ return n
else
return 0
end
@@ -1496,6 +1504,20 @@ function set.totable(n)
end
end
+function set.tolist(n)
+ if n == 0 or not tabs[n] then
+ return ""
+ else
+ local t = { }
+ for k, v in next, tabs[n] do
+ if v then
+ t[#t+1] = k
+ end
+ end
+ return concat(t," ")
+ end
+end
+
function set.contains(n,s)
if type(n) == "table" then
return n[s]
@@ -2600,6 +2622,235 @@ end -- of closure
do -- create closure to overcome 200 locals limit
+if not modules then modules = { } end modules ['l-aux'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+aux = aux or { }
+
+local concat, format, gmatch = table.concat, string.format, string.gmatch
+local tostring, type = tostring, type
+
+local space = lpeg.P(' ')
+local equal = lpeg.P("=")
+local comma = lpeg.P(",")
+local lbrace = lpeg.P("{")
+local rbrace = lpeg.P("}")
+local nobrace = 1 - (lbrace+rbrace)
+local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace }
+local spaces = space^0
+
+local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
+
+local key = lpeg.C((1-equal-comma)^1)
+local pattern_a = (space+comma)^0 * (key * equal * value + key * lpeg.C(""))
+local pattern_c = (space+comma)^0 * (key * equal * value)
+
+local key = lpeg.C((1-space-equal-comma)^1)
+local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + lpeg.C("")))
+
+-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored
+
+local hash = { }
+
+local function set(key,value) -- using Carg is slower here
+ hash[key] = value
+end
+
+local pattern_a_s = (pattern_a/set)^1
+local pattern_b_s = (pattern_b/set)^1
+local pattern_c_s = (pattern_c/set)^1
+
+aux.settings_to_hash_pattern_a = pattern_a_s
+aux.settings_to_hash_pattern_b = pattern_b_s
+aux.settings_to_hash_pattern_c = pattern_c_s
+
+function aux.make_settings_to_hash_pattern(set,how)
+ if how == "strict" then
+ return (pattern_c/set)^1
+ elseif how == "tolerant" then
+ return (pattern_b/set)^1
+ else
+ return (pattern_a/set)^1
+ end
+end
+
+function aux.settings_to_hash(str)
+ if str and str ~= "" then
+ hash = { }
+ if moretolerant then
+ pattern_b_s:match(str)
+ else
+ pattern_a_s:match(str)
+ end
+ return hash
+ else
+ return { }
+ end
+end
+
+function aux.settings_to_hash_tolerant(str)
+ if str and str ~= "" then
+ hash = { }
+ pattern_b_s:match(str)
+ return hash
+ else
+ return { }
+ end
+end
+
+function aux.settings_to_hash_strict(str)
+ if str and str ~= "" then
+ hash = { }
+ pattern_c_s:match(str)
+ return next(hash) and hash
+ else
+ return nil
+ end
+end
+
+local seperator = comma * space^0
+local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
+local pattern = lpeg.Ct(value*(seperator*value)^0)
+
+-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
+
+aux.settings_to_array_pattern = pattern
+
+function aux.settings_to_array(str)
+ if not str or str == "" then
+ return { }
+ else
+ return pattern:match(str)
+ end
+end
+
+local function set(t,v)
+ t[#t+1] = v
+end
+
+local value = lpeg.P(lpeg.Carg(1)*value) / set
+local pattern = value*(seperator*value)^0 * lpeg.Carg(1)
+
+function aux.add_settings_to_array(t,str)
+ return pattern:match(str, nil, t)
+end
+
+function aux.hash_to_string(h,separator,yes,no,strict,omit)
+ if h then
+ local t, s = { }, table.sortedkeys(h)
+ omit = omit and table.tohash(omit)
+ for i=1,#s do
+ local key = s[i]
+ if not omit or not omit[key] then
+ local value = h[key]
+ if type(value) == "boolean" then
+ if yes and no then
+ if value then
+ t[#t+1] = key .. '=' .. yes
+ elseif not strict then
+ t[#t+1] = key .. '=' .. no
+ end
+ elseif value or not strict then
+ t[#t+1] = key .. '=' .. tostring(value)
+ end
+ else
+ t[#t+1] = key .. '=' .. value
+ end
+ end
+ end
+ return concat(t,separator or ",")
+ else
+ return ""
+ end
+end
+
+function aux.array_to_string(a,separator)
+ if a then
+ return concat(a,separator or ",")
+ else
+ return ""
+ end
+end
+
+function aux.settings_to_set(str,t)
+ t = t or { }
+ for s in gmatch(str,"%s*([^,]+)") do
+ t[s] = true
+ end
+ return t
+end
+
+-- temporary here
+
+function aux.getparameters(self,class,parentclass,settings)
+ local sc = self[class]
+ if not sc then
+ sc = table.clone(self[parent])
+ self[class] = sc
+ end
+ aux.add_settings_to_array(sc, settings)
+end
+
+-- temporary here
+
+local digit = lpeg.R("09")
+local period = lpeg.P(".")
+local zero = lpeg.P("0")
+
+--~ local finish = lpeg.P(-1)
+--~ local nodigit = (1-digit) + finish
+--~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000
+--~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100
+
+local trailingzeros = zero^0 * -digit -- suggested by Roberto R
+local case_1 = period * trailingzeros / ""
+local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "")
+
+local number = digit^1 * (case_1 + case_2)
+local stripper = lpeg.Cs((number + 1)^0)
+
+--~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100"
+--~ collectgarbage("collect")
+--~ str = string.rep(sample,10000)
+--~ local ts = os.clock()
+--~ stripper:match(str)
+--~ print(#str, os.clock()-ts, stripper:match(sample))
+
+function aux.strip_zeros(str)
+ return stripper:match(str)
+end
+
+function aux.definetable(target) -- defines undefined tables
+ local composed, t = nil, { }
+ for name in gmatch(target,"([^%.]+)") do
+ if composed then
+ composed = composed .. "." .. name
+ else
+ composed = name
+ end
+ t[#t+1] = format("%s = %s or { }",composed,composed)
+ end
+ return concat(t,"\n")
+end
+
+function aux.accesstable(target)
+ local t = _G
+ for name in gmatch(target,"([^%.]+)") do
+ t = t[name]
+ end
+ return t
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
if not modules then modules = { } end modules ['lxml-tab'] = {
version = 1.001,
comment = "this module is the basis for the lxml-* ones",
@@ -3047,7 +3298,7 @@ generic table copier. Since we know what we're dealing with we
can speed up things a bit. The second argument is not to be used!</p>
--ldx]]--
-function copy(old,tables)
+local function copy(old,tables)
if old then
tables = tables or { }
local new = { }
@@ -3270,7 +3521,7 @@ function xml.tostring(root) -- 25% overhead due to collecting
return root
elseif next(root) then -- next is faster than type (and >0 test)
local result = { }
- serialize(root,function(s) result[#result+1] = s end)
+ serialize(root,function(s) result[#result+1] = s end) -- brrr, slow (direct printing is faster)
return concat(result,"")
end
end
@@ -5333,7 +5584,11 @@ trackers = trackers or { }
local data, done = { }, { }
local function set(what,value)
- for w in gmatch(lower(what),"[^, ]+") do
+ if type(what) == "string" then
+ what = aux.settings_to_array(what)
+ end
+ for i=1,#what do
+ local w = what[i]
for d, f in next, data do
if done[d] then
-- prevent recursion due to wildcards
@@ -5712,27 +5967,34 @@ statistics.threshold = 0.05
local clock = os.gettimeofday or os.clock
+local notimer
+
function statistics.hastimer(instance)
return instance and instance.starttime
end
function statistics.starttiming(instance)
- if instance then
- local it = instance.timing
- if not it then
- it = 0
- end
- if it == 0 then
- instance.starttime = clock()
- if not instance.loadtime then
- instance.loadtime = 0
- end
+ if not instance then
+ notimer = { }
+ instance = notimer
+ end
+ local it = instance.timing
+ if not it then
+ it = 0
+ end
+ if it == 0 then
+ instance.starttime = clock()
+ if not instance.loadtime then
+ instance.loadtime = 0
end
- instance.timing = it + 1
end
+ instance.timing = it + 1
end
function statistics.stoptiming(instance, report)
+ if not instance then
+ instance = notimer
+ end
if instance then
local it = instance.timing
if it > 1 then
@@ -5756,10 +6018,16 @@ function statistics.stoptiming(instance, report)
end
function statistics.elapsedtime(instance)
+ if not instance then
+ instance = notimer
+ end
return format("%0.3f",(instance and instance.loadtime) or 0)
end
function statistics.elapsedindeed(instance)
+ if not instance then
+ instance = notimer
+ end
local t = (instance and instance.loadtime) or 0
return t > statistics.threshold
end
@@ -5800,6 +6068,7 @@ function statistics.show(reporter)
reporter(s[1],r,n)
end
end
+ texio.write_nl("") -- final newline
statistics.enable = false
end
end
@@ -5857,6 +6126,7 @@ if not modules then modules = { } end modules ['luat-log'] = {
-- this is old code that needs an overhaul
local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format
+local texcount = tex and tex.count
if texlua then
write_nl = print
@@ -5936,10 +6206,8 @@ function logs.tex.line(fmt,...) -- new
end
end
-local texcount = tex and tex.count
-
function logs.tex.start_page_number()
- local real, user, sub = texcount[0], texcount[1], texcount[2]
+ local real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
if real > 0 then
if user > 0 then
if sub > 0 then
@@ -5994,7 +6262,7 @@ function logs.xml.stop_run()
end
function logs.xml.start_page_number()
- write_nl(format("<p real='%s' page='%s' sub='%s'", texcount[0], texcount[1], texcount[2]))
+ write_nl(format("<p real='%s' page='%s' sub='%s'", texcount.realpageno, texcount.userpageno, texcount.subpageno))
end
function logs.xml.stop_page_number()
@@ -6229,7 +6497,7 @@ formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' }
formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' }
formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' }
formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' }
-formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc' }
+formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' }
formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' }
formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' }
@@ -6251,6 +6519,7 @@ alternatives['fea files'] = 'fea'
alternatives['opentype fonts'] = 'otf'
alternatives['truetype fonts'] = 'ttf'
alternatives['truetype collections'] = 'ttc'
+alternatives['truetype dictionary'] = 'dfont'
alternatives['type1 fonts'] = 'pfb'
-- obscure ones
@@ -6367,12 +6636,12 @@ local function reset_hashes()
end
local function check_configuration() -- not yet ok, no time for debugging now
- local ie = instance.environment
+ local ie, iv = instance.environment, instance.variables
local function fix(varname,default)
local proname = varname .. "." .. instance.progname or "crap"
- local p, v = ie[proname], ie[varname]
+ local p, v = ie[proname], ie[varname] or iv[varname]
if not ((p and p ~= "") or (v and v ~= "")) then
- instance.variables[varname] = default -- or environment?
+ iv[varname] = default -- or environment?
end
end
local name = os.name
@@ -8307,7 +8576,9 @@ function caches.loaddata(path,name)
local tmaname, tmcname = caches.setluanames(path,name)
local loader = loadfile(tmcname) or loadfile(tmaname)
if loader then
- return loader()
+ loader = loader()
+ collectgarbage("step")
+ return loader
else
return false
end
@@ -9517,6 +9788,7 @@ own.libs = { -- todo: check which ones are really needed
-- 'l-unicode.lua',
-- 'l-tex.lua',
'l-utils.lua',
+ 'l-aux.lua',
-- 'l-xml.lua',
'lxml-tab.lua',
'lxml-pth.lua',
diff --git a/scripts/context/stubs/mswin/luatools.lua b/scripts/context/stubs/mswin/luatools.lua
index f0fcd517d..433d1b8dc 100644
--- a/scripts/context/stubs/mswin/luatools.lua
+++ b/scripts/context/stubs/mswin/luatools.lua
@@ -265,6 +265,11 @@ function string.tabtospace(str,tab)
return str
end
+function string:compactlong() -- strips newlines and leading spaces
+ self = gsub(self,"[\n\r]+ *","")
+ self = gsub(self,"^ *","")
+ return self
+end
end -- of closure
@@ -407,6 +412,10 @@ function table.strip(tab)
return lst
end
+local function compare(a,b)
+ return (tostring(a) < tostring(b))
+end
+
local function sortedkeys(tab)
local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in next, tab do
@@ -427,7 +436,7 @@ local function sortedkeys(tab)
end
end
if kind == 0 or kind == 3 then
- sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
+ sort(srt,compare)
else
sort(srt)
end
@@ -1058,7 +1067,7 @@ function table.insert_after_value(t,value,str)
end
local function are_equal(a,b,n,m) -- indexed
- if #a == #b then
+ if a and b and #a == #b then
n = n or 1
m = m or #a
for i=n,m do
@@ -1215,6 +1224,7 @@ end
function io.loaddata(filename,textmode)
local f = io.open(filename,(textmode and 'r') or 'rb')
if f then
+ -- collectgarbage("step") -- sometimes makes a big difference in mem consumption
local data = f:read('*all')
-- garbagecollector.check(data)
f:close()
@@ -1451,6 +1461,7 @@ set = set or { }
local nums = { }
local tabs = { }
local concat = table.concat
+local next, type = next, type
set.create = table.tohash
@@ -1458,17 +1469,19 @@ function set.tonumber(t)
if next(t) then
local s = ""
-- we could save mem by sorting, but it slows down
- for k, v in pairs(t) do
+ for k, v in next, t do
if v then
-- why bother about the leading space
s = s .. " " .. k
end
end
- if not nums[s] then
- tabs[#tabs+1] = t
- nums[s] = #tabs
+ local n = nums[s]
+ if not n then
+ n = #tabs + 1
+ tabs[n] = t
+ nums[s] = n
end
- return nums[s]
+ return n
else
return 0
end
@@ -1482,6 +1495,20 @@ function set.totable(n)
end
end
+function set.tolist(n)
+ if n == 0 or not tabs[n] then
+ return ""
+ else
+ local t = { }
+ for k, v in next, tabs[n] do
+ if v then
+ t[#t+1] = k
+ end
+ end
+ return concat(t," ")
+ end
+end
+
function set.contains(n,s)
if type(n) == "table" then
return n[s]
@@ -1678,8 +1705,8 @@ function file.replacesuffix(filename, suffix)
return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
end
-function file.dirname(name)
- return match(name,"^(.+)[/\\].-$") or ""
+function file.dirname(name,default)
+ return match(name,"^(.+)[/\\].-$") or (default or "")
end
function file.basename(name)
@@ -1717,15 +1744,8 @@ function file.join(...)
end
function file.iswritable(name)
- local a = lfs.attributes(name)
- if a and a.permissions:sub(2,2) == "w" then
- return true
- else
- name = file.dirname(name) or "."
- if name == "" then name = "." end
- a = lfs.attributes(name)
- return a and a.permissions:sub(2,2) == "w"
- end
+ local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,"."))
+ return a and a.permissions:sub(2,2) == "w"
end
function file.isreadable(name)
@@ -1893,6 +1913,26 @@ function file.is_rootbased_path(filename)
return rootbased:match(filename)
end
+local slash = lpeg.S("\\/")
+local period = lpeg.P(".")
+local drive = lpeg.C(lpeg.R("az","AZ")) * lpeg.P(":")
+local path = lpeg.C(((1-slash)^0 * slash)^0)
+local suffix = period * lpeg.C(lpeg.P(1-period)^0 * lpeg.P(-1))
+local base = lpeg.C((1-suffix)^0)
+
+local pattern = (drive + lpeg.Cc("")) * (path + lpeg.Cc("")) * (base + lpeg.Cc("")) * (suffix + lpeg.Cc(""))
+
+function file.splitname(str) -- returns drive, path, base, suffix
+ return pattern:match(str)
+end
+
+-- function test(t) for k, v in pairs(t) do print(v, "=>", file.splitname(v)) end end
+--
+-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
+-- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" }
+-- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" }
+-- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" }
+
end -- of closure
@@ -1948,7 +1988,7 @@ function file.checksum(name)
if md5 then
local data = io.loaddata(name)
if data then
- return md5.HEXsum(data)
+ return md5.HEX(data)
end
end
return nil
@@ -2862,6 +2902,235 @@ end -- of closure
do -- create closure to overcome 200 locals limit
+if not modules then modules = { } end modules ['l-aux'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+aux = aux or { }
+
+local concat, format, gmatch = table.concat, string.format, string.gmatch
+local tostring, type = tostring, type
+
+local space = lpeg.P(' ')
+local equal = lpeg.P("=")
+local comma = lpeg.P(",")
+local lbrace = lpeg.P("{")
+local rbrace = lpeg.P("}")
+local nobrace = 1 - (lbrace+rbrace)
+local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace }
+local spaces = space^0
+
+local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
+
+local key = lpeg.C((1-equal-comma)^1)
+local pattern_a = (space+comma)^0 * (key * equal * value + key * lpeg.C(""))
+local pattern_c = (space+comma)^0 * (key * equal * value)
+
+local key = lpeg.C((1-space-equal-comma)^1)
+local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + lpeg.C("")))
+
+-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored
+
+local hash = { }
+
+local function set(key,value) -- using Carg is slower here
+ hash[key] = value
+end
+
+local pattern_a_s = (pattern_a/set)^1
+local pattern_b_s = (pattern_b/set)^1
+local pattern_c_s = (pattern_c/set)^1
+
+aux.settings_to_hash_pattern_a = pattern_a_s
+aux.settings_to_hash_pattern_b = pattern_b_s
+aux.settings_to_hash_pattern_c = pattern_c_s
+
+function aux.make_settings_to_hash_pattern(set,how)
+ if how == "strict" then
+ return (pattern_c/set)^1
+ elseif how == "tolerant" then
+ return (pattern_b/set)^1
+ else
+ return (pattern_a/set)^1
+ end
+end
+
+function aux.settings_to_hash(str)
+ if str and str ~= "" then
+ hash = { }
+ if moretolerant then
+ pattern_b_s:match(str)
+ else
+ pattern_a_s:match(str)
+ end
+ return hash
+ else
+ return { }
+ end
+end
+
+function aux.settings_to_hash_tolerant(str)
+ if str and str ~= "" then
+ hash = { }
+ pattern_b_s:match(str)
+ return hash
+ else
+ return { }
+ end
+end
+
+function aux.settings_to_hash_strict(str)
+ if str and str ~= "" then
+ hash = { }
+ pattern_c_s:match(str)
+ return next(hash) and hash
+ else
+ return nil
+ end
+end
+
+local seperator = comma * space^0
+local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
+local pattern = lpeg.Ct(value*(seperator*value)^0)
+
+-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
+
+aux.settings_to_array_pattern = pattern
+
+function aux.settings_to_array(str)
+ if not str or str == "" then
+ return { }
+ else
+ return pattern:match(str)
+ end
+end
+
+local function set(t,v)
+ t[#t+1] = v
+end
+
+local value = lpeg.P(lpeg.Carg(1)*value) / set
+local pattern = value*(seperator*value)^0 * lpeg.Carg(1)
+
+function aux.add_settings_to_array(t,str)
+ return pattern:match(str, nil, t)
+end
+
+function aux.hash_to_string(h,separator,yes,no,strict,omit)
+ if h then
+ local t, s = { }, table.sortedkeys(h)
+ omit = omit and table.tohash(omit)
+ for i=1,#s do
+ local key = s[i]
+ if not omit or not omit[key] then
+ local value = h[key]
+ if type(value) == "boolean" then
+ if yes and no then
+ if value then
+ t[#t+1] = key .. '=' .. yes
+ elseif not strict then
+ t[#t+1] = key .. '=' .. no
+ end
+ elseif value or not strict then
+ t[#t+1] = key .. '=' .. tostring(value)
+ end
+ else
+ t[#t+1] = key .. '=' .. value
+ end
+ end
+ end
+ return concat(t,separator or ",")
+ else
+ return ""
+ end
+end
+
+function aux.array_to_string(a,separator)
+ if a then
+ return concat(a,separator or ",")
+ else
+ return ""
+ end
+end
+
+function aux.settings_to_set(str,t)
+ t = t or { }
+ for s in gmatch(str,"%s*([^,]+)") do
+ t[s] = true
+ end
+ return t
+end
+
+-- temporary here
+
+function aux.getparameters(self,class,parentclass,settings)
+ local sc = self[class]
+ if not sc then
+ sc = table.clone(self[parent])
+ self[class] = sc
+ end
+ aux.add_settings_to_array(sc, settings)
+end
+
+-- temporary here
+
+local digit = lpeg.R("09")
+local period = lpeg.P(".")
+local zero = lpeg.P("0")
+
+--~ local finish = lpeg.P(-1)
+--~ local nodigit = (1-digit) + finish
+--~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000
+--~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100
+
+local trailingzeros = zero^0 * -digit -- suggested by Roberto R
+local case_1 = period * trailingzeros / ""
+local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "")
+
+local number = digit^1 * (case_1 + case_2)
+local stripper = lpeg.Cs((number + 1)^0)
+
+--~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100"
+--~ collectgarbage("collect")
+--~ str = string.rep(sample,10000)
+--~ local ts = os.clock()
+--~ stripper:match(str)
+--~ print(#str, os.clock()-ts, stripper:match(sample))
+
+function aux.strip_zeros(str)
+ return stripper:match(str)
+end
+
+function aux.definetable(target) -- defines undefined tables
+ local composed, t = nil, { }
+ for name in gmatch(target,"([^%.]+)") do
+ if composed then
+ composed = composed .. "." .. name
+ else
+ composed = name
+ end
+ t[#t+1] = format("%s = %s or { }",composed,composed)
+ end
+ return concat(t,"\n")
+end
+
+function aux.accesstable(target)
+ local t = _G
+ for name in gmatch(target,"([^%.]+)") do
+ t = t[name]
+ end
+ return t
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
if not modules then modules = { } end modules ['trac-tra'] = {
version = 1.001,
comment = "companion to luat-lib.tex",
@@ -3012,7 +3281,11 @@ trackers = trackers or { }
local data, done = { }, { }
local function set(what,value)
- for w in gmatch(lower(what),"[^, ]+") do
+ if type(what) == "string" then
+ what = aux.settings_to_array(what)
+ end
+ for i=1,#what do
+ local w = what[i]
for d, f in next, data do
if done[d] then
-- prevent recursion due to wildcards
@@ -3391,27 +3664,34 @@ statistics.threshold = 0.05
local clock = os.gettimeofday or os.clock
+local notimer
+
function statistics.hastimer(instance)
return instance and instance.starttime
end
function statistics.starttiming(instance)
- if instance then
- local it = instance.timing
- if not it then
- it = 0
- end
- if it == 0 then
- instance.starttime = clock()
- if not instance.loadtime then
- instance.loadtime = 0
- end
+ if not instance then
+ notimer = { }
+ instance = notimer
+ end
+ local it = instance.timing
+ if not it then
+ it = 0
+ end
+ if it == 0 then
+ instance.starttime = clock()
+ if not instance.loadtime then
+ instance.loadtime = 0
end
- instance.timing = it + 1
end
+ instance.timing = it + 1
end
function statistics.stoptiming(instance, report)
+ if not instance then
+ instance = notimer
+ end
if instance then
local it = instance.timing
if it > 1 then
@@ -3435,10 +3715,16 @@ function statistics.stoptiming(instance, report)
end
function statistics.elapsedtime(instance)
+ if not instance then
+ instance = notimer
+ end
return format("%0.3f",(instance and instance.loadtime) or 0)
end
function statistics.elapsedindeed(instance)
+ if not instance then
+ instance = notimer
+ end
local t = (instance and instance.loadtime) or 0
return t > statistics.threshold
end
@@ -3479,6 +3765,7 @@ function statistics.show(reporter)
reporter(s[1],r,n)
end
end
+ texio.write_nl("") -- final newline
statistics.enable = false
end
end
@@ -3536,6 +3823,7 @@ if not modules then modules = { } end modules ['luat-log'] = {
-- this is old code that needs an overhaul
local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format
+local texcount = tex and tex.count
if texlua then
write_nl = print
@@ -3615,10 +3903,8 @@ function logs.tex.line(fmt,...) -- new
end
end
-local texcount = tex and tex.count
-
function logs.tex.start_page_number()
- local real, user, sub = texcount[0], texcount[1], texcount[2]
+ local real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
if real > 0 then
if user > 0 then
if sub > 0 then
@@ -3673,7 +3959,7 @@ function logs.xml.stop_run()
end
function logs.xml.start_page_number()
- write_nl(format("<p real='%s' page='%s' sub='%s'", texcount[0], texcount[1], texcount[2]))
+ write_nl(format("<p real='%s' page='%s' sub='%s'", texcount.realpageno, texcount.userpageno, texcount.subpageno))
end
function logs.xml.stop_page_number()
@@ -3908,7 +4194,7 @@ formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' }
formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' }
formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' }
formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' }
-formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc' }
+formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' }
formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' }
formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' }
@@ -3930,6 +4216,7 @@ alternatives['fea files'] = 'fea'
alternatives['opentype fonts'] = 'otf'
alternatives['truetype fonts'] = 'ttf'
alternatives['truetype collections'] = 'ttc'
+alternatives['truetype dictionary'] = 'dfont'
alternatives['type1 fonts'] = 'pfb'
-- obscure ones
@@ -4046,12 +4333,12 @@ local function reset_hashes()
end
local function check_configuration() -- not yet ok, no time for debugging now
- local ie = instance.environment
+ local ie, iv = instance.environment, instance.variables
local function fix(varname,default)
local proname = varname .. "." .. instance.progname or "crap"
- local p, v = ie[proname], ie[varname]
+ local p, v = ie[proname], ie[varname] or iv[varname]
if not ((p and p ~= "") or (v and v ~= "")) then
- instance.variables[varname] = default -- or environment?
+ iv[varname] = default -- or environment?
end
end
local name = os.name
@@ -5890,10 +6177,6 @@ caches.paths = caches.paths or nil
caches.force = false
caches.defaults = { "TEXMFCACHE", "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
-function caches.cleanname(name)
- return (gsub(lower(name),"[^%w%d]+","-"))
-end
-
function caches.temp()
local cachepath = nil
local function check(list,isenv)
@@ -5990,7 +6273,9 @@ function caches.loaddata(path,name)
local tmaname, tmcname = caches.setluanames(path,name)
local loader = loadfile(tmcname) or loadfile(tmaname)
if loader then
- return loader()
+ loader = loader()
+ collectgarbage("step")
+ return loader
else
return false
end
@@ -6132,7 +6417,7 @@ function containers.define(category, subcategory, version, enabled)
enabled = enabled,
version = version or 1.000,
trace = false,
- path = caches and caches.setpath(category,subcategory),
+ path = caches and caches.setpath and caches.setpath(category,subcategory),
}
c[subcategory] = s
end
@@ -6191,6 +6476,10 @@ function containers.content(container,name)
return container.storage[name]
end
+function containers.cleanname(name)
+ return (gsub(lower(name),"[^%w%d]+","-"))
+end
+
end -- of closure
@@ -6585,6 +6874,7 @@ own.libs = { -- todo: check which ones are really needed
'l-unicode.lua',
'l-math.lua',
'l-utils.lua',
+ 'l-aux.lua',
'trac-tra.lua',
'luat-env.lua',
'trac-inf.lua',
diff --git a/scripts/context/stubs/mswin/mtxrun.lua b/scripts/context/stubs/mswin/mtxrun.lua
index aba22a16e..82d1edecb 100644
--- a/scripts/context/stubs/mswin/mtxrun.lua
+++ b/scripts/context/stubs/mswin/mtxrun.lua
@@ -421,6 +421,10 @@ function table.strip(tab)
return lst
end
+local function compare(a,b)
+ return (tostring(a) < tostring(b))
+end
+
local function sortedkeys(tab)
local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in next, tab do
@@ -441,7 +445,7 @@ local function sortedkeys(tab)
end
end
if kind == 0 or kind == 3 then
- sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
+ sort(srt,compare)
else
sort(srt)
end
@@ -1072,7 +1076,7 @@ function table.insert_after_value(t,value,str)
end
local function are_equal(a,b,n,m) -- indexed
- if #a == #b then
+ if a and b and #a == #b then
n = n or 1
m = m or #a
for i=n,m do
@@ -1229,6 +1233,7 @@ end
function io.loaddata(filename,textmode)
local f = io.open(filename,(textmode and 'r') or 'rb')
if f then
+ -- collectgarbage("step") -- sometimes makes a big difference in mem consumption
local data = f:read('*all')
-- garbagecollector.check(data)
f:close()
@@ -1465,6 +1470,7 @@ set = set or { }
local nums = { }
local tabs = { }
local concat = table.concat
+local next, type = next, type
set.create = table.tohash
@@ -1472,17 +1478,19 @@ function set.tonumber(t)
if next(t) then
local s = ""
-- we could save mem by sorting, but it slows down
- for k, v in pairs(t) do
+ for k, v in next, t do
if v then
-- why bother about the leading space
s = s .. " " .. k
end
end
- if not nums[s] then
- tabs[#tabs+1] = t
- nums[s] = #tabs
+ local n = nums[s]
+ if not n then
+ n = #tabs + 1
+ tabs[n] = t
+ nums[s] = n
end
- return nums[s]
+ return n
else
return 0
end
@@ -1496,6 +1504,20 @@ function set.totable(n)
end
end
+function set.tolist(n)
+ if n == 0 or not tabs[n] then
+ return ""
+ else
+ local t = { }
+ for k, v in next, tabs[n] do
+ if v then
+ t[#t+1] = k
+ end
+ end
+ return concat(t," ")
+ end
+end
+
function set.contains(n,s)
if type(n) == "table" then
return n[s]
@@ -2600,6 +2622,235 @@ end -- of closure
do -- create closure to overcome 200 locals limit
+if not modules then modules = { } end modules ['l-aux'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+aux = aux or { }
+
+local concat, format, gmatch = table.concat, string.format, string.gmatch
+local tostring, type = tostring, type
+
+local space = lpeg.P(' ')
+local equal = lpeg.P("=")
+local comma = lpeg.P(",")
+local lbrace = lpeg.P("{")
+local rbrace = lpeg.P("}")
+local nobrace = 1 - (lbrace+rbrace)
+local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace }
+local spaces = space^0
+
+local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
+
+local key = lpeg.C((1-equal-comma)^1)
+local pattern_a = (space+comma)^0 * (key * equal * value + key * lpeg.C(""))
+local pattern_c = (space+comma)^0 * (key * equal * value)
+
+local key = lpeg.C((1-space-equal-comma)^1)
+local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + lpeg.C("")))
+
+-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored
+
+local hash = { }
+
+local function set(key,value) -- using Carg is slower here
+ hash[key] = value
+end
+
+local pattern_a_s = (pattern_a/set)^1
+local pattern_b_s = (pattern_b/set)^1
+local pattern_c_s = (pattern_c/set)^1
+
+aux.settings_to_hash_pattern_a = pattern_a_s
+aux.settings_to_hash_pattern_b = pattern_b_s
+aux.settings_to_hash_pattern_c = pattern_c_s
+
+function aux.make_settings_to_hash_pattern(set,how)
+ if how == "strict" then
+ return (pattern_c/set)^1
+ elseif how == "tolerant" then
+ return (pattern_b/set)^1
+ else
+ return (pattern_a/set)^1
+ end
+end
+
+function aux.settings_to_hash(str)
+ if str and str ~= "" then
+ hash = { }
+ if moretolerant then
+ pattern_b_s:match(str)
+ else
+ pattern_a_s:match(str)
+ end
+ return hash
+ else
+ return { }
+ end
+end
+
+function aux.settings_to_hash_tolerant(str)
+ if str and str ~= "" then
+ hash = { }
+ pattern_b_s:match(str)
+ return hash
+ else
+ return { }
+ end
+end
+
+function aux.settings_to_hash_strict(str)
+ if str and str ~= "" then
+ hash = { }
+ pattern_c_s:match(str)
+ return next(hash) and hash
+ else
+ return nil
+ end
+end
+
+local seperator = comma * space^0
+local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
+local pattern = lpeg.Ct(value*(seperator*value)^0)
+
+-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
+
+aux.settings_to_array_pattern = pattern
+
+function aux.settings_to_array(str)
+ if not str or str == "" then
+ return { }
+ else
+ return pattern:match(str)
+ end
+end
+
+local function set(t,v)
+ t[#t+1] = v
+end
+
+local value = lpeg.P(lpeg.Carg(1)*value) / set
+local pattern = value*(seperator*value)^0 * lpeg.Carg(1)
+
+function aux.add_settings_to_array(t,str)
+ return pattern:match(str, nil, t)
+end
+
+function aux.hash_to_string(h,separator,yes,no,strict,omit)
+ if h then
+ local t, s = { }, table.sortedkeys(h)
+ omit = omit and table.tohash(omit)
+ for i=1,#s do
+ local key = s[i]
+ if not omit or not omit[key] then
+ local value = h[key]
+ if type(value) == "boolean" then
+ if yes and no then
+ if value then
+ t[#t+1] = key .. '=' .. yes
+ elseif not strict then
+ t[#t+1] = key .. '=' .. no
+ end
+ elseif value or not strict then
+ t[#t+1] = key .. '=' .. tostring(value)
+ end
+ else
+ t[#t+1] = key .. '=' .. value
+ end
+ end
+ end
+ return concat(t,separator or ",")
+ else
+ return ""
+ end
+end
+
+function aux.array_to_string(a,separator)
+ if a then
+ return concat(a,separator or ",")
+ else
+ return ""
+ end
+end
+
+function aux.settings_to_set(str,t)
+ t = t or { }
+ for s in gmatch(str,"%s*([^,]+)") do
+ t[s] = true
+ end
+ return t
+end
+
+-- temporary here
+
+function aux.getparameters(self,class,parentclass,settings)
+ local sc = self[class]
+ if not sc then
+ sc = table.clone(self[parent])
+ self[class] = sc
+ end
+ aux.add_settings_to_array(sc, settings)
+end
+
+-- temporary here
+
+local digit = lpeg.R("09")
+local period = lpeg.P(".")
+local zero = lpeg.P("0")
+
+--~ local finish = lpeg.P(-1)
+--~ local nodigit = (1-digit) + finish
+--~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000
+--~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100
+
+local trailingzeros = zero^0 * -digit -- suggested by Roberto R
+local case_1 = period * trailingzeros / ""
+local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "")
+
+local number = digit^1 * (case_1 + case_2)
+local stripper = lpeg.Cs((number + 1)^0)
+
+--~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100"
+--~ collectgarbage("collect")
+--~ str = string.rep(sample,10000)
+--~ local ts = os.clock()
+--~ stripper:match(str)
+--~ print(#str, os.clock()-ts, stripper:match(sample))
+
+function aux.strip_zeros(str)
+ return stripper:match(str)
+end
+
+function aux.definetable(target) -- defines undefined tables
+ local composed, t = nil, { }
+ for name in gmatch(target,"([^%.]+)") do
+ if composed then
+ composed = composed .. "." .. name
+ else
+ composed = name
+ end
+ t[#t+1] = format("%s = %s or { }",composed,composed)
+ end
+ return concat(t,"\n")
+end
+
+function aux.accesstable(target)
+ local t = _G
+ for name in gmatch(target,"([^%.]+)") do
+ t = t[name]
+ end
+ return t
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
if not modules then modules = { } end modules ['lxml-tab'] = {
version = 1.001,
comment = "this module is the basis for the lxml-* ones",
@@ -3047,7 +3298,7 @@ generic table copier. Since we know what we're dealing with we
can speed up things a bit. The second argument is not to be used!</p>
--ldx]]--
-function copy(old,tables)
+local function copy(old,tables)
if old then
tables = tables or { }
local new = { }
@@ -3270,7 +3521,7 @@ function xml.tostring(root) -- 25% overhead due to collecting
return root
elseif next(root) then -- next is faster than type (and >0 test)
local result = { }
- serialize(root,function(s) result[#result+1] = s end)
+ serialize(root,function(s) result[#result+1] = s end) -- brrr, slow (direct printing is faster)
return concat(result,"")
end
end
@@ -5333,7 +5584,11 @@ trackers = trackers or { }
local data, done = { }, { }
local function set(what,value)
- for w in gmatch(lower(what),"[^, ]+") do
+ if type(what) == "string" then
+ what = aux.settings_to_array(what)
+ end
+ for i=1,#what do
+ local w = what[i]
for d, f in next, data do
if done[d] then
-- prevent recursion due to wildcards
@@ -5712,27 +5967,34 @@ statistics.threshold = 0.05
local clock = os.gettimeofday or os.clock
+local notimer
+
function statistics.hastimer(instance)
return instance and instance.starttime
end
function statistics.starttiming(instance)
- if instance then
- local it = instance.timing
- if not it then
- it = 0
- end
- if it == 0 then
- instance.starttime = clock()
- if not instance.loadtime then
- instance.loadtime = 0
- end
+ if not instance then
+ notimer = { }
+ instance = notimer
+ end
+ local it = instance.timing
+ if not it then
+ it = 0
+ end
+ if it == 0 then
+ instance.starttime = clock()
+ if not instance.loadtime then
+ instance.loadtime = 0
end
- instance.timing = it + 1
end
+ instance.timing = it + 1
end
function statistics.stoptiming(instance, report)
+ if not instance then
+ instance = notimer
+ end
if instance then
local it = instance.timing
if it > 1 then
@@ -5756,10 +6018,16 @@ function statistics.stoptiming(instance, report)
end
function statistics.elapsedtime(instance)
+ if not instance then
+ instance = notimer
+ end
return format("%0.3f",(instance and instance.loadtime) or 0)
end
function statistics.elapsedindeed(instance)
+ if not instance then
+ instance = notimer
+ end
local t = (instance and instance.loadtime) or 0
return t > statistics.threshold
end
@@ -5800,6 +6068,7 @@ function statistics.show(reporter)
reporter(s[1],r,n)
end
end
+ texio.write_nl("") -- final newline
statistics.enable = false
end
end
@@ -5857,6 +6126,7 @@ if not modules then modules = { } end modules ['luat-log'] = {
-- this is old code that needs an overhaul
local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format
+local texcount = tex and tex.count
if texlua then
write_nl = print
@@ -5936,10 +6206,8 @@ function logs.tex.line(fmt,...) -- new
end
end
-local texcount = tex and tex.count
-
function logs.tex.start_page_number()
- local real, user, sub = texcount[0], texcount[1], texcount[2]
+ local real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
if real > 0 then
if user > 0 then
if sub > 0 then
@@ -5994,7 +6262,7 @@ function logs.xml.stop_run()
end
function logs.xml.start_page_number()
- write_nl(format("<p real='%s' page='%s' sub='%s'", texcount[0], texcount[1], texcount[2]))
+ write_nl(format("<p real='%s' page='%s' sub='%s'", texcount.realpageno, texcount.userpageno, texcount.subpageno))
end
function logs.xml.stop_page_number()
@@ -6229,7 +6497,7 @@ formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' }
formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' }
formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' }
formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' }
-formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc' }
+formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' }
formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' }
formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' }
@@ -6251,6 +6519,7 @@ alternatives['fea files'] = 'fea'
alternatives['opentype fonts'] = 'otf'
alternatives['truetype fonts'] = 'ttf'
alternatives['truetype collections'] = 'ttc'
+alternatives['truetype dictionary'] = 'dfont'
alternatives['type1 fonts'] = 'pfb'
-- obscure ones
@@ -6367,12 +6636,12 @@ local function reset_hashes()
end
local function check_configuration() -- not yet ok, no time for debugging now
- local ie = instance.environment
+ local ie, iv = instance.environment, instance.variables
local function fix(varname,default)
local proname = varname .. "." .. instance.progname or "crap"
- local p, v = ie[proname], ie[varname]
+ local p, v = ie[proname], ie[varname] or iv[varname]
if not ((p and p ~= "") or (v and v ~= "")) then
- instance.variables[varname] = default -- or environment?
+ iv[varname] = default -- or environment?
end
end
local name = os.name
@@ -8307,7 +8576,9 @@ function caches.loaddata(path,name)
local tmaname, tmcname = caches.setluanames(path,name)
local loader = loadfile(tmcname) or loadfile(tmaname)
if loader then
- return loader()
+ loader = loader()
+ collectgarbage("step")
+ return loader
else
return false
end
@@ -9517,6 +9788,7 @@ own.libs = { -- todo: check which ones are really needed
-- 'l-unicode.lua',
-- 'l-tex.lua',
'l-utils.lua',
+ 'l-aux.lua',
-- 'l-xml.lua',
'lxml-tab.lua',
'lxml-pth.lua',
diff --git a/scripts/context/stubs/unix/luatools b/scripts/context/stubs/unix/luatools
index f0fcd517d..433d1b8dc 100755
--- a/scripts/context/stubs/unix/luatools
+++ b/scripts/context/stubs/unix/luatools
@@ -265,6 +265,11 @@ function string.tabtospace(str,tab)
return str
end
+function string:compactlong() -- strips newlines and leading spaces
+ self = gsub(self,"[\n\r]+ *","")
+ self = gsub(self,"^ *","")
+ return self
+end
end -- of closure
@@ -407,6 +412,10 @@ function table.strip(tab)
return lst
end
+local function compare(a,b)
+ return (tostring(a) < tostring(b))
+end
+
local function sortedkeys(tab)
local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in next, tab do
@@ -427,7 +436,7 @@ local function sortedkeys(tab)
end
end
if kind == 0 or kind == 3 then
- sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
+ sort(srt,compare)
else
sort(srt)
end
@@ -1058,7 +1067,7 @@ function table.insert_after_value(t,value,str)
end
local function are_equal(a,b,n,m) -- indexed
- if #a == #b then
+ if a and b and #a == #b then
n = n or 1
m = m or #a
for i=n,m do
@@ -1215,6 +1224,7 @@ end
function io.loaddata(filename,textmode)
local f = io.open(filename,(textmode and 'r') or 'rb')
if f then
+ -- collectgarbage("step") -- sometimes makes a big difference in mem consumption
local data = f:read('*all')
-- garbagecollector.check(data)
f:close()
@@ -1451,6 +1461,7 @@ set = set or { }
local nums = { }
local tabs = { }
local concat = table.concat
+local next, type = next, type
set.create = table.tohash
@@ -1458,17 +1469,19 @@ function set.tonumber(t)
if next(t) then
local s = ""
-- we could save mem by sorting, but it slows down
- for k, v in pairs(t) do
+ for k, v in next, t do
if v then
-- why bother about the leading space
s = s .. " " .. k
end
end
- if not nums[s] then
- tabs[#tabs+1] = t
- nums[s] = #tabs
+ local n = nums[s]
+ if not n then
+ n = #tabs + 1
+ tabs[n] = t
+ nums[s] = n
end
- return nums[s]
+ return n
else
return 0
end
@@ -1482,6 +1495,20 @@ function set.totable(n)
end
end
+function set.tolist(n)
+ if n == 0 or not tabs[n] then
+ return ""
+ else
+ local t = { }
+ for k, v in next, tabs[n] do
+ if v then
+ t[#t+1] = k
+ end
+ end
+ return concat(t," ")
+ end
+end
+
function set.contains(n,s)
if type(n) == "table" then
return n[s]
@@ -1678,8 +1705,8 @@ function file.replacesuffix(filename, suffix)
return (gsub(filename,"%.[%a%d]+$","")) .. "." .. suffix
end
-function file.dirname(name)
- return match(name,"^(.+)[/\\].-$") or ""
+function file.dirname(name,default)
+ return match(name,"^(.+)[/\\].-$") or (default or "")
end
function file.basename(name)
@@ -1717,15 +1744,8 @@ function file.join(...)
end
function file.iswritable(name)
- local a = lfs.attributes(name)
- if a and a.permissions:sub(2,2) == "w" then
- return true
- else
- name = file.dirname(name) or "."
- if name == "" then name = "." end
- a = lfs.attributes(name)
- return a and a.permissions:sub(2,2) == "w"
- end
+ local a = lfs.attributes(name) or lfs.attributes(file.dirname(name,"."))
+ return a and a.permissions:sub(2,2) == "w"
end
function file.isreadable(name)
@@ -1893,6 +1913,26 @@ function file.is_rootbased_path(filename)
return rootbased:match(filename)
end
+local slash = lpeg.S("\\/")
+local period = lpeg.P(".")
+local drive = lpeg.C(lpeg.R("az","AZ")) * lpeg.P(":")
+local path = lpeg.C(((1-slash)^0 * slash)^0)
+local suffix = period * lpeg.C(lpeg.P(1-period)^0 * lpeg.P(-1))
+local base = lpeg.C((1-suffix)^0)
+
+local pattern = (drive + lpeg.Cc("")) * (path + lpeg.Cc("")) * (base + lpeg.Cc("")) * (suffix + lpeg.Cc(""))
+
+function file.splitname(str) -- returns drive, path, base, suffix
+ return pattern:match(str)
+end
+
+-- function test(t) for k, v in pairs(t) do print(v, "=>", file.splitname(v)) end end
+--
+-- test { "c:", "c:/aa", "c:/aa/bb", "c:/aa/bb/cc", "c:/aa/bb/cc.dd", "c:/aa/bb/cc.dd.ee" }
+-- test { "c:", "c:aa", "c:aa/bb", "c:aa/bb/cc", "c:aa/bb/cc.dd", "c:aa/bb/cc.dd.ee" }
+-- test { "/aa", "/aa/bb", "/aa/bb/cc", "/aa/bb/cc.dd", "/aa/bb/cc.dd.ee" }
+-- test { "aa", "aa/bb", "aa/bb/cc", "aa/bb/cc.dd", "aa/bb/cc.dd.ee" }
+
end -- of closure
@@ -1948,7 +1988,7 @@ function file.checksum(name)
if md5 then
local data = io.loaddata(name)
if data then
- return md5.HEXsum(data)
+ return md5.HEX(data)
end
end
return nil
@@ -2862,6 +2902,235 @@ end -- of closure
do -- create closure to overcome 200 locals limit
+if not modules then modules = { } end modules ['l-aux'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+aux = aux or { }
+
+local concat, format, gmatch = table.concat, string.format, string.gmatch
+local tostring, type = tostring, type
+
+local space = lpeg.P(' ')
+local equal = lpeg.P("=")
+local comma = lpeg.P(",")
+local lbrace = lpeg.P("{")
+local rbrace = lpeg.P("}")
+local nobrace = 1 - (lbrace+rbrace)
+local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace }
+local spaces = space^0
+
+local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
+
+local key = lpeg.C((1-equal-comma)^1)
+local pattern_a = (space+comma)^0 * (key * equal * value + key * lpeg.C(""))
+local pattern_c = (space+comma)^0 * (key * equal * value)
+
+local key = lpeg.C((1-space-equal-comma)^1)
+local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + lpeg.C("")))
+
+-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored
+
+local hash = { }
+
+local function set(key,value) -- using Carg is slower here
+ hash[key] = value
+end
+
+local pattern_a_s = (pattern_a/set)^1
+local pattern_b_s = (pattern_b/set)^1
+local pattern_c_s = (pattern_c/set)^1
+
+aux.settings_to_hash_pattern_a = pattern_a_s
+aux.settings_to_hash_pattern_b = pattern_b_s
+aux.settings_to_hash_pattern_c = pattern_c_s
+
+function aux.make_settings_to_hash_pattern(set,how)
+ if how == "strict" then
+ return (pattern_c/set)^1
+ elseif how == "tolerant" then
+ return (pattern_b/set)^1
+ else
+ return (pattern_a/set)^1
+ end
+end
+
+function aux.settings_to_hash(str)
+ if str and str ~= "" then
+ hash = { }
+ if moretolerant then
+ pattern_b_s:match(str)
+ else
+ pattern_a_s:match(str)
+ end
+ return hash
+ else
+ return { }
+ end
+end
+
+function aux.settings_to_hash_tolerant(str)
+ if str and str ~= "" then
+ hash = { }
+ pattern_b_s:match(str)
+ return hash
+ else
+ return { }
+ end
+end
+
+function aux.settings_to_hash_strict(str)
+ if str and str ~= "" then
+ hash = { }
+ pattern_c_s:match(str)
+ return next(hash) and hash
+ else
+ return nil
+ end
+end
+
+local seperator = comma * space^0
+local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
+local pattern = lpeg.Ct(value*(seperator*value)^0)
+
+-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
+
+aux.settings_to_array_pattern = pattern
+
+function aux.settings_to_array(str)
+ if not str or str == "" then
+ return { }
+ else
+ return pattern:match(str)
+ end
+end
+
+local function set(t,v)
+ t[#t+1] = v
+end
+
+local value = lpeg.P(lpeg.Carg(1)*value) / set
+local pattern = value*(seperator*value)^0 * lpeg.Carg(1)
+
+function aux.add_settings_to_array(t,str)
+ return pattern:match(str, nil, t)
+end
+
+function aux.hash_to_string(h,separator,yes,no,strict,omit)
+ if h then
+ local t, s = { }, table.sortedkeys(h)
+ omit = omit and table.tohash(omit)
+ for i=1,#s do
+ local key = s[i]
+ if not omit or not omit[key] then
+ local value = h[key]
+ if type(value) == "boolean" then
+ if yes and no then
+ if value then
+ t[#t+1] = key .. '=' .. yes
+ elseif not strict then
+ t[#t+1] = key .. '=' .. no
+ end
+ elseif value or not strict then
+ t[#t+1] = key .. '=' .. tostring(value)
+ end
+ else
+ t[#t+1] = key .. '=' .. value
+ end
+ end
+ end
+ return concat(t,separator or ",")
+ else
+ return ""
+ end
+end
+
+function aux.array_to_string(a,separator)
+ if a then
+ return concat(a,separator or ",")
+ else
+ return ""
+ end
+end
+
+function aux.settings_to_set(str,t)
+ t = t or { }
+ for s in gmatch(str,"%s*([^,]+)") do
+ t[s] = true
+ end
+ return t
+end
+
+-- temporary here
+
+function aux.getparameters(self,class,parentclass,settings)
+ local sc = self[class]
+ if not sc then
+ sc = table.clone(self[parent])
+ self[class] = sc
+ end
+ aux.add_settings_to_array(sc, settings)
+end
+
+-- temporary here
+
+local digit = lpeg.R("09")
+local period = lpeg.P(".")
+local zero = lpeg.P("0")
+
+--~ local finish = lpeg.P(-1)
+--~ local nodigit = (1-digit) + finish
+--~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000
+--~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100
+
+local trailingzeros = zero^0 * -digit -- suggested by Roberto R
+local case_1 = period * trailingzeros / ""
+local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "")
+
+local number = digit^1 * (case_1 + case_2)
+local stripper = lpeg.Cs((number + 1)^0)
+
+--~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100"
+--~ collectgarbage("collect")
+--~ str = string.rep(sample,10000)
+--~ local ts = os.clock()
+--~ stripper:match(str)
+--~ print(#str, os.clock()-ts, stripper:match(sample))
+
+function aux.strip_zeros(str)
+ return stripper:match(str)
+end
+
+function aux.definetable(target) -- defines undefined tables
+ local composed, t = nil, { }
+ for name in gmatch(target,"([^%.]+)") do
+ if composed then
+ composed = composed .. "." .. name
+ else
+ composed = name
+ end
+ t[#t+1] = format("%s = %s or { }",composed,composed)
+ end
+ return concat(t,"\n")
+end
+
+function aux.accesstable(target)
+ local t = _G
+ for name in gmatch(target,"([^%.]+)") do
+ t = t[name]
+ end
+ return t
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
if not modules then modules = { } end modules ['trac-tra'] = {
version = 1.001,
comment = "companion to luat-lib.tex",
@@ -3012,7 +3281,11 @@ trackers = trackers or { }
local data, done = { }, { }
local function set(what,value)
- for w in gmatch(lower(what),"[^, ]+") do
+ if type(what) == "string" then
+ what = aux.settings_to_array(what)
+ end
+ for i=1,#what do
+ local w = what[i]
for d, f in next, data do
if done[d] then
-- prevent recursion due to wildcards
@@ -3391,27 +3664,34 @@ statistics.threshold = 0.05
local clock = os.gettimeofday or os.clock
+local notimer
+
function statistics.hastimer(instance)
return instance and instance.starttime
end
function statistics.starttiming(instance)
- if instance then
- local it = instance.timing
- if not it then
- it = 0
- end
- if it == 0 then
- instance.starttime = clock()
- if not instance.loadtime then
- instance.loadtime = 0
- end
+ if not instance then
+ notimer = { }
+ instance = notimer
+ end
+ local it = instance.timing
+ if not it then
+ it = 0
+ end
+ if it == 0 then
+ instance.starttime = clock()
+ if not instance.loadtime then
+ instance.loadtime = 0
end
- instance.timing = it + 1
end
+ instance.timing = it + 1
end
function statistics.stoptiming(instance, report)
+ if not instance then
+ instance = notimer
+ end
if instance then
local it = instance.timing
if it > 1 then
@@ -3435,10 +3715,16 @@ function statistics.stoptiming(instance, report)
end
function statistics.elapsedtime(instance)
+ if not instance then
+ instance = notimer
+ end
return format("%0.3f",(instance and instance.loadtime) or 0)
end
function statistics.elapsedindeed(instance)
+ if not instance then
+ instance = notimer
+ end
local t = (instance and instance.loadtime) or 0
return t > statistics.threshold
end
@@ -3479,6 +3765,7 @@ function statistics.show(reporter)
reporter(s[1],r,n)
end
end
+ texio.write_nl("") -- final newline
statistics.enable = false
end
end
@@ -3536,6 +3823,7 @@ if not modules then modules = { } end modules ['luat-log'] = {
-- this is old code that needs an overhaul
local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format
+local texcount = tex and tex.count
if texlua then
write_nl = print
@@ -3615,10 +3903,8 @@ function logs.tex.line(fmt,...) -- new
end
end
-local texcount = tex and tex.count
-
function logs.tex.start_page_number()
- local real, user, sub = texcount[0], texcount[1], texcount[2]
+ local real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
if real > 0 then
if user > 0 then
if sub > 0 then
@@ -3673,7 +3959,7 @@ function logs.xml.stop_run()
end
function logs.xml.start_page_number()
- write_nl(format("<p real='%s' page='%s' sub='%s'", texcount[0], texcount[1], texcount[2]))
+ write_nl(format("<p real='%s' page='%s' sub='%s'", texcount.realpageno, texcount.userpageno, texcount.subpageno))
end
function logs.xml.stop_page_number()
@@ -3908,7 +4194,7 @@ formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' }
formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' }
formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' }
formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' }
-formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc' }
+formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' }
formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' }
formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' }
@@ -3930,6 +4216,7 @@ alternatives['fea files'] = 'fea'
alternatives['opentype fonts'] = 'otf'
alternatives['truetype fonts'] = 'ttf'
alternatives['truetype collections'] = 'ttc'
+alternatives['truetype dictionary'] = 'dfont'
alternatives['type1 fonts'] = 'pfb'
-- obscure ones
@@ -4046,12 +4333,12 @@ local function reset_hashes()
end
local function check_configuration() -- not yet ok, no time for debugging now
- local ie = instance.environment
+ local ie, iv = instance.environment, instance.variables
local function fix(varname,default)
local proname = varname .. "." .. instance.progname or "crap"
- local p, v = ie[proname], ie[varname]
+ local p, v = ie[proname], ie[varname] or iv[varname]
if not ((p and p ~= "") or (v and v ~= "")) then
- instance.variables[varname] = default -- or environment?
+ iv[varname] = default -- or environment?
end
end
local name = os.name
@@ -5890,10 +6177,6 @@ caches.paths = caches.paths or nil
caches.force = false
caches.defaults = { "TEXMFCACHE", "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
-function caches.cleanname(name)
- return (gsub(lower(name),"[^%w%d]+","-"))
-end
-
function caches.temp()
local cachepath = nil
local function check(list,isenv)
@@ -5990,7 +6273,9 @@ function caches.loaddata(path,name)
local tmaname, tmcname = caches.setluanames(path,name)
local loader = loadfile(tmcname) or loadfile(tmaname)
if loader then
- return loader()
+ loader = loader()
+ collectgarbage("step")
+ return loader
else
return false
end
@@ -6132,7 +6417,7 @@ function containers.define(category, subcategory, version, enabled)
enabled = enabled,
version = version or 1.000,
trace = false,
- path = caches and caches.setpath(category,subcategory),
+ path = caches and caches.setpath and caches.setpath(category,subcategory),
}
c[subcategory] = s
end
@@ -6191,6 +6476,10 @@ function containers.content(container,name)
return container.storage[name]
end
+function containers.cleanname(name)
+ return (gsub(lower(name),"[^%w%d]+","-"))
+end
+
end -- of closure
@@ -6585,6 +6874,7 @@ own.libs = { -- todo: check which ones are really needed
'l-unicode.lua',
'l-math.lua',
'l-utils.lua',
+ 'l-aux.lua',
'trac-tra.lua',
'luat-env.lua',
'trac-inf.lua',
diff --git a/scripts/context/stubs/unix/mtxrun b/scripts/context/stubs/unix/mtxrun
index aba22a16e..82d1edecb 100755
--- a/scripts/context/stubs/unix/mtxrun
+++ b/scripts/context/stubs/unix/mtxrun
@@ -421,6 +421,10 @@ function table.strip(tab)
return lst
end
+local function compare(a,b)
+ return (tostring(a) < tostring(b))
+end
+
local function sortedkeys(tab)
local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in next, tab do
@@ -441,7 +445,7 @@ local function sortedkeys(tab)
end
end
if kind == 0 or kind == 3 then
- sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
+ sort(srt,compare)
else
sort(srt)
end
@@ -1072,7 +1076,7 @@ function table.insert_after_value(t,value,str)
end
local function are_equal(a,b,n,m) -- indexed
- if #a == #b then
+ if a and b and #a == #b then
n = n or 1
m = m or #a
for i=n,m do
@@ -1229,6 +1233,7 @@ end
function io.loaddata(filename,textmode)
local f = io.open(filename,(textmode and 'r') or 'rb')
if f then
+ -- collectgarbage("step") -- sometimes makes a big difference in mem consumption
local data = f:read('*all')
-- garbagecollector.check(data)
f:close()
@@ -1465,6 +1470,7 @@ set = set or { }
local nums = { }
local tabs = { }
local concat = table.concat
+local next, type = next, type
set.create = table.tohash
@@ -1472,17 +1478,19 @@ function set.tonumber(t)
if next(t) then
local s = ""
-- we could save mem by sorting, but it slows down
- for k, v in pairs(t) do
+ for k, v in next, t do
if v then
-- why bother about the leading space
s = s .. " " .. k
end
end
- if not nums[s] then
- tabs[#tabs+1] = t
- nums[s] = #tabs
+ local n = nums[s]
+ if not n then
+ n = #tabs + 1
+ tabs[n] = t
+ nums[s] = n
end
- return nums[s]
+ return n
else
return 0
end
@@ -1496,6 +1504,20 @@ function set.totable(n)
end
end
+function set.tolist(n)
+ if n == 0 or not tabs[n] then
+ return ""
+ else
+ local t = { }
+ for k, v in next, tabs[n] do
+ if v then
+ t[#t+1] = k
+ end
+ end
+ return concat(t," ")
+ end
+end
+
function set.contains(n,s)
if type(n) == "table" then
return n[s]
@@ -2600,6 +2622,235 @@ end -- of closure
do -- create closure to overcome 200 locals limit
+if not modules then modules = { } end modules ['l-aux'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.tex",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+aux = aux or { }
+
+local concat, format, gmatch = table.concat, string.format, string.gmatch
+local tostring, type = tostring, type
+
+local space = lpeg.P(' ')
+local equal = lpeg.P("=")
+local comma = lpeg.P(",")
+local lbrace = lpeg.P("{")
+local rbrace = lpeg.P("}")
+local nobrace = 1 - (lbrace+rbrace)
+local nested = lpeg.P{ lbrace * (nobrace + lpeg.V(1))^0 * rbrace }
+local spaces = space^0
+
+local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
+
+local key = lpeg.C((1-equal-comma)^1)
+local pattern_a = (space+comma)^0 * (key * equal * value + key * lpeg.C(""))
+local pattern_c = (space+comma)^0 * (key * equal * value)
+
+local key = lpeg.C((1-space-equal-comma)^1)
+local pattern_b = spaces * comma^0 * spaces * (key * ((spaces * equal * spaces * value) + lpeg.C("")))
+
+-- "a=1, b=2, c=3, d={a{b,c}d}, e=12345, f=xx{a{b,c}d}xx, g={}" : outer {} removes, leading spaces ignored
+
+local hash = { }
+
+local function set(key,value) -- using Carg is slower here
+ hash[key] = value
+end
+
+local pattern_a_s = (pattern_a/set)^1
+local pattern_b_s = (pattern_b/set)^1
+local pattern_c_s = (pattern_c/set)^1
+
+aux.settings_to_hash_pattern_a = pattern_a_s
+aux.settings_to_hash_pattern_b = pattern_b_s
+aux.settings_to_hash_pattern_c = pattern_c_s
+
+function aux.make_settings_to_hash_pattern(set,how)
+ if how == "strict" then
+ return (pattern_c/set)^1
+ elseif how == "tolerant" then
+ return (pattern_b/set)^1
+ else
+ return (pattern_a/set)^1
+ end
+end
+
+function aux.settings_to_hash(str)
+ if str and str ~= "" then
+ hash = { }
+ if moretolerant then
+ pattern_b_s:match(str)
+ else
+ pattern_a_s:match(str)
+ end
+ return hash
+ else
+ return { }
+ end
+end
+
+function aux.settings_to_hash_tolerant(str)
+ if str and str ~= "" then
+ hash = { }
+ pattern_b_s:match(str)
+ return hash
+ else
+ return { }
+ end
+end
+
+function aux.settings_to_hash_strict(str)
+ if str and str ~= "" then
+ hash = { }
+ pattern_c_s:match(str)
+ return next(hash) and hash
+ else
+ return nil
+ end
+end
+
+local seperator = comma * space^0
+local value = lpeg.P(lbrace * lpeg.C((nobrace + nested)^0) * rbrace) + lpeg.C((nested + (1-comma))^0)
+local pattern = lpeg.Ct(value*(seperator*value)^0)
+
+-- "aap, {noot}, mies" : outer {} removes, leading spaces ignored
+
+aux.settings_to_array_pattern = pattern
+
+function aux.settings_to_array(str)
+ if not str or str == "" then
+ return { }
+ else
+ return pattern:match(str)
+ end
+end
+
+local function set(t,v)
+ t[#t+1] = v
+end
+
+local value = lpeg.P(lpeg.Carg(1)*value) / set
+local pattern = value*(seperator*value)^0 * lpeg.Carg(1)
+
+function aux.add_settings_to_array(t,str)
+ return pattern:match(str, nil, t)
+end
+
+function aux.hash_to_string(h,separator,yes,no,strict,omit)
+ if h then
+ local t, s = { }, table.sortedkeys(h)
+ omit = omit and table.tohash(omit)
+ for i=1,#s do
+ local key = s[i]
+ if not omit or not omit[key] then
+ local value = h[key]
+ if type(value) == "boolean" then
+ if yes and no then
+ if value then
+ t[#t+1] = key .. '=' .. yes
+ elseif not strict then
+ t[#t+1] = key .. '=' .. no
+ end
+ elseif value or not strict then
+ t[#t+1] = key .. '=' .. tostring(value)
+ end
+ else
+ t[#t+1] = key .. '=' .. value
+ end
+ end
+ end
+ return concat(t,separator or ",")
+ else
+ return ""
+ end
+end
+
+function aux.array_to_string(a,separator)
+ if a then
+ return concat(a,separator or ",")
+ else
+ return ""
+ end
+end
+
+function aux.settings_to_set(str,t)
+ t = t or { }
+ for s in gmatch(str,"%s*([^,]+)") do
+ t[s] = true
+ end
+ return t
+end
+
+-- temporary here
+
+function aux.getparameters(self,class,parentclass,settings)
+ local sc = self[class]
+ if not sc then
+ sc = table.clone(self[parent])
+ self[class] = sc
+ end
+ aux.add_settings_to_array(sc, settings)
+end
+
+-- temporary here
+
+local digit = lpeg.R("09")
+local period = lpeg.P(".")
+local zero = lpeg.P("0")
+
+--~ local finish = lpeg.P(-1)
+--~ local nodigit = (1-digit) + finish
+--~ local case_1 = (period * zero^1 * #nodigit)/"" -- .000
+--~ local case_2 = (period * (1-(zero^0/"") * #nodigit)^1 * (zero^0/"") * nodigit) -- .010 .10 .100100
+
+local trailingzeros = zero^0 * -digit -- suggested by Roberto R
+local case_1 = period * trailingzeros / ""
+local case_2 = period * (digit - trailingzeros)^1 * (trailingzeros / "")
+
+local number = digit^1 * (case_1 + case_2)
+local stripper = lpeg.Cs((number + 1)^0)
+
+--~ local sample = "bla 11.00 bla 11 bla 0.1100 bla 1.00100 bla 0.00 bla 0.001 bla 1.1100 bla 0.100100100 bla 0.00100100100"
+--~ collectgarbage("collect")
+--~ str = string.rep(sample,10000)
+--~ local ts = os.clock()
+--~ stripper:match(str)
+--~ print(#str, os.clock()-ts, stripper:match(sample))
+
+function aux.strip_zeros(str)
+ return stripper:match(str)
+end
+
+function aux.definetable(target) -- defines undefined tables
+ local composed, t = nil, { }
+ for name in gmatch(target,"([^%.]+)") do
+ if composed then
+ composed = composed .. "." .. name
+ else
+ composed = name
+ end
+ t[#t+1] = format("%s = %s or { }",composed,composed)
+ end
+ return concat(t,"\n")
+end
+
+function aux.accesstable(target)
+ local t = _G
+ for name in gmatch(target,"([^%.]+)") do
+ t = t[name]
+ end
+ return t
+end
+
+
+end -- of closure
+
+do -- create closure to overcome 200 locals limit
+
if not modules then modules = { } end modules ['lxml-tab'] = {
version = 1.001,
comment = "this module is the basis for the lxml-* ones",
@@ -3047,7 +3298,7 @@ generic table copier. Since we know what we're dealing with we
can speed up things a bit. The second argument is not to be used!</p>
--ldx]]--
-function copy(old,tables)
+local function copy(old,tables)
if old then
tables = tables or { }
local new = { }
@@ -3270,7 +3521,7 @@ function xml.tostring(root) -- 25% overhead due to collecting
return root
elseif next(root) then -- next is faster than type (and >0 test)
local result = { }
- serialize(root,function(s) result[#result+1] = s end)
+ serialize(root,function(s) result[#result+1] = s end) -- brrr, slow (direct printing is faster)
return concat(result,"")
end
end
@@ -5333,7 +5584,11 @@ trackers = trackers or { }
local data, done = { }, { }
local function set(what,value)
- for w in gmatch(lower(what),"[^, ]+") do
+ if type(what) == "string" then
+ what = aux.settings_to_array(what)
+ end
+ for i=1,#what do
+ local w = what[i]
for d, f in next, data do
if done[d] then
-- prevent recursion due to wildcards
@@ -5712,27 +5967,34 @@ statistics.threshold = 0.05
local clock = os.gettimeofday or os.clock
+local notimer
+
function statistics.hastimer(instance)
return instance and instance.starttime
end
function statistics.starttiming(instance)
- if instance then
- local it = instance.timing
- if not it then
- it = 0
- end
- if it == 0 then
- instance.starttime = clock()
- if not instance.loadtime then
- instance.loadtime = 0
- end
+ if not instance then
+ notimer = { }
+ instance = notimer
+ end
+ local it = instance.timing
+ if not it then
+ it = 0
+ end
+ if it == 0 then
+ instance.starttime = clock()
+ if not instance.loadtime then
+ instance.loadtime = 0
end
- instance.timing = it + 1
end
+ instance.timing = it + 1
end
function statistics.stoptiming(instance, report)
+ if not instance then
+ instance = notimer
+ end
if instance then
local it = instance.timing
if it > 1 then
@@ -5756,10 +6018,16 @@ function statistics.stoptiming(instance, report)
end
function statistics.elapsedtime(instance)
+ if not instance then
+ instance = notimer
+ end
return format("%0.3f",(instance and instance.loadtime) or 0)
end
function statistics.elapsedindeed(instance)
+ if not instance then
+ instance = notimer
+ end
local t = (instance and instance.loadtime) or 0
return t > statistics.threshold
end
@@ -5800,6 +6068,7 @@ function statistics.show(reporter)
reporter(s[1],r,n)
end
end
+ texio.write_nl("") -- final newline
statistics.enable = false
end
end
@@ -5857,6 +6126,7 @@ if not modules then modules = { } end modules ['luat-log'] = {
-- this is old code that needs an overhaul
local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format
+local texcount = tex and tex.count
if texlua then
write_nl = print
@@ -5936,10 +6206,8 @@ function logs.tex.line(fmt,...) -- new
end
end
-local texcount = tex and tex.count
-
function logs.tex.start_page_number()
- local real, user, sub = texcount[0], texcount[1], texcount[2]
+ local real, user, sub = texcount.realpageno, texcount.userpageno, texcount.subpageno
if real > 0 then
if user > 0 then
if sub > 0 then
@@ -5994,7 +6262,7 @@ function logs.xml.stop_run()
end
function logs.xml.start_page_number()
- write_nl(format("<p real='%s' page='%s' sub='%s'", texcount[0], texcount[1], texcount[2]))
+ write_nl(format("<p real='%s' page='%s' sub='%s'", texcount.realpageno, texcount.userpageno, texcount.subpageno))
end
function logs.xml.stop_page_number()
@@ -6229,7 +6497,7 @@ formats['ovf'] = 'OVFFONTS' suffixes['ovf'] = { 'ovf', 'vf' }
formats['ovp'] = 'OVPFONTS' suffixes['ovp'] = { 'ovp' }
formats['tex'] = 'TEXINPUTS' suffixes['tex'] = { 'tex' }
formats['tfm'] = 'TFMFONTS' suffixes['tfm'] = { 'tfm' }
-formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc' }
+formats['ttf'] = 'TTFONTS' suffixes['ttf'] = { 'ttf', 'ttc', 'dfont' }
formats['pfb'] = 'T1FONTS' suffixes['pfb'] = { 'pfb', 'pfa' }
formats['vf'] = 'VFFONTS' suffixes['vf'] = { 'vf' }
@@ -6251,6 +6519,7 @@ alternatives['fea files'] = 'fea'
alternatives['opentype fonts'] = 'otf'
alternatives['truetype fonts'] = 'ttf'
alternatives['truetype collections'] = 'ttc'
+alternatives['truetype dictionary'] = 'dfont'
alternatives['type1 fonts'] = 'pfb'
-- obscure ones
@@ -6367,12 +6636,12 @@ local function reset_hashes()
end
local function check_configuration() -- not yet ok, no time for debugging now
- local ie = instance.environment
+ local ie, iv = instance.environment, instance.variables
local function fix(varname,default)
local proname = varname .. "." .. instance.progname or "crap"
- local p, v = ie[proname], ie[varname]
+ local p, v = ie[proname], ie[varname] or iv[varname]
if not ((p and p ~= "") or (v and v ~= "")) then
- instance.variables[varname] = default -- or environment?
+ iv[varname] = default -- or environment?
end
end
local name = os.name
@@ -8307,7 +8576,9 @@ function caches.loaddata(path,name)
local tmaname, tmcname = caches.setluanames(path,name)
local loader = loadfile(tmcname) or loadfile(tmaname)
if loader then
- return loader()
+ loader = loader()
+ collectgarbage("step")
+ return loader
else
return false
end
@@ -9517,6 +9788,7 @@ own.libs = { -- todo: check which ones are really needed
-- 'l-unicode.lua',
-- 'l-tex.lua',
'l-utils.lua',
+ 'l-aux.lua',
-- 'l-xml.lua',
'lxml-tab.lua',
'lxml-pth.lua',
diff --git a/tex/context/base/cont-new.tex b/tex/context/base/cont-new.tex
index 1b9d7d62e..26860f811 100644
--- a/tex/context/base/cont-new.tex
+++ b/tex/context/base/cont-new.tex
@@ -11,7 +11,7 @@
%C therefore copyrighted by \PRAGMA. See mreadme.pdf for
%C details.
-\newcontextversion{2009.08.13 13:13}
+\newcontextversion{2009.08.14 10:48}
%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/context.tex b/tex/context/base/context.tex
index c7bf9cdd7..f3c5cdcc5 100644
--- a/tex/context/base/context.tex
+++ b/tex/context/base/context.tex
@@ -20,7 +20,7 @@
%D your styles an modules.
\edef\contextformat {\jobname}
-\edef\contextversion{2009.08.13 13:13}
+\edef\contextversion{2009.08.14 10:48}
%D For those who want to use this:
diff --git a/tex/context/base/core-sys.mkiv b/tex/context/base/core-sys.mkiv
index 28ef1e520..f30c8a958 100644
--- a/tex/context/base/core-sys.mkiv
+++ b/tex/context/base/core-sys.mkiv
@@ -268,6 +268,82 @@
\definecomplexorsimpleempty\define
+% \startluacode
+% local texsprint, ctxcatcodes = tex.sprint, tex.ctxcatcodes
+% local format, match, gmatch, rep = string.format, string.match, string.gmatch, string.rep
+% local empty = {
+% "single",
+% "double",
+% "triple",
+% "quadruple",
+% "quintuple",
+% }
+% local check = {
+% "first",
+% "second",
+% "third",
+% "fourth",
+% "fifth",
+% }
+% function commands.define(str)
+% -- we could store the defaults in lua and call lua instead but why bother
+% local arg, cmd = match(str,"(.*)\\(.-)$")
+% local a = { }
+% for s in gmatch(arg,"%[(.-)%]") do
+% a[#a+1] = s
+% end
+% local n = tonumber(a[#a])
+% if n then
+% a[#a] = nil
+% else
+% n = 0
+% end
+% texsprint(ctxcatcodes,format("\\unexpanded\\def\\%s",cmd))
+% if #a > 0 then
+% texsprint(ctxcatcodes,format("{\\do%sempty\\do%s}",empty[#a],cmd))
+% texsprint(ctxcatcodes,format("\\def\\do%s",cmd))
+% for i=1,#a do
+% texsprint(ctxcatcodes,"[#",i,"]")
+% end
+% texsprint(ctxcatcodes,"{")
+% for i=#a,1,-1 do
+% texsprint(ctxcatcodes,format("\\if%sargument",check[i]))
+% texsprint(ctxcatcodes,format("\\def\\next{\\dodo%s",cmd))
+% for j=1,#a-i do
+% texsprint(ctxcatcodes,format("[%s]",a[j]))
+% end
+% for j=1,i do
+% texsprint(ctxcatcodes,format("[#%s]",j))
+% end
+% texsprint(ctxcatcodes,"}")
+% if i == 1 then
+% texsprint(ctxcatcodes,rep("\\fi",#a))
+% else
+% texsprint(ctxcatcodes,"\\else")
+% end
+% end
+% texsprint(ctxcatcodes,"\\next}")
+% texsprint(ctxcatcodes,format("\\def\\dodo%s",cmd))
+% for i=1,#a do
+% texsprint(ctxcatcodes,"[#",i,"]")
+% end
+% end
+% for i=1,n do
+% texsprint(ctxcatcodes,"#",#a+i)
+% end
+% end
+% \stopluacode
+%
+% \def\define#1#{\ctxlua{commands.define([[\detokenize{#1}]])}}
+%
+% \starttext
+% \define[2]\whatevera{#1+#2}
+% \whatevera{A}{B}
+% \define[me][too][2]\whateverb{#1+#2+#3+#4}
+% \whateverb[A]{B}{C}
+% \whateverb[A][B]{C}{D}
+% \stoptext
+
\unexpanded\def\macroname#1% brrr
{\executeifdefined{#1}\empty}
diff --git a/tex/context/base/data-res.lua b/tex/context/base/data-res.lua
index da51dc64a..39e4aa208 100644
--- a/tex/context/base/data-res.lua
+++ b/tex/context/base/data-res.lua
@@ -229,12 +229,12 @@ local function reset_hashes()
end
local function check_configuration() -- not yet ok, no time for debugging now
- local ie = instance.environment
+ local ie, iv = instance.environment, instance.variables
local function fix(varname,default)
local proname = varname .. "." .. instance.progname or "crap"
- local p, v = ie[proname], ie[varname]
+ local p, v = ie[proname], ie[varname] or iv[varname]
if not ((p and p ~= "") or (v and v ~= "")) then
- instance.variables[varname] = default -- or environment?
+ iv[varname] = default -- or environment?
end
end
local name = os.name
diff --git a/tex/context/base/font-syn.lua b/tex/context/base/font-syn.lua
index 84bf7f91c..828808ec5 100644
--- a/tex/context/base/font-syn.lua
+++ b/tex/context/base/font-syn.lua
@@ -49,6 +49,8 @@ filters.ttc = fontloader.info
filters.dfont = fontloader.info
function filters.afm(name)
+ -- we could parse the afm file as well, and then report an error but
+ -- it's not worth the trouble
local pfbname = resolvers.find_file(file.removesuffix(name)..".pfb","pfb") or ""
if pfbname == "" then
pfbname = resolvers.find_file(file.removesuffix(file.basename(name))..".pfb","pfb") or ""
@@ -70,7 +72,7 @@ function filters.afm(name)
return hash
end
end
- return nil
+ return nil, "no matching pfb file"
end
function filters.pfb(name)
@@ -239,7 +241,7 @@ function names.identify(verbose) -- lsr is for kpse
logs.report("fontnames","identifying %s font %s",suffix,completename)
logs.push()
end
- local result = filters[lower(suffix)](completename)
+ local result, message = filters[lower(suffix)](completename)
if trace then
logs.pop()
end
@@ -251,6 +253,11 @@ function names.identify(verbose) -- lsr is for kpse
check(result[r],storedname,suffix,true) -- was name
end
end
+ if message and message ~= "" then
+ logs.report("fontnames","warning when identifying %s font %s: %s",suffix,completename,message)
+ end
+ else
+ logs.report("fontnames","error when identifying %s font %s: %s",suffix,completename,message or "unknown")
end
done[name] = true
end
diff --git a/tex/context/base/lpdf-mis.lua b/tex/context/base/lpdf-mis.lua
index e3ed8919d..e47da1c49 100644
--- a/tex/context/base/lpdf-mis.lua
+++ b/tex/context/base/lpdf-mis.lua
@@ -143,18 +143,20 @@ end
local function flushjavascripts()
local t = javascripts.flushpreambles()
- local a = pdfarray()
- local pdf_javascript = pdfconstant("JavaScript")
- for i=1,#t do
- local name, script = t[i][1], t[i][2]
- local j = pdfdictionary {
- S = pdf_javascript,
- JS = pdfreference(pdfimmediateobj("stream",script)),
- }
- a[#a+1] = pdfstring(name)
- a[#a+1] = pdfreference(pdfimmediateobj(tostring(j)))
- end
- lpdf.addtonames("JavaScript",pdfreference(pdfimmediateobj(tostring(pdfdictionary{ Names = a }))))
+ if #t > 0 then
+ local a = pdfarray()
+ local pdf_javascript = pdfconstant("JavaScript")
+ for i=1,#t do
+ local name, script = t[i][1], t[i][2]
+ local j = pdfdictionary {
+ S = pdf_javascript,
+ JS = pdfreference(pdfimmediateobj("stream",script)),
+ }
+ a[#a+1] = pdfstring(name)
+ a[#a+1] = pdfreference(pdfimmediateobj(tostring(j)))
+ end
+ lpdf.addtonames("JavaScript",pdfreference(pdfimmediateobj(tostring(pdfdictionary{ Names = a }))))
+ end
end
lpdf.registerdocumentfinalizer(flushjavascripts)
diff --git a/tex/context/base/node-ref.lua b/tex/context/base/node-ref.lua
index 873302d6b..85d7e869e 100644
--- a/tex/context/base/node-ref.lua
+++ b/tex/context/base/node-ref.lua
@@ -40,28 +40,33 @@ local traverse = node.traverse
local find_node_tail = node.tail or node.slide
local tosequence = nodes.tosequence
---~ local copy_list = node.copy_list
---~ local flush_list = node.flush_list
---~
---~ local function dimensions(parent,start,stop) -- so we need parent for glue_set info
---~ local n = stop.next
---~ stop.next = nil
---~ local p = hpack_list(copy_list(start))
---~ stop.next = n
---~ local w, h, d = p.width, p.height, p.depth
---~ flush_list(p)
---~ return w, h, d
---~ end
-
-local function dimensions(parent,start,stop) -- so we need parent for glue_set info
+local function dimensions(parent,start,stop)
stop = stop and stop.next
- if stop then
- return list_dimensions(start,stop)
+ if parent then
+ if stop then
+ return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start,stop)
+ else
+ return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start)
+ end
else
- return list_dimensions(start)
+ if stop then
+ return list_dimensions(start,stop)
+ else
+ return list_dimensions(start)
+ end
end
end
+--~ more compact
+--~
+--~ local function dimensions(parent,start,stop)
+--~ if parent then
+--~ return list_dimensions(parent.glue_set,parent.glue_sign,parent.glue_order,start,stop and stop.next)
+--~ else
+--~ return list_dimensions(start,stop and stop.next)
+--~ end
+--~ end
+
local function inject_range(head,first,last,reference,make,stack,parent,pardir,txtdir)
local width, height, depth = dimensions(parent,first,last)
if pardir == "TRT" or txtdir == "+TRT" then
diff --git a/tex/generic/context/luatex-fonts-merged.lua b/tex/generic/context/luatex-fonts-merged.lua
index a17ea5411..6e2436369 100644
--- a/tex/generic/context/luatex-fonts-merged.lua
+++ b/tex/generic/context/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : c:/data/develop/context/texmf/tex/generic/context/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/texmf/tex/generic/context/luatex-fonts.lua
--- merge date : 08/13/09 13:15:16
+-- merge date : 08/14/09 10:50:13
do -- begin closure to overcome local limits and interference