summaryrefslogtreecommitdiff
path: root/scripts/context/lua/mtxrun.lua
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/context/lua/mtxrun.lua')
-rw-r--r--scripts/context/lua/mtxrun.lua306
1 files changed, 216 insertions, 90 deletions
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index 6a3df03d0..e0fc8d823 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -971,10 +971,6 @@ function table.fromhash(t)
return hsh
end
-table.serialize_functions = true
-table.serialize_compact = true
-table.serialize_inline = true
-
local noquotes, hexify, handle, reduce, compact, inline, functions
local reserved = table.tohash { -- intercept a language inconvenience: no reserved words as key
@@ -1257,15 +1253,36 @@ end
-- replacing handle by a direct t[#t+1] = ... (plus test) is not much
-- faster (0.03 on 1.00 for zapfino.tma)
-local function serialize(root,name,_handle,_reduce,_noquotes,_hexify)
- noquotes = _noquotes
- hexify = _hexify
- handle = _handle or print
- reduce = _reduce or false
- compact = table.serialize_compact
- inline = compact and table.serialize_inline
- functions = table.serialize_functions
+local function serialize(root,name,_handle,_reduce,_noquotes,_hexify) -- I might drop the _'s some day.
local tname = type(name)
+ if tname == "table" then
+ noquotes = name.noquotes
+ hexify = name.hexify
+ handle = name.handle or print
+ reduce = name.reduce or false
+ functions = name.functions
+ compact = name.compact
+ inline = name.inline and compact
+ name = name.name
+ tname = type(name)
+ if functions == nil then
+ functions = true
+ end
+ if compact == nil then
+ compact = true
+ end
+ if inline == nil then
+ inline = compact
+ end
+ else
+ noquotes = _noquotes
+ hexify = _hexify
+ handle = _handle or print
+ reduce = _reduce or false
+ compact = true
+ inline = true
+ functions = true
+ end
if tname == "string" then
if name == "return" then
handle("return {")
@@ -1324,12 +1341,11 @@ end
--
-- so this is on the todo list
-table.tofile_maxtab = 2*1024
+local maxtab = 2*1024
function table.tofile(filename,root,name,reduce,noquotes,hexify)
local f = io.open(filename,'w')
if f then
- local maxtab = table.tofile_maxtab
if maxtab > 1 then
local t, n = { }, 0
local function flush(s)
@@ -1532,8 +1548,12 @@ function table.sequenced(t,sep,simple) -- hash only
return concat(s, sep or " | ")
end
-function table.print(...)
- table.tohandle(print,...)
+function table.print(t,...)
+ if type(t) ~= "table" then
+ print(tostring(t))
+ else
+ table.tohandle(print,t,...)
+ end
end
-- -- -- obsolete but we keep them for a while and might comment them later -- -- --
@@ -2535,8 +2555,6 @@ function file.collapsepath(str,anchor)
end
end
-file.collapse_path = file.collapsepath
-
function file.robustname(str,strict)
str = gsub(str,"[^%a%d%/%-%.\\]+","-")
@@ -2651,14 +2669,12 @@ if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
-file.needs_updating_threshold = 1
-
-function file.needs_updating(oldname,newname) -- size modification access change
+function file.needs_updating(oldname,newname,threshold) -- size modification access change
local oldtime = lfs.attributes(oldname, modification)
local newtime = lfs.attributes(newname, modification)
if newtime >= oldtime then
return false
- elseif oldtime - newtime < file.needs_updating_threshold then
+ elseif oldtime - newtime < (threshold or 1) then
return false
else
return true
@@ -3666,7 +3682,7 @@ local tables = utilities.tables
local format, gmatch = string.format, string.gmatch
local concat, insert, remove = table.concat, table.insert, table.remove
-local setmetatable, tonumber, tostring = setmetatable, tonumber, tostring
+local setmetatable, getmetatable, tonumber, tostring = setmetatable, getmetatable, tonumber, tostring
function tables.definetable(target) -- defines undefined tables
local composed, t, n = nil, { }, 0
@@ -3731,12 +3747,6 @@ function tables.insertaftervalue(t,value,extra)
insert(t,#t+1,extra)
end
-local _empty_table_ = { __index = function(t,k) return "" end }
-
-function table.setemptymetatable(t)
- setmetatable(t,_empty_table_)
-end
-
-- experimental
local function toxml(t,d,result)
@@ -3753,9 +3763,14 @@ local function toxml(t,d,result)
end
end
-function table.toxml(t,name)
- local result = { "<?xml version='1.0' standalone='yes' ?>" }
- toxml( { [name or "root"] = t }, "", result)
+function table.toxml(t,name,nobanner)
+ local noroot = name == false
+ local result = (nobanner or noroot) and { } or { "<?xml version='1.0' standalone='yes' ?>" }
+ if noroot then
+ toxml( t, "", result)
+ else
+ toxml( { [name or "root"] = t }, "", result)
+ end
return concat(result,"\n")
end
@@ -3816,20 +3831,6 @@ function storage.checked(t)
return t
end
-function setmetatablekey(t,key,value)
- local m = getmetatable(t)
- if not m then
- m = { }
- setmetatable(t,m)
- end
- m[key] = value
-end
-
-function getmetatablekey(t,key,value)
- local m = getmetatable(t)
- return m and m[key]
-end
-
function storage.setinitializer(data,initialize)
local m = getmetatable(data) or { }
@@ -3852,6 +3853,77 @@ function storage.sparse(t)
return t
end
+-- table namespace ?
+
+local function f_empty () return "" end -- t,k
+local function f_self (t,k) t[k] = k return k end
+local function f_ignore() end -- t,k,v
+
+local t_empty = { __index = empty }
+local t_self = { __index = self }
+local t_ignore = { __newindex = ignore }
+
+function table.setmetatableindex(t,f)
+ local m = getmetatable(t)
+ if m then
+ if f == "empty" then
+ m.__index = f_empty
+ elseif f == "key" then
+ m.__index = f_self
+ else
+ m.__index = f
+ end
+ else
+ if f == "empty" then
+ setmetatable(t, t_empty)
+ elseif f == "key" then
+ setmetatable(t, t_self)
+ else
+ setmetatable(t,{ __index = f })
+ end
+ end
+end
+
+function table.setmetatablenewindex(t,f)
+ local m = getmetatable(t)
+ if m then
+ if f == "ignore" then
+ m.__newindex = f_ignore
+ else
+ m.__newindex = f
+ end
+ else
+ if f == "ignore" then
+ setmetatable(t, t_ignore)
+ else
+ setmetatable(t,{ __newindex = f })
+ end
+ end
+end
+
+function table.setmetatablecall(t,f)
+ local m = getmetatable(t)
+ if m then
+ m.__call = f
+ else
+ setmetatable(t,{ __call = f })
+ end
+end
+
+function table.setmetatablekey(t,key,value)
+ local m = getmetatable(t)
+ if not m then
+ m = { }
+ setmetatable(t,m)
+ end
+ m[key] = value
+end
+
+function table.getmetatablekey(t,key,value)
+ local m = getmetatable(t)
+ return m and m[key]
+end
+
end -- of closure
@@ -4047,18 +4119,20 @@ if not modules then modules = { } end modules ['util-prs'] = {
license = "see context related readme files"
}
+local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
+local lpegmatch = lpeg.match
+local concat, format, gmatch = table.concat, string.format, string.gmatch
+local tostring, type, next = tostring, type, next
+
utilities = utilities or {}
utilities.parsers = utilities.parsers or { }
local parsers = utilities.parsers
parsers.patterns = parsers.patterns or { }
--- we could use a Cf Cg construct
+local setmetatableindex = table.setmetatableindex
+local sortedhash = table.sortedhash
-local P, R, V, C, Ct, Carg = lpeg.P, lpeg.R, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Carg
-local lpegmatch = lpeg.match
-local concat, format, gmatch = table.concat, string.format, string.gmatch
-local tostring, type, next, setmetatable = tostring, type, next, setmetatable
-local sortedhash = table.sortedhash
+-- we could use a Cf Cg construct
local escape, left, right = P("\\"), P('{'), P('}')
@@ -4257,7 +4331,7 @@ function parsers.getparameters(self,class,parentclass,settings)
sp = { }
self[parentclass] = sp
end
- setmetatable(sc, { __index = sp })
+ setmetatableindex(sc,sp)
end
end
parsers.settings_to_hash(settings,sc)
@@ -4474,7 +4548,7 @@ end
local is_node = node and node.is_node
-function inspect(i)
+function inspect(i) -- global function
local ti = type(i)
if ti == "table" then
table.print(i,"table")
@@ -5044,6 +5118,8 @@ local escapedpattern = string.escapedpattern
local texcount = tex and tex.count
local next, type = next, type
+local setmetatableindex = table.setmetatableindex
+
--[[ldx--
<p>This is a prelude to a more extensive logging module. We no longer
provide <l n='xml'/> based logging a sparsing is relatively easy anyway.</p>
@@ -5064,11 +5140,11 @@ wiki : http://contextgarden.net
local function ignore() end
-setmetatable(logs, { __index = function(t,k) t[k] = ignore ; return ignore end })
+setmetatableindex(logs, function(t,k) t[k] = ignore ; return ignore end)
-local report, subreport, status, settarget, setformatter
+local report, subreport, status, settarget, setformats, settranslations
-local direct, subdirect, writer
+local direct, subdirect, writer, pushtarget, poptarget
if tex and tex.jobname or tex.formatname then
@@ -7308,6 +7384,8 @@ local type, next, tonumber, tostring, setmetatable, loadstring = type, next, ton
local format, upper, lower, gmatch, gsub, find, rep = string.format, string.upper, string.lower, string.gmatch, string.gsub, string.find, string.rep
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
+local setmetatableindex = table.setmetatableindex
+
-- beware, this is not xpath ... e.g. position is different (currently) and
-- we have reverse-sibling as reversed preceding sibling
@@ -7380,8 +7458,8 @@ local function fallback (t, name)
return fn
end
-setmetatable(finalizers.xml, { __index = fallback })
-setmetatable(finalizers.tex, { __index = fallback })
+setmetatableindex(finalizers.xml, fallback)
+setmetatableindex(finalizers.tex, fallback)
xml.defaultprotocol = "xml"
@@ -8078,14 +8156,13 @@ xml.nodesettostring = nodesettostring
local lpath -- we have a harmless kind of circular reference
+local lshowoptions = { name = false, functions = false }
+
local function lshow(parsed)
if type(parsed) == "string" then
parsed = lpath(parsed)
end
- local s = table.serialize_functions -- ugly
- table.serialize_functions = false -- ugly
- report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,table.serialize(parsed,false))
- table.serialize_functions = s -- ugly
+ report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern,table.serialize(parsed,lshowoptions))
end
xml.lshow = lshow
@@ -8679,8 +8756,8 @@ local xmlconvert, xmlcopy, xmlname = xml.convert, xml.copy, xml.name
local xmlinheritedconvert = xml.inheritedconvert
local xmlapplylpath = xml.applylpath
-local type = type
-local insert, remove = table.insert, table.remove
+local type, setmetatable, getmetatable = type, setmetatable, getmetatable
+local insert, remove, fastcopy = table.insert, table.remove, table.fastcopy
local gmatch, gsub = string.gmatch, string.gsub
local function report(what,pattern,c,e)
@@ -8889,6 +8966,41 @@ function xml.replace(root,pattern,whatever)
end
end
+local function wrap(e,wrapper)
+ local t = {
+ rn = e.rn,
+ tg = e.tg,
+ ns = e.ns,
+ at = e.at,
+ dt = e.dt,
+ __p__ = e,
+ }
+ setmetatable(t,getmetatable(e))
+ e.rn = wrapper.rn or e.rn or ""
+ e.tg = wrapper.tg or e.tg or ""
+ e.ns = wrapper.ns or e.ns or ""
+ e.at = fastcopy(wrapper.at)
+ e.dt = { t }
+end
+
+function xml.wrap(root,pattern,whatever)
+ if whatever then
+ local wrapper = xmltoelement(whatever,root)
+ local collected = xmlapplylpath(root,pattern)
+ if collected then
+ for c=1,#collected do
+ local e = collected[c]
+ if trace_manipulations then
+ report('wrapping',pattern,c,e)
+ end
+ wrap(e,wrapper)
+ end
+ end
+ else
+ wrap(root,xmltoelement(pattern))
+ end
+end
+
local function inject_element(root,pattern,whatever,prepend)
local element = root and xmltoelement(whatever,root)
local collected = element and xmlapplylpath(root,pattern)
@@ -8959,7 +9071,7 @@ local function include(xmldata,pattern,attribute,recursive,loaddata)
local ekat = ek.at
local epdt = ek.__p__.dt
if not attribute or attribute == "" then
- name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- ckeck, probably always tab or str
+ name = (type(ekdt) == "table" and ekdt[1]) or ekdt -- check, probably always tab or str
end
if not name then
for a in gmatch(attribute or "href","([^|]+)") do
@@ -10039,17 +10151,23 @@ if not modules then modules = { } end modules ['data-env'] = {
license = "see context related readme files",
}
-local allocate = utilities.storage.allocate
local lower, gsub = string.lower, string.gsub
-local fileextname = file.extname
-
local resolvers = resolvers
-local formats = allocate() resolvers.formats = formats
-local suffixes = allocate() resolvers.suffixes = suffixes
-local dangerous = allocate() resolvers.dangerous = dangerous
-local suffixmap = allocate() resolvers.suffixmap = suffixmap
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
+local fileextname = file.extname
+
+local formats = allocate()
+local suffixes = allocate()
+local dangerous = allocate()
+local suffixmap = allocate()
+
+resolvers.formats = formats
+resolvers.suffixes = suffixes
+resolvers.dangerous = dangerous
+resolvers.suffixmap = suffixmap
local relations = allocate { -- todo: handlers also here
core = {
@@ -10261,9 +10379,9 @@ local function simplified(t,k)
return rawget(t,lower(gsub(k," ","")))
end
-setmetatablekey(formats, "__index", simplified)
-setmetatablekey(suffixes, "__index", simplified)
-setmetatablekey(suffixmap, "__index", simplified)
+setmetatableindex(formats, simplified)
+setmetatableindex(suffixes, simplified)
+setmetatableindex(suffixmap, simplified)
-- A few accessors, mostly for command line tool.
@@ -10611,6 +10729,8 @@ function caches.is_writable(filepath,filename)
return file.is_writable(tmaname)
end
+local saveoptions = { name = "return", reduce = true }
+
function caches.savedata(filepath,filename,data,raw)
local tmaname, tmcname = caches.setluanames(filepath,filename)
local reduce, simplify = true, true
@@ -10619,9 +10739,9 @@ function caches.savedata(filepath,filename,data,raw)
end
data.cache_uuid = os.uuid()
if caches.direct then
- file.savedata(tmaname, table.serialize(data,'return',false,true,false)) -- no hex
+ file.savedata(tmaname,table.serialize(data,saveoptions))
else
- table.tofile(tmaname, data,'return',false,true,false) -- maybe not the last true
+ table.tofile(tmaname,data,saveoptions)
end
utilities.lua.compile(tmaname,tmcname)
end
@@ -10865,15 +10985,20 @@ if not modules then modules = { } end modules ['data-res'] = {
local format, gsub, find, lower, upper, match, gmatch = string.format, string.gsub, string.find, string.lower, string.upper, string.match, string.gmatch
local concat, insert, sortedkeys = table.concat, table.insert, table.sortedkeys
-local next, type, rawget, setmetatable, getmetatable = next, type, rawget, setmetatable, getmetatable
+local next, type, rawget = next, type, rawget
local os = os
local P, S, R, C, Cc, Cs, Ct, Carg = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Carg
local lpegmatch, lpegpatterns = lpeg.match, lpeg.patterns
-local filedirname, filebasename, fileextname, filejoin = file.dirname, file.basename, file.extname, file.join
-local collapsepath, joinpath = file.collapsepath, file.joinpath
-local allocate = utilities.storage.allocate
+local filedirname = file.dirname
+local filebasename = file.basename
+local fileextname = file.extname
+local filejoin = file.join
+local collapsepath = file.collapsepath
+local joinpath = file.joinpath
+local allocate = utilities.storage.allocate
+local setmetatableindex = table.setmetatableindex
local trace_locating = false trackers.register("resolvers.locating", function(v) trace_locating = v end)
local trace_detail = false trackers.register("resolvers.details", function(v) trace_detail = v end)
@@ -11010,7 +11135,8 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
force_suffixes = true,
}
- setmetatable(variables, { __index = function(t,k)
+ setmetatableindex(variables,function(t,k)
+ local v
for i=1,#order do
v = order[i][k]
if v ~= nil then
@@ -11023,10 +11149,10 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
end
t[k] = v
return v
- end } )
+ end)
- setmetatable(environment, { __index = function(t,k)
- v = osgetenv(k)
+ setmetatableindex(environment, function(t,k)
+ local v = osgetenv(k)
if v == nil then
v = variables[k]
end
@@ -11036,9 +11162,9 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
v = resolvers.repath(v) -- for taco who has a : separated osfontdir
t[k] = v
return v
- end } )
+ end)
- setmetatable(expansions, { __index = function(t,k)
+ setmetatableindex(expansions, function(t,k)
local v = environment[k]
if type(v) == "string" then
v = lpegmatch(variableresolver,v)
@@ -11046,7 +11172,7 @@ function resolvers.newinstance() -- todo: all vars will become lowercase and alp
end
t[k] = v
return v
- end } )
+ end)
return newinstance
@@ -11552,7 +11678,7 @@ function resolvers.registerfilehash(name,content,someerror)
end
end
-function isreadable(name)
+local function isreadable(name)
local readable = lfs.isfile(name) -- not file.is_readable(name) asit can be a dir
if trace_detail then
if readable then