File texmf-luatools.dif of Package texlive-bin
--- texmf-dist/scripts/context/lua/luatools.lua
+++ texmf-dist/scripts/context/lua/luatools.lua 2008-10-30 14:05:11.270545206 +0100
@@ -3,19 +3,21 @@
-- one can make a stub:
--
-- #!/bin/sh
--- env LUATEXDIR=/....../texmf/scripts/context/lua luatex --luaonly=luatools.lua "$@"
+-- env LUATEXDIR=/....../texmf/scripts/context/lua texlua luatools.lua "$@"
+
-- filename : luatools.lua
-- comment : companion to context.tex
-- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
-- copyright: PRAGMA ADE / ConTeXt Development Team
-- license : see context related readme files
+
-- Although this script is part of the ConTeXt distribution it is
-- relatively indepent of ConTeXt. The same is true for some of
-- the luat files. We may may make them even less dependent in
-- the future. As long as Luatex is under development the
-- interfaces and names of functions may change.
-banner = "version 1.2.0 - 2006+ - PRAGMA ADE / CONTEXT"
+banner = "version 1.2.2 - 2006+ - PRAGMA ADE / CONTEXT"
texlua = true
-- For the sake of independence we optionally can merge the library
@@ -111,7 +113,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
@@ -120,22 +122,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
@@ -177,7 +163,7 @@ end
--~ end end
-string.chr_to_esc = {
+local chr_to_esc = {
["%"] = "%%",
["."] = "%.",
["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
@@ -187,16 +173,18 @@ string.chr_to_esc = {
["{"] = "%{", ["}"] = "%}"
}
+string.chr_to_esc = chr_to_esc
+
function string:esc() -- variant 2
- return (self:gsub("(.)",string.chr_to_esc))
+ return (self:gsub("(.)",chr_to_esc))
end
-function string.unquote(str)
- return (str:gsub("^([\"\'])(.*)%1$","%2"))
+function string:unquote()
+ return (self:gsub("^([\"\'])(.*)%1$","%2"))
end
-function string.quote(str)
- return '"' .. str:unquote() .. '"'
+function string:quote()
+ return '"' .. self:unquote() .. '"'
end
function string:count(pattern) -- variant 3
@@ -446,6 +434,30 @@ function string:splitlines()
return capture:match(self)
end
+--~ local p = lpeg.splitat("->",false) print(p:match("oeps->what->more")) -- oeps what more
+--~ local p = lpeg.splitat("->",true) print(p:match("oeps->what->more")) -- oeps what->more
+--~ local p = lpeg.splitat("->",false) print(p:match("oeps")) -- oeps
+--~ local p = lpeg.splitat("->",true) print(p:match("oeps")) -- oeps
+
+local splitters_s, splitters_m = { }, { }
+
+function lpeg.splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = lpeg.P(separator)
+ if single then
+ local other, any = lpeg.C((1 - separator)^0), lpeg.P(1)
+ splitter = other * (separator * lpeg.C(any^0) + "")
+ splitters_s[separator] = splitter
+ else
+ local other = lpeg.C((1 - separator)^0)
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
-- filename : l-table.lua
-- comment : split off from luat-lib
@@ -457,11 +469,15 @@ if not versions then versions = { } end
table.join = table.concat
+local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
+local format = string.format
+local getmetatable, setmetatable = getmetatable, setmetatable
+local pairs, ipairs, type, next, tostring = pairs, ipairs, type, next, tostring
+
function table.strip(tab)
local lst = { }
- for k, v in ipairs(tab) do
- -- s = string.gsub(v, "^%s*(.-)%s*$", "%1")
- s = v:gsub("^%s*(.-)%s*$", "%1")
+ for i=1,#tab do
+ local s = tab[i]:gsub("^%s*(.-)%s*$","%1")
if s == "" then
-- skip this one
else
@@ -471,16 +487,7 @@ function table.strip(tab)
return lst
end
---~ function table.sortedkeys(tab)
---~ local srt = { }
---~ for key,_ in pairs(tab) do
---~ srt[#srt+1] = key
---~ end
---~ table.sort(srt)
---~ return srt
---~ end
-
-function table.sortedkeys(tab)
+local function sortedkeys(tab)
local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in pairs(tab) do
srt[#srt+1] = key
@@ -500,22 +507,34 @@ function table.sortedkeys(tab)
end
end
if kind == 0 or kind == 3 then
- table.sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
+ sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
else
- table.sort(srt)
+ sort(srt)
+ end
+ return srt
+end
+
+local function sortedhashkeys(tab) -- fast one
+ local srt = { }
+ for key,_ in pairs(tab) do
+ srt[#srt+1] = key
end
+ sort(srt)
return srt
end
+table.sortedkeys = sortedkeys
+table.sortedhashkeys = sortedhashkeys
+
function table.append(t, list)
for _,v in pairs(list) do
- table.insert(t,v)
+ insert(t,v)
end
end
function table.prepend(t, list)
for k,v in pairs(list) do
- table.insert(t,k,v)
+ insert(t,k,v)
end
end
@@ -562,70 +581,57 @@ function table.imerged(...)
return tmp
end
-if not table.fastcopy then do
-
- local type, pairs, getmetatable, setmetatable = type, pairs, getmetatable, setmetatable
-
- local function fastcopy(old) -- fast one
- if old then
- local new = { }
- for k,v in pairs(old) do
- if type(v) == "table" then
- new[k] = fastcopy(v) -- was just table.copy
- else
- new[k] = v
- end
- end
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+local function fastcopy(old) -- fast one
+ if old then
+ local new = { }
+ for k,v in pairs(old) do
+ if type(v) == "table" then
+ new[k] = fastcopy(v) -- was just table.copy
+ else
+ new[k] = v
end
- return new
- else
- return { }
end
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
+ return new
+ else
+ return { }
end
+end
- table.fastcopy = fastcopy
-
-end end
-
-if not table.copy then do
-
- local type, pairs, getmetatable, setmetatable = type, pairs, getmetatable, setmetatable
-
- local function copy(t, tables) -- taken from lua wiki, slightly adapted
- tables = tables or { }
- local tcopy = {}
- if not tables[t] then
- tables[t] = tcopy
- end
- for i,v in pairs(t) do -- brrr, what happens with sparse indexed
- if type(i) == "table" then
- if tables[i] then
- i = tables[i]
- else
- i = copy(i, tables)
- end
- end
- if type(v) ~= "table" then
- tcopy[i] = v
- elseif tables[v] then
- tcopy[i] = tables[v]
+local function copy(t, tables) -- taken from lua wiki, slightly adapted
+ tables = tables or { }
+ local tcopy = {}
+ if not tables[t] then
+ tables[t] = tcopy
+ end
+ for i,v in pairs(t) do -- brrr, what happens with sparse indexed
+ if type(i) == "table" then
+ if tables[i] then
+ i = tables[i]
else
- tcopy[i] = copy(v, tables)
+ i = copy(i, tables)
end
end
- local mt = getmetatable(t)
- if mt then
- setmetatable(tcopy,mt)
+ if type(v) ~= "table" then
+ tcopy[i] = v
+ elseif tables[v] then
+ tcopy[i] = tables[v]
+ else
+ tcopy[i] = copy(v, tables)
end
- return tcopy
end
+ local mt = getmetatable(t)
+ if mt then
+ setmetatable(tcopy,mt)
+ end
+ return tcopy
+end
- table.copy = copy
-
-end end
+table.fastcopy = fastcopy
+table.copy = copy
-- rougly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
@@ -654,334 +660,363 @@ function table.starts_at(t)
return ipairs(t,1)(t,0)
end
-do
+function table.tohash(t,value)
+ local h = { }
+ if value == nil then value = true end
+ for _, v in pairs(t) do -- no ipairs here
+ h[v] = value
+ end
+ return h
+end
+
+function table.fromhash(t)
+ local h = { }
+ for k, v in pairs(t) do -- no ipairs here
+ if v then h[#h+1] = k end
+ end
+ return h
+end
- -- one of my first exercises in lua ...
+--~ 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")
- -- 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
-
- table.serialize_functions = true
- table.serialize_compact = true
- table.serialize_inline = true
+table.serialize_functions = true
+table.serialize_compact = true
+table.serialize_inline = true
+
+local noquotes, hexify, handle, reduce, compact, inline, functions
+
+local reserved = table.tohash { -- intercept a language flaw, no reserved words as key
+ 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if',
+ 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while',
+}
- local function key(k)
- if type(k) == "number" then -- or k:find("^%d+$") then
- return "["..k.."]"
- elseif noquotes and k:find("^%a[%a%d%_]*$") then
- return k
+local function key(k)
+ if type(k) == "number" then -- or k:find("^%d+$") then
+ if hexify then
+ return ("[0x%04X]"):format(k)
else
- return '["'..k..'"]'
+ return "["..k.."]"
end
+ elseif noquotes and not reserved[k] and k:find("^%a[%a%d%_]*$") then
+ return k
+ else
+ return '["'..k..'"]'
end
+end
- local function simple_table(t)
- if #t > 0 then
- local n = 0
- for _,v in pairs(t) do
- n = n + 1
- end
- if n == #t then
- local tt = { }
- for i=1,#t do
- local v = t[i]
- local tv = type(v)
- if tv == "number" or tv == "boolean" then
- tt[#tt+1] = tostring(v)
- elseif tv == "string" then
- tt[#tt+1] = ("%q"):format(v)
+local function simple_table(t)
+ if #t > 0 then
+ local n = 0
+ for _,v in pairs(t) do
+ n = n + 1
+ end
+ if n == #t then
+ local tt = { }
+ for i=1,#t do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "number" then
+ if hexify then
+ tt[#tt+1] = ("0x%04X"):format(v)
else
- tt = nil
- break
+ tt[#tt+1] = tostring(v)
end
+ elseif tv == "boolean" then
+ tt[#tt+1] = tostring(v)
+ elseif tv == "string" then
+ tt[#tt+1] = ("%q"):format(v)
+ else
+ tt = nil
+ break
end
- return tt
end
+ return tt
end
- return nil
end
+ return nil
+end
- local function 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)))
- 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 (why)
- 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
+local function do_serialize(root,name,depth,level,indexed)
+ if level > 0 then
+ depth = depth .. " "
+ if indexed then
+ handle(("%s{"):format(depth))
+ elseif name then
+ handle(("%s%s={"):format(depth,key(name)))
+ else
+ handle(("%s{"):format(depth))
+ end
+ end
+ if root and next(root) then
+ local first, last = nil, 0 -- #root cannot be trusted here
+ if compact then
+ for k,v in ipairs(root) do -- NOT: for k=1,#root do (we need to quit at nil)
+ if not first then first = k end
+ last = last + 1
+ end
+ end
+ --~ for _,k in pairs(sortedkeys(root)) do -- 1% faster:
+ local sk = sortedkeys(root)
+ for i=1,#sk do
+ local k = sk[i]
+ local v = root[k]
+ local t = type(v)
+ if compact and first and type(k) == "number" and k >= first and k <= last then
+ if t == "number" then
+ if hexify then
+ handle(("%s 0x%04X,"):format(depth,v))
else
- handle(("%s %q,"):format(depth,tostring(v)))
- end
- elseif k == "__p__" then -- parent
- if false then
- handle(("%s __p__=nil,"):format(depth))
+ handle(("%s %s,"):format(depth,v))
end
- elseif t == "number" then
- handle(("%s %s=%s,"):format(depth,key(k),v))
elseif t == "string" then
if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
- handle(("%s %s=%s,"):format(depth,key(k),v))
+ handle(("%s %s,"):format(depth,v))
else
- handle(("%s %s=%q,"):format(depth,key(k),v))
+ handle(("%s %q,"):format(depth,v))
end
elseif t == "table" then
if not next(v) then
- handle(("%s %s={},"):format(depth,key(k)))
+ handle(("%s {},"):format(depth))
elseif inline then
local st = simple_table(v)
if st then
- handle(("%s %s={ %s },"):format(depth,key(k),table.concat(st,", ")))
+ handle(("%s { %s },"):format(depth,concat(st,", ")))
else
- serialize(v,k,handle,depth,level+1,reduce,noquotes)
+ do_serialize(v,k,depth,level+1,true)
end
else
- serialize(v,k,handle,depth,level+1,reduce,noquotes)
+ do_serialize(v,k,depth,level+1,true)
end
elseif t == "boolean" then
- handle(("%s %s=%s,"):format(depth,key(k),tostring(v)))
+ handle(("%s %s,"):format(depth,tostring(v)))
elseif t == "function" then
- if table.serialize_functions then
- handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(v)))
+ if functions then
+ handle(('%s loadstring(%q),'):format(depth,v:dump()))
else
- handle(('%s %s="function",'):format(depth,key(k)))
+ handle(('%s "function",'):format(depth))
end
else
- handle(("%s %s=%q,"):format(depth,key(k),tostring(v)))
- -- handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(function() return v end)))
+ handle(("%s %q,"):format(depth,tostring(v)))
+ end
+ elseif k == "__p__" then -- parent
+ if false then
+ handle(("%s __p__=nil,"):format(depth))
+ end
+ elseif t == "number" then
+ if hexify then
+ handle(("%s %s=0x%04X,"):format(depth,key(k),v))
+ else
+ handle(("%s %s=%s,"):format(depth,key(k),v))
+ end
+ elseif t == "string" then
+ if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
+ handle(("%s %s=%s,"):format(depth,key(k),v))
+ else
+ handle(("%s %s=%q,"):format(depth,key(k),v))
+ end
+ elseif t == "table" then
+ if not next(v) then
+ handle(("%s %s={},"):format(depth,key(k)))
+ elseif inline then
+ local st = simple_table(v)
+ if st then
+ handle(("%s %s={ %s },"):format(depth,key(k),concat(st,", ")))
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ elseif t == "boolean" then
+ handle(("%s %s=%s,"):format(depth,key(k),tostring(v)))
+ elseif t == "function" then
+ if functions then
+ handle(('%s %s=loadstring(%q),'):format(depth,key(k),v:dump()))
+ else
+ handle(('%s %s="function",'):format(depth,key(k)))
end
- end
- if level > 0 then
- handle(("%s},"):format(depth))
else
- handle(("%s}"):format(depth))
+ handle(("%s %s=%q,"):format(depth,key(k),tostring(v)))
+ -- handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(function() return v end)))
end
- else
- handle(("%s}"):format(depth))
end
end
+ if level > 0 then
+ 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
+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(("[0x%04X]={"):format(name))
+ else
+ handle("[" .. name .. "]={")
+ end
+ elseif tname == "boolean" then
+ if name then
+ handle("return {")
+ else
+ handle("{")
end
- serialize(root, name, flush, nil, 0, reduce, noquotes)
- return table.concat(t,"\n")
+ else
+ handle("t={")
+ end
+ if root and next(root) then
+ do_serialize(root,name,"",0,indexed)
end
+ handle("}")
+end
+
+--~ name:
+--~
+--~ true : return { }
+--~ false : { }
+--~ nil : t = { }
+--~ string : string = { }
+--~ 'return' : return { }
+--~ number : [number] = { }
- function table.tohandle(handle,root,name,reduce,noquotes)
- serialize(root, name, handle, nil, 0, 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,reduce,noquotes,hexify)
+ return concat(t,"\n")
+end
- -- sometimes tables are real use (zapfino extra pro is some 85M) in which
- -- case a stepwise serialization is nice; actually, we could consider:
- --
- -- for line in table.serializer(root,name,reduce,noquotes) do
- -- ...(line)
- -- end
- --
- -- so this is on the todo list
+function table.tohandle(handle,root,name,reduce,noquotes,hexify)
+ serialize(root,name,handle,reduce,noquotes,hexify)
+end
- table.tofile_maxtab = 2*1024
+-- sometimes tables are real use (zapfino extra pro is some 85M) in which
+-- case a stepwise serialization is nice; actually, we could consider:
+--
+-- for line in table.serializer(root,name,reduce,noquotes) do
+-- ...(line)
+-- end
+--
+-- so this is on the todo list
- function table.tofile(filename,root,name,reduce,noquotes)
- 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")
+table.tofile_maxtab = 2*1024
+
+function table.tofile(filename,root,name,reduce,noquotes,hexify)
+ local f = io.open(filename,'w')
+ if f then
+ local maxtab = table.tofile_maxtab
+ if maxtab > 1 then
+ local t = { }
+ local function flush(s)
+ t[#t+1] = s
+ if #t > maxtab then
+ f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
+ t = { }
end
- serialize(root, name, flush, nil, 0, reduce, noquotes)
end
- f:close()
+ serialize(root,name,flush,reduce,noquotes,hexify)
+ f:write(concat(t,"\n"),"\n")
+ else
+ local function flush(s)
+ f:write(s,"\n")
+ end
+ serialize(root,name,flush,reduce,noquotes,hexify)
end
+ f:close()
end
-
end
---~ 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)
- for i=1,#t do
- local v = t[i]
- if type(v) == "table" then
- if complete or type(v[1]) == "table" then
- flatten(v,f,complete)
- else
- f[#f+1] = v
- end
+local function flatten(t,f,complete)
+ for i=1,#t do
+ local v = t[i]
+ if type(v) == "table" then
+ if complete or type(v[1]) == "table" then
+ flatten(v,f,complete)
else
f[#f+1] = v
end
+ else
+ f[#f+1] = v
end
end
+end
- function table.flatten(t)
- local f = { }
- flatten(t,f,true)
- return f
- end
+function table.flatten(t)
+ local f = { }
+ flatten(t,f,true)
+ return f
+end
- function table.unnest(t) -- bad name
- local f = { }
- flatten(t,f,false)
- return f
- end
+function table.unnest(t) -- bad name
+ local f = { }
+ flatten(t,f,false)
+ return f
+end
+
+table.flatten_one_level = table.unnest
- table.flatten_one_level = table.unnest
+-- the next three may disappear
+function table.remove_value(t,value) -- todo: n
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ remove(t,i)
+ -- remove all, so no: return
+ end
+ end
+ end
end
function table.insert_before_value(t,value,str)
- for i=1,#t do
- if t[i] == value then
- table.insert(t,i,str)
- return
+ if str then
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i,str)
+ return
+ end
+ end
end
+ insert(t,1,str)
+ elseif value then
+ insert(t,1,value)
end
- table.insert(t,1,str)
end
function table.insert_after_value(t,value,str)
- for i=1,#t do
- if t[i] == value then
- table.insert(t,i+1,str)
- return
+ if str then
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i+1,str)
+ return
+ end
+ end
end
+ t[#t+1] = str
+ elseif value then
+ t[#t+1] = value
end
- t[#t+1] = str
end
function table.are_equal(a,b,n,m)
@@ -1012,27 +1047,11 @@ function table.compact(t)
end
end
-function table.tohash(t)
- local h = { }
- for _, v in pairs(t) do -- no ipairs here
- h[v] = true
- end
- return h
-end
-
-function table.fromhash(t)
- local h = { }
- for k, v in pairs(t) do -- no ipairs here
- if v then h[#h+1] = k end
- end
- return h
-end
-
function table.contains(t, v)
if t then
for i=1, #t do
if t[i] == v then
- return true
+ return i
end
end
end
@@ -1069,11 +1088,10 @@ function table.clone(t,p) -- t is option
return t
end
-
function table.hexed(t,seperator)
local tt = { }
- for i=1,#t do tt[i] = string.format("0x%04X",t[i]) end
- return table.concat(tt,seperator or " ")
+ for i=1,#t do tt[i] = ("0x%04X"):format(t[i]) end
+ return concat(tt,seperator or " ")
end
function table.reverse_hash(h)
@@ -1113,6 +1131,7 @@ function io.loaddata(filename)
local f = io.open(filename,'rb')
if f then
local data = f:read('*all')
+ -- garbagecollector.check(data)
f:close()
return data
else
@@ -1121,7 +1140,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 ""))
@@ -1131,6 +1150,9 @@ function io.savedata(filename,data,joine
f:write(data)
end
f:close()
+ return true
+ else
+ return false
end
end
@@ -1465,6 +1487,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)
@@ -1560,10 +1585,14 @@ if not versions then versions = { } end
if not file then file = { } end
+local concat = table.concat
+
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
@@ -1573,11 +1602,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)
@@ -1598,18 +1623,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
---~ t[i] = (t[i]:gsub("\\","/")):gsub("/+$","")
---~ end
---~ return table.concat(t,"/")
---~ end
-
--~ print(file.join("x/","/y"))
--~ print(file.join("http://","/y"))
--~ print(file.join("http://a","/y"))
@@ -1617,7 +1630,7 @@ end
--~ print(file.join("//nas-1","/y"))
function file.join(...)
- local pth = table.concat({...},"/")
+ local pth = concat({...},"/")
pth = pth:gsub("\\","/")
local a, b = pth:match("^(.*://)(.*)$")
if a and b then
@@ -1650,6 +1663,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(";")
@@ -1674,37 +1697,29 @@ function file.split_path(str)
end
function file.join_path(tab)
- return table.concat(tab,io.pathseparator) -- can have trailing //
+ return concat(tab,io.pathseparator) -- can have trailing //
end
---~ 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%/%-%.\\]+","-"))
@@ -1717,19 +1732,111 @@ function file.copy(oldname,newname)
file.savedata(newname,io.loaddata(oldname))
end
+-- lpeg variants, slightly faster, not always
--- filename : l-url.lua
--- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
--- copyright: PRAGMA ADE / ConTeXt Development Team
--- license : see context related readme files
+--~ local period = lpeg.P(".")
+--~ local slashes = lpeg.S("\\/")
+--~ local noperiod = 1-period
+--~ local noslashes = 1-slashes
+--~ local name = noperiod^1
-if not versions then versions = { } end versions['l-url'] = 1.001
-if not url then url = { } end
+--~ local pattern = (noslashes^0 * slashes)^0 * (noperiod^1 * period)^1 * lpeg.C(noperiod^1) * -1
--- from the spec (on the web):
---
--- foo://example.com:8042/over/there?name=ferret#nose
--- \_/ \______________/\_________/ \_________/ \__/
+--~ 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-url.lua
+-- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+-- copyright: PRAGMA ADE / ConTeXt Development Team
+-- license : see context related readme files
+
+if not versions then versions = { } end versions['l-url'] = 1.001
+if not url then url = { } end
+
+-- from the spec (on the web):
+--
+-- foo://example.com:8042/over/there?name=ferret#nose
+-- \_/ \______________/\_________/ \_________/ \__/
-- | | | | |
-- scheme authority path query fragment
-- | _____________________|__
@@ -1837,51 +1944,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
@@ -1910,30 +1972,6 @@ if lfs then do
dir.glob_pattern = glob_pattern
- --~ local function glob(pattern, action)
- --~ local t = { }
- --~ local path, rest, patt, recurse
- --~ local action = action or function(name) t[#t+1] = name end
- --~ local pattern = pattern:gsub("^%*%*","./**")
- --~ local pattern = pattern:gsub("/%*/","/**/")
- --~ path, rest = pattern:match("^(/)(.-)$")
- --~ if path then
- --~ path = path
- --~ else
- --~ path, rest = pattern:match("^([^/]*)/(.-)$")
- --~ end
- --~ if rest then
- --~ patt = rest:gsub("([%.%-%+])", "%%%1")
- --~ end
- --~ patt = patt:gsub("%*", "[^/]*")
- --~ patt = patt:gsub("%?", "[^/]")
- --~ patt = patt:gsub("%[%^/%]%*%[%^/%]%*", ".*")
- --~ if path == "" then path = "." end
- --~ recurse = patt:find("%.%*/") ~= nil
- --~ glob_pattern(path,patt,recurse,action)
- --~ return t
- --~ end
-
local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V
local pattern = Ct {
@@ -1959,13 +1997,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)
@@ -1993,16 +2035,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
@@ -2210,7 +2257,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
@@ -2229,9 +2276,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
@@ -2256,6 +2303,9 @@ end
if not versions then versions = { } end versions['l-unicode'] = 1.001
if not unicode then unicode = { } end
+local concat, utfchar, utfgsub = table.concat, unicode.utf8.char, unicode.utf8.gsub
+local char, byte = string.char, string.byte
+
if not garbagecollector then
garbagecollector = {
push = function() collectgarbage("stop") end,
@@ -2301,70 +2351,69 @@ function unicode.utftype(f) -- \000 fail
end
end
-function unicode.utf16_to_utf8(str, endian)
- garbagecollector.push()
- local result = { }
- local tc, uc = table.concat, unicode.utf8.char
- local tmp, n, m, p = { }, 0, 0, 0
+function unicode.utf16_to_utf8(str, endian) -- maybe a gsub is faster or an lpeg
+--~ garbagecollector.push()
+ local result, tmp, n, m, p = { }, { }, 0, 0, 0
-- lf | cr | crlf / (cr:13, lf:10)
local function doit()
if n == 10 then
if p ~= 13 then
- result[#result+1] = tc(tmp,"")
+ result[#result+1] = concat(tmp,"")
tmp = { }
p = 0
end
elseif n == 13 then
- result[#result+1] = tc(tmp,"")
+ result[#result+1] = concat(tmp,"")
tmp = { }
p = n
else
- tmp[#tmp+1] = uc(n)
+ tmp[#tmp+1] = utfchar(n)
p = 0
end
end
for l,r in str:bytepairs() do
- if endian then
- n = l*256 + r
- else
- n = r*256 + l
- end
- if m > 0 then
- n = (m-0xD800)*0x400 + (n-0xDC00) + 0x10000
- m = 0
- doit()
- elseif n >= 0xD800 and n <= 0xDBFF then
- m = n
- else
- doit()
+ if r then
+ if endian then
+ n = l*256 + r
+ else
+ n = r*256 + l
+ end
+ if m > 0 then
+ n = (m-0xD800)*0x400 + (n-0xDC00) + 0x10000
+ m = 0
+ doit()
+ elseif n >= 0xD800 and n <= 0xDBFF then
+ m = n
+ else
+ doit()
+ end
end
end
if #tmp > 0 then
- result[#result+1] = tc(tmp,"")
+ result[#result+1] = concat(tmp,"")
end
- garbagecollector.pop()
+--~ garbagecollector.pop()
return result
end
function unicode.utf32_to_utf8(str, endian)
- garbagecollector.push()
+--~ garbagecollector.push()
local result = { }
- local tc, uc = table.concat, unicode.utf8.char
local tmp, n, m, p = { }, 0, -1, 0
-- lf | cr | crlf / (cr:13, lf:10)
local function doit()
if n == 10 then
if p ~= 13 then
- result[#result+1] = tc(tmp,"")
+ result[#result+1] = concat(tmp,"")
tmp = { }
p = 0
end
elseif n == 13 then
- result[#result+1] = tc(tmp,"")
+ result[#result+1] = concat(tmp,"")
tmp = { }
p = n
else
- tmp[#tmp+1] = uc(n)
+ tmp[#tmp+1] = utfchar(n)
p = 0
end
end
@@ -2390,12 +2439,67 @@ function unicode.utf32_to_utf8(str, endi
end
end
if #tmp > 0 then
- result[#result+1] = tc(tmp,"")
+ result[#result+1] = concat(tmp,"")
end
- garbagecollector.pop()
+--~ garbagecollector.pop()
return result
end
+function unicode.utf8_to_utf16(str,littleendian)
+ if littleendian then
+ return char(255,254) .. utfgsub(str,".",function(c)
+ local b = byte(c)
+ if b < 0x10000 then
+ return char(b%256,b/256)
+ else
+ b = b - 0x10000
+ local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00
+ return char(b1%256,b1/256,b2%256,b2/256)
+ end
+ end)
+ else
+ return char(254,255) .. utfgsub(str,".",function(c)
+ local b = byte(c)
+ if b < 0x10000 then
+ return char(b/256,b%256)
+ else
+ b = b - 0x10000
+ local b1, b2 = b/1024 + 0xD800, b%1024 + 0xDC00
+ return char(b1/256,b1%256,b2/256,b2%256)
+ end
+ end)
+ end
+end
+
+
+-- filename : l-math.lua
+-- comment : split off from luat-lib
+-- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+-- copyright: PRAGMA ADE / ConTeXt Development Team
+-- license : see context related readme files
+
+if not versions then versions = { } end versions['l-math'] = 1.001
+
+local floor = math.floor
+
+if not math.round then
+ function math.round(x)
+ return floor(x + 0.5)
+ end
+end
+
+if not math.div then
+ function math.div(n,m)
+ return floor(n/m)
+ end
+end
+
+if not math.mod then
+ function math.mod(n,m)
+ return n % m
+ end
+end
+
-- filename : l-utils.lua
-- comment : split off from luat-lib
@@ -2429,11 +2533,20 @@ 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
+ utils.report("reading merge from %s",name)
data = f:read("*all")
f:close()
+ else
+ utils.report("unknown file to merge %s",name)
+ end
+ if data and utils.merger.strip_comment then
+ -- saves some 20K
+ data = data:gsub("%-%-~[^\n\r]*[\r\n]", "")
end
return data or ""
end
@@ -2442,6 +2555,7 @@ function utils.merger._self_save_(name,
if data ~= "" then
local f = io.open(name,'w')
if f then
+ utils.report("saving merge from %s",name)
f:write(data)
f:close()
end
@@ -2467,13 +2581,13 @@ function utils.merger._self_libs_(libs,l
local name = string.gsub(pth .. "/" .. lib,"\\","/")
f = io.open(name)
if f then
- -- utils.report("merging library",name)
+ utils.report("merging library %s",name)
result[#result+1] = f:read("*all")
f:close()
list = { pth } -- speed up the search
break
else
- -- utils.report("no library",name)
+ utils.report("no library %s",name)
end
end
end
@@ -2512,108 +2626,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
@@ -2634,19 +2702,21 @@ function environment.setargument(name,va
environment.arguments[name] = value
end
-function environment.argument(name)
- if environment.arguments[name] then
- return environment.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)
+function environment.argument(name) -- todo: default (plus typecheck on default)
+ local arguments, sortedflags = environment.arguments, environment.sortedflags
+ if arguments[name] then
+ return arguments[name]
+ else
+ 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
@@ -2667,48 +2737,106 @@ function environment.split_arguments(sep
return before, after
end
-function environment.reconstruct_commandline(arg)
+--~ function environment.reconstruct_commandline(arg)
+--~ if not arg then arg = environment.original_arguments end
+--~ local result = { }
+--~ for _,a in ipairs(arg) do -- ipairs 1 .. #n
+--~ local kk, vv = a:match("^(%-+.-)=(.+)$")
+--~ if kk and vv then
+--~ if vv:find(" ") then
+--~ vv = vv:unquote()
+--~ vv = vv:gsub('"','\\"')
+--~ result[#result+1] = kk .. "=" .. vv:quote()
+--~ else
+--~ a = a:unquote()
+--~ a = a:gsub('"','\\"')
+--~ result[#result+1] = a
+--~ end
+--~ elseif a:find(" ") then
+--~ a = a:unquote()
+--~ a = a:gsub('"','\\"')
+--~ result[#result+1] = a:quote()
+--~ else
+--~ result[#result+1] = a
+--~ end
+--~ end
+--~ return table.join(result," ")
+--~ end
+
+function environment.reconstruct_commandline(arg,noquote)
if not arg then arg = environment.original_arguments end
- local result = { }
- for _,a in ipairs(arg) do -- ipairs 1 .. #n
- local kk, vv = a:match("^(%-+.-)=(.+)$")
- if kk and vv then
- if vv:find(" ") then
- result[#result+1] = kk .. "=" .. string.quote(vv)
+ if noquote and #arg == 1 then
+ local a = arg[1]
+ a = input.resolve(a)
+ a = a:unquote()
+ return a
+ elseif #arg == 1 then
+ local result = { }
+ for _,a in ipairs(arg) do -- ipairs 1 .. #n
+ a = input.resolve(a)
+ a = a:unquote()
+ a = a:gsub('"','\\"') -- tricky
+ if a:find(" ") then
+ result[#result+1] = a:quote()
else
result[#result+1] = a
end
- elseif a:find(" ") then
- result[#result+1] = string.quote(a)
- else
- result[#result+1] = a
end
+ return table.join(result," ")
end
- return table.join(result," ")
end
if arg then
- environment.initialize_arguments(arg)
- environment.original_arguments = arg
+
+ -- new, reconstruct quoted snippets (maybe better just remnove the " then and add them later)
+ local newarg, instring = { }, false
+
+ for index, argument in ipairs(arg) do
+ if argument:find("^\"") then
+ newarg[#newarg+1] = argument:gsub("^\"","")
+ if not argument:find("\"$") then
+ instring = true
+ end
+ elseif argument:find("\"$") then
+ newarg[#newarg] = newarg[#newarg] .. " " .. argument:gsub("\"$","")
+ instring = false
+ elseif instring then
+ newarg[#newarg] = newarg[#newarg] .. " " .. argument
+ else
+ newarg[#newarg+1] = argument
+ end
+ end
+ for i=1,-5,-1 do
+ newarg[i] = arg[i]
+ end
+
+ environment.initialize_arguments(newarg)
+ environment.original_arguments = newarg
+ environment.raw_arguments = arg
+
arg = { } -- prevent duplicate handling
+
end
--- 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
@@ -2718,12 +2846,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
@@ -2736,7 +2858,7 @@ if not input.hashers then input.hashe
if not input.generators then input.generators = { } end -- generate databases
if not input.filters then input.filters = { } end -- conversion filters
-local format = string.format
+local format, concat, sortedkeys = string.format, table.concat, table.sortedkeys
input.locators.notfound = { nil }
input.hashers.notfound = { nil }
@@ -2749,8 +2871,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
@@ -2786,7 +2916,8 @@ input.suffixes['lua'] = { 'lua', 'luc',
-- 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]
@@ -2795,7 +2926,15 @@ function input.checkconfigdata(instance)
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
@@ -2822,14 +2961,20 @@ input.formats ['sfd']
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 = { }
@@ -2853,12 +2998,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
@@ -2869,23 +3014,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
@@ -2899,68 +3034,42 @@ function input.reset()
end
-function input.reset_hashes(instance)
- instance.lists = { }
- instance.found = { }
-end
+input.instance = input.instance or nil
-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"))
+function input.reset()
+ input.instance = input.newinstance()
+ return input.instance
end
-if texio then
- input.log = texio.write_nl
-else
- input.log = print
+function input.reset_hashes()
+ input.instance.lists = { }
+ input.instance.found = { }
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
-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))
@@ -2989,7 +3098,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
@@ -3005,18 +3114,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)
@@ -3034,81 +3143,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 !
@@ -3123,27 +3257,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
@@ -3155,14 +3289,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
@@ -3177,21 +3311,22 @@ function input.aux.collapse_cnf_data(ins
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
@@ -3223,227 +3358,226 @@ function input.aux.load_cnf(instance,fna
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 .. "}"
+ -- weird
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'] .. "}"
- 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)
-end
-
-do
-
- 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.generatedatabase(specification)
+ return input.methodhandler('generators', specification)
+end
+
+local weird = lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+
+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
@@ -3451,8 +3585,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)
@@ -3463,8 +3597,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)
@@ -3487,8 +3622,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
@@ -3497,19 +3633,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 = [[
@@ -3526,8 +3662,6 @@ function input.serialize(files)
-- luatools and mtxtools are called frequently. Okay,
-- we pay a small price for properly tabbed tables.
local t = { }
- local concat = table.concat
- local sorted = table.sortedkeys
local function dump(k,v,m)
if type(v) == 'string' then
return m .. "['" .. k .. "']='" .. v .. "',"
@@ -3538,12 +3672,12 @@ function input.serialize(files)
end
end
t[#t+1] = "return {"
- if instance.sortdata then
- for _, k in pairs(sorted(files)) do
+ if input.instance.sortdata then
+ for _, k in pairs(sortedkeys(files)) do
local fk = files[k]
if type(fk) == 'table' then
t[#t+1] = "\t['" .. k .. "']={"
- for _, kk in pairs(sorted(fk)) do
+ for _, kk in pairs(sortedkeys(fk)) do
t[#t+1] = dump(kk,fk[kk],"\t\t")
end
t[#t+1] = "\t},"
@@ -3570,11 +3704,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
@@ -3592,38 +3726,38 @@ function input.aux.save_data(instance, d
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
@@ -3636,13 +3770,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 = { }
@@ -3662,172 +3797,168 @@ function input.aux.load_texmfcnf(instanc
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
- local homedir =
- instance.environment[(os.type == "windows" and 'USERPROFILE') or 'HOME'] or '~'
- for k,v in pairs(instance.expansions) do
- v = v:gsub("^~", homedir)
- 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 = { }, { }
@@ -3837,7 +3968,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
@@ -3882,7 +4014,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
@@ -3923,39 +4056,41 @@ function input.expanded_path_list(instan
-- 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)
@@ -3985,9 +4120,9 @@ function input.var_of_format_or_suffix(s
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
@@ -4002,6 +4137,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
@@ -4010,19 +4146,19 @@ 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)
@@ -4030,9 +4166,9 @@ function input.aux.splitpathexpr(str, t,
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)
@@ -4040,50 +4176,41 @@ function input.aux.splitpathexpr(str, t,
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
@@ -4115,17 +4242,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
@@ -4133,12 +4259,13 @@ input.is_readable.tex = input.is_readabl
-- 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)
@@ -4152,7 +4279,7 @@ function input.aux.collect_files(instanc
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
@@ -4185,7 +4312,7 @@ function input.aux.collect_files(instanc
end
end
elseif input.trace > 1 then
- input.logger('! blobpath no',blobpath .. " (" .. bname ..")" )
+ input.logger('! blobpath no: %s (%s)',blobpath,bname)
end
end
end
@@ -4240,15 +4367,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
@@ -4257,16 +4386,22 @@ function input.aux.find_file(instance,fi
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
@@ -4274,22 +4409,26 @@ function input.aux.find_file(instance,fi
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
@@ -4307,10 +4446,14 @@ function input.aux.find_file(instance,fi
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
@@ -4319,16 +4462,18 @@ function input.aux.find_file(instance,fi
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',concat(wantedfiles," | "))
end
for _, fname in pairs(wantedfiles) do
if fname and input.is_readable.file(fname) then
@@ -4338,7 +4483,7 @@ function input.aux.find_file(instance,fi
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]
@@ -4347,12 +4492,12 @@ function input.aux.find_file(instance,fi
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',concat(pathlist," | ")) end
+ -- if filelist then input.logger('? file list: %s',concat(filelist," | ")) end
end
-- a bit messy ... esp the doscan setting here
for _, path in pairs(pathlist) do
@@ -4373,11 +4518,11 @@ function input.aux.find_file(instance,fi
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
@@ -4391,12 +4536,12 @@ function input.aux.find_file(instance,fi
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
@@ -4425,40 +4570,29 @@ function input.aux.find_file(instance,fi
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
@@ -4466,7 +4600,8 @@ if not input.concatinators then input.c
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
@@ -4475,16 +4610,17 @@ function input.find_files(instance,filen
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]
@@ -4512,11 +4648,12 @@ function input.find_given_files(instance
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("^*/","")
@@ -4569,16 +4706,19 @@ function input.find_wildcard_files(insta
if done and not allresults then break end
end
end
+ -- we can consider also searching the paths not in the database, but then
+ -- we end up with a messy search (all // in all path specs)
return result
end
-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
@@ -4588,7 +4728,7 @@ function input.save_used_files_in_trees(
f:write("\t<rl:name>" .. jobname .. "</rl:name>\n")
end
f:write("\t<rl:files>\n")
- for _,v in pairs(table.sortedkeys(instance.foundintrees)) do
+ for _,v in pairs(sorted(instance.foundintrees)) do -- ipairs
f:write("\t\t<rl:file n='" .. instance.foundintrees[v] .. "'>" .. v .. "</rl:file>\n")
end
f:write("\t</rl:files>\n")
@@ -4597,24 +4737,24 @@ function input.save_used_files_in_trees(
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
@@ -4627,7 +4767,7 @@ function input.for_files(instance, comma
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
@@ -4641,14 +4781,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)
@@ -4697,56 +4834,58 @@ function table.sequenced(t,sep) -- temp
for k, v in pairs(t) do
s[#s+1] = k .. "=" .. v
end
- return table.concat(s, sep or " | ")
+ return concat(s, sep or " | ")
end
-function input.methodhandler(what, 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
@@ -4792,16 +4931,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
@@ -4810,7 +4951,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
@@ -4837,37 +4979,22 @@ function input.with_files(instance,patte
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
@@ -4895,10 +5022,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
@@ -4916,16 +5043,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
@@ -4937,15 +5064,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
@@ -4954,10 +5081,185 @@ 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(str)
+ 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
+
+input.moreinfo = [[
+more information about ConTeXt and the tools that come with it can be found at:
+
+maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
+wiki : http://contextgarden.net
+]]
+
+function input.help(banner,message)
+ if not input.verbose then
+ input.verbose = true
+ -- input.report(banner,"\n")
+ end
+ input.report(banner,"\n")
+ input.report("")
+ input.reportlines(message)
+ if input.moreinfo and input.moreinfo ~= "" then
+ input.report("")
+ input.reportlines(input.moreinfo)
+ end
+end
+
+logs.set_level('error')
+logs.set_method('tex')
+
if not modules then modules = { } end modules ['luat-tmp'] = {
version = 1.001,
@@ -4983,63 +5285,82 @@ being written at the same time is small.
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])
- 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
+ check(input.clean_path_list("TEXMFCACHE") or { })
+ check(caches.defaults,true)
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
@@ -5047,14 +5368,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
@@ -5074,9 +5395,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
@@ -5099,26 +5420,28 @@ function caches.is_writable(filepath,fil
return file.is_writable(tmaname)
end
-function caches.savedata(filepath,filename,data,raw) -- raw needed for file cache
+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--
@@ -5141,7 +5464,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
@@ -5166,7 +5489,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
@@ -5231,13 +5554,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)
@@ -5245,12 +5571,11 @@ function input.aux.save_data(instance, d
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
@@ -5265,13 +5590,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
@@ -5280,16 +5605,16 @@ function input.automount(instance,usecac
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
@@ -5300,7 +5625,7 @@ input.storage.data = { }
input.storage.min = 0 -- 500
input.storage.max = input.storage.min - 1
input.storage.trace = false -- true
-input.storage.done = 0
+input.storage.done = input.storage.done or 0
input.storage.evaluators = { }
-- (evaluate,message,names)
@@ -5338,17 +5663,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
@@ -5358,6 +5683,8 @@ function input.storage.dump()
end
end
+-- we also need to count at generation time (nicer for message)
+
if lua.bytecode then -- from 0 upwards
local i = input.storage.min
while lua.bytecode[i] do
@@ -5377,6 +5704,8 @@ end
if not versions then versions = { } end versions['luat-zip'] = 1.001
+local format = string.format
+
if zip and input then
zip.supported = true
else
@@ -5408,7 +5737,7 @@ else
zip.archives = { }
zip.registeredfiles = { }
- function zip.openarchive(instance,name)
+ function zip.openarchive(name)
if not name or name == "" then
return nil
else
@@ -5416,7 +5745,7 @@ else
if arch then
return arch
else
- local full = input.find_file(instance,name) or ""
+ local full = input.find_file(name) or ""
local arch = (full ~= "" and zip.open(full)) or false
zip.archives[name] = arch
return arch
@@ -5424,7 +5753,7 @@ else
end
end
- function zip.closearchive(instance,name)
+ function zip.closearchive(name)
if not name or name == "" and zip.archives[name] then
zip.close(zip.archives[name])
zip.archives[name] = nil
@@ -5435,20 +5764,22 @@ else
-- zip:///texmf.zip?tree=/tex/texmf-local
-- zip:///texmf-mine.zip?tree=/tex/texmf-projects
- function input.locators.zip(instance,specification) -- where is this used? startup zips (untested)
+ function input.locators.zip(specification) -- where is this used? startup zips (untested)
specification = input.splitmethod(specification)
local zipfile = specification.path
- local zfile = zip.openarchive(instance,name) -- tricky, could be in to be initialized tree
- if zfile then
- input.logger('! zip locator', specification.original ..' found')
- else
- input.logger('? zip locator', specification.original ..' not found')
+ local zfile = zip.openarchive(name) -- tricky, could be in to be initialized tree
+ if input.trace > 0 then
+ if zfile then
+ input.logger('! zip locator, found: %s',specification.original)
+ else
+ input.logger('? zip locator, not found: %s',specification.original)
+ end
end
end
- function input.hashers.zip(instance,tag,name)
- input.report("loading zip file",name,"as",tag)
- input.usezipfile(instance,tag .."?tree=" .. name)
+ function input.hashers.zip(tag,name)
+ input.report("loading zip file %s as %s",name,tag)
+ input.usezipfile(tag .."?tree=" .. name)
end
function input.concatinators.zip(tag,path,name)
@@ -5463,101 +5794,124 @@ else
return true
end
- function input.finders.zip(instance,specification,filetype)
+ function input.finders.zip(specification,filetype)
specification = input.splitmethod(specification)
if specification.path then
local q = url.query(specification.query)
if q.name then
- local zfile = zip.openarchive(instance,specification.path)
+ local zfile = zip.openarchive(specification.path)
if zfile then
- input.logger('! zip finder',specification.path)
+ if input.trace > 0 then
+ input.logger('! zip finder, path: %s',specification.path)
+ end
local dfile = zfile:open(q.name)
if dfile then
dfile = zfile:close()
- input.logger('+ zip finder',q.name)
+ if input.trace > 0 then
+ input.logger('+ zip finder, name: %s',q.name)
+ end
return specification.original
end
- else
- input.logger('? zip finder',specification.path)
+ elseif input.trace > 0 then
+ input.logger('? zip finder, path %s',specification.path)
end
end
end
- input.logger('- zip finder',filename)
+ if input.trace > 0 then
+ input.logger('- zip finder, name: %s',filename)
+ end
return unpack(input.finders.notfound)
end
- function input.openers.zip(instance,specification)
+ function input.openers.zip(specification)
local zipspecification = input.splitmethod(specification)
if zipspecification.path then
local q = url.query(zipspecification.query)
if q.name then
- local zfile = zip.openarchive(instance,zipspecification.path)
+ local zfile = zip.openarchive(zipspecification.path)
if zfile then
- input.logger('+ zip starter',zipspecification.path)
+ if input.trace > 0 then
+ input.logger('+ zip starter, path: %s',zipspecification.path)
+ end
local dfile = zfile:open(q.name)
if dfile then
input.show_open(specification)
return input.openers.text_opener(specification,dfile,'zip')
end
- else
- input.logger('- zip starter',zipspecification.path)
+ elseif input.trace > 0 then
+ input.logger('- zip starter, path %s',zipspecification.path)
end
end
end
- input.logger('- zip opener',filename)
+ if input.trace > 0 then
+ input.logger('- zip opener, name: %s',filename)
+ end
return unpack(input.openers.notfound)
end
- function input.loaders.zip(instance,specification)
+ function input.loaders.zip(specification)
specification = input.splitmethod(specification)
if specification.path then
local q = url.query(specification.query)
if q.name then
- local zfile = zip.openarchive(instance,specification.path)
+ local zfile = zip.openarchive(specification.path)
if zfile then
- input.logger('+ zip starter',specification.path)
+ if input.trace > 0 then
+ input.logger('+ zip starter, path: %s',specification.path)
+ end
local dfile = zfile:open(q.name)
if dfile then
input.show_load(filename)
- input.logger('+ zip loader',filename)
+ if input.trace > 0 then
+ input.logger('+ zip loader, name: %s',filename)
+ end
local s = dfile:read("*all")
dfile:close()
return true, s, #s
end
- else
- input.logger('- zip starter',specification.path)
+ elseif input.trace > 0 then
+ input.logger('- zip starter, path: %s',specification.path)
end
end
end
- input.logger('- zip loader',filename)
+ if input.trace > 0 then
+ input.logger('- zip loader, name: %s',filename)
+ end
return unpack(input.openers.notfound)
end
-- zip:///somefile.zip
-- zip:///somefile.zip?tree=texmf-local -> mount
- function input.usezipfile(instance,zipname)
+ function input.usezipfile(zipname)
zipname = validzip(zipname)
- input.logger('! zip use','file '..zipname)
+ if input.trace > 0 then
+ input.logger('! zip use, file: %s',zipname)
+ end
local specification = input.splitmethod(zipname)
local zipfile = specification.path
if zipfile and not zip.registeredfiles[zipname] then
local tree = url.query(specification.query).tree or ""
- input.logger('! zip register','file '..zipname)
- local z = zip.openarchive(instance,zipfile)
+ if input.trace > 0 then
+ input.logger('! zip register, file: %s',zipname)
+ end
+ local z = zip.openarchive(zipfile)
if z then
- input.logger("= zipfile","registering "..zipname)
+ local instance = input.instance
+ if input.trace > 0 then
+ input.logger("= zipfile, registering: %s",zipname)
+ end
input.starttiming(instance)
- input.aux.prepend_hash(instance,'zip',zipname,zipfile)
- input.aux.extend_texmf_var(instance,zipname) -- resets hashes too
+ input.aux.prepend_hash('zip',zipname,zipfile)
+ input.aux.extend_texmf_var(zipname) -- resets hashes too
zip.registeredfiles[zipname] = z
instance.files[zipname] = input.aux.register_zip_file(z,tree or "")
input.stoptiming(instance)
- else
- input.logger("? zipfile","unknown "..zipname)
+ elseif input.trace > 0 then
+ input.logger("? zipfile, unknown: %s",zipname)
end
- else
- input.logger('! zip register','no file '..zipname)
+ elseif input.trace > 0 then
+ input.logger('! zip register, no file: %s',zipname)
end
end
@@ -5568,7 +5922,9 @@ else
else
filter = "^"..tree.."/(.+)/(.-)$"
end
- input.logger('= zip filter',filter)
+ if input.trace > 0 then
+ input.logger('= zip filter: %s',filter)
+ end
local register, n = input.aux.register_file, 0
for i in z:files() do
local path, name = i.filename:match(filter)
@@ -5584,7 +5940,7 @@ else
n = n + 1
end
end
- input.report('= zip entries',n)
+ input.logger('= zip entries: %s',n)
return files
end
@@ -5601,6 +5957,8 @@ if not versions then versions = { } end
-- special functions that deal with io
+local format = string.format
+
if texconfig and not texlua then
input.level = input.level or 0
@@ -5623,13 +5981,17 @@ if texconfig and not texlua then
function input.show_load () end
end
- function input.finders.generic(instance,tag,filename,filetype)
- local foundname = input.find_file(instance,filename,filetype)
+ function input.finders.generic(tag,filename,filetype)
+ local foundname = input.find_file(filename,filetype)
if foundname and foundname ~= "" then
- input.logger('+ ' .. tag .. ' finder',filename,'filetype')
+ if input.trace > 0 then
+ input.logger('+ finder: %s, file: %s', tag,filename)
+ end
return foundname
else
- input.logger('- ' .. tag .. ' finder',filename,'filetype')
+ if input.trace > 0 then
+ input.logger('- finder: %s, file: %s', tag,filename)
+ end
return unpack(input.finders.notfound)
end
end
@@ -5642,7 +6004,9 @@ if texconfig and not texlua then
local u = unicode.utftype(file_handle)
local t = { }
if u > 0 then
- input.logger('+ ' .. tag .. ' opener (' .. unicode.utfname[u] .. ')',filename)
+ if input.trace > 0 then
+ input.logger('+ opener: %s (%s), file: %s',tag,unicode.utfname[u],filename)
+ end
local l
if u > 2 then
l = unicode.utf32_to_utf8(file_handle:read("*a"),u==4)
@@ -5657,8 +6021,11 @@ if texconfig and not texlua then
handle = nil,
noflines = #l,
close = function()
- input.logger('= ' .. tag .. ' closer (' .. unicode.utfname[u] .. ')',filename)
+ if input.trace > 0 then
+ input.logger('= closer: %s (%s), file: %s',tag,unicode.utfname[u],filename)
+ end
input.show_close(filename)
+ t = nil
end,
--~ getline = function(n)
--~ local line = t.lines[n]
@@ -5693,7 +6060,9 @@ if texconfig and not texlua then
end
}
else
- input.logger('+ ' .. tag .. ' opener',filename)
+ if input.trace > 0 then
+ input.logger('+ opener: %s, file: %s',tag,filename)
+ end
-- todo: file;name -> freeze / eerste regel scannen -> freeze
local filters = input.filters
t = {
@@ -5713,9 +6082,12 @@ if texconfig and not texlua then
return line
end,
close = function()
- input.logger('= ' .. tag .. ' closer',filename)
+ if input.trace > 0 then
+ input.logger('= closer: %s, file: %s',tag,filename)
+ end
input.show_close(filename)
file_handle:close()
+ t = nil
end,
handle = function()
return file_handle
@@ -5729,7 +6101,7 @@ if texconfig and not texlua then
return t
end
- function input.openers.generic(instance,tag,filename)
+ function input.openers.generic(tag,filename)
if filename and filename ~= "" then
local f = io.open(filename,"r")
if f then
@@ -5737,35 +6109,42 @@ if texconfig and not texlua then
return input.openers.text_opener(filename,f,tag)
end
end
- input.logger('- ' .. tag .. ' opener',filename)
+ if input.trace > 0 then
+ input.logger('- opener: %s, file: %s',tag,filename)
+ end
return unpack(input.openers.notfound)
end
- function input.loaders.generic(instance,tag,filename)
+ function input.loaders.generic(tag,filename)
if filename and filename ~= "" then
local f = io.open(filename,"rb")
if f then
input.show_load(filename)
- input.logger('+ ' .. tag .. ' loader',filename)
+ if input.trace > 0 then
+ input.logger('+ loader: %s, file: %s',tag,filename)
+ end
local s = f:read("*a")
+ garbagecollector.check(s)
f:close()
if s then
return true, s, #s
end
end
end
- input.logger('- ' .. tag .. ' loader',filename)
+ if input.trace > 0 then
+ input.logger('- loader: %s, file: %s',tag,filename)
+ end
return unpack(input.loaders.notfound)
end
- function input.finders.tex(instance,filename,filetype)
- return input.finders.generic(instance,'tex',filename,filetype)
+ function input.finders.tex(filename,filetype)
+ return input.finders.generic('tex',filename,filetype)
end
- function input.openers.tex(instance,filename)
- return input.openers.generic(instance,'tex',filename)
+ function input.openers.tex(filename)
+ return input.openers.generic('tex',filename)
end
- function input.loaders.tex(instance,filename)
- return input.loaders.generic(instance,'tex',filename)
+ function input.loaders.tex(filename)
+ return input.loaders.generic('tex',filename)
end
end
@@ -5779,15 +6158,12 @@ if texconfig and not texlua then do
ctx = ctx or { }
- local ss = { }
-
- function ctx.writestatus(a,b)
- local s = ss[a]
- if not ss[a] then
- s = a:rpadd(15) .. ": "
- ss[a] = s
+ function ctx.writestatus(a,b,c,...)
+ if c then
+ texio.write_nl(("%-15s: %s\n"):format(a,b:format(c,...)))
+ else
+ texio.write_nl(("%-15s: %s\n"):format(a,b)) -- b can have %'s
end
- texio.write_nl(s .. b .. "\n")
end
-- this will become: ctx.install_statistics(fnc() return ..,.. end) etc
@@ -5799,63 +6175,75 @@ if texconfig and not texlua then do
if #tag > n then n = #tag end
end
+ function ctx.memused()
+ -- collectgarbage("collect")
+ return string.format("%s MB (ctx: %s MB)",math.round(collectgarbage("count")), math.round(status.luastate_bytes/1000))
+ end
+
function ctx.show_statistics() -- todo: move calls
+ local loadtime, register_statistics = input.loadtime, ctx.register_statistics
if caches then
- ctx.register_statistics("used config path", "%s", function() return caches.configpath(texmf.instance) end)
- ctx.register_statistics("used cache path", "%s", function() return caches.path end)
+ register_statistics("used config path", "%s", function() return caches.configpath() end)
+ register_statistics("used cache path", "%s", function() return caches.temp() or "?" end)
end
if status.luabytecodes > 0 and input.storage and input.storage.done then
- ctx.register_statistics("modules/dumps/instances", "%s/%s/%s", function() return status.luabytecodes-500, input.storage.done, status.luastates end)
+ register_statistics("modules/dumps/instances", "%s/%s/%s", function() return status.luabytecodes-500, input.storage.done, status.luastates end)
end
- if texmf.instance then
- ctx.register_statistics("input load time", "%s seconds", function() return input.loadtime(texmf.instance) end)
+ if input.instance then
+ register_statistics("input load time", "%s seconds", function() return loadtime(input.instance) end)
end
if fonts then
- ctx.register_statistics("fonts load time","%s seconds", function() return input.loadtime(fonts) end)
+ register_statistics("fonts load time","%s seconds", function() return loadtime(fonts) end)
end
if xml then
- ctx.register_statistics("xml load time", "%s seconds, backreferences: %i, outer filtering time: %s", function() return input.loadtime(xml), #lxml.self, input.loadtime(lxml) end)
+ register_statistics("xml load time", "%s seconds, lpath calls: %s, cached calls: %s", function()
+ local stats = xml.statistics()
+ return loadtime(xml), stats.lpathcalls, stats.lpathcached
+ end)
+ register_statistics("lxml load time", "%s seconds preparation, backreferences: %i", function()
+ return loadtime(lxml), #lxml.self
+ end)
end
if mptopdf then
- ctx.register_statistics("mps conversion time", "%s seconds", function() return input.loadtime(mptopdf) end)
+ register_statistics("mps conversion time", "%s seconds", function() return loadtime(mptopdf) end)
end
if nodes then
- ctx.register_statistics("node processing time", "%s seconds (including kernel)", function() return input.loadtime(nodes) end)
+ register_statistics("node processing time", "%s seconds including kernel", function() return loadtime(nodes) end)
end
if kernel then
- ctx.register_statistics("kernel processing time", "%s seconds", function() return input.loadtime(kernel) end)
+ register_statistics("kernel processing time", "%s seconds", function() return loadtime(kernel) end)
end
if attributes then
- ctx.register_statistics("attribute processing time", "%s seconds", function() return input.loadtime(attributes) end)
+ register_statistics("attribute processing time", "%s seconds", function() return loadtime(attributes) end)
end
if languages then
- ctx.register_statistics("language load time", "%s seconds, n=%s", function() return input.loadtime(languages), languages.hyphenation.n() end)
+ register_statistics("language load time", "%s seconds, n=%s", function() return loadtime(languages), languages.hyphenation.n() end)
end
if figures then
- ctx.register_statistics("graphics processing time", "%s seconds, n=%s (including tex)", function() return input.loadtime(figures), figures.n or "?" end)
+ register_statistics("graphics processing time", "%s seconds including tex, n=%s", function() return loadtime(figures), figures.n or "?" end)
end
if metapost then
- ctx.register_statistics("metapost processing time", "%s seconds, loading: %s seconds, execution: %s seconds, n: %s", function() return input.loadtime(metapost), input.loadtime(mplib), input.loadtime(metapost.exectime), metapost.n end)
+ register_statistics("metapost processing time", "%s seconds, loading: %s seconds, execution: %s seconds, n: %s", function() return loadtime(metapost), loadtime(mplib), loadtime(metapost.exectime), metapost.n end)
end
- if status.luastate_bytes then
- ctx.register_statistics("current memory usage", "%s bytes", function() return status.luastate_bytes end)
+ if status.luastate_bytes and ctx.memused then
+ register_statistics("current memory usage", "%s", ctx.memused)
end
if nodes then
- ctx.register_statistics("cleaned up reserved nodes", "%s nodes, %s lists of %s", function() return nodes.cleanup_reserved(tex.count[24]) end) -- \topofboxstack
+ register_statistics("cleaned up reserved nodes", "%s nodes, %s lists of %s", function() return nodes.cleanup_reserved(tex.count[24]) end) -- \topofboxstack
end
if status.node_mem_usage then
- ctx.register_statistics("node memory usage", "%s", function() return status.node_mem_usage end)
+ register_statistics("node memory usage", "%s", function() return status.node_mem_usage end)
end
if languages then
- ctx.register_statistics("loaded patterns", "%s", function() return languages.logger.report() end)
+ register_statistics("loaded patterns", "%s", function() return languages.logger.report() end)
end
if fonts then
- ctx.register_statistics("loaded fonts", "%s", function() return fonts.logger.report() end)
+ register_statistics("loaded fonts", "%s", function() return fonts.logger.report() end)
end
if xml then -- so we are in mkiv, we need a different check
- ctx.register_statistics("runtime", "%s seconds, %i processed pages, %i shipped pages, %.3f pages/second", function()
- input.stoptiming(texmf)
- local runtime = input.loadtime(texmf)
+ register_statistics("runtime", "%s seconds, %i processed pages, %i shipped pages, %.3f pages/second", function()
+ input.stoptiming(input.instance)
+ local runtime = loadtime(input.instance)
local shipped = tex.count['nofshipouts']
local pages = tex.count['realpageno'] - 1
local persecond = shipped / runtime
@@ -5864,8 +6252,8 @@ if texconfig and not texlua then do
end
for _, t in ipairs(statusinfo) do
local tag, pattern, fnc = t[1], t[2], t[3]
- ctx.writestatus("mkiv lua stats", string.format("%s - %s", tag:rpadd(n," "), pattern:format(fnc())))
- end
+ ctx.writestatus("mkiv lua stats", "%s - %s", tag:rpadd(n," "), pattern:format(fnc()))
+ end-- input.expanded_path_list("osfontdir")
end
end end
@@ -5878,65 +6266,65 @@ if texconfig and not texlua then
-- if still present, we overload kpse (put it off-line so to say)
- if not texmf then texmf = { } end
+ input.starttiming(input.instance)
- input.starttiming(texmf)
+ if not input.instance then
- if not texmf.instance then
+ if not input.instance then -- prevent a second loading
- if not texmf.instance then -- prevent a second loading
+ input.instance = input.reset()
+ input.instance.progname = 'context'
+ input.instance.engine = 'luatex'
+ input.instance.validfile = input.validctxfile
- texmf.instance = input.reset()
- texmf.instance.progname = environment.progname or 'context'
- texmf.instance.engine = environment.engine or 'luatex'
- texmf.instance.validfile = input.validctxfile
-
- input.load(texmf.instance)
+ input.load()
end
if callback then
- callback.register('find_read_file' , function(id,name) return input.findtexfile(texmf.instance,name) end)
- callback.register('open_read_file' , function( name) return input.opentexfile(texmf.instance,name) end)
+ callback.register('find_read_file' , function(id,name) return input.findtexfile(name) end)
+ callback.register('open_read_file' , function( name) return input.opentexfile(name) end)
end
if callback then
- callback.register('find_data_file' , function(name) return input.findbinfile(texmf.instance,name,"tex") end)
- callback.register('find_enc_file' , function(name) return input.findbinfile(texmf.instance,name,"enc") end)
- callback.register('find_font_file' , function(name) return input.findbinfile(texmf.instance,name,"tfm") end)
- callback.register('find_format_file' , function(name) return input.findbinfile(texmf.instance,name,"fmt") end)
- callback.register('find_image_file' , function(name) return input.findbinfile(texmf.instance,name,"tex") end)
- callback.register('find_map_file' , function(name) return input.findbinfile(texmf.instance,name,"map") end)
- callback.register('find_ocp_file' , function(name) return input.findbinfile(texmf.instance,name,"ocp") end)
- callback.register('find_opentype_file' , function(name) return input.findbinfile(texmf.instance,name,"otf") end)
- callback.register('find_output_file' , function(name) return name end)
- callback.register('find_pk_file' , function(name) return input.findbinfile(texmf.instance,name,"pk") end)
- callback.register('find_sfd_file' , function(name) return input.findbinfile(texmf.instance,name,"sfd") end)
- callback.register('find_truetype_file' , function(name) return input.findbinfile(texmf.instance,name,"ttf") end)
- callback.register('find_type1_file' , function(name) return input.findbinfile(texmf.instance,name,"pfb") end)
- callback.register('find_vf_file' , function(name) return input.findbinfile(texmf.instance,name,"vf") end)
-
- callback.register('read_data_file' , function(file) return input.loadbinfile(texmf.instance,file,"tex") end)
- callback.register('read_enc_file' , function(file) return input.loadbinfile(texmf.instance,file,"enc") end)
- callback.register('read_font_file' , function(file) return input.loadbinfile(texmf.instance,file,"tfm") end)
+ callback.register('find_data_file' , function(name) return input.findbinfile(name,"tex") end)
+ callback.register('find_enc_file' , function(name) return input.findbinfile(name,"enc") end)
+ callback.register('find_font_file' , function(name) return input.findbinfile(name,"tfm") end)
+ callback.register('find_format_file' , function(name) return input.findbinfile(name,"fmt") end)
+ callback.register('find_image_file' , function(name) return input.findbinfile(name,"tex") end)
+ callback.register('find_map_file' , function(name) return input.findbinfile(name,"map") end)
+ callback.register('find_ocp_file' , function(name) return input.findbinfile(name,"ocp") end)
+ callback.register('find_opentype_file' , function(name) return input.findbinfile(name,"otf") end)
+ callback.register('find_output_file' , function(name) return name end)
+ callback.register('find_pk_file' , function(name) return input.findbinfile(name,"pk") end)
+ callback.register('find_sfd_file' , function(name) return input.findbinfile(name,"sfd") end)
+ callback.register('find_truetype_file' , function(name) return input.findbinfile(name,"ttf") end)
+ callback.register('find_type1_file' , function(name) return input.findbinfile(name,"pfb") end)
+ callback.register('find_vf_file' , function(name) return input.findbinfile(name,"vf") end)
+
+ callback.register('read_data_file' , function(file) return input.loadbinfile(file,"tex") end)
+ callback.register('read_enc_file' , function(file) return input.loadbinfile(file,"enc") end)
+ callback.register('read_font_file' , function(file) return input.loadbinfile(file,"tfm") end)
-- format
-- image
- callback.register('read_map_file' , function(file) return input.loadbinfile(texmf.instance,file,"map") end)
- callback.register('read_ocp_file' , function(file) return input.loadbinfile(texmf.instance,file,"ocp") end)
- callback.register('read_opentype_file' , function(file) return input.loadbinfile(texmf.instance,file,"otf") end)
+ callback.register('read_map_file' , function(file) return input.loadbinfile(file,"map") end)
+ callback.register('read_ocp_file' , function(file) return input.loadbinfile(file,"ocp") end)
+ callback.register('read_opentype_file' , function(file) return input.loadbinfile(file,"otf") end)
-- output
- callback.register('read_pk_file' , function(file) return input.loadbinfile(texmf.instance,file,"pk") end)
- callback.register('read_sfd_file' , function(file) return input.loadbinfile(texmf.instance,file,"sfd") end)
- callback.register('read_truetype_file' , function(file) return input.loadbinfile(texmf.instance,file,"ttf") end)
- callback.register('read_type1_file' , function(file) return input.loadbinfile(texmf.instance,file,"pfb") end)
- callback.register('read_vf_file' , function(file) return input.loadbinfile(texmf.instance,file,"vf" ) end)
+ callback.register('read_pk_file' , function(file) return input.loadbinfile(file,"pk") end)
+ callback.register('read_sfd_file' , function(file) return input.loadbinfile(file,"sfd") end)
+ callback.register('read_truetype_file' , function(file) return input.loadbinfile(file,"ttf") end)
+ callback.register('read_type1_file' , function(file) return input.loadbinfile(file,"pfb") end)
+ callback.register('read_vf_file' , function(file) return input.loadbinfile(file,"vf" ) end)
end
- if callback and environment.aleph_mode then
- callback.register('find_font_file' , function(name) return input.findbinfile(texmf.instance,name,"ofm") end)
- callback.register('read_font_file' , function(file) return input.loadbinfile(texmf.instance,file,"ofm") end)
- callback.register('find_vf_file' , function(name) return input.findbinfile(texmf.instance,name,"ovf") end)
- callback.register('read_vf_file' , function(file) return input.loadbinfile(texmf.instance,file,"ovf") end)
+ if input.aleph_mode == nil then environment.aleph_mode = true end -- some day we will drop omega font support
+
+ if callback and input.aleph_mode then
+ callback.register('find_font_file' , function(name) return input.findbinfile(name,"ofm") end)
+ callback.register('read_font_file' , function(file) return input.loadbinfile(file,"ofm") end)
+ callback.register('find_vf_file' , function(name) return input.findbinfile(name,"ovf") end)
+ callback.register('read_vf_file' , function(file) return input.loadbinfile(file,"ovf") end)
end
if callback then
@@ -6024,16 +6412,16 @@ if texconfig and not texlua then
if kpse then
function kpse.find_file(filename,filetype,mustexist)
- return input.find_file(texmf.instance,filename,filetype,mustexist)
+ return input.find_file(filename,filetype,mustexist)
end
function kpse.expand_path(variable)
- return input.expand_path(texmf.instance,variable)
+ return input.expand_path(variable)
end
function kpse.expand_var(variable)
- return input.expand_var(texmf.instance,variable)
+ return input.expand_var(variable)
end
function kpse.expand_braces(variable)
- return input.expand_braces(texmf.instance,variable)
+ return input.expand_braces(variable)
end
end
@@ -6060,7 +6448,7 @@ if texconfig and not texlua then
function luatex.variables()
local t, x = { }, nil
for _,v in pairs(luatex.variablenames) do
- x = input.var_value(texmf.instance,v)
+ x = input.var_value(v)
if x and x:find("^%d+$") then
t[v] = tonumber(x)
end
@@ -6084,28 +6472,34 @@ if texconfig and not texlua then
end
--- some tex basics
+-- some tex basics, maybe this will move to ctx
-if not cs then cs = { } end
+if tex then
-function cs.def(k,v)
- tex.sprint(tex.texcatcodes, "\\def\\" .. k .. "{" .. v .. "}")
-end
+ local texsprint, texwrite = tex.sprint, tex.write
-function cs.chardef(k,v)
- tex.sprint(tex.texcatcodes, "\\chardef\\" .. k .. "=" .. v .. "\\relax")
-end
+ if not cs then cs = { } end
-function cs.boolcase(b)
- if b then tex.write(1) else tex.write(0) end
-end
+ function cs.def(k,v)
+ texsprint(tex.texcatcodes, "\\def\\" .. k .. "{" .. v .. "}")
+ end
-function cs.testcase(b)
- if b then
- tex.sprint(tex.texcatcodes, "\\firstoftwoarguments")
- else
- tex.sprint(tex.texcatcodes, "\\secondoftwoarguments")
+ function cs.chardef(k,v)
+ texsprint(tex.texcatcodes, "\\chardef\\" .. k .. "=" .. v .. "\\relax")
+ end
+
+ function cs.boolcase(b)
+ if b then texwrite(1) else texwrite(0) end
+ end
+
+ function cs.testcase(b)
+ if b then
+ texsprint(tex.texcatcodes, "\\firstoftwoarguments")
+ else
+ texsprint(tex.texcatcodes, "\\secondoftwoarguments")
+ end
end
+
end
@@ -6235,9 +6629,11 @@ own.libs = { -- todo: check which ones a
'l-dir.lua',
'l-boolean.lua',
'l-unicode.lua',
+ 'l-math.lua',
'l-utils.lua',
'luat-lib.lua',
'luat-inp.lua',
+ 'luat-log.lua',
'luat-tmp.lua',
'luat-zip.lua',
'luat-tex.lua',
@@ -6291,19 +6687,21 @@ if not input then
os.exit()
end
-instance = input.reset()
+input.instance = input.reset()
input.verbose = environment.arguments["verbose"] or false
-input.banner = 'LuaTools | '
+input.banner = 'LuaTools'
utils.report = input.report
input.defaultlibs = { -- not all are needed
'l-string.lua', 'l-lpeg.lua', 'l-table.lua', 'l-boolean.lua', 'l-number.lua', 'l-set.lua', 'l-unicode.lua',
- 'l-md5.lua', 'l-os.lua', 'l-io.lua', 'l-file.lua', 'l-url.lua', 'l-dir.lua', 'l-utils.lua', 'l-tex.lua',
- 'luat-env.lua', 'luat-lib.lua', 'luat-inp.lua', 'luat-tmp.lua', 'luat-zip.lua', 'luat-tex.lua'
+ 'l-md5.lua', 'l-os.lua', 'l-io.lua', 'l-file.lua', 'l-url.lua', 'l-dir.lua', 'l-utils.lua', 'l-dimen.lua',
+ 'luat-lib.lua', 'luat-inp.lua', 'luat-env.lua', 'luat-tmp.lua', 'luat-zip.lua', 'luat-tex.lua'
}
-- todo: use environment.argument() instead of environment.arguments[]
+local instance = input.instance
+
instance.engine = environment.arguments["engine"] or 'luatex'
instance.progname = environment.arguments["progname"] or 'context'
instance.luaname = environment.arguments["luafile"] or "" -- environment.ownname or ""
@@ -6328,19 +6726,19 @@ if environment.arguments["minimize"] the
end
end
-function input.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.my_prepare_a()
+ input.resetconfig()
+ input.identify_cnf()
+ input.load_lua()
+ input.expand_variables()
+ input.load_cnf()
+ input.expand_variables()
end
-function input.my_prepare_b(instance)
- input.my_prepare_a(instance)
- input.load_hash(instance)
- input.automount(instance)
+function input.my_prepare_b()
+ input.my_prepare_a()
+ input.load_hash()
+ input.automount()
end
-- barename
@@ -6382,10 +6780,11 @@ messages.help = [[
--lsr use lsr and cnf directly
]]
-function input.my_make_format(instance,texname)
+function input.my_make_format(texname)
+ local instance = input.instance
if texname and texname ~= "" then
if input.usecache then
- local path = file.join(caches.setpath(instance,"formats")) -- maybe platform
+ local path = file.join(caches.setpath("formats")) -- maybe platform
if path and lfs then
lfs.chdir(path)
end
@@ -6394,22 +6793,22 @@ function input.my_make_format(instance,t
if barename == texname then
texname = texname .. ".tex"
end
- local fullname = input.find_files(instance,texname)[1] or ""
+ local fullname = input.find_files(texname)[1] or ""
if fullname == "" then
- input.report("no tex file with name",texname)
+ input.report("no tex file with name: %s",texname)
else
local luaname, lucname, luapath, lualibs = "", "", "", { }
-- the following is optional, since context.lua can also
-- handle this collect and compile business
if environment.arguments["compile"] then
if luaname == "" then luaname = barename end
- input.report("creating initialization file " .. luaname)
+ input.report("creating initialization file: %s",luaname)
luapath = file.dirname(luaname)
if luapath == "" then
luapath = file.dirname(texname)
end
if luapath == "" then
- luapath = file.dirname(input.find_files(instance,texname)[1] or "")
+ luapath = file.dirname(input.find_files(texname)[1] or "")
end
lualibs = string.split(instance.lualibs,",")
luaname = file.basename(barename .. ".lua")
@@ -6419,27 +6818,28 @@ function input.my_make_format(instance,t
if lualibs[1] then
local firstlib = file.join(luapath,lualibs[1])
if not lfs.isfile(firstlib) then
- local foundname = input.find_files(instance,lualibs[1])[1]
+ local foundname = input.find_files(lualibs[1])[1]
if foundname then
- input.report("located library path : " .. luapath)
+ input.report("located library path: %s",luapath)
luapath = file.dirname(foundname)
end
end
end
- input.report("using library path : " .. luapath)
- input.report("using lua libraries: " .. table.join(lualibs," "))
+ input.report("using library path: %s",luapath)
+ input.report("using lua libraries: %s",table.join(lualibs," "))
utils.merger.selfcreate(lualibs,luapath,luaname)
- if utils.lua.compile(luaname, lucname) and io.exists(lucname) then
+ local strip = input.boolean_variable("LUACSTRIP", true)
+ if utils.lua.compile(luaname,lucname,false,strip) and io.exists(lucname) then
luaname = lucname
- input.report("using compiled initialization file " .. lucname)
+ input.report("using compiled initialization file: %s",lucname)
else
- input.report("using uncompiled initialization file " .. luaname)
+ input.report("using uncompiled initialization file: %s",luaname)
end
else
for _, v in pairs({instance.luaname, instance.progname, barename}) do
v = string.gsub(v..".lua","%.lua%.lua$",".lua")
if v and (v ~= "") then
- luaname = input.find_files(instance,v)[1] or ""
+ luaname = input.find_files(v)[1] or ""
if luaname ~= "" then
break
end
@@ -6448,22 +6848,30 @@ function input.my_make_format(instance,t
end
if luaname == "" then
input.reportlines(messages.no_ini_file)
- input.report("texname : " .. texname)
- input.report("luaname : " .. instance.luaname)
- input.report("progname : " .. instance.progname)
- input.report("barename : " .. barename)
- else
- input.report("using lua initialization file " .. luaname)
+ input.report("texname : %s",texname)
+ input.report("luaname : %s",instance.luaname)
+ input.report("progname: %s",instance.progname)
+ input.report("barename: %s",barename)
+ else
+ input.report("using lua initialization file: %s",luaname)
+ local mp = dir.glob(file.stripsuffix(file.basename(luaname)).."-*.mem")
+ if mp and #mp > 0 then
+ for _, name in ipairs(mp) do
+ input.report("removing related mplib format %s", file.basename(name))
+ os.remove(name)
+ end
+ end
local flags = { "--ini" }
if environment.arguments["mkii"] then
flags[#flags+1] = "--progname=" .. instance.progname
else
flags[#flags+1] = "--lua=" .. string.quote(luaname)
end
- local bs = (environment.platform == "unix" and "\\\\") or "\\" -- todo: make a function
+ local bs = (os.platform == "unix" and "\\\\") or "\\" -- todo: make a function
local command = "luatex ".. table.concat(flags," ") .. " " .. string.quote(fullname) .. " " .. bs .. "dump"
- input.report("running command: " .. command .. "\n")
+ input.report("running command: %s\n",command)
os.spawn(command)
+ -- todo: do a dummy run that generates the related metafun and mfplain formats
end
end
else
@@ -6471,22 +6879,22 @@ function input.my_make_format(instance,t
end
end
-function input.my_run_format(instance,name,data,more)
+function input.my_run_format(name,data,more)
-- hm, rather old code here; we can now use the file.whatever functions
if name and (name ~= "") then
local barename = name:gsub("%.%a+$","")
local fmtname = ""
if input.usecache then
- local path = file.join(caches.setpath(instance,"formats")) -- maybe platform
+ local path = file.join(caches.setpath("formats")) -- maybe platform
fmtname = file.join(path,barename..".fmt") or ""
end
if fmtname == "" then
- fmtname = input.find_files(instance,barename..".fmt")[1] or ""
+ fmtname = input.find_files(barename..".fmt")[1] or ""
end
fmtname = input.clean_path(fmtname)
barename = fmtname:gsub("%.%a+$","")
if fmtname == "" then
- input.report("no format with name",name)
+ input.report("no format with name: %s",name)
else
local luaname = barename .. ".luc"
local f = io.open(luaname)
@@ -6497,11 +6905,11 @@ function input.my_run_format(instance,na
if f then
f:close()
local command = "luatex --fmt=" .. string.quote(barename) .. " --lua=" .. string.quote(luaname) .. " " .. string.quote(data) .. " " .. string.quote(more)
- input.report("running command: " .. command)
+ input.report("running command: %s",command)
os.spawn(command)
else
- input.report("using format name",fmtname)
- input.report("no luc/lua with name",barename)
+ input.report("using format name: %s",fmtname)
+ input.report("no luc/lua with name: %s",barename)
end
end
end
@@ -6519,8 +6927,9 @@ local function tabstr(str)
end
end
-local function list(instance,list)
- local pat = string.upper(instance.pattern or "","")
+local function list(list)
+ local instance = input.instance
+ local pat = string.upper(pattern or "","")
for _,key in pairs(table.sortedkeys(list)) do
if instance.pattern == "" or string.find(key:upper(),pat) then
if instance.kpseonly then
@@ -6534,10 +6943,11 @@ local function list(instance,list)
end
end
-function input.listers.variables (instance) list(instance,instance.variables ) end
-function input.listers.expansions(instance) list(instance,instance.expansions) end
+function input.listers.variables () list(input.instance.variables ) end
+function input.listers.expansions() list(input.instance.expansions) end
-function input.listers.configurations(instance)
+function input.listers.configurations()
+ local instance = input.instance
for _,key in pairs(table.sortedkeys(instance.kpsevars)) do
if not instance.pattern or (instance.pattern=="") or key:find(instance.pattern) then
print(key.."\n")
@@ -6552,61 +6962,58 @@ function input.listers.configurations(in
end
end
-input.report(banner,"\n")
+input.report("%s\n",banner)
local ok = true
if environment.arguments["find-file"] then
- input.my_prepare_b(instance)
+ input.my_prepare_b()
instance.format = environment.arguments["format"] or instance.format
if instance.pattern then
instance.allresults = true
- input.for_files(instance, input.find_files, { instance.pattern }, instance.my_format)
+ input.for_files(input.find_files, { instance.pattern }, instance.my_format)
else
- input.for_files(instance, input.find_files, environment.files, instance.my_format)
+ input.for_files(input.find_files, environment.files, instance.my_format)
end
elseif environment.arguments["find-path"] then
- input.my_prepare_b(instance)
- local path = input.find_file(instance, environment.files[1], instance.my_format)
+ input.my_prepare_b()
+ local path = input.find_file(environment.files[1], instance.my_format)
if input.verbose then
input.report(file.dirname(path))
else
print(file.dirname(path))
end
---~ elseif environment.arguments["first-writable-path"] then
---~ input.my_prepare_b(instance)
---~ input.report(input.first_writable_path(instance,environment.files[1] or "."))
elseif environment.arguments["run"] then
- input.my_prepare_a(instance) -- ! no need for loading databases
+ input.my_prepare_a() -- ! no need for loading databases
input.verbose = true
- input.my_run_format(instance,environment.files[1] or "",environment.files[2] or "",environment.files[3] or "")
+ input.my_run_format(environment.files[1] or "",environment.files[2] or "",environment.files[3] or "")
elseif environment.arguments["fmt"] then
- input.my_prepare_a(instance) -- ! no need for loading databases
+ input.my_prepare_a() -- ! no need for loading databases
input.verbose = true
- input.my_run_format(instance,environment.arguments["fmt"], environment.files[1] or "",environment.files[2] or "")
+ input.my_run_format(environment.arguments["fmt"], environment.files[1] or "",environment.files[2] or "")
elseif environment.arguments["expand-braces"] then
- input.my_prepare_a(instance)
- input.for_files(instance, input.expand_braces, environment.files)
+ input.my_prepare_a()
+ input.for_files(input.expand_braces, environment.files)
elseif environment.arguments["expand-path"] then
- input.my_prepare_a(instance)
- input.for_files(instance, input.expand_path, environment.files)
+ input.my_prepare_a()
+ input.for_files(input.expand_path, environment.files)
elseif environment.arguments["expand-var"] or environment.arguments["expand-variable"] then
- input.my_prepare_a(instance)
- input.for_files(instance, input.expand_var, environment.files)
+ input.my_prepare_a()
+ input.for_files(input.expand_var, environment.files)
elseif environment.arguments["show-path"] or environment.arguments["path-value"] then
- input.my_prepare_a(instance)
- input.for_files(instance, input.show_path, environment.files)
+ input.my_prepare_a()
+ input.for_files(input.show_path, environment.files)
elseif environment.arguments["var-value"] or environment.arguments["show-value"] then
- input.my_prepare_a(instance)
- input.for_files(instance, input.var_value, environment.files)
+ input.my_prepare_a()
+ input.for_files(input.var_value, environment.files)
elseif environment.arguments["format-path"] then
- input.my_prepare_b(instance)
- input.report(caches.setpath(instance,"format"))
+ input.my_prepare_b()
+ input.report(caches.setpath("format"))
elseif instance.pattern then -- brrr
- input.my_prepare_b(instance)
+ input.my_prepare_b()
instance.format = environment.arguments["format"] or instance.format
instance.allresults = true
- input.for_files(instance, input.find_files, { instance.pattern }, instance.my_format)
+ input.for_files(input.find_files, { instance.pattern }, instance.my_format)
elseif environment.arguments["generate"] then
instance.renewcache = true
input.verbose = true
@@ -6614,46 +7021,36 @@ elseif environment.arguments["generate"]
elseif environment.arguments["make"] or environment.arguments["ini"] or environment.arguments["compile"] then
input.my_prepare_b(instance)
input.verbose = true
- input.my_make_format(instance,environment.files[1] or "")
+ input.my_make_format(environment.files[1] or "")
elseif environment.arguments["selfmerge"] then
utils.merger.selfmerge(own.name,own.libs,own.list)
elseif environment.arguments["selfclean"] then
utils.merger.selfclean(own.name)
elseif environment.arguments["selfupdate"] then
- input.my_prepare_b(instance)
+ input.my_prepare_b()
input.verbose = true
- input.update_script(instance,own.name,"luatools")
+ input.update_script(own.name,"luatools")
elseif environment.arguments["variables"] or environment.arguments["show-variables"] then
- input.my_prepare_a(instance)
- input.listers.variables(instance)
+ input.my_prepare_a()
+ input.listers.variables()
elseif environment.arguments["expansions"] or environment.arguments["show-expansions"] then
- input.my_prepare_a(instance)
- input.listers.expansions(instance)
+ input.my_prepare_a()
+ input.listers.expansions()
elseif environment.arguments["configurations"] or environment.arguments["show-configurations"] then
- input.my_prepare_a(instance)
- input.listers.configurations(instance)
+ input.my_prepare_a()
+ input.listers.configurations()
elseif environment.arguments["help"] or (environment.files[1]=='help') or (#environment.files==0) then
- if not input.verbose then
- input.verbose = true
- input.report(banner,"\n")
- end
- input.reportlines(messages.help)
+ input.help(banner,messages.help)
else
- input.my_prepare_b(instance)
- input.for_files(instance, input.find_files, environment.files, instance.my_format)
+ input.my_prepare_b()
+ input.for_files(input.find_files, environment.files, instance.my_format)
end
if input.verbose then
input.report("")
- input.report(string.format("runtime: %0.3f seconds",os.runtime()))
+ input.report("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
--- texmf-dist/scripts/context/lua/mtxrun.lua
+++ texmf-dist/scripts/context/lua/mtxrun.lua 2008-10-30 14:05:20.903589570 +0100
@@ -37,7 +37,7 @@ if not modules then modules = { } end mo
-- 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"
+banner = "version 1.1.2 - 2007+ - PRAGMA ADE / CONTEXT" -- not local
texlua = true
-- begin library merge
@@ -125,7 +125,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 +134,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
@@ -191,7 +175,7 @@ end
--~ end end
-string.chr_to_esc = {
+local chr_to_esc = {
["%"] = "%%",
["."] = "%.",
["+"] = "%+", ["-"] = "%-", ["*"] = "%*",
@@ -201,16 +185,18 @@ string.chr_to_esc = {
["{"] = "%{", ["}"] = "%}"
}
+string.chr_to_esc = chr_to_esc
+
function string:esc() -- variant 2
- return (self:gsub("(.)",string.chr_to_esc))
+ return (self:gsub("(.)",chr_to_esc))
end
-function string.unquote(str)
- return (str:gsub("^([\"\'])(.*)%1$","%2"))
+function string:unquote()
+ return (self:gsub("^([\"\'])(.*)%1$","%2"))
end
-function string.quote(str)
- return '"' .. str:unquote() .. '"'
+function string:quote()
+ return '"' .. self:unquote() .. '"'
end
function string:count(pattern) -- variant 3
@@ -460,6 +446,30 @@ function string:splitlines()
return capture:match(self)
end
+--~ local p = lpeg.splitat("->",false) print(p:match("oeps->what->more")) -- oeps what more
+--~ local p = lpeg.splitat("->",true) print(p:match("oeps->what->more")) -- oeps what->more
+--~ local p = lpeg.splitat("->",false) print(p:match("oeps")) -- oeps
+--~ local p = lpeg.splitat("->",true) print(p:match("oeps")) -- oeps
+
+local splitters_s, splitters_m = { }, { }
+
+function lpeg.splitat(separator,single)
+ local splitter = (single and splitters_s[separator]) or splitters_m[separator]
+ if not splitter then
+ separator = lpeg.P(separator)
+ if single then
+ local other, any = lpeg.C((1 - separator)^0), lpeg.P(1)
+ splitter = other * (separator * lpeg.C(any^0) + "")
+ splitters_s[separator] = splitter
+ else
+ local other = lpeg.C((1 - separator)^0)
+ splitter = other * (separator * other)^0
+ splitters_m[separator] = splitter
+ end
+ end
+ return splitter
+end
+
-- filename : l-table.lua
-- comment : split off from luat-lib
@@ -471,11 +481,15 @@ if not versions then versions = { } end
table.join = table.concat
+local concat, sort, insert, remove = table.concat, table.sort, table.insert, table.remove
+local format = string.format
+local getmetatable, setmetatable = getmetatable, setmetatable
+local pairs, ipairs, type, next, tostring = pairs, ipairs, type, next, tostring
+
function table.strip(tab)
local lst = { }
- for k, v in ipairs(tab) do
- -- s = string.gsub(v, "^%s*(.-)%s*$", "%1")
- s = v:gsub("^%s*(.-)%s*$", "%1")
+ for i=1,#tab do
+ local s = tab[i]:gsub("^%s*(.-)%s*$","%1")
if s == "" then
-- skip this one
else
@@ -485,16 +499,7 @@ function table.strip(tab)
return lst
end
---~ function table.sortedkeys(tab)
---~ local srt = { }
---~ for key,_ in pairs(tab) do
---~ srt[#srt+1] = key
---~ end
---~ table.sort(srt)
---~ return srt
---~ end
-
-function table.sortedkeys(tab)
+local function sortedkeys(tab)
local srt, kind = { }, 0 -- 0=unknown 1=string, 2=number 3=mixed
for key,_ in pairs(tab) do
srt[#srt+1] = key
@@ -514,22 +519,34 @@ function table.sortedkeys(tab)
end
end
if kind == 0 or kind == 3 then
- table.sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
+ sort(srt,function(a,b) return (tostring(a) < tostring(b)) end)
else
- table.sort(srt)
+ sort(srt)
end
return srt
end
+local function sortedhashkeys(tab) -- fast one
+ local srt = { }
+ for key,_ in pairs(tab) do
+ srt[#srt+1] = key
+ end
+ sort(srt)
+ return srt
+end
+
+table.sortedkeys = sortedkeys
+table.sortedhashkeys = sortedhashkeys
+
function table.append(t, list)
for _,v in pairs(list) do
- table.insert(t,v)
+ insert(t,v)
end
end
function table.prepend(t, list)
for k,v in pairs(list) do
- table.insert(t,k,v)
+ insert(t,k,v)
end
end
@@ -576,70 +593,57 @@ function table.imerged(...)
return tmp
end
-if not table.fastcopy then do
-
- local type, pairs, getmetatable, setmetatable = type, pairs, getmetatable, setmetatable
-
- local function fastcopy(old) -- fast one
- if old then
- local new = { }
- for k,v in pairs(old) do
- if type(v) == "table" then
- new[k] = fastcopy(v) -- was just table.copy
- else
- new[k] = v
- end
- end
- local mt = getmetatable(old)
- if mt then
- setmetatable(new,mt)
+local function fastcopy(old) -- fast one
+ if old then
+ local new = { }
+ for k,v in pairs(old) do
+ if type(v) == "table" then
+ new[k] = fastcopy(v) -- was just table.copy
+ else
+ new[k] = v
end
- return new
- else
- return { }
end
+ local mt = getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
+ return new
+ else
+ return { }
end
+end
- table.fastcopy = fastcopy
-
-end end
-
-if not table.copy then do
-
- local type, pairs, getmetatable, setmetatable = type, pairs, getmetatable, setmetatable
-
- local function copy(t, tables) -- taken from lua wiki, slightly adapted
- tables = tables or { }
- local tcopy = {}
- if not tables[t] then
- tables[t] = tcopy
- end
- for i,v in pairs(t) do -- brrr, what happens with sparse indexed
- if type(i) == "table" then
- if tables[i] then
- i = tables[i]
- else
- i = copy(i, tables)
- end
- end
- if type(v) ~= "table" then
- tcopy[i] = v
- elseif tables[v] then
- tcopy[i] = tables[v]
+local function copy(t, tables) -- taken from lua wiki, slightly adapted
+ tables = tables or { }
+ local tcopy = {}
+ if not tables[t] then
+ tables[t] = tcopy
+ end
+ for i,v in pairs(t) do -- brrr, what happens with sparse indexed
+ if type(i) == "table" then
+ if tables[i] then
+ i = tables[i]
else
- tcopy[i] = copy(v, tables)
+ i = copy(i, tables)
end
end
- local mt = getmetatable(t)
- if mt then
- setmetatable(tcopy,mt)
+ if type(v) ~= "table" then
+ tcopy[i] = v
+ elseif tables[v] then
+ tcopy[i] = tables[v]
+ else
+ tcopy[i] = copy(v, tables)
end
- return tcopy
end
+ local mt = getmetatable(t)
+ if mt then
+ setmetatable(tcopy,mt)
+ end
+ return tcopy
+end
- table.copy = copy
-
-end end
+table.fastcopy = fastcopy
+table.copy = copy
-- rougly: copy-loop : unpack : sub == 0.9 : 0.4 : 0.45 (so in critical apps, use unpack)
@@ -668,334 +672,363 @@ function table.starts_at(t)
return ipairs(t,1)(t,0)
end
-do
+function table.tohash(t,value)
+ local h = { }
+ if value == nil then value = true end
+ for _, v in pairs(t) do -- no ipairs here
+ h[v] = value
+ end
+ return h
+end
+
+function table.fromhash(t)
+ local h = { }
+ for k, v in pairs(t) do -- no ipairs here
+ if v then h[#h+1] = k end
+ end
+ return h
+end
- -- one of my first exercises in lua ...
+--~ 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")
- -- 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
-
- table.serialize_functions = true
- table.serialize_compact = true
- table.serialize_inline = true
+table.serialize_functions = true
+table.serialize_compact = true
+table.serialize_inline = true
+
+local noquotes, hexify, handle, reduce, compact, inline, functions
+
+local reserved = table.tohash { -- intercept a language flaw, no reserved words as key
+ 'and', 'break', 'do', 'else', 'elseif', 'end', 'false', 'for', 'function', 'if',
+ 'in', 'local', 'nil', 'not', 'or', 'repeat', 'return', 'then', 'true', 'until', 'while',
+}
- local function key(k)
- if type(k) == "number" then -- or k:find("^%d+$") then
- return "["..k.."]"
- elseif noquotes and k:find("^%a[%a%d%_]*$") then
- return k
+local function key(k)
+ if type(k) == "number" then -- or k:find("^%d+$") then
+ if hexify then
+ return ("[0x%04X]"):format(k)
else
- return '["'..k..'"]'
+ return "["..k.."]"
end
+ elseif noquotes and not reserved[k] and k:find("^%a[%a%d%_]*$") then
+ return k
+ else
+ return '["'..k..'"]'
end
+end
- local function simple_table(t)
- if #t > 0 then
- local n = 0
- for _,v in pairs(t) do
- n = n + 1
- end
- if n == #t then
- local tt = { }
- for i=1,#t do
- local v = t[i]
- local tv = type(v)
- if tv == "number" or tv == "boolean" then
- tt[#tt+1] = tostring(v)
- elseif tv == "string" then
- tt[#tt+1] = ("%q"):format(v)
+local function simple_table(t)
+ if #t > 0 then
+ local n = 0
+ for _,v in pairs(t) do
+ n = n + 1
+ end
+ if n == #t then
+ local tt = { }
+ for i=1,#t do
+ local v = t[i]
+ local tv = type(v)
+ if tv == "number" then
+ if hexify then
+ tt[#tt+1] = ("0x%04X"):format(v)
else
- tt = nil
- break
+ tt[#tt+1] = tostring(v)
end
+ elseif tv == "boolean" then
+ tt[#tt+1] = tostring(v)
+ elseif tv == "string" then
+ tt[#tt+1] = ("%q"):format(v)
+ else
+ tt = nil
+ break
end
- return tt
end
+ return tt
end
- return nil
end
+ return nil
+end
- local function 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)))
- 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 (why)
- 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
+local function do_serialize(root,name,depth,level,indexed)
+ if level > 0 then
+ depth = depth .. " "
+ if indexed then
+ handle(("%s{"):format(depth))
+ elseif name then
+ handle(("%s%s={"):format(depth,key(name)))
+ else
+ handle(("%s{"):format(depth))
+ end
+ end
+ if root and next(root) then
+ local first, last = nil, 0 -- #root cannot be trusted here
+ if compact then
+ for k,v in ipairs(root) do -- NOT: for k=1,#root do (we need to quit at nil)
+ if not first then first = k end
+ last = last + 1
+ end
+ end
+ --~ for _,k in pairs(sortedkeys(root)) do -- 1% faster:
+ local sk = sortedkeys(root)
+ for i=1,#sk do
+ local k = sk[i]
+ local v = root[k]
+ local t = type(v)
+ if compact and first and type(k) == "number" and k >= first and k <= last then
+ if t == "number" then
+ if hexify then
+ handle(("%s 0x%04X,"):format(depth,v))
else
- handle(("%s %q,"):format(depth,tostring(v)))
- end
- elseif k == "__p__" then -- parent
- if false then
- handle(("%s __p__=nil,"):format(depth))
+ handle(("%s %s,"):format(depth,v))
end
- elseif t == "number" then
- handle(("%s %s=%s,"):format(depth,key(k),v))
elseif t == "string" then
if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
- handle(("%s %s=%s,"):format(depth,key(k),v))
+ handle(("%s %s,"):format(depth,v))
else
- handle(("%s %s=%q,"):format(depth,key(k),v))
+ handle(("%s %q,"):format(depth,v))
end
elseif t == "table" then
if not next(v) then
- handle(("%s %s={},"):format(depth,key(k)))
+ handle(("%s {},"):format(depth))
elseif inline then
local st = simple_table(v)
if st then
- handle(("%s %s={ %s },"):format(depth,key(k),table.concat(st,", ")))
+ handle(("%s { %s },"):format(depth,concat(st,", ")))
else
- serialize(v,k,handle,depth,level+1,reduce,noquotes)
+ do_serialize(v,k,depth,level+1,true)
end
else
- serialize(v,k,handle,depth,level+1,reduce,noquotes)
+ do_serialize(v,k,depth,level+1,true)
end
elseif t == "boolean" then
- handle(("%s %s=%s,"):format(depth,key(k),tostring(v)))
+ handle(("%s %s,"):format(depth,tostring(v)))
elseif t == "function" then
- if table.serialize_functions then
- handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(v)))
+ if functions then
+ handle(('%s loadstring(%q),'):format(depth,v:dump()))
else
- handle(('%s %s="function",'):format(depth,key(k)))
+ handle(('%s "function",'):format(depth))
end
else
- handle(("%s %s=%q,"):format(depth,key(k),tostring(v)))
- -- handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(function() return v end)))
+ handle(("%s %q,"):format(depth,tostring(v)))
+ end
+ elseif k == "__p__" then -- parent
+ if false then
+ handle(("%s __p__=nil,"):format(depth))
+ end
+ elseif t == "number" then
+ if hexify then
+ handle(("%s %s=0x%04X,"):format(depth,key(k),v))
+ else
+ handle(("%s %s=%s,"):format(depth,key(k),v))
+ end
+ elseif t == "string" then
+ if reduce and (v:find("^[%-%+]?[%d]-%.?[%d+]$") == 1) then
+ handle(("%s %s=%s,"):format(depth,key(k),v))
+ else
+ handle(("%s %s=%q,"):format(depth,key(k),v))
+ end
+ elseif t == "table" then
+ if not next(v) then
+ handle(("%s %s={},"):format(depth,key(k)))
+ elseif inline then
+ local st = simple_table(v)
+ if st then
+ handle(("%s %s={ %s },"):format(depth,key(k),concat(st,", ")))
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ else
+ do_serialize(v,k,depth,level+1)
+ end
+ elseif t == "boolean" then
+ handle(("%s %s=%s,"):format(depth,key(k),tostring(v)))
+ elseif t == "function" then
+ if functions then
+ handle(('%s %s=loadstring(%q),'):format(depth,key(k),v:dump()))
+ else
+ handle(('%s %s="function",'):format(depth,key(k)))
end
- end
- if level > 0 then
- handle(("%s},"):format(depth))
else
- handle(("%s}"):format(depth))
+ handle(("%s %s=%q,"):format(depth,key(k),tostring(v)))
+ -- handle(('%s %s=loadstring(%q),'):format(depth,key(k),string.dump(function() return v end)))
end
- else
- handle(("%s}"):format(depth))
end
end
+ if level > 0 then
+ 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
+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(("[0x%04X]={"):format(name))
+ else
+ handle("[" .. name .. "]={")
end
- serialize(root, name, flush, nil, 0, reduce, noquotes)
- return table.concat(t,"\n")
+ elseif tname == "boolean" then
+ if name then
+ handle("return {")
+ else
+ handle("{")
+ end
+ else
+ handle("t={")
end
+ if root and next(root) then
+ do_serialize(root,name,"",0,indexed)
+ end
+ handle("}")
+end
+
+--~ name:
+--~
+--~ true : return { }
+--~ false : { }
+--~ nil : t = { }
+--~ string : string = { }
+--~ 'return' : return { }
+--~ number : [number] = { }
- function table.tohandle(handle,root,name,reduce,noquotes)
- serialize(root, name, handle, nil, 0, 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,reduce,noquotes,hexify)
+ return concat(t,"\n")
+end
- -- sometimes tables are real use (zapfino extra pro is some 85M) in which
- -- case a stepwise serialization is nice; actually, we could consider:
- --
- -- for line in table.serializer(root,name,reduce,noquotes) do
- -- ...(line)
- -- end
- --
- -- so this is on the todo list
+function table.tohandle(handle,root,name,reduce,noquotes,hexify)
+ serialize(root,name,handle,reduce,noquotes,hexify)
+end
- table.tofile_maxtab = 2*1024
+-- sometimes tables are real use (zapfino extra pro is some 85M) in which
+-- case a stepwise serialization is nice; actually, we could consider:
+--
+-- for line in table.serializer(root,name,reduce,noquotes) do
+-- ...(line)
+-- end
+--
+-- so this is on the todo list
- function table.tofile(filename,root,name,reduce,noquotes)
- 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")
+table.tofile_maxtab = 2*1024
+
+function table.tofile(filename,root,name,reduce,noquotes,hexify)
+ local f = io.open(filename,'w')
+ if f then
+ local maxtab = table.tofile_maxtab
+ if maxtab > 1 then
+ local t = { }
+ local function flush(s)
+ t[#t+1] = s
+ if #t > maxtab then
+ f:write(concat(t,"\n"),"\n") -- hm, write(sometable) should be nice
+ t = { }
end
- serialize(root, name, flush, nil, 0, reduce, noquotes)
end
- f:close()
+ serialize(root,name,flush,reduce,noquotes,hexify)
+ f:write(concat(t,"\n"),"\n")
+ else
+ local function flush(s)
+ f:write(s,"\n")
+ end
+ serialize(root,name,flush,reduce,noquotes,hexify)
end
+ f:close()
end
-
end
---~ 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)
- for i=1,#t do
- local v = t[i]
- if type(v) == "table" then
- if complete or type(v[1]) == "table" then
- flatten(v,f,complete)
- else
- f[#f+1] = v
- end
+local function flatten(t,f,complete)
+ for i=1,#t do
+ local v = t[i]
+ if type(v) == "table" then
+ if complete or type(v[1]) == "table" then
+ flatten(v,f,complete)
else
f[#f+1] = v
end
+ else
+ f[#f+1] = v
end
end
+end
- function table.flatten(t)
- local f = { }
- flatten(t,f,true)
- return f
- end
+function table.flatten(t)
+ local f = { }
+ flatten(t,f,true)
+ return f
+end
- function table.unnest(t) -- bad name
- local f = { }
- flatten(t,f,false)
- return f
- end
+function table.unnest(t) -- bad name
+ local f = { }
+ flatten(t,f,false)
+ return f
+end
- table.flatten_one_level = table.unnest
+table.flatten_one_level = table.unnest
+-- the next three may disappear
+
+function table.remove_value(t,value) -- todo: n
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ remove(t,i)
+ -- remove all, so no: return
+ end
+ end
+ end
end
function table.insert_before_value(t,value,str)
- for i=1,#t do
- if t[i] == value then
- table.insert(t,i,str)
- return
+ if str then
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i,str)
+ return
+ end
+ end
end
+ insert(t,1,str)
+ elseif value then
+ insert(t,1,value)
end
- table.insert(t,1,str)
end
function table.insert_after_value(t,value,str)
- for i=1,#t do
- if t[i] == value then
- table.insert(t,i+1,str)
- return
+ if str then
+ if value then
+ for i=1,#t do
+ if t[i] == value then
+ insert(t,i+1,str)
+ return
+ end
+ end
end
+ t[#t+1] = str
+ elseif value then
+ t[#t+1] = value
end
- t[#t+1] = str
end
function table.are_equal(a,b,n,m)
@@ -1026,27 +1059,11 @@ function table.compact(t)
end
end
-function table.tohash(t)
- local h = { }
- for _, v in pairs(t) do -- no ipairs here
- h[v] = true
- end
- return h
-end
-
-function table.fromhash(t)
- local h = { }
- for k, v in pairs(t) do -- no ipairs here
- if v then h[#h+1] = k end
- end
- return h
-end
-
function table.contains(t, v)
if t then
for i=1, #t do
if t[i] == v then
- return true
+ return i
end
end
end
@@ -1083,11 +1100,10 @@ function table.clone(t,p) -- t is option
return t
end
-
function table.hexed(t,seperator)
local tt = { }
- for i=1,#t do tt[i] = string.format("0x%04X",t[i]) end
- return table.concat(tt,seperator or " ")
+ for i=1,#t do tt[i] = ("0x%04X"):format(t[i]) end
+ return concat(tt,seperator or " ")
end
function table.reverse_hash(h)
@@ -1127,6 +1143,7 @@ function io.loaddata(filename)
local f = io.open(filename,'rb')
if f then
local data = f:read('*all')
+ -- garbagecollector.check(data)
f:close()
return data
else
@@ -1135,7 +1152,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 +1162,9 @@ function io.savedata(filename,data,joine
f:write(data)
end
f:close()
+ return true
+ else
+ return false
end
end
@@ -1499,6 +1519,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)
@@ -1574,10 +1597,14 @@ if not versions then versions = { } end
if not file then file = { } end
+local concat = table.concat
+
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 +1614,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,18 +1635,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
---~ t[i] = (t[i]:gsub("\\","/")):gsub("/+$","")
---~ end
---~ return table.concat(t,"/")
---~ end
-
--~ print(file.join("x/","/y"))
--~ print(file.join("http://","/y"))
--~ print(file.join("http://a","/y"))
@@ -1631,7 +1642,7 @@ end
--~ print(file.join("//nas-1","/y"))
function file.join(...)
- local pth = table.concat({...},"/")
+ local pth = concat({...},"/")
pth = pth:gsub("\\","/")
local a, b = pth:match("^(.*://)(.*)$")
if a and b then
@@ -1664,6 +1675,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(";")
@@ -1688,37 +1709,29 @@ function file.split_path(str)
end
function file.join_path(tab)
- return table.concat(tab,io.pathseparator) -- can have trailing //
+ return concat(tab,io.pathseparator) -- can have trailing //
end
---~ 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 +1744,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 +1851,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
@@ -1819,30 +1879,6 @@ if lfs then do
dir.glob_pattern = glob_pattern
- --~ local function glob(pattern, action)
- --~ local t = { }
- --~ local path, rest, patt, recurse
- --~ local action = action or function(name) t[#t+1] = name end
- --~ local pattern = pattern:gsub("^%*%*","./**")
- --~ local pattern = pattern:gsub("/%*/","/**/")
- --~ path, rest = pattern:match("^(/)(.-)$")
- --~ if path then
- --~ path = path
- --~ else
- --~ path, rest = pattern:match("^([^/]*)/(.-)$")
- --~ end
- --~ if rest then
- --~ patt = rest:gsub("([%.%-%+])", "%%%1")
- --~ end
- --~ patt = patt:gsub("%*", "[^/]*")
- --~ patt = patt:gsub("%?", "[^/]")
- --~ patt = patt:gsub("%[%^/%]%*%[%^/%]%*", ".*")
- --~ if path == "" then path = "." end
- --~ recurse = patt:find("%.%*/") ~= nil
- --~ glob_pattern(path,patt,recurse,action)
- --~ return t
- --~ end
-
local P, S, R, C, Cc, Cs, Ct, Cv, V = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cv, lpeg.V
local pattern = Ct {
@@ -1868,13 +1904,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 +1942,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 +2164,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 +2183,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
@@ -2156,6 +2201,35 @@ function boolean.falsetrue()
end
+-- filename : l-math.lua
+-- comment : split off from luat-lib
+-- author : Hans Hagen, PRAGMA-ADE, Hasselt NL
+-- copyright: PRAGMA ADE / ConTeXt Development Team
+-- license : see context related readme files
+
+if not versions then versions = { } end versions['l-math'] = 1.001
+
+local floor = math.floor
+
+if not math.round then
+ function math.round(x)
+ return floor(x + 0.5)
+ end
+end
+
+if not math.div then
+ function math.div(n,m)
+ return floor(n/m)
+ end
+end
+
+if not math.mod then
+ function math.mod(n,m)
+ return n % m
+ end
+end
+
+
if not modules then modules = { } end modules ['l-xml'] = {
version = 1.001,
comment = "this module is the basis for the lxml-* ones",
@@ -2199,11 +2273,11 @@ xml.trace_lpath = false
xml.trace_print = false
xml.trace_remap = false
-local format, concat = string.format, table.concat
+local format, concat, remove, insert, type, next = string.format, table.concat, table.remove, table.insert, type, next
--~ local pairs, next, type = pairs, next, type
--- todo: some things per xml file, liek namespace remapping
+-- todo: some things per xml file, like namespace remapping
--[[ldx--
<p>First a hack to enable namespace resolving. A namespace is characterized by
@@ -2312,7 +2386,7 @@ do
-- not just one big nested table capture (lpeg overflow)
- local remove, nsremap, resolvens = table.remove, xml.xmlns, xml.resolvens
+ local nsremap, resolvens = xml.xmlns, xml.resolvens
local stack, top, dt, at, xmlns, errorstr, entities = {}, {}, {}, {}, {}, nil, {}
@@ -2364,7 +2438,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 +2452,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 +2712,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 +2775,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 +2819,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 +2851,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
@@ -2798,8 +2877,8 @@ ens = ern
end
end
if not found then
- table.insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
- table.insert(dt, 2, "\n" )
+ insert(dt, 1, { special=true, ns="", tg="@pi@", dt = { "xml version='1.0' standalone='yes'"} } )
+ insert(dt, 2, "\n" )
end
end
end
@@ -2811,14 +2890,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 +2962,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,11 +3016,16 @@ of <l n='xpath'/> and since we're not co
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 { }
+ xml.functions = xml.functions or { }
+ xml.expressions = xml.expressions or { }
- local functions = xml.functions
+ local functions = xml.functions
+ local expressions = xml.expressions
local actions = {
[10] = "stay",
@@ -2953,34 +3049,32 @@ do
[40] = "processing instruction",
}
- --~ local function make_expression(str) --could also be an lpeg
- --~ str = str:gsub("@([a-zA-Z%-_]+)", "(a['%1'] or '')")
- --~ str = str:gsub("position%(%)", "i")
- --~ str = str:gsub("text%(%)", "t")
- --~ str = str:gsub("!=", "~=")
- --~ str = str:gsub("([^=!~<>])=([^=!~<>])", "%1==%2")
- --~ str = str:gsub("([a-zA-Z%-_]+)%(", "functions.%1(")
- --~ return str, loadstring(format("return function(functions,i,a,t) return %s end", str))()
- --~ end
-
-- a rather dumb lpeg
local P, S, R, C, V, Cc = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.V, lpeg.Cc
- local lp_position = P("position()") / "id"
+ -- instead of using functions we just parse a few names which saves a call
+ -- later on
+
+ local lp_position = P("position()") / "ps"
+ local lp_index = P("index()") / "id"
local lp_text = P("text()") / "tx"
- local lp_name = P("name()") / "((rt.ns~='' and rt.ns..':'..rt.tg) or '')"
- local lp_tag = P("tag()") / "(rt.tg or '')"
- local lp_ns = P("ns()") / "(rt.ns or '')"
+ local lp_name = P("name()") / "(ns~='' and ns..':'..tg)" -- "((rt.ns~='' and rt.ns..':'..rt.tg) or '')"
+ local lp_tag = P("tag()") / "tg" -- (rt.tg or '')
+ local lp_ns = P("ns()") / "ns" -- (rt.ns or '')
local lp_noequal = P("!=") / "~=" + P("<=") + P(">=") + P("==")
local lp_doequal = P("=") / "=="
local lp_attribute = P("@") / "" * Cc("(at['") * R("az","AZ","--","__")^1 * Cc("'] or '')")
- local lp_function = C(R("az","AZ","--","__")^1) * P("(") / function(t)
- if functions[t] then
- return "functions." .. t .. "("
+ local lp_lua_function = C(R("az","AZ","--","__")^1 * (P(".") * R("az","AZ","--","__")^1)^1) * P("(") / function(t) -- todo: better . handling
+ return t .. "("
+ end
+
+ local lp_function = C(R("az","AZ","--","__")^1) * P("(") / function(t) -- todo: better . handling
+ if expressions[t] then
+ return "expressions." .. t .. "("
else
- return "functions.error("
+ return "expressions.error("
end
end
@@ -2988,34 +3082,45 @@ do
local rparent = lpeg.P(")")
local noparent = 1 - (lparent+rparent)
local nested = lpeg.P{lparent * (noparent + lpeg.V(1))^0 * rparent}
- local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent)
+ local value = lpeg.P(lparent * lpeg.C((noparent + nested)^0) * rparent) -- lpeg.P{"("*C(((1-S("()"))+V(1))^0)*")"}
---~ local value = P { "(" * C(((1 - S("()")) + V(1))^0) * ")" }
+ -- if we use a dedicated namespace then we don't need to pass rt and k
local lp_special = (C(P("name")+P("text")+P("tag"))) * value / function(t,s)
- if functions[t] then
+ if expressions[t] then
if s then
- return "functions." .. t .. "(rt,k," .. s ..")"
+ return "expressions." .. t .. "(r,k," .. s ..")"
else
- return "functions." .. t .. "(rt,k)"
+ return "expressions." .. t .. "(r,k)"
end
else
- return "functions.error(" .. t .. ")"
+ return "expressions.error(" .. t .. ")"
end
end
local converter = lpeg.Cs ( (
lp_position +
+ lp_index +
lp_text + lp_name + -- fast one
lp_special +
lp_noequal + lp_doequal +
lp_attribute +
+ lp_lua_function +
lp_function +
1 )^1 )
+ -- expressions,root,rootdt,k,e,edt,ns,tg,idx,hsh[tg] or 1
+
+ local template = [[
+ return function(expressions,r,d,k,e,dt,ns,tg,id,ps)
+ local at, tx = e.at or { }, dt[1] or ""
+ return %s
+ end
+ ]]
+
local function make_expression(str)
str = converter:match(str)
- return str, loadstring(format("return function(functions,id,at,tx,rt,k) return %s end", str))()
+ return str, loadstring(format(template,str))()
end
local map = { }
@@ -3125,7 +3230,7 @@ do
local selector = (
instruction +
- many + any +
+--~ many + any + -- brrr, not here !
parent + stay +
dont_position + position +
dont_match_one_of_and_eq + dont_match_one_of_and_ne +
@@ -3137,6 +3242,7 @@ do
has_attribute + has_value +
dont_match_one_of + match_one_of +
dont_match + match +
+ many + any +
crap + empty
)
@@ -3173,7 +3279,7 @@ do
return { map[2] }
end
if m ~= 11 and m ~= 12 and m ~= 13 and m ~= 14 and m ~= 15 and m ~= 16 then
- table.insert(map, 1, { 16 })
+ insert(map, 1, { 16 })
end
-- print((table.serialize(map)):gsub("[ \n]+"," "))
return map
@@ -3184,11 +3290,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 +3307,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)
@@ -3266,22 +3378,25 @@ functions.</p>
do
- local functions = xml.functions
+ local functions = xml.functions
+ local expressions = xml.expressions
- functions.contains = string.find
- functions.find = string.find
- functions.upper = string.upper
- functions.lower = string.lower
- functions.number = tonumber
- functions.boolean = toboolean
+ expressions.contains = string.find
+ expressions.find = string.find
+ expressions.upper = string.upper
+ expressions.lower = string.lower
+ expressions.number = tonumber
+ expressions.boolean = toboolean
- functions.oneof = function(s,...) -- slow
+ expressions.oneof = function(s,...) -- slow
local t = {...} for i=1,#t do if s == t[i] then return true end end return false
end
- functions.error = function(str)
- xml.error_handler("unknown function in lpath expression",str)
+
+ expressions.error = function(str)
+ xml.error_handler("unknown function in lpath expression",str or "?")
return false
end
+
functions.text = function(root,k,n) -- unchecked, maybe one deeper
local t = type(t)
if t == "string" then
@@ -3291,35 +3406,21 @@ 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 +3428,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
@@ -3347,11 +3447,51 @@ do
else
return tg
end
- else
- return ""
+ else
+ 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
+ expressions.text = functions.text
+ expressions.name = functions.name
+ expressions.tag = functions.tag
+
local function traverse(root,pattern,handle,reverse,index,parent,wildcard) -- multiple only for tags, not for namespaces
if not root then -- error
return false
@@ -3424,10 +3564,13 @@ do
start, stop, step = stop, start, -1
end
local idx = 0
+ local hsh = { } -- this will slooow down the lot
for k=start,stop,step do -- we used to have functions for all but a case is faster
local e = rootdt[k]
local ns, tg = e.rn or e.ns, e.tg
if tg then
+ -- we can optimize this for simple searches, but it probably does not pay off
+ hsh[tg] = (hsh[tg] or 0) + 1
idx = idx + 1
if command == 30 then
local ns_a, tg_a = action[3], action[4]
@@ -3550,7 +3693,7 @@ do
end
if not action[2] then matched = not matched end
if matched then
- matched = action[6](functions,idx,e.at or { },edt[1],rootdt,k)
+ matched = action[6](expressions,root,rootdt,k,e,edt,ns,tg,idx,hsh[tg] or 1)
end
end
if matched then -- combine tg test and at test
@@ -4025,10 +4168,10 @@ do
local r, d, k, element = m[1], m[2], m[3], m[4]
if not before then k = k + 1 end
if element.tg then
- table.insert(d,k,element) -- untested
+ insert(d,k,element) -- untested
elseif element.dt then
for _,v in ipairs(element.dt) do -- i added
- table.insert(d,k,v)
+ insert(d,k,v)
k = k + 1
end
end
@@ -4116,15 +4259,27 @@ do
xml.each_element(xmldata, pattern, include)
end
- function xml.strip_whitespace(root, pattern)
+ function xml.strip_whitespace(root, pattern, nolines) -- strips all leading and trailing space !
traverse(root, lpath(pattern), function(r,d,k)
local dkdt = d[k].dt
if dkdt then -- can be optimized
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
+
+ if str == "" then
+ -- stripped
+ else
+ if nolines then
+ str = str:gsub("[ \n\r\t]+"," ")
+ end
+ if str == "" then
+ -- stripped
+ else
+ t[#t+1] = str
+ end
+ end
else
t[#t+1] = str
end
@@ -4326,9 +4481,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 +4493,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 +4514,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 +4580,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,11 +4665,20 @@ 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
+ utils.report("reading merge from %s",name)
data = f:read("*all")
f:close()
+ else
+ utils.report("unknown file to merge %s",name)
+ end
+ if data and utils.merger.strip_comment then
+ -- saves some 20K
+ data = data:gsub("%-%-~[^\n\r]*[\r\n]", "")
end
return data or ""
end
@@ -4518,6 +4687,7 @@ function utils.merger._self_save_(name,
if data ~= "" then
local f = io.open(name,'w')
if f then
+ utils.report("saving merge from %s",name)
f:write(data)
f:close()
end
@@ -4543,13 +4713,13 @@ function utils.merger._self_libs_(libs,l
local name = string.gsub(pth .. "/" .. lib,"\\","/")
f = io.open(name)
if f then
- -- utils.report("merging library",name)
+ utils.report("merging library %s",name)
result[#result+1] = f:read("*all")
f:close()
list = { pth } -- speed up the search
break
else
- -- utils.report("no library",name)
+ utils.report("no library %s",name)
end
end
end
@@ -4588,108 +4758,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
@@ -4710,19 +4834,21 @@ function environment.setargument(name,va
environment.arguments[name] = value
end
-function environment.argument(name)
- if environment.arguments[name] then
- return environment.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)
+function environment.argument(name) -- todo: default (plus typecheck on default)
+ local arguments, sortedflags = environment.arguments, environment.sortedflags
+ if arguments[name] then
+ return arguments[name]
+ else
+ 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
@@ -4743,48 +4869,106 @@ function environment.split_arguments(sep
return before, after
end
-function environment.reconstruct_commandline(arg)
+--~ function environment.reconstruct_commandline(arg)
+--~ if not arg then arg = environment.original_arguments end
+--~ local result = { }
+--~ for _,a in ipairs(arg) do -- ipairs 1 .. #n
+--~ local kk, vv = a:match("^(%-+.-)=(.+)$")
+--~ if kk and vv then
+--~ if vv:find(" ") then
+--~ vv = vv:unquote()
+--~ vv = vv:gsub('"','\\"')
+--~ result[#result+1] = kk .. "=" .. vv:quote()
+--~ else
+--~ a = a:unquote()
+--~ a = a:gsub('"','\\"')
+--~ result[#result+1] = a
+--~ end
+--~ elseif a:find(" ") then
+--~ a = a:unquote()
+--~ a = a:gsub('"','\\"')
+--~ result[#result+1] = a:quote()
+--~ else
+--~ result[#result+1] = a
+--~ end
+--~ end
+--~ return table.join(result," ")
+--~ end
+
+function environment.reconstruct_commandline(arg,noquote)
if not arg then arg = environment.original_arguments end
- local result = { }
- for _,a in ipairs(arg) do -- ipairs 1 .. #n
- local kk, vv = a:match("^(%-+.-)=(.+)$")
- if kk and vv then
- if vv:find(" ") then
- result[#result+1] = kk .. "=" .. string.quote(vv)
+ if noquote and #arg == 1 then
+ local a = arg[1]
+ a = input.resolve(a)
+ a = a:unquote()
+ return a
+ elseif #arg == 1 then
+ local result = { }
+ for _,a in ipairs(arg) do -- ipairs 1 .. #n
+ a = input.resolve(a)
+ a = a:unquote()
+ a = a:gsub('"','\\"') -- tricky
+ if a:find(" ") then
+ result[#result+1] = a:quote()
else
result[#result+1] = a
end
- elseif a:find(" ") then
- result[#result+1] = string.quote(a)
- else
- result[#result+1] = a
end
+ return table.join(result," ")
end
- return table.join(result," ")
end
if arg then
- environment.initialize_arguments(arg)
- environment.original_arguments = arg
+
+ -- new, reconstruct quoted snippets (maybe better just remnove the " then and add them later)
+ local newarg, instring = { }, false
+
+ for index, argument in ipairs(arg) do
+ if argument:find("^\"") then
+ newarg[#newarg+1] = argument:gsub("^\"","")
+ if not argument:find("\"$") then
+ instring = true
+ end
+ elseif argument:find("\"$") then
+ newarg[#newarg] = newarg[#newarg] .. " " .. argument:gsub("\"$","")
+ instring = false
+ elseif instring then
+ newarg[#newarg] = newarg[#newarg] .. " " .. argument
+ else
+ newarg[#newarg+1] = argument
+ end
+ end
+ for i=1,-5,-1 do
+ newarg[i] = arg[i]
+ end
+
+ environment.initialize_arguments(newarg)
+ environment.original_arguments = newarg
+ environment.raw_arguments = arg
+
arg = { } -- prevent duplicate handling
-end
+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 +4978,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
@@ -4812,7 +4990,7 @@ if not input.hashers then input.hashe
if not input.generators then input.generators = { } end -- generate databases
if not input.filters then input.filters = { } end -- conversion filters
-local format = string.format
+local format, concat, sortedkeys = string.format, table.concat, table.sortedkeys
input.locators.notfound = { nil }
input.hashers.notfound = { nil }
@@ -4825,8 +5003,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 +5048,8 @@ input.suffixes['lua'] = { 'lua', 'luc',
-- 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 +5058,15 @@ function input.checkconfigdata(instance)
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 +5093,20 @@ input.formats ['sfd']
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 +5130,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 +5146,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 +5166,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 +5230,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 +5246,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 +5275,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 +5389,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 +5421,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 +5443,22 @@ function input.aux.collapse_cnf_data(ins
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 +5490,226 @@ function input.aux.load_cnf(instance,fna
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 .. "}"
+ -- weird
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'] .. "}"
- 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)
-end
-
-do
-
- 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.generatedatabase(specification)
+ return input.methodhandler('generators', specification)
+end
+
+local weird = lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+
+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 +5717,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 +5729,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 +5754,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 +5765,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 = [[
@@ -5602,8 +5794,6 @@ function input.serialize(files)
-- luatools and mtxtools are called frequently. Okay,
-- we pay a small price for properly tabbed tables.
local t = { }
- local concat = table.concat
- local sorted = table.sortedkeys
local function dump(k,v,m)
if type(v) == 'string' then
return m .. "['" .. k .. "']='" .. v .. "',"
@@ -5614,12 +5804,12 @@ function input.serialize(files)
end
end
t[#t+1] = "return {"
- if instance.sortdata then
- for _, k in pairs(sorted(files)) do
+ if input.instance.sortdata then
+ for _, k in pairs(sortedkeys(files)) do
local fk = files[k]
if type(fk) == 'table' then
t[#t+1] = "\t['" .. k .. "']={"
- for _, kk in pairs(sorted(fk)) do
+ for _, kk in pairs(sortedkeys(fk)) do
t[#t+1] = dump(kk,fk[kk],"\t\t")
end
t[#t+1] = "\t},"
@@ -5646,11 +5836,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 +5858,38 @@ function input.aux.save_data(instance, d
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 +5902,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,172 +5929,168 @@ function input.aux.load_texmfcnf(instanc
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
- local homedir =
- instance.environment[(os.type == "windows" and 'USERPROFILE') or 'HOME'] or '~'
- for k,v in pairs(instance.expansions) do
- v = v:gsub("^~", homedir)
- 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 = { }, { }
@@ -5913,7 +6100,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
@@ -5958,7 +6146,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
@@ -5999,39 +6188,41 @@ function input.expanded_path_list(instan
-- 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)
@@ -6061,9 +6252,9 @@ function input.var_of_format_or_suffix(s
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
@@ -6078,6 +6269,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
@@ -6086,19 +6278,19 @@ 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)
@@ -6106,9 +6298,9 @@ function input.aux.splitpathexpr(str, t,
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)
@@ -6116,50 +6308,41 @@ function input.aux.splitpathexpr(str, t,
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
@@ -6191,17 +6374,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
@@ -6209,12 +6391,13 @@ input.is_readable.tex = input.is_readabl
-- 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)
@@ -6228,7 +6411,7 @@ function input.aux.collect_files(instanc
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
@@ -6261,7 +6444,7 @@ function input.aux.collect_files(instanc
end
end
elseif input.trace > 1 then
- input.logger('! blobpath no',blobpath .. " (" .. bname ..")" )
+ input.logger('! blobpath no: %s (%s)',blobpath,bname)
end
end
end
@@ -6316,15 +6499,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
@@ -6333,16 +6518,22 @@ function input.aux.find_file(instance,fi
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
@@ -6350,22 +6541,26 @@ function input.aux.find_file(instance,fi
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
@@ -6383,10 +6578,14 @@ function input.aux.find_file(instance,fi
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
@@ -6395,16 +6594,18 @@ function input.aux.find_file(instance,fi
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',concat(wantedfiles," | "))
end
for _, fname in pairs(wantedfiles) do
if fname and input.is_readable.file(fname) then
@@ -6414,7 +6615,7 @@ function input.aux.find_file(instance,fi
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]
@@ -6423,12 +6624,12 @@ function input.aux.find_file(instance,fi
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',concat(pathlist," | ")) end
+ -- if filelist then input.logger('? file list: %s',concat(filelist," | ")) end
end
-- a bit messy ... esp the doscan setting here
for _, path in pairs(pathlist) do
@@ -6449,11 +6650,11 @@ function input.aux.find_file(instance,fi
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
@@ -6467,12 +6668,12 @@ function input.aux.find_file(instance,fi
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
@@ -6501,40 +6702,29 @@ function input.aux.find_file(instance,fi
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
@@ -6542,7 +6732,8 @@ if not input.concatinators then input.c
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
@@ -6551,16 +6742,17 @@ function input.find_files(instance,filen
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]
@@ -6588,11 +6780,12 @@ function input.find_given_files(instance
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,16 +6838,19 @@ function input.find_wildcard_files(insta
if done and not allresults then break end
end
end
+ -- we can consider also searching the paths not in the database, but then
+ -- we end up with a messy search (all // in all path specs)
return result
end
-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
@@ -6664,7 +6860,7 @@ function input.save_used_files_in_trees(
f:write("\t<rl:name>" .. jobname .. "</rl:name>\n")
end
f:write("\t<rl:files>\n")
- for _,v in pairs(table.sortedkeys(instance.foundintrees)) do
+ for _,v in pairs(sorted(instance.foundintrees)) do -- ipairs
f:write("\t\t<rl:file n='" .. instance.foundintrees[v] .. "'>" .. v .. "</rl:file>\n")
end
f:write("\t</rl:files>\n")
@@ -6673,24 +6869,24 @@ function input.save_used_files_in_trees(
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
@@ -6703,7 +6899,7 @@ function input.for_files(instance, comma
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
@@ -6717,14 +6913,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,56 +6966,58 @@ function table.sequenced(t,sep) -- temp
for k, v in pairs(t) do
s[#s+1] = k .. "=" .. v
end
- return table.concat(s, sep or " | ")
+ return concat(s, sep or " | ")
end
-function input.methodhandler(what, 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
@@ -6868,16 +7063,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
@@ -6886,7 +7083,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
@@ -6913,37 +7111,22 @@ function input.with_files(instance,patte
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
@@ -6971,10 +7154,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
@@ -6992,16 +7175,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
@@ -7013,15 +7196,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
@@ -7030,10 +7213,185 @@ 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(str)
+ 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
+
+input.moreinfo = [[
+more information about ConTeXt and the tools that come with it can be found at:
+
+maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
+wiki : http://contextgarden.net
+]]
+
+function input.help(banner,message)
+ if not input.verbose then
+ input.verbose = true
+ -- input.report(banner,"\n")
+ end
+ input.report(banner,"\n")
+ input.report("")
+ input.reportlines(message)
+ if input.moreinfo and input.moreinfo ~= "" then
+ input.report("")
+ input.reportlines(input.moreinfo)
+ end
+end
+
+logs.set_level('error')
+logs.set_method('tex')
+
if not modules then modules = { } end modules ['luat-tmp'] = {
version = 1.001,
@@ -7059,63 +7417,82 @@ being written at the same time is small.
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])
- 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
+ check(input.clean_path_list("TEXMFCACHE") or { })
+ check(caches.defaults,true)
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
@@ -7123,14 +7500,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
@@ -7150,9 +7527,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
@@ -7175,26 +7552,28 @@ function caches.is_writable(filepath,fil
return file.is_writable(tmaname)
end
-function caches.savedata(filepath,filename,data,raw) -- raw needed for file cache
+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--
@@ -7217,7 +7596,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
@@ -7242,7 +7621,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
@@ -7307,13 +7686,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)
@@ -7321,12 +7703,11 @@ function input.aux.save_data(instance, d
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
@@ -7341,13 +7722,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
@@ -7356,16 +7737,16 @@ function input.automount(instance,usecac
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
@@ -7376,7 +7757,7 @@ input.storage.data = { }
input.storage.min = 0 -- 500
input.storage.max = input.storage.min - 1
input.storage.trace = false -- true
-input.storage.done = 0
+input.storage.done = input.storage.done or 0
input.storage.evaluators = { }
-- (evaluate,message,names)
@@ -7414,17 +7795,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
@@ -7434,6 +7815,8 @@ function input.storage.dump()
end
end
+-- we also need to count at generation time (nicer for message)
+
if lua.bytecode then -- from 0 upwards
local i = input.storage.min
while lua.bytecode[i] do
@@ -7460,6 +7843,11 @@ provide an <l n='xml'/> structured file.
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 { }
@@ -7475,8 +7863,7 @@ logs.levels = {
}
logs.functions = {
- 'error', 'warning', 'info', 'debug', 'report',
- 'start', 'stop', 'push', 'pop'
+ 'report', 'start', 'stop', 'push', 'pop', 'line', 'direct'
}
logs.callbacks = {
@@ -7486,89 +7873,112 @@ 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
+input.moreinfo = [[
+more information about ConTeXt and the tools that come with it can be found at:
+
+maillist : ntg-context@ntg.nl / http://www.ntg.nl/mailman/listinfo/ntg-context
+webpage : http://www.pragma-ade.nl / http://tex.aanhet.net
+wiki : http://contextgarden.net
+]]
+
+function input.help(banner,message)
+ if not input.verbose then
+ input.verbose = true
+ -- input.report(banner,"\n")
+ end
+ input.report(banner,"\n")
+ input.report("")
+ input.reportlines(message)
+ if input.moreinfo and input.moreinfo ~= "" then
+ input.report("")
+ input.reportlines(input.moreinfo)
+ end
end
logs.set_level('error')
@@ -7761,7 +8171,7 @@ end
-- end library merge
-own = { }
+own = { } -- not local
own.libs = { -- todo: check which ones are really needed
'l-string.lua',
@@ -7775,12 +8185,14 @@ own.libs = { -- todo: check which ones a
'l-file.lua',
'l-dir.lua',
'l-boolean.lua',
+ 'l-math.lua',
'l-xml.lua',
-- 'l-unicode.lua',
'l-utils.lua',
-- 'l-tex.lua',
'luat-lib.lua',
'luat-inp.lua',
+ 'luat-log.lua',
-- 'luat-zip.lua',
-- 'luat-tex.lua',
-- 'luat-kps.lua',
@@ -7810,7 +8222,7 @@ table.insert(own.list,own.path.."/../../
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,"\\","/")
@@ -7837,37 +8249,14 @@ if not input then
os.exit()
end
-instance = input.reset()
-input.verbose = environment.argument("verbose") or false
-input.banner = 'MtxRun | '
+input.instance = input.reset()
+input.banner = 'MtxRun'
utils.report = input.report
-instance.engine = environment.argument("engine") or 'luatex'
-instance.progname = environment.argument("progname") or 'context'
-instance.lsrmode = environment.argument("lsr") or false
+local instance = input.instance
--- 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
+-- use os.env or environment when available
function input.check_environment(tree)
input.report('')
@@ -7876,10 +8265,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
@@ -7968,9 +8357,9 @@ function file.needs_updating(oldname,new
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
@@ -7979,24 +8368,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
@@ -8014,6 +8397,8 @@ function os.currentplatform(name, defaul
local architecture = os.arch()
if architecture:find("x86_64") then
return "linux-64"
+ elseif architecture:find("ppc") then
+ return "linux-ppc"
else
return "linux"
end
@@ -8055,7 +8440,7 @@ input.runners.registered = {
mptopdf = { 'mptopdf.pl', true },
pstopdf = { 'pstopdf.rb', true },
- examplex = { 'examplex.rb', false },
+-- examplex = { 'examplex.rb', false },
concheck = { 'concheck.rb', false },
runtools = { 'runtools.rb', true },
@@ -8076,8 +8461,8 @@ input.runners.registered = {
if not messages then messages = { } end
messages.help = [[
---script run an mtx script
---execute run a script or program
+--script run an mtx script (--noquotes)
+--execute run a script or program (--noquotes)
--resolve resolve prefixed arguments
--ctxlua run internally (using preloaded libs)
--locate locate given filename
@@ -8100,46 +8485,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)
-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_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()
+ 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 ""
@@ -8158,15 +8543,17 @@ 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
+ local noquote = environment.argument("noquotes")
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
@@ -8190,16 +8577,16 @@ function input.runners.execute_script(in
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
@@ -8213,9 +8600,9 @@ function input.runners.execute_script(in
result = binary .. " " .. result
end
local before, after = environment.split_arguments(fullname)
- local command = result .. " " .. environment.reconstruct_commandline(after)
+ local command = result .. " " .. environment.reconstruct_commandline(after,noquote)
input.report("")
- input.report("executing: " .. command)
+ input.report("executing: %s",command)
input.report("\n \n")
io.flush()
local code = os.exec(command) -- maybe spawn
@@ -8227,9 +8614,10 @@ function input.runners.execute_script(in
return false
end
-function input.runners.execute_program(instance,fullname)
+function input.runners.execute_program(fullname)
+ local noquote = environment.argument("noquotes")
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
@@ -8238,9 +8626,9 @@ function input.runners.execute_program(i
local before, after = environment.split_arguments(fullname)
environment.initialize_arguments(after)
fullname = fullname:gsub("^bin:","")
- local command = fullname .. " " .. environment.reconstruct_commandline(after)
+ local command = fullname .. " " .. (environment.reconstruct_commandline(after or "",noquote) or "")
input.report("")
- input.report("executing: " .. 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
@@ -8250,12 +8638,12 @@ function input.runners.execute_program(i
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
@@ -8270,41 +8658,41 @@ function input.runners.handle_stubs(inst
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
@@ -8317,11 +8705,17 @@ function input.runners.report_location(i
end
end
-function input.runners.edit_script(instance,filename)
- local editor = os.getenv("MTXRUN_EDITOR") or os.getenv("TEXMFSTART_EDITOR") or os.getenv("EDITOR") or 'scite'
- local rest = input.resolve(instance,filename)
+function input.runners.edit_script(filename) -- we assume that vim is present on most systems
+ local editor = os.getenv("MTXRUN_EDITOR") or os.getenv("TEXMFSTART_EDITOR") or os.getenv("EDITOR") or 'vim'
+ local rest = input.resolve(filename)
if rest ~= "" then
- os.launch(editor .. " " .. rest)
+ local command = editor .. " " .. rest
+ if input.verbose then
+ input.report("")
+ input.report("starting editor: %s",command)
+ input.report("\n \n")
+ end
+ os.launch(command)
end
end
@@ -8364,7 +8758,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"]
@@ -8374,25 +8769,30 @@ function input.runners.launch_file(insta
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.find_mtx_script(filename)
local function found(name)
local path = file.dirname(name)
if path and path ~= "" then
@@ -8402,30 +8802,48 @@ function input.runners.execute_ctx_scrip
return io.exists(fullname) and fullname
end
end
- local suffix = ""
- if not filename:find("%.lua$") then suffix = ".lua" end
- local fullname = filename
- -- just <filename>
- fullname = filename .. suffix
- fullname = input.find_file(instance,fullname)
- -- mtx-<filename>
- if not fullname or fullname == "" then
- fullname = "mtx-" .. filename .. suffix
- fullname = found(fullname) or input.find_file(instance,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)
- 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)
+ filename = file.addsuffix(filename,"lua")
+ local basename = file.stripsuffix(file.basename(filename))
+ local suffix = file.extname(filename)
+ -- qualified path, raw name
+ local fullname = input.aux.qualified_path(filename) and io.exists(filename) and filename
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- current path, raw name
+ fullname = "./" .. filename
+ fullname = io.exists(fullname) and fullname
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>
+ fullname = "mtx-" .. filename
+ fullname = found(fullname) or input.find_file(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename>s
+ fullname = "mtx-" .. basename .. "s" .. "." .. suffix
+ fullname = found(fullname) or input.find_file(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
+ end
+ -- context namespace, mtx-<filename minus trailing s>
+ fullname = "mtx-" .. basename:gsub("s$","") .. "." .. suffix
+ fullname = found(fullname) or input.find_file(fullname)
+ if fullname and fullname ~= "" then
+ return fullname
end
+ -- context namespace, just <filename>
+ fullname = input.find_file(fullname)
+ return fullname
+end
+
+function input.runners.execute_ctx_script(filename,arguments)
+ local fullname = input.runners.find_mtx_script(filename)
-- that should do it
if fullname and fullname ~= "" then
- local state = input.runners.prepare(instance)
+ local state = input.runners.prepare()
if state == 'error' then
return false
elseif state == 'skip' then
@@ -8442,7 +8860,7 @@ function input.runners.execute_ctx_scrip
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']
@@ -8455,20 +8873,19 @@ function input.runners.execute_ctx_scrip
end
else
input.verbose = true
- input.report("unknown script: " .. filename)
+ filename = file.addsuffix(filename,"lua")
+ if filename == "" then
+ input.report("unknown script, no name given")
+ elseif input.aux.qualified_path(filename) then
+ input.report("unknown script '%s'",filename)
+ else
+ input.report("unknown script '%s' or 'mtx-%s'",filename,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
@@ -8478,12 +8895,14 @@ local filename = environment.files[1] or
local ok = true
local before, after = environment.split_arguments(filename)
+environment.initialize_arguments(before)
-input.runners.my_prepare_b(instance)
-before = input.resolve(instance,before) -- experimental here
-after = input.resolve(instance,after) -- experimental here
+instance.engine = environment.argument("engine") or 'luatex'
+instance.progname = environment.argument("progname") or 'context'
+instance.lsrmode = environment.argument("lsr") or false
+input.verbose = environment.argument("verbose") or false
-environment.initialize_arguments(before)
+input.runners.my_prepare_b()
if environment.argument("selfmerge") then
-- embed used libraries
@@ -8493,60 +8912,52 @@ elseif environment.argument("selfclean")
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)
- else
- ok = input.runners.execute_script(instance,filename)
- end
+elseif filename:find("^bin:") then
+ ok = input.runners.execute_program(filename)
+else
+ ok = input.runners.execute_script(filename)
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)
--- texmf-dist/tex/context/base/luat-inp.lua
+++ texmf-dist/tex/context/base/luat-inp.lua 2008-10-30 14:05:43.990092457 +0100
@@ -1,18 +1,21 @@
--- 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
@@ -22,12 +25,6 @@
-- 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
@@ -40,7 +37,7 @@ if not input.hashers then input.hashe
if not input.generators then input.generators = { } end -- generate databases
if not input.filters then input.filters = { } end -- conversion filters
-local format = string.format
+local format, concat, sortedkeys = string.format, table.concat, table.sortedkeys
input.locators.notfound = { nil }
input.hashers.notfound = { nil }
@@ -53,8 +50,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
@@ -90,7 +95,8 @@ input.suffixes['lua'] = { 'lua', 'luc',
-- 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]
@@ -99,7 +105,15 @@ function input.checkconfigdata(instance)
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
@@ -126,14 +140,20 @@ input.formats ['sfd']
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 = { }
@@ -157,6 +177,7 @@ function input.reset()
instance.cachepath = nil
instance.loaderror = false
instance.smallcache = false
+ instance.sortdata = false
instance.savelists = true
instance.cleanuppaths = true
instance.allresults = false
@@ -172,23 +193,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
@@ -202,68 +213,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))
@@ -274,27 +259,44 @@ input.settrace(tonumber(os.getenv("MTX.I
do
local clock = os.gettimeofday or os.clock
+ function input.hastimer(instance)
+ return instance and instance.starttime
+ end
+
function input.starttiming(instance)
if instance then
- instance.starttime = clock()
- if not instance.loadtime then
- instance.loadtime = 0
+ local it = instance.timing
+ if not it then
+ it = 0
+ end
+ if it == 0 then
+ instance.starttime = clock()
+ if not instance.loadtime then
+ instance.loadtime = 0
+ end
end
+ instance.timing = it + 1
end
end
function input.stoptiming(instance, report)
if instance then
- local starttime = instance.starttime
- if starttime then
- local stoptime = clock()
- local loadtime = stoptime - starttime
- instance.stoptime = stoptime
- instance.loadtime = instance.loadtime + loadtime
- if report then
- input.report('load time', format("%0.3f",loadtime))
+ local it = instance.timing
+ if it > 1 then
+ instance.timing = it - 1
+ else
+ local starttime = instance.starttime
+ if starttime then
+ local stoptime = clock()
+ local loadtime = stoptime - starttime
+ instance.stoptime = stoptime
+ instance.loadtime = instance.loadtime + loadtime
+ if report then
+ input.report("load time %0.3f",loadtime)
+ end
+ instance.timing = 0
+ return loadtime
end
- return loadtime
end
end
return 0
@@ -308,18 +310,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)
@@ -337,81 +339,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()
- 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()
+ break
+ end
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 !
@@ -426,27 +453,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
@@ -458,14 +485,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
@@ -480,21 +507,22 @@ function input.aux.collapse_cnf_data(ins
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
@@ -526,227 +554,226 @@ function input.aux.load_cnf(instance,fna
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)
-end
-
-do
-
- 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.generatedatabase(specification)
+ return input.methodhandler('generators', specification)
+end
+
+local weird = lpeg.anywhere(lpeg.S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+
+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
@@ -754,8 +781,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)
@@ -766,8 +793,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)
@@ -790,8 +818,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
@@ -800,19 +829,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 = [[
@@ -829,8 +858,6 @@ function input.serialize(files)
-- luatools and mtxtools are called frequently. Okay,
-- we pay a small price for properly tabbed tables.
local t = { }
- local concat = table.concat
- local sorted = table.sortedkeys
local function dump(k,v,m)
if type(v) == 'string' then
return m .. "['" .. k .. "']='" .. v .. "',"
@@ -841,12 +868,12 @@ function input.serialize(files)
end
end
t[#t+1] = "return {"
- if instance.sortdata then
- for _, k in pairs(sorted(files)) do
+ if input.instance.sortdata then
+ for _, k in pairs(sortedkeys(files)) do
local fk = files[k]
if type(fk) == 'table' then
t[#t+1] = "\t['" .. k .. "']={"
- for _, kk in pairs(sorted(fk)) do
+ for _, kk in pairs(sortedkeys(fk)) do
t[#t+1] = dump(kk,fk[kk],"\t\t")
end
t[#t+1] = "\t},"
@@ -873,11 +900,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
@@ -895,38 +922,38 @@ function input.aux.save_data(instance, d
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
@@ -939,13 +966,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 = { }
@@ -965,172 +993,168 @@ function input.aux.load_texmfcnf(instanc
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
- local homedir =
- instance.environment[(os.type == "windows" and 'USERPROFILE') or 'HOME'] or '~'
- for k,v in pairs(instance.expansions) do
- v = v:gsub("^~", homedir)
- 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 = { }, { }
@@ -1140,7 +1164,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
@@ -1185,7 +1210,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
@@ -1226,39 +1252,41 @@ function input.expanded_path_list(instan
-- 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)
@@ -1288,9 +1316,9 @@ function input.var_of_format_or_suffix(s
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
@@ -1305,6 +1333,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
@@ -1313,19 +1342,19 @@ 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)
@@ -1333,9 +1362,9 @@ function input.aux.splitpathexpr(str, t,
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)
@@ -1343,50 +1372,41 @@ function input.aux.splitpathexpr(str, t,
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
@@ -1418,17 +1438,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
@@ -1436,12 +1455,13 @@ input.is_readable.tex = input.is_readabl
-- 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)
@@ -1455,7 +1475,7 @@ function input.aux.collect_files(instanc
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
@@ -1488,7 +1508,7 @@ function input.aux.collect_files(instanc
end
end
elseif input.trace > 1 then
- input.logger('! blobpath no',blobpath .. " (" .. bname ..")" )
+ input.logger('! blobpath no: %s (%s)',blobpath,bname)
end
end
end
@@ -1543,15 +1563,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
@@ -1560,16 +1582,22 @@ function input.aux.find_file(instance,fi
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
@@ -1577,22 +1605,26 @@ function input.aux.find_file(instance,fi
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
@@ -1610,10 +1642,14 @@ function input.aux.find_file(instance,fi
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
@@ -1622,16 +1658,18 @@ function input.aux.find_file(instance,fi
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',concat(wantedfiles," | "))
end
for _, fname in pairs(wantedfiles) do
if fname and input.is_readable.file(fname) then
@@ -1641,7 +1679,7 @@ function input.aux.find_file(instance,fi
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]
@@ -1650,12 +1688,12 @@ function input.aux.find_file(instance,fi
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',concat(pathlist," | ")) end
+ -- if filelist then input.logger('? file list: %s',concat(filelist," | ")) end
end
-- a bit messy ... esp the doscan setting here
for _, path in pairs(pathlist) do
@@ -1676,11 +1714,11 @@ function input.aux.find_file(instance,fi
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
@@ -1694,12 +1732,12 @@ function input.aux.find_file(instance,fi
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
@@ -1728,40 +1766,29 @@ function input.aux.find_file(instance,fi
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
@@ -1769,7 +1796,8 @@ if not input.concatinators then input.c
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
@@ -1778,16 +1806,17 @@ function input.find_files(instance,filen
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]
@@ -1815,11 +1844,12 @@ function input.find_given_files(instance
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("^*/","")
@@ -1872,16 +1902,19 @@ function input.find_wildcard_files(insta
if done and not allresults then break end
end
end
+ -- we can consider also searching the paths not in the database, but then
+ -- we end up with a messy search (all // in all path specs)
return result
end
-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
@@ -1891,7 +1924,7 @@ function input.save_used_files_in_trees(
f:write("\t<rl:name>" .. jobname .. "</rl:name>\n")
end
f:write("\t<rl:files>\n")
- for _,v in pairs(table.sortedkeys(instance.foundintrees)) do
+ for _,v in pairs(sorted(instance.foundintrees)) do -- ipairs
f:write("\t\t<rl:file n='" .. instance.foundintrees[v] .. "'>" .. v .. "</rl:file>\n")
end
f:write("\t</rl:files>\n")
@@ -1900,24 +1933,24 @@ function input.save_used_files_in_trees(
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
@@ -1930,7 +1963,7 @@ function input.for_files(instance, comma
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
@@ -1944,14 +1977,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)
@@ -2000,56 +2030,58 @@ function table.sequenced(t,sep) -- temp
for k, v in pairs(t) do
s[#s+1] = k .. "=" .. v
end
- return table.concat(s, sep or " | ")
+ return concat(s, sep or " | ")
end
-function input.methodhandler(what, 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
@@ -2095,16 +2127,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
@@ -2113,7 +2147,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
@@ -2140,37 +2175,22 @@ function input.with_files(instance,patte
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
@@ -2198,10 +2218,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
@@ -2219,16 +2239,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
@@ -2240,15 +2260,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
@@ -2257,6 +2277,24 @@ 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(str)
+ if b == "" then
+ return default
+ else
+ b = toboolean(b)
+ return (b == nil and default) or b
+ end
+end