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.lua3004
1 files changed, 1749 insertions, 1255 deletions
diff --git a/scripts/context/lua/mtxrun.lua b/scripts/context/lua/mtxrun.lua
index 040214178..45a881839 100644
--- a/scripts/context/lua/mtxrun.lua
+++ b/scripts/context/lua/mtxrun.lua
@@ -37,9 +37,10 @@ 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.0.2 - 2007+ - PRAGMA ADE / CONTEXT"
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
@@ -125,7 +126,7 @@ end
function string:splitchr(chr)
if #self > 0 then
local t = { }
- for s in string.gmatch(self..chr,"(.-)"..chr) do
+ for s in (self..chr):gmatch("(.-)"..chr) do
t[#t+1] = s
end
return t
@@ -134,22 +135,6 @@ function string:splitchr(chr)
end
end
---~ function string.piecewise(str, pat, fnc) -- variant of split
---~ local fpat = "(.-)"..pat
---~ local last_end = 1
---~ local s, e, cap = string.find(str, fpat, 1)
---~ while s ~= nil do
---~ if s~=1 or cap~="" then
---~ fnc(cap)
---~ end
---~ last_end = e+1
---~ s, e, cap = string.find(str, fpat, last_end)
---~ end
---~ if last_end <= #str then
---~ fnc((string.sub(str,last_end)))
---~ end
---~ end
-
function string.piecewise(str, pat, fnc) -- variant of split
for k in string.splitter(str,pat) do fnc(k) end
end
@@ -668,35 +653,283 @@ function table.starts_at(t)
return ipairs(t,1)(t,0)
end
-do
+--~ 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
- -- one of my first exercises in lua ...
-
- -- 34.055.092 32.403.326 arabtype.tma
- -- 1.620.614 1.513.863 lmroman10-italic.tma
- -- 1.325.585 1.233.044 lmroman10-regular.tma
- -- 1.248.157 1.158.903 lmsans10-regular.tma
- -- 194.646 153.120 lmtypewriter10-regular.tma
- -- 1.771.678 1.658.461 palatinosanscom-bold.tma
- -- 1.695.251 1.584.491 palatinosanscom-regular.tma
- -- 13.736.534 13.409.446 zapfinoextraltpro.tma
-
- -- 13.679.038 11.774.106 arabtype.tmc
- -- 886.248 754.944 lmroman10-italic.tmc
- -- 729.828 466.864 lmroman10-regular.tmc
- -- 688.482 441.962 lmsans10-regular.tmc
- -- 128.685 95.853 lmtypewriter10-regular.tmc
- -- 715.929 582.985 palatinosanscom-bold.tmc
- -- 669.942 540.126 palatinosanscom-regular.tmc
- -- 1.560.588 1.317.000 zapfinoextraltpro.tmc
+--~ 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
+--~ }
+
+--~ print(table.serialize(t), "\n")
+--~ print(table.serialize(t,"name"), "\n")
+--~ print(table.serialize(t,false), "\n")
+--~ print(table.serialize(t,true), "\n")
+--~ 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
+ 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 function key(k)
if type(k) == "number" then -- or k:find("^%d+$") then
- return "["..k.."]"
+ if hexify then
+ return ("[0x%04X]"):format(k)
+ else
+ return "["..k.."]"
+ end
elseif noquotes and k:find("^%a[%a%d%_]*$") then
return k
else
@@ -715,7 +948,13 @@ do
for i=1,#t do
local v = t[i]
local tv = type(v)
- if tv == "number" or tv == "boolean" then
+ 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)
@@ -730,53 +969,38 @@ do
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
+ local function do_serialize(root,name,depth,level,indexed)
+ if level > 0 then
depth = depth .. " "
if indexed then
handle(("%s{"):format(depth))
- else
+ elseif name then
handle(("%s%s={"):format(depth,key(name)))
- 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={")
+ handle(("%s{"):format(depth))
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 (why)
+ 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
+ --~ 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
- handle(("%s %s,"):format(depth,v))
+ 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))
@@ -789,17 +1013,17 @@ do
elseif inline then
local st = simple_table(v)
if st then
- handle(("%s { %s },"):format(depth,table.concat(st,", ")))
+ handle(("%s { %s },"):format(depth,concat(st,", ")))
else
- serialize(v,k,handle,depth,level+1,reduce,noquotes,true)
+ do_serialize(v,k,depth,level+1,true)
end
else
- serialize(v,k,handle,depth,level+1,reduce,noquotes,true)
+ 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 table.serialize_functions then
+ if functions then
handle(('%s loadstring(%q),'):format(depth,string.dump(v)))
else
handle(('%s "function",'):format(depth))
@@ -812,7 +1036,11 @@ do
handle(("%s __p__=nil,"):format(depth))
end
elseif t == "number" then
- handle(("%s %s=%s,"):format(depth,key(k),v))
+ 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))
@@ -825,17 +1053,17 @@ do
elseif inline then
local st = simple_table(v)
if st then
- handle(("%s %s={ %s },"):format(depth,key(k),table.concat(st,", ")))
+ handle(("%s %s={ %s },"):format(depth,key(k),concat(st,", ")))
else
- serialize(v,k,handle,depth,level+1,reduce,noquotes)
+ do_serialize(v,k,depth,level+1)
end
else
- serialize(v,k,handle,depth,level+1,reduce,noquotes)
+ 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 table.serialize_functions then
+ if functions then
handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(v)))
else
handle(('%s %s="function",'):format(depth,key(k)))
@@ -845,14 +1073,46 @@ do
-- 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
+ 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(("%s}"):format(depth))
+ handle("{")
end
else
- handle(("%s}"):format(depth))
+ handle("t={")
+ end
+ if root and next(root) then
+ do_serialize(root,name,"",0,indexed)
end
+ handle("}")
end
--~ name:
@@ -864,17 +1124,17 @@ do
--~ 'return' : return { }
--~ number : [number] = { }
- function table.serialize(root,name,reduce,noquotes)
+ function table.serialize(root,name,reduce,noquotes,hexify)
local t = { }
local function flush(s)
t[#t+1] = s
end
- serialize(root, name, flush, nil, 0, reduce, noquotes)
- return table.concat(t,"\n")
+ serialize(root,name,flush,reduce,noquotes,hexify)
+ return concat(t,"\n")
end
- function table.tohandle(handle,root,name,reduce,noquotes)
- serialize(root, name, handle, nil, 0, reduce, noquotes)
+ function table.tohandle(handle,root,name,reduce,noquotes,hexify)
+ serialize(root,name,handle,reduce,noquotes,hexify)
end
-- sometimes tables are real use (zapfino extra pro is some 85M) in which
@@ -888,10 +1148,9 @@ do
table.tofile_maxtab = 2*1024
- function table.tofile(filename,root,name,reduce,noquotes)
+ function table.tofile(filename,root,name,reduce,noquotes,hexify)
local f = io.open(filename,'w')
if f then
- local concat = table.concat
local maxtab = table.tofile_maxtab
if maxtab > 1 then
local t = { }
@@ -902,13 +1161,13 @@ do
t = { }
end
end
- serialize(root, name, flush, nil, 0, reduce, noquotes)
+ 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, nil, 0, reduce, noquotes)
+ serialize(root,name,flush,reduce,noquotes,hexify)
end
f:close()
end
@@ -916,35 +1175,6 @@ do
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
---~ }
-
---~ print(table.serialize(t), "\n")
---~ print(table.serialize(t,"name"), "\n")
---~ print(table.serialize(t,false), "\n")
---~ print(table.serialize(t,true), "\n")
---~ print(table.serialize(t,"name",true), "\n")
---~ print(table.serialize(t,"name",true,true), "\n")
-
do
local function flatten(t,f,complete)
@@ -1135,7 +1365,7 @@ function io.loaddata(filename)
end
function io.savedata(filename,data,joiner)
- local f = io.open(filename, "wb")
+ local f = io.open(filename,"wb")
if f then
if type(data) == "table" then
f:write(table.join(data,joiner or ""))
@@ -1145,6 +1375,9 @@ function io.savedata(filename,data,joiner)
f:write(data)
end
f:close()
+ return true
+ else
+ return false
end
end
@@ -1499,6 +1732,9 @@ end
-- copyright: PRAGMA ADE / ConTeXt Development Team
-- license : see context related readme files
+
+--~ print(table.serialize(os.uname()))
+
if not versions then versions = { } end versions['l-os'] = 1.001
function os.resultof(command)
@@ -1575,9 +1811,11 @@ if not versions then versions = { } end versions['l-file'] = 1.001
if not file then file = { } end
function file.removesuffix(filename)
- return filename:gsub("%.[%a%d]+$", "")
+ return (filename:gsub("%.[%a%d]+$",""))
end
+file.stripsuffix = file.removesuffix
+
function file.addsuffix(filename, suffix)
if not filename:find("%.[%a%d]+$") then
return filename .. "." .. suffix
@@ -1587,11 +1825,7 @@ function file.addsuffix(filename, suffix)
end
function file.replacesuffix(filename, suffix)
- if not filename:find("%.[%a%d]+$") then
- return filename .. "." .. suffix
- else
- return (filename:gsub("%.[%a%d]+$","."..suffix))
- end
+ return (filename:gsub("%.[%a%d]+$","")) .. "." .. suffix
end
function file.dirname(name)
@@ -1612,10 +1846,6 @@ end
file.suffix = file.extname
-function file.stripsuffix(name)
- return (name:gsub("%.[%a%d]+$",""))
-end
-
--~ function file.join(...)
--~ local t = { ... }
--~ for i=1,#t do
@@ -1664,6 +1894,16 @@ function file.is_readable(name)
end
end
+function file.iswritable(name)
+ local a = lfs.attributes(name)
+ return a and a.permissions:sub(2,2) == "w"
+end
+
+function file.isreadable(name)
+ local a = lfs.attributes(name)
+ return a and a.permissions:sub(1,1) == "r"
+end
+
--~ function file.split_path(str)
--~ if str:find(';') then
--~ return str:splitchr(";")
@@ -1691,34 +1931,26 @@ function file.join_path(tab)
return table.concat(tab,io.pathseparator) -- can have trailing //
end
---~ print('test' .. " == " .. file.collapse_path("test"))
---~ print("test/test" .. " == " .. file.collapse_path("test/test"))
---~ print("test/test/test" .. " == " .. file.collapse_path("test/test/test"))
---~ print("test/test" .. " == " .. file.collapse_path("test/../test/test"))
---~ print("test" .. " == " .. file.collapse_path("test/../test"))
---~ print("../test" .. " == " .. file.collapse_path("../test"))
---~ print("../test/" .. " == " .. file.collapse_path("../test/"))
---~ print("a/a" .. " == " .. file.collapse_path("a/b/c/../../a"))
-
---~ function file.collapse_path(str)
---~ local ok, n = false, 0
---~ while not ok do
---~ ok = true
---~ str, n = str:gsub("[^%./]+/%.%./", function(s)
---~ ok = false
---~ return ""
---~ end)
---~ end
---~ return (str:gsub("/%./","/"))
---~ end
-
function file.collapse_path(str)
- local n = 1
- while n > 0 do
- str, n = str:gsub("([^/%.]+/%.%./)","")
- end
- return (str:gsub("/%./","/"))
-end
+ str = str:gsub("/%./","/")
+ local n, m = 1, 1
+ while n > 0 or m > 0 do
+ str, n = str:gsub("[^/%.]+/%.%.$","")
+ str, m = str:gsub("[^/%.]+/%.%./","")
+ end
+ str = str:gsub("([^/])/$","%1")
+ str = str:gsub("^%./","")
+ str = str:gsub("/%.$","")
+ if str == "" then str = "." end
+ return str
+end
+
+--~ print(file.collapse_path("a/./b/.."))
+--~ print(file.collapse_path("a/aa/../b/bb"))
+--~ print(file.collapse_path("a/../.."))
+--~ print(file.collapse_path("a/.././././b/.."))
+--~ print(file.collapse_path("a/./././b/.."))
+--~ print(file.collapse_path("a/b/c/../.."))
function file.robustname(str)
return (str:gsub("[^%a%d%/%-%.\\]+","-"))
@@ -1731,6 +1963,98 @@ function file.copy(oldname,newname)
file.savedata(newname,io.loaddata(oldname))
end
+-- lpeg variants, slightly faster, not always
+
+--~ local period = lpeg.P(".")
+--~ local slashes = lpeg.S("\\/")
+--~ local noperiod = 1-period
+--~ local noslashes = 1-slashes
+--~ local name = noperiod^1
+
+--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * lpeg.C(noperiod^1) * -1
+
+--~ function file.extname(name)
+--~ return pattern:match(name) or ""
+--~ end
+
+--~ local pattern = lpeg.Cs(((period * noperiod^1 * -1)/"" + 1)^1)
+
+--~ function file.removesuffix(name)
+--~ return pattern:match(name)
+--~ end
+
+--~ file.stripsuffix = file.removesuffix
+
+--~ local pattern = (noslashes^0 * slashes)^1 * lpeg.C(noslashes^1) * -1
+
+--~ function file.basename(name)
+--~ return pattern:match(name) or name
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^1 * lpeg.Cp() * noslashes^1 * -1
+
+--~ function file.dirname(name)
+--~ local p = pattern:match(name)
+--~ if p then
+--~ return name:sub(1,p-2)
+--~ else
+--~ return ""
+--~ end
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * lpeg.Cp() * noperiod^1 * -1
+
+--~ function file.addsuffix(name, suffix)
+--~ local p = pattern:match(name)
+--~ if p then
+--~ return name
+--~ else
+--~ return name .. "." .. suffix
+--~ end
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * lpeg.Cp() * noperiod^1 * -1
+
+--~ function file.replacesuffix(name,suffix)
+--~ local p = pattern:match(name)
+--~ if p then
+--~ return name:sub(1,p-2) .. "." .. suffix
+--~ else
+--~ return name .. "." .. suffix
+--~ end
+--~ end
+
+--~ local pattern = (noslashes^0 * slashes)^0 * lpeg.Cp() * ((noperiod^1 * period)^1 * lpeg.Cp() + lpeg.P(true)) * noperiod^1 * -1
+
+--~ function file.nameonly(name)
+--~ local a, b = pattern:match(name)
+--~ if b then
+--~ return name:sub(a,b-2)
+--~ elseif a then
+--~ return name:sub(a)
+--~ else
+--~ return name
+--~ end
+--~ end
+
+--~ local test = file.extname
+--~ local test = file.stripsuffix
+--~ local test = file.basename
+--~ local test = file.dirname
+--~ local test = file.addsuffix
+--~ local test = file.replacesuffix
+--~ local test = file.nameonly
+
+--~ print(1,test("./a/b/c/abd.def.xxx","!!!"))
+--~ print(2,test("./../b/c/abd.def.xxx","!!!"))
+--~ print(3,test("a/b/c/abd.def.xxx","!!!"))
+--~ print(4,test("a/b/c/def.xxx","!!!"))
+--~ print(5,test("a/b/c/def","!!!"))
+--~ print(6,test("def","!!!"))
+--~ print(7,test("def.xxx","!!!"))
+
+--~ local tim = os.clock() for i=1,250000 do local ext = test("abd.def.xxx","!!!") end print(os.clock()-tim)
+
-- filename : l-dir.lua
-- comment : split off from luat-lib
@@ -1746,51 +2070,6 @@ dir = { }
if lfs then do
---~ local attributes = lfs.attributes
---~ local walkdir = lfs.dir
---~
---~ local function glob_pattern(path,patt,recurse,action)
---~ local ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
---~ if ok and type(scanner) == "function" then
---~ if not path:find("/$") then path = path .. '/' end
---~ for name in scanner do
---~ local full = path .. name
---~ local mode = attributes(full,'mode')
---~ if mode == 'file' then
---~ if name:find(patt) then
---~ action(full)
---~ end
---~ elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
---~ glob_pattern(full,patt,recurse,action)
---~ end
---~ end
---~ end
---~ end
---~
---~ dir.glob_pattern = glob_pattern
---~
---~ local function glob(pattern, action)
---~ local t = { }
---~ local action = action or function(name) t[#t+1] = name end
---~ local path, patt = pattern:match("^(.*)/*%*%*/*(.-)$")
---~ local recurse = path and patt
---~ if not recurse then
---~ path, patt = pattern:match("^(.*)/(.-)$")
---~ if not (path and patt) then
---~ path, patt = '.', pattern
---~ end
---~ end
---~ patt = patt:gsub("([%.%-%+])", "%%%1")
---~ patt = patt:gsub("%*", ".*")
---~ patt = patt:gsub("%?", ".")
---~ patt = "^" .. patt .. "$"
---~ -- print('path: ' .. path .. ' | pattern: ' .. patt .. ' | recurse: ' .. tostring(recurse))
---~ glob_pattern(path,patt,recurse,action)
---~ return t
---~ end
---~
---~ dir.glob = glob
-
local attributes = lfs.attributes
local walkdir = lfs.dir
@@ -1868,13 +2147,17 @@ if lfs then do
glob(s,t)
end
return t
+ elseif lfs.isfile(str) then
+ local t = t or { }
+ t[#t+1] = str
+ return t
else
local split = pattern:match(str)
if split then
local t = t or { }
local action = action or function(name) t[#t+1] = name end
local root, path, base = split[1], split[2], split[3]
- local recurse = base:find("**")
+ local recurse = base:find("%*%*")
local start = root .. path
local result = filter:match(start .. base)
glob_pattern(start,result,recurse,action)
@@ -1902,16 +2185,21 @@ if lfs then do
for name in walkdir(path) do
if name:find("^%.") then
--- skip
- elseif attributes(name,'mode') == "directory" then
- if recurse then
- globfiles(path .. "/" .. name,recurse,func,files)
- end
- elseif func then
- if func(name) then
- files[#files+1] = path .. "/" .. name
- end
else
- files[#files+1] = path .. "/" .. name
+ local mode = attributes(name,'mode')
+ if mode == "directory" then
+ if recurse then
+ globfiles(path .. "/" .. name,recurse,func,files)
+ end
+ elseif mode == "file" then
+ if func then
+ if func(name) then
+ files[#files+1] = path .. "/" .. name
+ end
+ else
+ files[#files+1] = path .. "/" .. name
+ end
+ end
end
end
return files
@@ -2119,7 +2407,7 @@ function toboolean(str,tolerant)
if tolerant then
local tstr = type(str)
if tstr == "string" then
- return str == "true" or str == "yes" or str == "on" or str == "1"
+ return str == "true" or str == "yes" or str == "on" or str == "1" or str == "t"
elseif tstr == "number" then
return tonumber(str) ~= 0
elseif tstr == "nil" then
@@ -2138,9 +2426,9 @@ end
function string.is_boolean(str)
if type(str) == "string" then
- if str == "true" or str == "yes" or str == "on" then
+ if str == "true" or str == "yes" or str == "on" or str == "t" then
return true
- elseif str == "false" or str == "no" or str == "off" then
+ elseif str == "false" or str == "no" or str == "off" or str == "f" then
return false
end
end
@@ -2364,7 +2652,7 @@ do
end
dt = top.dt
dt[#dt+1] = toclose
- if at.xmlns then
+ if toclose.at.xmlns then
remove(xmlns)
end
end
@@ -2378,10 +2666,10 @@ do
local t = { ns=namespace or "", rn=resolved, tg=tag, at=at, dt={}, __p__ = top }
dt[#dt+1] = t
setmetatable(t, mt)
- at = { }
if at.xmlns then
remove(xmlns)
end
+ at = { }
end
local function add_text(text)
if cleanup and #text > 0 then
@@ -2638,22 +2926,19 @@ do
elseif not nocommands then
local ec = e.command
if ec ~= nil then -- we can have all kind of types
-
-if e.special then -- todo test for true/false
- local etg, edt = e.tg, e.dt
- local spc = specialconverter and specialconverter[etg]
- if spc then
---~ print("SPECIAL",etg,table.serialize(specialconverter), spc)
- local result = spc(edt[1])
- if result then
- handle(result)
- return
- else
- -- no need to handle any further
- end
- end
-end
-
+ if e.special then
+ local etg, edt = e.tg, e.dt
+ local spc = specialconverter and specialconverter[etg]
+ if spc then
+ local result = spc(edt[1])
+ if result then
+ handle(result)
+ return
+ else
+ -- no need to handle any further
+ end
+ end
+ end
local xc = xml.command
if xc then
xc(e,ec)
@@ -2704,17 +2989,7 @@ end
end
end
if ern and xml.trace_remap and ern ~= ens then
---~ if ats then
---~ ats[#ats+1] = format("xmlns:remapped='%s'",ern)
---~ else
---~ ats = { format("xmlns:remapped='%s'",ern) }
---~ end
---~ if ats then
---~ ats[#ats+1] = format("remappedns='%s'",ens or '-')
---~ else
---~ ats = { format("remappedns='%s'",ens or '-') }
---~ end
-ens = ern
+ ens = ern
end
if ens ~= "" then
if edt and #edt > 0 then
@@ -2758,7 +3033,16 @@ ens = ern
handle("<" .. etg .. ">")
end
for i=1,#edt do
- serialize(edt[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
+ local ei = edt[i]
+ if type(ei) == "string" then
+ if textconverter then
+ handle(textconverter(ei))
+ else
+ handle(ei)
+ end
+ else
+ serialize(ei,handle,textconverter,attributeconverter,specialconverter,nocommands)
+ end
end
-- handle(format("</%s>",etg))
handle("</" .. etg .. ">")
@@ -2781,7 +3065,16 @@ ens = ern
end
else
for i=1,#e do
- serialize(e[i],handle,textconverter,attributeconverter,specialconverter,nocommands)
+ local ei = e[i]
+ if type(ei) == "string" then
+ if textconverter then
+ handle(textconverter(ei))
+ else
+ handle(ei)
+ end
+ else
+ serialize(ei,handle,textconverter,attributeconverter,specialconverter,nocommands)
+ end
end
end
end
@@ -2811,14 +3104,14 @@ ens = ern
function xml.tostring(root) -- 25% overhead due to collecting
if root then
- if type(root) == 'string' then
- 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)
- return concat(result,"")
+ if type(root) == 'string' then
+ 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)
+ return concat(result,"")
+ end
end
- end
return ""
end
@@ -2883,6 +3176,18 @@ function xml.content(root) -- bugged
return (root and root.dt and xml.tostring(root.dt)) or ""
end
+function xml.isempty(root, pattern)
+ if pattern == "" or pattern == "*" then
+ pattern = nil
+ end
+ if pattern then
+ -- todo
+ return false
+ else
+ return not root or not root.dt or #root.dt == 0 or root.dt == ""
+ end
+end
+
--[[ldx--
<p>The next helper erases an element but keeps the table as it is,
and since empty strings are not serialized (effectively) it does
@@ -2925,6 +3230,9 @@ of <l n='xpath'/> and since we're not compatible we call it <l n='lpath'/>. We
will explain more about its usage in other documents.</p>
--ldx]]--
+local lpathcalls = 0 -- statisctics
+local lpathcached = 0 -- statisctics
+
do
xml.functions = xml.functions or { }
@@ -3184,11 +3492,13 @@ do
local cache = { }
function xml.lpath(pattern,trace)
+ lpathcalls = lpathcalls + 1
if type(pattern) == "string" then
local result = cache[pattern]
- if not result then
+ if result == nil then -- can be false which is valid -)
result = compose(pattern)
cache[pattern] = result
+ lpathcached = lpathcached + 1
end
if trace or xml.trace_lpath then
xml.lshow(result)
@@ -3199,6 +3509,10 @@ do
end
end
+ function lpath_cached_patterns()
+ return cache
+ end
+
local fallbackreport = (texio and texio.write) or io.write
function xml.lshow(pattern,report)
@@ -3291,35 +3605,20 @@ do
return (rdt and rdt[k]) or root[k] or ""
end
end
- functions.name = function(root,k,n)
- -- way too fuzzy
- local found
- if not k or not n then
- local ns, tg = root.rn or root.ns or "", root.tg
- if not tg then
- for i=1,#root do
- local e = root[i]
- if type(e) == "table" then
- found = e
- break
- end
- end
- elseif ns ~= "" then
- return ns .. ":" .. tg
- else
- return tg
- end
+ functions.name = function(d,k,n) -- ns + tg
+ local found = false
+ n = n or 0
+ if not k then
+ -- not found
elseif n == 0 then
- local e = root[k]
- if type(e) ~= "table" then
- found = e
- end
+ local dk = d[k]
+ found = dk and (type(dk) == "table") and dk
elseif n < 0 then
for i=k-1,1,-1 do
- local e = root[i]
- if type(e) == "table" then
+ local di = d[i]
+ if type(di) == "table" then
if n == -1 then
- found = e
+ found = di
break
else
n = n + 1
@@ -3327,12 +3626,11 @@ do
end
end
else
---~ print(k,n,#root)
- for i=k+1,#root,1 do
- local e = root[i]
- if type(e) == "table" then
+ for i=k+1,#d,1 do
+ local di = d[i]
+ if type(di) == "table" then
if n == 1 then
- found = e
+ found = di
break
else
n = n - 1
@@ -3351,6 +3649,41 @@ do
return ""
end
end
+ functions.tag = function(d,k,n) -- only tg
+ local found = false
+ n = n or 0
+ if not k then
+ -- not found
+ elseif n == 0 then
+ local dk = d[k]
+ found = dk and (type(dk) == "table") and dk
+ elseif n < 0 then
+ for i=k-1,1,-1 do
+ local di = d[i]
+ if type(di) == "table" then
+ if n == -1 then
+ found = di
+ break
+ else
+ n = n + 1
+ end
+ end
+ end
+ else
+ for i=k+1,#d,1 do
+ local di = d[i]
+ if type(di) == "table" then
+ if n == 1 then
+ found = di
+ break
+ else
+ n = n - 1
+ end
+ end
+ end
+ end
+ return (found and found.tg) or ""
+ end
local function traverse(root,pattern,handle,reverse,index,parent,wildcard) -- multiple only for tags, not for namespaces
if not root then -- error
@@ -4116,15 +4449,20 @@ do
xml.each_element(xmldata, pattern, include)
end
- function xml.strip_whitespace(root, pattern)
+ function xml.strip_whitespace(root, pattern) -- 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
local t = { }
for i=1,#dkdt do
local str = dkdt[i]
- if type(str) == "string" and str:find("^[ \n\r\t]*$") then
- -- stripped
+ if type(str) == "string" then
+ str = str:gsub("^[ \n\r\t]*(.-)[ \n\r\t]*$","%1")
+ if str == "" then
+ -- stripped
+ else
+ t[#t+1] = str
+ end
else
t[#t+1] = str
end
@@ -4326,9 +4664,9 @@ original entity is returned.</p>
do if unicode and unicode.utf8 then
- xml.entities = xml.entities or { } -- xml.entities.handler == function
+ xml.entities = xml.entities or { } -- xml.entity_handler == function
- function xml.entities.handler(e)
+ function xml.entity_handler(e)
return format("[%s]",e)
end
@@ -4338,8 +4676,6 @@ do if unicode and unicode.utf8 then
return char(tonumber(s,16))
end
- local entities = xml.entities -- global entities
-
function utfize(root)
local d = root.dt
for k=1,#d do
@@ -4361,11 +4697,11 @@ do if unicode and unicode.utf8 then
if e:find("#x") then
return char(tonumber(e:sub(3),16))
else
- local ee = entities[e]
+ local ee = xml.entities[e] -- we cannot shortcut this one (is reloaded)
if ee then
return ee
else
- local h = xml.entities.handler
+ local h = xml.entity_handler
return (h and h(e)) or "&" .. e .. ";"
end
end
@@ -4427,6 +4763,13 @@ do if unicode and unicode.utf8 then
end end
+function xml.statistics()
+ return {
+ lpathcalls = lpathcalls,
+ lpathcached = lpathcached,
+ }
+end
+
-- xml.set_text_cleanup(xml.show_text_entities)
-- xml.set_text_cleanup(xml.resolve_text_entities)
@@ -4505,12 +4848,18 @@ function utils.report(...)
print(...)
end
+utils.merger.strip_comment = true
+
function utils.merger._self_load_(name)
local f, data = io.open(name), ""
if f then
data = f:read("*all")
f:close()
end
+ if data and utils.merger.strip_comment then
+ -- saves some 20K
+ data = data:gsub("%-%-~[^\n\r]*[\r\n]", "")
+ end
return data or ""
end
@@ -4588,108 +4937,62 @@ function utils.merger.selfclean(name)
)
end
-utils.lua.compile_strip = true
-
-function utils.lua.compile(luafile, lucfile)
+function utils.lua.compile(luafile, lucfile, cleanup, strip) -- defaults: cleanup=false strip=true
-- utils.report("compiling",luafile,"into",lucfile)
os.remove(lucfile)
local command = "-o " .. string.quote(lucfile) .. " " .. string.quote(luafile)
- if utils.lua.compile_strip then
+ if strip ~= false then
command = "-s " .. command
end
- if os.spawn("texluac " .. command) == 0 then
- return true
- elseif os.spawn("luac " .. command) == 0 then
- return true
- else
- return false
+ local done = (os.spawn("texluac " .. command) == 0) or (os.spawn("luac " .. command) == 0)
+ if done and cleanup == true and lfs.isfile(lucfile) and lfs.isfile(luafile) then
+ -- utils.report("removing",luafile)
+ os.remove(luafile)
end
+ return done
end
--- filename : luat-lib.lua
--- 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
-
-if not versions then versions = { } end versions['luat-lib'] = 1.001
-
--- mostcode moved to the l-*.lua and other luat-*.lua files
+if not modules then modules = { } end modules ['luat-lib'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ comment = "companion to luat-lib.tex",
+}
--- os / io
+-- most code already moved to the l-*.lua and other luat-*.lua files
os.setlocale(nil,nil) -- useless feature and even dangerous in luatex
--- os.platform
-
--- mswin|bccwin|mingw|cygwin windows
--- darwin|rhapsody|nextstep macosx
--- netbsd|unix unix
--- linux linux
-
-if not io.fileseparator then
- if string.find(os.getenv("PATH"),";") then
- io.fileseparator, io.pathseparator, os.platform = "\\", ";", os.type or "windows"
- else
- io.fileseparator, io.pathseparator, os.platform = "/" , ":", os.type or "unix"
- end
-end
-
-os.platform = os.platform or os.type or (io.pathseparator == ";" and "windows") or "unix"
-
--- arg normalization
---
--- for k,v in pairs(arg) do print(k,v) end
-
--- environment
-
-if not environment then environment = { } end
-
-environment.ownbin = environment.ownbin or arg[-2] or arg[-1] or arg[0] or "luatex"
-
-local ownpath = nil -- we could use a metatable here
-
-function environment.ownpath()
- if not ownpath then
- for p in string.gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do
- local b = file.join(p,environment.ownbin)
- if lfs.isfile(b..".exe") or lfs.isfile(b) then
- ownpath = p
- break
- end
- end
- if not ownpath then ownpath = '.' end
- end
- return ownpath
+function os.setlocale()
+ -- no way you can mess with it
end
if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then
arg[-1]=arg[0] arg[0]=arg[2] for k=3,#arg do arg[k-2]=arg[k] end arg[#arg]=nil arg[#arg]=nil
end
-environment.arguments = { }
-environment.files = { }
-environment.sorted_argument_keys = nil
-
-environment.platform = os.platform
+environment = environment or { }
+environment.arguments = { }
+environment.files = { }
+environment.sortedflags = nil
function environment.initialize_arguments(arg)
- environment.arguments = { }
- environment.files = { }
- environment.sorted_argument_keys = nil
+ local arguments, files = { }, { }
+ environment.arguments, environment.files, environment.sortedflags = arguments, files, nil
for index, argument in pairs(arg) do
if index > 0 then
local flag, value = argument:match("^%-+(.+)=(.-)$")
if flag then
- environment.arguments[flag] = string.unquote(value or "")
+ arguments[flag] = string.unquote(value or "")
else
flag = argument:match("^%-+(.+)")
if flag then
- environment.arguments[flag] = true
+ arguments[flag] = true
else
- environment.files[#environment.files+1] = argument
+ files[#files+1] = argument
end
end
end
@@ -4711,18 +5014,20 @@ function environment.setargument(name,value)
end
function environment.argument(name)
- if environment.arguments[name] then
- return environment.arguments[name]
+ local arguments, sortedflags = environment.arguments, environment.sortedflags
+ if arguments[name] then
+ return arguments[name]
else
- if not environment.sorted_argument_keys then
- environment.sorted_argument_keys = { }
- for _,v in pairs(table.sortedkeys(environment.arguments)) do
- table.insert(environment.sorted_argument_keys, "^" .. v)
+ if not sortedflags then
+ sortedflags = { }
+ for _,v in pairs(table.sortedkeys(arguments)) do
+ sortedflags[#sortedflags+1] = "^" .. v
end
+ environment.sortedflags = sortedflags
end
- for _,v in pairs(environment.sorted_argument_keys) do
+ for _,v in ipairs(sortedflags) do
if name:find(v) then
- return environment.arguments[v:sub(2,#v)]
+ return arguments[v:sub(2,#v)]
end
end
end
@@ -4770,21 +5075,24 @@ if arg then
end
--- filename : luat-inp.lua
--- 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
-
--- This lib is multi-purpose and can be loaded again later on so that
--- additional functionality becomes available. We will split this
--- module in components when we're done with prototyping.
+if not modules then modules = { } end modules ['luat-inp'] = {
+ version = 1.001,
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files",
+ comment = "companion to luat-lib.tex",
+}
-- TODO: os.getenv -> os.env[]
-- TODO: instances.[hashes,cnffiles,configurations,522] -> ipairs (alles check, sneller)
-- TODO: check escaping in find etc, too much, too slow
--- This is the first code I wrote for LuaTeX, so it needs some cleanup.
+-- This lib is multi-purpose and can be loaded again later on so that
+-- additional functionality becomes available. We will split this
+-- module in components once we're done with prototyping. This is the
+-- first code I wrote for LuaTeX, so it needs some cleanup. Before changing
+-- something in this module one can best check with Taco or Hans first; there
+-- is some nasty trickery going on that relates to traditional kpse support.
-- To be considered: hash key lowercase, first entry in table filename
-- (any case), rest paths (so no need for optimization). Or maybe a
@@ -4794,12 +5102,6 @@ end
-- Beware, loading and saving is overloaded in luat-tmp!
-if not versions then versions = { } end versions['luat-inp'] = 1.001
-if not environment then environment = { } end
-if not file then file = { } end
-
-if environment.aleph_mode == nil then environment.aleph_mode = true end -- temp hack
-
if not input then input = { } end
if not input.suffixes then input.suffixes = { } end
if not input.formats then input.formats = { } end
@@ -4825,8 +5127,16 @@ input.debug = false
input.cnfname = 'texmf.cnf'
input.luaname = 'texmfcnf.lua'
input.lsrname = 'ls-R'
-input.luasuffix = '.tma'
-input.lucsuffix = '.tmc'
+input.homedir = os.env[os.platform == "windows" and 'USERPROFILE'] or os.env['HOME'] or '~'
+
+--~ input.luasuffix = 'tma'
+--~ input.lucsuffix = 'tmc'
+
+-- for the moment we have .local but this will disappear
+input.cnfdefault = '{$SELFAUTOLOC,$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}'
+
+-- chances are low that the cnf file is in the bin path
+input.cnfdefault = '{$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}'
-- we use a cleaned up list / format=any is a wildcard, as is *name
@@ -4862,7 +5172,8 @@ input.suffixes['lua'] = { 'lua', 'luc', 'tma', 'tmc' }
-- FONTFEATURES = .;$TEXMF/fonts/fea//
-- FONTCIDMAPS = .;$TEXMF/fonts/cid//
-function input.checkconfigdata(instance) -- not yet ok, no time for debugging now
+function input.checkconfigdata() -- not yet ok, no time for debugging now
+ local instance = input.instance
local function fix(varname,default)
local proname = varname .. "." .. instance.progname or "crap"
local p = instance.environment[proname]
@@ -4871,7 +5182,15 @@ function input.checkconfigdata(instance) -- not yet ok, no time for debugging no
instance.variables[varname] = default -- or environment?
end
end
- fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS")
+ local name = os.name
+ if name == "windows" then
+ fix("OSFONTDIR", "c:/windows/fonts//")
+ elseif name == "macosx" then
+ fix("OSFONTDIR", "$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//")
+ else
+ -- bad luck
+ end
+ fix("LUAINPUTS" , ".;$TEXINPUTS;$TEXMFSCRIPTS") -- no progname, hm
fix("FONTFEATURES", ".;$TEXMF/fonts/fea//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS")
fix("FONTCIDMAPS" , ".;$TEXMF/fonts/cid//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS")
end
@@ -4898,14 +5217,20 @@ input.formats ['sfd'] = 'SFDFONTS'
input.suffixes ['sfd'] = { 'sfd' }
input.alternatives['subfont definition files'] = 'sfd'
-function input.reset()
+-- In practice we will work within one tds tree, but i want to keep
+-- the option open to build tools that look at multiple trees, which is
+-- why we keep the tree specific data in a table. We used to pass the
+-- instance but for practical pusposes we now avoid this and use a
+-- instance variable.
+
+function input.newinstance()
local instance = { }
instance.rootpath = ''
instance.treepath = ''
- instance.progname = environment.progname or 'context'
- instance.engine = environment.engine or 'luatex'
+ instance.progname = 'context'
+ instance.engine = 'luatex'
instance.format = ''
instance.environment = { }
instance.variables = { }
@@ -4929,12 +5254,12 @@ function input.reset()
instance.cachepath = nil
instance.loaderror = false
instance.smallcache = false
+ instance.sortdata = false
instance.savelists = true
instance.cleanuppaths = true
instance.allresults = false
instance.pattern = nil -- lists
instance.kpseonly = false -- lists
- instance.cachefile = 'tmftools'
instance.loadtime = 0
instance.starttime = 0
instance.stoptime = 0
@@ -4945,23 +5270,13 @@ function input.reset()
instance.fakepaths = { }
instance.lsrmode = false
- if os.env then
- -- store once, freeze and faster
- for k,v in pairs(os.env) do
- instance.environment[k] = input.bare_variable(v)
- end
- else
- -- we will access os.env frequently
- for k,v in pairs({'HOME','TEXMF','TEXMFCNF'}) do
- local e = os.getenv(v)
- if e then
- -- input.report("setting",v,"to",input.bare_variable(e))
- instance.environment[v] = input.bare_variable(e)
- end
- end
+ -- store once, freeze and faster (once reset we can best use instance.environment)
+
+ for k,v in pairs(os.env) do
+ instance.environment[k] = input.bare_variable(v)
end
- -- cross referencing
+ -- cross referencing, delayed because we can add suffixes
for k, v in pairs(input.suffixes) do
for _, vv in pairs(v) do
@@ -4975,68 +5290,42 @@ function input.reset()
end
-function input.reset_hashes(instance)
- instance.lists = { }
- instance.found = { }
-end
-
-function input.bare_variable(str) -- assumes str is a string
- -- return string.gsub(string.gsub(string.gsub(str,"%s+$",""),'^"(.+)"$',"%1"),"^'(.+)'$","%1")
- return (str:gsub("\s*([\"\']?)(.+)%1\s*", "%2"))
-end
+input.instance = input.instance or nil
-if texio then
- input.log = texio.write_nl
-else
- input.log = print
+function input.reset()
+ input.instance = input.newinstance()
+ return input.instance
end
-function input.simple_logger(kind, name)
- if name and name ~= "" then
- if input.banner then
- input.log(input.banner..kind..": "..name)
- else
- input.log("<<"..kind..": "..name..">>")
- end
- else
- if input.banner then
- input.log(input.banner..kind..": no name")
- else
- input.log("<<"..kind..": no name>>")
- end
- end
+function input.reset_hashes()
+ input.instance.lists = { }
+ input.instance.found = { }
end
-function input.dummy_logger()
+function input.bare_variable(str) -- assumes str is a string
+ -- return string.gsub(string.gsub(string.gsub(str,"%s+$",""),'^"(.+)"$',"%1"),"^'(.+)'$","%1")
+ return (str:gsub("\s*([\"\']?)(.+)%1\s*", "%2"))
end
function input.settrace(n)
input.trace = tonumber(n or 0)
if input.trace > 0 then
- input.logger = input.simple_logger
input.verbose = true
- else
- input.logger = function() end
end
end
-function input.report(...) -- inefficient
+input.log = (texio and texio.write_nl) or print
+
+function input.report(...)
if input.verbose then
- if input.banner then
- input.log(input.banner .. table.concat({...},' '))
- elseif input.logmode() == 'xml' then
- input.log("<t>"..table.concat({...},' ').."</t>")
- else
- input.log("<<"..table.concat({...},' ')..">>")
- end
+ input.log("<<"..format(...)..">>")
end
end
-function input.reportlines(str)
- if type(str) == "string" then
- str = str:split("\n")
+function input.report(...)
+ if input.trace > 0 then -- extra test
+ input.log("<<"..format(...)..">>")
end
- for _,v in pairs(str) do input.report(v) end
end
input.settrace(tonumber(os.getenv("MTX.INPUT.TRACE") or os.getenv("MTX_INPUT_TRACE") or input.trace or 0))
@@ -5065,7 +5354,7 @@ do
instance.stoptime = stoptime
instance.loadtime = instance.loadtime + loadtime
if report then
- input.report('load time', format("%0.3f",loadtime))
+ input.report("load time %0.3f",loadtime)
end
return loadtime
end
@@ -5081,18 +5370,18 @@ end
function input.report_loadtime(instance)
if instance then
- input.report('total load time', input.elapsedtime(instance))
+ input.report('total load time %s', input.elapsedtime(instance))
end
end
input.loadtime = input.elapsedtime
-function input.env(instance,key)
- return instance.environment[key] or input.osenv(instance,key)
+function input.env(key)
+ return input.instance.environment[key] or input.osenv(key)
end
-function input.osenv(instance,key)
- local ie = instance.environment
+function input.osenv(key)
+ local ie = input.instance.environment
local value = ie[key]
if value == nil then
-- local e = os.getenv(key)
@@ -5110,81 +5399,106 @@ end
-- we follow a rather traditional approach:
--
-- (1) texmf.cnf given in TEXMFCNF
--- (2) texmf.cnf searched in TEXMF/web2c
+-- (2) texmf.cnf searched in default variable
--
--- for the moment we don't expect a configuration file in a zip
+-- also we now follow the stupid route: if not set then just assume *one*
+-- cnf file under texmf (i.e. distribution)
-function input.identify_cnf(instance)
- -- we no longer support treepath and rootpath (was handy for testing);
- -- also we now follow the stupid route: if not set then just assume *one*
- -- cnf file under texmf (i.e. distribution)
- if #instance.cnffiles == 0 then
- if input.env(instance,'TEXMFCNF') == "" then
- local ownpath = environment.ownpath() or "."
- if ownpath then
- -- beware, this is tricky on my own system because at that location I do have
- -- the raw tree that ends up in the zip; i.e. I cannot test this kind of mess
- local function locate(filename,list)
- local ownroot = input.normalize_name(file.join(ownpath,"../.."))
- if not lfs.isdir(file.join(ownroot,"texmf")) then
- ownroot = input.normalize_name(file.join(ownpath,".."))
- if not lfs.isdir(file.join(ownroot,"texmf")) then
- input.verbose = true
- input.report("error", "unable to identify cnf file")
- return
+input.ownpath = input.ownpath or nil
+input.ownbin = input.ownbin or arg[-2] or arg[-1] or arg[0] or "luatex"
+input.autoselfdir = true -- false may be handy for debugging
+
+function input.getownpath()
+ if not input.ownpath then
+ if input.autoselfdir and os.selfdir then
+ input.ownpath = os.selfdir
+ else
+ local binary = input.ownbin
+ if os.platform == "windows" then
+ binary = file.replacesuffix(binary,"exe")
+ end
+ for p in string.gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do
+ local b = file.join(p,binary)
+ if lfs.isfile(b) then
+ -- we assume that after changing to the path the currentdir function
+ -- resolves to the real location and use this side effect here; this
+ -- trick is needed because on the mac installations use symlinks in the
+ -- path instead of real locations
+ local olddir = lfs.currentdir()
+ if lfs.chdir(p) then
+ local pp = lfs.currentdir()
+ if input.verbose and p ~= pp then
+ input.report("following symlink %s to %s",p,pp)
end
- end
- local texmfcnf = file.join(ownroot,"texmf-local/web2c",filename) -- for minimals and myself
- if not lfs.isfile(texmfcnf) then
- texmfcnf = file.join(ownroot,"texmf/web2c",filename)
- if not lfs.isfile(texmfcnf) then
- input.verbose = true
- input.report("error", "unable to locate",filename)
- return
+ input.ownpath = pp
+ lfs.chdir(olddir)
+ else
+ if input.verbose then
+ input.report("unable to check path %s",p)
end
+ input.ownpath = p
end
- table.insert(list,texmfcnf)
- local ie = instance.environment
- if not ie['SELFAUTOPARENT'] then ie['SELFAUTOPARENT'] = ownroot end
- if not ie['TEXMFCNF'] then ie['TEXMFCNF'] = file.dirname(texmfcnf) end
- end
- locate(input.luaname,instance.luafiles)
- locate(input.cnfname,instance.cnffiles)
- if #instance.luafiles == 0 and instance.cnffiles == 0 then
- input.verbose = true
- input.report("error", "unable to locate",filename)
- os.exit()
+ break
end
- -- here we also assume then TEXMF is set in the distribution, if this trickery is
- -- used in the minimals, then users who don't use setuptex are on their own with
- -- regards to extra trees
- else
- input.verbose = true
- input.report("error", "unable to identify own path")
- os.exit()
end
- else
- local t = input.split_path(input.env(instance,'TEXMFCNF'))
- t = input.aux.expanded_path(instance,t)
- input.aux.expand_vars(instance,t)
- local function locate(filename,list)
- for _,v in ipairs(t) do
- local texmfcnf = input.normalize_name(file.join(v,filename))
- if lfs.isfile(texmfcnf) then
- table.insert(list,texmfcnf)
- end
+ end
+ if not input.ownpath then input.ownpath = '.' end
+ end
+ return input.ownpath
+end
+
+function input.identify_own()
+ local instance = input.instance
+ local ownpath = input.getownpath() or lfs.currentdir()
+ local ie = instance.environment
+ if ownpath then
+ if input.env('SELFAUTOLOC') == "" then os.env['SELFAUTOLOC'] = file.collapse_path(ownpath) end
+ if input.env('SELFAUTODIR') == "" then os.env['SELFAUTODIR'] = file.collapse_path(ownpath .. "/..") end
+ if input.env('SELFAUTOPARENT') == "" then os.env['SELFAUTOPARENT'] = file.collapse_path(ownpath .. "/../..") end
+ else
+ input.verbose = true
+ input.report("error: unable to locate ownpath")
+ os.exit()
+ end
+ if input.env('TEXMFCNF') == "" then os.env['TEXMFCNF'] = input.cnfdefault end
+ if input.env('TEXOS') == "" then os.env['TEXOS'] = input.env('SELFAUTODIR') end
+ if input.env('TEXROOT') == "" then os.env['TEXROOT'] = input.env('SELFAUTOPARENT') end
+ if input.verbose then
+ for _,v in ipairs({"SELFAUTOLOC","SELFAUTODIR","SELFAUTOPARENT","TEXMFCNF"}) do
+ input.report("variable %s set to %s",v,input.env(v) or "unknown")
+ end
+ end
+ function input.identify_own() end
+end
+
+function input.identify_cnf()
+ local instance = input.instance
+ if #instance.cnffiles == 0 then
+ -- fallback
+ input.identify_own()
+ -- the real search
+ input.expand_variables()
+ local t = input.split_path(input.env('TEXMFCNF'))
+ t = input.aux.expanded_path(t)
+ input.aux.expand_vars(t) -- redundant
+ local function locate(filename,list)
+ for _,v in ipairs(t) do
+ local texmfcnf = input.normalize_name(file.join(v,filename))
+ if lfs.isfile(texmfcnf) then
+ table.insert(list,texmfcnf)
end
end
- locate(input.luaname,instance.luafiles)
- locate(input.cnfname,instance.cnffiles)
end
+ locate(input.luaname,instance.luafiles)
+ locate(input.cnfname,instance.cnffiles)
end
end
-function input.load_cnf(instance)
+function input.load_cnf()
+ local instance = input.instance
local function loadoldconfigdata()
for _, fname in ipairs(instance.cnffiles) do
- input.aux.load_cnf(instance,fname)
+ input.aux.load_cnf(fname)
end
end
-- instance.cnffiles contain complete names now !
@@ -5199,27 +5513,27 @@ function input.load_cnf(instance)
instance.rootpath = file.dirname(instance.rootpath)
end
instance.rootpath = input.normalize_name(instance.rootpath)
- instance.environment['SELFAUTOPARENT'] = instance.rootpath -- just to be sure
if instance.lsrmode then
loadoldconfigdata()
elseif instance.diskcache and not instance.renewcache then
- input.loadoldconfig(instance,instance.cnffiles)
+ input.loadoldconfig(instance.cnffiles)
if instance.loaderror then
loadoldconfigdata()
- input.saveoldconfig(instance)
+ input.saveoldconfig()
end
else
loadoldconfigdata()
if instance.renewcache then
- input.saveoldconfig(instance)
+ input.saveoldconfig()
end
end
- input.aux.collapse_cnf_data(instance)
+ input.aux.collapse_cnf_data()
end
- input.checkconfigdata(instance)
+ input.checkconfigdata()
end
-function input.load_lua(instance)
+function input.load_lua()
+ local instance = input.instance
if #instance.luafiles == 0 then
-- yet harmless
else
@@ -5231,14 +5545,14 @@ function input.load_lua(instance)
instance.rootpath = file.dirname(instance.rootpath)
end
instance.rootpath = input.normalize_name(instance.rootpath)
- instance.environment['SELFAUTOPARENT'] = instance.rootpath -- just to be sure
- input.loadnewconfig(instance)
- input.aux.collapse_cnf_data(instance)
+ input.loadnewconfig()
+ input.aux.collapse_cnf_data()
end
- input.checkconfigdata(instance)
+ input.checkconfigdata()
end
-function input.aux.collapse_cnf_data(instance) -- potential optmization: pass start index (setup and configuration are shared)
+function input.aux.collapse_cnf_data() -- potential optimization: pass start index (setup and configuration are shared)
+ local instance = input.instance
for _,c in ipairs(instance.order) do
for k,v in pairs(c) do
if not instance.variables[k] then
@@ -5253,21 +5567,22 @@ function input.aux.collapse_cnf_data(instance) -- potential optmization: pass st
end
end
-function input.aux.load_cnf(instance,fname)
+function input.aux.load_cnf(fname)
+ local instance = input.instance
fname = input.clean_path(fname)
- local lname = fname:gsub("%.%a+$",input.luasuffix)
+ local lname = file.replacesuffix(fname,'lua')
local f = io.open(lname)
if f then -- this will go
f:close()
local dname = file.dirname(fname)
if not instance.configuration[dname] then
- input.aux.load_configuration(instance,dname,lname)
+ input.aux.load_configuration(dname,lname)
instance.order[#instance.order+1] = instance.configuration[dname]
end
else
f = io.open(fname)
if f then
- input.report("loading", fname)
+ input.report("loading %s", fname)
local line, data, n, k, v
local dname = file.dirname(fname)
if not instance.configuration[dname] then
@@ -5299,227 +5614,226 @@ function input.aux.load_cnf(instance,fname)
end
f:close()
else
- input.report("skipping", fname)
+ input.report("skipping %s", fname)
end
end
end
-- database loading
-function input.load_hash(instance)
- input.locatelists(instance)
+function input.load_hash()
+ local instance = input.instance
+ input.locatelists()
if instance.lsrmode then
- input.loadlists(instance)
+ input.loadlists()
elseif instance.diskcache and not instance.renewcache then
- input.loadfiles(instance)
+ input.loadfiles()
if instance.loaderror then
- input.loadlists(instance)
- input.savefiles(instance)
+ input.loadlists()
+ input.savefiles()
end
else
- input.loadlists(instance)
+ input.loadlists()
if instance.renewcache then
- input.savefiles(instance)
+ input.savefiles()
end
end
end
-function input.aux.append_hash(instance,type,tag,name)
- input.logger("= hash append",tag)
- table.insert(instance.hashes, { ['type']=type, ['tag']=tag, ['name']=name } )
+function input.aux.append_hash(type,tag,name)
+ if input.trace > 0 then
+ input.logger("= hash append: %s",tag)
+ end
+ table.insert(input.instance.hashes, { ['type']=type, ['tag']=tag, ['name']=name } )
end
-function input.aux.prepend_hash(instance,type,tag,name)
- input.logger("= hash prepend",tag)
- table.insert(instance.hashes, 1, { ['type']=type, ['tag']=tag, ['name']=name } )
+function input.aux.prepend_hash(type,tag,name)
+ if input.trace > 0 then
+ input.logger("= hash prepend: %s",tag)
+ end
+ table.insert(input.instance.hashes, 1, { ['type']=type, ['tag']=tag, ['name']=name } )
end
-function input.aux.extend_texmf_var(instance,specification) -- crap
- if instance.environment['TEXMF'] then
- input.report("extending environment variable TEXMF with", specification)
- instance.environment['TEXMF'] = instance.environment['TEXMF']:gsub("^%{", function()
- return "{" .. specification .. ","
- end)
- elseif instance.variables['TEXMF'] then
- input.report("extending configuration variable TEXMF with", specification)
- instance.variables['TEXMF'] = instance.variables['TEXMF']:gsub("^%{", function()
- return "{" .. specification .. ","
- end)
+function input.aux.extend_texmf_var(specification) -- crap, we could better prepend the hash
+ local instance = input.instance
+-- local t = input.expanded_path_list('TEXMF') -- full expansion
+ local t = input.split_path(input.env('TEXMF'))
+ table.insert(t,1,specification)
+ local newspec = table.join(t,";")
+ if instance.environment["TEXMF"] then
+ instance.environment["TEXMF"] = newspec
+ elseif instance.variables["TEXMF"] then
+ instance.variables["TEXMF"] = newspec
else
- input.report("setting configuration variable TEXMF to", specification)
- instance.variables['TEXMF'] = "{" .. specification .. "}"
- end
- if instance.variables['TEXMF']:find("%,") and not instance.variables['TEXMF']:find("^%{") then
- input.report("adding {} to complex TEXMF variable, best do that yourself")
- instance.variables['TEXMF'] = "{" .. instance.variables['TEXMF'] .. "}"
+ -- weird
end
- input.expand_variables(instance)
- input.reset_hashes(instance)
+ input.expand_variables()
+ input.reset_hashes()
end
-- locators
-function input.locatelists(instance)
- for _, path in pairs(input.simplified_list(input.expansion(instance,'TEXMF'))) do
- path = file.collapse_path(path)
- input.report("locating list of",path)
- input.locatedatabase(instance,input.normalize_name(path))
+function input.locatelists()
+ local instance = input.instance
+ for _, path in pairs(input.clean_path_list('TEXMF')) do
+ input.report("locating list of %s",path)
+ input.locatedatabase(input.normalize_name(path))
end
end
-function input.locatedatabase(instance,specification)
- return input.methodhandler('locators', instance, specification)
+function input.locatedatabase(specification)
+ return input.methodhandler('locators', specification)
end
-function input.locators.tex(instance,specification)
+function input.locators.tex(specification)
if specification and specification ~= '' and lfs.isdir(specification) then
- input.logger('! tex locator', specification..' found')
- input.aux.append_hash(instance,'file',specification,filename)
- else
- input.logger('? tex locator', specification..' not found')
+ if input.trace > 0 then
+ input.logger('! tex locator found: %s',specification)
+ end
+ input.aux.append_hash('file',specification,filename)
+ elseif input.trace > 0 then
+ input.logger('? tex locator not found: %s',specification)
end
end
-- hashers
-function input.hashdatabase(instance,tag,name)
- return input.methodhandler('hashers',instance,tag,name)
+function input.hashdatabase(tag,name)
+ return input.methodhandler('hashers',tag,name)
end
-function input.loadfiles(instance)
+function input.loadfiles()
+ local instance = input.instance
instance.loaderror = false
instance.files = { }
if not instance.renewcache then
for _, hash in ipairs(instance.hashes) do
- input.hashdatabase(instance,hash.tag,hash.name)
+ input.hashdatabase(hash.tag,hash.name)
if instance.loaderror then break end
end
end
end
-function input.hashers.tex(instance,tag,name)
- input.aux.load_files(instance,tag)
+function input.hashers.tex(tag,name)
+ input.aux.load_files(tag)
end
-- generators:
-function input.loadlists(instance)
- for _, hash in ipairs(instance.hashes) do
- input.generatedatabase(instance,hash.tag)
+function input.loadlists()
+ for _, hash in ipairs(input.instance.hashes) do
+ input.generatedatabase(hash.tag)
end
end
-function input.generatedatabase(instance,specification)
- return input.methodhandler('generators', instance, specification)
+function input.generatedatabase(specification)
+ return input.methodhandler('generators', specification)
end
-do
-
- local weird = lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local weird = lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
- function input.generators.tex(instance,specification)
- local tag = specification
- if not instance.lsrmode and lfs and lfs.dir then
- input.report("scanning path",specification)
- instance.files[tag] = { }
- local files = instance.files[tag]
- local n, m, r = 0, 0, 0
- local spec = specification .. '/'
- local attributes = lfs.attributes
- local directory = lfs.dir
- local small = instance.smallcache
- local function action(path)
- local mode, full
- if path then
- full = spec .. path .. '/'
+function input.generators.tex(specification)
+ local instance = input.instance
+ local tag = specification
+ if not instance.lsrmode and lfs.dir then
+ input.report("scanning path %s",specification)
+ instance.files[tag] = { }
+ local files = instance.files[tag]
+ local n, m, r = 0, 0, 0
+ local spec = specification .. '/'
+ local attributes = lfs.attributes
+ local directory = lfs.dir
+ local small = instance.smallcache
+ local function action(path)
+ local mode, full
+ if path then
+ full = spec .. path .. '/'
+ else
+ full = spec
+ end
+ for name in directory(full) do
+ if name:find("^%.") then
+ -- skip
+ -- elseif name:find("[%~%`%!%#%$%%%^%&%*%(%)%=%{%}%[%]%:%;\"\'%|%<%>%,%?\n\r\t]") then -- too much escaped
+ elseif weird:match(name) then
+ -- texio.write_nl("skipping " .. name)
+ -- skip
else
- full = spec
- end
- for name in directory(full) do
- if name:find("^%.") then
- -- skip
- -- elseif name:find("[%~%`%!%#%$%%%^%&%*%(%)%=%{%}%[%]%:%;\"\'%|%<%>%,%?\n\r\t]") then -- too much escaped
- elseif weird:match(name) then
- -- texio.write_nl("skipping " .. name)
- -- skip
- else
- mode = attributes(full..name,'mode')
- if mode == "directory" then
- m = m + 1
- if path then
- action(path..'/'..name)
- else
- action(name)
- end
- elseif path and mode == 'file' then
- n = n + 1
- local f = files[name]
- if f then
- if not small then
- if type(f) == 'string' then
- files[name] = { f, path }
- else
- f[#f+1] = path
- end
- end
- else
- files[name] = path
- local lower = name:lower()
- if name ~= lower then
- files["remap:"..lower] = name
- r = r + 1
- end
- end
+ mode = attributes(full..name,'mode')
+ if mode == 'directory' then
+ m = m + 1
+ if path then
+ action(path..'/'..name)
+ else
+ action(name)
end
- end
- end
- end
- action()
- input.report(format("%s files found on %s directories with %s uppercase remappings",n,m,r))
- else
- local fullname = file.join(specification,input.lsrname)
- local path = '.'
- local f = io.open(fullname)
- if f then
- instance.files[tag] = { }
- local files = instance.files[tag]
- local small = instance.smallcache
- input.report("loading lsr file",fullname)
- -- for line in f:lines() do -- much slower then the next one
- for line in (f:read("*a")):gmatch("(.-)\n") do
- if line:find("^[%a%d]") then
- local fl = files[line]
- if fl then
+ elseif path and mode == 'file' then
+ n = n + 1
+ local f = files[name]
+ if f then
if not small then
- if type(fl) == 'string' then
- files[line] = { fl, path } -- table
+ if type(f) == 'string' then
+ files[name] = { f, path }
else
- fl[#fl+1] = path
+ f[#f+1] = path
end
end
else
- files[line] = path -- string
- local lower = line:lower()
- if line ~= lower then
- files["remap:"..lower] = line
+ files[name] = path
+ local lower = name:lower()
+ if name ~= lower then
+ files["remap:"..lower] = name
+ r = r + 1
+ end
+ end
+ end
+ end
+ end
+ end
+ action()
+ input.report("%s files found on %s directories with %s uppercase remappings",n,m,r)
+ else
+ local fullname = file.join(specification,input.lsrname)
+ local path = '.'
+ local f = io.open(fullname)
+ if f then
+ instance.files[tag] = { }
+ local files = instance.files[tag]
+ local small = instance.smallcache
+ input.report("loading lsr file %s",fullname)
+ -- for line in f:lines() do -- much slower then the next one
+ for line in (f:read("*a")):gmatch("(.-)\n") do
+ if line:find("^[%a%d]") then
+ local fl = files[line]
+ if fl then
+ if not small then
+ if type(fl) == 'string' then
+ files[line] = { fl, path } -- table
+ else
+ fl[#fl+1] = path
end
end
else
- path = line:match("%.%/(.-)%:$") or path -- match could be nil due to empty line
+ files[line] = path -- string
+ local lower = line:lower()
+ if line ~= lower then
+ files["remap:"..lower] = line
+ end
end
+ else
+ path = line:match("%.%/(.-)%:$") or path -- match could be nil due to empty line
end
- f:close()
end
+ f:close()
end
end
-
end
-- savers, todo
-function input.savefiles(instance)
- input.aux.save_data(instance, 'files', function(k,v)
- return instance.validfile(k,v) -- path, name
+function input.savefiles()
+ input.aux.save_data('files', function(k,v)
+ return input.instance.validfile(k,v) -- path, name
end)
end
@@ -5527,8 +5841,8 @@ end
-- we join them and split them after the expansion has taken place. This
-- is more convenient.
-function input.splitconfig(instance)
- for i,c in ipairs(instance) do
+function input.splitconfig()
+ for i,c in ipairs(input.instance) do
for k,v in pairs(c) do
if type(v) == 'string' then
local t = file.split_path(v)
@@ -5539,8 +5853,9 @@ function input.splitconfig(instance)
end
end
end
-function input.joinconfig(instance)
- for i,c in ipairs(instance.order) do
+
+function input.joinconfig()
+ for i,c in ipairs(input.instance.order) do
for k,v in pairs(c) do
if type(v) == 'table' then
c[k] = file.join_path(v)
@@ -5563,8 +5878,9 @@ function input.join_path(str)
end
end
-function input.splitexpansions(instance)
- for k,v in pairs(instance.expansions) do
+function input.splitexpansions()
+ local ie = input.instance.expansions
+ for k,v in pairs(ie) do
local t, h = { }, { }
for _,vv in pairs(file.split_path(v)) do
if vv ~= "" and not h[vv] then
@@ -5573,19 +5889,19 @@ function input.splitexpansions(instance)
end
end
if #t > 1 then
- instance.expansions[k] = t
+ ie[k] = t
else
- instance.expansions[k] = t[1]
+ ie[k] = t[1]
end
end
end
-- end of split/join code
-function input.saveoldconfig(instance)
- input.splitconfig(instance)
- input.aux.save_data(instance, 'configuration', nil)
- input.joinconfig(instance)
+function input.saveoldconfig()
+ input.splitconfig()
+ input.aux.save_data('configuration', nil)
+ input.joinconfig()
end
input.configbanner = [[
@@ -5614,7 +5930,7 @@ function input.serialize(files)
end
end
t[#t+1] = "return {"
- if instance.sortdata then
+ if input.instance.sortdata then
for _, k in pairs(sorted(files)) do
local fk = files[k]
if type(fk) == 'table' then
@@ -5646,11 +5962,11 @@ end
if not texmf then texmf = {} end -- no longer needed, at least not here
-function input.aux.save_data(instance, dataname, check, makename) -- untested without cache overload
- for cachename, files in pairs(instance[dataname]) do
+function input.aux.save_data(dataname, check, makename) -- untested without cache overload
+ for cachename, files in pairs(input.instance[dataname]) do
local name = (makename or file.join)(cachename,dataname)
- local luaname, lucname = name .. input.luasuffix, name .. input.lucsuffix
- input.report("preparing " .. dataname .. " for", luaname)
+ local luaname, lucname = name .. ".lua", name .. ".luc"
+ input.report("preparing %s for %s",dataname,cachename)
for k, v in pairs(files) do
if not check or check(v,k) then -- path, name
if type(v) == "table" and #v == 1 then
@@ -5668,38 +5984,38 @@ function input.aux.save_data(instance, dataname, check, makename) -- untested wi
time = os.date("%H:%M:%S"),
content = files,
}
- local f = io.open(luaname,'w')
- if f then
- input.report("saving " .. dataname .. " in", luaname)
- f:write(input.serialize(data))
- f:close()
- input.report("compiling " .. dataname .. " to", lucname)
- if not utils.lua.compile(luaname,lucname) then
- input.report("compiling failed for " .. dataname .. ", deleting file " .. lucname)
+ local ok = io.savedata(luaname,input.serialize(data))
+ if ok then
+ input.report("%s saved in %s",dataname,luaname)
+ if utils.lua.compile(luaname,lucname,false,true) then -- no cleanup but strip
+ input.report("%s compiled to %s",dataname,lucname)
+ else
+ input.report("compiling failed for %s, deleting file %s",dataname,lucname)
os.remove(lucname)
end
else
- input.report("unable to save " .. dataname .. " in " .. name..input.luasuffix)
+ input.report("unable to save %s in %s (access error)",dataname,luaname)
end
end
end
-function input.aux.load_data(instance,pathname,dataname,filename,makename) -- untested without cache overload
+function input.aux.load_data(pathname,dataname,filename,makename) -- untested without cache overload
+ local instance = input.instance
filename = ((not filename or (filename == "")) and dataname) or filename
filename = (makename and makename(dataname,filename)) or file.join(pathname,filename)
- local blob = loadfile(filename .. input.lucsuffix) or loadfile(filename .. input.luasuffix)
+ local blob = loadfile(filename .. ".luc") or loadfile(filename .. ".lua")
if blob then
local data = blob()
if data and data.content and data.type == dataname and data.version == input.cacheversion then
- input.report("loading",dataname,"for",pathname,"from",filename)
+ input.report("loading %s for %s from %s",dataname,pathname,filename)
instance[dataname][pathname] = data.content
else
- input.report("skipping",dataname,"for",pathname,"from",filename)
+ input.report("skipping %s for %s from %s",dataname,pathname,filename)
instance[dataname][pathname] = { }
instance.loaderror = true
end
else
- input.report("skipping",dataname,"for",pathname,"from",filename)
+ input.report("skipping %s for %s from %s",dataname,pathname,filename)
end
end
@@ -5712,13 +6028,14 @@ end
-- TEXMFBOGUS = 'effe checken of dit werkt',
-- }
-function input.aux.load_texmfcnf(instance,dataname,pathname)
+function input.aux.load_texmfcnf(dataname,pathname)
+ local instance = input.instance
local filename = file.join(pathname,input.luaname)
local blob = loadfile(filename)
if blob then
local data = blob()
if data then
- input.report("loading","configuration file",filename)
+ input.report("loading configuration file %s",filename)
if true then
-- flatten to variable.progname
local t = { }
@@ -5738,169 +6055,168 @@ function input.aux.load_texmfcnf(instance,dataname,pathname)
instance[dataname][pathname] = data
end
else
- input.report("skipping","configuration file",filename)
+ input.report("skipping configuration file %s",filename)
instance[dataname][pathname] = { }
instance.loaderror = true
end
else
- input.report("skipping","configuration file",filename)
+ input.report("skipping configuration file %s",filename)
end
end
-function input.aux.load_configuration(instance,dname,lname)
- input.aux.load_data(instance,dname,'configuration',lname and file.basename(lname))
+function input.aux.load_configuration(dname,lname)
+ input.aux.load_data(dname,'configuration',lname and file.basename(lname))
end
-function input.aux.load_files(instance,tag)
- input.aux.load_data(instance,tag,'files')
+function input.aux.load_files(tag)
+ input.aux.load_data(tag,'files')
end
-function input.resetconfig(instance)
+function input.resetconfig()
+ input.identify_own()
+ local instance = input.instance
instance.configuration, instance.setup, instance.order, instance.loaderror = { }, { }, { }, false
end
-function input.loadnewconfig(instance)
+function input.loadnewconfig()
+ local instance = input.instance
for _, cnf in ipairs(instance.luafiles) do
local dname = file.dirname(cnf)
- input.aux.load_texmfcnf(instance,'setup',dname)
+ input.aux.load_texmfcnf('setup',dname)
instance.order[#instance.order+1] = instance.setup[dname]
if instance.loaderror then break end
end
end
-function input.loadoldconfig(instance)
+function input.loadoldconfig()
+ local instance = input.instance
if not instance.renewcache then
for _, cnf in ipairs(instance.cnffiles) do
local dname = file.dirname(cnf)
- input.aux.load_configuration(instance,dname)
+ input.aux.load_configuration(dname)
instance.order[#instance.order+1] = instance.configuration[dname]
if instance.loaderror then break end
end
end
- input.joinconfig(instance)
+ input.joinconfig()
end
-function input.expand_variables(instance)
- instance.expansions = { }
---~ instance.environment['SELFAUTOPARENT'] = instance.environment['SELFAUTOPARENT'] or instance.rootpath
- if instance.engine ~= "" then instance.environment['engine'] = instance.engine end
- if instance.progname ~= "" then instance.environment['progname'] = instance.progname end
- for k,v in pairs(instance.environment) do
+function input.expand_variables()
+ local instance = input.instance
+ local expansions, environment, variables = { }, instance.environment, instance.variables
+ local env = input.env
+ instance.expansions = expansions
+ if instance.engine ~= "" then environment['engine'] = instance.engine end
+ if instance.progname ~= "" then environment['progname'] = instance.progname end
+ for k,v in pairs(environment) do
local a, b = k:match("^(%a+)%_(.*)%s*$")
if a and b then
- instance.expansions[a..'.'..b] = v
+ expansions[a..'.'..b] = v
else
- instance.expansions[k] = v
+ expansions[k] = v
end
end
- for k,v in pairs(instance.environment) do -- move environment to expansions
- if not instance.expansions[k] then instance.expansions[k] = v end
+ for k,v in pairs(environment) do -- move environment to expansions
+ if not expansions[k] then expansions[k] = v end
end
- for k,v in pairs(instance.variables) do -- move variables to expansions
- if not instance.expansions[k] then instance.expansions[k] = v end
+ for k,v in pairs(variables) do -- move variables to expansions
+ if not expansions[k] then expansions[k] = v end
end
while true do
local busy = false
- for k,v in pairs(instance.expansions) do
+ for k,v in pairs(expansions) do
local s, n = v:gsub("%$([%a%d%_%-]+)", function(a)
busy = true
- return instance.expansions[a] or input.env(instance,a)
+ return expansions[a] or env(a)
end)
local s, m = s:gsub("%$%{([%a%d%_%-]+)%}", function(a)
busy = true
- return instance.expansions[a] or input.env(instance,a)
+ return expansions[a] or env(a)
end)
if n > 0 or m > 0 then
- instance.expansions[k]= s
+ expansions[k]= s
end
end
if not busy then break end
end
- for k,v in pairs(instance.expansions) do
- instance.expansions[k] = v:gsub("\\", '/')
+ for k,v in pairs(expansions) do
+ expansions[k] = v:gsub("\\", '/')
end
end
-function input.aux.expand_vars(instance,lst) -- simple vars
+function input.aux.expand_vars(lst) -- simple vars
+ local instance = input.instance
+ local variables, env = instance.variables, input.env
for k,v in pairs(lst) do
lst[k] = v:gsub("%$([%a%d%_%-]+)", function(a)
- return instance.variables[a] or input.env(instance,a)
+ return variables[a] or env(a)
end)
end
end
-function input.aux.expanded_var(instance,var) -- simple vars
+function input.aux.expanded_var(var) -- simple vars
+ local instance = input.instance
return var:gsub("%$([%a%d%_%-]+)", function(a)
- return instance.variables[a] or input.env(instance,a)
+ return instance.variables[a] or input.env(a)
end)
end
-function input.aux.entry(instance,entries,name)
+function input.aux.entry(entries,name)
if name and (name ~= "") then
+ local instance = input.instance
name = name:gsub('%$','')
local result = entries[name..'.'..instance.progname] or entries[name]
if result then
return result
else
- result = input.env(instance,name)
+ result = input.env(name)
if result then
instance.variables[name] = result
- input.expand_variables(instance)
+ input.expand_variables()
return instance.expansions[name] or ""
end
end
end
return ""
end
-function input.variable(instance,name)
- return input.aux.entry(instance,instance.variables,name)
+function input.variable(name)
+ return input.aux.entry(input.instance.variables,name)
end
-function input.expansion(instance,name)
- return input.aux.entry(instance,instance.expansions,name)
+function input.expansion(name)
+ return input.aux.entry(input.instance.expansions,name)
end
-function input.aux.is_entry(instance,entries,name)
+function input.aux.is_entry(entries,name)
if name and name ~= "" then
name = name:gsub('%$','')
- return (entries[name..'.'..instance.progname] or entries[name]) ~= nil
+ return (entries[name..'.'..input.instance.progname] or entries[name]) ~= nil
else
return false
end
end
-function input.is_variable(instance,name)
- return input.aux.is_entry(instance,instance.variables,name)
-end
-function input.is_expansion(instance,name)
- return input.aux.is_entry(instance,instance.expansions,name)
+function input.is_variable(name)
+ return input.aux.is_entry(input.instance.variables,name)
end
-function input.simplified_list(str)
- if type(str) == 'table' then
- return str -- troubles ; ipv , in texmf
- elseif str == '' then
- return { }
- else
- local t = { }
- for _,v in ipairs(string.splitchr(str:gsub("^\{(.+)\}$","%1"),",")) do
- t[#t+1] = (v:gsub("^[%!]*(.+)[%/\\]*$","%1"))
- end
- return t
- end
+function input.is_expansion(name)
+ return input.aux.is_entry(input.instance.expansions,name)
end
-function input.unexpanded_path_list(instance,str)
- local pth = input.variable(instance,str)
+function input.unexpanded_path_list(str)
+ local pth = input.variable(str)
local lst = input.split_path(pth)
- return input.aux.expanded_path(instance,lst)
+ return input.aux.expanded_path(lst)
end
-function input.unexpanded_path(instance,str)
- return file.join_path(input.unexpanded_path_list(instance,str))
+
+function input.unexpanded_path(str)
+ return file.join_path(input.unexpanded_path_list(str))
end
do
local done = { }
- function input.reset_extra_path(instance)
+ function input.reset_extra_path()
+ local instance = input.instance
local ep = instance.extra_paths
if not ep then
ep, done = { }, { }
@@ -5910,7 +6226,8 @@ do
end
end
- function input.register_extra_path(instance,paths,subpaths)
+ function input.register_extra_path(paths,subpaths)
+ local instance = input.instance
local ep = instance.extra_paths or { }
local n = #ep
if paths and paths ~= "" then
@@ -5955,7 +6272,8 @@ do
end
-function input.expanded_path_list(instance,str)
+function input.expanded_path_list(str)
+ local instance = input.instance
local function made_list(list)
local ep = instance.extra_paths
if not ep or #ep == 0 then
@@ -5996,39 +6314,41 @@ function input.expanded_path_list(instance,str)
-- engine+progname hash
str = str:gsub("%$","")
if not instance.lists[str] then -- cached
- local lst = made_list(input.split_path(input.expansion(instance,str)))
- instance.lists[str] = input.aux.expanded_path(instance,lst)
+ local lst = made_list(input.split_path(input.expansion(str)))
+ instance.lists[str] = input.aux.expanded_path(lst)
end
return instance.lists[str]
else
- local lst = input.split_path(input.expansion(instance,str))
- return made_list(input.aux.expanded_path(instance,lst))
+ local lst = input.split_path(input.expansion(str))
+ return made_list(input.aux.expanded_path(lst))
end
end
-function input.expand_path(instance,str)
- return file.join_path(input.expanded_path_list(instance,str))
+
+function input.clean_path_list(str)
+ local t = input.expanded_path_list(str)
+ if t then
+ for i=1,#t do
+ t[i] = file.collapse_path(input.clean_path(t[i]))
+ end
+ end
+ return t
end
---~ function input.first_writable_path(instance,name)
---~ for _,v in pairs(input.expanded_path_list(instance,name)) do
---~ if file.is_writable(file.join(v,'luatex-cache.tmp')) then
---~ return v
---~ end
---~ end
---~ return "."
---~ end
+function input.expand_path(str)
+ return file.join_path(input.expanded_path_list(str))
+end
-function input.expanded_path_list_from_var(instance,str) -- brrr
+function input.expanded_path_list_from_var(str) -- brrr
local tmp = input.var_of_format_or_suffix(str:gsub("%$",""))
if tmp ~= "" then
- return input.expanded_path_list(instance,str)
+ return input.expanded_path_list(str)
else
- return input.expanded_path_list(instance,tmp)
+ return input.expanded_path_list(tmp)
end
end
-function input.expand_path_from_var(instance,str)
- return file.join_path(input.expanded_path_list_from_var(instance,str))
+function input.expand_path_from_var(str)
+ return file.join_path(input.expanded_path_list_from_var(str))
end
function input.format_of_var(str)
@@ -6058,9 +6378,9 @@ function input.var_of_format_or_suffix(str)
return ''
end
-function input.expand_braces(instance,str) -- output variable and brace expansion of STRING
- local ori = input.variable(instance,str)
- local pth = input.aux.expanded_path(instance,input.split_path(ori))
+function input.expand_braces(str) -- output variable and brace expansion of STRING
+ local ori = input.variable(str)
+ local pth = input.aux.expanded_path(input.split_path(ori))
return file.join_path(pth)
end
@@ -6075,6 +6395,7 @@ end
-- {a,b,c/{p,q,r}/d/{x,y,z}//}
-- {a,b,c/{p,q/{x,y,z}},d/{p,q,r}}
-- {a,b,c/{p,q/{x,y,z},w}v,d/{p,q,r}}
+-- {$SELFAUTODIR,$SELFAUTOPARENT}{,{/share,}/texmf{-local,.local,}/web2c}
-- this one is better and faster, but it took me a while to realize
-- that this kind of replacement is cleaner than messy parsing and
@@ -6083,19 +6404,20 @@ end
-- work that well; the parsing is ok, but dealing with the resulting
-- table is a pain because we need to work inside-out recursively
--- get rid of piecewise here, just a gmatch is ok
-
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 .. "@"
while true do
local done = false
while true do
local ok = false
- str = str:gsub("([^{},]+){([^{}]-)}", function(a,b)
+ str = str:gsub("([^{},]+){([^{}]+)}", function(a,b)
local t = { }
- b:piecewise(",", function(s) t[#t+1] = a .. s end)
+ for s in b:gmatch("[^,]+") do t[#t+1] = a .. s end
ok, done = true, true
return "{" .. concat(t,",") .. "}"
end)
@@ -6103,9 +6425,9 @@ function input.aux.splitpathexpr(str, t, validate)
end
while true do
local ok = false
- str = str:gsub("{([^{}]-)}([^{},]+)", function(a,b)
+ str = str:gsub("{([^{}]+)}([^{},]+)", function(a,b)
local t = { }
- a:piecewise(",", function(s) t[#t+1] = s .. b end)
+ for s in a:gmatch("[^,]+") do t[#t+1] = s .. b end
ok, done = true, true
return "{" .. concat(t,",") .. "}"
end)
@@ -6113,50 +6435,41 @@ function input.aux.splitpathexpr(str, t, validate)
end
while true do
local ok = false
- str = str:gsub("([,{]){([^{}]+)}([,}])", function(a,b,c)
+ str = str:gsub("{([^{}]+)}{([^{}]+)}", function(a,b)
+ local t = { }
+ for sa in a:gmatch("[^,]+") do
+ for sb in b:gmatch("[^,]+") do
+ t[#t+1] = sa .. sb
+ end
+ end
ok, done = true, true
- return a .. b .. c
+ return "{" .. concat(t,",") .. "}"
end)
if not ok then break end
end
- if not done then break end
- end
- while true do
- local ok = false
- str = str:gsub("{([^{}]-)}{([^{}]-)}", function(a,b)
- local t = { }
- a:piecewise(",", function(sa)
- b:piecewise(",", function(sb)
- t[#t+1] = sa .. sb
- end)
- end)
- ok = true
- return "{" .. concat(t,",") .. "}"
- end)
- if not ok then break end
- end
- while true do
- local ok = false
- str = str:gsub("{([^{}]-)}", function(a)
- ok = true
- return a
+ str = str:gsub("({[^{}]*){([^{}]+)}([^{}]*})", function(a,b,c)
+ done = true
+ return a .. b.. c
end)
- if not ok then break end
+ if not done then break end
end
+ str = str:gsub("[{}]", "")
+ str = str:gsub("@","")
if validate then
- str:piecewise(",", function(s)
+ for s in str:gmatch("[^,]+") do
s = validate(s)
if s then t[#t+1] = s end
- end)
+ end
else
- str:piecewise(",", function(s)
+ for s in str:gmatch("[^,]+") do
t[#t+1] = s
- end)
+ end
end
return t
end
-function input.aux.expanded_path(instance,pathlist) -- maybe not a list, just a path
+function input.aux.expanded_path(pathlist) -- maybe not a list, just a path
+ local instance = input.instance
-- a previous version fed back into pathlist
local newlist, ok = { }, false
for _,v in ipairs(pathlist) do
@@ -6188,17 +6501,16 @@ input.is_readable = { }
function input.aux.is_readable(readable, name)
if input.trace > 2 then
if readable then
- input.logger("+ readable", name)
+ input.logger("+ readable: %s",name)
else
- input.logger("- readable", name)
+ input.logger("- readable: %s", name)
end
end
return readable
end
function input.is_readable.file(name)
- -- return input.aux.is_readable(file.is_readable(name), name)
- return input.aux.is_readable(input.aux.is_file(name), name)
+ return input.aux.is_readable(lfs.isfile(name), name)
end
input.is_readable.tex = input.is_readable.file
@@ -6206,12 +6518,13 @@ input.is_readable.tex = input.is_readable.file
-- name
-- name/name
-function input.aux.collect_files(instance,names)
+function input.aux.collect_files(names)
+ local instance = input.instance
local filelist = { }
for _, fname in pairs(names) do
if fname then
if input.trace > 2 then
- input.logger("? blobpath asked",fname)
+ input.logger("? blobpath asked: %s",fname)
end
local bname = file.basename(fname)
local dname = file.dirname(fname)
@@ -6225,7 +6538,7 @@ function input.aux.collect_files(instance,names)
local files = blobpath and instance.files[blobpath]
if files then
if input.trace > 2 then
- input.logger('? blobpath do',blobpath .. " (" .. bname ..")")
+ input.logger('? blobpath do: %s (%s)',blobpath,bname)
end
local blobfile = files[bname]
if not blobfile then
@@ -6258,7 +6571,7 @@ function input.aux.collect_files(instance,names)
end
end
elseif input.trace > 1 then
- input.logger('! blobpath no',blobpath .. " (" .. bname ..")" )
+ input.logger('! blobpath no: %s (%s)',blobpath,bname)
end
end
end
@@ -6313,15 +6626,17 @@ do
end
-function input.aux.register_in_trees(instance,name)
+function input.aux.register_in_trees(name)
if not name:find("^%.") then
+ local instance = input.instance
instance.foundintrees[name] = (instance.foundintrees[name] or 0) + 1 -- maybe only one
end
end
-- split the next one up, better for jit
-function input.aux.find_file(instance,filename) -- todo : plugin (scanners, checkers etc)
+function input.aux.find_file(filename) -- todo : plugin (scanners, checkers etc)
+ local instance = input.instance
local result = { }
local stamp = nil
filename = input.normalize_name(filename) -- elsewhere
@@ -6330,16 +6645,22 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
if instance.remember then
stamp = filename .. "--" .. instance.engine .. "--" .. instance.progname .. "--" .. instance.format
if instance.found[stamp] then
- input.logger('! remembered', filename)
+ if input.trace > 0 then
+ input.logger('! remembered: %s',filename)
+ end
return instance.found[stamp]
end
end
if filename:find('%*') then
- input.logger('! wildcard', filename)
- result = input.find_wildcard_files(instance,filename)
+ if input.trace > 0 then
+ input.logger('! wildcard: %s', filename)
+ end
+ result = input.find_wildcard_files(filename)
elseif input.aux.qualified_path(filename) then
if input.is_readable.file(filename) then
- input.logger('! qualified', filename)
+ if input.trace > 0 then
+ input.logger('! qualified: %s', filename)
+ end
result = { filename }
else
local forcedname, ok = "", false
@@ -6347,22 +6668,26 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
if instance.format == "" then
forcedname = filename .. ".tex"
if input.is_readable.file(forcedname) then
- input.logger('! no suffix, forcing standard filetype tex')
+ if input.trace > 0 then
+ input.logger('! no suffix, forcing standard filetype: tex')
+ end
result, ok = { forcedname }, true
end
else
for _, s in pairs(input.suffixes_of_format(instance.format)) do
forcedname = filename .. "." .. s
if input.is_readable.file(forcedname) then
- input.logger('! no suffix, forcing format filetype', s)
+ if input.trace > 0 then
+ input.logger('! no suffix, forcing format filetype: %s', s)
+ end
result, ok = { forcedname }, true
break
end
end
end
end
- if not ok then
- input.logger('? qualified', filename)
+ if not ok and input.trace > 0 then
+ input.logger('? qualified: %s', filename)
end
end
else
@@ -6380,10 +6705,14 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
local forcedname = filename .. '.tex'
wantedfiles[#wantedfiles+1] = forcedname
filetype = input.format_of_suffix(forcedname)
- input.logger('! forcing filetype',filetype)
+ if input.trace > 0 then
+ input.logger('! forcing filetype: %s',filetype)
+ end
else
filetype = input.format_of_suffix(filename)
- input.logger('! using suffix based filetype',filetype)
+ if input.trace > 0 then
+ input.logger('! using suffix based filetype: %s',filetype)
+ end
end
else
if ext == "" then
@@ -6392,16 +6721,18 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
end
end
filetype = instance.format
- input.logger('! using given filetype',filetype)
+ if input.trace > 0 then
+ input.logger('! using given filetype: %s',filetype)
+ end
end
local typespec = input.variable_of_format(filetype)
- local pathlist = input.expanded_path_list(instance,typespec)
+ local pathlist = input.expanded_path_list(typespec)
if not pathlist or #pathlist == 0 then
-- no pathlist, access check only / todo == wildcard
if input.trace > 2 then
- input.logger('? filename',filename)
- input.logger('? filetype',filetype or '?')
- input.logger('? wanted files',table.concat(wantedfiles," | "))
+ input.logger('? filename: %s',filename)
+ input.logger('? filetype: %s',filetype or '?')
+ input.logger('? wanted files: %s',table.concat(wantedfiles," | "))
end
for _, fname in pairs(wantedfiles) do
if fname and input.is_readable.file(fname) then
@@ -6411,7 +6742,7 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
end
end
-- this is actually 'other text files' or 'any' or 'whatever'
- local filelist = input.aux.collect_files(instance,wantedfiles)
+ local filelist = input.aux.collect_files(wantedfiles)
local fl = filelist and filelist[1]
if fl then
filename = fl[3]
@@ -6420,12 +6751,12 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
end
else
-- list search
- local filelist = input.aux.collect_files(instance,wantedfiles)
+ local filelist = input.aux.collect_files(wantedfiles)
local doscan, recurse
if input.trace > 2 then
- input.logger('? filename',filename)
- -- if pathlist then input.logger('? path list',table.concat(pathlist," | ")) end
- -- if filelist then input.logger('? file list',table.concat(filelist," | ")) end
+ 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
end
-- a bit messy ... esp the doscan setting here
for _, path in pairs(pathlist) do
@@ -6446,11 +6777,11 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
if f:find(expr) then
-- input.debug('T',' '..f)
if input.trace > 2 then
- input.logger('= found in hash',f)
+ input.logger('= found in hash: %s',f)
end
--- todo, test for readable
result[#result+1] = fl[3]
- input.aux.register_in_trees(instance,f) -- for tracing used files
+ input.aux.register_in_trees(f) -- for tracing used files
done = true
if not instance.allresults then break end
else
@@ -6464,12 +6795,12 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
local pname = pathname:gsub("%.%*$",'')
if not pname:find("%*") then
local ppname = pname:gsub("/+$","")
- if input.aux.can_be_dir(instance,ppname) then
+ if input.aux.can_be_dir(ppname) then
for _, w in pairs(wantedfiles) do
local fname = file.join(ppname,w)
if input.is_readable.file(fname) then
if input.trace > 2 then
- input.logger('= found by scanning',fname)
+ input.logger('= found by scanning: %s',fname)
end
result[#result+1] = fname
done = true
@@ -6498,40 +6829,29 @@ function input.aux.find_file(instance,filename) -- todo : plugin (scanners, chec
return result
end
-input.aux._find_file_ = input.aux.find_file
+input.aux._find_file_ = input.aux.find_file -- frozen variant
-function input.aux.find_file(instance,filename) -- maybe make a lowres cache too
- local result = input.aux._find_file_(instance,filename)
+function input.aux.find_file(filename) -- maybe make a lowres cache too
+ local result = input.aux._find_file_(filename)
if #result == 0 then
local lowered = filename:lower()
if filename ~= lowered then
- return input.aux._find_file_(instance,lowered)
+ return input.aux._find_file_(lowered)
end
end
return result
end
-if lfs and lfs.isfile then
- input.aux.is_file = lfs.isfile -- to be done: use this
-else
- input.aux.is_file = file.is_readable
-end
-
-if lfs and lfs.isdir then
- function input.aux.can_be_dir(instance,name)
- if not instance.fakepaths[name] then
- if lfs.isdir(name) then
- instance.fakepaths[name] = 1 -- directory
- else
- instance.fakepaths[name] = 2 -- no directory
- end
+function input.aux.can_be_dir(name)
+ local instance = input.instance
+ if not instance.fakepaths[name] then
+ if lfs.isdir(name) then
+ instance.fakepaths[name] = 1 -- directory
+ else
+ instance.fakepaths[name] = 2 -- no directory
end
- return (instance.fakepaths[name] == 1)
- end
-else
- function input.aux.can_be_dir()
- return true
end
+ return (instance.fakepaths[name] == 1)
end
if not input.concatinators then input.concatinators = { } end
@@ -6539,7 +6859,8 @@ if not input.concatinators then input.concatinators = { } end
input.concatinators.tex = file.join
input.concatinators.file = input.concatinators.tex
-function input.find_files(instance,filename,filetype,mustexist)
+function input.find_files(filename,filetype,mustexist)
+ local instance = input.instance
if type(mustexist) == boolean then
-- all set
elseif type(filetype) == 'boolean' then
@@ -6548,16 +6869,17 @@ function input.find_files(instance,filename,filetype,mustexist)
filetype, mustexist = nil, false
end
instance.format = filetype or ''
- local t = input.aux.find_file(instance,filename,true)
+ local t = input.aux.find_file(filename,true)
instance.format = ''
return t
end
-function input.find_file(instance,filename,filetype,mustexist)
- return (input.find_files(instance,filename,filetype,mustexist)[1] or "")
+function input.find_file(filename,filetype,mustexist)
+ return (input.find_files(filename,filetype,mustexist)[1] or "")
end
-function input.find_given_files(instance,filename)
+function input.find_given_files(filename)
+ local instance = input.instance
local bname, result = file.basename(filename), { }
for k, hash in ipairs(instance.hashes) do
local files = instance.files[hash.tag]
@@ -6585,11 +6907,12 @@ function input.find_given_files(instance,filename)
return result
end
-function input.find_given_file(instance,filename)
- return (input.find_given_files(instance,filename)[1] or "")
+function input.find_given_file(filename)
+ return (input.find_given_files(filename)[1] or "")
end
-function input.find_wildcard_files(instance,filename) -- todo: remap:
+function input.find_wildcard_files(filename) -- todo: remap:
+ local instance = input.instance
local result = { }
local bname, dname = file.basename(filename), file.dirname(filename)
local path = dname:gsub("^*/","")
@@ -6645,13 +6968,14 @@ function input.find_wildcard_files(instance,filename) -- todo: remap:
return result
end
-function input.find_wildcard_file(instance,filename)
- return (input.find_wildcard_files(instance,filename)[1] or "")
+function input.find_wildcard_file(filename)
+ return (input.find_wildcard_files(filename)[1] or "")
end
-- main user functions
-function input.save_used_files_in_trees(instance, filename,jobname)
+function input.save_used_files_in_trees(filename,jobname)
+ local instance = input.instance
if not filename then filename = 'luatex.jlg' end
local f = io.open(filename,'w')
if f then
@@ -6670,24 +6994,24 @@ function input.save_used_files_in_trees(instance, filename,jobname)
end
end
-function input.automount(instance)
+function input.automount()
-- implemented later
end
-function input.load(instance)
- input.starttiming(instance)
- input.resetconfig(instance)
- input.identify_cnf(instance)
- input.load_lua(instance)
- input.expand_variables(instance)
- input.load_cnf(instance)
- input.expand_variables(instance)
- input.load_hash(instance)
- input.automount(instance)
- input.stoptiming(instance)
+function input.load()
+ input.starttiming(input.instance)
+ input.resetconfig()
+ input.identify_cnf()
+ input.load_lua()
+ input.expand_variables()
+ input.load_cnf()
+ input.expand_variables()
+ input.load_hash()
+ input.automount()
+ input.stoptiming(input.instance)
end
-function input.for_files(instance, command, files, filetype, mustexist)
+function input.for_files(command, files, filetype, mustexist)
if files and #files > 0 then
local function report(str)
if input.verbose then
@@ -6700,7 +7024,7 @@ function input.for_files(instance, command, files, filetype, mustexist)
report('')
end
for _, file in pairs(files) do
- local result = command(instance,file,filetype,mustexist)
+ local result = command(file,filetype,mustexist)
if type(result) == 'string' then
report(result)
else
@@ -6714,14 +7038,11 @@ end
-- strtab
-function input.var_value(instance,str) -- output the value of variable $STRING.
- return input.variable(instance,str)
-end
-function input.expand_var(instance,str) -- output variable expansion of STRING.
- return input.expansion(instance,str)
-end
-function input.show_path(instance,str) -- output search path for file type NAME
- return file.join_path(input.expanded_path_list(instance,input.format_of_var(str)))
+input.var_value = input.variable -- output the value of variable $STRING.
+input.expand_var = input.expansion -- output variable expansion of STRING.
+
+function input.show_path(str) -- output search path for file type NAME
+ return file.join_path(input.expanded_path_list(input.format_of_var(str)))
end
-- input.find_file(filename)
@@ -6773,53 +7094,55 @@ function table.sequenced(t,sep) -- temp here
return table.concat(s, sep or " | ")
end
-function input.methodhandler(what, instance, filename, filetype) -- ...
+function input.methodhandler(what, filename, filetype) -- ...
local specification = (type(filename) == "string" and input.splitmethod(filename)) or filename -- no or { }, let it bomb
local scheme = specification.scheme
if input[what][scheme] then
- input.logger('= handler',specification.original .." -> " .. what .. " -> " .. table.sequenced(specification))
- return input[what][scheme](instance,filename,filetype) -- todo: specification
+ if input.trace > 0 then
+ input.logger('= handler: %s -> %s -> %s',specification.original,what,table.sequenced(specification))
+ end
+ return input[what][scheme](filename,filetype) -- todo: specification
else
- return input[what].tex(instance,filename,filetype) -- todo: specification
+ return input[what].tex(filename,filetype) -- todo: specification
end
end
-- also inside next test?
-function input.findtexfile(instance, filename, filetype)
- return input.methodhandler('finders',instance, input.normalize_name(filename), filetype)
+function input.findtexfile(filename, filetype)
+ return input.methodhandler('finders',input.normalize_name(filename), filetype)
end
-function input.opentexfile(instance,filename)
- return input.methodhandler('openers',instance, input.normalize_name(filename))
+function input.opentexfile(filename)
+ return input.methodhandler('openers',input.normalize_name(filename))
end
-function input.findbinfile(instance, filename, filetype)
- return input.methodhandler('finders',instance, input.normalize_name(filename), filetype)
+function input.findbinfile(filename, filetype)
+ return input.methodhandler('finders',input.normalize_name(filename), filetype)
end
-function input.openbinfile(instance,filename)
- return input.methodhandler('loaders',instance, input.normalize_name(filename))
+function input.openbinfile(filename)
+ return input.methodhandler('loaders',input.normalize_name(filename))
end
-function input.loadbinfile(instance, filename, filetype)
- local fname = input.findbinfile(instance, input.normalize_name(filename), filetype)
+function input.loadbinfile(filename, filetype)
+ local fname = input.findbinfile(input.normalize_name(filename), filetype)
if fname and fname ~= "" then
- return input.openbinfile(instance,fname)
+ return input.openbinfile(fname)
else
return unpack(input.loaders.notfound)
end
end
-function input.texdatablob(instance, filename, filetype)
- local ok, data, size = input.loadbinfile(instance, filename, filetype)
+function input.texdatablob(filename, filetype)
+ local ok, data, size = input.loadbinfile(filename, filetype)
return data or ""
end
input.loadtexfile = input.texdatablob
-function input.openfile(filename) -- brrr texmf.instance here / todo ! ! ! ! !
- local fullname = input.findtexfile(texmf.instance, filename)
+function input.openfile(filename)
+ local fullname = input.findtexfile(filename)
if fullname and (fullname ~= "") then
- return input.opentexfile(texmf.instance, fullname)
+ return input.opentexfile(fullname)
else
return nil
end
@@ -6865,16 +7188,18 @@ end
-- beware: i need to check where we still need a / on windows:
function input.clean_path(str)
---~ return (((str:gsub("\\","/")):gsub("^!+","")):gsub("//+","//"))
if str then
- return ((str:gsub("\\","/")):gsub("^!+",""))
+ str = str:gsub("\\","/")
+ str = str:gsub("^!+","")
+ str = str:gsub("^~",input.homedir)
+ return str
else
return nil
end
end
function input.do_with_path(name,func)
- for _, v in pairs(input.expanded_path_list(instance,name)) do
+ for _, v in pairs(input.expanded_path_list(name)) do
func("^"..input.clean_path(v))
end
end
@@ -6883,7 +7208,8 @@ function input.do_with_var(name,func)
func(input.aux.expanded_var(name))
end
-function input.with_files(instance,pattern,handle)
+function input.with_files(pattern,handle)
+ local instance = input.instance
for _, hash in ipairs(instance.hashes) do
local blobpath = hash.tag
local blobtype = hash.type
@@ -6910,37 +7236,22 @@ function input.with_files(instance,pattern,handle)
end
end
---~ function input.update_script(oldname,newname) -- oldname -> own.name, not per se a suffix
---~ newname = file.addsuffix(newname,"lua")
---~ local newscript = input.clean_path(input.find_file(instance, newname))
---~ local oldscript = input.clean_path(oldname)
---~ input.report("old script", oldscript)
---~ input.report("new script", newscript)
---~ if oldscript ~= newscript and (oldscript:find(file.removesuffix(newname).."$") or oldscript:find(newname.."$")) then
---~ local newdata = io.loaddata(newscript)
---~ if newdata then
---~ input.report("old script content replaced by new content")
---~ io.savedata(oldscript,newdata)
---~ end
---~ end
---~ end
-
-function input.update_script(instance,oldname,newname) -- oldname -> own.name, not per se a suffix
+function input.update_script(oldname,newname) -- oldname -> own.name, not per se a suffix
local scriptpath = "scripts/context/lua"
newname = file.addsuffix(newname,"lua")
local oldscript = input.clean_path(oldname)
- input.report("to be replaced old script", oldscript)
- local newscripts = input.find_files(instance, newname) or { }
+ input.report("to be replaced old script %s", oldscript)
+ local newscripts = input.find_files(newname) or { }
if #newscripts == 0 then
input.report("unable to locate new script")
else
for _, newscript in ipairs(newscripts) do
newscript = input.clean_path(newscript)
- input.report("checking new script", newscript)
+ input.report("checking new script %s", newscript)
if oldscript == newscript then
input.report("old and new script are the same")
elseif not newscript:find(scriptpath) then
- input.report("new script should come from",scriptpath)
+ input.report("new script should come from %s",scriptpath)
elseif not (oldscript:find(file.removesuffix(newname).."$") or oldscript:find(newname.."$")) then
input.report("invalid new script name")
else
@@ -6968,10 +7279,10 @@ do
local resolvers = { }
- resolvers.environment = function(instance,str)
+ resolvers.environment = function(str)
return input.clean_path(os.getenv(str) or os.getenv(str:upper()) or os.getenv(str:lower()) or "")
end
- resolvers.relative = function(instance,str,n)
+ resolvers.relative = function(str,n)
if io.exists(str) then
-- nothing
elseif io.exists("./" .. str) then
@@ -6989,16 +7300,16 @@ do
end
return input.clean_path(str)
end
- resolvers.locate = function(instance,str)
- local fullname = input.find_given_file(instance,str) or ""
+ resolvers.locate = function(str)
+ local fullname = input.find_given_file(str) or ""
return input.clean_path((fullname ~= "" and fullname) or str)
end
- resolvers.filename = function(instance,str)
- local fullname = input.find_given_file(instance,str) or ""
+ resolvers.filename = function(str)
+ local fullname = input.find_given_file(str) or ""
return input.clean_path(file.basename((fullname ~= "" and fullname) or str))
end
- resolvers.pathname = function(instance,str)
- local fullname = input.find_given_file(instance,str) or ""
+ resolvers.pathname = function(str)
+ local fullname = input.find_given_file(str) or ""
return input.clean_path(file.dirname((fullname ~= "" and fullname) or str))
end
@@ -7010,15 +7321,15 @@ do
resolvers.file = resolvers.filename
resolvers.path = resolvers.pathname
- local function resolve(instance,str)
+ local function resolve(str)
if type(str) == "table" then
for k, v in pairs(str) do
- str[k] = resolve(instance,v) or v
+ 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](instance,target)
+ return resolvers[method](target)
else
return method .. ":" .. target
end
@@ -7027,10 +7338,173 @@ do
return str
end
+ if os.uname then
+ for k, v in pairs(os.uname()) do
+ if not resolvers[k] then
+ resolvers[k] = function() return v end
+ end
+ end
+ end
+
input.resolve = resolve
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
+
+
+if not modules then modules = { } end modules ['luat-log'] = {
+ 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"
+}
+
+--[[ldx--
+<p>This is a prelude to a more extensive logging module. For the sake
+of parsing log files, in addition to the standard logging we will
+provide an <l n='xml'/> structured file. Actually, any logging that
+is hooked into callbacks will be \XML\ by default.</p>
+--ldx]]--
+
+-- input.logger -> special tracing, driven by log level (only input)
+-- input.report -> goes to terminal, depends on verbose, has banner
+-- logs.report -> module specific tracing and reporting, no banner but class
+
+
+input = input or { }
+logs = logs or { }
+
+--[[ldx--
+<p>This looks pretty ugly but we need to speed things up a bit.</p>
+--ldx]]--
+
+logs.levels = {
+ ['error'] = 1,
+ ['warning'] = 2,
+ ['info'] = 3,
+ ['debug'] = 4
+}
+
+logs.functions = {
+ 'report', 'start', 'stop', 'push', 'pop', 'line', 'direct'
+}
+
+logs.callbacks = {
+ 'start_page_number',
+ 'stop_page_number',
+ 'report_output_pages',
+ 'report_output_log'
+}
+
+logs.tracers = {
+}
+
+logs.xml = logs.xml or { }
+logs.tex = logs.tex or { }
+
+logs.level = 0
+
+local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format
+
+if texlua then
+ write_nl = print
+ write = io.write
+end
+
+function logs.xml.report(category,fmt,...) -- new
+ write_nl(format("<r category='%s'>%s</r>",category,format(fmt,...)))
+end
+function logs.xml.line(fmt,...) -- new
+ write_nl(format("<r>%s</r>",format(fmt,...)))
+end
+
+function logs.xml.start() if logs.level > 0 then tw("<%s>" ) end end
+function logs.xml.stop () if logs.level > 0 then tw("</%s>") end end
+function logs.xml.push () if logs.level > 0 then tw("<!-- ") end end
+function logs.xml.pop () if logs.level > 0 then tw(" -->" ) end end
+
+function logs.tex.report(category,fmt,...) -- new
+ -- write_nl(format("%s | %s",category,format(fmt,...))) -- arg to format can be tex comment so .. .
+ write_nl(category .. " | " .. format(fmt,...))
+end
+function logs.tex.line(fmt,...) -- new
+ write_nl(format(fmt,...))
+end
+
+function logs.set_level(level)
+ logs.level = logs.levels[level] or level
+end
+
+function logs.set_method(method)
+ for _, v in pairs(logs.functions) do
+ logs[v] = logs[method][v] or function() end
+ end
+ if callback and input[method] then
+ for _, cb in pairs(logs.callbacks) do
+ callback.register(cb, input[method][cb])
+ end
+ end
+end
+
+function logs.xml.start_page_number()
+ write_nl(format("<p real='%s' page='%s' sub='%s'", tex.count[0], tex.count[1], tex.count[2]))
+end
+
+function logs.xml.stop_page_number()
+ write("/>")
+ write_nl("")
+end
+
+function logs.xml.report_output_pages(p,b)
+ write_nl(format("<v k='pages' v='%s'/>", p))
+ write_nl(format("<v k='bytes' v='%s'/>", b))
+ write_nl("")
+end
+
+function logs.xml.report_output_log()
+end
+
+function input.logger(...) -- assumes test for input.trace > n
+ if input.trace > 0 then
+ logs.report(...)
+ end
+end
+
+function input.report(fmt,...)
+ if input.verbose then
+ logs.report(input.banner or "report",format(fmt,...))
+ end
+end
+
+function input.reportlines(str) -- todo: <lines></lines>
+ for line in str:gmatch("(.-)[\n\r]") do
+ logs.report(input.banner or "report",line)
+ end
+end
+
+function input.help(banner,message)
+ if not input.verbose then
+ input.verbose = true
+ -- input.report(banner,"\n")
+ end
+ input.report(banner,"\n")
+ input.report("")
+ input.reportlines(message)
+end
+
+logs.set_level('error')
+logs.set_method('tex')
+
if not modules then modules = { } end modules ['luat-tmp'] = {
version = 1.001,
@@ -7056,63 +7530,82 @@ being written at the same time is small. We also need to extend
luatools with a recache feature.</p>
--ldx]]--
+local format = string.format
+
caches = caches or { }
dir = dir or { }
texmf = texmf or { }
-caches.path = caches.path or nil
-caches.base = caches.base or "luatex-cache"
-caches.more = caches.more or "context"
-caches.direct = false -- true is faster but may need huge amounts of memory
-caches.trace = false
-caches.tree = false
-caches.paths = caches.paths or nil
-caches.force = false
-
-input.usecache = not toboolean(os.getenv("TEXMFSHARECACHE") or "false",true) -- true
-
-function caches.temp(instance)
- local function checkpath(cachepath)
- if not cachepath or cachepath == "" then
- return nil
- elseif lfs.attributes(cachepath,"mode") == "directory" then -- lfs.isdir(cachepath) then
- return cachepath
- elseif caches.force or io.ask(string.format("Should I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
- dir.mkdirs(cachepath)
- return (lfs.attributes(cachepath,"mode") == "directory") and cachepath
- else
- return nil
+caches.path = caches.path or nil
+caches.base = caches.base or "luatex-cache"
+caches.more = caches.more or "context"
+caches.direct = false -- true is faster but may need huge amounts of memory
+caches.trace = false
+caches.tree = false
+caches.paths = caches.paths or nil
+caches.force = false
+caches.defaults = { "TEXMFCACHE", "TMPDIR", "TEMPDIR", "TMP", "TEMP", "HOME", "HOMEPATH" }
+
+function caches.temp()
+ local cachepath = nil
+ local function check(list,isenv)
+ if not cachepath then
+ for _, v in ipairs(list) do
+ cachepath = (isenv and (os.env[v] or "")) or v or ""
+ if cachepath == "" then
+ -- next
+ else
+ cachepath = input.clean_path(cachepath)
+ if lfs.isdir(cachepath) and file.iswritable(cachepath) then -- lfs.attributes(cachepath,"mode") == "directory"
+ break
+ elseif caches.force or io.ask(format("\nShould I create the cache path %s?",cachepath), "no", { "yes", "no" }) == "yes" then
+ dir.mkdirs(cachepath)
+ if lfs.isdir(cachepath) and file.iswritable(cachepath) then
+ break
+ end
+ end
+ end
+ cachepath = nil
+ end
end
end
- local cachepath = input.expanded_path_list(instance,"TEXMFCACHE")
- cachepath = cachepath and #cachepath > 0 and checkpath(cachepath[1])
+ check(input.clean_path_list("TEXMFCACHE") or { })
+ check(caches.defaults,true)
if not cachepath then
- cachepath = os.getenv("TEXMFCACHE") or os.getenv("HOME") or os.getenv("HOMEPATH") or os.getenv("TMP") or os.getenv("TEMP") or os.getenv("TMPDIR") or nil
- cachepath = checkpath(cachepath)
- end
- if not cachepath then
- print("\nfatal error: there is no valid cache path defined\n")
+ print("\nfatal error: there is no valid (writable) cache path defined\n")
os.exit()
- elseif lfs.attributes(cachepath,"mode") ~= "directory" then
- print(string.format("\nfatal error: cache path %s is not a directory\n",cachepath))
+ elseif not lfs.isdir(cachepath) then -- lfs.attributes(cachepath,"mode") ~= "directory"
+ print(format("\nfatal error: cache path %s is not a directory\n",cachepath))
os.exit()
end
- function caches.temp(instance)
+ cachepath = input.normalize_name(cachepath)
+ function caches.temp()
return cachepath
end
return cachepath
end
-function caches.configpath(instance)
- return table.concat(instance.cnffiles,";")
+function caches.configpath()
+ return table.concat(input.instance.cnffiles,";")
end
function caches.hashed(tree)
return md5.hex((tree:lower()):gsub("[\\\/]+","/"))
end
-function caches.treehash(instance)
- local tree = caches.configpath(instance)
+--~ tracing:
+
+--~ function caches.hashed(tree)
+--~ tree = (tree:lower()):gsub("[\\\/]+","/")
+--~ local hash = md5.hex(tree)
+--~ if input.verbose then -- temp message
+--~ input.report("hashing %s => %s",tree,hash)
+--~ end
+--~ return hash
+--~ end
+
+function caches.treehash()
+ local tree = caches.configpath()
if not tree or tree == "" then
return false
else
@@ -7120,14 +7613,14 @@ function caches.treehash(instance)
end
end
-function caches.setpath(instance,...)
+function caches.setpath(...)
if not caches.path then
if not caches.path then
- caches.path = caches.temp(instance)
+ caches.path = caches.temp()
end
caches.path = input.clean_path(caches.path) -- to be sure
if lfs then
- caches.tree = caches.tree or caches.treehash(instance)
+ caches.tree = caches.tree or caches.treehash()
if caches.tree then
caches.path = dir.mkdirs(caches.path,caches.base,caches.more,caches.tree)
else
@@ -7147,9 +7640,9 @@ function caches.setpath(instance,...)
return caches.path
end
-function caches.definepath(instance,category,subcategory)
+function caches.definepath(category,subcategory)
return function()
- return caches.setpath(instance,category,subcategory)
+ return caches.setpath(category,subcategory)
end
end
@@ -7172,26 +7665,38 @@ function caches.is_writable(filepath,filename)
return file.is_writable(tmaname)
end
-function caches.savedata(filepath,filename,data,raw) -- raw needed for file cache
+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
if raw then
reduce, simplify = false, false
end
if caches.direct then
- file.savedata(tmaname, table.serialize(data,'return',true,true))
+ file.savedata(tmaname, table.serialize(data,'return',true,true,false)) -- no hex
else
- table.tofile (tmaname, data,'return',true,true) -- maybe not the last true
+ table.tofile(tmaname, data,'return',true,true,false) -- maybe not the last true
end
- utils.lua.compile(tmaname, tmcname)
+ local cleanup = input.boolean_variable("PURGECACHE", false)
+ local strip = input.boolean_variable("LUACSTRIP", true)
+ utils.lua.compile(tmaname, tmcname, cleanup, strip)
end
-- here we use the cache for format loading (texconfig.[formatname|jobname])
--~ if tex and texconfig and texconfig.formatname and texconfig.formatname == "" then
-if tex and texconfig and (not texconfig.formatname or texconfig.formatname == "") and texmf.instance then
+if tex and texconfig and (not texconfig.formatname or texconfig.formatname == "") and input and input.instance then
if not texconfig.luaname then texconfig.luaname = "cont-en.lua" end -- or luc
- texconfig.formatname = caches.setpath(texmf.instance,"formats") .. "/" .. texconfig.luaname:gsub("%.lu.$",".fmt")
+ texconfig.formatname = caches.setpath("formats") .. "/" .. texconfig.luaname:gsub("%.lu.$",".fmt")
end
--[[ldx--
@@ -7214,7 +7719,7 @@ do -- local report
local function report(container,tag,name)
if caches.trace or containers.trace or container.trace then
- logs.report(string.format("%s cache",container.subcategory),string.format("%s: %s",tag,name or 'invalid'))
+ logs.report(format("%s cache",container.subcategory),"%s: %s",tag,name or 'invalid')
end
end
@@ -7239,7 +7744,7 @@ do -- local report
enabled = enabled,
version = version or 1.000,
trace = false,
- path = caches.setpath(texmf.instance,category,subcategory),
+ path = caches.setpath(category,subcategory),
}
c[subcategory] = s
end
@@ -7304,13 +7809,16 @@ end
-- reimplement the saver.
local save_data = input.aux.save_data
+local load_data = input.aux.load_data
-input.cachepath = nil
+input.cachepath = nil -- public, for tracing
+input.usecache = true -- public, for tracing
-function input.aux.save_data(instance, dataname, check)
- input.cachepath = input.cachepath or caches.definepath(instance,"trees")
- save_data(instance, dataname, check, function(cachename,dataname)
+function input.aux.save_data(dataname, check)
+ save_data(dataname, check, function(cachename,dataname)
+ input.usecache = not toboolean(input.expansion("CACHEINTDS") or "false",true)
if input.usecache then
+ input.cachepath = input.cachepath or caches.definepath("trees")
return file.join(input.cachepath(),caches.hashed(cachename))
else
return file.join(cachename,dataname)
@@ -7318,12 +7826,11 @@ function input.aux.save_data(instance, dataname, check)
end)
end
-local load_data = input.aux.load_data
-
-function input.aux.load_data(instance,pathname,dataname,filename)
- input.cachepath = input.cachepath or caches.definepath(instance,"trees")
- load_data(instance,pathname,dataname,filename,function(dataname,filename)
+function input.aux.load_data(pathname,dataname,filename)
+ load_data(pathname,dataname,filename,function(dataname,filename)
+ input.usecache = not toboolean(input.expansion("CACHEINTDS") or "false",true)
if input.usecache then
+ input.cachepath = input.cachepath or caches.definepath("trees")
return file.join(input.cachepath(),caches.hashed(pathname))
else
if not filename or (filename == "") then
@@ -7338,13 +7845,13 @@ end
input.automounted = input.automounted or { }
-function input.automount(instance,usecache)
- local mountpaths = input.simplified_list(input.expansion(instance,'TEXMFMOUNT'))
+function input.automount(usecache)
+ local mountpaths = input.clean_path_list(input.expansion('TEXMFMOUNT'))
if table.is_empty(mountpaths) and usecache then
- mountpaths = { caches.setpath(instance,"mount") }
+ mountpaths = { caches.setpath("mount") }
end
if not table.is_empty(mountpaths) then
- input.starttiming(instance)
+ input.starttiming(input.instance)
for k, root in pairs(mountpaths) do
local f = io.open(root.."/url.tmi")
if f then
@@ -7353,16 +7860,16 @@ function input.automount(instance,usecache)
if line:find("^[%%#%-]") then -- or %W
-- skip
elseif line:find("^zip://") then
- input.report("mounting",line)
+ input.report("mounting %s",line)
table.insert(input.automounted,line)
- input.usezipfile(instance,line)
+ input.usezipfile(line)
end
end
end
f:close()
end
end
- input.stoptiming(instance)
+ input.stoptiming(input.instance)
end
end
@@ -7411,17 +7918,17 @@ function input.storage.dump()
else
name = str
end
- initialize = string.format("%s %s = %s or {} ", initialize, name, name)
+ initialize = format("%s %s = %s or {} ", initialize, name, name)
end
if evaluate then
finalize = "input.storage.evaluate(" .. name .. ")"
end
input.storage.max = input.storage.max + 1
if input.storage.trace then
- logs.report('storage',string.format('saving %s in slot %s',message,input.storage.max))
+ logs.report('storage','saving %s in slot %s',message,input.storage.max)
code =
initialize ..
- string.format("logs.report('storage','restoring %s from slot %s') ",message,input.storage.max) ..
+ format("logs.report('storage','restoring %s from slot %s') ",message,input.storage.max) ..
table.serialize(original,name) ..
finalize
else
@@ -7457,6 +7964,11 @@ provide an <l n='xml'/> structured file. Actually, any logging that
is hooked into callbacks will be \XML\ by default.</p>
--ldx]]--
+-- input.logger -> special tracing, driven by log level (only input)
+-- input.report -> goes to terminal, depends on verbose, has banner
+-- logs.report -> module specific tracing and reporting, no banner but class
+
+
input = input or { }
logs = logs or { }
@@ -7472,8 +7984,7 @@ logs.levels = {
}
logs.functions = {
- 'error', 'warning', 'info', 'debug', 'report',
- 'start', 'stop', 'push', 'pop'
+ 'report', 'start', 'stop', 'push', 'pop', 'line', 'direct'
}
logs.callbacks = {
@@ -7483,89 +7994,100 @@ logs.callbacks = {
'report_output_log'
}
+logs.tracers = {
+}
+
logs.xml = logs.xml or { }
logs.tex = logs.tex or { }
logs.level = 0
-do
- local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format
+local write_nl, write, format = texio.write_nl or print, texio.write or io.write, string.format
- if texlua then
- write_nl = print
- write = io.write
- end
+if texlua then
+ write_nl = print
+ write = io.write
+end
- function logs.xml.debug(category,str)
- if logs.level > 3 then write_nl(format("<d category='%s'>%s</d>",category,str)) end
- end
- function logs.xml.info(category,str)
- if logs.level > 2 then write_nl(format("<i category='%s'>%s</i>",category,str)) end
- end
- function logs.xml.warning(category,str)
- if logs.level > 1 then write_nl(format("<w category='%s'>%s</w>",category,str)) end
- end
- function logs.xml.error(category,str)
- if logs.level > 0 then write_nl(format("<e category='%s'>%s</e>",category,str)) end
- end
- function logs.xml.report(category,str)
- write_nl(format("<r category='%s'>%s</r>",category,str))
- end
+function logs.xml.report(category,fmt,...) -- new
+ write_nl(format("<r category='%s'>%s</r>",category,format(fmt,...)))
+end
+function logs.xml.line(fmt,...) -- new
+ write_nl(format("<r>%s</r>",format(fmt,...)))
+end
- function logs.xml.start() if logs.level > 0 then tw("<%s>" ) end end
- function logs.xml.stop () if logs.level > 0 then tw("</%s>") end end
- function logs.xml.push () if logs.level > 0 then tw("<!-- ") end end
- function logs.xml.pop () if logs.level > 0 then tw(" -->" ) end end
+function logs.xml.start() if logs.level > 0 then tw("<%s>" ) end end
+function logs.xml.stop () if logs.level > 0 then tw("</%s>") end end
+function logs.xml.push () if logs.level > 0 then tw("<!-- ") end end
+function logs.xml.pop () if logs.level > 0 then tw(" -->" ) end end
- function logs.tex.debug(category,str)
- if logs.level > 3 then write_nl(format("debug >> %s: %s" ,category,str)) end
- end
- function logs.tex.info(category,str)
- if logs.level > 2 then write_nl(format("info >> %s: %s" ,category,str)) end
- end
- function logs.tex.warning(category,str)
- if logs.level > 1 then write_nl(format("warning >> %s: %s",category,str)) end
- end
- function logs.tex.error(category,str)
- if logs.level > 0 then write_nl(format("error >> %s: %s" ,category,str)) end
- end
- function logs.tex.report(category,str)
- write_nl(format("report >> %s: %s" ,category,str))
- end
+function logs.tex.report(category,fmt,...) -- new
+ -- write_nl(format("%s | %s",category,format(fmt,...))) -- arg to format can be tex comment so .. .
+ write_nl(category .. " | " .. format(fmt,...))
+end
+function logs.tex.line(fmt,...) -- new
+ write_nl(format(fmt,...))
+end
- function logs.set_level(level)
- logs.level = logs.levels[level] or level
- end
+function logs.set_level(level)
+ logs.level = logs.levels[level] or level
+end
- function logs.set_method(method)
- for _, v in pairs(logs.functions) do
- logs[v] = logs[method][v] or function() end
- end
- if callback and input[method] then
- for _, cb in pairs(logs.callbacks) do
- callback.register(cb, input[method][cb])
- end
+function logs.set_method(method)
+ for _, v in pairs(logs.functions) do
+ logs[v] = logs[method][v] or function() end
+ end
+ if callback and input[method] then
+ for _, cb in pairs(logs.callbacks) do
+ callback.register(cb, input[method][cb])
end
end
+end
- function logs.xml.start_page_number()
- write_nl(format("<p real='%s' page='%s' sub='%s'", tex.count[0], tex.count[1], tex.count[2]))
- end
+function logs.xml.start_page_number()
+ write_nl(format("<p real='%s' page='%s' sub='%s'", tex.count[0], tex.count[1], tex.count[2]))
+end
+
+function logs.xml.stop_page_number()
+ write("/>")
+ write_nl("")
+end
+
+function logs.xml.report_output_pages(p,b)
+ write_nl(format("<v k='pages' v='%s'/>", p))
+ write_nl(format("<v k='bytes' v='%s'/>", b))
+ write_nl("")
+end
+
+function logs.xml.report_output_log()
+end
- function logs.xml.stop_page_number()
- write("/>")
- write_nl("")
+function input.logger(...) -- assumes test for input.trace > n
+ if input.trace > 0 then
+ logs.report(...)
end
+end
- function logs.xml.report_output_pages(p,b)
- write_nl(format("<v k='pages' v='%s'/>", p))
- write_nl(format("<v k='bytes' v='%s'/>", b))
- write_nl("")
+function input.report(fmt,...)
+ if input.verbose then
+ logs.report(input.banner or "report",format(fmt,...))
end
+end
- function logs.xml.report_output_log()
+function input.reportlines(str) -- todo: <lines></lines>
+ for line in str:gmatch("(.-)[\n\r]") do
+ logs.report(input.banner or "report",line)
end
+end
+function input.help(banner,message)
+ if not input.verbose then
+ input.verbose = true
+ -- input.report(banner,"\n")
+ end
+ input.report(banner,"\n")
+ input.report("")
+ input.reportlines(message)
end
logs.set_level('error')
@@ -7758,7 +8280,7 @@ end
-- end library merge
-own = { }
+own = { } -- not local
own.libs = { -- todo: check which ones are really needed
'l-string.lua',
@@ -7778,6 +8300,7 @@ own.libs = { -- todo: check which ones are really needed
-- 'l-tex.lua',
'luat-lib.lua',
'luat-inp.lua',
+ 'luat-log.lua',
-- 'luat-zip.lua',
-- 'luat-tex.lua',
-- 'luat-kps.lua',
@@ -7807,7 +8330,7 @@ table.insert(own.list,own.path.."/../../../tex/context/base")
table.insert(own.list,own.path.."/mtx")
table.insert(own.list,own.path.."/../sources")
-function locate_libs()
+local function locate_libs()
for _, lib in pairs(own.libs) do
for _, pth in pairs(own.list) do
local filename = string.gsub(pth .. "/" .. lib,"\\","/")
@@ -7834,38 +8357,19 @@ if not input then
os.exit()
end
-instance = input.reset()
+input.instance = input.reset()
input.verbose = environment.argument("verbose") or false
-input.banner = 'MtxRun | '
+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
---~ function input.check_environment(tree)
---~ input.report('')
---~ os.setenv('TMP', os.getenv('TMP') or os.getenv('TEMP') or os.getenv('TMPDIR') or os.getenv('HOME'))
---~ if os.platform == 'linux' then
---~ os.setenv('TEXOS', os.getenv('TEXOS') or 'texmf-linux')
---~ elseif os.platform == 'windows' then
---~ os.setenv('TEXOS', os.getenv('TEXOS') or 'texmf-windows')
---~ elseif os.platform == 'macosx' then
---~ os.setenv('TEXOS', os.getenv('TEXOS') or 'texmf-macosx')
---~ end
---~ os.setenv('TEXOS', string.gsub(string.gsub(os.getenv('TEXOS'),"^[\\\/]*", ''),"[\\\/]*$", ''))
---~ os.setenv('TEXPATH', string.gsub(tree,"\/+$",''))
---~ os.setenv('TEXMFOS', os.getenv('TEXPATH') .. "/" .. os.getenv('TEXOS'))
---~ input.report('')
---~ input.report("preset : TEXPATH => " .. os.getenv('TEXPATH'))
---~ input.report("preset : TEXOS => " .. os.getenv('TEXOS'))
---~ input.report("preset : TEXMFOS => " .. os.getenv('TEXMFOS'))
---~ input.report("preset : TMP => " .. os.getenv('TMP'))
---~ input.report('')
---~ end
-
function input.check_environment(tree)
input.report('')
os.setenv('TMP', os.getenv('TMP') or os.getenv('TEMP') or os.getenv('TMPDIR') or os.getenv('HOME'))
@@ -7873,10 +8377,10 @@ function input.check_environment(tree)
os.setenv('TEXPATH', (tree or "tex"):gsub("\/+$",''))
os.setenv('TEXMFOS', os.getenv('TEXPATH') .. "/" .. os.getenv('TEXOS'))
input.report('')
- input.report("preset : TEXPATH => " .. os.getenv('TEXPATH'))
- input.report("preset : TEXOS => " .. os.getenv('TEXOS'))
- input.report("preset : TEXMFOS => " .. os.getenv('TEXMFOS'))
- input.report("preset : TMP => " .. os.getenv('TMP'))
+ input.report("preset : TEXPATH => %s", os.getenv('TEXPATH'))
+ input.report("preset : TEXOS => %s", os.getenv('TEXOS'))
+ input.report("preset : TEXMFOS => %s", os.getenv('TEXMFOS'))
+ input.report("preset : TMP => %s", os.getenv('TMP'))
input.report('')
end
@@ -7965,9 +8469,9 @@ function file.needs_updating(oldname,newname) -- size modification access change
end
end
-function file.mdchecksum(name)
+function file.checksum(name)
if md5 then
- local data = io.loadall(name)
+ local data = io.loaddata(name)
if data then
return md5.HEXsum(data)
end
@@ -7976,24 +8480,18 @@ function file.mdchecksum(name)
end
function file.loadchecksum(name)
- if md then
- local data = io.loadall(name .. ".md5")
- if data then
- return string.gsub(md5.HEXsum(data),"%s$","")
- end
+ if md5 then
+ local data = io.loaddata(name .. ".md5")
+ return data and data:gsub("%s","")
end
return nil
end
function file.savechecksum(name, checksum)
- if not checksum then checksum = file.mdchecksum(name) end
+ if not checksum then checksum = file.checksum(name) end
if checksum then
- local f = io.open(name .. ".md5","w")
- if f then
- f:write(checksum)
- f:close()
- return checksum
- end
+ io.savedata(name .. ".md5",checksum)
+ return checksum
end
return nil
end
@@ -8097,46 +8595,46 @@ messages.help = [[
--progname=str format or backend
--edit launch editor with found file
---launch (--all) launch files (assume os support)
+--launch (--all) launch files like manuals, assumes os support
--intern run script using built in libraries
]]
-function input.runners.my_prepare_a(instance)
- input.resetconfig(instance)
- input.identify_cnf(instance)
- input.load_lua(instance)
- input.expand_variables(instance)
- input.load_cnf(instance)
- input.expand_variables(instance)
+function input.runners.my_prepare_a()
+ input.resetconfig()
+ input.identify_cnf()
+ input.load_lua()
+ input.expand_variables()
+ input.load_cnf()
+ input.expand_variables()
end
-function input.runners.my_prepare_b(instance)
- input.runners.my_prepare_a(instance)
- input.load_hash(instance)
- input.automount(instance)
+function input.runners.my_prepare_b()
+ input.runners.my_prepare_a()
+ input.load_hash()
+ input.automount()
end
-function input.runners.prepare(instance)
+function input.runners.prepare()
local checkname = environment.argument("ifchanged")
if checkname and checkname ~= "" then
local oldchecksum = file.loadchecksum(checkname)
local newchecksum = file.checksum(checkname)
if oldchecksum == newchecksum then
- report("file '" .. checkname .. "' is unchanged")
+ input.report("file '%s' is unchanged",checkname)
return "skip"
else
- report("file '" .. checkname .. "' is changed, processing started")
+ input.report("file '%s' is changed, processing started",checkname)
end
file.savechecksum(checkname)
end
local oldname, newname = string.split(environment.argument("iftouched") or "", ",")
if oldname and newname and oldname ~= "" and newname ~= "" then
if not file.needs_updating(oldname,newname) then
- report("file '" .. oldname .. "' and '" .. newname .. "'have same age")
+ input.report("file '%s' and '%s' have same age",oldname,newname)
return "skip"
else
- report("file '" .. newname .. "' is older than '" .. oldname .. "'")
+ input.report("file '%s' is older than '%s'",oldname,newname)
end
end
local tree = environment.argument('tree') or ""
@@ -8155,15 +8653,16 @@ function input.runners.prepare(instance)
end
local runpath = environment.argument("path")
if runpath and not dir.chdir(runpath) then
- input.report("unable to change to path '" .. runpath .. "'")
+ input.report("unable to change to path '%s'",runpath)
return "error"
end
return "run"
end
-function input.runners.execute_script(instance,fullname,internal)
+function input.runners.execute_script(fullname,internal)
+ local instance = input.instance
if fullname and fullname ~= "" then
- local state = input.runners.prepare(instance)
+ local state = input.runners.prepare()
if state == 'error' then
return false
elseif state == 'skip' then
@@ -8187,16 +8686,16 @@ function input.runners.execute_script(instance,fullname,internal)
if suffix == "" then
-- loop over known suffixes
for _,s in pairs(input.runners.suffixes) do
- result = input.find_file(instance, name .. "." .. s, 'texmfscripts')
+ result = input.find_file(name .. "." .. s, 'texmfscripts')
if result ~= "" then
break
end
end
elseif input.runners.applications[suffix] then
- result = input.find_file(instance, name, 'texmfscripts')
+ result = input.find_file(name, 'texmfscripts')
else
-- maybe look on path
- result = input.find_file(instance, name, 'other text files')
+ result = input.find_file(name, 'other text files')
end
end
if result and result ~= "" then
@@ -8212,7 +8711,7 @@ function input.runners.execute_script(instance,fullname,internal)
local before, after = environment.split_arguments(fullname)
local command = result .. " " .. environment.reconstruct_commandline(after)
input.report("")
- input.report("executing: " .. command)
+ input.report("executing: %s",command)
input.report("\n \n")
io.flush()
local code = os.exec(command) -- maybe spawn
@@ -8224,9 +8723,9 @@ function input.runners.execute_script(instance,fullname,internal)
return false
end
-function input.runners.execute_program(instance,fullname)
+function input.runners.execute_program(fullname)
if fullname and fullname ~= "" then
- local state = input.runners.prepare(instance)
+ local state = input.runners.prepare()
if state == 'error' then
return false
elseif state == 'skip' then
@@ -8237,7 +8736,7 @@ function input.runners.execute_program(instance,fullname)
fullname = fullname:gsub("^bin:","")
local command = fullname .. " " .. environment.reconstruct_commandline(after)
input.report("")
- input.report("executing: " .. command)
+ input.report("executing: %s",command)
input.report("\n \n")
io.flush()
local code = os.exec(command) -- (fullname,unpack(after)) does not work / maybe spawn
@@ -8247,12 +8746,12 @@ function input.runners.execute_program(instance,fullname)
return false
end
-function input.runners.handle_stubs(instance,create)
+function input.runners.handle_stubs(create)
local stubpath = environment.argument('stubpath') or '.' -- 'auto' no longer supported
local windows = environment.argument('windows') or environment.argument('mswin') or false
local unix = environment.argument('unix') or environment.argument('linux') or false
if not windows and not unix then
- if environment.platform == "unix" then
+ if os.platform == "unix" then
unix = true
else
windows = true
@@ -8267,41 +8766,41 @@ function input.runners.handle_stubs(instance,create)
local command = "luatex --luaonly mtxrun.lua " .. name
if windows then
io.savedata(base..".bat", {"@echo off", command.." %*"}, "\013\010")
- input.report("windows stub for '" .. base .. "' created")
+ input.report("windows stub for '%s' created",base)
end
if unix then
io.savedata(base, {"#!/bin/sh", command..' "$@"'}, "\010")
- input.report("unix stub for '" .. base .. "' created")
+ input.report("unix stub for '%s' created",base)
end
else
if windows and (os.remove(base..'.bat') or os.remove(base..'.cmd')) then
- input.report("windows stub for '" .. base .. "' removed")
+ input.report("windows stub for '%s' removed", base)
end
if unix and (os.remove(base) or os.remove(base..'.sh')) then
- input.report("unix stub for '" .. base .. "' removed")
+ input.report("unix stub for '%s' removed",base)
end
end
end
end
end
-function input.runners.resolve_string(instance,filename)
+function input.runners.resolve_string(filename)
if filename and filename ~= "" then
- input.runners.report_location(instance,input.resolve(instance,filename))
+ input.runners.report_location(input.resolve(filename))
end
end
-function input.runners.locate_file(instance,filename)
+function input.runners.locate_file(filename)
if filename and filename ~= "" then
- input.runners.report_location(instance,input.find_given_file(instance,filename))
+ input.runners.report_location(input.find_given_file(filename))
end
end
-function input.runners.locate_platform(instance)
- input.runners.report_location(instance,os.currentplatform())
+function input.runners.locate_platform()
+ input.runners.report_location(os.currentplatform())
end
-function input.runners.report_location(instance,result)
+function input.runners.report_location(result)
if input.verbose then
input.report("")
if result and result ~= "" then
@@ -8314,9 +8813,9 @@ function input.runners.report_location(instance,result)
end
end
-function input.runners.edit_script(instance,filename)
+function input.runners.edit_script(filename)
local editor = os.getenv("MTXRUN_EDITOR") or os.getenv("TEXMFSTART_EDITOR") or os.getenv("EDITOR") or 'scite'
- local rest = input.resolve(instance,filename)
+ local rest = input.resolve(filename)
if rest ~= "" then
os.launch(editor .. " " .. rest)
end
@@ -8361,7 +8860,8 @@ function input.launch(str)
os.launch(str)
end
-function input.runners.launch_file(instance,filename)
+function input.runners.launch_file(filename)
+ local instance = input.instance
instance.allresults = true
input.verbose = true
local pattern = environment.arguments["pattern"]
@@ -8371,25 +8871,30 @@ function input.runners.launch_file(instance,filename)
if not pattern or pattern == "" then
input.report("provide name or --pattern=")
else
- local t = input.find_files(instance,pattern)
- -- local t = input.aux.find_file(instance,"*/" .. pattern,true)
+ local t = input.find_files(pattern)
+ if not t or #t == 0 then
+ t = input.aux.find_file("*/" .. pattern,true)
+ end
+ if not t or #t == 0 then
+ t = input.aux.find_file("*/" .. pattern .. "*",true)
+ end
if t and #t > 0 then
if environment.arguments["all"] then
for _, v in pairs(t) do
- input.report("launching", v)
+ input.report("launching %s", v)
input.launch(v)
end
else
- input.report("launching", t[1])
+ input.report("launching %s", t[1])
input.launch(t[1])
end
else
- input.report("no match for", pattern)
+ input.report("no match for %s", pattern)
end
end
end
-function input.runners.execute_ctx_script(instance,filename,arguments)
+function input.runners.execute_ctx_script(filename,arguments)
local function found(name)
local path = file.dirname(name)
if path and path ~= "" then
@@ -8404,25 +8909,25 @@ function input.runners.execute_ctx_script(instance,filename,arguments)
local fullname = filename
-- just <filename>
fullname = filename .. suffix
- fullname = input.find_file(instance,fullname)
+ fullname = input.find_file(fullname)
-- mtx-<filename>
if not fullname or fullname == "" then
fullname = "mtx-" .. filename .. suffix
- fullname = found(fullname) or input.find_file(instance,fullname)
+ fullname = found(fullname) or input.find_file(fullname)
end
-- mtx-<filename>s
if not fullname or fullname == "" then
fullname = "mtx-" .. filename .. "s" .. suffix
- fullname = found(fullname) or input.find_file(instance,fullname)
+ fullname = found(fullname) or input.find_file(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(instance,fullname)
+ fullname = found(fullname) or input.find_file(fullname)
end
-- that should do it
if fullname and fullname ~= "" then
- local state = input.runners.prepare(instance)
+ local state = input.runners.prepare()
if state == 'error' then
return false
elseif state == 'skip' then
@@ -8439,7 +8944,7 @@ function input.runners.execute_ctx_script(instance,filename,arguments)
end
filename = environment.files[1]
if input.verbose then
- input.report("using script: " .. fullname)
+ input.report("using script: %s\n",fullname)
end
dofile(fullname)
local savename = environment.arguments['save']
@@ -8452,20 +8957,16 @@ function input.runners.execute_ctx_script(instance,filename,arguments)
end
else
input.verbose = true
- input.report("unknown script: " .. filename)
+ if filename == "" then
+ input.report("unknown script")
+ else
+ input.report("unknown script: %s",filename)
+ end
return false
end
end
-input.report(banner,"\n")
-
-function input.help(banner,message)
- if not input.verbose then
- input.verbose = true
- input.report(banner,"\n")
- end
- input.reportlines(message)
-end
+input.report("%s\n",banner)
-- this is a bit dirty ... first we store the first filename and next we
-- split the arguments so that we only see the ones meant for this script
@@ -8476,9 +8977,9 @@ local ok = true
local before, after = environment.split_arguments(filename)
-input.runners.my_prepare_b(instance)
-before = input.resolve(instance,before) -- experimental here
-after = input.resolve(instance,after) -- experimental here
+input.runners.my_prepare_b()
+before = input.resolve(before) -- experimental here
+after = input.resolve(after) -- experimental here
environment.initialize_arguments(before)
@@ -8490,60 +8991,53 @@ elseif environment.argument("selfclean") then
utils.merger.selfclean(own.name)
elseif environment.argument("selfupdate") then
input.verbose = true
- input.update_script(instance,own.name,"mtxrun")
+ input.update_script(own.name,"mtxrun")
elseif environment.argument("ctxlua") or environment.argument("internal") then
-- run a script by loading it (using libs)
- ok = input.runners.execute_script(instance,filename,true)
+ ok = input.runners.execute_script(filename,true)
elseif environment.argument("script") then
-- run a script by loading it (using libs), pass args
- ok = input.runners.execute_ctx_script(instance,filename,after)
+ ok = input.runners.execute_ctx_script(filename,after)
elseif environment.argument("execute") then
-- execute script
- ok = input.runners.execute_script(instance,filename)
+ ok = input.runners.execute_script(filename)
elseif environment.argument("direct") then
-- equals bin:
- ok = input.runners.execute_program(instance,filename)
+ ok = input.runners.execute_program(filename)
elseif environment.argument("edit") then
-- edit file
- input.runners.edit_script(instance,filename)
+ input.runners.edit_script(filename)
elseif environment.argument("launch") then
- input.runners.launch_file(instance,filename)
+ input.runners.launch_file(filename)
elseif environment.argument("make") then
-- make stubs
- input.runners.handle_stubs(instance,true)
+ input.runners.handle_stubs(true)
elseif environment.argument("remove") then
-- remove stub
- input.runners.handle_stubs(instance,false)
+ input.runners.handle_stubs(false)
elseif environment.argument("resolve") then
-- resolve string
- input.runners.resolve_string(instance,filename)
+ input.runners.resolve_string(filename)
elseif environment.argument("locate") then
-- locate file
- input.runners.locate_file(instance,filename)
+ input.runners.locate_file(filename)
elseif environment.argument("platform")then
-- locate platform
- input.runners.locate_platform(instance)
+ input.runners.locate_platform()
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(instance,filename)
+ ok = input.runners.execute_program(filename)
else
- ok = input.runners.execute_script(instance,filename)
+ ok = input.runners.execute_script(filename)
end
end
---~ if input.verbose then
---~ input.report("")
---~ input.report(string.format("runtime: %0.3f seconds",os.runtime()))
---~ end
-
---~ if ok then
---~ input.report("exit code: 0") os.exit(0)
---~ else
---~ input.report("exit code: 1") os.exit(1)
---~ end
-
-if environment.platform == "unix" then
+if os.platform == "unix" then
io.write("\n")
end
+
+if ok == false then ok = 1 elseif ok == true then ok = 0 end
+
+os.exit(ok)