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.lua1424
1 files changed, 672 insertions, 752 deletions
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index 45a881839..6c68ec51a 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -37,10 +37,9 @@ if not modules then modules = { } end modules ['mtxrun'] = {
-- remember for subruns: _CTX_K_S_#{original}_
-- remember for subruns: TEXMFSTART.#{original} [tex.rb texmfstart.rb]
+banner = "version 1.1.2 - 2007+ - PRAGMA ADE / CONTEXT" -- not local
texlua = true
-banner = "version 1.1.0 - 2007+ - PRAGMA ADE / CONTEXT" -- not local
-
-- begin library merge
-- filename : l-string.lua
-- comment : split off from luat-lib
@@ -176,7 +175,7 @@ end
--~ end end
-string.chr_to_esc = {
+local chr_to_esc = {
["%"] = "%%",
["."] = "%.",
["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
@@ -186,16 +185,18 @@ string.chr_to_esc = {
["{"] = "%{", ["}"] = "%}"
}
+string.chr_to_esc = chr_to_esc
+
function string:esc() -- variant 2
- return (self:gsub("(.)",string.chr_to_esc))
+ return (self:gsub("(.)",chr_to_esc))
end
-function string.unquote(str)
- return (str:gsub("^([\"\'])(.*)%1$","%2"))
+function string:unquote()
+ return (self:gsub("^([\"\'])(.*)%1$","%2"))
end
-function string.quote(str)
- return '"' .. str:unquote() .. '"'
+function string:quote()
+ return '"' .. self:unquote() .. '"'
end
function string:count(pattern) -- variant 3
@@ -445,6 +446,30 @@ function string:splitlines()
return capture:match(self)
end
+--~ local p = lpeg.splitat("->",false) print(p:match("oeps->what->more")) -- oeps what more
+--~ local p = lpeg.splitat("->",true) print(p:match("oeps->what->more")) -- oeps what->more
+--~ local p = lpeg.splitat("->",false) print(p:match("oeps")) -- oeps
+--~ local p = lpeg.splitat("->",true) print(p:match("oeps")) -- oeps
+
+local splitters_s, splitters_m = { }, { }
+
+function lpeg.splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = lpeg.P(separator)
+ if single then
+ local other, any = lpeg.C((1 - separator)^0), lpeg.P(1)
+ splitter = other * (separator * lpeg.C(any^0) + "")
+ splitters_s[separator] = splitter
+ else
+ local other = lpeg.C((1 - separator)^0)
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
-- filename : l-table.lua
-- comment : split off from luat-lib
@@ -456,11 +481,15 @@ if not versions then versions = { } end versions['l-table'] = 1.001
table.join = table.concat
+local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
+local format = string.format
+local getmetatable, setmetatable = getmetatable, setmetatable
+local pairs, ipairs, type, next, tostring = pairs, ipairs, type, next, tostring
+
function table.strip(tab)
local lst = { }
- for k, v in ipairs(tab) do
- -- s = string.gsub(v, "^%s*(.-)%s*$", "%1")
- s = v:gsub("^%s*(.-)%s*$", "%1")
+ for i=1,#tab do
+ local s = tab[i]:gsub("^%s*(.-)%s*$","%1")
if s == "" then
-- skip this one
else
@@ -470,16 +499,7 @@ function table.strip(tab)
return lst
end
---~ function table.sortedkeys(tab)
---~ local srt = { }
---~ for key,_ in pairs(tab) do
---~ srt[#srt+1] = key
---~ end
---~ table.sort(srt)
---~ return srt
---~ end
-
-function table.sortedkeys(tab)
+local function sortedkeys(tab)
local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in pairs(tab) do
srt[#srt+1] = key
@@ -499,22 +519,34 @@ function table.sortedkeys(tab)
end
end
if kind == 0 or kind == 3 then
- table.sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
+ sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
else
- table.sort(srt)
+ sort(srt)
+ end
+ return srt
+end
+
+local function sortedhashkeys(tab) -- fast one
+ local srt = { }
+ for key,_ in pairs(tab) do
+ srt[#srt+1] = key
end
+ sort(srt)
return srt
end
+table.sortedkeys = sortedkeys
+table.sortedhashkeys = sortedhashkeys
+
function table.append(t, list)
for _,v in pairs(list) do
- table.insert(t,v)
+ insert(t,v)
end
end
function table.prepend(t, list)
for k,v in pairs(list) do
- table.insert(t,k,v)
+ insert(t,k,v)
end
end
@@ -561,70 +593,57 @@ function table.imerged(...)
return tmp
end
-if not table.fastcopy then do
-
- local type, pairs, getmetatable, setmetatable = type, pairs, getmetatable, setmetatable
-
- local function fastcopy(old) -- fast one
- if old then
- local new = { }
- for k,v in pairs(old) do
- if type(v) == "table" then
- new[k] = fastcopy(v) -- was just table.copy
- else
- new[k] = v
- end
- end
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+local function fastcopy(old) -- fast one
+ if old then
+ local new = { }
+ for k,v in pairs(old) do
+ if type(v) == "table" then
+ new[k] = fastcopy(v) -- was just table.copy
+ else
+ new[k] = v
end
- return new
- else
- return { }
end
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
+ return new
+ else
+ return { }
end
+end
- table.fastcopy = fastcopy
-
-end end
-
-if not table.copy then do
-
- local type, pairs, getmetatable, setmetatable = type, pairs, getmetatable, setmetatable
-
- local function copy(t, tables) -- taken from lua wiki, slightly adapted
- tables = tables or { }
- local tcopy = {}
- if not tables[t] then
- tables[t] = tcopy
- end
- for i,v in pairs(t) do -- brrr, what happens with sparse indexed
- if type(i) == "table" then
- if tables[i] then
- i = tables[i]
- else
- i = copy(i, tables)
- end
- end
- if type(v) ~= "table" then
- tcopy[i] = v
- elseif tables[v] then
- tcopy[i] = tables[v]
+local function copy(t, tables) -- taken from lua wiki, slightly adapted
+ tables = tables or { }
+ local tcopy = {}
+ if not tables[t] then
+ tables[t] = tcopy
+ end
+ for i,v in pairs(t) do -- brrr, what happens with sparse indexed
+ if type(i) == "table" then
+ if tables[i] then
+ i = tables[i]
else
- tcopy[i] = copy(v, tables)
+ i = copy(i, tables)
end
end
- local mt = getmetatable(t)
- if mt then
- setmetatable(tcopy,mt)
+ if type(v) ~= "table" then
+ tcopy[i] = v
+ elseif tables[v] then
+ tcopy[i] = tables[v]
+ else
+ tcopy[i] = copy(v, tables)
end
- return tcopy
end
+ local mt = getmetatable(t)
+ if mt then
+ setmetatable(tcopy,mt)
+ end
+ return tcopy
+end
- table.copy = copy
-
-end end
+table.fastcopy = fastcopy
+table.copy = copy
-- rougly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
@@ -653,257 +672,22 @@ function table.starts_at(t)
return ipairs(t,1)(t,0)
end
---~ do
-
---~ -- one of my first exercises in lua ...
-
---~ table.serialize_functions = true
---~ table.serialize_compact = true
---~ table.serialize_inline = true
-
---~ local function key(k,noquotes)
---~ if type(k) == "number" then -- or k:find("^%d+$") then
---~ return "["..k.."]"
---~ elseif noquotes and k:find("^%a[%a%d%_]*$") then
---~ return k
---~ else
---~ return '["'..k..'"]'
---~ end
---~ end
-
---~ local function simple_table(t)
---~ if #t > 0 then
---~ local n = 0
---~ for _,v in pairs(t) do
---~ n = n + 1
---~ end
---~ if n == #t then
---~ local tt = { }
---~ for i=1,#t do
---~ local v = t[i]
---~ local tv = type(v)
---~ if tv == "number" or tv == "boolean" then
---~ tt[#tt+1] = tostring(v)
---~ elseif tv == "string" then
---~ tt[#tt+1] = ("%q"):format(v)
---~ else
---~ tt = nil
---~ break
---~ end
---~ end
---~ return tt
---~ end
---~ end
---~ return nil
---~ end
-
---~ local function serialize(root,name,handle,depth,level,reduce,noquotes,indexed)
---~ handle = handle or print
---~ reduce = reduce or false
---~ if depth then
---~ depth = depth .. " "
---~ if indexed then
---~ handle(("%s{"):format(depth))
---~ else
---~ handle(("%s%s={"):format(depth,key(name,noquotes)))
---~ end
---~ else
---~ depth = ""
---~ local tname = type(name)
---~ if tname == "string" then
---~ if name == "return" then
---~ handle("return {")
---~ else
---~ handle(name .. "={")
---~ end
---~ elseif tname == "number" then
---~ handle("[" .. name .. "]={")
---~ elseif tname == "boolean" then
---~ if name then
---~ handle("return {")
---~ else
---~ handle("{")
---~ end
---~ else
---~ handle("t={")
---~ end
---~ end
---~ if root and next(root) then
---~ local compact = table.serialize_compact
---~ local inline = compact and table.serialize_inline
---~ local first, last = nil, 0 -- #root cannot be trusted here
---~ if compact then
---~ for k,v in ipairs(root) do -- NOT: for k=1,#root do (we need to quit at nil)
---~ if not first then first = k end
---~ last = last + 1
---~ end
---~ end
---~ for _,k in pairs(table.sortedkeys(root)) do
---~ local v = root[k]
---~ local t = type(v)
---~ if compact and first and type(k) == "number" and k >= first and k <= last then
---~ if t == "number" then
---~ handle(("%s %s,"):format(depth,v))
---~ elseif t == "string" then
---~ if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
---~ handle(("%s %s,"):format(depth,v))
---~ else
---~ handle(("%s %q,"):format(depth,v))
---~ end
---~ elseif t == "table" then
---~ if not next(v) then
---~ handle(("%s {},"):format(depth))
---~ elseif inline then
---~ local st = simple_table(v)
---~ if st then
---~ handle(("%s { %s },"):format(depth,table.concat(st,", ")))
---~ else
---~ serialize(v,k,handle,depth,level+1,reduce,noquotes,true)
---~ end
---~ else
---~ serialize(v,k,handle,depth,level+1,reduce,noquotes,true)
---~ end
---~ elseif t == "boolean" then
---~ handle(("%s %s,"):format(depth,tostring(v)))
---~ elseif t == "function" then
---~ if table.serialize_functions then
---~ handle(('%s loadstring(%q),'):format(depth,string.dump(v)))
---~ else
---~ handle(('%s "function",'):format(depth))
---~ end
---~ else
---~ handle(("%s %q,"):format(depth,tostring(v)))
---~ end
---~ elseif k == "__p__" then -- parent
---~ if false then
---~ handle(("%s __p__=nil,"):format(depth))
---~ end
---~ elseif t == "number" then
---~ handle(("%s %s=%s,"):format(depth,key(k,noquotes),v))
---~ elseif t == "string" then
---~ if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
---~ handle(("%s %s=%s,"):format(depth,key(k,noquotes),v))
---~ else
---~ handle(("%s %s=%q,"):format(depth,key(k,noquotes),v))
---~ end
---~ elseif t == "table" then
---~ if not next(v) then
---~ handle(("%s %s={},"):format(depth,key(k,noquotes)))
---~ elseif inline then
---~ local st = simple_table(v)
---~ if st then
---~ handle(("%s %s={ %s },"):format(depth,key(k,noquotes),table.concat(st,", ")))
---~ else
---~ serialize(v,k,handle,depth,level+1,reduce,noquotes)
---~ end
---~ else
---~ serialize(v,k,handle,depth,level+1,reduce,noquotes)
---~ end
---~ elseif t == "boolean" then
---~ handle(("%s %s=%s,"):format(depth,key(k,noquotes),tostring(v)))
---~ elseif t == "function" then
---~ if table.serialize_functions then
---~ handle(('%s %s=loadstring(%q),'):format(depth,key(k,noquotes),string.dump(v)))
---~ else
---~ handle(('%s %s="function",'):format(depth,key(k,noquotes)))
---~ end
---~ else
---~ handle(("%s %s=%q,"):format(depth,key(k,noquotes),tostring(v)))
---~ -- handle(('%s %s=loadstring(%q),'):format(depth,key(k,noquotes),string.dump(function() return v end)))
---~ end
---~ end
---~ if level > 0 then
---~ handle(("%s},"):format(depth))
---~ else
---~ handle(("%s}"):format(depth))
---~ end
---~ else
---~ handle(("%s}"):format(depth))
---~ end
---~ end
-
---~ --~ name:
---~ --~
---~ --~ true : return { }
---~ --~ false : { }
---~ --~ nil : t = { }
---~ --~ string : string = { }
---~ --~ 'return' : return { }
---~ --~ number : [number] = { }
-
---~ function table.serialize(root,name,reduce,noquotes)
---~ local t = { }
---~ local function flush(s)
---~ t[#t+1] = s
---~ end
---~ serialize(root, name, flush, nil, 0, reduce, noquotes)
---~ return table.concat(t,"\n")
---~ end
-
---~ function table.tohandle(handle,root,name,reduce,noquotes)
---~ serialize(root, name, handle, nil, 0, reduce, noquotes)
---~ end
-
---~ -- sometimes tables are real use (zapfino extra pro is some 85M) in which
---~ -- case a stepwise serialization is nice; actually, we could consider:
---~ --
---~ -- for line in table.serializer(root,name,reduce,noquotes) do
---~ -- ...(line)
---~ -- end
---~ --
---~ -- so this is on the todo list
-
---~ table.tofile_maxtab = 2*1024
-
---~ function table.tofile(filename,root,name,reduce,noquotes)
---~ local f = io.open(filename,'w')
---~ if f then
---~ local concat = table.concat
---~ local maxtab = table.tofile_maxtab
---~ if maxtab > 1 then
---~ local t = { }
---~ local function flush(s)
---~ t[#t+1] = s
---~ if #t > maxtab then
---~ f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
---~ t = { }
---~ end
---~ end
---~ serialize(root, name, flush, nil, 0, reduce, noquotes)
---~ f:write(concat(t,"\n"),"\n")
---~ else
---~ local function flush(s)
---~ f:write(s,"\n")
---~ end
---~ serialize(root, name, flush, nil, 0, reduce, noquotes)
---~ end
---~ f:close()
---~ end
---~ end
-
---~ end
+function table.tohash(t,value)
+ local h = { }
+ if value == nil then value = true end
+ for _, v in pairs(t) do -- no ipairs here
+ h[v] = value
+ end
+ return h
+end
---~ t = {
---~ b = "123",
---~ a = "x",
---~ c = 1.23,
---~ d = "1.23",
---~ e = true,
---~ f = {
---~ d = "1.23",
---~ a = "x",
---~ b = "123",
---~ c = 1.23,
---~ e = true,
---~ f = {
---~ e = true,
---~ f = {
---~ e = true
---~ },
---~ },
---~ },
---~ g = function() end
---~ }
+function table.fromhash(t)
+ local h = { }
+ for k, v in pairs(t) do -- no ipairs here
+ if v then h[#h+1] = k end
+ end
+ return h
+end
--~ print(table.serialize(t), "\n")
--~ print(table.serialize(t,"name"), "\n")
@@ -912,320 +696,339 @@ end
--~ print(table.serialize(t,"name",true), "\n")
--~ print(table.serialize(t,"name",true,true), "\n")
-do
+table.serialize_functions = true
+table.serialize_compact = true
+table.serialize_inline = true
- table.serialize_functions = true
- table.serialize_compact = true
- table.serialize_inline = true
+local noquotes, hexify, handle, reduce, compact, inline, functions
- local sortedkeys = table.sortedkeys
- local format, concat = string.format, table.concat
- local noquotes, hexify, handle, reduce, compact, inline, functions
- local pairs, ipairs, type, next, tostring = pairs, ipairs, type, next, tostring
+local reserved = table.tohash { -- intercept a language flaw, no reserved words as key
+ 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if',
+ 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while',
+}
- local function key(k)
- if type(k) == "number" then -- or k:find("^%d+$") then
- if hexify then
- return ("[0x%04X]"):format(k)
- else
- return "["..k.."]"
- end
- elseif noquotes and k:find("^%a[%a%d%_]*$") then
- return k
+local function key(k)
+ if type(k) == "number" then -- or k:find("^%d+$") then
+ if hexify then
+ return ("[0x%04X]"):format(k)
else
- return '["'..k..'"]'
+ return "["..k.."]"
end
+ elseif noquotes and not reserved[k] and k:find("^%a[%a%d%_]*$") then
+ return k
+ else
+ return '["'..k..'"]'
end
+end
- local function simple_table(t)
- if #t > 0 then
- local n = 0
- for _,v in pairs(t) do
- n = n + 1
- end
- if n == #t then
- local tt = { }
- for i=1,#t do
- local v = t[i]
- local tv = type(v)
- if tv == "number" then
- if hexify then
- tt[#tt+1] = ("0x%04X"):format(v)
- else
- tt[#tt+1] = tostring(v)
- end
- elseif tv == "boolean" then
- tt[#tt+1] = tostring(v)
- elseif tv == "string" then
- tt[#tt+1] = ("%q"):format(v)
+local function simple_table(t)
+ if #t > 0 then
+ local n = 0
+ for _,v in pairs(t) do
+ n = n + 1
+ end
+ if n == #t then
+ local tt = { }
+ for i=1,#t do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "number" then
+ if hexify then
+ tt[#tt+1] = ("0x%04X"):format(v)
else
- tt = nil
- break
+ tt[#tt+1] = tostring(v)
end
+ elseif tv == "boolean" then
+ tt[#tt+1] = tostring(v)
+ elseif tv == "string" then
+ tt[#tt+1] = ("%q"):format(v)
+ else
+ tt = nil
+ break
end
- return tt
end
+ return tt
end
- return nil
end
+ return nil
+end
- local function do_serialize(root,name,depth,level,indexed)
- if level > 0 then
- depth = depth .. " "
- if indexed then
- handle(("%s{"):format(depth))
- elseif name then
- handle(("%s%s={"):format(depth,key(name)))
- else
- handle(("%s{"):format(depth))
- end
+local function do_serialize(root,name,depth,level,indexed)
+ if level > 0 then
+ depth = depth .. " "
+ if indexed then
+ handle(("%s{"):format(depth))
+ elseif name then
+ handle(("%s%s={"):format(depth,key(name)))
+ else
+ handle(("%s{"):format(depth))
end
- if root and next(root) then
- local first, last = nil, 0 -- #root cannot be trusted here
- if compact then
- for k,v in ipairs(root) do -- NOT: for k=1,#root do (we need to quit at nil)
- if not first then first = k end
- last = last + 1
- end
+ end
+ if root and next(root) then
+ local first, last = nil, 0 -- #root cannot be trusted here
+ if compact then
+ for k,v in ipairs(root) do -- NOT: for k=1,#root do (we need to quit at nil)
+ if not first then first = k end
+ last = last + 1
end
- --~ for _,k in pairs(sortedkeys(root)) do -- 1% faster:
- local sk = sortedkeys(root)
- for i=1,#sk do
- local k = sk[i]
- local v = root[k]
- local t = type(v)
- if compact and first and type(k) == "number" and k >= first and k <= last then
- if t == "number" then
- if hexify then
- handle(("%s 0x%04X,"):format(depth,v))
- else
- handle(("%s %s,"):format(depth,v))
- end
- elseif t == "string" then
- if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
- handle(("%s %s,"):format(depth,v))
- else
- handle(("%s %q,"):format(depth,v))
- end
- elseif t == "table" then
- if not next(v) then
- handle(("%s {},"):format(depth))
- elseif inline then
- local st = simple_table(v)
- if st then
- handle(("%s { %s },"):format(depth,concat(st,", ")))
- else
- do_serialize(v,k,depth,level+1,true)
- end
- else
- do_serialize(v,k,depth,level+1,true)
- end
- elseif t == "boolean" then
- handle(("%s %s,"):format(depth,tostring(v)))
- elseif t == "function" then
- if functions then
- handle(('%s loadstring(%q),'):format(depth,string.dump(v)))
- else
- handle(('%s "function",'):format(depth))
- end
- else
- handle(("%s %q,"):format(depth,tostring(v)))
- end
- elseif k == "__p__" then -- parent
- if false then
- handle(("%s __p__=nil,"):format(depth))
- end
- elseif t == "number" then
+ end
+ --~ for _,k in pairs(sortedkeys(root)) do -- 1% faster:
+ local sk = sortedkeys(root)
+ for i=1,#sk do
+ local k = sk[i]
+ local v = root[k]
+ local t = type(v)
+ if compact and first and type(k) == "number" and k >= first and k <= last then
+ if t == "number" then
if hexify then
- handle(("%s %s=0x%04X,"):format(depth,key(k),v))
+ handle(("%s 0x%04X,"):format(depth,v))
else
- handle(("%s %s=%s,"):format(depth,key(k),v))
+ handle(("%s %s,"):format(depth,v))
end
elseif t == "string" then
if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
- handle(("%s %s=%s,"):format(depth,key(k),v))
+ handle(("%s %s,"):format(depth,v))
else
- handle(("%s %s=%q,"):format(depth,key(k),v))
+ handle(("%s %q,"):format(depth,v))
end
elseif t == "table" then
if not next(v) then
- handle(("%s %s={},"):format(depth,key(k)))
+ handle(("%s {},"):format(depth))
elseif inline then
local st = simple_table(v)
if st then
- handle(("%s %s={ %s },"):format(depth,key(k),concat(st,", ")))
+ handle(("%s { %s },"):format(depth,concat(st,", ")))
else
- do_serialize(v,k,depth,level+1)
+ do_serialize(v,k,depth,level+1,true)
end
else
- do_serialize(v,k,depth,level+1)
+ do_serialize(v,k,depth,level+1,true)
end
elseif t == "boolean" then
- handle(("%s %s=%s,"):format(depth,key(k),tostring(v)))
+ handle(("%s %s,"):format(depth,tostring(v)))
elseif t == "function" then
if functions then
- handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(v)))
+ handle(('%s loadstring(%q),'):format(depth,v:dump()))
else
- handle(('%s %s="function",'):format(depth,key(k)))
+ handle(('%s "function",'):format(depth))
end
else
- handle(("%s %s=%q,"):format(depth,key(k),tostring(v)))
- -- handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(function() return v end)))
+ handle(("%s %q,"):format(depth,tostring(v)))
+ end
+ elseif k == "__p__" then -- parent
+ if false then
+ handle(("%s __p__=nil,"):format(depth))
+ end
+ elseif t == "number" then
+ if hexify then
+ handle(("%s %s=0x%04X,"):format(depth,key(k),v))
+ else
+ handle(("%s %s=%s,"):format(depth,key(k),v))
+ end
+ elseif t == "string" then
+ if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
+ handle(("%s %s=%s,"):format(depth,key(k),v))
+ else
+ handle(("%s %s=%q,"):format(depth,key(k),v))
+ end
+ elseif t == "table" then
+ if not next(v) then
+ handle(("%s %s={},"):format(depth,key(k)))
+ elseif inline then
+ local st = simple_table(v)
+ if st then
+ handle(("%s %s={ %s },"):format(depth,key(k),concat(st,", ")))
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ elseif t == "boolean" then
+ handle(("%s %s=%s,"):format(depth,key(k),tostring(v)))
+ elseif t == "function" then
+ if functions then
+ handle(('%s %s=loadstring(%q),'):format(depth,key(k),v:dump()))
+ else
+ handle(('%s %s="function",'):format(depth,key(k)))
end
+ else
+ handle(("%s %s=%q,"):format(depth,key(k),tostring(v)))
+ -- handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(function() return v end)))
end
end
- if level > 0 then
- handle(("%s},"):format(depth))
- end
end
+ if level > 0 then
+ handle(("%s},"):format(depth))
+ end
+end
- 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 tname = type(name)
- if tname == "string" then
- if name == "return" then
- handle("return {")
- else
- handle(name .. "={")
- end
- elseif tname == "number" then
- if hexify then
- handle(format("[0x%04X]={",name))
- else
- handle("[" .. name .. "]={")
- end
- elseif tname == "boolean" then
- if name then
- handle("return {")
- else
- handle("{")
- end
+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 tname = type(name)
+ if tname == "string" then
+ if name == "return" then
+ handle("return {")
else
- handle("t={")
+ handle(name .. "={")
end
- if root and next(root) then
- do_serialize(root,name,"",0,indexed)
+ elseif tname == "number" then
+ if hexify then
+ handle(("[0x%04X]={"):format(name))
+ else
+ handle("[" .. name .. "]={")
end
- handle("}")
- end
-
- --~ name:
- --~
- --~ true : return { }
- --~ false : { }
- --~ nil : t = { }
- --~ string : string = { }
- --~ 'return' : return { }
- --~ number : [number] = { }
-
- function table.serialize(root,name,reduce,noquotes,hexify)
- local t = { }
- local function flush(s)
- t[#t+1] = s
+ elseif tname == "boolean" then
+ if name then
+ handle("return {")
+ else
+ handle("{")
end
- serialize(root,name,flush,reduce,noquotes,hexify)
- return concat(t,"\n")
+ else
+ handle("t={")
+ end
+ if root and next(root) then
+ do_serialize(root,name,"",0,indexed)
end
+ handle("}")
+end
- function table.tohandle(handle,root,name,reduce,noquotes,hexify)
- serialize(root,name,handle,reduce,noquotes,hexify)
+--~ name:
+--~
+--~ true : return { }
+--~ false : { }
+--~ nil : t = { }
+--~ string : string = { }
+--~ 'return' : return { }
+--~ number : [number] = { }
+
+function table.serialize(root,name,reduce,noquotes,hexify)
+ local t = { }
+ local function flush(s)
+ t[#t+1] = s
end
+ serialize(root,name,flush,reduce,noquotes,hexify)
+ return concat(t,"\n")
+end
- -- sometimes tables are real use (zapfino extra pro is some 85M) in which
- -- case a stepwise serialization is nice; actually, we could consider:
- --
- -- for line in table.serializer(root,name,reduce,noquotes) do
- -- ...(line)
- -- end
- --
- -- so this is on the todo list
+function table.tohandle(handle,root,name,reduce,noquotes,hexify)
+ serialize(root,name,handle,reduce,noquotes,hexify)
+end
- table.tofile_maxtab = 2*1024
+-- sometimes tables are real use (zapfino extra pro is some 85M) in which
+-- case a stepwise serialization is nice; actually, we could consider:
+--
+-- for line in table.serializer(root,name,reduce,noquotes) do
+-- ...(line)
+-- end
+--
+-- so this is on the todo list
- 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 = { }
- local function flush(s)
- t[#t+1] = s
- if #t > maxtab then
- f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
- t = { }
- end
- end
- serialize(root,name,flush,reduce,noquotes,hexify)
- f:write(concat(t,"\n"),"\n")
- else
- local function flush(s)
- f:write(s,"\n")
+table.tofile_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 = { }
+ local function flush(s)
+ t[#t+1] = s
+ if #t > maxtab then
+ f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
+ t = { }
end
- serialize(root,name,flush,reduce,noquotes,hexify)
end
- f:close()
+ serialize(root,name,flush,reduce,noquotes,hexify)
+ f:write(concat(t,"\n"),"\n")
+ else
+ local function flush(s)
+ f:write(s,"\n")
+ end
+ serialize(root,name,flush,reduce,noquotes,hexify)
end
+ f:close()
end
-
end
-do
-
- local function flatten(t,f,complete)
- for i=1,#t do
- local v = t[i]
- if type(v) == "table" then
- if complete or type(v[1]) == "table" then
- flatten(v,f,complete)
- else
- f[#f+1] = v
- end
+local function flatten(t,f,complete)
+ for i=1,#t do
+ local v = t[i]
+ if type(v) == "table" then
+ if complete or type(v[1]) == "table" then
+ flatten(v,f,complete)
else
f[#f+1] = v
end
+ else
+ f[#f+1] = v
end
end
+end
- function table.flatten(t)
- local f = { }
- flatten(t,f,true)
- return f
- end
+function table.flatten(t)
+ local f = { }
+ flatten(t,f,true)
+ return f
+end
- function table.unnest(t) -- bad name
- local f = { }
- flatten(t,f,false)
- return f
- end
+function table.unnest(t) -- bad name
+ local f = { }
+ flatten(t,f,false)
+ return f
+end
+
+table.flatten_one_level = table.unnest
- table.flatten_one_level = table.unnest
+-- the next three may disappear
+function table.remove_value(t,value) -- todo: n
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ remove(t,i)
+ -- remove all, so no: return
+ end
+ end
+ end
end
function table.insert_before_value(t,value,str)
- for i=1,#t do
- if t[i] == value then
- table.insert(t,i,str)
- return
+ if str then
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i,str)
+ return
+ end
+ end
end
+ insert(t,1,str)
+ elseif value then
+ insert(t,1,value)
end
- table.insert(t,1,str)
end
function table.insert_after_value(t,value,str)
- for i=1,#t do
- if t[i] == value then
- table.insert(t,i+1,str)
- return
+ if str then
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i+1,str)
+ return
+ end
+ end
end
+ t[#t+1] = str
+ elseif value then
+ t[#t+1] = value
end
- t[#t+1] = str
end
function table.are_equal(a,b,n,m)
@@ -1256,27 +1059,11 @@ function table.compact(t)
end
end
-function table.tohash(t)
- local h = { }
- for _, v in pairs(t) do -- no ipairs here
- h[v] = true
- end
- return h
-end
-
-function table.fromhash(t)
- local h = { }
- for k, v in pairs(t) do -- no ipairs here
- if v then h[#h+1] = k end
- end
- return h
-end
-
function table.contains(t, v)
if t then
for i=1, #t do
if t[i] == v then
- return true
+ return i
end
end
end
@@ -1313,11 +1100,10 @@ function table.clone(t,p) -- t is optional or nil or table
return t
end
-
function table.hexed(t,seperator)
local tt = { }
- for i=1,#t do tt[i] = string.format("0x%04X",t[i]) end
- return table.concat(tt,seperator or " ")
+ for i=1,#t do tt[i] = ("0x%04X"):format(t[i]) end
+ return concat(tt,seperator or " ")
end
function table.reverse_hash(h)
@@ -1357,6 +1143,7 @@ function io.loaddata(filename)
local f = io.open(filename,'rb')
if f then
local data = f:read('*all')
+ -- garbagecollector.check(data)
f:close()
return data
else
@@ -1810,6 +1597,8 @@ if not versions then versions = { } end versions['l-file'] = 1.001
if not file then file = { } end
+local concat = table.concat
+
function file.removesuffix(filename)
return (filename:gsub("%.[%a%d]+$",""))
end
@@ -1846,14 +1635,6 @@ end
file.suffix = file.extname
---~ function file.join(...)
---~ local t = { ... }
---~ for i=1,#t do
---~ t[i] = (t[i]:gsub("\\","/")):gsub("/+$","")
---~ end
---~ return table.concat(t,"/")
---~ end
-
--~ print(file.join("x/","/y"))
--~ print(file.join("http://","/y"))
--~ print(file.join("http://a","/y"))
@@ -1861,7 +1642,7 @@ file.suffix = file.extname
--~ print(file.join("//nas-1","/y"))
function file.join(...)
- local pth = table.concat({...},"/")
+ local pth = concat({...},"/")
pth = pth:gsub("\\","/")
local a, b = pth:match("^(.*://)(.*)$")
if a and b then
@@ -1928,7 +1709,7 @@ function file.split_path(str)
end
function file.join_path(tab)
- return table.concat(tab,io.pathseparator) -- can have trailing //
+ return concat(tab,io.pathseparator) -- can have trailing //
end
function file.collapse_path(str)
@@ -2098,30 +1879,6 @@ if lfs then do
dir.glob_pattern = glob_pattern
- --~ local function glob(pattern, action)
- --~ local t = { }
- --~ local path, rest, patt, recurse
- --~ local action = action or function(name) t[#t+1] = name end
- --~ local pattern = pattern:gsub("^%*%*","./**")
- --~ local pattern = pattern:gsub("/%*/","/**/")
- --~ path, rest = pattern:match("^(/)(.-)$")
- --~ if path then
- --~ path = path
- --~ else
- --~ path, rest = pattern:match("^([^/]*)/(.-)$")
- --~ end
- --~ if rest then
- --~ patt = rest:gsub("([%.%-%+])", "%%%1")
- --~ end
- --~ patt = patt:gsub("%*", "[^/]*")
- --~ patt = patt:gsub("%?", "[^/]")
- --~ patt = patt:gsub("%[%^/%]%*%[%^/%]%*", ".*")
- --~ if path == "" then path = "." end
- --~ recurse = patt:find("%.%*/") ~= nil
- --~ glob_pattern(path,patt,recurse,action)
- --~ return t
- --~ end
-
local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V
local pattern = Ct {
@@ -2444,6 +2201,35 @@ function boolean.falsetrue()
end
+-- filename : l-math.lua
+-- comment : split off from luat-lib
+-- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+-- copyright: PRAGMA ADE / ConTeXt Development Team
+-- license : see context related readme files
+
+if not versions then versions = { } end versions['l-math'] = 1.001
+
+local floor = math.floor
+
+if not math.round then
+ function math.round(x)
+ return floor(x + 0.5)
+ end
+end
+
+if not math.div then
+ function math.div(n,m)
+ return floor(n/m)
+ end
+end
+
+if not math.mod then
+ function math.mod(n,m)
+ return n % m
+ end
+end
+
+
if not modules then modules = { } end modules ['l-xml'] = {
version = 1.001,
comment = "this module is the basis for the lxml-* ones",
@@ -2487,11 +2273,11 @@ xml.trace_lpath = false
xml.trace_print = false
xml.trace_remap = false
-local format, concat = string.format, table.concat
+local format, concat, remove, insert, type, next = string.format, table.concat, table.remove, table.insert, type, next
--~ local pairs, next, type = pairs, next, type
--- todo: some things per xml file, liek namespace remapping
+-- todo: some things per xml file, like namespace remapping
--[[ldx--
<p>First a hack to enable namespace resolving. A namespace is characterized by
@@ -2600,7 +2386,7 @@ do
-- not just one big nested table capture (lpeg overflow)
- local remove, nsremap, resolvens = table.remove, xml.xmlns, xml.resolvens
+ local nsremap, resolvens = xml.xmlns, xml.resolvens
local stack, top, dt, at, xmlns, errorstr, entities = {}, {}, {}, {}, {}, nil, {}
@@ -3091,8 +2877,8 @@ do
end
end
if not found then
- table.insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- table.insert(dt, 2, "\n" )
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
end
@@ -3235,9 +3021,11 @@ local lpathcached = 0 -- statisctics
do
- xml.functions = xml.functions or { }
+ xml.functions = xml.functions or { }
+ xml.expressions = xml.expressions or { }
- local functions = xml.functions
+ local functions = xml.functions
+ local expressions = xml.expressions
local actions = {
[10] = "stay",
@@ -3261,34 +3049,32 @@ do
[40] = "processing instruction",
}
- --~ local function make_expression(str) --could also be an lpeg
- --~ str = str:gsub("@([a-zA-Z%-_]+)", "(a['%1'] or '')")
- --~ str = str:gsub("position%(%)", "i")
- --~ str = str:gsub("text%(%)", "t")
- --~ str = str:gsub("!=", "~=")
- --~ str = str:gsub("([^=!~<>])=([^=!~<>])", "%1==%2")
- --~ str = str:gsub("([a-zA-Z%-_]+)%(", "functions.%1(")
- --~ return str, loadstring(format("return function(functions,i,a,t) return %s end", str))()
- --~ end
-
-- a rather dumb lpeg
local P, S, R, C, V, Cc = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc
- local lp_position = P("position()") / "id"
+ -- instead of using functions we just parse a few names which saves a call
+ -- later on
+
+ local lp_position = P("position()") / "ps"
+ local lp_index = P("index()") / "id"
local lp_text = P("text()") / "tx"
- local lp_name = P("name()") / "((rt.ns~='' and rt.ns..':'..rt.tg) or '')"
- local lp_tag = P("tag()") / "(rt.tg or '')"
- local lp_ns = P("ns()") / "(rt.ns or '')"
+ local lp_name = P("name()") / "(ns~='' and ns..':'..tg)" -- "((rt.ns~='' and rt.ns..':'..rt.tg) or '')"
+ local lp_tag = P("tag()") / "tg" -- (rt.tg or '')
+ local lp_ns = P("ns()") / "ns" -- (rt.ns or '')
local lp_noequal = P("!=") / "~=" + P("<=") + P(">=") + P("==")
local lp_doequal = P("=") / "=="
local lp_attribute = P("@") / "" * Cc("(at['") * R("az","AZ","--","__")^1 * Cc("'] or '')")
- local lp_function = C(R("az","AZ","--","__")^1) * P("(") / function(t)
- if functions[t] then
- return "functions." .. t .. "("
+ local lp_lua_function = C(R("az","AZ","--","__")^1 * (P(".") * R("az","AZ","--","__")^1)^1) * P("(") / function(t) -- todo: better . handling
+ return t .. "("
+ end
+
+ local lp_function = C(R("az","AZ","--","__")^1) * P("(") / function(t) -- todo: better . handling
+ if expressions[t] then
+ return "expressions." .. t .. "("
else
- return "functions.error("
+ return "expressions.error("
end
end
@@ -3296,34 +3082,45 @@ do
local rparent = lpeg.P(")")
local noparent = 1 - (lparent+rparent)
local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
- local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent)
+ local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
---~ local value = P { "(" * C(((1 - S("()")) + V(1))^0) * ")" }
+ -- if we use a dedicated namespace then we don't need to pass rt and k
local lp_special = (C(P("name")+P("text")+P("tag"))) * value / function(t,s)
- if functions[t] then
+ if expressions[t] then
if s then
- return "functions." .. t .. "(rt,k," .. s ..")"
+ return "expressions." .. t .. "(r,k," .. s ..")"
else
- return "functions." .. t .. "(rt,k)"
+ return "expressions." .. t .. "(r,k)"
end
else
- return "functions.error(" .. t .. ")"
+ return "expressions.error(" .. t .. ")"
end
end
local converter = lpeg.Cs ( (
lp_position +
+ lp_index +
lp_text + lp_name + -- fast one
lp_special +
lp_noequal + lp_doequal +
lp_attribute +
+ lp_lua_function +
lp_function +
1 )^1 )
+ -- expressions,root,rootdt,k,e,edt,ns,tg,idx,hsh[tg] or 1
+
+ local template = [[
+ return function(expressions,r,d,k,e,dt,ns,tg,id,ps)
+ local at, tx = e.at or { }, dt[1] or ""
+ return %s
+ end
+ ]]
+
local function make_expression(str)
str = converter:match(str)
- return str, loadstring(format("return function(functions,id,at,tx,rt,k) return %s end", str))()
+ return str, loadstring(format(template,str))()
end
local map = { }
@@ -3433,7 +3230,7 @@ do
local selector = (
instruction +
- many + any +
+--~ many + any + -- brrr, not here !
parent + stay +
dont_position + position +
dont_match_one_of_and_eq + dont_match_one_of_and_ne +
@@ -3445,6 +3242,7 @@ do
has_attribute + has_value +
dont_match_one_of + match_one_of +
dont_match + match +
+ many + any +
crap + empty
)
@@ -3481,7 +3279,7 @@ do
return { map[2] }
end
if m ~= 11 and m ~= 12 and m ~= 13 and m ~= 14 and m ~= 15 and m ~= 16 then
- table.insert(map, 1, { 16 })
+ insert(map, 1, { 16 })
end
-- print((table.serialize(map)):gsub("[ \n]+"," "))
return map
@@ -3580,22 +3378,25 @@ functions.</p>
do
- local functions = xml.functions
+ local functions = xml.functions
+ local expressions = xml.expressions
- functions.contains = string.find
- functions.find = string.find
- functions.upper = string.upper
- functions.lower = string.lower
- functions.number = tonumber
- functions.boolean = toboolean
+ expressions.contains = string.find
+ expressions.find = string.find
+ expressions.upper = string.upper
+ expressions.lower = string.lower
+ expressions.number = tonumber
+ expressions.boolean = toboolean
- functions.oneof = function(s,...) -- slow
+ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
- functions.error = function(str)
- xml.error_handler("unknown function in lpath expression",str)
+
+ expressions.error = function(str)
+ xml.error_handler("unknown function in lpath expression",str or "?")
return false
end
+
functions.text = function(root,k,n) -- unchecked, maybe one deeper
local t = type(t)
if t == "string" then
@@ -3605,6 +3406,7 @@ do
return (rdt and rdt[k]) or root[k] or ""
end
end
+
functions.name = function(d,k,n) -- ns + tg
local found = false
n = n or 0
@@ -3649,6 +3451,7 @@ do
return ""
end
end
+
functions.tag = function(d,k,n) -- only tg
local found = false
n = n or 0
@@ -3685,6 +3488,10 @@ do
return (found and found.tg) or ""
end
+ expressions.text = functions.text
+ expressions.name = functions.name
+ expressions.tag = functions.tag
+
local function traverse(root,pattern,handle,reverse,index,parent,wildcard) -- multiple only for tags, not for namespaces
if not root then -- error
return false
@@ -3757,10 +3564,13 @@ do
start, stop, step = stop, start, -1
end
local idx = 0
+ local hsh = { } -- this will slooow down the lot
for k=start,stop,step do -- we used to have functions for all but a case is faster
local e = rootdt[k]
local ns, tg = e.rn or e.ns, e.tg
if tg then
+ -- we can optimize this for simple searches, but it probably does not pay off
+ hsh[tg] = (hsh[tg] or 0) + 1
idx = idx + 1
if command == 30 then
local ns_a, tg_a = action[3], action[4]
@@ -3883,7 +3693,7 @@ do
end
if not action[2] then matched = not matched end
if matched then
- matched = action[6](functions,idx,e.at or { },edt[1],rootdt,k)
+ matched = action[6](expressions,root,rootdt,k,e,edt,ns,tg,idx,hsh[tg] or 1)
end
end
if matched then -- combine tg test and at test
@@ -4358,10 +4168,10 @@ do
local r, d, k, element = m[1], m[2], m[3], m[4]
if not before then k = k + 1 end
if element.tg then
- table.insert(d,k,element) -- untested
+ insert(d,k,element) -- untested
elseif element.dt then
for _,v in ipairs(element.dt) do -- i added
- table.insert(d,k,v)
+ insert(d,k,v)
k = k + 1
end
end
@@ -4449,7 +4259,7 @@ do
xml.each_element(xmldata, pattern, include)
end
- function xml.strip_whitespace(root, pattern) -- strips all leading and trailing space !
+ function xml.strip_whitespace(root, pattern, nolines) -- strips all leading and trailing space !
traverse(root, lpath(pattern), function(r,d,k)
local dkdt = d[k].dt
if dkdt then -- can be optimized
@@ -4457,11 +4267,18 @@ do
for i=1,#dkdt do
local str = dkdt[i]
if type(str) == "string" then
- str = str:gsub("^[ \n\r\t]*(.-)[ \n\r\t]*$","%1")
+
if str == "" then
-- stripped
else
- t[#t+1] = str
+ if nolines then
+ str = str:gsub("[ \n\r\t]+"," ")
+ end
+ if str == "" then
+ -- stripped
+ else
+ t[#t+1] = str
+ end
end
else
t[#t+1] = str
@@ -4853,8 +4670,11 @@ utils.merger.strip_comment = true
function utils.merger._self_load_(name)
local f, data = io.open(name), ""
if f then
+ utils.report("reading merge from %s",name)
data = f:read("*all")
f:close()
+ else
+ utils.report("unknown file to merge %s",name)
end
if data and utils.merger.strip_comment then
-- saves some 20K
@@ -4867,6 +4687,7 @@ function utils.merger._self_save_(name, data)
if data ~= "" then
local f = io.open(name,'w')
if f then
+ utils.report("saving merge from %s",name)
f:write(data)
f:close()
end
@@ -4892,13 +4713,13 @@ function utils.merger._self_libs_(libs,list)
local name = string.gsub(pth .. "/" .. lib,"\\","/")
f = io.open(name)
if f then
- -- utils.report("merging library",name)
+ utils.report("merging library %s",name)
result[#result+1] = f:read("*all")
f:close()
list = { pth } -- speed up the search
break
else
- -- utils.report("no library",name)
+ utils.report("no library %s",name)
end
end
end
@@ -5013,7 +4834,7 @@ function environment.setargument(name,value)
environment.arguments[name] = value
end
-function environment.argument(name)
+function environment.argument(name) -- todo: default (plus typecheck on default)
local arguments, sortedflags = environment.arguments, environment.sortedflags
if arguments[name] then
return arguments[name]
@@ -5048,30 +4869,85 @@ function environment.split_arguments(separator) -- rather special, cut-off befor
return before, after
end
-function environment.reconstruct_commandline(arg)
+--~ function environment.reconstruct_commandline(arg)
+--~ if not arg then arg = environment.original_arguments end
+--~ local result = { }
+--~ for _,a in ipairs(arg) do -- ipairs 1 .. #n
+--~ local kk, vv = a:match("^(%-+.-)=(.+)$")
+--~ if kk and vv then
+--~ if vv:find(" ") then
+--~ vv = vv:unquote()
+--~ vv = vv:gsub('"','\\"')
+--~ result[#result+1] = kk .. "=" .. vv:quote()
+--~ else
+--~ a = a:unquote()
+--~ a = a:gsub('"','\\"')
+--~ result[#result+1] = a
+--~ end
+--~ elseif a:find(" ") then
+--~ a = a:unquote()
+--~ a = a:gsub('"','\\"')
+--~ result[#result+1] = a:quote()
+--~ else
+--~ result[#result+1] = a
+--~ end
+--~ end
+--~ return table.join(result," ")
+--~ end
+
+function environment.reconstruct_commandline(arg,noquote)
if not arg then arg = environment.original_arguments end
- local result = { }
- for _,a in ipairs(arg) do -- ipairs 1 .. #n
- local kk, vv = a:match("^(%-+.-)=(.+)$")
- if kk and vv then
- if vv:find(" ") then
- result[#result+1] = kk .. "=" .. string.quote(vv)
+ if noquote and #arg == 1 then
+ local a = arg[1]
+ a = input.resolve(a)
+ a = a:unquote()
+ return a
+ elseif #arg == 1 then
+ local result = { }
+ for _,a in ipairs(arg) do -- ipairs 1 .. #n
+ a = input.resolve(a)
+ a = a:unquote()
+ a = a:gsub('"','\\"') -- tricky
+ if a:find(" ") then
+ result[#result+1] = a:quote()
else
result[#result+1] = a
end
- elseif a:find(" ") then
- result[#result+1] = string.quote(a)
- else
- result[#result+1] = a
end
+ return table.join(result," ")
end
- return table.join(result," ")
end
if arg then
- environment.initialize_arguments(arg)
- environment.original_arguments = arg
+
+ -- new, reconstruct quoted snippets (maybe better just remnove the " then and add them later)
+ local newarg, instring = { }, false
+
+ for index, argument in ipairs(arg) do
+ if argument:find("^\"") then
+ newarg[#newarg+1] = argument:gsub("^\"","")
+ if not argument:find("\"$") then
+ instring = true
+ end
+ elseif argument:find("\"$") then
+ newarg[#newarg] = newarg[#newarg] .. " " .. argument:gsub("\"$","")
+ instring = false
+ elseif instring then
+ newarg[#newarg] = newarg[#newarg] .. " " .. argument
+ else
+ newarg[#newarg+1] = argument
+ end
+ end
+ for i=1,-5,-1 do
+ newarg[i] = arg[i]
+ end
+
+ environment.initialize_arguments(newarg)
+ environment.original_arguments = newarg
+ environment.raw_arguments = arg
+
arg = { } -- prevent duplicate handling
+
end
@@ -5114,7 +4990,7 @@ if not input.hashers then input.hashers = { } end -- load databases
if not input.generators then input.generators = { } end -- generate databases
if not input.filters then input.filters = { } end -- conversion filters
-local format = string.format
+local format, concat, sortedkeys = string.format, table.concat, table.sortedkeys
input.locators.notfound = { nil }
input.hashers.notfound = { nil }
@@ -5918,8 +5794,6 @@ function input.serialize(files)
-- luatools and mtxtools are called frequently. Okay,
-- we pay a small price for properly tabbed tables.
local t = { }
- local concat = table.concat
- local sorted = table.sortedkeys
local function dump(k,v,m)
if type(v) == 'string' then
return m .. "['" .. k .. "']='" .. v .. "',"
@@ -5931,11 +5805,11 @@ function input.serialize(files)
end
t[#t+1] = "return {"
if input.instance.sortdata then
- for _, k in pairs(sorted(files)) do
+ for _, k in pairs(sortedkeys(files)) do
local fk = files[k]
if type(fk) == 'table' then
t[#t+1] = "\t['" .. k .. "']={"
- for _, kk in pairs(sorted(fk)) do
+ for _, kk in pairs(sortedkeys(fk)) do
t[#t+1] = dump(kk,fk[kk],"\t\t")
end
t[#t+1] = "\t},"
@@ -6407,7 +6281,6 @@ end
function input.aux.splitpathexpr(str, t, validate)
-- no need for optimization, only called a few times, we can use lpeg for the sub
t = t or { }
- local concat = table.concat
str = str:gsub(",}",",@}")
str = str:gsub("{,","{@,")
-- str = "@" .. str .. "@"
@@ -6732,7 +6605,7 @@ function input.aux.find_file(filename) -- todo : plugin (scanners, checkers etc)
if input.trace > 2 then
input.logger('? filename: %s',filename)
input.logger('? filetype: %s',filetype or '?')
- input.logger('? wanted files: %s',table.concat(wantedfiles," | "))
+ input.logger('? wanted files: %s',concat(wantedfiles," | "))
end
for _, fname in pairs(wantedfiles) do
if fname and input.is_readable.file(fname) then
@@ -6755,8 +6628,8 @@ function input.aux.find_file(filename) -- todo : plugin (scanners, checkers etc)
local doscan, recurse
if input.trace > 2 then
input.logger('? filename: %s',filename)
- -- if pathlist then input.logger('? path list: %s',table.concat(pathlist," | ")) end
- -- if filelist then input.logger('? file list: %s',table.concat(filelist," | ")) end
+ -- if pathlist then input.logger('? path list: %s',concat(pathlist," | ")) end
+ -- if filelist then input.logger('? file list: %s',concat(filelist," | ")) end
end
-- a bit messy ... esp the doscan setting here
for _, path in pairs(pathlist) do
@@ -6965,6 +6838,8 @@ function input.find_wildcard_files(filename) -- todo: remap:
if done and not allresults then break end
end
end
+ -- we can consider also searching the paths not in the database, but then
+ -- we end up with a messy search (all // in all path specs)
return result
end
@@ -6985,7 +6860,7 @@ function input.save_used_files_in_trees(filename,jobname)
f:write("\t<rl:name>" .. jobname .. "</rl:name>\n")
end
f:write("\t<rl:files>\n")
- for _,v in pairs(table.sortedkeys(instance.foundintrees)) do
+ for _,v in pairs(sorted(instance.foundintrees)) do -- ipairs
f:write("\t\t<rl:file n='" .. instance.foundintrees[v] .. "'>" .. v .. "</rl:file>\n")
end
f:write("\t</rl:files>\n")
@@ -7091,7 +6966,7 @@ function table.sequenced(t,sep) -- temp here
for k, v in pairs(t) do
s[#s+1] = k .. "=" .. v
end
- return table.concat(s, sep or " | ")
+ return concat(s, sep or " | ")
end
function input.methodhandler(what, filename, filetype) -- ...
@@ -7327,7 +7202,7 @@ do
str[k] = resolve(v) or v
end
elseif str and str ~= "" then
- str = str:gsub("([a-z]+):([^ ]*)", function(method,target)
+ str = str:gsub("([a-z]+):([^ \"\']*)", function(method,target)
if resolvers[method] then
return resolvers[method](target)
else
@@ -7351,7 +7226,7 @@ do
end
function input.boolean_variable(str,default)
- local b = input.expansion("PURGECACHE")
+ local b = input.expansion(str)
if b == "" then
return default
else
@@ -7492,6 +7367,14 @@ function input.reportlines(str) -- todo: <lines></lines>
end
end
+input.moreinfo = [[
+more information about ConTeXt and the tools that come with it can be found at:
+
+maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
+wiki : http://contextgarden.net
+]]
+
function input.help(banner,message)
if not input.verbose then
input.verbose = true
@@ -7500,6 +7383,10 @@ function input.help(banner,message)
input.report(banner,"\n")
input.report("")
input.reportlines(message)
+ if input.moreinfo and input.moreinfo ~= "" then
+ input.report("")
+ input.reportlines(input.moreinfo)
+ end
end
logs.set_level('error')
@@ -7665,16 +7552,6 @@ function caches.is_writable(filepath,filename)
return file.is_writable(tmaname)
end
-function input.boolean_variable(str,default)
- local b = input.expansion("PURGECACHE")
- if b == "" then
- return default
- else
- b = toboolean(b)
- return (b == nil and default) or b
- end
-end
-
function caches.savedata(filepath,filename,data,raw)
local tmaname, tmcname = caches.setluanames(filepath,filename)
local reduce, simplify = true, true
@@ -7880,7 +7757,7 @@ input.storage.data = { }
input.storage.min = 0 -- 500
input.storage.max = input.storage.min - 1
input.storage.trace = false -- true
-input.storage.done = 0
+input.storage.done = input.storage.done or 0
input.storage.evaluators = { }
-- (evaluate,message,names)
@@ -7938,6 +7815,8 @@ function input.storage.dump()
end
end
+-- we also need to count at generation time (nicer for message)
+
if lua.bytecode then -- from 0 upwards
local i = input.storage.min
while lua.bytecode[i] do
@@ -8080,6 +7959,14 @@ function input.reportlines(str) -- todo: <lines></lines>
end
end
+input.moreinfo = [[
+more information about ConTeXt and the tools that come with it can be found at:
+
+maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
+wiki : http://contextgarden.net
+]]
+
function input.help(banner,message)
if not input.verbose then
input.verbose = true
@@ -8088,6 +7975,10 @@ function input.help(banner,message)
input.report(banner,"\n")
input.report("")
input.reportlines(message)
+ if input.moreinfo and input.moreinfo ~= "" then
+ input.report("")
+ input.reportlines(input.moreinfo)
+ end
end
logs.set_level('error')
@@ -8294,6 +8185,7 @@ own.libs = { -- todo: check which ones are really needed
'l-file.lua',
'l-dir.lua',
'l-boolean.lua',
+ 'l-math.lua',
'l-xml.lua',
-- 'l-unicode.lua',
'l-utils.lua',
@@ -8358,15 +8250,11 @@ if not input then
end
input.instance = input.reset()
-input.verbose = environment.argument("verbose") or false
input.banner = 'MtxRun'
utils.report = input.report
local instance = input.instance
-instance.engine = environment.argument("engine") or 'luatex'
-instance.progname = environment.argument("progname") or 'context'
-instance.lsrmode = environment.argument("lsr") or false
-- use os.env or environment when available
@@ -8509,6 +8397,8 @@ function os.currentplatform(name, default)
local architecture = os.arch()
if architecture:find("x86_64") then
return "linux-64"
+ elseif architecture:find("ppc") then
+ return "linux-ppc"
else
return "linux"
end
@@ -8550,7 +8440,7 @@ input.runners.registered = {
mptopdf = { 'mptopdf.pl', true },
pstopdf = { 'pstopdf.rb', true },
- examplex = { 'examplex.rb', false },
+-- examplex = { 'examplex.rb', false },
concheck = { 'concheck.rb', false },
runtools = { 'runtools.rb', true },
@@ -8571,8 +8461,8 @@ input.runners.registered = {
if not messages then messages = { } end
messages.help = [[
---script run an mtx script
---execute run a script or program
+--script run an mtx script (--noquotes)
+--execute run a script or program (--noquotes)
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--locate locate given filename
@@ -8661,6 +8551,7 @@ end
function input.runners.execute_script(fullname,internal)
local instance = input.instance
+ local noquote = environment.argument("noquotes")
if fullname and fullname ~= "" then
local state = input.runners.prepare()
if state == 'error' then
@@ -8709,7 +8600,7 @@ function input.runners.execute_script(fullname,internal)
result = binary .. " " .. result
end
local before, after = environment.split_arguments(fullname)
- local command = result .. " " .. environment.reconstruct_commandline(after)
+ local command = result .. " " .. environment.reconstruct_commandline(after,noquote)
input.report("")
input.report("executing: %s",command)
input.report("\n \n")
@@ -8724,6 +8615,7 @@ function input.runners.execute_script(fullname,internal)
end
function input.runners.execute_program(fullname)
+ local noquote = environment.argument("noquotes")
if fullname and fullname ~= "" then
local state = input.runners.prepare()
if state == 'error' then
@@ -8734,7 +8626,7 @@ function input.runners.execute_program(fullname)
local before, after = environment.split_arguments(fullname)
environment.initialize_arguments(after)
fullname = fullname:gsub("^bin:","")
- local command = fullname .. " " .. environment.reconstruct_commandline(after)
+ local command = fullname .. " " .. (environment.reconstruct_commandline(after or "",noquote) or "")
input.report("")
input.report("executing: %s",command)
input.report("\n \n")
@@ -8813,11 +8705,17 @@ function input.runners.report_location(result)
end
end
-function input.runners.edit_script(filename)
- local editor = os.getenv("MTXRUN_EDITOR") or os.getenv("TEXMFSTART_EDITOR") or os.getenv("EDITOR") or 'scite'
+function input.runners.edit_script(filename) -- we assume that vim is present on most systems
+ local editor = os.getenv("MTXRUN_EDITOR") or os.getenv("TEXMFSTART_EDITOR") or os.getenv("EDITOR") or 'vim'
local rest = input.resolve(filename)
if rest ~= "" then
- os.launch(editor .. " " .. rest)
+ local command = editor .. " " .. rest
+ if input.verbose then
+ input.report("")
+ input.report("starting editor: %s",command)
+ input.report("\n \n")
+ end
+ os.launch(command)
end
end
@@ -8894,7 +8792,7 @@ function input.runners.launch_file(filename)
end
end
-function input.runners.execute_ctx_script(filename,arguments)
+function input.runners.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
if path and path ~= "" then
@@ -8904,27 +8802,45 @@ function input.runners.execute_ctx_script(filename,arguments)
return io.exists(fullname) and fullname
end
end
- local suffix = ""
- if not filename:find("%.lua$") then suffix = ".lua" end
- local fullname = filename
- -- just <filename>
- fullname = filename .. suffix
- fullname = input.find_file(fullname)
- -- mtx-<filename>
- if not fullname or fullname == "" then
- fullname = "mtx-" .. filename .. suffix
- fullname = found(fullname) or input.find_file(fullname)
+ filename = file.addsuffix(filename,"lua")
+ local basename = file.stripsuffix(file.basename(filename))
+ local suffix = file.extname(filename)
+ -- qualified path, raw name
+ local fullname = input.aux.qualified_path(filename) and io.exists(filename) and filename
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- current path, raw name
+ fullname = "./" .. filename
+ fullname = io.exists(fullname) and fullname
+ if fullname and fullname ~= "" then
+ return fullname
end
- -- mtx-<filename>s
- if not fullname or fullname == "" then
- fullname = "mtx-" .. filename .. "s" .. suffix
- fullname = found(fullname) or input.find_file(fullname)
+ -- context namespace, mtx-<filename>
+ fullname = "mtx-" .. filename
+ fullname = found(fullname) or input.find_file(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = "mtx-" .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or input.find_file(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
end
- -- mtx-<filename minus trailing s>
- if not fullname or fullname == "" then
- fullname = "mtx-" .. filename:gsub("s$","") .. suffix
- fullname = found(fullname) or input.find_file(fullname)
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = "mtx-" .. basename:gsub("s$","") .. "." .. suffix
+ fullname = found(fullname) or input.find_file(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
end
+ -- context namespace, just <filename>
+ fullname = input.find_file(fullname)
+ return fullname
+end
+
+function input.runners.execute_ctx_script(filename,arguments)
+ local fullname = input.runners.find_mtx_script(filename)
-- that should do it
if fullname and fullname ~= "" then
local state = input.runners.prepare()
@@ -8957,10 +8873,13 @@ function input.runners.execute_ctx_script(filename,arguments)
end
else
input.verbose = true
+ filename = file.addsuffix(filename,"lua")
if filename == "" then
- input.report("unknown script")
+ input.report("unknown script, no name given")
+ elseif input.aux.qualified_path(filename) then
+ input.report("unknown script '%s'",filename)
else
- input.report("unknown script: %s",filename)
+ input.report("unknown script '%s' or 'mtx-%s'",filename,filename)
end
return false
end
@@ -8976,12 +8895,14 @@ local filename = environment.files[1] or ""
local ok = true
local before, after = environment.split_arguments(filename)
+environment.initialize_arguments(before)
-input.runners.my_prepare_b()
-before = input.resolve(before) -- experimental here
-after = input.resolve(after) -- experimental here
+instance.engine = environment.argument("engine") or 'luatex'
+instance.progname = environment.argument("progname") or 'context'
+instance.lsrmode = environment.argument("lsr") or false
+input.verbose = environment.argument("verbose") or false
-environment.initialize_arguments(before)
+input.runners.my_prepare_b()
if environment.argument("selfmerge") then
-- embed used libraries
@@ -9027,11 +8948,10 @@ elseif environment.argument("platform")then
elseif environment.argument("help") or filename=='help' or filename == "" then
input.help(banner,messages.help)
-- execute script
- if filename:find("^bin:") then
- ok = input.runners.execute_program(filename)
- else
- ok = input.runners.execute_script(filename)
- end
+elseif filename:find("^bin:") then
+ ok = input.runners.execute_program(filename)
+else
+ ok = input.runners.execute_script(filename)
end
if os.platform == "unix" then