summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorElie Roux <elie.roux@telecom-bretagne.eu>2013-05-16 02:27:11 -0700
committerElie Roux <elie.roux@telecom-bretagne.eu>2013-05-16 02:27:11 -0700
commit1e629e2d39ceeca74aebc4786bcc79fe59a8ae16 (patch)
tree2e05507117aa41955a1c0096532107c151567b79
parent087a990dc8581be3a2980034e70f874d52f9577b (diff)
parentf75c554094c233227426668fed6192b9711c4304 (diff)
downloadluaotfload-1e629e2d39ceeca74aebc4786bcc79fe59a8ae16.tar.gz
Merge pull request #76 from phi-gamma/master
leave creating cache directories to the fontloader
-rw-r--r--luaotfload-basics-gen.lua33
-rw-r--r--luaotfload-blacklist.cnf5
-rw-r--r--luaotfload-filesystem-merged.lua2327
-rw-r--r--luaotfload-lib-dir.lua470
-rw-r--r--luaotfload-merged.lua30
-rw-r--r--luaotfload.dtx36
6 files changed, 527 insertions, 2374 deletions
diff --git a/luaotfload-basics-gen.lua b/luaotfload-basics-gen.lua
index 61f3910..0561778 100644
--- a/luaotfload-basics-gen.lua
+++ b/luaotfload-basics-gen.lua
@@ -11,9 +11,14 @@ if context then
os.exit()
end
-local dummyfunction = function() end
------ dummyreporter = function(c) return function(...) texio.write_nl(c .. " : " .. string.format(...)) end end
-local dummyreporter = function(c) return function(...) texio.write_nl(c .. " : " .. string.formatters(...)) end end
+local dummyfunction = function()
+end
+
+local dummyreporter = function(c)
+ return function(...)
+ (texio.reporter or texio.write_nl)(c .. " : " .. string.formatters(...))
+ end
+end
statistics = {
register = dummyfunction,
@@ -140,16 +145,24 @@ end
do
+ -- standard context tree setup
+
local cachepaths = kpse.expand_path('$TEXMFCACHE') or ""
+ -- quite like tex live or so
+
if cachepaths == "" then
cachepaths = kpse.expand_path('$TEXMFVAR')
end
+ -- this also happened to be used
+
if cachepaths == "" then
cachepaths = kpse.expand_path('$VARTEXMF')
end
+ -- and this is a last resort
+
if cachepaths == "" then
cachepaths = "."
end
@@ -157,8 +170,15 @@ do
cachepaths = string.split(cachepaths,os.type == "windows" and ";" or ":")
for i=1,#cachepaths do
- if file.is_writable(cachepaths[i]) then
- writable = file.join(cachepaths[i],"luatex-cache")
+ local cachepath = cachepaths[i]
+ if not lfs.isdir(cachepath) then
+ lfs.mkdirs(cachepath) -- needed for texlive and latex
+ if lfs.isdir(cachepath) then
+ texio.write(string.format("(created cache path: %s)",cachepath))
+ end
+ end
+ if file.is_writable(cachepath) then
+ writable = file.join(cachepath,"luatex-cache")
lfs.mkdir(writable)
writable = file.join(writable,caches.namespace)
lfs.mkdir(writable)
@@ -205,7 +225,6 @@ end
local function makefullname(path,name)
if path and path ~= "" then
- name = "temp-" .. name -- clash prevention
return file.addsuffix(file.join(path,name),"lua"), file.addsuffix(file.join(path,name),usingjit and "lub" or "luc")
end
end
@@ -290,7 +309,7 @@ function caches.compile(data,luaname,lucname)
d = table.serialize(data,true) -- slow
end
if d and d ~= "" then
- local f = io.open(lucname,'w')
+ local f = io.open(lucname,'wb')
if f then
local s = loadstring(d)
if s then
diff --git a/luaotfload-blacklist.cnf b/luaotfload-blacklist.cnf
index 2a21091..5f80e24 100644
--- a/luaotfload-blacklist.cnf
+++ b/luaotfload-blacklist.cnf
@@ -4,4 +4,7 @@ LastResort.ttf % a MacOSX font, but also available for free from unicode.org
lingoes.ttf
% http://tug.org/pipermail/luatex/2013-May/004239.html
Diablindall.ttf
-
+spltfgbd.ttf
+spltfgbi.ttf
+spltfgit.ttf
+spltfgrg.ttf
diff --git a/luaotfload-filesystem-merged.lua b/luaotfload-filesystem-merged.lua
deleted file mode 100644
index 1220fd8..0000000
--- a/luaotfload-filesystem-merged.lua
+++ /dev/null
@@ -1,2327 +0,0 @@
--- merged file : luaotfload-filesystem-merged.lua
--- parent file : luaotfload-filesystem.lua
--- merge date : Tue May 14 12:58:57 2013
-
-do -- begin closure to overcome local limits and interference
-
-if not modules then modules={} end modules ['l-lua']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local major,minor=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$")
-_MAJORVERSION=tonumber(major) or 5
-_MINORVERSION=tonumber(minor) or 1
-_LUAVERSION=_MAJORVERSION+_MINORVERSION/10
-if not lpeg then
- lpeg=require("lpeg")
-end
-if loadstring then
- local loadnormal=load
- function load(first,...)
- if type(first)=="string" then
- return loadstring(first,...)
- else
- return loadnormal(first,...)
- end
- end
-else
- loadstring=load
-end
-if not ipairs then
- local function iterate(a,i)
- i=i+1
- local v=a[i]
- if v~=nil then
- return i,v
- end
- end
- function ipairs(a)
- return iterate,a,0
- end
-end
-if not pairs then
- function pairs(t)
- return next,t
- end
-end
-if not table.unpack then
- table.unpack=_G.unpack
-elseif not unpack then
- _G.unpack=table.unpack
-end
-if not package.loaders then
- package.loaders=package.searchers
-end
-local print,select,tostring=print,select,tostring
-local inspectors={}
-function setinspector(inspector)
- inspectors[#inspectors+1]=inspector
-end
-function inspect(...)
- for s=1,select("#",...) do
- local value=select(s,...)
- local done=false
- for i=1,#inspectors do
- done=inspectors[i](value)
- if done then
- break
- end
- end
- if not done then
- print(tostring(value))
- end
- end
-end
-local dummy=function() end
-function optionalrequire(...)
- local ok,result=xpcall(require,dummy,...)
- if ok then
- return result
- end
-end
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
-if not modules then modules={} end modules ['l-lpeg']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-lpeg=require("lpeg")
-local type,next,tostring=type,next,tostring
-local byte,char,gmatch,format=string.byte,string.char,string.gmatch,string.format
-local floor=math.floor
-local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt
-local lpegtype,lpegmatch,lpegprint=lpeg.type,lpeg.match,lpeg.print
-setinspector(function(v) if lpegtype(v) then lpegprint(v) return true end end)
-lpeg.patterns=lpeg.patterns or {}
-local patterns=lpeg.patterns
-local anything=P(1)
-local endofstring=P(-1)
-local alwaysmatched=P(true)
-patterns.anything=anything
-patterns.endofstring=endofstring
-patterns.beginofstring=alwaysmatched
-patterns.alwaysmatched=alwaysmatched
-local digit,sign=R('09'),S('+-')
-local cr,lf,crlf=P("\r"),P("\n"),P("\r\n")
-local newline=crlf+S("\r\n")
-local escaped=P("\\")*anything
-local squote=P("'")
-local dquote=P('"')
-local space=P(" ")
-local utfbom_32_be=P('\000\000\254\255')
-local utfbom_32_le=P('\255\254\000\000')
-local utfbom_16_be=P('\255\254')
-local utfbom_16_le=P('\254\255')
-local utfbom_8=P('\239\187\191')
-local utfbom=utfbom_32_be+utfbom_32_le+utfbom_16_be+utfbom_16_le+utfbom_8
-local utftype=utfbom_32_be*Cc("utf-32-be")+utfbom_32_le*Cc("utf-32-le")+utfbom_16_be*Cc("utf-16-be")+utfbom_16_le*Cc("utf-16-le")+utfbom_8*Cc("utf-8")+alwaysmatched*Cc("utf-8")
-local utfoffset=utfbom_32_be*Cc(4)+utfbom_32_le*Cc(4)+utfbom_16_be*Cc(2)+utfbom_16_le*Cc(2)+utfbom_8*Cc(3)+Cc(0)
-local utf8next=R("\128\191")
-patterns.utf8one=R("\000\127")
-patterns.utf8two=R("\194\223")*utf8next
-patterns.utf8three=R("\224\239")*utf8next*utf8next
-patterns.utf8four=R("\240\244")*utf8next*utf8next*utf8next
-patterns.utfbom=utfbom
-patterns.utftype=utftype
-patterns.utfoffset=utfoffset
-local utf8char=patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four
-local validutf8char=utf8char^0*endofstring*Cc(true)+Cc(false)
-local utf8character=P(1)*R("\128\191")^0
-patterns.utf8=utf8char
-patterns.utf8char=utf8char
-patterns.utf8character=utf8character
-patterns.validutf8=validutf8char
-patterns.validutf8char=validutf8char
-local eol=S("\n\r")
-local spacer=S(" \t\f\v")
-local whitespace=eol+spacer
-local nonspacer=1-spacer
-local nonwhitespace=1-whitespace
-patterns.eol=eol
-patterns.spacer=spacer
-patterns.whitespace=whitespace
-patterns.nonspacer=nonspacer
-patterns.nonwhitespace=nonwhitespace
-local stripper=spacer^0*C((spacer^0*nonspacer^1)^0)
-local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0))
-patterns.stripper=stripper
-patterns.collapser=collapser
-patterns.digit=digit
-patterns.sign=sign
-patterns.cardinal=sign^0*digit^1
-patterns.integer=sign^0*digit^1
-patterns.unsigned=digit^0*P('.')*digit^1
-patterns.float=sign^0*patterns.unsigned
-patterns.cunsigned=digit^0*P(',')*digit^1
-patterns.cfloat=sign^0*patterns.cunsigned
-patterns.number=patterns.float+patterns.integer
-patterns.cnumber=patterns.cfloat+patterns.integer
-patterns.oct=P("0")*R("07")^1
-patterns.octal=patterns.oct
-patterns.HEX=P("0x")*R("09","AF")^1
-patterns.hex=P("0x")*R("09","af")^1
-patterns.hexadecimal=P("0x")*R("09","AF","af")^1
-patterns.lowercase=R("az")
-patterns.uppercase=R("AZ")
-patterns.letter=patterns.lowercase+patterns.uppercase
-patterns.space=space
-patterns.tab=P("\t")
-patterns.spaceortab=patterns.space+patterns.tab
-patterns.newline=newline
-patterns.emptyline=newline^1
-patterns.equal=P("=")
-patterns.comma=P(",")
-patterns.commaspacer=P(",")*spacer^0
-patterns.period=P(".")
-patterns.colon=P(":")
-patterns.semicolon=P(";")
-patterns.underscore=P("_")
-patterns.escaped=escaped
-patterns.squote=squote
-patterns.dquote=dquote
-patterns.nosquote=(escaped+(1-squote))^0
-patterns.nodquote=(escaped+(1-dquote))^0
-patterns.unsingle=(squote/"")*patterns.nosquote*(squote/"")
-patterns.undouble=(dquote/"")*patterns.nodquote*(dquote/"")
-patterns.unquoted=patterns.undouble+patterns.unsingle
-patterns.unspacer=((patterns.spacer^1)/"")^0
-patterns.singlequoted=squote*patterns.nosquote*squote
-patterns.doublequoted=dquote*patterns.nodquote*dquote
-patterns.quoted=patterns.doublequoted+patterns.singlequoted
-patterns.propername=R("AZ","az","__")*R("09","AZ","az","__")^0*P(-1)
-patterns.somecontent=(anything-newline-space)^1
-patterns.beginline=#(1-newline)
-patterns.longtostring=Cs(whitespace^0/""*nonwhitespace^0*((whitespace^0/" "*(patterns.quoted+nonwhitespace)^1)^0))
-local function anywhere(pattern)
- return P { P(pattern)+1*V(1) }
-end
-lpeg.anywhere=anywhere
-function lpeg.instringchecker(p)
- p=anywhere(p)
- return function(str)
- return lpegmatch(p,str) and true or false
- end
-end
-function lpeg.splitter(pattern,action)
- return (((1-P(pattern))^1)/action+1)^0
-end
-function lpeg.tsplitter(pattern,action)
- return Ct((((1-P(pattern))^1)/action+1)^0)
-end
-local splitters_s,splitters_m,splitters_t={},{},{}
-local function splitat(separator,single)
- local splitter=(single and splitters_s[separator]) or splitters_m[separator]
- if not splitter then
- separator=P(separator)
- local other=C((1-separator)^0)
- if single then
- local any=anything
- splitter=other*(separator*C(any^0)+"")
- splitters_s[separator]=splitter
- else
- splitter=other*(separator*other)^0
- splitters_m[separator]=splitter
- end
- end
- return splitter
-end
-local function tsplitat(separator)
- local splitter=splitters_t[separator]
- if not splitter then
- splitter=Ct(splitat(separator))
- splitters_t[separator]=splitter
- end
- return splitter
-end
-lpeg.splitat=splitat
-lpeg.tsplitat=tsplitat
-function string.splitup(str,separator)
- if not separator then
- separator=","
- end
- return lpegmatch(splitters_m[separator] or splitat(separator),str)
-end
-local cache={}
-function lpeg.split(separator,str)
- local c=cache[separator]
- if not c then
- c=tsplitat(separator)
- cache[separator]=c
- end
- return lpegmatch(c,str)
-end
-function string.split(str,separator)
- if separator then
- local c=cache[separator]
- if not c then
- c=tsplitat(separator)
- cache[separator]=c
- end
- return lpegmatch(c,str)
- else
- return { str }
- end
-end
-local spacing=patterns.spacer^0*newline
-local empty=spacing*Cc("")
-local nonempty=Cs((1-spacing)^1)*spacing^-1
-local content=(empty+nonempty)^1
-patterns.textline=content
-local linesplitter=tsplitat(newline)
-patterns.linesplitter=linesplitter
-function string.splitlines(str)
- return lpegmatch(linesplitter,str)
-end
-local cache={}
-function lpeg.checkedsplit(separator,str)
- local c=cache[separator]
- if not c then
- separator=P(separator)
- local other=C((1-separator)^1)
- c=Ct(separator^0*other*(separator^1*other)^0)
- cache[separator]=c
- end
- return lpegmatch(c,str)
-end
-function string.checkedsplit(str,separator)
- local c=cache[separator]
- if not c then
- separator=P(separator)
- local other=C((1-separator)^1)
- c=Ct(separator^0*other*(separator^1*other)^0)
- cache[separator]=c
- end
- return lpegmatch(c,str)
-end
-local function f2(s) local c1,c2=byte(s,1,2) return c1*64+c2-12416 end
-local function f3(s) local c1,c2,c3=byte(s,1,3) return (c1*64+c2)*64+c3-925824 end
-local function f4(s) local c1,c2,c3,c4=byte(s,1,4) return ((c1*64+c2)*64+c3)*64+c4-63447168 end
-local utf8byte=patterns.utf8one/byte+patterns.utf8two/f2+patterns.utf8three/f3+patterns.utf8four/f4
-patterns.utf8byte=utf8byte
-local cache={}
-function lpeg.stripper(str)
- if type(str)=="string" then
- local s=cache[str]
- if not s then
- s=Cs(((S(str)^1)/""+1)^0)
- cache[str]=s
- end
- return s
- else
- return Cs(((str^1)/""+1)^0)
- end
-end
-local cache={}
-function lpeg.keeper(str)
- if type(str)=="string" then
- local s=cache[str]
- if not s then
- s=Cs((((1-S(str))^1)/""+1)^0)
- cache[str]=s
- end
- return s
- else
- return Cs((((1-str)^1)/""+1)^0)
- end
-end
-function lpeg.frontstripper(str)
- return (P(str)+P(true))*Cs(anything^0)
-end
-function lpeg.endstripper(str)
- return Cs((1-P(str)*endofstring)^0)
-end
-function lpeg.replacer(one,two,makefunction,isutf)
- local pattern
- local u=isutf and utf8char or 1
- if type(one)=="table" then
- local no=#one
- local p=P(false)
- if no==0 then
- for k,v in next,one do
- p=p+P(k)/v
- end
- pattern=Cs((p+u)^0)
- elseif no==1 then
- local o=one[1]
- one,two=P(o[1]),o[2]
- pattern=Cs((one/two+u)^0)
- else
- for i=1,no do
- local o=one[i]
- p=p+P(o[1])/o[2]
- end
- pattern=Cs((p+u)^0)
- end
- else
- pattern=Cs((P(one)/(two or "")+u)^0)
- end
- if makefunction then
- return function(str)
- return lpegmatch(pattern,str)
- end
- else
- return pattern
- end
-end
-function lpeg.finder(lst,makefunction)
- local pattern
- if type(lst)=="table" then
- pattern=P(false)
- if #lst==0 then
- for k,v in next,lst do
- pattern=pattern+P(k)
- end
- else
- for i=1,#lst do
- pattern=pattern+P(lst[i])
- end
- end
- else
- pattern=P(lst)
- end
- pattern=(1-pattern)^0*pattern
- if makefunction then
- return function(str)
- return lpegmatch(pattern,str)
- end
- else
- return pattern
- end
-end
-local splitters_f,splitters_s={},{}
-function lpeg.firstofsplit(separator)
- local splitter=splitters_f[separator]
- if not splitter then
- separator=P(separator)
- splitter=C((1-separator)^0)
- splitters_f[separator]=splitter
- end
- return splitter
-end
-function lpeg.secondofsplit(separator)
- local splitter=splitters_s[separator]
- if not splitter then
- separator=P(separator)
- splitter=(1-separator)^0*separator*C(anything^0)
- splitters_s[separator]=splitter
- end
- return splitter
-end
-function lpeg.balancer(left,right)
- left,right=P(left),P(right)
- return P { left*((1-left-right)+V(1))^0*right }
-end
-local nany=utf8char/""
-function lpeg.counter(pattern)
- pattern=Cs((P(pattern)/" "+nany)^0)
- return function(str)
- return #lpegmatch(pattern,str)
- end
-end
-utf=utf or (unicode and unicode.utf8) or {}
-local utfcharacters=utf and utf.characters or string.utfcharacters
-local utfgmatch=utf and utf.gmatch
-local utfchar=utf and utf.char
-lpeg.UP=lpeg.P
-if utfcharacters then
- function lpeg.US(str)
- local p=P(false)
- for uc in utfcharacters(str) do
- p=p+P(uc)
- end
- return p
- end
-elseif utfgmatch then
- function lpeg.US(str)
- local p=P(false)
- for uc in utfgmatch(str,".") do
- p=p+P(uc)
- end
- return p
- end
-else
- function lpeg.US(str)
- local p=P(false)
- local f=function(uc)
- p=p+P(uc)
- end
- lpegmatch((utf8char/f)^0,str)
- return p
- end
-end
-local range=utf8byte*utf8byte+Cc(false)
-function lpeg.UR(str,more)
- local first,last
- if type(str)=="number" then
- first=str
- last=more or first
- else
- first,last=lpegmatch(range,str)
- if not last then
- return P(str)
- end
- end
- if first==last then
- return P(str)
- elseif utfchar and (last-first<8) then
- local p=P(false)
- for i=first,last do
- p=p+P(utfchar(i))
- end
- return p
- else
- local f=function(b)
- return b>=first and b<=last
- end
- return utf8byte/f
- end
-end
-function lpeg.is_lpeg(p)
- return p and lpegtype(p)=="pattern"
-end
-function lpeg.oneof(list,...)
- if type(list)~="table" then
- list={ list,... }
- end
- local p=P(list[1])
- for l=2,#list do
- p=p+P(list[l])
- end
- return p
-end
-local sort=table.sort
-local function copyindexed(old)
- local new={}
- for i=1,#old do
- new[i]=old
- end
- return new
-end
-local function sortedkeys(tab)
- local keys,s={},0
- for key,_ in next,tab do
- s=s+1
- keys[s]=key
- end
- sort(keys)
- return keys
-end
-function lpeg.append(list,pp,delayed,checked)
- local p=pp
- if #list>0 then
- local keys=copyindexed(list)
- sort(keys)
- for i=#keys,1,-1 do
- local k=keys[i]
- if p then
- p=P(k)+p
- else
- p=P(k)
- end
- end
- elseif delayed then
- local keys=sortedkeys(list)
- if p then
- for i=1,#keys,1 do
- local k=keys[i]
- local v=list[k]
- p=P(k)/list+p
- end
- else
- for i=1,#keys do
- local k=keys[i]
- local v=list[k]
- if p then
- p=P(k)+p
- else
- p=P(k)
- end
- end
- if p then
- p=p/list
- end
- end
- elseif checked then
- local keys=sortedkeys(list)
- for i=1,#keys do
- local k=keys[i]
- local v=list[k]
- if p then
- if k==v then
- p=P(k)+p
- else
- p=P(k)/v+p
- end
- else
- if k==v then
- p=P(k)
- else
- p=P(k)/v
- end
- end
- end
- else
- local keys=sortedkeys(list)
- for i=1,#keys do
- local k=keys[i]
- local v=list[k]
- if p then
- p=P(k)/v+p
- else
- p=P(k)/v
- end
- end
- end
- return p
-end
-local function make(t)
- local p
- 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)
- else
- p=p+P(k)
- end
- end
- end
- return p
-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]={}
- end
- t=t[c]
- end
- end
- return make(tree)
-end
-patterns.containseol=lpeg.finder(eol)
-local function nextstep(n,step,result)
- local m=n%step
- local d=floor(n/step)
- if d>0 then
- local v=V(tostring(step))
- local s=result.start
- for i=1,d do
- if s then
- s=v*s
- else
- s=v
- end
- end
- result.start=s
- end
- if step>1 and result.start then
- local v=V(tostring(step/2))
- result[tostring(step)]=v*v
- end
- if step>0 then
- return nextstep(m,step/2,result)
- else
- return result
- end
-end
-function lpeg.times(pattern,n)
- return P(nextstep(n,2^16,{ "start",["1"]=pattern }))
-end
-local digit=R("09")
-local period=P(".")
-local zero=P("0")
-local trailingzeros=zero^0*-digit
-local case_1=period*trailingzeros/""
-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
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
-if not modules then modules={} end modules ['l-string']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local string=string
-local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower
-local lpegmatch,patterns=lpeg.match,lpeg.patterns
-local P,S,C,Ct,Cc,Cs=lpeg.P,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cc,lpeg.Cs
-local unquoted=patterns.squote*C(patterns.nosquote)*patterns.squote+patterns.dquote*C(patterns.nodquote)*patterns.dquote
-function string.unquoted(str)
- return lpegmatch(unquoted,str) or str
-end
-function string.quoted(str)
- return format("%q",str)
-end
-function string.count(str,pattern)
- local n=0
- for _ in gmatch(str,pattern) do
- n=n+1
- end
- return n
-end
-function string.limit(str,n,sentinel)
- if #str>n then
- sentinel=sentinel or "..."
- return sub(str,1,(n-#sentinel))..sentinel
- else
- return str
- end
-end
-local stripper=patterns.stripper
-local collapser=patterns.collapser
-local longtostring=patterns.longtostring
-function string.strip(str)
- return lpegmatch(stripper,str) or ""
-end
-function string.collapsespaces(str)
- return lpegmatch(collapser,str) or ""
-end
-function string.longtostring(str)
- return lpegmatch(longtostring,str) or ""
-end
-local pattern=P(" ")^0*P(-1)
-function string.is_empty(str)
- if str=="" then
- return true
- else
- return lpegmatch(pattern,str) and true or false
- end
-end
-local anything=patterns.anything
-local allescapes=Cc("%")*S(".-+%?()[]*")
-local someescapes=Cc("%")*S(".-+%()[]")
-local matchescapes=Cc(".")*S("*?")
-local pattern_a=Cs ((allescapes+anything )^0 )
-local pattern_b=Cs ((someescapes+matchescapes+anything )^0 )
-local pattern_c=Cs (Cc("^")*(someescapes+matchescapes+anything )^0*Cc("$") )
-function string.escapedpattern(str,simple)
- return lpegmatch(simple and pattern_b or pattern_a,str)
-end
-function string.topattern(str,lowercase,strict)
- if str=="" or type(str)~="string" then
- return ".*"
- elseif strict then
- str=lpegmatch(pattern_c,str)
- else
- str=lpegmatch(pattern_b,str)
- end
- if lowercase then
- return lower(str)
- else
- return str
- end
-end
-function string.valid(str,default)
- return (type(str)=="string" and str~="" and str) or default or nil
-end
-string.itself=function(s) return s end
-local pattern=Ct(C(1)^0)
-function string.totable(str)
- return lpegmatch(pattern,str)
-end
-local replacer=lpeg.replacer("@","%%")
-function string.tformat(fmt,...)
- return format(lpegmatch(replacer,fmt),...)
-end
-string.quote=string.quoted
-string.unquote=string.unquoted
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
-if not modules then modules={} end modules ['l-table']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-local type,next,tostring,tonumber,ipairs,select=type,next,tostring,tonumber,ipairs,select
-local table,string=table,string
-local concat,sort,insert,remove=table.concat,table.sort,table.insert,table.remove
-local format,lower,dump=string.format,string.lower,string.dump
-local getmetatable,setmetatable=getmetatable,setmetatable
-local getinfo=debug.getinfo
-local lpegmatch,patterns=lpeg.match,lpeg.patterns
-local floor=math.floor
-local stripper=patterns.stripper
-function table.strip(tab)
- local lst,l={},0
- for i=1,#tab do
- local s=lpegmatch(stripper,tab[i]) or ""
- if s=="" then
- else
- l=l+1
- lst[l]=s
- end
- end
- return lst
-end
-function table.keys(t)
- if t then
- local keys,k={},0
- for key,_ in next,t do
- k=k+1
- keys[k]=key
- end
- return keys
- else
- return {}
- end
-end
-local function compare(a,b)
- local ta,tb=type(a),type(b)
- if ta==tb then
- return a<b
- else
- return tostring(a)<tostring(b)
- end
-end
-local function sortedkeys(tab)
- if tab then
- local srt,category,s={},0,0
- for key,_ in next,tab do
- s=s+1
- srt[s]=key
- if category==3 then
- else
- local tkey=type(key)
- if tkey=="string" then
- category=(category==2 and 3) or 1
- elseif tkey=="number" then
- category=(category==1 and 3) or 2
- else
- category=3
- end
- end
- end
- if category==0 or category==3 then
- sort(srt,compare)
- else
- sort(srt)
- end
- return srt
- else
- return {}
- end
-end
-local function sortedhashkeys(tab,cmp)
- if tab then
- local srt,s={},0
- for key,_ in next,tab do
- if key then
- s=s+1
- srt[s]=key
- end
- end
- sort(srt,cmp)
- return srt
- else
- return {}
- end
-end
-function table.allkeys(t)
- local keys={}
- for k,v in next,t do
- for k,v in next,v do
- keys[k]=true
- end
- end
- return sortedkeys(keys)
-end
-table.sortedkeys=sortedkeys
-table.sortedhashkeys=sortedhashkeys
-local function nothing() end
-local function sortedhash(t,cmp)
- if t 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 function kv(s)
- n=n+1
- local k=s[n]
- return k,t[k]
- end
- return kv,s
- else
- return nothing
- end
-end
-table.sortedhash=sortedhash
-table.sortedpairs=sortedhash
-function table.append(t,list)
- local n=#t
- for i=1,#list do
- n=n+1
- t[n]=list[i]
- end
- return t
-end
-function table.prepend(t,list)
- local nl=#list
- local nt=nl+#t
- for i=#t,1,-1 do
- t[nt]=t[i]
- nt=nt-1
- end
- for i=1,#list do
- t[i]=list[i]
- end
- return t
-end
-function table.merge(t,...)
- t=t or {}
- for i=1,select("#",...) do
- for k,v in next,(select(i,...)) do
- t[k]=v
- end
- end
- return t
-end
-function table.merged(...)
- local t={}
- for i=1,select("#",...) do
- for k,v in next,(select(i,...)) do
- t[k]=v
- end
- end
- return t
-end
-function table.imerge(t,...)
- local nt=#t
- for i=1,select("#",...) do
- local nst=select(i,...)
- for j=1,#nst do
- nt=nt+1
- t[nt]=nst[j]
- end
- end
- return t
-end
-function table.imerged(...)
- local tmp,ntmp={},0
- for i=1,select("#",...) do
- local nst=select(i,...)
- for j=1,#nst do
- ntmp=ntmp+1
- tmp[ntmp]=nst[j]
- end
- end
- return tmp
-end
-local function fastcopy(old,metatabletoo)
- if old then
- local new={}
- for k,v in next,old do
- if type(v)=="table" then
- new[k]=fastcopy(v,metatabletoo)
- else
- new[k]=v
- end
- end
- if metatabletoo then
- local mt=getmetatable(old)
- if mt then
- setmetatable(new,mt)
- end
- end
- return new
- else
- return {}
- end
-end
-local function copy(t,tables)
- tables=tables or {}
- local tcopy={}
- if not tables[t] then
- tables[t]=tcopy
- end
- for i,v in next,t do
- if type(i)=="table" then
- if tables[i] then
- i=tables[i]
- else
- i=copy(i,tables)
- end
- end
- if type(v)~="table" then
- tcopy[i]=v
- elseif tables[v] then
- tcopy[i]=tables[v]
- else
- tcopy[i]=copy(v,tables)
- end
- end
- local mt=getmetatable(t)
- if mt then
- setmetatable(tcopy,mt)
- end
- return tcopy
-end
-table.fastcopy=fastcopy
-table.copy=copy
-function table.derive(parent)
- local child={}
- if parent then
- setmetatable(child,{ __index=parent })
- end
- return child
-end
-function table.tohash(t,value)
- local h={}
- if t then
- if value==nil then value=true end
- for _,v in next,t do
- h[v]=value
- end
- end
- return h
-end
-function table.fromhash(t)
- local hsh,h={},0
- for k,v in next,t do
- if v then
- h=h+1
- hsh[h]=k
- end
- end
- return hsh
-end
-local noquotes,hexify,handle,reduce,compact,inline,functions
-local reserved=table.tohash {
- 'and','break','do','else','elseif','end','false','for','function','if',
- 'in','local','nil','not','or','repeat','return','then','true','until','while',
-}
-local function simple_table(t)
- if #t>0 then
- local n=0
- for _,v in next,t do
- n=n+1
- end
- if n==#t then
- local tt,nt={},0
- for i=1,#t do
- local v=t[i]
- local tv=type(v)
- if tv=="number" then
- nt=nt+1
- if hexify then
- tt[nt]=format("0x%04X",v)
- else
- tt[nt]=tostring(v)
- end
- elseif tv=="boolean" then
- nt=nt+1
- tt[nt]=tostring(v)
- elseif tv=="string" then
- nt=nt+1
- tt[nt]=format("%q",v)
- else
- tt=nil
- break
- end
- end
- return tt
- end
- end
- return nil
-end
-local propername=patterns.propername
-local function dummy() end
-local function do_serialize(root,name,depth,level,indexed)
- if level>0 then
- depth=depth.." "
- if indexed then
- handle(format("%s{",depth))
- else
- local tn=type(name)
- if tn=="number" then
- if hexify then
- handle(format("%s[0x%04X]={",depth,name))
- else
- handle(format("%s[%s]={",depth,name))
- end
- elseif tn=="string" then
- if noquotes and not reserved[name] and lpegmatch(propername,name) then
- handle(format("%s%s={",depth,name))
- else
- handle(format("%s[%q]={",depth,name))
- end
- elseif tn=="boolean" then
- handle(format("%s[%s]={",depth,tostring(name)))
- else
- handle(format("%s{",depth))
- end
- end
- end
- if root and next(root) then
- local first,last=nil,0
- if compact then
- last=#root
- for k=1,last do
- if root[k]==nil then
- last=k-1
- break
- end
- end
- if last>0 then
- first=1
- end
- end
- local sk=sortedkeys(root)
- for i=1,#sk do
- local k=sk[i]
- local v=root[k]
- local t,tk=type(v),type(k)
- if compact and first and tk=="number" and k>=first and k<=last then
- if t=="number" then
- if hexify then
- handle(format("%s 0x%04X,",depth,v))
- else
- handle(format("%s %s,",depth,v))
- end
- elseif t=="string" then
- if reduce and tonumber(v) then
- handle(format("%s %s,",depth,v))
- else
- handle(format("%s %q,",depth,v))
- end
- elseif t=="table" then
- if not next(v) then
- handle(format("%s {},",depth))
- elseif inline then
- local st=simple_table(v)
- if st then
- handle(format("%s { %s },",depth,concat(st,", ")))
- else
- do_serialize(v,k,depth,level+1,true)
- end
- else
- do_serialize(v,k,depth,level+1,true)
- end
- elseif t=="boolean" then
- handle(format("%s %s,",depth,tostring(v)))
- elseif t=="function" then
- if functions then
- handle(format('%s load(%q),',depth,dump(v)))
- else
- handle(format('%s "function",',depth))
- end
- else
- handle(format("%s %q,",depth,tostring(v)))
- end
- elseif k=="__p__" then
- if false then
- handle(format("%s __p__=nil,",depth))
- end
- elseif t=="number" then
- if tk=="number" then
- if hexify then
- handle(format("%s [0x%04X]=0x%04X,",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,tostring(k),v))
- else
- handle(format("%s [%s]=%s,",depth,tostring(k),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))
- else
- handle(format("%s %s=%s,",depth,k,v))
- end
- else
- if hexify then
- handle(format("%s [%q]=0x%04X,",depth,k,v))
- else
- handle(format("%s [%q]=%s,",depth,k,v))
- end
- end
- elseif t=="string" then
- if reduce and tonumber(v) then
- if tk=="number" then
- if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,v))
- else
- handle(format("%s [%s]=%s,",depth,k,v))
- end
- elseif tk=="boolean" then
- handle(format("%s [%s]=%s,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s=%s,",depth,k,v))
- else
- handle(format("%s [%q]=%s,",depth,k,v))
- end
- else
- if tk=="number" then
- if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,v))
- else
- handle(format("%s [%s]=%q,",depth,k,v))
- end
- elseif tk=="boolean" then
- handle(format("%s [%s]=%q,",depth,tostring(k),v))
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s=%q,",depth,k,v))
- else
- handle(format("%s [%q]=%q,",depth,k,v))
- end
- end
- elseif t=="table" then
- if not next(v) then
- if tk=="number" then
- if hexify then
- handle(format("%s [0x%04X]={},",depth,k))
- else
- handle(format("%s [%s]={},",depth,k))
- end
- elseif tk=="boolean" then
- handle(format("%s [%s]={},",depth,tostring(k)))
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s={},",depth,k))
- else
- handle(format("%s [%q]={},",depth,k))
- end
- elseif inline then
- local st=simple_table(v)
- if st then
- if tk=="number" then
- if hexify then
- handle(format("%s [0x%04X]={ %s },",depth,k,concat(st,", ")))
- else
- handle(format("%s [%s]={ %s },",depth,k,concat(st,", ")))
- end
- elseif tk=="boolean" then
- handle(format("%s [%s]={ %s },",depth,tostring(k),concat(st,", ")))
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s={ %s },",depth,k,concat(st,", ")))
- else
- handle(format("%s [%q]={ %s },",depth,k,concat(st,", ")))
- end
- else
- do_serialize(v,k,depth,level+1)
- end
- else
- do_serialize(v,k,depth,level+1)
- end
- elseif t=="boolean" then
- if tk=="number" then
- if hexify then
- handle(format("%s [0x%04X]=%s,",depth,k,tostring(v)))
- else
- handle(format("%s [%s]=%s,",depth,k,tostring(v)))
- end
- elseif tk=="boolean" then
- handle(format("%s [%s]=%s,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s=%s,",depth,k,tostring(v)))
- else
- handle(format("%s [%q]=%s,",depth,k,tostring(v)))
- end
- elseif t=="function" then
- if functions then
- 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))
- else
- handle(format("%s [%s]=load(%q),",depth,k,f))
- end
- elseif tk=="boolean" then
- handle(format("%s [%s]=load(%q),",depth,tostring(k),f))
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s=load(%q),",depth,k,f))
- else
- handle(format("%s [%q]=load(%q),",depth,k,f))
- end
- end
- else
- if tk=="number" then
- if hexify then
- handle(format("%s [0x%04X]=%q,",depth,k,tostring(v)))
- else
- handle(format("%s [%s]=%q,",depth,k,tostring(v)))
- end
- elseif tk=="boolean" then
- handle(format("%s [%s]=%q,",depth,tostring(k),tostring(v)))
- elseif noquotes and not reserved[k] and lpegmatch(propername,k) then
- handle(format("%s %s=%q,",depth,k,tostring(v)))
- else
- handle(format("%s [%q]=%q,",depth,k,tostring(v)))
- end
- end
- end
- end
- if level>0 then
- handle(format("%s},",depth))
- end
-end
-local function serialize(_handle,root,name,specification)
- local tname=type(name)
- if type(specification)=="table" then
- noquotes=specification.noquotes
- hexify=specification.hexify
- handle=_handle or specification.handle or print
- reduce=specification.reduce or false
- functions=specification.functions
- compact=specification.compact
- inline=specification.inline and compact
- if functions==nil then
- functions=true
- end
- if compact==nil then
- compact=true
- end
- if inline==nil then
- inline=compact
- end
- else
- noquotes=false
- hexify=false
- handle=_handle or print
- reduce=false
- compact=true
- inline=true
- functions=true
- end
- if tname=="string" then
- if name=="return" then
- handle("return {")
- else
- handle(name.."={")
- end
- elseif tname=="number" then
- if hexify then
- handle(format("[0x%04X]={",name))
- else
- handle("["..name.."]={")
- end
- elseif tname=="boolean" then
- if name then
- handle("return {")
- else
- handle("{")
- end
- else
- handle("t={")
- end
- if root then
- if getmetatable(root) then
- 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
- do_serialize(root,name,"",0)
- end
- end
- handle("}")
-end
-function table.serialize(root,name,specification)
- local t,n={},0
- local function flush(s)
- n=n+1
- t[n]=s
- end
- serialize(flush,root,name,specification)
- return concat(t,"\n")
-end
-table.tohandle=serialize
-local maxtab=2*1024
-function table.tofile(filename,root,name,specification)
- local f=io.open(filename,'w')
- if f then
- if maxtab>1 then
- local t,n={},0
- local function flush(s)
- n=n+1
- t[n]=s
- if n>maxtab then
- f:write(concat(t,"\n"),"\n")
- t,n={},0
- end
- end
- serialize(flush,root,name,specification)
- f:write(concat(t,"\n"),"\n")
- else
- local function flush(s)
- f:write(s,"\n")
- end
- serialize(flush,root,name,specification)
- end
- f:close()
- io.flush()
- end
-end
-local function flattened(t,f,depth)
- if f==nil then
- f={}
- depth=0xFFFF
- elseif tonumber(f) then
- depth=f
- f={}
- elseif not depth then
- depth=0xFFFF
- end
- for k,v in next,t do
- if type(k)~="number" then
- if depth>0 and type(v)=="table" then
- flattened(v,f,depth-1)
- else
- f[#f+1]=v
- end
- end
- end
- for k=1,#t do
- local v=t[k]
- if depth>0 and type(v)=="table" then
- flattened(v,f,depth-1)
- else
- f[#f+1]=v
- end
- end
- return f
-end
-table.flattened=flattened
-local function unnest(t,f)
- if not f then
- f={}
- end
- for i=1,#t do
- local v=t[i]
- if type(v)=="table" then
- if type(v[1])=="table" then
- unnest(v,f)
- else
- f[#f+1]=v
- end
- else
- f[#f+1]=v
- end
- end
- return f
-end
-function table.unnest(t)
- return unnest(t)
-end
-local function are_equal(a,b,n,m)
- if a and b and #a==#b then
- n=n or 1
- m=m or #a
- for i=n,m do
- local ai,bi=a[i],b[i]
- if ai==bi then
- elseif type(ai)=="table" and type(bi)=="table" then
- if not are_equal(ai,bi) then
- return false
- end
- else
- return false
- end
- end
- return true
- else
- return false
- end
-end
-local function identical(a,b)
- for ka,va in next,a do
- local vb=b[ka]
- if va==vb then
- elseif type(va)=="table" and type(vb)=="table" then
- if not identical(va,vb) then
- return false
- end
- else
- return false
- end
- end
- return true
-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
- end
- end
- end
-end
-function table.contains(t,v)
- if t then
- for i=1,#t do
- if t[i]==v then
- return i
- end
- end
- end
- return false
-end
-function table.count(t)
- local n=0
- for k,v in next,t do
- n=n+1
- end
- return n
-end
-function table.swapped(t,s)
- local n={}
- if s then
- for k,v in next,s do
- n[k]=v
- end
- end
- for k,v in next,t do
- n[v]=k
- end
- return n
-end
-function table.mirrored(t)
- local n={}
- for k,v in next,t do
- n[v]=k
- n[k]=v
- end
- return n
-end
-function table.reversed(t)
- if t then
- local tt,tn={},#t
- if tn>0 then
- local ttn=0
- for i=tn,1,-1 do
- ttn=ttn+1
- tt[ttn]=t[i]
- end
- end
- return tt
- end
-end
-function table.reverse(t)
- if t then
- local n=#t
- for i=1,floor(n/2) do
- local j=n-i+1
- t[i],t[j]=t[j],t[i]
- end
- return t
- end
-end
-function table.sequenced(t,sep,simple)
- if not t then
- return ""
- end
- local n=#t
- local s={}
- if n>0 then
- for i=1,n do
- s[i]=tostring(t[i])
- end
- else
- n=0
- for k,v in sortedhash(t) do
- if simple then
- if v==true then
- n=n+1
- s[n]=k
- elseif v and v~="" then
- n=n+1
- s[n]=k.."="..tostring(v)
- end
- else
- n=n+1
- s[n]=k.."="..tostring(v)
- end
- end
- end
- return concat(s,sep or " | ")
-end
-function table.print(t,...)
- if type(t)~="table" then
- print(tostring(t))
- else
- serialize(print,t,...)
- end
-end
-setinspector(function(v) if type(v)=="table" then serialize(print,v,"table") return true end end)
-function table.sub(t,i,j)
- return { unpack(t,i,j) }
-end
-function table.is_empty(t)
- return not t or not next(t)
-end
-function table.has_one_entry(t)
- return t and not next(t,next(t))
-end
-function table.loweredkeys(t)
- local l={}
- for k,v in next,t do
- l[lower(k)]=v
- end
- return l
-end
-function table.unique(old)
- local hash={}
- local new={}
- local n=0
- for i=1,#old do
- local oi=old[i]
- if not hash[oi] then
- n=n+1
- new[n]=oi
- hash[oi]=true
- end
- end
- return new
-end
-function table.sorted(t,...)
- sort(t,...)
- return t
-end
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
-if not modules then modules={} end modules ['l-file']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
-}
-file=file or {}
-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=string.match,string.find
-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 colon=P(":")
-local period=P(".")
-local periods=P("..")
-local fwslash=P("/")
-local bwslash=P("\\")
-local slashes=S("\\/")
-local noperiod=1-period
-local noslashes=1-slashes
-local name=noperiod^1
-local suffix=period/""*(1-period-slashes)^1*-1
-local pattern=C((1-(slashes^1*noslashes^1*-1))^1)*P(1)
-local function pathpart(name,default)
- return name and lpegmatch(pattern,name) or default or ""
-end
-local pattern=(noslashes^0*slashes)^1*C(noslashes^1)*-1
-local function basename(name)
- return name and lpegmatch(pattern,name) or name
-end
-local pattern=(noslashes^0*slashes^1)^0*Cs((1-suffix)^1)*suffix^0
-local function nameonly(name)
- return name and lpegmatch(pattern,name) or name
-end
-local pattern=(noslashes^0*slashes)^0*(noperiod^1*period)^1*C(noperiod^1)*-1
-local function suffixonly(name)
- return name and lpegmatch(pattern,name) or ""
-end
-file.pathpart=pathpart
-file.basename=basename
-file.nameonly=nameonly
-file.suffixonly=suffixonly
-file.suffix=suffixonly
-file.dirname=pathpart
-file.extname=suffixonly
-local drive=C(R("az","AZ"))*colon
-local path=C((noslashes^0*slashes)^0)
-local suffix=period*C(P(1-period)^0*P(-1))
-local base=C((1-suffix)^0)
-local rest=C(P(1)^0)
-drive=drive+Cc("")
-path=path+Cc("")
-base=base+Cc("")
-suffix=suffix+Cc("")
-local pattern_a=drive*path*base*suffix
-local pattern_b=path*base*suffix
-local pattern_c=C(drive*path)*C(base*suffix)
-local pattern_d=path*rest
-function file.splitname(str,splitdrive)
- if not str then
- elseif splitdrive then
- return lpegmatch(pattern_a,str)
- else
- return lpegmatch(pattern_b,str)
- end
-end
-function file.splitbase(str)
- return str and lpegmatch(pattern_d,str)
-end
-function file.nametotable(str,splitdrive)
- if str then
- local path,drive,subpath,name,base,suffix=lpegmatch(pattern_c,str)
- if splitdrive then
- return {
- path=path,
- drive=drive,
- subpath=subpath,
- name=name,
- base=base,
- suffix=suffix,
- }
- else
- return {
- path=path,
- name=name,
- base=base,
- suffix=suffix,
- }
- end
- end
-end
-local pattern=Cs(((period*(1-period-slashes)^1*-1)/""+1)^1)
-function file.removesuffix(name)
- return name and lpegmatch(pattern,name)
-end
-local suffix=period/""*(1-period-slashes)^1*-1
-local pattern=Cs((noslashes^0*slashes^1)^0*((1-suffix)^1))*Cs(suffix)
-function file.addsuffix(filename,suffix,criterium)
- if not filename or not suffix or suffix=="" then
- return filename
- elseif criterium==true then
- return filename.."."..suffix
- elseif not criterium then
- local n,s=lpegmatch(pattern,filename)
- if not s or s=="" then
- return filename.."."..suffix
- else
- return filename
- end
- else
- local n,s=lpegmatch(pattern,filename)
- if s and s~="" then
- local t=type(criterium)
- if t=="table" then
- for i=1,#criterium do
- if s==criterium[i] then
- return filename
- end
- end
- elseif t=="string" then
- if s==criterium then
- return filename
- end
- end
- end
- return (n or filename).."."..suffix
- end
-end
-local suffix=period*(1-period-slashes)^1*-1
-local pattern=Cs((1-suffix)^0)
-function file.replacesuffix(name,suffix)
- if name and suffix and suffix~="" then
- return lpegmatch(pattern,name).."."..suffix
- else
- return name
- end
-end
-local reslasher=lpeg.replacer(P("\\"),"/")
-function file.reslash(str)
- return str and lpegmatch(reslasher,str)
-end
-function file.is_writable(name)
- if not name then
- elseif lfs.isdir(name) then
- name=name.."/m_t_x_t_e_s_t.tmp"
- local f=io.open(name,"wb")
- if f then
- f:close()
- os.remove(name)
- return true
- end
- elseif lfs.isfile(name) then
- local f=io.open(name,"ab")
- if f then
- f:close()
- return true
- end
- else
- local f=io.open(name,"ab")
- if f then
- f:close()
- os.remove(name)
- return true
- end
- end
- return false
-end
-local readable=P("r")*Cc(true)
-function file.is_readable(name)
- if name then
- local a=attributes(name)
- return a and lpegmatch(readable,a.permissions) or false
- else
- return false
- end
-end
-file.isreadable=file.is_readable
-file.iswritable=file.is_writable
-function file.size(name)
- if name then
- local a=attributes(name)
- return a and a.size or 0
- else
- return 0
- end
-end
-function file.splitpath(str,separator)
- return str and checkedsplit(lpegmatch(reslasher,str),separator or io.pathseparator)
-end
-function file.joinpath(tab,separator)
- return tab and concat(tab,separator or io.pathseparator)
-end
-local stripper=Cs(P(fwslash)^0/""*reslasher)
-local isnetwork=fwslash*fwslash*(1-fwslash)+(1-fwslash-colon)^1*colon
-local isroot=fwslash^1*-1
-local hasroot=fwslash^1
-local deslasher=lpeg.replacer(S("\\/")^1,"/")
-function file.join(...)
- local lst={... }
- local one=lst[1]
- if lpegmatch(isnetwork,one) then
- local two=lpegmatch(deslasher,concat(lst,"/",2))
- return one.."/"..two
- elseif lpegmatch(isroot,one) then
- local two=lpegmatch(deslasher,concat(lst,"/",2))
- 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,"/"))
- end
-end
-local drivespec=R("az","AZ")^1*colon
-local anchors=fwslash+drivespec
-local untouched=periods+(1-period)^1*P(-1)
-local splitstarter=(Cs(drivespec*(bwslash/"/"+fwslash)^0)+Cc(false))*Ct(lpeg.splitat(S("/\\")^1))
-local absolute=fwslash
-function file.collapsepath(str,anchor)
- if not str then
- return
- end
- if anchor==true and not lpegmatch(anchors,str) then
- str=getcurrentdir().."/"..str
- end
- if str=="" or str=="." then
- return "."
- elseif lpegmatch(untouched,str) then
- return lpegmatch(reslasher,str)
- end
- local starter,oldelements=lpegmatch(splitstarter,str)
- local newelements={}
- local i=#oldelements
- while i>0 do
- local element=oldelements[i]
- if element=='.' then
- elseif element=='..' then
- local n=i-1
- while n>0 do
- local element=oldelements[n]
- if element~='..' and element~='.' then
- oldelements[n]='.'
- break
- else
- n=n-1
- end
- end
- if n<1 then
- insert(newelements,1,'..')
- end
- elseif element~="" then
- insert(newelements,1,element)
- end
- i=i-1
- end
- if #newelements==0 then
- return starter or "."
- elseif starter then
- return starter..concat(newelements,'/')
- elseif lpegmatch(absolute,str) then
- return "/"..concat(newelements,'/')
- else
- newelements=concat(newelements,'/')
- if anchor=="." and find(str,"^%./") then
- return "./"..newelements
- else
- return newelements
- end
- end
-end
-local validchars=R("az","09","AZ","--","..")
-local pattern_a=lpeg.replacer(1-validchars)
-local pattern_a=Cs((validchars+P(1)/"-")^1)
-local whatever=P("-")^0/""
-local pattern_b=Cs(whatever*(1-whatever*-1)^1)
-function file.robustname(str,strict)
- if str then
- str=lpegmatch(pattern_a,str) or str
- if strict then
- return lpegmatch(pattern_b,str) or str
- else
- return str
- end
- end
-end
-file.readdata=io.loaddata
-file.savedata=io.savedata
-function file.copy(oldname,newname)
- if oldname and newname then
- local data=io.loaddata(oldname)
- if data and data~="" then
- file.savedata(newname,data)
- end
- end
-end
-local letter=R("az","AZ")+S("_-+")
-local separator=P("://")
-local qualified=period^0*fwslash+letter*colon+letter^1*separator+letter^1*fwslash
-local rootbased=fwslash+letter*colon
-lpeg.patterns.qualified=qualified
-lpeg.patterns.rootbased=rootbased
-function file.is_qualified_path(filename)
- return filename and lpegmatch(qualified,filename)~=nil
-end
-function file.is_rootbased_path(filename)
- return filename and lpegmatch(rootbased,filename)~=nil
-end
-function file.strip(name,dir)
- if name then
- local b,a=match(name,"^(.-)"..dir.."(.*)$")
- return a~="" and a or name
- end
-end
-
-end -- closure
-
-do -- begin closure to overcome local limits and interference
-
-if not modules then modules={} end modules ['l-dir']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- 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 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
-dir=dir or {}
-local dir=dir
-local lfs=lfs
-local attributes=lfs.attributes
-local walkdir=lfs.dir
-local isdir=lfs.isdir
-local isfile=lfs.isfile
-local currentdir=lfs.currentdir
-local chdir=lfs.chdir
-if not isdir then
- function isdir(name)
- local a=attributes(name)
- return a and a.mode=="directory"
- end
- lfs.isdir=isdir
-end
-if not isfile then
- function isfile(name)
- local a=attributes(name)
- return a and a.mode=="file"
- end
- lfs.isfile=isfile
-end
-function dir.current()
- return (gsub(currentdir(),"\\","/"))
-end
-local lfsisdir=isdir
-local function isdir(path)
- path=gsub(path,"[/\\]+$","")
- return lfsisdir(path)
-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)
- end
- elseif recurse and (mode=="directory") and (name~='.') and (name~="..") then
- globpattern(full,patt,recurse,action)
- end
- end
- end
-end
-dir.globpattern=globpattern
-local function collectpattern(path,patt,recurse,result)
- local ok,scanner
- result=result or {}
- if path=="/" then
- ok,scanner,first=xpcall(function() return walkdir(path..".") end,function() end)
- else
- 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
- 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
- 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 pattern=Ct {
- [1]=(C(P(".")+P("/")^1)+C(R("az","AZ")*P(":")*P("/")^0)+Cc("./"))*V(2)*V(3),
- [2]=C(((1-S("*?/"))^0*P("/"))^0),
- [3]=C(P(1)^0)
-}
-local filter=Cs ((
- P("**")/".*"+P("*")/"[^/]*"+P("?")/"[^/]"+P(".")/"%%."+P("+")/"%%+"+P("-")/"%%-"+P(1)
-)^0 )
-local function glob(str,t)
- if type(t)=="function" then
- if type(str)=="table" then
- for s=1,#str do
- glob(str[s],t)
- end
- 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 recurse=find(base,"%*%*")
- local start=root..path
- local result=lpegmatch(filter,start..base)
- globpattern(start,result,recurse,t)
- end
- end
- else
- if type(str)=="table" then
- local t=t or {}
- for s=1,#str do
- glob(str[s],t)
- end
- return t
- elseif isfile(str) then
- if t then
- t[#t+1]=str
- return t
- else
- 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 recurse=find(base,"%*%*")
- local start=root..path
- local result=lpegmatch(filter,start..base)
- globpattern(start,result,recurse,action)
- return t
- else
- return {}
- end
- end
- end
-end
-dir.glob=glob
-local function globfiles(path,recurse,func,files)
- if type(func)=="string" then
- local s=func
- func=function(name) return find(name,s) end
- end
- files=files or {}
- local noffiles=#files
- for name in walkdir(path) do
- if find(name,"^%.") then
- else
- local mode=attributes(name,'mode')
- if mode=="directory" then
- if recurse then
- globfiles(path.."/"..name,recurse,func,files)
- end
- elseif mode=="file" then
- if not func or func(name) then
- noffiles=noffiles+1
- files[noffiles]=path.."/"..name
- end
- end
- end
- end
- return files
-end
-dir.globfiles=globfiles
-function dir.ls(pattern)
- return concat(glob(pattern),"\n")
-end
-local make_indeed=true
-local onwindows=os.type=="windows" or find(os.getenv("PATH"),";")
-if onwindows then
- function dir.mkdirs(...)
- local str,pth="",""
- for i=1,select("#",...) do
- local s=select(i,...)
- if s=="" then
- elseif str=="" then
- str=s
- else
- str=str.."/"..s
- end
- end
- local first,middle,last
- local drive=false
- first,middle,last=match(str,"^(//)(//*)(.*)$")
- if first then
- else
- first,last=match(str,"^(//)/*(.-)$")
- if first then
- middle,last=match(str,"([^/]+)/+(.-)$")
- if middle then
- pth="//"..middle
- else
- pth="//"..last
- last=""
- end
- else
- first,middle,last=match(str,"^([a-zA-Z]:)(/*)(.-)$")
- if first then
- pth,drive=first..middle,true
- else
- middle,last=match(str,"^(/*)(.-)$")
- if not middle then
- last=str
- end
- end
- end
- end
- for s in gmatch(last,"[^/]+") do
- if pth=="" then
- pth=s
- elseif drive then
- pth,drive=pth..s,false
- else
- pth=pth.."/"..s
- end
- if make_indeed and not isdir(pth) then
- lfs.mkdir(pth)
- end
- end
- return pth,(isdir(pth)==true)
- end
-else
- function dir.mkdirs(...)
- local str,pth="",""
- for i=1,select("#",...) do
- local s=select(i,...)
- if s and s~="" then
- if str~="" then
- str=str.."/"..s
- else
- str=s
- end
- end
- end
- str=gsub(str,"/+","/")
- if find(str,"^/") then
- pth="/"
- for s in gmatch(str,"[^/]+") do
- local first=(pth=="/")
- if first then
- pth=pth..s
- else
- pth=pth.."/"..s
- end
- if make_indeed and not first and not isdir(pth) then
- lfs.mkdir(pth)
- end
- end
- else
- pth="."
- for s in gmatch(str,"[^/]+") do
- pth=pth.."/"..s
- if make_indeed and not isdir(pth) then
- lfs.mkdir(pth)
- end
- end
- end
- return pth,(isdir(pth)==true)
- 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()
- end
- chdir(d)
- 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
- end
- str=gsub(str,"//","/")
- str=gsub(str,"/%./","/")
- str=gsub(str,"(.)/%.$","%1")
- return str
- end
-end
-file.expandname=dir.expandname
-local stack={}
-function dir.push(newdir)
- insert(stack,currentdir())
- if newdir and newdir~="" then
- chdir(newdir)
- end
-end
-function dir.pop()
- local d=remove(stack)
- if d then
- chdir(d)
- end
- return d
-end
-local function found(...)
- for i=1,select("#",...) do
- local path=select(i,...)
- local kind=type(path)
- if kind=="string" then
- if isdir(path) then
- return path
- end
- elseif kind=="table" then
- local path=found(unpack(path))
- if path then
- return path
- end
- end
- end
-end
-dir.found=found
-
-end -- closure
diff --git a/luaotfload-lib-dir.lua b/luaotfload-lib-dir.lua
new file mode 100644
index 0000000..3d0576e
--- /dev/null
+++ b/luaotfload-lib-dir.lua
@@ -0,0 +1,470 @@
+if not modules then modules = { } end modules ['l-dir'] = {
+ version = 1.001,
+ comment = "companion to luat-lib.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- dir.expandname will be merged with cleanpath and collapsepath
+
+local type, select = type, select
+local find, gmatch, match, gsub = string.find, string.gmatch, string.match, string.gsub
+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
+
+dir = dir or { }
+local dir = dir
+local lfs = lfs
+
+local attributes = lfs.attributes
+local walkdir = lfs.dir
+local isdir = lfs.isdir
+local isfile = lfs.isfile
+local currentdir = lfs.currentdir
+local chdir = lfs.chdir
+
+-- in case we load outside luatex
+
+if not isdir then
+ function isdir(name)
+ local a = attributes(name)
+ return a and a.mode == "directory"
+ end
+ lfs.isdir = isdir
+end
+
+if not isfile then
+ function isfile(name)
+ local a = attributes(name)
+ return a and a.mode == "file"
+ end
+ lfs.isfile = isfile
+end
+
+-- handy
+
+function dir.current()
+ return (gsub(currentdir(),"\\","/"))
+end
+
+-- optimizing for no find (*) does not save time
+
+--~ local function globpattern(path,patt,recurse,action) -- fails in recent luatex due to some change in lfs
+--~ local ok, scanner
+--~ if path == "/" then
+--~ ok, scanner = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+--~ else
+--~ ok, scanner = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+--~ end
+--~ if ok and type(scanner) == "function" then
+--~ if not find(path,"/$") then path = path .. '/' end
+--~ for name in scanner do
+--~ local full = path .. name
+--~ local mode = attributes(full,'mode')
+--~ if mode == 'file' then
+--~ if find(full,patt) then
+--~ action(full)
+--~ end
+--~ elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
+--~ globpattern(full,patt,recurse,action)
+--~ end
+--~ end
+--~ end
+--~ end
+
+local lfsisdir = isdir
+
+local function isdir(path)
+ path = gsub(path,"[/\\]+$","")
+ return lfsisdir(path)
+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 -- lfs.isdir does not like trailing /
+ for name in walkdir(path) do -- lfs.dir accepts trailing /
+ local full = path .. name
+ local mode = attributes(full,'mode')
+ if mode == 'file' then
+ if find(full,patt) then
+ action(full)
+ end
+ elseif recurse and (mode == "directory") and (name ~= '.') and (name ~= "..") then
+ globpattern(full,patt,recurse,action)
+ end
+ end
+ end
+end
+
+dir.globpattern = globpattern
+
+local function collectpattern(path,patt,recurse,result)
+ local ok, scanner
+ result = result or { }
+ if path == "/" then
+ ok, scanner, first = xpcall(function() return walkdir(path..".") end, function() end) -- kepler safe
+ else
+ ok, scanner, first = xpcall(function() return walkdir(path) end, function() end) -- kepler safe
+ end
+ if ok and type(scanner) == "function" then
+ 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
+ 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 pattern = Ct {
+ [1] = (C(P(".") + P("/")^1) + C(R("az","AZ") * P(":") * P("/")^0) + Cc("./")) * V(2) * V(3),
+ [2] = C(((1-S("*?/"))^0 * P("/"))^0),
+ [3] = C(P(1)^0)
+}
+
+local filter = Cs ( (
+ P("**") / ".*" +
+ P("*") / "[^/]*" +
+ P("?") / "[^/]" +
+ P(".") / "%%." +
+ P("+") / "%%+" +
+ P("-") / "%%-" +
+ P(1)
+)^0 )
+
+local function glob(str,t)
+ if type(t) == "function" then
+ if type(str) == "table" then
+ for s=1,#str do
+ glob(str[s],t)
+ end
+ elseif isfile(str) then
+ t(str)
+ else
+ local split = lpegmatch(pattern,str) -- we could use the file splitter
+ if split then
+ local root, path, base = split[1], split[2], split[3]
+ local recurse = find(base,"%*%*")
+ local start = root .. path
+ local result = lpegmatch(filter,start .. base)
+ globpattern(start,result,recurse,t)
+ end
+ end
+ else
+ if type(str) == "table" then
+ local t = t or { }
+ for s=1,#str do
+ glob(str[s],t)
+ end
+ return t
+ elseif isfile(str) then
+ if t then
+ t[#t+1] = str
+ return t
+ else
+ return { str }
+ end
+ else
+ local split = lpegmatch(pattern,str) -- we could use the file splitter
+ if split then
+ local t = t or { }
+ local action = action or function(name) t[#t+1] = name end
+ local root, path, base = split[1], split[2], split[3]
+ local recurse = find(base,"%*%*")
+ local start = root .. path
+ local result = lpegmatch(filter,start .. base)
+ globpattern(start,result,recurse,action)
+ return t
+ else
+ return { }
+ end
+ end
+ end
+end
+
+dir.glob = glob
+
+--~ list = dir.glob("**/*.tif")
+--~ list = dir.glob("/**/*.tif")
+--~ list = dir.glob("./**/*.tif")
+--~ list = dir.glob("oeps/**/*.tif")
+--~ list = dir.glob("/oeps/**/*.tif")
+
+local function globfiles(path,recurse,func,files) -- func == pattern or function
+ if type(func) == "string" then
+ local s = func
+ func = function(name) return find(name,s) end
+ end
+ files = files or { }
+ local noffiles = #files
+ for name in walkdir(path) do
+ if find(name,"^%.") then
+ --- skip
+ else
+ local mode = attributes(name,'mode')
+ if mode == "directory" then
+ if recurse then
+ globfiles(path .. "/" .. name,recurse,func,files)
+ end
+ elseif mode == "file" then
+ if not func or func(name) then
+ noffiles = noffiles + 1
+ files[noffiles] = path .. "/" .. name
+ end
+ end
+ end
+ end
+ return files
+end
+
+dir.globfiles = globfiles
+
+-- t = dir.glob("c:/data/develop/context/sources/**/????-*.tex")
+-- t = dir.glob("c:/data/develop/tex/texmf/**/*.tex")
+-- t = dir.glob("c:/data/develop/context/texmf/**/*.tex")
+-- t = dir.glob("f:/minimal/tex/**/*")
+-- print(dir.ls("f:/minimal/tex/**/*"))
+-- print(dir.ls("*.tex"))
+
+function dir.ls(pattern)
+ return concat(glob(pattern),"\n")
+end
+
+--~ mkdirs("temp")
+--~ mkdirs("a/b/c")
+--~ mkdirs(".","/a/b/c")
+--~ mkdirs("a","b","c")
+
+local make_indeed = true -- false
+
+local onwindows = os.type == "windows" or find(os.getenv("PATH"),";")
+
+if onwindows then
+
+ function dir.mkdirs(...)
+ local str, pth = "", ""
+ for i=1,select("#",...) do
+ local s = select(i,...)
+ if s == "" then
+ -- skip
+ elseif str == "" then
+ str = s
+ else
+ str = str .. "/" .. s
+ end
+ end
+ local first, middle, last
+ local drive = false
+ first, middle, last = match(str,"^(//)(//*)(.*)$")
+ if first then
+ -- empty network path == local path
+ else
+ first, last = match(str,"^(//)/*(.-)$")
+ if first then
+ middle, last = match(str,"([^/]+)/+(.-)$")
+ if middle then
+ pth = "//" .. middle
+ else
+ pth = "//" .. last
+ last = ""
+ end
+ else
+ first, middle, last = match(str,"^([a-zA-Z]:)(/*)(.-)$")
+ if first then
+ pth, drive = first .. middle, true
+ else
+ middle, last = match(str,"^(/*)(.-)$")
+ if not middle then
+ last = str
+ end
+ end
+ end
+ end
+ for s in gmatch(last,"[^/]+") do
+ if pth == "" then
+ pth = s
+ elseif drive then
+ pth, drive = pth .. s, false
+ else
+ pth = pth .. "/" .. s
+ end
+ if make_indeed and not isdir(pth) then
+ lfs.mkdir(pth)
+ end
+ end
+ return pth, (isdir(pth) == true)
+ end
+
+ --~ print(dir.mkdirs("","","a","c"))
+ --~ print(dir.mkdirs("a"))
+ --~ print(dir.mkdirs("a:"))
+ --~ print(dir.mkdirs("a:/b/c"))
+ --~ print(dir.mkdirs("a:b/c"))
+ --~ print(dir.mkdirs("a:/bbb/c"))
+ --~ print(dir.mkdirs("/a/b/c"))
+ --~ print(dir.mkdirs("/aaa/b/c"))
+ --~ print(dir.mkdirs("//a/b/c"))
+ --~ print(dir.mkdirs("///a/b/c"))
+ --~ print(dir.mkdirs("a/bbb//ccc/"))
+
+else
+
+ function dir.mkdirs(...)
+ local str, pth = "", ""
+ for i=1,select("#",...) do
+ local s = select(i,...)
+ if s and s ~= "" then -- we catch nil and false
+ if str ~= "" then
+ str = str .. "/" .. s
+ else
+ str = s
+ end
+ end
+ end
+ str = gsub(str,"/+","/")
+ if find(str,"^/") then
+ pth = "/"
+ for s in gmatch(str,"[^/]+") do
+ local first = (pth == "/")
+ if first then
+ pth = pth .. s
+ else
+ pth = pth .. "/" .. s
+ end
+ if make_indeed and not first and not isdir(pth) then
+ lfs.mkdir(pth)
+ end
+ end
+ else
+ pth = "."
+ for s in gmatch(str,"[^/]+") do
+ pth = pth .. "/" .. s
+ if make_indeed and not isdir(pth) then
+ lfs.mkdir(pth)
+ end
+ end
+ end
+ return pth, (isdir(pth) == true)
+ end
+
+ --~ print(dir.mkdirs("","","a","c"))
+ --~ print(dir.mkdirs("a"))
+ --~ print(dir.mkdirs("/a/b/c"))
+ --~ print(dir.mkdirs("/aaa/b/c"))
+ --~ print(dir.mkdirs("//a/b/c"))
+ --~ print(dir.mkdirs("///a/b/c"))
+ --~ print(dir.mkdirs("a/bbb//ccc/"))
+
+end
+
+dir.makedirs = dir.mkdirs
+
+-- we can only define it here as it uses dir.current
+
+if onwindows then
+
+ function dir.expandname(str) -- will be merged with cleanpath and collapsepath
+ local first, nothing, last = match(str,"^(//)(//*)(.*)$")
+ if first then
+ first = dir.current() .. "/" -- dir.current sanitizes
+ 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()
+ end
+ chdir(d)
+ 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) -- will be merged with cleanpath and collapsepath
+ if not find(str,"^/") then
+ str = currentdir() .. "/" .. str
+ end
+ str = gsub(str,"//","/")
+ str = gsub(str,"/%./","/")
+ str = gsub(str,"(.)/%.$","%1")
+ return str
+ end
+
+end
+
+file.expandname = dir.expandname -- for convenience
+
+local stack = { }
+
+function dir.push(newdir)
+ insert(stack,currentdir())
+ if newdir and newdir ~= "" then
+ chdir(newdir)
+ end
+end
+
+function dir.pop()
+ local d = remove(stack)
+ if d then
+ chdir(d)
+ end
+ return d
+end
+
+local function found(...) -- can have nil entries
+ for i=1,select("#",...) do
+ local path = select(i,...)
+ local kind = type(path)
+ if kind == "string" then
+ if isdir(path) then
+ return path
+ end
+ elseif kind == "table" then
+ -- here we asume no holes, i.e. an indexed table
+ local path = found(unpack(path))
+ if path then
+ return path
+ end
+ end
+ end
+ -- return nil -- if we want print("crappath") to show something
+end
+
+dir.found = found
diff --git a/luaotfload-merged.lua b/luaotfload-merged.lua
index 14667bd..ffb0016 100644
--- a/luaotfload-merged.lua
+++ b/luaotfload-merged.lua
@@ -1,6 +1,6 @@
-- merged file : luatex-fonts-merged.lua
-- parent file : luatex-fonts.lua
--- merge date : 05/14/13 23:14:52
+-- merge date : 05/16/13 00:29:34
do -- begin closure to overcome local limits and interference
@@ -1986,7 +1986,7 @@ elseif not lfs.isfile then
end
end
local insert,concat=table.insert,table.concat
-local match,find=string.match,string.find
+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
@@ -2299,6 +2299,19 @@ function file.strip(name,dir)
return a~="" and a or name
end
end
+function lfs.mkdirs(path)
+ local full
+ for sub in gmatch(path,"([^\\/]+)") do
+ if full then
+ full=full.."/"..sub
+ else
+ full=sub
+ end
+ if not lfs.isdir(full) then
+ lfs.mkdir(full)
+ end
+ end
+end
end -- closure
@@ -3006,8 +3019,15 @@ do
end
cachepaths=string.split(cachepaths,os.type=="windows" and ";" or ":")
for i=1,#cachepaths do
- if file.is_writable(cachepaths[i]) then
- writable=file.join(cachepaths[i],"luatex-cache")
+ local cachepath=cachepaths[i]
+ if not lfs.isdir(cachepath) then
+ lfs.mkdirs(cachepath)
+ if lfs.isdir(cachepath) then
+ texio.write(string.format("(created cache path: %s)",cachepath))
+ end
+ end
+ if file.is_writable(cachepath) then
+ writable=file.join(cachepath,"luatex-cache")
lfs.mkdir(writable)
writable=file.join(writable,caches.namespace)
lfs.mkdir(writable)
@@ -6809,7 +6829,7 @@ local function checkmathsize(tfmdata,mathsize)
end
registerotffeature {
name="mathsize",
- description="apply mathsize as specified in the font",
+ description="apply mathsize specified in the font",
initializers={
base=checkmathsize,
node=checkmathsize,
diff --git a/luaotfload.dtx b/luaotfload.dtx
index 1438e8e..88cc599 100644
--- a/luaotfload.dtx
+++ b/luaotfload.dtx
@@ -1512,40 +1512,6 @@ local loadmodule = function (name)
end
% \end{macrocode}
-% The font loader expects the \TEX Live cache directories to be in
-% place and due to some quirk in \fileent{data-con.lua} they are
-% fixed during the run. It follows that we have to ensure their
-% presence before we can initialize the fontloader.
-% The most reliable way to do so is by using the
-% \luafunction{mkdirs()} function from \CONTEXT’s
-% \fileent{l-dir.lua}.
-% Unfortunately, for this to work we need to to preload substantial
-% parts of the \LUA libraries.
-%
-% \begin{macrocode}
-
-loadmodule"filesystem-merged.lua"
-
-% \end{macrocode}
-% Prepare directories: the cache function in Luatex-Fonts checks for a
-% writable directory only once during startup. If there is no
-% \fileent{texmf-var} at this time it will create a subdirectory
-% \fileent{./luatex-cache} instead.
-% Thus everything has to be laid out before we load the fontloader.
-%
-% \begin{macrocode}
-
-
-local cachepath = kpse.expand_var"$TEXMFVAR"
-
-if not lfs.isdir(cachepath) then
- dir.mkdirs(cachepath)
- if not lfs.isdir(cachepath) then
- error( "ERROR could not create directory %s", cachepath)
- end
-end
-
-% \end{macrocode}
% Before \TeX Live 2013 version, \LUATEX had a bug that made ofm fonts fail
% when called with their extension. There was a side-effect making ofm
% totally unloadable when luaotfload was present. The following lines are
@@ -1796,6 +1762,7 @@ add_to_callback("hpack_filter",
add_to_callback("find_vf_file",
find_vf_file, "luaotfload.find_vf_file")
+loadmodule"lib-dir.lua" --- required by luaofload-database.lua
loadmodule"override.lua" --- “luat-ovr”
logs.set_loglevel(config.luaotfload.loglevel)
@@ -1922,6 +1889,7 @@ end
% system, otherwise we fall back to the \verb|file:| lookup.
%
% \begin{macrocode}
+
request_resolvers.path = function (specification)
local name = specification.name
local exists, _ = lfsisfile(name)