summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/scripts/context/stubs
diff options
context:
space:
mode:
authorKarl Berry <karl@freefriends.org>2015-04-18 22:52:45 +0000
committerKarl Berry <karl@freefriends.org>2015-04-18 22:52:45 +0000
commit16aa5a7c87f18a2483d0d61795899f886781b51c (patch)
tree1d72f00b2a4185425393598402fe055c61d1de58 /Master/texmf-dist/scripts/context/stubs
parente68dc4d5506d46bf72823234f902bc76d1f70352 (diff)
context, from www.pragma-ade.com/context/beta/cont-tmf.zip (18apr15)
git-svn-id: svn://tug.org/texlive/trunk@36923 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/scripts/context/stubs')
-rw-r--r--Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua3573
-rwxr-xr-xMaster/texmf-dist/scripts/context/stubs/unix/mtxrun3573
-rw-r--r--Master/texmf-dist/scripts/context/stubs/win64/mtxrun.lua3573
3 files changed, 6888 insertions, 3831 deletions
diff --git a/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua b/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua
index 5cb5c8d2416..48a9a27a250 100644
--- a/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua
+++ b/Master/texmf-dist/scripts/context/stubs/mswin/mtxrun.lua
@@ -56,7 +56,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-lua"] = package.loaded["l-lua"] or true
--- original size: 3409, stripped down to: 1763
+-- original size: 3888, stripped down to: 2197
if not modules then modules={} end modules ['l-lua']={
version=1.001,
@@ -139,6 +139,13 @@ end
if lua then
lua.mask=load([[τεχ = 1]]) and "utf" or "ascii"
end
+local flush=io.flush
+if flush then
+ local execute=os.execute if execute then function os.execute(...) flush() return execute(...) end end
+ local exec=os.exec if exec then function os.exec (...) flush() return exec (...) end end
+ local spawn=os.spawn if spawn then function os.spawn (...) flush() return spawn (...) end end
+ local popen=io.popen if popen then function io.popen (...) flush() return popen (...) end end
+end
end -- of closure
@@ -437,7 +444,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true
--- original size: 29983, stripped down to: 16202
+-- original size: 36225, stripped down to: 19891
if not modules then modules={} end modules ['l-lpeg']={
version=1.001,
@@ -498,6 +505,8 @@ patterns.utfbom_16_le=utfbom_16_le
patterns.utfbom_8=utfbom_8
patterns.utf_16_be_nl=P("\000\r\000\n")+P("\000\r")+P("\000\n")
patterns.utf_16_le_nl=P("\r\000\n\000")+P("\r\000")+P("\n\000")
+patterns.utf_32_be_nl=P("\000\000\000\r\000\000\000\n")+P("\000\000\000\r")+P("\000\000\000\n")
+patterns.utf_32_le_nl=P("\r\000\000\000\n\000\000\000")+P("\r\000\000\000")+P("\n\000\000\000")
patterns.utf8one=R("\000\127")
patterns.utf8two=R("\194\223")*utf8next
patterns.utf8three=R("\224\239")*utf8next*utf8next
@@ -527,9 +536,21 @@ patterns.nonwhitespace=nonwhitespace
local stripper=spacer^0*C((spacer^0*nonspacer^1)^0)
local fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0)
local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0))
+local b_collapser=Cs(whitespace^0/""*(nonwhitespace^1+whitespace^1/" ")^0)
+local e_collapser=Cs((whitespace^1*P(-1)/""+nonwhitespace^1+whitespace^1/" ")^0)
+local m_collapser=Cs((nonwhitespace^1+whitespace^1/" ")^0)
+local b_stripper=Cs(spacer^0/""*(nonspacer^1+spacer^1/" ")^0)
+local e_stripper=Cs((spacer^1*P(-1)/""+nonspacer^1+spacer^1/" ")^0)
+local m_stripper=Cs((nonspacer^1+spacer^1/" ")^0)
patterns.stripper=stripper
patterns.fullstripper=fullstripper
patterns.collapser=collapser
+patterns.b_collapser=b_collapser
+patterns.m_collapser=m_collapser
+patterns.e_collapser=e_collapser
+patterns.b_stripper=b_stripper
+patterns.m_stripper=m_stripper
+patterns.e_stripper=e_stripper
patterns.lowercase=lowercase
patterns.uppercase=uppercase
patterns.letter=patterns.lowercase+patterns.uppercase
@@ -566,9 +587,12 @@ patterns.integer=sign^-1*digit^1
patterns.unsigned=digit^0*period*digit^1
patterns.float=sign^-1*patterns.unsigned
patterns.cunsigned=digit^0*comma*digit^1
+patterns.cpunsigned=digit^0*(period+comma)*digit^1
patterns.cfloat=sign^-1*patterns.cunsigned
+patterns.cpfloat=sign^-1*patterns.cpunsigned
patterns.number=patterns.float+patterns.integer
patterns.cnumber=patterns.cfloat+patterns.integer
+patterns.cpnumber=patterns.cpfloat+patterns.integer
patterns.oct=zero*octdigit^1
patterns.octal=patterns.oct
patterns.HEX=zero*P("X")*(digit+uppercase)^1
@@ -985,23 +1009,40 @@ function lpeg.append(list,pp,delayed,checked)
end
return p
end
+local p_false=P(false)
+local p_true=P(true)
local function make(t)
- local p
+ local function making(t)
+ local p=p_false
+ local keys=sortedkeys(t)
+ for i=1,#keys do
+ local k=keys[i]
+ if k~="" then
+ local v=t[k]
+ if v==true then
+ p=p+P(k)*p_true
+ elseif v==false then
+ else
+ p=p+P(k)*making(v)
+ end
+ end
+ end
+ if t[""] then
+ p=p+p_true
+ end
+ return p
+ end
+ local p=p_false
local keys=sortedkeys(t)
for i=1,#keys do
local k=keys[i]
- local v=t[k]
- if not p then
- if next(v) then
- p=P(k)*make(v)
- else
- p=P(k)
- end
- else
- if next(v) then
- p=p+P(k)*make(v)
+ if k~="" then
+ local v=t[k]
+ if v==true then
+ p=p+P(k)*p_true
+ elseif v==false then
else
- p=p+P(k)
+ p=p+P(k)*making(v)
end
end
end
@@ -1009,13 +1050,73 @@ local function make(t)
end
function lpeg.utfchartabletopattern(list)
local tree={}
- for i=1,#list do
- local t=tree
- for c in gmatch(list[i],".") do
- if not t[c] then
- t[c]={}
+ local n=#list
+ if n==0 then
+ for s in next,list do
+ local t=tree
+ local p,pk
+ for c in gmatch(s,".") do
+ if t==true then
+ t={ [c]=true,[""]=true }
+ p[pk]=t
+ p=t
+ t=false
+ elseif t==false then
+ t={ [c]=false }
+ p[pk]=t
+ p=t
+ t=false
+ else
+ local tc=t[c]
+ if not tc then
+ tc=false
+ t[c]=false
+ end
+ p=t
+ t=tc
+ end
+ pk=c
+ end
+ if t==false then
+ p[pk]=true
+ elseif t==true then
+ else
+ t[""]=true
+ end
+ end
+ else
+ for i=1,n do
+ local s=list[i]
+ local t=tree
+ local p,pk
+ for c in gmatch(s,".") do
+ if t==true then
+ t={ [c]=true,[""]=true }
+ p[pk]=t
+ p=t
+ t=false
+ elseif t==false then
+ t={ [c]=false }
+ p[pk]=t
+ p=t
+ t=false
+ else
+ local tc=t[c]
+ if not tc then
+ tc=false
+ t[c]=false
+ end
+ p=t
+ t=tc
+ end
+ pk=c
+ end
+ if t==false then
+ p[pk]=true
+ elseif t==true then
+ else
+ t[""]=true
end
- t=t[c]
end
end
return make(tree)
@@ -1055,6 +1156,65 @@ local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"")
local number=digit^1*(case_1+case_2)
local stripper=Cs((number+1)^0)
lpeg.patterns.stripzeros=stripper
+local byte_to_HEX={}
+local byte_to_hex={}
+local byte_to_dec={}
+local hex_to_byte={}
+for i=0,255 do
+ local H=format("%02X",i)
+ local h=format("%02x",i)
+ local d=format("%03i",i)
+ local c=char(i)
+ byte_to_HEX[c]=H
+ byte_to_hex[c]=h
+ byte_to_dec[c]=d
+ hex_to_byte[h]=c
+ hex_to_byte[H]=c
+end
+local hextobyte=P(2)/hex_to_byte
+local bytetoHEX=P(1)/byte_to_HEX
+local bytetohex=P(1)/byte_to_hex
+local bytetodec=P(1)/byte_to_dec
+local hextobytes=Cs(hextobyte^0)
+local bytestoHEX=Cs(bytetoHEX^0)
+local bytestohex=Cs(bytetohex^0)
+local bytestodec=Cs(bytetodec^0)
+patterns.hextobyte=hextobyte
+patterns.bytetoHEX=bytetoHEX
+patterns.bytetohex=bytetohex
+patterns.bytetodec=bytetodec
+patterns.hextobytes=hextobytes
+patterns.bytestoHEX=bytestoHEX
+patterns.bytestohex=bytestohex
+patterns.bytestodec=bytestodec
+function string.toHEX(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(bytestoHEX,s)
+ end
+end
+function string.tohex(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(bytestohex,s)
+ end
+end
+function string.todec(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(bytestodec,s)
+ end
+end
+function string.tobytes(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(hextobytes,s)
+ end
+end
end -- of closure
@@ -1082,7 +1242,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-string"] = package.loaded["l-string"] or true
--- original size: 5671, stripped down to: 2827
+-- original size: 5694, stripped down to: 2827
if not modules then modules={} end modules ['l-string']={
version=1.001,
@@ -1187,7 +1347,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-table"] = package.loaded["l-table"] or true
--- original size: 31860, stripped down to: 20846
+-- original size: 33830, stripped down to: 21894
if not modules then modules={} end modules ['l-table']={
version=1.001,
@@ -1230,11 +1390,12 @@ function table.keys(t)
end
end
local function compare(a,b)
- local ta,tb=type(a),type(b)
- if ta==tb then
+ local ta=type(a)
+ local tb=type(b)
+ if ta==tb and ta=="number" then
return a<b
else
- return tostring(a)<tostring(b)
+ return tostring(a)<tostring(b)
end
end
local function sortedkeys(tab)
@@ -1334,14 +1495,14 @@ local function sortedhash(t,cmp)
end
local n=0
local m=#s
- local function kv(s)
+ local function kv()
if n<m then
n=n+1
local k=s[n]
return k,t[k]
end
end
- return kv,s
+ return kv
else
return nothing
end
@@ -1506,7 +1667,7 @@ local function simple_table(t)
if tv=="number" then
nt=nt+1
if hexify then
- tt[nt]=format("0x%04X",v)
+ tt[nt]=format("0x%X",v)
else
tt[nt]=tostring(v)
end
@@ -1537,7 +1698,7 @@ local function do_serialize(root,name,depth,level,indexed)
local tn=type(name)
if tn=="number" then
if hexify then
- handle(format("%s[0x%04X]={",depth,name))
+ handle(format("%s[0x%X]={",depth,name))
else
handle(format("%s[%s]={",depth,name))
end
@@ -1554,7 +1715,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
end
end
- if root and next(root) then
+ if root and next(root)~=nil then
local first,last=nil,0
if compact then
last=#root
@@ -1576,7 +1737,7 @@ local function do_serialize(root,name,depth,level,indexed)
if compact and first and tk=="number" and k>=first and k<=last then
if tv=="number" then
if hexify then
- handle(format("%s 0x%04X,",depth,v))
+ handle(format("%s 0x%X,",depth,v))
else
handle(format("%s %s,",depth,v))
end
@@ -1587,7 +1748,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s %q,",depth,v))
end
elseif tv=="table" then
- if not next(v) then
+ if next(v)==nil then
handle(format("%s {},",depth))
elseif inline then
local st=simple_table(v)
@@ -1617,25 +1778,25 @@ local function do_serialize(root,name,depth,level,indexed)
elseif tv=="number" then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
+ handle(format("%s [0x%X]=0x%X,",depth,k,v))
else
handle(format("%s [%s]=%s,",depth,k,v))
end
elseif tk=="boolean" then
if hexify then
- handle(format("%s [%s]=0x%04X,",depth,k and "true" or "false",v))
+ handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v))
else
handle(format("%s [%s]=%s,",depth,k and "true" or "false",v))
end
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
if hexify then
- handle(format("%s %s=0x%04X,",depth,k,v))
+ handle(format("%s %s=0x%X,",depth,k,v))
else
handle(format("%s %s=%s,",depth,k,v))
end
else
if hexify then
- handle(format("%s [%q]=0x%04X,",depth,k,v))
+ handle(format("%s [%q]=0x%X,",depth,k,v))
else
handle(format("%s [%q]=%s,",depth,k,v))
end
@@ -1644,7 +1805,7 @@ local function do_serialize(root,name,depth,level,indexed)
if reduce and tonumber(v) then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,v))
+ handle(format("%s [0x%X]=%s,",depth,k,v))
else
handle(format("%s [%s]=%s,",depth,k,v))
end
@@ -1658,7 +1819,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,v))
+ handle(format("%s [0x%X]=%q,",depth,k,v))
else
handle(format("%s [%s]=%q,",depth,k,v))
end
@@ -1671,10 +1832,10 @@ local function do_serialize(root,name,depth,level,indexed)
end
end
elseif tv=="table" then
- if not next(v) then
+ if next(v)==nil then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]={},",depth,k))
+ handle(format("%s [0x%X]={},",depth,k))
else
handle(format("%s [%s]={},",depth,k))
end
@@ -1690,7 +1851,7 @@ local function do_serialize(root,name,depth,level,indexed)
if st then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
+ handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
end
@@ -1710,7 +1871,7 @@ local function do_serialize(root,name,depth,level,indexed)
elseif tv=="boolean" then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,v and "true" or "false"))
+ handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false"))
else
handle(format("%s [%s]=%s,",depth,k,v and "true" or "false"))
end
@@ -1726,7 +1887,7 @@ local function do_serialize(root,name,depth,level,indexed)
local f=getinfo(v).what=="C" and dump(dummy) or dump(v)
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=load(%q),",depth,k,f))
+ handle(format("%s [0x%X]=load(%q),",depth,k,f))
else
handle(format("%s [%s]=load(%q),",depth,k,f))
end
@@ -1741,7 +1902,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
+ handle(format("%s [0x%X]=%q,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%q,",depth,k,tostring(v)))
end
@@ -1795,7 +1956,7 @@ local function serialize(_handle,root,name,specification)
end
elseif tname=="number" then
if hexify then
- handle(format("[0x%04X]={",name))
+ handle(format("[0x%X]={",name))
else
handle("["..name.."]={")
end
@@ -1813,7 +1974,7 @@ local function serialize(_handle,root,name,specification)
local dummy=root._w_h_a_t_e_v_e_r_
root._w_h_a_t_e_v_e_r_=nil
end
- if next(root) then
+ if next(root)~=nil then
do_serialize(root,name,"",0)
end
end
@@ -1942,14 +2103,25 @@ local function identical(a,b)
end
table.identical=identical
table.are_equal=are_equal
-function table.compact(t)
- if t then
- for k,v in next,t do
- if not next(v) then
- t[k]=nil
+local function sparse(old,nest,keeptables)
+ local new={}
+ for k,v in next,old do
+ if not (v=="" or v==false) then
+ if nest and type(v)=="table" then
+ v=sparse(v,nest)
+ if keeptables or next(v)~=nil then
+ new[k]=v
+ end
+ else
+ new[k]=v
end
end
end
+ return new
+end
+table.sparse=sparse
+function table.compact(t)
+ return sparse(t,true,true)
end
function table.contains(t,v)
if t then
@@ -2054,10 +2226,10 @@ function table.sub(t,i,j)
return { unpack(t,i,j) }
end
function table.is_empty(t)
- return not t or not next(t)
+ return not t or next(t)==nil
end
function table.has_one_entry(t)
- return t and not next(t,next(t))
+ return t and next(t,next(t))==nil
end
function table.loweredkeys(t)
local l={}
@@ -2102,6 +2274,44 @@ function table.values(t,s)
return {}
end
end
+function table.filtered(t,pattern,sort,cmp)
+ if t and type(pattern)=="string" then
+ if sort then
+ local s
+ if cmp then
+ s=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
+ else
+ s=sortedkeys(t)
+ end
+ local n=0
+ local m=#s
+ local function kv(s)
+ while n<m do
+ n=n+1
+ local k=s[n]
+ if find(k,pattern) then
+ return k,t[k]
+ end
+ end
+ end
+ return kv,s
+ else
+ local n=next(t)
+ local function iterator()
+ while n~=nil do
+ local k=n
+ n=next(t,k)
+ if find(k,pattern) then
+ return k,t[k]
+ end
+ end
+ end
+ return iterator,t
+ end
+ else
+ return nothing
+ end
+end
end -- of closure
@@ -2110,7 +2320,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-io"] = package.loaded["l-io"] or true
--- original size: 8824, stripped down to: 6347
+-- original size: 8643, stripped down to: 6232
if not modules then modules={} end modules ['l-io']={
version=1.001,
@@ -2417,8 +2627,6 @@ function io.readstring(f,n,m)
local str=gsub(f:read(n),"\000","")
return str
end
-if not io.i_limiter then function io.i_limiter() end end
-if not io.o_limiter then function io.o_limiter() end end
end -- of closure
@@ -2645,7 +2853,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-os"] = package.loaded["l-os"] or true
--- original size: 16093, stripped down to: 9704
+-- original size: 15761, stripped down to: 9403
if not modules then modules={} end modules ['l-os']={
version=1.001,
@@ -2719,13 +2927,10 @@ if not os.__getenv__ then
setmetatable(os.env,{ __index=__index,__newindex=__newindex } )
end
end
-local execute,spawn,exec,iopopen,ioflush=os.execute,os.spawn or os.execute,os.exec or os.execute,io.popen,io.flush
-function os.execute(...) ioflush() return execute(...) end
-function os.spawn (...) ioflush() return spawn (...) end
-function os.exec (...) ioflush() return exec (...) end
-function io.popen (...) ioflush() return iopopen(...) end
+local execute=os.execute
+local iopopen=io.popen
function os.resultof(command)
- local handle=io.popen(command,"r")
+ local handle=iopopen(command,"r")
if handle then
local result=handle:read("*all") or ""
handle:close()
@@ -2754,7 +2959,7 @@ local launchers={
unix="$BROWSER %s &> /dev/null &",
}
function os.launch(str)
- os.execute(format(launchers[os.name] or launchers.unix,str))
+ execute(format(launchers[os.name] or launchers.unix,str))
end
if not os.times then
function os.times()
@@ -3029,7 +3234,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-file"] = package.loaded["l-file"] or true
--- original size: 18308, stripped down to: 9948
+-- original size: 20949, stripped down to: 9945
if not modules then modules={} end modules ['l-file']={
version=1.001,
@@ -3043,41 +3248,28 @@ local file=file
if not lfs then
lfs=optionalrequire("lfs")
end
-if not lfs then
- lfs={
- getcurrentdir=function()
- return "."
- end,
- attributes=function()
- return nil
- end,
- isfile=function(name)
- local f=io.open(name,'rb')
- if f then
- f:close()
- return true
- end
- end,
- isdir=function(name)
- print("you need to load lfs")
- return false
- end
- }
-elseif not lfs.isfile then
- local attributes=lfs.attributes
- function lfs.isdir(name)
- return attributes(name,"mode")=="directory"
- end
- function lfs.isfile(name)
- return attributes(name,"mode")=="file"
- end
-end
local insert,concat=table.insert,table.concat
local match,find,gmatch=string.match,string.find,string.gmatch
local lpegmatch=lpeg.match
local getcurrentdir,attributes=lfs.currentdir,lfs.attributes
local checkedsplit=string.checkedsplit
local P,R,S,C,Cs,Cp,Cc,Ct=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cp,lpeg.Cc,lpeg.Ct
+local tricky=S("/\\")*P(-1)
+local attributes=lfs.attributes
+if sandbox then
+ sandbox.redefine(lfs.isfile,"lfs.isfile")
+ sandbox.redefine(lfs.isdir,"lfs.isdir")
+end
+function lfs.isdir(name)
+ if lpegmatch(tricky,name) then
+ return attributes(name,"mode")=="directory"
+ else
+ return attributes(name.."/.","mode")=="directory"
+ end
+end
+function lfs.isfile(name)
+ return attributes(name,"mode")=="file"
+end
local colon=P(":")
local period=P(".")
local periods=P("..")
@@ -3279,28 +3471,30 @@ local isroot=fwslash^1*-1
local hasroot=fwslash^1
local reslasher=lpeg.replacer(S("\\/"),"/")
local deslasher=lpeg.replacer(S("\\/")^1,"/")
-function file.join(...)
- local lst={... }
- local one=lst[1]
+function file.join(one,two,three,...)
+ if not two then
+ return one=="" and one or lpegmatch(stripper,one)
+ end
+ if one=="" then
+ return lpegmatch(stripper,three and concat({ two,three,... },"/") or two)
+ end
if lpegmatch(isnetwork,one) then
local one=lpegmatch(reslasher,one)
- local two=lpegmatch(deslasher,concat(lst,"/",2))
+ local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two)
if lpegmatch(hasroot,two) then
return one..two
else
return one.."/"..two
end
elseif lpegmatch(isroot,one) then
- local two=lpegmatch(deslasher,concat(lst,"/",2))
+ local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two)
if lpegmatch(hasroot,two) then
return two
else
return "/"..two
end
- elseif one=="" then
- return lpegmatch(stripper,concat(lst,"/",2))
else
- return lpegmatch(deslasher,concat(lst,"/"))
+ return lpegmatch(deslasher,concat({ one,two,three,... },"/"))
end
end
local drivespec=R("az","AZ")^1*colon
@@ -3474,7 +3668,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-md5"] = package.loaded["l-md5"] or true
--- original size: 3760, stripped down to: 2088
+-- original size: 3248, stripped down to: 2266
if not modules then modules={} end modules ['l-md5']={
version=1.001,
@@ -3492,14 +3686,20 @@ if not md5 then
}
end
local md5,file=md5,file
-local gsub,format,byte=string.gsub,string.format,string.byte
-local md5sum=md5.sum
-local function convert(str,fmt)
- return (gsub(md5sum(str),".",function(chr) return format(fmt,byte(chr)) end))
-end
-if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end
-if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
-if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
+local gsub=string.gsub
+do
+ local patterns=lpeg and lpeg.patterns
+ if patterns then
+ local bytestoHEX=patterns.bytestoHEX
+ local bytestohex=patterns.bytestohex
+ local bytestodec=patterns.bytestodec
+ local lpegmatch=lpeg.match
+ local md5sum=md5.sum
+ if not md5.HEX then function md5.HEX(str) if str then return lpegmatch(bytestoHEX,md5sum(str)) end end end
+ if not md5.hex then function md5.hex(str) if str then return lpegmatch(bytestohex,md5sum(str)) end end end
+ if not md5.dec then function md5.dec(str) if str then return lpegmatch(bytestodec,md5sum(str)) end end end
+ end
+end
function file.needsupdating(oldname,newname,threshold)
local oldtime=lfs.attributes(oldname,"modification")
if oldtime then
@@ -3556,7 +3756,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-url"] = package.loaded["l-url"] or true
--- original size: 12292, stripped down to: 5585
+-- original size: 12531, stripped down to: 5721
if not modules then modules={} end modules ['l-url']={
version=1.001,
@@ -3642,19 +3842,25 @@ local splitquery=Cf (Ct("")*P { "sequence",
pair=Cg(key*equal*value),
},rawset)
local function hashed(str)
- if str=="" then
+ if not str or str=="" then
return {
scheme="invalid",
original=str,
}
end
- local s=split(str)
- local rawscheme=s[1]
- local rawquery=s[4]
- local somescheme=rawscheme~=""
- local somequery=rawquery~=""
+ local detailed=split(str)
+ local rawscheme=""
+ local rawquery=""
+ local somescheme=false
+ local somequery=false
+ if detailed then
+ rawscheme=detailed[1]
+ rawquery=detailed[4]
+ somescheme=rawscheme~=""
+ somequery=rawquery~=""
+ end
if not somescheme and not somequery then
- s={
+ return {
scheme="file",
authority="",
path=str,
@@ -3664,28 +3870,28 @@ local function hashed(str)
noscheme=true,
filename=str,
}
- else
- local authority,path,filename=s[2],s[3]
- if authority=="" then
- filename=path
- elseif path=="" then
- filename=""
- else
- filename=authority.."/"..path
- end
- s={
- scheme=rawscheme,
- authority=authority,
- path=path,
- query=lpegmatch(unescaper,rawquery),
- queries=lpegmatch(splitquery,rawquery),
- fragment=s[5],
- original=str,
- noscheme=false,
- filename=filename,
- }
end
- return s
+ local authority=detailed[2]
+ local path=detailed[3]
+ local filename=nil
+ if authority=="" then
+ filename=path
+ elseif path=="" then
+ filename=""
+ else
+ filename=authority.."/"..path
+ end
+ return {
+ scheme=rawscheme,
+ authority=authority,
+ path=path,
+ query=lpegmatch(unescaper,rawquery),
+ queries=lpegmatch(splitquery,rawquery),
+ fragment=detailed[5],
+ original=str,
+ noscheme=false,
+ filename=filename,
+ }
end
url.split=split
url.hasscheme=hasscheme
@@ -3719,7 +3925,7 @@ function url.construct(hash)
end
return lpegmatch(escaper,concat(fullurl))
end
-local pattern=Cs(noslash*R("az","AZ")*(S(":|")/":")*noslash*P(1)^0)
+local pattern=Cs(slash^-1/""*R("az","AZ")*((S(":|")/":")+P(":"))*slash*P(1)^0)
function url.filename(filename)
local spec=hashed(filename)
local path=spec.path
@@ -3767,7 +3973,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-dir"] = package.loaded["l-dir"] or true
--- original size: 14788, stripped down to: 9096
+-- original size: 16765, stripped down to: 11003
if not modules then modules={} end modules ['l-dir']={
version=1.001,
@@ -3777,7 +3983,7 @@ if not modules then modules={} end modules ['l-dir']={
license="see context related readme files"
}
local type,select=type,select
-local find,gmatch,match,gsub=string.find,string.gmatch,string.match,string.gsub
+local find,gmatch,match,gsub,sub=string.find,string.gmatch,string.match,string.gsub,string.sub
local concat,insert,remove,unpack=table.concat,table.insert,table.remove,table.unpack
local lpegmatch=lpeg.match
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
@@ -3786,53 +3992,126 @@ local dir=dir
local lfs=lfs
local attributes=lfs.attributes
local walkdir=lfs.dir
-local isdir=lfs.isdir
-local isfile=lfs.isfile
+local isdir=lfs.isdir
+local isfile=lfs.isfile
local currentdir=lfs.currentdir
local chdir=lfs.chdir
local mkdir=lfs.mkdir
local onwindows=os.type=="windows" or find(os.getenv("PATH"),";",1,true)
-if not isdir then
- function isdir(name)
- local a=attributes(name)
- return a and a.mode=="directory"
+if onwindows then
+ local tricky=S("/\\")*P(-1)
+ isdir=function(name)
+ if lpegmatch(tricky,name) then
+ return attributes(name,"mode")=="directory"
+ else
+ return attributes(name.."/.","mode")=="directory"
+ end
+ end
+ isfile=function(name)
+ return attributes(name,"mode")=="file"
end
lfs.isdir=isdir
-end
-if not isfile then
- function isfile(name)
- local a=attributes(name)
- return a and a.mode=="file"
+ lfs.isfile=isfile
+else
+ isdir=function(name)
+ return attributes(name,"mode")=="directory"
end
+ isfile=function(name)
+ return attributes(name,"mode")=="file"
+ end
+ lfs.isdir=isdir
lfs.isfile=isfile
end
function dir.current()
return (gsub(currentdir(),"\\","/"))
end
-local lfsisdir=isdir
-local function isdir(path)
- path=gsub(path,"[/\\]+$","")
- return lfsisdir(path)
+local function glob_pattern_function(path,patt,recurse,action)
+ if isdir(path) then
+ local usedpath
+ if path=="/" then
+ usedpath="/."
+ elseif not find(path,"/$") then
+ usedpath=path.."/."
+ path=path.."/"
+ else
+ usedpath=path
+ end
+ local dirs
+ for name in walkdir(usedpath) do
+ if name~="." and name~=".." then
+ local full=path..name
+ local mode=attributes(full,'mode')
+ if mode=='file' then
+ if not patt or find(full,patt) then
+ action(full)
+ end
+ elseif recurse and mode=="directory" then
+ if not dirs then
+ dirs={ full }
+ else
+ dirs[#dirs+1]=full
+ end
+ end
+ end
+ end
+ if dirs then
+ for i=1,#dirs do
+ glob_pattern_function(dirs[i],patt,recurse,action)
+ end
+ end
+ end
end
-lfs.isdir=isdir
-local function globpattern(path,patt,recurse,action)
- if path=="/" then
- path=path.."."
- elseif not find(path,"/$") then
- path=path..'/'
- end
- if isdir(path) then
- for name in walkdir(path) do
- local full=path..name
- local mode=attributes(full,'mode')
- if mode=='file' then
- if find(full,patt) then
- action(full)
+local function glob_pattern_table(path,patt,recurse,result)
+ if not result then
+ result={}
+ end
+ if isdir(path) then
+ local usedpath
+ if path=="/" then
+ usedpath="/."
+ elseif not find(path,"/$") then
+ usedpath=path.."/."
+ path=path.."/"
+ else
+ usedpath=path
+ end
+ local dirs
+ for name in walkdir(usedpath) do
+ if name~="." and name~=".." then
+ local full=path..name
+ local mode=attributes(full,'mode')
+ if mode=='file' then
+ if not patt or find(full,patt) then
+ result[#result+1]=full
+ end
+ elseif recurse and mode=="directory" then
+ if not dirs then
+ dirs={ full }
+ else
+ dirs[#dirs+1]=full
+ end
end
- elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
- globpattern(full,patt,recurse,action)
end
end
+ if dirs then
+ for i=1,#dirs do
+ glob_pattern_table(dirs[i],patt,recurse,result)
+ end
+ end
+ end
+ return result
+end
+local function globpattern(path,patt,recurse,method)
+ local kind=type(method)
+ if patt and sub(patt,1,-3)==path then
+ patt=false
+ end
+ if kind=="function" then
+ return glob_pattern_function(path,patt,recurse,method)
+ elseif kind=="table" then
+ return glob_pattern_table(path,patt,recurse,method)
+ else
+ return glob_pattern_table(path,patt,recurse,{})
end
end
dir.globpattern=globpattern
@@ -3845,34 +4124,40 @@ local function collectpattern(path,patt,recurse,result)
ok,scanner,first=xpcall(function() return walkdir(path) end,function() end)
end
if ok and type(scanner)=="function" then
- if not find(path,"/$") then path=path..'/' end
+ if not find(path,"/$") then
+ path=path..'/'
+ end
for name in scanner,first do
- local full=path..name
- local attr=attributes(full)
- local mode=attr.mode
- if mode=='file' then
- if find(full,patt) then
+ if name=="." then
+ elseif name==".." then
+ else
+ local full=path..name
+ local attr=attributes(full)
+ local mode=attr.mode
+ if mode=='file' then
+ if find(full,patt) then
+ result[name]=attr
+ end
+ elseif recurse and mode=="directory" then
+ attr.list=collectpattern(full,patt,recurse)
result[name]=attr
end
- elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
- attr.list=collectpattern(full,patt,recurse)
- result[name]=attr
end
end
end
return result
end
dir.collectpattern=collectpattern
-local separator
-if onwindows then
+local separator,pattern
+if onwindows then
local slash=S("/\\")/"/"
- pattern=Ct {
+ pattern={
[1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3),
[2]=Cs(((1-S("*?/\\"))^0*slash)^0),
[3]=Cs(P(1)^0)
}
-else
- pattern=Ct {
+else
+ pattern={
[1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3),
[2]=C(((1-S("*?/"))^0*P("/"))^0),
[3]=C(P(1)^0)
@@ -3890,9 +4175,8 @@ local function glob(str,t)
elseif isfile(str) then
t(str)
else
- local split=lpegmatch(pattern,str)
- if split then
- local root,path,base=split[1],split[2],split[3]
+ local root,path,base=lpegmatch(pattern,str)
+ if root and path and base then
local recurse=find(base,"**",1,true)
local start=root..path
local result=lpegmatch(filter,start..base)
@@ -3914,16 +4198,12 @@ local function glob(str,t)
return { str }
end
else
- local split=lpegmatch(pattern,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 root,path,base=lpegmatch(pattern,str)
+ if root and path and base then
local recurse=find(base,"**",1,true)
local start=root..path
local result=lpegmatch(filter,start..base)
- globpattern(start,result,recurse,action)
- return t
+ return globpattern(start,result,recurse,t)
else
return {}
end
@@ -4071,47 +4351,51 @@ else
end
end
dir.makedirs=dir.mkdirs
-if onwindows then
- function dir.expandname(str)
- local first,nothing,last=match(str,"^(//)(//*)(.*)$")
- if first then
- first=dir.current().."/"
- end
- if not first then
- first,last=match(str,"^(//)/*(.*)$")
- end
- if not first then
- first,last=match(str,"^([a-zA-Z]:)(.*)$")
- if first and not find(last,"^/") then
- local d=currentdir()
- if chdir(first) then
- first=dir.current()
+do
+ local chdir=sandbox and sandbox.original(chdir) or chdir
+ if onwindows then
+ local xcurrentdir=dir.current
+ function dir.expandname(str)
+ local first,nothing,last=match(str,"^(//)(//*)(.*)$")
+ if first then
+ first=xcurrentdir().."/"
+ end
+ if not first then
+ first,last=match(str,"^(//)/*(.*)$")
+ end
+ if not first then
+ first,last=match(str,"^([a-zA-Z]:)(.*)$")
+ if first and not find(last,"^/") then
+ local d=currentdir()
+ if chdir(first) then
+ first=xcurrentdir()
+ end
+ chdir(d)
end
- chdir(d)
+ end
+ if not first then
+ first,last=xcurrentdir(),str
+ end
+ last=gsub(last,"//","/")
+ last=gsub(last,"/%./","/")
+ last=gsub(last,"^/*","")
+ first=gsub(first,"/*$","")
+ if last=="" or last=="." then
+ return first
+ else
+ return first.."/"..last
end
end
- if not first then
- first,last=dir.current(),str
- end
- last=gsub(last,"//","/")
- last=gsub(last,"/%./","/")
- last=gsub(last,"^/*","")
- first=gsub(first,"/*$","")
- if last=="" or last=="." then
- return first
- else
- return first.."/"..last
- end
- end
-else
- function dir.expandname(str)
- if not find(str,"^/") then
- str=currentdir().."/"..str
+ else
+ function dir.expandname(str)
+ if not find(str,"^/") then
+ str=currentdir().."/"..str
+ end
+ str=gsub(str,"//","/")
+ str=gsub(str,"/%./","/")
+ str=gsub(str,"(.)/%.$","%1")
+ return str
end
- str=gsub(str,"//","/")
- str=gsub(str,"/%./","/")
- str=gsub(str,"(.)/%.$","%1")
- return str
end
end
file.expandname=dir.expandname
@@ -4154,7 +4438,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-boolean"] = package.loaded["l-boolean"] or true
--- original size: 1809, stripped down to: 1527
+-- original size: 1850, stripped down to: 1568
if not modules then modules={} end modules ['l-boolean']={
version=1.001,
@@ -4208,11 +4492,11 @@ function string.booleanstring(str)
return str=="yes" or str=="on" or str=="t"
end
end
-function string.is_boolean(str,default)
+function string.is_boolean(str,default,strict)
if type(str)=="string" then
- if str=="true" or str=="yes" or str=="on" or str=="t" or str=="1" then
+ if str=="true" or str=="yes" or str=="on" or str=="t" or (not strict and str=="1") then
return true
- elseif str=="false" or str=="no" or str=="off" or str=="f" or str=="0" then
+ elseif str=="false" or str=="no" or str=="off" or str=="f" or (not strict and str=="0") then
return false
end
end
@@ -4226,7 +4510,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-unicode"] = package.loaded["l-unicode"] or true
--- original size: 33706, stripped down to: 14938
+-- original size: 37233, stripped down to: 15684
if not modules then modules={} end modules ['l-unicode']={
version=1.001,
@@ -4242,7 +4526,9 @@ local type=type
local char,byte,format,sub,gmatch=string.char,string.byte,string.format,string.sub,string.gmatch
local concat=table.concat
local P,C,R,Cs,Ct,Cmt,Cc,Carg,Cp=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Ct,lpeg.Cmt,lpeg.Cc,lpeg.Carg,lpeg.Cp
-local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local lpegmatch=lpeg.match
+local patterns=lpeg.patterns
+local tabletopattern=lpeg.utfchartabletopattern
local bytepairs=string.bytepairs
local finder=lpeg.finder
local replacer=lpeg.replacer
@@ -4251,7 +4537,7 @@ local utfgmatch=utf.gmatch
local p_utftype=patterns.utftype
local p_utfstricttype=patterns.utfstricttype
local p_utfoffset=patterns.utfoffset
-local p_utf8char=patterns.utf8char
+local p_utf8char=patterns.utf8character
local p_utf8byte=patterns.utf8byte
local p_utfbom=patterns.utfbom
local p_newline=patterns.newline
@@ -4450,15 +4736,52 @@ if not utf.sub then
end
end
end
-function utf.remapper(mapping)
- local pattern=Cs((p_utf8char/mapping)^0)
- return function(str)
- if not str or str=="" then
- return ""
+function utf.remapper(mapping,option)
+ local variant=type(mapping)
+ if variant=="table" then
+ if option=="dynamic" then
+ local pattern=false
+ table.setmetatablenewindex(mapping,function(t,k,v) rawset(t,k,v) pattern=false end)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ if not pattern then
+ pattern=Cs((tabletopattern(mapping)/mapping+p_utf8char)^0)
+ end
+ return lpegmatch(pattern,str)
+ end
+ end
+ elseif option=="pattern" then
+ return Cs((tabletopattern(mapping)/mapping+p_utf8char)^0)
else
- return lpegmatch(pattern,str)
+ local pattern=Cs((tabletopattern(mapping)/mapping+p_utf8char)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+ end
+ elseif variant=="function" then
+ if option=="pattern" then
+ return Cs((p_utf8char/mapping+p_utf8char)^0)
+ else
+ local pattern=Cs((p_utf8char/mapping+p_utf8char)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+ end
+ else
+ return function(str)
+ return str or ""
end
- end,pattern
+ end
end
function utf.replacer(t)
local r=replacer(t,false,false,true)
@@ -4508,190 +4831,157 @@ function utf.magic(f)
end
local utf16_to_utf8_be,utf16_to_utf8_le
local utf32_to_utf8_be,utf32_to_utf8_le
-local utf_16_be_linesplitter=patterns.utfbom_16_be^-1*lpeg.tsplitat(patterns.utf_16_be_nl)
-local utf_16_le_linesplitter=patterns.utfbom_16_le^-1*lpeg.tsplitat(patterns.utf_16_le_nl)
-if bytepairs then
- utf16_to_utf8_be=function(t)
- if type(t)=="string" then
- t=lpegmatch(utf_16_be_linesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,0
- for left,right in bytepairs(t[i]) do
- if right then
- local now=256*left+right
- if more>0 then
- now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
- more=0
- r=r+1
- result[r]=utfchar(now)
- elseif now>=0xD800 and now<=0xDBFF then
- more=now
- else
- r=r+1
- result[r]=utfchar(now)
- end
- end
- end
- t[i]=concat(result,"",1,r)
- end
- return t
+local utf_16_be_getbom=patterns.utfbom_16_be^-1
+local utf_16_le_getbom=patterns.utfbom_16_le^-1
+local utf_32_be_getbom=patterns.utfbom_32_be^-1
+local utf_32_le_getbom=patterns.utfbom_32_le^-1
+local utf_16_be_linesplitter=utf_16_be_getbom*lpeg.tsplitat(patterns.utf_16_be_nl)
+local utf_16_le_linesplitter=utf_16_le_getbom*lpeg.tsplitat(patterns.utf_16_le_nl)
+local utf_32_be_linesplitter=utf_32_be_getbom*lpeg.tsplitat(patterns.utf_32_be_nl)
+local utf_32_le_linesplitter=utf_32_le_getbom*lpeg.tsplitat(patterns.utf_32_le_nl)
+local more=0
+local p_utf16_to_utf8_be=C(1)*C(1)/function(left,right)
+ local now=256*byte(left)+byte(right)
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ return utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ return ""
+ else
+ return utfchar(now)
+ end
+end
+local p_utf16_to_utf8_le=C(1)*C(1)/function(right,left)
+ local now=256*byte(left)+byte(right)
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ return utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ return ""
+ else
+ return utfchar(now)
+ end
+end
+local p_utf32_to_utf8_be=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d)
+ return utfchar(256*256*256*byte(a)+256*256*byte(b)+256*byte(c)+byte(d))
+end
+local p_utf32_to_utf8_le=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d)
+ return utfchar(256*256*256*byte(d)+256*256*byte(c)+256*byte(b)+byte(a))
+end
+p_utf16_to_utf8_be=P(true)/function() more=0 end*utf_16_be_getbom*Cs(p_utf16_to_utf8_be^0)
+p_utf16_to_utf8_le=P(true)/function() more=0 end*utf_16_le_getbom*Cs(p_utf16_to_utf8_le^0)
+p_utf32_to_utf8_be=P(true)/function() more=0 end*utf_32_be_getbom*Cs(p_utf32_to_utf8_be^0)
+p_utf32_to_utf8_le=P(true)/function() more=0 end*utf_32_le_getbom*Cs(p_utf32_to_utf8_le^0)
+patterns.utf16_to_utf8_be=p_utf16_to_utf8_be
+patterns.utf16_to_utf8_le=p_utf16_to_utf8_le
+patterns.utf32_to_utf8_be=p_utf32_to_utf8_be
+patterns.utf32_to_utf8_le=p_utf32_to_utf8_le
+utf16_to_utf8_be=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf16_to_utf8_be,s)
+ else
+ return s
end
- utf16_to_utf8_le=function(t)
- if type(t)=="string" then
- t=lpegmatch(utf_16_le_linesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,0
- for left,right in bytepairs(t[i]) do
- if right then
- local now=256*right+left
- if more>0 then
- now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
- more=0
- r=r+1
- result[r]=utfchar(now)
- elseif now>=0xD800 and now<=0xDBFF then
- more=now
- else
- r=r+1
- result[r]=utfchar(now)
- end
- end
- end
- t[i]=concat(result,"",1,r)
- end
- return t
+end
+local utf16_to_utf8_be_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_16_be_linesplitter,t)
end
- utf32_to_utf8_be=function(t)
- if type(t)=="string" then
- t=lpegmatch(utflinesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,-1
- for a,b in bytepairs(t[i]) do
- if a and b then
- if more<0 then
- more=256*256*256*a+256*256*b
- else
- r=r+1
- result[t]=utfchar(more+256*a+b)
- more=-1
- end
- else
- break
- end
- end
- t[i]=concat(result,"",1,r)
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf16_to_utf8_be,s)
end
- return t
end
- utf32_to_utf8_le=function(t)
- if type(t)=="string" then
- t=lpegmatch(utflinesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,-1
- for a,b in bytepairs(t[i]) do
- if a and b then
- if more<0 then
- more=256*b+a
- else
- r=r+1
- result[t]=utfchar(more+256*256*256*b+256*256*a)
- more=-1
- end
- else
- break
- end
- end
- t[i]=concat(result,"",1,r)
- end
- return t
+ return t
+end
+utf16_to_utf8_le=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf16_to_utf8_le,s)
+ else
+ return s
end
-else
- utf16_to_utf8_be=function(t)
- if type(t)=="string" then
- t=lpegmatch(utf_16_be_linesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,0
- for left,right in gmatch(t[i],"(.)(.)") do
- if left=="\000" then
- r=r+1
- result[r]=utfchar(byte(right))
- elseif right then
- local now=256*byte(left)+byte(right)
- if more>0 then
- now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
- more=0
- r=r+1
- result[r]=utfchar(now)
- elseif now>=0xD800 and now<=0xDBFF then
- more=now
- else
- r=r+1
- result[r]=utfchar(now)
- end
- end
- end
- t[i]=concat(result,"",1,r)
+end
+local utf16_to_utf8_le_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_16_le_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf16_to_utf8_le,s)
end
- return t
end
- utf16_to_utf8_le=function(t)
- if type(t)=="string" then
- t=lpegmatch(utf_16_le_linesplitter,t)
+ return t
+end
+utf32_to_utf8_be=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf32_to_utf8_be,s)
+ else
+ return s
+ end
+end
+local utf32_to_utf8_be_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_32_be_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf32_to_utf8_be,s)
end
- local result={}
- for i=1,#t do
- local r,more=0,0
- for left,right in gmatch(t[i],"(.)(.)") do
- if right=="\000" then
- r=r+1
- result[r]=utfchar(byte(left))
- elseif right then
- local now=256*byte(right)+byte(left)
- if more>0 then
- now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
- more=0
- r=r+1
- result[r]=utfchar(now)
- elseif now>=0xD800 and now<=0xDBFF then
- more=now
- else
- r=r+1
- result[r]=utfchar(now)
- end
- end
- end
- t[i]=concat(result,"",1,r)
+ end
+ return t
+end
+utf32_to_utf8_le=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf32_to_utf8_le,s)
+ else
+ return s
+ end
+end
+local utf32_to_utf8_le_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_32_le_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf32_to_utf8_le,s)
end
- return t
end
- utf32_to_utf8_le=function() return {} end
- utf32_to_utf8_be=function() return {} end
+ return t
end
+utf.utf16_to_utf8_le_t=utf16_to_utf8_le_t
+utf.utf16_to_utf8_be_t=utf16_to_utf8_be_t
+utf.utf32_to_utf8_le_t=utf32_to_utf8_le_t
+utf.utf32_to_utf8_be_t=utf32_to_utf8_be_t
utf.utf16_to_utf8_le=utf16_to_utf8_le
utf.utf16_to_utf8_be=utf16_to_utf8_be
utf.utf32_to_utf8_le=utf32_to_utf8_le
utf.utf32_to_utf8_be=utf32_to_utf8_be
-function utf.utf8_to_utf8(t)
+function utf.utf8_to_utf8_t(t)
return type(t)=="string" and lpegmatch(utflinesplitter,t) or t
end
-function utf.utf16_to_utf8(t,endian)
- return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
+function utf.utf16_to_utf8_t(t,endian)
+ return endian and utf16_to_utf8_be_t(t) or utf16_to_utf8_le_t(t) or t
end
-function utf.utf32_to_utf8(t,endian)
- return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
+function utf.utf32_to_utf8_t(t,endian)
+ return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t
end
-local function little(c)
- local b=byte(c)
+local function little(b)
if b<0x10000 then
return char(b%256,b/256)
else
@@ -4700,8 +4990,7 @@ local function little(c)
return char(b1%256,b1/256,b2%256,b2/256)
end
end
-local function big(c)
- local b=byte(c)
+local function big(b)
if b<0x10000 then
return char(b/256,b%256)
else
@@ -4710,27 +4999,29 @@ local function big(c)
return char(b1/256,b1%256,b2/256,b2%256)
end
end
-local _,l_remap=utf.remapper(little)
-local _,b_remap=utf.remapper(big)
-function utf.utf8_to_utf16_be(str,nobom)
+local l_remap=Cs((p_utf8byte/little+P(1)/"")^0)
+local b_remap=Cs((p_utf8byte/big+P(1)/"")^0)
+local function utf8_to_utf16_be(str,nobom)
if nobom then
return lpegmatch(b_remap,str)
else
return char(254,255)..lpegmatch(b_remap,str)
end
end
-function utf.utf8_to_utf16_le(str,nobom)
+local function utf8_to_utf16_le(str,nobom)
if nobom then
return lpegmatch(l_remap,str)
else
return char(255,254)..lpegmatch(l_remap,str)
end
end
+utf.utf8_to_utf16_be=utf8_to_utf16_be
+utf.utf8_to_utf16_le=utf8_to_utf16_le
function utf.utf8_to_utf16(str,littleendian,nobom)
if littleendian then
- return utf.utf8_to_utf16_le(str,nobom)
+ return utf8_to_utf16_le(str,nobom)
else
- return utf.utf8_to_utf16_be(str,nobom)
+ return utf8_to_utf16_be(str,nobom)
end
end
local pattern=Cs (
@@ -4746,16 +5037,16 @@ function utf.xstring(s)
return format("0x%05X",type(s)=="number" and s or utfbyte(s))
end
function utf.toeight(str)
- if not str then
+ if not str or str=="" then
return nil
end
local utftype=lpegmatch(p_utfstricttype,str)
if utftype=="utf-8" then
- return sub(str,4)
- elseif utftype=="utf-16-le" then
- return utf16_to_utf8_le(str)
+ return sub(str,4)
elseif utftype=="utf-16-be" then
- return utf16_to_utf8_ne(str)
+ return utf16_to_utf8_be(str)
+ elseif utftype=="utf-16-le" then
+ return utf16_to_utf8_le(str)
else
return str
end
@@ -4834,7 +5125,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-math"] = package.loaded["l-math"] or true
--- original size: 915, stripped down to: 836
+-- original size: 974, stripped down to: 890
if not modules then modules={} end modules ['l-math']={
version=1.001,
@@ -4844,6 +5135,9 @@ if not modules then modules={} end modules ['l-math']={
license="see context related readme files"
}
local floor,sin,cos,tan=math.floor,math.sin,math.cos,math.tan
+if not math.ceiling then
+ math.ceiling=math.ceil
+end
if not math.round then
function math.round(x) return floor(x+0.5) end
end
@@ -4871,7 +5165,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-str"] = package.loaded["util-str"] or true
--- original size: 33063, stripped down to: 18397
+-- original size: 34407, stripped down to: 18852
if not modules then modules={} end modules ['util-str']={
version=1.001,
@@ -5001,10 +5295,12 @@ local striplinepatterns={
["retain"]=p_retain_normal,
["retain and collapse"]=p_retain_collapse,
["retain and no empty"]=p_retain_noempty,
+ ["collapse"]=patterns.collapser,
}
+setmetatable(striplinepatterns,{ __index=function(t,k) return p_prune_collapse end })
strings.striplinepatterns=striplinepatterns
function strings.striplines(str,how)
- return str and lpegmatch(how and striplinepatterns[how] or p_prune_collapse,str) or str
+ return str and lpegmatch(striplinepatterns[how],str) or str
end
strings.striplong=strings.striplines
function strings.nice(str)
@@ -5044,10 +5340,10 @@ string.tracedchars=tracedchars
strings.tracers=tracedchars
function string.tracedchar(b)
if type(b)=="number" then
- return tracedchars[b] or (utfchar(b).." (U+"..format('%05X',b)..")")
+ return tracedchars[b] or (utfchar(b).." (U+"..format("%05X",b)..")")
else
local c=utfbyte(b)
- return tracedchars[c] or (b.." (U+"..format('%05X',c)..")")
+ return tracedchars[c] or (b.." (U+"..(c and format("%05X",c) or "?????")..")")
end
end
function number.signed(i)
@@ -5184,12 +5480,12 @@ local format_f=function(f)
n=n+1
return format("format('%%%sf',a%s)",f,n)
end
-local format_F=function(f)
+local format_F=function(f)
n=n+1
if not f or f=="" then
- return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or (a%s == 1 and '1') or format('%%.9f',a%s))",n,n,n,n)
+ return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or format((a%s %% 1 == 0) and '%%i' or '%%.9f',a%s))",n,n,n,n)
else
- return format("((a%s == 0 and '0') or (a%s == 1 and '1') or format('%%%sf',a%s))",n,n,f,n)
+ return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n)
end
end
local format_g=function(f)
@@ -5417,7 +5713,6 @@ local builder=Cs { "start",
+V("j")+V("J")
+V("m")+V("M")
+V("z")
-+V("*")
)+V("*")
)*(P(-1)+Carg(1))
)^0,
@@ -5461,6 +5756,7 @@ local builder=Cs { "start",
["a"]=(prefix_any*P("a"))/format_a,
["A"]=(prefix_any*P("A"))/format_A,
["*"]=Cs(((1-P("%"))^1+P("%%")/"%%")^1)/format_rest,
+ ["?"]=Cs(((1-P("%"))^1 )^1)/format_rest,
["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension,
}
local direct=Cs (
@@ -5535,6 +5831,15 @@ else
add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape })
add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape })
end
+local dquote=patterns.dquote
+local equote=patterns.escaped+dquote/'\\"'+1
+local space=patterns.space
+local cquote=Cc('"')
+local pattern=Cs(dquote*(equote-P(-2))^0*dquote)
++Cs(cquote*(equote-space)^0*space*equote^0*cquote)
+function string.optionalquoted(str)
+ return lpegmatch(pattern,str) or str
+end
end -- of closure
@@ -5543,7 +5848,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-tab"] = package.loaded["util-tab"] or true
--- original size: 23985, stripped down to: 16069
+-- original size: 24267, stripped down to: 16260
if not modules then modules={} end modules ['util-tab']={
version=1.001,
@@ -5633,6 +5938,15 @@ function tables.removevalue(t,value)
end
end
end
+function tables.replacevalue(t,oldvalue,newvalue)
+ if oldvalue and newvalue then
+ for i=1,#t do
+ if t[i]==oldvalue then
+ t[i]=newvalue
+ end
+ end
+ end
+end
function tables.insertbeforevalue(t,value,extra)
for i=1,#t do
if t[i]==extra then
@@ -6026,7 +6340,7 @@ function table.serialize(root,name,specification)
end
depth=depth+1
end
- if root and next(root) then
+ if root and next(root)~=nil then
local first=nil
local last=0
last=#root
@@ -6051,7 +6365,7 @@ function table.serialize(root,name,specification)
elseif tv=="string" then
n=n+1 t[n]=f_val_str(depth,v)
elseif tv=="table" then
- if not next(v) then
+ if next(v)==nil then
n=n+1 t[n]=f_val_not(depth)
else
local st=simple_table(v)
@@ -6081,7 +6395,7 @@ function table.serialize(root,name,specification)
n=n+1 t[n]=f_key_boo_value_str(depth,k,v)
end
elseif tv=="table" then
- if not next(v) then
+ if next(v)==nil then
if tk=="number" then
n=n+1 t[n]=f_key_num_value_not(depth,k,v)
elseif tk=="string" then
@@ -6139,7 +6453,7 @@ function table.serialize(root,name,specification)
local dummy=root._w_h_a_t_e_v_e_r_
root._w_h_a_t_e_v_e_r_=nil
end
- if next(root) then
+ if next(root)~=nil then
do_serialize(root,name,1,0)
end
end
@@ -6302,7 +6616,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-prs"] = package.loaded["util-prs"] or true
--- original size: 19618, stripped down to: 14012
+-- original size: 21751, stripped down to: 15108
if not modules then modules={} end modules ['util-prs']={
version=1.001,
@@ -6458,11 +6772,30 @@ function parsers.settings_to_array(str,strict)
return { str }
end
end
-local separator=space^0*comma*space^0
-local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-(space^0*(comma+P(-1)))))^0)
-local withvalue=Carg(1)*value/function(f,s) return f(s) end
-local pattern_a=spaces*Ct(value*(separator*value)^0)
-local pattern_b=spaces*withvalue*(separator*withvalue)^0
+local cache_a={}
+local cache_b={}
+function parsers.groupedsplitat(symbol,withaction)
+ if not symbol then
+ symbol=","
+ end
+ local pattern=(withaction and cache_b or cache_a)[symbol]
+ if not pattern then
+ local symbols=S(symbol)
+ local separator=space^0*symbols*space^0
+ local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-(space^0*(symbols+P(-1)))))^0)
+ if withaction then
+ local withvalue=Carg(1)*value/function(f,s) return f(s) end
+ pattern=spaces*withvalue*(separator*withvalue)^0
+ cache_b[symbol]=pattern
+ else
+ pattern=spaces*Ct(value*(separator*value)^0)
+ cache_a[symbol]=pattern
+ end
+ end
+ return pattern
+end
+local pattern_a=parsers.groupedsplitat(",",false)
+local pattern_b=parsers.groupedsplitat(",",true)
function parsers.stripped_settings_to_array(str)
if not str or str=="" then
return {}
@@ -6524,12 +6857,9 @@ function parsers.array_to_string(a,separator)
return ""
end
end
-function parsers.settings_to_set(str,t)
- t=t or {}
- for s in gmatch(str,"[^, ]+") do
- t[s]=true
- end
- return t
+local pattern=Cf(Ct("")*Cg(C((1-S(", "))^1)*S(", ")^0*Cc(true))^1,rawset)
+function utilities.parsers.settings_to_set(str,t)
+ return str and lpegmatch(pattern,str) or {}
end
function parsers.simple_hash_to_string(h,separator)
local t,tn={},0
@@ -6541,12 +6871,16 @@ function parsers.simple_hash_to_string(h,separator)
end
return concat(t,separator or ",")
end
-local str=C((1-whitespace-equal)^1)
+local str=Cs(lpegpatterns.unquoted)+C((1-whitespace-equal)^1)
local setting=Cf(Carg(1)*(whitespace^0*Cg(str*whitespace^0*(equal*whitespace^0*str+Cc(""))))^1,rawset)
local splitter=setting^1
function utilities.parsers.options_to_hash(str,target)
return str and lpegmatch(splitter,str,1,target or {}) or {}
end
+local splitter=lpeg.tsplitat(" ")
+function utilities.parsers.options_to_array(str)
+ return str and lpegmatch(splitter,str) or {}
+end
local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C(digit^1*lparent*(noparent+nestedparents)^1*rparent)+C((nestedbraces+(1-comma))^1)
local pattern_a=spaces*Ct(value*(separator*value)^0)
local function repeater(n,str)
@@ -6668,7 +7002,7 @@ function parsers.rfc4180splitter(specification)
local field=escaped+non_escaped+Cc("")
local record=Ct(field*(separator*field)^1)
local headerline=record*Cp()
- local wholeblob=Ct((newline^-1*record)^0)
+ local wholeblob=Ct((newline^(specification.strict and -1 or 1)*record)^0)
return function(data,getheader)
if getheader then
local header,position=lpegmatch(headerline,data)
@@ -6705,13 +7039,13 @@ function parsers.stepper(str,n,action)
lpegmatch(stepper,str,1,n,action or print)
end
end
-local pattern_math=Cs((P("%")/"\\percent "+P("^")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0)
-local pattern_text=Cs((P("%")/"\\percent "+(P("^")/"\\high")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0)
+local pattern_math=Cs((P("%")/"\\percent "+P("^")*Cc("{")*lpegpatterns.integer*Cc("}")+anything)^0)
+local pattern_text=Cs((P("%")/"\\percent "+(P("^")/"\\high")*Cc("{")*lpegpatterns.integer*Cc("}")+anything)^0)
patterns.unittotex=pattern
function parsers.unittotex(str,textmode)
return lpegmatch(textmode and pattern_text or pattern_math,str)
end
-local pattern=Cs((P("^")/"<sup>"*lpegpatterns.integer*Cc("</sup>")+P(1))^0)
+local pattern=Cs((P("^")/"<sup>"*lpegpatterns.integer*Cc("</sup>")+anything)^0)
function parsers.unittoxml(str)
return lpegmatch(pattern,str)
end
@@ -6783,6 +7117,18 @@ function utilities.parsers.runtime(time)
local seconds=mod(time,60)
return days,hours,minutes,seconds
end
+local spacing=whitespace^0
+local apply=P("->")
+local method=C((1-apply)^1)
+local token=lbrace*C((1-rbrace)^1)*rbrace+C(anything^1)
+local pattern=spacing*(method*spacing*apply+Carg(1))*spacing*token
+function utilities.parsers.splitmethod(str,default)
+ if str then
+ return lpegmatch(pattern,str,1,default or false)
+ else
+ return default or false,""
+ end
+end
end -- of closure
@@ -6872,7 +7218,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["trac-set"] = package.loaded["trac-set"] or true
--- original size: 12365, stripped down to: 8799
+-- original size: 12482, stripped down to: 8864
if not modules then modules={} end modules ['trac-set']={
version=1.001,
@@ -6900,7 +7246,7 @@ function setters.initialize(filename,name,values)
local data=setter.data
if data then
for key,newvalue in next,values do
- local newvalue=is_boolean(newvalue,newvalue)
+ local newvalue=is_boolean(newvalue,newvalue,true)
local functions=data[key]
if functions then
local oldvalue=functions.value
@@ -6954,7 +7300,7 @@ local function set(t,what,newvalue)
elseif not value then
value=false
else
- value=is_boolean(value,value)
+ value=is_boolean(value,value,true)
end
w=topattern(w,true,true)
for name,functions in next,data do
@@ -7093,6 +7439,7 @@ function setters.new(name)
report=function(...) setters.report (setter,...) end,
enable=function(...) enable (setter,...) end,
disable=function(...) disable (setter,...) end,
+ reset=function(...) reset (setter,...) end,
register=function(...) register(setter,...) end,
list=function(...) list (setter,...) end,
show=function(...) show (setter,...) end,
@@ -7184,7 +7531,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["trac-log"] = package.loaded["trac-log"] or true
--- original size: 25613, stripped down to: 16617
+-- original size: 29359, stripped down to: 20483
if not modules then modules={} end modules ['trac-log']={
version=1.001,
@@ -7193,15 +7540,18 @@ if not modules then modules={} end modules ['trac-log']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
+local next,type,select,print=next,type,select,print
local write_nl,write=texio and texio.write_nl or print,texio and texio.write or io.write
local format,gmatch,find=string.format,string.gmatch,string.find
local concat,insert,remove=table.concat,table.insert,table.remove
local topattern=string.topattern
-local next,type,select=next,type,select
local utfchar=utf.char
+local datetime=os.date
+local openfile=io.open
local setmetatableindex=table.setmetatableindex
local formatters=string.formatters
local texgetcount=tex and tex.getcount
+local variant="default"
logs=logs or {}
local logs=logs
local moreinfo=[[
@@ -7211,32 +7561,122 @@ 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
]]
-utilities.strings.formatters.add (
+formatters.add (
formatters,"unichr",
[["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
)
-utilities.strings.formatters.add (
+formatters.add (
formatters,"chruni",
[[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
)
local function ignore() end
setmetatableindex(logs,function(t,k) t[k]=ignore;return ignore end)
local report,subreport,status,settarget,setformats,settranslations
-local direct,subdirect,writer,pushtarget,poptarget,setlogfile,settimedlog,setprocessor,setformatters
+local direct,subdirect,writer,pushtarget,poptarget,setlogfile,settimedlog,setprocessor,setformatters,newline
if tex and (tex.jobname or tex.formatname) then
- local valueiskey={ __index=function(t,k) t[k]=k return k end }
- local target="term and log"
+ local function useluawrites()
+ local texio_write_nl=texio.write_nl
+ local texio_write=texio.write
+ local io_write=io.write
+ write_nl=function(target,...)
+ if not io_write then
+ io_write=io.write
+ end
+ if target=="term and log" then
+ texio_write_nl("log",...)
+ texio_write_nl("term","")
+ io_write(...)
+ elseif target=="log" then
+ texio_write_nl("log",...)
+ elseif target=="term" then
+ texio_write_nl("term","")
+ io_write(...)
+ elseif target~="none" then
+ texio_write_nl("log",target,...)
+ texio_write_nl("term","")
+ io_write(target,...)
+ end
+ end
+ write=function(target,...)
+ if not io_write then
+ io_write=io.write
+ end
+ if target=="term and log" then
+ texio_write("log",...)
+ io_write(...)
+ elseif target=="log" then
+ texio_write("log",...)
+ elseif target=="term" then
+ io_write(...)
+ elseif target~="none" then
+ texio_write("log",target,...)
+ io_write(target,...)
+ end
+ end
+ texio.write=write
+ texio.write_nl=write_nl
+ useluawrites=ignore
+ end
+ local whereto="both"
+ local target=nil
+ local targets=nil
+ local formats=table.setmetatableindex("self")
+ local translations=table.setmetatableindex("self")
+ local report_yes,subreport_yes,direct_yes,subdirect_yes,status_yes
+ local report_nop,subreport_nop,direct_nop,subdirect_nop,status_nop
+ local variants={
+ default={
+ formats={
+ report_yes=formatters["%-15s > %s\n"],
+ report_nop=formatters["%-15s >\n"],
+ direct_yes=formatters["%-15s > %s"],
+ direct_nop=formatters["%-15s >"],
+ subreport_yes=formatters["%-15s > %s > %s\n"],
+ subreport_nop=formatters["%-15s > %s >\n"],
+ subdirect_yes=formatters["%-15s > %s > %s"],
+ subdirect_nop=formatters["%-15s > %s >"],
+ status_yes=formatters["%-15s : %s\n"],
+ status_nop=formatters["%-15s :\n"],
+ },
+ targets={
+ logfile="log",
+ log="log",
+ file="log",
+ console="term",
+ terminal="term",
+ both="term and log",
+ },
+ },
+ ansi={
+ formats={
+ report_yes=formatters["%-15s > %s\n"],
+ report_nop=formatters["%-15s >\n"],
+ direct_yes=formatters["%-15s > %s"],
+ direct_nop=formatters["%-15s >"],
+ subreport_yes=formatters["%-15s > %s > %s\n"],
+ subreport_nop=formatters["%-15s > %s >\n"],
+ subdirect_yes=formatters["%-15s > %s > %s"],
+ subdirect_nop=formatters["%-15s > %s >"],
+ status_yes=formatters["%-15s : %s\n"],
+ status_nop=formatters["%-15s :\n"],
+ },
+ targets={
+ logfile="none",
+ log="none",
+ file="none",
+ console="term",
+ terminal="term",
+ both="term",
+ },
+ }
+ }
logs.flush=io.flush
- local formats={} setmetatable(formats,valueiskey)
- local translations={} setmetatable(translations,valueiskey)
writer=function(...)
write_nl(target,...)
end
newline=function()
write_nl(target,"\n")
end
- local report_yes=formatters["%-15s > %s\n"]
- local report_nop=formatters["%-15s >\n"]
report=function(a,b,c,...)
if c then
write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...)))
@@ -7248,8 +7688,6 @@ if tex and (tex.jobname or tex.formatname) then
write_nl(target,"\n")
end
end
- local direct_yes=formatters["%-15s > %s"]
- local direct_nop=formatters["%-15s >"]
direct=function(a,b,c,...)
if c then
return direct_yes(translations[a],formatters[formats[b]](c,...))
@@ -7261,8 +7699,6 @@ if tex and (tex.jobname or tex.formatname) then
return ""
end
end
- local subreport_yes=formatters["%-15s > %s > %s\n"]
- local subreport_nop=formatters["%-15s > %s >\n"]
subreport=function(a,s,b,c,...)
if c then
write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...)))
@@ -7274,8 +7710,6 @@ if tex and (tex.jobname or tex.formatname) then
write_nl(target,"\n")
end
end
- local subdirect_yes=formatters["%-15s > %s > %s"]
- local subdirect_nop=formatters["%-15s > %s >"]
subdirect=function(a,s,b,c,...)
if c then
return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...))
@@ -7287,8 +7721,6 @@ if tex and (tex.jobname or tex.formatname) then
return ""
end
end
- local status_yes=formatters["%-15s : %s\n"]
- local status_nop=formatters["%-15s :\n"]
status=function(a,b,c,...)
if c then
write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...)))
@@ -7300,16 +7732,13 @@ if tex and (tex.jobname or tex.formatname) then
write_nl(target,"\n")
end
end
- local targets={
- logfile="log",
- log="log",
- file="log",
- console="term",
- terminal="term",
- both="term and log",
- }
- settarget=function(whereto)
- target=targets[whereto or "both"] or targets.both
+ settarget=function(askedwhereto)
+ whereto=askedwhereto or whereto or "both"
+ target=targets[whereto]
+ if not target then
+ whereto="both"
+ target=targets[whereto]
+ end
if target=="term" or target=="term and log" then
logs.flush=io.flush
else
@@ -7338,21 +7767,74 @@ if tex and (tex.jobname or tex.formatname) then
writeline(target,f(...))
end
end
- setformatters=function(f)
- report_yes=f.report_yes or report_yes
- report_nop=f.report_nop or report_nop
- subreport_yes=f.subreport_yes or subreport_yes
- subreport_nop=f.subreport_nop or subreport_nop
- direct_yes=f.direct_yes or direct_yes
- direct_nop=f.direct_nop or direct_nop
- subdirect_yes=f.subdirect_yes or subdirect_yes
- subdirect_nop=f.subdirect_nop or subdirect_nop
- status_yes=f.status_yes or status_yes
- status_nop=f.status_nop or status_nop
- end
+ setformatters=function(specification)
+ local t=nil
+ local f=nil
+ local d=variants.default
+ if not specification then
+ elseif type(specification)=="table" then
+ t=specification.targets
+ f=specification.formats or specification
+ else
+ local v=variants[specification]
+ if v then
+ t=v.targets
+ f=v.formats
+ variant=specification
+ end
+ end
+ targets=t or d.targets
+ target=targets[whereto] or target
+ if f then
+ d=d.formats
+ else
+ f=d.formats
+ d=f
+ end
+ setmetatableindex(f,d)
+ report_yes=f.report_yes
+ report_nop=f.report_nop
+ subreport_yes=f.subreport_yes
+ subreport_nop=f.subreport_nop
+ direct_yes=f.direct_yes
+ direct_nop=f.direct_nop
+ subdirect_yes=f.subdirect_yes
+ subdirect_nop=f.subdirect_nop
+ status_yes=f.status_yes
+ status_nop=f.status_nop
+ if variant=="ansi" then
+ useluawrites()
+ end
+ settarget(whereto)
+ end
+ setformatters(variant)
setlogfile=ignore
settimedlog=ignore
else
+ local report_yes,subreport_yes,status_yes
+ local report_nop,subreport_nop,status_nop
+ local variants={
+ default={
+ formats={
+ report_yes=formatters["%-15s | %s"],
+ report_nop=formatters["%-15s |"],
+ subreport_yes=formatters["%-15s | %s | %s"],
+ subreport_nop=formatters["%-15s | %s |"],
+ status_yes=formatters["%-15s : %s\n"],
+ status_nop=formatters["%-15s :\n"],
+ },
+ },
+ ansi={
+ formats={
+ report_yes=formatters["%-15s | %s"],
+ report_nop=formatters["%-15s |"],
+ subreport_yes=formatters["%-15s | %s | %s"],
+ subreport_nop=formatters["%-15s | %s |"],
+ status_yes=formatters["%-15s : %s\n"],
+ status_nop=formatters["%-15s :\n"],
+ },
+ },
+ }
logs.flush=ignore
writer=function(s)
write_nl(s)
@@ -7360,8 +7842,6 @@ else
newline=function()
write_nl("\n")
end
- local report_yes=formatters["%-15s | %s"]
- local report_nop=formatters["%-15s |"]
report=function(a,b,c,...)
if c then
write_nl(report_yes(a,formatters[b](c,...)))
@@ -7373,8 +7853,6 @@ else
write_nl("")
end
end
- local subreport_yes=formatters["%-15s | %s | %s"]
- local subreport_nop=formatters["%-15s | %s |"]
subreport=function(a,sub,b,c,...)
if c then
write_nl(subreport_yes(a,sub,formatters[b](c,...)))
@@ -7386,8 +7864,6 @@ else
write_nl("")
end
end
- local status_yes=formatters["%-15s : %s\n"]
- local status_nop=formatters["%-15s :\n"]
status=function(a,b,c,...)
if c then
write_nl(status_yes(a,formatters[b](c,...)))
@@ -7412,14 +7888,34 @@ else
writeline(f(s))
end
end
- setformatters=function(f)
- report_yes=f.report_yes or report_yes
- report_nop=f.report_nop or report_nop
- subreport_yes=f.subreport_yes or subreport_yes
- subreport_nop=f.subreport_nop or subreport_nop
- status_yes=f.status_yes or status_yes
- status_nop=f.status_nop or status_nop
- end
+ setformatters=function(specification)
+ local f=nil
+ local d=variants.default
+ if specification then
+ if type(specification)=="table" then
+ f=specification.formats or specification
+ else
+ local v=variants[specification]
+ if v then
+ f=v.formats
+ end
+ end
+ end
+ if f then
+ d=d.formats
+ else
+ f=d.formats
+ d=f
+ end
+ setmetatableindex(f,d)
+ report_yes=f.report_yes
+ report_nop=f.report_nop
+ subreport_yes=f.subreport_yes
+ subreport_nop=f.subreport_nop
+ status_yes=f.status_yes
+ status_nop=f.status_nop
+ end
+ setformatters(variant)
setlogfile=function(name,keepopen)
if name and name~="" then
local localtime=os.localtime
@@ -7672,13 +8168,13 @@ end
local simple=logs.reporter("comment")
logs.simple=simple
logs.simpleline=simple
-function logs.setprogram () end
-function logs.extendbanner() end
-function logs.reportlines () end
-function logs.reportbanner() end
-function logs.reportline () end
-function logs.simplelines () end
-function logs.help () end
+logs.setprogram=ignore
+logs.extendbanner=ignore
+logs.reportlines=ignore
+logs.reportbanner=ignore
+logs.reportline=ignore
+logs.simplelines=ignore
+logs.help=ignore
local Carg,C,lpegmatch=lpeg.Carg,lpeg.C,lpeg.match
local p_newline=lpeg.patterns.newline
local linewise=(
@@ -7755,10 +8251,11 @@ function logs.application(t)
end
return t
end
-function logs.system(whereto,process,jobname,category,...)
- local message=formatters["%s %s => %s => %s => %s\r"](os.date("%d/%m/%y %H:%m:%S"),process,jobname,category,format(...))
+local f_syslog=formatters["%s %s => %s => %s => %s\r"]
+function logs.system(whereto,process,jobname,category,fmt,arg,...)
+ local message=f_syslog(datetime("%d/%m/%y %H:%m:%S"),process,jobname,category,arg==nil and fmt or format(fmt,arg,...))
for i=1,10 do
- local f=io.open(whereto,"a")
+ local f=openfile(whereto,"a")
if f then
f:write(message)
f:close()
@@ -7820,7 +8317,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["trac-inf"] = package.loaded["trac-inf"] or true
--- original size: 7011, stripped down to: 5590
+-- original size: 6704, stripped down to: 5343
if not modules then modules={} end modules ['trac-inf']={
version=1.001,
@@ -7993,15 +8490,6 @@ function statistics.tracefunction(base,tag,...)
statistics.register(formatters["%s.%s"](tag,name),function() return serialize(stat,"calls") end)
end
end
-commands=commands or {}
-function commands.resettimer(name)
- resettiming(name or "whatever")
- starttiming(name or "whatever")
-end
-function commands.elapsedtime(name)
- stoptiming(name or "whatever")
- context(elapsedtime(name or "whatever"))
-end
end -- of closure
@@ -8568,7 +9056,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-tpl"] = package.loaded["util-tpl"] or true
--- original size: 6251, stripped down to: 3488
+-- original size: 7100, stripped down to: 3978
if not modules then modules={} end modules ['util-tpl']={
version=1.001,
@@ -8610,7 +9098,7 @@ local sqlescape=lpeg.replacer {
{ "\r\n","\\n" },
{ "\r","\\n" },
}
-local sqlquoted=lpeg.Cs(lpeg.Cc("'")*sqlescape*lpeg.Cc("'"))
+local sqlquoted=Cs(Cc("'")*sqlescape*Cc("'"))
lpegpatterns.sqlescape=sqlescape
lpegpatterns.sqlquoted=sqlquoted
local luaescape=lpegpatterns.luaescape
@@ -8633,12 +9121,24 @@ local quotedescapers={
local luaescaper=escapers.lua
local quotedluaescaper=quotedescapers.lua
local function replacekeyunquoted(s,t,how,recurse)
- local escaper=how and escapers[how] or luaescaper
- return escaper(replacekey(s,t,how,recurse))
+ if how==false then
+ return replacekey(s,t,how,recurse)
+ else
+ local escaper=how and escapers[how] or luaescaper
+ return escaper(replacekey(s,t,how,recurse))
+ end
end
local function replacekeyquoted(s,t,how,recurse)
- local escaper=how and quotedescapers[how] or quotedluaescaper
- return escaper(replacekey(s,t,how,recurse))
+ if how==false then
+ return replacekey(s,t,how,recurse)
+ else
+ local escaper=how and quotedescapers[how] or quotedluaescaper
+ return escaper(replacekey(s,t,how,recurse))
+ end
+end
+local function replaceoptional(l,m,r,t,how,recurse)
+ local v=t[l]
+ return v and v~="" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or ""
end
local single=P("%")
local double=P("%%")
@@ -8653,11 +9153,16 @@ local nolquoted=lquoted/''
local norquoted=rquoted/''
local nolquotedq=lquotedq/''
local norquotedq=rquotedq/''
-local key=nosingle*((C((1-nosingle )^1)*Carg(1)*Carg(2)*Carg(3))/replacekey )*nosingle
-local quoted=nolquotedq*((C((1-norquotedq)^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyquoted )*norquotedq
-local unquoted=nolquoted*((C((1-norquoted )^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyunquoted)*norquoted
+local noloptional=P("%?")/''
+local noroptional=P("?%")/''
+local nomoptional=P(":")/''
+local args=Carg(1)*Carg(2)*Carg(3)
+local key=nosingle*((C((1-nosingle )^1)*args)/replacekey )*nosingle
+local quoted=nolquotedq*((C((1-norquotedq )^1)*args)/replacekeyquoted )*norquotedq
+local unquoted=nolquoted*((C((1-norquoted )^1)*args)/replacekeyunquoted)*norquoted
+local optional=noloptional*((C((1-nomoptional)^1)*nomoptional*C((1-noroptional)^1)*args)/replaceoptional)*noroptional
local any=P(1)
- replacer=Cs((unquoted+quoted+escape+key+any)^0)
+ replacer=Cs((unquoted+quoted+escape+optional+key+any)^0)
local function replace(str,mapping,how,recurse)
if mapping and str then
return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
@@ -8696,7 +9201,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-env"] = package.loaded["util-env"] or true
--- original size: 8814, stripped down to: 5092
+-- original size: 8022, stripped down to: 5038
if not modules then modules={} end modules ['util-env']={
version=1.001,
@@ -8707,7 +9212,7 @@ if not modules then modules={} end modules ['util-env']={
}
local allocate,mark=utilities.storage.allocate,utilities.storage.mark
local format,sub,match,gsub,find=string.format,string.sub,string.match,string.gsub,string.find
-local unquoted,quoted=string.unquoted,string.quoted
+local unquoted,quoted,optionalquoted=string.unquoted,string.quoted,string.optionalquoted
local concat,insert,remove=table.concat,table.insert,table.remove
environment=environment or {}
local environment=environment
@@ -8820,24 +9325,14 @@ function environment.splitarguments(separator)
return before,after
end
function environment.reconstructcommandline(arg,noquote)
+ local resolveprefix=resolvers.resolve
arg=arg or environment.originalarguments
if noquote and #arg==1 then
- local a=arg[1]
- a=resolvers.resolve(a)
- a=unquoted(a)
- return a
+ return unquoted(resolveprefix and resolveprefix(arg[1]) or arg[1])
elseif #arg>0 then
local result={}
for i=1,#arg do
- local a=arg[i]
- a=resolvers.resolve(a)
- a=unquoted(a)
- a=gsub(a,'"','\\"')
- if find(a," ",1,true) then
- result[#result+1]=quoted(a)
- else
- result[#result+1]=a
- end
+ result[i]=optionalquoted(resolveprefix and resolveprefix(arg[i]) or resolveprefix)
end
return concat(result," ")
else
@@ -9046,7 +9541,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true
--- original size: 42614, stripped down to: 26694
+-- original size: 43882, stripped down to: 26870
if not modules then modules={} end modules ['lxml-tab']={
version=1.001,
@@ -9061,10 +9556,10 @@ if lpeg.setmaxstack then lpeg.setmaxstack(1000) end
xml=xml or {}
local xml=xml
local concat,remove,insert=table.concat,table.remove,table.insert
-local type,next,setmetatable,getmetatable,tonumber=type,next,setmetatable,getmetatable,tonumber
+local type,next,setmetatable,getmetatable,tonumber,rawset=type,next,setmetatable,getmetatable,tonumber,rawset
local lower,find,match,gsub=string.lower,string.find,string.match,string.gsub
local utfchar=utf.char
-local lpegmatch=lpeg.match
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
local P,S,R,C,V,C,Cs=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.C,lpeg.Cs
local formatters=string.formatters
xml.xmlns=xml.xmlns or {}
@@ -9226,9 +9721,10 @@ local function fromdec(s)
return formatters["d:%s"](s),true
end
end
-local rest=(1-P(";"))^0
-local many=P(1)^0
-local parsedentity=P("&")*(P("#x")*(rest/fromhex)+P("#")*(rest/fromdec))*P(";")*P(-1)+(P("#x")*(many/fromhex)+P("#")*(many/fromdec))
+local p_rest=(1-P(";"))^0
+local p_many=P(1)^0
+local p_char=lpegpatterns.utf8character
+local parsedentity=P("&")*(P("#x")*(p_rest/fromhex)+P("#")*(p_rest/fromdec))*P(";")*P(-1)+(P("#x")*(p_many/fromhex)+P("#")*(p_many/fromdec))
local predefined_unified={
[38]="&amp;",
[42]="&quot;",
@@ -9254,7 +9750,9 @@ local privates_u={
local privates_p={}
local privates_n={
}
-local escaped=utf.remapper(privates_u)
+local escaped=utf.remapper(privates_u,"dynamic")
+local unprivatized=utf.remapper(privates_p,"dynamic")
+xml.unprivatized=unprivatized
local function unescaped(s)
local p=privates_n[s]
if not p then
@@ -9267,9 +9765,7 @@ local function unescaped(s)
end
return p
end
-local unprivatized=utf.remapper(privates_p)
xml.privatetoken=unescaped
-xml.unprivatized=unprivatized
xml.privatecodes=privates_n
local function handle_hex_entity(str)
local h=hcache[str]
@@ -9422,7 +9918,7 @@ local valid=R('az','AZ','09')+S('_-.')
local name_yes=C(valid^1)*colon*C(valid^1)
local name_nop=C(P(true))*C(valid^1)
local name=name_yes+name_nop
-local utfbom=lpeg.patterns.utfbom
+local utfbom=lpegpatterns.utfbom
local spacing=C(space^0)
local anyentitycontent=(1-open-semicolon-space-close)^0
local hexentitycontent=R("AF","af","09")^0
@@ -9590,7 +10086,7 @@ local function _xmlconvert_(data,settings)
reported_attribute_errors,mt,errorhandler=nil,nil,nil
return result
end
-function xmlconvert(data,settings)
+local function xmlconvert(data,settings)
local ok,result=pcall(function() return _xmlconvert_(data,settings) end)
if ok then
return result
@@ -9682,14 +10178,17 @@ function xml.checkbom(root)
insert(dt,2,"\n" )
end
end
-local function verbose_element(e,handlers)
+local f_attribute=formatters['%s=%q']
+local function verbose_element(e,handlers,escape)
local handle=handlers.handle
local serialize=handlers.serialize
local ens,etg,eat,edt,ern=e.ns,e.tg,e.at,e.dt,e.rn
local ats=eat and next(eat) and {}
if ats then
+ local n=0
for k,v in next,eat do
- ats[#ats+1]=formatters['%s=%q'](k,escaped(v))
+ n=n+1
+ ats[n]=f_attribute(k,escaped(v))
end
end
if ern and trace_entities and ern~=ens then
@@ -10033,7 +10532,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true
--- original size: 48030, stripped down to: 30595
+-- original size: 48229, stripped down to: 30684
if not modules then modules={} end modules ['lxml-lpt']={
version=1.001,
@@ -10418,8 +10917,8 @@ local lp_builtin=P (
P("ns")/"ll.ns"
)*((spaces*P("(")*spaces*P(")"))/"")
local lp_attribute=(P("@")+P("attribute::"))/""*Cc("(ll.at and ll.at['")*((R("az","AZ")+S("-_:"))^1)*Cc("'])")
-lp_fastpos_p=P("+")^0*R("09")^1*P(-1)/"l==%0"
-lp_fastpos_n=P("-")*R("09")^1*P(-1)/"(%0<0 and (#list+%0==l))"
+local lp_fastpos_p=P("+")^0*R("09")^1*P(-1)/"l==%0"
+local lp_fastpos_n=P("-")*R("09")^1*P(-1)/"(%0<0 and (#list+%0==l))"
local lp_fastpos=lp_fastpos_n+lp_fastpos_p
local lp_reserved=C("and")+C("or")+C("not")+C("div")+C("mod")+C("true")+C("false")
local lp_lua_function=Cs((R("az","AZ","__")^1*(P(".")*R("az","AZ","__")^1)^1)*("("))/"%0"
@@ -10598,7 +11097,7 @@ local function nodesettostring(set,nodetest)
if not ns or ns=="" then ns="*" end
if not tg or tg=="" then tg="*" end
tg=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
- t[i]=(directive and tg) or format("not(%s)",tg)
+ t[#t+1]=(directive and tg) or format("not(%s)",tg)
end
if nodetest==false then
return format("not(%s)",concat(t,"|"))
@@ -10864,7 +11363,6 @@ expressions.print=function(...)
print(...)
return true
end
-expressions.contains=find
expressions.find=find
expressions.upper=upper
expressions.lower=lower
@@ -10886,6 +11384,9 @@ function expressions.contains(str,pattern)
end
return false
end
+function xml.expressions.idstring(str)
+ return type(str)=="string" and gsub(str,"^#","") or ""
+end
local function traverse(root,pattern,handle)
local collected=applylpath(root,pattern)
if collected then
@@ -11173,7 +11674,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["lxml-aux"] = package.loaded["lxml-aux"] or true
--- original size: 23804, stripped down to: 16817
+-- original size: 28225, stripped down to: 20125
if not modules then modules={} end modules ['lxml-aux']={
version=1.001,
@@ -11183,16 +11684,19 @@ if not modules then modules={} end modules ['lxml-aux']={
license="see context related readme files"
}
local trace_manipulations=false trackers.register("lxml.manipulations",function(v) trace_manipulations=v end)
+local trace_inclusions=false trackers.register("lxml.inclusions",function(v) trace_inclusions=v end)
local report_xml=logs.reporter("xml")
local xml=xml
-local xmlconvert,xmlcopy,xmlname=xml.convert,xml.copy,xml.name
+local xmlcopy,xmlname=xml.copy,xml.name
local xmlinheritedconvert=xml.inheritedconvert
local xmlapplylpath=xml.applylpath
local xmlfilter=xml.filter
-local type,setmetatable,getmetatable=type,setmetatable,getmetatable
+local type,next,setmetatable,getmetatable=type,next,setmetatable,getmetatable
local insert,remove,fastcopy,concat=table.insert,table.remove,table.fastcopy,table.concat
local gmatch,gsub,format,find,strip=string.gmatch,string.gsub,string.format,string.find,string.strip
local utfbyte=utf.byte
+local lpegmatch=lpeg.match
+local striplinepatterns=utilities.strings.striplinepatterns
local function report(what,pattern,c,e)
report_xml("%s element %a, root %a, position %a, index %a, pattern %a",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
end
@@ -11247,13 +11751,15 @@ end
function xml.each(root,pattern,handle,reverse)
local collected=xmlapplylpath(root,pattern)
if collected then
- if reverse then
- for c=#collected,1,-1 do
- handle(collected[c])
- end
- else
- for c=1,#collected do
- handle(collected[c])
+ if handle then
+ if reverse then
+ for c=#collected,1,-1 do
+ handle(collected[c])
+ end
+ else
+ for c=1,#collected do
+ handle(collected[c])
+ end
end
end
return collected
@@ -11309,6 +11815,7 @@ local function redo_ni(d)
end
end
end
+xml.reindex=redo_ni
local function xmltoelement(whatever,root)
if not whatever then
return nil
@@ -11360,8 +11867,16 @@ function xml.delete(root,pattern)
report('deleting',pattern,c,e)
end
local d=p.dt
- remove(d,e.ni)
- redo_ni(d)
+ local ni=e.ni
+ if ni<=#d then
+ if false then
+ p.dt[ni]=""
+ else
+ remove(d,ni)
+ redo_ni(d)
+ end
+ else
+ end
end
end
end
@@ -11481,28 +11996,40 @@ xml.insertafter=insert_element
xml.insertbefore=function(r,p,e) insert_element(r,p,e,true) end
xml.injectafter=inject_element
xml.injectbefore=function(r,p,e) inject_element(r,p,e,true) end
-local function include(xmldata,pattern,attribute,recursive,loaddata)
+local function include(xmldata,pattern,attribute,recursive,loaddata,level)
pattern=pattern or 'include'
loaddata=loaddata or io.loaddata
local collected=xmlapplylpath(xmldata,pattern)
if collected then
+ if not level then
+ level=1
+ end
for c=1,#collected do
local ek=collected[c]
local name=nil
local ekdt=ek.dt
local ekat=ek.at
- local epdt=ek.__p__.dt
+ local ekrt=ek.__p__
+ local epdt=ekrt.dt
if not attribute or attribute=="" then
name=(type(ekdt)=="table" and ekdt[1]) or ekdt
end
if not name then
for a in gmatch(attribute or "href","([^|]+)") do
name=ekat[a]
- if name then break end
+ if name then
+ break
+ end
+ end
+ end
+ local data=nil
+ if name and name~="" then
+ data=loaddata(name) or ""
+ if trace_inclusions then
+ report_xml("including %s bytes from %a at level %s by pattern %a and attribute %a (%srecursing)",#data,name,level,pattern,attribute or "",recursive and "" or "not ")
end
end
- local data=(name and name~="" and loaddata(name)) or ""
- if data=="" then
+ if not data or data=="" then
epdt[ek.ni]=""
elseif ekat["parse"]=="text" then
epdt[ek.ni]=xml.escaped(data)
@@ -11512,70 +12039,113 @@ local function include(xmldata,pattern,attribute,recursive,loaddata)
epdt[ek.ni]=""
else
if recursive then
- include(xi,pattern,attribute,recursive,loaddata)
+ include(xi,pattern,attribute,recursive,loaddata,level+1)
+ end
+ local child=xml.body(xi)
+ child.__p__=ekrt
+ child.__f__=name
+ epdt[ek.ni]=child
+ local inclusions=xmldata.settings.inclusions
+ if inclusions then
+ inclusions[#inclusions+1]=name
+ else
+ xmldata.settings.inclusions={ name }
end
- epdt[ek.ni]=xml.body(xi)
end
end
end
end
end
xml.include=include
+function xml.inclusion(e,default)
+ while e do
+ local f=e.__f__
+ if f then
+ return f
+ else
+ e=e.__p__
+ end
+ end
+ return default
+end
+function xml.inclusions(e,sorted)
+ while e do
+ local settings=e.settings
+ if settings then
+ local inclusions=settings.inclusions
+ if inclusions then
+ inclusions=table.unique(inclusions)
+ if sorted then
+ table.sort(inclusions)
+ end
+ return inclusions
+ else
+ e=e.__p__
+ end
+ else
+ e=e.__p__
+ end
+ end
+end
+local b_collapser=lpeg.patterns.b_collapser
+local m_collapser=lpeg.patterns.m_collapser
+local e_collapser=lpeg.patterns.e_collapser
+local b_stripper=lpeg.patterns.b_stripper
+local m_stripper=lpeg.patterns.m_stripper
+local e_stripper=lpeg.patterns.e_stripper
+local lpegmatch=lpeg.match
local function stripelement(e,nolines,anywhere)
local edt=e.dt
if edt then
- if anywhere then
- local t,n={},0
- for e=1,#edt do
+ local n=#edt
+ if n==0 then
+ return e
+ elseif anywhere then
+ local t={}
+ local m=0
+ for e=1,n do
local str=edt[e]
if type(str)~="string" then
- n=n+1
- t[n]=str
+ m=m+1
+ t[m]=str
elseif str~="" then
if nolines then
- str=gsub(str,"%s+"," ")
+ str=lpegmatch((n==1 and b_collapser) or (n==m and e_collapser) or m_collapser,str)
+ else
+ str=lpegmatch((n==1 and b_stripper) or (n==m and e_stripper) or m_stripper,str)
end
- str=gsub(str,"^%s*(.-)%s*$","%1")
if str~="" then
- n=n+1
- t[n]=str
+ m=m+1
+ t[m]=str
end
end
end
e.dt=t
else
- if #edt>0 then
- local str=edt[1]
- if type(str)~="string" then
- elseif str=="" then
+ local str=edt[1]
+ if type(str)=="string" then
+ if str~="" then
+ str=lpegmatch(nolines and b_collapser or b_stripper,str)
+ end
+ if str=="" then
remove(edt,1)
+ n=n-1
else
- if nolines then
- str=gsub(str,"%s+"," ")
- end
- str=gsub(str,"^%s+","")
- if str=="" then
- remove(edt,1)
- else
- edt[1]=str
- end
+ edt[1]=str
end
end
- local nedt=#edt
- if nedt>0 then
- local str=edt[nedt]
- if type(str)~="string" then
- elseif str=="" then
- remove(edt)
- else
- if nolines then
- str=gsub(str,"%s+"," ")
- end
- str=gsub(str,"%s+$","")
+ if n>0 then
+ str=edt[n]
+ if type(str)=="string" then
if str=="" then
remove(edt)
else
- edt[nedt]=str
+ str=lpegmatch(nolines and e_collapser or e_stripper,str)
+ if str=="" then
+ remove(edt)
+ else
+ edt[n]=str
+ end
end
end
end
@@ -11761,8 +12331,8 @@ function xml.finalizers.xml.cdata(collected)
end
return ""
end
-function xml.insertcomment(e,str,n)
- table.insert(e.dt,n or 1,{
+function xml.insertcomment(e,str,n)
+ insert(e.dt,n or 1,{
tg="@cm@",
ns="",
special=true,
@@ -11770,7 +12340,25 @@ function xml.insertcomment(e,str,n)
dt={ str },
})
end
-function xml.setcdata(e,str)
+function xml.insertcdata(e,str,n)
+ insert(e.dt,n or 1,{
+ tg="@cd@",
+ ns="",
+ special=true,
+ at={},
+ dt={ str },
+ })
+end
+function xml.setcomment(e,str,n)
+ e.dt={ {
+ tg="@cm@",
+ ns="",
+ special=true,
+ at={},
+ dt={ str },
+ } }
+end
+function xml.setcdata(e,str)
e.dt={ {
tg="@cd@",
ns="",
@@ -11840,7 +12428,7 @@ local function recurse(e,action)
for i=1,#edt do
local str=edt[i]
if type(str)~="string" then
- recurse(str,action,recursive)
+ recurse(str,action)
elseif str~="" then
edt[i]=action(str)
end
@@ -11858,6 +12446,65 @@ function helpers.recursetext(collected,action,recursive)
end
end
end
+local specials={
+ ["@rt@"]="root",
+ ["@pi@"]="instruction",
+ ["@cm@"]="comment",
+ ["@dt@"]="declaration",
+ ["@cd@"]="cdata",
+}
+local function convert(x,strip,flat)
+ local ns=x.ns
+ local tg=x.tg
+ local at=x.at
+ local dt=x.dt
+ local node=flat and {
+ [0]=(not x.special and (ns~="" and ns..":"..tg or tg)) or nil,
+ } or {
+ _namespace=ns~="" and ns or nil,
+ _tag=not x.special and tg or nil,
+ _type=specials[tg] or "_element",
+ }
+ if at then
+ for k,v in next,at do
+ node[k]=v
+ end
+ end
+ local n=0
+ for i=1,#dt do
+ local di=dt[i]
+ if type(di)=="table" then
+ if flat and di.special then
+ else
+ di=convert(di,strip,flat)
+ if di then
+ n=n+1
+ node[n]=di
+ end
+ end
+ elseif strip then
+ di=lpegmatch(strip,di)
+ if di~="" then
+ n=n+1
+ node[n]=di
+ end
+ else
+ n=n+1
+ node[n]=di
+ end
+ end
+ if next(node) then
+ return node
+ end
+end
+function xml.totable(x,strip,flat)
+ if type(x)=="table" then
+ if strip then
+ strip=striplinepatterns[strip]
+ end
+ return convert(x,strip,flat)
+ end
+end
end -- of closure
@@ -12414,7 +13061,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-ini"] = package.loaded["data-ini"] or true
--- original size: 7927, stripped down to: 5528
+-- original size: 11085, stripped down to: 7662
if not modules then modules={} end modules ['data-ini']={
version=1.001,
@@ -12423,14 +13070,15 @@ if not modules then modules={} end modules ['data-ini']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files",
}
+local next,type,getmetatable,rawset=next,type,getmetatable,rawset
local gsub,find,gmatch,char=string.gsub,string.find,string.gmatch,string.char
-local next,type=next,type
local filedirname,filebasename,filejoin=file.dirname,file.basename,file.join
+local ostype,osname,osuname,ossetenv,osgetenv=os.type,os.name,os.uname,os.setenv,os.getenv
+local P,S,R,C,Cs,Cc,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.match
local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
local trace_detail=false trackers.register("resolvers.details",function(v) trace_detail=v end)
local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
local report_initialization=logs.reporter("resolvers","initialization")
-local ostype,osname,ossetenv,osgetenv=os.type,os.name,os.setenv,os.getenv
resolvers=resolvers or {}
local resolvers=resolvers
texconfig.kpse_init=false
@@ -12563,10 +13211,103 @@ if type(profiler)=="table" and not jit then
profiler.start("luatex-profile.log")
end)
end
-if not resolvers.resolve then
- function resolvers.resolve (s) return s end
- function resolvers.unresolve(s) return s end
- function resolvers.repath (s) return s end
+local prefixes=utilities.storage.allocate()
+resolvers.prefixes=prefixes
+local resolved={}
+local abstract={}
+local dynamic={}
+function resolvers.resetresolve(str)
+ resolved,abstract={},{}
+end
+function resolvers.allprefixes(separator)
+ local all=table.sortedkeys(prefixes)
+ if separator then
+ for i=1,#all do
+ all[i]=all[i]..":"
+ end
+ end
+ return all
+end
+local function _resolve_(method,target)
+ local action=prefixes[method]
+ if action then
+ return action(target)
+ else
+ return method..":"..target
+ end
+end
+function resolvers.unresolve(str)
+ return abstract[str] or str
+end
+function resolvers.setdynamic(str)
+ dynamic[str]=true
+end
+local pattern=Cs((C(R("az")^2)*P(":")*C((1-S(" \"\';,"))^1)/_resolve_+P(1))^0)
+local prefix=C(R("az")^2)*P(":")
+local target=C((1-S(" \"\';,"))^1)
+local notarget=(#S(";,")+P(-1))*Cc("")
+local p_resolve=Cs(((prefix*(target+notarget))/_resolve_+P(1))^0)
+local p_simple=prefix*P(-1)
+local function resolve(str)
+ if type(str)=="table" then
+ local res={}
+ for i=1,#str do
+ res[i]=resolve(str[i])
+ end
+ return res
+ end
+ local res=resolved[str]
+ if res then
+ return res
+ end
+ local simple=lpegmatch(p_simple,str)
+ local action=prefixes[simple]
+ if action then
+ local res=action(res)
+ if not dynamic[simple] then
+ resolved[simple]=res
+ abstract[res]=simple
+ end
+ return res
+ end
+ res=lpegmatch(p_resolve,str)
+ resolved[str]=res
+ abstract[res]=str
+ return res
+end
+resolvers.resolve=resolve
+if type(osuname)=="function" then
+ for k,v in next,osuname() do
+ if not prefixes[k] then
+ prefixes[k]=function() return v end
+ end
+ end
+end
+if ostype=="unix" then
+ local pattern
+ local function makepattern(t,k,v)
+ if t then
+ rawset(t,k,v)
+ end
+ local colon=P(":")
+ for k,v in table.sortedpairs(prefixes) do
+ if p then
+ p=P(k)+p
+ else
+ p=P(k)
+ end
+ end
+ pattern=Cs((p*colon+colon/";"+P(1))^0)
+ end
+ makepattern()
+ table.setmetatablenewindex(prefixes,makepattern)
+ function resolvers.repath(str)
+ return lpegmatch(pattern,str)
+ end
+else
+ function resolvers.repath(str)
+ return str
+ end
end
@@ -12576,7 +13317,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-exp"] = package.loaded["data-exp"] or true
--- original size: 15317, stripped down to: 9723
+-- original size: 17216, stripped down to: 10657
if not modules then modules={} end modules ['data-exp']={
version=1.001,
@@ -12590,12 +13331,16 @@ local concat,sort=table.concat,table.sort
local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
local Ct,Cs,Cc,Carg,P,C,S=lpeg.Ct,lpeg.Cs,lpeg.Cc,lpeg.Carg,lpeg.P,lpeg.C,lpeg.S
local type,next=type,next
+local isdir=lfs.isdir
local ostype=os.type
-local collapsepath=file.collapsepath
+local collapsepath,joinpath,basename=file.collapsepath,file.join,file.basename
local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local trace_globbing=true trackers.register("resolvers.globbing",function(v) trace_globbing=v end)
local report_expansions=logs.reporter("resolvers","expansions")
+local report_globbing=logs.reporter("resolvers","globbing")
local resolvers=resolvers
+local resolveprefix=resolvers.resolve
local function f_both(a,b)
local t,n={},0
for sb in gmatch(b,"[^,]+") do
@@ -12685,35 +13430,27 @@ function resolvers.expandedpathfromlist(pathlist)
end
return newlist
end
-local cleanup=lpeg.replacer {
- { "!","" },
- { "\\","/" },
-}
-function resolvers.cleanpath(str)
- local doslashes=(P("\\")/"/"+1)^0
- local donegation=(P("!")/"" )^0
- local homedir=lpegmatch(Cs(donegation*doslashes),environment.homedir or "")
- if homedir=="~" or homedir=="" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if not str or find(str,"~",1,true) then
- return ""
- else
- return lpegmatch(cleanup,str)
+local usedhomedir=nil
+local donegation=(P("!")/"" )^0
+local doslashes=(P("\\")/"/"+1)^0
+local function expandedhome()
+ if not usedhomedir then
+ usedhomedir=lpegmatch(Cs(donegation*doslashes),environment.homedir or "")
+ if usedhomedir=="~" or usedhomedir=="" or not isdir(usedhomedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent path using current path")
end
- end
- else
- local dohome=((P("~")+P("$HOME"))/homedir)^0
- local cleanup=Cs(donegation*dohome*doslashes)
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str) or ""
+ usedhomedir="."
end
end
- return resolvers.cleanpath(str)
+ return usedhomedir
+end
+local dohome=((P("~")+P("$HOME")+P("%HOME%"))/expandedhome)^0
+local cleanup=Cs(donegation*dohome*doslashes)
+resolvers.cleanpath=function(str)
+ return str and lpegmatch(cleanup,str) or ""
end
-local expandhome=P("~")/"$HOME"
+local expandhome=P("~")/"$HOME"
local dodouble=P('"')/""*(expandhome+(1-P('"')))^0*P('"')/""
local dosingle=P("'")/""*(expandhome+(1-P("'")))^0*P("'")/""
local dostring=(expandhome+1 )^0
@@ -12765,46 +13502,67 @@ function resolvers.splitpath(str)
end
function resolvers.joinpath(str)
if type(str)=='table' then
- return file.joinpath(str)
+ return joinpath(str)
else
return str
end
end
local attributes,directory=lfs.attributes,lfs.dir
local weird=P(".")^1+lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local lessweird=P(".")^1+lpeg.anywhere(S("~`#$%^&*:;\"\'||<>,?\n\r\t"))
local timer={}
local scanned={}
local nofscans=0
local scancache={}
-local function scan(files,spec,path,n,m,r)
- local full=(path=="" and spec) or (spec..path..'/')
+local fullcache={}
+local nofsharedscans=0
+local function scan(files,remap,spec,path,n,m,r,onlyone,tolerant)
+ local full=path=="" and spec or (spec..path..'/')
local dirs={}
local nofdirs=0
+ local pattern=tolerant and lessweird or weird
for name in directory(full) do
- if not lpegmatch(weird,name) then
- local mode=attributes(full..name,'mode')
- if mode=='file' then
+ if not lpegmatch(pattern,name) then
+ local mode=attributes(full..name,"mode")
+ if mode=="file" then
n=n+1
- local f=files[name]
- if f then
- if type(f)=='string' then
- files[name]={ f,path }
+ local lower=lower(name)
+ local paths=files[lower]
+ if paths then
+ if onlyone then
else
- f[#f+1]=path
+ if type(paths)=="string" then
+ files[lower]={ paths,path }
+ else
+ paths[#paths+1]=path
+ end
+ if name~=lower then
+ local rl=remap[lower]
+ if not rl then
+ remap[lower]=name
+ r=r+1
+ elseif trace_globbing and rl~=name then
+ report_globbing("confusing filename, name: %a, lower: %a, already: %a",name,lower,rl)
+ end
+ end
end
else
- files[name]=path
- local lower=lower(name)
+ files[lower]=path
if name~=lower then
- files["remap:"..lower]=name
- r=r+1
+ local rl=remap[lower]
+ if not rl then
+ remap[lower]=name
+ r=r+1
+ elseif trace_globbing and rl~=name then
+ report_globbing("confusing filename, name: %a, lower: %a, already: %a",name,lower,rl)
+ end
end
end
- elseif mode=='directory' then
+ elseif mode=="directory" then
m=m+1
nofdirs=nofdirs+1
if path~="" then
- dirs[nofdirs]=path..'/'..name
+ dirs[nofdirs]=path.."/"..name
else
dirs[nofdirs]=name
end
@@ -12814,107 +13572,69 @@ local function scan(files,spec,path,n,m,r)
if nofdirs>0 then
sort(dirs)
for i=1,nofdirs do
- files,n,m,r=scan(files,spec,dirs[i],n,m,r)
+ files,remap,n,m,r=scan(files,remap,spec,dirs[i],n,m,r,onlyonce,tolerant)
end
end
scancache[sub(full,1,-2)]=files
- return files,n,m,r
+ return files,remap,n,m,r
end
-local fullcache={}
-function resolvers.scanfiles(path,branch,usecache)
- statistics.starttiming(timer)
- local realpath=resolvers.resolve(path)
+function resolvers.scanfiles(path,branch,usecache,onlyonce,tolerant)
+ local realpath=resolveprefix(path)
if usecache then
- local files=fullcache[realpath]
- if files then
+ local content=fullcache[realpath]
+ if content then
if trace_locating then
- report_expansions("using caches scan of path %a, branch %a",path,branch or path)
+ report_expansions("using cached scan of path %a, branch %a",path,branch or path)
end
- return files
+ nofsharedscans=nofsharedscans+1
+ return content
end
end
+ statistics.starttiming(timer)
if trace_locating then
report_expansions("scanning path %a, branch %a",path,branch or path)
end
- local files,n,m,r=scan({},realpath..'/',"",0,0,0)
- files.__path__=path
- files.__files__=n
- files.__directories__=m
- files.__remappings__=r
- if trace_locating then
- report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
- end
- if usecache then
- scanned[#scanned+1]=realpath
- fullcache[realpath]=files
- end
- nofscans=nofscans+1
- statistics.stoptiming(timer)
- return files
-end
-local function simplescan(files,spec,path)
- local full=(path=="" and spec) or (spec..path..'/')
- local dirs={}
- local nofdirs=0
- for name in directory(full) do
- if not lpegmatch(weird,name) then
- local mode=attributes(full..name,'mode')
- if mode=='file' then
- if not files[name] then
- files[name]=path
- end
- elseif mode=='directory' then
- nofdirs=nofdirs+1
- if path~="" then
- dirs[nofdirs]=path..'/'..name
- else
- dirs[nofdirs]=name
- end
- end
- end
- end
- if nofdirs>0 then
- sort(dirs)
- for i=1,nofdirs do
- files=simplescan(files,spec,dirs[i])
- end
- end
- return files
-end
-local simplecache={}
-local nofsharedscans=0
-function resolvers.simplescanfiles(path,branch,usecache)
- statistics.starttiming(timer)
- local realpath=resolvers.resolve(path)
- if usecache then
- local files=simplecache[realpath]
- if not files then
- files=scancache[realpath]
- if files then
- nofsharedscans=nofsharedscans+1
- end
+ local content
+ if isdir(realpath) then
+ local files,remap,n,m,r=scan({},{},realpath..'/',"",0,0,0,onlyonce,tolerant)
+ content={
+ metadata={
+ path=path,
+ files=n,
+ directories=m,
+ remappings=r,
+ },
+ files=files,
+ remap=remap,
+ }
+ if trace_locating then
+ report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
- if files then
- if trace_locating then
- report_expansions("using caches scan of path %a, branch %a",path,branch or path)
- end
- return files
+ else
+ content={
+ metadata={
+ path=path,
+ files=0,
+ directories=0,
+ remappings=0,
+ },
+ files={},
+ remap={},
+ }
+ if trace_locating then
+ report_expansions("invalid path %a",realpath)
end
end
- if trace_locating then
- report_expansions("scanning path %a, branch %a",path,branch or path)
- end
- local files=simplescan({},realpath..'/',"")
- if trace_locating then
- report_expansions("%s files found",table.count(files))
- end
if usecache then
scanned[#scanned+1]=realpath
- simplecache[realpath]=files
+ fullcache[realpath]=content
end
nofscans=nofscans+1
statistics.stoptiming(timer)
- return files
+ return content
+end
+function resolvers.simplescanfiles(path,branch,usecache)
+ return resolvers.scanfiles(path,branch,usecache,true,true)
end
function resolvers.scandata()
table.sort(scanned)
@@ -12925,6 +13645,52 @@ function resolvers.scandata()
paths=scanned,
}
end
+function resolvers.get_from_content(content,path,name)
+ if not content then
+ return
+ end
+ local files=content.files
+ if not files then
+ return
+ end
+ local remap=content.remap
+ if not remap then
+ return
+ end
+ if name then
+ local used=lower(name)
+ return path,remap[used] or used
+ else
+ local name=path
+ local used=lower(name)
+ local path=files[used]
+ if path then
+ return path,remap[used] or used
+ end
+ end
+end
+local nothing=function() end
+function resolvers.filtered_from_content(content,pattern)
+ if content and type(pattern)=="string" then
+ local pattern=lower(pattern)
+ local files=content.files
+ local remap=content.remap
+ if files and remap then
+ local n=next(files)
+ local function iterator()
+ while n do
+ local k=n
+ n=next(files,k)
+ if find(k,pattern) then
+ return files[k],remap and remap[k] or k
+ end
+ end
+ end
+ return iterator
+ end
+ end
+ return nothing
+end
end -- of closure
@@ -12933,7 +13699,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-env"] = package.loaded["data-env"] or true
--- original size: 8769, stripped down to: 6490
+-- original size: 9216, stripped down to: 6798
if not modules then modules={} end modules ['data-env']={
version=1.001,
@@ -12951,10 +13717,12 @@ local formats=allocate()
local suffixes=allocate()
local dangerous=allocate()
local suffixmap=allocate()
+local usertypes=allocate()
resolvers.formats=formats
resolvers.suffixes=suffixes
resolvers.dangerous=dangerous
resolvers.suffixmap=suffixmap
+resolvers.usertypes=usertypes
local luasuffixes=utilities.lua.suffixes
local relations=allocate {
core={
@@ -13022,11 +13790,13 @@ local relations=allocate {
names={ "mp" },
variable='MPINPUTS',
suffixes={ 'mp','mpvi','mpiv','mpii' },
+ usertype=true,
},
tex={
names={ "tex" },
variable='TEXINPUTS',
- suffixes={ 'tex',"mkvi","mkiv","mkii" },
+ suffixes={ "tex","mkvi","mkiv","mkii","cld","lfg","xml" },
+ usertype=true,
},
icc={
names={ "icc","icc profile","icc profiles" },
@@ -13042,6 +13812,7 @@ local relations=allocate {
names={ "lua" },
variable='LUAINPUTS',
suffixes={ luasuffixes.lua,luasuffixes.luc,luasuffixes.tma,luasuffixes.tmc },
+ usertype=true,
},
lib={
names={ "lib" },
@@ -13050,11 +13821,15 @@ local relations=allocate {
},
bib={
names={ 'bib' },
+ variable='BIBINPUTS',
suffixes={ 'bib' },
+ usertype=true,
},
bst={
names={ 'bst' },
+ variable='BSTINPUTS',
suffixes={ 'bst' },
+ usertype=true,
},
fontconfig={
names={ 'fontconfig','fontconfig file','fontconfig files' },
@@ -13136,8 +13911,9 @@ function resolvers.updaterelations()
for name,relation in next,categories do
local rn=relation.names
local rv=relation.variable
- local rs=relation.suffixes
if rn and rv then
+ local rs=relation.suffixes
+ local ru=relation.usertype
for i=1,#rn do
local rni=lower(gsub(rn[i]," ",""))
formats[rni]=rv
@@ -13149,8 +13925,9 @@ function resolvers.updaterelations()
end
end
end
- end
- if rs then
+ if ru then
+ usertypes[name]=true
+ end
end
end
end
@@ -13201,7 +13978,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-tmp"] = package.loaded["data-tmp"] or true
--- original size: 15532, stripped down to: 11648
+-- original size: 15681, stripped down to: 11761
if not modules then modules={} end modules ['data-tmp']={
version=1.100,
@@ -13220,6 +13997,7 @@ local trace_cache=false trackers.register("resolvers.cache",function(v) trace_ca
local report_caches=logs.reporter("resolvers","caches")
local report_resolvers=logs.reporter("resolvers","caching")
local resolvers=resolvers
+local cleanpath=resolvers.cleanpath
local directive_cleanup=false directives.register("system.compile.cleanup",function(v) directive_cleanup=v end)
local directive_strip=false directives.register("system.compile.strip",function(v) directive_strip=v end)
local compile=utilities.lua.compile
@@ -13241,7 +14019,7 @@ caches.relocate=false
caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" }
local writable,readables,usedreadables=nil,{},{}
local function identify()
- local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE")
+ local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE")
if texmfcaches then
for k=1,#texmfcaches do
local cachepath=texmfcaches[k]
@@ -13495,10 +14273,12 @@ local content_state={}
function caches.contentstate()
return content_state or {}
end
-function caches.loadcontent(cachename,dataname)
- local name=caches.hashed(cachename)
- local full,path=caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
- local filename=file.join(path,name)
+function caches.loadcontent(cachename,dataname,filename)
+ if not filename then
+ local name=caches.hashed(cachename)
+ local full,path=caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
+ filename=file.join(path,name)
+ end
local blob=loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
if blob then
local data=blob()
@@ -13530,10 +14310,12 @@ function caches.collapsecontent(content)
end
end
end
-function caches.savecontent(cachename,dataname,content)
- local name=caches.hashed(cachename)
- local full,path=caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
- local filename=file.join(path,name)
+function caches.savecontent(cachename,dataname,content,filename)
+ if not filename then
+ local name=caches.hashed(cachename)
+ local full,path=caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
+ filename=file.join(path,name)
+ end
local luaname=addsuffix(filename,luasuffixes.lua)
local lucname=addsuffix(filename,luasuffixes.luc)
if trace_locating then
@@ -13576,7 +14358,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-met"] = package.loaded["data-met"] or true
--- original size: 5460, stripped down to: 4014
+-- original size: 5347, stripped down to: 4015
if not modules then modules={} end modules ['data-met']={
version=1.100,
@@ -13604,7 +14386,7 @@ local function splitmethod(filename)
if type(filename)=="table" then
return filename
end
- filename=file.collapsepath(filename,".")
+ filename=file.collapsepath(filename,".")
if not find(filename,"://",1,true) then
return { scheme="file",path=filename,original=filename,filename=filename }
end
@@ -13695,7 +14477,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-res"] = package.loaded["data-res"] or true
--- original size: 62045, stripped down to: 43116
+-- original size: 67003, stripped down to: 46291
if not modules then modules={} end modules ['data-res']={
version=1.001,
@@ -13705,7 +14487,7 @@ if not modules then modules={} end modules ['data-res']={
license="see context related readme files",
}
local gsub,find,lower,upper,match,gmatch=string.gsub,string.find,string.lower,string.upper,string.match,string.gmatch
-local concat,insert,sortedkeys=table.concat,table.insert,table.sortedkeys
+local concat,insert,remove,sortedkeys,sortedhash=table.concat,table.insert,table.remove,table.sortedkeys,table.sortedhash
local next,type,rawget=next,type,rawget
local os=os
local P,S,R,C,Cc,Cs,Ct,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Carg
@@ -13714,17 +14496,23 @@ local formatters=string.formatters
local filedirname=file.dirname
local filebasename=file.basename
local suffixonly=file.suffixonly
+local addsuffix=file.addsuffix
+local removesuffix=file.removesuffix
local filejoin=file.join
local collapsepath=file.collapsepath
local joinpath=file.joinpath
+local is_qualified_path=file.is_qualified_path
local allocate=utilities.storage.allocate
local settings_to_array=utilities.parsers.settings_to_array
+local getcurrentdir=lfs.currentdir
+local isfile=lfs.isfile
+local isdir=lfs.isdir
local setmetatableindex=table.setmetatableindex
local luasuffixes=utilities.lua.suffixes
-local getcurrentdir=lfs.currentdir
local trace_locating=false trackers .register("resolvers.locating",function(v) trace_locating=v end)
local trace_detail=false trackers .register("resolvers.details",function(v) trace_detail=v end)
local trace_expansions=false trackers .register("resolvers.expansions",function(v) trace_expansions=v end)
+local trace_paths=false trackers .register("resolvers.paths",function(v) trace_paths=v end)
local resolve_otherwise=true directives.register("resolvers.otherwise",function(v) resolve_otherwise=v end)
local report_resolving=logs.reporter("resolvers","resolving")
local resolvers=resolvers
@@ -13732,10 +14520,14 @@ local expandedpathfromlist=resolvers.expandedpathfromlist
local checkedvariable=resolvers.checkedvariable
local splitconfigurationpath=resolvers.splitconfigurationpath
local methodhandler=resolvers.methodhandler
+local filtered=resolvers.filtered_from_content
+local lookup=resolvers.get_from_content
+local cleanpath=resolvers.cleanpath
+local resolveprefix=resolvers.resolve
local initializesetter=utilities.setters.initialize
local ostype,osname,osenv,ossetenv,osgetenv=os.type,os.name,os.env,os.setenv,os.getenv
-resolvers.cacheversion='1.0.1'
-resolvers.configbanner=''
+resolvers.cacheversion="1.100"
+resolvers.configbanner=""
resolvers.homedir=environment.homedir
resolvers.criticalvars=allocate { "SELFAUTOLOC","SELFAUTODIR","SELFAUTOPARENT","TEXMFCNF","TEXMF","TEXOS" }
resolvers.luacnfname="texmfcnf.lua"
@@ -13754,6 +14546,7 @@ end
local unset_variable="unset"
local formats=resolvers.formats
local suffixes=resolvers.suffixes
+local usertypes=resolvers.usertypes
local dangerous=resolvers.dangerous
local suffixmap=resolvers.suffixmap
resolvers.defaultsuffixes={ "tex" }
@@ -13762,7 +14555,7 @@ local instance=resolvers.instance or nil
function resolvers.setenv(key,value,raw)
if instance then
instance.environment[key]=value
- ossetenv(key,raw and value or resolvers.resolve(value))
+ ossetenv(key,raw and value or resolveprefix(value))
end
end
local function getenv(key)
@@ -13776,7 +14569,7 @@ local function getenv(key)
end
resolvers.getenv=getenv
resolvers.env=getenv
-local function resolve(k)
+local function resolvevariable(k)
return instance.expansions[k]
end
local dollarstripper=lpeg.stripper("$")
@@ -13785,19 +14578,19 @@ local backslashswapper=lpeg.replacer("\\","/")
local somevariable=P("$")/""
local somekey=C(R("az","AZ","09","__","--")^1)
local somethingelse=P(";")*((1-S("!{}/\\"))^1*P(";")/"")+P(";")*(P(";")/"")+P(1)
-local variableexpander=Cs((somevariable*(somekey/resolve)+somethingelse)^1 )
+local variableexpander=Cs((somevariable*(somekey/resolvevariable)+somethingelse)^1 )
local cleaner=P("\\")/"/"+P(";")*S("!{}/\\")^0*P(";")^1/";"
local variablecleaner=Cs((cleaner+P(1))^0)
-local somevariable=R("az","AZ","09","__","--")^1/resolve
+local somevariable=R("az","AZ","09","__","--")^1/resolvevariable
local variable=(P("$")/"")*(somevariable+(P("{")/"")*somevariable*(P("}")/""))
local variableresolver=Cs((variable+P(1))^0)
local function expandedvariable(var)
return lpegmatch(variableexpander,var) or var
end
-function resolvers.newinstance()
- if trace_locating then
+function resolvers.newinstance()
+ if trace_locating then
report_resolving("creating instance")
- end
+ end
local environment,variables,expansions,order=allocate(),allocate(),allocate(),allocate()
local newinstance={
environment=environment,
@@ -13810,6 +14603,7 @@ function resolvers.newinstance()
foundintrees=allocate(),
hashes=allocate(),
hashed=allocate(),
+ pathlists=false,
specification=allocate(),
lists=allocate(),
data=allocate(),
@@ -13822,6 +14616,7 @@ function resolvers.newinstance()
savelists=true,
pattern=nil,
force_suffixes=true,
+ pathstack={},
}
setmetatableindex(variables,function(t,k)
local v
@@ -13871,8 +14666,13 @@ function resolvers.reset()
end
local function reset_hashes()
instance.lists={}
+ instance.pathlists=false
instance.found={}
end
+local function reset_caches()
+ instance.lists={}
+ instance.pathlists=false
+end
local slash=P("/")
local pathexpressionpattern=Cs (
Cc("^")*(
@@ -13924,13 +14724,13 @@ local function identify_configuration_files()
for i=1,#cnfpaths do
local filepath=cnfpaths[i]
local filename=collapsepath(filejoin(filepath,luacnfname))
- local realname=resolvers.resolve(filename)
+ local realname=resolveprefix(filename)
if trace_locating then
- local fullpath=gsub(resolvers.resolve(collapsepath(filepath)),"//","/")
+ local fullpath=gsub(resolveprefix(collapsepath(filepath)),"//","/")
local weirdpath=find(fullpath,"/texmf.+/texmf") or not find(fullpath,"/web2c",1,true)
report_resolving("looking for %a on %s path %a from specification %a",luacnfname,weirdpath and "weird" or "given",fullpath,filepath)
end
- if lfs.isfile(realname) then
+ if isfile(realname) then
specification[#specification+1]=filename
if trace_locating then
report_resolving("found configuration file %a",realname)
@@ -13952,7 +14752,7 @@ local function load_configuration_files()
local filename=specification[i]
local pathname=filedirname(filename)
local filename=filejoin(pathname,luacnfname)
- local realname=resolvers.resolve(filename)
+ local realname=resolveprefix(filename)
local blob=loadfile(realname)
if blob then
local setups=instance.setups
@@ -13960,7 +14760,7 @@ local function load_configuration_files()
local parent=data and data.parent
if parent then
local filename=filejoin(pathname,parent)
- local realname=resolvers.resolve(filename)
+ local realname=resolveprefix(filename)
local blob=loadfile(realname)
if blob then
local parentdata=blob()
@@ -13985,7 +14785,7 @@ local function load_configuration_files()
elseif variables[k]==nil then
if trace_locating and not warning then
report_resolving("variables like %a in configuration file %a should move to the 'variables' subtable",
- k,resolvers.resolve(filename))
+ k,resolveprefix(filename))
warning=true
end
variables[k]=v
@@ -14045,7 +14845,7 @@ local function locate_file_databases()
local stripped=lpegmatch(inhibitstripper,path)
if stripped~="" then
local runtime=stripped==path
- path=resolvers.cleanpath(path)
+ path=cleanpath(path)
local spec=resolvers.splitmethod(stripped)
if runtime and (spec.noscheme or spec.scheme=="file") then
stripped="tree:///"..stripped
@@ -14108,8 +14908,8 @@ function resolvers.renew(hashname)
report_resolving("identifying tree %a",hashname)
end
end
- local realpath=resolvers.resolve(hashname)
- if lfs.isdir(realpath) then
+ local realpath=resolveprefix(hashname)
+ if isdir(realpath) then
if trace_locating then
report_resolving("using path %a",realpath)
end
@@ -14210,19 +15010,53 @@ end
function resolvers.unexpandedpath(str)
return joinpath(resolvers.unexpandedpathlist(str))
end
+function resolvers.pushpath(name)
+ local pathstack=instance.pathstack
+ local lastpath=pathstack[#pathstack]
+ local pluspath=filedirname(name)
+ if lastpath then
+ lastpath=collapsepath(filejoin(lastpath,pluspath))
+ else
+ lastpath=collapsepath(pluspath)
+ end
+ insert(pathstack,lastpath)
+ if trace_paths then
+ report_resolving("pushing path %a",lastpath)
+ end
+end
+function resolvers.poppath()
+ local pathstack=instance.pathstack
+ if trace_paths and #pathstack>0 then
+ report_resolving("popping path %a",pathstack[#pathstack])
+ end
+ remove(pathstack)
+end
+function resolvers.stackpath()
+ local pathstack=instance.pathstack
+ local currentpath=pathstack[#pathstack]
+ return currentpath~="" and currentpath or nil
+end
local done={}
function resolvers.resetextrapath()
local ep=instance.extra_paths
if not ep then
- ep,done={},{}
- instance.extra_paths=ep
+ done={}
+ instance.extra_paths={}
elseif #ep>0 then
- instance.lists,done={},{}
+ done={}
+ reset_caches()
end
end
function resolvers.registerextrapath(paths,subpaths)
- paths=settings_to_array(paths)
- subpaths=settings_to_array(subpaths)
+ if not subpaths or subpaths=="" then
+ if not paths or path=="" then
+ return
+ elseif done[paths] then
+ return
+ end
+ end
+ local paths=settings_to_array(paths)
+ local subpaths=settings_to_array(subpaths)
local ep=instance.extra_paths or {}
local oldn=#ep
local newn=oldn
@@ -14237,7 +15071,7 @@ function resolvers.registerextrapath(paths,subpaths)
local ps=p.."/"..s
if not done[ps] then
newn=newn+1
- ep[newn]=resolvers.cleanpath(ps)
+ ep[newn]=cleanpath(ps)
done[ps]=true
end
end
@@ -14247,7 +15081,7 @@ function resolvers.registerextrapath(paths,subpaths)
local p=paths[i]
if not done[p] then
newn=newn+1
- ep[newn]=resolvers.cleanpath(p)
+ ep[newn]=cleanpath(p)
done[p]=true
end
end
@@ -14259,7 +15093,7 @@ function resolvers.registerextrapath(paths,subpaths)
local ps=ep[i].."/"..s
if not done[ps] then
newn=newn+1
- ep[newn]=resolvers.cleanpath(ps)
+ ep[newn]=cleanpath(ps)
done[ps]=true
end
end
@@ -14268,52 +15102,70 @@ function resolvers.registerextrapath(paths,subpaths)
if newn>0 then
instance.extra_paths=ep
end
- if newn>oldn then
- instance.lists={}
+ if newn~=oldn then
+ reset_caches()
end
end
-local function made_list(instance,list)
- local ep=instance.extra_paths
- if not ep or #ep==0 then
- return list
+function resolvers.pushextrapath(path)
+ local paths=settings_to_array(path)
+ if instance.extra_stack then
+ insert(instance.extra_stack,1,paths)
else
- local done,new,newn={},{},0
- for k=1,#list do
- local v=list[k]
- if not done[v] then
- if find(v,"^[%.%/]$") then
- done[v]=true
- newn=newn+1
- new[newn]=v
- else
- break
- end
- end
- end
- for k=1,#ep do
- local v=ep[k]
+ instance.extra_stack={ paths }
+ end
+ reset_caches()
+end
+function resolvers.popextrapath()
+ if instance.extra_stack then
+ reset_caches()
+ return remove(instance.extra_stack,1)
+ end
+end
+local function made_list(instance,list,extra_too)
+ local done={}
+ local new={}
+ local newn=0
+ local function add(p)
+ for k=1,#p do
+ local v=p[k]
if not done[v] then
done[v]=true
newn=newn+1
new[newn]=v
end
end
- for k=1,#list do
- local v=list[k]
- if not done[v] then
- done[v]=true
- newn=newn+1
- new[newn]=v
+ end
+ for k=1,#list do
+ local v=list[k]
+ if done[v] then
+ elseif find(v,"^[%.%/]$") then
+ done[v]=true
+ newn=newn+1
+ new[newn]=v
+ else
+ break
+ end
+ end
+ if extra_too then
+ local es=instance.extra_stack
+ if es and #es>0 then
+ for k=1,#es do
+ add(es[k])
end
end
- return new
+ local ep=instance.extra_paths
+ if ep and #ep>0 then
+ add(ep)
+ end
end
+ add(list)
+ return new
end
function resolvers.cleanpathlist(str)
local t=resolvers.expandedpathlist(str)
if t then
for i=1,#t do
- t[i]=collapsepath(resolvers.cleanpath(t[i]))
+ t[i]=collapsepath(cleanpath(t[i]))
end
end
return t
@@ -14321,22 +15173,22 @@ end
function resolvers.expandpath(str)
return joinpath(resolvers.expandedpathlist(str))
end
-function resolvers.expandedpathlist(str)
+function resolvers.expandedpathlist(str,extra_too)
if not str then
return {}
- elseif instance.savelists then
+ elseif instance.savelists then
str=lpegmatch(dollarstripper,str)
local lists=instance.lists
local lst=lists[str]
if not lst then
- local l=made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
+ local l=made_list(instance,resolvers.splitpath(resolvers.expansion(str)),extra_too)
lst=expandedpathfromlist(l)
lists[str]=lst
end
return lst
else
local lst=resolvers.splitpath(resolvers.expansion(str))
- return made_list(instance,expandedpathfromlist(lst))
+ return made_list(instance,expandedpathfromlist(lst),extra_too)
end
end
function resolvers.expandedpathlistfromvariable(str)
@@ -14347,6 +15199,13 @@ end
function resolvers.expandpathfromvariable(str)
return joinpath(resolvers.expandedpathlistfromvariable(str))
end
+function resolvers.cleanedpathlist(v)
+ local t=resolvers.expandedpathlist(v)
+ for i=1,#t do
+ t[i]=resolvers.resolve(resolvers.cleanpath(t[i]))
+ end
+ return t
+end
function resolvers.expandbraces(str)
local ori=str
local pth=expandedpathfromlist(resolvers.splitpath(ori))
@@ -14363,7 +15222,7 @@ function resolvers.registerfilehash(name,content,someerror)
end
end
local function isreadable(name)
- local readable=lfs.isfile(name)
+ local readable=isfile(name)
if trace_detail then
if readable then
report_resolving("file %a is readable",name)
@@ -14373,70 +15232,57 @@ local function isreadable(name)
end
return readable
end
-local function collect_files(names)
- local filelist,noffiles={},0
+local function collect_files(names)
+ local filelist={}
+ local noffiles=0
+ local function check(hash,root,pathname,path,name)
+ if not pathname or find(path,pathname) then
+ local variant=hash.type
+ local search=filejoin(root,path,name)
+ local result=methodhandler('concatinators',variant,root,path,name)
+ if trace_detail then
+ report_resolving("match: variant %a, search %a, result %a",variant,search,result)
+ end
+ noffiles=noffiles+1
+ filelist[noffiles]={ variant,search,result }
+ end
+ end
for k=1,#names do
- local fname=names[k]
+ local filename=names[k]
if trace_detail then
- report_resolving("checking name %a",fname)
+ report_resolving("checking name %a",filename)
end
- local bname=filebasename(fname)
- local dname=filedirname(fname)
- if dname=="" or find(dname,"^%.") then
- dname=false
+ local basename=filebasename(filename)
+ local pathname=filedirname(filename)
+ if pathname=="" or find(pathname,"^%.") then
+ pathname=false
else
- dname=gsub(dname,"%*",".*")
- dname="/"..dname.."$"
+ pathname=gsub(pathname,"%*",".*")
+ pathname="/"..pathname.."$"
end
local hashes=instance.hashes
for h=1,#hashes do
local hash=hashes[h]
- local blobpath=hash.name
- local files=blobpath and instance.files[blobpath]
- if files then
+ local hashname=hash.name
+ local content=hashname and instance.files[hashname]
+ if content then
if trace_detail then
- report_resolving("deep checking %a, base %a, pattern %a",blobpath,bname,dname)
- end
- local blobfile=files[bname]
- if not blobfile then
- local rname="remap:"..bname
- blobfile=files[rname]
- if blobfile then
- bname=files[rname]
- blobfile=files[bname]
- end
+ report_resolving("deep checking %a, base %a, pattern %a",hashname,basename,pathname)
end
- if blobfile then
- local blobroot=files.__path__ or blobpath
- if type(blobfile)=='string' then
- if not dname or find(blobfile,dname) then
- local variant=hash.type
- local search=filejoin(blobroot,blobfile,bname)
- local result=methodhandler('concatinators',hash.type,blobroot,blobfile,bname)
- if trace_detail then
- report_resolving("match: variant %a, search %a, result %a",variant,search,result)
- end
- noffiles=noffiles+1
- filelist[noffiles]={ variant,search,result }
- end
+ local path,name=lookup(content,basename)
+ if path then
+ local metadata=content.metadata
+ local realroot=metadata and metadata.path or hashname
+ if type(path)=="string" then
+ check(hash,realroot,pathname,path,name)
else
- for kk=1,#blobfile do
- local vv=blobfile[kk]
- if not dname or find(vv,dname) then
- local variant=hash.type
- local search=filejoin(blobroot,vv,bname)
- local result=methodhandler('concatinators',hash.type,blobroot,vv,bname)
- if trace_detail then
- report_resolving("match: variant %a, search %a, result %a",variant,search,result)
- end
- noffiles=noffiles+1
- filelist[noffiles]={ variant,search,result }
- end
+ for i=1,#path do
+ check(hash,realroot,pathname,path[i],name)
end
end
end
elseif trace_locating then
- report_resolving("no match in %a (%s)",blobpath,bname)
+ report_resolving("no match in %a (%s)",hashname,basename)
end
end
end
@@ -14461,7 +15307,7 @@ end
local function can_be_dir(name)
local fakepaths=instance.fakepaths
if not fakepaths[name] then
- if lfs.isdir(name) then
+ if isdir(name) then
fakepaths[name]=1
else
fakepaths[name]=2
@@ -14477,10 +15323,11 @@ local function find_analyze(filename,askedformat,allresults)
if askedformat=="" then
if ext=="" or not suffixmap[ext] then
local defaultsuffixes=resolvers.defaultsuffixes
+ local formatofsuffix=resolvers.formatofsuffix
for i=1,#defaultsuffixes do
local forcedname=filename..'.'..defaultsuffixes[i]
wantedfiles[#wantedfiles+1]=forcedname
- filetype=resolvers.formatofsuffix(forcedname)
+ filetype=formatofsuffix(forcedname)
if trace_locating then
report_resolving("forcing filetype %a",filetype)
end
@@ -14520,14 +15367,14 @@ local function find_wildcard(filename,allresults)
if trace_locating then
report_resolving("checking wildcard %a",filename)
end
- local method,result=resolvers.findwildcardfiles(filename)
+ local result=resolvers.findwildcardfiles(filename)
if result then
return "wildcard",result
end
end
end
local function find_qualified(filename,allresults,askedformat,alsostripped)
- if not file.is_qualified_path(filename) then
+ if not is_qualified_path(filename) then
return
end
if trace_locating then
@@ -14601,33 +15448,66 @@ local function check_subpath(fname)
return fname
end
end
-local function find_intree(filename,filetype,wantedfiles,allresults)
+local function makepathlist(list,filetype)
local typespec=resolvers.variableofformat(filetype)
- local pathlist=resolvers.expandedpathlist(typespec)
- local method="intree"
+ local pathlist=resolvers.expandedpathlist(typespec,filetype and usertypes[filetype])
+ local entry={}
if pathlist and #pathlist>0 then
- local filelist=collect_files(wantedfiles)
+ for k=1,#pathlist do
+ local path=pathlist[k]
+ local prescanned=find(path,'^!!')
+ local resursive=find(path,'//$')
+ local pathname=lpegmatch(inhibitstripper,path)
+ local expression=makepathexpression(pathname)
+ local barename=gsub(pathname,"/+$","")
+ barename=resolveprefix(barename)
+ local scheme=url.hasscheme(barename)
+ local schemename=gsub(barename,"%.%*$",'')
+ entry[k]={
+ path=path,
+ pathname=pathname,
+ prescanned=prescanned,
+ recursive=recursive,
+ expression=expression,
+ barename=barename,
+ scheme=scheme,
+ schemename=schemename,
+ }
+ end
+ entry.typespec=typespec
+ list[filetype]=entry
+ else
+ list[filetype]=false
+ end
+ return entry
+end
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local pathlists=instance.pathlists
+ if not pathlists then
+ pathlists=setmetatableindex(allocate(),makepathlist)
+ instance.pathlists=pathlists
+ end
+ local pathlist=pathlists[filetype]
+ if pathlist then
+ local method="intree"
+ local filelist=collect_files(wantedfiles)
local dirlist={}
+ local result={}
if filelist then
for i=1,#filelist do
dirlist[i]=filedirname(filelist[i][3]).."/"
end
end
if trace_detail then
- report_resolving("checking filename %a",filename)
+ report_resolving("checking filename %a in tree",filename)
end
- local resolve=resolvers.resolve
- local result={}
for k=1,#pathlist do
- local path=pathlist[k]
- local pathname=lpegmatch(inhibitstripper,path)
- local doscan=path==pathname
- if not find (pathname,'//$') then
- doscan=false
- end
+ local entry=pathlist[k]
+ local path=entry.path
+ local pathname=entry.pathname
local done=false
if filelist then
- local expression=makepathexpression(pathname)
+ local expression=entry.expression
if trace_detail then
report_resolving("using pattern %a for path %a",expression,pathname)
end
@@ -14635,8 +15515,8 @@ local function find_intree(filename,filetype,wantedfiles,allresults)
local fl=filelist[k]
local f=fl[2]
local d=dirlist[k]
- if find(d,expression) or find(resolve(d),expression) then
- result[#result+1]=resolve(fl[3])
+ if find(d,expression) or find(resolveprefix(d),expression) then
+ result[#result+1]=resolveprefix(fl[3])
done=true
if allresults then
if trace_detail then
@@ -14657,56 +15537,62 @@ local function find_intree(filename,filetype,wantedfiles,allresults)
method="database"
else
method="filesystem"
- pathname=gsub(pathname,"/+$","")
- pathname=resolve(pathname)
- local scheme=url.hasscheme(pathname)
+ local scheme=entry.scheme
if not scheme or scheme=="file" then
- local pname=gsub(pathname,"%.%*$",'')
+ local pname=entry.schemename
if not find(pname,"*",1,true) then
if can_be_dir(pname) then
- for k=1,#wantedfiles do
- local w=wantedfiles[k]
- local fname=check_subpath(filejoin(pname,w))
- if fname then
- result[#result+1]=fname
- done=true
- if not allresults then
- break
- end
+ if not done and not entry.prescanned then
+ if trace_detail then
+ report_resolving("quick root scan for %a",pname)
end
- end
- if not done and doscan then
- local files=resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w=wantedfiles[k]
- local subpath=files[w]
- if not subpath or subpath=="" then
- elseif type(subpath)=="string" then
- local fname=check_subpath(filejoin(pname,subpath,w))
- if fname then
- result[#result+1]=fname
- done=true
- if not allresults then
- break
- end
+ local fname=check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
end
- else
- for i=1,#subpath do
- local sp=subpath[i]
- if sp=="" then
- else
- local fname=check_subpath(filejoin(pname,sp,w))
- if fname then
- result[#result+1]=fname
- done=true
- if not allresults then
- break
+ end
+ end
+ if not done and entry.recursive then
+ if trace_detail then
+ report_resolving("scanning filesystem for %a",pname)
+ end
+ local files=resolvers.simplescanfiles(pname,false,true)
+ for k=1,#wantedfiles do
+ local w=wantedfiles[k]
+ local subpath=files[w]
+ if not subpath or subpath=="" then
+ elseif type(subpath)=="string" then
+ local fname=check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp=subpath[i]
+ if sp=="" then
+ else
+ local fname=check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
end
end
end
- end
- if done and not allresults then
- break
+ if done and not allresults then
+ break
+ end
end
end
end
@@ -14714,6 +15600,18 @@ local function find_intree(filename,filetype,wantedfiles,allresults)
end
else
end
+ else
+ for k=1,#wantedfiles do
+ local pname=entry.barename
+ local fname=methodhandler('finders',pname.."/"..wantedfiles[k])
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
+ end
+ end
end
end
if done and not allresults then
@@ -14748,10 +15646,13 @@ local function find_otherwise(filename,filetype,wantedfiles,allresults)
local filelist=collect_files(wantedfiles)
local fl=filelist and filelist[1]
if fl then
- return "otherwise",{ resolvers.resolve(fl[3]) }
+ return "otherwise",{ resolveprefix(fl[3]) }
end
end
collect_instance_files=function(filename,askedformat,allresults)
+ if not filename or filename=="" then
+ return {}
+ end
askedformat=askedformat or ""
filename=collapsepath(filename,".")
filename=gsub(filename,"^%./",getcurrentdir().."/")
@@ -14786,7 +15687,11 @@ collect_instance_files=function(filename,askedformat,allresults)
else
local method,result,stamp,filetype,wantedfiles
if instance.remember then
- stamp=formatters["%s--%s"](filename,askedformat)
+ if askedformat=="" then
+ stamp=formatters["%s::%s"](suffixonly(filename),filename)
+ else
+ stamp=formatters["%s::%s"](askedformat,filename)
+ end
result=stamp and instance.found[stamp]
if result then
if trace_locating then
@@ -14821,7 +15726,7 @@ collect_instance_files=function(filename,askedformat,allresults)
end
if stamp then
if trace_locating then
- report_resolving("remembering file %a",filename)
+ report_resolving("remembering file %a using hash %a",filename,stamp)
end
instance.found[stamp]=result
end
@@ -14829,6 +15734,9 @@ collect_instance_files=function(filename,askedformat,allresults)
end
end
local function findfiles(filename,filetype,allresults)
+ if not filename or filename=="" then
+ return {}
+ end
local result,status=collect_instance_files(filename,filetype or "",allresults)
if not result or #result==0 then
local lowered=lower(filename)
@@ -14848,39 +15756,30 @@ function resolvers.findpath(filename,filetype)
return filedirname(findfiles(filename,filetype,false)[1] or "")
end
local function findgivenfiles(filename,allresults)
- local bname,result=filebasename(filename),{}
+ local base=filebasename(filename)
+ local result={}
local hashes=instance.hashes
- local noffound=0
+ local function okay(hash,path,name)
+ local found=methodhandler('concatinators',hash.type,hash.name,path,name)
+ if found and found~="" then
+ result[#result+1]=resolveprefix(found)
+ return not allresults
+ end
+ end
for k=1,#hashes do
local hash=hashes[k]
- local files=instance.files[hash.name] or {}
- local blist=files[bname]
- if not blist then
- local rname="remap:"..bname
- blist=files[rname]
- if blist then
- bname=files[rname]
- blist=files[bname]
- end
- end
- if blist then
- if type(blist)=='string' then
- local found=methodhandler('concatinators',hash.type,hash.name,blist,bname) or ""
- if found~="" then
- noffound=noffound+1
- result[noffound]=resolvers.resolve(found)
- if not allresults then
- break
- end
+ local content=instance.files[hash.name]
+ if content then
+ local path,name=lookup(content,base)
+ if not path then
+ elseif type(path)=="string" then
+ if okay(hash,path,name) then
+ return result
end
else
- for kk=1,#blist do
- local vv=blist[kk]
- local found=methodhandler('concatinators',hash.type,hash.name,vv,bname) or ""
- if found~="" then
- noffound=noffound+1
- result[noffound]=resolvers.resolve(found)
- if not allresults then break end
+ for i=1,#path do
+ if okay(hash,path[i],name) then
+ return result
end
end
end
@@ -14894,64 +15793,80 @@ end
function resolvers.findgivenfile(filename)
return findgivenfiles(filename,false)[1] or ""
end
-local function doit(path,blist,bname,tag,variant,result,allresults)
- local done=false
- if blist and variant then
- local resolve=resolvers.resolve
- if type(blist)=='string' then
- if find(lower(blist),path) then
- local full=methodhandler('concatinators',variant,tag,blist,bname) or ""
- result[#result+1]=resolve(full)
- done=true
- end
- else
- for kk=1,#blist do
- local vv=blist[kk]
- if find(lower(vv),path) then
- local full=methodhandler('concatinators',variant,tag,vv,bname) or ""
- result[#result+1]=resolve(full)
- done=true
- if not allresults then break end
- end
- end
- end
- end
- return done
-end
local makewildcard=Cs(
(P("^")^0*P("/")*P(-1)+P(-1))/".*"+(P("^")^0*P("/")/"")^0*(P("*")/".*"+P("-")/"%%-"+P(".")/"%%."+P("?")/"."+P("\\")/"/"+P(1))^0
)
function resolvers.wildcardpattern(pattern)
return lpegmatch(makewildcard,pattern) or pattern
end
-local function findwildcardfiles(filename,allresults,result)
- result=result or {}
+local function findwildcardfiles(filename,allresults,result)
+ local result=result or {}
local base=filebasename(filename)
local dirn=filedirname(filename)
local path=lower(lpegmatch(makewildcard,dirn) or dirn)
local name=lower(lpegmatch(makewildcard,base) or base)
- local files,done=instance.files,false
+ local files=instance.files
if find(name,"*",1,true) then
local hashes=instance.hashes
+ local function okay(found,path,base,hashname,hashtype)
+ if find(found,path) then
+ local full=methodhandler('concatinators',hashtype,hashname,found,base)
+ if full and full~="" then
+ result[#result+1]=resolveprefix(full)
+ return not allresults
+ end
+ end
+ end
for k=1,#hashes do
local hash=hashes[k]
- local hashname,hashtype=hash.name,hash.type
- for kk,hh in next,files[hashname] do
- if not find(kk,"^remap:") then
- if find(lower(kk),name) then
- if doit(path,hh,kk,hashname,hashtype,result,allresults) then done=true end
- if done and not allresults then break end
+ local hashname=hash.name
+ local hashtype=hash.type
+ if hashname and hashtype then
+ for found,base in filtered(files[hashname],name) do
+ if type(found)=='string' then
+ if okay(found,path,base,hashname,hashtype) then
+ break
+ end
+ else
+ for i=1,#found do
+ if okay(found[i],path,base,hashname,hashtype) then
+ break
+ end
+ end
end
end
end
end
else
+ local function okayokay(found,path,base,hashname,hashtype)
+ if find(found,path) then
+ local full=methodhandler('concatinators',hashtype,hashname,found,base)
+ if full and full~="" then
+ result[#result+1]=resolveprefix(full)
+ return not allresults
+ end
+ end
+ end
local hashes=instance.hashes
for k=1,#hashes do
local hash=hashes[k]
- local hashname,hashtype=hash.name,hash.type
- if doit(path,files[hashname][base],base,hashname,hashtype,result,allresults) then done=true end
- if done and not allresults then break end
+ local hashname=hash.name
+ local hashtype=hash.type
+ if hashname and hashtype then
+ local found,base=lookup(content,base)
+ if not found then
+ elseif type(found)=='string' then
+ if okay(found,path,base,hashname,hashtype) then
+ break
+ end
+ else
+ for i=1,#found do
+ if okay(found[i],path,base,hashname,hashtype) then
+ break
+ end
+ end
+ end
+ end
end
end
return result
@@ -15024,7 +15939,7 @@ end
function resolvers.dowithpath(name,func)
local pathlist=resolvers.expandedpathlist(name)
for i=1,#pathlist do
- func("^"..resolvers.cleanpath(pathlist[i]))
+ func("^"..cleanpath(pathlist[i]))
end
end
function resolvers.dowithvariable(name,func)
@@ -15032,23 +15947,23 @@ function resolvers.dowithvariable(name,func)
end
function resolvers.locateformat(name)
local engine=environment.ownmain or "luatex"
- local barename=file.removesuffix(name)
- local fullname=file.addsuffix(barename,"fmt")
+ local barename=removesuffix(name)
+ local fullname=addsuffix(barename,"fmt")
local fmtname=caches.getfirstreadablefile(fullname,"formats",engine) or ""
if fmtname=="" then
fmtname=resolvers.findfile(fullname)
- fmtname=resolvers.cleanpath(fmtname)
+ fmtname=cleanpath(fmtname)
end
if fmtname~="" then
- local barename=file.removesuffix(fmtname)
- local luaname=file.addsuffix(barename,luasuffixes.lua)
- local lucname=file.addsuffix(barename,luasuffixes.luc)
- local luiname=file.addsuffix(barename,luasuffixes.lui)
- if lfs.isfile(luiname) then
+ local barename=removesuffix(fmtname)
+ local luaname=addsuffix(barename,luasuffixes.lua)
+ local lucname=addsuffix(barename,luasuffixes.luc)
+ local luiname=addsuffix(barename,luasuffixes.lui)
+ if isfile(luiname) then
return barename,luiname
- elseif lfs.isfile(lucname) then
+ elseif isfile(lucname) then
return barename,lucname
- elseif lfs.isfile(luaname) then
+ elseif isfile(luaname) then
return barename,luaname
end
end
@@ -15070,29 +15985,24 @@ function resolvers.dowithfilesintree(pattern,handle,before,after)
local hash=hashes[i]
local blobtype=hash.type
local blobpath=hash.name
- if blobpath then
+ if blobtype and blobpath then
+ local total=0
+ local checked=0
+ local done=0
if before then
before(blobtype,blobpath,pattern)
end
- local files=instance.files[blobpath]
- local total,checked,done=0,0,0
- if files then
- for k,v in table.sortedhash(files) do
- total=total+1
- if find(k,"^remap:") then
- elseif find(k,pattern) then
- if type(v)=="string" then
- checked=checked+1
- if handle(blobtype,blobpath,v,k) then
- done=done+1
- end
- else
- checked=checked+#v
- for i=1,#v do
- if handle(blobtype,blobpath,v[i],k) then
- done=done+1
- end
- end
+ for path,name in filtered(instance.files[blobpath],pattern) do
+ if type(path)=="string" then
+ checked=checked+1
+ if handle(blobtype,blobpath,path,name) then
+ done=done+1
+ end
+ else
+ checked=checked+#path
+ for i=1,#path do
+ if handle(blobtype,blobpath,path[i],name) then
+ done=done+1
end
end
end
@@ -15103,8 +16013,8 @@ function resolvers.dowithfilesintree(pattern,handle,before,after)
end
end
end
-resolvers.obsolete=resolvers.obsolete or {}
-local obsolete=resolvers.obsolete
+local obsolete=resolvers.obsolete or {}
+resolvers.obsolete=obsolete
resolvers.find_file=resolvers.findfile obsolete.find_file=resolvers.findfile
resolvers.find_files=resolvers.findfiles obsolete.find_files=resolvers.findfiles
@@ -15115,7 +16025,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-pre"] = package.loaded["data-pre"] or true
--- original size: 6643, stripped down to: 4401
+-- original size: 3950, stripped down to: 2935
if not modules then modules={} end modules ['data-pre']={
version=1.001,
@@ -15125,44 +16035,51 @@ if not modules then modules={} end modules ['data-pre']={
license="see context related readme files"
}
local resolvers=resolvers
-local prefixes=utilities.storage.allocate()
-resolvers.prefixes=prefixes
-local cleanpath,findgivenfile,expansion=resolvers.cleanpath,resolvers.findgivenfile,resolvers.expansion
+local prefixes=resolvers.prefixes
+local cleanpath=resolvers.cleanpath
+local findgivenfile=resolvers.findgivenfile
+local expansion=resolvers.expansion
local getenv=resolvers.getenv
-local P,S,R,C,Cs,Cc,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.match
-local joinpath,basename,dirname=file.join,file.basename,file.dirname
-local getmetatable,rawset,type=getmetatable,rawset,type
+local basename=file.basename
+local dirname=file.dirname
+local joinpath=file.join
+local isfile=lfs.isfile
prefixes.environment=function(str)
return cleanpath(expansion(str))
end
-prefixes.relative=function(str,n)
- if io.exists(str) then
- elseif io.exists("./"..str) then
- str="./"..str
- else
- local p="../"
- for i=1,n or 2 do
- if io.exists(p..str) then
- str=p..str
- break
- else
- p=p.."../"
+local function relative(str,n)
+ if not isfile(str) then
+ local pstr="./"..str
+ if isfile(pstr) then
+ str=pstr
+ else
+ local p="../"
+ for i=1,n or 2 do
+ local pstr=p..str
+ if isfile(pstr) then
+ str=pstr
+ break
+ else
+ p=p.."../"
+ end
end
end
end
return cleanpath(str)
end
+local function locate(str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath(fullname~="" and fullname or str)
+end
+prefixes.relative=relative
+prefixes.locate=locate
prefixes.auto=function(str)
- local fullname=prefixes.relative(str)
- if not lfs.isfile(fullname) then
- fullname=prefixes.locate(str)
+ local fullname=relative(str)
+ if not isfile(fullname) then
+ fullname=locate(str)
end
return fullname
end
-prefixes.locate=function(str)
- local fullname=findgivenfile(str) or ""
- return cleanpath((fullname~="" and fullname) or str)
-end
prefixes.filename=function(str)
local fullname=findgivenfile(str) or ""
return cleanpath(basename((fullname~="" and fullname) or str))
@@ -15183,6 +16100,13 @@ end
prefixes.home=function(str)
return cleanpath(joinpath(getenv('HOME'),str))
end
+prefixes.env=prefixes.environment
+prefixes.rel=prefixes.relative
+prefixes.loc=prefixes.locate
+prefixes.kpse=prefixes.locate
+prefixes.full=prefixes.locate
+prefixes.file=prefixes.filename
+prefixes.path=prefixes.pathname
local function toppath()
local inputstack=resolvers.inputstack
if not inputstack then
@@ -15195,98 +16119,22 @@ local function toppath()
return pathname
end
end
-resolvers.toppath=toppath
-prefixes.toppath=function(str)
- return cleanpath(joinpath(toppath(),str))
-end
-prefixes.env=prefixes.environment
-prefixes.rel=prefixes.relative
-prefixes.loc=prefixes.locate
-prefixes.kpse=prefixes.locate
-prefixes.full=prefixes.locate
-prefixes.file=prefixes.filename
-prefixes.path=prefixes.pathname
-function resolvers.allprefixes(separator)
- local all=table.sortedkeys(prefixes)
- if separator then
- for i=1,#all do
- all[i]=all[i]..":"
- end
- end
- return all
-end
-local function _resolve_(method,target)
- local action=prefixes[method]
- if action then
- return action(target)
- else
- return method..":"..target
- end
-end
-local resolved,abstract={},{}
-function resolvers.resetresolve(str)
- resolved,abstract={},{}
-end
-local pattern=Cs((C(R("az")^2)*P(":")*C((1-S(" \"\';,"))^1)/_resolve_+P(1))^0)
-local prefix=C(R("az")^2)*P(":")
-local target=C((1-S(" \"\';,"))^1)
-local notarget=(#S(";,")+P(-1))*Cc("")
-local pattern=Cs(((prefix*(target+notarget))/_resolve_+P(1))^0)
-local function resolve(str)
- if type(str)=="table" then
- local t={}
- for i=1,#str do
- t[i]=resolve(str[i])
- end
- return t
+local function jobpath()
+ local path=resolvers.stackpath()
+ if not path or path=="" then
+ return "."
else
- local res=resolved[str]
- if not res then
- res=lpegmatch(pattern,str)
- resolved[str]=res
- abstract[res]=str
- end
- return res
- end
-end
-local function unresolve(str)
- return abstract[str] or str
-end
-resolvers.resolve=resolve
-resolvers.unresolve=unresolve
-if type(os.uname)=="function" then
- for k,v in next,os.uname() do
- if not prefixes[k] then
- prefixes[k]=function() return v end
- end
- end
-end
-if os.type=="unix" then
- local pattern
- local function makepattern(t,k,v)
- if t then
- rawset(t,k,v)
- end
- local colon=P(":")
- for k,v in table.sortedpairs(prefixes) do
- if p then
- p=P(k)+p
- else
- p=P(k)
- end
- end
- pattern=Cs((p*colon+colon/";"+P(1))^0)
- end
- makepattern()
- getmetatable(prefixes).__newindex=makepattern
- function resolvers.repath(str)
- return lpegmatch(pattern,str)
- end
-else
- function resolvers.repath(str)
- return str
+ return path
end
end
+resolvers.toppath=toppath
+resolvers.jobpath=jobpath
+prefixes.toppath=function(str) return cleanpath(joinpath(toppath(),str)) end
+prefixes.jobpath=function(str) return cleanpath(joinpath(jobpath(),str)) end
+resolvers.setdynamic("toppath")
+resolvers.setdynamic("jobpath")
+prefixes.jobfile=prefixes.jobpath
+resolvers.setdynamic("jobfile")
end -- of closure
@@ -15348,7 +16196,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-fil"] = package.loaded["data-fil"] or true
--- original size: 3801, stripped down to: 3231
+-- original size: 3863, stripped down to: 3310
if not modules then modules={} end modules ['data-fil']={
version=1.001,
@@ -15360,30 +16208,31 @@ if not modules then modules={} end modules ['data-fil']={
local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
local report_files=logs.reporter("resolvers","files")
local resolvers=resolvers
+local resolveprefix=resolvers.resolve
local finders,openers,loaders,savers=resolvers.finders,resolvers.openers,resolvers.loaders,resolvers.savers
local locators,hashers,generators,concatinators=resolvers.locators,resolvers.hashers,resolvers.generators,resolvers.concatinators
local checkgarbage=utilities.garbagecollector and utilities.garbagecollector.check
function locators.file(specification)
- local name=specification.filename
- local realname=resolvers.resolve(name)
+ local filename=specification.filename
+ local realname=resolveprefix(filename)
if realname and realname~='' and lfs.isdir(realname) then
if trace_locating then
- report_files("file locator %a found as %a",name,realname)
+ report_files("file locator %a found as %a",filename,realname)
end
- resolvers.appendhash('file',name,true)
+ resolvers.appendhash('file',filename,true)
elseif trace_locating then
- report_files("file locator %a not found",name)
+ report_files("file locator %a not found",filename)
end
end
function hashers.file(specification)
- local name=specification.filename
- local content=caches.loadcontent(name,'files')
- resolvers.registerfilehash(name,content,content==nil)
+ local pathname=specification.filename
+ local content=caches.loadcontent(pathname,'files')
+ resolvers.registerfilehash(pathname,content,content==nil)
end
function generators.file(specification)
- local path=specification.filename
- local content=resolvers.scanfiles(path,false,true)
- resolvers.registerfilehash(path,content,true)
+ local pathname=specification.filename
+ local content=resolvers.scanfiles(pathname,false,true)
+ resolvers.registerfilehash(pathname,content,true)
end
concatinators.file=file.join
function finders.file(specification,filetype)
@@ -15665,7 +16514,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-zip"] = package.loaded["data-zip"] or true
--- original size: 8489, stripped down to: 6757
+-- original size: 8772, stripped down to: 6841
if not modules then modules={} end modules ['data-zip']={
version=1.001,
@@ -15684,16 +16533,6 @@ zip.archives=zip.archives or {}
local archives=zip.archives
zip.registeredfiles=zip.registeredfiles or {}
local registeredfiles=zip.registeredfiles
-local limited=false
-directives.register("system.inputmode",function(v)
- if not limited then
- local i_limiter=io.i_limiter(v)
- if i_limiter then
- zip.open=i_limiter.protect(zip.open)
- limited=true
- end
- end
-end)
local function validzip(str)
if not find(str,"^zip://") then
return "zip:///"..str
@@ -15708,7 +16547,7 @@ function zip.openarchive(name)
local arch=archives[name]
if not arch then
local full=resolvers.findfile(name) or ""
- arch=(full~="" and zip.open(full)) or false
+ arch=full~="" and zip.open(full) or false
archives[name]=arch
end
return arch
@@ -15867,31 +16706,42 @@ function resolvers.usezipfile(archive)
end
end
function resolvers.registerzipfile(z,tree)
- local files,filter={},""
- if tree=="" then
- filter="^(.+)/(.-)$"
- else
- filter=format("^%s/(.+)/(.-)$",tree)
- end
+ local names={}
+ local files={}
+ local remap={}
+ local n=0
+ local filter=tree=="" and "^(.+)/(.-)$" or format("^%s/(.+)/(.-)$",tree)
+ local register=resolvers.registerfile
if trace_locating then
report_zip("registering: using filter %a",filter)
end
- local register,n=resolvers.registerfile,0
for i in z:files() do
- local path,name=match(i.filename,filter)
- if path then
- if name and name~='' then
- register(files,name,path)
- n=n+1
- else
+ local filename=i.filename
+ local path,name=match(filename,filter)
+ if not path then
+ n=n+1
+ register(names,filename,"")
+ local usedname=lower(filename)
+ files[usedname]=""
+ if usedname~=filename then
+ remap[usedname]=filename
end
- else
- register(files,i.filename,'')
+ elseif name and name~="" then
n=n+1
+ register(names,name,path)
+ local usedname=lower(name)
+ files[usedname]=path
+ if usedname~=name then
+ remap[usedname]=name
+ end
+ else
end
end
report_zip("registering: %s files registered",n)
- return files
+ return {
+ files=files,
+ remap=remap,
+ }
end
@@ -15901,7 +16751,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-tre"] = package.loaded["data-tre"] or true
--- original size: 2508, stripped down to: 2074
+-- original size: 8479, stripped down to: 5580
if not modules then modules={} end modules ['data-tre']={
version=1.001,
@@ -15910,42 +16760,64 @@ if not modules then modules={} end modules ['data-tre']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local find,gsub,format=string.find,string.gsub,string.format
+local find,gsub,lower=string.find,string.gsub,string.lower
+local basename,dirname,joinname=file.basename,file.dirname,file .join
+local globdir,isdir,isfile=dir.glob,lfs.isdir,lfs.isfile
+local P,lpegmatch=lpeg.P,lpeg.match
local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
local report_trees=logs.reporter("resolvers","trees")
local resolvers=resolvers
-local done,found,notfound={},{},resolvers.finders.notfound
-function resolvers.finders.tree(specification)
+local resolveprefix=resolvers.resolve
+local notfound=resolvers.finders.notfound
+local lookup=resolvers.get_from_content
+local collectors={}
+local found={}
+function resolvers.finders.tree(specification)
local spec=specification.filename
- local fnd=found[spec]
- if fnd==nil then
+ local okay=found[spec]
+ if okay==nil then
if spec~="" then
- local path,name=file.dirname(spec),file.basename(spec)
- if path=="" then path="." end
- local hash=done[path]
- if not hash then
- local pattern=path.."/*"
- hash=dir.glob(pattern)
- done[path]=hash
+ local path=dirname(spec)
+ local name=basename(spec)
+ if path=="" then
+ path="."
+ end
+ local names=collectors[path]
+ if not names then
+ local pattern=find(path,"/%*+$") and path or (path.."/*")
+ names=globdir(pattern)
+ collectors[path]=names
end
local pattern="/"..gsub(name,"([%.%-%+])","%%%1").."$"
- for k=1,#hash do
- local v=hash[k]
- if find(v,pattern) then
- found[spec]=v
- return v
+ for i=1,#names do
+ local fullname=names[i]
+ if find(fullname,pattern) then
+ found[spec]=fullname
+ return fullname
+ end
+ end
+ local pattern=lower(pattern)
+ for i=1,#names do
+ local fullname=lower(names[i])
+ if find(fullname,pattern) then
+ if isfile(fullname) then
+ found[spec]=fullname
+ return fullname
+ else
+ break
+ end
end
end
end
- fnd=notfound()
- found[spec]=fnd
+ okay=notfound()
+ found[spec]=okay
end
- return fnd
+ return okay
end
function resolvers.locators.tree(specification)
local name=specification.filename
- local realname=resolvers.resolve(name)
- if realname and realname~='' and lfs.isdir(realname) then
+ local realname=resolveprefix(name)
+ if realname and realname~='' and isdir(realname) then
if trace_locating then
report_trees("locator %a found",realname)
end
@@ -15956,16 +16828,110 @@ function resolvers.locators.tree(specification)
end
function resolvers.hashers.tree(specification)
local name=specification.filename
- if trace_locating then
- report_trees("analysing %a",name)
- end
+ report_trees("analyzing %a",name)
resolvers.methodhandler("hashers",name)
resolvers.generators.file(specification)
end
-resolvers.concatinators.tree=resolvers.concatinators.file
-resolvers.generators.tree=resolvers.generators.file
-resolvers.openers.tree=resolvers.openers.file
-resolvers.loaders.tree=resolvers.loaders.file
+local collectors={}
+local splitter=lpeg.splitat("/**/")
+local stripper=lpeg.replacer { [P("/")*P("*")^1*P(-1)]="" }
+table.setmetatableindex(collectors,function(t,k)
+ local rootname=lpegmatch(stripper,k)
+ local dataname=joinname(rootname,"dirlist")
+ local content=caches.loadcontent(dataname,"files",dataname)
+ if not content then
+ content=resolvers.scanfiles(rootname,nil,nil,false,true)
+ caches.savecontent(dataname,"files",content,dataname)
+ end
+ t[k]=content
+ return content
+end)
+local function checked(root,p,n)
+ if p then
+ if type(p)=="table" then
+ for i=1,#p do
+ local fullname=joinname(root,p[i],n)
+ if isfile(fullname) then
+ return fullname
+ end
+ end
+ else
+ local fullname=joinname(root,p,n)
+ if isfile(fullname) then
+ return fullname
+ end
+ end
+ end
+ return notfound()
+end
+local function resolve(specification)
+ local filename=specification.filename
+ if filename~="" then
+ local root,rest=lpegmatch(splitter,filename)
+ if root and rest then
+ local path,name=dirname(rest),basename(rest)
+ if name~=rest then
+ local content=collectors[root]
+ local p,n=lookup(content,name)
+ if not p then
+ return notfound()
+ end
+ local pattern=".*/"..path.."$"
+ local istable=type(p)=="table"
+ if istable then
+ for i=1,#p do
+ local pi=p[i]
+ if pi==path or find(pi,pattern) then
+ local fullname=joinname(root,pi,n)
+ if isfile(fullname) then
+ return fullname
+ end
+ end
+ end
+ elseif p==path or find(p,pattern) then
+ local fullname=joinname(root,p,n)
+ if isfile(fullname) then
+ return fullname
+ end
+ end
+ local queries=specification.queries
+ if queries and queries.option=="fileonly" then
+ return checked(root,p,n)
+ else
+ return notfound()
+ end
+ end
+ end
+ local path,name=dirname(filename),basename(filename)
+ local root=lpegmatch(stripper,path)
+ local content=collectors[path]
+ local p,n=lookup(content,name)
+ if p then
+ return checked(root,p,n)
+ end
+ end
+ return notfound()
+end
+resolvers.finders .dirlist=resolve
+resolvers.locators .dirlist=resolvers.locators .tree
+resolvers.hashers .dirlist=resolvers.hashers .tree
+resolvers.generators.dirlist=resolvers.generators.file
+resolvers.openers .dirlist=resolvers.openers .file
+resolvers.loaders .dirlist=resolvers.loaders .file
+function resolvers.finders.dirfile(specification)
+ local queries=specification.queries
+ if queries then
+ queries.option="fileonly"
+ else
+ specification.queries={ option="fileonly" }
+ end
+ return resolve(specification)
+end
+resolvers.locators .dirfile=resolvers.locators .dirlist
+resolvers.hashers .dirfile=resolvers.hashers .dirlist
+resolvers.generators.dirfile=resolvers.generators.dirlist
+resolvers.openers .dirfile=resolvers.openers .dirlist
+resolvers.loaders .dirfile=resolvers.loaders .dirlist
end -- of closure
@@ -15974,7 +16940,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-sch"] = package.loaded["data-sch"] or true
--- original size: 6213, stripped down to: 5160
+-- original size: 6569, stripped down to: 5304
if not modules then modules={} end modules ['data-sch']={
version=1.001,
@@ -16000,8 +16966,13 @@ directives.register("schemes.threshold",function(v) threshold=tonumber(v) or thr
function cleaners.none(specification)
return specification.original
end
-function cleaners.strip(specification)
- return (gsub(specification.original,"[^%a%d%.]+","-"))
+function cleaners.strip(specification)
+ local path,name=file.splitbase(specification.original)
+ if path=="" then
+ return (gsub(name,"[^%a%d%.]+","-"))
+ else
+ return (gsub((gsub(path,"%.","-").."-"..name),"[^%a%d%.]+","-"))
+ end
end
function cleaners.md5(specification)
return file.addsuffix(md5.hex(specification.original),file.suffix(specification.path))
@@ -16018,7 +16989,7 @@ end
local cached,loaded,reused,thresholds,handlers={},{},{},{},{}
local function runcurl(name,cachename)
local command="curl --silent --insecure --create-dirs --output "..cachename.." "..name
- os.spawn(command)
+ os.execute(command)
end
local function fetch(specification)
local original=specification.original
@@ -16150,7 +17121,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-lua"] = package.loaded["data-lua"] or true
--- original size: 4237, stripped down to: 3177
+-- original size: 4313, stripped down to: 3227
if not modules then modules={} end modules ['data-lua']={
version=1.001,
@@ -16159,7 +17130,7 @@ if not modules then modules={} end modules ['data-lua']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local resolvers,package=resolvers,package
+local package,lpeg=package,lpeg
local gsub=string.gsub
local concat=table.concat
local addsuffix=file.addsuffix
@@ -16170,9 +17141,11 @@ local luaformats={ 'TEXINPUTS','LUAINPUTS' }
local libformats={ 'CLUAINPUTS' }
local helpers=package.helpers or {}
local methods=helpers.methods or {}
+local resolvers=resolvers
+local resolveprefix=resolvers.resolve
+helpers.report=logs.reporter("resolvers","libraries")
trackers.register("resolvers.libraries",function(v) helpers.trace=v end)
trackers.register("resolvers.locating",function(v) helpers.trace=v end)
-helpers.report=logs.reporter("resolvers","libraries")
helpers.sequence={
"already loaded",
"preload table",
@@ -16187,7 +17160,7 @@ helpers.sequence={
}
local pattern=Cs(P("!")^0/""*(P("/")*P(-1)/"/"+P("/")^1/"/"+1)^0)
function helpers.cleanpath(path)
- return resolvers.resolve(lpegmatch(pattern,path))
+ return resolveprefix(lpegmatch(pattern,path))
end
local loadedaslib=helpers.loadedaslib
local getextraluapaths=package.extraluapaths
@@ -16324,7 +17297,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-tmf"] = package.loaded["data-tmf"] or true
--- original size: 2600, stripped down to: 1627
+-- original size: 2601, stripped down to: 1627
if not modules then modules={} end modules ['data-tmf']={
version=1.001,
@@ -16380,7 +17353,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-lst"] = package.loaded["data-lst"] or true
--- original size: 2654, stripped down to: 2301
+-- original size: 2734, stripped down to: 2354
if not modules then modules={} end modules ['data-lst']={
version=1.001,
@@ -16389,10 +17362,13 @@ if not modules then modules={} end modules ['data-lst']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local find,concat,upper,format=string.find,table.concat,string.upper,string.format
+local rawget,type,next=rawget,type,next
+local find,concat,upper=string.find,table.concat,string.upper
local fastcopy,sortedpairs=table.fastcopy,table.sortedpairs
-resolvers.listers=resolvers.listers or {}
local resolvers=resolvers
+local listers=resolvers.listers or {}
+resolvers.listers=listers
+local resolveprefix=resolvers.resolve
local report_lists=logs.reporter("resolvers","lists")
local function tabstr(str)
if type(str)=='table' then
@@ -16401,7 +17377,7 @@ local function tabstr(str)
return str
end
end
-function resolvers.listers.variables(pattern)
+function listers.variables(pattern)
local instance=resolvers.instance
local environment=instance.environment
local variables=instance.variables
@@ -16422,10 +17398,10 @@ function resolvers.listers.variables(pattern)
for key,value in sortedpairs(configured) do
if key~="" and (pattern=="" or find(upper(key),pattern)) then
report_lists(key)
- report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
- report_lists(" var: %s",tabstr(configured[key]) or "unset")
- report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
- report_lists(" res: %s",tabstr(resolvers.resolve(expansions[key])) or "unset")
+ report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
+ report_lists(" var: %s",tabstr(configured[key]) or "unset")
+ report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
+ report_lists(" res: %s",tabstr(resolveprefix(expansions[key])) or "unset")
end
end
instance.environment=fastcopy(env)
@@ -16433,15 +17409,15 @@ function resolvers.listers.variables(pattern)
instance.expansions=fastcopy(exp)
end
local report_resolved=logs.reporter("system","resolved")
-function resolvers.listers.configurations()
+function listers.configurations()
local configurations=resolvers.instance.specification
for i=1,#configurations do
- report_resolved("file : %s",resolvers.resolve(configurations[i]))
+ report_resolved("file : %s",resolveprefix(configurations[i]))
end
report_resolved("")
local list=resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))
for i=1,#list do
- local li=resolvers.resolve(list[i])
+ local li=resolveprefix(list[i])
if lfs.isdir(li) then
report_resolved("path - %s",li)
else
@@ -16746,7 +17722,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["luat-fmt"] = package.loaded["luat-fmt"] or true
--- original size: 5951, stripped down to: 4922
+-- original size: 5955, stripped down to: 4926
if not modules then modules={} end modules ['luat-fmt']={
version=1.001,
@@ -16834,7 +17810,7 @@ function environment.make_format(name)
end
local command=format("%s --ini %s --lua=%s %s %sdump",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform=="unix" and "\\\\" or "\\")
report_format("running command: %s\n",command)
- os.spawn(command)
+ os.execute(command)
local pattern=file.removesuffix(file.basename(usedluastub)).."-*.mem"
local mp=dir.glob(pattern)
if mp then
@@ -16869,7 +17845,7 @@ function environment.run_format(name,data,more)
else
local command=format("%s %s --fmt=%s --lua=%s %s %s",engine,primaryflags(),quoted(barename),quoted(luaname),quoted(data),more~="" and quoted(more) or "")
report_format("running command: %s",command)
- os.spawn(command)
+ os.execute(command)
end
end
end
@@ -16880,8 +17856,8 @@ end -- of closure
-- used libraries : l-lua.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-mrg.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua
-- skipped libraries : -
--- original bytes : 695180
--- stripped bytes : 246794
+-- original bytes : 739251
+-- stripped bytes : 264497
-- end library merge
@@ -17107,6 +18083,7 @@ local helpinfo = [[
<category name="basic">
<subcategory>
<flag name="script"><short>run an mtx script (lua prefered method) (<ref name="noquotes"/>), no script gives list</short></flag>
+ <flag name="evaluate"><short>run code passed on the commandline (between quotes)</short></flag>
<flag name="execute"><short>run a script or program (texmfstart method) (<ref name="noquotes"/>)</short></flag>
<flag name="resolve"><short>resolve prefixed arguments</short></flag>
<flag name="ctxlua"><short>run internally (using preloaded libs)</short></flag>
@@ -17132,6 +18109,7 @@ local helpinfo = [[
<flag name="verbose"><short>give a bit more info</short></flag>
<flag name="trackers" value="list"><short>enable given trackers</short></flag>
<flag name="progname" value="str"><short>format or backend</short></flag>
+ <flag name="systeminfo" value="str"><short>show current operating system, processor, etc</short></flag>
</subcategory>
<subcategory>
<flag name="edit"><short>launch editor with found file</short></flag>
@@ -17761,6 +18739,39 @@ function runners.associate(filename)
os.launch(filename)
end
+function runners.evaluate(code,filename) -- for Luigi
+ if code == "loop" then
+ while true do
+ io.write("> ")
+ local code = io.read()
+ if code ~= "" then
+ local temp = string.match(code,"^= (.*)$")
+ if temp then
+ code = "print("..temp..")"
+ end
+ local compiled, message = loadstring(code)
+ if type(compiled) ~= "function" then
+ io.write("! " .. (message or code).."\n")
+ else
+ io.write(compiled())
+ end
+ end
+ end
+ else
+ if type(code) ~= "string" or code == "" then
+ code = filename
+ end
+ if code ~= "" then
+ local compiled, message = loadstring(code)
+ if type(compiled) ~= "function" then
+ io.write("invalid lua code: " .. (message or code))
+ return
+ end
+ io.write(compiled())
+ end
+ end
+end
+
function runners.gethelp(filename)
local url = environment.argument("url")
if url and url ~= "" then
@@ -17772,6 +18783,15 @@ function runners.gethelp(filename)
end
end
+function runners.systeminfo()
+ report("architecture : %s",os.platform or "<unset>")
+ report("operating system : %s",os.name or "<unset>")
+ report("file architecture : %s",os.type or "<unset>")
+ report("binary path : %s",os.selfdir or "<unset>")
+ report("binary suffix : %s",os.binsuffix or "<unset>")
+ report("library suffix : %s",os.libsuffix or "<unset>")
+end
+
-- 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
-- ... later we will use the second half
@@ -17887,16 +18907,7 @@ end
if e_argument("ansi") then
- local formatters = string.formatters
-
- logs.setformatters {
- report_yes = formatters["%-15s | %s"],
- report_nop = formatters["%-15s |"],
- subreport_yes = formatters["%-15s | %s | %s"],
- subreport_nop = formatters["%-15s | %s |"],
- status_yes = formatters["%-15s : %s\n"],
- status_nop = formatters["%-15s :\n"],
- }
+ logs.setformatters("ansi")
local script = e_argument("script") or e_argument("scripts")
@@ -17921,6 +18932,10 @@ if e_argument("script") or e_argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
+elseif e_argument("evaluate") then
+
+ runners.evaluate(e_argument("evaluate"),filename)
+
elseif e_argument("selfmerge") then
-- embed used libraries
@@ -18213,6 +19228,10 @@ elseif e_argument("exporthelp") then
runners.loadbase()
application.export(e_argument("exporthelp"),filename)
+elseif e_argument("systeminfo") then
+
+ runners.systeminfo()
+
elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
diff --git a/Master/texmf-dist/scripts/context/stubs/unix/mtxrun b/Master/texmf-dist/scripts/context/stubs/unix/mtxrun
index 5cb5c8d2416..48a9a27a250 100755
--- a/Master/texmf-dist/scripts/context/stubs/unix/mtxrun
+++ b/Master/texmf-dist/scripts/context/stubs/unix/mtxrun
@@ -56,7 +56,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-lua"] = package.loaded["l-lua"] or true
--- original size: 3409, stripped down to: 1763
+-- original size: 3888, stripped down to: 2197
if not modules then modules={} end modules ['l-lua']={
version=1.001,
@@ -139,6 +139,13 @@ end
if lua then
lua.mask=load([[τεχ = 1]]) and "utf" or "ascii"
end
+local flush=io.flush
+if flush then
+ local execute=os.execute if execute then function os.execute(...) flush() return execute(...) end end
+ local exec=os.exec if exec then function os.exec (...) flush() return exec (...) end end
+ local spawn=os.spawn if spawn then function os.spawn (...) flush() return spawn (...) end end
+ local popen=io.popen if popen then function io.popen (...) flush() return popen (...) end end
+end
end -- of closure
@@ -437,7 +444,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true
--- original size: 29983, stripped down to: 16202
+-- original size: 36225, stripped down to: 19891
if not modules then modules={} end modules ['l-lpeg']={
version=1.001,
@@ -498,6 +505,8 @@ patterns.utfbom_16_le=utfbom_16_le
patterns.utfbom_8=utfbom_8
patterns.utf_16_be_nl=P("\000\r\000\n")+P("\000\r")+P("\000\n")
patterns.utf_16_le_nl=P("\r\000\n\000")+P("\r\000")+P("\n\000")
+patterns.utf_32_be_nl=P("\000\000\000\r\000\000\000\n")+P("\000\000\000\r")+P("\000\000\000\n")
+patterns.utf_32_le_nl=P("\r\000\000\000\n\000\000\000")+P("\r\000\000\000")+P("\n\000\000\000")
patterns.utf8one=R("\000\127")
patterns.utf8two=R("\194\223")*utf8next
patterns.utf8three=R("\224\239")*utf8next*utf8next
@@ -527,9 +536,21 @@ patterns.nonwhitespace=nonwhitespace
local stripper=spacer^0*C((spacer^0*nonspacer^1)^0)
local fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0)
local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0))
+local b_collapser=Cs(whitespace^0/""*(nonwhitespace^1+whitespace^1/" ")^0)
+local e_collapser=Cs((whitespace^1*P(-1)/""+nonwhitespace^1+whitespace^1/" ")^0)
+local m_collapser=Cs((nonwhitespace^1+whitespace^1/" ")^0)
+local b_stripper=Cs(spacer^0/""*(nonspacer^1+spacer^1/" ")^0)
+local e_stripper=Cs((spacer^1*P(-1)/""+nonspacer^1+spacer^1/" ")^0)
+local m_stripper=Cs((nonspacer^1+spacer^1/" ")^0)
patterns.stripper=stripper
patterns.fullstripper=fullstripper
patterns.collapser=collapser
+patterns.b_collapser=b_collapser
+patterns.m_collapser=m_collapser
+patterns.e_collapser=e_collapser
+patterns.b_stripper=b_stripper
+patterns.m_stripper=m_stripper
+patterns.e_stripper=e_stripper
patterns.lowercase=lowercase
patterns.uppercase=uppercase
patterns.letter=patterns.lowercase+patterns.uppercase
@@ -566,9 +587,12 @@ patterns.integer=sign^-1*digit^1
patterns.unsigned=digit^0*period*digit^1
patterns.float=sign^-1*patterns.unsigned
patterns.cunsigned=digit^0*comma*digit^1
+patterns.cpunsigned=digit^0*(period+comma)*digit^1
patterns.cfloat=sign^-1*patterns.cunsigned
+patterns.cpfloat=sign^-1*patterns.cpunsigned
patterns.number=patterns.float+patterns.integer
patterns.cnumber=patterns.cfloat+patterns.integer
+patterns.cpnumber=patterns.cpfloat+patterns.integer
patterns.oct=zero*octdigit^1
patterns.octal=patterns.oct
patterns.HEX=zero*P("X")*(digit+uppercase)^1
@@ -985,23 +1009,40 @@ function lpeg.append(list,pp,delayed,checked)
end
return p
end
+local p_false=P(false)
+local p_true=P(true)
local function make(t)
- local p
+ local function making(t)
+ local p=p_false
+ local keys=sortedkeys(t)
+ for i=1,#keys do
+ local k=keys[i]
+ if k~="" then
+ local v=t[k]
+ if v==true then
+ p=p+P(k)*p_true
+ elseif v==false then
+ else
+ p=p+P(k)*making(v)
+ end
+ end
+ end
+ if t[""] then
+ p=p+p_true
+ end
+ return p
+ end
+ local p=p_false
local keys=sortedkeys(t)
for i=1,#keys do
local k=keys[i]
- local v=t[k]
- if not p then
- if next(v) then
- p=P(k)*make(v)
- else
- p=P(k)
- end
- else
- if next(v) then
- p=p+P(k)*make(v)
+ if k~="" then
+ local v=t[k]
+ if v==true then
+ p=p+P(k)*p_true
+ elseif v==false then
else
- p=p+P(k)
+ p=p+P(k)*making(v)
end
end
end
@@ -1009,13 +1050,73 @@ local function make(t)
end
function lpeg.utfchartabletopattern(list)
local tree={}
- for i=1,#list do
- local t=tree
- for c in gmatch(list[i],".") do
- if not t[c] then
- t[c]={}
+ local n=#list
+ if n==0 then
+ for s in next,list do
+ local t=tree
+ local p,pk
+ for c in gmatch(s,".") do
+ if t==true then
+ t={ [c]=true,[""]=true }
+ p[pk]=t
+ p=t
+ t=false
+ elseif t==false then
+ t={ [c]=false }
+ p[pk]=t
+ p=t
+ t=false
+ else
+ local tc=t[c]
+ if not tc then
+ tc=false
+ t[c]=false
+ end
+ p=t
+ t=tc
+ end
+ pk=c
+ end
+ if t==false then
+ p[pk]=true
+ elseif t==true then
+ else
+ t[""]=true
+ end
+ end
+ else
+ for i=1,n do
+ local s=list[i]
+ local t=tree
+ local p,pk
+ for c in gmatch(s,".") do
+ if t==true then
+ t={ [c]=true,[""]=true }
+ p[pk]=t
+ p=t
+ t=false
+ elseif t==false then
+ t={ [c]=false }
+ p[pk]=t
+ p=t
+ t=false
+ else
+ local tc=t[c]
+ if not tc then
+ tc=false
+ t[c]=false
+ end
+ p=t
+ t=tc
+ end
+ pk=c
+ end
+ if t==false then
+ p[pk]=true
+ elseif t==true then
+ else
+ t[""]=true
end
- t=t[c]
end
end
return make(tree)
@@ -1055,6 +1156,65 @@ local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"")
local number=digit^1*(case_1+case_2)
local stripper=Cs((number+1)^0)
lpeg.patterns.stripzeros=stripper
+local byte_to_HEX={}
+local byte_to_hex={}
+local byte_to_dec={}
+local hex_to_byte={}
+for i=0,255 do
+ local H=format("%02X",i)
+ local h=format("%02x",i)
+ local d=format("%03i",i)
+ local c=char(i)
+ byte_to_HEX[c]=H
+ byte_to_hex[c]=h
+ byte_to_dec[c]=d
+ hex_to_byte[h]=c
+ hex_to_byte[H]=c
+end
+local hextobyte=P(2)/hex_to_byte
+local bytetoHEX=P(1)/byte_to_HEX
+local bytetohex=P(1)/byte_to_hex
+local bytetodec=P(1)/byte_to_dec
+local hextobytes=Cs(hextobyte^0)
+local bytestoHEX=Cs(bytetoHEX^0)
+local bytestohex=Cs(bytetohex^0)
+local bytestodec=Cs(bytetodec^0)
+patterns.hextobyte=hextobyte
+patterns.bytetoHEX=bytetoHEX
+patterns.bytetohex=bytetohex
+patterns.bytetodec=bytetodec
+patterns.hextobytes=hextobytes
+patterns.bytestoHEX=bytestoHEX
+patterns.bytestohex=bytestohex
+patterns.bytestodec=bytestodec
+function string.toHEX(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(bytestoHEX,s)
+ end
+end
+function string.tohex(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(bytestohex,s)
+ end
+end
+function string.todec(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(bytestodec,s)
+ end
+end
+function string.tobytes(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(hextobytes,s)
+ end
+end
end -- of closure
@@ -1082,7 +1242,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-string"] = package.loaded["l-string"] or true
--- original size: 5671, stripped down to: 2827
+-- original size: 5694, stripped down to: 2827
if not modules then modules={} end modules ['l-string']={
version=1.001,
@@ -1187,7 +1347,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-table"] = package.loaded["l-table"] or true
--- original size: 31860, stripped down to: 20846
+-- original size: 33830, stripped down to: 21894
if not modules then modules={} end modules ['l-table']={
version=1.001,
@@ -1230,11 +1390,12 @@ function table.keys(t)
end
end
local function compare(a,b)
- local ta,tb=type(a),type(b)
- if ta==tb then
+ local ta=type(a)
+ local tb=type(b)
+ if ta==tb and ta=="number" then
return a<b
else
- return tostring(a)<tostring(b)
+ return tostring(a)<tostring(b)
end
end
local function sortedkeys(tab)
@@ -1334,14 +1495,14 @@ local function sortedhash(t,cmp)
end
local n=0
local m=#s
- local function kv(s)
+ local function kv()
if n<m then
n=n+1
local k=s[n]
return k,t[k]
end
end
- return kv,s
+ return kv
else
return nothing
end
@@ -1506,7 +1667,7 @@ local function simple_table(t)
if tv=="number" then
nt=nt+1
if hexify then
- tt[nt]=format("0x%04X",v)
+ tt[nt]=format("0x%X",v)
else
tt[nt]=tostring(v)
end
@@ -1537,7 +1698,7 @@ local function do_serialize(root,name,depth,level,indexed)
local tn=type(name)
if tn=="number" then
if hexify then
- handle(format("%s[0x%04X]={",depth,name))
+ handle(format("%s[0x%X]={",depth,name))
else
handle(format("%s[%s]={",depth,name))
end
@@ -1554,7 +1715,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
end
end
- if root and next(root) then
+ if root and next(root)~=nil then
local first,last=nil,0
if compact then
last=#root
@@ -1576,7 +1737,7 @@ local function do_serialize(root,name,depth,level,indexed)
if compact and first and tk=="number" and k>=first and k<=last then
if tv=="number" then
if hexify then
- handle(format("%s 0x%04X,",depth,v))
+ handle(format("%s 0x%X,",depth,v))
else
handle(format("%s %s,",depth,v))
end
@@ -1587,7 +1748,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s %q,",depth,v))
end
elseif tv=="table" then
- if not next(v) then
+ if next(v)==nil then
handle(format("%s {},",depth))
elseif inline then
local st=simple_table(v)
@@ -1617,25 +1778,25 @@ local function do_serialize(root,name,depth,level,indexed)
elseif tv=="number" then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
+ handle(format("%s [0x%X]=0x%X,",depth,k,v))
else
handle(format("%s [%s]=%s,",depth,k,v))
end
elseif tk=="boolean" then
if hexify then
- handle(format("%s [%s]=0x%04X,",depth,k and "true" or "false",v))
+ handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v))
else
handle(format("%s [%s]=%s,",depth,k and "true" or "false",v))
end
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
if hexify then
- handle(format("%s %s=0x%04X,",depth,k,v))
+ handle(format("%s %s=0x%X,",depth,k,v))
else
handle(format("%s %s=%s,",depth,k,v))
end
else
if hexify then
- handle(format("%s [%q]=0x%04X,",depth,k,v))
+ handle(format("%s [%q]=0x%X,",depth,k,v))
else
handle(format("%s [%q]=%s,",depth,k,v))
end
@@ -1644,7 +1805,7 @@ local function do_serialize(root,name,depth,level,indexed)
if reduce and tonumber(v) then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,v))
+ handle(format("%s [0x%X]=%s,",depth,k,v))
else
handle(format("%s [%s]=%s,",depth,k,v))
end
@@ -1658,7 +1819,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,v))
+ handle(format("%s [0x%X]=%q,",depth,k,v))
else
handle(format("%s [%s]=%q,",depth,k,v))
end
@@ -1671,10 +1832,10 @@ local function do_serialize(root,name,depth,level,indexed)
end
end
elseif tv=="table" then
- if not next(v) then
+ if next(v)==nil then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]={},",depth,k))
+ handle(format("%s [0x%X]={},",depth,k))
else
handle(format("%s [%s]={},",depth,k))
end
@@ -1690,7 +1851,7 @@ local function do_serialize(root,name,depth,level,indexed)
if st then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
+ handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
end
@@ -1710,7 +1871,7 @@ local function do_serialize(root,name,depth,level,indexed)
elseif tv=="boolean" then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,v and "true" or "false"))
+ handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false"))
else
handle(format("%s [%s]=%s,",depth,k,v and "true" or "false"))
end
@@ -1726,7 +1887,7 @@ local function do_serialize(root,name,depth,level,indexed)
local f=getinfo(v).what=="C" and dump(dummy) or dump(v)
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=load(%q),",depth,k,f))
+ handle(format("%s [0x%X]=load(%q),",depth,k,f))
else
handle(format("%s [%s]=load(%q),",depth,k,f))
end
@@ -1741,7 +1902,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
+ handle(format("%s [0x%X]=%q,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%q,",depth,k,tostring(v)))
end
@@ -1795,7 +1956,7 @@ local function serialize(_handle,root,name,specification)
end
elseif tname=="number" then
if hexify then
- handle(format("[0x%04X]={",name))
+ handle(format("[0x%X]={",name))
else
handle("["..name.."]={")
end
@@ -1813,7 +1974,7 @@ local function serialize(_handle,root,name,specification)
local dummy=root._w_h_a_t_e_v_e_r_
root._w_h_a_t_e_v_e_r_=nil
end
- if next(root) then
+ if next(root)~=nil then
do_serialize(root,name,"",0)
end
end
@@ -1942,14 +2103,25 @@ local function identical(a,b)
end
table.identical=identical
table.are_equal=are_equal
-function table.compact(t)
- if t then
- for k,v in next,t do
- if not next(v) then
- t[k]=nil
+local function sparse(old,nest,keeptables)
+ local new={}
+ for k,v in next,old do
+ if not (v=="" or v==false) then
+ if nest and type(v)=="table" then
+ v=sparse(v,nest)
+ if keeptables or next(v)~=nil then
+ new[k]=v
+ end
+ else
+ new[k]=v
end
end
end
+ return new
+end
+table.sparse=sparse
+function table.compact(t)
+ return sparse(t,true,true)
end
function table.contains(t,v)
if t then
@@ -2054,10 +2226,10 @@ function table.sub(t,i,j)
return { unpack(t,i,j) }
end
function table.is_empty(t)
- return not t or not next(t)
+ return not t or next(t)==nil
end
function table.has_one_entry(t)
- return t and not next(t,next(t))
+ return t and next(t,next(t))==nil
end
function table.loweredkeys(t)
local l={}
@@ -2102,6 +2274,44 @@ function table.values(t,s)
return {}
end
end
+function table.filtered(t,pattern,sort,cmp)
+ if t and type(pattern)=="string" then
+ if sort then
+ local s
+ if cmp then
+ s=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
+ else
+ s=sortedkeys(t)
+ end
+ local n=0
+ local m=#s
+ local function kv(s)
+ while n<m do
+ n=n+1
+ local k=s[n]
+ if find(k,pattern) then
+ return k,t[k]
+ end
+ end
+ end
+ return kv,s
+ else
+ local n=next(t)
+ local function iterator()
+ while n~=nil do
+ local k=n
+ n=next(t,k)
+ if find(k,pattern) then
+ return k,t[k]
+ end
+ end
+ end
+ return iterator,t
+ end
+ else
+ return nothing
+ end
+end
end -- of closure
@@ -2110,7 +2320,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-io"] = package.loaded["l-io"] or true
--- original size: 8824, stripped down to: 6347
+-- original size: 8643, stripped down to: 6232
if not modules then modules={} end modules ['l-io']={
version=1.001,
@@ -2417,8 +2627,6 @@ function io.readstring(f,n,m)
local str=gsub(f:read(n),"\000","")
return str
end
-if not io.i_limiter then function io.i_limiter() end end
-if not io.o_limiter then function io.o_limiter() end end
end -- of closure
@@ -2645,7 +2853,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-os"] = package.loaded["l-os"] or true
--- original size: 16093, stripped down to: 9704
+-- original size: 15761, stripped down to: 9403
if not modules then modules={} end modules ['l-os']={
version=1.001,
@@ -2719,13 +2927,10 @@ if not os.__getenv__ then
setmetatable(os.env,{ __index=__index,__newindex=__newindex } )
end
end
-local execute,spawn,exec,iopopen,ioflush=os.execute,os.spawn or os.execute,os.exec or os.execute,io.popen,io.flush
-function os.execute(...) ioflush() return execute(...) end
-function os.spawn (...) ioflush() return spawn (...) end
-function os.exec (...) ioflush() return exec (...) end
-function io.popen (...) ioflush() return iopopen(...) end
+local execute=os.execute
+local iopopen=io.popen
function os.resultof(command)
- local handle=io.popen(command,"r")
+ local handle=iopopen(command,"r")
if handle then
local result=handle:read("*all") or ""
handle:close()
@@ -2754,7 +2959,7 @@ local launchers={
unix="$BROWSER %s &> /dev/null &",
}
function os.launch(str)
- os.execute(format(launchers[os.name] or launchers.unix,str))
+ execute(format(launchers[os.name] or launchers.unix,str))
end
if not os.times then
function os.times()
@@ -3029,7 +3234,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-file"] = package.loaded["l-file"] or true
--- original size: 18308, stripped down to: 9948
+-- original size: 20949, stripped down to: 9945
if not modules then modules={} end modules ['l-file']={
version=1.001,
@@ -3043,41 +3248,28 @@ local file=file
if not lfs then
lfs=optionalrequire("lfs")
end
-if not lfs then
- lfs={
- getcurrentdir=function()
- return "."
- end,
- attributes=function()
- return nil
- end,
- isfile=function(name)
- local f=io.open(name,'rb')
- if f then
- f:close()
- return true
- end
- end,
- isdir=function(name)
- print("you need to load lfs")
- return false
- end
- }
-elseif not lfs.isfile then
- local attributes=lfs.attributes
- function lfs.isdir(name)
- return attributes(name,"mode")=="directory"
- end
- function lfs.isfile(name)
- return attributes(name,"mode")=="file"
- end
-end
local insert,concat=table.insert,table.concat
local match,find,gmatch=string.match,string.find,string.gmatch
local lpegmatch=lpeg.match
local getcurrentdir,attributes=lfs.currentdir,lfs.attributes
local checkedsplit=string.checkedsplit
local P,R,S,C,Cs,Cp,Cc,Ct=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cp,lpeg.Cc,lpeg.Ct
+local tricky=S("/\\")*P(-1)
+local attributes=lfs.attributes
+if sandbox then
+ sandbox.redefine(lfs.isfile,"lfs.isfile")
+ sandbox.redefine(lfs.isdir,"lfs.isdir")
+end
+function lfs.isdir(name)
+ if lpegmatch(tricky,name) then
+ return attributes(name,"mode")=="directory"
+ else
+ return attributes(name.."/.","mode")=="directory"
+ end
+end
+function lfs.isfile(name)
+ return attributes(name,"mode")=="file"
+end
local colon=P(":")
local period=P(".")
local periods=P("..")
@@ -3279,28 +3471,30 @@ local isroot=fwslash^1*-1
local hasroot=fwslash^1
local reslasher=lpeg.replacer(S("\\/"),"/")
local deslasher=lpeg.replacer(S("\\/")^1,"/")
-function file.join(...)
- local lst={... }
- local one=lst[1]
+function file.join(one,two,three,...)
+ if not two then
+ return one=="" and one or lpegmatch(stripper,one)
+ end
+ if one=="" then
+ return lpegmatch(stripper,three and concat({ two,three,... },"/") or two)
+ end
if lpegmatch(isnetwork,one) then
local one=lpegmatch(reslasher,one)
- local two=lpegmatch(deslasher,concat(lst,"/",2))
+ local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two)
if lpegmatch(hasroot,two) then
return one..two
else
return one.."/"..two
end
elseif lpegmatch(isroot,one) then
- local two=lpegmatch(deslasher,concat(lst,"/",2))
+ local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two)
if lpegmatch(hasroot,two) then
return two
else
return "/"..two
end
- elseif one=="" then
- return lpegmatch(stripper,concat(lst,"/",2))
else
- return lpegmatch(deslasher,concat(lst,"/"))
+ return lpegmatch(deslasher,concat({ one,two,three,... },"/"))
end
end
local drivespec=R("az","AZ")^1*colon
@@ -3474,7 +3668,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-md5"] = package.loaded["l-md5"] or true
--- original size: 3760, stripped down to: 2088
+-- original size: 3248, stripped down to: 2266
if not modules then modules={} end modules ['l-md5']={
version=1.001,
@@ -3492,14 +3686,20 @@ if not md5 then
}
end
local md5,file=md5,file
-local gsub,format,byte=string.gsub,string.format,string.byte
-local md5sum=md5.sum
-local function convert(str,fmt)
- return (gsub(md5sum(str),".",function(chr) return format(fmt,byte(chr)) end))
-end
-if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end
-if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
-if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
+local gsub=string.gsub
+do
+ local patterns=lpeg and lpeg.patterns
+ if patterns then
+ local bytestoHEX=patterns.bytestoHEX
+ local bytestohex=patterns.bytestohex
+ local bytestodec=patterns.bytestodec
+ local lpegmatch=lpeg.match
+ local md5sum=md5.sum
+ if not md5.HEX then function md5.HEX(str) if str then return lpegmatch(bytestoHEX,md5sum(str)) end end end
+ if not md5.hex then function md5.hex(str) if str then return lpegmatch(bytestohex,md5sum(str)) end end end
+ if not md5.dec then function md5.dec(str) if str then return lpegmatch(bytestodec,md5sum(str)) end end end
+ end
+end
function file.needsupdating(oldname,newname,threshold)
local oldtime=lfs.attributes(oldname,"modification")
if oldtime then
@@ -3556,7 +3756,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-url"] = package.loaded["l-url"] or true
--- original size: 12292, stripped down to: 5585
+-- original size: 12531, stripped down to: 5721
if not modules then modules={} end modules ['l-url']={
version=1.001,
@@ -3642,19 +3842,25 @@ local splitquery=Cf (Ct("")*P { "sequence",
pair=Cg(key*equal*value),
},rawset)
local function hashed(str)
- if str=="" then
+ if not str or str=="" then
return {
scheme="invalid",
original=str,
}
end
- local s=split(str)
- local rawscheme=s[1]
- local rawquery=s[4]
- local somescheme=rawscheme~=""
- local somequery=rawquery~=""
+ local detailed=split(str)
+ local rawscheme=""
+ local rawquery=""
+ local somescheme=false
+ local somequery=false
+ if detailed then
+ rawscheme=detailed[1]
+ rawquery=detailed[4]
+ somescheme=rawscheme~=""
+ somequery=rawquery~=""
+ end
if not somescheme and not somequery then
- s={
+ return {
scheme="file",
authority="",
path=str,
@@ -3664,28 +3870,28 @@ local function hashed(str)
noscheme=true,
filename=str,
}
- else
- local authority,path,filename=s[2],s[3]
- if authority=="" then
- filename=path
- elseif path=="" then
- filename=""
- else
- filename=authority.."/"..path
- end
- s={
- scheme=rawscheme,
- authority=authority,
- path=path,
- query=lpegmatch(unescaper,rawquery),
- queries=lpegmatch(splitquery,rawquery),
- fragment=s[5],
- original=str,
- noscheme=false,
- filename=filename,
- }
end
- return s
+ local authority=detailed[2]
+ local path=detailed[3]
+ local filename=nil
+ if authority=="" then
+ filename=path
+ elseif path=="" then
+ filename=""
+ else
+ filename=authority.."/"..path
+ end
+ return {
+ scheme=rawscheme,
+ authority=authority,
+ path=path,
+ query=lpegmatch(unescaper,rawquery),
+ queries=lpegmatch(splitquery,rawquery),
+ fragment=detailed[5],
+ original=str,
+ noscheme=false,
+ filename=filename,
+ }
end
url.split=split
url.hasscheme=hasscheme
@@ -3719,7 +3925,7 @@ function url.construct(hash)
end
return lpegmatch(escaper,concat(fullurl))
end
-local pattern=Cs(noslash*R("az","AZ")*(S(":|")/":")*noslash*P(1)^0)
+local pattern=Cs(slash^-1/""*R("az","AZ")*((S(":|")/":")+P(":"))*slash*P(1)^0)
function url.filename(filename)
local spec=hashed(filename)
local path=spec.path
@@ -3767,7 +3973,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-dir"] = package.loaded["l-dir"] or true
--- original size: 14788, stripped down to: 9096
+-- original size: 16765, stripped down to: 11003
if not modules then modules={} end modules ['l-dir']={
version=1.001,
@@ -3777,7 +3983,7 @@ if not modules then modules={} end modules ['l-dir']={
license="see context related readme files"
}
local type,select=type,select
-local find,gmatch,match,gsub=string.find,string.gmatch,string.match,string.gsub
+local find,gmatch,match,gsub,sub=string.find,string.gmatch,string.match,string.gsub,string.sub
local concat,insert,remove,unpack=table.concat,table.insert,table.remove,table.unpack
local lpegmatch=lpeg.match
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
@@ -3786,53 +3992,126 @@ local dir=dir
local lfs=lfs
local attributes=lfs.attributes
local walkdir=lfs.dir
-local isdir=lfs.isdir
-local isfile=lfs.isfile
+local isdir=lfs.isdir
+local isfile=lfs.isfile
local currentdir=lfs.currentdir
local chdir=lfs.chdir
local mkdir=lfs.mkdir
local onwindows=os.type=="windows" or find(os.getenv("PATH"),";",1,true)
-if not isdir then
- function isdir(name)
- local a=attributes(name)
- return a and a.mode=="directory"
+if onwindows then
+ local tricky=S("/\\")*P(-1)
+ isdir=function(name)
+ if lpegmatch(tricky,name) then
+ return attributes(name,"mode")=="directory"
+ else
+ return attributes(name.."/.","mode")=="directory"
+ end
+ end
+ isfile=function(name)
+ return attributes(name,"mode")=="file"
end
lfs.isdir=isdir
-end
-if not isfile then
- function isfile(name)
- local a=attributes(name)
- return a and a.mode=="file"
+ lfs.isfile=isfile
+else
+ isdir=function(name)
+ return attributes(name,"mode")=="directory"
end
+ isfile=function(name)
+ return attributes(name,"mode")=="file"
+ end
+ lfs.isdir=isdir
lfs.isfile=isfile
end
function dir.current()
return (gsub(currentdir(),"\\","/"))
end
-local lfsisdir=isdir
-local function isdir(path)
- path=gsub(path,"[/\\]+$","")
- return lfsisdir(path)
+local function glob_pattern_function(path,patt,recurse,action)
+ if isdir(path) then
+ local usedpath
+ if path=="/" then
+ usedpath="/."
+ elseif not find(path,"/$") then
+ usedpath=path.."/."
+ path=path.."/"
+ else
+ usedpath=path
+ end
+ local dirs
+ for name in walkdir(usedpath) do
+ if name~="." and name~=".." then
+ local full=path..name
+ local mode=attributes(full,'mode')
+ if mode=='file' then
+ if not patt or find(full,patt) then
+ action(full)
+ end
+ elseif recurse and mode=="directory" then
+ if not dirs then
+ dirs={ full }
+ else
+ dirs[#dirs+1]=full
+ end
+ end
+ end
+ end
+ if dirs then
+ for i=1,#dirs do
+ glob_pattern_function(dirs[i],patt,recurse,action)
+ end
+ end
+ end
end
-lfs.isdir=isdir
-local function globpattern(path,patt,recurse,action)
- if path=="/" then
- path=path.."."
- elseif not find(path,"/$") then
- path=path..'/'
- end
- if isdir(path) then
- for name in walkdir(path) do
- local full=path..name
- local mode=attributes(full,'mode')
- if mode=='file' then
- if find(full,patt) then
- action(full)
+local function glob_pattern_table(path,patt,recurse,result)
+ if not result then
+ result={}
+ end
+ if isdir(path) then
+ local usedpath
+ if path=="/" then
+ usedpath="/."
+ elseif not find(path,"/$") then
+ usedpath=path.."/."
+ path=path.."/"
+ else
+ usedpath=path
+ end
+ local dirs
+ for name in walkdir(usedpath) do
+ if name~="." and name~=".." then
+ local full=path..name
+ local mode=attributes(full,'mode')
+ if mode=='file' then
+ if not patt or find(full,patt) then
+ result[#result+1]=full
+ end
+ elseif recurse and mode=="directory" then
+ if not dirs then
+ dirs={ full }
+ else
+ dirs[#dirs+1]=full
+ end
end
- elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
- globpattern(full,patt,recurse,action)
end
end
+ if dirs then
+ for i=1,#dirs do
+ glob_pattern_table(dirs[i],patt,recurse,result)
+ end
+ end
+ end
+ return result
+end
+local function globpattern(path,patt,recurse,method)
+ local kind=type(method)
+ if patt and sub(patt,1,-3)==path then
+ patt=false
+ end
+ if kind=="function" then
+ return glob_pattern_function(path,patt,recurse,method)
+ elseif kind=="table" then
+ return glob_pattern_table(path,patt,recurse,method)
+ else
+ return glob_pattern_table(path,patt,recurse,{})
end
end
dir.globpattern=globpattern
@@ -3845,34 +4124,40 @@ local function collectpattern(path,patt,recurse,result)
ok,scanner,first=xpcall(function() return walkdir(path) end,function() end)
end
if ok and type(scanner)=="function" then
- if not find(path,"/$") then path=path..'/' end
+ if not find(path,"/$") then
+ path=path..'/'
+ end
for name in scanner,first do
- local full=path..name
- local attr=attributes(full)
- local mode=attr.mode
- if mode=='file' then
- if find(full,patt) then
+ if name=="." then
+ elseif name==".." then
+ else
+ local full=path..name
+ local attr=attributes(full)
+ local mode=attr.mode
+ if mode=='file' then
+ if find(full,patt) then
+ result[name]=attr
+ end
+ elseif recurse and mode=="directory" then
+ attr.list=collectpattern(full,patt,recurse)
result[name]=attr
end
- elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
- attr.list=collectpattern(full,patt,recurse)
- result[name]=attr
end
end
end
return result
end
dir.collectpattern=collectpattern
-local separator
-if onwindows then
+local separator,pattern
+if onwindows then
local slash=S("/\\")/"/"
- pattern=Ct {
+ pattern={
[1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3),
[2]=Cs(((1-S("*?/\\"))^0*slash)^0),
[3]=Cs(P(1)^0)
}
-else
- pattern=Ct {
+else
+ pattern={
[1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3),
[2]=C(((1-S("*?/"))^0*P("/"))^0),
[3]=C(P(1)^0)
@@ -3890,9 +4175,8 @@ local function glob(str,t)
elseif isfile(str) then
t(str)
else
- local split=lpegmatch(pattern,str)
- if split then
- local root,path,base=split[1],split[2],split[3]
+ local root,path,base=lpegmatch(pattern,str)
+ if root and path and base then
local recurse=find(base,"**",1,true)
local start=root..path
local result=lpegmatch(filter,start..base)
@@ -3914,16 +4198,12 @@ local function glob(str,t)
return { str }
end
else
- local split=lpegmatch(pattern,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 root,path,base=lpegmatch(pattern,str)
+ if root and path and base then
local recurse=find(base,"**",1,true)
local start=root..path
local result=lpegmatch(filter,start..base)
- globpattern(start,result,recurse,action)
- return t
+ return globpattern(start,result,recurse,t)
else
return {}
end
@@ -4071,47 +4351,51 @@ else
end
end
dir.makedirs=dir.mkdirs
-if onwindows then
- function dir.expandname(str)
- local first,nothing,last=match(str,"^(//)(//*)(.*)$")
- if first then
- first=dir.current().."/"
- end
- if not first then
- first,last=match(str,"^(//)/*(.*)$")
- end
- if not first then
- first,last=match(str,"^([a-zA-Z]:)(.*)$")
- if first and not find(last,"^/") then
- local d=currentdir()
- if chdir(first) then
- first=dir.current()
+do
+ local chdir=sandbox and sandbox.original(chdir) or chdir
+ if onwindows then
+ local xcurrentdir=dir.current
+ function dir.expandname(str)
+ local first,nothing,last=match(str,"^(//)(//*)(.*)$")
+ if first then
+ first=xcurrentdir().."/"
+ end
+ if not first then
+ first,last=match(str,"^(//)/*(.*)$")
+ end
+ if not first then
+ first,last=match(str,"^([a-zA-Z]:)(.*)$")
+ if first and not find(last,"^/") then
+ local d=currentdir()
+ if chdir(first) then
+ first=xcurrentdir()
+ end
+ chdir(d)
end
- chdir(d)
+ end
+ if not first then
+ first,last=xcurrentdir(),str
+ end
+ last=gsub(last,"//","/")
+ last=gsub(last,"/%./","/")
+ last=gsub(last,"^/*","")
+ first=gsub(first,"/*$","")
+ if last=="" or last=="." then
+ return first
+ else
+ return first.."/"..last
end
end
- if not first then
- first,last=dir.current(),str
- end
- last=gsub(last,"//","/")
- last=gsub(last,"/%./","/")
- last=gsub(last,"^/*","")
- first=gsub(first,"/*$","")
- if last=="" or last=="." then
- return first
- else
- return first.."/"..last
- end
- end
-else
- function dir.expandname(str)
- if not find(str,"^/") then
- str=currentdir().."/"..str
+ else
+ function dir.expandname(str)
+ if not find(str,"^/") then
+ str=currentdir().."/"..str
+ end
+ str=gsub(str,"//","/")
+ str=gsub(str,"/%./","/")
+ str=gsub(str,"(.)/%.$","%1")
+ return str
end
- str=gsub(str,"//","/")
- str=gsub(str,"/%./","/")
- str=gsub(str,"(.)/%.$","%1")
- return str
end
end
file.expandname=dir.expandname
@@ -4154,7 +4438,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-boolean"] = package.loaded["l-boolean"] or true
--- original size: 1809, stripped down to: 1527
+-- original size: 1850, stripped down to: 1568
if not modules then modules={} end modules ['l-boolean']={
version=1.001,
@@ -4208,11 +4492,11 @@ function string.booleanstring(str)
return str=="yes" or str=="on" or str=="t"
end
end
-function string.is_boolean(str,default)
+function string.is_boolean(str,default,strict)
if type(str)=="string" then
- if str=="true" or str=="yes" or str=="on" or str=="t" or str=="1" then
+ if str=="true" or str=="yes" or str=="on" or str=="t" or (not strict and str=="1") then
return true
- elseif str=="false" or str=="no" or str=="off" or str=="f" or str=="0" then
+ elseif str=="false" or str=="no" or str=="off" or str=="f" or (not strict and str=="0") then
return false
end
end
@@ -4226,7 +4510,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-unicode"] = package.loaded["l-unicode"] or true
--- original size: 33706, stripped down to: 14938
+-- original size: 37233, stripped down to: 15684
if not modules then modules={} end modules ['l-unicode']={
version=1.001,
@@ -4242,7 +4526,9 @@ local type=type
local char,byte,format,sub,gmatch=string.char,string.byte,string.format,string.sub,string.gmatch
local concat=table.concat
local P,C,R,Cs,Ct,Cmt,Cc,Carg,Cp=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Ct,lpeg.Cmt,lpeg.Cc,lpeg.Carg,lpeg.Cp
-local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local lpegmatch=lpeg.match
+local patterns=lpeg.patterns
+local tabletopattern=lpeg.utfchartabletopattern
local bytepairs=string.bytepairs
local finder=lpeg.finder
local replacer=lpeg.replacer
@@ -4251,7 +4537,7 @@ local utfgmatch=utf.gmatch
local p_utftype=patterns.utftype
local p_utfstricttype=patterns.utfstricttype
local p_utfoffset=patterns.utfoffset
-local p_utf8char=patterns.utf8char
+local p_utf8char=patterns.utf8character
local p_utf8byte=patterns.utf8byte
local p_utfbom=patterns.utfbom
local p_newline=patterns.newline
@@ -4450,15 +4736,52 @@ if not utf.sub then
end
end
end
-function utf.remapper(mapping)
- local pattern=Cs((p_utf8char/mapping)^0)
- return function(str)
- if not str or str=="" then
- return ""
+function utf.remapper(mapping,option)
+ local variant=type(mapping)
+ if variant=="table" then
+ if option=="dynamic" then
+ local pattern=false
+ table.setmetatablenewindex(mapping,function(t,k,v) rawset(t,k,v) pattern=false end)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ if not pattern then
+ pattern=Cs((tabletopattern(mapping)/mapping+p_utf8char)^0)
+ end
+ return lpegmatch(pattern,str)
+ end
+ end
+ elseif option=="pattern" then
+ return Cs((tabletopattern(mapping)/mapping+p_utf8char)^0)
else
- return lpegmatch(pattern,str)
+ local pattern=Cs((tabletopattern(mapping)/mapping+p_utf8char)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+ end
+ elseif variant=="function" then
+ if option=="pattern" then
+ return Cs((p_utf8char/mapping+p_utf8char)^0)
+ else
+ local pattern=Cs((p_utf8char/mapping+p_utf8char)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+ end
+ else
+ return function(str)
+ return str or ""
end
- end,pattern
+ end
end
function utf.replacer(t)
local r=replacer(t,false,false,true)
@@ -4508,190 +4831,157 @@ function utf.magic(f)
end
local utf16_to_utf8_be,utf16_to_utf8_le
local utf32_to_utf8_be,utf32_to_utf8_le
-local utf_16_be_linesplitter=patterns.utfbom_16_be^-1*lpeg.tsplitat(patterns.utf_16_be_nl)
-local utf_16_le_linesplitter=patterns.utfbom_16_le^-1*lpeg.tsplitat(patterns.utf_16_le_nl)
-if bytepairs then
- utf16_to_utf8_be=function(t)
- if type(t)=="string" then
- t=lpegmatch(utf_16_be_linesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,0
- for left,right in bytepairs(t[i]) do
- if right then
- local now=256*left+right
- if more>0 then
- now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
- more=0
- r=r+1
- result[r]=utfchar(now)
- elseif now>=0xD800 and now<=0xDBFF then
- more=now
- else
- r=r+1
- result[r]=utfchar(now)
- end
- end
- end
- t[i]=concat(result,"",1,r)
- end
- return t
+local utf_16_be_getbom=patterns.utfbom_16_be^-1
+local utf_16_le_getbom=patterns.utfbom_16_le^-1
+local utf_32_be_getbom=patterns.utfbom_32_be^-1
+local utf_32_le_getbom=patterns.utfbom_32_le^-1
+local utf_16_be_linesplitter=utf_16_be_getbom*lpeg.tsplitat(patterns.utf_16_be_nl)
+local utf_16_le_linesplitter=utf_16_le_getbom*lpeg.tsplitat(patterns.utf_16_le_nl)
+local utf_32_be_linesplitter=utf_32_be_getbom*lpeg.tsplitat(patterns.utf_32_be_nl)
+local utf_32_le_linesplitter=utf_32_le_getbom*lpeg.tsplitat(patterns.utf_32_le_nl)
+local more=0
+local p_utf16_to_utf8_be=C(1)*C(1)/function(left,right)
+ local now=256*byte(left)+byte(right)
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ return utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ return ""
+ else
+ return utfchar(now)
+ end
+end
+local p_utf16_to_utf8_le=C(1)*C(1)/function(right,left)
+ local now=256*byte(left)+byte(right)
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ return utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ return ""
+ else
+ return utfchar(now)
+ end
+end
+local p_utf32_to_utf8_be=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d)
+ return utfchar(256*256*256*byte(a)+256*256*byte(b)+256*byte(c)+byte(d))
+end
+local p_utf32_to_utf8_le=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d)
+ return utfchar(256*256*256*byte(d)+256*256*byte(c)+256*byte(b)+byte(a))
+end
+p_utf16_to_utf8_be=P(true)/function() more=0 end*utf_16_be_getbom*Cs(p_utf16_to_utf8_be^0)
+p_utf16_to_utf8_le=P(true)/function() more=0 end*utf_16_le_getbom*Cs(p_utf16_to_utf8_le^0)
+p_utf32_to_utf8_be=P(true)/function() more=0 end*utf_32_be_getbom*Cs(p_utf32_to_utf8_be^0)
+p_utf32_to_utf8_le=P(true)/function() more=0 end*utf_32_le_getbom*Cs(p_utf32_to_utf8_le^0)
+patterns.utf16_to_utf8_be=p_utf16_to_utf8_be
+patterns.utf16_to_utf8_le=p_utf16_to_utf8_le
+patterns.utf32_to_utf8_be=p_utf32_to_utf8_be
+patterns.utf32_to_utf8_le=p_utf32_to_utf8_le
+utf16_to_utf8_be=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf16_to_utf8_be,s)
+ else
+ return s
end
- utf16_to_utf8_le=function(t)
- if type(t)=="string" then
- t=lpegmatch(utf_16_le_linesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,0
- for left,right in bytepairs(t[i]) do
- if right then
- local now=256*right+left
- if more>0 then
- now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
- more=0
- r=r+1
- result[r]=utfchar(now)
- elseif now>=0xD800 and now<=0xDBFF then
- more=now
- else
- r=r+1
- result[r]=utfchar(now)
- end
- end
- end
- t[i]=concat(result,"",1,r)
- end
- return t
+end
+local utf16_to_utf8_be_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_16_be_linesplitter,t)
end
- utf32_to_utf8_be=function(t)
- if type(t)=="string" then
- t=lpegmatch(utflinesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,-1
- for a,b in bytepairs(t[i]) do
- if a and b then
- if more<0 then
- more=256*256*256*a+256*256*b
- else
- r=r+1
- result[t]=utfchar(more+256*a+b)
- more=-1
- end
- else
- break
- end
- end
- t[i]=concat(result,"",1,r)
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf16_to_utf8_be,s)
end
- return t
end
- utf32_to_utf8_le=function(t)
- if type(t)=="string" then
- t=lpegmatch(utflinesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,-1
- for a,b in bytepairs(t[i]) do
- if a and b then
- if more<0 then
- more=256*b+a
- else
- r=r+1
- result[t]=utfchar(more+256*256*256*b+256*256*a)
- more=-1
- end
- else
- break
- end
- end
- t[i]=concat(result,"",1,r)
- end
- return t
+ return t
+end
+utf16_to_utf8_le=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf16_to_utf8_le,s)
+ else
+ return s
end
-else
- utf16_to_utf8_be=function(t)
- if type(t)=="string" then
- t=lpegmatch(utf_16_be_linesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,0
- for left,right in gmatch(t[i],"(.)(.)") do
- if left=="\000" then
- r=r+1
- result[r]=utfchar(byte(right))
- elseif right then
- local now=256*byte(left)+byte(right)
- if more>0 then
- now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
- more=0
- r=r+1
- result[r]=utfchar(now)
- elseif now>=0xD800 and now<=0xDBFF then
- more=now
- else
- r=r+1
- result[r]=utfchar(now)
- end
- end
- end
- t[i]=concat(result,"",1,r)
+end
+local utf16_to_utf8_le_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_16_le_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf16_to_utf8_le,s)
end
- return t
end
- utf16_to_utf8_le=function(t)
- if type(t)=="string" then
- t=lpegmatch(utf_16_le_linesplitter,t)
+ return t
+end
+utf32_to_utf8_be=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf32_to_utf8_be,s)
+ else
+ return s
+ end
+end
+local utf32_to_utf8_be_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_32_be_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf32_to_utf8_be,s)
end
- local result={}
- for i=1,#t do
- local r,more=0,0
- for left,right in gmatch(t[i],"(.)(.)") do
- if right=="\000" then
- r=r+1
- result[r]=utfchar(byte(left))
- elseif right then
- local now=256*byte(right)+byte(left)
- if more>0 then
- now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
- more=0
- r=r+1
- result[r]=utfchar(now)
- elseif now>=0xD800 and now<=0xDBFF then
- more=now
- else
- r=r+1
- result[r]=utfchar(now)
- end
- end
- end
- t[i]=concat(result,"",1,r)
+ end
+ return t
+end
+utf32_to_utf8_le=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf32_to_utf8_le,s)
+ else
+ return s
+ end
+end
+local utf32_to_utf8_le_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_32_le_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf32_to_utf8_le,s)
end
- return t
end
- utf32_to_utf8_le=function() return {} end
- utf32_to_utf8_be=function() return {} end
+ return t
end
+utf.utf16_to_utf8_le_t=utf16_to_utf8_le_t
+utf.utf16_to_utf8_be_t=utf16_to_utf8_be_t
+utf.utf32_to_utf8_le_t=utf32_to_utf8_le_t
+utf.utf32_to_utf8_be_t=utf32_to_utf8_be_t
utf.utf16_to_utf8_le=utf16_to_utf8_le
utf.utf16_to_utf8_be=utf16_to_utf8_be
utf.utf32_to_utf8_le=utf32_to_utf8_le
utf.utf32_to_utf8_be=utf32_to_utf8_be
-function utf.utf8_to_utf8(t)
+function utf.utf8_to_utf8_t(t)
return type(t)=="string" and lpegmatch(utflinesplitter,t) or t
end
-function utf.utf16_to_utf8(t,endian)
- return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
+function utf.utf16_to_utf8_t(t,endian)
+ return endian and utf16_to_utf8_be_t(t) or utf16_to_utf8_le_t(t) or t
end
-function utf.utf32_to_utf8(t,endian)
- return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
+function utf.utf32_to_utf8_t(t,endian)
+ return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t
end
-local function little(c)
- local b=byte(c)
+local function little(b)
if b<0x10000 then
return char(b%256,b/256)
else
@@ -4700,8 +4990,7 @@ local function little(c)
return char(b1%256,b1/256,b2%256,b2/256)
end
end
-local function big(c)
- local b=byte(c)
+local function big(b)
if b<0x10000 then
return char(b/256,b%256)
else
@@ -4710,27 +4999,29 @@ local function big(c)
return char(b1/256,b1%256,b2/256,b2%256)
end
end
-local _,l_remap=utf.remapper(little)
-local _,b_remap=utf.remapper(big)
-function utf.utf8_to_utf16_be(str,nobom)
+local l_remap=Cs((p_utf8byte/little+P(1)/"")^0)
+local b_remap=Cs((p_utf8byte/big+P(1)/"")^0)
+local function utf8_to_utf16_be(str,nobom)
if nobom then
return lpegmatch(b_remap,str)
else
return char(254,255)..lpegmatch(b_remap,str)
end
end
-function utf.utf8_to_utf16_le(str,nobom)
+local function utf8_to_utf16_le(str,nobom)
if nobom then
return lpegmatch(l_remap,str)
else
return char(255,254)..lpegmatch(l_remap,str)
end
end
+utf.utf8_to_utf16_be=utf8_to_utf16_be
+utf.utf8_to_utf16_le=utf8_to_utf16_le
function utf.utf8_to_utf16(str,littleendian,nobom)
if littleendian then
- return utf.utf8_to_utf16_le(str,nobom)
+ return utf8_to_utf16_le(str,nobom)
else
- return utf.utf8_to_utf16_be(str,nobom)
+ return utf8_to_utf16_be(str,nobom)
end
end
local pattern=Cs (
@@ -4746,16 +5037,16 @@ function utf.xstring(s)
return format("0x%05X",type(s)=="number" and s or utfbyte(s))
end
function utf.toeight(str)
- if not str then
+ if not str or str=="" then
return nil
end
local utftype=lpegmatch(p_utfstricttype,str)
if utftype=="utf-8" then
- return sub(str,4)
- elseif utftype=="utf-16-le" then
- return utf16_to_utf8_le(str)
+ return sub(str,4)
elseif utftype=="utf-16-be" then
- return utf16_to_utf8_ne(str)
+ return utf16_to_utf8_be(str)
+ elseif utftype=="utf-16-le" then
+ return utf16_to_utf8_le(str)
else
return str
end
@@ -4834,7 +5125,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-math"] = package.loaded["l-math"] or true
--- original size: 915, stripped down to: 836
+-- original size: 974, stripped down to: 890
if not modules then modules={} end modules ['l-math']={
version=1.001,
@@ -4844,6 +5135,9 @@ if not modules then modules={} end modules ['l-math']={
license="see context related readme files"
}
local floor,sin,cos,tan=math.floor,math.sin,math.cos,math.tan
+if not math.ceiling then
+ math.ceiling=math.ceil
+end
if not math.round then
function math.round(x) return floor(x+0.5) end
end
@@ -4871,7 +5165,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-str"] = package.loaded["util-str"] or true
--- original size: 33063, stripped down to: 18397
+-- original size: 34407, stripped down to: 18852
if not modules then modules={} end modules ['util-str']={
version=1.001,
@@ -5001,10 +5295,12 @@ local striplinepatterns={
["retain"]=p_retain_normal,
["retain and collapse"]=p_retain_collapse,
["retain and no empty"]=p_retain_noempty,
+ ["collapse"]=patterns.collapser,
}
+setmetatable(striplinepatterns,{ __index=function(t,k) return p_prune_collapse end })
strings.striplinepatterns=striplinepatterns
function strings.striplines(str,how)
- return str and lpegmatch(how and striplinepatterns[how] or p_prune_collapse,str) or str
+ return str and lpegmatch(striplinepatterns[how],str) or str
end
strings.striplong=strings.striplines
function strings.nice(str)
@@ -5044,10 +5340,10 @@ string.tracedchars=tracedchars
strings.tracers=tracedchars
function string.tracedchar(b)
if type(b)=="number" then
- return tracedchars[b] or (utfchar(b).." (U+"..format('%05X',b)..")")
+ return tracedchars[b] or (utfchar(b).." (U+"..format("%05X",b)..")")
else
local c=utfbyte(b)
- return tracedchars[c] or (b.." (U+"..format('%05X',c)..")")
+ return tracedchars[c] or (b.." (U+"..(c and format("%05X",c) or "?????")..")")
end
end
function number.signed(i)
@@ -5184,12 +5480,12 @@ local format_f=function(f)
n=n+1
return format("format('%%%sf',a%s)",f,n)
end
-local format_F=function(f)
+local format_F=function(f)
n=n+1
if not f or f=="" then
- return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or (a%s == 1 and '1') or format('%%.9f',a%s))",n,n,n,n)
+ return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or format((a%s %% 1 == 0) and '%%i' or '%%.9f',a%s))",n,n,n,n)
else
- return format("((a%s == 0 and '0') or (a%s == 1 and '1') or format('%%%sf',a%s))",n,n,f,n)
+ return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n)
end
end
local format_g=function(f)
@@ -5417,7 +5713,6 @@ local builder=Cs { "start",
+V("j")+V("J")
+V("m")+V("M")
+V("z")
-+V("*")
)+V("*")
)*(P(-1)+Carg(1))
)^0,
@@ -5461,6 +5756,7 @@ local builder=Cs { "start",
["a"]=(prefix_any*P("a"))/format_a,
["A"]=(prefix_any*P("A"))/format_A,
["*"]=Cs(((1-P("%"))^1+P("%%")/"%%")^1)/format_rest,
+ ["?"]=Cs(((1-P("%"))^1 )^1)/format_rest,
["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension,
}
local direct=Cs (
@@ -5535,6 +5831,15 @@ else
add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape })
add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape })
end
+local dquote=patterns.dquote
+local equote=patterns.escaped+dquote/'\\"'+1
+local space=patterns.space
+local cquote=Cc('"')
+local pattern=Cs(dquote*(equote-P(-2))^0*dquote)
++Cs(cquote*(equote-space)^0*space*equote^0*cquote)
+function string.optionalquoted(str)
+ return lpegmatch(pattern,str) or str
+end
end -- of closure
@@ -5543,7 +5848,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-tab"] = package.loaded["util-tab"] or true
--- original size: 23985, stripped down to: 16069
+-- original size: 24267, stripped down to: 16260
if not modules then modules={} end modules ['util-tab']={
version=1.001,
@@ -5633,6 +5938,15 @@ function tables.removevalue(t,value)
end
end
end
+function tables.replacevalue(t,oldvalue,newvalue)
+ if oldvalue and newvalue then
+ for i=1,#t do
+ if t[i]==oldvalue then
+ t[i]=newvalue
+ end
+ end
+ end
+end
function tables.insertbeforevalue(t,value,extra)
for i=1,#t do
if t[i]==extra then
@@ -6026,7 +6340,7 @@ function table.serialize(root,name,specification)
end
depth=depth+1
end
- if root and next(root) then
+ if root and next(root)~=nil then
local first=nil
local last=0
last=#root
@@ -6051,7 +6365,7 @@ function table.serialize(root,name,specification)
elseif tv=="string" then
n=n+1 t[n]=f_val_str(depth,v)
elseif tv=="table" then
- if not next(v) then
+ if next(v)==nil then
n=n+1 t[n]=f_val_not(depth)
else
local st=simple_table(v)
@@ -6081,7 +6395,7 @@ function table.serialize(root,name,specification)
n=n+1 t[n]=f_key_boo_value_str(depth,k,v)
end
elseif tv=="table" then
- if not next(v) then
+ if next(v)==nil then
if tk=="number" then
n=n+1 t[n]=f_key_num_value_not(depth,k,v)
elseif tk=="string" then
@@ -6139,7 +6453,7 @@ function table.serialize(root,name,specification)
local dummy=root._w_h_a_t_e_v_e_r_
root._w_h_a_t_e_v_e_r_=nil
end
- if next(root) then
+ if next(root)~=nil then
do_serialize(root,name,1,0)
end
end
@@ -6302,7 +6616,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-prs"] = package.loaded["util-prs"] or true
--- original size: 19618, stripped down to: 14012
+-- original size: 21751, stripped down to: 15108
if not modules then modules={} end modules ['util-prs']={
version=1.001,
@@ -6458,11 +6772,30 @@ function parsers.settings_to_array(str,strict)
return { str }
end
end
-local separator=space^0*comma*space^0
-local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-(space^0*(comma+P(-1)))))^0)
-local withvalue=Carg(1)*value/function(f,s) return f(s) end
-local pattern_a=spaces*Ct(value*(separator*value)^0)
-local pattern_b=spaces*withvalue*(separator*withvalue)^0
+local cache_a={}
+local cache_b={}
+function parsers.groupedsplitat(symbol,withaction)
+ if not symbol then
+ symbol=","
+ end
+ local pattern=(withaction and cache_b or cache_a)[symbol]
+ if not pattern then
+ local symbols=S(symbol)
+ local separator=space^0*symbols*space^0
+ local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-(space^0*(symbols+P(-1)))))^0)
+ if withaction then
+ local withvalue=Carg(1)*value/function(f,s) return f(s) end
+ pattern=spaces*withvalue*(separator*withvalue)^0
+ cache_b[symbol]=pattern
+ else
+ pattern=spaces*Ct(value*(separator*value)^0)
+ cache_a[symbol]=pattern
+ end
+ end
+ return pattern
+end
+local pattern_a=parsers.groupedsplitat(",",false)
+local pattern_b=parsers.groupedsplitat(",",true)
function parsers.stripped_settings_to_array(str)
if not str or str=="" then
return {}
@@ -6524,12 +6857,9 @@ function parsers.array_to_string(a,separator)
return ""
end
end
-function parsers.settings_to_set(str,t)
- t=t or {}
- for s in gmatch(str,"[^, ]+") do
- t[s]=true
- end
- return t
+local pattern=Cf(Ct("")*Cg(C((1-S(", "))^1)*S(", ")^0*Cc(true))^1,rawset)
+function utilities.parsers.settings_to_set(str,t)
+ return str and lpegmatch(pattern,str) or {}
end
function parsers.simple_hash_to_string(h,separator)
local t,tn={},0
@@ -6541,12 +6871,16 @@ function parsers.simple_hash_to_string(h,separator)
end
return concat(t,separator or ",")
end
-local str=C((1-whitespace-equal)^1)
+local str=Cs(lpegpatterns.unquoted)+C((1-whitespace-equal)^1)
local setting=Cf(Carg(1)*(whitespace^0*Cg(str*whitespace^0*(equal*whitespace^0*str+Cc(""))))^1,rawset)
local splitter=setting^1
function utilities.parsers.options_to_hash(str,target)
return str and lpegmatch(splitter,str,1,target or {}) or {}
end
+local splitter=lpeg.tsplitat(" ")
+function utilities.parsers.options_to_array(str)
+ return str and lpegmatch(splitter,str) or {}
+end
local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C(digit^1*lparent*(noparent+nestedparents)^1*rparent)+C((nestedbraces+(1-comma))^1)
local pattern_a=spaces*Ct(value*(separator*value)^0)
local function repeater(n,str)
@@ -6668,7 +7002,7 @@ function parsers.rfc4180splitter(specification)
local field=escaped+non_escaped+Cc("")
local record=Ct(field*(separator*field)^1)
local headerline=record*Cp()
- local wholeblob=Ct((newline^-1*record)^0)
+ local wholeblob=Ct((newline^(specification.strict and -1 or 1)*record)^0)
return function(data,getheader)
if getheader then
local header,position=lpegmatch(headerline,data)
@@ -6705,13 +7039,13 @@ function parsers.stepper(str,n,action)
lpegmatch(stepper,str,1,n,action or print)
end
end
-local pattern_math=Cs((P("%")/"\\percent "+P("^")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0)
-local pattern_text=Cs((P("%")/"\\percent "+(P("^")/"\\high")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0)
+local pattern_math=Cs((P("%")/"\\percent "+P("^")*Cc("{")*lpegpatterns.integer*Cc("}")+anything)^0)
+local pattern_text=Cs((P("%")/"\\percent "+(P("^")/"\\high")*Cc("{")*lpegpatterns.integer*Cc("}")+anything)^0)
patterns.unittotex=pattern
function parsers.unittotex(str,textmode)
return lpegmatch(textmode and pattern_text or pattern_math,str)
end
-local pattern=Cs((P("^")/"<sup>"*lpegpatterns.integer*Cc("</sup>")+P(1))^0)
+local pattern=Cs((P("^")/"<sup>"*lpegpatterns.integer*Cc("</sup>")+anything)^0)
function parsers.unittoxml(str)
return lpegmatch(pattern,str)
end
@@ -6783,6 +7117,18 @@ function utilities.parsers.runtime(time)
local seconds=mod(time,60)
return days,hours,minutes,seconds
end
+local spacing=whitespace^0
+local apply=P("->")
+local method=C((1-apply)^1)
+local token=lbrace*C((1-rbrace)^1)*rbrace+C(anything^1)
+local pattern=spacing*(method*spacing*apply+Carg(1))*spacing*token
+function utilities.parsers.splitmethod(str,default)
+ if str then
+ return lpegmatch(pattern,str,1,default or false)
+ else
+ return default or false,""
+ end
+end
end -- of closure
@@ -6872,7 +7218,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["trac-set"] = package.loaded["trac-set"] or true
--- original size: 12365, stripped down to: 8799
+-- original size: 12482, stripped down to: 8864
if not modules then modules={} end modules ['trac-set']={
version=1.001,
@@ -6900,7 +7246,7 @@ function setters.initialize(filename,name,values)
local data=setter.data
if data then
for key,newvalue in next,values do
- local newvalue=is_boolean(newvalue,newvalue)
+ local newvalue=is_boolean(newvalue,newvalue,true)
local functions=data[key]
if functions then
local oldvalue=functions.value
@@ -6954,7 +7300,7 @@ local function set(t,what,newvalue)
elseif not value then
value=false
else
- value=is_boolean(value,value)
+ value=is_boolean(value,value,true)
end
w=topattern(w,true,true)
for name,functions in next,data do
@@ -7093,6 +7439,7 @@ function setters.new(name)
report=function(...) setters.report (setter,...) end,
enable=function(...) enable (setter,...) end,
disable=function(...) disable (setter,...) end,
+ reset=function(...) reset (setter,...) end,
register=function(...) register(setter,...) end,
list=function(...) list (setter,...) end,
show=function(...) show (setter,...) end,
@@ -7184,7 +7531,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["trac-log"] = package.loaded["trac-log"] or true
--- original size: 25613, stripped down to: 16617
+-- original size: 29359, stripped down to: 20483
if not modules then modules={} end modules ['trac-log']={
version=1.001,
@@ -7193,15 +7540,18 @@ if not modules then modules={} end modules ['trac-log']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
+local next,type,select,print=next,type,select,print
local write_nl,write=texio and texio.write_nl or print,texio and texio.write or io.write
local format,gmatch,find=string.format,string.gmatch,string.find
local concat,insert,remove=table.concat,table.insert,table.remove
local topattern=string.topattern
-local next,type,select=next,type,select
local utfchar=utf.char
+local datetime=os.date
+local openfile=io.open
local setmetatableindex=table.setmetatableindex
local formatters=string.formatters
local texgetcount=tex and tex.getcount
+local variant="default"
logs=logs or {}
local logs=logs
local moreinfo=[[
@@ -7211,32 +7561,122 @@ 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
]]
-utilities.strings.formatters.add (
+formatters.add (
formatters,"unichr",
[["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
)
-utilities.strings.formatters.add (
+formatters.add (
formatters,"chruni",
[[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
)
local function ignore() end
setmetatableindex(logs,function(t,k) t[k]=ignore;return ignore end)
local report,subreport,status,settarget,setformats,settranslations
-local direct,subdirect,writer,pushtarget,poptarget,setlogfile,settimedlog,setprocessor,setformatters
+local direct,subdirect,writer,pushtarget,poptarget,setlogfile,settimedlog,setprocessor,setformatters,newline
if tex and (tex.jobname or tex.formatname) then
- local valueiskey={ __index=function(t,k) t[k]=k return k end }
- local target="term and log"
+ local function useluawrites()
+ local texio_write_nl=texio.write_nl
+ local texio_write=texio.write
+ local io_write=io.write
+ write_nl=function(target,...)
+ if not io_write then
+ io_write=io.write
+ end
+ if target=="term and log" then
+ texio_write_nl("log",...)
+ texio_write_nl("term","")
+ io_write(...)
+ elseif target=="log" then
+ texio_write_nl("log",...)
+ elseif target=="term" then
+ texio_write_nl("term","")
+ io_write(...)
+ elseif target~="none" then
+ texio_write_nl("log",target,...)
+ texio_write_nl("term","")
+ io_write(target,...)
+ end
+ end
+ write=function(target,...)
+ if not io_write then
+ io_write=io.write
+ end
+ if target=="term and log" then
+ texio_write("log",...)
+ io_write(...)
+ elseif target=="log" then
+ texio_write("log",...)
+ elseif target=="term" then
+ io_write(...)
+ elseif target~="none" then
+ texio_write("log",target,...)
+ io_write(target,...)
+ end
+ end
+ texio.write=write
+ texio.write_nl=write_nl
+ useluawrites=ignore
+ end
+ local whereto="both"
+ local target=nil
+ local targets=nil
+ local formats=table.setmetatableindex("self")
+ local translations=table.setmetatableindex("self")
+ local report_yes,subreport_yes,direct_yes,subdirect_yes,status_yes
+ local report_nop,subreport_nop,direct_nop,subdirect_nop,status_nop
+ local variants={
+ default={
+ formats={
+ report_yes=formatters["%-15s > %s\n"],
+ report_nop=formatters["%-15s >\n"],
+ direct_yes=formatters["%-15s > %s"],
+ direct_nop=formatters["%-15s >"],
+ subreport_yes=formatters["%-15s > %s > %s\n"],
+ subreport_nop=formatters["%-15s > %s >\n"],
+ subdirect_yes=formatters["%-15s > %s > %s"],
+ subdirect_nop=formatters["%-15s > %s >"],
+ status_yes=formatters["%-15s : %s\n"],
+ status_nop=formatters["%-15s :\n"],
+ },
+ targets={
+ logfile="log",
+ log="log",
+ file="log",
+ console="term",
+ terminal="term",
+ both="term and log",
+ },
+ },
+ ansi={
+ formats={
+ report_yes=formatters["%-15s > %s\n"],
+ report_nop=formatters["%-15s >\n"],
+ direct_yes=formatters["%-15s > %s"],
+ direct_nop=formatters["%-15s >"],
+ subreport_yes=formatters["%-15s > %s > %s\n"],
+ subreport_nop=formatters["%-15s > %s >\n"],
+ subdirect_yes=formatters["%-15s > %s > %s"],
+ subdirect_nop=formatters["%-15s > %s >"],
+ status_yes=formatters["%-15s : %s\n"],
+ status_nop=formatters["%-15s :\n"],
+ },
+ targets={
+ logfile="none",
+ log="none",
+ file="none",
+ console="term",
+ terminal="term",
+ both="term",
+ },
+ }
+ }
logs.flush=io.flush
- local formats={} setmetatable(formats,valueiskey)
- local translations={} setmetatable(translations,valueiskey)
writer=function(...)
write_nl(target,...)
end
newline=function()
write_nl(target,"\n")
end
- local report_yes=formatters["%-15s > %s\n"]
- local report_nop=formatters["%-15s >\n"]
report=function(a,b,c,...)
if c then
write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...)))
@@ -7248,8 +7688,6 @@ if tex and (tex.jobname or tex.formatname) then
write_nl(target,"\n")
end
end
- local direct_yes=formatters["%-15s > %s"]
- local direct_nop=formatters["%-15s >"]
direct=function(a,b,c,...)
if c then
return direct_yes(translations[a],formatters[formats[b]](c,...))
@@ -7261,8 +7699,6 @@ if tex and (tex.jobname or tex.formatname) then
return ""
end
end
- local subreport_yes=formatters["%-15s > %s > %s\n"]
- local subreport_nop=formatters["%-15s > %s >\n"]
subreport=function(a,s,b,c,...)
if c then
write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...)))
@@ -7274,8 +7710,6 @@ if tex and (tex.jobname or tex.formatname) then
write_nl(target,"\n")
end
end
- local subdirect_yes=formatters["%-15s > %s > %s"]
- local subdirect_nop=formatters["%-15s > %s >"]
subdirect=function(a,s,b,c,...)
if c then
return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...))
@@ -7287,8 +7721,6 @@ if tex and (tex.jobname or tex.formatname) then
return ""
end
end
- local status_yes=formatters["%-15s : %s\n"]
- local status_nop=formatters["%-15s :\n"]
status=function(a,b,c,...)
if c then
write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...)))
@@ -7300,16 +7732,13 @@ if tex and (tex.jobname or tex.formatname) then
write_nl(target,"\n")
end
end
- local targets={
- logfile="log",
- log="log",
- file="log",
- console="term",
- terminal="term",
- both="term and log",
- }
- settarget=function(whereto)
- target=targets[whereto or "both"] or targets.both
+ settarget=function(askedwhereto)
+ whereto=askedwhereto or whereto or "both"
+ target=targets[whereto]
+ if not target then
+ whereto="both"
+ target=targets[whereto]
+ end
if target=="term" or target=="term and log" then
logs.flush=io.flush
else
@@ -7338,21 +7767,74 @@ if tex and (tex.jobname or tex.formatname) then
writeline(target,f(...))
end
end
- setformatters=function(f)
- report_yes=f.report_yes or report_yes
- report_nop=f.report_nop or report_nop
- subreport_yes=f.subreport_yes or subreport_yes
- subreport_nop=f.subreport_nop or subreport_nop
- direct_yes=f.direct_yes or direct_yes
- direct_nop=f.direct_nop or direct_nop
- subdirect_yes=f.subdirect_yes or subdirect_yes
- subdirect_nop=f.subdirect_nop or subdirect_nop
- status_yes=f.status_yes or status_yes
- status_nop=f.status_nop or status_nop
- end
+ setformatters=function(specification)
+ local t=nil
+ local f=nil
+ local d=variants.default
+ if not specification then
+ elseif type(specification)=="table" then
+ t=specification.targets
+ f=specification.formats or specification
+ else
+ local v=variants[specification]
+ if v then
+ t=v.targets
+ f=v.formats
+ variant=specification
+ end
+ end
+ targets=t or d.targets
+ target=targets[whereto] or target
+ if f then
+ d=d.formats
+ else
+ f=d.formats
+ d=f
+ end
+ setmetatableindex(f,d)
+ report_yes=f.report_yes
+ report_nop=f.report_nop
+ subreport_yes=f.subreport_yes
+ subreport_nop=f.subreport_nop
+ direct_yes=f.direct_yes
+ direct_nop=f.direct_nop
+ subdirect_yes=f.subdirect_yes
+ subdirect_nop=f.subdirect_nop
+ status_yes=f.status_yes
+ status_nop=f.status_nop
+ if variant=="ansi" then
+ useluawrites()
+ end
+ settarget(whereto)
+ end
+ setformatters(variant)
setlogfile=ignore
settimedlog=ignore
else
+ local report_yes,subreport_yes,status_yes
+ local report_nop,subreport_nop,status_nop
+ local variants={
+ default={
+ formats={
+ report_yes=formatters["%-15s | %s"],
+ report_nop=formatters["%-15s |"],
+ subreport_yes=formatters["%-15s | %s | %s"],
+ subreport_nop=formatters["%-15s | %s |"],
+ status_yes=formatters["%-15s : %s\n"],
+ status_nop=formatters["%-15s :\n"],
+ },
+ },
+ ansi={
+ formats={
+ report_yes=formatters["%-15s | %s"],
+ report_nop=formatters["%-15s |"],
+ subreport_yes=formatters["%-15s | %s | %s"],
+ subreport_nop=formatters["%-15s | %s |"],
+ status_yes=formatters["%-15s : %s\n"],
+ status_nop=formatters["%-15s :\n"],
+ },
+ },
+ }
logs.flush=ignore
writer=function(s)
write_nl(s)
@@ -7360,8 +7842,6 @@ else
newline=function()
write_nl("\n")
end
- local report_yes=formatters["%-15s | %s"]
- local report_nop=formatters["%-15s |"]
report=function(a,b,c,...)
if c then
write_nl(report_yes(a,formatters[b](c,...)))
@@ -7373,8 +7853,6 @@ else
write_nl("")
end
end
- local subreport_yes=formatters["%-15s | %s | %s"]
- local subreport_nop=formatters["%-15s | %s |"]
subreport=function(a,sub,b,c,...)
if c then
write_nl(subreport_yes(a,sub,formatters[b](c,...)))
@@ -7386,8 +7864,6 @@ else
write_nl("")
end
end
- local status_yes=formatters["%-15s : %s\n"]
- local status_nop=formatters["%-15s :\n"]
status=function(a,b,c,...)
if c then
write_nl(status_yes(a,formatters[b](c,...)))
@@ -7412,14 +7888,34 @@ else
writeline(f(s))
end
end
- setformatters=function(f)
- report_yes=f.report_yes or report_yes
- report_nop=f.report_nop or report_nop
- subreport_yes=f.subreport_yes or subreport_yes
- subreport_nop=f.subreport_nop or subreport_nop
- status_yes=f.status_yes or status_yes
- status_nop=f.status_nop or status_nop
- end
+ setformatters=function(specification)
+ local f=nil
+ local d=variants.default
+ if specification then
+ if type(specification)=="table" then
+ f=specification.formats or specification
+ else
+ local v=variants[specification]
+ if v then
+ f=v.formats
+ end
+ end
+ end
+ if f then
+ d=d.formats
+ else
+ f=d.formats
+ d=f
+ end
+ setmetatableindex(f,d)
+ report_yes=f.report_yes
+ report_nop=f.report_nop
+ subreport_yes=f.subreport_yes
+ subreport_nop=f.subreport_nop
+ status_yes=f.status_yes
+ status_nop=f.status_nop
+ end
+ setformatters(variant)
setlogfile=function(name,keepopen)
if name and name~="" then
local localtime=os.localtime
@@ -7672,13 +8168,13 @@ end
local simple=logs.reporter("comment")
logs.simple=simple
logs.simpleline=simple
-function logs.setprogram () end
-function logs.extendbanner() end
-function logs.reportlines () end
-function logs.reportbanner() end
-function logs.reportline () end
-function logs.simplelines () end
-function logs.help () end
+logs.setprogram=ignore
+logs.extendbanner=ignore
+logs.reportlines=ignore
+logs.reportbanner=ignore
+logs.reportline=ignore
+logs.simplelines=ignore
+logs.help=ignore
local Carg,C,lpegmatch=lpeg.Carg,lpeg.C,lpeg.match
local p_newline=lpeg.patterns.newline
local linewise=(
@@ -7755,10 +8251,11 @@ function logs.application(t)
end
return t
end
-function logs.system(whereto,process,jobname,category,...)
- local message=formatters["%s %s => %s => %s => %s\r"](os.date("%d/%m/%y %H:%m:%S"),process,jobname,category,format(...))
+local f_syslog=formatters["%s %s => %s => %s => %s\r"]
+function logs.system(whereto,process,jobname,category,fmt,arg,...)
+ local message=f_syslog(datetime("%d/%m/%y %H:%m:%S"),process,jobname,category,arg==nil and fmt or format(fmt,arg,...))
for i=1,10 do
- local f=io.open(whereto,"a")
+ local f=openfile(whereto,"a")
if f then
f:write(message)
f:close()
@@ -7820,7 +8317,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["trac-inf"] = package.loaded["trac-inf"] or true
--- original size: 7011, stripped down to: 5590
+-- original size: 6704, stripped down to: 5343
if not modules then modules={} end modules ['trac-inf']={
version=1.001,
@@ -7993,15 +8490,6 @@ function statistics.tracefunction(base,tag,...)
statistics.register(formatters["%s.%s"](tag,name),function() return serialize(stat,"calls") end)
end
end
-commands=commands or {}
-function commands.resettimer(name)
- resettiming(name or "whatever")
- starttiming(name or "whatever")
-end
-function commands.elapsedtime(name)
- stoptiming(name or "whatever")
- context(elapsedtime(name or "whatever"))
-end
end -- of closure
@@ -8568,7 +9056,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-tpl"] = package.loaded["util-tpl"] or true
--- original size: 6251, stripped down to: 3488
+-- original size: 7100, stripped down to: 3978
if not modules then modules={} end modules ['util-tpl']={
version=1.001,
@@ -8610,7 +9098,7 @@ local sqlescape=lpeg.replacer {
{ "\r\n","\\n" },
{ "\r","\\n" },
}
-local sqlquoted=lpeg.Cs(lpeg.Cc("'")*sqlescape*lpeg.Cc("'"))
+local sqlquoted=Cs(Cc("'")*sqlescape*Cc("'"))
lpegpatterns.sqlescape=sqlescape
lpegpatterns.sqlquoted=sqlquoted
local luaescape=lpegpatterns.luaescape
@@ -8633,12 +9121,24 @@ local quotedescapers={
local luaescaper=escapers.lua
local quotedluaescaper=quotedescapers.lua
local function replacekeyunquoted(s,t,how,recurse)
- local escaper=how and escapers[how] or luaescaper
- return escaper(replacekey(s,t,how,recurse))
+ if how==false then
+ return replacekey(s,t,how,recurse)
+ else
+ local escaper=how and escapers[how] or luaescaper
+ return escaper(replacekey(s,t,how,recurse))
+ end
end
local function replacekeyquoted(s,t,how,recurse)
- local escaper=how and quotedescapers[how] or quotedluaescaper
- return escaper(replacekey(s,t,how,recurse))
+ if how==false then
+ return replacekey(s,t,how,recurse)
+ else
+ local escaper=how and quotedescapers[how] or quotedluaescaper
+ return escaper(replacekey(s,t,how,recurse))
+ end
+end
+local function replaceoptional(l,m,r,t,how,recurse)
+ local v=t[l]
+ return v and v~="" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or ""
end
local single=P("%")
local double=P("%%")
@@ -8653,11 +9153,16 @@ local nolquoted=lquoted/''
local norquoted=rquoted/''
local nolquotedq=lquotedq/''
local norquotedq=rquotedq/''
-local key=nosingle*((C((1-nosingle )^1)*Carg(1)*Carg(2)*Carg(3))/replacekey )*nosingle
-local quoted=nolquotedq*((C((1-norquotedq)^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyquoted )*norquotedq
-local unquoted=nolquoted*((C((1-norquoted )^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyunquoted)*norquoted
+local noloptional=P("%?")/''
+local noroptional=P("?%")/''
+local nomoptional=P(":")/''
+local args=Carg(1)*Carg(2)*Carg(3)
+local key=nosingle*((C((1-nosingle )^1)*args)/replacekey )*nosingle
+local quoted=nolquotedq*((C((1-norquotedq )^1)*args)/replacekeyquoted )*norquotedq
+local unquoted=nolquoted*((C((1-norquoted )^1)*args)/replacekeyunquoted)*norquoted
+local optional=noloptional*((C((1-nomoptional)^1)*nomoptional*C((1-noroptional)^1)*args)/replaceoptional)*noroptional
local any=P(1)
- replacer=Cs((unquoted+quoted+escape+key+any)^0)
+ replacer=Cs((unquoted+quoted+escape+optional+key+any)^0)
local function replace(str,mapping,how,recurse)
if mapping and str then
return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
@@ -8696,7 +9201,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-env"] = package.loaded["util-env"] or true
--- original size: 8814, stripped down to: 5092
+-- original size: 8022, stripped down to: 5038
if not modules then modules={} end modules ['util-env']={
version=1.001,
@@ -8707,7 +9212,7 @@ if not modules then modules={} end modules ['util-env']={
}
local allocate,mark=utilities.storage.allocate,utilities.storage.mark
local format,sub,match,gsub,find=string.format,string.sub,string.match,string.gsub,string.find
-local unquoted,quoted=string.unquoted,string.quoted
+local unquoted,quoted,optionalquoted=string.unquoted,string.quoted,string.optionalquoted
local concat,insert,remove=table.concat,table.insert,table.remove
environment=environment or {}
local environment=environment
@@ -8820,24 +9325,14 @@ function environment.splitarguments(separator)
return before,after
end
function environment.reconstructcommandline(arg,noquote)
+ local resolveprefix=resolvers.resolve
arg=arg or environment.originalarguments
if noquote and #arg==1 then
- local a=arg[1]
- a=resolvers.resolve(a)
- a=unquoted(a)
- return a
+ return unquoted(resolveprefix and resolveprefix(arg[1]) or arg[1])
elseif #arg>0 then
local result={}
for i=1,#arg do
- local a=arg[i]
- a=resolvers.resolve(a)
- a=unquoted(a)
- a=gsub(a,'"','\\"')
- if find(a," ",1,true) then
- result[#result+1]=quoted(a)
- else
- result[#result+1]=a
- end
+ result[i]=optionalquoted(resolveprefix and resolveprefix(arg[i]) or resolveprefix)
end
return concat(result," ")
else
@@ -9046,7 +9541,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true
--- original size: 42614, stripped down to: 26694
+-- original size: 43882, stripped down to: 26870
if not modules then modules={} end modules ['lxml-tab']={
version=1.001,
@@ -9061,10 +9556,10 @@ if lpeg.setmaxstack then lpeg.setmaxstack(1000) end
xml=xml or {}
local xml=xml
local concat,remove,insert=table.concat,table.remove,table.insert
-local type,next,setmetatable,getmetatable,tonumber=type,next,setmetatable,getmetatable,tonumber
+local type,next,setmetatable,getmetatable,tonumber,rawset=type,next,setmetatable,getmetatable,tonumber,rawset
local lower,find,match,gsub=string.lower,string.find,string.match,string.gsub
local utfchar=utf.char
-local lpegmatch=lpeg.match
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
local P,S,R,C,V,C,Cs=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.C,lpeg.Cs
local formatters=string.formatters
xml.xmlns=xml.xmlns or {}
@@ -9226,9 +9721,10 @@ local function fromdec(s)
return formatters["d:%s"](s),true
end
end
-local rest=(1-P(";"))^0
-local many=P(1)^0
-local parsedentity=P("&")*(P("#x")*(rest/fromhex)+P("#")*(rest/fromdec))*P(";")*P(-1)+(P("#x")*(many/fromhex)+P("#")*(many/fromdec))
+local p_rest=(1-P(";"))^0
+local p_many=P(1)^0
+local p_char=lpegpatterns.utf8character
+local parsedentity=P("&")*(P("#x")*(p_rest/fromhex)+P("#")*(p_rest/fromdec))*P(";")*P(-1)+(P("#x")*(p_many/fromhex)+P("#")*(p_many/fromdec))
local predefined_unified={
[38]="&amp;",
[42]="&quot;",
@@ -9254,7 +9750,9 @@ local privates_u={
local privates_p={}
local privates_n={
}
-local escaped=utf.remapper(privates_u)
+local escaped=utf.remapper(privates_u,"dynamic")
+local unprivatized=utf.remapper(privates_p,"dynamic")
+xml.unprivatized=unprivatized
local function unescaped(s)
local p=privates_n[s]
if not p then
@@ -9267,9 +9765,7 @@ local function unescaped(s)
end
return p
end
-local unprivatized=utf.remapper(privates_p)
xml.privatetoken=unescaped
-xml.unprivatized=unprivatized
xml.privatecodes=privates_n
local function handle_hex_entity(str)
local h=hcache[str]
@@ -9422,7 +9918,7 @@ local valid=R('az','AZ','09')+S('_-.')
local name_yes=C(valid^1)*colon*C(valid^1)
local name_nop=C(P(true))*C(valid^1)
local name=name_yes+name_nop
-local utfbom=lpeg.patterns.utfbom
+local utfbom=lpegpatterns.utfbom
local spacing=C(space^0)
local anyentitycontent=(1-open-semicolon-space-close)^0
local hexentitycontent=R("AF","af","09")^0
@@ -9590,7 +10086,7 @@ local function _xmlconvert_(data,settings)
reported_attribute_errors,mt,errorhandler=nil,nil,nil
return result
end
-function xmlconvert(data,settings)
+local function xmlconvert(data,settings)
local ok,result=pcall(function() return _xmlconvert_(data,settings) end)
if ok then
return result
@@ -9682,14 +10178,17 @@ function xml.checkbom(root)
insert(dt,2,"\n" )
end
end
-local function verbose_element(e,handlers)
+local f_attribute=formatters['%s=%q']
+local function verbose_element(e,handlers,escape)
local handle=handlers.handle
local serialize=handlers.serialize
local ens,etg,eat,edt,ern=e.ns,e.tg,e.at,e.dt,e.rn
local ats=eat and next(eat) and {}
if ats then
+ local n=0
for k,v in next,eat do
- ats[#ats+1]=formatters['%s=%q'](k,escaped(v))
+ n=n+1
+ ats[n]=f_attribute(k,escaped(v))
end
end
if ern and trace_entities and ern~=ens then
@@ -10033,7 +10532,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true
--- original size: 48030, stripped down to: 30595
+-- original size: 48229, stripped down to: 30684
if not modules then modules={} end modules ['lxml-lpt']={
version=1.001,
@@ -10418,8 +10917,8 @@ local lp_builtin=P (
P("ns")/"ll.ns"
)*((spaces*P("(")*spaces*P(")"))/"")
local lp_attribute=(P("@")+P("attribute::"))/""*Cc("(ll.at and ll.at['")*((R("az","AZ")+S("-_:"))^1)*Cc("'])")
-lp_fastpos_p=P("+")^0*R("09")^1*P(-1)/"l==%0"
-lp_fastpos_n=P("-")*R("09")^1*P(-1)/"(%0<0 and (#list+%0==l))"
+local lp_fastpos_p=P("+")^0*R("09")^1*P(-1)/"l==%0"
+local lp_fastpos_n=P("-")*R("09")^1*P(-1)/"(%0<0 and (#list+%0==l))"
local lp_fastpos=lp_fastpos_n+lp_fastpos_p
local lp_reserved=C("and")+C("or")+C("not")+C("div")+C("mod")+C("true")+C("false")
local lp_lua_function=Cs((R("az","AZ","__")^1*(P(".")*R("az","AZ","__")^1)^1)*("("))/"%0"
@@ -10598,7 +11097,7 @@ local function nodesettostring(set,nodetest)
if not ns or ns=="" then ns="*" end
if not tg or tg=="" then tg="*" end
tg=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
- t[i]=(directive and tg) or format("not(%s)",tg)
+ t[#t+1]=(directive and tg) or format("not(%s)",tg)
end
if nodetest==false then
return format("not(%s)",concat(t,"|"))
@@ -10864,7 +11363,6 @@ expressions.print=function(...)
print(...)
return true
end
-expressions.contains=find
expressions.find=find
expressions.upper=upper
expressions.lower=lower
@@ -10886,6 +11384,9 @@ function expressions.contains(str,pattern)
end
return false
end
+function xml.expressions.idstring(str)
+ return type(str)=="string" and gsub(str,"^#","") or ""
+end
local function traverse(root,pattern,handle)
local collected=applylpath(root,pattern)
if collected then
@@ -11173,7 +11674,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["lxml-aux"] = package.loaded["lxml-aux"] or true
--- original size: 23804, stripped down to: 16817
+-- original size: 28225, stripped down to: 20125
if not modules then modules={} end modules ['lxml-aux']={
version=1.001,
@@ -11183,16 +11684,19 @@ if not modules then modules={} end modules ['lxml-aux']={
license="see context related readme files"
}
local trace_manipulations=false trackers.register("lxml.manipulations",function(v) trace_manipulations=v end)
+local trace_inclusions=false trackers.register("lxml.inclusions",function(v) trace_inclusions=v end)
local report_xml=logs.reporter("xml")
local xml=xml
-local xmlconvert,xmlcopy,xmlname=xml.convert,xml.copy,xml.name
+local xmlcopy,xmlname=xml.copy,xml.name
local xmlinheritedconvert=xml.inheritedconvert
local xmlapplylpath=xml.applylpath
local xmlfilter=xml.filter
-local type,setmetatable,getmetatable=type,setmetatable,getmetatable
+local type,next,setmetatable,getmetatable=type,next,setmetatable,getmetatable
local insert,remove,fastcopy,concat=table.insert,table.remove,table.fastcopy,table.concat
local gmatch,gsub,format,find,strip=string.gmatch,string.gsub,string.format,string.find,string.strip
local utfbyte=utf.byte
+local lpegmatch=lpeg.match
+local striplinepatterns=utilities.strings.striplinepatterns
local function report(what,pattern,c,e)
report_xml("%s element %a, root %a, position %a, index %a, pattern %a",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
end
@@ -11247,13 +11751,15 @@ end
function xml.each(root,pattern,handle,reverse)
local collected=xmlapplylpath(root,pattern)
if collected then
- if reverse then
- for c=#collected,1,-1 do
- handle(collected[c])
- end
- else
- for c=1,#collected do
- handle(collected[c])
+ if handle then
+ if reverse then
+ for c=#collected,1,-1 do
+ handle(collected[c])
+ end
+ else
+ for c=1,#collected do
+ handle(collected[c])
+ end
end
end
return collected
@@ -11309,6 +11815,7 @@ local function redo_ni(d)
end
end
end
+xml.reindex=redo_ni
local function xmltoelement(whatever,root)
if not whatever then
return nil
@@ -11360,8 +11867,16 @@ function xml.delete(root,pattern)
report('deleting',pattern,c,e)
end
local d=p.dt
- remove(d,e.ni)
- redo_ni(d)
+ local ni=e.ni
+ if ni<=#d then
+ if false then
+ p.dt[ni]=""
+ else
+ remove(d,ni)
+ redo_ni(d)
+ end
+ else
+ end
end
end
end
@@ -11481,28 +11996,40 @@ xml.insertafter=insert_element
xml.insertbefore=function(r,p,e) insert_element(r,p,e,true) end
xml.injectafter=inject_element
xml.injectbefore=function(r,p,e) inject_element(r,p,e,true) end
-local function include(xmldata,pattern,attribute,recursive,loaddata)
+local function include(xmldata,pattern,attribute,recursive,loaddata,level)
pattern=pattern or 'include'
loaddata=loaddata or io.loaddata
local collected=xmlapplylpath(xmldata,pattern)
if collected then
+ if not level then
+ level=1
+ end
for c=1,#collected do
local ek=collected[c]
local name=nil
local ekdt=ek.dt
local ekat=ek.at
- local epdt=ek.__p__.dt
+ local ekrt=ek.__p__
+ local epdt=ekrt.dt
if not attribute or attribute=="" then
name=(type(ekdt)=="table" and ekdt[1]) or ekdt
end
if not name then
for a in gmatch(attribute or "href","([^|]+)") do
name=ekat[a]
- if name then break end
+ if name then
+ break
+ end
+ end
+ end
+ local data=nil
+ if name and name~="" then
+ data=loaddata(name) or ""
+ if trace_inclusions then
+ report_xml("including %s bytes from %a at level %s by pattern %a and attribute %a (%srecursing)",#data,name,level,pattern,attribute or "",recursive and "" or "not ")
end
end
- local data=(name and name~="" and loaddata(name)) or ""
- if data=="" then
+ if not data or data=="" then
epdt[ek.ni]=""
elseif ekat["parse"]=="text" then
epdt[ek.ni]=xml.escaped(data)
@@ -11512,70 +12039,113 @@ local function include(xmldata,pattern,attribute,recursive,loaddata)
epdt[ek.ni]=""
else
if recursive then
- include(xi,pattern,attribute,recursive,loaddata)
+ include(xi,pattern,attribute,recursive,loaddata,level+1)
+ end
+ local child=xml.body(xi)
+ child.__p__=ekrt
+ child.__f__=name
+ epdt[ek.ni]=child
+ local inclusions=xmldata.settings.inclusions
+ if inclusions then
+ inclusions[#inclusions+1]=name
+ else
+ xmldata.settings.inclusions={ name }
end
- epdt[ek.ni]=xml.body(xi)
end
end
end
end
end
xml.include=include
+function xml.inclusion(e,default)
+ while e do
+ local f=e.__f__
+ if f then
+ return f
+ else
+ e=e.__p__
+ end
+ end
+ return default
+end
+function xml.inclusions(e,sorted)
+ while e do
+ local settings=e.settings
+ if settings then
+ local inclusions=settings.inclusions
+ if inclusions then
+ inclusions=table.unique(inclusions)
+ if sorted then
+ table.sort(inclusions)
+ end
+ return inclusions
+ else
+ e=e.__p__
+ end
+ else
+ e=e.__p__
+ end
+ end
+end
+local b_collapser=lpeg.patterns.b_collapser
+local m_collapser=lpeg.patterns.m_collapser
+local e_collapser=lpeg.patterns.e_collapser
+local b_stripper=lpeg.patterns.b_stripper
+local m_stripper=lpeg.patterns.m_stripper
+local e_stripper=lpeg.patterns.e_stripper
+local lpegmatch=lpeg.match
local function stripelement(e,nolines,anywhere)
local edt=e.dt
if edt then
- if anywhere then
- local t,n={},0
- for e=1,#edt do
+ local n=#edt
+ if n==0 then
+ return e
+ elseif anywhere then
+ local t={}
+ local m=0
+ for e=1,n do
local str=edt[e]
if type(str)~="string" then
- n=n+1
- t[n]=str
+ m=m+1
+ t[m]=str
elseif str~="" then
if nolines then
- str=gsub(str,"%s+"," ")
+ str=lpegmatch((n==1 and b_collapser) or (n==m and e_collapser) or m_collapser,str)
+ else
+ str=lpegmatch((n==1 and b_stripper) or (n==m and e_stripper) or m_stripper,str)
end
- str=gsub(str,"^%s*(.-)%s*$","%1")
if str~="" then
- n=n+1
- t[n]=str
+ m=m+1
+ t[m]=str
end
end
end
e.dt=t
else
- if #edt>0 then
- local str=edt[1]
- if type(str)~="string" then
- elseif str=="" then
+ local str=edt[1]
+ if type(str)=="string" then
+ if str~="" then
+ str=lpegmatch(nolines and b_collapser or b_stripper,str)
+ end
+ if str=="" then
remove(edt,1)
+ n=n-1
else
- if nolines then
- str=gsub(str,"%s+"," ")
- end
- str=gsub(str,"^%s+","")
- if str=="" then
- remove(edt,1)
- else
- edt[1]=str
- end
+ edt[1]=str
end
end
- local nedt=#edt
- if nedt>0 then
- local str=edt[nedt]
- if type(str)~="string" then
- elseif str=="" then
- remove(edt)
- else
- if nolines then
- str=gsub(str,"%s+"," ")
- end
- str=gsub(str,"%s+$","")
+ if n>0 then
+ str=edt[n]
+ if type(str)=="string" then
if str=="" then
remove(edt)
else
- edt[nedt]=str
+ str=lpegmatch(nolines and e_collapser or e_stripper,str)
+ if str=="" then
+ remove(edt)
+ else
+ edt[n]=str
+ end
end
end
end
@@ -11761,8 +12331,8 @@ function xml.finalizers.xml.cdata(collected)
end
return ""
end
-function xml.insertcomment(e,str,n)
- table.insert(e.dt,n or 1,{
+function xml.insertcomment(e,str,n)
+ insert(e.dt,n or 1,{
tg="@cm@",
ns="",
special=true,
@@ -11770,7 +12340,25 @@ function xml.insertcomment(e,str,n)
dt={ str },
})
end
-function xml.setcdata(e,str)
+function xml.insertcdata(e,str,n)
+ insert(e.dt,n or 1,{
+ tg="@cd@",
+ ns="",
+ special=true,
+ at={},
+ dt={ str },
+ })
+end
+function xml.setcomment(e,str,n)
+ e.dt={ {
+ tg="@cm@",
+ ns="",
+ special=true,
+ at={},
+ dt={ str },
+ } }
+end
+function xml.setcdata(e,str)
e.dt={ {
tg="@cd@",
ns="",
@@ -11840,7 +12428,7 @@ local function recurse(e,action)
for i=1,#edt do
local str=edt[i]
if type(str)~="string" then
- recurse(str,action,recursive)
+ recurse(str,action)
elseif str~="" then
edt[i]=action(str)
end
@@ -11858,6 +12446,65 @@ function helpers.recursetext(collected,action,recursive)
end
end
end
+local specials={
+ ["@rt@"]="root",
+ ["@pi@"]="instruction",
+ ["@cm@"]="comment",
+ ["@dt@"]="declaration",
+ ["@cd@"]="cdata",
+}
+local function convert(x,strip,flat)
+ local ns=x.ns
+ local tg=x.tg
+ local at=x.at
+ local dt=x.dt
+ local node=flat and {
+ [0]=(not x.special and (ns~="" and ns..":"..tg or tg)) or nil,
+ } or {
+ _namespace=ns~="" and ns or nil,
+ _tag=not x.special and tg or nil,
+ _type=specials[tg] or "_element",
+ }
+ if at then
+ for k,v in next,at do
+ node[k]=v
+ end
+ end
+ local n=0
+ for i=1,#dt do
+ local di=dt[i]
+ if type(di)=="table" then
+ if flat and di.special then
+ else
+ di=convert(di,strip,flat)
+ if di then
+ n=n+1
+ node[n]=di
+ end
+ end
+ elseif strip then
+ di=lpegmatch(strip,di)
+ if di~="" then
+ n=n+1
+ node[n]=di
+ end
+ else
+ n=n+1
+ node[n]=di
+ end
+ end
+ if next(node) then
+ return node
+ end
+end
+function xml.totable(x,strip,flat)
+ if type(x)=="table" then
+ if strip then
+ strip=striplinepatterns[strip]
+ end
+ return convert(x,strip,flat)
+ end
+end
end -- of closure
@@ -12414,7 +13061,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-ini"] = package.loaded["data-ini"] or true
--- original size: 7927, stripped down to: 5528
+-- original size: 11085, stripped down to: 7662
if not modules then modules={} end modules ['data-ini']={
version=1.001,
@@ -12423,14 +13070,15 @@ if not modules then modules={} end modules ['data-ini']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files",
}
+local next,type,getmetatable,rawset=next,type,getmetatable,rawset
local gsub,find,gmatch,char=string.gsub,string.find,string.gmatch,string.char
-local next,type=next,type
local filedirname,filebasename,filejoin=file.dirname,file.basename,file.join
+local ostype,osname,osuname,ossetenv,osgetenv=os.type,os.name,os.uname,os.setenv,os.getenv
+local P,S,R,C,Cs,Cc,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.match
local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
local trace_detail=false trackers.register("resolvers.details",function(v) trace_detail=v end)
local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
local report_initialization=logs.reporter("resolvers","initialization")
-local ostype,osname,ossetenv,osgetenv=os.type,os.name,os.setenv,os.getenv
resolvers=resolvers or {}
local resolvers=resolvers
texconfig.kpse_init=false
@@ -12563,10 +13211,103 @@ if type(profiler)=="table" and not jit then
profiler.start("luatex-profile.log")
end)
end
-if not resolvers.resolve then
- function resolvers.resolve (s) return s end
- function resolvers.unresolve(s) return s end
- function resolvers.repath (s) return s end
+local prefixes=utilities.storage.allocate()
+resolvers.prefixes=prefixes
+local resolved={}
+local abstract={}
+local dynamic={}
+function resolvers.resetresolve(str)
+ resolved,abstract={},{}
+end
+function resolvers.allprefixes(separator)
+ local all=table.sortedkeys(prefixes)
+ if separator then
+ for i=1,#all do
+ all[i]=all[i]..":"
+ end
+ end
+ return all
+end
+local function _resolve_(method,target)
+ local action=prefixes[method]
+ if action then
+ return action(target)
+ else
+ return method..":"..target
+ end
+end
+function resolvers.unresolve(str)
+ return abstract[str] or str
+end
+function resolvers.setdynamic(str)
+ dynamic[str]=true
+end
+local pattern=Cs((C(R("az")^2)*P(":")*C((1-S(" \"\';,"))^1)/_resolve_+P(1))^0)
+local prefix=C(R("az")^2)*P(":")
+local target=C((1-S(" \"\';,"))^1)
+local notarget=(#S(";,")+P(-1))*Cc("")
+local p_resolve=Cs(((prefix*(target+notarget))/_resolve_+P(1))^0)
+local p_simple=prefix*P(-1)
+local function resolve(str)
+ if type(str)=="table" then
+ local res={}
+ for i=1,#str do
+ res[i]=resolve(str[i])
+ end
+ return res
+ end
+ local res=resolved[str]
+ if res then
+ return res
+ end
+ local simple=lpegmatch(p_simple,str)
+ local action=prefixes[simple]
+ if action then
+ local res=action(res)
+ if not dynamic[simple] then
+ resolved[simple]=res
+ abstract[res]=simple
+ end
+ return res
+ end
+ res=lpegmatch(p_resolve,str)
+ resolved[str]=res
+ abstract[res]=str
+ return res
+end
+resolvers.resolve=resolve
+if type(osuname)=="function" then
+ for k,v in next,osuname() do
+ if not prefixes[k] then
+ prefixes[k]=function() return v end
+ end
+ end
+end
+if ostype=="unix" then
+ local pattern
+ local function makepattern(t,k,v)
+ if t then
+ rawset(t,k,v)
+ end
+ local colon=P(":")
+ for k,v in table.sortedpairs(prefixes) do
+ if p then
+ p=P(k)+p
+ else
+ p=P(k)
+ end
+ end
+ pattern=Cs((p*colon+colon/";"+P(1))^0)
+ end
+ makepattern()
+ table.setmetatablenewindex(prefixes,makepattern)
+ function resolvers.repath(str)
+ return lpegmatch(pattern,str)
+ end
+else
+ function resolvers.repath(str)
+ return str
+ end
end
@@ -12576,7 +13317,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-exp"] = package.loaded["data-exp"] or true
--- original size: 15317, stripped down to: 9723
+-- original size: 17216, stripped down to: 10657
if not modules then modules={} end modules ['data-exp']={
version=1.001,
@@ -12590,12 +13331,16 @@ local concat,sort=table.concat,table.sort
local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
local Ct,Cs,Cc,Carg,P,C,S=lpeg.Ct,lpeg.Cs,lpeg.Cc,lpeg.Carg,lpeg.P,lpeg.C,lpeg.S
local type,next=type,next
+local isdir=lfs.isdir
local ostype=os.type
-local collapsepath=file.collapsepath
+local collapsepath,joinpath,basename=file.collapsepath,file.join,file.basename
local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local trace_globbing=true trackers.register("resolvers.globbing",function(v) trace_globbing=v end)
local report_expansions=logs.reporter("resolvers","expansions")
+local report_globbing=logs.reporter("resolvers","globbing")
local resolvers=resolvers
+local resolveprefix=resolvers.resolve
local function f_both(a,b)
local t,n={},0
for sb in gmatch(b,"[^,]+") do
@@ -12685,35 +13430,27 @@ function resolvers.expandedpathfromlist(pathlist)
end
return newlist
end
-local cleanup=lpeg.replacer {
- { "!","" },
- { "\\","/" },
-}
-function resolvers.cleanpath(str)
- local doslashes=(P("\\")/"/"+1)^0
- local donegation=(P("!")/"" )^0
- local homedir=lpegmatch(Cs(donegation*doslashes),environment.homedir or "")
- if homedir=="~" or homedir=="" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if not str or find(str,"~",1,true) then
- return ""
- else
- return lpegmatch(cleanup,str)
+local usedhomedir=nil
+local donegation=(P("!")/"" )^0
+local doslashes=(P("\\")/"/"+1)^0
+local function expandedhome()
+ if not usedhomedir then
+ usedhomedir=lpegmatch(Cs(donegation*doslashes),environment.homedir or "")
+ if usedhomedir=="~" or usedhomedir=="" or not isdir(usedhomedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent path using current path")
end
- end
- else
- local dohome=((P("~")+P("$HOME"))/homedir)^0
- local cleanup=Cs(donegation*dohome*doslashes)
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str) or ""
+ usedhomedir="."
end
end
- return resolvers.cleanpath(str)
+ return usedhomedir
+end
+local dohome=((P("~")+P("$HOME")+P("%HOME%"))/expandedhome)^0
+local cleanup=Cs(donegation*dohome*doslashes)
+resolvers.cleanpath=function(str)
+ return str and lpegmatch(cleanup,str) or ""
end
-local expandhome=P("~")/"$HOME"
+local expandhome=P("~")/"$HOME"
local dodouble=P('"')/""*(expandhome+(1-P('"')))^0*P('"')/""
local dosingle=P("'")/""*(expandhome+(1-P("'")))^0*P("'")/""
local dostring=(expandhome+1 )^0
@@ -12765,46 +13502,67 @@ function resolvers.splitpath(str)
end
function resolvers.joinpath(str)
if type(str)=='table' then
- return file.joinpath(str)
+ return joinpath(str)
else
return str
end
end
local attributes,directory=lfs.attributes,lfs.dir
local weird=P(".")^1+lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local lessweird=P(".")^1+lpeg.anywhere(S("~`#$%^&*:;\"\'||<>,?\n\r\t"))
local timer={}
local scanned={}
local nofscans=0
local scancache={}
-local function scan(files,spec,path,n,m,r)
- local full=(path=="" and spec) or (spec..path..'/')
+local fullcache={}
+local nofsharedscans=0
+local function scan(files,remap,spec,path,n,m,r,onlyone,tolerant)
+ local full=path=="" and spec or (spec..path..'/')
local dirs={}
local nofdirs=0
+ local pattern=tolerant and lessweird or weird
for name in directory(full) do
- if not lpegmatch(weird,name) then
- local mode=attributes(full..name,'mode')
- if mode=='file' then
+ if not lpegmatch(pattern,name) then
+ local mode=attributes(full..name,"mode")
+ if mode=="file" then
n=n+1
- local f=files[name]
- if f then
- if type(f)=='string' then
- files[name]={ f,path }
+ local lower=lower(name)
+ local paths=files[lower]
+ if paths then
+ if onlyone then
else
- f[#f+1]=path
+ if type(paths)=="string" then
+ files[lower]={ paths,path }
+ else
+ paths[#paths+1]=path
+ end
+ if name~=lower then
+ local rl=remap[lower]
+ if not rl then
+ remap[lower]=name
+ r=r+1
+ elseif trace_globbing and rl~=name then
+ report_globbing("confusing filename, name: %a, lower: %a, already: %a",name,lower,rl)
+ end
+ end
end
else
- files[name]=path
- local lower=lower(name)
+ files[lower]=path
if name~=lower then
- files["remap:"..lower]=name
- r=r+1
+ local rl=remap[lower]
+ if not rl then
+ remap[lower]=name
+ r=r+1
+ elseif trace_globbing and rl~=name then
+ report_globbing("confusing filename, name: %a, lower: %a, already: %a",name,lower,rl)
+ end
end
end
- elseif mode=='directory' then
+ elseif mode=="directory" then
m=m+1
nofdirs=nofdirs+1
if path~="" then
- dirs[nofdirs]=path..'/'..name
+ dirs[nofdirs]=path.."/"..name
else
dirs[nofdirs]=name
end
@@ -12814,107 +13572,69 @@ local function scan(files,spec,path,n,m,r)
if nofdirs>0 then
sort(dirs)
for i=1,nofdirs do
- files,n,m,r=scan(files,spec,dirs[i],n,m,r)
+ files,remap,n,m,r=scan(files,remap,spec,dirs[i],n,m,r,onlyonce,tolerant)
end
end
scancache[sub(full,1,-2)]=files
- return files,n,m,r
+ return files,remap,n,m,r
end
-local fullcache={}
-function resolvers.scanfiles(path,branch,usecache)
- statistics.starttiming(timer)
- local realpath=resolvers.resolve(path)
+function resolvers.scanfiles(path,branch,usecache,onlyonce,tolerant)
+ local realpath=resolveprefix(path)
if usecache then
- local files=fullcache[realpath]
- if files then
+ local content=fullcache[realpath]
+ if content then
if trace_locating then
- report_expansions("using caches scan of path %a, branch %a",path,branch or path)
+ report_expansions("using cached scan of path %a, branch %a",path,branch or path)
end
- return files
+ nofsharedscans=nofsharedscans+1
+ return content
end
end
+ statistics.starttiming(timer)
if trace_locating then
report_expansions("scanning path %a, branch %a",path,branch or path)
end
- local files,n,m,r=scan({},realpath..'/',"",0,0,0)
- files.__path__=path
- files.__files__=n
- files.__directories__=m
- files.__remappings__=r
- if trace_locating then
- report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
- end
- if usecache then
- scanned[#scanned+1]=realpath
- fullcache[realpath]=files
- end
- nofscans=nofscans+1
- statistics.stoptiming(timer)
- return files
-end
-local function simplescan(files,spec,path)
- local full=(path=="" and spec) or (spec..path..'/')
- local dirs={}
- local nofdirs=0
- for name in directory(full) do
- if not lpegmatch(weird,name) then
- local mode=attributes(full..name,'mode')
- if mode=='file' then
- if not files[name] then
- files[name]=path
- end
- elseif mode=='directory' then
- nofdirs=nofdirs+1
- if path~="" then
- dirs[nofdirs]=path..'/'..name
- else
- dirs[nofdirs]=name
- end
- end
- end
- end
- if nofdirs>0 then
- sort(dirs)
- for i=1,nofdirs do
- files=simplescan(files,spec,dirs[i])
- end
- end
- return files
-end
-local simplecache={}
-local nofsharedscans=0
-function resolvers.simplescanfiles(path,branch,usecache)
- statistics.starttiming(timer)
- local realpath=resolvers.resolve(path)
- if usecache then
- local files=simplecache[realpath]
- if not files then
- files=scancache[realpath]
- if files then
- nofsharedscans=nofsharedscans+1
- end
+ local content
+ if isdir(realpath) then
+ local files,remap,n,m,r=scan({},{},realpath..'/',"",0,0,0,onlyonce,tolerant)
+ content={
+ metadata={
+ path=path,
+ files=n,
+ directories=m,
+ remappings=r,
+ },
+ files=files,
+ remap=remap,
+ }
+ if trace_locating then
+ report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
- if files then
- if trace_locating then
- report_expansions("using caches scan of path %a, branch %a",path,branch or path)
- end
- return files
+ else
+ content={
+ metadata={
+ path=path,
+ files=0,
+ directories=0,
+ remappings=0,
+ },
+ files={},
+ remap={},
+ }
+ if trace_locating then
+ report_expansions("invalid path %a",realpath)
end
end
- if trace_locating then
- report_expansions("scanning path %a, branch %a",path,branch or path)
- end
- local files=simplescan({},realpath..'/',"")
- if trace_locating then
- report_expansions("%s files found",table.count(files))
- end
if usecache then
scanned[#scanned+1]=realpath
- simplecache[realpath]=files
+ fullcache[realpath]=content
end
nofscans=nofscans+1
statistics.stoptiming(timer)
- return files
+ return content
+end
+function resolvers.simplescanfiles(path,branch,usecache)
+ return resolvers.scanfiles(path,branch,usecache,true,true)
end
function resolvers.scandata()
table.sort(scanned)
@@ -12925,6 +13645,52 @@ function resolvers.scandata()
paths=scanned,
}
end
+function resolvers.get_from_content(content,path,name)
+ if not content then
+ return
+ end
+ local files=content.files
+ if not files then
+ return
+ end
+ local remap=content.remap
+ if not remap then
+ return
+ end
+ if name then
+ local used=lower(name)
+ return path,remap[used] or used
+ else
+ local name=path
+ local used=lower(name)
+ local path=files[used]
+ if path then
+ return path,remap[used] or used
+ end
+ end
+end
+local nothing=function() end
+function resolvers.filtered_from_content(content,pattern)
+ if content and type(pattern)=="string" then
+ local pattern=lower(pattern)
+ local files=content.files
+ local remap=content.remap
+ if files and remap then
+ local n=next(files)
+ local function iterator()
+ while n do
+ local k=n
+ n=next(files,k)
+ if find(k,pattern) then
+ return files[k],remap and remap[k] or k
+ end
+ end
+ end
+ return iterator
+ end
+ end
+ return nothing
+end
end -- of closure
@@ -12933,7 +13699,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-env"] = package.loaded["data-env"] or true
--- original size: 8769, stripped down to: 6490
+-- original size: 9216, stripped down to: 6798
if not modules then modules={} end modules ['data-env']={
version=1.001,
@@ -12951,10 +13717,12 @@ local formats=allocate()
local suffixes=allocate()
local dangerous=allocate()
local suffixmap=allocate()
+local usertypes=allocate()
resolvers.formats=formats
resolvers.suffixes=suffixes
resolvers.dangerous=dangerous
resolvers.suffixmap=suffixmap
+resolvers.usertypes=usertypes
local luasuffixes=utilities.lua.suffixes
local relations=allocate {
core={
@@ -13022,11 +13790,13 @@ local relations=allocate {
names={ "mp" },
variable='MPINPUTS',
suffixes={ 'mp','mpvi','mpiv','mpii' },
+ usertype=true,
},
tex={
names={ "tex" },
variable='TEXINPUTS',
- suffixes={ 'tex',"mkvi","mkiv","mkii" },
+ suffixes={ "tex","mkvi","mkiv","mkii","cld","lfg","xml" },
+ usertype=true,
},
icc={
names={ "icc","icc profile","icc profiles" },
@@ -13042,6 +13812,7 @@ local relations=allocate {
names={ "lua" },
variable='LUAINPUTS',
suffixes={ luasuffixes.lua,luasuffixes.luc,luasuffixes.tma,luasuffixes.tmc },
+ usertype=true,
},
lib={
names={ "lib" },
@@ -13050,11 +13821,15 @@ local relations=allocate {
},
bib={
names={ 'bib' },
+ variable='BIBINPUTS',
suffixes={ 'bib' },
+ usertype=true,
},
bst={
names={ 'bst' },
+ variable='BSTINPUTS',
suffixes={ 'bst' },
+ usertype=true,
},
fontconfig={
names={ 'fontconfig','fontconfig file','fontconfig files' },
@@ -13136,8 +13911,9 @@ function resolvers.updaterelations()
for name,relation in next,categories do
local rn=relation.names
local rv=relation.variable
- local rs=relation.suffixes
if rn and rv then
+ local rs=relation.suffixes
+ local ru=relation.usertype
for i=1,#rn do
local rni=lower(gsub(rn[i]," ",""))
formats[rni]=rv
@@ -13149,8 +13925,9 @@ function resolvers.updaterelations()
end
end
end
- end
- if rs then
+ if ru then
+ usertypes[name]=true
+ end
end
end
end
@@ -13201,7 +13978,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-tmp"] = package.loaded["data-tmp"] or true
--- original size: 15532, stripped down to: 11648
+-- original size: 15681, stripped down to: 11761
if not modules then modules={} end modules ['data-tmp']={
version=1.100,
@@ -13220,6 +13997,7 @@ local trace_cache=false trackers.register("resolvers.cache",function(v) trace_ca
local report_caches=logs.reporter("resolvers","caches")
local report_resolvers=logs.reporter("resolvers","caching")
local resolvers=resolvers
+local cleanpath=resolvers.cleanpath
local directive_cleanup=false directives.register("system.compile.cleanup",function(v) directive_cleanup=v end)
local directive_strip=false directives.register("system.compile.strip",function(v) directive_strip=v end)
local compile=utilities.lua.compile
@@ -13241,7 +14019,7 @@ caches.relocate=false
caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" }
local writable,readables,usedreadables=nil,{},{}
local function identify()
- local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE")
+ local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE")
if texmfcaches then
for k=1,#texmfcaches do
local cachepath=texmfcaches[k]
@@ -13495,10 +14273,12 @@ local content_state={}
function caches.contentstate()
return content_state or {}
end
-function caches.loadcontent(cachename,dataname)
- local name=caches.hashed(cachename)
- local full,path=caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
- local filename=file.join(path,name)
+function caches.loadcontent(cachename,dataname,filename)
+ if not filename then
+ local name=caches.hashed(cachename)
+ local full,path=caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
+ filename=file.join(path,name)
+ end
local blob=loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
if blob then
local data=blob()
@@ -13530,10 +14310,12 @@ function caches.collapsecontent(content)
end
end
end
-function caches.savecontent(cachename,dataname,content)
- local name=caches.hashed(cachename)
- local full,path=caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
- local filename=file.join(path,name)
+function caches.savecontent(cachename,dataname,content,filename)
+ if not filename then
+ local name=caches.hashed(cachename)
+ local full,path=caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
+ filename=file.join(path,name)
+ end
local luaname=addsuffix(filename,luasuffixes.lua)
local lucname=addsuffix(filename,luasuffixes.luc)
if trace_locating then
@@ -13576,7 +14358,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-met"] = package.loaded["data-met"] or true
--- original size: 5460, stripped down to: 4014
+-- original size: 5347, stripped down to: 4015
if not modules then modules={} end modules ['data-met']={
version=1.100,
@@ -13604,7 +14386,7 @@ local function splitmethod(filename)
if type(filename)=="table" then
return filename
end
- filename=file.collapsepath(filename,".")
+ filename=file.collapsepath(filename,".")
if not find(filename,"://",1,true) then
return { scheme="file",path=filename,original=filename,filename=filename }
end
@@ -13695,7 +14477,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-res"] = package.loaded["data-res"] or true
--- original size: 62045, stripped down to: 43116
+-- original size: 67003, stripped down to: 46291
if not modules then modules={} end modules ['data-res']={
version=1.001,
@@ -13705,7 +14487,7 @@ if not modules then modules={} end modules ['data-res']={
license="see context related readme files",
}
local gsub,find,lower,upper,match,gmatch=string.gsub,string.find,string.lower,string.upper,string.match,string.gmatch
-local concat,insert,sortedkeys=table.concat,table.insert,table.sortedkeys
+local concat,insert,remove,sortedkeys,sortedhash=table.concat,table.insert,table.remove,table.sortedkeys,table.sortedhash
local next,type,rawget=next,type,rawget
local os=os
local P,S,R,C,Cc,Cs,Ct,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Carg
@@ -13714,17 +14496,23 @@ local formatters=string.formatters
local filedirname=file.dirname
local filebasename=file.basename
local suffixonly=file.suffixonly
+local addsuffix=file.addsuffix
+local removesuffix=file.removesuffix
local filejoin=file.join
local collapsepath=file.collapsepath
local joinpath=file.joinpath
+local is_qualified_path=file.is_qualified_path
local allocate=utilities.storage.allocate
local settings_to_array=utilities.parsers.settings_to_array
+local getcurrentdir=lfs.currentdir
+local isfile=lfs.isfile
+local isdir=lfs.isdir
local setmetatableindex=table.setmetatableindex
local luasuffixes=utilities.lua.suffixes
-local getcurrentdir=lfs.currentdir
local trace_locating=false trackers .register("resolvers.locating",function(v) trace_locating=v end)
local trace_detail=false trackers .register("resolvers.details",function(v) trace_detail=v end)
local trace_expansions=false trackers .register("resolvers.expansions",function(v) trace_expansions=v end)
+local trace_paths=false trackers .register("resolvers.paths",function(v) trace_paths=v end)
local resolve_otherwise=true directives.register("resolvers.otherwise",function(v) resolve_otherwise=v end)
local report_resolving=logs.reporter("resolvers","resolving")
local resolvers=resolvers
@@ -13732,10 +14520,14 @@ local expandedpathfromlist=resolvers.expandedpathfromlist
local checkedvariable=resolvers.checkedvariable
local splitconfigurationpath=resolvers.splitconfigurationpath
local methodhandler=resolvers.methodhandler
+local filtered=resolvers.filtered_from_content
+local lookup=resolvers.get_from_content
+local cleanpath=resolvers.cleanpath
+local resolveprefix=resolvers.resolve
local initializesetter=utilities.setters.initialize
local ostype,osname,osenv,ossetenv,osgetenv=os.type,os.name,os.env,os.setenv,os.getenv
-resolvers.cacheversion='1.0.1'
-resolvers.configbanner=''
+resolvers.cacheversion="1.100"
+resolvers.configbanner=""
resolvers.homedir=environment.homedir
resolvers.criticalvars=allocate { "SELFAUTOLOC","SELFAUTODIR","SELFAUTOPARENT","TEXMFCNF","TEXMF","TEXOS" }
resolvers.luacnfname="texmfcnf.lua"
@@ -13754,6 +14546,7 @@ end
local unset_variable="unset"
local formats=resolvers.formats
local suffixes=resolvers.suffixes
+local usertypes=resolvers.usertypes
local dangerous=resolvers.dangerous
local suffixmap=resolvers.suffixmap
resolvers.defaultsuffixes={ "tex" }
@@ -13762,7 +14555,7 @@ local instance=resolvers.instance or nil
function resolvers.setenv(key,value,raw)
if instance then
instance.environment[key]=value
- ossetenv(key,raw and value or resolvers.resolve(value))
+ ossetenv(key,raw and value or resolveprefix(value))
end
end
local function getenv(key)
@@ -13776,7 +14569,7 @@ local function getenv(key)
end
resolvers.getenv=getenv
resolvers.env=getenv
-local function resolve(k)
+local function resolvevariable(k)
return instance.expansions[k]
end
local dollarstripper=lpeg.stripper("$")
@@ -13785,19 +14578,19 @@ local backslashswapper=lpeg.replacer("\\","/")
local somevariable=P("$")/""
local somekey=C(R("az","AZ","09","__","--")^1)
local somethingelse=P(";")*((1-S("!{}/\\"))^1*P(";")/"")+P(";")*(P(";")/"")+P(1)
-local variableexpander=Cs((somevariable*(somekey/resolve)+somethingelse)^1 )
+local variableexpander=Cs((somevariable*(somekey/resolvevariable)+somethingelse)^1 )
local cleaner=P("\\")/"/"+P(";")*S("!{}/\\")^0*P(";")^1/";"
local variablecleaner=Cs((cleaner+P(1))^0)
-local somevariable=R("az","AZ","09","__","--")^1/resolve
+local somevariable=R("az","AZ","09","__","--")^1/resolvevariable
local variable=(P("$")/"")*(somevariable+(P("{")/"")*somevariable*(P("}")/""))
local variableresolver=Cs((variable+P(1))^0)
local function expandedvariable(var)
return lpegmatch(variableexpander,var) or var
end
-function resolvers.newinstance()
- if trace_locating then
+function resolvers.newinstance()
+ if trace_locating then
report_resolving("creating instance")
- end
+ end
local environment,variables,expansions,order=allocate(),allocate(),allocate(),allocate()
local newinstance={
environment=environment,
@@ -13810,6 +14603,7 @@ function resolvers.newinstance()
foundintrees=allocate(),
hashes=allocate(),
hashed=allocate(),
+ pathlists=false,
specification=allocate(),
lists=allocate(),
data=allocate(),
@@ -13822,6 +14616,7 @@ function resolvers.newinstance()
savelists=true,
pattern=nil,
force_suffixes=true,
+ pathstack={},
}
setmetatableindex(variables,function(t,k)
local v
@@ -13871,8 +14666,13 @@ function resolvers.reset()
end
local function reset_hashes()
instance.lists={}
+ instance.pathlists=false
instance.found={}
end
+local function reset_caches()
+ instance.lists={}
+ instance.pathlists=false
+end
local slash=P("/")
local pathexpressionpattern=Cs (
Cc("^")*(
@@ -13924,13 +14724,13 @@ local function identify_configuration_files()
for i=1,#cnfpaths do
local filepath=cnfpaths[i]
local filename=collapsepath(filejoin(filepath,luacnfname))
- local realname=resolvers.resolve(filename)
+ local realname=resolveprefix(filename)
if trace_locating then
- local fullpath=gsub(resolvers.resolve(collapsepath(filepath)),"//","/")
+ local fullpath=gsub(resolveprefix(collapsepath(filepath)),"//","/")
local weirdpath=find(fullpath,"/texmf.+/texmf") or not find(fullpath,"/web2c",1,true)
report_resolving("looking for %a on %s path %a from specification %a",luacnfname,weirdpath and "weird" or "given",fullpath,filepath)
end
- if lfs.isfile(realname) then
+ if isfile(realname) then
specification[#specification+1]=filename
if trace_locating then
report_resolving("found configuration file %a",realname)
@@ -13952,7 +14752,7 @@ local function load_configuration_files()
local filename=specification[i]
local pathname=filedirname(filename)
local filename=filejoin(pathname,luacnfname)
- local realname=resolvers.resolve(filename)
+ local realname=resolveprefix(filename)
local blob=loadfile(realname)
if blob then
local setups=instance.setups
@@ -13960,7 +14760,7 @@ local function load_configuration_files()
local parent=data and data.parent
if parent then
local filename=filejoin(pathname,parent)
- local realname=resolvers.resolve(filename)
+ local realname=resolveprefix(filename)
local blob=loadfile(realname)
if blob then
local parentdata=blob()
@@ -13985,7 +14785,7 @@ local function load_configuration_files()
elseif variables[k]==nil then
if trace_locating and not warning then
report_resolving("variables like %a in configuration file %a should move to the 'variables' subtable",
- k,resolvers.resolve(filename))
+ k,resolveprefix(filename))
warning=true
end
variables[k]=v
@@ -14045,7 +14845,7 @@ local function locate_file_databases()
local stripped=lpegmatch(inhibitstripper,path)
if stripped~="" then
local runtime=stripped==path
- path=resolvers.cleanpath(path)
+ path=cleanpath(path)
local spec=resolvers.splitmethod(stripped)
if runtime and (spec.noscheme or spec.scheme=="file") then
stripped="tree:///"..stripped
@@ -14108,8 +14908,8 @@ function resolvers.renew(hashname)
report_resolving("identifying tree %a",hashname)
end
end
- local realpath=resolvers.resolve(hashname)
- if lfs.isdir(realpath) then
+ local realpath=resolveprefix(hashname)
+ if isdir(realpath) then
if trace_locating then
report_resolving("using path %a",realpath)
end
@@ -14210,19 +15010,53 @@ end
function resolvers.unexpandedpath(str)
return joinpath(resolvers.unexpandedpathlist(str))
end
+function resolvers.pushpath(name)
+ local pathstack=instance.pathstack
+ local lastpath=pathstack[#pathstack]
+ local pluspath=filedirname(name)
+ if lastpath then
+ lastpath=collapsepath(filejoin(lastpath,pluspath))
+ else
+ lastpath=collapsepath(pluspath)
+ end
+ insert(pathstack,lastpath)
+ if trace_paths then
+ report_resolving("pushing path %a",lastpath)
+ end
+end
+function resolvers.poppath()
+ local pathstack=instance.pathstack
+ if trace_paths and #pathstack>0 then
+ report_resolving("popping path %a",pathstack[#pathstack])
+ end
+ remove(pathstack)
+end
+function resolvers.stackpath()
+ local pathstack=instance.pathstack
+ local currentpath=pathstack[#pathstack]
+ return currentpath~="" and currentpath or nil
+end
local done={}
function resolvers.resetextrapath()
local ep=instance.extra_paths
if not ep then
- ep,done={},{}
- instance.extra_paths=ep
+ done={}
+ instance.extra_paths={}
elseif #ep>0 then
- instance.lists,done={},{}
+ done={}
+ reset_caches()
end
end
function resolvers.registerextrapath(paths,subpaths)
- paths=settings_to_array(paths)
- subpaths=settings_to_array(subpaths)
+ if not subpaths or subpaths=="" then
+ if not paths or path=="" then
+ return
+ elseif done[paths] then
+ return
+ end
+ end
+ local paths=settings_to_array(paths)
+ local subpaths=settings_to_array(subpaths)
local ep=instance.extra_paths or {}
local oldn=#ep
local newn=oldn
@@ -14237,7 +15071,7 @@ function resolvers.registerextrapath(paths,subpaths)
local ps=p.."/"..s
if not done[ps] then
newn=newn+1
- ep[newn]=resolvers.cleanpath(ps)
+ ep[newn]=cleanpath(ps)
done[ps]=true
end
end
@@ -14247,7 +15081,7 @@ function resolvers.registerextrapath(paths,subpaths)
local p=paths[i]
if not done[p] then
newn=newn+1
- ep[newn]=resolvers.cleanpath(p)
+ ep[newn]=cleanpath(p)
done[p]=true
end
end
@@ -14259,7 +15093,7 @@ function resolvers.registerextrapath(paths,subpaths)
local ps=ep[i].."/"..s
if not done[ps] then
newn=newn+1
- ep[newn]=resolvers.cleanpath(ps)
+ ep[newn]=cleanpath(ps)
done[ps]=true
end
end
@@ -14268,52 +15102,70 @@ function resolvers.registerextrapath(paths,subpaths)
if newn>0 then
instance.extra_paths=ep
end
- if newn>oldn then
- instance.lists={}
+ if newn~=oldn then
+ reset_caches()
end
end
-local function made_list(instance,list)
- local ep=instance.extra_paths
- if not ep or #ep==0 then
- return list
+function resolvers.pushextrapath(path)
+ local paths=settings_to_array(path)
+ if instance.extra_stack then
+ insert(instance.extra_stack,1,paths)
else
- local done,new,newn={},{},0
- for k=1,#list do
- local v=list[k]
- if not done[v] then
- if find(v,"^[%.%/]$") then
- done[v]=true
- newn=newn+1
- new[newn]=v
- else
- break
- end
- end
- end
- for k=1,#ep do
- local v=ep[k]
+ instance.extra_stack={ paths }
+ end
+ reset_caches()
+end
+function resolvers.popextrapath()
+ if instance.extra_stack then
+ reset_caches()
+ return remove(instance.extra_stack,1)
+ end
+end
+local function made_list(instance,list,extra_too)
+ local done={}
+ local new={}
+ local newn=0
+ local function add(p)
+ for k=1,#p do
+ local v=p[k]
if not done[v] then
done[v]=true
newn=newn+1
new[newn]=v
end
end
- for k=1,#list do
- local v=list[k]
- if not done[v] then
- done[v]=true
- newn=newn+1
- new[newn]=v
+ end
+ for k=1,#list do
+ local v=list[k]
+ if done[v] then
+ elseif find(v,"^[%.%/]$") then
+ done[v]=true
+ newn=newn+1
+ new[newn]=v
+ else
+ break
+ end
+ end
+ if extra_too then
+ local es=instance.extra_stack
+ if es and #es>0 then
+ for k=1,#es do
+ add(es[k])
end
end
- return new
+ local ep=instance.extra_paths
+ if ep and #ep>0 then
+ add(ep)
+ end
end
+ add(list)
+ return new
end
function resolvers.cleanpathlist(str)
local t=resolvers.expandedpathlist(str)
if t then
for i=1,#t do
- t[i]=collapsepath(resolvers.cleanpath(t[i]))
+ t[i]=collapsepath(cleanpath(t[i]))
end
end
return t
@@ -14321,22 +15173,22 @@ end
function resolvers.expandpath(str)
return joinpath(resolvers.expandedpathlist(str))
end
-function resolvers.expandedpathlist(str)
+function resolvers.expandedpathlist(str,extra_too)
if not str then
return {}
- elseif instance.savelists then
+ elseif instance.savelists then
str=lpegmatch(dollarstripper,str)
local lists=instance.lists
local lst=lists[str]
if not lst then
- local l=made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
+ local l=made_list(instance,resolvers.splitpath(resolvers.expansion(str)),extra_too)
lst=expandedpathfromlist(l)
lists[str]=lst
end
return lst
else
local lst=resolvers.splitpath(resolvers.expansion(str))
- return made_list(instance,expandedpathfromlist(lst))
+ return made_list(instance,expandedpathfromlist(lst),extra_too)
end
end
function resolvers.expandedpathlistfromvariable(str)
@@ -14347,6 +15199,13 @@ end
function resolvers.expandpathfromvariable(str)
return joinpath(resolvers.expandedpathlistfromvariable(str))
end
+function resolvers.cleanedpathlist(v)
+ local t=resolvers.expandedpathlist(v)
+ for i=1,#t do
+ t[i]=resolvers.resolve(resolvers.cleanpath(t[i]))
+ end
+ return t
+end
function resolvers.expandbraces(str)
local ori=str
local pth=expandedpathfromlist(resolvers.splitpath(ori))
@@ -14363,7 +15222,7 @@ function resolvers.registerfilehash(name,content,someerror)
end
end
local function isreadable(name)
- local readable=lfs.isfile(name)
+ local readable=isfile(name)
if trace_detail then
if readable then
report_resolving("file %a is readable",name)
@@ -14373,70 +15232,57 @@ local function isreadable(name)
end
return readable
end
-local function collect_files(names)
- local filelist,noffiles={},0
+local function collect_files(names)
+ local filelist={}
+ local noffiles=0
+ local function check(hash,root,pathname,path,name)
+ if not pathname or find(path,pathname) then
+ local variant=hash.type
+ local search=filejoin(root,path,name)
+ local result=methodhandler('concatinators',variant,root,path,name)
+ if trace_detail then
+ report_resolving("match: variant %a, search %a, result %a",variant,search,result)
+ end
+ noffiles=noffiles+1
+ filelist[noffiles]={ variant,search,result }
+ end
+ end
for k=1,#names do
- local fname=names[k]
+ local filename=names[k]
if trace_detail then
- report_resolving("checking name %a",fname)
+ report_resolving("checking name %a",filename)
end
- local bname=filebasename(fname)
- local dname=filedirname(fname)
- if dname=="" or find(dname,"^%.") then
- dname=false
+ local basename=filebasename(filename)
+ local pathname=filedirname(filename)
+ if pathname=="" or find(pathname,"^%.") then
+ pathname=false
else
- dname=gsub(dname,"%*",".*")
- dname="/"..dname.."$"
+ pathname=gsub(pathname,"%*",".*")
+ pathname="/"..pathname.."$"
end
local hashes=instance.hashes
for h=1,#hashes do
local hash=hashes[h]
- local blobpath=hash.name
- local files=blobpath and instance.files[blobpath]
- if files then
+ local hashname=hash.name
+ local content=hashname and instance.files[hashname]
+ if content then
if trace_detail then
- report_resolving("deep checking %a, base %a, pattern %a",blobpath,bname,dname)
- end
- local blobfile=files[bname]
- if not blobfile then
- local rname="remap:"..bname
- blobfile=files[rname]
- if blobfile then
- bname=files[rname]
- blobfile=files[bname]
- end
+ report_resolving("deep checking %a, base %a, pattern %a",hashname,basename,pathname)
end
- if blobfile then
- local blobroot=files.__path__ or blobpath
- if type(blobfile)=='string' then
- if not dname or find(blobfile,dname) then
- local variant=hash.type
- local search=filejoin(blobroot,blobfile,bname)
- local result=methodhandler('concatinators',hash.type,blobroot,blobfile,bname)
- if trace_detail then
- report_resolving("match: variant %a, search %a, result %a",variant,search,result)
- end
- noffiles=noffiles+1
- filelist[noffiles]={ variant,search,result }
- end
+ local path,name=lookup(content,basename)
+ if path then
+ local metadata=content.metadata
+ local realroot=metadata and metadata.path or hashname
+ if type(path)=="string" then
+ check(hash,realroot,pathname,path,name)
else
- for kk=1,#blobfile do
- local vv=blobfile[kk]
- if not dname or find(vv,dname) then
- local variant=hash.type
- local search=filejoin(blobroot,vv,bname)
- local result=methodhandler('concatinators',hash.type,blobroot,vv,bname)
- if trace_detail then
- report_resolving("match: variant %a, search %a, result %a",variant,search,result)
- end
- noffiles=noffiles+1
- filelist[noffiles]={ variant,search,result }
- end
+ for i=1,#path do
+ check(hash,realroot,pathname,path[i],name)
end
end
end
elseif trace_locating then
- report_resolving("no match in %a (%s)",blobpath,bname)
+ report_resolving("no match in %a (%s)",hashname,basename)
end
end
end
@@ -14461,7 +15307,7 @@ end
local function can_be_dir(name)
local fakepaths=instance.fakepaths
if not fakepaths[name] then
- if lfs.isdir(name) then
+ if isdir(name) then
fakepaths[name]=1
else
fakepaths[name]=2
@@ -14477,10 +15323,11 @@ local function find_analyze(filename,askedformat,allresults)
if askedformat=="" then
if ext=="" or not suffixmap[ext] then
local defaultsuffixes=resolvers.defaultsuffixes
+ local formatofsuffix=resolvers.formatofsuffix
for i=1,#defaultsuffixes do
local forcedname=filename..'.'..defaultsuffixes[i]
wantedfiles[#wantedfiles+1]=forcedname
- filetype=resolvers.formatofsuffix(forcedname)
+ filetype=formatofsuffix(forcedname)
if trace_locating then
report_resolving("forcing filetype %a",filetype)
end
@@ -14520,14 +15367,14 @@ local function find_wildcard(filename,allresults)
if trace_locating then
report_resolving("checking wildcard %a",filename)
end
- local method,result=resolvers.findwildcardfiles(filename)
+ local result=resolvers.findwildcardfiles(filename)
if result then
return "wildcard",result
end
end
end
local function find_qualified(filename,allresults,askedformat,alsostripped)
- if not file.is_qualified_path(filename) then
+ if not is_qualified_path(filename) then
return
end
if trace_locating then
@@ -14601,33 +15448,66 @@ local function check_subpath(fname)
return fname
end
end
-local function find_intree(filename,filetype,wantedfiles,allresults)
+local function makepathlist(list,filetype)
local typespec=resolvers.variableofformat(filetype)
- local pathlist=resolvers.expandedpathlist(typespec)
- local method="intree"
+ local pathlist=resolvers.expandedpathlist(typespec,filetype and usertypes[filetype])
+ local entry={}
if pathlist and #pathlist>0 then
- local filelist=collect_files(wantedfiles)
+ for k=1,#pathlist do
+ local path=pathlist[k]
+ local prescanned=find(path,'^!!')
+ local resursive=find(path,'//$')
+ local pathname=lpegmatch(inhibitstripper,path)
+ local expression=makepathexpression(pathname)
+ local barename=gsub(pathname,"/+$","")
+ barename=resolveprefix(barename)
+ local scheme=url.hasscheme(barename)
+ local schemename=gsub(barename,"%.%*$",'')
+ entry[k]={
+ path=path,
+ pathname=pathname,
+ prescanned=prescanned,
+ recursive=recursive,
+ expression=expression,
+ barename=barename,
+ scheme=scheme,
+ schemename=schemename,
+ }
+ end
+ entry.typespec=typespec
+ list[filetype]=entry
+ else
+ list[filetype]=false
+ end
+ return entry
+end
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local pathlists=instance.pathlists
+ if not pathlists then
+ pathlists=setmetatableindex(allocate(),makepathlist)
+ instance.pathlists=pathlists
+ end
+ local pathlist=pathlists[filetype]
+ if pathlist then
+ local method="intree"
+ local filelist=collect_files(wantedfiles)
local dirlist={}
+ local result={}
if filelist then
for i=1,#filelist do
dirlist[i]=filedirname(filelist[i][3]).."/"
end
end
if trace_detail then
- report_resolving("checking filename %a",filename)
+ report_resolving("checking filename %a in tree",filename)
end
- local resolve=resolvers.resolve
- local result={}
for k=1,#pathlist do
- local path=pathlist[k]
- local pathname=lpegmatch(inhibitstripper,path)
- local doscan=path==pathname
- if not find (pathname,'//$') then
- doscan=false
- end
+ local entry=pathlist[k]
+ local path=entry.path
+ local pathname=entry.pathname
local done=false
if filelist then
- local expression=makepathexpression(pathname)
+ local expression=entry.expression
if trace_detail then
report_resolving("using pattern %a for path %a",expression,pathname)
end
@@ -14635,8 +15515,8 @@ local function find_intree(filename,filetype,wantedfiles,allresults)
local fl=filelist[k]
local f=fl[2]
local d=dirlist[k]
- if find(d,expression) or find(resolve(d),expression) then
- result[#result+1]=resolve(fl[3])
+ if find(d,expression) or find(resolveprefix(d),expression) then
+ result[#result+1]=resolveprefix(fl[3])
done=true
if allresults then
if trace_detail then
@@ -14657,56 +15537,62 @@ local function find_intree(filename,filetype,wantedfiles,allresults)
method="database"
else
method="filesystem"
- pathname=gsub(pathname,"/+$","")
- pathname=resolve(pathname)
- local scheme=url.hasscheme(pathname)
+ local scheme=entry.scheme
if not scheme or scheme=="file" then
- local pname=gsub(pathname,"%.%*$",'')
+ local pname=entry.schemename
if not find(pname,"*",1,true) then
if can_be_dir(pname) then
- for k=1,#wantedfiles do
- local w=wantedfiles[k]
- local fname=check_subpath(filejoin(pname,w))
- if fname then
- result[#result+1]=fname
- done=true
- if not allresults then
- break
- end
+ if not done and not entry.prescanned then
+ if trace_detail then
+ report_resolving("quick root scan for %a",pname)
end
- end
- if not done and doscan then
- local files=resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w=wantedfiles[k]
- local subpath=files[w]
- if not subpath or subpath=="" then
- elseif type(subpath)=="string" then
- local fname=check_subpath(filejoin(pname,subpath,w))
- if fname then
- result[#result+1]=fname
- done=true
- if not allresults then
- break
- end
+ local fname=check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
end
- else
- for i=1,#subpath do
- local sp=subpath[i]
- if sp=="" then
- else
- local fname=check_subpath(filejoin(pname,sp,w))
- if fname then
- result[#result+1]=fname
- done=true
- if not allresults then
- break
+ end
+ end
+ if not done and entry.recursive then
+ if trace_detail then
+ report_resolving("scanning filesystem for %a",pname)
+ end
+ local files=resolvers.simplescanfiles(pname,false,true)
+ for k=1,#wantedfiles do
+ local w=wantedfiles[k]
+ local subpath=files[w]
+ if not subpath or subpath=="" then
+ elseif type(subpath)=="string" then
+ local fname=check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp=subpath[i]
+ if sp=="" then
+ else
+ local fname=check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
end
end
end
- end
- if done and not allresults then
- break
+ if done and not allresults then
+ break
+ end
end
end
end
@@ -14714,6 +15600,18 @@ local function find_intree(filename,filetype,wantedfiles,allresults)
end
else
end
+ else
+ for k=1,#wantedfiles do
+ local pname=entry.barename
+ local fname=methodhandler('finders',pname.."/"..wantedfiles[k])
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
+ end
+ end
end
end
if done and not allresults then
@@ -14748,10 +15646,13 @@ local function find_otherwise(filename,filetype,wantedfiles,allresults)
local filelist=collect_files(wantedfiles)
local fl=filelist and filelist[1]
if fl then
- return "otherwise",{ resolvers.resolve(fl[3]) }
+ return "otherwise",{ resolveprefix(fl[3]) }
end
end
collect_instance_files=function(filename,askedformat,allresults)
+ if not filename or filename=="" then
+ return {}
+ end
askedformat=askedformat or ""
filename=collapsepath(filename,".")
filename=gsub(filename,"^%./",getcurrentdir().."/")
@@ -14786,7 +15687,11 @@ collect_instance_files=function(filename,askedformat,allresults)
else
local method,result,stamp,filetype,wantedfiles
if instance.remember then
- stamp=formatters["%s--%s"](filename,askedformat)
+ if askedformat=="" then
+ stamp=formatters["%s::%s"](suffixonly(filename),filename)
+ else
+ stamp=formatters["%s::%s"](askedformat,filename)
+ end
result=stamp and instance.found[stamp]
if result then
if trace_locating then
@@ -14821,7 +15726,7 @@ collect_instance_files=function(filename,askedformat,allresults)
end
if stamp then
if trace_locating then
- report_resolving("remembering file %a",filename)
+ report_resolving("remembering file %a using hash %a",filename,stamp)
end
instance.found[stamp]=result
end
@@ -14829,6 +15734,9 @@ collect_instance_files=function(filename,askedformat,allresults)
end
end
local function findfiles(filename,filetype,allresults)
+ if not filename or filename=="" then
+ return {}
+ end
local result,status=collect_instance_files(filename,filetype or "",allresults)
if not result or #result==0 then
local lowered=lower(filename)
@@ -14848,39 +15756,30 @@ function resolvers.findpath(filename,filetype)
return filedirname(findfiles(filename,filetype,false)[1] or "")
end
local function findgivenfiles(filename,allresults)
- local bname,result=filebasename(filename),{}
+ local base=filebasename(filename)
+ local result={}
local hashes=instance.hashes
- local noffound=0
+ local function okay(hash,path,name)
+ local found=methodhandler('concatinators',hash.type,hash.name,path,name)
+ if found and found~="" then
+ result[#result+1]=resolveprefix(found)
+ return not allresults
+ end
+ end
for k=1,#hashes do
local hash=hashes[k]
- local files=instance.files[hash.name] or {}
- local blist=files[bname]
- if not blist then
- local rname="remap:"..bname
- blist=files[rname]
- if blist then
- bname=files[rname]
- blist=files[bname]
- end
- end
- if blist then
- if type(blist)=='string' then
- local found=methodhandler('concatinators',hash.type,hash.name,blist,bname) or ""
- if found~="" then
- noffound=noffound+1
- result[noffound]=resolvers.resolve(found)
- if not allresults then
- break
- end
+ local content=instance.files[hash.name]
+ if content then
+ local path,name=lookup(content,base)
+ if not path then
+ elseif type(path)=="string" then
+ if okay(hash,path,name) then
+ return result
end
else
- for kk=1,#blist do
- local vv=blist[kk]
- local found=methodhandler('concatinators',hash.type,hash.name,vv,bname) or ""
- if found~="" then
- noffound=noffound+1
- result[noffound]=resolvers.resolve(found)
- if not allresults then break end
+ for i=1,#path do
+ if okay(hash,path[i],name) then
+ return result
end
end
end
@@ -14894,64 +15793,80 @@ end
function resolvers.findgivenfile(filename)
return findgivenfiles(filename,false)[1] or ""
end
-local function doit(path,blist,bname,tag,variant,result,allresults)
- local done=false
- if blist and variant then
- local resolve=resolvers.resolve
- if type(blist)=='string' then
- if find(lower(blist),path) then
- local full=methodhandler('concatinators',variant,tag,blist,bname) or ""
- result[#result+1]=resolve(full)
- done=true
- end
- else
- for kk=1,#blist do
- local vv=blist[kk]
- if find(lower(vv),path) then
- local full=methodhandler('concatinators',variant,tag,vv,bname) or ""
- result[#result+1]=resolve(full)
- done=true
- if not allresults then break end
- end
- end
- end
- end
- return done
-end
local makewildcard=Cs(
(P("^")^0*P("/")*P(-1)+P(-1))/".*"+(P("^")^0*P("/")/"")^0*(P("*")/".*"+P("-")/"%%-"+P(".")/"%%."+P("?")/"."+P("\\")/"/"+P(1))^0
)
function resolvers.wildcardpattern(pattern)
return lpegmatch(makewildcard,pattern) or pattern
end
-local function findwildcardfiles(filename,allresults,result)
- result=result or {}
+local function findwildcardfiles(filename,allresults,result)
+ local result=result or {}
local base=filebasename(filename)
local dirn=filedirname(filename)
local path=lower(lpegmatch(makewildcard,dirn) or dirn)
local name=lower(lpegmatch(makewildcard,base) or base)
- local files,done=instance.files,false
+ local files=instance.files
if find(name,"*",1,true) then
local hashes=instance.hashes
+ local function okay(found,path,base,hashname,hashtype)
+ if find(found,path) then
+ local full=methodhandler('concatinators',hashtype,hashname,found,base)
+ if full and full~="" then
+ result[#result+1]=resolveprefix(full)
+ return not allresults
+ end
+ end
+ end
for k=1,#hashes do
local hash=hashes[k]
- local hashname,hashtype=hash.name,hash.type
- for kk,hh in next,files[hashname] do
- if not find(kk,"^remap:") then
- if find(lower(kk),name) then
- if doit(path,hh,kk,hashname,hashtype,result,allresults) then done=true end
- if done and not allresults then break end
+ local hashname=hash.name
+ local hashtype=hash.type
+ if hashname and hashtype then
+ for found,base in filtered(files[hashname],name) do
+ if type(found)=='string' then
+ if okay(found,path,base,hashname,hashtype) then
+ break
+ end
+ else
+ for i=1,#found do
+ if okay(found[i],path,base,hashname,hashtype) then
+ break
+ end
+ end
end
end
end
end
else
+ local function okayokay(found,path,base,hashname,hashtype)
+ if find(found,path) then
+ local full=methodhandler('concatinators',hashtype,hashname,found,base)
+ if full and full~="" then
+ result[#result+1]=resolveprefix(full)
+ return not allresults
+ end
+ end
+ end
local hashes=instance.hashes
for k=1,#hashes do
local hash=hashes[k]
- local hashname,hashtype=hash.name,hash.type
- if doit(path,files[hashname][base],base,hashname,hashtype,result,allresults) then done=true end
- if done and not allresults then break end
+ local hashname=hash.name
+ local hashtype=hash.type
+ if hashname and hashtype then
+ local found,base=lookup(content,base)
+ if not found then
+ elseif type(found)=='string' then
+ if okay(found,path,base,hashname,hashtype) then
+ break
+ end
+ else
+ for i=1,#found do
+ if okay(found[i],path,base,hashname,hashtype) then
+ break
+ end
+ end
+ end
+ end
end
end
return result
@@ -15024,7 +15939,7 @@ end
function resolvers.dowithpath(name,func)
local pathlist=resolvers.expandedpathlist(name)
for i=1,#pathlist do
- func("^"..resolvers.cleanpath(pathlist[i]))
+ func("^"..cleanpath(pathlist[i]))
end
end
function resolvers.dowithvariable(name,func)
@@ -15032,23 +15947,23 @@ function resolvers.dowithvariable(name,func)
end
function resolvers.locateformat(name)
local engine=environment.ownmain or "luatex"
- local barename=file.removesuffix(name)
- local fullname=file.addsuffix(barename,"fmt")
+ local barename=removesuffix(name)
+ local fullname=addsuffix(barename,"fmt")
local fmtname=caches.getfirstreadablefile(fullname,"formats",engine) or ""
if fmtname=="" then
fmtname=resolvers.findfile(fullname)
- fmtname=resolvers.cleanpath(fmtname)
+ fmtname=cleanpath(fmtname)
end
if fmtname~="" then
- local barename=file.removesuffix(fmtname)
- local luaname=file.addsuffix(barename,luasuffixes.lua)
- local lucname=file.addsuffix(barename,luasuffixes.luc)
- local luiname=file.addsuffix(barename,luasuffixes.lui)
- if lfs.isfile(luiname) then
+ local barename=removesuffix(fmtname)
+ local luaname=addsuffix(barename,luasuffixes.lua)
+ local lucname=addsuffix(barename,luasuffixes.luc)
+ local luiname=addsuffix(barename,luasuffixes.lui)
+ if isfile(luiname) then
return barename,luiname
- elseif lfs.isfile(lucname) then
+ elseif isfile(lucname) then
return barename,lucname
- elseif lfs.isfile(luaname) then
+ elseif isfile(luaname) then
return barename,luaname
end
end
@@ -15070,29 +15985,24 @@ function resolvers.dowithfilesintree(pattern,handle,before,after)
local hash=hashes[i]
local blobtype=hash.type
local blobpath=hash.name
- if blobpath then
+ if blobtype and blobpath then
+ local total=0
+ local checked=0
+ local done=0
if before then
before(blobtype,blobpath,pattern)
end
- local files=instance.files[blobpath]
- local total,checked,done=0,0,0
- if files then
- for k,v in table.sortedhash(files) do
- total=total+1
- if find(k,"^remap:") then
- elseif find(k,pattern) then
- if type(v)=="string" then
- checked=checked+1
- if handle(blobtype,blobpath,v,k) then
- done=done+1
- end
- else
- checked=checked+#v
- for i=1,#v do
- if handle(blobtype,blobpath,v[i],k) then
- done=done+1
- end
- end
+ for path,name in filtered(instance.files[blobpath],pattern) do
+ if type(path)=="string" then
+ checked=checked+1
+ if handle(blobtype,blobpath,path,name) then
+ done=done+1
+ end
+ else
+ checked=checked+#path
+ for i=1,#path do
+ if handle(blobtype,blobpath,path[i],name) then
+ done=done+1
end
end
end
@@ -15103,8 +16013,8 @@ function resolvers.dowithfilesintree(pattern,handle,before,after)
end
end
end
-resolvers.obsolete=resolvers.obsolete or {}
-local obsolete=resolvers.obsolete
+local obsolete=resolvers.obsolete or {}
+resolvers.obsolete=obsolete
resolvers.find_file=resolvers.findfile obsolete.find_file=resolvers.findfile
resolvers.find_files=resolvers.findfiles obsolete.find_files=resolvers.findfiles
@@ -15115,7 +16025,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-pre"] = package.loaded["data-pre"] or true
--- original size: 6643, stripped down to: 4401
+-- original size: 3950, stripped down to: 2935
if not modules then modules={} end modules ['data-pre']={
version=1.001,
@@ -15125,44 +16035,51 @@ if not modules then modules={} end modules ['data-pre']={
license="see context related readme files"
}
local resolvers=resolvers
-local prefixes=utilities.storage.allocate()
-resolvers.prefixes=prefixes
-local cleanpath,findgivenfile,expansion=resolvers.cleanpath,resolvers.findgivenfile,resolvers.expansion
+local prefixes=resolvers.prefixes
+local cleanpath=resolvers.cleanpath
+local findgivenfile=resolvers.findgivenfile
+local expansion=resolvers.expansion
local getenv=resolvers.getenv
-local P,S,R,C,Cs,Cc,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.match
-local joinpath,basename,dirname=file.join,file.basename,file.dirname
-local getmetatable,rawset,type=getmetatable,rawset,type
+local basename=file.basename
+local dirname=file.dirname
+local joinpath=file.join
+local isfile=lfs.isfile
prefixes.environment=function(str)
return cleanpath(expansion(str))
end
-prefixes.relative=function(str,n)
- if io.exists(str) then
- elseif io.exists("./"..str) then
- str="./"..str
- else
- local p="../"
- for i=1,n or 2 do
- if io.exists(p..str) then
- str=p..str
- break
- else
- p=p.."../"
+local function relative(str,n)
+ if not isfile(str) then
+ local pstr="./"..str
+ if isfile(pstr) then
+ str=pstr
+ else
+ local p="../"
+ for i=1,n or 2 do
+ local pstr=p..str
+ if isfile(pstr) then
+ str=pstr
+ break
+ else
+ p=p.."../"
+ end
end
end
end
return cleanpath(str)
end
+local function locate(str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath(fullname~="" and fullname or str)
+end
+prefixes.relative=relative
+prefixes.locate=locate
prefixes.auto=function(str)
- local fullname=prefixes.relative(str)
- if not lfs.isfile(fullname) then
- fullname=prefixes.locate(str)
+ local fullname=relative(str)
+ if not isfile(fullname) then
+ fullname=locate(str)
end
return fullname
end
-prefixes.locate=function(str)
- local fullname=findgivenfile(str) or ""
- return cleanpath((fullname~="" and fullname) or str)
-end
prefixes.filename=function(str)
local fullname=findgivenfile(str) or ""
return cleanpath(basename((fullname~="" and fullname) or str))
@@ -15183,6 +16100,13 @@ end
prefixes.home=function(str)
return cleanpath(joinpath(getenv('HOME'),str))
end
+prefixes.env=prefixes.environment
+prefixes.rel=prefixes.relative
+prefixes.loc=prefixes.locate
+prefixes.kpse=prefixes.locate
+prefixes.full=prefixes.locate
+prefixes.file=prefixes.filename
+prefixes.path=prefixes.pathname
local function toppath()
local inputstack=resolvers.inputstack
if not inputstack then
@@ -15195,98 +16119,22 @@ local function toppath()
return pathname
end
end
-resolvers.toppath=toppath
-prefixes.toppath=function(str)
- return cleanpath(joinpath(toppath(),str))
-end
-prefixes.env=prefixes.environment
-prefixes.rel=prefixes.relative
-prefixes.loc=prefixes.locate
-prefixes.kpse=prefixes.locate
-prefixes.full=prefixes.locate
-prefixes.file=prefixes.filename
-prefixes.path=prefixes.pathname
-function resolvers.allprefixes(separator)
- local all=table.sortedkeys(prefixes)
- if separator then
- for i=1,#all do
- all[i]=all[i]..":"
- end
- end
- return all
-end
-local function _resolve_(method,target)
- local action=prefixes[method]
- if action then
- return action(target)
- else
- return method..":"..target
- end
-end
-local resolved,abstract={},{}
-function resolvers.resetresolve(str)
- resolved,abstract={},{}
-end
-local pattern=Cs((C(R("az")^2)*P(":")*C((1-S(" \"\';,"))^1)/_resolve_+P(1))^0)
-local prefix=C(R("az")^2)*P(":")
-local target=C((1-S(" \"\';,"))^1)
-local notarget=(#S(";,")+P(-1))*Cc("")
-local pattern=Cs(((prefix*(target+notarget))/_resolve_+P(1))^0)
-local function resolve(str)
- if type(str)=="table" then
- local t={}
- for i=1,#str do
- t[i]=resolve(str[i])
- end
- return t
+local function jobpath()
+ local path=resolvers.stackpath()
+ if not path or path=="" then
+ return "."
else
- local res=resolved[str]
- if not res then
- res=lpegmatch(pattern,str)
- resolved[str]=res
- abstract[res]=str
- end
- return res
- end
-end
-local function unresolve(str)
- return abstract[str] or str
-end
-resolvers.resolve=resolve
-resolvers.unresolve=unresolve
-if type(os.uname)=="function" then
- for k,v in next,os.uname() do
- if not prefixes[k] then
- prefixes[k]=function() return v end
- end
- end
-end
-if os.type=="unix" then
- local pattern
- local function makepattern(t,k,v)
- if t then
- rawset(t,k,v)
- end
- local colon=P(":")
- for k,v in table.sortedpairs(prefixes) do
- if p then
- p=P(k)+p
- else
- p=P(k)
- end
- end
- pattern=Cs((p*colon+colon/";"+P(1))^0)
- end
- makepattern()
- getmetatable(prefixes).__newindex=makepattern
- function resolvers.repath(str)
- return lpegmatch(pattern,str)
- end
-else
- function resolvers.repath(str)
- return str
+ return path
end
end
+resolvers.toppath=toppath
+resolvers.jobpath=jobpath
+prefixes.toppath=function(str) return cleanpath(joinpath(toppath(),str)) end
+prefixes.jobpath=function(str) return cleanpath(joinpath(jobpath(),str)) end
+resolvers.setdynamic("toppath")
+resolvers.setdynamic("jobpath")
+prefixes.jobfile=prefixes.jobpath
+resolvers.setdynamic("jobfile")
end -- of closure
@@ -15348,7 +16196,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-fil"] = package.loaded["data-fil"] or true
--- original size: 3801, stripped down to: 3231
+-- original size: 3863, stripped down to: 3310
if not modules then modules={} end modules ['data-fil']={
version=1.001,
@@ -15360,30 +16208,31 @@ if not modules then modules={} end modules ['data-fil']={
local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
local report_files=logs.reporter("resolvers","files")
local resolvers=resolvers
+local resolveprefix=resolvers.resolve
local finders,openers,loaders,savers=resolvers.finders,resolvers.openers,resolvers.loaders,resolvers.savers
local locators,hashers,generators,concatinators=resolvers.locators,resolvers.hashers,resolvers.generators,resolvers.concatinators
local checkgarbage=utilities.garbagecollector and utilities.garbagecollector.check
function locators.file(specification)
- local name=specification.filename
- local realname=resolvers.resolve(name)
+ local filename=specification.filename
+ local realname=resolveprefix(filename)
if realname and realname~='' and lfs.isdir(realname) then
if trace_locating then
- report_files("file locator %a found as %a",name,realname)
+ report_files("file locator %a found as %a",filename,realname)
end
- resolvers.appendhash('file',name,true)
+ resolvers.appendhash('file',filename,true)
elseif trace_locating then
- report_files("file locator %a not found",name)
+ report_files("file locator %a not found",filename)
end
end
function hashers.file(specification)
- local name=specification.filename
- local content=caches.loadcontent(name,'files')
- resolvers.registerfilehash(name,content,content==nil)
+ local pathname=specification.filename
+ local content=caches.loadcontent(pathname,'files')
+ resolvers.registerfilehash(pathname,content,content==nil)
end
function generators.file(specification)
- local path=specification.filename
- local content=resolvers.scanfiles(path,false,true)
- resolvers.registerfilehash(path,content,true)
+ local pathname=specification.filename
+ local content=resolvers.scanfiles(pathname,false,true)
+ resolvers.registerfilehash(pathname,content,true)
end
concatinators.file=file.join
function finders.file(specification,filetype)
@@ -15665,7 +16514,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-zip"] = package.loaded["data-zip"] or true
--- original size: 8489, stripped down to: 6757
+-- original size: 8772, stripped down to: 6841
if not modules then modules={} end modules ['data-zip']={
version=1.001,
@@ -15684,16 +16533,6 @@ zip.archives=zip.archives or {}
local archives=zip.archives
zip.registeredfiles=zip.registeredfiles or {}
local registeredfiles=zip.registeredfiles
-local limited=false
-directives.register("system.inputmode",function(v)
- if not limited then
- local i_limiter=io.i_limiter(v)
- if i_limiter then
- zip.open=i_limiter.protect(zip.open)
- limited=true
- end
- end
-end)
local function validzip(str)
if not find(str,"^zip://") then
return "zip:///"..str
@@ -15708,7 +16547,7 @@ function zip.openarchive(name)
local arch=archives[name]
if not arch then
local full=resolvers.findfile(name) or ""
- arch=(full~="" and zip.open(full)) or false
+ arch=full~="" and zip.open(full) or false
archives[name]=arch
end
return arch
@@ -15867,31 +16706,42 @@ function resolvers.usezipfile(archive)
end
end
function resolvers.registerzipfile(z,tree)
- local files,filter={},""
- if tree=="" then
- filter="^(.+)/(.-)$"
- else
- filter=format("^%s/(.+)/(.-)$",tree)
- end
+ local names={}
+ local files={}
+ local remap={}
+ local n=0
+ local filter=tree=="" and "^(.+)/(.-)$" or format("^%s/(.+)/(.-)$",tree)
+ local register=resolvers.registerfile
if trace_locating then
report_zip("registering: using filter %a",filter)
end
- local register,n=resolvers.registerfile,0
for i in z:files() do
- local path,name=match(i.filename,filter)
- if path then
- if name and name~='' then
- register(files,name,path)
- n=n+1
- else
+ local filename=i.filename
+ local path,name=match(filename,filter)
+ if not path then
+ n=n+1
+ register(names,filename,"")
+ local usedname=lower(filename)
+ files[usedname]=""
+ if usedname~=filename then
+ remap[usedname]=filename
end
- else
- register(files,i.filename,'')
+ elseif name and name~="" then
n=n+1
+ register(names,name,path)
+ local usedname=lower(name)
+ files[usedname]=path
+ if usedname~=name then
+ remap[usedname]=name
+ end
+ else
end
end
report_zip("registering: %s files registered",n)
- return files
+ return {
+ files=files,
+ remap=remap,
+ }
end
@@ -15901,7 +16751,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-tre"] = package.loaded["data-tre"] or true
--- original size: 2508, stripped down to: 2074
+-- original size: 8479, stripped down to: 5580
if not modules then modules={} end modules ['data-tre']={
version=1.001,
@@ -15910,42 +16760,64 @@ if not modules then modules={} end modules ['data-tre']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local find,gsub,format=string.find,string.gsub,string.format
+local find,gsub,lower=string.find,string.gsub,string.lower
+local basename,dirname,joinname=file.basename,file.dirname,file .join
+local globdir,isdir,isfile=dir.glob,lfs.isdir,lfs.isfile
+local P,lpegmatch=lpeg.P,lpeg.match
local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
local report_trees=logs.reporter("resolvers","trees")
local resolvers=resolvers
-local done,found,notfound={},{},resolvers.finders.notfound
-function resolvers.finders.tree(specification)
+local resolveprefix=resolvers.resolve
+local notfound=resolvers.finders.notfound
+local lookup=resolvers.get_from_content
+local collectors={}
+local found={}
+function resolvers.finders.tree(specification)
local spec=specification.filename
- local fnd=found[spec]
- if fnd==nil then
+ local okay=found[spec]
+ if okay==nil then
if spec~="" then
- local path,name=file.dirname(spec),file.basename(spec)
- if path=="" then path="." end
- local hash=done[path]
- if not hash then
- local pattern=path.."/*"
- hash=dir.glob(pattern)
- done[path]=hash
+ local path=dirname(spec)
+ local name=basename(spec)
+ if path=="" then
+ path="."
+ end
+ local names=collectors[path]
+ if not names then
+ local pattern=find(path,"/%*+$") and path or (path.."/*")
+ names=globdir(pattern)
+ collectors[path]=names
end
local pattern="/"..gsub(name,"([%.%-%+])","%%%1").."$"
- for k=1,#hash do
- local v=hash[k]
- if find(v,pattern) then
- found[spec]=v
- return v
+ for i=1,#names do
+ local fullname=names[i]
+ if find(fullname,pattern) then
+ found[spec]=fullname
+ return fullname
+ end
+ end
+ local pattern=lower(pattern)
+ for i=1,#names do
+ local fullname=lower(names[i])
+ if find(fullname,pattern) then
+ if isfile(fullname) then
+ found[spec]=fullname
+ return fullname
+ else
+ break
+ end
end
end
end
- fnd=notfound()
- found[spec]=fnd
+ okay=notfound()
+ found[spec]=okay
end
- return fnd
+ return okay
end
function resolvers.locators.tree(specification)
local name=specification.filename
- local realname=resolvers.resolve(name)
- if realname and realname~='' and lfs.isdir(realname) then
+ local realname=resolveprefix(name)
+ if realname and realname~='' and isdir(realname) then
if trace_locating then
report_trees("locator %a found",realname)
end
@@ -15956,16 +16828,110 @@ function resolvers.locators.tree(specification)
end
function resolvers.hashers.tree(specification)
local name=specification.filename
- if trace_locating then
- report_trees("analysing %a",name)
- end
+ report_trees("analyzing %a",name)
resolvers.methodhandler("hashers",name)
resolvers.generators.file(specification)
end
-resolvers.concatinators.tree=resolvers.concatinators.file
-resolvers.generators.tree=resolvers.generators.file
-resolvers.openers.tree=resolvers.openers.file
-resolvers.loaders.tree=resolvers.loaders.file
+local collectors={}
+local splitter=lpeg.splitat("/**/")
+local stripper=lpeg.replacer { [P("/")*P("*")^1*P(-1)]="" }
+table.setmetatableindex(collectors,function(t,k)
+ local rootname=lpegmatch(stripper,k)
+ local dataname=joinname(rootname,"dirlist")
+ local content=caches.loadcontent(dataname,"files",dataname)
+ if not content then
+ content=resolvers.scanfiles(rootname,nil,nil,false,true)
+ caches.savecontent(dataname,"files",content,dataname)
+ end
+ t[k]=content
+ return content
+end)
+local function checked(root,p,n)
+ if p then
+ if type(p)=="table" then
+ for i=1,#p do
+ local fullname=joinname(root,p[i],n)
+ if isfile(fullname) then
+ return fullname
+ end
+ end
+ else
+ local fullname=joinname(root,p,n)
+ if isfile(fullname) then
+ return fullname
+ end
+ end
+ end
+ return notfound()
+end
+local function resolve(specification)
+ local filename=specification.filename
+ if filename~="" then
+ local root,rest=lpegmatch(splitter,filename)
+ if root and rest then
+ local path,name=dirname(rest),basename(rest)
+ if name~=rest then
+ local content=collectors[root]
+ local p,n=lookup(content,name)
+ if not p then
+ return notfound()
+ end
+ local pattern=".*/"..path.."$"
+ local istable=type(p)=="table"
+ if istable then
+ for i=1,#p do
+ local pi=p[i]
+ if pi==path or find(pi,pattern) then
+ local fullname=joinname(root,pi,n)
+ if isfile(fullname) then
+ return fullname
+ end
+ end
+ end
+ elseif p==path or find(p,pattern) then
+ local fullname=joinname(root,p,n)
+ if isfile(fullname) then
+ return fullname
+ end
+ end
+ local queries=specification.queries
+ if queries and queries.option=="fileonly" then
+ return checked(root,p,n)
+ else
+ return notfound()
+ end
+ end
+ end
+ local path,name=dirname(filename),basename(filename)
+ local root=lpegmatch(stripper,path)
+ local content=collectors[path]
+ local p,n=lookup(content,name)
+ if p then
+ return checked(root,p,n)
+ end
+ end
+ return notfound()
+end
+resolvers.finders .dirlist=resolve
+resolvers.locators .dirlist=resolvers.locators .tree
+resolvers.hashers .dirlist=resolvers.hashers .tree
+resolvers.generators.dirlist=resolvers.generators.file
+resolvers.openers .dirlist=resolvers.openers .file
+resolvers.loaders .dirlist=resolvers.loaders .file
+function resolvers.finders.dirfile(specification)
+ local queries=specification.queries
+ if queries then
+ queries.option="fileonly"
+ else
+ specification.queries={ option="fileonly" }
+ end
+ return resolve(specification)
+end
+resolvers.locators .dirfile=resolvers.locators .dirlist
+resolvers.hashers .dirfile=resolvers.hashers .dirlist
+resolvers.generators.dirfile=resolvers.generators.dirlist
+resolvers.openers .dirfile=resolvers.openers .dirlist
+resolvers.loaders .dirfile=resolvers.loaders .dirlist
end -- of closure
@@ -15974,7 +16940,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-sch"] = package.loaded["data-sch"] or true
--- original size: 6213, stripped down to: 5160
+-- original size: 6569, stripped down to: 5304
if not modules then modules={} end modules ['data-sch']={
version=1.001,
@@ -16000,8 +16966,13 @@ directives.register("schemes.threshold",function(v) threshold=tonumber(v) or thr
function cleaners.none(specification)
return specification.original
end
-function cleaners.strip(specification)
- return (gsub(specification.original,"[^%a%d%.]+","-"))
+function cleaners.strip(specification)
+ local path,name=file.splitbase(specification.original)
+ if path=="" then
+ return (gsub(name,"[^%a%d%.]+","-"))
+ else
+ return (gsub((gsub(path,"%.","-").."-"..name),"[^%a%d%.]+","-"))
+ end
end
function cleaners.md5(specification)
return file.addsuffix(md5.hex(specification.original),file.suffix(specification.path))
@@ -16018,7 +16989,7 @@ end
local cached,loaded,reused,thresholds,handlers={},{},{},{},{}
local function runcurl(name,cachename)
local command="curl --silent --insecure --create-dirs --output "..cachename.." "..name
- os.spawn(command)
+ os.execute(command)
end
local function fetch(specification)
local original=specification.original
@@ -16150,7 +17121,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-lua"] = package.loaded["data-lua"] or true
--- original size: 4237, stripped down to: 3177
+-- original size: 4313, stripped down to: 3227
if not modules then modules={} end modules ['data-lua']={
version=1.001,
@@ -16159,7 +17130,7 @@ if not modules then modules={} end modules ['data-lua']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local resolvers,package=resolvers,package
+local package,lpeg=package,lpeg
local gsub=string.gsub
local concat=table.concat
local addsuffix=file.addsuffix
@@ -16170,9 +17141,11 @@ local luaformats={ 'TEXINPUTS','LUAINPUTS' }
local libformats={ 'CLUAINPUTS' }
local helpers=package.helpers or {}
local methods=helpers.methods or {}
+local resolvers=resolvers
+local resolveprefix=resolvers.resolve
+helpers.report=logs.reporter("resolvers","libraries")
trackers.register("resolvers.libraries",function(v) helpers.trace=v end)
trackers.register("resolvers.locating",function(v) helpers.trace=v end)
-helpers.report=logs.reporter("resolvers","libraries")
helpers.sequence={
"already loaded",
"preload table",
@@ -16187,7 +17160,7 @@ helpers.sequence={
}
local pattern=Cs(P("!")^0/""*(P("/")*P(-1)/"/"+P("/")^1/"/"+1)^0)
function helpers.cleanpath(path)
- return resolvers.resolve(lpegmatch(pattern,path))
+ return resolveprefix(lpegmatch(pattern,path))
end
local loadedaslib=helpers.loadedaslib
local getextraluapaths=package.extraluapaths
@@ -16324,7 +17297,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-tmf"] = package.loaded["data-tmf"] or true
--- original size: 2600, stripped down to: 1627
+-- original size: 2601, stripped down to: 1627
if not modules then modules={} end modules ['data-tmf']={
version=1.001,
@@ -16380,7 +17353,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-lst"] = package.loaded["data-lst"] or true
--- original size: 2654, stripped down to: 2301
+-- original size: 2734, stripped down to: 2354
if not modules then modules={} end modules ['data-lst']={
version=1.001,
@@ -16389,10 +17362,13 @@ if not modules then modules={} end modules ['data-lst']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local find,concat,upper,format=string.find,table.concat,string.upper,string.format
+local rawget,type,next=rawget,type,next
+local find,concat,upper=string.find,table.concat,string.upper
local fastcopy,sortedpairs=table.fastcopy,table.sortedpairs
-resolvers.listers=resolvers.listers or {}
local resolvers=resolvers
+local listers=resolvers.listers or {}
+resolvers.listers=listers
+local resolveprefix=resolvers.resolve
local report_lists=logs.reporter("resolvers","lists")
local function tabstr(str)
if type(str)=='table' then
@@ -16401,7 +17377,7 @@ local function tabstr(str)
return str
end
end
-function resolvers.listers.variables(pattern)
+function listers.variables(pattern)
local instance=resolvers.instance
local environment=instance.environment
local variables=instance.variables
@@ -16422,10 +17398,10 @@ function resolvers.listers.variables(pattern)
for key,value in sortedpairs(configured) do
if key~="" and (pattern=="" or find(upper(key),pattern)) then
report_lists(key)
- report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
- report_lists(" var: %s",tabstr(configured[key]) or "unset")
- report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
- report_lists(" res: %s",tabstr(resolvers.resolve(expansions[key])) or "unset")
+ report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
+ report_lists(" var: %s",tabstr(configured[key]) or "unset")
+ report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
+ report_lists(" res: %s",tabstr(resolveprefix(expansions[key])) or "unset")
end
end
instance.environment=fastcopy(env)
@@ -16433,15 +17409,15 @@ function resolvers.listers.variables(pattern)
instance.expansions=fastcopy(exp)
end
local report_resolved=logs.reporter("system","resolved")
-function resolvers.listers.configurations()
+function listers.configurations()
local configurations=resolvers.instance.specification
for i=1,#configurations do
- report_resolved("file : %s",resolvers.resolve(configurations[i]))
+ report_resolved("file : %s",resolveprefix(configurations[i]))
end
report_resolved("")
local list=resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))
for i=1,#list do
- local li=resolvers.resolve(list[i])
+ local li=resolveprefix(list[i])
if lfs.isdir(li) then
report_resolved("path - %s",li)
else
@@ -16746,7 +17722,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["luat-fmt"] = package.loaded["luat-fmt"] or true
--- original size: 5951, stripped down to: 4922
+-- original size: 5955, stripped down to: 4926
if not modules then modules={} end modules ['luat-fmt']={
version=1.001,
@@ -16834,7 +17810,7 @@ function environment.make_format(name)
end
local command=format("%s --ini %s --lua=%s %s %sdump",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform=="unix" and "\\\\" or "\\")
report_format("running command: %s\n",command)
- os.spawn(command)
+ os.execute(command)
local pattern=file.removesuffix(file.basename(usedluastub)).."-*.mem"
local mp=dir.glob(pattern)
if mp then
@@ -16869,7 +17845,7 @@ function environment.run_format(name,data,more)
else
local command=format("%s %s --fmt=%s --lua=%s %s %s",engine,primaryflags(),quoted(barename),quoted(luaname),quoted(data),more~="" and quoted(more) or "")
report_format("running command: %s",command)
- os.spawn(command)
+ os.execute(command)
end
end
end
@@ -16880,8 +17856,8 @@ end -- of closure
-- used libraries : l-lua.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-mrg.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua
-- skipped libraries : -
--- original bytes : 695180
--- stripped bytes : 246794
+-- original bytes : 739251
+-- stripped bytes : 264497
-- end library merge
@@ -17107,6 +18083,7 @@ local helpinfo = [[
<category name="basic">
<subcategory>
<flag name="script"><short>run an mtx script (lua prefered method) (<ref name="noquotes"/>), no script gives list</short></flag>
+ <flag name="evaluate"><short>run code passed on the commandline (between quotes)</short></flag>
<flag name="execute"><short>run a script or program (texmfstart method) (<ref name="noquotes"/>)</short></flag>
<flag name="resolve"><short>resolve prefixed arguments</short></flag>
<flag name="ctxlua"><short>run internally (using preloaded libs)</short></flag>
@@ -17132,6 +18109,7 @@ local helpinfo = [[
<flag name="verbose"><short>give a bit more info</short></flag>
<flag name="trackers" value="list"><short>enable given trackers</short></flag>
<flag name="progname" value="str"><short>format or backend</short></flag>
+ <flag name="systeminfo" value="str"><short>show current operating system, processor, etc</short></flag>
</subcategory>
<subcategory>
<flag name="edit"><short>launch editor with found file</short></flag>
@@ -17761,6 +18739,39 @@ function runners.associate(filename)
os.launch(filename)
end
+function runners.evaluate(code,filename) -- for Luigi
+ if code == "loop" then
+ while true do
+ io.write("> ")
+ local code = io.read()
+ if code ~= "" then
+ local temp = string.match(code,"^= (.*)$")
+ if temp then
+ code = "print("..temp..")"
+ end
+ local compiled, message = loadstring(code)
+ if type(compiled) ~= "function" then
+ io.write("! " .. (message or code).."\n")
+ else
+ io.write(compiled())
+ end
+ end
+ end
+ else
+ if type(code) ~= "string" or code == "" then
+ code = filename
+ end
+ if code ~= "" then
+ local compiled, message = loadstring(code)
+ if type(compiled) ~= "function" then
+ io.write("invalid lua code: " .. (message or code))
+ return
+ end
+ io.write(compiled())
+ end
+ end
+end
+
function runners.gethelp(filename)
local url = environment.argument("url")
if url and url ~= "" then
@@ -17772,6 +18783,15 @@ function runners.gethelp(filename)
end
end
+function runners.systeminfo()
+ report("architecture : %s",os.platform or "<unset>")
+ report("operating system : %s",os.name or "<unset>")
+ report("file architecture : %s",os.type or "<unset>")
+ report("binary path : %s",os.selfdir or "<unset>")
+ report("binary suffix : %s",os.binsuffix or "<unset>")
+ report("library suffix : %s",os.libsuffix or "<unset>")
+end
+
-- 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
-- ... later we will use the second half
@@ -17887,16 +18907,7 @@ end
if e_argument("ansi") then
- local formatters = string.formatters
-
- logs.setformatters {
- report_yes = formatters["%-15s | %s"],
- report_nop = formatters["%-15s |"],
- subreport_yes = formatters["%-15s | %s | %s"],
- subreport_nop = formatters["%-15s | %s |"],
- status_yes = formatters["%-15s : %s\n"],
- status_nop = formatters["%-15s :\n"],
- }
+ logs.setformatters("ansi")
local script = e_argument("script") or e_argument("scripts")
@@ -17921,6 +18932,10 @@ if e_argument("script") or e_argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
+elseif e_argument("evaluate") then
+
+ runners.evaluate(e_argument("evaluate"),filename)
+
elseif e_argument("selfmerge") then
-- embed used libraries
@@ -18213,6 +19228,10 @@ elseif e_argument("exporthelp") then
runners.loadbase()
application.export(e_argument("exporthelp"),filename)
+elseif e_argument("systeminfo") then
+
+ runners.systeminfo()
+
elseif e_argument("help") or filename=='help' or filename == "" then
application.help()
diff --git a/Master/texmf-dist/scripts/context/stubs/win64/mtxrun.lua b/Master/texmf-dist/scripts/context/stubs/win64/mtxrun.lua
index 5cb5c8d2416..48a9a27a250 100644
--- a/Master/texmf-dist/scripts/context/stubs/win64/mtxrun.lua
+++ b/Master/texmf-dist/scripts/context/stubs/win64/mtxrun.lua
@@ -56,7 +56,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-lua"] = package.loaded["l-lua"] or true
--- original size: 3409, stripped down to: 1763
+-- original size: 3888, stripped down to: 2197
if not modules then modules={} end modules ['l-lua']={
version=1.001,
@@ -139,6 +139,13 @@ end
if lua then
lua.mask=load([[τεχ = 1]]) and "utf" or "ascii"
end
+local flush=io.flush
+if flush then
+ local execute=os.execute if execute then function os.execute(...) flush() return execute(...) end end
+ local exec=os.exec if exec then function os.exec (...) flush() return exec (...) end end
+ local spawn=os.spawn if spawn then function os.spawn (...) flush() return spawn (...) end end
+ local popen=io.popen if popen then function io.popen (...) flush() return popen (...) end end
+end
end -- of closure
@@ -437,7 +444,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true
--- original size: 29983, stripped down to: 16202
+-- original size: 36225, stripped down to: 19891
if not modules then modules={} end modules ['l-lpeg']={
version=1.001,
@@ -498,6 +505,8 @@ patterns.utfbom_16_le=utfbom_16_le
patterns.utfbom_8=utfbom_8
patterns.utf_16_be_nl=P("\000\r\000\n")+P("\000\r")+P("\000\n")
patterns.utf_16_le_nl=P("\r\000\n\000")+P("\r\000")+P("\n\000")
+patterns.utf_32_be_nl=P("\000\000\000\r\000\000\000\n")+P("\000\000\000\r")+P("\000\000\000\n")
+patterns.utf_32_le_nl=P("\r\000\000\000\n\000\000\000")+P("\r\000\000\000")+P("\n\000\000\000")
patterns.utf8one=R("\000\127")
patterns.utf8two=R("\194\223")*utf8next
patterns.utf8three=R("\224\239")*utf8next*utf8next
@@ -527,9 +536,21 @@ patterns.nonwhitespace=nonwhitespace
local stripper=spacer^0*C((spacer^0*nonspacer^1)^0)
local fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0)
local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0))
+local b_collapser=Cs(whitespace^0/""*(nonwhitespace^1+whitespace^1/" ")^0)
+local e_collapser=Cs((whitespace^1*P(-1)/""+nonwhitespace^1+whitespace^1/" ")^0)
+local m_collapser=Cs((nonwhitespace^1+whitespace^1/" ")^0)
+local b_stripper=Cs(spacer^0/""*(nonspacer^1+spacer^1/" ")^0)
+local e_stripper=Cs((spacer^1*P(-1)/""+nonspacer^1+spacer^1/" ")^0)
+local m_stripper=Cs((nonspacer^1+spacer^1/" ")^0)
patterns.stripper=stripper
patterns.fullstripper=fullstripper
patterns.collapser=collapser
+patterns.b_collapser=b_collapser
+patterns.m_collapser=m_collapser
+patterns.e_collapser=e_collapser
+patterns.b_stripper=b_stripper
+patterns.m_stripper=m_stripper
+patterns.e_stripper=e_stripper
patterns.lowercase=lowercase
patterns.uppercase=uppercase
patterns.letter=patterns.lowercase+patterns.uppercase
@@ -566,9 +587,12 @@ patterns.integer=sign^-1*digit^1
patterns.unsigned=digit^0*period*digit^1
patterns.float=sign^-1*patterns.unsigned
patterns.cunsigned=digit^0*comma*digit^1
+patterns.cpunsigned=digit^0*(period+comma)*digit^1
patterns.cfloat=sign^-1*patterns.cunsigned
+patterns.cpfloat=sign^-1*patterns.cpunsigned
patterns.number=patterns.float+patterns.integer
patterns.cnumber=patterns.cfloat+patterns.integer
+patterns.cpnumber=patterns.cpfloat+patterns.integer
patterns.oct=zero*octdigit^1
patterns.octal=patterns.oct
patterns.HEX=zero*P("X")*(digit+uppercase)^1
@@ -985,23 +1009,40 @@ function lpeg.append(list,pp,delayed,checked)
end
return p
end
+local p_false=P(false)
+local p_true=P(true)
local function make(t)
- local p
+ local function making(t)
+ local p=p_false
+ local keys=sortedkeys(t)
+ for i=1,#keys do
+ local k=keys[i]
+ if k~="" then
+ local v=t[k]
+ if v==true then
+ p=p+P(k)*p_true
+ elseif v==false then
+ else
+ p=p+P(k)*making(v)
+ end
+ end
+ end
+ if t[""] then
+ p=p+p_true
+ end
+ return p
+ end
+ local p=p_false
local keys=sortedkeys(t)
for i=1,#keys do
local k=keys[i]
- local v=t[k]
- if not p then
- if next(v) then
- p=P(k)*make(v)
- else
- p=P(k)
- end
- else
- if next(v) then
- p=p+P(k)*make(v)
+ if k~="" then
+ local v=t[k]
+ if v==true then
+ p=p+P(k)*p_true
+ elseif v==false then
else
- p=p+P(k)
+ p=p+P(k)*making(v)
end
end
end
@@ -1009,13 +1050,73 @@ local function make(t)
end
function lpeg.utfchartabletopattern(list)
local tree={}
- for i=1,#list do
- local t=tree
- for c in gmatch(list[i],".") do
- if not t[c] then
- t[c]={}
+ local n=#list
+ if n==0 then
+ for s in next,list do
+ local t=tree
+ local p,pk
+ for c in gmatch(s,".") do
+ if t==true then
+ t={ [c]=true,[""]=true }
+ p[pk]=t
+ p=t
+ t=false
+ elseif t==false then
+ t={ [c]=false }
+ p[pk]=t
+ p=t
+ t=false
+ else
+ local tc=t[c]
+ if not tc then
+ tc=false
+ t[c]=false
+ end
+ p=t
+ t=tc
+ end
+ pk=c
+ end
+ if t==false then
+ p[pk]=true
+ elseif t==true then
+ else
+ t[""]=true
+ end
+ end
+ else
+ for i=1,n do
+ local s=list[i]
+ local t=tree
+ local p,pk
+ for c in gmatch(s,".") do
+ if t==true then
+ t={ [c]=true,[""]=true }
+ p[pk]=t
+ p=t
+ t=false
+ elseif t==false then
+ t={ [c]=false }
+ p[pk]=t
+ p=t
+ t=false
+ else
+ local tc=t[c]
+ if not tc then
+ tc=false
+ t[c]=false
+ end
+ p=t
+ t=tc
+ end
+ pk=c
+ end
+ if t==false then
+ p[pk]=true
+ elseif t==true then
+ else
+ t[""]=true
end
- t=t[c]
end
end
return make(tree)
@@ -1055,6 +1156,65 @@ local case_2=period*(digit-trailingzeros)^1*(trailingzeros/"")
local number=digit^1*(case_1+case_2)
local stripper=Cs((number+1)^0)
lpeg.patterns.stripzeros=stripper
+local byte_to_HEX={}
+local byte_to_hex={}
+local byte_to_dec={}
+local hex_to_byte={}
+for i=0,255 do
+ local H=format("%02X",i)
+ local h=format("%02x",i)
+ local d=format("%03i",i)
+ local c=char(i)
+ byte_to_HEX[c]=H
+ byte_to_hex[c]=h
+ byte_to_dec[c]=d
+ hex_to_byte[h]=c
+ hex_to_byte[H]=c
+end
+local hextobyte=P(2)/hex_to_byte
+local bytetoHEX=P(1)/byte_to_HEX
+local bytetohex=P(1)/byte_to_hex
+local bytetodec=P(1)/byte_to_dec
+local hextobytes=Cs(hextobyte^0)
+local bytestoHEX=Cs(bytetoHEX^0)
+local bytestohex=Cs(bytetohex^0)
+local bytestodec=Cs(bytetodec^0)
+patterns.hextobyte=hextobyte
+patterns.bytetoHEX=bytetoHEX
+patterns.bytetohex=bytetohex
+patterns.bytetodec=bytetodec
+patterns.hextobytes=hextobytes
+patterns.bytestoHEX=bytestoHEX
+patterns.bytestohex=bytestohex
+patterns.bytestodec=bytestodec
+function string.toHEX(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(bytestoHEX,s)
+ end
+end
+function string.tohex(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(bytestohex,s)
+ end
+end
+function string.todec(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(bytestodec,s)
+ end
+end
+function string.tobytes(s)
+ if not s or s=="" then
+ return s
+ else
+ return lpegmatch(hextobytes,s)
+ end
+end
end -- of closure
@@ -1082,7 +1242,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-string"] = package.loaded["l-string"] or true
--- original size: 5671, stripped down to: 2827
+-- original size: 5694, stripped down to: 2827
if not modules then modules={} end modules ['l-string']={
version=1.001,
@@ -1187,7 +1347,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-table"] = package.loaded["l-table"] or true
--- original size: 31860, stripped down to: 20846
+-- original size: 33830, stripped down to: 21894
if not modules then modules={} end modules ['l-table']={
version=1.001,
@@ -1230,11 +1390,12 @@ function table.keys(t)
end
end
local function compare(a,b)
- local ta,tb=type(a),type(b)
- if ta==tb then
+ local ta=type(a)
+ local tb=type(b)
+ if ta==tb and ta=="number" then
return a<b
else
- return tostring(a)<tostring(b)
+ return tostring(a)<tostring(b)
end
end
local function sortedkeys(tab)
@@ -1334,14 +1495,14 @@ local function sortedhash(t,cmp)
end
local n=0
local m=#s
- local function kv(s)
+ local function kv()
if n<m then
n=n+1
local k=s[n]
return k,t[k]
end
end
- return kv,s
+ return kv
else
return nothing
end
@@ -1506,7 +1667,7 @@ local function simple_table(t)
if tv=="number" then
nt=nt+1
if hexify then
- tt[nt]=format("0x%04X",v)
+ tt[nt]=format("0x%X",v)
else
tt[nt]=tostring(v)
end
@@ -1537,7 +1698,7 @@ local function do_serialize(root,name,depth,level,indexed)
local tn=type(name)
if tn=="number" then
if hexify then
- handle(format("%s[0x%04X]={",depth,name))
+ handle(format("%s[0x%X]={",depth,name))
else
handle(format("%s[%s]={",depth,name))
end
@@ -1554,7 +1715,7 @@ local function do_serialize(root,name,depth,level,indexed)
end
end
end
- if root and next(root) then
+ if root and next(root)~=nil then
local first,last=nil,0
if compact then
last=#root
@@ -1576,7 +1737,7 @@ local function do_serialize(root,name,depth,level,indexed)
if compact and first and tk=="number" and k>=first and k<=last then
if tv=="number" then
if hexify then
- handle(format("%s 0x%04X,",depth,v))
+ handle(format("%s 0x%X,",depth,v))
else
handle(format("%s %s,",depth,v))
end
@@ -1587,7 +1748,7 @@ local function do_serialize(root,name,depth,level,indexed)
handle(format("%s %q,",depth,v))
end
elseif tv=="table" then
- if not next(v) then
+ if next(v)==nil then
handle(format("%s {},",depth))
elseif inline then
local st=simple_table(v)
@@ -1617,25 +1778,25 @@ local function do_serialize(root,name,depth,level,indexed)
elseif tv=="number" then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=0x%04X,",depth,k,v))
+ handle(format("%s [0x%X]=0x%X,",depth,k,v))
else
handle(format("%s [%s]=%s,",depth,k,v))
end
elseif tk=="boolean" then
if hexify then
- handle(format("%s [%s]=0x%04X,",depth,k and "true" or "false",v))
+ handle(format("%s [%s]=0x%X,",depth,k and "true" or "false",v))
else
handle(format("%s [%s]=%s,",depth,k and "true" or "false",v))
end
elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
if hexify then
- handle(format("%s %s=0x%04X,",depth,k,v))
+ handle(format("%s %s=0x%X,",depth,k,v))
else
handle(format("%s %s=%s,",depth,k,v))
end
else
if hexify then
- handle(format("%s [%q]=0x%04X,",depth,k,v))
+ handle(format("%s [%q]=0x%X,",depth,k,v))
else
handle(format("%s [%q]=%s,",depth,k,v))
end
@@ -1644,7 +1805,7 @@ local function do_serialize(root,name,depth,level,indexed)
if reduce and tonumber(v) then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,v))
+ handle(format("%s [0x%X]=%s,",depth,k,v))
else
handle(format("%s [%s]=%s,",depth,k,v))
end
@@ -1658,7 +1819,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,v))
+ handle(format("%s [0x%X]=%q,",depth,k,v))
else
handle(format("%s [%s]=%q,",depth,k,v))
end
@@ -1671,10 +1832,10 @@ local function do_serialize(root,name,depth,level,indexed)
end
end
elseif tv=="table" then
- if not next(v) then
+ if next(v)==nil then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]={},",depth,k))
+ handle(format("%s [0x%X]={},",depth,k))
else
handle(format("%s [%s]={},",depth,k))
end
@@ -1690,7 +1851,7 @@ local function do_serialize(root,name,depth,level,indexed)
if st then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
+ handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", ")))
else
handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
end
@@ -1710,7 +1871,7 @@ local function do_serialize(root,name,depth,level,indexed)
elseif tv=="boolean" then
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,v and "true" or "false"))
+ handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false"))
else
handle(format("%s [%s]=%s,",depth,k,v and "true" or "false"))
end
@@ -1726,7 +1887,7 @@ local function do_serialize(root,name,depth,level,indexed)
local f=getinfo(v).what=="C" and dump(dummy) or dump(v)
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=load(%q),",depth,k,f))
+ handle(format("%s [0x%X]=load(%q),",depth,k,f))
else
handle(format("%s [%s]=load(%q),",depth,k,f))
end
@@ -1741,7 +1902,7 @@ local function do_serialize(root,name,depth,level,indexed)
else
if tk=="number" then
if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
+ handle(format("%s [0x%X]=%q,",depth,k,tostring(v)))
else
handle(format("%s [%s]=%q,",depth,k,tostring(v)))
end
@@ -1795,7 +1956,7 @@ local function serialize(_handle,root,name,specification)
end
elseif tname=="number" then
if hexify then
- handle(format("[0x%04X]={",name))
+ handle(format("[0x%X]={",name))
else
handle("["..name.."]={")
end
@@ -1813,7 +1974,7 @@ local function serialize(_handle,root,name,specification)
local dummy=root._w_h_a_t_e_v_e_r_
root._w_h_a_t_e_v_e_r_=nil
end
- if next(root) then
+ if next(root)~=nil then
do_serialize(root,name,"",0)
end
end
@@ -1942,14 +2103,25 @@ local function identical(a,b)
end
table.identical=identical
table.are_equal=are_equal
-function table.compact(t)
- if t then
- for k,v in next,t do
- if not next(v) then
- t[k]=nil
+local function sparse(old,nest,keeptables)
+ local new={}
+ for k,v in next,old do
+ if not (v=="" or v==false) then
+ if nest and type(v)=="table" then
+ v=sparse(v,nest)
+ if keeptables or next(v)~=nil then
+ new[k]=v
+ end
+ else
+ new[k]=v
end
end
end
+ return new
+end
+table.sparse=sparse
+function table.compact(t)
+ return sparse(t,true,true)
end
function table.contains(t,v)
if t then
@@ -2054,10 +2226,10 @@ function table.sub(t,i,j)
return { unpack(t,i,j) }
end
function table.is_empty(t)
- return not t or not next(t)
+ return not t or next(t)==nil
end
function table.has_one_entry(t)
- return t and not next(t,next(t))
+ return t and next(t,next(t))==nil
end
function table.loweredkeys(t)
local l={}
@@ -2102,6 +2274,44 @@ function table.values(t,s)
return {}
end
end
+function table.filtered(t,pattern,sort,cmp)
+ if t and type(pattern)=="string" then
+ if sort then
+ local s
+ if cmp then
+ s=sortedhashkeys(t,function(a,b) return cmp(t,a,b) end)
+ else
+ s=sortedkeys(t)
+ end
+ local n=0
+ local m=#s
+ local function kv(s)
+ while n<m do
+ n=n+1
+ local k=s[n]
+ if find(k,pattern) then
+ return k,t[k]
+ end
+ end
+ end
+ return kv,s
+ else
+ local n=next(t)
+ local function iterator()
+ while n~=nil do
+ local k=n
+ n=next(t,k)
+ if find(k,pattern) then
+ return k,t[k]
+ end
+ end
+ end
+ return iterator,t
+ end
+ else
+ return nothing
+ end
+end
end -- of closure
@@ -2110,7 +2320,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-io"] = package.loaded["l-io"] or true
--- original size: 8824, stripped down to: 6347
+-- original size: 8643, stripped down to: 6232
if not modules then modules={} end modules ['l-io']={
version=1.001,
@@ -2417,8 +2627,6 @@ function io.readstring(f,n,m)
local str=gsub(f:read(n),"\000","")
return str
end
-if not io.i_limiter then function io.i_limiter() end end
-if not io.o_limiter then function io.o_limiter() end end
end -- of closure
@@ -2645,7 +2853,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-os"] = package.loaded["l-os"] or true
--- original size: 16093, stripped down to: 9704
+-- original size: 15761, stripped down to: 9403
if not modules then modules={} end modules ['l-os']={
version=1.001,
@@ -2719,13 +2927,10 @@ if not os.__getenv__ then
setmetatable(os.env,{ __index=__index,__newindex=__newindex } )
end
end
-local execute,spawn,exec,iopopen,ioflush=os.execute,os.spawn or os.execute,os.exec or os.execute,io.popen,io.flush
-function os.execute(...) ioflush() return execute(...) end
-function os.spawn (...) ioflush() return spawn (...) end
-function os.exec (...) ioflush() return exec (...) end
-function io.popen (...) ioflush() return iopopen(...) end
+local execute=os.execute
+local iopopen=io.popen
function os.resultof(command)
- local handle=io.popen(command,"r")
+ local handle=iopopen(command,"r")
if handle then
local result=handle:read("*all") or ""
handle:close()
@@ -2754,7 +2959,7 @@ local launchers={
unix="$BROWSER %s &> /dev/null &",
}
function os.launch(str)
- os.execute(format(launchers[os.name] or launchers.unix,str))
+ execute(format(launchers[os.name] or launchers.unix,str))
end
if not os.times then
function os.times()
@@ -3029,7 +3234,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-file"] = package.loaded["l-file"] or true
--- original size: 18308, stripped down to: 9948
+-- original size: 20949, stripped down to: 9945
if not modules then modules={} end modules ['l-file']={
version=1.001,
@@ -3043,41 +3248,28 @@ local file=file
if not lfs then
lfs=optionalrequire("lfs")
end
-if not lfs then
- lfs={
- getcurrentdir=function()
- return "."
- end,
- attributes=function()
- return nil
- end,
- isfile=function(name)
- local f=io.open(name,'rb')
- if f then
- f:close()
- return true
- end
- end,
- isdir=function(name)
- print("you need to load lfs")
- return false
- end
- }
-elseif not lfs.isfile then
- local attributes=lfs.attributes
- function lfs.isdir(name)
- return attributes(name,"mode")=="directory"
- end
- function lfs.isfile(name)
- return attributes(name,"mode")=="file"
- end
-end
local insert,concat=table.insert,table.concat
local match,find,gmatch=string.match,string.find,string.gmatch
local lpegmatch=lpeg.match
local getcurrentdir,attributes=lfs.currentdir,lfs.attributes
local checkedsplit=string.checkedsplit
local P,R,S,C,Cs,Cp,Cc,Ct=lpeg.P,lpeg.R,lpeg.S,lpeg.C,lpeg.Cs,lpeg.Cp,lpeg.Cc,lpeg.Ct
+local tricky=S("/\\")*P(-1)
+local attributes=lfs.attributes
+if sandbox then
+ sandbox.redefine(lfs.isfile,"lfs.isfile")
+ sandbox.redefine(lfs.isdir,"lfs.isdir")
+end
+function lfs.isdir(name)
+ if lpegmatch(tricky,name) then
+ return attributes(name,"mode")=="directory"
+ else
+ return attributes(name.."/.","mode")=="directory"
+ end
+end
+function lfs.isfile(name)
+ return attributes(name,"mode")=="file"
+end
local colon=P(":")
local period=P(".")
local periods=P("..")
@@ -3279,28 +3471,30 @@ local isroot=fwslash^1*-1
local hasroot=fwslash^1
local reslasher=lpeg.replacer(S("\\/"),"/")
local deslasher=lpeg.replacer(S("\\/")^1,"/")
-function file.join(...)
- local lst={... }
- local one=lst[1]
+function file.join(one,two,three,...)
+ if not two then
+ return one=="" and one or lpegmatch(stripper,one)
+ end
+ if one=="" then
+ return lpegmatch(stripper,three and concat({ two,three,... },"/") or two)
+ end
if lpegmatch(isnetwork,one) then
local one=lpegmatch(reslasher,one)
- local two=lpegmatch(deslasher,concat(lst,"/",2))
+ local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two)
if lpegmatch(hasroot,two) then
return one..two
else
return one.."/"..two
end
elseif lpegmatch(isroot,one) then
- local two=lpegmatch(deslasher,concat(lst,"/",2))
+ local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two)
if lpegmatch(hasroot,two) then
return two
else
return "/"..two
end
- elseif one=="" then
- return lpegmatch(stripper,concat(lst,"/",2))
else
- return lpegmatch(deslasher,concat(lst,"/"))
+ return lpegmatch(deslasher,concat({ one,two,three,... },"/"))
end
end
local drivespec=R("az","AZ")^1*colon
@@ -3474,7 +3668,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-md5"] = package.loaded["l-md5"] or true
--- original size: 3760, stripped down to: 2088
+-- original size: 3248, stripped down to: 2266
if not modules then modules={} end modules ['l-md5']={
version=1.001,
@@ -3492,14 +3686,20 @@ if not md5 then
}
end
local md5,file=md5,file
-local gsub,format,byte=string.gsub,string.format,string.byte
-local md5sum=md5.sum
-local function convert(str,fmt)
- return (gsub(md5sum(str),".",function(chr) return format(fmt,byte(chr)) end))
-end
-if not md5.HEX then function md5.HEX(str) return convert(str,"%02X") end end
-if not md5.hex then function md5.hex(str) return convert(str,"%02x") end end
-if not md5.dec then function md5.dec(str) return convert(str,"%03i") end end
+local gsub=string.gsub
+do
+ local patterns=lpeg and lpeg.patterns
+ if patterns then
+ local bytestoHEX=patterns.bytestoHEX
+ local bytestohex=patterns.bytestohex
+ local bytestodec=patterns.bytestodec
+ local lpegmatch=lpeg.match
+ local md5sum=md5.sum
+ if not md5.HEX then function md5.HEX(str) if str then return lpegmatch(bytestoHEX,md5sum(str)) end end end
+ if not md5.hex then function md5.hex(str) if str then return lpegmatch(bytestohex,md5sum(str)) end end end
+ if not md5.dec then function md5.dec(str) if str then return lpegmatch(bytestodec,md5sum(str)) end end end
+ end
+end
function file.needsupdating(oldname,newname,threshold)
local oldtime=lfs.attributes(oldname,"modification")
if oldtime then
@@ -3556,7 +3756,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-url"] = package.loaded["l-url"] or true
--- original size: 12292, stripped down to: 5585
+-- original size: 12531, stripped down to: 5721
if not modules then modules={} end modules ['l-url']={
version=1.001,
@@ -3642,19 +3842,25 @@ local splitquery=Cf (Ct("")*P { "sequence",
pair=Cg(key*equal*value),
},rawset)
local function hashed(str)
- if str=="" then
+ if not str or str=="" then
return {
scheme="invalid",
original=str,
}
end
- local s=split(str)
- local rawscheme=s[1]
- local rawquery=s[4]
- local somescheme=rawscheme~=""
- local somequery=rawquery~=""
+ local detailed=split(str)
+ local rawscheme=""
+ local rawquery=""
+ local somescheme=false
+ local somequery=false
+ if detailed then
+ rawscheme=detailed[1]
+ rawquery=detailed[4]
+ somescheme=rawscheme~=""
+ somequery=rawquery~=""
+ end
if not somescheme and not somequery then
- s={
+ return {
scheme="file",
authority="",
path=str,
@@ -3664,28 +3870,28 @@ local function hashed(str)
noscheme=true,
filename=str,
}
- else
- local authority,path,filename=s[2],s[3]
- if authority=="" then
- filename=path
- elseif path=="" then
- filename=""
- else
- filename=authority.."/"..path
- end
- s={
- scheme=rawscheme,
- authority=authority,
- path=path,
- query=lpegmatch(unescaper,rawquery),
- queries=lpegmatch(splitquery,rawquery),
- fragment=s[5],
- original=str,
- noscheme=false,
- filename=filename,
- }
end
- return s
+ local authority=detailed[2]
+ local path=detailed[3]
+ local filename=nil
+ if authority=="" then
+ filename=path
+ elseif path=="" then
+ filename=""
+ else
+ filename=authority.."/"..path
+ end
+ return {
+ scheme=rawscheme,
+ authority=authority,
+ path=path,
+ query=lpegmatch(unescaper,rawquery),
+ queries=lpegmatch(splitquery,rawquery),
+ fragment=detailed[5],
+ original=str,
+ noscheme=false,
+ filename=filename,
+ }
end
url.split=split
url.hasscheme=hasscheme
@@ -3719,7 +3925,7 @@ function url.construct(hash)
end
return lpegmatch(escaper,concat(fullurl))
end
-local pattern=Cs(noslash*R("az","AZ")*(S(":|")/":")*noslash*P(1)^0)
+local pattern=Cs(slash^-1/""*R("az","AZ")*((S(":|")/":")+P(":"))*slash*P(1)^0)
function url.filename(filename)
local spec=hashed(filename)
local path=spec.path
@@ -3767,7 +3973,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-dir"] = package.loaded["l-dir"] or true
--- original size: 14788, stripped down to: 9096
+-- original size: 16765, stripped down to: 11003
if not modules then modules={} end modules ['l-dir']={
version=1.001,
@@ -3777,7 +3983,7 @@ if not modules then modules={} end modules ['l-dir']={
license="see context related readme files"
}
local type,select=type,select
-local find,gmatch,match,gsub=string.find,string.gmatch,string.match,string.gsub
+local find,gmatch,match,gsub,sub=string.find,string.gmatch,string.match,string.gsub,string.sub
local concat,insert,remove,unpack=table.concat,table.insert,table.remove,table.unpack
local lpegmatch=lpeg.match
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
@@ -3786,53 +3992,126 @@ local dir=dir
local lfs=lfs
local attributes=lfs.attributes
local walkdir=lfs.dir
-local isdir=lfs.isdir
-local isfile=lfs.isfile
+local isdir=lfs.isdir
+local isfile=lfs.isfile
local currentdir=lfs.currentdir
local chdir=lfs.chdir
local mkdir=lfs.mkdir
local onwindows=os.type=="windows" or find(os.getenv("PATH"),";",1,true)
-if not isdir then
- function isdir(name)
- local a=attributes(name)
- return a and a.mode=="directory"
+if onwindows then
+ local tricky=S("/\\")*P(-1)
+ isdir=function(name)
+ if lpegmatch(tricky,name) then
+ return attributes(name,"mode")=="directory"
+ else
+ return attributes(name.."/.","mode")=="directory"
+ end
+ end
+ isfile=function(name)
+ return attributes(name,"mode")=="file"
end
lfs.isdir=isdir
-end
-if not isfile then
- function isfile(name)
- local a=attributes(name)
- return a and a.mode=="file"
+ lfs.isfile=isfile
+else
+ isdir=function(name)
+ return attributes(name,"mode")=="directory"
end
+ isfile=function(name)
+ return attributes(name,"mode")=="file"
+ end
+ lfs.isdir=isdir
lfs.isfile=isfile
end
function dir.current()
return (gsub(currentdir(),"\\","/"))
end
-local lfsisdir=isdir
-local function isdir(path)
- path=gsub(path,"[/\\]+$","")
- return lfsisdir(path)
+local function glob_pattern_function(path,patt,recurse,action)
+ if isdir(path) then
+ local usedpath
+ if path=="/" then
+ usedpath="/."
+ elseif not find(path,"/$") then
+ usedpath=path.."/."
+ path=path.."/"
+ else
+ usedpath=path
+ end
+ local dirs
+ for name in walkdir(usedpath) do
+ if name~="." and name~=".." then
+ local full=path..name
+ local mode=attributes(full,'mode')
+ if mode=='file' then
+ if not patt or find(full,patt) then
+ action(full)
+ end
+ elseif recurse and mode=="directory" then
+ if not dirs then
+ dirs={ full }
+ else
+ dirs[#dirs+1]=full
+ end
+ end
+ end
+ end
+ if dirs then
+ for i=1,#dirs do
+ glob_pattern_function(dirs[i],patt,recurse,action)
+ end
+ end
+ end
end
-lfs.isdir=isdir
-local function globpattern(path,patt,recurse,action)
- if path=="/" then
- path=path.."."
- elseif not find(path,"/$") then
- path=path..'/'
- end
- if isdir(path) then
- for name in walkdir(path) do
- local full=path..name
- local mode=attributes(full,'mode')
- if mode=='file' then
- if find(full,patt) then
- action(full)
+local function glob_pattern_table(path,patt,recurse,result)
+ if not result then
+ result={}
+ end
+ if isdir(path) then
+ local usedpath
+ if path=="/" then
+ usedpath="/."
+ elseif not find(path,"/$") then
+ usedpath=path.."/."
+ path=path.."/"
+ else
+ usedpath=path
+ end
+ local dirs
+ for name in walkdir(usedpath) do
+ if name~="." and name~=".." then
+ local full=path..name
+ local mode=attributes(full,'mode')
+ if mode=='file' then
+ if not patt or find(full,patt) then
+ result[#result+1]=full
+ end
+ elseif recurse and mode=="directory" then
+ if not dirs then
+ dirs={ full }
+ else
+ dirs[#dirs+1]=full
+ end
end
- elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
- globpattern(full,patt,recurse,action)
end
end
+ if dirs then
+ for i=1,#dirs do
+ glob_pattern_table(dirs[i],patt,recurse,result)
+ end
+ end
+ end
+ return result
+end
+local function globpattern(path,patt,recurse,method)
+ local kind=type(method)
+ if patt and sub(patt,1,-3)==path then
+ patt=false
+ end
+ if kind=="function" then
+ return glob_pattern_function(path,patt,recurse,method)
+ elseif kind=="table" then
+ return glob_pattern_table(path,patt,recurse,method)
+ else
+ return glob_pattern_table(path,patt,recurse,{})
end
end
dir.globpattern=globpattern
@@ -3845,34 +4124,40 @@ local function collectpattern(path,patt,recurse,result)
ok,scanner,first=xpcall(function() return walkdir(path) end,function() end)
end
if ok and type(scanner)=="function" then
- if not find(path,"/$") then path=path..'/' end
+ if not find(path,"/$") then
+ path=path..'/'
+ end
for name in scanner,first do
- local full=path..name
- local attr=attributes(full)
- local mode=attr.mode
- if mode=='file' then
- if find(full,patt) then
+ if name=="." then
+ elseif name==".." then
+ else
+ local full=path..name
+ local attr=attributes(full)
+ local mode=attr.mode
+ if mode=='file' then
+ if find(full,patt) then
+ result[name]=attr
+ end
+ elseif recurse and mode=="directory" then
+ attr.list=collectpattern(full,patt,recurse)
result[name]=attr
end
- elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
- attr.list=collectpattern(full,patt,recurse)
- result[name]=attr
end
end
end
return result
end
dir.collectpattern=collectpattern
-local separator
-if onwindows then
+local separator,pattern
+if onwindows then
local slash=S("/\\")/"/"
- pattern=Ct {
+ pattern={
[1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3),
[2]=Cs(((1-S("*?/\\"))^0*slash)^0),
[3]=Cs(P(1)^0)
}
-else
- pattern=Ct {
+else
+ pattern={
[1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3),
[2]=C(((1-S("*?/"))^0*P("/"))^0),
[3]=C(P(1)^0)
@@ -3890,9 +4175,8 @@ local function glob(str,t)
elseif isfile(str) then
t(str)
else
- local split=lpegmatch(pattern,str)
- if split then
- local root,path,base=split[1],split[2],split[3]
+ local root,path,base=lpegmatch(pattern,str)
+ if root and path and base then
local recurse=find(base,"**",1,true)
local start=root..path
local result=lpegmatch(filter,start..base)
@@ -3914,16 +4198,12 @@ local function glob(str,t)
return { str }
end
else
- local split=lpegmatch(pattern,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 root,path,base=lpegmatch(pattern,str)
+ if root and path and base then
local recurse=find(base,"**",1,true)
local start=root..path
local result=lpegmatch(filter,start..base)
- globpattern(start,result,recurse,action)
- return t
+ return globpattern(start,result,recurse,t)
else
return {}
end
@@ -4071,47 +4351,51 @@ else
end
end
dir.makedirs=dir.mkdirs
-if onwindows then
- function dir.expandname(str)
- local first,nothing,last=match(str,"^(//)(//*)(.*)$")
- if first then
- first=dir.current().."/"
- end
- if not first then
- first,last=match(str,"^(//)/*(.*)$")
- end
- if not first then
- first,last=match(str,"^([a-zA-Z]:)(.*)$")
- if first and not find(last,"^/") then
- local d=currentdir()
- if chdir(first) then
- first=dir.current()
+do
+ local chdir=sandbox and sandbox.original(chdir) or chdir
+ if onwindows then
+ local xcurrentdir=dir.current
+ function dir.expandname(str)
+ local first,nothing,last=match(str,"^(//)(//*)(.*)$")
+ if first then
+ first=xcurrentdir().."/"
+ end
+ if not first then
+ first,last=match(str,"^(//)/*(.*)$")
+ end
+ if not first then
+ first,last=match(str,"^([a-zA-Z]:)(.*)$")
+ if first and not find(last,"^/") then
+ local d=currentdir()
+ if chdir(first) then
+ first=xcurrentdir()
+ end
+ chdir(d)
end
- chdir(d)
+ end
+ if not first then
+ first,last=xcurrentdir(),str
+ end
+ last=gsub(last,"//","/")
+ last=gsub(last,"/%./","/")
+ last=gsub(last,"^/*","")
+ first=gsub(first,"/*$","")
+ if last=="" or last=="." then
+ return first
+ else
+ return first.."/"..last
end
end
- if not first then
- first,last=dir.current(),str
- end
- last=gsub(last,"//","/")
- last=gsub(last,"/%./","/")
- last=gsub(last,"^/*","")
- first=gsub(first,"/*$","")
- if last=="" or last=="." then
- return first
- else
- return first.."/"..last
- end
- end
-else
- function dir.expandname(str)
- if not find(str,"^/") then
- str=currentdir().."/"..str
+ else
+ function dir.expandname(str)
+ if not find(str,"^/") then
+ str=currentdir().."/"..str
+ end
+ str=gsub(str,"//","/")
+ str=gsub(str,"/%./","/")
+ str=gsub(str,"(.)/%.$","%1")
+ return str
end
- str=gsub(str,"//","/")
- str=gsub(str,"/%./","/")
- str=gsub(str,"(.)/%.$","%1")
- return str
end
end
file.expandname=dir.expandname
@@ -4154,7 +4438,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-boolean"] = package.loaded["l-boolean"] or true
--- original size: 1809, stripped down to: 1527
+-- original size: 1850, stripped down to: 1568
if not modules then modules={} end modules ['l-boolean']={
version=1.001,
@@ -4208,11 +4492,11 @@ function string.booleanstring(str)
return str=="yes" or str=="on" or str=="t"
end
end
-function string.is_boolean(str,default)
+function string.is_boolean(str,default,strict)
if type(str)=="string" then
- if str=="true" or str=="yes" or str=="on" or str=="t" or str=="1" then
+ if str=="true" or str=="yes" or str=="on" or str=="t" or (not strict and str=="1") then
return true
- elseif str=="false" or str=="no" or str=="off" or str=="f" or str=="0" then
+ elseif str=="false" or str=="no" or str=="off" or str=="f" or (not strict and str=="0") then
return false
end
end
@@ -4226,7 +4510,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-unicode"] = package.loaded["l-unicode"] or true
--- original size: 33706, stripped down to: 14938
+-- original size: 37233, stripped down to: 15684
if not modules then modules={} end modules ['l-unicode']={
version=1.001,
@@ -4242,7 +4526,9 @@ local type=type
local char,byte,format,sub,gmatch=string.char,string.byte,string.format,string.sub,string.gmatch
local concat=table.concat
local P,C,R,Cs,Ct,Cmt,Cc,Carg,Cp=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Ct,lpeg.Cmt,lpeg.Cc,lpeg.Carg,lpeg.Cp
-local lpegmatch,patterns=lpeg.match,lpeg.patterns
+local lpegmatch=lpeg.match
+local patterns=lpeg.patterns
+local tabletopattern=lpeg.utfchartabletopattern
local bytepairs=string.bytepairs
local finder=lpeg.finder
local replacer=lpeg.replacer
@@ -4251,7 +4537,7 @@ local utfgmatch=utf.gmatch
local p_utftype=patterns.utftype
local p_utfstricttype=patterns.utfstricttype
local p_utfoffset=patterns.utfoffset
-local p_utf8char=patterns.utf8char
+local p_utf8char=patterns.utf8character
local p_utf8byte=patterns.utf8byte
local p_utfbom=patterns.utfbom
local p_newline=patterns.newline
@@ -4450,15 +4736,52 @@ if not utf.sub then
end
end
end
-function utf.remapper(mapping)
- local pattern=Cs((p_utf8char/mapping)^0)
- return function(str)
- if not str or str=="" then
- return ""
+function utf.remapper(mapping,option)
+ local variant=type(mapping)
+ if variant=="table" then
+ if option=="dynamic" then
+ local pattern=false
+ table.setmetatablenewindex(mapping,function(t,k,v) rawset(t,k,v) pattern=false end)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ if not pattern then
+ pattern=Cs((tabletopattern(mapping)/mapping+p_utf8char)^0)
+ end
+ return lpegmatch(pattern,str)
+ end
+ end
+ elseif option=="pattern" then
+ return Cs((tabletopattern(mapping)/mapping+p_utf8char)^0)
else
- return lpegmatch(pattern,str)
+ local pattern=Cs((tabletopattern(mapping)/mapping+p_utf8char)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+ end
+ elseif variant=="function" then
+ if option=="pattern" then
+ return Cs((p_utf8char/mapping+p_utf8char)^0)
+ else
+ local pattern=Cs((p_utf8char/mapping+p_utf8char)^0)
+ return function(str)
+ if not str or str=="" then
+ return ""
+ else
+ return lpegmatch(pattern,str)
+ end
+ end,pattern
+ end
+ else
+ return function(str)
+ return str or ""
end
- end,pattern
+ end
end
function utf.replacer(t)
local r=replacer(t,false,false,true)
@@ -4508,190 +4831,157 @@ function utf.magic(f)
end
local utf16_to_utf8_be,utf16_to_utf8_le
local utf32_to_utf8_be,utf32_to_utf8_le
-local utf_16_be_linesplitter=patterns.utfbom_16_be^-1*lpeg.tsplitat(patterns.utf_16_be_nl)
-local utf_16_le_linesplitter=patterns.utfbom_16_le^-1*lpeg.tsplitat(patterns.utf_16_le_nl)
-if bytepairs then
- utf16_to_utf8_be=function(t)
- if type(t)=="string" then
- t=lpegmatch(utf_16_be_linesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,0
- for left,right in bytepairs(t[i]) do
- if right then
- local now=256*left+right
- if more>0 then
- now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
- more=0
- r=r+1
- result[r]=utfchar(now)
- elseif now>=0xD800 and now<=0xDBFF then
- more=now
- else
- r=r+1
- result[r]=utfchar(now)
- end
- end
- end
- t[i]=concat(result,"",1,r)
- end
- return t
+local utf_16_be_getbom=patterns.utfbom_16_be^-1
+local utf_16_le_getbom=patterns.utfbom_16_le^-1
+local utf_32_be_getbom=patterns.utfbom_32_be^-1
+local utf_32_le_getbom=patterns.utfbom_32_le^-1
+local utf_16_be_linesplitter=utf_16_be_getbom*lpeg.tsplitat(patterns.utf_16_be_nl)
+local utf_16_le_linesplitter=utf_16_le_getbom*lpeg.tsplitat(patterns.utf_16_le_nl)
+local utf_32_be_linesplitter=utf_32_be_getbom*lpeg.tsplitat(patterns.utf_32_be_nl)
+local utf_32_le_linesplitter=utf_32_le_getbom*lpeg.tsplitat(patterns.utf_32_le_nl)
+local more=0
+local p_utf16_to_utf8_be=C(1)*C(1)/function(left,right)
+ local now=256*byte(left)+byte(right)
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ return utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ return ""
+ else
+ return utfchar(now)
+ end
+end
+local p_utf16_to_utf8_le=C(1)*C(1)/function(right,left)
+ local now=256*byte(left)+byte(right)
+ if more>0 then
+ now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
+ more=0
+ return utfchar(now)
+ elseif now>=0xD800 and now<=0xDBFF then
+ more=now
+ return ""
+ else
+ return utfchar(now)
+ end
+end
+local p_utf32_to_utf8_be=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d)
+ return utfchar(256*256*256*byte(a)+256*256*byte(b)+256*byte(c)+byte(d))
+end
+local p_utf32_to_utf8_le=C(1)*C(1)*C(1)*C(1)/function(a,b,c,d)
+ return utfchar(256*256*256*byte(d)+256*256*byte(c)+256*byte(b)+byte(a))
+end
+p_utf16_to_utf8_be=P(true)/function() more=0 end*utf_16_be_getbom*Cs(p_utf16_to_utf8_be^0)
+p_utf16_to_utf8_le=P(true)/function() more=0 end*utf_16_le_getbom*Cs(p_utf16_to_utf8_le^0)
+p_utf32_to_utf8_be=P(true)/function() more=0 end*utf_32_be_getbom*Cs(p_utf32_to_utf8_be^0)
+p_utf32_to_utf8_le=P(true)/function() more=0 end*utf_32_le_getbom*Cs(p_utf32_to_utf8_le^0)
+patterns.utf16_to_utf8_be=p_utf16_to_utf8_be
+patterns.utf16_to_utf8_le=p_utf16_to_utf8_le
+patterns.utf32_to_utf8_be=p_utf32_to_utf8_be
+patterns.utf32_to_utf8_le=p_utf32_to_utf8_le
+utf16_to_utf8_be=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf16_to_utf8_be,s)
+ else
+ return s
end
- utf16_to_utf8_le=function(t)
- if type(t)=="string" then
- t=lpegmatch(utf_16_le_linesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,0
- for left,right in bytepairs(t[i]) do
- if right then
- local now=256*right+left
- if more>0 then
- now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
- more=0
- r=r+1
- result[r]=utfchar(now)
- elseif now>=0xD800 and now<=0xDBFF then
- more=now
- else
- r=r+1
- result[r]=utfchar(now)
- end
- end
- end
- t[i]=concat(result,"",1,r)
- end
- return t
+end
+local utf16_to_utf8_be_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_16_be_linesplitter,t)
end
- utf32_to_utf8_be=function(t)
- if type(t)=="string" then
- t=lpegmatch(utflinesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,-1
- for a,b in bytepairs(t[i]) do
- if a and b then
- if more<0 then
- more=256*256*256*a+256*256*b
- else
- r=r+1
- result[t]=utfchar(more+256*a+b)
- more=-1
- end
- else
- break
- end
- end
- t[i]=concat(result,"",1,r)
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf16_to_utf8_be,s)
end
- return t
end
- utf32_to_utf8_le=function(t)
- if type(t)=="string" then
- t=lpegmatch(utflinesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,-1
- for a,b in bytepairs(t[i]) do
- if a and b then
- if more<0 then
- more=256*b+a
- else
- r=r+1
- result[t]=utfchar(more+256*256*256*b+256*256*a)
- more=-1
- end
- else
- break
- end
- end
- t[i]=concat(result,"",1,r)
- end
- return t
+ return t
+end
+utf16_to_utf8_le=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf16_to_utf8_le,s)
+ else
+ return s
end
-else
- utf16_to_utf8_be=function(t)
- if type(t)=="string" then
- t=lpegmatch(utf_16_be_linesplitter,t)
- end
- local result={}
- for i=1,#t do
- local r,more=0,0
- for left,right in gmatch(t[i],"(.)(.)") do
- if left=="\000" then
- r=r+1
- result[r]=utfchar(byte(right))
- elseif right then
- local now=256*byte(left)+byte(right)
- if more>0 then
- now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
- more=0
- r=r+1
- result[r]=utfchar(now)
- elseif now>=0xD800 and now<=0xDBFF then
- more=now
- else
- r=r+1
- result[r]=utfchar(now)
- end
- end
- end
- t[i]=concat(result,"",1,r)
+end
+local utf16_to_utf8_le_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_16_le_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf16_to_utf8_le,s)
end
- return t
end
- utf16_to_utf8_le=function(t)
- if type(t)=="string" then
- t=lpegmatch(utf_16_le_linesplitter,t)
+ return t
+end
+utf32_to_utf8_be=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf32_to_utf8_be,s)
+ else
+ return s
+ end
+end
+local utf32_to_utf8_be_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_32_be_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf32_to_utf8_be,s)
end
- local result={}
- for i=1,#t do
- local r,more=0,0
- for left,right in gmatch(t[i],"(.)(.)") do
- if right=="\000" then
- r=r+1
- result[r]=utfchar(byte(left))
- elseif right then
- local now=256*byte(right)+byte(left)
- if more>0 then
- now=(more-0xD800)*0x400+(now-0xDC00)+0x10000
- more=0
- r=r+1
- result[r]=utfchar(now)
- elseif now>=0xD800 and now<=0xDBFF then
- more=now
- else
- r=r+1
- result[r]=utfchar(now)
- end
- end
- end
- t[i]=concat(result,"",1,r)
+ end
+ return t
+end
+utf32_to_utf8_le=function(s)
+ if s and s~="" then
+ return lpegmatch(p_utf32_to_utf8_le,s)
+ else
+ return s
+ end
+end
+local utf32_to_utf8_le_t=function(t)
+ if not t then
+ return nil
+ elseif type(t)=="string" then
+ t=lpegmatch(utf_32_le_linesplitter,t)
+ end
+ for i=1,#t do
+ local s=t[i]
+ if s~="" then
+ t[i]=lpegmatch(p_utf32_to_utf8_le,s)
end
- return t
end
- utf32_to_utf8_le=function() return {} end
- utf32_to_utf8_be=function() return {} end
+ return t
end
+utf.utf16_to_utf8_le_t=utf16_to_utf8_le_t
+utf.utf16_to_utf8_be_t=utf16_to_utf8_be_t
+utf.utf32_to_utf8_le_t=utf32_to_utf8_le_t
+utf.utf32_to_utf8_be_t=utf32_to_utf8_be_t
utf.utf16_to_utf8_le=utf16_to_utf8_le
utf.utf16_to_utf8_be=utf16_to_utf8_be
utf.utf32_to_utf8_le=utf32_to_utf8_le
utf.utf32_to_utf8_be=utf32_to_utf8_be
-function utf.utf8_to_utf8(t)
+function utf.utf8_to_utf8_t(t)
return type(t)=="string" and lpegmatch(utflinesplitter,t) or t
end
-function utf.utf16_to_utf8(t,endian)
- return endian and utf16_to_utf8_be(t) or utf16_to_utf8_le(t) or t
+function utf.utf16_to_utf8_t(t,endian)
+ return endian and utf16_to_utf8_be_t(t) or utf16_to_utf8_le_t(t) or t
end
-function utf.utf32_to_utf8(t,endian)
- return endian and utf32_to_utf8_be(t) or utf32_to_utf8_le(t) or t
+function utf.utf32_to_utf8_t(t,endian)
+ return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t
end
-local function little(c)
- local b=byte(c)
+local function little(b)
if b<0x10000 then
return char(b%256,b/256)
else
@@ -4700,8 +4990,7 @@ local function little(c)
return char(b1%256,b1/256,b2%256,b2/256)
end
end
-local function big(c)
- local b=byte(c)
+local function big(b)
if b<0x10000 then
return char(b/256,b%256)
else
@@ -4710,27 +4999,29 @@ local function big(c)
return char(b1/256,b1%256,b2/256,b2%256)
end
end
-local _,l_remap=utf.remapper(little)
-local _,b_remap=utf.remapper(big)
-function utf.utf8_to_utf16_be(str,nobom)
+local l_remap=Cs((p_utf8byte/little+P(1)/"")^0)
+local b_remap=Cs((p_utf8byte/big+P(1)/"")^0)
+local function utf8_to_utf16_be(str,nobom)
if nobom then
return lpegmatch(b_remap,str)
else
return char(254,255)..lpegmatch(b_remap,str)
end
end
-function utf.utf8_to_utf16_le(str,nobom)
+local function utf8_to_utf16_le(str,nobom)
if nobom then
return lpegmatch(l_remap,str)
else
return char(255,254)..lpegmatch(l_remap,str)
end
end
+utf.utf8_to_utf16_be=utf8_to_utf16_be
+utf.utf8_to_utf16_le=utf8_to_utf16_le
function utf.utf8_to_utf16(str,littleendian,nobom)
if littleendian then
- return utf.utf8_to_utf16_le(str,nobom)
+ return utf8_to_utf16_le(str,nobom)
else
- return utf.utf8_to_utf16_be(str,nobom)
+ return utf8_to_utf16_be(str,nobom)
end
end
local pattern=Cs (
@@ -4746,16 +5037,16 @@ function utf.xstring(s)
return format("0x%05X",type(s)=="number" and s or utfbyte(s))
end
function utf.toeight(str)
- if not str then
+ if not str or str=="" then
return nil
end
local utftype=lpegmatch(p_utfstricttype,str)
if utftype=="utf-8" then
- return sub(str,4)
- elseif utftype=="utf-16-le" then
- return utf16_to_utf8_le(str)
+ return sub(str,4)
elseif utftype=="utf-16-be" then
- return utf16_to_utf8_ne(str)
+ return utf16_to_utf8_be(str)
+ elseif utftype=="utf-16-le" then
+ return utf16_to_utf8_le(str)
else
return str
end
@@ -4834,7 +5125,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["l-math"] = package.loaded["l-math"] or true
--- original size: 915, stripped down to: 836
+-- original size: 974, stripped down to: 890
if not modules then modules={} end modules ['l-math']={
version=1.001,
@@ -4844,6 +5135,9 @@ if not modules then modules={} end modules ['l-math']={
license="see context related readme files"
}
local floor,sin,cos,tan=math.floor,math.sin,math.cos,math.tan
+if not math.ceiling then
+ math.ceiling=math.ceil
+end
if not math.round then
function math.round(x) return floor(x+0.5) end
end
@@ -4871,7 +5165,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-str"] = package.loaded["util-str"] or true
--- original size: 33063, stripped down to: 18397
+-- original size: 34407, stripped down to: 18852
if not modules then modules={} end modules ['util-str']={
version=1.001,
@@ -5001,10 +5295,12 @@ local striplinepatterns={
["retain"]=p_retain_normal,
["retain and collapse"]=p_retain_collapse,
["retain and no empty"]=p_retain_noempty,
+ ["collapse"]=patterns.collapser,
}
+setmetatable(striplinepatterns,{ __index=function(t,k) return p_prune_collapse end })
strings.striplinepatterns=striplinepatterns
function strings.striplines(str,how)
- return str and lpegmatch(how and striplinepatterns[how] or p_prune_collapse,str) or str
+ return str and lpegmatch(striplinepatterns[how],str) or str
end
strings.striplong=strings.striplines
function strings.nice(str)
@@ -5044,10 +5340,10 @@ string.tracedchars=tracedchars
strings.tracers=tracedchars
function string.tracedchar(b)
if type(b)=="number" then
- return tracedchars[b] or (utfchar(b).." (U+"..format('%05X',b)..")")
+ return tracedchars[b] or (utfchar(b).." (U+"..format("%05X",b)..")")
else
local c=utfbyte(b)
- return tracedchars[c] or (b.." (U+"..format('%05X',c)..")")
+ return tracedchars[c] or (b.." (U+"..(c and format("%05X",c) or "?????")..")")
end
end
function number.signed(i)
@@ -5184,12 +5480,12 @@ local format_f=function(f)
n=n+1
return format("format('%%%sf',a%s)",f,n)
end
-local format_F=function(f)
+local format_F=function(f)
n=n+1
if not f or f=="" then
- return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or (a%s == 1 and '1') or format('%%.9f',a%s))",n,n,n,n)
+ return format("(((a%s > -0.0000000005 and a%s < 0.0000000005) and '0') or format((a%s %% 1 == 0) and '%%i' or '%%.9f',a%s))",n,n,n,n)
else
- return format("((a%s == 0 and '0') or (a%s == 1 and '1') or format('%%%sf',a%s))",n,n,f,n)
+ return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n)
end
end
local format_g=function(f)
@@ -5417,7 +5713,6 @@ local builder=Cs { "start",
+V("j")+V("J")
+V("m")+V("M")
+V("z")
-+V("*")
)+V("*")
)*(P(-1)+Carg(1))
)^0,
@@ -5461,6 +5756,7 @@ local builder=Cs { "start",
["a"]=(prefix_any*P("a"))/format_a,
["A"]=(prefix_any*P("A"))/format_A,
["*"]=Cs(((1-P("%"))^1+P("%%")/"%%")^1)/format_rest,
+ ["?"]=Cs(((1-P("%"))^1 )^1)/format_rest,
["!"]=Carg(2)*prefix_any*P("!")*C((1-P("!"))^1)*P("!")/format_extension,
}
local direct=Cs (
@@ -5535,6 +5831,15 @@ else
add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape })
add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape })
end
+local dquote=patterns.dquote
+local equote=patterns.escaped+dquote/'\\"'+1
+local space=patterns.space
+local cquote=Cc('"')
+local pattern=Cs(dquote*(equote-P(-2))^0*dquote)
++Cs(cquote*(equote-space)^0*space*equote^0*cquote)
+function string.optionalquoted(str)
+ return lpegmatch(pattern,str) or str
+end
end -- of closure
@@ -5543,7 +5848,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-tab"] = package.loaded["util-tab"] or true
--- original size: 23985, stripped down to: 16069
+-- original size: 24267, stripped down to: 16260
if not modules then modules={} end modules ['util-tab']={
version=1.001,
@@ -5633,6 +5938,15 @@ function tables.removevalue(t,value)
end
end
end
+function tables.replacevalue(t,oldvalue,newvalue)
+ if oldvalue and newvalue then
+ for i=1,#t do
+ if t[i]==oldvalue then
+ t[i]=newvalue
+ end
+ end
+ end
+end
function tables.insertbeforevalue(t,value,extra)
for i=1,#t do
if t[i]==extra then
@@ -6026,7 +6340,7 @@ function table.serialize(root,name,specification)
end
depth=depth+1
end
- if root and next(root) then
+ if root and next(root)~=nil then
local first=nil
local last=0
last=#root
@@ -6051,7 +6365,7 @@ function table.serialize(root,name,specification)
elseif tv=="string" then
n=n+1 t[n]=f_val_str(depth,v)
elseif tv=="table" then
- if not next(v) then
+ if next(v)==nil then
n=n+1 t[n]=f_val_not(depth)
else
local st=simple_table(v)
@@ -6081,7 +6395,7 @@ function table.serialize(root,name,specification)
n=n+1 t[n]=f_key_boo_value_str(depth,k,v)
end
elseif tv=="table" then
- if not next(v) then
+ if next(v)==nil then
if tk=="number" then
n=n+1 t[n]=f_key_num_value_not(depth,k,v)
elseif tk=="string" then
@@ -6139,7 +6453,7 @@ function table.serialize(root,name,specification)
local dummy=root._w_h_a_t_e_v_e_r_
root._w_h_a_t_e_v_e_r_=nil
end
- if next(root) then
+ if next(root)~=nil then
do_serialize(root,name,1,0)
end
end
@@ -6302,7 +6616,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-prs"] = package.loaded["util-prs"] or true
--- original size: 19618, stripped down to: 14012
+-- original size: 21751, stripped down to: 15108
if not modules then modules={} end modules ['util-prs']={
version=1.001,
@@ -6458,11 +6772,30 @@ function parsers.settings_to_array(str,strict)
return { str }
end
end
-local separator=space^0*comma*space^0
-local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-(space^0*(comma+P(-1)))))^0)
-local withvalue=Carg(1)*value/function(f,s) return f(s) end
-local pattern_a=spaces*Ct(value*(separator*value)^0)
-local pattern_b=spaces*withvalue*(separator*withvalue)^0
+local cache_a={}
+local cache_b={}
+function parsers.groupedsplitat(symbol,withaction)
+ if not symbol then
+ symbol=","
+ end
+ local pattern=(withaction and cache_b or cache_a)[symbol]
+ if not pattern then
+ local symbols=S(symbol)
+ local separator=space^0*symbols*space^0
+ local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C((nestedbraces+(1-(space^0*(symbols+P(-1)))))^0)
+ if withaction then
+ local withvalue=Carg(1)*value/function(f,s) return f(s) end
+ pattern=spaces*withvalue*(separator*withvalue)^0
+ cache_b[symbol]=pattern
+ else
+ pattern=spaces*Ct(value*(separator*value)^0)
+ cache_a[symbol]=pattern
+ end
+ end
+ return pattern
+end
+local pattern_a=parsers.groupedsplitat(",",false)
+local pattern_b=parsers.groupedsplitat(",",true)
function parsers.stripped_settings_to_array(str)
if not str or str=="" then
return {}
@@ -6524,12 +6857,9 @@ function parsers.array_to_string(a,separator)
return ""
end
end
-function parsers.settings_to_set(str,t)
- t=t or {}
- for s in gmatch(str,"[^, ]+") do
- t[s]=true
- end
- return t
+local pattern=Cf(Ct("")*Cg(C((1-S(", "))^1)*S(", ")^0*Cc(true))^1,rawset)
+function utilities.parsers.settings_to_set(str,t)
+ return str and lpegmatch(pattern,str) or {}
end
function parsers.simple_hash_to_string(h,separator)
local t,tn={},0
@@ -6541,12 +6871,16 @@ function parsers.simple_hash_to_string(h,separator)
end
return concat(t,separator or ",")
end
-local str=C((1-whitespace-equal)^1)
+local str=Cs(lpegpatterns.unquoted)+C((1-whitespace-equal)^1)
local setting=Cf(Carg(1)*(whitespace^0*Cg(str*whitespace^0*(equal*whitespace^0*str+Cc(""))))^1,rawset)
local splitter=setting^1
function utilities.parsers.options_to_hash(str,target)
return str and lpegmatch(splitter,str,1,target or {}) or {}
end
+local splitter=lpeg.tsplitat(" ")
+function utilities.parsers.options_to_array(str)
+ return str and lpegmatch(splitter,str) or {}
+end
local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+C(digit^1*lparent*(noparent+nestedparents)^1*rparent)+C((nestedbraces+(1-comma))^1)
local pattern_a=spaces*Ct(value*(separator*value)^0)
local function repeater(n,str)
@@ -6668,7 +7002,7 @@ function parsers.rfc4180splitter(specification)
local field=escaped+non_escaped+Cc("")
local record=Ct(field*(separator*field)^1)
local headerline=record*Cp()
- local wholeblob=Ct((newline^-1*record)^0)
+ local wholeblob=Ct((newline^(specification.strict and -1 or 1)*record)^0)
return function(data,getheader)
if getheader then
local header,position=lpegmatch(headerline,data)
@@ -6705,13 +7039,13 @@ function parsers.stepper(str,n,action)
lpegmatch(stepper,str,1,n,action or print)
end
end
-local pattern_math=Cs((P("%")/"\\percent "+P("^")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0)
-local pattern_text=Cs((P("%")/"\\percent "+(P("^")/"\\high")*Cc("{")*lpegpatterns.integer*Cc("}")+P(1))^0)
+local pattern_math=Cs((P("%")/"\\percent "+P("^")*Cc("{")*lpegpatterns.integer*Cc("}")+anything)^0)
+local pattern_text=Cs((P("%")/"\\percent "+(P("^")/"\\high")*Cc("{")*lpegpatterns.integer*Cc("}")+anything)^0)
patterns.unittotex=pattern
function parsers.unittotex(str,textmode)
return lpegmatch(textmode and pattern_text or pattern_math,str)
end
-local pattern=Cs((P("^")/"<sup>"*lpegpatterns.integer*Cc("</sup>")+P(1))^0)
+local pattern=Cs((P("^")/"<sup>"*lpegpatterns.integer*Cc("</sup>")+anything)^0)
function parsers.unittoxml(str)
return lpegmatch(pattern,str)
end
@@ -6783,6 +7117,18 @@ function utilities.parsers.runtime(time)
local seconds=mod(time,60)
return days,hours,minutes,seconds
end
+local spacing=whitespace^0
+local apply=P("->")
+local method=C((1-apply)^1)
+local token=lbrace*C((1-rbrace)^1)*rbrace+C(anything^1)
+local pattern=spacing*(method*spacing*apply+Carg(1))*spacing*token
+function utilities.parsers.splitmethod(str,default)
+ if str then
+ return lpegmatch(pattern,str,1,default or false)
+ else
+ return default or false,""
+ end
+end
end -- of closure
@@ -6872,7 +7218,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["trac-set"] = package.loaded["trac-set"] or true
--- original size: 12365, stripped down to: 8799
+-- original size: 12482, stripped down to: 8864
if not modules then modules={} end modules ['trac-set']={
version=1.001,
@@ -6900,7 +7246,7 @@ function setters.initialize(filename,name,values)
local data=setter.data
if data then
for key,newvalue in next,values do
- local newvalue=is_boolean(newvalue,newvalue)
+ local newvalue=is_boolean(newvalue,newvalue,true)
local functions=data[key]
if functions then
local oldvalue=functions.value
@@ -6954,7 +7300,7 @@ local function set(t,what,newvalue)
elseif not value then
value=false
else
- value=is_boolean(value,value)
+ value=is_boolean(value,value,true)
end
w=topattern(w,true,true)
for name,functions in next,data do
@@ -7093,6 +7439,7 @@ function setters.new(name)
report=function(...) setters.report (setter,...) end,
enable=function(...) enable (setter,...) end,
disable=function(...) disable (setter,...) end,
+ reset=function(...) reset (setter,...) end,
register=function(...) register(setter,...) end,
list=function(...) list (setter,...) end,
show=function(...) show (setter,...) end,
@@ -7184,7 +7531,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["trac-log"] = package.loaded["trac-log"] or true
--- original size: 25613, stripped down to: 16617
+-- original size: 29359, stripped down to: 20483
if not modules then modules={} end modules ['trac-log']={
version=1.001,
@@ -7193,15 +7540,18 @@ if not modules then modules={} end modules ['trac-log']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
+local next,type,select,print=next,type,select,print
local write_nl,write=texio and texio.write_nl or print,texio and texio.write or io.write
local format,gmatch,find=string.format,string.gmatch,string.find
local concat,insert,remove=table.concat,table.insert,table.remove
local topattern=string.topattern
-local next,type,select=next,type,select
local utfchar=utf.char
+local datetime=os.date
+local openfile=io.open
local setmetatableindex=table.setmetatableindex
local formatters=string.formatters
local texgetcount=tex and tex.getcount
+local variant="default"
logs=logs or {}
local logs=logs
local moreinfo=[[
@@ -7211,32 +7561,122 @@ 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
]]
-utilities.strings.formatters.add (
+formatters.add (
formatters,"unichr",
[["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]]
)
-utilities.strings.formatters.add (
+formatters.add (
formatters,"chruni",
[[utfchar(%s) .. " (U+" .. format("%%05X",%s) .. ")"]]
)
local function ignore() end
setmetatableindex(logs,function(t,k) t[k]=ignore;return ignore end)
local report,subreport,status,settarget,setformats,settranslations
-local direct,subdirect,writer,pushtarget,poptarget,setlogfile,settimedlog,setprocessor,setformatters
+local direct,subdirect,writer,pushtarget,poptarget,setlogfile,settimedlog,setprocessor,setformatters,newline
if tex and (tex.jobname or tex.formatname) then
- local valueiskey={ __index=function(t,k) t[k]=k return k end }
- local target="term and log"
+ local function useluawrites()
+ local texio_write_nl=texio.write_nl
+ local texio_write=texio.write
+ local io_write=io.write
+ write_nl=function(target,...)
+ if not io_write then
+ io_write=io.write
+ end
+ if target=="term and log" then
+ texio_write_nl("log",...)
+ texio_write_nl("term","")
+ io_write(...)
+ elseif target=="log" then
+ texio_write_nl("log",...)
+ elseif target=="term" then
+ texio_write_nl("term","")
+ io_write(...)
+ elseif target~="none" then
+ texio_write_nl("log",target,...)
+ texio_write_nl("term","")
+ io_write(target,...)
+ end
+ end
+ write=function(target,...)
+ if not io_write then
+ io_write=io.write
+ end
+ if target=="term and log" then
+ texio_write("log",...)
+ io_write(...)
+ elseif target=="log" then
+ texio_write("log",...)
+ elseif target=="term" then
+ io_write(...)
+ elseif target~="none" then
+ texio_write("log",target,...)
+ io_write(target,...)
+ end
+ end
+ texio.write=write
+ texio.write_nl=write_nl
+ useluawrites=ignore
+ end
+ local whereto="both"
+ local target=nil
+ local targets=nil
+ local formats=table.setmetatableindex("self")
+ local translations=table.setmetatableindex("self")
+ local report_yes,subreport_yes,direct_yes,subdirect_yes,status_yes
+ local report_nop,subreport_nop,direct_nop,subdirect_nop,status_nop
+ local variants={
+ default={
+ formats={
+ report_yes=formatters["%-15s > %s\n"],
+ report_nop=formatters["%-15s >\n"],
+ direct_yes=formatters["%-15s > %s"],
+ direct_nop=formatters["%-15s >"],
+ subreport_yes=formatters["%-15s > %s > %s\n"],
+ subreport_nop=formatters["%-15s > %s >\n"],
+ subdirect_yes=formatters["%-15s > %s > %s"],
+ subdirect_nop=formatters["%-15s > %s >"],
+ status_yes=formatters["%-15s : %s\n"],
+ status_nop=formatters["%-15s :\n"],
+ },
+ targets={
+ logfile="log",
+ log="log",
+ file="log",
+ console="term",
+ terminal="term",
+ both="term and log",
+ },
+ },
+ ansi={
+ formats={
+ report_yes=formatters["%-15s > %s\n"],
+ report_nop=formatters["%-15s >\n"],
+ direct_yes=formatters["%-15s > %s"],
+ direct_nop=formatters["%-15s >"],
+ subreport_yes=formatters["%-15s > %s > %s\n"],
+ subreport_nop=formatters["%-15s > %s >\n"],
+ subdirect_yes=formatters["%-15s > %s > %s"],
+ subdirect_nop=formatters["%-15s > %s >"],
+ status_yes=formatters["%-15s : %s\n"],
+ status_nop=formatters["%-15s :\n"],
+ },
+ targets={
+ logfile="none",
+ log="none",
+ file="none",
+ console="term",
+ terminal="term",
+ both="term",
+ },
+ }
+ }
logs.flush=io.flush
- local formats={} setmetatable(formats,valueiskey)
- local translations={} setmetatable(translations,valueiskey)
writer=function(...)
write_nl(target,...)
end
newline=function()
write_nl(target,"\n")
end
- local report_yes=formatters["%-15s > %s\n"]
- local report_nop=formatters["%-15s >\n"]
report=function(a,b,c,...)
if c then
write_nl(target,report_yes(translations[a],formatters[formats[b]](c,...)))
@@ -7248,8 +7688,6 @@ if tex and (tex.jobname or tex.formatname) then
write_nl(target,"\n")
end
end
- local direct_yes=formatters["%-15s > %s"]
- local direct_nop=formatters["%-15s >"]
direct=function(a,b,c,...)
if c then
return direct_yes(translations[a],formatters[formats[b]](c,...))
@@ -7261,8 +7699,6 @@ if tex and (tex.jobname or tex.formatname) then
return ""
end
end
- local subreport_yes=formatters["%-15s > %s > %s\n"]
- local subreport_nop=formatters["%-15s > %s >\n"]
subreport=function(a,s,b,c,...)
if c then
write_nl(target,subreport_yes(translations[a],translations[s],formatters[formats[b]](c,...)))
@@ -7274,8 +7710,6 @@ if tex and (tex.jobname or tex.formatname) then
write_nl(target,"\n")
end
end
- local subdirect_yes=formatters["%-15s > %s > %s"]
- local subdirect_nop=formatters["%-15s > %s >"]
subdirect=function(a,s,b,c,...)
if c then
return subdirect_yes(translations[a],translations[s],formatters[formats[b]](c,...))
@@ -7287,8 +7721,6 @@ if tex and (tex.jobname or tex.formatname) then
return ""
end
end
- local status_yes=formatters["%-15s : %s\n"]
- local status_nop=formatters["%-15s :\n"]
status=function(a,b,c,...)
if c then
write_nl(target,status_yes(translations[a],formatters[formats[b]](c,...)))
@@ -7300,16 +7732,13 @@ if tex and (tex.jobname or tex.formatname) then
write_nl(target,"\n")
end
end
- local targets={
- logfile="log",
- log="log",
- file="log",
- console="term",
- terminal="term",
- both="term and log",
- }
- settarget=function(whereto)
- target=targets[whereto or "both"] or targets.both
+ settarget=function(askedwhereto)
+ whereto=askedwhereto or whereto or "both"
+ target=targets[whereto]
+ if not target then
+ whereto="both"
+ target=targets[whereto]
+ end
if target=="term" or target=="term and log" then
logs.flush=io.flush
else
@@ -7338,21 +7767,74 @@ if tex and (tex.jobname or tex.formatname) then
writeline(target,f(...))
end
end
- setformatters=function(f)
- report_yes=f.report_yes or report_yes
- report_nop=f.report_nop or report_nop
- subreport_yes=f.subreport_yes or subreport_yes
- subreport_nop=f.subreport_nop or subreport_nop
- direct_yes=f.direct_yes or direct_yes
- direct_nop=f.direct_nop or direct_nop
- subdirect_yes=f.subdirect_yes or subdirect_yes
- subdirect_nop=f.subdirect_nop or subdirect_nop
- status_yes=f.status_yes or status_yes
- status_nop=f.status_nop or status_nop
- end
+ setformatters=function(specification)
+ local t=nil
+ local f=nil
+ local d=variants.default
+ if not specification then
+ elseif type(specification)=="table" then
+ t=specification.targets
+ f=specification.formats or specification
+ else
+ local v=variants[specification]
+ if v then
+ t=v.targets
+ f=v.formats
+ variant=specification
+ end
+ end
+ targets=t or d.targets
+ target=targets[whereto] or target
+ if f then
+ d=d.formats
+ else
+ f=d.formats
+ d=f
+ end
+ setmetatableindex(f,d)
+ report_yes=f.report_yes
+ report_nop=f.report_nop
+ subreport_yes=f.subreport_yes
+ subreport_nop=f.subreport_nop
+ direct_yes=f.direct_yes
+ direct_nop=f.direct_nop
+ subdirect_yes=f.subdirect_yes
+ subdirect_nop=f.subdirect_nop
+ status_yes=f.status_yes
+ status_nop=f.status_nop
+ if variant=="ansi" then
+ useluawrites()
+ end
+ settarget(whereto)
+ end
+ setformatters(variant)
setlogfile=ignore
settimedlog=ignore
else
+ local report_yes,subreport_yes,status_yes
+ local report_nop,subreport_nop,status_nop
+ local variants={
+ default={
+ formats={
+ report_yes=formatters["%-15s | %s"],
+ report_nop=formatters["%-15s |"],
+ subreport_yes=formatters["%-15s | %s | %s"],
+ subreport_nop=formatters["%-15s | %s |"],
+ status_yes=formatters["%-15s : %s\n"],
+ status_nop=formatters["%-15s :\n"],
+ },
+ },
+ ansi={
+ formats={
+ report_yes=formatters["%-15s | %s"],
+ report_nop=formatters["%-15s |"],
+ subreport_yes=formatters["%-15s | %s | %s"],
+ subreport_nop=formatters["%-15s | %s |"],
+ status_yes=formatters["%-15s : %s\n"],
+ status_nop=formatters["%-15s :\n"],
+ },
+ },
+ }
logs.flush=ignore
writer=function(s)
write_nl(s)
@@ -7360,8 +7842,6 @@ else
newline=function()
write_nl("\n")
end
- local report_yes=formatters["%-15s | %s"]
- local report_nop=formatters["%-15s |"]
report=function(a,b,c,...)
if c then
write_nl(report_yes(a,formatters[b](c,...)))
@@ -7373,8 +7853,6 @@ else
write_nl("")
end
end
- local subreport_yes=formatters["%-15s | %s | %s"]
- local subreport_nop=formatters["%-15s | %s |"]
subreport=function(a,sub,b,c,...)
if c then
write_nl(subreport_yes(a,sub,formatters[b](c,...)))
@@ -7386,8 +7864,6 @@ else
write_nl("")
end
end
- local status_yes=formatters["%-15s : %s\n"]
- local status_nop=formatters["%-15s :\n"]
status=function(a,b,c,...)
if c then
write_nl(status_yes(a,formatters[b](c,...)))
@@ -7412,14 +7888,34 @@ else
writeline(f(s))
end
end
- setformatters=function(f)
- report_yes=f.report_yes or report_yes
- report_nop=f.report_nop or report_nop
- subreport_yes=f.subreport_yes or subreport_yes
- subreport_nop=f.subreport_nop or subreport_nop
- status_yes=f.status_yes or status_yes
- status_nop=f.status_nop or status_nop
- end
+ setformatters=function(specification)
+ local f=nil
+ local d=variants.default
+ if specification then
+ if type(specification)=="table" then
+ f=specification.formats or specification
+ else
+ local v=variants[specification]
+ if v then
+ f=v.formats
+ end
+ end
+ end
+ if f then
+ d=d.formats
+ else
+ f=d.formats
+ d=f
+ end
+ setmetatableindex(f,d)
+ report_yes=f.report_yes
+ report_nop=f.report_nop
+ subreport_yes=f.subreport_yes
+ subreport_nop=f.subreport_nop
+ status_yes=f.status_yes
+ status_nop=f.status_nop
+ end
+ setformatters(variant)
setlogfile=function(name,keepopen)
if name and name~="" then
local localtime=os.localtime
@@ -7672,13 +8168,13 @@ end
local simple=logs.reporter("comment")
logs.simple=simple
logs.simpleline=simple
-function logs.setprogram () end
-function logs.extendbanner() end
-function logs.reportlines () end
-function logs.reportbanner() end
-function logs.reportline () end
-function logs.simplelines () end
-function logs.help () end
+logs.setprogram=ignore
+logs.extendbanner=ignore
+logs.reportlines=ignore
+logs.reportbanner=ignore
+logs.reportline=ignore
+logs.simplelines=ignore
+logs.help=ignore
local Carg,C,lpegmatch=lpeg.Carg,lpeg.C,lpeg.match
local p_newline=lpeg.patterns.newline
local linewise=(
@@ -7755,10 +8251,11 @@ function logs.application(t)
end
return t
end
-function logs.system(whereto,process,jobname,category,...)
- local message=formatters["%s %s => %s => %s => %s\r"](os.date("%d/%m/%y %H:%m:%S"),process,jobname,category,format(...))
+local f_syslog=formatters["%s %s => %s => %s => %s\r"]
+function logs.system(whereto,process,jobname,category,fmt,arg,...)
+ local message=f_syslog(datetime("%d/%m/%y %H:%m:%S"),process,jobname,category,arg==nil and fmt or format(fmt,arg,...))
for i=1,10 do
- local f=io.open(whereto,"a")
+ local f=openfile(whereto,"a")
if f then
f:write(message)
f:close()
@@ -7820,7 +8317,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["trac-inf"] = package.loaded["trac-inf"] or true
--- original size: 7011, stripped down to: 5590
+-- original size: 6704, stripped down to: 5343
if not modules then modules={} end modules ['trac-inf']={
version=1.001,
@@ -7993,15 +8490,6 @@ function statistics.tracefunction(base,tag,...)
statistics.register(formatters["%s.%s"](tag,name),function() return serialize(stat,"calls") end)
end
end
-commands=commands or {}
-function commands.resettimer(name)
- resettiming(name or "whatever")
- starttiming(name or "whatever")
-end
-function commands.elapsedtime(name)
- stoptiming(name or "whatever")
- context(elapsedtime(name or "whatever"))
-end
end -- of closure
@@ -8568,7 +9056,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-tpl"] = package.loaded["util-tpl"] or true
--- original size: 6251, stripped down to: 3488
+-- original size: 7100, stripped down to: 3978
if not modules then modules={} end modules ['util-tpl']={
version=1.001,
@@ -8610,7 +9098,7 @@ local sqlescape=lpeg.replacer {
{ "\r\n","\\n" },
{ "\r","\\n" },
}
-local sqlquoted=lpeg.Cs(lpeg.Cc("'")*sqlescape*lpeg.Cc("'"))
+local sqlquoted=Cs(Cc("'")*sqlescape*Cc("'"))
lpegpatterns.sqlescape=sqlescape
lpegpatterns.sqlquoted=sqlquoted
local luaescape=lpegpatterns.luaescape
@@ -8633,12 +9121,24 @@ local quotedescapers={
local luaescaper=escapers.lua
local quotedluaescaper=quotedescapers.lua
local function replacekeyunquoted(s,t,how,recurse)
- local escaper=how and escapers[how] or luaescaper
- return escaper(replacekey(s,t,how,recurse))
+ if how==false then
+ return replacekey(s,t,how,recurse)
+ else
+ local escaper=how and escapers[how] or luaescaper
+ return escaper(replacekey(s,t,how,recurse))
+ end
end
local function replacekeyquoted(s,t,how,recurse)
- local escaper=how and quotedescapers[how] or quotedluaescaper
- return escaper(replacekey(s,t,how,recurse))
+ if how==false then
+ return replacekey(s,t,how,recurse)
+ else
+ local escaper=how and quotedescapers[how] or quotedluaescaper
+ return escaper(replacekey(s,t,how,recurse))
+ end
+end
+local function replaceoptional(l,m,r,t,how,recurse)
+ local v=t[l]
+ return v and v~="" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or ""
end
local single=P("%")
local double=P("%%")
@@ -8653,11 +9153,16 @@ local nolquoted=lquoted/''
local norquoted=rquoted/''
local nolquotedq=lquotedq/''
local norquotedq=rquotedq/''
-local key=nosingle*((C((1-nosingle )^1)*Carg(1)*Carg(2)*Carg(3))/replacekey )*nosingle
-local quoted=nolquotedq*((C((1-norquotedq)^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyquoted )*norquotedq
-local unquoted=nolquoted*((C((1-norquoted )^1)*Carg(1)*Carg(2)*Carg(3))/replacekeyunquoted)*norquoted
+local noloptional=P("%?")/''
+local noroptional=P("?%")/''
+local nomoptional=P(":")/''
+local args=Carg(1)*Carg(2)*Carg(3)
+local key=nosingle*((C((1-nosingle )^1)*args)/replacekey )*nosingle
+local quoted=nolquotedq*((C((1-norquotedq )^1)*args)/replacekeyquoted )*norquotedq
+local unquoted=nolquoted*((C((1-norquoted )^1)*args)/replacekeyunquoted)*norquoted
+local optional=noloptional*((C((1-nomoptional)^1)*nomoptional*C((1-noroptional)^1)*args)/replaceoptional)*noroptional
local any=P(1)
- replacer=Cs((unquoted+quoted+escape+key+any)^0)
+ replacer=Cs((unquoted+quoted+escape+optional+key+any)^0)
local function replace(str,mapping,how,recurse)
if mapping and str then
return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str
@@ -8696,7 +9201,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["util-env"] = package.loaded["util-env"] or true
--- original size: 8814, stripped down to: 5092
+-- original size: 8022, stripped down to: 5038
if not modules then modules={} end modules ['util-env']={
version=1.001,
@@ -8707,7 +9212,7 @@ if not modules then modules={} end modules ['util-env']={
}
local allocate,mark=utilities.storage.allocate,utilities.storage.mark
local format,sub,match,gsub,find=string.format,string.sub,string.match,string.gsub,string.find
-local unquoted,quoted=string.unquoted,string.quoted
+local unquoted,quoted,optionalquoted=string.unquoted,string.quoted,string.optionalquoted
local concat,insert,remove=table.concat,table.insert,table.remove
environment=environment or {}
local environment=environment
@@ -8820,24 +9325,14 @@ function environment.splitarguments(separator)
return before,after
end
function environment.reconstructcommandline(arg,noquote)
+ local resolveprefix=resolvers.resolve
arg=arg or environment.originalarguments
if noquote and #arg==1 then
- local a=arg[1]
- a=resolvers.resolve(a)
- a=unquoted(a)
- return a
+ return unquoted(resolveprefix and resolveprefix(arg[1]) or arg[1])
elseif #arg>0 then
local result={}
for i=1,#arg do
- local a=arg[i]
- a=resolvers.resolve(a)
- a=unquoted(a)
- a=gsub(a,'"','\\"')
- if find(a," ",1,true) then
- result[#result+1]=quoted(a)
- else
- result[#result+1]=a
- end
+ result[i]=optionalquoted(resolveprefix and resolveprefix(arg[i]) or resolveprefix)
end
return concat(result," ")
else
@@ -9046,7 +9541,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true
--- original size: 42614, stripped down to: 26694
+-- original size: 43882, stripped down to: 26870
if not modules then modules={} end modules ['lxml-tab']={
version=1.001,
@@ -9061,10 +9556,10 @@ if lpeg.setmaxstack then lpeg.setmaxstack(1000) end
xml=xml or {}
local xml=xml
local concat,remove,insert=table.concat,table.remove,table.insert
-local type,next,setmetatable,getmetatable,tonumber=type,next,setmetatable,getmetatable,tonumber
+local type,next,setmetatable,getmetatable,tonumber,rawset=type,next,setmetatable,getmetatable,tonumber,rawset
local lower,find,match,gsub=string.lower,string.find,string.match,string.gsub
local utfchar=utf.char
-local lpegmatch=lpeg.match
+local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
local P,S,R,C,V,C,Cs=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.C,lpeg.Cs
local formatters=string.formatters
xml.xmlns=xml.xmlns or {}
@@ -9226,9 +9721,10 @@ local function fromdec(s)
return formatters["d:%s"](s),true
end
end
-local rest=(1-P(";"))^0
-local many=P(1)^0
-local parsedentity=P("&")*(P("#x")*(rest/fromhex)+P("#")*(rest/fromdec))*P(";")*P(-1)+(P("#x")*(many/fromhex)+P("#")*(many/fromdec))
+local p_rest=(1-P(";"))^0
+local p_many=P(1)^0
+local p_char=lpegpatterns.utf8character
+local parsedentity=P("&")*(P("#x")*(p_rest/fromhex)+P("#")*(p_rest/fromdec))*P(";")*P(-1)+(P("#x")*(p_many/fromhex)+P("#")*(p_many/fromdec))
local predefined_unified={
[38]="&amp;",
[42]="&quot;",
@@ -9254,7 +9750,9 @@ local privates_u={
local privates_p={}
local privates_n={
}
-local escaped=utf.remapper(privates_u)
+local escaped=utf.remapper(privates_u,"dynamic")
+local unprivatized=utf.remapper(privates_p,"dynamic")
+xml.unprivatized=unprivatized
local function unescaped(s)
local p=privates_n[s]
if not p then
@@ -9267,9 +9765,7 @@ local function unescaped(s)
end
return p
end
-local unprivatized=utf.remapper(privates_p)
xml.privatetoken=unescaped
-xml.unprivatized=unprivatized
xml.privatecodes=privates_n
local function handle_hex_entity(str)
local h=hcache[str]
@@ -9422,7 +9918,7 @@ local valid=R('az','AZ','09')+S('_-.')
local name_yes=C(valid^1)*colon*C(valid^1)
local name_nop=C(P(true))*C(valid^1)
local name=name_yes+name_nop
-local utfbom=lpeg.patterns.utfbom
+local utfbom=lpegpatterns.utfbom
local spacing=C(space^0)
local anyentitycontent=(1-open-semicolon-space-close)^0
local hexentitycontent=R("AF","af","09")^0
@@ -9590,7 +10086,7 @@ local function _xmlconvert_(data,settings)
reported_attribute_errors,mt,errorhandler=nil,nil,nil
return result
end
-function xmlconvert(data,settings)
+local function xmlconvert(data,settings)
local ok,result=pcall(function() return _xmlconvert_(data,settings) end)
if ok then
return result
@@ -9682,14 +10178,17 @@ function xml.checkbom(root)
insert(dt,2,"\n" )
end
end
-local function verbose_element(e,handlers)
+local f_attribute=formatters['%s=%q']
+local function verbose_element(e,handlers,escape)
local handle=handlers.handle
local serialize=handlers.serialize
local ens,etg,eat,edt,ern=e.ns,e.tg,e.at,e.dt,e.rn
local ats=eat and next(eat) and {}
if ats then
+ local n=0
for k,v in next,eat do
- ats[#ats+1]=formatters['%s=%q'](k,escaped(v))
+ n=n+1
+ ats[n]=f_attribute(k,escaped(v))
end
end
if ern and trace_entities and ern~=ens then
@@ -10033,7 +10532,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true
--- original size: 48030, stripped down to: 30595
+-- original size: 48229, stripped down to: 30684
if not modules then modules={} end modules ['lxml-lpt']={
version=1.001,
@@ -10418,8 +10917,8 @@ local lp_builtin=P (
P("ns")/"ll.ns"
)*((spaces*P("(")*spaces*P(")"))/"")
local lp_attribute=(P("@")+P("attribute::"))/""*Cc("(ll.at and ll.at['")*((R("az","AZ")+S("-_:"))^1)*Cc("'])")
-lp_fastpos_p=P("+")^0*R("09")^1*P(-1)/"l==%0"
-lp_fastpos_n=P("-")*R("09")^1*P(-1)/"(%0<0 and (#list+%0==l))"
+local lp_fastpos_p=P("+")^0*R("09")^1*P(-1)/"l==%0"
+local lp_fastpos_n=P("-")*R("09")^1*P(-1)/"(%0<0 and (#list+%0==l))"
local lp_fastpos=lp_fastpos_n+lp_fastpos_p
local lp_reserved=C("and")+C("or")+C("not")+C("div")+C("mod")+C("true")+C("false")
local lp_lua_function=Cs((R("az","AZ","__")^1*(P(".")*R("az","AZ","__")^1)^1)*("("))/"%0"
@@ -10598,7 +11097,7 @@ local function nodesettostring(set,nodetest)
if not ns or ns=="" then ns="*" end
if not tg or tg=="" then tg="*" end
tg=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg)
- t[i]=(directive and tg) or format("not(%s)",tg)
+ t[#t+1]=(directive and tg) or format("not(%s)",tg)
end
if nodetest==false then
return format("not(%s)",concat(t,"|"))
@@ -10864,7 +11363,6 @@ expressions.print=function(...)
print(...)
return true
end
-expressions.contains=find
expressions.find=find
expressions.upper=upper
expressions.lower=lower
@@ -10886,6 +11384,9 @@ function expressions.contains(str,pattern)
end
return false
end
+function xml.expressions.idstring(str)
+ return type(str)=="string" and gsub(str,"^#","") or ""
+end
local function traverse(root,pattern,handle)
local collected=applylpath(root,pattern)
if collected then
@@ -11173,7 +11674,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["lxml-aux"] = package.loaded["lxml-aux"] or true
--- original size: 23804, stripped down to: 16817
+-- original size: 28225, stripped down to: 20125
if not modules then modules={} end modules ['lxml-aux']={
version=1.001,
@@ -11183,16 +11684,19 @@ if not modules then modules={} end modules ['lxml-aux']={
license="see context related readme files"
}
local trace_manipulations=false trackers.register("lxml.manipulations",function(v) trace_manipulations=v end)
+local trace_inclusions=false trackers.register("lxml.inclusions",function(v) trace_inclusions=v end)
local report_xml=logs.reporter("xml")
local xml=xml
-local xmlconvert,xmlcopy,xmlname=xml.convert,xml.copy,xml.name
+local xmlcopy,xmlname=xml.copy,xml.name
local xmlinheritedconvert=xml.inheritedconvert
local xmlapplylpath=xml.applylpath
local xmlfilter=xml.filter
-local type,setmetatable,getmetatable=type,setmetatable,getmetatable
+local type,next,setmetatable,getmetatable=type,next,setmetatable,getmetatable
local insert,remove,fastcopy,concat=table.insert,table.remove,table.fastcopy,table.concat
local gmatch,gsub,format,find,strip=string.gmatch,string.gsub,string.format,string.find,string.strip
local utfbyte=utf.byte
+local lpegmatch=lpeg.match
+local striplinepatterns=utilities.strings.striplinepatterns
local function report(what,pattern,c,e)
report_xml("%s element %a, root %a, position %a, index %a, pattern %a",what,xmlname(e),xmlname(e.__p__),c,e.ni,pattern)
end
@@ -11247,13 +11751,15 @@ end
function xml.each(root,pattern,handle,reverse)
local collected=xmlapplylpath(root,pattern)
if collected then
- if reverse then
- for c=#collected,1,-1 do
- handle(collected[c])
- end
- else
- for c=1,#collected do
- handle(collected[c])
+ if handle then
+ if reverse then
+ for c=#collected,1,-1 do
+ handle(collected[c])
+ end
+ else
+ for c=1,#collected do
+ handle(collected[c])
+ end
end
end
return collected
@@ -11309,6 +11815,7 @@ local function redo_ni(d)
end
end
end
+xml.reindex=redo_ni
local function xmltoelement(whatever,root)
if not whatever then
return nil
@@ -11360,8 +11867,16 @@ function xml.delete(root,pattern)
report('deleting',pattern,c,e)
end
local d=p.dt
- remove(d,e.ni)
- redo_ni(d)
+ local ni=e.ni
+ if ni<=#d then
+ if false then
+ p.dt[ni]=""
+ else
+ remove(d,ni)
+ redo_ni(d)
+ end
+ else
+ end
end
end
end
@@ -11481,28 +11996,40 @@ xml.insertafter=insert_element
xml.insertbefore=function(r,p,e) insert_element(r,p,e,true) end
xml.injectafter=inject_element
xml.injectbefore=function(r,p,e) inject_element(r,p,e,true) end
-local function include(xmldata,pattern,attribute,recursive,loaddata)
+local function include(xmldata,pattern,attribute,recursive,loaddata,level)
pattern=pattern or 'include'
loaddata=loaddata or io.loaddata
local collected=xmlapplylpath(xmldata,pattern)
if collected then
+ if not level then
+ level=1
+ end
for c=1,#collected do
local ek=collected[c]
local name=nil
local ekdt=ek.dt
local ekat=ek.at
- local epdt=ek.__p__.dt
+ local ekrt=ek.__p__
+ local epdt=ekrt.dt
if not attribute or attribute=="" then
name=(type(ekdt)=="table" and ekdt[1]) or ekdt
end
if not name then
for a in gmatch(attribute or "href","([^|]+)") do
name=ekat[a]
- if name then break end
+ if name then
+ break
+ end
+ end
+ end
+ local data=nil
+ if name and name~="" then
+ data=loaddata(name) or ""
+ if trace_inclusions then
+ report_xml("including %s bytes from %a at level %s by pattern %a and attribute %a (%srecursing)",#data,name,level,pattern,attribute or "",recursive and "" or "not ")
end
end
- local data=(name and name~="" and loaddata(name)) or ""
- if data=="" then
+ if not data or data=="" then
epdt[ek.ni]=""
elseif ekat["parse"]=="text" then
epdt[ek.ni]=xml.escaped(data)
@@ -11512,70 +12039,113 @@ local function include(xmldata,pattern,attribute,recursive,loaddata)
epdt[ek.ni]=""
else
if recursive then
- include(xi,pattern,attribute,recursive,loaddata)
+ include(xi,pattern,attribute,recursive,loaddata,level+1)
+ end
+ local child=xml.body(xi)
+ child.__p__=ekrt
+ child.__f__=name
+ epdt[ek.ni]=child
+ local inclusions=xmldata.settings.inclusions
+ if inclusions then
+ inclusions[#inclusions+1]=name
+ else
+ xmldata.settings.inclusions={ name }
end
- epdt[ek.ni]=xml.body(xi)
end
end
end
end
end
xml.include=include
+function xml.inclusion(e,default)
+ while e do
+ local f=e.__f__
+ if f then
+ return f
+ else
+ e=e.__p__
+ end
+ end
+ return default
+end
+function xml.inclusions(e,sorted)
+ while e do
+ local settings=e.settings
+ if settings then
+ local inclusions=settings.inclusions
+ if inclusions then
+ inclusions=table.unique(inclusions)
+ if sorted then
+ table.sort(inclusions)
+ end
+ return inclusions
+ else
+ e=e.__p__
+ end
+ else
+ e=e.__p__
+ end
+ end
+end
+local b_collapser=lpeg.patterns.b_collapser
+local m_collapser=lpeg.patterns.m_collapser
+local e_collapser=lpeg.patterns.e_collapser
+local b_stripper=lpeg.patterns.b_stripper
+local m_stripper=lpeg.patterns.m_stripper
+local e_stripper=lpeg.patterns.e_stripper
+local lpegmatch=lpeg.match
local function stripelement(e,nolines,anywhere)
local edt=e.dt
if edt then
- if anywhere then
- local t,n={},0
- for e=1,#edt do
+ local n=#edt
+ if n==0 then
+ return e
+ elseif anywhere then
+ local t={}
+ local m=0
+ for e=1,n do
local str=edt[e]
if type(str)~="string" then
- n=n+1
- t[n]=str
+ m=m+1
+ t[m]=str
elseif str~="" then
if nolines then
- str=gsub(str,"%s+"," ")
+ str=lpegmatch((n==1 and b_collapser) or (n==m and e_collapser) or m_collapser,str)
+ else
+ str=lpegmatch((n==1 and b_stripper) or (n==m and e_stripper) or m_stripper,str)
end
- str=gsub(str,"^%s*(.-)%s*$","%1")
if str~="" then
- n=n+1
- t[n]=str
+ m=m+1
+ t[m]=str
end
end
end
e.dt=t
else
- if #edt>0 then
- local str=edt[1]
- if type(str)~="string" then
- elseif str=="" then
+ local str=edt[1]
+ if type(str)=="string" then
+ if str~="" then
+ str=lpegmatch(nolines and b_collapser or b_stripper,str)
+ end
+ if str=="" then
remove(edt,1)
+ n=n-1
else
- if nolines then
- str=gsub(str,"%s+"," ")
- end
- str=gsub(str,"^%s+","")
- if str=="" then
- remove(edt,1)
- else
- edt[1]=str
- end
+ edt[1]=str
end
end
- local nedt=#edt
- if nedt>0 then
- local str=edt[nedt]
- if type(str)~="string" then
- elseif str=="" then
- remove(edt)
- else
- if nolines then
- str=gsub(str,"%s+"," ")
- end
- str=gsub(str,"%s+$","")
+ if n>0 then
+ str=edt[n]
+ if type(str)=="string" then
if str=="" then
remove(edt)
else
- edt[nedt]=str
+ str=lpegmatch(nolines and e_collapser or e_stripper,str)
+ if str=="" then
+ remove(edt)
+ else
+ edt[n]=str
+ end
end
end
end
@@ -11761,8 +12331,8 @@ function xml.finalizers.xml.cdata(collected)
end
return ""
end
-function xml.insertcomment(e,str,n)
- table.insert(e.dt,n or 1,{
+function xml.insertcomment(e,str,n)
+ insert(e.dt,n or 1,{
tg="@cm@",
ns="",
special=true,
@@ -11770,7 +12340,25 @@ function xml.insertcomment(e,str,n)
dt={ str },
})
end
-function xml.setcdata(e,str)
+function xml.insertcdata(e,str,n)
+ insert(e.dt,n or 1,{
+ tg="@cd@",
+ ns="",
+ special=true,
+ at={},
+ dt={ str },
+ })
+end
+function xml.setcomment(e,str,n)
+ e.dt={ {
+ tg="@cm@",
+ ns="",
+ special=true,
+ at={},
+ dt={ str },
+ } }
+end
+function xml.setcdata(e,str)
e.dt={ {
tg="@cd@",
ns="",
@@ -11840,7 +12428,7 @@ local function recurse(e,action)
for i=1,#edt do
local str=edt[i]
if type(str)~="string" then
- recurse(str,action,recursive)
+ recurse(str,action)
elseif str~="" then
edt[i]=action(str)
end
@@ -11858,6 +12446,65 @@ function helpers.recursetext(collected,action,recursive)
end
end
end
+local specials={
+ ["@rt@"]="root",
+ ["@pi@"]="instruction",
+ ["@cm@"]="comment",
+ ["@dt@"]="declaration",
+ ["@cd@"]="cdata",
+}
+local function convert(x,strip,flat)
+ local ns=x.ns
+ local tg=x.tg
+ local at=x.at
+ local dt=x.dt
+ local node=flat and {
+ [0]=(not x.special and (ns~="" and ns..":"..tg or tg)) or nil,
+ } or {
+ _namespace=ns~="" and ns or nil,
+ _tag=not x.special and tg or nil,
+ _type=specials[tg] or "_element",
+ }
+ if at then
+ for k,v in next,at do
+ node[k]=v
+ end
+ end
+ local n=0
+ for i=1,#dt do
+ local di=dt[i]
+ if type(di)=="table" then
+ if flat and di.special then
+ else
+ di=convert(di,strip,flat)
+ if di then
+ n=n+1
+ node[n]=di
+ end
+ end
+ elseif strip then
+ di=lpegmatch(strip,di)
+ if di~="" then
+ n=n+1
+ node[n]=di
+ end
+ else
+ n=n+1
+ node[n]=di
+ end
+ end
+ if next(node) then
+ return node
+ end
+end
+function xml.totable(x,strip,flat)
+ if type(x)=="table" then
+ if strip then
+ strip=striplinepatterns[strip]
+ end
+ return convert(x,strip,flat)
+ end
+end
end -- of closure
@@ -12414,7 +13061,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-ini"] = package.loaded["data-ini"] or true
--- original size: 7927, stripped down to: 5528
+-- original size: 11085, stripped down to: 7662
if not modules then modules={} end modules ['data-ini']={
version=1.001,
@@ -12423,14 +13070,15 @@ if not modules then modules={} end modules ['data-ini']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files",
}
+local next,type,getmetatable,rawset=next,type,getmetatable,rawset
local gsub,find,gmatch,char=string.gsub,string.find,string.gmatch,string.char
-local next,type=next,type
local filedirname,filebasename,filejoin=file.dirname,file.basename,file.join
+local ostype,osname,osuname,ossetenv,osgetenv=os.type,os.name,os.uname,os.setenv,os.getenv
+local P,S,R,C,Cs,Cc,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.match
local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
local trace_detail=false trackers.register("resolvers.details",function(v) trace_detail=v end)
local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
local report_initialization=logs.reporter("resolvers","initialization")
-local ostype,osname,ossetenv,osgetenv=os.type,os.name,os.setenv,os.getenv
resolvers=resolvers or {}
local resolvers=resolvers
texconfig.kpse_init=false
@@ -12563,10 +13211,103 @@ if type(profiler)=="table" and not jit then
profiler.start("luatex-profile.log")
end)
end
-if not resolvers.resolve then
- function resolvers.resolve (s) return s end
- function resolvers.unresolve(s) return s end
- function resolvers.repath (s) return s end
+local prefixes=utilities.storage.allocate()
+resolvers.prefixes=prefixes
+local resolved={}
+local abstract={}
+local dynamic={}
+function resolvers.resetresolve(str)
+ resolved,abstract={},{}
+end
+function resolvers.allprefixes(separator)
+ local all=table.sortedkeys(prefixes)
+ if separator then
+ for i=1,#all do
+ all[i]=all[i]..":"
+ end
+ end
+ return all
+end
+local function _resolve_(method,target)
+ local action=prefixes[method]
+ if action then
+ return action(target)
+ else
+ return method..":"..target
+ end
+end
+function resolvers.unresolve(str)
+ return abstract[str] or str
+end
+function resolvers.setdynamic(str)
+ dynamic[str]=true
+end
+local pattern=Cs((C(R("az")^2)*P(":")*C((1-S(" \"\';,"))^1)/_resolve_+P(1))^0)
+local prefix=C(R("az")^2)*P(":")
+local target=C((1-S(" \"\';,"))^1)
+local notarget=(#S(";,")+P(-1))*Cc("")
+local p_resolve=Cs(((prefix*(target+notarget))/_resolve_+P(1))^0)
+local p_simple=prefix*P(-1)
+local function resolve(str)
+ if type(str)=="table" then
+ local res={}
+ for i=1,#str do
+ res[i]=resolve(str[i])
+ end
+ return res
+ end
+ local res=resolved[str]
+ if res then
+ return res
+ end
+ local simple=lpegmatch(p_simple,str)
+ local action=prefixes[simple]
+ if action then
+ local res=action(res)
+ if not dynamic[simple] then
+ resolved[simple]=res
+ abstract[res]=simple
+ end
+ return res
+ end
+ res=lpegmatch(p_resolve,str)
+ resolved[str]=res
+ abstract[res]=str
+ return res
+end
+resolvers.resolve=resolve
+if type(osuname)=="function" then
+ for k,v in next,osuname() do
+ if not prefixes[k] then
+ prefixes[k]=function() return v end
+ end
+ end
+end
+if ostype=="unix" then
+ local pattern
+ local function makepattern(t,k,v)
+ if t then
+ rawset(t,k,v)
+ end
+ local colon=P(":")
+ for k,v in table.sortedpairs(prefixes) do
+ if p then
+ p=P(k)+p
+ else
+ p=P(k)
+ end
+ end
+ pattern=Cs((p*colon+colon/";"+P(1))^0)
+ end
+ makepattern()
+ table.setmetatablenewindex(prefixes,makepattern)
+ function resolvers.repath(str)
+ return lpegmatch(pattern,str)
+ end
+else
+ function resolvers.repath(str)
+ return str
+ end
end
@@ -12576,7 +13317,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-exp"] = package.loaded["data-exp"] or true
--- original size: 15317, stripped down to: 9723
+-- original size: 17216, stripped down to: 10657
if not modules then modules={} end modules ['data-exp']={
version=1.001,
@@ -12590,12 +13331,16 @@ local concat,sort=table.concat,table.sort
local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns
local Ct,Cs,Cc,Carg,P,C,S=lpeg.Ct,lpeg.Cs,lpeg.Cc,lpeg.Carg,lpeg.P,lpeg.C,lpeg.S
local type,next=type,next
+local isdir=lfs.isdir
local ostype=os.type
-local collapsepath=file.collapsepath
+local collapsepath,joinpath,basename=file.collapsepath,file.join,file.basename
local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
local trace_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end)
+local trace_globbing=true trackers.register("resolvers.globbing",function(v) trace_globbing=v end)
local report_expansions=logs.reporter("resolvers","expansions")
+local report_globbing=logs.reporter("resolvers","globbing")
local resolvers=resolvers
+local resolveprefix=resolvers.resolve
local function f_both(a,b)
local t,n={},0
for sb in gmatch(b,"[^,]+") do
@@ -12685,35 +13430,27 @@ function resolvers.expandedpathfromlist(pathlist)
end
return newlist
end
-local cleanup=lpeg.replacer {
- { "!","" },
- { "\\","/" },
-}
-function resolvers.cleanpath(str)
- local doslashes=(P("\\")/"/"+1)^0
- local donegation=(P("!")/"" )^0
- local homedir=lpegmatch(Cs(donegation*doslashes),environment.homedir or "")
- if homedir=="~" or homedir=="" or not lfs.isdir(homedir) then
- if trace_expansions then
- report_expansions("no home dir set, ignoring dependent paths")
- end
- function resolvers.cleanpath(str)
- if not str or find(str,"~",1,true) then
- return ""
- else
- return lpegmatch(cleanup,str)
+local usedhomedir=nil
+local donegation=(P("!")/"" )^0
+local doslashes=(P("\\")/"/"+1)^0
+local function expandedhome()
+ if not usedhomedir then
+ usedhomedir=lpegmatch(Cs(donegation*doslashes),environment.homedir or "")
+ if usedhomedir=="~" or usedhomedir=="" or not isdir(usedhomedir) then
+ if trace_expansions then
+ report_expansions("no home dir set, ignoring dependent path using current path")
end
- end
- else
- local dohome=((P("~")+P("$HOME"))/homedir)^0
- local cleanup=Cs(donegation*dohome*doslashes)
- function resolvers.cleanpath(str)
- return str and lpegmatch(cleanup,str) or ""
+ usedhomedir="."
end
end
- return resolvers.cleanpath(str)
+ return usedhomedir
+end
+local dohome=((P("~")+P("$HOME")+P("%HOME%"))/expandedhome)^0
+local cleanup=Cs(donegation*dohome*doslashes)
+resolvers.cleanpath=function(str)
+ return str and lpegmatch(cleanup,str) or ""
end
-local expandhome=P("~")/"$HOME"
+local expandhome=P("~")/"$HOME"
local dodouble=P('"')/""*(expandhome+(1-P('"')))^0*P('"')/""
local dosingle=P("'")/""*(expandhome+(1-P("'")))^0*P("'")/""
local dostring=(expandhome+1 )^0
@@ -12765,46 +13502,67 @@ function resolvers.splitpath(str)
end
function resolvers.joinpath(str)
if type(str)=='table' then
- return file.joinpath(str)
+ return joinpath(str)
else
return str
end
end
local attributes,directory=lfs.attributes,lfs.dir
local weird=P(".")^1+lpeg.anywhere(S("~`!#$%^&*()={}[]:;\"\'||<>,?\n\r\t"))
+local lessweird=P(".")^1+lpeg.anywhere(S("~`#$%^&*:;\"\'||<>,?\n\r\t"))
local timer={}
local scanned={}
local nofscans=0
local scancache={}
-local function scan(files,spec,path,n,m,r)
- local full=(path=="" and spec) or (spec..path..'/')
+local fullcache={}
+local nofsharedscans=0
+local function scan(files,remap,spec,path,n,m,r,onlyone,tolerant)
+ local full=path=="" and spec or (spec..path..'/')
local dirs={}
local nofdirs=0
+ local pattern=tolerant and lessweird or weird
for name in directory(full) do
- if not lpegmatch(weird,name) then
- local mode=attributes(full..name,'mode')
- if mode=='file' then
+ if not lpegmatch(pattern,name) then
+ local mode=attributes(full..name,"mode")
+ if mode=="file" then
n=n+1
- local f=files[name]
- if f then
- if type(f)=='string' then
- files[name]={ f,path }
+ local lower=lower(name)
+ local paths=files[lower]
+ if paths then
+ if onlyone then
else
- f[#f+1]=path
+ if type(paths)=="string" then
+ files[lower]={ paths,path }
+ else
+ paths[#paths+1]=path
+ end
+ if name~=lower then
+ local rl=remap[lower]
+ if not rl then
+ remap[lower]=name
+ r=r+1
+ elseif trace_globbing and rl~=name then
+ report_globbing("confusing filename, name: %a, lower: %a, already: %a",name,lower,rl)
+ end
+ end
end
else
- files[name]=path
- local lower=lower(name)
+ files[lower]=path
if name~=lower then
- files["remap:"..lower]=name
- r=r+1
+ local rl=remap[lower]
+ if not rl then
+ remap[lower]=name
+ r=r+1
+ elseif trace_globbing and rl~=name then
+ report_globbing("confusing filename, name: %a, lower: %a, already: %a",name,lower,rl)
+ end
end
end
- elseif mode=='directory' then
+ elseif mode=="directory" then
m=m+1
nofdirs=nofdirs+1
if path~="" then
- dirs[nofdirs]=path..'/'..name
+ dirs[nofdirs]=path.."/"..name
else
dirs[nofdirs]=name
end
@@ -12814,107 +13572,69 @@ local function scan(files,spec,path,n,m,r)
if nofdirs>0 then
sort(dirs)
for i=1,nofdirs do
- files,n,m,r=scan(files,spec,dirs[i],n,m,r)
+ files,remap,n,m,r=scan(files,remap,spec,dirs[i],n,m,r,onlyonce,tolerant)
end
end
scancache[sub(full,1,-2)]=files
- return files,n,m,r
+ return files,remap,n,m,r
end
-local fullcache={}
-function resolvers.scanfiles(path,branch,usecache)
- statistics.starttiming(timer)
- local realpath=resolvers.resolve(path)
+function resolvers.scanfiles(path,branch,usecache,onlyonce,tolerant)
+ local realpath=resolveprefix(path)
if usecache then
- local files=fullcache[realpath]
- if files then
+ local content=fullcache[realpath]
+ if content then
if trace_locating then
- report_expansions("using caches scan of path %a, branch %a",path,branch or path)
+ report_expansions("using cached scan of path %a, branch %a",path,branch or path)
end
- return files
+ nofsharedscans=nofsharedscans+1
+ return content
end
end
+ statistics.starttiming(timer)
if trace_locating then
report_expansions("scanning path %a, branch %a",path,branch or path)
end
- local files,n,m,r=scan({},realpath..'/',"",0,0,0)
- files.__path__=path
- files.__files__=n
- files.__directories__=m
- files.__remappings__=r
- if trace_locating then
- report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
- end
- if usecache then
- scanned[#scanned+1]=realpath
- fullcache[realpath]=files
- end
- nofscans=nofscans+1
- statistics.stoptiming(timer)
- return files
-end
-local function simplescan(files,spec,path)
- local full=(path=="" and spec) or (spec..path..'/')
- local dirs={}
- local nofdirs=0
- for name in directory(full) do
- if not lpegmatch(weird,name) then
- local mode=attributes(full..name,'mode')
- if mode=='file' then
- if not files[name] then
- files[name]=path
- end
- elseif mode=='directory' then
- nofdirs=nofdirs+1
- if path~="" then
- dirs[nofdirs]=path..'/'..name
- else
- dirs[nofdirs]=name
- end
- end
- end
- end
- if nofdirs>0 then
- sort(dirs)
- for i=1,nofdirs do
- files=simplescan(files,spec,dirs[i])
- end
- end
- return files
-end
-local simplecache={}
-local nofsharedscans=0
-function resolvers.simplescanfiles(path,branch,usecache)
- statistics.starttiming(timer)
- local realpath=resolvers.resolve(path)
- if usecache then
- local files=simplecache[realpath]
- if not files then
- files=scancache[realpath]
- if files then
- nofsharedscans=nofsharedscans+1
- end
+ local content
+ if isdir(realpath) then
+ local files,remap,n,m,r=scan({},{},realpath..'/',"",0,0,0,onlyonce,tolerant)
+ content={
+ metadata={
+ path=path,
+ files=n,
+ directories=m,
+ remappings=r,
+ },
+ files=files,
+ remap=remap,
+ }
+ if trace_locating then
+ report_expansions("%s files found on %s directories with %s uppercase remappings",n,m,r)
end
- if files then
- if trace_locating then
- report_expansions("using caches scan of path %a, branch %a",path,branch or path)
- end
- return files
+ else
+ content={
+ metadata={
+ path=path,
+ files=0,
+ directories=0,
+ remappings=0,
+ },
+ files={},
+ remap={},
+ }
+ if trace_locating then
+ report_expansions("invalid path %a",realpath)
end
end
- if trace_locating then
- report_expansions("scanning path %a, branch %a",path,branch or path)
- end
- local files=simplescan({},realpath..'/',"")
- if trace_locating then
- report_expansions("%s files found",table.count(files))
- end
if usecache then
scanned[#scanned+1]=realpath
- simplecache[realpath]=files
+ fullcache[realpath]=content
end
nofscans=nofscans+1
statistics.stoptiming(timer)
- return files
+ return content
+end
+function resolvers.simplescanfiles(path,branch,usecache)
+ return resolvers.scanfiles(path,branch,usecache,true,true)
end
function resolvers.scandata()
table.sort(scanned)
@@ -12925,6 +13645,52 @@ function resolvers.scandata()
paths=scanned,
}
end
+function resolvers.get_from_content(content,path,name)
+ if not content then
+ return
+ end
+ local files=content.files
+ if not files then
+ return
+ end
+ local remap=content.remap
+ if not remap then
+ return
+ end
+ if name then
+ local used=lower(name)
+ return path,remap[used] or used
+ else
+ local name=path
+ local used=lower(name)
+ local path=files[used]
+ if path then
+ return path,remap[used] or used
+ end
+ end
+end
+local nothing=function() end
+function resolvers.filtered_from_content(content,pattern)
+ if content and type(pattern)=="string" then
+ local pattern=lower(pattern)
+ local files=content.files
+ local remap=content.remap
+ if files and remap then
+ local n=next(files)
+ local function iterator()
+ while n do
+ local k=n
+ n=next(files,k)
+ if find(k,pattern) then
+ return files[k],remap and remap[k] or k
+ end
+ end
+ end
+ return iterator
+ end
+ end
+ return nothing
+end
end -- of closure
@@ -12933,7 +13699,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-env"] = package.loaded["data-env"] or true
--- original size: 8769, stripped down to: 6490
+-- original size: 9216, stripped down to: 6798
if not modules then modules={} end modules ['data-env']={
version=1.001,
@@ -12951,10 +13717,12 @@ local formats=allocate()
local suffixes=allocate()
local dangerous=allocate()
local suffixmap=allocate()
+local usertypes=allocate()
resolvers.formats=formats
resolvers.suffixes=suffixes
resolvers.dangerous=dangerous
resolvers.suffixmap=suffixmap
+resolvers.usertypes=usertypes
local luasuffixes=utilities.lua.suffixes
local relations=allocate {
core={
@@ -13022,11 +13790,13 @@ local relations=allocate {
names={ "mp" },
variable='MPINPUTS',
suffixes={ 'mp','mpvi','mpiv','mpii' },
+ usertype=true,
},
tex={
names={ "tex" },
variable='TEXINPUTS',
- suffixes={ 'tex',"mkvi","mkiv","mkii" },
+ suffixes={ "tex","mkvi","mkiv","mkii","cld","lfg","xml" },
+ usertype=true,
},
icc={
names={ "icc","icc profile","icc profiles" },
@@ -13042,6 +13812,7 @@ local relations=allocate {
names={ "lua" },
variable='LUAINPUTS',
suffixes={ luasuffixes.lua,luasuffixes.luc,luasuffixes.tma,luasuffixes.tmc },
+ usertype=true,
},
lib={
names={ "lib" },
@@ -13050,11 +13821,15 @@ local relations=allocate {
},
bib={
names={ 'bib' },
+ variable='BIBINPUTS',
suffixes={ 'bib' },
+ usertype=true,
},
bst={
names={ 'bst' },
+ variable='BSTINPUTS',
suffixes={ 'bst' },
+ usertype=true,
},
fontconfig={
names={ 'fontconfig','fontconfig file','fontconfig files' },
@@ -13136,8 +13911,9 @@ function resolvers.updaterelations()
for name,relation in next,categories do
local rn=relation.names
local rv=relation.variable
- local rs=relation.suffixes
if rn and rv then
+ local rs=relation.suffixes
+ local ru=relation.usertype
for i=1,#rn do
local rni=lower(gsub(rn[i]," ",""))
formats[rni]=rv
@@ -13149,8 +13925,9 @@ function resolvers.updaterelations()
end
end
end
- end
- if rs then
+ if ru then
+ usertypes[name]=true
+ end
end
end
end
@@ -13201,7 +13978,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-tmp"] = package.loaded["data-tmp"] or true
--- original size: 15532, stripped down to: 11648
+-- original size: 15681, stripped down to: 11761
if not modules then modules={} end modules ['data-tmp']={
version=1.100,
@@ -13220,6 +13997,7 @@ local trace_cache=false trackers.register("resolvers.cache",function(v) trace_ca
local report_caches=logs.reporter("resolvers","caches")
local report_resolvers=logs.reporter("resolvers","caching")
local resolvers=resolvers
+local cleanpath=resolvers.cleanpath
local directive_cleanup=false directives.register("system.compile.cleanup",function(v) directive_cleanup=v end)
local directive_strip=false directives.register("system.compile.strip",function(v) directive_strip=v end)
local compile=utilities.lua.compile
@@ -13241,7 +14019,7 @@ caches.relocate=false
caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" }
local writable,readables,usedreadables=nil,{},{}
local function identify()
- local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE")
+ local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE")
if texmfcaches then
for k=1,#texmfcaches do
local cachepath=texmfcaches[k]
@@ -13495,10 +14273,12 @@ local content_state={}
function caches.contentstate()
return content_state or {}
end
-function caches.loadcontent(cachename,dataname)
- local name=caches.hashed(cachename)
- local full,path=caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
- local filename=file.join(path,name)
+function caches.loadcontent(cachename,dataname,filename)
+ if not filename then
+ local name=caches.hashed(cachename)
+ local full,path=caches.getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees")
+ filename=file.join(path,name)
+ end
local blob=loadfile(addsuffix(filename,luasuffixes.luc)) or loadfile(addsuffix(filename,luasuffixes.lua))
if blob then
local data=blob()
@@ -13530,10 +14310,12 @@ function caches.collapsecontent(content)
end
end
end
-function caches.savecontent(cachename,dataname,content)
- local name=caches.hashed(cachename)
- local full,path=caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
- local filename=file.join(path,name)
+function caches.savecontent(cachename,dataname,content,filename)
+ if not filename then
+ local name=caches.hashed(cachename)
+ local full,path=caches.setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees")
+ filename=file.join(path,name)
+ end
local luaname=addsuffix(filename,luasuffixes.lua)
local lucname=addsuffix(filename,luasuffixes.luc)
if trace_locating then
@@ -13576,7 +14358,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-met"] = package.loaded["data-met"] or true
--- original size: 5460, stripped down to: 4014
+-- original size: 5347, stripped down to: 4015
if not modules then modules={} end modules ['data-met']={
version=1.100,
@@ -13604,7 +14386,7 @@ local function splitmethod(filename)
if type(filename)=="table" then
return filename
end
- filename=file.collapsepath(filename,".")
+ filename=file.collapsepath(filename,".")
if not find(filename,"://",1,true) then
return { scheme="file",path=filename,original=filename,filename=filename }
end
@@ -13695,7 +14477,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-res"] = package.loaded["data-res"] or true
--- original size: 62045, stripped down to: 43116
+-- original size: 67003, stripped down to: 46291
if not modules then modules={} end modules ['data-res']={
version=1.001,
@@ -13705,7 +14487,7 @@ if not modules then modules={} end modules ['data-res']={
license="see context related readme files",
}
local gsub,find,lower,upper,match,gmatch=string.gsub,string.find,string.lower,string.upper,string.match,string.gmatch
-local concat,insert,sortedkeys=table.concat,table.insert,table.sortedkeys
+local concat,insert,remove,sortedkeys,sortedhash=table.concat,table.insert,table.remove,table.sortedkeys,table.sortedhash
local next,type,rawget=next,type,rawget
local os=os
local P,S,R,C,Cc,Cs,Ct,Carg=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Carg
@@ -13714,17 +14496,23 @@ local formatters=string.formatters
local filedirname=file.dirname
local filebasename=file.basename
local suffixonly=file.suffixonly
+local addsuffix=file.addsuffix
+local removesuffix=file.removesuffix
local filejoin=file.join
local collapsepath=file.collapsepath
local joinpath=file.joinpath
+local is_qualified_path=file.is_qualified_path
local allocate=utilities.storage.allocate
local settings_to_array=utilities.parsers.settings_to_array
+local getcurrentdir=lfs.currentdir
+local isfile=lfs.isfile
+local isdir=lfs.isdir
local setmetatableindex=table.setmetatableindex
local luasuffixes=utilities.lua.suffixes
-local getcurrentdir=lfs.currentdir
local trace_locating=false trackers .register("resolvers.locating",function(v) trace_locating=v end)
local trace_detail=false trackers .register("resolvers.details",function(v) trace_detail=v end)
local trace_expansions=false trackers .register("resolvers.expansions",function(v) trace_expansions=v end)
+local trace_paths=false trackers .register("resolvers.paths",function(v) trace_paths=v end)
local resolve_otherwise=true directives.register("resolvers.otherwise",function(v) resolve_otherwise=v end)
local report_resolving=logs.reporter("resolvers","resolving")
local resolvers=resolvers
@@ -13732,10 +14520,14 @@ local expandedpathfromlist=resolvers.expandedpathfromlist
local checkedvariable=resolvers.checkedvariable
local splitconfigurationpath=resolvers.splitconfigurationpath
local methodhandler=resolvers.methodhandler
+local filtered=resolvers.filtered_from_content
+local lookup=resolvers.get_from_content
+local cleanpath=resolvers.cleanpath
+local resolveprefix=resolvers.resolve
local initializesetter=utilities.setters.initialize
local ostype,osname,osenv,ossetenv,osgetenv=os.type,os.name,os.env,os.setenv,os.getenv
-resolvers.cacheversion='1.0.1'
-resolvers.configbanner=''
+resolvers.cacheversion="1.100"
+resolvers.configbanner=""
resolvers.homedir=environment.homedir
resolvers.criticalvars=allocate { "SELFAUTOLOC","SELFAUTODIR","SELFAUTOPARENT","TEXMFCNF","TEXMF","TEXOS" }
resolvers.luacnfname="texmfcnf.lua"
@@ -13754,6 +14546,7 @@ end
local unset_variable="unset"
local formats=resolvers.formats
local suffixes=resolvers.suffixes
+local usertypes=resolvers.usertypes
local dangerous=resolvers.dangerous
local suffixmap=resolvers.suffixmap
resolvers.defaultsuffixes={ "tex" }
@@ -13762,7 +14555,7 @@ local instance=resolvers.instance or nil
function resolvers.setenv(key,value,raw)
if instance then
instance.environment[key]=value
- ossetenv(key,raw and value or resolvers.resolve(value))
+ ossetenv(key,raw and value or resolveprefix(value))
end
end
local function getenv(key)
@@ -13776,7 +14569,7 @@ local function getenv(key)
end
resolvers.getenv=getenv
resolvers.env=getenv
-local function resolve(k)
+local function resolvevariable(k)
return instance.expansions[k]
end
local dollarstripper=lpeg.stripper("$")
@@ -13785,19 +14578,19 @@ local backslashswapper=lpeg.replacer("\\","/")
local somevariable=P("$")/""
local somekey=C(R("az","AZ","09","__","--")^1)
local somethingelse=P(";")*((1-S("!{}/\\"))^1*P(";")/"")+P(";")*(P(";")/"")+P(1)
-local variableexpander=Cs((somevariable*(somekey/resolve)+somethingelse)^1 )
+local variableexpander=Cs((somevariable*(somekey/resolvevariable)+somethingelse)^1 )
local cleaner=P("\\")/"/"+P(";")*S("!{}/\\")^0*P(";")^1/";"
local variablecleaner=Cs((cleaner+P(1))^0)
-local somevariable=R("az","AZ","09","__","--")^1/resolve
+local somevariable=R("az","AZ","09","__","--")^1/resolvevariable
local variable=(P("$")/"")*(somevariable+(P("{")/"")*somevariable*(P("}")/""))
local variableresolver=Cs((variable+P(1))^0)
local function expandedvariable(var)
return lpegmatch(variableexpander,var) or var
end
-function resolvers.newinstance()
- if trace_locating then
+function resolvers.newinstance()
+ if trace_locating then
report_resolving("creating instance")
- end
+ end
local environment,variables,expansions,order=allocate(),allocate(),allocate(),allocate()
local newinstance={
environment=environment,
@@ -13810,6 +14603,7 @@ function resolvers.newinstance()
foundintrees=allocate(),
hashes=allocate(),
hashed=allocate(),
+ pathlists=false,
specification=allocate(),
lists=allocate(),
data=allocate(),
@@ -13822,6 +14616,7 @@ function resolvers.newinstance()
savelists=true,
pattern=nil,
force_suffixes=true,
+ pathstack={},
}
setmetatableindex(variables,function(t,k)
local v
@@ -13871,8 +14666,13 @@ function resolvers.reset()
end
local function reset_hashes()
instance.lists={}
+ instance.pathlists=false
instance.found={}
end
+local function reset_caches()
+ instance.lists={}
+ instance.pathlists=false
+end
local slash=P("/")
local pathexpressionpattern=Cs (
Cc("^")*(
@@ -13924,13 +14724,13 @@ local function identify_configuration_files()
for i=1,#cnfpaths do
local filepath=cnfpaths[i]
local filename=collapsepath(filejoin(filepath,luacnfname))
- local realname=resolvers.resolve(filename)
+ local realname=resolveprefix(filename)
if trace_locating then
- local fullpath=gsub(resolvers.resolve(collapsepath(filepath)),"//","/")
+ local fullpath=gsub(resolveprefix(collapsepath(filepath)),"//","/")
local weirdpath=find(fullpath,"/texmf.+/texmf") or not find(fullpath,"/web2c",1,true)
report_resolving("looking for %a on %s path %a from specification %a",luacnfname,weirdpath and "weird" or "given",fullpath,filepath)
end
- if lfs.isfile(realname) then
+ if isfile(realname) then
specification[#specification+1]=filename
if trace_locating then
report_resolving("found configuration file %a",realname)
@@ -13952,7 +14752,7 @@ local function load_configuration_files()
local filename=specification[i]
local pathname=filedirname(filename)
local filename=filejoin(pathname,luacnfname)
- local realname=resolvers.resolve(filename)
+ local realname=resolveprefix(filename)
local blob=loadfile(realname)
if blob then
local setups=instance.setups
@@ -13960,7 +14760,7 @@ local function load_configuration_files()
local parent=data and data.parent
if parent then
local filename=filejoin(pathname,parent)
- local realname=resolvers.resolve(filename)
+ local realname=resolveprefix(filename)
local blob=loadfile(realname)
if blob then
local parentdata=blob()
@@ -13985,7 +14785,7 @@ local function load_configuration_files()
elseif variables[k]==nil then
if trace_locating and not warning then
report_resolving("variables like %a in configuration file %a should move to the 'variables' subtable",
- k,resolvers.resolve(filename))
+ k,resolveprefix(filename))
warning=true
end
variables[k]=v
@@ -14045,7 +14845,7 @@ local function locate_file_databases()
local stripped=lpegmatch(inhibitstripper,path)
if stripped~="" then
local runtime=stripped==path
- path=resolvers.cleanpath(path)
+ path=cleanpath(path)
local spec=resolvers.splitmethod(stripped)
if runtime and (spec.noscheme or spec.scheme=="file") then
stripped="tree:///"..stripped
@@ -14108,8 +14908,8 @@ function resolvers.renew(hashname)
report_resolving("identifying tree %a",hashname)
end
end
- local realpath=resolvers.resolve(hashname)
- if lfs.isdir(realpath) then
+ local realpath=resolveprefix(hashname)
+ if isdir(realpath) then
if trace_locating then
report_resolving("using path %a",realpath)
end
@@ -14210,19 +15010,53 @@ end
function resolvers.unexpandedpath(str)
return joinpath(resolvers.unexpandedpathlist(str))
end
+function resolvers.pushpath(name)
+ local pathstack=instance.pathstack
+ local lastpath=pathstack[#pathstack]
+ local pluspath=filedirname(name)
+ if lastpath then
+ lastpath=collapsepath(filejoin(lastpath,pluspath))
+ else
+ lastpath=collapsepath(pluspath)
+ end
+ insert(pathstack,lastpath)
+ if trace_paths then
+ report_resolving("pushing path %a",lastpath)
+ end
+end
+function resolvers.poppath()
+ local pathstack=instance.pathstack
+ if trace_paths and #pathstack>0 then
+ report_resolving("popping path %a",pathstack[#pathstack])
+ end
+ remove(pathstack)
+end
+function resolvers.stackpath()
+ local pathstack=instance.pathstack
+ local currentpath=pathstack[#pathstack]
+ return currentpath~="" and currentpath or nil
+end
local done={}
function resolvers.resetextrapath()
local ep=instance.extra_paths
if not ep then
- ep,done={},{}
- instance.extra_paths=ep
+ done={}
+ instance.extra_paths={}
elseif #ep>0 then
- instance.lists,done={},{}
+ done={}
+ reset_caches()
end
end
function resolvers.registerextrapath(paths,subpaths)
- paths=settings_to_array(paths)
- subpaths=settings_to_array(subpaths)
+ if not subpaths or subpaths=="" then
+ if not paths or path=="" then
+ return
+ elseif done[paths] then
+ return
+ end
+ end
+ local paths=settings_to_array(paths)
+ local subpaths=settings_to_array(subpaths)
local ep=instance.extra_paths or {}
local oldn=#ep
local newn=oldn
@@ -14237,7 +15071,7 @@ function resolvers.registerextrapath(paths,subpaths)
local ps=p.."/"..s
if not done[ps] then
newn=newn+1
- ep[newn]=resolvers.cleanpath(ps)
+ ep[newn]=cleanpath(ps)
done[ps]=true
end
end
@@ -14247,7 +15081,7 @@ function resolvers.registerextrapath(paths,subpaths)
local p=paths[i]
if not done[p] then
newn=newn+1
- ep[newn]=resolvers.cleanpath(p)
+ ep[newn]=cleanpath(p)
done[p]=true
end
end
@@ -14259,7 +15093,7 @@ function resolvers.registerextrapath(paths,subpaths)
local ps=ep[i].."/"..s
if not done[ps] then
newn=newn+1
- ep[newn]=resolvers.cleanpath(ps)
+ ep[newn]=cleanpath(ps)
done[ps]=true
end
end
@@ -14268,52 +15102,70 @@ function resolvers.registerextrapath(paths,subpaths)
if newn>0 then
instance.extra_paths=ep
end
- if newn>oldn then
- instance.lists={}
+ if newn~=oldn then
+ reset_caches()
end
end
-local function made_list(instance,list)
- local ep=instance.extra_paths
- if not ep or #ep==0 then
- return list
+function resolvers.pushextrapath(path)
+ local paths=settings_to_array(path)
+ if instance.extra_stack then
+ insert(instance.extra_stack,1,paths)
else
- local done,new,newn={},{},0
- for k=1,#list do
- local v=list[k]
- if not done[v] then
- if find(v,"^[%.%/]$") then
- done[v]=true
- newn=newn+1
- new[newn]=v
- else
- break
- end
- end
- end
- for k=1,#ep do
- local v=ep[k]
+ instance.extra_stack={ paths }
+ end
+ reset_caches()
+end
+function resolvers.popextrapath()
+ if instance.extra_stack then
+ reset_caches()
+ return remove(instance.extra_stack,1)
+ end
+end
+local function made_list(instance,list,extra_too)
+ local done={}
+ local new={}
+ local newn=0
+ local function add(p)
+ for k=1,#p do
+ local v=p[k]
if not done[v] then
done[v]=true
newn=newn+1
new[newn]=v
end
end
- for k=1,#list do
- local v=list[k]
- if not done[v] then
- done[v]=true
- newn=newn+1
- new[newn]=v
+ end
+ for k=1,#list do
+ local v=list[k]
+ if done[v] then
+ elseif find(v,"^[%.%/]$") then
+ done[v]=true
+ newn=newn+1
+ new[newn]=v
+ else
+ break
+ end
+ end
+ if extra_too then
+ local es=instance.extra_stack
+ if es and #es>0 then
+ for k=1,#es do
+ add(es[k])
end
end
- return new
+ local ep=instance.extra_paths
+ if ep and #ep>0 then
+ add(ep)
+ end
end
+ add(list)
+ return new
end
function resolvers.cleanpathlist(str)
local t=resolvers.expandedpathlist(str)
if t then
for i=1,#t do
- t[i]=collapsepath(resolvers.cleanpath(t[i]))
+ t[i]=collapsepath(cleanpath(t[i]))
end
end
return t
@@ -14321,22 +15173,22 @@ end
function resolvers.expandpath(str)
return joinpath(resolvers.expandedpathlist(str))
end
-function resolvers.expandedpathlist(str)
+function resolvers.expandedpathlist(str,extra_too)
if not str then
return {}
- elseif instance.savelists then
+ elseif instance.savelists then
str=lpegmatch(dollarstripper,str)
local lists=instance.lists
local lst=lists[str]
if not lst then
- local l=made_list(instance,resolvers.splitpath(resolvers.expansion(str)))
+ local l=made_list(instance,resolvers.splitpath(resolvers.expansion(str)),extra_too)
lst=expandedpathfromlist(l)
lists[str]=lst
end
return lst
else
local lst=resolvers.splitpath(resolvers.expansion(str))
- return made_list(instance,expandedpathfromlist(lst))
+ return made_list(instance,expandedpathfromlist(lst),extra_too)
end
end
function resolvers.expandedpathlistfromvariable(str)
@@ -14347,6 +15199,13 @@ end
function resolvers.expandpathfromvariable(str)
return joinpath(resolvers.expandedpathlistfromvariable(str))
end
+function resolvers.cleanedpathlist(v)
+ local t=resolvers.expandedpathlist(v)
+ for i=1,#t do
+ t[i]=resolvers.resolve(resolvers.cleanpath(t[i]))
+ end
+ return t
+end
function resolvers.expandbraces(str)
local ori=str
local pth=expandedpathfromlist(resolvers.splitpath(ori))
@@ -14363,7 +15222,7 @@ function resolvers.registerfilehash(name,content,someerror)
end
end
local function isreadable(name)
- local readable=lfs.isfile(name)
+ local readable=isfile(name)
if trace_detail then
if readable then
report_resolving("file %a is readable",name)
@@ -14373,70 +15232,57 @@ local function isreadable(name)
end
return readable
end
-local function collect_files(names)
- local filelist,noffiles={},0
+local function collect_files(names)
+ local filelist={}
+ local noffiles=0
+ local function check(hash,root,pathname,path,name)
+ if not pathname or find(path,pathname) then
+ local variant=hash.type
+ local search=filejoin(root,path,name)
+ local result=methodhandler('concatinators',variant,root,path,name)
+ if trace_detail then
+ report_resolving("match: variant %a, search %a, result %a",variant,search,result)
+ end
+ noffiles=noffiles+1
+ filelist[noffiles]={ variant,search,result }
+ end
+ end
for k=1,#names do
- local fname=names[k]
+ local filename=names[k]
if trace_detail then
- report_resolving("checking name %a",fname)
+ report_resolving("checking name %a",filename)
end
- local bname=filebasename(fname)
- local dname=filedirname(fname)
- if dname=="" or find(dname,"^%.") then
- dname=false
+ local basename=filebasename(filename)
+ local pathname=filedirname(filename)
+ if pathname=="" or find(pathname,"^%.") then
+ pathname=false
else
- dname=gsub(dname,"%*",".*")
- dname="/"..dname.."$"
+ pathname=gsub(pathname,"%*",".*")
+ pathname="/"..pathname.."$"
end
local hashes=instance.hashes
for h=1,#hashes do
local hash=hashes[h]
- local blobpath=hash.name
- local files=blobpath and instance.files[blobpath]
- if files then
+ local hashname=hash.name
+ local content=hashname and instance.files[hashname]
+ if content then
if trace_detail then
- report_resolving("deep checking %a, base %a, pattern %a",blobpath,bname,dname)
- end
- local blobfile=files[bname]
- if not blobfile then
- local rname="remap:"..bname
- blobfile=files[rname]
- if blobfile then
- bname=files[rname]
- blobfile=files[bname]
- end
+ report_resolving("deep checking %a, base %a, pattern %a",hashname,basename,pathname)
end
- if blobfile then
- local blobroot=files.__path__ or blobpath
- if type(blobfile)=='string' then
- if not dname or find(blobfile,dname) then
- local variant=hash.type
- local search=filejoin(blobroot,blobfile,bname)
- local result=methodhandler('concatinators',hash.type,blobroot,blobfile,bname)
- if trace_detail then
- report_resolving("match: variant %a, search %a, result %a",variant,search,result)
- end
- noffiles=noffiles+1
- filelist[noffiles]={ variant,search,result }
- end
+ local path,name=lookup(content,basename)
+ if path then
+ local metadata=content.metadata
+ local realroot=metadata and metadata.path or hashname
+ if type(path)=="string" then
+ check(hash,realroot,pathname,path,name)
else
- for kk=1,#blobfile do
- local vv=blobfile[kk]
- if not dname or find(vv,dname) then
- local variant=hash.type
- local search=filejoin(blobroot,vv,bname)
- local result=methodhandler('concatinators',hash.type,blobroot,vv,bname)
- if trace_detail then
- report_resolving("match: variant %a, search %a, result %a",variant,search,result)
- end
- noffiles=noffiles+1
- filelist[noffiles]={ variant,search,result }
- end
+ for i=1,#path do
+ check(hash,realroot,pathname,path[i],name)
end
end
end
elseif trace_locating then
- report_resolving("no match in %a (%s)",blobpath,bname)
+ report_resolving("no match in %a (%s)",hashname,basename)
end
end
end
@@ -14461,7 +15307,7 @@ end
local function can_be_dir(name)
local fakepaths=instance.fakepaths
if not fakepaths[name] then
- if lfs.isdir(name) then
+ if isdir(name) then
fakepaths[name]=1
else
fakepaths[name]=2
@@ -14477,10 +15323,11 @@ local function find_analyze(filename,askedformat,allresults)
if askedformat=="" then
if ext=="" or not suffixmap[ext] then
local defaultsuffixes=resolvers.defaultsuffixes
+ local formatofsuffix=resolvers.formatofsuffix
for i=1,#defaultsuffixes do
local forcedname=filename..'.'..defaultsuffixes[i]
wantedfiles[#wantedfiles+1]=forcedname
- filetype=resolvers.formatofsuffix(forcedname)
+ filetype=formatofsuffix(forcedname)
if trace_locating then
report_resolving("forcing filetype %a",filetype)
end
@@ -14520,14 +15367,14 @@ local function find_wildcard(filename,allresults)
if trace_locating then
report_resolving("checking wildcard %a",filename)
end
- local method,result=resolvers.findwildcardfiles(filename)
+ local result=resolvers.findwildcardfiles(filename)
if result then
return "wildcard",result
end
end
end
local function find_qualified(filename,allresults,askedformat,alsostripped)
- if not file.is_qualified_path(filename) then
+ if not is_qualified_path(filename) then
return
end
if trace_locating then
@@ -14601,33 +15448,66 @@ local function check_subpath(fname)
return fname
end
end
-local function find_intree(filename,filetype,wantedfiles,allresults)
+local function makepathlist(list,filetype)
local typespec=resolvers.variableofformat(filetype)
- local pathlist=resolvers.expandedpathlist(typespec)
- local method="intree"
+ local pathlist=resolvers.expandedpathlist(typespec,filetype and usertypes[filetype])
+ local entry={}
if pathlist and #pathlist>0 then
- local filelist=collect_files(wantedfiles)
+ for k=1,#pathlist do
+ local path=pathlist[k]
+ local prescanned=find(path,'^!!')
+ local resursive=find(path,'//$')
+ local pathname=lpegmatch(inhibitstripper,path)
+ local expression=makepathexpression(pathname)
+ local barename=gsub(pathname,"/+$","")
+ barename=resolveprefix(barename)
+ local scheme=url.hasscheme(barename)
+ local schemename=gsub(barename,"%.%*$",'')
+ entry[k]={
+ path=path,
+ pathname=pathname,
+ prescanned=prescanned,
+ recursive=recursive,
+ expression=expression,
+ barename=barename,
+ scheme=scheme,
+ schemename=schemename,
+ }
+ end
+ entry.typespec=typespec
+ list[filetype]=entry
+ else
+ list[filetype]=false
+ end
+ return entry
+end
+local function find_intree(filename,filetype,wantedfiles,allresults)
+ local pathlists=instance.pathlists
+ if not pathlists then
+ pathlists=setmetatableindex(allocate(),makepathlist)
+ instance.pathlists=pathlists
+ end
+ local pathlist=pathlists[filetype]
+ if pathlist then
+ local method="intree"
+ local filelist=collect_files(wantedfiles)
local dirlist={}
+ local result={}
if filelist then
for i=1,#filelist do
dirlist[i]=filedirname(filelist[i][3]).."/"
end
end
if trace_detail then
- report_resolving("checking filename %a",filename)
+ report_resolving("checking filename %a in tree",filename)
end
- local resolve=resolvers.resolve
- local result={}
for k=1,#pathlist do
- local path=pathlist[k]
- local pathname=lpegmatch(inhibitstripper,path)
- local doscan=path==pathname
- if not find (pathname,'//$') then
- doscan=false
- end
+ local entry=pathlist[k]
+ local path=entry.path
+ local pathname=entry.pathname
local done=false
if filelist then
- local expression=makepathexpression(pathname)
+ local expression=entry.expression
if trace_detail then
report_resolving("using pattern %a for path %a",expression,pathname)
end
@@ -14635,8 +15515,8 @@ local function find_intree(filename,filetype,wantedfiles,allresults)
local fl=filelist[k]
local f=fl[2]
local d=dirlist[k]
- if find(d,expression) or find(resolve(d),expression) then
- result[#result+1]=resolve(fl[3])
+ if find(d,expression) or find(resolveprefix(d),expression) then
+ result[#result+1]=resolveprefix(fl[3])
done=true
if allresults then
if trace_detail then
@@ -14657,56 +15537,62 @@ local function find_intree(filename,filetype,wantedfiles,allresults)
method="database"
else
method="filesystem"
- pathname=gsub(pathname,"/+$","")
- pathname=resolve(pathname)
- local scheme=url.hasscheme(pathname)
+ local scheme=entry.scheme
if not scheme or scheme=="file" then
- local pname=gsub(pathname,"%.%*$",'')
+ local pname=entry.schemename
if not find(pname,"*",1,true) then
if can_be_dir(pname) then
- for k=1,#wantedfiles do
- local w=wantedfiles[k]
- local fname=check_subpath(filejoin(pname,w))
- if fname then
- result[#result+1]=fname
- done=true
- if not allresults then
- break
- end
+ if not done and not entry.prescanned then
+ if trace_detail then
+ report_resolving("quick root scan for %a",pname)
end
- end
- if not done and doscan then
- local files=resolvers.simplescanfiles(pname,false,true)
for k=1,#wantedfiles do
local w=wantedfiles[k]
- local subpath=files[w]
- if not subpath or subpath=="" then
- elseif type(subpath)=="string" then
- local fname=check_subpath(filejoin(pname,subpath,w))
- if fname then
- result[#result+1]=fname
- done=true
- if not allresults then
- break
- end
+ local fname=check_subpath(filejoin(pname,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
end
- else
- for i=1,#subpath do
- local sp=subpath[i]
- if sp=="" then
- else
- local fname=check_subpath(filejoin(pname,sp,w))
- if fname then
- result[#result+1]=fname
- done=true
- if not allresults then
- break
+ end
+ end
+ if not done and entry.recursive then
+ if trace_detail then
+ report_resolving("scanning filesystem for %a",pname)
+ end
+ local files=resolvers.simplescanfiles(pname,false,true)
+ for k=1,#wantedfiles do
+ local w=wantedfiles[k]
+ local subpath=files[w]
+ if not subpath or subpath=="" then
+ elseif type(subpath)=="string" then
+ local fname=check_subpath(filejoin(pname,subpath,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
+ end
+ else
+ for i=1,#subpath do
+ local sp=subpath[i]
+ if sp=="" then
+ else
+ local fname=check_subpath(filejoin(pname,sp,w))
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
end
end
end
- end
- if done and not allresults then
- break
+ if done and not allresults then
+ break
+ end
end
end
end
@@ -14714,6 +15600,18 @@ local function find_intree(filename,filetype,wantedfiles,allresults)
end
else
end
+ else
+ for k=1,#wantedfiles do
+ local pname=entry.barename
+ local fname=methodhandler('finders',pname.."/"..wantedfiles[k])
+ if fname then
+ result[#result+1]=fname
+ done=true
+ if not allresults then
+ break
+ end
+ end
+ end
end
end
if done and not allresults then
@@ -14748,10 +15646,13 @@ local function find_otherwise(filename,filetype,wantedfiles,allresults)
local filelist=collect_files(wantedfiles)
local fl=filelist and filelist[1]
if fl then
- return "otherwise",{ resolvers.resolve(fl[3]) }
+ return "otherwise",{ resolveprefix(fl[3]) }
end
end
collect_instance_files=function(filename,askedformat,allresults)
+ if not filename or filename=="" then
+ return {}
+ end
askedformat=askedformat or ""
filename=collapsepath(filename,".")
filename=gsub(filename,"^%./",getcurrentdir().."/")
@@ -14786,7 +15687,11 @@ collect_instance_files=function(filename,askedformat,allresults)
else
local method,result,stamp,filetype,wantedfiles
if instance.remember then
- stamp=formatters["%s--%s"](filename,askedformat)
+ if askedformat=="" then
+ stamp=formatters["%s::%s"](suffixonly(filename),filename)
+ else
+ stamp=formatters["%s::%s"](askedformat,filename)
+ end
result=stamp and instance.found[stamp]
if result then
if trace_locating then
@@ -14821,7 +15726,7 @@ collect_instance_files=function(filename,askedformat,allresults)
end
if stamp then
if trace_locating then
- report_resolving("remembering file %a",filename)
+ report_resolving("remembering file %a using hash %a",filename,stamp)
end
instance.found[stamp]=result
end
@@ -14829,6 +15734,9 @@ collect_instance_files=function(filename,askedformat,allresults)
end
end
local function findfiles(filename,filetype,allresults)
+ if not filename or filename=="" then
+ return {}
+ end
local result,status=collect_instance_files(filename,filetype or "",allresults)
if not result or #result==0 then
local lowered=lower(filename)
@@ -14848,39 +15756,30 @@ function resolvers.findpath(filename,filetype)
return filedirname(findfiles(filename,filetype,false)[1] or "")
end
local function findgivenfiles(filename,allresults)
- local bname,result=filebasename(filename),{}
+ local base=filebasename(filename)
+ local result={}
local hashes=instance.hashes
- local noffound=0
+ local function okay(hash,path,name)
+ local found=methodhandler('concatinators',hash.type,hash.name,path,name)
+ if found and found~="" then
+ result[#result+1]=resolveprefix(found)
+ return not allresults
+ end
+ end
for k=1,#hashes do
local hash=hashes[k]
- local files=instance.files[hash.name] or {}
- local blist=files[bname]
- if not blist then
- local rname="remap:"..bname
- blist=files[rname]
- if blist then
- bname=files[rname]
- blist=files[bname]
- end
- end
- if blist then
- if type(blist)=='string' then
- local found=methodhandler('concatinators',hash.type,hash.name,blist,bname) or ""
- if found~="" then
- noffound=noffound+1
- result[noffound]=resolvers.resolve(found)
- if not allresults then
- break
- end
+ local content=instance.files[hash.name]
+ if content then
+ local path,name=lookup(content,base)
+ if not path then
+ elseif type(path)=="string" then
+ if okay(hash,path,name) then
+ return result
end
else
- for kk=1,#blist do
- local vv=blist[kk]
- local found=methodhandler('concatinators',hash.type,hash.name,vv,bname) or ""
- if found~="" then
- noffound=noffound+1
- result[noffound]=resolvers.resolve(found)
- if not allresults then break end
+ for i=1,#path do
+ if okay(hash,path[i],name) then
+ return result
end
end
end
@@ -14894,64 +15793,80 @@ end
function resolvers.findgivenfile(filename)
return findgivenfiles(filename,false)[1] or ""
end
-local function doit(path,blist,bname,tag,variant,result,allresults)
- local done=false
- if blist and variant then
- local resolve=resolvers.resolve
- if type(blist)=='string' then
- if find(lower(blist),path) then
- local full=methodhandler('concatinators',variant,tag,blist,bname) or ""
- result[#result+1]=resolve(full)
- done=true
- end
- else
- for kk=1,#blist do
- local vv=blist[kk]
- if find(lower(vv),path) then
- local full=methodhandler('concatinators',variant,tag,vv,bname) or ""
- result[#result+1]=resolve(full)
- done=true
- if not allresults then break end
- end
- end
- end
- end
- return done
-end
local makewildcard=Cs(
(P("^")^0*P("/")*P(-1)+P(-1))/".*"+(P("^")^0*P("/")/"")^0*(P("*")/".*"+P("-")/"%%-"+P(".")/"%%."+P("?")/"."+P("\\")/"/"+P(1))^0
)
function resolvers.wildcardpattern(pattern)
return lpegmatch(makewildcard,pattern) or pattern
end
-local function findwildcardfiles(filename,allresults,result)
- result=result or {}
+local function findwildcardfiles(filename,allresults,result)
+ local result=result or {}
local base=filebasename(filename)
local dirn=filedirname(filename)
local path=lower(lpegmatch(makewildcard,dirn) or dirn)
local name=lower(lpegmatch(makewildcard,base) or base)
- local files,done=instance.files,false
+ local files=instance.files
if find(name,"*",1,true) then
local hashes=instance.hashes
+ local function okay(found,path,base,hashname,hashtype)
+ if find(found,path) then
+ local full=methodhandler('concatinators',hashtype,hashname,found,base)
+ if full and full~="" then
+ result[#result+1]=resolveprefix(full)
+ return not allresults
+ end
+ end
+ end
for k=1,#hashes do
local hash=hashes[k]
- local hashname,hashtype=hash.name,hash.type
- for kk,hh in next,files[hashname] do
- if not find(kk,"^remap:") then
- if find(lower(kk),name) then
- if doit(path,hh,kk,hashname,hashtype,result,allresults) then done=true end
- if done and not allresults then break end
+ local hashname=hash.name
+ local hashtype=hash.type
+ if hashname and hashtype then
+ for found,base in filtered(files[hashname],name) do
+ if type(found)=='string' then
+ if okay(found,path,base,hashname,hashtype) then
+ break
+ end
+ else
+ for i=1,#found do
+ if okay(found[i],path,base,hashname,hashtype) then
+ break
+ end
+ end
end
end
end
end
else
+ local function okayokay(found,path,base,hashname,hashtype)
+ if find(found,path) then
+ local full=methodhandler('concatinators',hashtype,hashname,found,base)
+ if full and full~="" then
+ result[#result+1]=resolveprefix(full)
+ return not allresults
+ end
+ end
+ end
local hashes=instance.hashes
for k=1,#hashes do
local hash=hashes[k]
- local hashname,hashtype=hash.name,hash.type
- if doit(path,files[hashname][base],base,hashname,hashtype,result,allresults) then done=true end
- if done and not allresults then break end
+ local hashname=hash.name
+ local hashtype=hash.type
+ if hashname and hashtype then
+ local found,base=lookup(content,base)
+ if not found then
+ elseif type(found)=='string' then
+ if okay(found,path,base,hashname,hashtype) then
+ break
+ end
+ else
+ for i=1,#found do
+ if okay(found[i],path,base,hashname,hashtype) then
+ break
+ end
+ end
+ end
+ end
end
end
return result
@@ -15024,7 +15939,7 @@ end
function resolvers.dowithpath(name,func)
local pathlist=resolvers.expandedpathlist(name)
for i=1,#pathlist do
- func("^"..resolvers.cleanpath(pathlist[i]))
+ func("^"..cleanpath(pathlist[i]))
end
end
function resolvers.dowithvariable(name,func)
@@ -15032,23 +15947,23 @@ function resolvers.dowithvariable(name,func)
end
function resolvers.locateformat(name)
local engine=environment.ownmain or "luatex"
- local barename=file.removesuffix(name)
- local fullname=file.addsuffix(barename,"fmt")
+ local barename=removesuffix(name)
+ local fullname=addsuffix(barename,"fmt")
local fmtname=caches.getfirstreadablefile(fullname,"formats",engine) or ""
if fmtname=="" then
fmtname=resolvers.findfile(fullname)
- fmtname=resolvers.cleanpath(fmtname)
+ fmtname=cleanpath(fmtname)
end
if fmtname~="" then
- local barename=file.removesuffix(fmtname)
- local luaname=file.addsuffix(barename,luasuffixes.lua)
- local lucname=file.addsuffix(barename,luasuffixes.luc)
- local luiname=file.addsuffix(barename,luasuffixes.lui)
- if lfs.isfile(luiname) then
+ local barename=removesuffix(fmtname)
+ local luaname=addsuffix(barename,luasuffixes.lua)
+ local lucname=addsuffix(barename,luasuffixes.luc)
+ local luiname=addsuffix(barename,luasuffixes.lui)
+ if isfile(luiname) then
return barename,luiname
- elseif lfs.isfile(lucname) then
+ elseif isfile(lucname) then
return barename,lucname
- elseif lfs.isfile(luaname) then
+ elseif isfile(luaname) then
return barename,luaname
end
end
@@ -15070,29 +15985,24 @@ function resolvers.dowithfilesintree(pattern,handle,before,after)
local hash=hashes[i]
local blobtype=hash.type
local blobpath=hash.name
- if blobpath then
+ if blobtype and blobpath then
+ local total=0
+ local checked=0
+ local done=0
if before then
before(blobtype,blobpath,pattern)
end
- local files=instance.files[blobpath]
- local total,checked,done=0,0,0
- if files then
- for k,v in table.sortedhash(files) do
- total=total+1
- if find(k,"^remap:") then
- elseif find(k,pattern) then
- if type(v)=="string" then
- checked=checked+1
- if handle(blobtype,blobpath,v,k) then
- done=done+1
- end
- else
- checked=checked+#v
- for i=1,#v do
- if handle(blobtype,blobpath,v[i],k) then
- done=done+1
- end
- end
+ for path,name in filtered(instance.files[blobpath],pattern) do
+ if type(path)=="string" then
+ checked=checked+1
+ if handle(blobtype,blobpath,path,name) then
+ done=done+1
+ end
+ else
+ checked=checked+#path
+ for i=1,#path do
+ if handle(blobtype,blobpath,path[i],name) then
+ done=done+1
end
end
end
@@ -15103,8 +16013,8 @@ function resolvers.dowithfilesintree(pattern,handle,before,after)
end
end
end
-resolvers.obsolete=resolvers.obsolete or {}
-local obsolete=resolvers.obsolete
+local obsolete=resolvers.obsolete or {}
+resolvers.obsolete=obsolete
resolvers.find_file=resolvers.findfile obsolete.find_file=resolvers.findfile
resolvers.find_files=resolvers.findfiles obsolete.find_files=resolvers.findfiles
@@ -15115,7 +16025,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-pre"] = package.loaded["data-pre"] or true
--- original size: 6643, stripped down to: 4401
+-- original size: 3950, stripped down to: 2935
if not modules then modules={} end modules ['data-pre']={
version=1.001,
@@ -15125,44 +16035,51 @@ if not modules then modules={} end modules ['data-pre']={
license="see context related readme files"
}
local resolvers=resolvers
-local prefixes=utilities.storage.allocate()
-resolvers.prefixes=prefixes
-local cleanpath,findgivenfile,expansion=resolvers.cleanpath,resolvers.findgivenfile,resolvers.expansion
+local prefixes=resolvers.prefixes
+local cleanpath=resolvers.cleanpath
+local findgivenfile=resolvers.findgivenfile
+local expansion=resolvers.expansion
local getenv=resolvers.getenv
-local P,S,R,C,Cs,Cc,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.match
-local joinpath,basename,dirname=file.join,file.basename,file.dirname
-local getmetatable,rawset,type=getmetatable,rawset,type
+local basename=file.basename
+local dirname=file.dirname
+local joinpath=file.join
+local isfile=lfs.isfile
prefixes.environment=function(str)
return cleanpath(expansion(str))
end
-prefixes.relative=function(str,n)
- if io.exists(str) then
- elseif io.exists("./"..str) then
- str="./"..str
- else
- local p="../"
- for i=1,n or 2 do
- if io.exists(p..str) then
- str=p..str
- break
- else
- p=p.."../"
+local function relative(str,n)
+ if not isfile(str) then
+ local pstr="./"..str
+ if isfile(pstr) then
+ str=pstr
+ else
+ local p="../"
+ for i=1,n or 2 do
+ local pstr=p..str
+ if isfile(pstr) then
+ str=pstr
+ break
+ else
+ p=p.."../"
+ end
end
end
end
return cleanpath(str)
end
+local function locate(str)
+ local fullname=findgivenfile(str) or ""
+ return cleanpath(fullname~="" and fullname or str)
+end
+prefixes.relative=relative
+prefixes.locate=locate
prefixes.auto=function(str)
- local fullname=prefixes.relative(str)
- if not lfs.isfile(fullname) then
- fullname=prefixes.locate(str)
+ local fullname=relative(str)
+ if not isfile(fullname) then
+ fullname=locate(str)
end
return fullname
end
-prefixes.locate=function(str)
- local fullname=findgivenfile(str) or ""
- return cleanpath((fullname~="" and fullname) or str)
-end
prefixes.filename=function(str)
local fullname=findgivenfile(str) or ""
return cleanpath(basename((fullname~="" and fullname) or str))
@@ -15183,6 +16100,13 @@ end
prefixes.home=function(str)
return cleanpath(joinpath(getenv('HOME'),str))
end
+prefixes.env=prefixes.environment
+prefixes.rel=prefixes.relative
+prefixes.loc=prefixes.locate
+prefixes.kpse=prefixes.locate
+prefixes.full=prefixes.locate
+prefixes.file=prefixes.filename
+prefixes.path=prefixes.pathname
local function toppath()
local inputstack=resolvers.inputstack
if not inputstack then
@@ -15195,98 +16119,22 @@ local function toppath()
return pathname
end
end
-resolvers.toppath=toppath
-prefixes.toppath=function(str)
- return cleanpath(joinpath(toppath(),str))
-end
-prefixes.env=prefixes.environment
-prefixes.rel=prefixes.relative
-prefixes.loc=prefixes.locate
-prefixes.kpse=prefixes.locate
-prefixes.full=prefixes.locate
-prefixes.file=prefixes.filename
-prefixes.path=prefixes.pathname
-function resolvers.allprefixes(separator)
- local all=table.sortedkeys(prefixes)
- if separator then
- for i=1,#all do
- all[i]=all[i]..":"
- end
- end
- return all
-end
-local function _resolve_(method,target)
- local action=prefixes[method]
- if action then
- return action(target)
- else
- return method..":"..target
- end
-end
-local resolved,abstract={},{}
-function resolvers.resetresolve(str)
- resolved,abstract={},{}
-end
-local pattern=Cs((C(R("az")^2)*P(":")*C((1-S(" \"\';,"))^1)/_resolve_+P(1))^0)
-local prefix=C(R("az")^2)*P(":")
-local target=C((1-S(" \"\';,"))^1)
-local notarget=(#S(";,")+P(-1))*Cc("")
-local pattern=Cs(((prefix*(target+notarget))/_resolve_+P(1))^0)
-local function resolve(str)
- if type(str)=="table" then
- local t={}
- for i=1,#str do
- t[i]=resolve(str[i])
- end
- return t
+local function jobpath()
+ local path=resolvers.stackpath()
+ if not path or path=="" then
+ return "."
else
- local res=resolved[str]
- if not res then
- res=lpegmatch(pattern,str)
- resolved[str]=res
- abstract[res]=str
- end
- return res
- end
-end
-local function unresolve(str)
- return abstract[str] or str
-end
-resolvers.resolve=resolve
-resolvers.unresolve=unresolve
-if type(os.uname)=="function" then
- for k,v in next,os.uname() do
- if not prefixes[k] then
- prefixes[k]=function() return v end
- end
- end
-end
-if os.type=="unix" then
- local pattern
- local function makepattern(t,k,v)
- if t then
- rawset(t,k,v)
- end
- local colon=P(":")
- for k,v in table.sortedpairs(prefixes) do
- if p then
- p=P(k)+p
- else
- p=P(k)
- end
- end
- pattern=Cs((p*colon+colon/";"+P(1))^0)
- end
- makepattern()
- getmetatable(prefixes).__newindex=makepattern
- function resolvers.repath(str)
- return lpegmatch(pattern,str)
- end
-else
- function resolvers.repath(str)
- return str
+ return path
end
end
+resolvers.toppath=toppath
+resolvers.jobpath=jobpath
+prefixes.toppath=function(str) return cleanpath(joinpath(toppath(),str)) end
+prefixes.jobpath=function(str) return cleanpath(joinpath(jobpath(),str)) end
+resolvers.setdynamic("toppath")
+resolvers.setdynamic("jobpath")
+prefixes.jobfile=prefixes.jobpath
+resolvers.setdynamic("jobfile")
end -- of closure
@@ -15348,7 +16196,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-fil"] = package.loaded["data-fil"] or true
--- original size: 3801, stripped down to: 3231
+-- original size: 3863, stripped down to: 3310
if not modules then modules={} end modules ['data-fil']={
version=1.001,
@@ -15360,30 +16208,31 @@ if not modules then modules={} end modules ['data-fil']={
local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
local report_files=logs.reporter("resolvers","files")
local resolvers=resolvers
+local resolveprefix=resolvers.resolve
local finders,openers,loaders,savers=resolvers.finders,resolvers.openers,resolvers.loaders,resolvers.savers
local locators,hashers,generators,concatinators=resolvers.locators,resolvers.hashers,resolvers.generators,resolvers.concatinators
local checkgarbage=utilities.garbagecollector and utilities.garbagecollector.check
function locators.file(specification)
- local name=specification.filename
- local realname=resolvers.resolve(name)
+ local filename=specification.filename
+ local realname=resolveprefix(filename)
if realname and realname~='' and lfs.isdir(realname) then
if trace_locating then
- report_files("file locator %a found as %a",name,realname)
+ report_files("file locator %a found as %a",filename,realname)
end
- resolvers.appendhash('file',name,true)
+ resolvers.appendhash('file',filename,true)
elseif trace_locating then
- report_files("file locator %a not found",name)
+ report_files("file locator %a not found",filename)
end
end
function hashers.file(specification)
- local name=specification.filename
- local content=caches.loadcontent(name,'files')
- resolvers.registerfilehash(name,content,content==nil)
+ local pathname=specification.filename
+ local content=caches.loadcontent(pathname,'files')
+ resolvers.registerfilehash(pathname,content,content==nil)
end
function generators.file(specification)
- local path=specification.filename
- local content=resolvers.scanfiles(path,false,true)
- resolvers.registerfilehash(path,content,true)
+ local pathname=specification.filename
+ local content=resolvers.scanfiles(pathname,false,true)
+ resolvers.registerfilehash(pathname,content,true)
end
concatinators.file=file.join
function finders.file(specification,filetype)
@@ -15665,7 +16514,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-zip"] = package.loaded["data-zip"] or true
--- original size: 8489, stripped down to: 6757
+-- original size: 8772, stripped down to: 6841
if not modules then modules={} end modules ['data-zip']={
version=1.001,
@@ -15684,16 +16533,6 @@ zip.archives=zip.archives or {}
local archives=zip.archives
zip.registeredfiles=zip.registeredfiles or {}
local registeredfiles=zip.registeredfiles
-local limited=false
-directives.register("system.inputmode",function(v)
- if not limited then
- local i_limiter=io.i_limiter(v)
- if i_limiter then
- zip.open=i_limiter.protect(zip.open)
- limited=true
- end
- end
-end)
local function validzip(str)
if not find(str,"^zip://") then
return "zip:///"..str
@@ -15708,7 +16547,7 @@ function zip.openarchive(name)
local arch=archives[name]
if not arch then
local full=resolvers.findfile(name) or ""
- arch=(full~="" and zip.open(full)) or false
+ arch=full~="" and zip.open(full) or false
archives[name]=arch
end
return arch
@@ -15867,31 +16706,42 @@ function resolvers.usezipfile(archive)
end
end
function resolvers.registerzipfile(z,tree)
- local files,filter={},""
- if tree=="" then
- filter="^(.+)/(.-)$"
- else
- filter=format("^%s/(.+)/(.-)$",tree)
- end
+ local names={}
+ local files={}
+ local remap={}
+ local n=0
+ local filter=tree=="" and "^(.+)/(.-)$" or format("^%s/(.+)/(.-)$",tree)
+ local register=resolvers.registerfile
if trace_locating then
report_zip("registering: using filter %a",filter)
end
- local register,n=resolvers.registerfile,0
for i in z:files() do
- local path,name=match(i.filename,filter)
- if path then
- if name and name~='' then
- register(files,name,path)
- n=n+1
- else
+ local filename=i.filename
+ local path,name=match(filename,filter)
+ if not path then
+ n=n+1
+ register(names,filename,"")
+ local usedname=lower(filename)
+ files[usedname]=""
+ if usedname~=filename then
+ remap[usedname]=filename
end
- else
- register(files,i.filename,'')
+ elseif name and name~="" then
n=n+1
+ register(names,name,path)
+ local usedname=lower(name)
+ files[usedname]=path
+ if usedname~=name then
+ remap[usedname]=name
+ end
+ else
end
end
report_zip("registering: %s files registered",n)
- return files
+ return {
+ files=files,
+ remap=remap,
+ }
end
@@ -15901,7 +16751,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-tre"] = package.loaded["data-tre"] or true
--- original size: 2508, stripped down to: 2074
+-- original size: 8479, stripped down to: 5580
if not modules then modules={} end modules ['data-tre']={
version=1.001,
@@ -15910,42 +16760,64 @@ if not modules then modules={} end modules ['data-tre']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local find,gsub,format=string.find,string.gsub,string.format
+local find,gsub,lower=string.find,string.gsub,string.lower
+local basename,dirname,joinname=file.basename,file.dirname,file .join
+local globdir,isdir,isfile=dir.glob,lfs.isdir,lfs.isfile
+local P,lpegmatch=lpeg.P,lpeg.match
local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end)
local report_trees=logs.reporter("resolvers","trees")
local resolvers=resolvers
-local done,found,notfound={},{},resolvers.finders.notfound
-function resolvers.finders.tree(specification)
+local resolveprefix=resolvers.resolve
+local notfound=resolvers.finders.notfound
+local lookup=resolvers.get_from_content
+local collectors={}
+local found={}
+function resolvers.finders.tree(specification)
local spec=specification.filename
- local fnd=found[spec]
- if fnd==nil then
+ local okay=found[spec]
+ if okay==nil then
if spec~="" then
- local path,name=file.dirname(spec),file.basename(spec)
- if path=="" then path="." end
- local hash=done[path]
- if not hash then
- local pattern=path.."/*"
- hash=dir.glob(pattern)
- done[path]=hash
+ local path=dirname(spec)
+ local name=basename(spec)
+ if path=="" then
+ path="."
+ end
+ local names=collectors[path]
+ if not names then
+ local pattern=find(path,"/%*+$") and path or (path.."/*")
+ names=globdir(pattern)
+ collectors[path]=names
end
local pattern="/"..gsub(name,"([%.%-%+])","%%%1").."$"
- for k=1,#hash do
- local v=hash[k]
- if find(v,pattern) then
- found[spec]=v
- return v
+ for i=1,#names do
+ local fullname=names[i]
+ if find(fullname,pattern) then
+ found[spec]=fullname
+ return fullname
+ end
+ end
+ local pattern=lower(pattern)
+ for i=1,#names do
+ local fullname=lower(names[i])
+ if find(fullname,pattern) then
+ if isfile(fullname) then
+ found[spec]=fullname
+ return fullname
+ else
+ break
+ end
end
end
end
- fnd=notfound()
- found[spec]=fnd
+ okay=notfound()
+ found[spec]=okay
end
- return fnd
+ return okay
end
function resolvers.locators.tree(specification)
local name=specification.filename
- local realname=resolvers.resolve(name)
- if realname and realname~='' and lfs.isdir(realname) then
+ local realname=resolveprefix(name)
+ if realname and realname~='' and isdir(realname) then
if trace_locating then
report_trees("locator %a found",realname)
end
@@ -15956,16 +16828,110 @@ function resolvers.locators.tree(specification)
end
function resolvers.hashers.tree(specification)
local name=specification.filename
- if trace_locating then
- report_trees("analysing %a",name)
- end
+ report_trees("analyzing %a",name)
resolvers.methodhandler("hashers",name)
resolvers.generators.file(specification)
end
-resolvers.concatinators.tree=resolvers.concatinators.file
-resolvers.generators.tree=resolvers.generators.file
-resolvers.openers.tree=resolvers.openers.file
-resolvers.loaders.tree=resolvers.loaders.file
+local collectors={}
+local splitter=lpeg.splitat("/**/")
+local stripper=lpeg.replacer { [P("/")*P("*")^1*P(-1)]="" }
+table.setmetatableindex(collectors,function(t,k)
+ local rootname=lpegmatch(stripper,k)
+ local dataname=joinname(rootname,"dirlist")
+ local content=caches.loadcontent(dataname,"files",dataname)
+ if not content then
+ content=resolvers.scanfiles(rootname,nil,nil,false,true)
+ caches.savecontent(dataname,"files",content,dataname)
+ end
+ t[k]=content
+ return content
+end)
+local function checked(root,p,n)
+ if p then
+ if type(p)=="table" then
+ for i=1,#p do
+ local fullname=joinname(root,p[i],n)
+ if isfile(fullname) then
+ return fullname
+ end
+ end
+ else
+ local fullname=joinname(root,p,n)
+ if isfile(fullname) then
+ return fullname
+ end
+ end
+ end
+ return notfound()
+end
+local function resolve(specification)
+ local filename=specification.filename
+ if filename~="" then
+ local root,rest=lpegmatch(splitter,filename)
+ if root and rest then
+ local path,name=dirname(rest),basename(rest)
+ if name~=rest then
+ local content=collectors[root]
+ local p,n=lookup(content,name)
+ if not p then
+ return notfound()
+ end
+ local pattern=".*/"..path.."$"
+ local istable=type(p)=="table"
+ if istable then
+ for i=1,#p do
+ local pi=p[i]
+ if pi==path or find(pi,pattern) then
+ local fullname=joinname(root,pi,n)
+ if isfile(fullname) then
+ return fullname
+ end
+ end
+ end
+ elseif p==path or find(p,pattern) then
+ local fullname=joinname(root,p,n)
+ if isfile(fullname) then
+ return fullname
+ end
+ end
+ local queries=specification.queries
+ if queries and queries.option=="fileonly" then
+ return checked(root,p,n)
+ else
+ return notfound()
+ end
+ end
+ end
+ local path,name=dirname(filename),basename(filename)
+ local root=lpegmatch(stripper,path)
+ local content=collectors[path]
+ local p,n=lookup(content,name)
+ if p then
+ return checked(root,p,n)
+ end
+ end
+ return notfound()
+end
+resolvers.finders .dirlist=resolve
+resolvers.locators .dirlist=resolvers.locators .tree
+resolvers.hashers .dirlist=resolvers.hashers .tree
+resolvers.generators.dirlist=resolvers.generators.file
+resolvers.openers .dirlist=resolvers.openers .file
+resolvers.loaders .dirlist=resolvers.loaders .file
+function resolvers.finders.dirfile(specification)
+ local queries=specification.queries
+ if queries then
+ queries.option="fileonly"
+ else
+ specification.queries={ option="fileonly" }
+ end
+ return resolve(specification)
+end
+resolvers.locators .dirfile=resolvers.locators .dirlist
+resolvers.hashers .dirfile=resolvers.hashers .dirlist
+resolvers.generators.dirfile=resolvers.generators.dirlist
+resolvers.openers .dirfile=resolvers.openers .dirlist
+resolvers.loaders .dirfile=resolvers.loaders .dirlist
end -- of closure
@@ -15974,7 +16940,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-sch"] = package.loaded["data-sch"] or true
--- original size: 6213, stripped down to: 5160
+-- original size: 6569, stripped down to: 5304
if not modules then modules={} end modules ['data-sch']={
version=1.001,
@@ -16000,8 +16966,13 @@ directives.register("schemes.threshold",function(v) threshold=tonumber(v) or thr
function cleaners.none(specification)
return specification.original
end
-function cleaners.strip(specification)
- return (gsub(specification.original,"[^%a%d%.]+","-"))
+function cleaners.strip(specification)
+ local path,name=file.splitbase(specification.original)
+ if path=="" then
+ return (gsub(name,"[^%a%d%.]+","-"))
+ else
+ return (gsub((gsub(path,"%.","-").."-"..name),"[^%a%d%.]+","-"))
+ end
end
function cleaners.md5(specification)
return file.addsuffix(md5.hex(specification.original),file.suffix(specification.path))
@@ -16018,7 +16989,7 @@ end
local cached,loaded,reused,thresholds,handlers={},{},{},{},{}
local function runcurl(name,cachename)
local command="curl --silent --insecure --create-dirs --output "..cachename.." "..name
- os.spawn(command)
+ os.execute(command)
end
local function fetch(specification)
local original=specification.original
@@ -16150,7 +17121,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-lua"] = package.loaded["data-lua"] or true
--- original size: 4237, stripped down to: 3177
+-- original size: 4313, stripped down to: 3227
if not modules then modules={} end modules ['data-lua']={
version=1.001,
@@ -16159,7 +17130,7 @@ if not modules then modules={} end modules ['data-lua']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local resolvers,package=resolvers,package
+local package,lpeg=package,lpeg
local gsub=string.gsub
local concat=table.concat
local addsuffix=file.addsuffix
@@ -16170,9 +17141,11 @@ local luaformats={ 'TEXINPUTS','LUAINPUTS' }
local libformats={ 'CLUAINPUTS' }
local helpers=package.helpers or {}
local methods=helpers.methods or {}
+local resolvers=resolvers
+local resolveprefix=resolvers.resolve
+helpers.report=logs.reporter("resolvers","libraries")
trackers.register("resolvers.libraries",function(v) helpers.trace=v end)
trackers.register("resolvers.locating",function(v) helpers.trace=v end)
-helpers.report=logs.reporter("resolvers","libraries")
helpers.sequence={
"already loaded",
"preload table",
@@ -16187,7 +17160,7 @@ helpers.sequence={
}
local pattern=Cs(P("!")^0/""*(P("/")*P(-1)/"/"+P("/")^1/"/"+1)^0)
function helpers.cleanpath(path)
- return resolvers.resolve(lpegmatch(pattern,path))
+ return resolveprefix(lpegmatch(pattern,path))
end
local loadedaslib=helpers.loadedaslib
local getextraluapaths=package.extraluapaths
@@ -16324,7 +17297,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-tmf"] = package.loaded["data-tmf"] or true
--- original size: 2600, stripped down to: 1627
+-- original size: 2601, stripped down to: 1627
if not modules then modules={} end modules ['data-tmf']={
version=1.001,
@@ -16380,7 +17353,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["data-lst"] = package.loaded["data-lst"] or true
--- original size: 2654, stripped down to: 2301
+-- original size: 2734, stripped down to: 2354
if not modules then modules={} end modules ['data-lst']={
version=1.001,
@@ -16389,10 +17362,13 @@ if not modules then modules={} end modules ['data-lst']={
copyright="PRAGMA ADE / ConTeXt Development Team",
license="see context related readme files"
}
-local find,concat,upper,format=string.find,table.concat,string.upper,string.format
+local rawget,type,next=rawget,type,next
+local find,concat,upper=string.find,table.concat,string.upper
local fastcopy,sortedpairs=table.fastcopy,table.sortedpairs
-resolvers.listers=resolvers.listers or {}
local resolvers=resolvers
+local listers=resolvers.listers or {}
+resolvers.listers=listers
+local resolveprefix=resolvers.resolve
local report_lists=logs.reporter("resolvers","lists")
local function tabstr(str)
if type(str)=='table' then
@@ -16401,7 +17377,7 @@ local function tabstr(str)
return str
end
end
-function resolvers.listers.variables(pattern)
+function listers.variables(pattern)
local instance=resolvers.instance
local environment=instance.environment
local variables=instance.variables
@@ -16422,10 +17398,10 @@ function resolvers.listers.variables(pattern)
for key,value in sortedpairs(configured) do
if key~="" and (pattern=="" or find(upper(key),pattern)) then
report_lists(key)
- report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
- report_lists(" var: %s",tabstr(configured[key]) or "unset")
- report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
- report_lists(" res: %s",tabstr(resolvers.resolve(expansions[key])) or "unset")
+ report_lists(" env: %s",tabstr(rawget(environment,key)) or "unset")
+ report_lists(" var: %s",tabstr(configured[key]) or "unset")
+ report_lists(" exp: %s",tabstr(expansions[key]) or "unset")
+ report_lists(" res: %s",tabstr(resolveprefix(expansions[key])) or "unset")
end
end
instance.environment=fastcopy(env)
@@ -16433,15 +17409,15 @@ function resolvers.listers.variables(pattern)
instance.expansions=fastcopy(exp)
end
local report_resolved=logs.reporter("system","resolved")
-function resolvers.listers.configurations()
+function listers.configurations()
local configurations=resolvers.instance.specification
for i=1,#configurations do
- report_resolved("file : %s",resolvers.resolve(configurations[i]))
+ report_resolved("file : %s",resolveprefix(configurations[i]))
end
report_resolved("")
local list=resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.luacnfspec))
for i=1,#list do
- local li=resolvers.resolve(list[i])
+ local li=resolveprefix(list[i])
if lfs.isdir(li) then
report_resolved("path - %s",li)
else
@@ -16746,7 +17722,7 @@ do -- create closure to overcome 200 locals limit
package.loaded["luat-fmt"] = package.loaded["luat-fmt"] or true
--- original size: 5951, stripped down to: 4922
+-- original size: 5955, stripped down to: 4926
if not modules then modules={} end modules ['luat-fmt']={
version=1.001,
@@ -16834,7 +17810,7 @@ function environment.make_format(name)
end
local command=format("%s --ini %s --lua=%s %s %sdump",engine,primaryflags(),quoted(usedluastub),quoted(fulltexsourcename),os.platform=="unix" and "\\\\" or "\\")
report_format("running command: %s\n",command)
- os.spawn(command)
+ os.execute(command)
local pattern=file.removesuffix(file.basename(usedluastub)).."-*.mem"
local mp=dir.glob(pattern)
if mp then
@@ -16869,7 +17845,7 @@ function environment.run_format(name,data,more)
else
local command=format("%s %s --fmt=%s --lua=%s %s %s",engine,primaryflags(),quoted(barename),quoted(luaname),quoted(data),more~="" and quoted(more) or "")
report_format("running command: %s",command)
- os.spawn(command)
+ os.execute(command)
end
end
end
@@ -16880,8 +17856,8 @@ end -- of closure
-- used libraries : l-lua.lua l-package.lua l-lpeg.lua l-function.lua l-string.lua l-table.lua l-io.lua l-number.lua l-set.lua l-os.lua l-file.lua l-gzip.lua l-md5.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-sto.lua util-prs.lua util-fmt.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-mrg.lua util-tpl.lua util-env.lua luat-env.lua lxml-tab.lua lxml-lpt.lua lxml-mis.lua lxml-aux.lua lxml-xml.lua trac-xml.lua data-ini.lua data-exp.lua data-env.lua data-tmp.lua data-met.lua data-res.lua data-pre.lua data-inp.lua data-out.lua data-fil.lua data-con.lua data-use.lua data-zip.lua data-tre.lua data-sch.lua data-lua.lua data-aux.lua data-tmf.lua data-lst.lua util-lib.lua luat-sta.lua luat-fmt.lua
-- skipped libraries : -
--- original bytes : 695180
--- stripped bytes : 246794
+-- original bytes : 739251
+-- stripped bytes : 264497
-- end library merge
@@ -17107,6 +18083,7 @@ local helpinfo = [[
<category name="basic">
<subcategory>
<flag name="script"><short>run an mtx script (lua prefered method) (<ref name="noquotes"/>), no script gives list</short></flag>
+ <flag name="evaluate"><short>run code passed on the commandline (between quotes)</short></flag>
<flag name="execute"><short>run a script or program (texmfstart method) (<ref name="noquotes"/>)</short></flag>
<flag name="resolve"><short>resolve prefixed arguments</short></flag>
<flag name="ctxlua"><short>run internally (using preloaded libs)</short></flag>
@@ -17132,6 +18109,7 @@ local helpinfo = [[
<flag name="verbose"><short>give a bit more info</short></flag>
<flag name="trackers" value="list"><short>enable given trackers</short></flag>
<flag name="progname" value="str"><short>format or backend</short></flag>
+ <flag name="systeminfo" value="str"><short>show current operating system, processor, etc</short></flag>
</subcategory>
<subcategory>
<flag name="edit"><short>launch editor with found file</short></flag>
@@ -17761,6 +18739,39 @@ function runners.associate(filename)
os.launch(filename)
end
+function runners.evaluate(code,filename) -- for Luigi
+ if code == "loop" then
+ while true do
+ io.write("> ")
+ local code = io.read()
+ if code ~= "" then
+ local temp = string.match(code,"^= (.*)$")
+ if temp then
+ code = "print("..temp..")"
+ end
+ local compiled, message = loadstring(code)
+ if type(compiled) ~= "function" then
+ io.write("! " .. (message or code).."\n")
+ else
+ io.write(compiled())
+ end
+ end
+ end
+ else
+ if type(code) ~= "string" or code == "" then
+ code = filename
+ end
+ if code ~= "" then
+ local compiled, message = loadstring(code)
+ if type(compiled) ~= "function" then
+ io.write("invalid lua code: " .. (message or code))
+ return
+ end
+ io.write(compiled())
+ end
+ end
+end
+
function runners.gethelp(filename)
local url = environment.argument("url")
if url and url ~= "" then
@@ -17772,6 +18783,15 @@ function runners.gethelp(filename)
end
end
+function runners.systeminfo()
+ report("architecture : %s",os.platform or "<unset>")
+ report("operating system : %s",os.name or "<unset>")
+ report("file architecture : %s",os.type or "<unset>")
+ report("binary path : %s",os.selfdir or "<unset>")
+ report("binary suffix : %s",os.binsuffix or "<unset>")
+ report("library suffix : %s",os.libsuffix or "<unset>")
+end
+
-- 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
-- ... later we will use the second half
@@ -17887,16 +18907,7 @@ end
if e_argument("ansi") then
- local formatters = string.formatters
-
- logs.setformatters {
- report_yes = formatters["%-15s | %s"],
- report_nop = formatters["%-15s |"],
- subreport_yes = formatters["%-15s | %s | %s"],
- subreport_nop = formatters["%-15s | %s |"],
- status_yes = formatters["%-15s : %s\n"],
- status_nop = formatters["%-15s :\n"],
- }
+ logs.setformatters("ansi")
local script = e_argument("script") or e_argument("scripts")
@@ -17921,6 +18932,10 @@ if e_argument("script") or e_argument("scripts") then
ok = runners.execute_ctx_script(filename)
end
+elseif e_argument("evaluate") then
+
+ runners.evaluate(e_argument("evaluate"),filename)
+
elseif e_argument("selfmerge") then
-- embed used libraries
@@ -18213,6 +19228,10 @@ elseif e_argument("exporthelp") then
runners.loadbase()
application.export(e_argument("exporthelp"),filename)
+elseif e_argument("systeminfo") then
+
+ runners.systeminfo()
+
elseif e_argument("help") or filename=='help' or filename == "" then
application.help()