diff options
Diffstat (limited to 'Master/bin/x86_64-darwinlegacy')
l---------[-rw-r--r--] | Master/bin/x86_64-darwinlegacy/mtxrun.lua | 27611 |
1 files changed, 1 insertions, 27610 deletions
diff --git a/Master/bin/x86_64-darwinlegacy/mtxrun.lua b/Master/bin/x86_64-darwinlegacy/mtxrun.lua index a00dc59288c..8825f964657 100644..120000 --- a/Master/bin/x86_64-darwinlegacy/mtxrun.lua +++ b/Master/bin/x86_64-darwinlegacy/mtxrun.lua @@ -1,27610 +1 @@ -#!/usr/bin/env texlua - -if not modules then modules = { } end modules ['mtxrun'] = { - version = 1.001, - comment = "runner, lua replacement for texmfstart.rb", - author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright = "PRAGMA ADE / ConTeXt Development Team", - license = "see context related readme files" -} - --- one can make a stub: - --- mtxrun : --- --- #!/bin/sh --- env LUATEXDIR=/....../texmf/scripts/context/lua luatex --luaonly mtxrun.lua "$@" - --- mtxrun.cmd : --- --- @luatex --luaonly %~d0%~p0mtxrun.lua %* - --- filename : mtxrun.lua --- comment : companion to context.tex --- author : Hans Hagen, PRAGMA-ADE, Hasselt NL --- copyright: PRAGMA ADE / ConTeXt Development Team --- license : see context related readme files - --- This script is based on texmfstart.rb but does not use kpsewhich to locate files. --- Although kpse is a library it never came to opening up its interface to other --- programs (esp scripting languages) and so we do it ourselves. The lua variant --- evolved out of an experimental ruby one. Interesting is that using a scripting --- language instead of c does not have a speed penalty. Actually the lua variant is --- more efficient, especially when multiple calls to kpsewhich are involved. The lua --- library also gives way more control. - --- When libraries used here are updates you can run --- --- mtxrun --selfmerge --- --- to update the embedded code. After that you might need to run --- --- mtxrun --selfupdate --- --- to copy the new script (from scripts/context/lua) to location where --- binaries are expected. If you want to remove the embedded code you can run --- --- mtxxun --selfclean - --- to be done / considered --- --- support for --exec or make it default --- support for jar files (or maybe not, never used, too messy) --- support for $RUBYINPUTS cum suis (if still needed) --- remember for subruns: _CTX_K_V_#{original}_ --- remember for subruns: _CTX_K_S_#{original}_ --- remember for subruns: TEXMFSTART.#{original} [tex.rb texmfstart.rb] - --- begin library merge - - - -do -- create closure to overcome 200 locals limit - -package.loaded["l-bit32"] = package.loaded["l-bit32"] or true - --- original size: 3607, stripped down to: 3009 - -if not modules then modules={} end modules ['l-bit32']={ - version=1.001, - license="the same as regular Lua", - source="bitwise.lua, v 1.24 2014/12/26 17:20:53 roberto", - comment="drop-in for bit32, adapted a bit by Hans Hagen", -} -if bit32 then -elseif utf8 then - load ([[ -local select = select -- instead of: arg = { ... } -bit32 = { - bnot = function (a) - return ~a & 0xFFFFFFFF - end, - band = function (x, y, z, ...) - if not z then - return ((x or -1) & (y or -1)) & 0xFFFFFFFF - else - local res = x & y & z - for i=1,select("#",...) do - res = res & select(i,...) - end - return res & 0xFFFFFFFF - end - end, - bor = function (x, y, z, ...) - if not z then - return ((x or 0) | (y or 0)) & 0xFFFFFFFF - else - local res = x | y | z - for i=1,select("#",...) do - res = res | select(i,...) - end - return res & 0xFFFFFFFF - end - end, - bxor = function (x, y, z, ...) - if not z then - return ((x or 0) ~ (y or 0)) & 0xFFFFFFFF - else - local res = x ~ y ~ z - for i=1,select("#",...) do - res = res ~ select(i,...) - end - return res & 0xFFFFFFFF - end - end, - btest = function (x, y, z, ...) - if not z then - return (((x or -1) & (y or -1)) & 0xFFFFFFFF) ~= 0 - else - local res = x & y & z - for i=1,select("#",...) do - res = res & select(i,...) - end - return (res & 0xFFFFFFFF) ~= 0 - end - end, - lshift = function (a, b) - return ((a & 0xFFFFFFFF) << b) & 0xFFFFFFFF - end, - rshift = function (a, b) - return ((a & 0xFFFFFFFF) >> b) & 0xFFFFFFFF - end, - arshift = function (a, b) - a = a & 0xFFFFFFFF - if b <= 0 or (a & 0x80000000) == 0 then - return (a >> b) & 0xFFFFFFFF - else - return ((a >> b) | ~(0xFFFFFFFF >> b)) & 0xFFFFFFFF - end - end, - lrotate = function (a ,b) - b = b & 31 - a = a & 0xFFFFFFFF - a = (a << b) | (a >> (32 - b)) - return a & 0xFFFFFFFF - end, - rrotate = function (a, b) - b = -b & 31 - a = a & 0xFFFFFFFF - a = (a << b) | (a >> (32 - b)) - return a & 0xFFFFFFFF - end, - extract = function (a, f, w) - return (a >> f) & ~(-1 << (w or 1)) - end, - replace = function (a, v, f, w) - local mask = ~(-1 << (w or 1)) - return ((a & ~(mask << f)) | ((v & mask) << f)) & 0xFFFFFFFF - end, -} - ]] ) () -elseif bit then - load ([[ -local band, bnot, rshift, lshift = bit.band, bit.bnot, bit.rshift, bit.lshift -bit32 = { - arshift = bit.arshift, - band = band, - bnot = bnot, - bor = bit.bor, - bxor = bit.bxor, - btest = function(...) - return band(...) ~= 0 - end, - extract = function(a,f,w) - return band(rshift(a,f),2^(w or 1)-1) - end, - lrotate = bit.rol, - lshift = lshift, - replace = function(a,v,f,w) - local mask = 2^(w or 1)-1 - return band(a,bnot(lshift(mask,f)))+lshift(band(v,mask),f) - end, - rrotate = bit.ror, - rshift = rshift, -} - ]] ) () -else - xpcall(function() local _,t=require("bit32") if t then bit32=t end return end,function() end) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-lua"] = package.loaded["l-lua"] or true - --- original size: 6405, stripped down to: 2865 - -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 next,type,tonumber=next,type,tonumber -LUAMAJORVERSION,LUAMINORVERSION=string.match(_VERSION,"^[^%d]+(%d+)%.(%d+).*$") -LUAMAJORVERSION=tonumber(LUAMAJORVERSION) or 5 -LUAMINORVERSION=tonumber(LUAMINORVERSION) or 1 -LUAVERSION=LUAMAJORVERSION+LUAMINORVERSION/10 -if LUAVERSION<5.2 and jit then - MINORVERSION=2 - LUAVERSION=5.2 -end -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(kind,inspector) - inspectors[kind]=inspector -end -function inspect(...) - for s=1,select("#",...) do - local value=select(s,...) - if value==nil then - print("nil") - else - local done=false - local kind=type(value) - local inspector=inspectors[kind] - if inspector then - done=inspector(value) - if done then - break - end - end - for kind,inspector in next,inspectors do - done=inspector(value) - if done then - break - end - end - if not done then - print(tostring(value)) - end - end - end -end -local dummy=function() end -function optionalrequire(...) - local ok,result=xpcall(require,dummy,...) - if ok then - return result - end -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 -FFISUPPORTED=type(ffi)=="table" and ffi.os~="" and ffi.arch~="" and ffi.load -if not FFISUPPORTED then - local okay;okay,ffi=pcall(require,"ffi") - FFISUPPORTED=type(ffi)=="table" and ffi.os~="" and ffi.arch~="" and ffi.load -end -if not FFISUPPORTED then - ffi=nil -elseif not ffi.number then - ffi.number=tonumber -end -if LUAVERSION>5.3 then -end -if status and os.setenv then - os.setenv("engine",string.lower(status.luatex_engine or "unknown")) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-macro"] = package.loaded["l-macro"] or true - --- original size: 10130, stripped down to: 5990 - -if not modules then modules={} end modules ['l-macros']={ - 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 S,P,R,V,C,Cs,Cc,Ct,Carg=lpeg.S,lpeg.P,lpeg.R,lpeg.V,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Carg -local lpegmatch=lpeg.match -local concat=table.concat -local format,sub,match=string.format,string.sub,string.match -local next,load,type=next,load,type -local newline=S("\n\r")^1 -local continue=P("\\")*newline -local whitespace=S(" \t\n\r") -local spaces=S(" \t")+continue -local nametoken=R("az","AZ","__","09") -local name=nametoken^1 -local body=((continue/""+1)-newline)^1 -local lparent=P("(") -local rparent=P(")") -local noparent=1-(lparent+rparent) -local nested=P { lparent*(noparent+V(1))^0*rparent } -local escaped=P("\\")*P(1) -local squote=P("'") -local dquote=P('"') -local quoted=dquote*(escaped+(1-dquote))^0*dquote+squote*(escaped+(1-squote))^0*squote -local arguments=lparent*Ct((Cs((nested+(quoted+1-S("),")))^1)+S(", "))^0)*rparent -local macros=lua.macros or {} -lua.macros=macros -local patterns={} -local definitions={} -local resolve -local subparser -local report_lua=function(...) - if logs and logs.reporter then - report_lua=logs.reporter("system","lua") - report_lua(...) - else - print(format(...)) - end -end -local safeguard=P("local")*whitespace^1*name*(whitespace+P("=")) -resolve=safeguard+C(C(name)*(arguments^-1))/function(raw,s,a) - local d=definitions[s] - if d then - if a then - local n=#a - local p=patterns[s][n] - if p then - local d=d[n] - for i=1,n do - a[i]=lpegmatch(subparser,a[i]) or a[i] - end - return lpegmatch(p,d,1,a) or d - else - return raw - end - else - return d[0] or raw - end - elseif a then - for i=1,#a do - a[i]=lpegmatch(subparser,a[i]) or a[i] - end - return s.."("..concat(a,",")..")" - else - return raw - end -end -subparser=Cs((resolve+P(1))^1) -local enddefine=P("#enddefine")/"" -local beginregister=(C(name)*(arguments+Cc(false))*C((1-enddefine)^1)*enddefine)/function(k,a,v) - local n=0 - if a then - n=#a - local pattern=P(false) - for i=1,n do - pattern=pattern+(P(a[i])*Carg(1))/function(t) return t[i] end - end - pattern=Cs((pattern+P(1))^1) - local p=patterns[k] - if not p then - p={ [0]=false,false,false,false,false,false,false,false,false } - patterns[k]=p - end - p[n]=pattern - end - local d=definitions[k] - if not d then - d={ a=a,[0]=false,false,false,false,false,false,false,false,false } - definitions[k]=d - end - d[n]=lpegmatch(subparser,v) or v - return "" -end -local register=(Cs(name)*(arguments+Cc(false))*spaces^0*Cs(body))/function(k,a,v) - local n=0 - if a then - n=#a - local pattern=P(false) - for i=1,n do - pattern=pattern+(P(a[i])*Carg(1))/function(t) return t[i] end - end - pattern=Cs((pattern+P(1))^1) - local p=patterns[k] - if not p then - p={ [0]=false,false,false,false,false,false,false,false,false } - patterns[k]=p - end - p[n]=pattern - end - local d=definitions[k] - if not d then - d={ a=a,[0]=false,false,false,false,false,false,false,false,false } - definitions[k]=d - end - d[n]=lpegmatch(subparser,v) or v - return "" -end -local unregister=(C(name)*spaces^0*(arguments+Cc(false)))/function(k,a) - local n=0 - if a then - n=#a - local p=patterns[k] - if p then - p[n]=false - end - end - local d=definitions[k] - if d then - d[n]=false - end - return "" -end -local begindefine=(P("begindefine")*spaces^0/"")*beginregister -local define=(P("define" )*spaces^0/"")*register -local undefine=(P("undefine" )*spaces^0/"")*unregister -local parser=Cs((((P("#")/"")*(define+begindefine+undefine)*(newline^0/"") )+resolve+P(1) )^0 ) -function macros.reset() - definitions={} - patterns={} -end -function macros.showdefinitions() - for name,list in table.sortedhash(definitions) do - local arguments=list.a - if arguments then - arguments="("..concat(arguments,",")..")" - else - arguments="" - end - print("macro: "..name..arguments) - for i=0,#list do - local l=list[i] - if l then - print(" "..l) - end - end - end -end -function macros.resolvestring(str) - return lpegmatch(parser,str) or str -end -function macros.resolving() - return next(patterns) -end -local function reload(path,name,data) - local only=match(name,".-([^/]+)%.lua") - if only and only~="" then - local name=path.."/"..only - local f=io.open(name,"wb") - f:write(data) - f:close() - local f=loadfile(name) - os.remove(name) - return f - end -end -local function reload(path,name,data) - if path and path~="" then - local only=string.match(name,".-([^/]+)%.lua") - if only and only~="" then - local name=path.."/"..only.."-macro.lua" - local f=io.open(name,"wb") - if f then - f:write(data) - f:close() - local l=loadfile(name) - os.remove(name) - return l - end - end - end - return load(data,name) -end -local function loaded(name,trace,detail) - local f=io.open(name,"rb") - if not f then - return false,format("file '%s' not found",name) - end - local c=f:read("*a") - if not c then - return false,format("file '%s' is invalid",name) - end - f:close() - local n=lpegmatch(parser,c) - if trace then - if #n~=#c then - report_lua("macros expanded in '%s' (%i => %i bytes)",name,#c,#n) - if detail then - report_lua() - report_lua(n) - report_lua() - end - elseif detail then - report_lua("no macros expanded in '%s'",name) - end - end - return reload(lfs and lfs.currentdir(),name,n) -end -macros.loaded=loaded -function required(name,trace) - local filename=file.addsuffix(name,"lua") - local fullname=resolvers and resolvers.findfile(filename) or filename - if not fullname or fullname=="" then - return false - end - local codeblob=package.loaded[fullname] - if codeblob then - return codeblob - end - local code,message=loaded(fullname,macros,trace,trace) - if type(code)=="function" then - code=code() - else - report_lua("error when loading '%s'",fullname) - return false,message - end - if code==nil then - code=false - end - package.loaded[fullname]=code - return code -end -macros.required=required - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-sandbox"] = package.loaded["l-sandbox"] or true - --- original size: 9604, stripped down to: 6394 - -if not modules then modules={} end modules ['l-sandbox']={ - 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 global=_G -local next=next -local unpack=unpack or table.unpack -local type=type -local tprint=texio and texio.write_nl or print -local tostring=tostring -local format=string.format -local concat=table.concat -local sort=table.sort -local gmatch=string.gmatch -local gsub=string.gsub -local requiem=require -sandbox={} -local sandboxed=false -local overloads={} -local skiploads={} -local initializers={} -local finalizers={} -local originals={} -local comments={} -local trace=false -local logger=false -local blocked={} -local function report(...) - tprint("sandbox ! "..format(...)) -end -sandbox.report=report -function sandbox.setreporter(r) - report=r - sandbox.report=r -end -function sandbox.settrace(v) - trace=v -end -function sandbox.setlogger(l) - logger=type(l)=="function" and l or false -end -local function register(func,overload,comment) - if type(func)=="function" then - if type(overload)=="string" then - comment=overload - overload=nil - end - local function f(...) - if sandboxed then - local overload=overloads[f] - if overload then - if logger then - local result={ overload(func,...) } - logger { - comment=comments[f] or tostring(f), - arguments={... }, - result=result[1] and true or false, - } - return unpack(result) - else - return overload(func,...) - end - else - end - else - return func(...) - end - end - if comment then - comments[f]=comment - if trace then - report("registering function: %s",comment) - end - end - overloads[f]=overload or false - originals[f]=func - return f - end -end -local function redefine(func,comment) - if type(func)=="function" then - skiploads[func]=comment or comments[func] or "unknown" - if overloads[func]==false then - overloads[func]=nil - end - end -end -sandbox.register=register -sandbox.redefine=redefine -function sandbox.original(func) - return originals and originals[func] or func -end -function sandbox.overload(func,overload,comment) - comment=comment or comments[func] or "?" - if type(func)~="function" then - if trace then - report("overloading unknown function: %s",comment) - end - elseif type(overload)~="function" then - if trace then - report("overloading function with bad overload: %s",comment) - end - elseif overloads[func]==nil then - if trace then - report("function is not registered: %s",comment) - end - elseif skiploads[func] then - if trace then - report("function is not skipped: %s",comment) - end - else - if trace then - report("overloading function: %s",comment) - end - overloads[func]=overload - end - return func -end -local function whatever(specification,what,target) - if type(specification)~="table" then - report("%s needs a specification",what) - elseif type(specification.category)~="string" or type(specification.action)~="function" then - report("%s needs a category and action",what) - elseif not sandboxed then - target[#target+1]=specification - elseif trace then - report("already enabled, discarding %s",what) - end -end -function sandbox.initializer(specification) - whatever(specification,"initializer",initializers) -end -function sandbox.finalizer(specification) - whatever(specification,"finalizer",finalizers) -end -function require(name) - local n=gsub(name,"^.*[\\/]","") - local n=gsub(n,"[%.].*$","") - local b=blocked[n] - if b==false then - return nil - elseif b then - if trace then - report("using blocked: %s",n) - end - return b - else - if trace then - report("requiring: %s",name) - end - return requiem(name) - end -end -function blockrequire(name,lib) - if trace then - report("preventing reload of: %s",name) - end - blocked[name]=lib or _G[name] or false -end -function sandbox.enable() - if not sandboxed then - debug={ - traceback=debug.traceback, - } - for i=1,#initializers do - initializers[i].action() - end - for i=1,#finalizers do - finalizers[i].action() - end - local nnot=0 - local nyes=0 - local cnot={} - local cyes={} - local skip={} - for k,v in next,overloads do - local c=comments[k] - if v then - if c then - cyes[#cyes+1]=c - else - nyes=nyes+1 - end - else - if c then - cnot[#cnot+1]=c - else - nnot=nnot+1 - end - end - end - for k,v in next,skiploads do - skip[#skip+1]=v - end - if #cyes>0 then - sort(cyes) - report("overloaded known: %s",concat(cyes," | ")) - end - if nyes>0 then - report("overloaded unknown: %s",nyes) - end - if #cnot>0 then - sort(cnot) - report("not overloaded known: %s",concat(cnot," | ")) - end - if nnot>0 then - report("not overloaded unknown: %s",nnot) - end - if #skip>0 then - sort(skip) - report("not overloaded redefined: %s",concat(skip," | ")) - end - initializers=nil - finalizers=nil - originals=nil - sandboxed=true - end -end -blockrequire("lfs",lfs) -blockrequire("io",io) -blockrequire("os",os) -blockrequire("ffi",ffi) -local function supported(library) - local l=_G[library] - return l -end -loadfile=register(loadfile,"loadfile") -if supported("lua") then - lua.openfile=register(lua.openfile,"lua.openfile") -end -if supported("io") then - io.open=register(io.open,"io.open") - io.popen=register(io.popen,"io.popen") - io.lines=register(io.lines,"io.lines") - io.output=register(io.output,"io.output") - io.input=register(io.input,"io.input") -end -if supported("os") then - os.execute=register(os.execute,"os.execute") - os.spawn=register(os.spawn,"os.spawn") - os.exec=register(os.exec,"os.exec") - os.rename=register(os.rename,"os.rename") - os.remove=register(os.remove,"os.remove") -end -if supported("lfs") then - lfs.chdir=register(lfs.chdir,"lfs.chdir") - lfs.mkdir=register(lfs.mkdir,"lfs.mkdir") - lfs.rmdir=register(lfs.rmdir,"lfs.rmdir") - lfs.isfile=register(lfs.isfile,"lfs.isfile") - lfs.isdir=register(lfs.isdir,"lfs.isdir") - lfs.attributes=register(lfs.attributes,"lfs.attributes") - lfs.dir=register(lfs.dir,"lfs.dir") - lfs.lock_dir=register(lfs.lock_dir,"lfs.lock_dir") - lfs.touch=register(lfs.touch,"lfs.touch") - lfs.link=register(lfs.link,"lfs.link") - lfs.setmode=register(lfs.setmode,"lfs.setmode") - lfs.readlink=register(lfs.readlink,"lfs.readlink") - lfs.shortname=register(lfs.shortname,"lfs.shortname") - lfs.symlinkattributes=register(lfs.symlinkattributes,"lfs.symlinkattributes") -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-package"] = package.loaded["l-package"] or true - --- original size: 12566, stripped down to: 8937 - -if not modules then modules={} end modules ['l-package']={ - 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,unpack=type,unpack -local gsub,format,find=string.gsub,string.format,string.find -local insert,remove=table.insert,table.remove -local P,S,Cs,lpegmatch=lpeg.P,lpeg.S,lpeg.Cs,lpeg.match -local package=package -local searchers=package.searchers or package.loaders -local filejoin=file and file.join or function(path,name) return path.."/"..name end -local isreadable=file and file.is_readable or function(name) local f=io.open(name) if f then f:close() return true end end -local addsuffix=file and file.addsuffix or function(name,suffix) return name.."."..suffix end -local function cleanpath(path) - return path -end -local pattern=Cs((((1-S("\\/"))^0*(S("\\/")^1/"/"))^0*(P(".")^1/"/"+P(1))^1)*-1) -local function lualibfile(name) - return lpegmatch(pattern,name) or name -end -local offset=luarocks and 1 or 0 -local helpers=package.helpers or { - cleanpath=cleanpath, - lualibfile=lualibfile, - trace=false, - report=function(...) print(format(...)) end, - builtin={ - ["preload table"]=searchers[1+offset], - ["path specification"]=searchers[2+offset], - ["cpath specification"]=searchers[3+offset], - ["all in one fallback"]=searchers[4+offset], - }, - methods={}, - sequence={ - "reset loaded", - "already loaded", - "preload table", - "qualified path", - "lua extra list", - "lib extra list", - "path specification", - "cpath specification", - "all in one fallback", - "not loaded", - } -} -package.helpers=helpers -local methods=helpers.methods -local builtin=helpers.builtin -local extraluapaths={} -local extralibpaths={} -local checkedfiles={} -local luapaths=nil -local libpaths=nil -local oldluapath=nil -local oldlibpath=nil -local nofextralua=-1 -local nofextralib=-1 -local nofpathlua=-1 -local nofpathlib=-1 -local function listpaths(what,paths) - local nofpaths=#paths - if nofpaths>0 then - for i=1,nofpaths do - helpers.report("using %s path %i: %s",what,i,paths[i]) - end - else - helpers.report("no %s paths defined",what) - end - return nofpaths -end -local function getextraluapaths() - if helpers.trace and #extraluapaths~=nofextralua then - nofextralua=listpaths("extra lua",extraluapaths) - end - return extraluapaths -end -local function getextralibpaths() - if helpers.trace and #extralibpaths~=nofextralib then - nofextralib=listpaths("extra lib",extralibpaths) - end - return extralibpaths -end -local function getluapaths() - local luapath=package.path or "" - if oldluapath~=luapath then - luapaths=file.splitpath(luapath,";") - oldluapath=luapath - nofpathlua=-1 - end - if helpers.trace and #luapaths~=nofpathlua then - nofpathlua=listpaths("builtin lua",luapaths) - end - return luapaths -end -local function getlibpaths() - local libpath=package.cpath or "" - if oldlibpath~=libpath then - libpaths=file.splitpath(libpath,";") - oldlibpath=libpath - nofpathlib=-1 - end - if helpers.trace and #libpaths~=nofpathlib then - nofpathlib=listpaths("builtin lib",libpaths) - end - return libpaths -end -package.luapaths=getluapaths -package.libpaths=getlibpaths -package.extraluapaths=getextraluapaths -package.extralibpaths=getextralibpaths -local hashes={ - lua={}, - lib={}, -} -local function registerpath(tag,what,target,...) - local pathlist={... } - local cleanpath=helpers.cleanpath - local trace=helpers.trace - local report=helpers.report - local hash=hashes[what] - local function add(path) - local path=cleanpath(path) - if not hash[path] then - target[#target+1]=path - hash[path]=true - if trace then - report("registered %s path %s: %s",tag,#target,path) - end - else - if trace then - report("duplicate %s path: %s",tag,path) - end - end - end - for p=1,#pathlist do - local path=pathlist[p] - if type(path)=="table" then - for i=1,#path do - add(path[i]) - end - else - add(path) - end - end -end -local function pushpath(tag,what,target,path) - local path=helpers.cleanpath(path) - insert(target,1,path) - if helpers.trace then - helpers.report("pushing %s path in front: %s",tag,path) - end -end -local function poppath(tag,what,target) - local path=remove(target,1) - if helpers.trace then - if path then - helpers.report("popping %s path from front: %s",tag,path) - else - helpers.report("no %s path to pop",tag) - end - end -end -helpers.registerpath=registerpath -function package.extraluapath(...) - registerpath("extra lua","lua",extraluapaths,...) -end -function package.pushluapath(path) - pushpath("extra lua","lua",extraluapaths,path) -end -function package.popluapath() - poppath("extra lua","lua",extraluapaths) -end -function package.extralibpath(...) - registerpath("extra lib","lib",extralibpaths,...) -end -function package.pushlibpath(path) - pushpath("extra lib","lib",extralibpaths,path) -end -function package.poplibpath() - poppath("extra lib","lua",extralibpaths) -end -local function loadedaslib(resolved,rawname) - local base=gsub(rawname,"%.","_") - local init="luaopen_"..gsub(base,"%.","_") - local data={ resolved,init,"" } - checkedfiles[#checkedfiles+1]=data - if helpers.trace then - helpers.report("calling loadlib with '%s' with init '%s'",resolved,init) - end - local a,b,c=package.loadlib(resolved,init) - if not a and type(b)=="string" then - data[3]=string.fullstrip(b or "unknown error") - end - return a,b,c -end -helpers.loadedaslib=loadedaslib -local function loadedbypath(name,rawname,paths,islib,what) - local trace=helpers.trace - for p=1,#paths do - local path=paths[p] - local resolved=filejoin(path,name) - if trace then - helpers.report("%s path, identifying '%s' on '%s'",what,name,path) - end - if isreadable(resolved) then - if trace then - helpers.report("%s path, '%s' found on '%s'",what,name,resolved) - end - if islib then - return loadedaslib(resolved,rawname) - else - return loadfile(resolved) - end - end - end -end -helpers.loadedbypath=loadedbypath -local function loadedbyname(name,rawname) - if find(name,"^/") or find(name,"^[a-zA-Z]:/") then - local trace=helpers.trace - if trace then - helpers.report("qualified name, identifying '%s'",what,name) - end - if isreadable(name) then - if trace then - helpers.report("qualified name, '%s' found",what,name) - end - return loadfile(name) - end - end -end -helpers.loadedbyname=loadedbyname -methods["reset loaded"]=function(name) - checkedfiles={} - return false -end -methods["already loaded"]=function(name) - return package.loaded[name] -end -methods["preload table"]=function(name) - local f=builtin["preload table"] - if f then - return f(name) - end -end -methods["qualified path"]=function(name) - return loadedbyname(addsuffix(lualibfile(name),"lua"),name) -end -methods["lua extra list"]=function(name) - return loadedbypath(addsuffix(lualibfile(name),"lua"),name,getextraluapaths(),false,"lua") -end -methods["lib extra list"]=function(name) - return loadedbypath(addsuffix(lualibfile(name),os.libsuffix),name,getextralibpaths(),true,"lib") -end -methods["path specification"]=function(name) - local f=builtin["path specification"] - if f then - getluapaths() - return f(name) - end -end -methods["cpath specification"]=function(name) - local f=builtin["cpath specification"] - if f then - getlibpaths() - return f(name) - end -end -methods["all in one fallback"]=function(name) - local f=builtin["all in one fallback"] - if f then - return f(name) - end -end -methods["not loaded"]=function(name) - if helpers.trace then - helpers.report("unable to locate '%s'",name or "?") - for i=1,#checkedfiles do - helpers.report("checked file '%s', initializer '%s', message '%s'",unpack(checkedfiles[i])) - end - end - return nil -end -local level=0 -local used={} -helpers.traceused=false -function helpers.loaded(name) - local sequence=helpers.sequence - level=level+1 - for i=1,#sequence do - local method=sequence[i] - local lookup=method and methods[method] - if type(lookup)=="function" then - if helpers.trace then - helpers.report("%s, level '%s', method '%s', name '%s'","locating",level,method,name) - end - local result,rest=lookup(name) - if type(result)=="function" then - if helpers.trace then - helpers.report("%s, level '%s', method '%s', name '%s'","found",level,method,name) - end - if helpers.traceused then - used[#used+1]={ level=level,name=name } - end - level=level-1 - return result,rest - end - end - end - level=level-1 - return nil -end -function helpers.showused() - local n=#used - if n>0 then - helpers.report("%s libraries loaded:",n) - helpers.report() - for i=1,n do - local u=used[i] - helpers.report("%i %a",u.level,u.name) - end - helpers.report() - end -end -function helpers.unload(name) - if helpers.trace then - if package.loaded[name] then - helpers.report("unloading, name '%s', %s",name,"done") - else - helpers.report("unloading, name '%s', %s",name,"not loaded") - end - end - package.loaded[name]=nil -end -table.insert(searchers,1,helpers.loaded) -if context then - package.path="" -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-lpeg"] = package.loaded["l-lpeg"] or true - --- original size: 38742, stripped down to: 19489 - -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 lpeg=lpeg -if not lpeg.print then function lpeg.print(...) print(lpeg.pcode(...)) end end -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 -if setinspector then - setinspector("lpeg",function(v) if lpegtype(v) then lpegprint(v) return true end 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 sign=S('+-') -local zero=P('0') -local digit=R('09') -local digits=digit^1 -local octdigit=R("07") -local octdigits=octdigit^1 -local lowercase=R("az") -local uppercase=R("AZ") -local underscore=P("_") -local hexdigit=digit+lowercase+uppercase -local hexdigits=hexdigit^1 -local cr,lf,crlf=P("\r"),P("\n"),P("\r\n") -local newline=P("\r")*(P("\n")+P(true))+P("\n") -local escaped=P("\\")*anything -local squote=P("'") -local dquote=P('"') -local space=P(" ") -local period=P(".") -local comma=P(",") -local utfbom_32_be=P('\000\000\254\255') -local utfbom_32_le=P('\255\254\000\000') -local utfbom_16_be=P('\254\255') -local utfbom_16_le=P('\255\254') -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 utfstricttype=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") -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.utfbom_32_be=utfbom_32_be -patterns.utfbom_32_le=utfbom_32_le -patterns.utfbom_16_be=utfbom_16_be -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 -patterns.utf8four=R("\240\244")*utf8next*utf8next*utf8next -patterns.utfbom=utfbom -patterns.utftype=utftype -patterns.utfstricttype=utfstricttype -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 fullstripper=whitespace^0*C((whitespace^0*nonwhitespace^1)^0) -local collapser=Cs(spacer^0/""*nonspacer^0*((spacer^0/" "*nonspacer^1)^0)) -local nospacer=Cs((whitespace^1/""+nonwhitespace^1)^0) -local b_collapser=Cs(whitespace^0/""*(nonwhitespace^1+whitespace^1/" ")^0) -local m_collapser=Cs((nonwhitespace^1+whitespace^1/" ")^0) -local e_collapser=Cs((whitespace^1*endofstring/""+nonwhitespace^1+whitespace^1/" ")^0) -local x_collapser=Cs((nonwhitespace^1+whitespace^1/"" )^0) -local b_stripper=Cs(spacer^0/""*(nonspacer^1+spacer^1/" ")^0) -local m_stripper=Cs((nonspacer^1+spacer^1/" ")^0) -local e_stripper=Cs((spacer^1*endofstring/""+nonspacer^1+spacer^1/" ")^0) -local x_stripper=Cs((nonspacer^1+spacer^1/"" )^0) -patterns.stripper=stripper -patterns.fullstripper=fullstripper -patterns.collapser=collapser -patterns.nospacer=nospacer -patterns.b_collapser=b_collapser -patterns.m_collapser=m_collapser -patterns.e_collapser=e_collapser -patterns.x_collapser=x_collapser -patterns.b_stripper=b_stripper -patterns.m_stripper=m_stripper -patterns.e_stripper=e_stripper -patterns.x_stripper=x_stripper -patterns.lowercase=lowercase -patterns.uppercase=uppercase -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=comma -patterns.commaspacer=comma*spacer^0 -patterns.period=period -patterns.colon=P(":") -patterns.semicolon=P(";") -patterns.underscore=underscore -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.digit=digit -patterns.digits=digits -patterns.octdigit=octdigit -patterns.octdigits=octdigits -patterns.hexdigit=hexdigit -patterns.hexdigits=hexdigits -patterns.sign=sign -patterns.cardinal=digits -patterns.integer=sign^-1*digits -patterns.unsigned=digit^0*period*digits -patterns.float=sign^-1*patterns.unsigned -patterns.cunsigned=digit^0*comma*digits -patterns.cpunsigned=digit^0*(period+comma)*digits -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*octdigits -patterns.octal=patterns.oct -patterns.HEX=zero*P("X")*(digit+uppercase)^1 -patterns.hex=zero*P("x")*(digit+lowercase)^1 -patterns.hexadecimal=zero*S("xX")*hexdigits -patterns.hexafloat=sign^-1*zero*S("xX")*(hexdigit^0*period*hexdigits+hexdigits*period*hexdigit^0+hexdigits)*(S("pP")*sign^-1*hexdigits)^-1 -patterns.decafloat=sign^-1*(digit^0*period*digits+digits*period*digit^0+digits)*S("eE")*sign^-1*digits -patterns.propername=(uppercase+lowercase+underscore)*(uppercase+lowercase+underscore+digit)^0*endofstring -patterns.somecontent=(anything-newline-space)^1 -patterns.beginline=#(1-newline) -patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(endofstring+Cc(" ")))^0)) -local function anywhere(pattern) - return (1-P(pattern))^0*P(pattern) -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) - if action then - return (((1-P(pattern))^1)/action+1)^0 - else - return (Cs((1-P(pattern))^1)+1)^0 - end -end -function lpeg.tsplitter(pattern,action) - if action then - return Ct((((1-P(pattern))^1)/action+1)^0) - else - return Ct((Cs((1-P(pattern))^1)+1)^0) - end -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,isutf) - 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 - if isutf then - pattern=((utf8char or 1)-pattern)^0*pattern - else - pattern=(1-pattern)^0*pattern - end - 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 - local pattern=P(separator) - splitter=C((1-pattern)^0) - splitters_f[separator]=splitter - end - return splitter -end -function lpeg.secondofsplit(separator) - local splitter=splitters_s[separator] - if not splitter then - local pattern=P(separator) - splitter=(1-pattern)^0*pattern*C(anything^0) - splitters_s[separator]=splitter - end - return splitter -end -local splitters_s,splitters_p={},{} -function lpeg.beforesuffix(separator) - local splitter=splitters_s[separator] - if not splitter then - local pattern=P(separator) - splitter=C((1-pattern)^0)*pattern*endofstring - splitters_s[separator]=splitter - end - return splitter -end -function lpeg.afterprefix(separator) - local splitter=splitters_p[separator] - if not splitter then - local pattern=P(separator) - splitter=pattern*C(anything^0) - splitters_p[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 -function lpeg.counter(pattern,action) - local n=0 - local pattern=(P(pattern)/function() n=n+1 end+anything)^0 - if action then - return function(str) n=0;lpegmatch(pattern,str);action(n) end - else - return function(str) n=0;lpegmatch(pattern,str);return n end - 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 p_false=P(false) -local p_true=P(true) -local lower=utf and utf.lower or string.lower -local upper=utf and utf.upper or string.upper -function lpeg.setutfcasers(l,u) - lower=l or lower - upper=u or upper -end -local function make1(t,rest) - 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)*make1(v,v[""]) - end - end - end - if rest then - p=p+p_true - end - return p -end -local function make2(t,rest) - 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(lower(k))+P(upper(k)))*p_true - elseif v==false then - else - p=p+(P(lower(k))+P(upper(k)))*make2(v,v[""]) - end - end - end - if rest then - p=p+p_true - end - return p -end -local function utfchartabletopattern(list,insensitive) - local tree={} - 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 - end - end - return (insensitive and make2 or make1)(tree) -end -lpeg.utfchartabletopattern=utfchartabletopattern -function lpeg.utfreplacer(list,insensitive) - local pattern=Cs((utfchartabletopattern(list,insensitive)/list+utf8character)^0) - return function(str) - return lpegmatch(pattern,str) or str - end -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 -do - local trailingzeros=zero^0*-digit - local stripper=Cs(( - digits*( - period*trailingzeros/""+period*(digit-trailingzeros)^1*(trailingzeros/"") - )+1 - )^0) - lpeg.patterns.stripzeros=stripper - local nonzero=digit-zero - local trailingzeros=zero^1*endofstring - local stripper=Cs((1-period)^0*( - period*trailingzeros/""+period*(nonzero^1+(trailingzeros/"")+zero^1)^0+endofstring - )) - lpeg.patterns.stripzero=stripper -end -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 -local patterns={} -local function containsws(what) - local p=patterns[what] - if not p then - local p1=P(what)*(whitespace+endofstring)*Cc(true) - local p2=whitespace*P(p1) - p=P(p1)+P(1-p2)^0*p2+Cc(false) - patterns[what]=p - end - return p -end -lpeg.containsws=containsws -function string.containsws(str,what) - return lpegmatch(patterns[what] or containsws(what),str) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-function"] = package.loaded["l-function"] or true - --- original size: 361, stripped down to: 317 - -if not modules then modules={} end modules ['l-functions']={ - 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" -} -functions=functions or {} -function functions.dummy() end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-string"] = package.loaded["l-string"] or true - --- original size: 6955, stripped down to: 3504 - -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,find=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower,string.find -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 - local i=1 - local l=#pattern - while true do - i=find(str,pattern,i) - if i then - n=n+1 - i=i+l - else - break - end - 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 fullstripper=patterns.fullstripper -local collapser=patterns.collapser -local nospacer=patterns.nospacer -local longtostring=patterns.longtostring -function string.strip(str) - return str and lpegmatch(stripper,str) or "" -end -function string.fullstrip(str) - return str and lpegmatch(fullstripper,str) or "" -end -function string.collapsespaces(str) - return str and lpegmatch(collapser,str) or "" -end -function string.nospaces(str) - return str and lpegmatch(nospacer,str) or "" -end -function string.longtostring(str) - return str and lpegmatch(longtostring,str) or "" -end -local pattern=P(" ")^0*P(-1) -function string.is_empty(str) - if not str or str=="" then - return true - else - return lpegmatch(pattern,str) and true or false - end -end -local anything=patterns.anything -local moreescapes=Cc("%")*S(".-+%?()[]*$^{}") -local allescapes=Cc("%")*S(".-+%?()[]*") -local someescapes=Cc("%")*S(".-+%()[]") -local matchescapes=Cc(".")*S("*?") -local pattern_m=Cs ((moreescapes+anything )^0 ) -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=="all" then - str=lpegmatch(pattern_m,str) - 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_c=Ct(C(1)^0) -local pattern_b=Ct((C(1)/byte)^0) -function string.totable(str,bytes) - return lpegmatch(bytes and pattern_b or pattern_c,str) -end -local replacer=lpeg.replacer("@","%%") -function string.tformat(fmt,...) - return format(lpegmatch(replacer,fmt),...) -end -string.quote=string.quoted -string.unquote=string.unquoted -if not string.bytetable then - local limit=5000 - function string.bytetable(str) - local n=#str - if n>limit then - local t={ byte(str,1,limit) } - for i=limit+1,n do - t[i]=byte(str,i) - end - return t - else - return { byte(str,1,n) } - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-table"] = package.loaded["l-table"] or true - --- original size: 41758, stripped down to: 22643 - -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,select,rawget=type,next,tostring,tonumber,select,rawget -local table,string=table,string -local concat,sort=table.concat,table.sort -local format,lower,dump=string.format,string.lower,string.dump -local getmetatable,setmetatable=getmetatable,setmetatable -local lpegmatch,patterns=lpeg.match,lpeg.patterns -local floor=math.floor -local stripper=patterns.stripper -function table.getn(t) - return t and #t -end -function table.strip(tab) - local lst={} - local 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={} - local 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=type(a) - if ta=="number" then - local tb=type(b) - if ta==tb then - return a<b - elseif tb=="string" then - return tostring(a)<b - end - elseif ta=="string" then - local tb=type(b) - if ta==tb then - return a<b - else - return a<tostring(b) - end - end - return tostring(a)<tostring(b) -end -local function sortedkeys(tab) - if tab then - local srt={} - local category=0 - local s=0 - for key in next,tab do - s=s+1 - srt[s]=key - if category~=3 then - local tkey=type(key) - if category==1 then - if tkey~="string" then - category=3 - end - elseif category==2 then - if tkey~="number" then - category=3 - end - else - if tkey=="string" then - category=1 - elseif tkey=="number" then - category=2 - else - category=3 - end - end - end - end - if s<2 then - elseif category==3 then - sort(srt,compare) - else - sort(srt) - end - return srt - else - return {} - end -end -local function sortedhashonly(tab) - if tab then - local srt={} - local s=0 - for key in next,tab do - if type(key)=="string" then - s=s+1 - srt[s]=key - end - end - if s>1 then - sort(srt) - end - return srt - else - return {} - end -end -local function sortedindexonly(tab) - if tab then - local srt={} - local s=0 - for key in next,tab do - if type(key)=="number" then - s=s+1 - srt[s]=key - end - end - if s>1 then - sort(srt) - end - return srt - else - return {} - end -end -local function sortedhashkeys(tab,cmp) - if tab then - local srt={} - local s=0 - for key in next,tab do - if key then - s=s+1 - srt[s]=key - end - end - if s>1 then - sort(srt,cmp) - end - return srt - else - return {} - end -end -function table.allkeys(t) - local keys={} - for k,v in next,t do - for k in next,v do - keys[k]=true - end - end - return sortedkeys(keys) -end -table.sortedkeys=sortedkeys -table.sortedhashonly=sortedhashonly -table.sortedindexonly=sortedindexonly -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 m=#s - if m==1 then - return next,t - elseif m>0 then - local n=0 - return function() - if n<m then - n=n+1 - local k=s[n] - return k,t[k] - end - end - end - end - return nothing -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,...) - if not t then - t={} - end - 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={} - local 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) - if not tables then - tables={} - end - 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={} - local 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,compact,inline,functions,metacheck,accurate -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', - 'NaN','goto','const', -} -local function is_simple_table(t,hexify,accurate) - local nt=#t - if nt>0 then - local n=0 - for _,v in next,t do - n=n+1 - if type(v)=="table" then - return nil - end - end - local haszero=rawget(t,0) - if n==nt then - local tt={} - for i=1,nt do - local v=t[i] - local tv=type(v) - if tv=="number" then - if hexify then - tt[i]=format("0x%X",v) - elseif accurate then - tt[i]=format("%q",v) - else - tt[i]=v - end - elseif tv=="string" then - tt[i]=format("%q",v) - elseif tv=="boolean" then - tt[i]=v and "true" or "false" - else - return nil - end - end - return tt - elseif haszero and (n==nt+1) then - local tt={} - for i=0,nt do - local v=t[i] - local tv=type(v) - if tv=="number" then - if hexify then - tt[i+1]=format("0x%X",v) - elseif accurate then - tt[i+1]=format("%q",v) - else - tt[i+1]=v - end - elseif tv=="string" then - tt[i+1]=format("%q",v) - elseif tv=="boolean" then - tt[i+1]=v and "true" or "false" - else - return nil - end - end - tt[1]="[0] = "..tt[1] - return tt - end - end - return nil -end -table.is_simple_table=is_simple_table -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%X]={",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,name and "true" or "false")) - else - handle(format("%s{",depth)) - end - end - end - if root and next(root)~=nil then - local first=nil - local last=0 - if compact then - last=#root - for k=1,last do - if rawget(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 tv=type(v) - local tk=type(k) - 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%X,",depth,v)) - elseif accurate then - handle(format("%s %q,",depth,v)) - else - handle(format("%s %s,",depth,v)) - end - elseif tv=="string" then - handle(format("%s %q,",depth,v)) - elseif tv=="table" then - if next(v)==nil then - handle(format("%s {},",depth)) - elseif inline then - local st=is_simple_table(v,hexify,accurate) - 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 tv=="boolean" then - handle(format("%s %s,",depth,v and "true" or "false")) - elseif tv=="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 tv=="number" then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=0x%X,",depth,k,v)) - elseif accurate then - handle(format("%s [%s]=%q,",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%X,",depth,k and "true" or "false",v)) - elseif accurate then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) - else - handle(format("%s [%s]=%s,",depth,k and "true" or "false",v)) - end - elseif tk~="string" then - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - if hexify then - handle(format("%s %s=0x%X,",depth,k,v)) - elseif accurate then - handle(format("%s %s=%q,",depth,k,v)) - else - handle(format("%s %s=%s,",depth,k,v)) - end - else - if hexify then - handle(format("%s [%q]=0x%X,",depth,k,v)) - elseif accurate then - handle(format("%s [%q]=%q,",depth,k,v)) - else - handle(format("%s [%q]=%s,",depth,k,v)) - end - end - elseif tv=="string" then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=%q,",depth,k,v)) - elseif accurate then - handle(format("%s [%q]=%q,",depth,k,v)) - else - handle(format("%s [%s]=%q,",depth,k,v)) - end - elseif tk=="boolean" then - handle(format("%s [%s]=%q,",depth,k and "true" or "false",v)) - elseif tk~="string" then - 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 - elseif tv=="table" then - if next(v)==nil then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]={},",depth,k)) - elseif accurate then - handle(format("%s [%q]={},",depth,k)) - else - handle(format("%s [%s]={},",depth,k)) - end - elseif tk=="boolean" then - handle(format("%s [%s]={},",depth,k and "true" or "false")) - elseif tk~="string" then - 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=is_simple_table(v,hexify,accurate) - if st then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]={ %s },",depth,k,concat(st,", "))) - elseif accurate then - handle(format("%s [%q]={ %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,k and "true" or "false",concat(st,", "))) - elseif tk~="string" then - 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 tv=="boolean" then - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false")) - elseif accurate then - handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) - else - handle(format("%s [%s]=%s,",depth,k,v and "true" or "false")) - end - elseif tk=="boolean" then - handle(format("%s [%s]=%s,",depth,tostring(k),v and "true" or "false")) - elseif tk~="string" then - elseif noquotes and not reserved[k] and lpegmatch(propername,k) then - handle(format("%s %s=%s,",depth,k,v and "true" or "false")) - else - handle(format("%s [%q]=%s,",depth,k,v and "true" or "false")) - end - elseif tv=="function" then - if functions then - local getinfo=debug and debug.getinfo - if getinfo then - local f=getinfo(v).what=="C" and dump(dummy) or dump(v) - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=load(%q),",depth,k,f)) - elseif accurate then - handle(format("%s [%q]=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,k and "true" or "false",f)) - elseif tk~="string" then - 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 - end - else - if tk=="number" then - if hexify then - handle(format("%s [0x%X]=%q,",depth,k,tostring(v))) - elseif accurate then - handle(format("%s [%q]=%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,k and "true" or "false",tostring(v))) - elseif tk~="string" then - 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 - accurate=specification.accurate - handle=_handle or specification.handle or print - functions=specification.functions - compact=specification.compact - inline=specification.inline and compact - metacheck=specification.metacheck - if functions==nil then - functions=true - end - if compact==nil then - compact=true - end - if inline==nil then - inline=compact - end - if metacheck==nil then - metacheck=true - end - else - noquotes=false - hexify=false - handle=_handle or print - compact=true - inline=true - functions=true - metacheck=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%X]={",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 metacheck and 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)~=nil then - do_serialize(root,name,"",0) - end - end - handle("}") -end -function table.serialize(root,name,specification) - local t={} - local 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={} - local 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 collapsed(t,f,h) - if f==nil then - f={} - h={} - end - for k=1,#t do - local v=t[k] - if type(v)=="table" then - collapsed(v,f,h) - elseif not h[v] then - f[#f+1]=v - h[v]=true - end - end - return f -end -local function collapsedhash(t,h) - if h==nil then - h={} - end - for k=1,#t do - local v=t[k] - if type(v)=="table" then - collapsedhash(v,h) - else - h[v]=true - end - end - return h -end -table.collapsed=collapsed -table.collapsedhash=collapsedhash -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==b then - return true - elseif a and b and #a==#b then - if not n then - n=1 - end - if not m then - m=#a - end - 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) - if a~=b then - 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 - end - return true -end -table.identical=identical -table.are_equal=are_equal -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 - 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.hashed(t) - for i=1,#t do - t[t[i]]=i - end - return t -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={} - local 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 - local m=n+1 - for i=1,floor(n/2) do - local j=m-i - t[i],t[j]=t[j],t[i] - end - return t - end -end -local function sequenced(t,sep,simple) - if not t then - return "" - elseif type(t)~="table" then - return t - end - local n=#t - local s={} - if n>0 then - for i=1,n do - local v=t[i] - if type(v)=="table" then - s[i]="{"..sequenced(v,sep,simple).."}" - else - s[i]=tostring(t[i]) - end - 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 - if type(v)=="table" then - s[n]=k.."={"..sequenced(v,sep,simple).."}" - else - s[n]=k.."="..tostring(v) - end - end - else - n=n+1 - if type(v)=="table" then - s[n]=k.."={"..sequenced(v,sep,simple).."}" - else - s[n]=k.."="..tostring(v) - end - end - end - end - if sep==true then - return "{ "..concat(s,", ").." }" - else - return concat(s,sep or " | ") - end -end -table.sequenced=sequenced -function table.print(t,...) - if type(t)~="table" then - print(tostring(t)) - else - serialize(print,t,...) - end -end -if setinspector then - setinspector("table",function(v) if type(v)=="table" then serialize(print,v,"table") return true end end) -end -function table.sub(t,i,j) - return { unpack(t,i,j) } -end -function table.is_empty(t) - return not t or next(t)==nil -end -function table.has_one_entry(t) - return t and next(t,next(t))==nil -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 -function table.values(t,s) - if t then - local values={} - local keys={} - local v=0 - for key,value in next,t do - if not keys[value] then - v=v+1 - values[v]=value - keys[k]=key - end - end - if s then - sort(values) - end - return values - else - 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 -if not table.move then - function table.move(a1,f,e,t,a2) - if a2 and a1~=a2 then - for i=f,e do - a2[t]=a1[i] - t=t+1 - end - return a2 - else - t=t+e-f - for i=e,f,-1 do - a1[t]=a1[i] - t=t-1 - end - return a1 - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-io"] = package.loaded["l-io"] or true - --- original size: 11988, stripped down to: 6430 - -if not modules then modules={} end modules ['l-io']={ - 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 io=io -local open,flush,write,read=io.open,io.flush,io.write,io.read -local byte,find,gsub,format=string.byte,string.find,string.gsub,string.format -local concat=table.concat -local type=type -if string.find(os.getenv("PATH") or "",";",1,true) then - io.fileseparator,io.pathseparator="\\",";" -else - io.fileseparator,io.pathseparator="/",":" -end -local large=0x01000000 -local medium=0x00100000 -local small=0x00020000 -local function readall(f) - local size=f:seek("end") - if size>0 then - f:seek("set",0) - return f:read(size) - else - return "" - end -end -io.readall=readall -function io.loaddata(filename,textmode) - local f=open(filename,(textmode and 'r') or 'rb') - if f then - local size=f:seek("end") - local data=nil - if size>0 then - f:seek("set",0) - data=f:read(size) - end - f:close() - return data - end -end -function io.copydata(source,target,action) - local f=open(source,"rb") - if f then - local g=open(target,"wb") - if g then - local size=f:seek("end") - if size>0 then - f:seek("set",0) - local data=f:read(size) - if action then - data=action(data) - end - if data then - g:write(data) - end - end - g:close() - end - f:close() - flush() - end -end -function io.savedata(filename,data,joiner,append) - local f=open(filename,append and "ab" or "wb") - if f then - if append and joiner and f:seek("end")>0 then - f:write(joiner) - end - if type(data)=="table" then - f:write(concat(data,joiner or "")) - elseif type(data)=="function" then - data(f) - else - f:write(data or "") - end - f:close() - flush() - return true - else - return false - end -end -if fio and fio.readline then - local readline=fio.readline - function io.loadlines(filename,n) - local f=open(filename,'r') - if not f then - elseif n then - local lines={} - for i=1,n do - local line=readline(f) - if line then - lines[i]=line - else - break - end - end - f:close() - lines=concat(lines,"\n") - if #lines>0 then - return lines - end - else - local line=readline(f) - f:close() - if line and #line>0 then - return line - end - end - end -else - function io.loadlines(filename,n) - local f=open(filename,'r') - if not f then - elseif n then - local lines={} - for i=1,n do - local line=f:read("*lines") - if line then - lines[i]=line - else - break - end - end - f:close() - lines=concat(lines,"\n") - if #lines>0 then - return lines - end - else - local line=f:read("*line") or "" - f:close() - if #line>0 then - return line - end - end - end -end -function io.loadchunk(filename,n) - local f=open(filename,'rb') - if f then - local data=f:read(n or 1024) - f:close() - if #data>0 then - return data - end - end -end -function io.exists(filename) - local f=open(filename) - if f==nil then - return false - else - f:close() - return true - end -end -function io.size(filename) - local f=open(filename) - if f==nil then - return 0 - else - local s=f:seek("end") - f:close() - return s - end -end -local function noflines(f) - if type(f)=="string" then - local f=open(filename) - if f then - local n=f and noflines(f) or 0 - f:close() - return n - else - return 0 - end - else - local n=0 - for _ in f:lines() do - n=n+1 - end - f:seek('set',0) - return n - end -end -io.noflines=noflines -local nextchar={ - [ 4]=function(f) - return f:read(1,1,1,1) - end, - [ 2]=function(f) - return f:read(1,1) - end, - [ 1]=function(f) - return f:read(1) - end, - [-2]=function(f) - local a,b=f:read(1,1) - return b,a - end, - [-4]=function(f) - local a,b,c,d=f:read(1,1,1,1) - return d,c,b,a - end -} -function io.characters(f,n) - if f then - return nextchar[n or 1],f - end -end -local nextbyte={ - [4]=function(f) - local a,b,c,d=f:read(1,1,1,1) - if d then - return byte(a),byte(b),byte(c),byte(d) - end - end, - [3]=function(f) - local a,b,c=f:read(1,1,1) - if b then - return byte(a),byte(b),byte(c) - end - end, - [2]=function(f) - local a,b=f:read(1,1) - if b then - return byte(a),byte(b) - end - end, - [1]=function (f) - local a=f:read(1) - if a then - return byte(a) - end - end, - [-2]=function (f) - local a,b=f:read(1,1) - if b then - return byte(b),byte(a) - end - end, - [-3]=function(f) - local a,b,c=f:read(1,1,1) - if b then - return byte(c),byte(b),byte(a) - end - end, - [-4]=function(f) - local a,b,c,d=f:read(1,1,1,1) - if d then - return byte(d),byte(c),byte(b),byte(a) - end - end -} -function io.bytes(f,n) - if f then - return nextbyte[n or 1],f - else - return nil,nil - end -end -function io.ask(question,default,options) - while true do - write(question) - if options then - write(format(" [%s]",concat(options,"|"))) - end - if default then - write(format(" [%s]",default)) - end - write(format(" ")) - flush() - local answer=read() - answer=gsub(answer,"^%s*(.*)%s*$","%1") - if answer=="" and default then - return default - elseif not options then - return answer - else - for k=1,#options do - if options[k]==answer then - return answer - end - end - local pattern="^"..answer - for k=1,#options do - local v=options[k] - if find(v,pattern) then - return v - end - end - end - end -end -local function readnumber(f,n,m) - if m then - f:seek("set",n) - n=m - end - if n==1 then - return byte(f:read(1)) - elseif n==2 then - local a,b=byte(f:read(2),1,2) - return 0x100*a+b - elseif n==3 then - local a,b,c=byte(f:read(3),1,3) - return 0x10000*a+0x100*b+c - elseif n==4 then - local a,b,c,d=byte(f:read(4),1,4) - return 0x1000000*a+0x10000*b+0x100*c+d - elseif n==8 then - local a,b=readnumber(f,4),readnumber(f,4) - return 0x100*a+b - elseif n==12 then - local a,b,c=readnumber(f,4),readnumber(f,4),readnumber(f,4) - return 0x10000*a+0x100*b+c - elseif n==-2 then - local b,a=byte(f:read(2),1,2) - return 0x100*a+b - elseif n==-3 then - local c,b,a=byte(f:read(3),1,3) - return 0x10000*a+0x100*b+c - elseif n==-4 then - local d,c,b,a=byte(f:read(4),1,4) - return 0x1000000*a+0x10000*b+0x100*c+d - elseif n==-8 then - local h,g,f,e,d,c,b,a=byte(f:read(8),1,8) - return 0x100000000000000*a+0x1000000000000*b+0x10000000000*c+0x100000000*d+0x1000000*e+0x10000*f+0x100*g+h - else - return 0 - end -end -io.readnumber=readnumber -function io.readstring(f,n,m) - if m then - f:seek("set",n) - n=m - end - local str=gsub(f:read(n),"\000","") - return str -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-number"] = package.loaded["l-number"] or true - --- original size: 4588, stripped down to: 2159 - -if not modules then modules={} end modules ['l-number']={ - version=1.001, - comment="companion to luat-lib.mkxl", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local tostring,tonumber=tostring,tonumber -local format,match,rep=string.format,string.match,string.rep -local concat,insert=table.concat,table.insert -local lpegmatch=lpeg.match -local floor=math.floor -number=number or {} -local number=number -if bit32 then - local bextract=bit32.extract - local t={ - "0","0","0","0","0","0","0","0", - "0","0","0","0","0","0","0","0", - "0","0","0","0","0","0","0","0", - "0","0","0","0","0","0","0","0", - } - function number.tobitstring(b,m,w) - if not w then - w=32 - end - local n=w - for i=0,w-1 do - local v=bextract(b,i) - local k=w-i - if v==1 then - n=k - t[k]="1" - else - t[k]="0" - end - end - if w then - return concat(t,"",1,w) - elseif m then - m=33-m*8 - if m<1 then - m=1 - end - return concat(t,"",1,m) - elseif n<8 then - return concat(t) - elseif n<16 then - return concat(t,"",9) - elseif n<24 then - return concat(t,"",17) - else - return concat(t,"",25) - end - end -else - function number.tobitstring(n,m) - if n>0 then - local t={} - while n>0 do - insert(t,1,n%2>0 and 1 or 0) - n=floor(n/2) - end - local nn=8-#t%8 - if nn>0 and nn<8 then - for i=1,nn do - insert(t,1,0) - end - end - if m then - m=m*8-#t - if m>0 then - insert(t,1,rep("0",m)) - end - end - return concat(t) - elseif m then - rep("00000000",m) - else - return "00000000" - end - end -end -function number.valid(str,default) - return tonumber(str) or default or nil -end -function number.toevenhex(n) - local s=format("%X",n) - if #s%2==0 then - return s - else - return "0"..s - end -end -function number.bytetodecimal(b) - local d=floor(b*100/255+0.5) - if d>100 then - return 100 - elseif d<-100 then - return -100 - else - return d - end -end -function number.decimaltobyte(d) - local b=floor(d*255/100+0.5) - if b>255 then - return 255 - elseif b<-255 then - return -255 - else - return b - end -end -function number.idiv(i,d) - return floor(i/d) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-set"] = package.loaded["l-set"] or true - --- original size: 1923, stripped down to: 1044 - -if not modules then modules={} end modules ['l-set']={ - 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" -} -set=set or {} -local nums={} -local tabs={} -local concat=table.concat -local next,type=next,type -set.create=table.tohash -function set.tonumber(t) - if next(t) then - local s="" - for k,v in next,t do - if v then - s=s.." "..k - end - end - local n=nums[s] - if not n then - n=#tabs+1 - tabs[n]=t - nums[s]=n - end - return n - else - return 0 - end -end -function set.totable(n) - if n==0 then - return {} - else - return tabs[n] or {} - end -end -function set.tolist(n) - if n==0 or not tabs[n] then - return "" - else - local t,n={},0 - for k,v in next,tabs[n] do - if v then - n=n+1 - t[n]=k - end - end - return concat(t," ") - end -end -function set.contains(n,s) - if type(n)=="table" then - return n[s] - elseif n==0 then - return false - else - local t=tabs[n] - return t and t[s] - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-os"] = package.loaded["l-os"] or true - --- original size: 20585, stripped down to: 10701 - -if not modules then modules={} end modules ['l-os']={ - 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 os=os -local date,time,difftime=os.date,os.time,os.difftime -local find,format,gsub,upper,gmatch=string.find,string.format,string.gsub,string.upper,string.gmatch -local concat=table.concat -local random,ceil,randomseed,modf=math.random,math.ceil,math.randomseed,math.modf -local type,setmetatable,tonumber,tostring=type,setmetatable,tonumber,tostring -do - local selfdir=os.selfdir - if selfdir=="" then - selfdir=nil - end - if not selfdir then - if arg then - for i=1,#arg do - local a=arg[i] - if find(a,"^%-%-[c:]*texmfbinpath=") then - selfdir=gsub(a,"^.-=","") - break - end - end - end - if not selfdir then - selfdir=os.selfbin or "luatex" - if find(selfdir,"[/\\]") then - selfdir=gsub(selfdir,"[/\\][^/\\]*$","") - elseif os.getenv then - local path=os.getenv("PATH") - local name=gsub(selfdir,"^.*[/\\][^/\\]","") - local patt="[^:]+" - if os.type=="windows" then - patt="[^;]+" - name=name..".exe" - end - local isfile - if lfs then - local attributes=lfs.attributes - isfile=function(name) - local a=attributes(name,"mode") - return a=="file" or a=="link" or nil - end - else - local open=io.open - isfile=function(name) - local f=open(name) - if f then - f:close() - return true - end - end - end - for p in gmatch(path,patt) do - if isfile(p.."/"..name) then - selfdir=p - break - end - end - end - end - os.selfdir=selfdir or "." - end -end -math.initialseed=tonumber(string.sub(string.reverse(tostring(ceil(socket and socket.gettime()*10000 or time()))),1,6)) -randomseed(math.initialseed) -if not os.__getenv__ then - os.__getenv__=os.getenv - os.__setenv__=os.setenv - if os.env then - local osgetenv=os.getenv - local ossetenv=os.setenv - local osenv=os.env local _=osenv.PATH - function os.setenv(k,v) - if v==nil then - v="" - end - local K=upper(k) - osenv[K]=v - if type(v)=="table" then - v=concat(v,";") - end - ossetenv(K,v) - end - function os.getenv(k) - local K=upper(k) - local v=osenv[K] or osenv[k] or osgetenv(K) or osgetenv(k) - if v=="" then - return nil - else - return v - end - end - else - local ossetenv=os.setenv - local osgetenv=os.getenv - local osenv={} - function os.setenv(k,v) - if v==nil then - v="" - end - local K=upper(k) - osenv[K]=v - end - function os.getenv(k) - local K=upper(k) - local v=osenv[K] or osgetenv(K) or osgetenv(k) - if v=="" then - return nil - else - return v - end - end - local function __index(t,k) - return os.getenv(k) - end - local function __newindex(t,k,v) - os.setenv(k,v) - end - os.env={} - setmetatable(os.env,{ __index=__index,__newindex=__newindex } ) - end -end -if not io.fileseparator then - if find(os.getenv("PATH"),";",1,true) then - io.fileseparator,io.pathseparator,os.type="\\",";",os.type or "windows" - else - io.fileseparator,io.pathseparator,os.type="/",":",os.type or "unix" - end -end -os.type=os.type or (io.pathseparator==";" and "windows") or "unix" -os.name=os.name or (os.type=="windows" and "mswin" ) or "linux" -if os.type=="windows" then - os.libsuffix,os.binsuffix,os.binsuffixes='dll','exe',{ 'exe','cmd','bat' } -else - os.libsuffix,os.binsuffix,os.binsuffixes='so','',{ '' } -end -do - local execute=os.execute - local iopopen=io.popen - local ostype=os.type - local function resultof(command) - local handle=iopopen(command,ostype=="windows" and "rb" or "r") - if handle then - local result=handle:read("*all") or "" - handle:close() - return result - else - return "" - end - end - os.resultof=resultof - function os.pipeto(command) - return iopopen(command,"w") - end - local launchers={ - windows="start %s", - macosx="open %s", - unix="xdg-open %s &> /dev/null &", - } - function os.launch(str) - local command=format(launchers[os.name] or launchers.unix,str) - execute(command) - end -end -do - local gettimeofday=os.gettimeofday or os.clock - os.gettimeofday=gettimeofday - local startuptime=gettimeofday() - function os.runtime() - return gettimeofday()-startuptime - end -end -do - local name=os.name or "linux" - local platform=os.getenv("MTX_PLATFORM") or "" - local architecture=os.uname and os.uname().machine - local bits=os.getenv("MTX_BITS") or find(platform,"64") and 64 or 32 - if platform~="" then - elseif os.type=="windows" then - architecture=string.lower(architecture or os.getenv("PROCESSOR_ARCHITECTURE") or "") - if architecture=="x86_64" then - bits,platform=64,"win64" - elseif find(architecture,"amd64") then - bits,platform=64,"win64" - elseif find(architecture,"arm64") then - bits,platform=64,"windows-arm64" - elseif find(architecture,"arm32") then - bits,platform=32,"windows-arm32" - else - bits,platform=32,"mswin" - end - elseif name=="linux" then - architecture=architecture or os.getenv("HOSTTYPE") or resultof("uname -m") or "" - local musl=find(os.selfdir or "","linuxmusl") - if find(architecture,"x86_64") then - bits,platform=64,musl and "linuxmusl" or "linux-64" - elseif find(architecture,"ppc") then - bits,platform=32,"linux-ppc" - else - bits,platform=32,musl and "linuxmusl" or "linux" - end - elseif name=="macosx" then - architecture=architecture or resultof("echo $HOSTTYPE") or "" - if architecture=="" then - bits,platform=64,"osx-intel" - elseif find(architecture,"i386") then - bits,platform=64,"osx-intel" - elseif find(architecture,"x86_64") then - bits,platform=64,"osx-64" - elseif find(architecture,"arm64") then - bits,platform=64,"osx-arm" - else - bits,platform=32,"osx-ppc" - end - elseif name=="sunos" then - architecture=architecture or resultof("uname -m") or "" - if find(architecture,"sparc") then - bits,platform=32,"solaris-sparc" - else - bits,platform=32,"solaris-intel" - end - elseif name=="freebsd" then - architecture=architecture or os.getenv("MACHTYPE") or resultof("uname -m") or "" - if find(architecture,"amd64") or find(architecture,"AMD64") then - bits,platform=64,"freebsd-amd64" - else - bits,platform=32,"freebsd" - end - elseif name=="kfreebsd" then - architecture=architecture or os.getenv("HOSTTYPE") or resultof("uname -m") or "" - if architecture=="x86_64" then - bits,platform=64,"kfreebsd-amd64" - else - bits,platform=32,"kfreebsd-i386" - end - else - architecture=architecture or resultof("uname -m") or "" - if find(architecture,"aarch64") then - bits,platform="linux-aarch64" - elseif find(architecture,"armv7l") then - bits,platform=32,"linux-armhf" - elseif find(architecture,"mips64") or find(architecture,"mips64el") then - bits,platform=64,"linux-mipsel" - elseif find(architecture,"mipsel") or find(architecture,"mips") then - bits,platform=32,"linux-mipsel" - else - bits,platform=64,"linux-64" - end - end - os.setenv("MTX_PLATFORM",platform) - os.setenv("MTX_BITS",bits) - os.platform=platform - os.bits=bits - os.newline=name=="windows" and "\013\010" or "\010" -end -do - local t={ 8,9,"a","b" } - function os.uuid() - return format("%04x%04x-4%03x-%s%03x-%04x-%04x%04x%04x", - random(0xFFFF),random(0xFFFF), - random(0x0FFF), - t[ceil(random(4))] or 8,random(0x0FFF), - random(0xFFFF), - random(0xFFFF),random(0xFFFF),random(0xFFFF) - ) - end -end -do - local hour,min - function os.timezone(difference) - if not hour then - local current=time() - local utcdate=date("!*t",current) - local localdate=date("*t",current) - localdate.isdst=false - local timediff=difftime(time(localdate),time(utcdate)) - hour,min=modf(timediff/3600) - min=min*60 - end - if difference then - return hour,min - else - return format("%+03d:%02d",hour,min) - end - end - local timeformat=format("%%s%s",os.timezone()) - local dateformat="%Y-%m-%d %H:%M:%S" - local lasttime=nil - local lastdate=nil - function os.fulltime(t,default) - t=t and tonumber(t) or 0 - if t>0 then - elseif default then - return default - else - t=time() - end - if t~=lasttime then - lasttime=t - lastdate=format(timeformat,date(dateformat)) - end - return lastdate - end - local dateformat="%Y-%m-%d %H:%M:%S" - local lasttime=nil - local lastdate=nil - function os.localtime(t,default) - t=t and tonumber(t) or 0 - if t>0 then - elseif default then - return default - else - t=time() - end - if t~=lasttime then - lasttime=t - lastdate=date(dateformat,t) - end - return lastdate - end - function os.converttime(t,default) - local t=tonumber(t) - if t and t>0 then - return date(dateformat,t) - else - return default or "-" - end - end - function os.today() - return date("!*t") - end - function os.now() - return date("!%Y-%m-%d %H:%M:%S") - end -end -do - local cache={} - local function which(filename) - local fullname=cache[filename] - if fullname==nil then - local suffix=file.suffix(filename) - local suffixes=suffix=="" and os.binsuffixes or { suffix } - for directory in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do - local df=file.join(directory,filename) - for i=1,#suffixes do - local dfs=file.addsuffix(df,suffixes[i]) - if io.exists(dfs) then - fullname=dfs - break - end - end - end - if not fullname then - fullname=false - end - cache[filename]=fullname - end - return fullname - end - os.which=which - os.where=which -end -if not os.sleep then - local socket=socket - function os.sleep(n) - if not socket then - socket=require("socket") - end - socket.sleep(n) - end -end -do - local function isleapyear(year) - return (year%4==0) and (year%100~=0 or year%400==0) - end - os.isleapyear=isleapyear - local days={ 31,28,31,30,31,30,31,31,30,31,30,31 } - local function nofdays(year,month,day) - if not month then - return isleapyear(year) and 365 or 364 - elseif not day then - return month==2 and isleapyear(year) and 29 or days[month] - else - for i=1,month-1 do - day=day+days[i] - end - if month>2 and isleapyear(year) then - day=day+1 - end - return day - end - end - os.nofdays=nofdays - function os.weekday(day,month,year) - return date("%w",time { year=year,month=month,day=day })+1 - end - function os.validdate(year,month,day) - if month<1 then - month=1 - elseif month>12 then - month=12 - end - if day<1 then - day=1 - else - local max=nofdays(year,month) - if day>max then - day=max - end - end - return year,month,day - end - function os.date(fmt,...) - if not fmt then - fmt="%Y-%m-%d %H:%M" - end - return date(fmt,...) - end -end -do - local osexit=os.exit - local exitcode=nil - function os.setexitcode(code) - exitcode=code - end - function os.exit(c) - if exitcode~=nil then - return osexit(exitcode) - end - if c~=nil then - return osexit(c) - end - return osexit() - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-file"] = package.loaded["l-file"] or true - --- original size: 22186, stripped down to: 10313 - -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 -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 attributes=lfs.attributes -function lfs.isdir(name) - if name then - return attributes(name,"mode")=="directory" - end -end -function lfs.isfile(name) - if name then - local a=attributes(name,"mode") - return a=="file" or a=="link" or nil - end -end -function lfs.isfound(name) - if name then - local a=attributes(name,"mode") - return (a=="file" or a=="link") and name or nil - end -end -function lfs.modification(name) - return name and attributes(name,"modification") or nil -end -if sandbox then - sandbox.redefine(lfs.isfile,"lfs.isfile") - sandbox.redefine(lfs.isdir,"lfs.isdir") - sandbox.redefine(lfs.isfound,"lfs.isfound") -end -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 -local pattern=(noslashes^0*slashes)^0*noperiod^1*((period*C(noperiod^1))^1)*-1+Cc("") -local function suffixesonly(name) - if name then - return lpegmatch(pattern,name) - else - return "" - end -end -file.pathpart=pathpart -file.basename=basename -file.nameonly=nameonly -file.suffixonly=suffixonly -file.suffix=suffixonly -file.suffixesonly=suffixesonly -file.suffixes=suffixesonly -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) - if str then - return lpegmatch(pattern_d,str) - else - return "",str - end -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 -if lfs.isreadablefile and lfs.iswritablefile then - file.is_readable=lfs.isreadablefile - file.is_writable=lfs.iswritablefile -else - 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 -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 someslash=S("\\/") -local stripper=Cs(P(fwslash)^0/""*reslasher) -local isnetwork=someslash*someslash*(1-someslash)+(1-fwslash-colon)^1*colon -local isroot=fwslash^1*-1 -local hasroot=fwslash^1 -local reslasher=lpeg.replacer(S("\\/"),"/") -local deslasher=lpeg.replacer(S("\\/")^1,"/") -function file.join(one,two,three,...) - if not two then - return one=="" and one or lpegmatch(reslasher,one) - end - if not one or 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,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,three and concat({ two,three,... },"/") or two) - if lpegmatch(hasroot,two) then - return two - else - return "/"..two - end - else - return lpegmatch(deslasher,concat({ one,two,three,... },"/")) - end -end -local drivespec=R("az","AZ")^1*colon -local anchors=fwslash+drivespec -local untouched=periods+(1-period)^1*P(-1) -local mswindrive=Cs(drivespec*(bwslash/"/"+fwslash)^0) -local mswinuncpath=(bwslash+fwslash)*(bwslash+fwslash)*Cc("//") -local splitstarter=(mswindrive+mswinuncpath+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 -local loaddata=io.loaddata -local savedata=io.savedata -file.readdata=loaddata -file.savedata=savedata -function file.copy(oldname,newname) - if oldname and newname then - local data=loaddata(oldname) - if data and data~="" then - 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 -function lfs.mkdirs(path) - local full="" - for sub in gmatch(path,"(/*[^\\/]+)") do - full=full..sub - lfs.mkdir(full) - end -end -function file.withinbase(path) - local l=0 - if not find(path,"^/") then - path="/"..path - end - for dir in gmatch(path,"/([^/]+)") do - if dir==".." then - l=l-1 - elseif dir~="." then - l=l+1 - end - if l<0 then - return false - end - end - return true -end -local symlinkattributes=lfs.symlinkattributes -function lfs.readlink(name) - return symlinkattributes(name,"target") or nil -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-gzip"] = package.loaded["l-gzip"] or true - --- original size: 268, stripped down to: 216 - -if not modules then modules={} end modules ['l-gzip']={ - version=1.001, - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-md5"] = package.loaded["l-md5"] or true - --- original size: 3414, stripped down to: 2307 - -if not modules then modules={} end modules ['l-md5']={ - version=1.001, - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -if not md5 then - md5=optionalrequire("md5") -end -if not md5 then - md5={ - sum=function(str) print("error: md5 is not loaded (sum ignored)") return str end, - sumhexa=function(str) print("error: md5 is not loaded (sumhexa ignored)") return str end, - } -end -local md5,file=md5,file -local gsub=string.gsub -local modification,isfile,touch=lfs.modification,lfs.isfile,lfs.touch -local loaddata,savedata=io.loaddata,io.savedata -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 - md5.sumhexa=md5.hex - md5.sumHEXA=md5.HEX - end -end -local md5HEX=md5.HEX -function file.needsupdating(oldname,newname,threshold) - local oldtime=modification(oldname) - if oldtime then - local newtime=modification(newname) - if not newtime then - return true - elseif newtime>=oldtime then - return false - elseif oldtime-newtime<(threshold or 1) then - return false - else - return true - end - else - return false - end -end -file.needs_updating=file.needsupdating -function file.syncmtimes(oldname,newname) - local oldtime=modification(oldname) - if oldtime and isfile(newname) then - touch(newname,oldtime,oldtime) - end -end -local function checksum(name) - if md5 then - local data=loaddata(name) - if data then - return md5HEX(data) - end - end - return nil -end -file.checksum=checksum -function file.loadchecksum(name) - if md5 then - local data=loaddata(name..".md5") - return data and (gsub(data,"%s","")) - end - return nil -end -function file.savechecksum(name,checksum) - if not checksum then checksum=checksum(name) end - if checksum then - savedata(name..".md5",checksum) - return checksum - end - return nil -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-sha"] = package.loaded["l-sha"] or true - --- original size: 1085, stripped down to: 969 - -if not modules then modules={} end modules ['l-sha']={ - 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" -} -if sha2 then - local lpegmatch=lpeg.match - local lpegpatterns=lpeg.patterns - local bytestohex=lpegpatterns.bytestohex - local bytestoHEX=lpegpatterns.bytestoHEX - local digest256=sha2.digest256 - local digest384=sha2.digest384 - local digest512=sha2.digest512 - sha2.hash256=function(str) return lpegmatch(bytestohex,digest256(str)) end - sha2.hash384=function(str) return lpegmatch(bytestohex,digest384(str)) end - sha2.hash512=function(str) return lpegmatch(bytestohex,digest512(str)) end - sha2.HASH256=function(str) return lpegmatch(bytestoHEX,digest256(str)) end - sha2.HASH384=function(str) return lpegmatch(bytestoHEX,digest384(str)) end - sha2.HASH512=function(str) return lpegmatch(bytestoHEX,digest512(str)) end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-url"] = package.loaded["l-url"] or true - --- original size: 14713, stripped down to: 6981 - -if not modules then modules={} end modules ['l-url']={ - 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 char,format,byte=string.char,string.format,string.byte -local concat=table.concat -local tonumber,type,next=tonumber,type,next -local P,C,R,S,Cs,Cc,Ct,Cf,Cg,V=lpeg.P,lpeg.C,lpeg.R,lpeg.S,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.Cf,lpeg.Cg,lpeg.V -local lpegmatch,lpegpatterns,replacer=lpeg.match,lpeg.patterns,lpeg.replacer -local sortedhash=table.sortedhash -url=url or {} -local url=url -local unescapes={} -local escapes={} -setmetatable(unescapes,{ __index=function(t,k) - local v=char(tonumber(k,16)) - t[k]=v - return v -end }) -setmetatable(escapes,{ __index=function(t,k) - local v=format("%%%02X",byte(k)) - t[k]=v - return v -end }) -local colon=P(":") -local qmark=P("?") -local hash=P("#") -local slash=P("/") -local atsign=P("@") -local percent=P("%") -local endofstring=P(-1) -local hexdigit=R("09","AF","af") -local plus=P("+") -local nothing=Cc("") -local okay=R("09","AZ","az")+S("-_.,:=+*~!'()@&$") -local escapedchar=(percent*C(hexdigit*hexdigit))/unescapes -local unescapedchar=P(1)/escapes -local escaped=(plus/" ")+escapedchar -local noslash=P("/")/"" -local plustospace=P("+")/" " -local decoder=Cs(( - plustospace+escapedchar+P("\r\n")/"\n"+P(1) - )^0 ) -local encoder=Cs(( - R("09","AZ","az")^1+S("-./_")^1+P(" ")/"+"+P("\n")/"\r\n"+unescapedchar - )^0 ) -lpegpatterns.urldecoder=decoder -lpegpatterns.urlencoder=encoder -function url.decode (str) return str and lpegmatch(decoder,str) or str end -function url.encode (str) return str and lpegmatch(encoder,str) or str end -function url.unescape(str) return str and lpegmatch(unescaper,str) or str end -local schemestr=Cs((escaped+(1-colon-slash-qmark-hash))^2) -local authoritystr=Cs((escaped+(1- slash-qmark-hash))^0) -local pathstr=Cs((escaped+(1- qmark-hash))^0) -local querystr=Cs(((1- hash))^0) -local fragmentstr=Cs((escaped+(1- endofstring))^0) -local scheme=schemestr*colon+nothing -local authority=slash*slash*authoritystr+nothing -local path=slash*pathstr+nothing -local query=qmark*querystr+nothing -local fragment=hash*fragmentstr+nothing -local validurl=scheme*authority*path*query*fragment -local parser=Ct(validurl) -lpegpatterns.url=validurl -lpegpatterns.urlsplitter=parser -local escaper=Cs((R("09","AZ","az")^1+P(" ")/"%%20"+S("-./_:")^1+P(1)/escapes)^0) -local unescaper=Cs((escapedchar+1)^0) -local getcleaner=Cs((P("+++")/"%%2B"+P("+")/"%%20"+P(1))^1) -lpegpatterns.urlunescaped=escapedchar -lpegpatterns.urlescaper=escaper -lpegpatterns.urlunescaper=unescaper -lpegpatterns.urlgetcleaner=getcleaner -function url.unescapeget(str) - return lpegmatch(getcleaner,str) -end -local function split(str) - return (type(str)=="string" and lpegmatch(parser,str)) or str -end -local isscheme=schemestr*colon*slash*slash -local function hasscheme(str) - if str then - local scheme=lpegmatch(isscheme,str) - return scheme~="" and scheme or false - else - return false - end -end -local rootletter=R("az","AZ")+S("_-+") -local separator=P("://") -local qualified=P(".")^0*P("/")+rootletter*P(":")+rootletter^1*separator+rootletter^1*P("/") -local rootbased=P("/")+rootletter*P(":") -local barswapper=replacer("|",":") -local backslashswapper=replacer("\\","/") -local equal=P("=") -local amp=P("&") -local key=Cs(((plustospace+escapedchar+1)-equal )^0) -local value=Cs(((plustospace+escapedchar+1)-amp-endofstring)^0) -local splitquery=Cf (Ct("")*P { "sequence", - sequence=V("pair")*(amp*V("pair"))^0, - pair=Cg(key*equal*value), -},rawset) -local userpart=(1-atsign-colon)^1 -local serverpart=(1-colon)^1 -local splitauthority=((Cs(userpart)*colon*Cs(userpart)+Cs(userpart)*Cc(nil))*atsign+Cc(nil)*Cc(nil))*Cs(serverpart)*(colon*(serverpart/tonumber)+Cc(nil)) -local function hashed(str) - if not str or str=="" then - return { - scheme="invalid", - original=str, - } - end - 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 - return { - scheme="file", - authority="", - path=str, - query="", - fragment="", - original=str, - noscheme=true, - filename=str, - } - end - local authority=detailed[2] - local path=detailed[3] - local filename - local username - local password - local host - local port - if authority~="" then - username,password,host,port=lpegmatch(splitauthority,authority) - end - 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, - host=host, - port=port, - } -end -url.split=split -url.hasscheme=hasscheme -url.hashed=hashed -function url.addscheme(str,scheme) - if hasscheme(str) then - return str - elseif not scheme then - return "file:///"..str - else - return scheme..":///"..str - end -end -function url.construct(hash) - local result,r={},0 - local scheme=hash.scheme - local authority=hash.authority - local path=hash.path - local queries=hash.queries - local fragment=hash.fragment - if scheme and scheme~="" then - r=r+1;result[r]=lpegmatch(escaper,scheme) - r=r+1;result[r]="://" - end - if authority and authority~="" then - r=r+1;result[r]=lpegmatch(escaper,authority) - end - if path and path~="" then - r=r+1;result[r]="/" - r=r+1;result[r]=lpegmatch(escaper,path) - end - if queries then - local done=false - for k,v in sortedhash(queries) do - r=r+1;result[r]=done and "&" or "?" - r=r+1;result[r]=lpegmatch(escaper,k) - r=r+1;result[r]="=" - r=r+1;result[r]=lpegmatch(escaper,v) - done=true - end - end - if fragment and fragment~="" then - r=r+1;result[r]="#" - r=r+1;result[r]=lpegmatch(escaper,fragment) - end - return concat(result) -end -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 - return (spec.scheme=="file" and path and lpegmatch(pattern,path)) or filename -end -local function escapestring(str) - return lpegmatch(escaper,str) -end -url.escape=escapestring -function url.query(str) - if type(str)=="string" then - return lpegmatch(splitquery,str) or "" - else - return str - end -end -function url.toquery(data) - local td=type(data) - if td=="string" then - return #str and escape(data) or nil - elseif td=="table" then - if next(data) then - local t={} - for k,v in next,data do - t[#t+1]=format("%s=%s",k,escapestring(v)) - end - return concat(t,"&") - end - else - end -end -local pattern=Cs(noslash^0*(1-noslash*P(-1))^0) -function url.barepath(path) - if not path or path=="" then - return "" - else - return lpegmatch(pattern,path) - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-dir"] = package.loaded["l-dir"] or true - --- original size: 18217, stripped down to: 10792 - -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,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 -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 -local mkdir=lfs.mkdir -local onwindows=os.type=="windows" or find(os.getenv("PATH"),";",1,true) -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 - 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 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 - local nofdirs=0 - for name,mode,size,time in walkdir(usedpath) do - if name~="." and name~=".." then - local full=path..name - if mode==nil then - mode=attributes(full,'mode') - end - if mode=='file' then - if not patt or find(full,patt) then - action(full,size,time) - end - elseif recurse and mode=="directory" then - if dirs then - nofdirs=nofdirs+1 - dirs[nofdirs]=full - else - nofdirs=1 - dirs={ full } - end - end - end - end - if dirs then - for i=1,nofdirs do - glob_pattern_function(dirs[i],patt,recurse,action) - end - end - end -end -local function glob_pattern_table(path,patt,recurse,result) - if not result then - result={} - end - local usedpath - if path=="/" then - usedpath="/." - elseif not find(path,"/$") then - usedpath=path.."/." - path=path.."/" - else - usedpath=path - end - local dirs - local nofdirs=0 - local noffiles=#result - for name,mode in walkdir(usedpath) do - if name~="." and name~=".." then - local full=path..name - if mode==nil then - mode=attributes(full,'mode') - end - if mode=='file' then - if not patt or find(full,patt) then - noffiles=noffiles+1 - result[noffiles]=full - end - elseif recurse and mode=="directory" then - if dirs then - nofdirs=nofdirs+1 - dirs[nofdirs]=full - else - nofdirs=1 - dirs={ full } - end - end - end - end - if dirs then - for i=1,nofdirs do - glob_pattern_table(dirs[i],patt,recurse,result) - 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 - local okay=isdir(path) - if kind=="function" then - return okay and glob_pattern_function(path,patt,recurse,method) or {} - elseif kind=="table" then - return okay and glob_pattern_table(path,patt,recurse,method) or method - else - return okay and glob_pattern_table(path,patt,recurse,{}) or {} - 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 - 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 - end - end - end - return result -end -dir.collectpattern=collectpattern -local separator,pattern -if onwindows then - local slash=S("/\\")/"/" - pattern={ - (Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3), - Cs(((1-S("*?/\\"))^0*slash)^0), - Cs(P(1)^0) - } -else - pattern={ - (C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3), - C(((1-S("*?/"))^0*P("/"))^0), - C(P(1)^0) - } -end -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 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,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 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) - return globpattern(start,result,recurse,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,mode in walkdir(path) do - if find(name,"^%.") then - else - if mode==nil then - mode=attributes(name,'mode') - end - 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 -local function globdirs(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,mode in walkdir(path) do - if find(name,"^%.") then - else - if mode==nil then - mode=attributes(name,'mode') - end - if mode=="directory" then - if not func or func(name) then - noffiles=noffiles+1 - files[noffiles]=path.."/"..name - if recurse then - globdirs(path.."/"..name,recurse,func,files) - end - end - end - end - end - return files -end -dir.globdirs=globdirs -function dir.ls(pattern) - return concat(glob(pattern),"\n") -end -local make_indeed=true -if onwindows then - function dir.mkdirs(...) - local n=select("#",...) - local str - if n==1 then - str=select(1,...) - if isdir(str) then - return str,true - end - else - str="" - for i=1,n do - local s=select(i,...) - if s=="" then - elseif str=="" then - str=s - else - str=str.."/"..s - end - end - end - local pth="" - local drive=false - local 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 - mkdir(pth) - end - end - return pth,(isdir(pth)==true) - end -else - function dir.mkdirs(...) - local n=select("#",...) - local str,pth - if n==1 then - str=select(1,...) - if isdir(str) then - return str,true - end - else - str="" - for i=1,n do - local s=select(i,...) - if s and s~="" then - if str~="" then - str=str.."/"..s - else - str=s - end - 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 - mkdir(pth) - end - end - else - pth="." - for s in gmatch(str,"[^/]+") do - pth=pth.."/"..s - if make_indeed and not isdir(pth) then - mkdir(pth) - end - end - end - return pth,(isdir(pth)==true) - end -end -dir.makedirs=dir.mkdirs -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 - 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 - 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 -end -file.expandname=dir.expandname -local stack={} -function dir.push(newdir) - local curdir=currentdir() - insert(stack,curdir) - if newdir and newdir~="" and chdir(newdir) then - return newdir - else - return curdir - 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 -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-boolean"] = package.loaded["l-boolean"] or true - --- original size: 1850, stripped down to: 1498 - -if not modules then modules={} end modules ['l-boolean']={ - 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,tonumber=type,tonumber -boolean=boolean or {} -local boolean=boolean -function boolean.tonumber(b) - if b then return 1 else return 0 end -end -function toboolean(str,tolerant) - if str==nil then - return false - elseif str==false then - return false - elseif str==true then - return true - elseif str=="true" then - return true - elseif str=="false" then - return false - elseif not tolerant then - return false - elseif str==0 then - return false - elseif (tonumber(str) or 0)>0 then - return true - else - return str=="yes" or str=="on" or str=="t" - end -end -string.toboolean=toboolean -function string.booleanstring(str) - if str=="0" then - return false - elseif str=="1" then - return true - elseif str=="" then - return false - elseif str=="false" then - return false - elseif str=="true" then - return true - elseif (tonumber(str) or 0)>0 then - return true - else - return str=="yes" or str=="on" or str=="t" - end -end -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 (not strict and str=="1") then - return true - elseif str=="false" or str=="no" or str=="off" or str=="f" or (not strict and str=="0") then - return false - end - end - return default -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-unicode"] = package.loaded["l-unicode"] or true - --- original size: 41303, stripped down to: 17277 - -if not modules then modules={} end modules ['l-unicode']={ - version=1.001, - optimize=true, - 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" -} -utf=utf or {} -unicode=nil -if not string.utfcharacters then - local gmatch=string.gmatch - function string.characters(str) - return gmatch(str,".[\128-\191]*") - end -end -utf.characters=string.utfcharacters -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=lpeg.match -local patterns=lpeg.patterns -local tabletopattern=lpeg.utfchartabletopattern -local bytepairs=string.bytepairs -local finder=lpeg.finder -local replacer=lpeg.replacer -local p_utftype=patterns.utftype -local p_utfstricttype=patterns.utfstricttype -local p_utfoffset=patterns.utfoffset -local p_utf8character=patterns.utf8character -local p_utf8char=patterns.utf8char -local p_utf8byte=patterns.utf8byte -local p_utfbom=patterns.utfbom -local p_newline=patterns.newline -local p_whitespace=patterns.whitespace -if not utf.char then - utf.char=string.utfcharacter or (utf8 and utf8.char) - if not utf.char then - local char=string.char - if bit32 then - local rshift=bit32.rshift - function utf.char(n) - if n<0x80 then - return char(n) - elseif n<0x800 then - return char( - 0xC0+rshift(n,6), - 0x80+(n%0x40) - ) - elseif n<0x10000 then - return char( - 0xE0+rshift(n,12), - 0x80+(rshift(n,6)%0x40), - 0x80+(n%0x40) - ) - elseif n<0x200000 then - return char( - 0xF0+rshift(n,18), - 0x80+(rshift(n,12)%0x40), - 0x80+(rshift(n,6)%0x40), - 0x80+(n%0x40) - ) - else - return "" - end - end - else - local floor=math.floor - function utf.char(n) - if n<0x80 then - return char(n) - elseif n<0x800 then - return char( - 0xC0+floor(n/0x40), - 0x80+(n%0x40) - ) - elseif n<0x10000 then - return char( - 0xE0+floor(n/0x1000), - 0x80+(floor(n/0x40)%0x40), - 0x80+(n%0x40) - ) - elseif n<0x200000 then - return char( - 0xF0+floor(n/0x40000), - 0x80+(floor(n/0x1000)%0x40), - 0x80+(floor(n/0x40)%0x40), - 0x80+(n%0x40) - ) - else - return "" - end - end - end - end -end -if not utf.byte then - utf.byte=string.utfvalue or (utf8 and utf8.codepoint) - if not utf.byte then - function utf.byte(c) - return lpegmatch(p_utf8byte,c) - end - end -end -local utfchar,utfbyte=utf.char,utf.byte -function utf.filetype(data) - return data and lpegmatch(p_utftype,data) or "unknown" -end -local toentities=Cs ( - ( - patterns.utf8one+( - patterns.utf8two+patterns.utf8three+patterns.utf8four - )/function(s) local b=utfbyte(s) if b<127 then return s else return format("&#%X;",b) end end - )^0 -) -patterns.toentities=toentities -function utf.toentities(str) - return lpegmatch(toentities,str) -end -local one=P(1) -local two=C(1)*C(1) -local four=C(R(utfchar(0xD8),utfchar(0xFF)))*C(1)*C(1)*C(1) -local pattern=P("\254\255")*Cs(( - four/function(a,b,c,d) - local ab=0xFF*byte(a)+byte(b) - local cd=0xFF*byte(c)+byte(d) - return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000) - end+two/function(a,b) - return utfchar(byte(a)*256+byte(b)) - end+one - )^1 )+P("\255\254")*Cs(( - four/function(b,a,d,c) - local ab=0xFF*byte(a)+byte(b) - local cd=0xFF*byte(c)+byte(d) - return utfchar((ab-0xD800)*0x400+(cd-0xDC00)+0x10000) - end+two/function(b,a) - return utfchar(byte(a)*256+byte(b)) - end+one - )^1 ) -function string.toutf(s) - return lpegmatch(pattern,s) or s -end -local validatedutf=Cs ( - ( - patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�" - )^0 -) -patterns.validatedutf=validatedutf -function utf.is_valid(str) - return type(str)=="string" and lpegmatch(validatedutf,str) or false -end -if not utf.len then - utf.len=string.utflength or (utf8 and utf8.len) - if not utf.len then - local n,f=0,1 - local utfcharcounter=patterns.utfbom^-1*Cmt ( - Cc(1)*patterns.utf8one^1+Cc(2)*patterns.utf8two^1+Cc(3)*patterns.utf8three^1+Cc(4)*patterns.utf8four^1, - function(_,t,d) - n=n+(t-f)/d - f=t - return true - end - )^0 - function utf.len(str) - n,f=0,1 - lpegmatch(utfcharcounter,str or "") - return n - end - end -end -utf.length=utf.len -if not utf.sub then - local utflength=utf.length - local b,e,n,first,last=0,0,0,0,0 - local function slide_zero(s,p) - n=n+1 - if n>=last then - e=p-1 - else - return p - end - end - local function slide_one(s,p) - n=n+1 - if n==first then - b=p - end - if n>=last then - e=p-1 - else - return p - end - end - local function slide_two(s,p) - n=n+1 - if n==first then - b=p - else - return true - end - end - local pattern_zero=Cmt(p_utf8character,slide_zero)^0 - local pattern_one=Cmt(p_utf8character,slide_one )^0 - local pattern_two=Cmt(p_utf8character,slide_two )^0 - local pattern_first=C(p_utf8character) - function utf.sub(str,start,stop) - if not start then - return str - end - if start==0 then - start=1 - end - if not stop then - if start<0 then - local l=utflength(str) - start=l+start - else - start=start-1 - end - b,n,first=0,0,start - lpegmatch(pattern_two,str) - if n>=first then - return sub(str,b) - else - return "" - end - end - if start<0 or stop<0 then - local l=utf.length(str) - if start<0 then - start=l+start - if start<=0 then - start=1 - else - start=start+1 - end - end - if stop<0 then - stop=l+stop - if stop==0 then - stop=1 - else - stop=stop+1 - end - end - end - if start==1 and stop==1 then - return lpegmatch(pattern_first,str) or "" - elseif start>stop then - return "" - elseif start>1 then - b,e,n,first,last=0,0,0,start-1,stop - lpegmatch(pattern_one,str) - if n>=first and e==0 then - e=#str - end - return sub(str,b,e) - else - b,e,n,last=1,0,0,stop - lpegmatch(pattern_zero,str) - if e==0 then - e=#str - end - return sub(str,b,e) - end - end -end -function utf.remapper(mapping,option,action) - local variant=type(mapping) - if variant=="table" then - action=action or mapping - 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)/action+p_utf8character)^0) - end - return lpegmatch(pattern,str) - end - end - elseif option=="pattern" then - return Cs((tabletopattern(mapping)/action+p_utf8character)^0) - else - local pattern=Cs((tabletopattern(mapping)/action+p_utf8character)^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_utf8character/mapping+p_utf8character)^0) - else - local pattern=Cs((p_utf8character/mapping+p_utf8character)^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 -end -function utf.replacer(t) - local r=replacer(t,false,false,true) - return function(str) - return lpegmatch(r,str) - end -end -function utf.subtituter(t) - local f=finder (t) - local r=replacer(t,false,false,true) - return function(str) - local i=lpegmatch(f,str) - if not i then - return str - elseif i>#str then - return str - else - return lpegmatch(r,str) - end - end -end -local utflinesplitter=p_utfbom^-1*lpeg.tsplitat(p_newline) -local utfcharsplitter_ows=p_utfbom^-1*Ct(C(p_utf8character)^0) -local utfcharsplitter_iws=p_utfbom^-1*Ct((p_whitespace^1+C(p_utf8character))^0) -local utfcharsplitter_raw=Ct(C(p_utf8character)^0) -patterns.utflinesplitter=utflinesplitter -function utf.splitlines(str) - return lpegmatch(utflinesplitter,str or "") -end -function utf.split(str,ignorewhitespace) - if ignorewhitespace then - return lpegmatch(utfcharsplitter_iws,str or "") - else - return lpegmatch(utfcharsplitter_ows,str or "") - end -end -function utf.totable(str) - return lpegmatch(utfcharsplitter_raw,str) -end -function utf.magic(f) - local str=f:read(4) or "" - local off=lpegmatch(p_utfoffset,str) - if off<4 then - f:seek('set',off) - end - return lpegmatch(p_utftype,str) -end -local utf16_to_utf8_be,utf16_to_utf8_le -local utf32_to_utf8_be,utf32_to_utf8_le -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 -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 - for i=1,#t do - local s=t[i] - if s~="" then - t[i]=lpegmatch(p_utf16_to_utf8_be,s) - end - end - 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 -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 - end - 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 - 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 - 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(t) - return type(t)=="string" and lpegmatch(utflinesplitter,t) or t -end -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(t,endian) - return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t -end -if bit32 then - local rshift=bit32.rshift - local function little(b) - if b<0x10000 then - return char(b%256,rshift(b,8)) - else - b=b-0x10000 - local b1=rshift(b,10)+0xD800 - local b2=b%1024+0xDC00 - return char(b1%256,rshift(b1,8),b2%256,rshift(b2,8)) - end - end - local function big(b) - if b<0x10000 then - return char(rshift(b,8),b%256) - else - b=b-0x10000 - local b1=rshift(b,10)+0xD800 - local b2=b%1024+0xDC00 - return char(rshift(b1,8),b1%256,rshift(b2,8),b2%256) - end - end - 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 - 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 utf8_to_utf16_le(str,nobom) - else - return utf8_to_utf16_be(str,nobom) - end - end -end -local pattern=Cs ( - (p_utf8byte/function(unicode ) return format("0x%04X",unicode) end)*(p_utf8byte*Carg(1)/function(unicode,separator) return format("%s0x%04X",separator,unicode) end)^0 -) -function utf.tocodes(str,separator) - return lpegmatch(pattern,str,1,separator or " ") -end -function utf.ustring(s) - return format("U+%05X",type(s)=="number" and s or utfbyte(s)) -end -function utf.xstring(s) - return format("0x%05X",type(s)=="number" and s or utfbyte(s)) -end -function utf.toeight(str) - 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-be" then - return utf16_to_utf8_be(str) - elseif utftype=="utf-16-le" then - return utf16_to_utf8_le(str) - else - return str - end -end -do - local p_nany=p_utf8character/"" - local cache={} - function utf.count(str,what) - if type(what)=="string" then - local p=cache[what] - if not p then - p=Cs((P(what)/" "+p_nany)^0) - cache[p]=p - end - return #lpegmatch(p,str) - else - return #lpegmatch(Cs((P(what)/" "+p_nany)^0),str) - end - end -end -if not string.utfvalues then - local find=string.find - local dummy=function() - end - function string.utfvalues(str) - local n=#str - if n==0 then - return dummy - elseif n==1 then - return function() return utfbyte(str) end - else - local p=1 - return function() - local b,e=find(str,".[\128-\191]*",p) - if b then - p=e+1 - return utfbyte(sub(str,b,e)) - end - end - end - end -end -utf.values=string.utfvalues -function utf.chrlen(u) - return - (u<0x80 and 1) or - (u<0xE0 and 2) or - (u<0xF0 and 3) or - (u<0xF8 and 4) or - (u<0xFC and 5) or - (u<0xFE and 6) or 0 -end -if bit32 then - local extract=bit32.extract - local char=string.char - function utf.toutf32string(n) - if n<=0xFF then - return - char(n).."\000\000\000" - elseif n<=0xFFFF then - return - char(extract(n,0,8))..char(extract(n,8,8)).."\000\000" - elseif n<=0xFFFFFF then - return - char(extract(n,0,8))..char(extract(n,8,8))..char(extract(n,16,8)).."\000" - else - return - char(extract(n,0,8))..char(extract(n,8,8))..char(extract(n,16,8))..char(extract(n,24,8)) - end - end -end -local len=utf.len -local rep=rep -function string.utfpadd(s,n) - if n and n~=0 then - local l=len(s) - if n>0 then - local d=n-l - if d>0 then - return rep(c or " ",d)..s - end - else - local d=- n-l - if d>0 then - return s..rep(c or " ",d) - end - end - end - return s -end -do - local utfcharacters=utf.characters or string.utfcharacters - local utfchar=utf.char or string.utfcharacter - lpeg.UP=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 - else - function lpeg.US(str) - local p=P(false) - local f=function(uc) - p=p+P(uc) - end - lpegmatch((p_utf8char/f)^0,str) - return p - end - end - local range=p_utf8byte*p_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) - end - if not utfchar then - utfchar=utf.char - end - if 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 p_utf8byte/f - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["l-math"] = package.loaded["l-math"] or true - --- original size: 2679, stripped down to: 1909 - -if not modules then modules={} end modules ['l-math']={ - 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" -} -if not math.ceiling then - math.ceiling=math.ceil -end -if not math.round then - if xmath then - math.round=xmath.round - else - local floor=math.floor - function math.round(x) - return x<0 and -floor(-x+0.5) or floor(x+0.5) - end - end -end -if not math.div then - local floor=math.floor - function math.div(n,m) return floor(n/m) end -end -if not math.mod then - function math.mod(n,m) return n%m end -end -if not math.sind then - local sin,cos,tan=math.sin,math.cos,math.tan - local pipi=2*math.pi/360 - function math.sind(d) return sin(d*pipi) end - function math.cosd(d) return cos(d*pipi) end - function math.tand(d) return tan(d*pipi) end -end -if not math.odd then - function math.odd (n) return n%2~=0 end - function math.even(n) return n%2==0 end -end -if not math.cosh then - local exp=math.exp - function math.cosh(x) - local xx=exp(x) - return (xx+1/xx)/2 - end - function math.sinh(x) - local xx=exp(x) - return (xx-1/xx)/2 - end - function math.tanh(x) - local xx=exp(x) - return (xx-1/xx)/(xx+1/xx) - end -end -if not math.pow then - function math.pow(x,y) - return x^y - end -end -if not math.atan2 then - math.atan2=math.atan -end -if not math.ldexp then - function math.ldexp(x,e) - return x*2.0^e - end -end -if not math.log10 then - local log=math.log - function math.log10(x) - return log(x,10) - end -end -if not math.type then - function math.type() - return "float" - end -end -if not math.tointeger then - math.mininteger=-0x4FFFFFFFFFFF - math.maxinteger=0x4FFFFFFFFFFF - local floor=math.floor - function math.tointeger(n) - local f=floor(n) - return f==n and f or nil - end -end -if not math.ult then - local floor=math.floor - function math.ult(m,n) - return floor(m)<floor(n) - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-str"] = package.loaded["util-str"] or true - --- original size: 46322, stripped down to: 24128 - -if not modules then modules={} end modules ['util-str']={ - 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" -} -utilities=utilities or {} -utilities.strings=utilities.strings or {} -local strings=utilities.strings -local format,gsub,rep,sub,find,char=string.format,string.gsub,string.rep,string.sub,string.find,string.char -local load,dump=load,string.dump -local tonumber,type,tostring,next,setmetatable=tonumber,type,tostring,next,setmetatable -local unpack,concat=table.unpack,table.concat -local P,V,C,S,R,Ct,Cs,Cp,Carg,Cc=lpeg.P,lpeg.V,lpeg.C,lpeg.S,lpeg.R,lpeg.Ct,lpeg.Cs,lpeg.Cp,lpeg.Carg,lpeg.Cc -local patterns,lpegmatch=lpeg.patterns,lpeg.match -local tsplitat=lpeg.tsplitat -local utfchar,utfbyte,utflen=utf.char,utf.byte,utf.len -local loadstripped=function(str,shortcuts) - if shortcuts then - return load(dump(load(str),true),nil,nil,shortcuts) - else - return load(dump(load(str),true)) - end -end -if not number then number={} end -local stripzero=patterns.stripzero -local stripzeros=patterns.stripzeros -local newline=patterns.newline -local endofstring=patterns.endofstring -local anything=patterns.anything -local whitespace=patterns.whitespace -local space=patterns.space -local spacer=patterns.spacer -local spaceortab=patterns.spaceortab -local digit=patterns.digit -local sign=patterns.sign -local period=patterns.period -local ptf=1/65536 -local bpf=(7200/7227)/65536 -local function points(n) - if n==0 then - return "0pt" - end - n=tonumber(n) - if not n or n==0 then - return "0pt" - end - n=n*ptf - if n%1==0 then - return format("%ipt",n) - else - return lpegmatch(stripzeros,format("%.5fpt",n)) - end -end -local function nupoints(n) - if n==0 then - return "0" - end - n=tonumber(n) - if not n or n==0 then - return "0" - end - n=n*ptf - if n%1==0 then - return format("%i",n) - else - return format("%.5f",n) - end -end -local function basepoints(n) - if n==0 then - return "0bp" - end - n=tonumber(n) - if not n or n==0 then - return "0bp" - end - n=n*bpf - if n%1==0 then - return format("%ibp",n) - else - return lpegmatch(stripzeros,format("%.5fbp",n)) - end -end -local function nubasepoints(n) - if n==0 then - return "0" - end - n=tonumber(n) - if not n or n==0 then - return "0" - end - n=n*bpf - if n%1==0 then - return format("%i",n) - else - return format("%.5f",n) - end -end -number.points=points -number.nupoints=nupoints -number.basepoints=basepoints -number.nubasepoints=nubasepoints -local rubish=spaceortab^0*newline -local anyrubish=spaceortab+newline -local stripped=(spaceortab^1/"")*newline -local leading=rubish^0/"" -local trailing=(anyrubish^1*endofstring)/"" -local redundant=rubish^3/"\n" -local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0) -function strings.collapsecrlf(str) - return lpegmatch(pattern,str) -end -local repeaters={} -function strings.newrepeater(str,offset) - offset=offset or 0 - local s=repeaters[str] - if not s then - s={} - repeaters[str]=s - end - local t=s[offset] - if t then - return t - end - t={} - setmetatable(t,{ __index=function(t,k) - if not k then - return "" - end - local n=k+offset - local s=n>0 and rep(str,n) or "" - t[k]=s - return s - end }) - s[offset]=t - return t -end -local extra,tab,start=0,0,4,0 -local nspaces=strings.newrepeater(" ") -string.nspaces=nspaces -local pattern=Carg(1)/function(t) - extra,tab,start=0,t or 7,1 - end*Cs(( - Cp()*patterns.tab/function(position) - local current=(position-start+1)+extra - local spaces=tab-(current-1)%tab - if spaces>0 then - extra=extra+spaces-1 - return nspaces[spaces] - else - return "" - end - end+newline*Cp()/function(position) - extra,start=0,position - end+anything - )^1) -function strings.tabtospace(str,tab) - return lpegmatch(pattern,str,1,tab or 7) -end -function string.utfpadding(s,n) - if not n or n==0 then - return "" - end - local l=utflen(s) - if n>0 then - return nspaces[n-l] - else - return nspaces[-n-l] - end -end -local optionalspace=spacer^0 -local nospace=optionalspace/"" -local endofline=nospace*newline -local stripend=(whitespace^1*endofstring)/"" -local normalline=(nospace*((1-optionalspace*(newline+endofstring))^1)*nospace) -local stripempty=endofline^1/"" -local normalempty=endofline^1 -local singleempty=endofline*(endofline^0/"") -local doubleempty=endofline*endofline^-1*(endofline^0/"") -local stripstart=stripempty^0 -local intospace=whitespace^1/" " -local noleading=whitespace^1/"" -local notrailing=noleading*endofstring -local p_prune_normal=Cs (stripstart*(stripend+normalline+normalempty )^0 ) -local p_prune_collapse=Cs (stripstart*(stripend+normalline+doubleempty )^0 ) -local p_prune_noempty=Cs (stripstart*(stripend+normalline+singleempty )^0 ) -local p_prune_intospace=Cs (noleading*(notrailing+intospace+1 )^0 ) -local p_retain_normal=Cs ((normalline+normalempty )^0 ) -local p_retain_collapse=Cs ((normalline+doubleempty )^0 ) -local p_retain_noempty=Cs ((normalline+singleempty )^0 ) -local striplinepatterns={ - ["prune"]=p_prune_normal, - ["prune and collapse"]=p_prune_collapse, - ["prune and no empty"]=p_prune_noempty, - ["prune and to space"]=p_prune_intospace, - ["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(striplinepatterns[how],str) or str -end -function strings.collapse(str) - return str and lpegmatch(p_prune_intospace,str) or str -end -strings.striplong=strings.striplines -function strings.nice(str) - str=gsub(str,"[:%-+_]+"," ") - return str -end -local n=0 -local sequenced=table.sequenced -function string.autodouble(s,sep) - if s==nil then - return '""' - end - local t=type(s) - if t=="number" then - return tostring(s) - end - if t=="table" then - return ('"'..sequenced(s,sep or ",")..'"') - end - return ('"'..tostring(s)..'"') -end -function string.autosingle(s,sep) - if s==nil then - return "''" - end - local t=type(s) - if t=="number" then - return tostring(s) - end - if t=="table" then - return ("'"..sequenced(s,sep or ",").."'") - end - return ("'"..tostring(s).."'") -end -local tracedchars={ [0]= - "[null]","[soh]","[stx]","[etx]","[eot]","[enq]","[ack]","[bel]", - "[bs]","[ht]","[lf]","[vt]","[ff]","[cr]","[so]","[si]", - "[dle]","[dc1]","[dc2]","[dc3]","[dc4]","[nak]","[syn]","[etb]", - "[can]","[em]","[sub]","[esc]","[fs]","[gs]","[rs]","[us]", - "[space]", -} -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)..")") - else - local c=utfbyte(b) - return tracedchars[c] or (b.." (U+"..(c and format("%05X",c) or "?????")..")") - end -end -function number.signed(i) - if i>0 then - return "+",i - else - return "-",-i - end -end -local two=digit*digit -local three=two*digit -local prefix=(Carg(1)*three)^1 -local splitter=Cs ( - (((1-(three^1*period))^1+C(three))*prefix+C((1-period)^1))*(anything/""*Carg(2))*C(2) -) -local splitter3=Cs ( - three*prefix*endofstring+two*prefix*endofstring+digit*prefix*endofstring+three+two+digit -) -patterns.formattednumber=splitter -function number.formatted(n,sep1,sep2) - if sep1==false then - if type(n)=="number" then - n=tostring(n) - end - return lpegmatch(splitter3,n,1,sep2 or ".") - else - if type(n)=="number" then - n=format("%0.2f",n) - end - if sep1==true then - return lpegmatch(splitter,n,1,".",",") - elseif sep1=="." then - return lpegmatch(splitter,n,1,sep1,sep2 or ",") - elseif sep1=="," then - return lpegmatch(splitter,n,1,sep1,sep2 or ".") - else - return lpegmatch(splitter,n,1,sep1 or ",",sep2 or ".") - end - end -end -local p=Cs( - P("-")^0*(P("0")^1/"")^0*(1-period)^0*(period*P("0")^1*endofstring/""+period^0)*P(1-P("0")^1*endofstring)^0 - ) -function number.compactfloat(n,fmt) - if n==0 then - return "0" - elseif n==1 then - return "1" - end - n=lpegmatch(p,format(fmt or "%0.3f",n)) - if n=="." or n=="" or n=="-" then - return "0" - end - return n -end -local zero=P("0")^1/"" -local plus=P("+")/"" -local minus=P("-") -local separator=period -local trailing=zero^1*#S("eE") -local exponent=(S("eE")*(plus+Cs((minus*zero^0*endofstring)/"")+minus)*zero^0*(endofstring*Cc("0")+anything^1)) -local pattern_a=Cs(minus^0*digit^1*(separator/""*trailing+separator*(trailing+digit)^0)*exponent) -local pattern_b=Cs((exponent+anything)^0) -function number.sparseexponent(f,n) - if not n then - n=f - f="%e" - end - local tn=type(n) - if tn=="string" then - local m=tonumber(n) - if m then - return lpegmatch((f=="%e" or f=="%E") and pattern_a or pattern_b,format(f,m)) - end - elseif tn=="number" then - return lpegmatch((f=="%e" or f=="%E") and pattern_a or pattern_b,format(f,n)) - end - return tostring(n) -end -local hf={} -local hs={} -setmetatable(hf,{ __index=function(t,k) - local v="%."..k.."f" - t[k]=v - return v -end } ) -setmetatable(hs,{ __index=function(t,k) - local v="%"..k.."s" - t[k]=v - return v -end } ) -function number.formattedfloat(n,b,a) - local s=format(hf[a],n) - local l=(b or 0)+(a or 0)+1 - if #s<l then - return format(hs[l],s) - else - return s - end -end -local template=[[ -%s -%s -return function(%s) return %s end -]] -local pattern=Cs(Cc('"')*( - (1-S('"\\\n\r'))^1+P('"')/'\\"'+P('\\')/'\\\\'+P('\n')/'\\n'+P('\r')/'\\r' -)^0*Cc('"')) -patterns.escapedquotes=pattern -function string.escapedquotes(s) - return lpegmatch(pattern,s) -end -local pattern=(1-P("\\"))^1;pattern=Cs ( - pattern*((P("\\")/""*(digit^-3/function(s) return char(tonumber(s)) end))+pattern )^1 -) -patterns.unescapedquotes=pattern -function string.unescapedquotes(s) - return lpegmatch(pattern,s) or s -end -string.texnewlines=lpeg.replacer(patterns.newline,"\r",true) -local preamble="" -local environment={ - global=global or _G, - lpeg=lpeg, - type=type, - tostring=tostring, - tonumber=tonumber, - format=string.format, - concat=table.concat, - signed=number.signed, - points=number.points, - nupoints=number.nupoints, - basepoints=number.basepoints, - nubasepoints=number.nubasepoints, - utfchar=utf.char, - utfbyte=utf.byte, - lpegmatch=lpeg.match, - nspaces=string.nspaces, - utfpadding=string.utfpadding, - tracedchar=string.tracedchar, - autosingle=string.autosingle, - autodouble=string.autodouble, - sequenced=table.sequenced, - formattednumber=number.formatted, - sparseexponent=number.sparseexponent, - formattedfloat=number.formattedfloat, - stripzero=patterns.stripzero, - stripzeros=patterns.stripzeros, - escapedquotes=string.escapedquotes, - FORMAT=string.f6, -} -local arguments={ "a1" } -setmetatable(arguments,{ __index=function(t,k) - local v=t[k-1]..",a"..k - t[k]=v - return v - end -}) -local prefix_any=C((sign+space+period+digit)^0) -local prefix_sub=(C((sign+digit)^0)+Cc(0))*period*(C((sign+digit)^0)+Cc(0)) -local prefix_tab=P("{")*C((1-P("}"))^0)*P("}")+C((1-R("az","AZ","09","%%"))^0) -local format_s=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%ss',a%s)",f,n) - else - return format("(a%s or '')",n) - end -end -local format_S=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%ss',tostring(a%s))",f,n) - else - return format("tostring(a%s)",n) - end -end -local format_right=function(f) - n=n+1 - f=tonumber(f) - if not f or f==0 then - return format("(a%s or '')",n) - elseif f>0 then - return format("utfpadding(a%s,%i)..a%s",n,f,n) - else - return format("a%s..utfpadding(a%s,%i)",n,n,f) - end -end -local format_left=function(f) - n=n+1 - f=tonumber(f) - if not f or f==0 then - return format("(a%s or '')",n) - end - if f<0 then - return format("utfpadding(a%s,%i)..a%s",n,-f,n) - else - return format("a%s..utfpadding(a%s,%i)",n,n,-f) - end -end -local format_q=JITSUPPORTED and function() - n=n+1 - return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n) -end or function() - n=n+1 - return format("(a%s ~= nil and format('%%q',a%s) or '')",n,n) -end -local format_Q=function() - n=n+1 - return format("escapedquotes(tostring(a%s))",n) -end -local format_i=function(f) - n=n+1 - if f and f~="" then - return format("format('%%%si',a%s)",f,n) - else - return format("format('%%i',a%s)",n) - end -end -local format_d=format_i -local format_I=function(f) - n=n+1 - return format("format('%%s%%%si',signed(a%s))",f,n) -end -local format_f=function(f) - n=n+1 - return format("format('%%%sf',a%s)",f,n) -end -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 format((a%s %% 1 == 0) and '%%i' or '%%.9f',a%s))",n,n,n,n) - else - return format("format((a%s %% 1 == 0) and '%%i' or '%%%sf',a%s)",n,f,n) - end -end -local format_k=function(b,a) - n=n+1 - return format("formattedfloat(a%s,%s,%s)",n,b or 0,a or 0) -end -local format_g=function(f) - n=n+1 - return format("format('%%%sg',a%s)",f,n) -end -local format_G=function(f) - n=n+1 - return format("format('%%%sG',a%s)",f,n) -end -local format_e=function(f) - n=n+1 - return format("format('%%%se',a%s)",f,n) -end -local format_E=function(f) - n=n+1 - return format("format('%%%sE',a%s)",f,n) -end -local format_j=function(f) - n=n+1 - return format("sparseexponent('%%%se',a%s)",f,n) -end -local format_J=function(f) - n=n+1 - return format("sparseexponent('%%%sE',a%s)",f,n) -end -local format_x=function(f) - n=n+1 - return format("format('%%%sx',a%s)",f,n) -end -local format_X=function(f) - n=n+1 - return format("format('%%%sX',a%s)",f,n) -end -local format_o=function(f) - n=n+1 - return format("format('%%%so',a%s)",f,n) -end -local format_c=function() - n=n+1 - return format("utfchar(a%s)",n) -end -local format_C=function() - n=n+1 - return format("tracedchar(a%s)",n) -end -local format_r=function(f) - n=n+1 - return format("format('%%%s.0f',a%s)",f,n) -end -local format_h=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('0x%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_H=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('0x%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_u=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('u+%%%sx',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_U=function(f) - n=n+1 - if f=="-" then - f=sub(f,2) - return format("format('%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - else - return format("format('U+%%%sX',type(a%s) == 'number' and a%s or utfbyte(a%s))",f=="" and "05" or f,n,n,n) - end -end -local format_p=function() - n=n+1 - return format("points(a%s)",n) -end -local format_P=function() - n=n+1 - return format("nupoints(a%s)",n) -end -local format_b=function() - n=n+1 - return format("basepoints(a%s)",n) -end -local format_B=function() - n=n+1 - return format("nubasepoints(a%s)",n) -end -local format_t=function(f) - n=n+1 - if f and f~="" then - return format("concat(a%s,%q)",n,f) - else - return format("concat(a%s)",n) - end -end -local format_T=function(f) - n=n+1 - if f and f~="" then - return format("sequenced(a%s,%q)",n,f) - else - return format("sequenced(a%s)",n) - end -end -local format_l=function() - n=n+1 - return format("(a%s and 'true' or 'false')",n) -end -local format_L=function() - n=n+1 - return format("(a%s and 'TRUE' or 'FALSE')",n) -end -local format_n=function() - n=n+1 - return format("((a%s %% 1 == 0) and format('%%i',a%s) or tostring(a%s))",n,n,n) -end -local format_N if environment.FORMAT then - format_N=function(f) - n=n+1 - if not f or f=="" then - return format("FORMAT(a%s,'%%.9f')",n) - elseif f==".6" or f=="0.6" then - return format("FORMAT(a%s)",n) - else - return format("FORMAT(a%s,'%%%sf')",n,f) - end - end -else - format_N=function(f) - n=n+1 - if not f or f=="" then - f=".9" - end - return format("(((a%s %% 1 == 0) and format('%%i',a%s)) or lpegmatch(stripzero,format('%%%sf',a%s)))",n,n,f,n) - end -end -local format_a=function(f) - n=n+1 - if f and f~="" then - return format("autosingle(a%s,%q)",n,f) - else - return format("autosingle(a%s)",n) - end -end -local format_A=function(f) - n=n+1 - if f and f~="" then - return format("autodouble(a%s,%q)",n,f) - else - return format("autodouble(a%s)",n) - end -end -local format_w=function(f) - n=n+1 - f=tonumber(f) - if f then - return format("nspaces[%s+a%s]",f,n) - else - return format("nspaces[a%s]",n) - end -end -local format_W=function(f) - return format("nspaces[%s]",tonumber(f) or 0) -end -local format_m=function(f) - n=n+1 - if not f or f=="" then - f="," - end - if f=="0" then - return format([[formattednumber(a%s,false)]],n) - else - return format([[formattednumber(a%s,%q,".")]],n,f) - end -end -local format_M=function(f) - n=n+1 - if not f or f=="" then - f="." - end - if f=="0" then - return format([[formattednumber(a%s,false)]],n) - else - return format([[formattednumber(a%s,%q,",")]],n,f) - end -end -local format_z=function(f) - n=n+(tonumber(f) or 1) - return "''" -end -local format_rest=function(s) - return format("%q",s) -end -local format_extension=function(extensions,f,name) - local extension=extensions[name] or "tostring(%s)" - local f=tonumber(f) or 1 - local w=find(extension,"%.%.%.") - if f==0 then - if w then - extension=gsub(extension,"%.%.%.","") - end - return extension - elseif f==1 then - if w then - extension=gsub(extension,"%.%.%.","%%s") - end - n=n+1 - local a="a"..n - return format(extension,a,a) - elseif f<0 then - if w then - extension=gsub(extension,"%.%.%.","") - return extension - else - local a="a"..(n+f+1) - return format(extension,a,a) - end - else - if w then - extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s") - end - local t={} - for i=1,f do - n=n+1 - t[i]="a"..n - end - return format(extension,unpack(t)) - end -end -local builder=Cs { "start", - start=( - ( - P("%")/""*( - V("!") -+V("s")+V("q")+V("i")+V("d")+V("f")+V("F")+V("g")+V("G")+V("e")+V("E")+V("x")+V("X")+V("o") -+V("c")+V("C")+V("S") -+V("Q") -+V("n") -+V("N") -+V("k") -+V("r")+V("h")+V("H")+V("u")+V("U")+V("p")+V("P")+V("b")+V("B")+V("t")+V("T")+V("l")+V("L")+V("I")+V("w") -+V("W") -+V("a") -+V("A") -+V("j")+V("J") -+V("m")+V("M") -+V("z") -+V(">") -+V("<") - )+V("*") - )*(endofstring+Carg(1)) - )^0, - ["s"]=(prefix_any*P("s"))/format_s, - ["q"]=(prefix_any*P("q"))/format_q, - ["i"]=(prefix_any*P("i"))/format_i, - ["d"]=(prefix_any*P("d"))/format_d, - ["f"]=(prefix_any*P("f"))/format_f, - ["F"]=(prefix_any*P("F"))/format_F, - ["g"]=(prefix_any*P("g"))/format_g, - ["G"]=(prefix_any*P("G"))/format_G, - ["e"]=(prefix_any*P("e"))/format_e, - ["E"]=(prefix_any*P("E"))/format_E, - ["x"]=(prefix_any*P("x"))/format_x, - ["X"]=(prefix_any*P("X"))/format_X, - ["o"]=(prefix_any*P("o"))/format_o, - ["S"]=(prefix_any*P("S"))/format_S, - ["Q"]=(prefix_any*P("Q"))/format_Q, - ["n"]=(prefix_any*P("n"))/format_n, - ["N"]=(prefix_any*P("N"))/format_N, - ["k"]=(prefix_sub*P("k"))/format_k, - ["c"]=(prefix_any*P("c"))/format_c, - ["C"]=(prefix_any*P("C"))/format_C, - ["r"]=(prefix_any*P("r"))/format_r, - ["h"]=(prefix_any*P("h"))/format_h, - ["H"]=(prefix_any*P("H"))/format_H, - ["u"]=(prefix_any*P("u"))/format_u, - ["U"]=(prefix_any*P("U"))/format_U, - ["p"]=(prefix_any*P("p"))/format_p, - ["P"]=(prefix_any*P("P"))/format_P, - ["b"]=(prefix_any*P("b"))/format_b, - ["B"]=(prefix_any*P("B"))/format_B, - ["t"]=(prefix_tab*P("t"))/format_t, - ["T"]=(prefix_tab*P("T"))/format_T, - ["l"]=(prefix_any*P("l"))/format_l, - ["L"]=(prefix_any*P("L"))/format_L, - ["I"]=(prefix_any*P("I"))/format_I, - ["w"]=(prefix_any*P("w"))/format_w, - ["W"]=(prefix_any*P("W"))/format_W, - ["j"]=(prefix_any*P("j"))/format_j, - ["J"]=(prefix_any*P("J"))/format_J, - ["m"]=(prefix_any*P("m"))/format_m, - ["M"]=(prefix_any*P("M"))/format_M, - ["z"]=(prefix_any*P("z"))/format_z, - ["a"]=(prefix_any*P("a"))/format_a, - ["A"]=(prefix_any*P("A"))/format_A, - ["<"]=(prefix_any*P("<"))/format_left, - [">"]=(prefix_any*P(">"))/format_right, - ["*"]=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 xx=setmetatable({},{ __index=function(t,k) local v=format("%02x",k) t[k]=v return v end }) -local XX=setmetatable({},{ __index=function(t,k) local v=format("%02X",k) t[k]=v return v end }) -local preset={ - ["%02x"]=function(n) return xx[n] end, - ["%02X"]=function(n) return XX[n] end, -} -local direct=P("%")*(sign+space+period+digit)^0*S("sqidfgGeExXo")*endofstring/[[local format = string.format return function(str) return format("%0",str) end]] -local function make(t,str) - local f=preset[str] - if f then - return f - end - local p=lpegmatch(direct,str) - if p then - f=loadstripped(p)() - else - n=0 - p=lpegmatch(builder,str,1,t._connector_,t._extensions_) - if n>0 then - p=format(template,preamble,t._preamble_,arguments[n],p) - f=loadstripped(p,t._environment_)() - else - f=function() return str end - end - end - t[str]=f - return f -end -local function use(t,fmt,...) - return t[fmt](...) -end -strings.formatters={} -function strings.formatters.new(noconcat) - local e={} - for k,v in next,environment do - e[k]=v - end - local t={ - _type_="formatter", - _connector_=noconcat and "," or "..", - _extensions_={}, - _preamble_="", - _environment_=e, - } - setmetatable(t,{ __index=make,__call=use }) - return t -end -local formatters=strings.formatters.new() -string.formatters=formatters -string.formatter=function(str,...) return formatters[str](...) end -local function add(t,name,template,preamble) - if type(t)=="table" and t._type_=="formatter" then - t._extensions_[name]=template or "%s" - if type(preamble)=="string" then - t._preamble_=preamble.."\n"..t._preamble_ - elseif type(preamble)=="table" then - for k,v in next,preamble do - t._environment_[k]=v - end - end - end -end -strings.formatters.add=add -patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"""+anything)^0) -patterns.texescape=Cs((C(S("#$%\\{}"))/"\\%1"+anything)^0) -patterns.luaescape=Cs(((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0) -patterns.luaquoted=Cs(Cc('"')*((1-S('"\n'))^1+P('"')/'\\"'+P('\n')/'\\n"')^0*Cc('"')) -add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=patterns.xmlescape }) -add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=patterns.texescape }) -add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=patterns.luaescape }) -local dquote=patterns.dquote -local equote=patterns.escaped+dquote/'\\"'+1 -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 -local pattern=Cs((newline/(os.newline or "\r")+1)^0) -function string.replacenewlines(str) - return lpegmatch(pattern,str) -end -function strings.newcollector() - local result,r={},0 - return - function(fmt,str,...) - r=r+1 - result[r]=str==nil and fmt or formatters[fmt](str,...) - end, - function(connector) - if result then - local str=concat(result,connector) - result,r={},0 - return str - end - end -end -local f_16_16=formatters["%0.5N"] -function number.to16dot16(n) - return f_16_16(n/65536.0) -end -if not string.explode then - local p_utf=patterns.utf8character - local p_check=C(p_utf)*(P("+")*Cc(true))^0 - local p_split=Ct(C(p_utf)^0) - local p_space=Ct((C(1-P(" ")^1)+P(" ")^1)^0) - function string.explode(str,symbol) - if symbol=="" then - return lpegmatch(p_split,str) - elseif symbol then - local a,b=lpegmatch(p_check,symbol) - if b then - return lpegmatch(tsplitat(P(a)^1),str) - else - return lpegmatch(tsplitat(a),str) - end - else - return lpegmatch(p_space,str) - end - end -end -do - local p_whitespace=patterns.whitespace^1 - local cache=setmetatable({},{ __index=function(t,k) - local p=tsplitat(p_whitespace*P(k)*p_whitespace) - local v=function(s) - return lpegmatch(p,s) - end - t[k]=v - return v - end }) - function string.wordsplitter(s) - return cache[s] - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-tab"] = package.loaded["util-tab"] or true - --- original size: 34148, stripped down to: 18419 - -if not modules then modules={} end modules ['util-tab']={ - 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" -} -utilities=utilities or {} -utilities.tables=utilities.tables or {} -local tables=utilities.tables -local format,gmatch,gsub,sub=string.format,string.gmatch,string.gsub,string.sub -local concat,insert,remove,sort=table.concat,table.insert,table.remove,table.sort -local setmetatable,getmetatable,tonumber,tostring,rawget=setmetatable,getmetatable,tonumber,tostring,rawget -local type,next,rawset,tonumber,tostring,load,select=type,next,rawset,tonumber,tostring,load,select -local lpegmatch,P,Cs,Cc=lpeg.match,lpeg.P,lpeg.Cs,lpeg.Cc -local sortedkeys,sortedpairs=table.sortedkeys,table.sortedpairs -local formatters=string.formatters -local utftoeight=utf.toeight -local splitter=lpeg.tsplitat(".") -function utilities.tables.definetable(target,nofirst,nolast) - local composed=nil - local t={} - local snippets=lpegmatch(splitter,target) - for i=1,#snippets-(nolast and 1 or 0) do - local name=snippets[i] - if composed then - composed=composed.."."..name - t[#t+1]=formatters["if not %s then %s = { } end"](composed,composed) - else - composed=name - if not nofirst then - t[#t+1]=formatters["%s = %s or { }"](composed,composed) - end - end - end - if composed then - if nolast then - composed=composed.."."..snippets[#snippets] - end - return concat(t,"\n"),composed - else - return "",target - end -end -function tables.definedtable(...) - local t=_G - for i=1,select("#",...) do - local li=select(i,...) - local tl=t[li] - if not tl then - tl={} - t[li]=tl - end - t=tl - end - return t -end -function tables.accesstable(target,root) - local t=root or _G - for name in gmatch(target,"([^%.]+)") do - t=t[name] - if not t then - return - end - end - return t -end -function tables.migratetable(target,v,root) - local t=root or _G - local names=lpegmatch(splitter,target) - for i=1,#names-1 do - local name=names[i] - t[name]=t[name] or {} - t=t[name] - if not t then - return - end - end - t[names[#names]]=v -end -function tables.removevalue(t,value) - if value then - for i=1,#t do - if t[i]==value then - remove(t,i) - end - 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 - remove(t,i) - end - end - for i=1,#t do - if t[i]==value then - insert(t,i,extra) - return - end - end - insert(t,1,extra) -end -function tables.insertaftervalue(t,value,extra) - for i=1,#t do - if t[i]==extra then - remove(t,i) - end - end - for i=1,#t do - if t[i]==value then - insert(t,i+1,extra) - return - end - end - insert(t,#t+1,extra) -end -local escape=Cs(Cc('"')*((P('"')/'""'+P(1))^0)*Cc('"')) -function table.tocsv(t,specification) - if t and #t>0 then - local result={} - local r={} - specification=specification or {} - local fields=specification.fields - if type(fields)~="string" then - fields=sortedkeys(t[1]) - end - local separator=specification.separator or "," - local noffields=#fields - if specification.preamble==true then - for f=1,noffields do - r[f]=lpegmatch(escape,tostring(fields[f])) - end - result[1]=concat(r,separator) - end - for i=1,#t do - local ti=t[i] - for f=1,noffields do - local field=ti[fields[f]] - if type(field)=="string" then - r[f]=lpegmatch(escape,field) - else - r[f]=tostring(field) - end - end - result[i+1]=concat(r,separator) - end - return concat(result,"\n") - else - return "" - end -end -local nspaces=utilities.strings.newrepeater(" ") -local function toxml(t,d,result,step) - local r=#result - for k,v in sortedpairs(t) do - local s=nspaces[d] - local tk=type(k) - local tv=type(v) - if tv=="table" then - if tk=="number" then - r=r+1 result[r]=formatters["%s<entry n='%s'>"](s,k) - toxml(v,d+step,result,step) - r=r+1 result[r]=formatters["%s</entry>"](s,k) - else - r=r+1 result[r]=formatters["%s<%s>"](s,k) - toxml(v,d+step,result,step) - r=r+1 result[r]=formatters["%s</%s>"](s,k) - end - elseif tv=="string" then - if tk=="number" then - r=r+1 result[r]=formatters["%s<entry n='%s'>%!xml!</entry>"](s,k,v,k) - else - r=r+1 result[r]=formatters["%s<%s>%!xml!</%s>"](s,k,v,k) - end - elseif tk=="number" then - r=r+1 result[r]=formatters["%s<entry n='%s'>%S</entry>"](s,k,v,k) - else - r=r+1 result[r]=formatters["%s<%s>%S</%s>"](s,k,v,k) - end - end -end -function table.toxml(t,specification) - specification=specification or {} - local name=specification.name - local noroot=name==false - local result=(specification.nobanner or noroot) and {} or { "<?xml version='1.0' standalone='yes' ?>" } - local indent=specification.indent or 0 - local spaces=specification.spaces or 1 - if noroot then - toxml(t,indent,result,spaces) - else - toxml({ [name or "data"]=t },indent,result,spaces) - end - return concat(result,"\n") -end -function tables.encapsulate(core,capsule,protect) - if type(capsule)~="table" then - protect=true - capsule={} - end - for key,value in next,core do - if capsule[key] then - print(formatters["\ninvalid %s %a in %a"]("inheritance",key,core)) - os.exit() - else - capsule[key]=value - end - end - if protect then - for key,value in next,core do - core[key]=nil - end - setmetatable(core,{ - __index=capsule, - __newindex=function(t,key,value) - if capsule[key] then - print(formatters["\ninvalid %s %a' in %a"]("overload",key,core)) - os.exit() - else - rawset(t,key,value) - end - end - } ) - end -end -if JITSUPPORTED then - local f_hashed_string=formatters["[%Q]=%Q,"] - local f_hashed_number=formatters["[%Q]=%s,"] - local f_hashed_boolean=formatters["[%Q]=%l,"] - local f_hashed_table=formatters["[%Q]="] - local f_indexed_string=formatters["[%s]=%Q,"] - local f_indexed_number=formatters["[%s]=%s,"] - local f_indexed_boolean=formatters["[%s]=%l,"] - local f_indexed_table=formatters["[%s]="] - local f_ordered_string=formatters["%Q,"] - local f_ordered_number=formatters["%s,"] - local f_ordered_boolean=formatters["%l,"] - function table.fastserialize(t,prefix) - local r={ type(prefix)=="string" and prefix or "return" } - local m=1 - local function fastserialize(t,outer) - local n=#t - m=m+1 - r[m]="{" - if n>0 then - local v=t[0] - if v then - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_indexed_string(0,v) - elseif tv=="number" then - m=m+1 r[m]=f_indexed_number(0,v) - elseif tv=="table" then - m=m+1 r[m]=f_indexed_table(0) - fastserialize(v) - m=m+1 r[m]=f_indexed_table(0) - elseif tv=="boolean" then - m=m+1 r[m]=f_indexed_boolean(0,v) - end - end - for i=1,n do - local v=t[i] - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_ordered_string(v) - elseif tv=="number" then - m=m+1 r[m]=f_ordered_number(v) - elseif tv=="table" then - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_ordered_boolean(v) - end - end - end - for k,v in next,t do - local tk=type(k) - if tk=="number" then - if k>n or k<0 then - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_indexed_string(k,v) - elseif tv=="number" then - m=m+1 r[m]=f_indexed_number(k,v) - elseif tv=="table" then - m=m+1 r[m]=f_indexed_table(k) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_indexed_boolean(k,v) - end - end - else - local tv=type(v) - if tv=="string" then - m=m+1 r[m]=f_hashed_string(k,v) - elseif tv=="number" then - m=m+1 r[m]=f_hashed_number(k,v) - elseif tv=="table" then - m=m+1 r[m]=f_hashed_table(k) - fastserialize(v) - elseif tv=="boolean" then - m=m+1 r[m]=f_hashed_boolean(k,v) - end - end - end - m=m+1 - if outer then - r[m]="}" - else - r[m]="}," - end - return r - end - return concat(fastserialize(t,true)) - end -else - function table.fastserialize(t,prefix) - local r={ type(prefix)=="string" and prefix or "return" } - local m=1 - local function fastserialize(t,outer) - local n=#t - m=m+1 - r[m]="{" - if n>0 then - local v=t[0] - if v then - m=m+1 - r[m]="[0]=" - if type(v)=="table" then - fastserialize(v) - else - r[m]=format("%q,",v) - end - end - for i=1,n do - local v=t[i] - m=m+1 - if type(v)=="table" then - r[m]=format("[%i]=",i) - fastserialize(v) - else - r[m]=format("[%i]=%q,",i,v) - end - end - end - for k,v in next,t do - local tk=type(k) - if tk=="number" then - if k>n or k<0 then - m=m+1 - if type(v)=="table" then - r[m]=format("[%i]=",k) - fastserialize(v) - else - r[m]=format("[%i]=%q,",k,v) - end - end - else - m=m+1 - if type(v)=="table" then - r[m]=format("[%q]=",k) - fastserialize(v) - else - r[m]=format("[%q]=%q,",k,v) - end - end - end - m=m+1 - if outer then - r[m]="}" - else - r[m]="}," - end - return r - end - return concat(fastserialize(t,true)) - end -end -function table.deserialize(str) - if not str or str=="" then - return - end - local code=load(str) - if not code then - return - end - code=code() - if not code then - return - end - return code -end -function table.load(filename,loader) - if filename then - local t=(loader or io.loaddata)(filename) - if t and t~="" then - local t=utftoeight(t) - t=load(t) - if type(t)=="function" then - t=t() - if type(t)=="table" then - return t - end - end - end - end -end -function table.save(filename,t,n,...) - io.savedata(filename,table.serialize(t,n==nil and true or n,...)) -end -local f_key_value=formatters["%s=%q"] -local f_add_table=formatters[" {%t},\n"] -local f_return_table=formatters["return {\n%t}"] -local function slowdrop(t) - local r={} - local l={} - for i=1,#t do - local ti=t[i] - local j=0 - for k,v in next,ti do - j=j+1 - l[j]=f_key_value(k,v) - end - r[i]=f_add_table(l) - end - return f_return_table(r) -end -local function fastdrop(t) - local r={ "return {\n" } - local m=1 - for i=1,#t do - local ti=t[i] - m=m+1 r[m]=" {" - for k,v in next,ti do - m=m+1 r[m]=f_key_value(k,v) - end - m=m+1 r[m]="},\n" - end - m=m+1 - r[m]="}" - return concat(r) -end -function table.drop(t,slow) - if #t==0 then - return "return { }" - elseif slow==true then - return slowdrop(t) - else - return fastdrop(t) - end -end -local selfmapper={ __index=function(t,k) t[k]=k return k end } -function table.twowaymapper(t) - if not t then - t={} - else - local zero=rawget(t,0) - for i=zero and 0 or 1,#t do - local ti=t[i] - if ti then - local i=tostring(i) - t[i]=ti - t[ti]=i - end - end - end - setmetatable(t,selfmapper) - return t -end -local f_start_key_idx=formatters["%w{"] -local f_start_key_num=JITSUPPORTED and formatters["%w[%s]={"] or formatters["%w[%q]={"] -local f_start_key_str=formatters["%w[%q]={"] -local f_start_key_boo=formatters["%w[%l]={"] -local f_start_key_nop=formatters["%w{"] -local f_stop=formatters["%w},"] -local f_key_num_value_num=JITSUPPORTED and formatters["%w[%s]=%s,"] or formatters["%w[%s]=%q,"] -local f_key_str_value_num=JITSUPPORTED and formatters["%w[%Q]=%s,"] or formatters["%w[%Q]=%q,"] -local f_key_boo_value_num=JITSUPPORTED and formatters["%w[%l]=%s,"] or formatters["%w[%l]=%q,"] -local f_key_num_value_str=JITSUPPORTED and formatters["%w[%s]=%Q,"] or formatters["%w[%q]=%Q,"] -local f_key_str_value_str=formatters["%w[%Q]=%Q,"] -local f_key_boo_value_str=formatters["%w[%l]=%Q,"] -local f_key_num_value_boo=JITSUPPORTED and formatters["%w[%s]=%l,"] or formatters["%w[%q]=%l,"] -local f_key_str_value_boo=formatters["%w[%Q]=%l,"] -local f_key_boo_value_boo=formatters["%w[%l]=%l,"] -local f_key_num_value_not=JITSUPPORTED and formatters["%w[%s]={},"] or formatters["%w[%q]={},"] -local f_key_str_value_not=formatters["%w[%Q]={},"] -local f_key_boo_value_not=formatters["%w[%l]={},"] -local f_key_num_value_seq=JITSUPPORTED and formatters["%w[%s]={ %, t },"] or formatters["%w[%q]={ %, t },"] -local f_key_str_value_seq=formatters["%w[%Q]={ %, t },"] -local f_key_boo_value_seq=formatters["%w[%l]={ %, t },"] -local f_val_num=JITSUPPORTED and formatters["%w%s,"] or formatters["%w%q,"] -local f_val_str=formatters["%w%Q,"] -local f_val_boo=formatters["%w%l,"] -local f_val_not=formatters["%w{},"] -local f_val_seq=formatters["%w{ %, t },"] -local f_fin_seq=formatters[" %, t }"] -local f_table_return=formatters["return {"] -local f_table_name=formatters["%s={"] -local f_table_direct=formatters["{"] -local f_table_entry=formatters["[%Q]={"] -local f_table_finish=formatters["}"] -local spaces=utilities.strings.newrepeater(" ") -local original_serialize=table.serialize -local is_simple_table=table.is_simple_table -local function serialize(root,name,specification) - if type(specification)=="table" then - return original_serialize(root,name,specification) - end - local t - local n=1 - local unknown=false - local function do_serialize(root,name,depth,level,indexed) - if level>0 then - n=n+1 - if indexed then - t[n]=f_start_key_idx(depth) - else - local tn=type(name) - if tn=="number" then - t[n]=f_start_key_num(depth,name) - elseif tn=="string" then - t[n]=f_start_key_str(depth,name) - elseif tn=="boolean" then - t[n]=f_start_key_boo(depth,name) - else - t[n]=f_start_key_nop(depth) - end - end - depth=depth+1 - end - if root and next(root)~=nil then - local first=nil - local last=#root - if last>0 then - for k=1,last do - if rawget(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 tv=type(v) - local tk=type(k) - if first and tk=="number" and k<=last and k>=first then - if tv=="number" then - n=n+1 t[n]=f_val_num(depth,v) - elseif tv=="string" then - n=n+1 t[n]=f_val_str(depth,v) - elseif tv=="table" then - if next(v)==nil then - n=n+1 t[n]=f_val_not(depth) - else - local st=is_simple_table(v) - if st then - n=n+1 t[n]=f_val_seq(depth,st) - else - do_serialize(v,k,depth,level+1,true) - end - end - elseif tv=="boolean" then - n=n+1 t[n]=f_val_boo(depth,v) - elseif unknown then - n=n+1 t[n]=f_val_str(depth,tostring(v)) - end - elseif tv=="number" then - if tk=="number" then - n=n+1 t[n]=f_key_num_value_num(depth,k,v) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_num(depth,k,v) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_num(depth,k,v) - elseif unknown then - n=n+1 t[n]=f_key_str_value_num(depth,tostring(k),v) - end - elseif tv=="string" then - if tk=="number" then - n=n+1 t[n]=f_key_num_value_str(depth,k,v) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_str(depth,k,v) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_str(depth,k,v) - elseif unknown then - n=n+1 t[n]=f_key_str_value_str(depth,tostring(k),v) - end - elseif tv=="table" then - if next(v)==nil then - if tk=="number" then - n=n+1 t[n]=f_key_num_value_not(depth,k) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_not(depth,k) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_not(depth,k) - elseif unknown then - n=n+1 t[n]=f_key_str_value_not(depth,tostring(k)) - end - else - local st=is_simple_table(v) - if not st then - do_serialize(v,k,depth,level+1) - elseif tk=="number" then - n=n+1 t[n]=f_key_num_value_seq(depth,k,st) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_seq(depth,k,st) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_seq(depth,k,st) - elseif unknown then - n=n+1 t[n]=f_key_str_value_seq(depth,tostring(k),st) - end - end - elseif tv=="boolean" then - if tk=="number" then - n=n+1 t[n]=f_key_num_value_boo(depth,k,v) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_boo(depth,k,v) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_boo(depth,k,v) - elseif unknown then - n=n+1 t[n]=f_key_str_value_boo(depth,tostring(k),v) - end - else - if tk=="number" then - n=n+1 t[n]=f_key_num_value_str(depth,k,tostring(v)) - elseif tk=="string" then - n=n+1 t[n]=f_key_str_value_str(depth,k,tostring(v)) - elseif tk=="boolean" then - n=n+1 t[n]=f_key_boo_value_str(depth,k,tostring(v)) - elseif unknown then - n=n+1 t[n]=f_key_str_value_str(depth,tostring(k),tostring(v)) - end - end - end - end - if level>0 then - n=n+1 t[n]=f_stop(depth-1) - end - end - local tname=type(name) - if tname=="string" then - if name=="return" then - t={ f_table_return() } - else - t={ f_table_name(name) } - end - elseif tname=="number" then - t={ f_table_entry(name) } - elseif tname=="boolean" then - if name then - t={ f_table_return() } - else - t={ f_table_direct() } - end - else - t={ f_table_name("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)~=nil then - local st=is_simple_table(root) - if st then - return t[1]..f_fin_seq(st) - else - do_serialize(root,name,1,0) - end - end - end - n=n+1 - t[n]=f_table_finish() - return concat(t,"\n") -end -table.serialize=serialize -if setinspector then - setinspector("table",function(v) - if type(v)=="table" then - print(serialize(v,"table",{ metacheck=false })) - return true - end - end) -end -local mt={ - __newindex=function(t,k,v) - local n=t.last+1 - t.last=n - t.list[n]=k - t.hash[k]=v - end, - __index=function(t,k) - return t.hash[k] - end, - __len=function(t) - return t.last - end, -} -function table.orderedhash() - return setmetatable({ list={},hash={},last=0 },mt) -end -function table.ordered(t) - local n=t.last - if n>0 then - local l=t.list - local i=1 - local h=t.hash - local f=function() - if i<=n then - local k=i - local v=h[l[k]] - i=i+1 - return k,v - end - end - return f,1,h[l[1]] - else - return function() end - end -end -function combine(target,source) - if target then - for k,v in next,source do - if type(v)=="table" then - target[k]=combine(target[k],source[k]) - else - target[k]=v - end - end - return target - else - return source - end -end -table.combine=combine - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-fil"] = package.loaded["util-fil"] or true - --- original size: 11474, stripped down to: 8973 - -if not modules then modules={} end modules ['util-fil']={ - version=1.001, - optimize=true, - 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 tonumber=tonumber -local byte=string.byte -local char=string.char -utilities=utilities or {} -local files={} -utilities.files=files -local zerobased={} -function files.open(filename,zb) - local f=io.open(filename,"rb") - if f then - zerobased[f]=zb or false - end - return f -end -function files.close(f) - zerobased[f]=nil - f:close() -end -function files.size(f) - local current=f:seek() - local size=f:seek("end") - f:seek("set",current) - return size -end -files.getsize=files.size -function files.setposition(f,n) - if zerobased[f] then - f:seek("set",n) - else - f:seek("set",n-1) - end -end -function files.getposition(f) - if zerobased[f] then - return f:seek() - else - return f:seek()+1 - end -end -function files.look(f,n,chars) - local p=f:seek() - local s=f:read(n) - f:seek("set",p) - if chars then - return s - else - return byte(s,1,#s) - end -end -function files.skip(f,n) - if n==1 then - f:read(n) - else - f:seek("set",f:seek()+n) - end -end -function files.readbyte(f) - return byte(f:read(1)) -end -function files.readbytes(f,n) - return byte(f:read(n),1,n) -end -function files.readbytetable(f,n) - local s=f:read(n or 1) - return { byte(s,1,#s) } -end -function files.readchar(f) - return f:read(1) -end -function files.readstring(f,n) - return f:read(n or 1) -end -function files.readinteger1(f) - local n=byte(f:read(1)) - if n>=0x80 then - return n-0x100 - else - return n - end -end -files.readcardinal1=files.readbyte -files.readcardinal=files.readcardinal1 -files.readinteger=files.readinteger1 -files.readsignedbyte=files.readinteger1 -function files.readcardinal2(f) - local a,b=byte(f:read(2),1,2) - return 0x100*a+b -end -function files.readcardinal2le(f) - local b,a=byte(f:read(2),1,2) - return 0x100*a+b -end -function files.readinteger2(f) - local a,b=byte(f:read(2),1,2) - if a>=0x80 then - return 0x100*a+b-0x10000 - else - return 0x100*a+b - end -end -function files.readinteger2le(f) - local b,a=byte(f:read(2),1,2) - if a>=0x80 then - return 0x100*a+b-0x10000 - else - return 0x100*a+b - end -end -function files.readcardinal3(f) - local a,b,c=byte(f:read(3),1,3) - return 0x10000*a+0x100*b+c -end -function files.readcardinal3le(f) - local c,b,a=byte(f:read(3),1,3) - return 0x10000*a+0x100*b+c -end -function files.readinteger3(f) - local a,b,c=byte(f:read(3),1,3) - if a>=0x80 then - return 0x10000*a+0x100*b+c-0x1000000 - else - return 0x10000*a+0x100*b+c - end -end -function files.readinteger3le(f) - local c,b,a=byte(f:read(3),1,3) - if a>=0x80 then - return 0x10000*a+0x100*b+c-0x1000000 - else - return 0x10000*a+0x100*b+c - end -end -function files.readcardinal4(f) - local a,b,c,d=byte(f:read(4),1,4) - return 0x1000000*a+0x10000*b+0x100*c+d -end -function files.readcardinal4le(f) - local d,c,b,a=byte(f:read(4),1,4) - return 0x1000000*a+0x10000*b+0x100*c+d -end -function files.readinteger4(f) - local a,b,c,d=byte(f:read(4),1,4) - if a>=0x80 then - return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000 - else - return 0x1000000*a+0x10000*b+0x100*c+d - end -end -function files.readinteger4le(f) - local d,c,b,a=byte(f:read(4),1,4) - if a>=0x80 then - return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000 - else - return 0x1000000*a+0x10000*b+0x100*c+d - end -end -function files.readfixed2(f) - local n1,n2=byte(f:read(2),1,2) - if n1>=0x80 then - n1=n1-0x100 - end - return n1+n2/0xFF -end -function files.readfixed4(f) - local a,b,c,d=byte(f:read(4),1,4) - local n1=0x100*a+b - local n2=0x100*c+d - if n1>=0x8000 then - n1=n1-0x10000 - end - return n1+n2/0xFFFF -end -if bit32 then - local extract=bit32.extract - local band=bit32.band - function files.read2dot14(f) - local a,b=byte(f:read(2),1,2) - if a>=0x80 then - local n=-(0x100*a+b) - return-(extract(n,14,2)+(band(n,0x3FFF)/16384.0)) - else - local n=0x100*a+b - return (extract(n,14,2)+(band(n,0x3FFF)/16384.0)) - end - end -end -function files.skipshort(f,n) - f:read(2*(n or 1)) -end -function files.skiplong(f,n) - f:read(4*(n or 1)) -end -if bit32 then - local rshift=bit32.rshift - function files.writecardinal2(f,n) - local a=char(n%256) - n=rshift(n,8) - local b=char(n%256) - f:write(b,a) - end - function files.writecardinal4(f,n) - local a=char(n%256) - n=rshift(n,8) - local b=char(n%256) - n=rshift(n,8) - local c=char(n%256) - n=rshift(n,8) - local d=char(n%256) - f:write(d,c,b,a) - end - function files.writecardinal2le(f,n) - local a=char(n%256) - n=rshift(n,8) - local b=char(n%256) - f:write(a,b) - end - function files.writecardinal4le(f,n) - local a=char(n%256) - n=rshift(n,8) - local b=char(n%256) - n=rshift(n,8) - local c=char(n%256) - n=rshift(n,8) - local d=char(n%256) - f:write(a,b,c,d) - end -else - local floor=math.floor - function files.writecardinal2(f,n) - local a=char(n%256) - n=floor(n/256) - local b=char(n%256) - f:write(b,a) - end - function files.writecardinal4(f,n) - local a=char(n%256) - n=floor(n/256) - local b=char(n%256) - n=floor(n/256) - local c=char(n%256) - n=floor(n/256) - local d=char(n%256) - f:write(d,c,b,a) - end - function files.writecardinal2le(f,n) - local a=char(n%256) - n=floor(n/256) - local b=char(n%256) - f:write(a,b) - end - function files.writecardinal4le(f,n) - local a=char(n%256) - n=floor(n/256) - local b=char(n%256) - n=floor(n/256) - local c=char(n%256) - n=floor(n/256) - local d=char(n%256) - f:write(a,b,c,d) - end -end -function files.writestring(f,s) - f:write(char(byte(s,1,#s))) -end -function files.writebyte(f,b) - f:write(char(b)) -end -if fio and fio.readcardinal1 then - files.readcardinal1=fio.readcardinal1 - files.readcardinal2=fio.readcardinal2 - files.readcardinal3=fio.readcardinal3 - files.readcardinal4=fio.readcardinal4 - files.readcardinal1le=fio.readcardinal1le or files.readcardinal1le - files.readcardinal2le=fio.readcardinal2le or files.readcardinal2le - files.readcardinal3le=fio.readcardinal3le or files.readcardinal3le - files.readcardinal4le=fio.readcardinal4le or files.readcardinal4le - files.readinteger1=fio.readinteger1 - files.readinteger2=fio.readinteger2 - files.readinteger3=fio.readinteger3 - files.readinteger4=fio.readinteger4 - files.readinteger1le=fio.readinteger1le or files.readinteger1le - files.readinteger2le=fio.readinteger2le or files.readinteger2le - files.readinteger3le=fio.readinteger3le or files.readinteger3le - files.readinteger4le=fio.readinteger4le or files.readinteger4le - files.readfixed2=fio.readfixed2 - files.readfixed4=fio.readfixed4 - files.read2dot14=fio.read2dot14 - files.setposition=fio.setposition - files.getposition=fio.getposition - files.readbyte=files.readcardinal1 - files.readsignedbyte=files.readinteger1 - files.readcardinal=files.readcardinal1 - files.readinteger=files.readinteger1 - local skipposition=fio.skipposition - files.skipposition=skipposition - files.readbytes=fio.readbytes - files.readbytetable=fio.readbytetable - function files.skipshort(f,n) - skipposition(f,2*(n or 1)) - end - function files.skiplong(f,n) - skipposition(f,4*(n or 1)) - end -end -if fio and fio.writecardinal1 then - files.writecardinal1=fio.writecardinal1 - files.writecardinal2=fio.writecardinal2 - files.writecardinal3=fio.writecardinal3 - files.writecardinal4=fio.writecardinal4 - files.writecardinal1le=fio.writecardinal1le - files.writecardinal2le=fio.writecardinal2le - files.writecardinal3le=fio.writecardinal3le - files.writecardinal4le=fio.writecardinal4le - files.writeinteger1=fio.writeinteger1 or fio.writecardinal1 - files.writeinteger2=fio.writeinteger2 or fio.writecardinal2 - files.writeinteger3=fio.writeinteger3 or fio.writecardinal3 - files.writeinteger4=fio.writeinteger4 or fio.writecardinal4 - files.writeinteger1le=files.writeinteger1le or fio.writecardinal1le - files.writeinteger2le=files.writeinteger2le or fio.writecardinal2le - files.writeinteger3le=files.writeinteger3le or fio.writecardinal3le - files.writeinteger4le=files.writeinteger4le or fio.writecardinal4le -end -if fio and fio.readcardinaltable then - files.readcardinaltable=fio.readcardinaltable - files.readintegertable=fio.readintegertable -else - local readcardinal1=files.readcardinal1 - local readcardinal2=files.readcardinal2 - local readcardinal3=files.readcardinal3 - local readcardinal4=files.readcardinal4 - function files.readcardinaltable(f,n,b) - local t={} - if b==1 then for i=1,n do t[i]=readcardinal1(f) end - elseif b==2 then for i=1,n do t[i]=readcardinal2(f) end - elseif b==3 then for i=1,n do t[i]=readcardinal3(f) end - elseif b==4 then for i=1,n do t[i]=readcardinal4(f) end end - return t - end - local readinteger1=files.readinteger1 - local readinteger2=files.readinteger2 - local readinteger3=files.readinteger3 - local readinteger4=files.readinteger4 - function files.readintegertable(f,n,b) - local t={} - if b==1 then for i=1,n do t[i]=readinteger1(f) end - elseif b==2 then for i=1,n do t[i]=readinteger2(f) end - elseif b==3 then for i=1,n do t[i]=readinteger3(f) end - elseif b==4 then for i=1,n do t[i]=readinteger4(f) end end - return t - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-sac"] = package.loaded["util-sac"] or true - --- original size: 14071, stripped down to: 10417 - -if not modules then modules={} end modules ['util-sac']={ - version=1.001, - optimize=true, - 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 byte,sub=string.byte,string.sub -local tonumber=tonumber -utilities=utilities or {} -local streams={} -utilities.streams=streams -function streams.open(filename,zerobased) - local f=filename and io.loaddata(filename) - if f then - return { f,1,#f,zerobased or false } - end -end -function streams.openstring(f,zerobased) - if f then - return { f,1,#f,zerobased or false } - end -end -function streams.getstring(f) - if f then - return f[1] - end -end -function streams.close() -end -function streams.size(f) - return f and f[3] or 0 -end -streams.getsize=streams.size -function streams.setposition(f,i) - if f[4] then - if i<=0 then - f[2]=1 - else - f[2]=i+1 - end - else - if i<=1 then - f[2]=1 - else - f[2]=i - end - end -end -function streams.getposition(f) - if f[4] then - return f[2]-1 - else - return f[2] - end -end -function streams.look(f,n,chars) - local b=f[2] - local e=b+n-1 - if chars then - return sub(f[1],b,e) - else - return byte(f[1],b,e) - end -end -function streams.skip(f,n) - f[2]=f[2]+n -end -function streams.readbyte(f) - local i=f[2] - f[2]=i+1 - return byte(f[1],i) -end -function streams.readbytes(f,n) - local i=f[2] - local j=i+n - f[2]=j - return byte(f[1],i,j-1) -end -function streams.readbytetable(f,n) - local i=f[2] - local j=i+n - f[2]=j - return { byte(f[1],i,j-1) } -end -function streams.skipbytes(f,n) - f[2]=f[2]+n -end -function streams.readchar(f) - local i=f[2] - f[2]=i+1 - return sub(f[1],i,i) -end -function streams.readstring(f,n) - local i=f[2] - local j=i+n - f[2]=j - return sub(f[1],i,j-1) -end -function streams.readinteger1(f) - local i=f[2] - f[2]=i+1 - local n=byte(f[1],i) - if n>=0x80 then - return n-0x100 - else - return n - end -end -streams.readcardinal1=streams.readbyte -streams.readcardinal=streams.readcardinal1 -streams.readinteger=streams.readinteger1 -function streams.readcardinal2(f) - local i=f[2] - local j=i+1 - f[2]=j+1 - local a,b=byte(f[1],i,j) - return 0x100*a+b -end -function streams.readcardinal2le(f) - local i=f[2] - local j=i+1 - f[2]=j+1 - local b,a=byte(f[1],i,j) - return 0x100*a+b -end -function streams.readinteger2(f) - local i=f[2] - local j=i+1 - f[2]=j+1 - local a,b=byte(f[1],i,j) - if a>=0x80 then - return 0x100*a+b-0x10000 - else - return 0x100*a+b - end -end -function streams.readinteger2le(f) - local i=f[2] - local j=i+1 - f[2]=j+1 - local b,a=byte(f[1],i,j) - if a>=0x80 then - return 0x100*a+b-0x10000 - else - return 0x100*a+b - end -end -function streams.readcardinal3(f) - local i=f[2] - local j=i+2 - f[2]=j+1 - local a,b,c=byte(f[1],i,j) - return 0x10000*a+0x100*b+c -end -function streams.readcardinal3le(f) - local i=f[2] - local j=i+2 - f[2]=j+1 - local c,b,a=byte(f[1],i,j) - return 0x10000*a+0x100*b+c -end -function streams.readinteger3(f) - local i=f[2] - local j=i+3 - f[2]=j+1 - local a,b,c=byte(f[1],i,j) - if a>=0x80 then - return 0x10000*a+0x100*b+c-0x1000000 - else - return 0x10000*a+0x100*b+c - end -end -function streams.readinteger3le(f) - local i=f[2] - local j=i+3 - f[2]=j+1 - local c,b,a=byte(f[1],i,j) - if a>=0x80 then - return 0x10000*a+0x100*b+c-0x1000000 - else - return 0x10000*a+0x100*b+c - end -end -function streams.readcardinal4(f) - local i=f[2] - local j=i+3 - f[2]=j+1 - local a,b,c,d=byte(f[1],i,j) - return 0x1000000*a+0x10000*b+0x100*c+d -end -function streams.readcardinal4le(f) - local i=f[2] - local j=i+3 - f[2]=j+1 - local d,c,b,a=byte(f[1],i,j) - return 0x1000000*a+0x10000*b+0x100*c+d -end -function streams.readinteger4(f) - local i=f[2] - local j=i+3 - f[2]=j+1 - local a,b,c,d=byte(f[1],i,j) - if a>=0x80 then - return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000 - else - return 0x1000000*a+0x10000*b+0x100*c+d - end -end -function streams.readinteger4le(f) - local i=f[2] - local j=i+3 - f[2]=j+1 - local d,c,b,a=byte(f[1],i,j) - if a>=0x80 then - return 0x1000000*a+0x10000*b+0x100*c+d-0x100000000 - else - return 0x1000000*a+0x10000*b+0x100*c+d - end -end -function streams.readfixed2(f) - local i=f[2] - local j=i+1 - f[2]=j+1 - local n1,n2=byte(f[1],i,j) - if n1>=0x80 then - n1=n1-0x100 - end - return n1+n2/0xFF -end -function streams.readfixed4(f) - local i=f[2] - local j=i+3 - f[2]=j+1 - local a,b,c,d=byte(f[1],i,j) - local n1=0x100*a+b - local n2=0x100*c+d - if n1>=0x8000 then - n1=n1-0x10000 - end - return n1+n2/0xFFFF -end -if bit32 then - local extract=bit32.extract - local band=bit32.band - function streams.read2dot14(f) - local i=f[2] - local j=i+1 - f[2]=j+1 - local a,b=byte(f[1],i,j) - if a>=0x80 then - local n=-(0x100*a+b) - return-(extract(n,14,2)+(band(n,0x3FFF)/16384.0)) - else - local n=0x100*a+b - return (extract(n,14,2)+(band(n,0x3FFF)/16384.0)) - end - end -end -function streams.skipshort(f,n) - f[2]=f[2]+2*(n or 1) -end -function streams.skiplong(f,n) - f[2]=f[2]+4*(n or 1) -end -if sio and sio.readcardinal2 then - local readcardinal1=sio.readcardinal1 - local readcardinal2=sio.readcardinal2 - local readcardinal3=sio.readcardinal3 - local readcardinal4=sio.readcardinal4 - local readinteger1=sio.readinteger1 - local readinteger2=sio.readinteger2 - local readinteger3=sio.readinteger3 - local readinteger4=sio.readinteger4 - local readfixed2=sio.readfixed2 - local readfixed4=sio.readfixed4 - local read2dot14=sio.read2dot14 - local readbytes=sio.readbytes - local readbytetable=sio.readbytetable - function streams.readcardinal1(f) - local i=f[2] - f[2]=i+1 - return readcardinal1(f[1],i) - end - function streams.readcardinal2(f) - local i=f[2] - f[2]=i+2 - return readcardinal2(f[1],i) - end - function streams.readcardinal3(f) - local i=f[2] - f[2]=i+3 - return readcardinal3(f[1],i) - end - function streams.readcardinal4(f) - local i=f[2] - f[2]=i+4 - return readcardinal4(f[1],i) - end - function streams.readinteger1(f) - local i=f[2] - f[2]=i+1 - return readinteger1(f[1],i) - end - function streams.readinteger2(f) - local i=f[2] - f[2]=i+2 - return readinteger2(f[1],i) - end - function streams.readinteger3(f) - local i=f[2] - f[2]=i+3 - return readinteger3(f[1],i) - end - function streams.readinteger4(f) - local i=f[2] - f[2]=i+4 - return readinteger4(f[1],i) - end - function streams.readfixed2(f) - local i=f[2] - f[2]=i+2 - return readfixed2(f[1],i) - end - function streams.readfixed4(f) - local i=f[2] - f[2]=i+4 - return readfixed4(f[1],i) - end - function streams.read2dot14(f) - local i=f[2] - f[2]=i+2 - return read2dot14(f[1],i) - end - function streams.readbytes(f,n) - local i=f[2] - local s=f[3] - local p=i+n - if p>s then - f[2]=s+1 - else - f[2]=p - end - return readbytes(f[1],i,n) - end - function streams.readbytetable(f,n) - local i=f[2] - local s=f[3] - local p=i+n - if p>s then - f[2]=s+1 - else - f[2]=p - end - return readbytetable(f[1],i,n) - end - streams.readbyte=streams.readcardinal1 - streams.readsignedbyte=streams.readinteger1 - streams.readcardinal=streams.readcardinal1 - streams.readinteger=streams.readinteger1 -end -if sio and sio.readcardinaltable then - local readcardinaltable=sio.readcardinaltable - local readintegertable=sio.readintegertable - function utilities.streams.readcardinaltable(f,n,b) - local i=f[2] - local s=f[3] - local p=i+n*b - if p>s then - f[2]=s+1 - else - f[2]=p - end - return readcardinaltable(f[1],i,n,b) - end - function utilities.streams.readintegertable(f,n,b) - local i=f[2] - local s=f[3] - local p=i+n*b - if p>s then - f[2]=s+1 - else - f[2]=p - end - return readintegertable(f[1],i,n,b) - end -else - local readcardinal1=streams.readcardinal1 - local readcardinal2=streams.readcardinal2 - local readcardinal3=streams.readcardinal3 - local readcardinal4=streams.readcardinal4 - function streams.readcardinaltable(f,n,b) - local i=f[2] - local s=f[3] - local p=i+n*b - if p>s then - f[2]=s+1 - else - f[2]=p - end - local t={} - if b==1 then for i=1,n do t[i]=readcardinal1(f[1],i) end - elseif b==2 then for i=1,n do t[i]=readcardinal2(f[1],i) end - elseif b==3 then for i=1,n do t[i]=readcardinal3(f[1],i) end - elseif b==4 then for i=1,n do t[i]=readcardinal4(f[1],i) end end - return t - end - local readinteger1=streams.readinteger1 - local readinteger2=streams.readinteger2 - local readinteger3=streams.readinteger3 - local readinteger4=streams.readinteger4 - function streams.readintegertable(f,n,b) - local i=f[2] - local s=f[3] - local p=i+n*b - if p>s then - f[2]=s+1 - else - f[2]=p - end - local t={} - if b==1 then for i=1,n do t[i]=readinteger1(f[1],i) end - elseif b==2 then for i=1,n do t[i]=readinteger2(f[1],i) end - elseif b==3 then for i=1,n do t[i]=readinteger3(f[1],i) end - elseif b==4 then for i=1,n do t[i]=readinteger4(f[1],i) end end - return t - end -end -do - local files=utilities.files - if files then - local openfile=files.open - local openstream=streams.open - local openstring=streams.openstring - local setmetatable=setmetatable - function io.newreader(str,method) - local f,m - if method=="string" then - f=openstring(str,true) - m=streams - elseif method=="stream" then - f=openstream(str,true) - m=streams - else - f=openfile(str,"rb") - m=files - end - if f then - local t={} - setmetatable(t,{ - __index=function(t,k) - local r=m[k] - if k=="close" then - if f then - m.close(f) - f=nil - end - return function() end - elseif r then - local v=function(_,a,b) return r(f,a,b) end - t[k]=v - return v - else - print("unknown key",k) - end - end - } ) - return t - end - end - end -end -if bit32 and not streams.tocardinal1 then - local extract=bit32.extract - local char=string.char - streams.tocardinal1=char - function streams.tocardinal2(n) return char(extract(8,8),extract(0,8)) end - function streams.tocardinal3(n) return char(extract(16,8),extract(8,8),extract(0,8)) end - function streams.tocardinal4(n) return char(extract(24,8),extract(16,8),extract(8,8),extract(0,8)) end - streams.tocardinal1le=char - function streams.tocardinal2le(n) return char(extract(0,8),extract(8,8)) end - function streams.tocardinal3le(n) return char(extract(0,8),extract(8,8),extract(16,8)) end - function streams.tocardinal4le(n) return char(extract(0,8),extract(8,8),extract(16,8),extract(24,8)) end -end -if not streams.readcstring then - local readchar=streams.readchar - local concat=table.concat - function streams.readcstring(f) - local t={} - while true do - local c=readchar(f) - if c and c~="\0" then - t[#t+1]=c - else - return concat(t) - end - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-sto"] = package.loaded["util-sto"] or true - --- original size: 6661, stripped down to: 3074 - -if not modules then modules={} end modules ['util-sto']={ - 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 setmetatable,getmetatable,rawset,type=setmetatable,getmetatable,rawset,type -utilities=utilities or {} -utilities.storage=utilities.storage or {} -local storage=utilities.storage -function storage.mark(t) - if not t then - print("\nfatal error: storage cannot be marked\n") - os.exit() - return - end - local m=getmetatable(t) - if not m then - m={} - setmetatable(t,m) - end - m.__storage__=true - return t -end -function storage.allocate(t) - t=t or {} - local m=getmetatable(t) - if not m then - m={} - setmetatable(t,m) - end - m.__storage__=true - return t -end -function storage.marked(t) - local m=getmetatable(t) - return m and m.__storage__ -end -function storage.checked(t) - if not t then - report("\nfatal error: storage has not been allocated\n") - os.exit() - return - end - return t -end -function storage.setinitializer(data,initialize) - local m=getmetatable(data) or {} - m.__index=function(data,k) - m.__index=nil - initialize() - return data[k] - end - setmetatable(data,m) -end -local keyisvalue={ __index=function(t,k) - t[k]=k - return k -end } -function storage.sparse(t) - t=t or {} - setmetatable(t,keyisvalue) - return t -end -local function f_empty () return "" end -local function f_self (t,k) t[k]=k return k end -local function f_table (t,k) local v={} t[k]=v return v end -local function f_number(t,k) t[k]=0 return 0 end -local function f_ignore() end -local f_index={ - ["empty"]=f_empty, - ["self"]=f_self, - ["table"]=f_table, - ["number"]=f_number, -} -function table.setmetatableindex(t,f) - if type(t)~="table" then - f,t=t,{} - end - local m=getmetatable(t) - local i=f_index[f] or f - if m then - m.__index=i - else - setmetatable(t,{ __index=i }) - end - return t -end -local f_index={ - ["ignore"]=f_ignore, -} -function table.setmetatablenewindex(t,f) - if type(t)~="table" then - f,t=t,{} - end - local m=getmetatable(t) - local i=f_index[f] or f - if m then - m.__newindex=i - else - setmetatable(t,{ __newindex=i }) - end - return t -end -function table.setmetatablecall(t,f) - if type(t)~="table" then - f,t=t,{} - end - local m=getmetatable(t) - if m then - m.__call=f - else - setmetatable(t,{ __call=f }) - end - return t -end -function table.setmetatableindices(t,f,n,c) - if type(t)~="table" then - f,t=t,{} - end - local m=getmetatable(t) - local i=f_index[f] or f - if m then - m.__index=i - m.__newindex=n - m.__call=c - else - setmetatable(t,{ - __index=i, - __newindex=n, - __call=c, - }) - end - return t -end -function table.setmetatablekey(t,key,value) - local m=getmetatable(t) - if not m then - m={} - setmetatable(t,m) - end - m[key]=value - return t -end -function table.getmetatablekey(t,key,value) - local m=getmetatable(t) - return m and m[key] -end -function table.makeweak(t) - if not t then - t={} - end - local m=getmetatable(t) - if m then - m.__mode="v" - else - setmetatable(t,{ __mode="v" }) - end - return t -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-prs"] = package.loaded["util-prs"] or true - --- original size: 25542, stripped down to: 16783 - -if not modules then modules={} end modules ['util-prs']={ - 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 lpeg,table,string=lpeg,table,string -local P,R,V,S,C,Ct,Cs,Carg,Cc,Cg,Cf,Cp=lpeg.P,lpeg.R,lpeg.V,lpeg.S,lpeg.C,lpeg.Ct,lpeg.Cs,lpeg.Carg,lpeg.Cc,lpeg.Cg,lpeg.Cf,lpeg.Cp -local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns -local concat,gmatch,find=table.concat,string.gmatch,string.find -local tonumber,tostring,type,next,rawset=tonumber,tostring,type,next,rawset -local mod,div=math.mod,math.div -utilities=utilities or {} -local parsers=utilities.parsers or {} -utilities.parsers=parsers -local patterns=parsers.patterns or {} -parsers.patterns=patterns -local setmetatableindex=table.setmetatableindex -local sortedhash=table.sortedhash -local sortedkeys=table.sortedkeys -local tohash=table.tohash -local hashes={} -parsers.hashes=hashes -local digit=R("09") -local space=P(' ') -local equal=P("=") -local colon=P(":") -local comma=P(",") -local lbrace=P("{") -local rbrace=P("}") -local lparent=P("(") -local rparent=P(")") -local lbracket=P("[") -local rbracket=P("]") -local period=S(".") -local punctuation=S(".,:;") -local spacer=lpegpatterns.spacer -local whitespace=lpegpatterns.whitespace -local newline=lpegpatterns.newline -local anything=lpegpatterns.anything -local endofstring=lpegpatterns.endofstring -local nobrace=1-(lbrace+rbrace ) -local noparent=1-(lparent+rparent) -local nobracket=1-(lbracket+rbracket) -local escape,left,right=P("\\"),P('{'),P('}') -lpegpatterns.balanced=P { - ((escape*(left+right))+(1-(left+right))+V(2))^0, - left*V(1)*right -} -local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace } -local nestedparents=P { lparent*(noparent+V(1))^0*rparent } -local nestedbrackets=P { lbracket*(nobracket+V(1))^0*rbracket } -local spaces=space^0 -local argument=Cs((lbrace/"")*((nobrace+nestedbraces)^0)*(rbrace/"")) -local content=(1-endofstring)^0 -lpegpatterns.nestedbraces=nestedbraces -lpegpatterns.nestedparents=nestedparents -lpegpatterns.nestedbrackets=nestedbrackets -lpegpatterns.nested=nestedbraces -lpegpatterns.argument=argument -lpegpatterns.content=content -local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace+C((nestedbraces+(1-comma))^0) -local key=C((1-equal-comma)^1) -local pattern_a=(space+comma)^0*(key*equal*value+key*C("")) -local pattern_c=(space+comma)^0*(key*equal*value) -local pattern_d=(space+comma)^0*(key*(equal+colon)*value+key*C("")) -local key=C((1-space-equal-comma)^1) -local pattern_b=spaces*comma^0*spaces*(key*((spaces*equal*spaces*value)+C(""))) -local hash={} -local function set(key,value) - hash[key]=value -end -local pattern_a_s=(pattern_a/set)^1 -local pattern_b_s=(pattern_b/set)^1 -local pattern_c_s=(pattern_c/set)^1 -local pattern_d_s=(pattern_d/set)^1 -patterns.settings_to_hash_a=pattern_a_s -patterns.settings_to_hash_b=pattern_b_s -patterns.settings_to_hash_c=pattern_c_s -patterns.settings_to_hash_d=pattern_d_s -function parsers.make_settings_to_hash_pattern(set,how) - if how=="strict" then - return (pattern_c/set)^1 - elseif how=="tolerant" then - return (pattern_b/set)^1 - else - return (pattern_a/set)^1 - end -end -function parsers.settings_to_hash(str,existing) - if not str or str=="" then - return {} - elseif type(str)=="table" then - if existing then - for k,v in next,str do - existing[k]=v - end - return exiting - else - return str - end - else - hash=existing or {} - lpegmatch(pattern_a_s,str) - return hash - end -end -function parsers.settings_to_hash_colon_too(str) - if not str or str=="" then - return {} - elseif type(str)=="table" then - return str - else - hash={} - lpegmatch(pattern_d_s,str) - return hash - end -end -function parsers.settings_to_hash_tolerant(str,existing) - if not str or str=="" then - return {} - elseif type(str)=="table" then - if existing then - for k,v in next,str do - existing[k]=v - end - return exiting - else - return str - end - else - hash=existing or {} - lpegmatch(pattern_b_s,str) - return hash - end -end -function parsers.settings_to_hash_strict(str,existing) - if not str or str=="" then - return nil - elseif type(str)=="table" then - if existing then - for k,v in next,str do - existing[k]=v - end - return exiting - else - return str - end - elseif str and str~="" then - hash=existing or {} - lpegmatch(pattern_c_s,str) - return next(hash) and hash - end -end -local separator=comma*space^0 -local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace+C((nestedbraces+(1-comma))^0) -local pattern=spaces*Ct(value*(separator*value)^0) -patterns.settings_to_array=pattern -function parsers.settings_to_array(str,strict) - if not str or str=="" then - return {} - elseif type(str)=="table" then - return str - elseif strict then - if find(str,"{",1,true) then - return lpegmatch(pattern,str) - else - return { str } - end - elseif find(str,",",1,true) then - return lpegmatch(pattern,str) - else - return { str } - end -end -function parsers.settings_to_numbers(str) - if not str or str=="" then - return {} - end - if type(str)=="table" then - elseif find(str,",",1,true) then - str=lpegmatch(pattern,str) - else - return { tonumber(str) } - end - for i=1,#str do - str[i]=tonumber(str[i]) - end - return str -end -local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace+C((nestedbraces+nestedbrackets+nestedparents+(1-comma))^0) -local pattern=spaces*Ct(value*(separator*value)^0) -function parsers.settings_to_array_obey_fences(str) - return lpegmatch(pattern,str) -end -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=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 {} - else - return lpegmatch(pattern_a,str) - end -end -function parsers.process_stripped_settings(str,action) - if not str or str=="" then - return {} - else - return lpegmatch(pattern_b,str,1,action) - end -end -local function set(t,v) - t[#t+1]=v -end -local value=P(Carg(1)*value)/set -local pattern=value*(separator*value)^0*Carg(1) -function parsers.add_settings_to_array(t,str) - return lpegmatch(pattern,str,nil,t) -end -function parsers.hash_to_string(h,separator,yes,no,strict,omit) - if h then - local t={} - local tn=0 - local s=sortedkeys(h) - omit=omit and tohash(omit) - for i=1,#s do - local key=s[i] - if not omit or not omit[key] then - local value=h[key] - if type(value)=="boolean" then - if yes and no then - if value then - tn=tn+1 - t[tn]=key..'='..yes - elseif not strict then - tn=tn+1 - t[tn]=key..'='..no - end - elseif value or not strict then - tn=tn+1 - t[tn]=key..'='..tostring(value) - end - else - tn=tn+1 - t[tn]=key..'='..value - end - end - end - return concat(t,separator or ",") - else - return "" - end -end -function parsers.array_to_string(a,separator) - if a then - return concat(a,separator or ",") - else - return "" - end -end -local pattern=Cf(Ct("")*Cg(C((1-S(", "))^1)*S(", ")^0*Cc(true))^1,rawset) -function parsers.settings_to_set(str) - return str and lpegmatch(pattern,str) or {} -end -hashes.settings_to_set=table.setmetatableindex(function(t,k) - local v=k and lpegmatch(pattern,k) or {} - t[k]=v - return v -end) -getmetatable(hashes.settings_to_set).__mode="kv" -function parsers.simple_hash_to_string(h,separator) - local t={} - local tn=0 - for k,v in sortedhash(h) do - if v then - tn=tn+1 - t[tn]=k - end - end - return concat(t,separator or ",") -end -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 parsers.options_to_hash(str,target) - return str and lpegmatch(splitter,str,1,target or {}) or {} -end -local splitter=lpeg.tsplitat(" ") -function 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) - if not n then - return str - else - local s=lpegmatch(pattern_a,str) - if n==1 then - return unpack(s) - else - local t={} - local tn=0 - for i=1,n do - for j=1,#s do - tn=tn+1 - t[tn]=s[j] - end - end - return unpack(t) - end - end -end -local value=P(lbrace*C((nobrace+nestedbraces)^0)*rbrace)+(C(digit^1)/tonumber*lparent*Cs((noparent+nestedparents)^1)*rparent)/repeater+C((nestedbraces+(1-comma))^1) -local pattern_b=spaces*Ct(value*(separator*value)^0) -function parsers.settings_to_array_with_repeat(str,expand) - if expand then - return lpegmatch(pattern_b,str) or {} - else - return lpegmatch(pattern_a,str) or {} - end -end -local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace -local pattern=Ct((space+value)^0) -function parsers.arguments_to_table(str) - return lpegmatch(pattern,str) -end -function parsers.getparameters(self,class,parentclass,settings) - local sc=self[class] - if not sc then - sc={} - self[class]=sc - if parentclass then - local sp=self[parentclass] - if not sp then - sp={} - self[parentclass]=sp - end - setmetatableindex(sc,sp) - end - end - parsers.settings_to_hash(settings,sc) -end -function parsers.listitem(str) - return gmatch(str,"[^, ]+") -end -local pattern=Cs { "start", - start=V("one")+V("two")+V("three"), - rest=(Cc(",")*V("thousand"))^0*(P(".")+endofstring)*anything^0, - thousand=digit*digit*digit, - one=digit*V("rest"), - two=digit*digit*V("rest"), - three=V("thousand")*V("rest"), -} -lpegpatterns.splitthousands=pattern -function parsers.splitthousands(str) - return lpegmatch(pattern,str) or str -end -local optionalwhitespace=whitespace^0 -lpegpatterns.words=Ct((Cs((1-punctuation-whitespace)^1)+anything)^1) -lpegpatterns.sentences=Ct((optionalwhitespace*Cs((1-period)^0*period))^1) -lpegpatterns.paragraphs=Ct((optionalwhitespace*Cs((whitespace^1*endofstring/""+1-(spacer^0*newline*newline))^1))^1) -local dquote=P('"') -local equal=P('=') -local escape=P('\\') -local separator=S(' ,') -local key=C((1-equal)^1) -local value=dquote*C((1-dquote-escape*dquote)^0)*dquote -local pattern=Cf(Ct("")*(Cg(key*equal*value)*separator^0)^1,rawset)^0*P(-1) -function parsers.keq_to_hash(str) - if str and str~="" then - return lpegmatch(pattern,str) - else - return {} - end -end -local defaultspecification={ separator=",",quote='"' } -function parsers.csvsplitter(specification) - specification=specification and setmetatableindex(specification,defaultspecification) or defaultspecification - local separator=specification.separator - local quotechar=specification.quote - local numbers=specification.numbers - local separator=S(separator~="" and separator or ",") - local whatever=C((1-separator-newline)^0) - if quotechar and quotechar~="" then - local quotedata=nil - for chr in gmatch(quotechar,".") do - local quotechar=P(chr) - local quoteitem=(1-quotechar)^0 - local quoteword=quotechar*(numbers and (quoteitem/tonumber) or C(quoteitem))*quotechar - if quotedata then - quotedata=quotedata+quoteword - else - quotedata=quoteword - end - end - whatever=quotedata+whatever - end - local parser=Ct((Ct(whatever*(separator*whatever)^0)*S("\n\r")^1)^0 ) - return function(data) - return lpegmatch(parser,data) - end -end -function parsers.rfc4180splitter(specification) - specification=specification and setmetatableindex(specification,defaultspecification) or defaultspecification - local numbers=specification.numbers - local separator=specification.separator - local quotechar=P(specification.quote) - local dquotechar=quotechar*quotechar -/specification.quote - local separator=S(separator~="" and separator or ",") - local whatever=(dquotechar+(1-quotechar))^0 - local escaped=quotechar*(numbers and (whatever/tonumber) or Cs(whatever))*quotechar - local non_escaped=C((1-quotechar-newline-separator)^1) - local field=escaped+non_escaped+Cc("") - local record=Ct(field*(separator*field)^1) - local headerline=record*Cp() - local morerecords=(newline^(specification.strict and -1 or 1)*record)^0 - local headeryes=Ct(morerecords) - local headernop=Ct(record*morerecords) - return function(data,getheader) - if getheader then - local header,position=lpegmatch(headerline,data) - local data=lpegmatch(headeryes,data,position) - return data,header - else - return lpegmatch(headernop,data) - end - end -end -local function ranger(first,last,n,action) - if not first then - elseif last==true then - for i=first,n or first do - action(i) - end - elseif last then - for i=first,last do - action(i) - end - else - action(first) - end -end -local cardinal=(lpegpatterns.hexadecimal+lpegpatterns.cardinal)/tonumber -local spacers=lpegpatterns.spacer^0 -local endofstring=lpegpatterns.endofstring -local stepper=spacers*(cardinal*(spacers*S(":-")*spacers*(cardinal+Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1 -local stepper=spacers*(cardinal*(spacers*S(":-")*spacers*(cardinal+(P("*")+endofstring)*Cc(true) )+Cc(false) )*Carg(1)*Carg(2)/ranger*S(", ")^0 )^1*endofstring -function parsers.stepper(str,n,action) - local ts=type(str) - if type(n)=="function" then - if ts=="number" then - n(str) - elseif ts=="table" then - for i=1,#str do - n(str[i]) - end - else - lpegmatch(stepper,str,1,false,n or print) - end - elseif ts=="string" then - lpegmatch(stepper,str,1,n,action or print) - end -end -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>")+anything)^0) -function parsers.unittoxml(str) - return lpegmatch(pattern,str) -end -local cache={} -local spaces=lpegpatterns.space^0 -local dummy=function() end -setmetatableindex(cache,function(t,k) - local separator=S(k) - local value=(1-separator)^0 - local pattern=spaces*C(value)*separator^0*Cp() - t[k]=pattern - return pattern -end) -local commalistiterator=cache[","] -function parsers.iterator(str,separator) - local n=#str - if n==0 then - return dummy - else - local pattern=separator and cache[separator] or commalistiterator - local p=1 - return function() - if p<=n then - local s,e=lpegmatch(pattern,str,p) - if e then - p=e - return s - end - end - end - end -end -local function initialize(t,name) - local source=t[name] - if source then - local result={} - for k,v in next,t[name] do - result[k]=v - end - return result - else - return {} - end -end -local function fetch(t,name) - return t[name] or {} -end -local function process(result,more) - for k,v in next,more do - result[k]=v - end - return result -end -local name=C((1-S(", "))^1) -local parser=(Carg(1)*name/initialize)*(S(", ")^1*(Carg(1)*name/fetch))^0 -local merge=Cf(parser,process) -function parsers.mergehashes(hash,list) - return lpegmatch(merge,list,1,hash) -end -function parsers.runtime(time) - if not time then - time=os.runtime() - end - local days=div(time,24*60*60) - time=mod(time,24*60*60) - local hours=div(time,60*60) - time=mod(time,60*60) - local minutes=div(time,60) - 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 parsers.splitmethod(str,default) - if str then - return lpegmatch(pattern,str,1,default or false) - else - return default or false,"" - end -end -local p_year=lpegpatterns.digit^4/tonumber -local pattern=Cf(Ct("")*( - (Cg(Cc("year")*p_year)*S("-/")*Cg(Cc("month")*cardinal)*S("-/")*Cg(Cc("day")*cardinal) - )+(Cg(Cc("day")*cardinal)*S("-/")*Cg(Cc("month")*cardinal)*S("-/")*Cg(Cc("year")*p_year) - )+(Cg(Cc("year")*p_year)*S("-/")*Cg(Cc("month")*cardinal) - )+(Cg(Cc("month")*cardinal)*S("-/")*Cg(Cc("year")*p_year) - ) - )*( - P(" ")*Cg(Cc("hour")*cardinal)*P(":")*Cg(Cc("min")*cardinal)*(P(":")*Cg(Cc("sec")*cardinal))^-1+P(-1) ) -,rawset) -lpegpatterns.splittime=pattern -function parsers.totime(str) - return lpegmatch(pattern,str) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-fmt"] = package.loaded["util-fmt"] or true - --- original size: 2541, stripped down to: 1624 - -if not modules then modules={} end modules ['util-fmt']={ - 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" -} -utilities=utilities or {} -utilities.formatters=utilities.formatters or {} -local formatters=utilities.formatters -local concat,format=table.concat,string.format -local tostring,type=tostring,type -local strip=string.strip -local lpegmatch=lpeg.match -local stripper=lpeg.patterns.stripzeros -function formatters.stripzeros(str) - return lpegmatch(stripper,str) -end -function formatters.formatcolumns(result,between) - if result and #result>0 then - between=between or " " - local widths,numbers={},{} - local first=result[1] - local n=#first - for i=1,n do - widths[i]=0 - end - for i=1,#result do - local r=result[i] - for j=1,n do - local rj=r[j] - local tj=type(rj) - if tj=="number" then - numbers[j]=true - rj=tostring(rj) - elseif tj~="string" then - rj=tostring(rj) - r[j]=rj - end - local w=#rj - if w>widths[j] then - widths[j]=w - end - end - end - for i=1,n do - local w=widths[i] - if numbers[i] then - if w>80 then - widths[i]="%s"..between - else - widths[i]="%0"..w.."i"..between - end - else - if w>80 then - widths[i]="%s"..between - elseif w>0 then - widths[i]="%-"..w.."s"..between - else - widths[i]="%s" - end - end - end - local template=strip(concat(widths)) - for i=1,#result do - local str=format(template,unpack(result[i])) - result[i]=strip(str) - end - end - return result -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-soc-imp-reset"] = package.loaded["util-soc-imp-reset"] or true - --- original size: 374, stripped down to: 282 - -local loaded=package.loaded -loaded["socket"]=nil -loaded["copas"]=nil -loaded["ltn12"]=nil -loaded["mbox"]=nil -loaded["mime"]=nil -loaded["socket.url"]=nil -loaded["socket.headers"]=nil -loaded["socket.tp"]=nil -loaded["socket.http"]=nil -loaded["socket.ftp"]=nil -loaded["socket.smtp"]=nil - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-soc-imp-socket"] = package.loaded["util-soc-imp-socket"] or true - --- original size: 4905, stripped down to: 3562 - - -local type,tostring,setmetatable=type,tostring,setmetatable -local min=math.min -local format=string.format -local socket=socket or package.loaded.socket or require("socket.core") -local connect=socket.connect -local tcp4=socket.tcp4 -local tcp6=socket.tcp6 -local getaddrinfo=socket.dns.getaddrinfo -local defaulthost="0.0.0.0" -local function report(fmt,first,...) - if logs then - report=logs and logs.reporter("socket") - report(fmt,first,...) - elseif fmt then - fmt="socket: "..fmt - if first then - print(format(fmt,first,...)) - else - print(fmt) - end - end -end -socket.report=report -function socket.connect4(address,port,laddress,lport) - return connect(address,port,laddress,lport,"inet") -end -function socket.connect6(address,port,laddress,lport) - return connect(address,port,laddress,lport,"inet6") -end -function socket.bind(host,port,backlog) - if host=="*" or host=="" then - host=defaulthost - end - local addrinfo,err=getaddrinfo(host) - if not addrinfo then - return nil,err - end - for i=1,#addrinfo do - local alt=addrinfo[i] - local sock,err=(alt.family=="inet" and tcp4 or tcp6)() - if not sock then - return nil,err or "unknown error" - end - sock:setoption("reuseaddr",true) - local res,err=sock:bind(alt.addr,port) - if res then - res,err=sock:listen(backlog) - if res then - return sock - else - sock:close() - end - else - sock:close() - end - end - return nil,"invalid address" -end -socket.try=socket.newtry() -function socket.choose(list) - return function(name,opt1,opt2) - if type(name)~="string" then - name,opt1,opt2="default",name,opt1 - end - local f=list[name or "nil"] - if f then - return f(opt1,opt2) - else - report("error: unknown key '%s'",tostring(name)) - end - end -end -local sourcet={} -local sinkt={} -socket.sourcet=sourcet -socket.sinkt=sinkt -socket.BLOCKSIZE=2048 -sinkt["close-when-done"]=function(sock) - return setmetatable ( - { - getfd=function() return sock:getfd() end, - dirty=function() return sock:dirty() end, - }, - { - __call=function(self,chunk,err) - if chunk then - return sock:send(chunk) - else - sock:close() - return 1 - end - end - } - ) -end -sinkt["keep-open"]=function(sock) - return setmetatable ( - { - getfd=function() return sock:getfd() end, - dirty=function() return sock:dirty() end, - },{ - __call=function(self,chunk,err) - if chunk then - return sock:send(chunk) - else - return 1 - end - end - } - ) -end -sinkt["default"]=sinkt["keep-open"] -socket.sink=socket.choose(sinkt) -sourcet["by-length"]=function(sock,length) - local blocksize=socket.BLOCKSIZE - return setmetatable ( - { - getfd=function() return sock:getfd() end, - dirty=function() return sock:dirty() end, - }, - { - __call=function() - if length<=0 then - return nil - end - local chunk,err=sock:receive(min(blocksize,length)) - if err then - return nil,err - end - length=length-#chunk - return chunk - end - } - ) -end -sourcet["until-closed"]=function(sock) - local blocksize=socket.BLOCKSIZE - local done=false - return setmetatable ( - { - getfd=function() return sock:getfd() end, - dirty=function() return sock:dirty() end, - },{ - __call=function() - if done then - return nil - end - local chunk,status,partial=sock:receive(blocksize) - if not status then - return chunk - elseif status=="closed" then - sock:close() - done=true - return partial - else - return nil,status - end - end - } - ) -end -sourcet["default"]=sourcet["until-closed"] -socket.source=socket.choose(sourcet) -_G.socket=socket -package.loaded["socket"]=socket - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-soc-imp-copas"] = package.loaded["util-soc-imp-copas"] or true - --- original size: 26186, stripped down to: 14893 - - -local socket=socket or require("socket") -local ssl=ssl or nil -local WATCH_DOG_TIMEOUT=120 -local UDP_DATAGRAM_MAX=8192 -local type,next,pcall,getmetatable,tostring=type,next,pcall,getmetatable,tostring -local min,max,random=math.min,math.max,math.random -local find=string.find -local insert,remove=table.insert,table.remove -local gettime=socket.gettime -local selectsocket=socket.select -local createcoroutine=coroutine.create -local resumecoroutine=coroutine.resume -local yieldcoroutine=coroutine.yield -local runningcoroutine=coroutine.running -local function report(fmt,first,...) - if logs then - report=logs and logs.reporter("copas") - report(fmt,first,...) - elseif fmt then - fmt="copas: "..fmt - if first then - print(format(fmt,first,...)) - else - print(fmt) - end - end -end -local copas={ - _COPYRIGHT="Copyright (C) 2005-2016 Kepler Project", - _DESCRIPTION="Coroutine Oriented Portable Asynchronous Services", - _VERSION="Copas 2.0.1", - autoclose=true, - running=false, - report=report, - trace=false, -} -local function statushandler(status,...) - if status then - return... - end - local err=(...) - if type(err)=="table" then - err=err[1] - end - if copas.trace then - report("error: %s",tostring(err)) - end - return nil,err -end -function socket.protect(func) - return function(...) - return statushandler(pcall(func,...)) - end -end -function socket.newtry(finalizer) - return function (...) - local status=(...) - if not status then - local detail=select(2,...) - pcall(finalizer,detail) - if copas.trace then - report("error: %s",tostring(detail)) - end - return - end - return... - end -end -local function newset() - local reverse={} - local set={} - local queue={} - setmetatable(set,{ - __index={ - insert=function(set,value) - if not reverse[value] then - local n=#set+1 - set[n]=value - reverse[value]=n - end - end, - remove=function(set,value) - local index=reverse[value] - if index then - reverse[value]=nil - local n=#set - local top=set[n] - set[n]=nil - if top~=value then - reverse[top]=index - set[index]=top - end - end - end, - push=function (set,key,itm) - local entry=queue[key] - if entry==nil then - queue[key]={ itm } - else - entry[#entry+1]=itm - end - end, - pop=function (set,key) - local top=queue[key] - if top~=nil then - local ret=remove(top,1) - if top[1]==nil then - queue[key]=nil - end - return ret - end - end - } - } ) - return set -end -local _sleeping={ - times={}, - cos={}, - lethargy={}, - insert=function() - end, - remove=function() - end, - push=function(self,sleeptime,co) - if not co then - return - end - if sleeptime<0 then - self.lethargy[co]=true - return - else - sleeptime=gettime()+sleeptime - end - local t=self.times - local c=self.cos - local i=1 - local n=#t - while i<=n and t[i]<=sleeptime do - i=i+1 - end - insert(t,i,sleeptime) - insert(c,i,co) - end, - getnext= - function(self) - local t=self.times - local delay=t[1] and t[1]-gettime() or nil - return delay and max(delay,0) or nil - end, - pop= - function(self,time) - local t=self.times - local c=self.cos - if #t==0 or time<t[1] then - return - end - local co=c[1] - remove(t,1) - remove(c,1) - return co - end, - wakeup=function(self,co) - local let=self.lethargy - if let[co] then - self:push(0,co) - let[co]=nil - else - local c=self.cos - local t=self.times - for i=1,#c do - if c[i]==co then - remove(c,i) - remove(t,i) - self:push(0,co) - return - end - end - end - end -} -local _servers=newset() -local _reading=newset() -local _writing=newset() -local _reading_log={} -local _writing_log={} -local _is_timeout={ - timeout=true, - wantread=true, - wantwrite=true, -} -local function isTCP(socket) - return not find(tostring(socket),"^udp") -end -local function copasreceive(client,pattern,part) - if not pattern or pattern=="" then - pattern="*l" - end - local current_log=_reading_log - local s,err - repeat - s,err,part=client:receive(pattern,part) - if s or (not _is_timeout[err]) then - current_log[client]=nil - return s,err,part - end - if err=="wantwrite" then - current_log=_writing_log - current_log[client]=gettime() - yieldcoroutine(client,_writing) - else - current_log=_reading_log - current_log[client]=gettime() - yieldcoroutine(client,_reading) - end - until false -end -local function copasreceivefrom(client,size) - local s,err,port - if not size or size==0 then - size=UDP_DATAGRAM_MAX - end - repeat - s,err,port=client:receivefrom(size) - if s or err~="timeout" then - _reading_log[client]=nil - return s,err,port - end - _reading_log[client]=gettime() - yieldcoroutine(client,_reading) - until false -end -local function copasreceivepartial(client,pattern,part) - if not pattern or pattern=="" then - pattern="*l" - end - local logger=_reading_log - local queue=_reading - local s,err - repeat - s,err,part=client:receive(pattern,part) - if s or (type(pattern)=="number" and part~="" and part) or not _is_timeout[err] then - logger[client]=nil - return s,err,part - end - if err=="wantwrite" then - logger=_writing_log - queue=_writing - else - logger=_reading_log - queue=_reading - end - logger[client]=gettime() - yieldcoroutine(client,queue) - until false -end -local function copassend(client,data,from,to) - if not from then - from=1 - end - local lastIndex=from-1 - local logger=_writing_log - local queue=_writing - local s,err - repeat - s,err,lastIndex=client:send(data,lastIndex+1,to) - if random(100)>90 then - logger[client]=gettime() - yieldcoroutine(client,queue) - end - if s or not _is_timeout[err] then - logger[client]=nil - return s,err,lastIndex - end - if err=="wantread" then - logger=_reading_log - queue=_reading - else - logger=_writing_log - queue=_writing - end - logger[client]=gettime() - yieldcoroutine(client,queue) - until false -end -local function copassendto(client,data,ip,port) - repeat - local s,err=client:sendto(data,ip,port) - if random(100)>90 then - _writing_log[client]=gettime() - yieldcoroutine(client,_writing) - end - if s or err~="timeout" then - _writing_log[client]=nil - return s,err - end - _writing_log[client]=gettime() - yieldcoroutine(client,_writing) - until false -end -local function copasconnect(skt,host,port) - skt:settimeout(0) - local ret,err,tried_more_than_once - repeat - ret,err=skt:connect (host,port) - if ret or (err~="timeout" and err~="Operation already in progress") then - if not ret and err=="already connected" and tried_more_than_once then - ret=1 - err=nil - end - _writing_log[skt]=nil - return ret,err - end - tried_more_than_once=tried_more_than_once or true - _writing_log[skt]=gettime() - yieldcoroutine(skt,_writing) - until false -end -local function copasdohandshake(skt,sslt) - if not ssl then - ssl=require("ssl") - end - if not ssl then - report("error: no ssl library") - return - end - local nskt,err=ssl.wrap(skt,sslt) - if not nskt then - report("error: %s",tostring(err)) - return - end - nskt:settimeout(0) - local queue - repeat - local success,err=nskt:dohandshake() - if success then - return nskt - elseif err=="wantwrite" then - queue=_writing - elseif err=="wantread" then - queue=_reading - else - report("error: %s",tostring(err)) - return - end - yieldcoroutine(nskt,queue) - until false -end -local function copasflush(client) -end -copas.connect=copassconnect -copas.send=copassend -copas.sendto=copassendto -copas.receive=copasreceive -copas.receivefrom=copasreceivefrom -copas.copasreceivepartial=copasreceivepartial -copas.copasreceivePartial=copasreceivepartial -copas.dohandshake=copasdohandshake -copas.flush=copasflush -local function _skt_mt_tostring(self) - return tostring(self.socket).." (copas wrapped)" -end -local _skt_mt_tcp_index={ - send=function(self,data,from,to) - return copassend (self.socket,data,from,to) - end, - receive=function (self,pattern,prefix) - if self.timeout==0 then - return copasreceivePartial(self.socket,pattern,prefix) - else - return copasreceive(self.socket,pattern,prefix) - end - end, - flush=function (self) - return copasflush(self.socket) - end, - settimeout=function (self,time) - self.timeout=time - return true - end, - connect=function(self,...) - local res,err=copasconnect(self.socket,...) - if res and self.ssl_params then - res,err=self:dohandshake() - end - return res,err - end, - close=function(self,...) - return self.socket:close(...) - end, - bind=function(self,...) - return self.socket:bind(...) - end, - getsockname=function(self,...) - return self.socket:getsockname(...) - end, - getstats=function(self,...) - return self.socket:getstats(...) - end, - setstats=function(self,...) - return self.socket:setstats(...) - end, - listen=function(self,...) - return self.socket:listen(...) - end, - accept=function(self,...) - return self.socket:accept(...) - end, - setoption=function(self,...) - return self.socket:setoption(...) - end, - getpeername=function(self,...) - return self.socket:getpeername(...) - end, - shutdown=function(self,...) - return self.socket:shutdown(...) - end, - dohandshake=function(self,sslt) - self.ssl_params=sslt or self.ssl_params - local nskt,err=copasdohandshake(self.socket,self.ssl_params) - if not nskt then - return nskt,err - end - self.socket=nskt - return self - end, -} -local _skt_mt_tcp={ - __tostring=_skt_mt_tostring, - __index=_skt_mt_tcp_index, -} -local _skt_mt_udp_index={ - sendto=function (self,...) - return copassendto(self.socket,...) - end, - receive=function (self,size) - return copasreceive(self.socket,size or UDP_DATAGRAM_MAX) - end, - receivefrom=function (self,size) - return copasreceivefrom(self.socket,size or UDP_DATAGRAM_MAX) - end, - setpeername=function(self,...) - return self.socket:getpeername(...) - end, - setsockname=function(self,...) - return self.socket:setsockname(...) - end, - close=function(self,...) - return true - end -} -local _skt_mt_udp={ - __tostring=_skt_mt_tostring, - __index=_skt_mt_udp_index, -} -for k,v in next,_skt_mt_tcp_index do - if not _skt_mt_udp_index[k] then - _skt_mt_udp_index[k]=v - end -end -local function wrap(skt,sslt) - if getmetatable(skt)==_skt_mt_tcp or getmetatable(skt)==_skt_mt_udp then - return skt - end - skt:settimeout(0) - if isTCP(skt) then - return setmetatable ({ socket=skt,ssl_params=sslt },_skt_mt_tcp) - else - return setmetatable ({ socket=skt },_skt_mt_udp) - end -end -copas.wrap=wrap -function copas.handler(handler,sslparams) - return function (skt,...) - skt=wrap(skt) - if sslparams then - skt:dohandshake(sslparams) - end - return handler(skt,...) - end -end -local _errhandlers={} -function copas.setErrorHandler(err) - local co=runningcoroutine() - if co then - _errhandlers[co]=err - end -end -local function _deferror (msg,co,skt) - report("%s (%s) (%s)",msg,tostring(co),tostring(skt)) -end -local function _doTick (co,skt,...) - if not co then - return - end - local ok,res,new_q=resumecoroutine(co,skt,...) - if ok and res and new_q then - new_q:insert(res) - new_q:push(res,co) - else - if not ok then - pcall(_errhandlers[co] or _deferror,res,co,skt) - end - if skt and copas.autoclose and isTCP(skt) then - skt:close() - end - _errhandlers[co]=nil - end -end -local function _accept(input,handler) - local client=input:accept() - if client then - client:settimeout(0) - local co=createcoroutine(handler) - _doTick (co,client) - end - return client -end -local function _tickRead(skt) - _doTick(_reading:pop(skt),skt) -end -local function _tickWrite(skt) - _doTick(_writing:pop(skt),skt) -end -local function addTCPserver(server,handler,timeout) - server:settimeout(timeout or 0) - _servers[server]=handler - _reading:insert(server) -end -local function addUDPserver(server,handler,timeout) - server:settimeout(timeout or 0) - local co=createcoroutine(handler) - _reading:insert(server) - _doTick(co,server) -end -function copas.addserver(server,handler,timeout) - if isTCP(server) then - addTCPserver(server,handler,timeout) - else - addUDPserver(server,handler,timeout) - end -end -function copas.removeserver(server,keep_open) - local s=server - local mt=getmetatable(server) - if mt==_skt_mt_tcp or mt==_skt_mt_udp then - s=server.socket - end - _servers[s]=nil - _reading:remove(s) - if keep_open then - return true - end - return server:close() -end -function copas.addthread(handler,...) - local thread=createcoroutine(function(_,...) return handler(...) end) - _doTick(thread,nil,...) - return thread -end -local _tasks={} -local function addtaskRead(task) - task.def_tick=_tickRead - _tasks[task]=true -end -local function addtaskWrite(task) - task.def_tick=_tickWrite - _tasks[task]=true -end -local function tasks() - return next,_tasks -end -local _readable_t={ - events=function(self) - local i=0 - return function () - i=i+1 - return self._evs[i] - end - end, - tick=function(self,input) - local handler=_servers[input] - if handler then - input=_accept(input,handler) - else - _reading:remove(input) - self.def_tick(input) - end - end -} -addtaskRead(_readable_t) -local _writable_t={ - events=function(self) - local i=0 - return function() - i=i+1 - return self._evs[i] - end - end, - tick=function(self,output) - _writing:remove(output) - self.def_tick(output) - end -} -addtaskWrite(_writable_t) -local _sleeping_t={ - tick=function(self,time,...) - _doTick(_sleeping:pop(time),...) - end -} -function copas.sleep(sleeptime) - yieldcoroutine((sleeptime or 0),_sleeping) -end -function copas.wakeup(co) - _sleeping:wakeup(co) -end -local last_cleansing=0 -local function _select(timeout) - local now=gettime() - local r_evs,w_evs,err=selectsocket(_reading,_writing,timeout) - _readable_t._evs=r_evs - _writable_t._evs=w_evs - if (last_cleansing-now)>WATCH_DOG_TIMEOUT then - last_cleansing=now - for skt,time in next,_reading_log do - if not r_evs[skt] and (time-now)>WATCH_DOG_TIMEOUT then - local n=#r_evs+1 - _reading_log[skt]=nil - r_evs[n]=skt - r_evs[skt]=n - end - end - for skt,time in next,_writing_log do - if not w_evs[skt] and (time-now)>WATCH_DOG_TIMEOUT then - local n=#w_evs+1 - _writing_log[skt]=nil - w_evs[n]=skt - w_evs[skt]=n - end - end - end - if err=="timeout" and #r_evs+#w_evs>0 then - return nil - else - return err - end -end -local function copasfinished() - return not (next(_reading) or next(_writing) or _sleeping:getnext()) -end -local function copasstep(timeout) - _sleeping_t:tick(gettime()) - local nextwait=_sleeping:getnext() - if nextwait then - timeout=timeout and min(nextwait,timeout) or nextwait - elseif copasfinished() then - return false - end - local err=_select(timeout) - if err then - if err=="timeout" then - return false - end - return nil,err - end - for task in tasks() do - for event in task:events() do - task:tick(event) - end - end - return true -end -copas.finished=copasfinished -copas.step=copasstep -function copas.loop(timeout) - copas.running=true - while not copasfinished() do - copasstep(timeout) - end - copas.running=false -end -package.loaded["copas"]=copas - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-soc-imp-ltn12"] = package.loaded["util-soc-imp-ltn12"] or true - --- original size: 8709, stripped down to: 5411 - - -local select,unpack=select,unpack -local insert,remove=table.insert,table.remove -local sub=string.sub -local function report(fmt,first,...) - if logs then - report=logs and logs.reporter("ltn12") - report(fmt,first,...) - elseif fmt then - fmt="ltn12: "..fmt - if first then - print(format(fmt,first,...)) - else - print(fmt) - end - end -end -local filter={} -local source={} -local sink={} -local pump={} -local ltn12={ - _VERSION="LTN12 1.0.3", - BLOCKSIZE=2048, - filter=filter, - source=source, - sink=sink, - pump=pump, - report=report, -} -function filter.cycle(low,ctx,extra) - if low then - return function(chunk) - return (low(ctx,chunk,extra)) - end - end -end -function filter.chain(...) - local arg={... } - local n=select('#',...) - local top=1 - local index=1 - local retry="" - return function(chunk) - retry=chunk and retry - while true do - local action=arg[index] - if index==top then - chunk=action(chunk) - if chunk=="" or top==n then - return chunk - elseif chunk then - index=index+1 - else - top=top+1 - index=top - end - else - chunk=action(chunk or "") - if chunk=="" then - index=index-1 - chunk=retry - elseif chunk then - if index==n then - return chunk - else - index=index+1 - end - else - report("error: filter returned inappropriate 'nil'") - return - end - end - end - end -end -local function empty() - return nil -end -function source.empty() - return empty -end -local function sourceerror(err) - return function() - return nil,err - end -end -source.error=sourceerror -function source.file(handle,io_err) - if handle then - local blocksize=ltn12.BLOCKSIZE - return function() - local chunk=handle:read(blocksize) - if not chunk then - handle:close() - end - return chunk - end - else - return sourceerror(io_err or "unable to open file") - end -end -function source.simplify(src) - return function() - local chunk,err_or_new=src() - if err_or_new then - src=err_or_new - end - if chunk then - return chunk - else - return nil,err_or_new - end - end -end -function source.string(s) - if s then - local blocksize=ltn12.BLOCKSIZE - local i=1 - return function() - local nexti=i+blocksize - local chunk=sub(s,i,nexti-1) - i=nexti - if chunk~="" then - return chunk - else - return nil - end - end - else return source.empty() end -end -function source.rewind(src) - local t={} - return function(chunk) - if chunk then - insert(t,chunk) - else - chunk=remove(t) - if chunk then - return chunk - else - return src() - end - end - end -end -function source.chain(src,f,...) - if... then - f=filter.chain(f,...) - end - local last_in="" - local last_out="" - local state="feeding" - local err - return function() - if not last_out then - report("error: source is empty") - return - end - while true do - if state=="feeding" then - last_in,err=src() - if err then - return nil,err - end - last_out=f(last_in) - if not last_out then - if last_in then - report("error: filter returned inappropriate 'nil'") - end - return nil - elseif last_out~="" then - state="eating" - if last_in then - last_in="" - end - return last_out - end - else - last_out=f(last_in) - if last_out=="" then - if last_in=="" then - state="feeding" - else - report("error: filter returned nothing") - return - end - elseif not last_out then - if last_in then - report("filter returned inappropriate 'nil'") - end - return nil - else - return last_out - end - end - end - end -end -function source.cat(...) - local arg={... } - local src=remove(arg,1) - return function() - while src do - local chunk,err=src() - if chunk then - return chunk - end - if err then - return nil,err - end - src=remove(arg,1) - end - end -end -function sink.table(t) - if not t then - t={} - end - local f=function(chunk,err) - if chunk then - insert(t,chunk) - end - return 1 - end - return f,t -end -function sink.simplify(snk) - return function(chunk,err) - local ret,err_or_new=snk(chunk,err) - if not ret then - return nil,err_or_new - end - if err_or_new then - snk=err_or_new - end - return 1 - end -end -local function null() - return 1 -end -function sink.null() - return null -end -local function sinkerror(err) - return function() - return nil,err - end -end -sink.error=sinkerror -function sink.file(handle,io_err) - if handle then - return function(chunk,err) - if not chunk then - handle:close() - return 1 - else - return handle:write(chunk) - end - end - else - return sinkerror(io_err or "unable to open file") - end -end -function sink.chain(f,snk,...) - if... then - local args={ f,snk,... } - snk=remove(args,#args) - f=filter.chain(unpack(args)) - end - return function(chunk,err) - if chunk~="" then - local filtered=f(chunk) - local done=chunk and "" - while true do - local ret,snkerr=snk(filtered,err) - if not ret then - return nil,snkerr - end - if filtered==done then - return 1 - end - filtered=f(done) - end - else - return 1 - end - end -end -function pump.step(src,snk) - local chunk,src_err=src() - local ret,snk_err=snk(chunk,src_err) - if chunk and ret then - return 1 - else - return nil,src_err or snk_err - end -end -function pump.all(src,snk,step) - if not step then - step=pump.step - end - while true do - local ret,err=step(src,snk) - if not ret then - if err then - return nil,err - else - return 1 - end - end - end -end -package.loaded["ltn12"]=ltn12 - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-soc-imp-mime"] = package.loaded["util-soc-imp-mime"] or true - --- original size: 2373, stripped down to: 1931 - - -local type,tostring=type,tostring -local mime=mime or package.loaded.mime or require("mime.core") -local ltn12=ltn12 or package.loaded.ltn12 or require("ltn12") -local filtercycle=ltn12.filter.cycle -local function report(fmt,first,...) - if logs then - report=logs and logs.reporter("mime") - report(fmt,first,...) - elseif fmt then - fmt="mime: "..fmt - if first then - print(format(fmt,first,...)) - else - print(fmt) - end - end -end -mime.report=report -local encodet={} -local decodet={} -local wrapt={} -mime.encodet=encodet -mime.decodet=decodet -mime.wrapt=wrapt -local mime_b64=mime.b64 -local mime_qp=mime.qp -local mime_unb64=mime.unb64 -local mime_unqp=mime.unqp -local mime_wrp=mime.wrp -local mime_qpwrp=mime.qpwrp -local mime_eol=mime_eol -local mime_dot=mime_dot -encodet['base64']=function() - return filtercycle(mime_b64,"") -end -encodet['quoted-printable']=function(mode) - return filtercycle(mime_qp,"",mode=="binary" and "=0D=0A" or "\r\n") -end -decodet['base64']=function() - return filtercycle(mime_unb64,"") -end -decodet['quoted-printable']=function() - return filtercycle(mime_unqp,"") -end -local wraptext=function(length) - if not length then - length=76 - end - return filtercycle(mime_wrp,length,length) -end -local wrapquoted=function() - return filtercycle(mime_qpwrp,76,76) -end -wrapt['text']=wraptext -wrapt['base64']=wraptext -wrapt['default']=wraptext -wrapt['quoted-printable']=wrapquoted -function mime.normalize(marker) - return filtercycle(mime_eol,0,marker) -end -function mime.stuff() - return filtercycle(mime_dot,2) -end -local function choose(list) - return function(name,opt1,opt2) - if type(name)~="string" then - name,opt1,opt2="default",name,opt1 - end - local filter=list[name or "nil"] - if filter then - return filter(opt1,opt2) - else - report("error: unknown key '%s'",tostring(name)) - end - end -end -mime.encode=choose(encodet) -mime.decode=choose(decodet) -mime.wrap=choose(wrapt) -package.loaded["mime"]=mime - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-soc-imp-url"] = package.loaded["util-soc-imp-url"] or true - --- original size: 6863, stripped down to: 5269 - - -local tonumber,tostring,type=tonumber,tostring,type -local gsub,sub,match,find,format,byte,char=string.gsub,string.sub,string.match,string.find,string.format,string.byte,string.char -local insert=table.insert -local socket=socket or require("socket") -local url={ - _VERSION="URL 1.0.3", -} -socket.url=url -function url.escape(s) - return (gsub(s,"([^A-Za-z0-9_])",function(c) - return format("%%%02x",byte(c)) - end)) -end -local function make_set(t) - local s={} - for i=1,#t do - s[t[i]]=true - end - return s -end -local segment_set=make_set { - "-","_",".","!","~","*","'","(", - ")",":","@","&","=","+","$",",", -} -local function protect_segment(s) - return gsub(s,"([^A-Za-z0-9_])",function(c) - if segment_set[c] then - return c - else - return format("%%%02X",byte(c)) - end - end) -end -function url.unescape(s) - return (gsub(s,"%%(%x%x)",function(hex) - return char(tonumber(hex,16)) - end)) -end -local function absolute_path(base_path,relative_path) - if find(relative_path,"^/") then - return relative_path - end - local path=gsub(base_path,"[^/]*$","") - path=path..relative_path - path=gsub(path,"([^/]*%./)",function (s) - if s~="./" then - return s - else - return "" - end - end) - path=gsub(path,"/%.$","/") - local reduced - while reduced~=path do - reduced=path - path=gsub(reduced,"([^/]*/%.%./)",function (s) - if s~="../../" then - return "" - else - return s - end - end) - end - path=gsub(reduced,"([^/]*/%.%.)$",function (s) - if s~="../.." then - return "" - else - return s - end - end) - return path -end -function url.parse(url,default) - local parsed={} - for k,v in next,default or parsed do - parsed[k]=v - end - if not url or url=="" then - return nil,"invalid url" - end - url=gsub(url,"#(.*)$",function(f) - parsed.fragment=f - return "" - end) - url=gsub(url,"^([%w][%w%+%-%.]*)%:",function(s) - parsed.scheme=s - return "" - end) - url=gsub(url,"^//([^/]*)",function(n) - parsed.authority=n - return "" - end) - url=gsub(url,"%?(.*)",function(q) - parsed.query=q - return "" - end) - url=gsub(url,"%;(.*)",function(p) - parsed.params=p - return "" - end) - if url~="" then - parsed.path=url - end - local authority=parsed.authority - if not authority then - return parsed - end - authority=gsub(authority,"^([^@]*)@",function(u) - parsed.userinfo=u - return "" - end) - authority=gsub(authority,":([^:%]]*)$",function(p) - parsed.port=p - return "" - end) - if authority~="" then - parsed.host=match(authority,"^%[(.+)%]$") or authority - end - local userinfo=parsed.userinfo - if not userinfo then - return parsed - end - userinfo=gsub(userinfo,":([^:]*)$",function(p) - parsed.password=p - return "" - end) - parsed.user=userinfo - return parsed -end -function url.build(parsed) - local url=parsed.path or "" - if parsed.params then - url=url..";"..parsed.params - end - if parsed.query then - url=url.."?"..parsed.query - end - local authority=parsed.authority - if parsed.host then - authority=parsed.host - if find(authority,":") then - authority="["..authority.."]" - end - if parsed.port then - authority=authority..":"..tostring(parsed.port) - end - local userinfo=parsed.userinfo - if parsed.user then - userinfo=parsed.user - if parsed.password then - userinfo=userinfo..":"..parsed.password - end - end - if userinfo then authority=userinfo.."@"..authority end - end - if authority then - url="//"..authority..url - end - if parsed.scheme then - url=parsed.scheme..":"..url - end - if parsed.fragment then - url=url.."#"..parsed.fragment - end - return url -end -function url.absolute(base_url,relative_url) - local base_parsed - if type(base_url)=="table" then - base_parsed=base_url - base_url=url.build(base_parsed) - else - base_parsed=url.parse(base_url) - end - local relative_parsed=url.parse(relative_url) - if not base_parsed then - return relative_url - elseif not relative_parsed then - return base_url - elseif relative_parsed.scheme then - return relative_url - else - relative_parsed.scheme=base_parsed.scheme - if not relative_parsed.authority then - relative_parsed.authority=base_parsed.authority - if not relative_parsed.path then - relative_parsed.path=base_parsed.path - if not relative_parsed.params then - relative_parsed.params=base_parsed.params - if not relative_parsed.query then - relative_parsed.query=base_parsed.query - end - end - else - relative_parsed.path=absolute_path(base_parsed.path or "",relative_parsed.path) - end - end - return url.build(relative_parsed) - end -end -function url.parse_path(path) - local parsed={} - path=path or "" - gsub(path,"([^/]+)",function (s) - insert(parsed,s) - end) - for i=1,#parsed do - parsed[i]=url.unescape(parsed[i]) - end - if sub(path,1,1)=="/" then - parsed.is_absolute=1 - end - if sub(path,-1,-1)=="/" then - parsed.is_directory=1 - end - return parsed -end -function url.build_path(parsed,unsafe) - local path="" - local n=#parsed - if unsafe then - for i=1,n-1 do - path=path..parsed[i].."/" - end - if n>0 then - path=path..parsed[n] - if parsed.is_directory then - path=path.."/" - end - end - else - for i=1,n-1 do - path=path..protect_segment(parsed[i]).."/" - end - if n>0 then - path=path..protect_segment(parsed[n]) - if parsed.is_directory then - path=path.."/" - end - end - end - if parsed.is_absolute then - path="/"..path - end - return path -end -package.loaded["socket.url"]=url - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-soc-imp-headers"] = package.loaded["util-soc-imp-headers"] or true - --- original size: 5721, stripped down to: 3754 - - -local next=next -local lower=string.lower -local concat=table.concat -local socket=socket or require("socket") -local headers={} -socket.headers=headers -local canonic={ - ["accept"]="Accept", - ["accept-charset"]="Accept-Charset", - ["accept-encoding"]="Accept-Encoding", - ["accept-language"]="Accept-Language", - ["accept-ranges"]="Accept-Ranges", - ["action"]="Action", - ["alternate-recipient"]="Alternate-Recipient", - ["age"]="Age", - ["allow"]="Allow", - ["arrival-date"]="Arrival-Date", - ["authorization"]="Authorization", - ["bcc"]="Bcc", - ["cache-control"]="Cache-Control", - ["cc"]="Cc", - ["comments"]="Comments", - ["connection"]="Connection", - ["content-description"]="Content-Description", - ["content-disposition"]="Content-Disposition", - ["content-encoding"]="Content-Encoding", - ["content-id"]="Content-ID", - ["content-language"]="Content-Language", - ["content-length"]="Content-Length", - ["content-location"]="Content-Location", - ["content-md5"]="Content-MD5", - ["content-range"]="Content-Range", - ["content-transfer-encoding"]="Content-Transfer-Encoding", - ["content-type"]="Content-Type", - ["cookie"]="Cookie", - ["date"]="Date", - ["diagnostic-code"]="Diagnostic-Code", - ["dsn-gateway"]="DSN-Gateway", - ["etag"]="ETag", - ["expect"]="Expect", - ["expires"]="Expires", - ["final-log-id"]="Final-Log-ID", - ["final-recipient"]="Final-Recipient", - ["from"]="From", - ["host"]="Host", - ["if-match"]="If-Match", - ["if-modified-since"]="If-Modified-Since", - ["if-none-match"]="If-None-Match", - ["if-range"]="If-Range", - ["if-unmodified-since"]="If-Unmodified-Since", - ["in-reply-to"]="In-Reply-To", - ["keywords"]="Keywords", - ["last-attempt-date"]="Last-Attempt-Date", - ["last-modified"]="Last-Modified", - ["location"]="Location", - ["max-forwards"]="Max-Forwards", - ["message-id"]="Message-ID", - ["mime-version"]="MIME-Version", - ["original-envelope-id"]="Original-Envelope-ID", - ["original-recipient"]="Original-Recipient", - ["pragma"]="Pragma", - ["proxy-authenticate"]="Proxy-Authenticate", - ["proxy-authorization"]="Proxy-Authorization", - ["range"]="Range", - ["received"]="Received", - ["received-from-mta"]="Received-From-MTA", - ["references"]="References", - ["referer"]="Referer", - ["remote-mta"]="Remote-MTA", - ["reply-to"]="Reply-To", - ["reporting-mta"]="Reporting-MTA", - ["resent-bcc"]="Resent-Bcc", - ["resent-cc"]="Resent-Cc", - ["resent-date"]="Resent-Date", - ["resent-from"]="Resent-From", - ["resent-message-id"]="Resent-Message-ID", - ["resent-reply-to"]="Resent-Reply-To", - ["resent-sender"]="Resent-Sender", - ["resent-to"]="Resent-To", - ["retry-after"]="Retry-After", - ["return-path"]="Return-Path", - ["sender"]="Sender", - ["server"]="Server", - ["smtp-remote-recipient"]="SMTP-Remote-Recipient", - ["status"]="Status", - ["subject"]="Subject", - ["te"]="TE", - ["to"]="To", - ["trailer"]="Trailer", - ["transfer-encoding"]="Transfer-Encoding", - ["upgrade"]="Upgrade", - ["user-agent"]="User-Agent", - ["vary"]="Vary", - ["via"]="Via", - ["warning"]="Warning", - ["will-retry-until"]="Will-Retry-Until", - ["www-authenticate"]="WWW-Authenticate", - ["x-mailer"]="X-Mailer", -} -headers.canonic=setmetatable(canonic,{ - __index=function(t,k) - socket.report("invalid header: %s",k) - t[k]=k - return k - end -}) -function headers.normalize(headers) - if not headers then - return {} - end - local normalized={} - for k,v in next,headers do - normalized[#normalized+1]=canonic[k]..": "..v - end - normalized[#normalized+1]="" - normalized[#normalized+1]="" - return concat(normalized,"\r\n") -end -function headers.lower(lowered,headers) - if not lowered then - return {} - end - if not headers then - lowered,headers={},lowered - end - for k,v in next,headers do - lowered[lower(k)]=v - end - return lowered -end -socket.headers=headers -package.loaded["socket.headers"]=headers - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-soc-imp-tp"] = package.loaded["util-soc-imp-tp"] or true - --- original size: 3116, stripped down to: 2533 - - -local setmetatable,next,type,tonumber=setmetatable,next,type,tonumber -local find,upper=string.find,string.upper -local socket=socket or require("socket") -local ltn12=ltn12 or require("ltn12") -local skipsocket=socket.skip -local sinksocket=socket.sink -local tcpsocket=socket.tcp -local ltn12pump=ltn12.pump -local pumpall=ltn12pump.all -local pumpstep=ltn12pump.step -local tp={ - TIMEOUT=60, -} -socket.tp=tp -local function get_reply(c) - local line,err=c:receive() - local reply=line - if err then return - nil,err - end - local code,sep=skipsocket(2,find(line,"^(%d%d%d)(.?)")) - if not code then - return nil,"invalid server reply" - end - if sep=="-" then - local current - repeat - line,err=c:receive() - if err then - return nil,err - end - current,sep=skipsocket(2,find(line,"^(%d%d%d)(.?)")) - reply=reply.."\n"..line - until code==current and sep==" " - end - return code,reply -end -local methods={} -local mt={ __index=methods } -function methods.getpeername(self) - return self.c:getpeername() -end -function methods.getsockname(self) - return self.c:getpeername() -end -function methods.check(self,ok) - local code,reply=get_reply(self.c) - if not code then - return nil,reply - end - local c=tonumber(code) - local t=type(ok) - if t=="function" then - return ok(c,reply) - elseif t=="table" then - for i=1,#ok do - if find(code,ok[i]) then - return c,reply - end - end - return nil,reply - elseif find(code,ok) then - return c,reply - else - return nil,reply - end -end -function methods.command(self,cmd,arg) - cmd=upper(cmd) - if arg then - cmd=cmd.." "..arg.."\r\n" - else - cmd=cmd.."\r\n" - end - return self.c:send(cmd) -end -function methods.sink(self,snk,pat) - local chunk,err=self.c:receive(pat) - return snk(chunk,err) -end -function methods.send(self,data) - return self.c:send(data) -end -function methods.receive(self,pat) - return self.c:receive(pat) -end -function methods.getfd(self) - return self.c:getfd() -end -function methods.dirty(self) - return self.c:dirty() -end -function methods.getcontrol(self) - return self.c -end -function methods.source(self,source,step) - local sink=sinksocket("keep-open",self.c) - local ret,err=pumpall(source,sink,step or pumpstep) - return ret,err -end -function methods.close(self) - self.c:close() - return 1 -end -function tp.connect(host,port,timeout,create) - local c,e=(create or tcpsocket)() - if not c then - return nil,e - end - c:settimeout(timeout or tp.TIMEOUT) - local r,e=c:connect(host,port) - if not r then - c:close() - return nil,e - end - return setmetatable({ c=c },mt) -end -package.loaded["socket.tp"]=tp - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-soc-imp-http"] = package.loaded["util-soc-imp-http"] or true - --- original size: 12624, stripped down to: 9598 - - -local tostring,tonumber,setmetatable,next,type=tostring,tonumber,setmetatable,next,type -local find,lower,format,gsub,match=string.find,string.lower,string.format,string.gsub,string.match -local concat=table.concat -local socket=socket or require("socket") -local url=socket.url or require("socket.url") -local ltn12=ltn12 or require("ltn12") -local mime=mime or require("mime") -local headers=socket.headers or require("socket.headers") -local normalizeheaders=headers.normalize -local parseurl=url.parse -local buildurl=url.build -local absoluteurl=url.absolute -local unescapeurl=url.unescape -local skipsocket=socket.skip -local sinksocket=socket.sink -local sourcesocket=socket.source -local trysocket=socket.try -local tcpsocket=socket.tcp -local newtrysocket=socket.newtry -local protectsocket=socket.protect -local emptysource=ltn12.source.empty -local stringsource=ltn12.source.string -local rewindsource=ltn12.source.rewind -local pumpstep=ltn12.pump.step -local pumpall=ltn12.pump.all -local sinknull=ltn12.sink.null -local sinktable=ltn12.sink.table -local lowerheaders=headers.lower -local mimeb64=mime.b64 -local http={ - TIMEOUT=60, - USERAGENT=socket._VERSION, -} -socket.http=http -local PORT=80 -local SCHEMES={ - http=true, -} -local function receiveheaders(sock,headers) - if not headers then - headers={} - end - local line,err=sock:receive("*l") - if err then - return nil,err - end - while line~="" do - local name,value=skipsocket(2,find(line,"^(.-):%s*(.*)")) - if not (name and value) then - return nil,"malformed reponse headers" - end - name=lower(name) - line,err=sock:receive("*l") - if err then - return nil,err - end - while find(line,"^%s") do - value=value..line - line=sock:receive("*l") - if err then - return nil,err - end - end - local found=headers[name] - if found then - value=found..", "..value - end - headers[name]=value - end - return headers -end -socket.sourcet["http-chunked"]=function(sock,headers) - return setmetatable ( - { - getfd=function() return sock:getfd() end, - dirty=function() return sock:dirty() end, - },{ - __call=function() - local line,err=sock:receive("*l") - if err then - return nil,err - end - local size=tonumber(gsub(line,";.*",""),16) - if not size then - return nil,"invalid chunk size" - end - if size>0 then - local chunk,err,part=sock:receive(size) - if chunk then - sock:receive("*a") - end - return chunk,err - else - headers,err=receiveheaders(sock,headers) - if not headers then - return nil,err - end - end - end - } - ) -end -socket.sinkt["http-chunked"]=function(sock) - return setmetatable( - { - getfd=function() return sock:getfd() end, - dirty=function() return sock:dirty() end, - }, - { - __call=function(self,chunk,err) - if not chunk then - chunk="" - end - return sock:send(format("%X\r\n%s\r\n",#chunk,chunk)) - end - }) -end -local methods={} -local mt={ __index=methods } -local function openhttp(host,port,create) - local c=trysocket((create or tcpsocket)()) - local h=setmetatable({ c=c },mt) - local try=newtrysocket(function() h:close() end) - h.try=try - try(c:settimeout(http.TIMEOUT)) - try(c:connect(host,port or PORT)) - return h -end -http.open=openhttp -function methods.sendrequestline(self,method,uri) - local requestline=format("%s %s HTTP/1.1\r\n",method or "GET",uri) - return self.try(self.c:send(requestline)) -end -function methods.sendheaders(self,headers) - self.try(self.c:send(normalizeheaders(headers))) - return 1 -end -function methods.sendbody(self,headers,source,step) - if not source then - source=emptysource() - end - if not step then - step=pumpstep - end - local mode="http-chunked" - if headers["content-length"] then - mode="keep-open" - end - return self.try(pumpall(source,sinksocket(mode,self.c),step)) -end -function methods.receivestatusline(self) - local try=self.try - local status=try(self.c:receive(5)) - if status~="HTTP/" then - return nil,status - end - status=try(self.c:receive("*l",status)) - local code=skipsocket(2,find(status,"HTTP/%d*%.%d* (%d%d%d)")) - return try(tonumber(code),status) -end -function methods.receiveheaders(self) - return self.try(receiveheaders(self.c)) -end -function methods.receivebody(self,headers,sink,step) - if not sink then - sink=sinknull() - end - if not step then - step=pumpstep - end - local length=tonumber(headers["content-length"]) - local encoding=headers["transfer-encoding"] - local mode="default" - if encoding and encoding~="identity" then - mode="http-chunked" - elseif length then - mode="by-length" - end - return self.try(pumpall(sourcesocket(mode,self.c,length),sink,step)) -end -function methods.receive09body(self,status,sink,step) - local source=rewindsource(sourcesocket("until-closed",self.c)) - source(status) - return self.try(pumpall(source,sink,step)) -end -function methods.close(self) - return self.c:close() -end -local function adjusturi(request) - if not request.proxy and not http.PROXY then - request={ - path=trysocket(request.path,"invalid path 'nil'"), - params=request.params, - query=request.query, - fragment=request.fragment, - } - end - return buildurl(request) -end -local function adjustheaders(request) - local headers={ - ["user-agent"]=http.USERAGENT, - ["host"]=gsub(request.authority,"^.-@",""), - ["connection"]="close, TE", - ["te"]="trailers" - } - local username=request.user - local password=request.password - if username and password then - headers["authorization"]="Basic "..(mimeb64(username..":"..unescapeurl(password))) - end - local proxy=request.proxy or http.PROXY - if proxy then - proxy=parseurl(proxy) - local username=proxy.user - local password=proxy.password - if username and password then - headers["proxy-authorization"]="Basic "..(mimeb64(username..":"..password)) - end - end - local requestheaders=request.headers - if requestheaders then - headers=lowerheaders(headers,requestheaders) - end - return headers -end -local default={ - host="", - port=PORT, - path="/", - scheme="http" -} -local function adjustrequest(originalrequest) - local url=originalrequest.url - local request=url and parseurl(url,default) or {} - for k,v in next,originalrequest do - request[k]=v - end - local host=request.host - local port=request.port - local uri=request.uri - if not host or host=="" then - trysocket(nil,"invalid host '"..tostring(host).."'") - end - if port=="" then - request.port=PORT - end - if not uri or uri=="" then - request.uri=adjusturi(request) - end - request.headers=adjustheaders(request) - local proxy=request.proxy or http.PROXY - if proxy then - proxy=parseurl(proxy) - request.host=proxy.host - request.port=proxy.port or 3128 - end - return request -end -local maxredericts=4 -local validredirects={ [301]=true,[302]=true,[303]=true,[307]=true } -local validmethods={ [false]=true,GET=true,HEAD=true } -local function shouldredirect(request,code,headers) - local location=headers.location - if not location then - return false - end - location=gsub(location,"%s","") - if location=="" then - return false - end - local scheme=match(location,"^([%w][%w%+%-%.]*)%:") - if scheme and not SCHEMES[scheme] then - return false - end - local method=request.method - local redirect=request.redirect - local redirects=request.nredirects or 0 - return redirect and validredirects[code] and validmethods[method] and redirects<=maxredericts -end -local function shouldreceivebody(request,code) - if request.method=="HEAD" then - return nil - end - if code==204 or code==304 then - return nil - end - if code>=100 and code<200 then - return nil - end - return 1 -end -local tredirect,trequest,srequest -tredirect=function(request,location) - local result,code,headers,status=trequest { - url=absoluteurl(request.url,location), - source=request.source, - sink=request.sink, - headers=request.headers, - proxy=request.proxy, - nredirects=(request.nredirects or 0)+1, - create=request.create, - } - if not headers then - headers={} - end - if not headers.location then - headers.location=location - end - return result,code,headers,status -end -trequest=function(originalrequest) - local request=adjustrequest(originalrequest) - local connection=openhttp(request.host,request.port,request.create) - local headers=request.headers - connection:sendrequestline(request.method,request.uri) - connection:sendheaders(headers) - if request.source then - connection:sendbody(headers,request.source,request.step) - end - local code,status=connection:receivestatusline() - if not code then - connection:receive09body(status,request.sink,request.step) - return 1,200 - end - while code==100 do - headers=connection:receiveheaders() - code,status=connection:receivestatusline() - end - headers=connection:receiveheaders() - if shouldredirect(request,code,headers) and not request.source then - connection:close() - return tredirect(originalrequest,headers.location) - end - if shouldreceivebody(request,code) then - connection:receivebody(headers,request.sink,request.step) - end - connection:close() - return 1,code,headers,status -end -local function genericform(url,body) - local buffer={} - local request={ - url=url, - sink=sinktable(buffer), - target=buffer, - } - if body then - request.source=stringsource(body) - request.method="POST" - request.headers={ - ["content-length"]=#body, - ["content-type"]="application/x-www-form-urlencoded" - } - end - return request -end -http.genericform=genericform -srequest=function(url,body) - local request=genericform(url,body) - local _,code,headers,status=trequest(request) - return concat(request.target),code,headers,status -end -http.request=protectsocket(function(request,body) - if type(request)=="string" then - return srequest(request,body) - else - return trequest(request) - end -end) -package.loaded["socket.http"]=http - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-soc-imp-ftp"] = package.loaded["util-soc-imp-ftp"] or true - --- original size: 10357, stripped down to: 8548 - - -local setmetatable,type,next=setmetatable,type,next -local find,format,gsub,match=string.find,string.format,string.gsub,string.match -local concat=table.concat -local mod=math.mod -local socket=socket or require("socket") -local url=socket.url or require("socket.url") -local tp=socket.tp or require("socket.tp") -local ltn12=ltn12 or require("ltn12") -local tcpsocket=socket.tcp -local trysocket=socket.try -local skipsocket=socket.skip -local sinksocket=socket.sink -local selectsocket=socket.select -local bindsocket=socket.bind -local newtrysocket=socket.newtry -local sourcesocket=socket.source -local protectsocket=socket.protect -local parseurl=url.parse -local unescapeurl=url.unescape -local pumpall=ltn12.pump.all -local pumpstep=ltn12.pump.step -local sourcestring=ltn12.source.string -local sinktable=ltn12.sink.table -local ftp={ - TIMEOUT=60, - USER="ftp", - PASSWORD="anonymous@anonymous.org", -} -socket.ftp=ftp -local PORT=21 -local methods={} -local mt={ __index=methods } -function ftp.open(server,port,create) - local tp=trysocket(tp.connect(server,port or PORT,ftp.TIMEOUT,create)) - local f=setmetatable({ tp=tp },metat) - f.try=newtrysocket(function() f:close() end) - return f -end -function methods.portconnect(self) - local try=self.try - local server=self.server - try(server:settimeout(ftp.TIMEOUT)) - self.data=try(server:accept()) - try(self.data:settimeout(ftp.TIMEOUT)) -end -function methods.pasvconnect(self) - local try=self.try - self.data=try(tcpsocket()) - self(self.data:settimeout(ftp.TIMEOUT)) - self(self.data:connect(self.pasvt.address,self.pasvt.port)) -end -function methods.login(self,user,password) - local try=self.try - local tp=self.tp - try(tp:command("user",user or ftp.USER)) - local code,reply=try(tp:check{"2..",331}) - if code==331 then - try(tp:command("pass",password or ftp.PASSWORD)) - try(tp:check("2..")) - end - return 1 -end -function methods.pasv(self) - local try=self.try - local tp=self.tp - try(tp:command("pasv")) - local code,reply=try(self.tp:check("2..")) - local pattern="(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)%D(%d+)" - local a,b,c,d,p1,p2=skipsocket(2,find(reply,pattern)) - try(a and b and c and d and p1 and p2,reply) - local address=format("%d.%d.%d.%d",a,b,c,d) - local port=p1*256+p2 - local server=self.server - self.pasvt={ - address=address, - port=port, - } - if server then - server:close() - self.server=nil - end - return address,port -end -function methods.epsv(self) - local try=self.try - local tp=self.tp - try(tp:command("epsv")) - local code,reply=try(tp:check("229")) - local pattern="%((.)(.-)%1(.-)%1(.-)%1%)" - local d,prt,address,port=match(reply,pattern) - try(port,"invalid epsv response") - local address=tp:getpeername() - local server=self.server - self.pasvt={ - address=address, - port=port, - } - if self.server then - server:close() - self.server=nil - end - return address,port -end -function methods.port(self,address,port) - local try=self.try - local tp=self.tp - self.pasvt=nil - if not address then - address,port=try(tp:getsockname()) - self.server=try(bindsocket(address,0)) - address,port=try(self.server:getsockname()) - try(self.server:settimeout(ftp.TIMEOUT)) - end - local pl=mod(port,256) - local ph=(port-pl)/256 - local arg=gsub(format("%s,%d,%d",address,ph,pl),"%.",",") - try(tp:command("port",arg)) - try(tp:check("2..")) - return 1 -end -function methods.eprt(self,family,address,port) - local try=self.try - local tp=self.tp - self.pasvt=nil - if not address then - address,port=try(tp:getsockname()) - self.server=try(bindsocket(address,0)) - address,port=try(self.server:getsockname()) - try(self.server:settimeout(ftp.TIMEOUT)) - end - local arg=format("|%s|%s|%d|",family,address,port) - try(tp:command("eprt",arg)) - try(tp:check("2..")) - return 1 -end -function methods.send(self,sendt) - local try=self.try - local tp=self.tp - try(self.pasvt or self.server,"need port or pasv first") - if self.pasvt then - self:pasvconnect() - end - local argument=sendt.argument or unescapeurl(gsub(sendt.path or "","^[/\\]","")) - if argument=="" then - argument=nil - end - local command=sendt.command or "stor" - try(tp:command(command,argument)) - local code,reply=try(tp:check{"2..","1.."}) - if not self.pasvt then - self:portconnect() - end - local step=sendt.step or pumpstep - local readt={ tp } - local checkstep=function(src,snk) - local readyt=selectsocket(readt,nil,0) - if readyt[tp] then - code=try(tp:check("2..")) - end - return step(src,snk) - end - local sink=sinksocket("close-when-done",self.data) - try(pumpall(sendt.source,sink,checkstep)) - if find(code,"1..") then - try(tp:check("2..")) - end - self.data:close() - local sent=skipsocket(1,self.data:getstats()) - self.data=nil - return sent -end -function methods.receive(self,recvt) - local try=self.try - local tp=self.tp - try(self.pasvt or self.server,"need port or pasv first") - if self.pasvt then self:pasvconnect() end - local argument=recvt.argument or unescapeurl(gsub(recvt.path or "","^[/\\]","")) - if argument=="" then - argument=nil - end - local command=recvt.command or "retr" - try(tp:command(command,argument)) - local code,reply=try(tp:check{"1..","2.."}) - if code>=200 and code<=299 then - recvt.sink(reply) - return 1 - end - if not self.pasvt then - self:portconnect() - end - local source=sourcesocket("until-closed",self.data) - local step=recvt.step or pumpstep - try(pumpall(source,recvt.sink,step)) - if find(code,"1..") then - try(tp:check("2..")) - end - self.data:close() - self.data=nil - return 1 -end -function methods.cwd(self,dir) - local try=self.try - local tp=self.tp - try(tp:command("cwd",dir)) - try(tp:check(250)) - return 1 -end -function methods.type(self,typ) - local try=self.try - local tp=self.tp - try(tp:command("type",typ)) - try(tp:check(200)) - return 1 -end -function methods.greet(self) - local try=self.try - local tp=self.tp - local code=try(tp:check{"1..","2.."}) - if find(code,"1..") then - try(tp:check("2..")) - end - return 1 -end -function methods.quit(self) - local try=self.try - try(self.tp:command("quit")) - try(self.tp:check("2..")) - return 1 -end -function methods.close(self) - local data=self.data - if data then - data:close() - end - local server=self.server - if server then - server:close() - end - local tp=self.tp - if tp then - tp:close() - end -end -local function override(t) - if t.url then - local u=parseurl(t.url) - for k,v in next,t do - u[k]=v - end - return u - else - return t - end -end -local function tput(putt) - putt=override(putt) - local host=putt.host - trysocket(host,"missing hostname") - local f=ftp.open(host,putt.port,putt.create) - f:greet() - f:login(putt.user,putt.password) - local typ=putt.type - if typ then - f:type(typ) - end - f:epsv() - local sent=f:send(putt) - f:quit() - f:close() - return sent -end -local default={ - path="/", - scheme="ftp", -} -local function genericform(u) - local t=trysocket(parseurl(u,default)) - trysocket(t.scheme=="ftp","wrong scheme '"..t.scheme.."'") - trysocket(t.host,"missing hostname") - local pat="^type=(.)$" - if t.params then - local typ=skipsocket(2,find(t.params,pat)) - t.type=typ - trysocket(typ=="a" or typ=="i","invalid type '"..typ.."'") - end - return t -end -ftp.genericform=genericform -local function sput(u,body) - local putt=genericform(u) - putt.source=sourcestring(body) - return tput(putt) -end -ftp.put=protectsocket(function(putt,body) - if type(putt)=="string" then - return sput(putt,body) - else - return tput(putt) - end -end) -local function tget(gett) - gett=override(gett) - local host=gett.host - trysocket(host,"missing hostname") - local f=ftp.open(host,gett.port,gett.create) - f:greet() - f:login(gett.user,gett.password) - if gett.type then - f:type(gett.type) - end - f:epsv() - f:receive(gett) - f:quit() - return f:close() -end -local function sget(u) - local gett=genericform(u) - local t={} - gett.sink=sinktable(t) - tget(gett) - return concat(t) -end -ftp.command=protectsocket(function(cmdt) - cmdt=override(cmdt) - local command=cmdt.command - local argument=cmdt.argument - local check=cmdt.check - local host=cmdt.host - trysocket(host,"missing hostname") - trysocket(command,"missing command") - local f=ftp.open(host,cmdt.port,cmdt.create) - local try=f.try - local tp=f.tp - f:greet() - f:login(cmdt.user,cmdt.password) - if type(command)=="table" then - local argument=argument or {} - for i=1,#command do - local cmd=command[i] - try(tp:command(cmd,argument[i])) - if check and check[i] then - try(tp:check(check[i])) - end - end - else - try(tp:command(command,argument)) - if check then - try(tp:check(check)) - end - end - f:quit() - return f:close() -end) -ftp.get=protectsocket(function(gett) - if type(gett)=="string" then - return sget(gett) - else - return tget(gett) - end -end) -package.loaded["socket.ftp"]=ftp - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-soc-imp-smtp"] = package.loaded["util-soc-imp-smtp"] or true - --- original size: 7018, stripped down to: 5883 - - -local type,setmetatable,next=type,setmetatable,next -local find,lower,format=string.find,string.lower,string.format -local osdate,osgetenv=os.date,os.getenv -local random=math.random -local socket=socket or require("socket") -local headers=socket.headers or require("socket.headers") -local ltn12=ltn12 or require("ltn12") -local tp=socket.tp or require("socket.tp") -local mime=mime or require("mime") -local mimeb64=mime.b64 -local mimestuff=mime.stuff -local skipsocket=socket.skip -local trysocket=socket.try -local newtrysocket=socket.newtry -local protectsocket=socket.protect -local normalizeheaders=headers.normalize -local lowerheaders=headers.lower -local createcoroutine=coroutine.create -local resumecoroutine=coroutine.resume -local yieldcoroutine=coroutine.resume -local smtp={ - TIMEOUT=60, - SERVER="localhost", - PORT=25, - DOMAIN=osgetenv("SERVER_NAME") or "localhost", - ZONE="-0000", -} -socket.smtp=smtp -local methods={} -local mt={ __index=methods } -function methods.greet(self,domain) - local try=self.try - local tp=self.tp - try(tp:check("2..")) - try(tp:command("EHLO",domain or _M.DOMAIN)) - return skipsocket(1,try(tp:check("2.."))) -end -function methods.mail(self,from) - local try=self.try - local tp=self.tp - try(tp:command("MAIL","FROM:"..from)) - return try(tp:check("2..")) -end -function methods.rcpt(self,to) - local try=self.try - local tp=self.tp - try(tp:command("RCPT","TO:"..to)) - return try(tp:check("2..")) -end -function methods.data(self,src,step) - local try=self.try - local tp=self.tp - try(tp:command("DATA")) - try(tp:check("3..")) - try(tp:source(src,step)) - try(tp:send("\r\n.\r\n")) - return try(tp:check("2..")) -end -function methods.quit(self) - local try=self.try - local tp=self.tp - try(tp:command("QUIT")) - return try(tp:check("2..")) -end -function methods.close(self) - return self.tp:close() -end -function methods.login(self,user,password) - local try=self.try - local tp=self.tp - try(tp:command("AUTH","LOGIN")) - try(tp:check("3..")) - try(tp:send(mimeb64(user).."\r\n")) - try(tp:check("3..")) - try(tp:send(mimeb64(password).."\r\n")) - return try(tp:check("2..")) -end -function methods.plain(self,user,password) - local try=self.try - local tp=self.tp - local auth="PLAIN "..mimeb64("\0"..user.."\0"..password) - try(tp:command("AUTH",auth)) - return try(tp:check("2..")) -end -function methods.auth(self,user,password,ext) - if not user or not password then - return 1 - end - local try=self.try - if find(ext,"AUTH[^\n]+LOGIN") then - return self:login(user,password) - elseif find(ext,"AUTH[^\n]+PLAIN") then - return self:plain(user,password) - else - try(nil,"authentication not supported") - end -end -function methods.send(self,mail) - self:mail(mail.from) - local receipt=mail.rcpt - if type(receipt)=="table" then - for i=1,#receipt do - self:rcpt(receipt[i]) - end - elseif receipt then - self:rcpt(receipt) - end - self:data(ltn12.source.chain(mail.source,mimestuff()),mail.step) -end -local function opensmtp(self,server,port,create) - if not server or server=="" then - server=smtp.SERVER - end - if not port or port=="" then - port=smtp.PORT - end - local s={ - tp=trysocket(tp.connect(server,port,smtp.TIMEOUT,create)), - try=newtrysocket(function() - s:close() - end), - } - setmetatable(s,mt) - return s -end -smtp.open=opensmtp -local nofboundaries=0 -local function newboundary() - nofboundaries=nofboundaries+1 - return format('%s%05d==%05u',osdate('%d%m%Y%H%M%S'),random(0,99999),nofboundaries) -end -local send_message -local function send_headers(headers) - yieldcoroutine(normalizeheaders(headers)) -end -local function send_multipart(message) - local boundary=newboundary() - local headers=lowerheaders(message.headers) - local body=message.body - local preamble=body.preamble - local epilogue=body.epilogue - local content=headers['content-type'] or 'multipart/mixed' - headers['content-type']=content..'; boundary="'..boundary..'"' - send_headers(headers) - if preamble then - yieldcoroutine(preamble) - yieldcoroutine("\r\n") - end - for i=1,#body do - yieldcoroutine("\r\n--"..boundary.."\r\n") - send_message(body[i]) - end - yieldcoroutine("\r\n--"..boundary.."--\r\n\r\n") - if epilogue then - yieldcoroutine(epilogue) - yieldcoroutine("\r\n") - end -end -local default_content_type='text/plain; charset="UTF-8"' -local function send_source(message) - local headers=lowerheaders(message.headers) - if not headers['content-type'] then - headers['content-type']=default_content_type - end - send_headers(headers) - local getchunk=message.body - while true do - local chunk,err=getchunk() - if err then - yieldcoroutine(nil,err) - elseif chunk then - yieldcoroutine(chunk) - else - break - end - end -end -local function send_string(message) - local headers=lowerheaders(message.headers) - if not headers['content-type'] then - headers['content-type']=default_content_type - end - send_headers(headers) - yieldcoroutine(message.body) -end -function send_message(message) - local body=message.body - if type(body)=="table" then - send_multipart(message) - elseif type(body)=="function" then - send_source(message) - else - send_string(message) - end -end -local function adjust_headers(message) - local headers=lowerheaders(message.headers) - if not headers["date"] then - headers["date"]=osdate("!%a, %d %b %Y %H:%M:%S ")..(message.zone or smtp.ZONE) - end - if not headers["x-mailer"] then - headers["x-mailer"]=socket._VERSION - end - headers["mime-version"]="1.0" - return headers -end -function smtp.message(message) - message.headers=adjust_headers(message) - local action=createcoroutine(function() - send_message(message) - end) - return function() - local ret,a,b=resumecoroutine(action) - if ret then - return a,b - else - return nil,a - end - end -end -smtp.send=protectsocket(function(mail) - local snd=opensmtp(smtp,mail.server,mail.port,mail.create) - local ext=snd:greet(mail.domain) - snd:auth(mail.user,mail.password,ext) - snd:send(mail) - snd:quit() - return snd:close() -end) -package.loaded["socket.smtp"]=smtp - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["trac-set"] = package.loaded["trac-set"] or true - --- original size: 14568, stripped down to: 9644 - -if not modules then modules={} end modules ['trac-set']={ - 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=type,next,tostring,tonumber -local print=print -local concat,sortedhash=table.concat,table.sortedhash -local formatters,find,lower,gsub,topattern=string.formatters,string.find,string.lower,string.gsub,string.topattern -local is_boolean=string.is_boolean -local settings_to_hash=utilities.parsers.settings_to_hash -local allocate=utilities.storage.allocate -utilities=utilities or {} -local utilities=utilities -local setters=utilities.setters or {} -utilities.setters=setters -local data={} -local trace_initialize=false -local frozen=true -local function initialize_setter(filename,name,values) - local setter=data[name] - if setter then - local data=setter.data - if data then - for key,newvalue in sortedhash(values) do - local newvalue=is_boolean(newvalue,newvalue,true) - local functions=data[key] - if functions then - local oldvalue=functions.value - if functions.frozen then - if trace_initialize then - setter.report("%s: %a is %s to %a",filename,key,"frozen",oldvalue) - end - elseif #functions>0 and not oldvalue then - if trace_initialize then - setter.report("%s: %a is %s to %a",filename,key,"set",newvalue) - end - for i=1,#functions do - functions[i](newvalue) - end - functions.value=newvalue - functions.frozen=functions.frozen or frozen - else - if trace_initialize then - setter.report("%s: %a is %s as %a",filename,key,"kept",oldvalue) - end - end - else - functions={ default=newvalue,frozen=frozen } - data[key]=functions - if trace_initialize then - setter.report("%s: %a is %s to %a",filename,key,"defaulted",newvalue) - end - end - end - return true - end - end -end -local function set(t,what,newvalue) - local data=t.data - if data and not data.frozen then - local done=t.done - if type(what)=="string" then - what=settings_to_hash(what) - end - if type(what)~="table" then - return - end - if not done then - done={} - t.done=done - end - for w,value in sortedhash(what) do - if value=="" then - value=newvalue - elseif not value then - value=false - else - value=is_boolean(value,value,true) - end - w=topattern(w,true,true) - for name,functions in sortedhash(data) do - if done[name] then - elseif find(name,w) then - done[name]=true - for i=1,#functions do - functions[i](value) - end - functions.value=value - end - end - end - end -end -local function reset(t) - local data=t.data - if data and not data.frozen then - for name,functions in sortedthash(data) do - for i=1,#functions do - functions[i](false) - end - functions.value=false - end - end -end -local function enable(t,what) - set(t,what,true) -end -local function disable(t,what) - local data=t.data - if not what or what=="" then - t.done={} - reset(t) - else - set(t,what,false) - end -end -local function register_setter(t,what,...) - local data=t.data - what=lower(what) - local functions=data[what] - if not functions then - functions={} - data[what]=functions - if trace_initialize then - t.report("defining %a",what) - end - end - local default=functions.default - for i=1,select("#",...) do - local fnc=select(i,...) - local typ=type(fnc) - if typ=="string" then - if trace_initialize then - t.report("coupling %a to %a",what,fnc) - end - local s=fnc - fnc=function(value) set(t,s,value) end - elseif typ=="table" then - functions.values=fnc - fnc=nil - elseif typ~="function" then - fnc=nil - end - if fnc then - functions[#functions+1]=fnc - local value=functions.value or default - if value~=nil then - fnc(value) - functions.value=value - end - end - end - return false -end -local function enable_setter(t,what) - local e=t.enable - t.enable,t.done=enable,{} - set(t,what,true) - enable(t,what) - t.enable,t.done=e,{} -end -local function disable_setter(t,what) - local e=t.disable - t.disable,t.done=disable,{} - disable(t,what) - t.disable,t.done=e,{} -end -local function reset_setter(t) - t.done={} - reset(t) -end -local function list_setter(t) - local list=table.sortedkeys(t.data) - local user,system={},{} - for l=1,#list do - local what=list[l] - if find(what,"^%*") then - system[#system+1]=what - else - user[#user+1]=what - end - end - return user,system -end -local function show_setter(t,pattern) - local list=list_setter(t) - t.report() - for k=1,#list do - local name=list[k] - if not pattern or find(name,pattern) then - local functions=t.data[name] - if functions then - local value=functions.value - local default=functions.default - local values=functions.values - local modules=#functions - if default==nil then - default="unset" - elseif type(default)=="table" then - default=concat(default,"|") - else - default=tostring(default) - end - if value==nil then - value="unset" - elseif type(value)=="table" then - value=concat(value,"|") - else - value=tostring(value) - end - t.report(name) - t.report(" modules : %i",modules) - t.report(" default : %s",default) - t.report(" value : %s",value) - if values then - local v={} for i=1,#values do v[i]=tostring(values[i]) end - t.report(" values : % t",v) - end - t.report() - end - end - end -end -function setters.report(setter,fmt,...) - if fmt then - print(formatters["%-15s : %s"](setter.name,formatters[fmt](...))) - else - print("") - end -end -local function setter_default(setter,name) - local d=setter.data[name] - return d and d.default -end -local function setter_value(setter,name) - local d=setter.data[name] - return d and (d.value or d.default) -end -local function setter_values(setter,name) - local d=setter.data[name] - return d and d.values -end -local function new_setter(name) - local setter - setter={ - data=allocate(), - name=name, - report=function(...) setters.report (setter,...) end, - enable=function(...) enable_setter (setter,...) end, - disable=function(...) disable_setter (setter,...) end, - reset=function(...) reset_setter (setter,...) end, - register=function(...) register_setter(setter,...) end, - list=function(...) return list_setter (setter,...) end, - show=function(...) show_setter (setter,...) end, - default=function(...) return setter_default (setter,...) end, - value=function(...) return setter_value (setter,...) end, - values=function(...) return setter_values (setter,...) end, - } - data[name]=setter - return setter -end -setters.enable=enable_setter -setters.disable=disable_setter -setters.register=register_setter -setters.list=list_setter -setters.show=show_setter -setters.reset=reset_setter -setters.new=new_setter -setters.initialize=initialize_setter -trackers=new_setter("trackers") -directives=new_setter("directives") -experiments=new_setter("experiments") -local t_enable,t_disable=trackers .enable,trackers .disable -local d_enable,d_disable=directives .enable,directives .disable -local e_enable,e_disable=experiments.enable,experiments.disable -local trace_directives=false local trace_directives=false trackers.register("system.directives",function(v) trace_directives=v end) -local trace_experiments=false local trace_experiments=false trackers.register("system.experiments",function(v) trace_experiments=v end) -function directives.enable(...) - if trace_directives then - directives.report("enabling: % t",{...}) - end - d_enable(...) -end -function directives.disable(...) - if trace_directives then - directives.report("disabling: % t",{...}) - end - d_disable(...) -end -function experiments.enable(...) - if trace_experiments then - experiments.report("enabling: % t",{...}) - end - e_enable(...) -end -function experiments.disable(...) - if trace_experiments then - experiments.report("disabling: % t",{...}) - end - e_disable(...) -end -directives.register("system.nostatistics",function(v) - if statistics then - statistics.enable=not v - else - end -end) -directives.register("system.nolibraries",function(v) - if libraries then - libraries=nil - else - end -end) -if environment then - local engineflags=environment.engineflags - if engineflags then - local list=engineflags["c:trackers"] or engineflags["trackers"] - if type(list)=="string" then - initialize_setter("commandline flags","trackers",settings_to_hash(list)) - end - local list=engineflags["c:directives"] or engineflags["directives"] - if type(list)=="string" then - initialize_setter("commandline flags","directives",settings_to_hash(list)) - end - end -end -if texconfig then - local function set(k,v) - local v=tonumber(v) - if v then - texconfig[k]=v - end - end - directives.register("luatex.expanddepth",function(v) set("expand_depth",v) end) - directives.register("luatex.hashextra",function(v) set("hash_extra",v) end) - directives.register("luatex.nestsize",function(v) set("nest_size",v) end) - directives.register("luatex.maxinopen",function(v) set("max_in_open",v) end) - directives.register("luatex.maxprintline",function(v) set("max_print_line",v) end) - directives.register("luatex.maxstrings",function(v) set("max_strings",v) end) - directives.register("luatex.paramsize",function(v) set("param_size",v) end) - directives.register("luatex.savesize",function(v) set("save_size",v) end) - directives.register("luatex.stacksize",function(v) set("stack_size",v) end) -end -local data=table.setmetatableindex("table") -updaters={ - register=function(what,f) - local d=data[what] - d[#d+1]=f - end, - apply=function(what,...) - local d=data[what] - for i=1,#d do - d[i](...) - end - end, -} - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["trac-log"] = package.loaded["trac-log"] or true - --- original size: 16017, stripped down to: 11045 - -if not modules then modules={} end modules ['trac-log']={ - version=1.001, - comment="companion to trac-log.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local next,type,select,print=next,type,select,print -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 utfchar=utf.char -local datetime=os.date -local openfile=io.open -local write_nl=print -local write=io.write -local setmetatableindex=table.setmetatableindex -local formatters=string.formatters -local settings_to_hash=utilities.parsers.settings_to_hash -local sortedkeys=table.sortedkeys -local variant="default" -logs=logs or {} -local logs=logs -local moreinfo=[[ -More information about ConTeXt and the tools that come with it can be found at: -]].."\n"..[[ -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 -]] -formatters.add ( - formatters,"unichr", - [["U+" .. format("%%05X",%s) .. " (" .. utfchar(%s) .. ")"]] -) -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,newline -local function ansisupported(specification) - if specification~="ansi" and specification~="ansilog" then - return false - elseif os and os.enableansi then - return os.enableansi() - else - return false - end -end -do - 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["[0;32m%-15s [0;1m|[0m %s"], - report_nop=formatters["[0;32m%-15s [0;1m|[0m"], - subreport_yes=formatters["[0;32m%-15s [0;1m|[0;31m %s [0;1m|[0m %s"], - subreport_nop=formatters["[0;32m%-15s [0;1m|[0;31m %s [0;1m|[0m"], - status_yes=formatters["[0;32m%-15s [0;1m:[0m %s\n"], - status_nop=formatters["[0;32m%-15s [0;1m:[0m\n"], - }, - }, - } - logs.flush=ignore - writer=function(s) - write_nl(s) - end - newline=function() - write_nl("\n") - end - report=function(a,b,c,...) - if c then - write_nl(report_yes(a,formatters[b](c,...))) - elseif b then - write_nl(report_yes(a,b)) - elseif a then - write_nl(report_nop(a)) - else - write_nl("") - end - end - subreport=function(a,sub,b,c,...) - if c then - write_nl(subreport_yes(a,sub,formatters[b](c,...))) - elseif b then - write_nl(subreport_yes(a,sub,b)) - elseif a then - write_nl(subreport_nop(a,sub)) - else - write_nl("") - end - end - status=function(a,b,c,...) - if c then - write_nl(status_yes(a,formatters[b](c,...))) - elseif b then - write_nl(status_yes(a,b)) - elseif a then - write_nl(status_nop(a)) - else - write_nl("\n") - end - end - direct=ignore - subdirect=ignore - settarget=ignore - pushtarget=ignore - poptarget=ignore - setformats=ignore - settranslations=ignore - setprocessor=function(f) - local writeline=write_nl - write_nl=function(s) - writeline(f(s)) - end - 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 - if not ansisupported(specification) then - specification="default" - end - 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 - local writeline=write_nl - if keepopen then - local f=io.open(name,"ab") - write_nl=function(s) - writeline(s) - f:write(localtime()," | ",s,"\n") - end - else - write_nl=function(s) - writeline(s) - local f=io.open(name,"ab") - f:write(localtime()," | ",s,"\n") - f:close() - end - end - end - setlogfile=ignore - end - settimedlog=function() - local localtime=os.localtime - local writeline=write_nl - write_nl=function(s) - writeline(localtime().." | "..s) - end - settimedlog=ignore - end -end -logs.report=report -logs.subreport=subreport -logs.status=status -logs.settarget=settarget -logs.pushtarget=pushtarget -logs.poptarget=poptarget -logs.setformats=setformats -logs.settranslations=settranslations -logs.setlogfile=setlogfile -logs.settimedlog=settimedlog -logs.setprocessor=setprocessor -logs.setformatters=setformatters -logs.direct=direct -logs.subdirect=subdirect -logs.writer=writer -logs.newline=newline -local data={} -local states=nil -local force=false -function logs.reporter(category,subcategory) - local logger=data[category] - if not logger then - local state=states==true - if not state and type(states)=="table" then - for c,_ in next,states do - if find(category,c) then - state=true - break - end - end - end - logger={ - reporters={}, - state=state, - } - data[category]=logger - end - local reporter=logger.reporters[subcategory or "default"] - if not reporter then - if subcategory then - reporter=function(...) - if force or not logger.state then - subreport(category,subcategory,...) - end - end - logger.reporters[subcategory]=reporter - else - local tag=category - reporter=function(...) - if force or not logger.state then - report(category,...) - end - end - logger.reporters.default=reporter - end - end - return reporter -end -logs.new=logs.reporter -local ctxreport=logs.writer -function logs.setmessenger(m) - ctxreport=m -end -function logs.messenger(category,subcategory) - if subcategory then - return function(...) - ctxreport(subdirect(category,subcategory,...)) - end - else - return function(...) - ctxreport(direct(category,...)) - end - end -end -local function setblocked(category,value) - if category==true or category=="all" then - category,value="*",true - elseif category==false then - category,value="*",false - elseif value==nil then - value=true - end - if category=="*" then - states=value - for k,v in next,data do - v.state=value - end - else - alllocked=false - states=settings_to_hash(category,type(states)=="table" and states or nil) - for c in next,states do - local v=data[c] - if v then - v.state=value - else - c=topattern(c,true,true) - for k,v in next,data do - if find(k,c) then - v.state=value - end - end - end - end - end -end -function logs.disable(category,value) - setblocked(category,value==nil and true or value) -end -function logs.enable(category) - setblocked(category,false) -end -function logs.categories() - return sortedkeys(data) -end -function logs.show() - local n,c,s,max=0,0,0,0 - for category,v in table.sortedpairs(data) do - n=n+1 - local state=v.state - local reporters=v.reporters - local nc=#category - if nc>c then - c=nc - end - for subcategory,_ in next,reporters do - local ns=#subcategory - if ns>c then - s=ns - end - local m=nc+ns - if m>max then - max=m - end - end - local subcategories=concat(sortedkeys(reporters),", ") - if state==true then - state="disabled" - elseif state==false then - state="enabled" - else - state="unknown" - end - report("logging","category %a, subcategories %a, state %a",category,subcategories,state) - end - report("logging","categories: %s, max category: %s, max subcategory: %s, max combined: %s",n,c,s,max) -end -local delayed_reporters={} -setmetatableindex(delayed_reporters,function(t,k) - local v=logs.reporter(k.name) - t[k]=v - return v -end) -function utilities.setters.report(setter,...) - delayed_reporters[setter](...) -end -directives.register("logs.blocked",function(v) - setblocked(v,true) -end) -directives.register("logs.target",function(v) - settarget(v) -end) -local nesting=0 -local verbose=false -local hasscheme=url.hasscheme -local simple=logs.reporter("comment") -logs.simple=simple -logs.simpleline=simple -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=( - Carg(1)*C((1-p_newline)^1)/function(t,s) t.report(s) end+Carg(1)*p_newline^2/function(t) t.report() end+p_newline -)^1 -local function reportlines(t,str) - if str then - lpegmatch(linewise,str,1,t) - end -end -local function reportbanner(t) - local banner=t.banner - if banner then - t.report(banner) - t.report() - end -end -local function reportversion(t) - local banner=t.banner - if banner then - t.report(banner) - end -end -local function reporthelp(t,...) - local helpinfo=t.helpinfo - if type(helpinfo)=="string" then - reportlines(t,helpinfo) - elseif type(helpinfo)=="table" then - for i=1,select("#",...) do - reportlines(t,t.helpinfo[select(i,...)]) - if i<n then - t.report() - end - end - end -end -local function reportinfo(t) - t.report() - reportlines(t,t.moreinfo) -end -local function reportexport(t,method) - report(t.helpinfo) -end -local reporters={ - lines=reportlines, - banner=reportbanner, - version=reportversion, - help=reporthelp, - info=reportinfo, - export=reportexport, -} -local exporters={ -} -logs.reporters=reporters -logs.exporters=exporters -function logs.application(t) - local arguments=environment and environment.arguments - if arguments then - local ansi=arguments.ansi or arguments.ansilog - if ansi then - logs.setformatters(arguments.ansi and "ansi" or "ansilog") - end - end - t.name=t.name or "unknown" - t.banner=t.banner - t.moreinfo=moreinfo - t.report=logs.reporter(t.name) - t.help=function(...) - reporters.banner(t) - reporters.help(t,...) - reporters.info(t) - end - t.export=function(...) - reporters.export(t,...) - end - t.identify=function() - reporters.banner(t) - end - t.version=function() - reporters.version(t) - end - return t -end -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=openfile(whereto,"a") - if f then - f:write(message) - f:close() - break - else - sleep(0.1) - end - end -end -local report_system=logs.reporter("system","logs") -if utilities then - utilities.report=report_system -end -if package.helpers.report then - package.helpers.report=logs.reporter("package loader") -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["trac-inf"] = package.loaded["trac-inf"] or true - --- original size: 9740, stripped down to: 7296 - -if not modules then modules={} end modules ['trac-inf']={ - version=1.001, - comment="companion to trac-inf.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,tonumber,select=type,tonumber,select -local format,lower,find=string.format,string.lower,string.find -local concat=table.concat -local clock=os.gettimeofday or os.clock -local setmetatableindex=table.setmetatableindex -local serialize=table.serialize -local formatters=string.formatters -statistics=statistics or {} -local statistics=statistics -statistics.enable=true -statistics.threshold=0.01 -local statusinfo,n,registered,timers={},0,{},{} -setmetatableindex(timers,function(t,k) - local v={ timing=0,loadtime=0,offset=0 } - t[k]=v - return v -end) -local function hastiming(instance) - return instance and timers[instance] -end -local function resettiming(instance) - timers[instance or "notimer"]={ timing=0,loadtime=0,offset=0 } -end -local ticks=clock -local seconds=function(n) return n or 0 end -if os.type~="windows" then -elseif lua.getpreciseticks then - ticks=lua.getpreciseticks - seconds=lua.getpreciseseconds -elseif FFISUPPORTED then - local okay,kernel=pcall(ffi.load,"kernel32") - if kernel then - local tonumber=ffi.number or tonumber - ffi.cdef[[ - int QueryPerformanceFrequency(int64_t *lpFrequency); - int QueryPerformanceCounter(int64_t *lpPerformanceCount); - ]] - local target=ffi.new("__int64[1]") - ticks=function() - if kernel.QueryPerformanceCounter(target)==1 then - return tonumber(target[0]) - else - return 0 - end - end - local target=ffi.new("__int64[1]") - seconds=function(ticks) - if kernel.QueryPerformanceFrequency(target)==1 then - return ticks/tonumber(target[0]) - else - return 0 - end - end - end -else -end -local function starttiming(instance,reset) - local timer=timers[instance or "notimer"] - local it=timer.timing - if reset then - it=0 - timer.loadtime=0 - end - if it==0 then - timer.starttime=ticks() - if not timer.loadtime then - timer.loadtime=0 - end - end - timer.timing=it+1 -end -local function stoptiming(instance) - local timer=timers[instance or "notimer"] - local it=timer.timing - if it>1 then - timer.timing=it-1 - else - local starttime=timer.starttime - if starttime and starttime>0 then - local stoptime=ticks() - local loadtime=stoptime-starttime - timer.stoptime=stoptime - timer.loadtime=timer.loadtime+loadtime - timer.timing=0 - timer.starttime=0 - end - end -end -local function benchmarktimer(instance) - local timer=timers[instance or "notimer"] - local it=timer.timing - if it>1 then - timer.timing=it-1 - else - local starttime=timer.starttime - if starttime and starttime>0 then - timer.offset=ticks()-starttime - else - timer.offset=0 - end - end -end -local function elapsed(instance) - if type(instance)=="number" then - return instance - else - local timer=timers[instance or "notimer"] - return timer and seconds(timer.loadtime-2*(timer.offset or 0)) or 0 - end -end -local function currenttime(instance) - if type(instance)=="number" then - return instance - else - local timer=timers[instance or "notimer"] - local it=timer.timing - if it>1 then - else - local starttime=timer.starttime - if starttime and starttime>0 then - return seconds(timer.loadtime+ticks()-starttime-2*(timer.offset or 0)) - end - end - return 0 - end -end -local function elapsedtime(instance) - return format("%0.3f",elapsed(instance)) -end -local function elapsedindeed(instance) - return elapsed(instance)>statistics.threshold -end -local function elapsedseconds(instance,rest) - if elapsedindeed(instance) then - return format("%0.3f seconds %s",elapsed(instance),rest or "") - end -end -statistics.hastiming=hastiming -statistics.resettiming=resettiming -statistics.starttiming=starttiming -statistics.stoptiming=stoptiming -statistics.currenttime=currenttime -statistics.elapsed=elapsed -statistics.elapsedtime=elapsedtime -statistics.elapsedindeed=elapsedindeed -statistics.elapsedseconds=elapsedseconds -statistics.benchmarktimer=benchmarktimer -function statistics.register(tag,fnc) - if statistics.enable and type(fnc)=="function" then - local rt=registered[tag] or (#statusinfo+1) - statusinfo[rt]={ tag,fnc } - registered[tag]=rt - if #tag>n then n=#tag end - end -end -local report=logs.reporter("mkiv lua stats") -function statistics.show() - if statistics.enable then - local register=statistics.register - register("used platform",function() - return format("%s, type: %s, binary subtree: %s", - os.platform or "unknown",os.type or "unknown",environment.texos or "unknown") - end) - register("used engine",function() - return format("%s version: %s, functionality level: %s, banner: %s", - LUATEXENGINE,LUATEXVERSION,LUATEXFUNCTIONALITY,lower(status.banner)) - end) - register("used hash slots",function() - return format("%s of %s + %s",status.cs_count,status.hash_size,status.hash_extra) - end) - register("callbacks",statistics.callbacks) - if JITSUPPORTED then - local jitstatus=jit.status - if jitstatus then - local jitstatus={ jitstatus() } - if jitstatus[1] then - register("luajit options",concat(jitstatus," ",2)) - end - end - end - register("lua properties",function() - local hash=2^status.luatex_hashchars - local mask=load([[τεχ = 1]]) and "utf" or "ascii" - return format("engine: %s %s, used memory: %s, hash chars: min(%i,40), symbol mask: %s (%s)", - jit and "luajit" or "lua",LUAVERSION,statistics.memused(),hash,mask,mask=="utf" and "τεχ" or "tex") - end) - register("runtime",statistics.runtime) - logs.newline() - for i=1,#statusinfo do - local s=statusinfo[i] - local r=s[2]() - if r then - report("%s: %s",s[1],r) - end - end - statistics.enable=false - end -end -function statistics.memused() - local round=math.round or math.floor - return format("%s MB, ctx: %s MB, max: %s MB", - round(collectgarbage("count")/1000), - round(status.luastate_bytes/1000000), - status.luastate_bytes_max and round(status.luastate_bytes_max/1000000) or "unknown" - ) -end -starttiming(statistics) -function statistics.formatruntime(runtime) - return format("%s seconds",runtime) -end -function statistics.runtime() - stoptiming(statistics) - local runtime=lua.getruntime and lua.getruntime() or elapsedtime(statistics) - return statistics.formatruntime(runtime) -end -local report=logs.reporter("system") -function statistics.timed(action,all) - starttiming("run") - action() - stoptiming("run") - local runtime=tonumber(elapsedtime("run")) - if all then - local alltime=tonumber(lua.getruntime and lua.getruntime() or elapsedtime(statistics)) - if alltime and alltime>0 then - report("total runtime: %0.3f seconds of %0.3f seconds",runtime,alltime) - return - end - end - report("total runtime: %0.3f seconds",runtime) -end -function statistics.tracefunction(base,tag,...) - for i=1,select("#",...) do - local name=select(i,...) - local stat={} - local func=base[name] - setmetatableindex(stat,function(t,k) t[k]=0 return 0 end) - base[name]=function(n,k,v) stat[k]=stat[k]+1 return func(n,k,v) end - statistics.register(formatters["%s.%s"](tag,name),function() return serialize(stat,"calls") end) - end -end -function status.getreadstate() - return { - filename=status.filename or "?", - linenumber=status.linenumber or 0, - iocode=status.inputid or 0, - } -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["trac-pro"] = package.loaded["trac-pro"] or true - --- original size: 5841, stripped down to: 3352 - -if not modules then modules={} end modules ['trac-pro']={ - 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 getmetatable,setmetatable,rawset,type,next=getmetatable,setmetatable,rawset,type,next -local trace_namespaces=false trackers.register("system.namespaces",function(v) trace_namespaces=v end) -local report_system=logs.reporter("system","protection") -namespaces=namespaces or {} -local namespaces=namespaces -local registered={} -local function report_index(k,name) - if trace_namespaces then - report_system("reference to %a in protected namespace %a: %s",k,name) - debugger.showtraceback(report_system) - else - report_system("reference to %a in protected namespace %a",k,name) - end -end -local function report_newindex(k,name) - if trace_namespaces then - report_system("assignment to %a in protected namespace %a: %s",k,name) - debugger.showtraceback(report_system) - else - report_system("assignment to %a in protected namespace %a",k,name) - end -end -local function register(name) - local data=name=="global" and _G or _G[name] - if not data then - return - end - registered[name]=data - local m=getmetatable(data) - if not m then - m={} - setmetatable(data,m) - end - local index,newindex={},{} - m.__saved__index=m.__index - m.__no__index=function(t,k) - if not index[k] then - index[k]=true - report_index(k,name) - end - return nil - end - m.__saved__newindex=m.__newindex - m.__no__newindex=function(t,k,v) - if not newindex[k] then - newindex[k]=true - report_newindex(k,name) - end - rawset(t,k,v) - end - m.__protection__depth=0 -end -local function private(name) - local data=registered[name] - if not data then - data=_G[name] - if not data then - data={} - _G[name]=data - end - register(name) - end - return data -end -local function protect(name) - local data=registered[name] - if not data then - return - end - local m=getmetatable(data) - local pd=m.__protection__depth - if pd>0 then - m.__protection__depth=pd+1 - else - m.__save_d_index,m.__saved__newindex=m.__index,m.__newindex - m.__index,m.__newindex=m.__no__index,m.__no__newindex - m.__protection__depth=1 - end -end -local function unprotect(name) - local data=registered[name] - if not data then - return - end - local m=getmetatable(data) - local pd=m.__protection__depth - if pd>1 then - m.__protection__depth=pd-1 - else - m.__index,m.__newindex=m.__saved__index,m.__saved__newindex - m.__protection__depth=0 - end -end -local function protectall() - for name,_ in next,registered do - if name~="global" then - protect(name) - end - end -end -local function unprotectall() - for name,_ in next,registered do - if name~="global" then - unprotect(name) - end - end -end -namespaces.register=register -namespaces.private=private -namespaces.protect=protect -namespaces.unprotect=unprotect -namespaces.protectall=protectall -namespaces.unprotectall=unprotectall -namespaces.private("namespaces") registered={} register("global") -directives.register("system.protect",function(v) - if v then - protectall() - else - unprotectall() - end -end) -directives.register("system.checkglobals",function(v) - if v then - report_system("enabling global namespace guard") - protect("global") - else - report_system("disabling global namespace guard") - unprotect("global") - end -end) - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-lua"] = package.loaded["util-lua"] or true - --- original size: 7149, stripped down to: 4997 - -if not modules then modules={} end modules ['util-lua']={ - version=1.001, - comment="companion to luat-lib.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - comment="the strip code is written by Peter Cawley", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local rep,sub,byte,dump,format=string.rep,string.sub,string.byte,string.dump,string.format -local load,loadfile,type,collectgarbage=load,loadfile,type,collectgarbage -utilities=utilities or {} -utilities.lua=utilities.lua or {} -local luautilities=utilities.lua -local report_lua=logs.reporter("system","lua") -local report_mem=logs.reporter("system","lua memory") -local tracestripping=false -local tracememory=false -luautilities.stripcode=true -luautilities.alwaysstripcode=false -luautilities.nofstrippedchunks=0 -luautilities.nofstrippedbytes=0 -local strippedchunks={} -luautilities.strippedchunks=strippedchunks -if not LUATEXENGINE then - LUATEXENGINE=status.luatex_engine and string.lower(status.luatex_engine) - JITSUPPORTED=LUATEXENGINE=="luajittex" or jit - CONTEXTLMTXMODE=CONTEXTLMTXMODE or (LUATEXENGINE=="luametatex" and 1) or 0 -end -luautilities.suffixes={ - tma="tma", - tmc=(CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 and "tmd") or (jit and "tmb") or "tmc", - lua="lua", - luc=(CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 and "lud") or (jit and "lub") or "luc", - lui="lui", - luv="luv", - luj="luj", - tua="tua", - tuc=(CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 and "tud") or (jit and "tub") or "tuc", -} -local function register(name) - if tracestripping then - report_lua("stripped bytecode from %a",name or "unknown") - end - strippedchunks[#strippedchunks+1]=name - luautilities.nofstrippedchunks=luautilities.nofstrippedchunks+1 -end -local function stupidcompile(luafile,lucfile,strip) - local code=io.loaddata(luafile) - if code and code~="" then - code=load(code) - if code then - code=dump(code,strip and luautilities.stripcode or luautilities.alwaysstripcode) - if code and code~="" then - register(name) - io.savedata(lucfile,code) - return true,0 - end - else - report_lua("fatal error %a in file %a",1,luafile) - end - else - report_lua("fatal error %a in file %a",2,luafile) - end - return false,0 -end -function luautilities.loadedluacode(fullname,forcestrip,name,macros) - name=name or fullname - if macros then - macros=lua.macros - end - local code,message - if macros then - code,message=macros.loaded(fullname,true,false) - else - code,message=loadfile(fullname) - end - if code then - code() - else - report_lua("loading of file %a failed:\n\t%s",fullname,message or "no message") - code,message=loadfile(fullname) - end - if forcestrip and luautilities.stripcode then - if type(forcestrip)=="function" then - forcestrip=forcestrip(fullname) - end - if forcestrip or luautilities.alwaysstripcode then - register(name) - return load(dump(code,true)),0 - else - return code,0 - end - elseif luautilities.alwaysstripcode then - register(name) - return load(dump(code,true)),0 - else - return code,0 - end -end -function luautilities.strippedloadstring(code,name,forcestrip) - local code,message=load(code) - if not code then - report_lua("loading of file %a failed:\n\t%s",name,message or "no message") - end - if forcestrip and luautilities.stripcode or luautilities.alwaysstripcode then - register(name) - return load(dump(code,true)),0 - else - return code,0 - end -end -function luautilities.loadstring(code,name) - local code,message=load(code) - if not code then - report_lua("loading of file %a failed:\n\t%s",name,message or "no message") - end - return code,0 -end -function luautilities.compile(luafile,lucfile,cleanup,strip,fallback) - report_lua("compiling %a into %a",luafile,lucfile) - os.remove(lucfile) - local done=stupidcompile(luafile,lucfile,strip~=false) - if done then - report_lua("dumping %a into %a stripped",luafile,lucfile) - if cleanup==true and lfs.isfile(lucfile) and lfs.isfile(luafile) then - report_lua("removing %a",luafile) - os.remove(luafile) - end - end - return done -end -function luautilities.loadstripped(...) - local l=load(...) - if l then - return load(dump(l,true)) - end -end -local finalizers={} -setmetatable(finalizers,{ - __gc=function(t) - for i=1,#t do - pcall(t[i]) - end - end -} ) -function luautilities.registerfinalizer(f) - finalizers[#finalizers+1]=f -end -function luautilities.checkmemory(previous,threshold,trace) - local current=collectgarbage("count") - if previous then - local checked=(threshold or 64)*1024 - local delta=current-previous - if current-previous>checked then - collectgarbage("collect") - local afterwards=collectgarbage("count") - if trace or tracememory then - report_mem("previous %r MB, current %r MB, delta %r MB, threshold %r MB, afterwards %r MB", - previous/1024,current/1024,delta/1024,threshold,afterwards) - end - return afterwards - elseif trace or tracememory then - report_mem("previous %r MB, current %r MB, delta %r MB, threshold %r MB", - previous/1024,current/1024,delta/1024,threshold) - end - end - return current -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-deb"] = package.loaded["util-deb"] or true - --- original size: 10593, stripped down to: 7102 - -if not modules then modules={} end modules ['util-deb']={ - 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=type,next,tostring,tonumber -local format,find,sub,gsub=string.format,string.find,string.sub,string.gsub -local insert,remove,sort=table.insert,table.remove,table.sort -local setmetatableindex=table.setmetatableindex -utilities=utilities or {} -local debugger=utilities.debugger or {} -utilities.debugger=debugger -local report=logs.reporter("debugger") -local ticks=os.gettimeofday or os.clock -local seconds=function(n) return n or 0 end -local overhead=0 -local dummycalls=10*1000 -local nesting=0 -local names={} -local initialize=false -if lua.getpreciseticks then - initialize=function() - ticks=lua.getpreciseticks - seconds=lua.getpreciseseconds - initialize=false - end -elseif not (FFISUPPORTED and ffi) then -elseif os.type=="windows" then - initialize=function() - local kernel=ffilib("kernel32","system") - if kernel then - local tonumber=ffi.number or tonumber - ffi.cdef[[ - int QueryPerformanceFrequency(int64_t *lpFrequency); - int QueryPerformanceCounter(int64_t *lpPerformanceCount); - ]] - local target=ffi.new("__int64[1]") - ticks=function() - if kernel.QueryPerformanceCounter(target)==1 then - return tonumber(target[0]) - else - return 0 - end - end - local target=ffi.new("__int64[1]") - seconds=function(ticks) - if kernel.QueryPerformanceFrequency(target)==1 then - return ticks/tonumber(target[0]) - else - return 0 - end - end - end - initialize=false - end -elseif os.type=="unix" then - initialize=function() - local C=ffi.C - local tonumber=ffi.number or tonumber - ffi.cdef [[ - /* what a mess */ - typedef int clk_id_t; - typedef enum { CLOCK_REALTIME, CLOCK_MONOTONIC, CLOCK_PROCESS_CPUTIME_ID } clk_id; - typedef struct timespec { long sec; long nsec; } ctx_timespec; - int clock_gettime(clk_id_t timerid, struct timespec *t); - ]] - local target=ffi.new("ctx_timespec[?]",1) - local clock=C.CLOCK_PROCESS_CPUTIME_ID - ticks=function () - C.clock_gettime(clock,target) - return tonumber(target[0].sec*1000000000+target[0].nsec) - end - seconds=function(ticks) - return ticks/1000000000 - end - initialize=false - end -end -setmetatableindex(names,function(t,name) - local v=setmetatableindex(function(t,source) - local v=setmetatableindex(function(t,line) - local v={ total=0,count=0,nesting=0 } - t[line]=v - return v - end) - t[source]=v - return v - end) - t[name]=v - return v -end) -local getinfo=nil -local sethook=nil -local function hook(where) - local f=getinfo(2,"nSl") - if f then - local source=f.short_src - if not source then - return - end - local line=f.linedefined or 0 - local name=f.name - if not name then - local what=f.what - if what=="C" then - name="<anonymous>" - else - name=f.namewhat or what or "<unknown>" - end - end - local data=names[name][source][line] - if where=="call" then - local nesting=data.nesting - if nesting==0 then - data.count=data.count+1 - insert(data,ticks()) - data.nesting=1 - else - data.nesting=nesting+1 - end - elseif where=="return" then - local nesting=data.nesting - if nesting==1 then - local t=remove(data) - if t then - data.total=data.total+ticks()-t - end - data.nesting=0 - else - data.nesting=nesting-1 - end - end - end -end -function debugger.showstats(printer,threshold) - local printer=printer or report - local calls=0 - local functions=0 - local dataset={} - local length=0 - local realtime=0 - local totaltime=0 - local threshold=threshold or 0 - for name,sources in next,names do - for source,lines in next,sources do - for line,data in next,lines do - local count=data.count - if count>threshold then - if #name>length then - length=#name - end - local total=data.total - local real=total - if real>0 then - real=total-(count*overhead/dummycalls) - if real<0 then - real=0 - end - realtime=realtime+real - end - totaltime=totaltime+total - if line<0 then - line=0 - end - dataset[#dataset+1]={ real,total,count,name,source,line } - end - end - end - end - sort(dataset,function(a,b) - if a[1]==b[1] then - if a[2]==b[2] then - if a[3]==b[3] then - if a[4]==b[4] then - if a[5]==b[5] then - return a[6]<b[6] - else - return a[5]<b[5] - end - else - return a[4]<b[4] - end - else - return b[3]<a[3] - end - else - return b[2]<a[2] - end - else - return b[1]<a[1] - end - end) - if length>50 then - length=50 - end - local fmt=string.formatters["%4.9k s %3.3k %% %4.9k s %3.3k %% %8i # %-"..length.."s %4i %s"] - for i=1,#dataset do - local data=dataset[i] - local real=data[1] - local total=data[2] - local count=data[3] - local name=data[4] - local source=data[5] - local line=data[6] - calls=calls+count - functions=functions+1 - name=gsub(name,"%s+"," ") - if #name>length then - name=sub(name,1,length) - end - printer(fmt(seconds(total),100*total/totaltime,seconds(real),100*real/realtime,count,name,line,source)) - end - printer("") - printer(format("functions : %i",functions)) - printer(format("calls : %i",calls)) - printer(format("overhead : %f",seconds(overhead/1000))) -end -local function getdebug() - if sethook and getinfo then - return - end - if not debug then - local okay - okay,debug=pcall(require,"debug") - end - if type(debug)~="table" then - return - end - getinfo=debug.getinfo - sethook=debug.sethook - if type(getinfo)~="function" then - getinfo=nil - end - if type(sethook)~="function" then - sethook=nil - end -end -function debugger.savestats(filename,threshold) - local f=io.open(filename,'w') - if f then - debugger.showstats(function(str) f:write(str,"\n") end,threshold) - f:close() - end -end -function debugger.enable() - getdebug() - if sethook and getinfo and nesting==0 then - running=true - if initialize then - initialize() - end - sethook(hook,"cr") - local function dummy() end - local t=ticks() - for i=1,dummycalls do - dummy() - end - overhead=ticks()-t - end - if nesting>0 then - nesting=nesting+1 - end -end -function debugger.disable() - if nesting>0 then - nesting=nesting-1 - end - if sethook and getinfo and nesting==0 then - sethook() - end -end -local function showtraceback(rep) - getdebug() - if getinfo then - local level=2 - local reporter=rep or report - while true do - local info=getinfo(level,"Sl") - if not info then - break - elseif info.what=="C" then - reporter("%2i : %s",level-1,"C function") - else - reporter("%2i : %s : %s",level-1,info.short_src,info.currentline) - end - level=level+1 - end - end -end -debugger.showtraceback=showtraceback -if luac then - local show,dump=luac.print,string.dump - function luac.inspect(v) - if type(v)=="function" then - local ok,str=xpcall(dump,function() end,v) - if ok then - v=str - end - end - if type(v)=="string" then - show(v,true) - else - print(v) - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-tpl"] = package.loaded["util-tpl"] or true - --- original size: 7722, stripped down to: 4212 - -if not modules then modules={} end modules ['util-tpl']={ - 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" -} -utilities.templates=utilities.templates or {} -local templates=utilities.templates -local trace_template=false trackers.register("templates.trace",function(v) trace_template=v end) -local report_template=logs.reporter("template") -local tostring,next=tostring,next -local format,sub,byte=string.format,string.sub,string.byte -local P,C,R,Cs,Cc,Carg,lpegmatch,lpegpatterns=lpeg.P,lpeg.C,lpeg.R,lpeg.Cs,lpeg.Cc,lpeg.Carg,lpeg.match,lpeg.patterns -local formatters=string.formatters -local replacer -local function replacekey(k,t,how,recursive) - local v=t[k] - if not v then - if trace_template then - report_template("unknown key %a",k) - end - return "" - else - v=tostring(v) - if trace_template then - report_template("setting key %a to value %a",k,v) - end - if recursive then - return lpegmatch(replacer,v,1,t,how,recursive) - else - return v - end - end -end -local sqlescape=lpeg.replacer { - { "'","''" }, - { "\\","\\\\" }, - { "\r\n","\\n" }, - { "\r","\\n" }, -} -local sqlquoted=Cs(Cc("'")*sqlescape*Cc("'")) -lpegpatterns.sqlescape=sqlescape -lpegpatterns.sqlquoted=sqlquoted -local luaescape=lpegpatterns.luaescape -local escapers={ - lua=function(s) - return lpegmatch(luaescape,s) - end, - sql=function(s) - return lpegmatch(sqlescape,s) - end, -} -local quotedescapers={ - lua=function(s) - return format("%q",s) - end, - sql=function(s) - return lpegmatch(sqlquoted,s) - end, -} -local luaescaper=escapers.lua -local quotedluaescaper=quotedescapers.lua -local function replacekeyunquoted(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) - 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 function replaceformatted(l,m,r,t,how,recurse) - local v=t[r] - return v and formatters[l](v) -end -local single=P("%") -local double=P("%%") -local lquoted=P("%[") -local rquoted=P("]%") -local lquotedq=P("%(") -local rquotedq=P(")%") -local escape=double/'%%' -local nosingle=single/'' -local nodouble=double/'' -local nolquoted=lquoted/'' -local norquoted=rquoted/'' -local nolquotedq=lquotedq/'' -local norquotedq=rquotedq/'' -local nolformatted=P(":")/"%%" -local norformatted=P(":")/"" -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 formatted=nosingle*((Cs(nolformatted*(1-norformatted )^1)*norformatted*C((1-nosingle)^1)*args)/replaceformatted)*nosingle -local any=P(1) - replacer=Cs((unquoted+quoted+formatted+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 - else - return str - end -end -templates.replace=replace -function templates.replacer(str,how,recurse) - return function(mapping) - return lpegmatch(replacer,str,1,mapping,how or "lua",recurse or false) or str - end -end -function templates.load(filename,mapping,how,recurse) - local data=io.loaddata(filename) or "" - if mapping and next(mapping) then - return replace(data,mapping,how,recurse) - else - return data - end -end -function templates.resolve(t,mapping,how,recurse) - if not mapping then - mapping=t - end - for k,v in next,t do - t[k]=replace(v,mapping,how,recurse) - end - return t -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-sbx"] = package.loaded["util-sbx"] or true - --- original size: 21145, stripped down to: 13271 - -if not modules then modules={} end modules ['util-sbx']={ - 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" -} -if not sandbox then require("l-sandbox") end -local next,type=next,type -local replace=utilities.templates.replace -local collapsepath=file.collapsepath -local expandname=dir.expandname -local sortedhash=table.sortedhash -local lpegmatch=lpeg.match -local platform=os.type -local P,S,C=lpeg.P,lpeg.S,lpeg.C -local gsub=string.gsub -local lower=string.lower -local find=string.find -local concat=string.concat -local unquoted=string.unquoted -local optionalquoted=string.optionalquoted -local basename=file.basename -local nameonly=file.nameonly -local sandbox=sandbox -local validroots={} -local validrunners={} -local validbinaries=true -local validlibraries=true -local validators={} -local finalized=nil -local trace=false -local p_validroot=nil -local p_split=lpeg.firstofsplit(" ") -local report=logs.reporter("sandbox") -trackers.register("sandbox",function(v) trace=v end) -sandbox.setreporter(report) -sandbox.finalizer { - category="files", - action=function() - finalized=true - end -} -local function registerroot(root,what) - if finalized then - report("roots are already finalized") - else - if type(root)=="table" then - root,what=root[1],root[2] - end - if type(root)=="string" and root~="" then - root=collapsepath(expandname(root)) - if what=="r" or what=="ro" or what=="readable" then - what="read" - elseif what=="w" or what=="wo" or what=="writable" then - what="write" - end - validroots[root]=what=="write" or false - end - end -end -sandbox.finalizer { - category="files", - action=function() - if p_validroot then - report("roots are already initialized") - else - sandbox.registerroot(".","write") - for name in sortedhash(validroots) do - if p_validroot then - p_validroot=P(name)+p_validroot - else - p_validroot=P(name) - end - end - p_validroot=p_validroot/validroots - end - end -} -local function registerbinary(name) - if finalized then - report("binaries are already finalized") - elseif type(name)=="string" and name~="" then - if not validbinaries then - return - end - if validbinaries==true then - validbinaries={ [name]=true } - else - validbinaries[name]=true - end - elseif name==true then - validbinaries={} - end -end -local function registerlibrary(name) - if finalized then - report("libraries are already finalized") - elseif type(name)=="string" and name~="" then - if not validlibraries then - return - end - if validlibraries==true then - validlibraries={ [nameonly(name)]=true } - else - validlibraries[nameonly(name)]=true - end - elseif name==true then - validlibraries={} - end -end -local p_write=S("wa") p_write=(1-p_write)^0*p_write -local p_path=S("\\/~$%:") p_path=(1-p_path )^0*p_path -local function normalized(name) - if platform=="windows" then - name=gsub(name,"/","\\") - end - return name -end -function sandbox.possiblepath(name) - return lpegmatch(p_path,name) and true or false -end -local filenamelogger=false -function sandbox.setfilenamelogger(l) - filenamelogger=type(l)=="function" and l or false -end -local function validfilename(name,what) - if p_validroot and type(name)=="string" and lpegmatch(p_path,name) then - local asked=collapsepath(expandname(name)) - local okay=lpegmatch(p_validroot,asked) - if okay==true then - if filenamelogger then - filenamelogger(name,"w",asked,true) - end - return name - elseif okay==false then - if not what then - if filenamelogger then - filenamelogger(name,"r",asked,true) - end - return name - elseif lpegmatch(p_write,what) then - if filenamelogger then - filenamelogger(name,"w",asked,false) - end - return - else - if filenamelogger then - filenamelogger(name,"r",asked,true) - end - return name - end - elseif filenamelogger then - filenamelogger(name,"*",name,false) - end - else - return name - end -end -local function readable(name,finalized) - return validfilename(name,"r") -end -local function normalizedreadable(name,finalized) - local valid=validfilename(name,"r") - if valid then - return normalized(valid) - end -end -local function writeable(name,finalized) - return validfilename(name,"w") -end -local function normalizedwriteable(name,finalized) - local valid=validfilename(name,"w") - if valid then - return normalized(valid) - end -end -validators.readable=readable -validators.writeable=normalizedwriteable -validators.normalizedreadable=normalizedreadable -validators.normalizedwriteable=writeable -validators.filename=readable -table.setmetatableindex(validators,function(t,k) - if k then - t[k]=readable - end - return readable -end) -function validators.string(s,finalized) - if finalized and suspicious(s) then - return "" - else - return s - end -end -function validators.cache(s) - if finalized then - return basename(s) - else - return s - end -end -function validators.url(s) - if finalized and find("^file:") then - return "" - else - return s - end -end -local function filehandlerone(action,one,...) - local checkedone=validfilename(one) - if checkedone then - return action(one,...) - else - end -end -local function filehandlertwo(action,one,two,...) - local checkedone=validfilename(one) - if checkedone then - local checkedtwo=validfilename(two) - if checkedtwo then - return action(one,two,...) - else - end - else - end -end -local function iohandler(action,one,...) - if type(one)=="string" then - local checkedone=validfilename(one) - if checkedone then - return action(one,...) - end - elseif one then - return action(one,...) - else - return action() - end -end -local osexecute=sandbox.original(os.execute) -local iopopen=sandbox.original(io.popen) -local reported={} -local function validcommand(name,program,template,checkers,defaults,variables,reporter,strict) - if validbinaries~=false and (validbinaries==true or validbinaries[program]) then - local binpath=nil - if variables then - for variable,value in next,variables do - local chktype=checkers[variable] - if chktype=="verbose" then - else - local checker=validators[chktype] - if checker and type(value)=="string" then - value=checker(unquoted(value),strict) - if value then - variables[variable]=optionalquoted(value) - else - report("variable %a with value %a fails the check",variable,value) - return - end - else - report("variable %a has no checker",variable) - return - end - end - end - for variable,default in next,defaults do - local value=variables[variable] - if not value or value=="" then - local chktype=checkers[variable] - if chktype=="verbose" then - elseif type(default)=="string" then - local checker=validators[chktype] - if checker then - default=checker(unquoted(default),strict) - if default then - variables[variable]=optionalquoted(default) - else - report("variable %a with default %a fails the check",variable,default) - return - end - end - end - end - end - binpath=variables.binarypath - end - if type(binpath)=="string" and binpath~="" then - program=binpath.."/"..program - end - local command=program.." "..replace(template,variables) - if reporter then - reporter("executing runner %a: %s",name,command) - elseif trace then - report("executing runner %a: %s",name,command) - end - return command - elseif not reported[name] then - report("executing program %a of runner %a is not permitted",program,name) - reported[name]=true - end -end -local runners={ - resultof=function(...) - local command=validcommand(...) - if command then - if trace then - report("resultof: %s",command) - end - local handle=iopopen(command,"r") - if handle then - local result=handle:read("*all") or "" - handle:close() - return result - end - end - end, - execute=function(...) - local command=validcommand(...) - if command then - if trace then - report("execute: %s",command) - end - local okay=osexecute(command) - return okay - end - end, - pipeto=function(...) - local command=validcommand(...) - if command then - if trace then - report("pipeto: %s",command) - end - return iopopen(command,"w") - end - end, -} -function sandbox.registerrunner(specification) - if type(specification)=="string" then - local wrapped=validrunners[specification] - inspect(table.sortedkeys(validrunners)) - if wrapped then - return wrapped - else - report("unknown predefined runner %a",specification) - return - end - end - if type(specification)~="table" then - report("specification should be a table (or string)") - return - end - local name=specification.name - if type(name)~="string" then - report("invalid name, string expected",name) - return - end - if validrunners[name] then - report("invalid name, runner %a already defined",name) - return - end - local program=specification.program - if type(program)=="string" then - elseif type(program)=="table" then - program=program[platform] or program.default or program.unix - end - if type(program)~="string" or program=="" then - report("invalid runner %a specified for platform %a",name,platform) - return - end - local template=specification.template - if not template then - report("missing template for runner %a",name) - return - end - local method=specification.method or "execute" - local checkers=specification.checkers or {} - local defaults=specification.defaults or {} - local runner=runners[method] - if runner then - local finalized=finalized - local wrapped=function(variables) - return runner(name,program,template,checkers,defaults,variables,specification.reporter,finalized) - end - validrunners[name]=wrapped - return wrapped - else - validrunners[name]=nil - report("invalid method for runner %a",name) - end -end -function sandbox.getrunner(name) - return name and validrunners[name] -end -local function suspicious(str) - return (find(str,"[/\\]") or find(command,"..",1,true)) and true or false -end -local function binaryrunner(action,command,...) - if validbinaries==false then - report("no binaries permitted, ignoring command: %s",command) - return - end - if type(command)~="string" then - report("command should be a string") - return - end - local program=lpegmatch(p_split,command) - if not program or program=="" then - report("unable to filter binary from command: %s",command) - return - end - if validbinaries==true then - elseif not validbinaries[program] then - report("binary not permitted, ignoring command: %s",command) - return - elseif suspicious(command) then - report("/ \\ or .. found, ignoring command (use sandbox.registerrunner): %s",command) - return - end - return action(command,...) -end -local function dummyrunner(action,command,...) - if type(command)=="table" then - command=concat(command," ",command[0] and 0 or 1) - end - report("ignoring command: %s",command) -end -sandbox.filehandlerone=filehandlerone -sandbox.filehandlertwo=filehandlertwo -sandbox.iohandler=iohandler -function sandbox.disablerunners() - validbinaries=false -end -function sandbox.disablelibraries() - validlibraries=false -end -if FFISUPPORTED and ffi then - function sandbox.disablelibraries() - validlibraries=false - for k,v in next,ffi do - if k~="gc" then - ffi[k]=nil - end - end - end - local fiiload=ffi.load - if fiiload then - local reported={} - function ffi.load(name,...) - if validlibraries==false then - elseif validlibraries==true then - return fiiload(name,...) - elseif validlibraries[nameonly(name)] then - return fiiload(name,...) - else - end - if not reported[name] then - report("using library %a is not permitted",name) - reported[name]=true - end - return nil - end - end -end -local overload=sandbox.overload -local register=sandbox.register - overload(loadfile,filehandlerone,"loadfile") -if io then - overload(io.open,filehandlerone,"io.open") - overload(io.popen,binaryrunner,"io.popen") - overload(io.input,iohandler,"io.input") - overload(io.output,iohandler,"io.output") - overload(io.lines,filehandlerone,"io.lines") -end -if os then - overload(os.execute,binaryrunner,"os.execute") - overload(os.spawn,dummyrunner,"os.spawn") - overload(os.exec,dummyrunner,"os.exec") - overload(os.resultof,binaryrunner,"os.resultof") - overload(os.pipeto,binaryrunner,"os.pipeto") - overload(os.rename,filehandlertwo,"os.rename") - overload(os.remove,filehandlerone,"os.remove") -end -if lfs then - overload(lfs.chdir,filehandlerone,"lfs.chdir") - overload(lfs.mkdir,filehandlerone,"lfs.mkdir") - overload(lfs.rmdir,filehandlerone,"lfs.rmdir") - overload(lfs.isfile,filehandlerone,"lfs.isfile") - overload(lfs.isdir,filehandlerone,"lfs.isdir") - overload(lfs.attributes,filehandlerone,"lfs.attributes") - overload(lfs.dir,filehandlerone,"lfs.dir") - overload(lfs.lock_dir,filehandlerone,"lfs.lock_dir") - overload(lfs.touch,filehandlerone,"lfs.touch") - overload(lfs.link,filehandlertwo,"lfs.link") - overload(lfs.setmode,filehandlerone,"lfs.setmode") - overload(lfs.readlink,filehandlerone,"lfs.readlink") - overload(lfs.shortname,filehandlerone,"lfs.shortname") - overload(lfs.symlinkattributes,filehandlerone,"lfs.symlinkattributes") -end -if zip then - zip.open=register(zip.open,filehandlerone,"zip.open") -end -sandbox.registerroot=registerroot -sandbox.registerbinary=registerbinary -sandbox.registerlibrary=registerlibrary -sandbox.validfilename=validfilename - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-mrg"] = package.loaded["util-mrg"] or true - --- original size: 7819, stripped down to: 5881 - -if not modules then modules={} end modules ['util-mrg']={ - 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 gsub,format=string.gsub,string.format -local concat=table.concat -local type,next=type,next -local P,R,S,V,Ct,C,Cs,Cc,Cp,Cmt,Cb,Cg=lpeg.P,lpeg.R,lpeg.S,lpeg.V,lpeg.Ct,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Cp,lpeg.Cmt,lpeg.Cb,lpeg.Cg -local lpegmatch,patterns=lpeg.match,lpeg.patterns -utilities=utilities or {} -local merger=utilities.merger or {} -utilities.merger=merger -merger.strip_comment=true -local report=logs.reporter("system","merge") -utilities.report=report -local m_begin_merge="begin library merge" -local m_end_merge="end library merge" -local m_begin_closure="do -- create closure to overcome 200 locals limit" -local m_end_closure="end -- of closure" -local m_pattern="%c+".."%-%-%s+"..m_begin_merge.."%c+(.-)%c+".."%-%-%s+"..m_end_merge.."%c+" -local m_format="\n\n-- "..m_begin_merge.."\n%s\n".."-- "..m_end_merge.."\n\n" -local m_faked="-- ".."created merged file".."\n\n".."-- "..m_begin_merge.."\n\n".."-- "..m_end_merge.."\n\n" -local m_report=[[ --- used libraries : %s --- skipped libraries : %s --- original bytes : %s --- stripped bytes : %s -]] -local m_preloaded=[[package.loaded[%q] = package.loaded[%q] or true]] -local function self_fake() - return m_faked -end -local function self_nothing() - return "" -end -local function self_load(name) - local data=io.loaddata(name) or "" - if data=="" then - report("unknown file %a",name) - else - report("inserting file %a",name) - end - return data or "" -end -local space=patterns.space -local eol=patterns.newline -local equals=P("=")^0 -local open=P("[")*Cg(equals,"init")*P("[")*P("\n")^-1 -local close=P("]")*C(equals)*P("]") -local closeeq=Cmt(close*Cb("init"),function(s,i,a,b) return a==b end) -local longstring=open*(1-closeeq)^0*close -local quoted=patterns.quoted -local digit=patterns.digit -local emptyline=space^0*eol -local operator1=P("<=")+P(">=")+P("~=")+P("..")+S("/^<>=*+%%") -local operator2=S("*+/") -local operator3=S("-") -local operator4=P("..") -local separator=S(",;") -local ignore=(P("]")*space^1*P("=")*space^1*P("]"))/"]=["+(P("=")*space^1*P("{"))/"={"+(P("(")*space^1)/"("+(P("{")*(space+eol)^1*P("}"))/"{}" -local strings=quoted -local longcmt=(emptyline^0*P("--")*longstring*emptyline^0)/"" -local longstr=longstring -local comment=emptyline^0*P("--")*P("-")^0*(1-eol)^0*emptyline^1/"\n" -local optionalspaces=space^0/"" -local mandatespaces=space^1/"" -local optionalspacing=(eol+space)^0/"" -local mandatespacing=(eol+space)^1/"" -local pack=digit*space^1*operator4*optionalspacing+optionalspacing*operator1*optionalspacing+optionalspacing*operator2*optionalspaces+mandatespacing*operator3*mandatespaces+optionalspaces*separator*optionalspaces -local lines=emptyline^2/"\n" -local spaces=(space*space)/" " -local spaces=(space*space*space*space)/" " -local compact=Cs (( - ignore+strings+longcmt+longstr+comment+pack+lines+spaces+1 -)^1 ) -local strip=Cs((emptyline^2/"\n"+1)^0) -local stripreturn=Cs((1-P("return")*space^1*P(1-space-eol)^1*(space+eol)^0*P(-1))^1) -function merger.compact(data) - return lpegmatch(strip,lpegmatch(compact,data)) -end -local function self_compact(data) - local delta=0 - if merger.strip_comment then - local before=#data - data=lpegmatch(compact,data) - data=lpegmatch(strip,data) - local after=#data - delta=before-after - report("original size %s, compacted to %s, stripped %s",before,after,delta) - data=format("-- original size: %s, stripped down to: %s\n\n%s",before,after,data) - end - return lpegmatch(stripreturn,data) or data,delta -end -local function self_save(name,data) - if data~="" then - io.savedata(name,data) - report("saving %s with size %s",name,#data) - end -end -local function self_swap(data,code) - return data~="" and (gsub(data,m_pattern,function() return format(m_format,code) end,1)) or "" -end -local function self_libs(libs,list) - local result,f,frozen,foundpath={},nil,false,nil - result[#result+1]="\n" - if type(libs)=='string' then libs={ libs } end - if type(list)=='string' then list={ list } end - for i=1,#libs do - local lib=libs[i] - for j=1,#list do - local pth=gsub(list[j],"\\","/") - report("checking library path %a",pth) - local name=pth.."/"..lib - if lfs.isfile(name) then - foundpath=pth - end - end - if foundpath then break end - end - if foundpath then - report("using library path %a",foundpath) - local right,wrong,original,stripped={},{},0,0 - for i=1,#libs do - local lib=libs[i] - local fullname=foundpath.."/"..lib - if lfs.isfile(fullname) then - report("using library %a",fullname) - local preloaded=file.nameonly(lib) - local data=io.loaddata(fullname,true) - original=original+#data - local data,delta=self_compact(data) - right[#right+1]=lib - result[#result+1]=m_begin_closure - result[#result+1]=format(m_preloaded,preloaded,preloaded) - result[#result+1]=data - result[#result+1]=m_end_closure - stripped=stripped+delta - else - report("skipping library %a",fullname) - wrong[#wrong+1]=lib - end - end - right=#right>0 and concat(right," ") or "-" - wrong=#wrong>0 and concat(wrong," ") or "-" - report("used libraries: %a",right) - report("skipped libraries: %a",wrong) - report("original bytes: %a",original) - report("stripped bytes: %a",stripped) - result[#result+1]=format(m_report,right,wrong,original,stripped) - else - report("no valid library path found") - end - return concat(result,"\n\n") -end -function merger.selfcreate(libs,list,target) - if target then - self_save(target,self_swap(self_fake(),self_libs(libs,list))) - end -end -function merger.selfmerge(name,libs,list,target) - self_save(target or name,self_swap(self_load(name),self_libs(libs,list))) -end -function merger.selfclean(name) - self_save(name,self_swap(self_load(name),self_nothing())) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-env"] = package.loaded["util-env"] or true - --- original size: 9738, stripped down to: 5531 - -if not modules then modules={} end modules ['util-env']={ - 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 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,optionalquoted=string.unquoted,string.quoted,string.optionalquoted -local concat,insert,remove=table.concat,table.insert,table.remove -environment=environment or {} -local environment=environment -local setlocale=os.setlocale -setlocale(nil,nil) -local report=logs.reporter("system") -function os.setlocale(a,b) - if a or b then - if report then - report() - report("You're messing with os.locale in a supposedly locale neutral enviroment. From") - report("now on are on your own and without support. Crashes or unexpected side effects") - report("can happen but don't bother the luatex and context developer team with it.") - report() - report=nil - end - setlocale(a,b) - end -end -local validengines=allocate { - ["luatex"]=true, - ["luajittex"]=true, -} -local basicengines=allocate { - ["luatex"]="luatex", - ["texlua"]="luatex", - ["texluac"]="luatex", - ["luajittex"]="luajittex", - ["texluajit"]="luajittex", -} -local luaengines=allocate { - ["lua"]=true, - ["luajit"]=true, -} -environment.validengines=validengines -environment.basicengines=basicengines -if not arg then - environment.used_as_library=true -elseif luaengines[file.removesuffix(arg[-1])] then -elseif validengines[file.removesuffix(arg[0])] then - if arg[1]=="--luaonly" then - arg[-1]=arg[0] - arg[ 0]=arg[2] - for k=3,#arg do - arg[k-2]=arg[k] - end - remove(arg) - remove(arg) - else - end - local originalzero=file.basename(arg[0]) - local specialmapping={ luatools=="base" } - if originalzero~="mtxrun" and originalzero~="mtxrun.lua" then - arg[0]=specialmapping[originalzero] or originalzero - insert(arg,0,"--script") - insert(arg,0,"mtxrun") - end -end -environment.arguments=allocate() -environment.files=allocate() -environment.sortedflags=nil -function environment.initializearguments(arg) - local arguments={} - local files={} - environment.arguments=arguments - environment.files=files - environment.sortedflags=nil - for index=1,#arg do - local argument=arg[index] - if index>0 then - local flag,value=match(argument,"^%-+(.-)=(.-)$") - if flag then - flag=gsub(flag,"^c:","") - arguments[flag]=unquoted(value or "") - else - flag=match(argument,"^%-+(.+)") - if flag then - flag=gsub(flag,"^c:","") - arguments[flag]=true - else - files[#files+1]=argument - end - end - end - end - if not environment.ownname then - if os.selfpath and os.selfname then - environment.ownname=file.addsuffix(file.join(os.selfpath,os.selfname),"lua") - end - end - environment.ownname=file.reslash(environment.ownname or arg[0] or 'unknown.lua') -end -function environment.setargument(name,value) - environment.arguments[name]=value -end -function environment.getargument(name,partial) - local arguments,sortedflags=environment.arguments,environment.sortedflags - if arguments[name] then - return arguments[name] - elseif partial then - if not sortedflags then - sortedflags=allocate(table.sortedkeys(arguments)) - for k=1,#sortedflags do - sortedflags[k]="^"..sortedflags[k] - end - environment.sortedflags=sortedflags - end - for k=1,#sortedflags do - local v=sortedflags[k] - if find(name,v) then - return arguments[sub(v,2,#v)] - end - end - end - return nil -end -environment.argument=environment.getargument -function environment.splitarguments(separator) - local done,before,after=false,{},{} - local originalarguments=environment.originalarguments - for k=1,#originalarguments do - local v=originalarguments[k] - if not done and v==separator then - done=true - elseif done then - after[#after+1]=v - else - before[#before+1]=v - end - end - return before,after -end -function environment.reconstructcommandline(arg,noquote) - local resolveprefix=resolvers.resolve - arg=arg or environment.originalarguments - if noquote and #arg==1 then - return unquoted(resolveprefix and resolveprefix(arg[1]) or arg[1]) - elseif #arg>0 then - local result={} - for i=1,#arg do - result[i]=optionalquoted(resolveprefix and resolveprefix(arg[i]) or resolveprefix) - end - return concat(result," ") - else - return "" - end -end -function environment.relativepath(path,root) - if not path then - path="" - end - if not file.is_rootbased_path(path) then - if not root then - root=file.pathpart(environment.ownscript or environment.ownname or ".") - end - if root=="" then - root="." - end - path=root.."/"..path - end - return file.collapsepath(path,true) -end -if arg then - local newarg,instring={},false - for index=1,#arg do - local argument=arg[index] - if find(argument,"^\"") then - if find(argument,"\"$") then - newarg[#newarg+1]=gsub(argument,"^\"(.-)\"$","%1") - instring=false - else - newarg[#newarg+1]=gsub(argument,"^\"","") - instring=true - end - elseif find(argument,"\"$") then - if instring then - newarg[#newarg]=newarg[#newarg].." "..gsub(argument,"\"$","") - instring=false - else - newarg[#newarg+1]=argument - end - elseif instring then - newarg[#newarg]=newarg[#newarg].." "..argument - else - newarg[#newarg+1]=argument - end - end - for i=1,-5,-1 do - newarg[i]=arg[i] - end - environment.initializearguments(newarg) - environment.originalarguments=mark(newarg) - environment.rawarguments=mark(arg) - arg={} -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["luat-env"] = package.loaded["luat-env"] or true - --- original size: 6267, stripped down to: 4115 - - if not modules then modules={} end modules ['luat-env']={ - 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 rawset,loadfile=rawset,loadfile -local gsub=string.gsub -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local report_lua=logs.reporter("resolvers","lua") -local luautilities=utilities.lua -local luasuffixes=luautilities.suffixes -local texgettoks=tex and tex.gettoks -environment=environment or {} -local environment=environment -local mt={ - __index=function(_,k) - if k=="version" then - local version=texgettoks and texgettoks("contextversiontoks") - if version and version~="" then - rawset(environment,"version",version) - return version - else - return "unknown" - end - elseif k=="jobname" or k=="formatname" then - local name=tex and tex[k] - if name or name=="" then - rawset(environment,k,name) - return name - else - return "unknown" - end - elseif k=="outputfilename" then - local name=environment.jobname - rawset(environment,k,name) - return name - end - end -} -setmetatable(environment,mt) -function environment.texfile(filename) - return resolvers.findfile(filename,'tex') -end -function environment.luafile(filename) - if CONTEXTLMTXMODE and CONTEXTLMTXMODE>0 and file.suffix(filename)=="lua" then - local resolved=resolvers.findfile(file.replacesuffix(filename,"lmt")) or "" - if resolved~="" then - return resolved - end - end - local resolved=resolvers.findfile(filename,'tex') or "" - if resolved~="" then - return resolved - end - resolved=resolvers.findfile(filename,'texmfscripts') or "" - if resolved~="" then - return resolved - end - return resolvers.findfile(filename,'luatexlibs') or "" -end -local stripindeed=false directives.register("system.compile.strip",function(v) stripindeed=v end) -local function strippable(filename) - if stripindeed then - local modu=modules[file.nameonly(filename)] - return modu and modu.dataonly - else - return false - end -end -function environment.luafilechunk(filename,silent,macros) - filename=file.replacesuffix(filename,"lua") - local fullname=environment.luafile(filename) - if fullname and fullname~="" then - local data=luautilities.loadedluacode(fullname,strippable,filename,macros) - if not silent then - report_lua("loading file %a %s",fullname,not data and "failed" or "succeeded") - end - return data - else - if not silent then - report_lua("unknown file %a",filename) - end - return nil - end -end -function environment.loadluafile(filename,version) - local lucname,luaname,chunk - local basename=file.removesuffix(filename) - if basename==filename then - luaname=file.addsuffix(basename,luasuffixes.lua) - lucname=file.addsuffix(basename,luasuffixes.luc) - else - luaname=filename - lucname=nil - end - local fullname=(lucname and environment.luafile(lucname)) or "" - if fullname~="" then - if trace_locating then - report_lua("loading %a",fullname) - end - chunk=loadfile(fullname) - end - if chunk then - chunk() - if version then - local v=version - if modules and modules[filename] then - v=modules[filename].version - elseif versions and versions[filename] then - v=versions[filename] - end - if v==version then - return true - else - if trace_locating then - report_lua("version mismatch for %a, lua version %a, luc version %a",filename,v,version) - end - environment.loadluafile(filename) - end - else - return true - end - end - fullname=(luaname and environment.luafile(luaname)) or "" - if fullname~="" then - if trace_locating then - report_lua("loading %a",fullname) - end - chunk=loadfile(fullname) - if not chunk then - if trace_locating then - report_lua("unknown file %a",filename) - end - else - chunk() - return true - end - end - return false -end -environment.filenames=setmetatable({},{ - __index=function(t,k) - local v=environment.files[k] - if v then - return (gsub(v,"%.+$","")) - end - end, - __newindex=function(t,k) - end, - __len=function(t) - return #environment.files - end, -} ) - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["util-zip"] = package.loaded["util-zip"] or true - --- original size: 23730, stripped down to: 14293 - -if not modules then modules={} end modules ['util-zip']={ - version=1.001, - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local type,tostring,tonumber=type,tostring,tonumber -local sort,concat=table.sort,table.concat -local find,format,sub,gsub=string.find,string.format,string.sub,string.gsub -local osdate,ostime,osclock=os.date,os.time,os.clock -local ioopen=io.open -local loaddata,savedata=io.loaddata,io.savedata -local filejoin,isdir,dirname,mkdirs=file.join,lfs.isdir,file.dirname,dir.mkdirs -local suffix,suffixes=file.suffix,file.suffixes -local openfile=io.open -gzip=gzip or {} -if not zlib then - zlib=xzip -elseif not xzip then - xzip=zlib -end -local files=utilities.files -local openfile=files.open -local closefile=files.close -local readstring=files.readstring -local readcardinal2=files.readcardinal2le -local readcardinal4=files.readcardinal4le -local setposition=files.setposition -local getposition=files.getposition -local band=bit32.band -local rshift=bit32.rshift -local lshift=bit32.lshift -local zlibdecompress=zlib.decompress -local zlibdecompresssize=zlib.decompresssize -local zlibchecksum=zlib.crc32 -if not CONTEXTLMTXMODE or CONTEXTLMTXMODE==0 then - local cs=zlibchecksum - zlibchecksum=function(str,n) return cs(n or 0,str) end -end -local decompress=function(source) return zlibdecompress (source,-15) end -local decompresssize=function(source,targetsize) return zlibdecompresssize(source,targetsize,-15) end -local calculatecrc=function(buffer,initial) return zlibchecksum (initial or 0,buffer) end -local zipfiles={} -utilities.zipfiles=zipfiles -local openzipfile,closezipfile,unzipfile,foundzipfile,getziphash,getziplist do - function openzipfile(name) - return { - name=name, - handle=openfile(name,0), - } - end - local function collect(z) - if not z.list then - local list={} - local hash={} - local position=0 - local index=0 - local handle=z.handle - while true do - setposition(handle,position) - local signature=readstring(handle,4) - if signature=="PK\3\4" then - local version=readcardinal2(handle) - local flag=readcardinal2(handle) - local method=readcardinal2(handle) - local filetime=readcardinal2(handle) - local filedate=readcardinal2(handle) - local crc32=readcardinal4(handle) - local compressed=readcardinal4(handle) - local uncompressed=readcardinal4(handle) - local namelength=readcardinal2(handle) - local extralength=readcardinal2(handle) - local filename=readstring(handle,namelength) - local descriptor=band(flag,8)~=0 - local encrypted=band(flag,1)~=0 - local acceptable=method==0 or method==8 - local skipped=0 - local size=0 - if encrypted then - size=readcardinal2(handle) - skipbytes(size) - skipped=skipped+size+2 - skipbytes(8) - skipped=skipped+8 - size=readcardinal2(handle) - skipbytes(size) - skipped=skipped+size+2 - size=readcardinal4(handle) - skipbytes(size) - skipped=skipped+size+4 - size=readcardinal2(handle) - skipbytes(size) - skipped=skipped+size+2 - end - position=position+30+namelength+extralength+skipped - if descriptor then - setposition(handle,position+compressed) - crc32=readcardinal4(handle) - compressed=readcardinal4(handle) - uncompressed=readcardinal4(handle) - end - if acceptable then - index=index+1 - local data={ - filename=filename, - index=index, - position=position, - method=method, - compressed=compressed, - uncompressed=uncompressed, - crc32=crc32, - encrypted=encrypted, - } - hash[filename]=data - list[index]=data - else - end - position=position+compressed - else - break - end - z.list=list - z.hash=hash - end - end - end - function getziplist(z) - local list=z.list - if not list then - collect(z) - end - return z.list - end - function getziphash(z) - local hash=z.hash - if not hash then - collect(z) - end - return z.hash - end - function foundzipfile(z,name) - return getziphash(z)[name] - end - function closezipfile(z) - local f=z.handle - if f then - closefile(f) - z.handle=nil - end - end - function unzipfile(z,filename,check) - local hash=z.hash - if not hash then - hash=zipfiles.hash(z) - end - local data=hash[filename] - if not data then - end - if data then - local handle=z.handle - local position=data.position - local compressed=data.compressed - if compressed>0 then - setposition(handle,position) - local result=readstring(handle,compressed) - if data.method==8 then - if decompresssize then - result=decompresssize(result,data.uncompressed) - else - result=decompress(result) - end - end - if check and data.crc32~=calculatecrc(result) then - print("checksum mismatch") - return "" - end - return result - else - return "" - end - end - end - zipfiles.open=openzipfile - zipfiles.close=closezipfile - zipfiles.unzip=unzipfile - zipfiles.hash=getziphash - zipfiles.list=getziplist - zipfiles.found=foundzipfile -end -if xzip then - local writecardinal1=files.writebyte - local writecardinal2=files.writecardinal2le - local writecardinal4=files.writecardinal4le - local logwriter=logs.writer - local globpattern=dir.globpattern - local compress=xzip.compress - local checksum=xzip.crc32 - local function fromdostime(dostime,dosdate) - return ostime { - year=rshift(dosdate,9)+1980, - month=band(rshift(dosdate,5),0x0F), - day=band((dosdate ),0x1F), - hour=band(rshift(dostime,11) ), - min=band(rshift(dostime,5),0x3F), - sec=band((dostime ),0x1F), - } - end - local function todostime(time) - local t=osdate("*t",time) - return - lshift(t.year-1980,9)+lshift(t.month,5)+t.day, - lshift(t.hour,11)+lshift(t.min,5)+rshift(t.sec,1) - end - local function openzip(filename,level,comment,verbose) - local f=ioopen(filename,"wb") - if f then - return { - filename=filename, - handle=f, - list={}, - level=tonumber(level) or 3, - comment=tostring(comment), - verbose=verbose, - uncompressed=0, - compressed=0, - } - end - end - local function writezip(z,name,data,level,time) - local f=z.handle - local list=z.list - local level=tonumber(level) or z.level or 3 - local method=8 - local zipped=compress(data,level) - local checksum=checksum(data) - local verbose=z.verbose - if not zipped then - method=0 - zipped=data - end - local start=f:seek() - local compressed=#zipped - local uncompressed=#data - z.compressed=z.compressed+compressed - z.uncompressed=z.uncompressed+uncompressed - if verbose then - local pct=100*compressed/uncompressed - if pct>=100 then - logwriter(format("%10i %s",uncompressed,name)) - else - logwriter(format("%10i %02.1f %s",uncompressed,pct,name)) - end - end - f:write("\x50\x4b\x03\x04") - writecardinal2(f,0) - writecardinal2(f,0) - writecardinal2(f,method) - writecardinal2(f,0) - writecardinal2(f,0) - writecardinal4(f,checksum) - writecardinal4(f,compressed) - writecardinal4(f,uncompressed) - writecardinal2(f,#name) - writecardinal2(f,0) - f:write(name) - f:write(zipped) - list[#list+1]={ #zipped,#data,name,checksum,start,time or 0 } - end - local function closezip(z) - local f=z.handle - local list=z.list - local comment=z.comment - local verbose=z.verbose - local count=#list - local start=f:seek() - for i=1,count do - local l=list[i] - local compressed=l[1] - local uncompressed=l[2] - local name=l[3] - local checksum=l[4] - local start=l[5] - local time=l[6] - local date,time=todostime(time) - f:write('\x50\x4b\x01\x02') - writecardinal2(f,0) - writecardinal2(f,0) - writecardinal2(f,0) - writecardinal2(f,8) - writecardinal2(f,time) - writecardinal2(f,date) - writecardinal4(f,checksum) - writecardinal4(f,compressed) - writecardinal4(f,uncompressed) - writecardinal2(f,#name) - writecardinal2(f,0) - writecardinal2(f,0) - writecardinal2(f,0) - writecardinal2(f,0) - writecardinal4(f,0) - writecardinal4(f,start) - f:write(name) - end - local stop=f:seek() - local size=stop-start - f:write('\x50\x4b\x05\x06') - writecardinal2(f,0) - writecardinal2(f,0) - writecardinal2(f,count) - writecardinal2(f,count) - writecardinal4(f,size) - writecardinal4(f,start) - if type(comment)=="string" and comment~="" then - writecardinal2(f,#comment) - f:write(comment) - else - writecardinal2(f,0) - end - if verbose then - local compressed=z.compressed - local uncompressed=z.uncompressed - local filename=z.filename - local pct=100*compressed/uncompressed - logwriter("") - if pct>=100 then - logwriter(format("%10i %s",uncompressed,filename)) - else - logwriter(format("%10i %02.1f %s",uncompressed,pct,filename)) - end - end - f:close() - end - local function zipdir(zipname,path,level,verbose) - if type(zipname)=="table" then - verbose=zipname.verbose - level=zipname.level - path=zipname.path - zipname=zipname.zipname - end - if not zipname or zipname=="" then - return - end - if not path or path=="" then - path="." - end - if not isdir(path) then - return - end - path=gsub(path,"\\+","/") - path=gsub(path,"/+","/") - local list={} - local count=0 - globpattern(path,"",true,function(name,size,time) - count=count+1 - list[count]={ name,time } - end) - sort(list,function(a,b) - return a[1]<b[1] - end) - local zipf=openzip(zipname,level,comment,verbose) - if zipf then - local p=#path+2 - for i=1,count do - local li=list[i] - local name=li[1] - local time=li[2] - local data=loaddata(name) - local name=sub(name,p,#name) - writezip(zipf,name,data,level,time,verbose) - end - closezip(zipf) - end - end - local function unzipdir(zipname,path,verbose) - if type(zipname)=="table" then - verbose=zipname.verbose - path=zipname.path - zipname=zipname.zipname - end - if not zipname or zipname=="" then - return - end - if not path or path=="" then - path="." - end - local z=openzipfile(zipname) - if z then - local list=getziplist(z) - if list then - local total=0 - local count=#list - local step=number.idiv(count,10) - local done=0 - local steps=verbose=="steps" - local time=steps and osclock() - for i=1,count do - local l=list[i] - local n=l.filename - local d=unzipfile(z,n) - if d then - local p=filejoin(path,n) - if mkdirs(dirname(p)) then - if steps then - total=total+#d - done=done+1 - if done>=step then - done=0 - logwriter(format("%4i files of %4i done, %10i bytes, %0.3f seconds",i,count,total,osclock()-time)) - end - elseif verbose then - logwriter(n) - end - savedata(p,d) - end - else - logwriter(format("problem with file %s",n)) - end - end - if steps then - logwriter(format("%4i files of %4i done, %10i bytes, %0.3f seconds",count,count,total,osclock()-time)) - end - closezipfile(z) - return true - else - closezipfile(z) - end - end - end - zipfiles.zipdir=zipdir - zipfiles.unzipdir=unzipdir -end -local pattern="^\x1F\x8B\x08" -local gziplevel=3 -function gzip.suffix(filename) - local suffix,extra=suffixes(filename) - local gzipped=extra=="gz" - return suffix,gzipped -end -function gzip.compressed(s) - return s and find(s,pattern) -end -local getdecompressed -local putcompressed -if gzip.compress then - local gzipwindow=15+16 - local compress=zlib.compress - local decompress=zlib.decompress - getdecompressed=function(str) - return decompress(str,gzipwindow) - end - putcompressed=function(str,level) - return compress(str,level or gziplevel,nil,gzipwindow) - end -else - local gzipwindow=-15 - local identifier="\x1F\x8B" - local compress=zlib.compress - local decompress=zlib.decompress - local zlibchecksum=zlib.crc32 - if not CONTEXTLMTXMODE or CONTEXTLMTXMODE==0 then - local cs=zlibchecksum - zlibchecksum=function(str,n) return cs(n or 0,str) end - end - local streams=utilities.streams - local openstream=streams.openstring - local closestream=streams.close - local getposition=streams.getposition - local readbyte=streams.readbyte - local readcardinal4=streams.readcardinal4le - local readcardinal2=streams.readcardinal2le - local readstring=streams.readstring - local readcstring=streams.readcstring - local skipbytes=streams.skip - local tocardinal1=streams.tocardinal1 - local tocardinal4=streams.tocardinal4le - getdecompressed=function(str) - local s=openstream(str) - local identifier=readstring(s,2) - local method=readbyte(s,1) - local flags=readbyte(s,1) - local timestamp=readcardinal4(s) - local compression=readbyte(s,1) - local operating=readbyte(s,1) - local isjusttext=band(flags,0x01)~=0 and true or false - local extrasize=band(flags,0x04)~=0 and readcardinal2(s) or 0 - local filename=band(flags,0x08)~=0 and readcstring(s) or "" - local comment=band(flags,0x10)~=0 and readcstring(s) or "" - local checksum=band(flags,0x02)~=0 and readcardinal2(s) or 0 - local compressed=readstring(s,#str) - local data=decompress(compressed,gzipwindow) - return data - end - putcompressed=function(str,level,originalname) - return concat { - identifier, - tocardinal1(0x08), - tocardinal1(0x08), - tocardinal4(os.time()), - tocardinal1(0x02), - tocardinal1(0xFF), - (originalname or "unknownname").."\0", - compress(str,level,nil,gzipwindow), - tocardinal4(zlibchecksum(str)), - tocardinal4(#str), - } - end -end -function gzip.load(filename) - local f=openfile(filename,"rb") - if not f then - else - local data=f:read("*all") - f:close() - if data and data~="" then - if suffix(filename)=="gz" then - data=getdecompressed(data) - end - return data - end - end -end -function gzip.save(filename,data,level,originalname) - if suffix(filename)~="gz" then - filename=filename..".gz" - end - local f=openfile(filename,"wb") - if f then - data=putcompressed(data or "",level or gziplevel,originalname) - f:write(data) - f:close() - return #data - end -end -function gzip.compress(s,level) - if s and not find(s,pattern) then - if not level then - level=gziplevel - elseif level<=0 then - return s - elseif level>9 then - level=9 - end - return putcompressed(s,level or gziplevel) or s - end -end -function gzip.decompress(s) - if s and find(s,pattern) then - return getdecompressed(s) - else - return s - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["lxml-tab"] = package.loaded["lxml-tab"] or true - --- original size: 62810, stripped down to: 36225 - -if not modules then modules={} end modules ['lxml-tab']={ - version=1.001, - comment="this module is the basis for the lxml-* ones", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local trace_entities=false trackers.register("xml.entities",function(v) trace_entities=v end) -local report_xml=logs and logs.reporter("xml","core") or function(...) print(string.format(...)) end -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,rawset,select=type,next,setmetatable,getmetatable,tonumber,rawset,select -local lower,find,match,gsub=string.lower,string.find,string.match,string.gsub -local sort=table.sort -local utfchar=utf.char -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 -do -xml.xmlns=xml.xmlns or {} -local check=P(false) -local parse=check -function xml.registerns(namespace,pattern) - check=check+C(P(lower(pattern)))/namespace - parse=P { P(check)+1*V(1) } -end -function xml.checkns(namespace,url) - local ns=lpegmatch(parse,lower(url)) - if ns and namespace~=ns then - xml.xmlns[namespace]=ns - end -end -function xml.resolvens(url) - return lpegmatch(parse,lower(url)) or "" -end -end -local nsremap,resolvens=xml.xmlns,xml.resolvens -local stack,level,top,at,xmlnms,errorstr -local entities,parameters -local strip,utfize,resolve,cleanup,resolve_predefined,unify_predefined -local dcache,hcache,acache -local mt,dt,nt -local currentfilename,currentline,linenumbers -local grammar_parsed_text_one -local grammar_parsed_text_two -local grammar_unparsed_text -local handle_hex_entity -local handle_dec_entity -local handle_any_entity_dtd -local handle_any_entity_text -local function preparexmlstate(settings) - if settings then - linenumbers=settings.linenumbers - stack={} - level=0 - top={} - at={} - mt={} - dt={} - nt=0 - xmlns={} - errorstr=nil - strip=settings.strip_cm_and_dt - utfize=settings.utfize_entities - resolve=settings.resolve_entities - resolve_predefined=settings.resolve_predefined_entities - unify_predefined=settings.unify_predefined_entities - cleanup=settings.text_cleanup - entities=settings.entities or {} - currentfilename=settings.currentresource - currentline=1 - parameters={} - reported_at_errors={} - dcache={} - hcache={} - acache={} - if utfize==nil then - settings.utfize_entities=true - utfize=true - end - if resolve_predefined==nil then - settings.resolve_predefined_entities=true - resolve_predefined=true - end - else - linenumbers=false - stack=nil - level=nil - top=nil - at=nil - mt=nil - dt=nil - nt=nil - xmlns=nil - errorstr=nil - strip=nil - utfize=nil - resolve=nil - resolve_predefined=nil - unify_predefined=nil - cleanup=nil - entities=nil - parameters=nil - reported_at_errors=nil - dcache=nil - hcache=nil - acache=nil - currentfilename=nil - currentline=1 - end -end -local function initialize_mt(root) - mt={ __index=root } -end -function xml.setproperty(root,k,v) - getmetatable(root).__index[k]=v -end -function xml.checkerror(top,toclose) - return "" -end -local checkns=xml.checkns -local function add_attribute(namespace,tag,value) - if cleanup and value~="" then - value=cleanup(value) - end - if tag=="xmlns" then - xmlns[#xmlns+1]=resolvens(value) - at[tag]=value - elseif namespace=="" then - at[tag]=value - elseif namespace=="xmlns" then - checkns(tag,value) - at["xmlns:"..tag]=value - else - at[namespace..":"..tag]=value - end -end -local function add_empty(spacing,namespace,tag) - if spacing~="" then - nt=nt+1 - dt[nt]=spacing - end - local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace - top=stack[level] - dt=top.dt - nt=#dt+1 - local t=linenumbers and { - ns=namespace or "", - rn=resolved, - tg=tag, - at=at, - dt={}, - ni=nt, - cf=currentfilename, - cl=currentline, - __p__=top, - } or { - ns=namespace or "", - rn=resolved, - tg=tag, - at=at, - dt={}, - ni=nt, - __p__=top, - } - dt[nt]=t - setmetatable(t,mt) - if at.xmlns then - remove(xmlns) - end - at={} -end -local function add_begin(spacing,namespace,tag) - if spacing~="" then - nt=nt+1 - dt[nt]=spacing - end - local resolved=namespace=="" and xmlns[#xmlns] or nsremap[namespace] or namespace - dt={} - top=linenumbers and { - ns=namespace or "", - rn=resolved, - tg=tag, - at=at, - dt=dt, - ni=nil, - cf=currentfilename, - cl=currentline, - __p__=stack[level], - } or { - ns=namespace or "", - rn=resolved, - tg=tag, - at=at, - dt=dt, - ni=nil, - __p__=stack[level], - } - setmetatable(top,mt) - nt=0 - level=level+1 - stack[level]=top - at={} -end -local function add_end(spacing,namespace,tag) - if spacing~="" then - nt=nt+1 - dt[nt]=spacing - end - local toclose=stack[level] - level=level-1 - top=stack[level] - if level<1 then - errorstr=formatters["unable to close %s %s"](tag,xml.checkerror(top,toclose) or "") - report_xml(errorstr) - elseif toclose.tg~=tag then - errorstr=formatters["unable to close %s with %s %s"](toclose.tg,tag,xml.checkerror(top,toclose) or "") - report_xml(errorstr) - end - dt=top.dt - nt=#dt+1 - dt[nt]=toclose - toclose.ni=nt - if toclose.at.xmlns then - remove(xmlns) - end -end -local function add_text(text) - if text=="" then - return - elseif cleanup then - if nt>0 then - local s=dt[nt] - if type(s)=="string" then - dt[nt]=s..cleanup(text) - else - nt=nt+1 - dt[nt]=cleanup(text) - end - else - nt=1 - dt[1]=cleanup(text) - end - else - if nt>0 then - local s=dt[nt] - if type(s)=="string" then - dt[nt]=s..text - else - nt=nt+1 - dt[nt]=text - end - else - nt=1 - dt[1]=text - end - end -end -local function add_special(what,spacing,text) - if spacing~="" then - nt=nt+1 - dt[nt]=spacing - end - if strip and (what=="@cm@" or what=="@dt@") then - else - nt=nt+1 - dt[nt]=linenumbers and { - special=true, - ns="", - tg=what, - ni=nil, - dt={ text }, - cf=currentfilename, - cl=currentline, - } or { - special=true, - ns="", - tg=what, - ni=nil, - dt={ text }, - } - end -end -local function set_message(txt) - errorstr="garbage at the end of the file: "..gsub(txt,"([ \n\r\t]*)","") -end -local function attribute_value_error(str) - if not reported_at_errors[str] then - report_xml("invalid attribute value %a",str) - reported_at_errors[str]=true - at._error_=str - end - return str -end -local function attribute_specification_error(str) - if not reported_at_errors[str] then - report_xml("invalid attribute specification %a",str) - reported_at_errors[str]=true - at._error_=str - end - return str -end -do - local badentity="&" - xml.placeholders={ - unknown_dec_entity=function(str) return str=="" and badentity or formatters["&%s;"](str) end, - unknown_hex_entity=function(str) return formatters["&#x%s;"](str) end, - unknown_any_entity=function(str) return formatters["&#x%s;"](str) end, - } - local function fromhex(s) - local n=tonumber(s,16) - if n then - return utfchar(n) - else - return formatters["h:%s"](s),true - end - end - local function fromdec(s) - local n=tonumber(s) - if n then - return utfchar(n) - else - return formatters["d:%s"](s),true - end - end - local p_rest=(1-P(";"))^0 - local p_many=P(1)^0 - local parsedentity=P("&#")*(P("x")*(p_rest/fromhex)+(p_rest/fromdec))*P(";")*P(-1)+P ("#")*(P("x")*(p_many/fromhex)+(p_many/fromdec)) - xml.parsedentitylpeg=parsedentity - local predefined_unified={ - [38]="&", - [42]=""", - [47]="'", - [74]="<", - [76]=">", - } - local predefined_simplified={ - [38]="&",amp="&", - [42]='"',quot='"', - [47]="'",apos="'", - [74]="<",lt="<", - [76]=">",gt=">", - } - local nofprivates=0xF0000 - local privates_u={ - [ [[&]] ]="&", - [ [["]] ]=""", - [ [[']] ]="'", - [ [[<]] ]="<", - [ [[>]] ]=">", - } - local privates_p={ - } - local privates_s={ - [ [["]] ]="&U+22;", - [ [[#]] ]="&U+23;", - [ [[$]] ]="&U+24;", - [ [[%]] ]="&U+25;", - [ [[&]] ]="&U+26;", - [ [[']] ]="&U+27;", - [ [[<]] ]="&U+3C;", - [ [[>]] ]="&U+3E;", - [ [[\]] ]="&U+5C;", - [ [[{]] ]="&U+7B;", - [ [[|]] ]="&U+7C;", - [ [[}]] ]="&U+7D;", - [ [[~]] ]="&U+7E;", - } - local privates_x={ - [ [["]] ]="&U+22;", - [ [[#]] ]="&U+23;", - [ [[$]] ]="&U+24;", - [ [[%]] ]="&U+25;", - [ [[']] ]="&U+27;", - [ [[\]] ]="&U+5C;", - [ [[{]] ]="&U+7B;", - [ [[|]] ]="&U+7C;", - [ [[}]] ]="&U+7D;", - [ [[~]] ]="&U+7E;", - } - local privates_n={ - } - local escaped=utf.remapper(privates_u,"dynamic") - local unprivatized=utf.remapper(privates_p,"dynamic") - local unspecialized=utf.remapper(privates_s,"dynamic") - local despecialized=utf.remapper(privates_x,"dynamic") - xml.unprivatized=unprivatized - xml.unspecialized=unspecialized - xml.despecialized=despecialized - xml.escaped=escaped - local function unescaped(s) - local p=privates_n[s] - if not p then - nofprivates=nofprivates+1 - p=utfchar(nofprivates) - privates_n[s]=p - s="&"..s..";" - privates_u[p]=s - privates_p[p]=s - privates_s[p]=s - end - return p - end - xml.privatetoken=unescaped - xml.privatecodes=privates_n - xml.specialcodes=privates_s - function xml.addspecialcode(key,value) - privates_s[key]=value or "&"..s..";" - end - handle_hex_entity=function(str) - local h=hcache[str] - if not h then - local n=tonumber(str,16) - h=unify_predefined and predefined_unified[n] - if h then - if trace_entities then - report_xml("utfize, converting hex entity &#x%s; into %a",str,h) - end - elseif utfize then - h=(n and utfchar(n)) or xml.unknown_hex_entity(str) or "" - if not n then - report_xml("utfize, ignoring hex entity &#x%s;",str) - elseif trace_entities then - report_xml("utfize, converting hex entity &#x%s; into %a",str,h) - end - else - if trace_entities then - report_xml("found entity &#x%s;",str) - end - h="&#x"..str..";" - end - hcache[str]=h - end - return h - end - handle_dec_entity=function(str) - local d=dcache[str] - if not d then - local n=tonumber(str) - d=unify_predefined and predefined_unified[n] - if d then - if trace_entities then - report_xml("utfize, converting dec entity &#%s; into %a",str,d) - end - elseif utfize then - d=(n and utfchar(n)) or placeholders.unknown_dec_entity(str) or "" - if not n then - report_xml("utfize, ignoring dec entity &#%s;",str) - elseif trace_entities then - report_xml("utfize, converting dec entity &#%s; into %a",str,d) - end - else - if trace_entities then - report_xml("found entity &#%s;",str) - end - d="&#"..str..";" - end - dcache[str]=d - end - return d - end - handle_any_entity_dtd=function(str) - if resolve then - local a=resolve_predefined and predefined_simplified[str] - if a then - if trace_entities then - report_xml("resolving entity &%s; to predefined %a",str,a) - end - else - if type(resolve)=="function" then - a=resolve(str,entities) or entities[str] - else - a=entities[str] - end - if a then - if type(a)=="function" then - if trace_entities then - report_xml("expanding entity &%s; to function call",str) - end - a=a(str) or "" - end - a=lpegmatch(parsedentity,a) or a - if trace_entities then - report_xml("resolving entity &%s; to internal %a",str,a) - end - else - local unknown_any_entity=placeholders.unknown_any_entity - if unknown_any_entity then - a=unknown_any_entity(str) or "" - end - if a then - if trace_entities then - report_xml("resolving entity &%s; to external %s",str,a) - end - else - if trace_entities then - report_xml("keeping entity &%s;",str) - end - if str=="" then - a=badentity - else - a="&"..str..";" - end - end - end - end - return a - else - local a=acache[str] - if not a then - a=resolve_predefined and predefined_simplified[str] - if a then - acache[str]=a - if trace_entities then - report_xml("entity &%s; becomes %a",str,a) - end - elseif str=="" then - if trace_entities then - report_xml("invalid entity &%s;",str) - end - a=badentity - acache[str]=a - else - if trace_entities then - report_xml("entity &%s; is made private",str) - end - a=unescaped(str) - acache[str]=a - end - end - return a - end - end - handle_any_entity_text=function(str) - if resolve then - local a=resolve_predefined and predefined_simplified[str] - if a then - if trace_entities then - report_xml("resolving entity &%s; to predefined %a",str,a) - end - else - if type(resolve)=="function" then - a=resolve(str,entities) or entities[str] - else - a=entities[str] - end - if a then - if type(a)=="function" then - if trace_entities then - report_xml("expanding entity &%s; to function call",str) - end - a=a(str) or "" - end - a=lpegmatch(grammar_parsed_text_two,a) or a - if type(a)=="number" then - return "" - else - a=lpegmatch(parsedentity,a) or a - if trace_entities then - report_xml("resolving entity &%s; to internal %a",str,a) - end - end - if trace_entities then - report_xml("resolving entity &%s; to internal %a",str,a) - end - else - local unknown_any_entity=placeholders.unknown_any_entity - if unknown_any_entity then - a=unknown_any_entity(str) or "" - end - if a then - if trace_entities then - report_xml("resolving entity &%s; to external %s",str,a) - end - else - if trace_entities then - report_xml("keeping entity &%s;",str) - end - if str=="" then - a=badentity - else - a="&"..str..";" - end - end - end - end - return a - else - local a=acache[str] - if not a then - a=resolve_predefined and predefined_simplified[str] - if a then - acache[str]=a - if trace_entities then - report_xml("entity &%s; becomes %a",str,a) - end - elseif str=="" then - if trace_entities then - report_xml("invalid entity &%s;",str) - end - a=badentity - acache[str]=a - else - if trace_entities then - report_xml("entity &%s; is made private",str) - end - a=unescaped(str) - acache[str]=a - end - end - return a - end - end - local p_rest=(1-P(";"))^1 - local spec={ - [0x23]="\\Ux{23}", - [0x24]="\\Ux{24}", - [0x25]="\\Ux{25}", - [0x5C]="\\Ux{5C}", - [0x7B]="\\Ux{7B}", - [0x7C]="\\Ux{7C}", - [0x7D]="\\Ux{7D}", - [0x7E]="\\Ux{7E}", - } - local hash=table.setmetatableindex(spec,function(t,k) - local v=utfchar(k) - t[k]=v - return v - end) - local function fromuni(s) - local n=tonumber(s,16) - if n then - return hash[n] - else - return formatters["u:%s"](s),true - end - end - local function fromhex(s) - local n=tonumber(s,16) - if n then - return hash[n] - else - return formatters["h:%s"](s),true - end - end - local function fromdec(s) - local n=tonumber(s) - if n then - return hash[n] - else - return formatters["d:%s"](s),true - end - end - local reparsedentity=P("U+")*(p_rest/fromuni)+P("#")*( - P("x")*(p_rest/fromhex)+p_rest/fromdec - ) - local hash=table.setmetatableindex(function(t,k) - local v=utfchar(k) - t[k]=v - return v - end) - local function fromuni(s) - local n=tonumber(s,16) - if n then - return hash[n] - else - return formatters["u:%s"](s),true - end - end - local function fromhex(s) - local n=tonumber(s,16) - if n then - return hash[n] - else - return formatters["h:%s"](s),true - end - end - local function fromdec(s) - local n=tonumber(s) - if n then - return hash[n] - else - return formatters["d:%s"](s),true - end - end - local unescapedentity=P("U+")*(p_rest/fromuni)+P("#")*( - P("x")*(p_rest/fromhex)+p_rest/fromdec - ) - xml.reparsedentitylpeg=reparsedentity - xml.unescapedentitylpeg=unescapedentity -end -local escaped=xml.escaped -local unescaped=xml.unescaped -local placeholders=xml.placeholders -local function handle_end_entity(str) - report_xml("error in entity, %a found without ending %a",str,";") - return str -end -local function handle_crap_error(chr) - report_xml("error in parsing, unexpected %a found ",chr) - add_text(chr) - return chr -end -local function handlenewline() - currentline=currentline+1 -end -local spacetab=S(' \t') -local space=S(' \r\n\t') -local newline=lpegpatterns.newline/handlenewline -local anything=P(1) -local open=P('<') -local close=P('>') -local squote=S("'") -local dquote=S('"') -local equal=P('=') -local slash=P('/') -local colon=P(':') -local semicolon=P(';') -local ampersand=P('&') -local valid_0=R("\128\255") -local valid_1=R('az','AZ')+S('_')+valid_0 -local valid_2=valid_1+R('09')+S('-.') -local valid=valid_1*valid_2^0 -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=lpegpatterns.utfbom -local spacing=C(space^0) -local space_nl=spacetab+newline -local spacing_nl=Cs((space_nl)^0) -local anything_nl=newline+P(1) -local function weirdentity(k,v) - if trace_entities then - report_xml("registering %s entity %a as %a","weird",k,v) - end - parameters[k]=v -end -local function normalentity(k,v) - if trace_entities then - report_xml("registering %s entity %a as %a","normal",k,v) - end - entities[k]=v -end -local function systementity(k,v,n) - if trace_entities then - report_xml("registering %s entity %a as %a","system",k,v) - end - entities[k]=v -end -local function publicentity(k,v,n) - if trace_entities then - report_xml("registering %s entity %a as %a","public",k,v) - end - entities[k]=v -end -local function entityfile(pattern,k,v,n) - if n then - local okay,data - local loadbinfile=resolvers and resolvers.loadbinfile - if loadbinfile then - okay,data=loadbinfile(n) - else - data=io.loaddata(n) - okay=data and data~="" - end - if okay then - if trace_entities then - report_xml("loading public entities %a as %a from %a",k,v,n) - end - lpegmatch(pattern,data) - return - end - end - report_xml("ignoring public entities %a as %a from %a",k,v,n) -end -local function install(spacenewline,spacing,anything) - local anyentitycontent=(1-open-semicolon-space-close-ampersand)^0 - local hexentitycontent=R("AF","af","09")^1 - local decentitycontent=R("09")^1 - local parsedentity=P("#")/""*( - P("x")/""*(hexentitycontent/handle_hex_entity)+(decentitycontent/handle_dec_entity) - )+(anyentitycontent/handle_any_entity_dtd) - local parsedentity_text=P("#")/""*( - P("x")/""*(hexentitycontent/handle_hex_entity)+(decentitycontent/handle_dec_entity) - )+(anyentitycontent/handle_any_entity_text) - local entity=(ampersand/"")*parsedentity*(semicolon/"")+ampersand*(anyentitycontent/handle_end_entity) - local entity_text=(ampersand/"")*parsedentity_text*(semicolon/"")+ampersand*(anyentitycontent/handle_end_entity) - local text_unparsed=Cs((anything-open)^1) - local text_parsed=(Cs((anything-open-ampersand)^1)/add_text+Cs(entity_text)/add_text)^1 - local somespace=(spacenewline)^1 - local optionalspace=(spacenewline)^0 - local value=(squote*Cs((entity+(anything-squote))^0)*squote)+(dquote*Cs((entity+(anything-dquote))^0)*dquote) - local endofattributes=slash*close+close - local whatever=space*name*optionalspace*equal - local wrongvalue=Cs(P(entity+(1-space-endofattributes))^1)/attribute_value_error - local attributevalue=value+wrongvalue - local attribute=(somespace*name*optionalspace*equal*optionalspace*attributevalue)/add_attribute - local attributes=(attribute+somespace^-1*(((anything-endofattributes)^1)/attribute_specification_error))^0 - local parsedtext=text_parsed - local unparsedtext=text_unparsed/add_text - local balanced=P { "["*((anything-S"[]")+V(1))^0*"]" } - local emptyelement=(spacing*open*name*attributes*optionalspace*slash*close)/add_empty - local beginelement=(spacing*open*name*attributes*optionalspace*close)/add_begin - local endelement=(spacing*open*slash*name*optionalspace*close)/add_end - local begincomment=open*P("!--") - local endcomment=P("--")*close - local begininstruction=open*P("?") - local endinstruction=P("?")*close - local begincdata=open*P("![CDATA[") - local endcdata=P("]]")*close - local someinstruction=C((anything-endinstruction)^0) - local somecomment=C((anything-endcomment )^0) - local somecdata=C((anything-endcdata )^0) - local begindoctype=open*P("!DOCTYPE") - local enddoctype=close - local beginset=P("[") - local endset=P("]") - local wrdtypename=C((anything-somespace-P(";"))^1) - local doctypename=C((anything-somespace-close)^0) - local elementdoctype=optionalspace*P("<!ELEMENT")*(anything-close)^0*close - local basiccomment=begincomment*((anything-endcomment)^0)*endcomment - local weirdentitytype=P("%")*(somespace*doctypename*somespace*value)/weirdentity - local normalentitytype=(doctypename*somespace*value)/normalentity - local publicentitytype=(doctypename*somespace*P("PUBLIC")*somespace*value)/publicentity - local systementitytype=(doctypename*somespace*P("SYSTEM")*somespace*value*somespace*P("NDATA")*somespace*doctypename)/systementity - local entitydoctype=optionalspace*P("<!ENTITY")*somespace*(systementitytype+publicentitytype+normalentitytype+weirdentitytype)*optionalspace*close - local publicentityfile=(doctypename*somespace*P("PUBLIC")*somespace*value*(somespace*value)^0)/function(...) - entityfile(entitydoctype,...) - end - local function weirdresolve(s) - lpegmatch(entitydoctype,parameters[s]) - end - local function normalresolve(s) - lpegmatch(entitydoctype,entities[s]) - end - local entityresolve=P("%")*(wrdtypename/weirdresolve )*P(";")+P("&")*(wrdtypename/normalresolve)*P(";") - entitydoctype=entitydoctype+entityresolve - local doctypeset=beginset*optionalspace*P(elementdoctype+entitydoctype+entityresolve+basiccomment+space)^0*optionalspace*endset - local definitiondoctype=doctypename*somespace*doctypeset - local publicdoctype=doctypename*somespace*P("PUBLIC")*somespace*value*somespace*value*somespace*doctypeset - local systemdoctype=doctypename*somespace*P("SYSTEM")*somespace*value*somespace*doctypeset - local simpledoctype=(anything-close)^1 - local somedoctype=C((somespace*(publicentityfile+publicdoctype+systemdoctype+definitiondoctype+simpledoctype)*optionalspace)^0) - local instruction=(spacing*begininstruction*someinstruction*endinstruction)/function(...) add_special("@pi@",...) end - local comment=(spacing*begincomment*somecomment*endcomment )/function(...) add_special("@cm@",...) end - local cdata=(spacing*begincdata*somecdata*endcdata )/function(...) add_special("@cd@",...) end - local doctype=(spacing*begindoctype*somedoctype*enddoctype )/function(...) add_special("@dt@",...) end - local crap_parsed=anything-beginelement-endelement-emptyelement-begininstruction-begincomment-begincdata-ampersand - local crap_unparsed=anything-beginelement-endelement-emptyelement-begininstruction-begincomment-begincdata - local parsedcrap=Cs((crap_parsed^1+entity_text)^1)/handle_crap_error - local parsedcrap=Cs((crap_parsed^1+entity_text)^1)/handle_crap_error - local unparsedcrap=Cs((crap_unparsed )^1)/handle_crap_error - local trailer=space^0*(text_unparsed/set_message)^0 - local grammar_parsed_text_one=P { "preamble", - preamble=utfbom^0*instruction^0*(doctype+comment+instruction)^0, - } - local grammar_parsed_text_two=P { "followup", - followup=V("parent")*trailer, - parent=beginelement*V("children")^0*endelement, - children=parsedtext+V("parent")+emptyelement+comment+cdata+instruction+parsedcrap, - } - local grammar_unparsed_text=P { "preamble", - preamble=utfbom^0*instruction^0*(doctype+comment+instruction)^0*V("parent")*trailer, - parent=beginelement*V("children")^0*endelement, - children=unparsedtext+V("parent")+emptyelement+comment+cdata+instruction+unparsedcrap, - } - return grammar_parsed_text_one,grammar_parsed_text_two,grammar_unparsed_text -end -local - grammar_parsed_text_one_nop, - grammar_parsed_text_two_nop, - grammar_unparsed_text_nop=install(space,spacing,anything) -local - grammar_parsed_text_one_yes, - grammar_parsed_text_two_yes, - grammar_unparsed_text_yes=install(space_nl,spacing_nl,anything_nl) -local function _xmlconvert_(data,settings,detail) - settings=settings or {} - preparexmlstate(settings) - if settings.linenumbers then - grammar_parsed_text_one=grammar_parsed_text_one_yes - grammar_parsed_text_two=grammar_parsed_text_two_yes - grammar_unparsed_text=grammar_unparsed_text_yes - else - grammar_parsed_text_one=grammar_parsed_text_one_nop - grammar_parsed_text_two=grammar_parsed_text_two_nop - grammar_unparsed_text=grammar_unparsed_text_nop - end - local preprocessor=settings.preprocessor - if data and data~="" and type(preprocessor)=="function" then - data=preprocessor(data,settings) or data - end - if settings.parent_root then - mt=getmetatable(settings.parent_root) - else - initialize_mt(top) - end - level=level+1 - stack[level]=top - top.dt={} - dt=top.dt - nt=0 - if not data or data=="" then - errorstr="empty xml file" - elseif data==true then - errorstr=detail or "problematic xml file" - elseif utfize or resolve then - local m=lpegmatch(grammar_parsed_text_one,data) - if m then - m=lpegmatch(grammar_parsed_text_two,data,m) - end - if m then - else - errorstr="invalid xml file - parsed text" - end - elseif type(data)=="string" then - if lpegmatch(grammar_unparsed_text,data) then - errorstr="" - else - errorstr="invalid xml file - unparsed text" - end - else - errorstr="invalid xml file - no text at all" - end - local result - if errorstr and errorstr~="" then - result={ dt={ { ns="",tg="error",dt={ errorstr },at={},er=true } } } - setmetatable(result,mt) - setmetatable(result.dt[1],mt) - setmetatable(stack,mt) - local errorhandler=settings.error_handler - if errorhandler==false then - else - errorhandler=errorhandler or xml.errorhandler - if errorhandler then - local currentresource=settings.currentresource - if currentresource and currentresource~="" then - xml.errorhandler(formatters["load error in [%s]: %s"](currentresource,errorstr),currentresource) - else - xml.errorhandler(formatters["load error: %s"](errorstr)) - end - end - end - else - result=stack[1] - end - if not settings.no_root then - result={ special=true,ns="",tg='@rt@',dt=result.dt,at={},entities=entities,settings=settings } - setmetatable(result,mt) - local rdt=result.dt - for k=1,#rdt do - local v=rdt[k] - if type(v)=="table" and not v.special then - result.ri=k - v.__p__=result - break - end - end - end - if errorstr and errorstr~="" then - result.error=true - else - errorstr=nil - end - result.statistics={ - errormessage=errorstr, - entities={ - decimals=dcache, - hexadecimals=hcache, - names=acache, - intermediates=parameters, - } - } - preparexmlstate() - return result -end -local function xmlconvert(data,settings) - local ok,result=pcall(function() return _xmlconvert_(data,settings) end) - if ok then - return result - elseif type(result)=="string" then - return _xmlconvert_(true,settings,result) - else - return _xmlconvert_(true,settings) - end -end -xml.convert=xmlconvert -function xml.inheritedconvert(data,xmldata,cleanup) - local settings=xmldata.settings - if settings then - settings.parent_root=xmldata - end - local xc=xmlconvert(data,settings) - if cleanup then - local x=xc.dt - if x then - x=x[1] - if x and x.tg=="@pi@" then - local dt=x.dt - local pi=dt and dt[1] - if type(pi)=="string" and find(pi,"^xml") then - remove(dt,1) - end - end - end - end - return xc -end -function xml.is_valid(root) - return root and root.dt and root.dt[1] and type(root.dt[1])=="table" and not root.dt[1].er -end -function xml.package(tag,attributes,data) - local ns,tg=match(tag,"^(.-):?([^:]+)$") - local t={ ns=ns,tg=tg,dt=data or "",at=attributes or {} } - setmetatable(t,mt) - return t -end -function xml.is_valid(root) - return root and not root.error -end -xml.errorhandler=report_xml -function xml.load(filename,settings) - local data="" - if type(filename)=="string" then - local f=io.open(filename,'r') - if f then - data=f:read("*all") - f:close() - end - elseif filename then - data=filename:read("*all") - end - if settings then - settings.currentresource=filename - local result=xmlconvert(data,settings) - settings.currentresource=nil - return result - else - return xmlconvert(data,{ currentresource=filename }) - end -end -local no_root={ no_root=true } -function xml.toxml(data) - if type(data)=="string" then - local root={ xmlconvert(data,no_root) } - return (#root>1 and root) or root[1] - else - return data - end -end -local function copy(old,p) - if old then - local new={} - for k,v in next,old do - local t=type(v)=="table" - if k=="at" then - local t={} - for k,v in next,v do - t[k]=v - end - new[k]=t - elseif k=="dt" then - v.__p__=nil - local t={} - for i=1,#v do - local vi=v[i] - if type(vi)=="table" then - t[i]=copy(vi,new) - else - t[i]=vi - end - end - new[k]=t - t.__p__=p - else - new[k]=v - end - end - local mt=getmetatable(old) - if mt then - setmetatable(new,mt) - end - return new - else - return {} - end -end -xml.copy=copy -function xml.checkbom(root) - if root.ri then - local dt=root.dt - for k=1,#dt do - local v=dt[k] - if type(v)=="table" and v.special and v.tg=="@pi@" and find(v.dt[1],"xml.*version=") then - return - end - end - insert(dt,1,{ special=true,ns="",tg="@pi@",dt={ "xml version='1.0' standalone='yes'" } } ) - insert(dt,2,"\n" ) - end -end -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 in next,eat do - n=n+1 - ats[n]=k - end - if n==1 then - local k=ats[1] - ats=f_attribute(k,escaped(eat[k])) - else - sort(ats) - for i=1,n do - local k=ats[i] - ats[i]=f_attribute(k,escaped(eat[k])) - end - ats=concat(ats," ") - end - end - if ern and trace_entities and ern~=ens then - ens=ern - end - local n=edt and #edt - if ens~="" then - if n and n>0 then - if ats then - handle("<",ens,":",etg," ",ats,">") - else - handle("<",ens,":",etg,">") - end - for i=1,n do - local e=edt[i] - if type(e)=="string" then - handle(escaped(e)) - else - serialize(e,handlers) - end - end - handle("</",ens,":",etg,">") - else - if ats then - handle("<",ens,":",etg," ",ats,"/>") - else - handle("<",ens,":",etg,"/>") - end - end - else - if n and n>0 then - if ats then - handle("<",etg," ",ats,">") - else - handle("<",etg,">") - end - for i=1,n do - local e=edt[i] - if type(e)=="string" then - handle(escaped(e)) - else - serialize(e,handlers) - end - end - handle("</",etg,">") - else - if ats then - handle("<",etg," ",ats,"/>") - else - handle("<",etg,"/>") - end - end - end -end -local function verbose_pi(e,handlers) - handlers.handle("<?",e.dt[1],"?>") -end -local function verbose_comment(e,handlers) - handlers.handle("<!--",e.dt[1],"-->") -end -local function verbose_cdata(e,handlers) - handlers.handle("<![CDATA[",e.dt[1],"]]>") -end -local function verbose_doctype(e,handlers) - handlers.handle("<!DOCTYPE",e.dt[1],">") -end -local function verbose_root(e,handlers) - handlers.serialize(e.dt,handlers) -end -local function verbose_text(e,handlers) - handlers.handle(escaped(e)) -end -local function verbose_document(e,handlers) - local serialize=handlers.serialize - local functions=handlers.functions - for i=1,#e do - local ei=e[i] - if type(ei)=="string" then - functions["@tx@"](ei,handlers) - else - serialize(ei,handlers) - end - end -end -local function serialize(e,handlers,...) - if e then - local initialize=handlers.initialize - local finalize=handlers.finalize - local functions=handlers.functions - if initialize then - local state=initialize(...) - if not state==true then - return state - end - end - local etg=e.tg - if etg then - (functions[etg] or functions["@el@"])(e,handlers) - else - functions["@dc@"](e,handlers) - end - if finalize then - return finalize() - end - end -end -local function xserialize(e,handlers) - if e then - local functions=handlers.functions - local etg=e.tg - if etg then - (functions[etg] or functions["@el@"])(e,handlers) - else - functions["@dc@"](e,handlers) - end - end -end -local handlers={} -local function newhandlers(settings) - local t=table.copy(handlers[settings and settings.parent or "verbose"] or {}) - if settings then - for k,v in next,settings do - if type(v)=="table" then - local tk=t[k] if not tk then tk={} t[k]=tk end - for kk,vv in next,v do - tk[kk]=vv - end - else - t[k]=v - end - end - if settings.name then - handlers[settings.name]=t - end - end - utilities.storage.mark(t) - return t -end -local nofunction=function() end -function xml.sethandlersfunction(handler,name,fnc) - handler.functions[name]=fnc or nofunction -end -function xml.gethandlersfunction(handler,name) - return handler.functions[name] -end -function xml.gethandlers(name) - return handlers[name] -end -newhandlers { - name="verbose", - initialize=false, - finalize=false, - serialize=xserialize, - handle=print, - functions={ - ["@dc@"]=verbose_document, - ["@dt@"]=verbose_doctype, - ["@rt@"]=verbose_root, - ["@el@"]=verbose_element, - ["@pi@"]=verbose_pi, - ["@cm@"]=verbose_comment, - ["@cd@"]=verbose_cdata, - ["@tx@"]=verbose_text, - } -} -local result -local xmlfilehandler=newhandlers { - name="file", - initialize=function(name) - result=io.open(name,"wb") - return result - end, - finalize=function() - result:close() - return true - end, - handle=function(...) - result:write(...) - end, -} -function xml.save(root,name) - serialize(root,xmlfilehandler,name) -end -local result,r,threshold={},0,512 -local xmlstringhandler=newhandlers { - name="string", - initialize=function() - r=0 - return result - end, - finalize=function() - local done=concat(result,"",1,r) - r=0 - if r>threshold then - result={} - end - return done - end, - handle=function(...) - for i=1,select("#",...) do - r=r+1 - result[r]=select(i,...) - end - end, -} -local function xmltostring(root) - if not root then - return "" - elseif type(root)=="string" then - return root - else - return serialize(root,xmlstringhandler) or "" - end -end -local function __tostring(root) - return (root and xmltostring(root)) or "" -end -initialize_mt=function(root) - mt={ __tostring=__tostring,__index=root } -end -xml.defaulthandlers=handlers -xml.newhandlers=newhandlers -xml.serialize=serialize -xml.tostring=xmltostring -local function xmlstring(e,handle) - if not handle or (e.special and e.tg~="@rt@") then - elseif e.tg then - local edt=e.dt - if edt then - for i=1,#edt do - xmlstring(edt[i],handle) - end - end - else - handle(e) - end -end -xml.string=xmlstring -function xml.settings(e) - while e do - local s=e.settings - if s then - return s - else - e=e.__p__ - end - end - return nil -end -function xml.root(e) - local r=e - while e do - e=e.__p__ - if e then - r=e - end - end - return r -end -function xml.parent(root) - return root.__p__ -end -function xml.body(root) - return root.ri and root.dt[root.ri] or root -end -function xml.name(root) - if not root then - return "" - end - local ns=root.ns - local tg=root.tg - if ns=="" then - return tg - else - return ns..":"..tg - end -end -function xml.erase(dt,k) - if dt then - if k then - dt[k]="" - else for k=1,#dt do - dt[1]={ "" } - end end - end -end -function xml.assign(dt,k,root) - if dt and k then - dt[k]=type(root)=="table" and xml.body(root) or root - return dt[k] - else - return xml.body(root) - end -end -function xml.tocdata(e,wrapper) - local whatever=type(e)=="table" and xmltostring(e.dt) or e or "" - if wrapper then - whatever=formatters["<%s>%s</%s>"](wrapper,whatever,wrapper) - end - local t={ special=true,ns="",tg="@cd@",at={},rn="",dt={ whatever },__p__=e } - setmetatable(t,getmetatable(e)) - e.dt={ t } -end -function xml.makestandalone(root) - if root.ri then - local dt=root.dt - for k=1,#dt do - local v=dt[k] - if type(v)=="table" and v.special and v.tg=="@pi@" then - local txt=v.dt[1] - if find(txt,"xml.*version=") then - v.dt[1]=txt.." standalone='yes'" - break - end - end - end - end - return root -end -function xml.kind(e) - local dt=e and e.dt - if dt then - local n=#dt - if n==1 then - local d=dt[1] - if d.special then - local tg=d.tg - if tg=="@cd@" then - return "cdata" - elseif tg=="@cm@" then - return "comment" - elseif tg=="@pi@" then - return "instruction" - elseif tg=="@dt@" then - return "declaration" - end - elseif type(d)=="string" then - return "text" - end - return "element" - elseif n>0 then - return "mixed" - end - end - return "empty" -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["lxml-lpt"] = package.loaded["lxml-lpt"] or true - --- original size: 54733, stripped down to: 31258 - -if not modules then modules={} end modules ['lxml-lpt']={ - version=1.001, - comment="this module is the basis for the lxml-* ones", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local concat,remove,insert=table.concat,table.remove,table.insert -local type,next,tonumber,tostring,setmetatable,load,select=type,next,tonumber,tostring,setmetatable,load,select -local format,upper,lower,gmatch,gsub,find,rep=string.format,string.upper,string.lower,string.gmatch,string.gsub,string.find,string.rep -local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns -local setmetatableindex=table.setmetatableindex -local formatters=string.formatters -local trace_lpath=false -local trace_lparse=false -local trace_lprofile=false -local report_lpath=logs.reporter("xml","lpath") -if trackers then - trackers.register("xml.path",function(v) - trace_lpath=v - end) - trackers.register("xml.parse",function(v) - trace_lparse=v - end) - trackers.register("xml.profile",function(v) - trace_lpath=v - trace_lparse=v - trace_lprofile=v - end) -end -local xml=xml -local lpathcalls=0 function xml.lpathcalls () return lpathcalls end -local lpathcached=0 function xml.lpathcached() return lpathcached end -xml.functions=xml.functions or {} -local functions=xml.functions -xml.expressions=xml.expressions or {} -local expressions=xml.expressions -xml.finalizers=xml.finalizers or {} -local finalizers=xml.finalizers -xml.specialhandler=xml.specialhandler or {} -local specialhandler=xml.specialhandler -lpegpatterns.xml=lpegpatterns.xml or {} -local xmlpatterns=lpegpatterns.xml -finalizers.xml=finalizers.xml or {} -finalizers.tex=finalizers.tex or {} -local function fallback (t,name) - local fn=finalizers[name] - if fn then - t[name]=fn - else - report_lpath("unknown sub finalizer %a",name) - fn=function() end - end - return fn -end -setmetatableindex(finalizers.xml,fallback) -setmetatableindex(finalizers.tex,fallback) -xml.defaultprotocol="xml" -local apply_axis={} -apply_axis['root']=function(list) - local collected={} - for l=1,#list do - local ll=list[l] - local rt=ll - while ll do - ll=ll.__p__ - if ll then - rt=ll - end - end - collected[l]=rt - end - return collected -end -apply_axis['self']=function(list) - return list -end -apply_axis['child']=function(list) - local collected={} - local c=0 - for l=1,#list do - local ll=list[l] - local dt=ll.dt - if dt then - local n=#dt - if n==0 then - ll.en=0 - elseif n==1 then - local dk=dt[1] - if dk.tg then - c=c+1 - collected[c]=dk - dk.ni=1 - dk.ei=1 - ll.en=1 - end - else - local en=0 - for k=1,#dt do - local dk=dt[k] - if dk.tg then - c=c+1 - en=en+1 - collected[c]=dk - dk.ni=k - dk.ei=en - end - end - ll.en=en - end - end - end - return collected -end -local function collect(list,collected,c) - local dt=list.dt - if dt then - local n=#dt - if n==0 then - list.en=0 - elseif n==1 then - local dk=dt[1] - if dk.tg then - c=c+1 - collected[c]=dk - dk.ni=1 - dk.ei=1 - c=collect(dk,collected,c) - list.en=1 - else - list.en=0 - end - else - local en=0 - for k=1,n do - local dk=dt[k] - if dk.tg then - c=c+1 - en=en+1 - collected[c]=dk - dk.ni=k - dk.ei=en - c=collect(dk,collected,c) - end - end - list.en=en - end - end - return c -end -apply_axis['descendant']=function(list) - local collected={} - local c=0 - for l=1,#list do - c=collect(list[l],collected,c) - end - return collected -end -local function collect(list,collected,c) - local dt=list.dt - if dt then - local n=#dt - if n==0 then - list.en=0 - elseif n==1 then - local dk=dt[1] - if dk.tg then - c=c+1 - collected[c]=dk - dk.ni=1 - dk.ei=1 - c=collect(dk,collected,c) - list.en=1 - end - else - local en=0 - for k=1,#dt do - local dk=dt[k] - if dk.tg then - c=c+1 - en=en+1 - collected[c]=dk - dk.ni=k - dk.ei=en - c=collect(dk,collected,c) - end - end - list.en=en - end - end - return c -end -apply_axis['descendant-or-self']=function(list) - local collected={} - local c=0 - for l=1,#list do - local ll=list[l] - if ll.special~=true then - c=c+1 - collected[c]=ll - end - c=collect(ll,collected,c) - end - return collected -end -apply_axis['ancestor']=function(list) - local collected={} - local c=0 - for l=1,#list do - local ll=list[l] - while ll do - ll=ll.__p__ - if ll then - c=c+1 - collected[c]=ll - end - end - end - return collected -end -apply_axis['ancestor-or-self']=function(list) - local collected={} - local c=0 - for l=1,#list do - local ll=list[l] - c=c+1 - collected[c]=ll - while ll do - ll=ll.__p__ - if ll then - c=c+1 - collected[c]=ll - end - end - end - return collected -end -apply_axis['parent']=function(list) - local collected={} - local c=0 - for l=1,#list do - local pl=list[l].__p__ - if pl then - c=c+1 - collected[c]=pl - end - end - return collected -end -apply_axis['attribute']=function(list) - return {} -end -apply_axis['namespace']=function(list) - return {} -end -apply_axis['following']=function(list) - return {} -end -apply_axis['preceding']=function(list) - return {} -end -apply_axis['following-sibling']=function(list) - local collected={} - local c=0 - for l=1,#list do - local ll=list[l] - local p=ll.__p__ - local d=p.dt - for i=ll.ni+1,#d do - local di=d[i] - if type(di)=="table" then - c=c+1 - collected[c]=di - end - end - end - return collected -end -apply_axis['preceding-sibling']=function(list) - local collected={} - local c=0 - for l=1,#list do - local ll=list[l] - local p=ll.__p__ - local d=p.dt - for i=1,ll.ni-1 do - local di=d[i] - if type(di)=="table" then - c=c+1 - collected[c]=di - end - end - end - return collected -end -apply_axis['reverse-sibling']=function(list) - local collected={} - local c=0 - for l=1,#list do - local ll=list[l] - local p=ll.__p__ - local d=p.dt - for i=ll.ni-1,1,-1 do - local di=d[i] - if type(di)=="table" then - c=c+1 - collected[c]=di - end - end - end - return collected -end -apply_axis['auto-descendant-or-self']=apply_axis['descendant-or-self'] -apply_axis['auto-descendant']=apply_axis['descendant'] -apply_axis['auto-child']=apply_axis['child'] -apply_axis['auto-self']=apply_axis['self'] -apply_axis['initial-child']=apply_axis['child'] -local function apply_nodes(list,directive,nodes) - local maxn=#nodes - if maxn==3 then - local nns=nodes[2] - local ntg=nodes[3] - if not nns and not ntg then - if directive then - return list - else - return {} - end - else - local collected={} - local c=0 - local m=0 - local p=nil - if not nns then - for l=1,#list do - local ll=list[l] - local ltg=ll.tg - if ltg then - if directive then - if ntg==ltg then - local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end - c=c+1 - collected[c]=ll - ll.mi=m - end - elseif ntg~=ltg then - local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end - c=c+1 - collected[c]=ll - ll.mi=m - end - end - end - elseif not ntg then - for l=1,#list do - local ll=list[l] - local lns=ll.rn or ll.ns - if lns then - if directive then - if lns==nns then - local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end - c=c+1 - collected[c]=ll - ll.mi=m - end - elseif lns~=nns then - local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end - c=c+1 - collected[c]=ll - ll.mi=m - end - end - end - else - for l=1,#list do - local ll=list[l] - local ltg=ll.tg - if ltg then - local lns=ll.rn or ll.ns - local ok=ltg==ntg and lns==nns - if directive then - if ok then - local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end - c=c+1 - collected[c]=ll - ll.mi=m - end - elseif not ok then - local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end - c=c+1 - collected[c]=ll - ll.mi=m - end - end - end - end - return collected - end - else - local collected={} - local c=0 - local m=0 - local p=nil - for l=1,#list do - local ll=list[l] - local ltg=ll.tg - if ltg then - local lns=ll.rn or ll.ns - local ok=false - for n=1,maxn,3 do - local nns=nodes[n+1] - local ntg=nodes[n+2] - ok=(not ntg or ltg==ntg) and (not nns or lns==nns) - if ok then - break - end - end - if directive then - if ok then - local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end - c=c+1 - collected[c]=ll - ll.mi=m - end - elseif not ok then - local llp=ll.__p__;if llp~=p then p=llp;m=1 else m=m+1 end - c=c+1 - collected[c]=ll - ll.mi=m - end - end - end - return collected - end -end -local quit_expression=false -local function apply_expression(list,expression,order) - local collected={} - local c=0 - quit_expression=false - for l=1,#list do - local ll=list[l] - if expression(list,ll,l,order) then - c=c+1 - collected[c]=ll - end - if quit_expression then - break - end - end - return collected -end -local function apply_selector(list,specification) - if xml.applyselector then - apply_selector=xml.applyselector - return apply_selector(list,specification) - else - return list - end -end -local P,V,C,Cs,Cc,Ct,R,S,Cg,Cb=lpeg.P,lpeg.V,lpeg.C,lpeg.Cs,lpeg.Cc,lpeg.Ct,lpeg.R,lpeg.S,lpeg.Cg,lpeg.Cb -local spaces=S(" \n\r\t\f")^0 -local lp_space=S(" \n\r\t\f") -local lp_any=P(1) -local lp_noequal=P("!=")/"~="+P("<=")+P(">=")+P("==") -local lp_doequal=P("=")/"==" -local lp_or=P("|")/" or " -local lp_and=P("&")/" and " -local builtin={ - text="(ll.dt[1] or '')", - content="ll.dt", - name="((ll.ns~='' and ll.ns..':'..ll.tg) or ll.tg)", - tag="ll.tg", - position="l", - firstindex="1", - firstelement="1", - first="1", - lastindex="(#ll.__p__.dt or 1)", - lastelement="(ll.__p__.en or 1)", - last="#list", - list="list", - self="ll", - rootposition="order", - order="order", - element="(ll.ei or 1)", - index="(ll.ni or 1)", - match="(ll.mi or 1)", - namespace="ll.ns", - ns="ll.ns", -} -local lp_builtin=lpeg.utfchartabletopattern(builtin)/builtin*((spaces*P("(")*spaces*P(")"))/"") -local lp_attribute=(P("@")+P("attribute::"))/""*Cc("(ll.at and ll.at['")*((R("az","AZ")+S("-_:"))^1)*Cc("'])") -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+1==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" -local lp_function=C(R("az","AZ","__")^1)*P("(")/function(t) - if expressions[t] then - return "expr."..t.."(" - else - return "expr.error(" - end -end -local lparent=P("(") -local rparent=P(")") -local noparent=1-(lparent+rparent) -local nested=P{lparent*(noparent+V(1))^0*rparent} -local value=P(lparent*C((noparent+nested)^0)*rparent) -local lp_child=Cc("expr.child(ll,'")*R("az","AZ")*R("az","AZ","--","__")^0*Cc("')") -local lp_number=S("+-")*R("09")^1 -local lp_string=Cc("'")*R("az","AZ","--","__")^1*Cc("'") -local lp_content=(P("'")*(1-P("'"))^0*P("'")+P('"')*(1-P('"'))^0*P('"')) -local cleaner -local lp_special=(C(P("name")+P("text")+P("tag")+P("count")+P("child")))*value/function(t,s) - if expressions[t] then - s=s and s~="" and lpegmatch(cleaner,s) - if s and s~="" then - return "expr."..t.."(ll,"..s..")" - else - return "expr."..t.."(ll)" - end - else - return "expr.error("..t..")" - end -end -local content=lp_builtin+lp_attribute+lp_special+lp_noequal+lp_doequal+lp_or+lp_and+lp_reserved+lp_lua_function+lp_function+lp_content+ - lp_child+lp_any -local converter=Cs ( - lp_fastpos+(P { lparent*(V(1))^0*rparent+content } )^0 -) -cleaner=Cs (( - lp_reserved+lp_number+lp_string+1 )^1 ) -local template_e=[[ - local expr = xml.expressions - return function(list,ll,l,order) - return %s - end -]] -local template_f_y=[[ - local finalizer = xml.finalizers['%s']['%s'] - return function(collection) - return finalizer(collection,%s) - end -]] -local template_f_n=[[ - return xml.finalizers['%s']['%s'] -]] -local register_last_match={ kind="axis",axis="last-match" } -local register_self={ kind="axis",axis="self" } -local register_parent={ kind="axis",axis="parent" } -local register_descendant={ kind="axis",axis="descendant" } -local register_child={ kind="axis",axis="child" } -local register_descendant_or_self={ kind="axis",axis="descendant-or-self" } -local register_root={ kind="axis",axis="root" } -local register_ancestor={ kind="axis",axis="ancestor" } -local register_ancestor_or_self={ kind="axis",axis="ancestor-or-self" } -local register_attribute={ kind="axis",axis="attribute" } -local register_namespace={ kind="axis",axis="namespace" } -local register_following={ kind="axis",axis="following" } -local register_following_sibling={ kind="axis",axis="following-sibling" } -local register_preceding={ kind="axis",axis="preceding" } -local register_preceding_sibling={ kind="axis",axis="preceding-sibling" } -local register_reverse_sibling={ kind="axis",axis="reverse-sibling" } -local register_auto_descendant_or_self={ kind="axis",axis="auto-descendant-or-self" } -local register_auto_descendant={ kind="axis",axis="auto-descendant" } -local register_auto_self={ kind="axis",axis="auto-self" } -local register_auto_child={ kind="axis",axis="auto-child" } -local register_initial_child={ kind="axis",axis="initial-child" } -local register_all_nodes={ kind="nodes",nodetest=true,nodes={ true,false,false } } -local skip={} -local function errorrunner_e(str,cnv) - if not skip[str] then - report_lpath("error in expression: %s => %s",str,cnv) - skip[str]=cnv or str - end - return false -end -local function errorrunner_f(str,arg) - report_lpath("error in finalizer: %s(%s)",str,arg or "") - return false -end -local function register_nodes(nodetest,nodes) - return { kind="nodes",nodetest=nodetest,nodes=nodes } -end -local function register_selector(specification) - return { kind="selector",specification=specification } -end -local function register_expression(expression) - local converted=lpegmatch(converter,expression) - local wrapped=format(template_e,converted) - local runner=load(wrapped) - runner=(runner and runner()) or function() errorrunner_e(expression,converted) end - return { kind="expression",expression=expression,converted=converted,evaluator=runner } -end -local function register_finalizer(protocol,name,arguments) - local runner - if arguments and arguments~="" then - runner=load(format(template_f_y,protocol or xml.defaultprotocol,name,arguments)) - else - runner=load(format(template_f_n,protocol or xml.defaultprotocol,name)) - end - runner=(runner and runner()) or function() errorrunner_f(name,arguments) end - return { kind="finalizer",name=name,arguments=arguments,finalizer=runner } -end -local expression=P { "ex", - ex="["*C((V("sq")+V("dq")+(1-S("[]"))+V("ex"))^0)*"]", - sq="'"*(1-S("'"))^0*"'", - dq='"'*(1-S('"'))^0*'"', -} -local arguments=P { "ar", - ar="("*Cs((V("sq")+V("dq")+V("nq")+P(1-P(")")))^0)*")", - nq=((1-S("),'\""))^1)/function(s) return format("%q",s) end, - sq=P("'")*(1-P("'"))^0*P("'"), - dq=P('"')*(1-P('"'))^0*P('"'), -} -local function register_error(str) - return { kind="error",error=format("unparsed: %s",str) } -end -local special_1=P("*")*Cc(register_auto_descendant)*Cc(register_all_nodes) -local special_2=P("/")*Cc(register_auto_self) -local special_3=P("")*Cc(register_auto_self) -local no_nextcolon=P(-1)+#(1-P(":")) -local no_nextlparent=P(-1)+#(1-P("(")) -local pathparser=Ct { "patterns", - patterns=spaces*V("protocol")*spaces*( - (V("special")*spaces*P(-1) )+(V("initial")*spaces*V("step")*spaces*(P("/")*spaces*V("step")*spaces)^0 ) - ), - protocol=Cg(V("letters"),"protocol")*P("://")+Cg(Cc(nil),"protocol"), - step=((V("shortcuts")+V("selector")+P("/")+V("axis"))*spaces*V("nodes")^0+V("error"))*spaces*V("expressions")^0*spaces*V("finalizer")^0, - axis=V("last_match")+V("descendant")+V("child")+V("parent")+V("self")+V("root")+V("ancestor")+V("descendant_or_self")+V("following_sibling")+V("following")+V("reverse_sibling")+V("preceding_sibling")+V("preceding")+V("ancestor_or_self")+#(1-P(-1))*Cc(register_auto_child), - special=special_1+special_2+special_3, - initial=(P("/")*spaces*Cc(register_initial_child))^-1, - error=(P(1)^1)/register_error, - shortcuts_a=V("s_descendant_or_self")+V("s_descendant")+V("s_child")+V("s_parent")+V("s_self")+V("s_root")+V("s_ancestor")+V("s_lastmatch"), - shortcuts=V("shortcuts_a")*(spaces*"/"*spaces*V("shortcuts_a"))^0, - s_descendant_or_self=(P("***/")+P("/"))*Cc(register_descendant_or_self), - s_descendant=P("**")*Cc(register_descendant), - s_child=P("*")*no_nextcolon*Cc(register_child), - s_parent=P("..")*Cc(register_parent), - s_self=P("." )*Cc(register_self), - s_root=P("^^")*Cc(register_root), - s_ancestor=P("^")*Cc(register_ancestor), - s_lastmatch=P("=")*Cc(register_last_match), - descendant=P("descendant::")*Cc(register_descendant), - child=P("child::")*Cc(register_child), - parent=P("parent::")*Cc(register_parent), - self=P("self::")*Cc(register_self), - root=P('root::')*Cc(register_root), - ancestor=P('ancestor::')*Cc(register_ancestor), - descendant_or_self=P('descendant-or-self::')*Cc(register_descendant_or_self), - ancestor_or_self=P('ancestor-or-self::')*Cc(register_ancestor_or_self), - following=P('following::')*Cc(register_following), - following_sibling=P('following-sibling::')*Cc(register_following_sibling), - preceding=P('preceding::')*Cc(register_preceding), - preceding_sibling=P('preceding-sibling::')*Cc(register_preceding_sibling), - reverse_sibling=P('reverse-sibling::')*Cc(register_reverse_sibling), - last_match=P('last-match::')*Cc(register_last_match), - selector=P("{")*C((1-P("}"))^1)*P("}")/register_selector, - nodes=(V("nodefunction")*spaces*P("(")*V("nodeset")*P(")")+V("nodetest")*V("nodeset"))/register_nodes, - expressions=expression/register_expression, - letters=R("az")^1, - name=(1-S("/[]()|:*!"))^1, - negate=P("!")*Cc(false), - nodefunction=V("negate")+P("not")*Cc(false)+Cc(true), - nodetest=V("negate")+Cc(true), - nodename=(V("negate")+Cc(true))*spaces*((V("wildnodename")*P(":")*V("wildnodename"))+(Cc(false)*V("wildnodename"))), - wildnodename=(C(V("name"))+P("*")*Cc(false))*no_nextlparent, - nodeset=spaces*Ct(V("nodename")*(spaces*P("|")*spaces*V("nodename"))^0)*spaces, - finalizer=(Cb("protocol")*P("/")^-1*C(V("name"))*arguments*P(-1))/register_finalizer, -} -xmlpatterns.pathparser=pathparser -local cache={} -local function nodesettostring(set,nodetest) - local t={} - for i=1,#set,3 do - local directive,ns,tg=set[i],set[i+1],set[i+2] - 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[#t+1]=(directive and tg) or format("not(%s)",tg) - end - if nodetest==false then - return format("not(%s)",concat(t,"|")) - else - return concat(t,"|") - end -end -local function tagstostring(list) - if #list==0 then - return "no elements" - else - local t={} - for i=1,#list do - local li=list[i] - local ns=li.ns - local tg=li.tg - if not ns or ns=="" then ns="*" end - if not tg or tg=="" then tg="*" end - t[i]=(tg=="@rt@" and "[root]") or format("%s:%s",ns,tg) - end - return concat(t," ") - end -end -xml.nodesettostring=nodesettostring -local lpath -local function lshow(parsed) - if type(parsed)=="string" then - parsed=lpath(parsed) - end - report_lpath("%s://%s => %s",parsed.protocol or xml.defaultprotocol,parsed.pattern, - table.serialize(parsed,false)) -end -xml.lshow=lshow -local function add_comment(p,str) - local pc=p.comment - if not pc then - p.comment={ str } - else - pc[#pc+1]=str - end -end -lpath=function (pattern) - lpathcalls=lpathcalls+1 - if type(pattern)=="table" then - return pattern - else - local parsed=cache[pattern] - if parsed then - lpathcached=lpathcached+1 - else - parsed=lpegmatch(pathparser,pattern) - if parsed then - parsed.pattern=pattern - local np=#parsed - if np==0 then - parsed={ pattern=pattern,register_self,state="parsing error" } - report_lpath("parsing error in pattern: %s",pattern) - lshow(parsed) - else - local pi=parsed[1] - if pi.axis=="auto-child" then - if false then - add_comment(parsed,"auto-child replaced by auto-descendant-or-self") - parsed[1]=register_auto_descendant_or_self - else - add_comment(parsed,"auto-child replaced by auto-descendant") - parsed[1]=register_auto_descendant - end - elseif pi.axis=="initial-child" and np>1 and parsed[2].axis then - add_comment(parsed,"initial-child removed") - remove(parsed,1) - end - local np=#parsed - if np>1 then - local pnp=parsed[np] - if pnp.kind=="nodes" and pnp.nodetest==true then - local nodes=pnp.nodes - if nodes[1]==true and nodes[2]==false and nodes[3]==false then - add_comment(parsed,"redundant final wildcard filter removed") - remove(parsed,np) - end - end - end - end - else - parsed={ pattern=pattern } - end - cache[pattern]=parsed - if trace_lparse and not trace_lprofile then - lshow(parsed) - end - end - return parsed - end -end -xml.lpath=lpath -do - local profiled={} - xml.profiled=profiled - local lastmatch=nil - local keepmatch=nil - if directives then - directives.register("xml.path.keeplastmatch",function(v) - keepmatch=v - lastmatch=nil - end) - end - apply_axis["last-match"]=function() - return lastmatch or {} - end - local function profiled_apply(list,parsed,nofparsed,order) - local p=profiled[parsed.pattern] - if p then - p.tested=p.tested+1 - else - p={ tested=1,matched=0,finalized=0 } - profiled[parsed.pattern]=p - end - local collected=list - for i=1,nofparsed do - local pi=parsed[i] - local kind=pi.kind - if kind=="axis" then - collected=apply_axis[pi.axis](collected) - elseif kind=="nodes" then - collected=apply_nodes(collected,pi.nodetest,pi.nodes) - elseif kind=="expression" then - collected=apply_expression(collected,pi.evaluator,order) - elseif kind=="selector" then - collected=apply_selector(collected,pi.specification) - elseif kind=="finalizer" then - collected=pi.finalizer(collected) - p.matched=p.matched+1 - p.finalized=p.finalized+1 - return collected - end - if not collected or #collected==0 then - local pn=i<nofparsed and parsed[nofparsed] - if pn and pn.kind=="finalizer" then - collected=pn.finalizer(collected) - p.finalized=p.finalized+1 - return collected - end - return nil - end - end - if collected then - p.matched=p.matched+1 - end - return collected - end - local function traced_apply(list,parsed,nofparsed,order) - if trace_lparse then - lshow(parsed) - end - report_lpath("collecting: %s",parsed.pattern) - report_lpath("root tags : %s",tagstostring(list)) - report_lpath("order : %s",order or "unset") - local collected=list - for i=1,nofparsed do - local pi=parsed[i] - local kind=pi.kind - if kind=="axis" then - collected=apply_axis[pi.axis](collected) - report_lpath("% 10i : ax : %s",(collected and #collected) or 0,pi.axis) - elseif kind=="nodes" then - collected=apply_nodes(collected,pi.nodetest,pi.nodes) - report_lpath("% 10i : ns : %s",(collected and #collected) or 0,nodesettostring(pi.nodes,pi.nodetest)) - elseif kind=="expression" then - collected=apply_expression(collected,pi.evaluator,order) - report_lpath("% 10i : ex : %s -> %s",(collected and #collected) or 0,pi.expression,pi.converted) - elseif kind=="selector" then - collected=apply_selector(collected,pi.specification) - report_lpath("% 10i : se : %s ",(collected and #collected) or 0,pi.specification) - elseif kind=="finalizer" then - collected=pi.finalizer(collected) - report_lpath("% 10i : fi : %s : %s(%s)",(type(collected)=="table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pi.name,pi.arguments or "") - return collected - end - if not collected or #collected==0 then - local pn=i<nofparsed and parsed[nofparsed] - if pn and pn.kind=="finalizer" then - collected=pn.finalizer(collected) - report_lpath("% 10i : fi : %s : %s(%s)",(type(collected)=="table" and #collected) or 0,parsed.protocol or xml.defaultprotocol,pn.name,pn.arguments or "") - return collected - end - return nil - end - end - return collected - end - local function normal_apply(list,parsed,nofparsed,order) - local collected=list - for i=1,nofparsed do - local pi=parsed[i] - local kind=pi.kind - if kind=="axis" then - local axis=pi.axis - if axis~="self" then - collected=apply_axis[axis](collected) - end - elseif kind=="nodes" then - collected=apply_nodes(collected,pi.nodetest,pi.nodes) - elseif kind=="expression" then - collected=apply_expression(collected,pi.evaluator,order) - elseif kind=="selector" then - collected=apply_selector(collected,pi.specification) - elseif kind=="finalizer" then - return pi.finalizer(collected) - end - if not collected or #collected==0 then - local pf=i<nofparsed and parsed[nofparsed].finalizer - if pf then - return pf(collected) - end - return nil - end - end - return collected - end - local apply=normal_apply - if trackers then - trackers.register("xml.path,xml.parse,xml.profile",function() - if trace_lprofile then - apply=profiled_apply - elseif trace_lpath then - apply=traced_apply - else - apply=normal_apply - end - end) - end - function xml.applylpath(list,pattern) - if not list then - lastmatch=nil - return - end - local parsed=cache[pattern] - if parsed then - lpathcalls=lpathcalls+1 - lpathcached=lpathcached+1 - elseif type(pattern)=="table" then - lpathcalls=lpathcalls+1 - parsed=pattern - else - parsed=lpath(pattern) or pattern - end - if not parsed then - lastmatch=nil - return - end - local nofparsed=#parsed - if nofparsed==0 then - lastmatch=nil - return - end - local collected=apply({ list },parsed,nofparsed,list.mi) - lastmatch=keepmatch and collected or nil - return collected - end - function xml.lastmatch() - return lastmatch - end - local stack={} - function xml.pushmatch() - insert(stack,lastmatch) - end - function xml.popmatch() - lastmatch=remove(stack) - end -end -local applylpath=xml.applylpath -function xml.filter(root,pattern) - return applylpath(root,pattern) -end -expressions.child=function(e,pattern) - return applylpath(e,pattern) -end -expressions.count=function(e,pattern) - local collected=applylpath(e,pattern) - return pattern and (collected and #collected) or 0 -end -expressions.attribute=function(e,name,value) - if type(e)=="table" and name then - local a=e.at - if a then - local v=a[name] - if value then - return v==value - else - return v - end - end - end - return nil -end -expressions.oneof=function(s,...) - for i=1,select("#",...) do - if s==select(i,...) then - return true - end - end - return false -end -expressions.error=function(str) - xml.errorhandler(format("unknown function in lpath expression: %s",tostring(str or "?"))) - return false -end -expressions.undefined=function(s) - return s==nil -end -expressions.quit=function(s) - if s or s==nil then - quit_expression=true - end - return true -end -expressions.print=function(...) - print(...) - return true -end -expressions.find=find -expressions.upper=upper -expressions.lower=lower -expressions.number=tonumber -expressions.boolean=toboolean -function expressions.contains(str,pattern) - local t=type(str) - if t=="string" then - if find(str,pattern) then - return true - end - elseif t=="table" then - for i=1,#str do - local d=str[i] - if type(d)=="string" and find(d,pattern) then - return true - end - end - end - return false -end -function 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 - for c=1,#collected do - local e=collected[c] - local r=e.__p__ - handle(r,r.dt,e.ni) - end - end -end -local function selection(root,pattern,handle) - local collected=applylpath(root,pattern) - if collected then - if handle then - for c=1,#collected do - handle(collected[c]) - end - else - return collected - end - end -end -xml.traverse=traverse -xml.selection=selection -local function dofunction(collected,fnc,...) - if collected then - local f=functions[fnc] - if f then - for c=1,#collected do - f(collected[c],...) - end - else - report_lpath("unknown function %a",fnc) - end - end -end -finalizers.xml["function"]=dofunction -finalizers.tex["function"]=dofunction -expressions.text=function(e,n) - local rdt=e.__p__.dt - return rdt and rdt[n] or "" -end -expressions.name=function(e,n) - local found=false - n=tonumber(n) or 0 - if n==0 then - found=type(e)=="table" and e - elseif n<0 then - local d=e.__p__.dt - local k=e.ni - for i=k-1,1,-1 do - local di=d[i] - if type(di)=="table" then - if n==-1 then - found=di - break - else - n=n+1 - end - end - end - else - local d=e.__p__.dt - local k=e.ni - for i=k+1,#d,1 do - local di=d[i] - if type(di)=="table" then - if n==1 then - found=di - break - else - n=n-1 - end - end - end - end - if found then - local ns=found.rn or found.ns or "" - local tg=found.tg - if ns~="" then - return ns..":"..tg - else - return tg - end - else - return "" - end -end -expressions.tag=function(e,n) - if not e then - return "" - else - local found=false - n=tonumber(n) or 0 - if n==0 then - found=(type(e)=="table") and e - elseif n<0 then - local d=e.__p__.dt - local k=e.ni - for i=k-1,1,-1 do - local di=d[i] - if type(di)=="table" then - if n==-1 then - found=di - break - else - n=n+1 - end - end - end - else - local d=e.__p__.dt - local k=e.ni - for i=k+1,#d,1 do - local di=d[i] - if type(di)=="table" then - if n==1 then - found=di - break - else - n=n-1 - end - end - end - end - return (found and found.tg) or "" - end -end -local dummy=function() end -function xml.elements(root,pattern,reverse) - local collected=applylpath(root,pattern) - if not collected then - return dummy - end - local n=#collected - if n==0 then - return dummy - end - if reverse then - local c=n+1 - return function() - if c>1 then - c=c-1 - local e=collected[c] - local r=e.__p__ - return r,r.dt,e.ni - end - end - else - local c=0 - return function() - if c<n then - c=c+1 - local e=collected[c] - local r=e.__p__ - return r,r.dt,e.ni - end - end - end -end -function xml.collected(root,pattern,reverse) - local collected=applylpath(root,pattern) - if not collected then - return dummy - end - local n=#collected - if n==0 then - return dummy - end - if reverse then - local c=n+1 - return function() - if c>1 then - c=c-1 - return collected[c] - end - end - else - local c=0 - return function() - if c<n then - c=c+1 - return collected[c] - end - end - end -end -function xml.inspect(collection,pattern) - pattern=pattern or "." - for e in xml.collected(collection,pattern or ".") do - report_lpath("pattern: %s\n\n%s\n",pattern,xml.tostring(e)) - end -end -local function split(e) - local dt=e.dt - if dt then - for i=1,#dt do - local dti=dt[i] - if type(dti)=="string" then - dti=gsub(dti,"^[\n\r]*(.-)[\n\r]*","%1") - dti=gsub(dti,"[\n\r]+","\n\n") - dt[i]=dti - else - split(dti) - end - end - end - return e -end -function xml.finalizers.paragraphs(c) - for i=1,#c do - split(c[i]) - end - return c -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["lxml-mis"] = package.loaded["lxml-mis"] or true - --- original size: 3574, stripped down to: 1808 - -if not modules then modules={} end modules ['lxml-mis']={ - version=1.001, - comment="this module is the basis for the lxml-* ones", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local xml,lpeg,string=xml,lpeg,string -local type=type -local concat=table.concat -local format,gsub,match=string.format,string.gsub,string.match -local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns -local P,S,R,C,V,Cc,Cs=lpeg.P,lpeg.S,lpeg.R,lpeg.C,lpeg.V,lpeg.Cc,lpeg.Cs -lpegpatterns.xml=lpegpatterns.xml or {} -local xmlpatterns=lpegpatterns.xml -local function xmlgsub(t,old,new) - local dt=t.dt - if dt then - for k=1,#dt do - local v=dt[k] - if type(v)=="string" then - dt[k]=gsub(v,old,new) - else - xmlgsub(v,old,new) - end - end - end -end -function xml.stripleadingspaces(dk,d,k) - if d and k then - local dkm=d[k-1] - if dkm and type(dkm)=="string" then - local s=match(dkm,"\n(%s+)") - xmlgsub(dk,"\n"..rep(" ",#s),"\n") - end - end -end -local normal=(1-S("<&>"))^0 -local special=P("<")/"<"+P(">")/">"+P("&")/"&" -local escaped=Cs(normal*(special*normal)^0) -local normal=(1-S"&")^0 -local special=P("<")/"<"+P(">")/">"+P("&")/"&" -local unescaped=Cs(normal*(special*normal)^0) -local cleansed=Cs(((P("<")*(1-P(">"))^0*P(">"))/""+1)^0) -xmlpatterns.escaped=escaped -xmlpatterns.unescaped=unescaped -xmlpatterns.cleansed=cleansed -function xml.escaped (str) return lpegmatch(escaped,str) end -function xml.unescaped(str) return lpegmatch(unescaped,str) end -function xml.cleansed (str) return lpegmatch(cleansed,str) end -function xml.fillin(root,pattern,str,check) - local e=xml.first(root,pattern) - if e then - local n=#e.dt - if not check or n==0 or (n==1 and e.dt[1]=="") then - e.dt={ str } - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["lxml-aux"] = package.loaded["lxml-aux"] or true - --- original size: 34661, stripped down to: 21511 - -if not modules then modules={} end modules ['lxml-aux']={ - version=1.001, - comment="this module is the basis for the lxml-* ones", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - 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 xmlcopy,xmlname=xml.copy,xml.name -local xmlinheritedconvert=xml.inheritedconvert -local xmlapplylpath=xml.applylpath -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,match=string.gmatch,string.gsub,string.format,string.find,string.strip,string.match -local utfbyte=utf.byte -local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns -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 -local function withelements(e,handle,depth) - if e and handle then - local edt=e.dt - if edt then - depth=depth or 0 - for i=1,#edt do - local e=edt[i] - if type(e)=="table" then - handle(e,depth) - withelements(e,handle,depth+1) - end - end - end - end -end -xml.withelements=withelements -function xml.withelement(e,n,handle) - if e and n~=0 and handle then - local edt=e.dt - if edt then - if n>0 then - for i=1,#edt do - local ei=edt[i] - if type(ei)=="table" then - if n==1 then - handle(ei) - return - else - n=n-1 - end - end - end - elseif n<0 then - for i=#edt,1,-1 do - local ei=edt[i] - if type(ei)=="table" then - if n==-1 then - handle(ei) - return - else - n=n+1 - end - end - end - end - end - end -end -function xml.each(root,pattern,handle,reverse) - local collected=xmlapplylpath(root,pattern) - if collected then - 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 - end -end -function xml.processattributes(root,pattern,handle) - local collected=xmlapplylpath(root,pattern) - if collected and handle then - for c=1,#collected do - handle(collected[c].at) - end - end - return collected -end -function xml.collect(root,pattern) - return xmlapplylpath(root,pattern) -end -function xml.collecttexts(root,pattern,flatten) - local collected=xmlapplylpath(root,pattern) - if collected and flatten then - local xmltostring=xml.tostring - for c=1,#collected do - collected[c]=xmltostring(collected[c].dt) - end - end - return collected or {} -end -function xml.collect_tags(root,pattern,nonamespace) - local collected=xmlapplylpath(root,pattern) - if collected then - local t={} - local n=0 - for c=1,#collected do - local e=collected[c] - local ns=e.ns - local tg=e.tg - n=n+1 - if nonamespace then - t[n]=tg - elseif ns=="" then - t[n]=tg - else - t[n]=ns..":"..tg - end - end - return t - end -end -local no_root={ no_root=true } -local function redo_ni(d) - for k=1,#d do - local dk=d[k] - if type(dk)=="table" then - dk.ni=k - end - end -end -xml.reindex=redo_ni -local function xmltoelement(whatever,root) - if not whatever then - return nil - end - local element - if type(whatever)=="string" then - element=xmlinheritedconvert(whatever,root,true) - else - element=whatever - end - if element.error then - return whatever - end - if element then - end - return element -end -xml.toelement=xmltoelement -local function copiedelement(element,newparent) - if type(element)~="string" then - element=xmlcopy(element).dt - if newparent and type(element)=="table" then - for i=1,#element do - local e=element[i] - if type(e)=="table" then - e.__p__=newparent - end - end - end - end - return element -end -function xml.delete(root,pattern) - if not pattern or pattern=="" then - local p=root.__p__ - if p then - if trace_manipulations then - report('deleting',"--",c,root) - end - local d=p.dt - remove(d,root.ni) - redo_ni(d) - end - else - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - local p=e.__p__ - if p then - if trace_manipulations then - report('deleting',pattern,c,e) - end - local d=p.dt - 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 - end -end -function xml.wipe(root,pattern) - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - local p=e.__p__ - if p then - local d=p.dt - local ni=e.ni - if ni<=#d then - local dt=e.dt - if #dt==1 then - local d1=dt[1] - if type(d1)=="string" and match(d1,"^%s*$") then - if trace_manipulations then - report('wiping',pattern,c,e) - end - remove(d,ni) - redo_ni(d) - end - end - end - end - end - end -end -function xml.replace(root,pattern,whatever) - local element=root and xmltoelement(whatever,root) - local collected=element and xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - local p=e.__p__ - if p then - if trace_manipulations then - report('replacing',pattern,c,e) - end - local d=p.dt - local n=e.ni - local t=copiedelement(element,p) - if type(t)=="table" then - d[n]=t[1] - for i=2,#t do - n=n+1 - insert(d,n,t[i]) - end - else - d[n]=t - end - redo_ni(d) - end - end - end -end -function xml.expand(root,pattern,whatever) - local collected=root and xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - local p=e.__p__ - if p then - if trace_manipulations then - report('expanding',pattern,c,e) - end - local d=p.dt - local n=e.ni - local t=whatever(e,p) - if t then - if type(t)=="table" then - t=xmlcopy(t) - d[n]=t[1] - for i=2,#t do - n=n+1 - insert(d,n,t[i]) - end - else - d[n]=t - end - redo_ni(d) - end - end - end - end -end -local function wrap(e,wrapper) - local t={ - rn=e.rn, - tg=e.tg, - ns=e.ns, - at=e.at, - dt=e.dt, - __p__=e, - } - setmetatable(t,getmetatable(e)) - e.rn=wrapper.rn or e.rn or "" - e.tg=wrapper.tg or e.tg or "" - e.ns=wrapper.ns or e.ns or "" - e.at=fastcopy(wrapper.at) - e.dt={ t } -end -function xml.wrap(root,pattern,whatever) - if whatever then - local wrapper=xmltoelement(whatever,root) - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - if trace_manipulations then - report('wrapping',pattern,c,e) - end - wrap(e,wrapper) - end - end - else - wrap(root,xmltoelement(pattern)) - end -end -local function inject_element(root,pattern,whatever,prepend) - local element=root and xmltoelement(whatever,root) - local collected=element and xmlapplylpath(root,pattern) - local function inject_e(e) - local r=e.__p__ - local d=r.dt - local k=e.ni - local rri=r.ri - local edt=(rri and d[rri].dt) or (d and d[k] and d[k].dt) - if edt then - local be,af - local cp=copiedelement(element,e) - if prepend then - be,af=cp,edt - else - be,af=edt,cp - end - local bn=#be - for i=1,#af do - bn=bn+1 - be[bn]=af[i] - end - if rri then - r.dt[rri].dt=be - else - d[k].dt=be - end - redo_ni(d) - end - end - if not collected then - elseif collected.tg then - inject_e(collected) - else - for c=1,#collected do - inject_e(collected[c]) - end - end -end -local function insert_element(root,pattern,whatever,before) - local element=root and xmltoelement(whatever,root) - local collected=element and xmlapplylpath(root,pattern) - local function insert_e(e) - local r=e.__p__ - local d=r.dt - local k=e.ni - if not before then - k=k+1 - end - insert(d,k,copiedelement(element,r)) - redo_ni(d) - end - if not collected then - elseif collected.tg then - insert_e(collected) - else - for c=1,#collected do - insert_e(collected[c]) - end - end -end -xml.insert_element=insert_element -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,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 - if ekdt then - local ekat=ek.at - local ekrt=ek.__p__ - if ekrt then - 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 - end - end - local data=nil - if name and name~="" then - local d,n=loaddata(name) - data=d or "" - name=n or name - 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 - if not data or data=="" then - epdt[ek.ni]="" - elseif ekat["parse"]=="text" then - epdt[ek.ni]=xml.escaped(data) - else - local settings=xmldata.settings - local savedresource=settings.currentresource - settings.currentresource=name - local xi=xmlinheritedconvert(data,xmldata,true) - if not xi then - epdt[ek.ni]="" - else - if recursive then - include(xi,pattern,attribute,recursive,loaddata,level+1) - end - local child=xml.body(xi) - child.__p__=ekrt - child.__f__=name - child.cf=name - epdt[ek.ni]=child - local settings=xmldata.settings - local inclusions=settings and settings.inclusions - if inclusions then - inclusions[#inclusions+1]=name - elseif settings then - settings.inclusions={ name } - else - settings={ inclusions={ name } } - xmldata.settings=settings - end - if child.er then - local badinclusions=settings.badinclusions - if badinclusions then - badinclusions[#badinclusions+1]=name - else - settings.badinclusions={ name } - end - end - end -settings.currentresource=savedresource - end - 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 -local function getinclusions(key,e,sorted) - while e do - local settings=e.settings - if settings then - local inclusions=settings[key] - 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 -function xml.inclusions(e,sorted) - return getinclusions("inclusions",e,sorted) -end -function xml.badinclusions(e,sorted) - return getinclusions("badinclusions",e,sorted) -end -local b_collapser=lpegpatterns.b_collapser -local m_collapser=lpegpatterns.m_collapser -local e_collapser=lpegpatterns.e_collapser -local x_collapser=lpegpatterns.x_collapser -local b_stripper=lpegpatterns.b_stripper -local m_stripper=lpegpatterns.m_stripper -local e_stripper=lpegpatterns.e_stripper -local x_stripper=lpegpatterns.x_stripper -local function stripelement(e,nolines,anywhere,everything) - local edt=e.dt - if edt then - local n=#edt - if n==0 then - return e - elseif everything then - local t={} - local m=0 - for i=1,n do - local str=edt[i] - if type(str)~="string" then - m=m+1 - t[m]=str - elseif str~="" then - str=lpegmatch(x_collapser,str) - if str~="" then - m=m+1 - t[m]=str - end - end - end - e.dt=t - elseif anywhere then - local t={} - local m=0 - for i=1,n do - local str=edt[i] - if type(str)~="string" then - m=m+1 - t[m]=str - elseif str~="" then - if nolines then - str=lpegmatch((i==1 and b_collapser) or (i==m and e_collapser) or m_collapser,str) - else - str=lpegmatch((i==1 and b_stripper) or (i==m and e_stripper) or m_stripper,str) - end - if str~="" then - m=m+1 - t[m]=str - end - end - end - e.dt=t - else - 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 - edt[1]=str - end - end - if n>0 then - str=edt[n] - if type(str)=="string" then - if str=="" then - remove(edt) - else - str=lpegmatch(nolines and e_collapser or e_stripper,str) - if str=="" then - remove(edt) - else - edt[n]=str - end - end - end - end - end - end - return e -end -xml.stripelement=stripelement -function xml.strip(root,pattern,nolines,anywhere,everything) - local collected=xmlapplylpath(root,pattern) - if collected then - for i=1,#collected do - stripelement(collected[i],nolines,anywhere,everything) - end - end -end -local function compactelement(e) - local edt=e.dt - if edt then - for e=1,#edt do - local str=edt[e] - if type(str)=="string" and not find(str,"%S") then - edt[e]="" - end - end - end - return e -end -xml.compactelement=compactelement -local function renamespace(root,oldspace,newspace) - local ndt=#root.dt - for i=1,ndt or 0 do - local e=root[i] - if type(e)=="table" then - if e.ns==oldspace then - e.ns=newspace - if e.rn then - e.rn=newspace - end - end - local edt=e.dt - if edt then - renamespace(edt,oldspace,newspace) - end - end - end -end -xml.renamespace=renamespace -function xml.remaptag(root,pattern,newtg) - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - collected[c].tg=newtg - end - end -end -function xml.remapnamespace(root,pattern,newns) - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - collected[c].ns=newns - end - end -end -function xml.checknamespace(root,pattern,newns) - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - if (not e.rn or e.rn=="") and e.ns=="" then - e.rn=newns - end - end - end -end -function xml.remapname(root,pattern,newtg,newns,newrn) - local collected=xmlapplylpath(root,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - e.tg,e.ns,e.rn=newtg,newns,newrn - end - end -end -function xml.cdatatotext(e) - local dt=e.dt - if #dt==1 then - local first=dt[1] - if first.tg=="@cd@" then - e.dt=first.dt - end - else - end -end -function xml.texttocdata(e) - local dt=e.dt - local s=xml.tostring(dt) - e.tg="@cd@" - e.special=true - e.ns="" - e.rn="" - e.dt={ s } - e.at=nil -end -function xml.elementtocdata(e) - local dt=e.dt - local s=xml.tostring(e) - e.tg="@cd@" - e.special=true - e.ns="" - e.rn="" - e.dt={ s } - e.at=nil -end -xml.builtinentities=table.tohash { "amp","quot","apos","lt","gt" } -local entities=characters and characters.entities or nil -local builtinentities=xml.builtinentities -function xml.addentitiesdoctype(root,option) - if not entities then - require("char-ent") - entities=characters.entities - end - if entities and root and root.tg=="@rt@" and root.statistics then - local list={} - local hexify=option=="hexadecimal" - for k,v in table.sortedhash(root.statistics.entities.names) do - if not builtinentities[k] then - local e=entities[k] - if not e then - e=format("[%s]",k) - elseif hexify then - e=format("&#%05X;",utfbyte(k)) - end - list[#list+1]=format(" <!ENTITY %s %q >",k,e) - end - end - local dt=root.dt - local n=dt[1].tg=="@pi@" and 2 or 1 - if #list>0 then - insert(dt,n,{ "\n" }) - insert(dt,n,{ - tg="@dt@", - dt={ format("Something [\n%s\n] ",concat(list)) }, - ns="", - special=true, - }) - insert(dt,n,{ "\n\n" }) - else - end - end -end -xml.all=xml.each -xml.insert=xml.insertafter -xml.inject=xml.injectafter -xml.after=xml.insertafter -xml.before=xml.insertbefore -xml.process=xml.each -xml.obsolete=xml.obsolete or {} -local obsolete=xml.obsolete -xml.strip_whitespace=xml.strip obsolete.strip_whitespace=xml.strip -xml.collect_elements=xml.collect obsolete.collect_elements=xml.collect -xml.delete_element=xml.delete obsolete.delete_element=xml.delete -xml.replace_element=xml.replace obsolete.replace_element=xml.replace -xml.each_element=xml.each obsolete.each_element=xml.each -xml.process_elements=xml.process obsolete.process_elements=xml.process -xml.insert_element_after=xml.insertafter obsolete.insert_element_after=xml.insertafter -xml.insert_element_before=xml.insertbefore obsolete.insert_element_before=xml.insertbefore -xml.inject_element_after=xml.injectafter obsolete.inject_element_after=xml.injectafter -xml.inject_element_before=xml.injectbefore obsolete.inject_element_before=xml.injectbefore -xml.process_attributes=xml.processattributes obsolete.process_attributes=xml.processattributes -xml.collect_texts=xml.collecttexts obsolete.collect_texts=xml.collecttexts -xml.inject_element=xml.inject obsolete.inject_element=xml.inject -xml.remap_tag=xml.remaptag obsolete.remap_tag=xml.remaptag -xml.remap_name=xml.remapname obsolete.remap_name=xml.remapname -xml.remap_namespace=xml.remapnamespace obsolete.remap_namespace=xml.remapnamespace -function xml.cdata(e) - if e then - local dt=e.dt - if dt and #dt==1 then - local first=dt[1] - return first.tg=="@cd@" and first.dt[1] or "" - end - end - return "" -end -function xml.finalizers.xml.cdata(collected) - if collected then - local e=collected[1] - if e then - local dt=e.dt - if dt and #dt==1 then - local first=dt[1] - return first.tg=="@cd@" and first.dt[1] or "" - end - end - end - return "" -end -function xml.insertcomment(e,str,n) - insert(e.dt,n or 1,{ - tg="@cm@", - ns="", - special=true, - at={}, - dt={ str }, - }) -end -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="", - special=true, - at={}, - dt={ str }, - } } -end -function xml.separate(x,pattern) - local collected=xmlapplylpath(x,pattern) - if collected then - for c=1,#collected do - local e=collected[c] - local d=e.dt - if d==x then - report_xml("warning: xml.separate changes root") - x=d - end - local t={ "\n" } - local n=1 - local i=1 - local nd=#d - while i<=nd do - while i<=nd do - local di=d[i] - if type(di)=="string" then - if di=="\n" or find(di,"^%s+$") then - i=i+1 - else - d[i]=strip(di) - break - end - else - break - end - end - if i>nd then - break - end - t[n+1]="\n" - t[n+2]=d[i] - t[n+3]="\n" - n=n+3 - i=i+1 - end - t[n+1]="\n" - setmetatable(t,getmetatable(d)) - e.dt=t - end - end - return x -end -local helpers=xml.helpers or {} -xml.helpers=helpers -local function normal(e,action) - local edt=e.dt - if edt then - for i=1,#edt do - local str=edt[i] - if type(str)=="string" and str~="" then - edt[i]=action(str) - end - end - end -end -local function recurse(e,action) - local edt=e.dt - if edt then - for i=1,#edt do - local str=edt[i] - if type(str)~="string" then - recurse(str,action) - elseif str~="" then - edt[i]=action(str) - end - end - end -end -function helpers.recursetext(collected,action,recursive) - if recursive then - for i=1,#collected do - recurse(collected[i],action) - end - else - for i=1,#collected do - normal(collected[i],action) - 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 -function xml.rename(e,namespace,name,attributes) - if type(e)~="table" or not e.tg then - return - end - if type(name)=="table" then - attributes=name - name=namespace - namespace="" - elseif type(name)~="string" then - attributes={} - name=namespace - namespace="" - end - if type(attributes)~="table" then - attributes={} - end - e.ns=namespace - e.rn=namespace - e.tg=name - e.at=attributes -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["lxml-xml"] = package.loaded["lxml-xml"] or true - --- original size: 11096, stripped down to: 7702 - -if not modules then modules={} end modules ['lxml-xml']={ - version=1.001, - comment="this module is the basis for the lxml-* ones", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local tonumber,next=tonumber,next -local concat=table.concat -local find,lower,upper=string.find,string.lower,string.upper -local xml=xml -local finalizers=xml.finalizers.xml -local xmlfilter=xml.filter -local xmltostring=xml.tostring -local xmlserialize=xml.serialize -local xmlcollected=xml.collected -local xmlnewhandlers=xml.newhandlers -local reparsedentity=xml.reparsedentitylpeg -local unescapedentity=xml.unescapedentitylpeg -local parsedentity=reparsedentity -local function first(collected) - return collected and collected[1] -end -local function last(collected) - return collected and collected[#collected] -end -local function all(collected) - return collected -end -local reverse=table.reversed -local function attribute(collected,name) - if collected and #collected>0 then - local at=collected[1].at - return at and at[name] - end -end -local function att(id,name) - local at=id.at - return at and at[name] -end -local function count(collected) - return collected and #collected or 0 -end -local function position(collected,n) - if not collected then - return 0 - end - local nc=#collected - if nc==0 then - return 0 - end - n=tonumber(n) or 0 - if n<0 then - return collected[nc+n+1] - elseif n>0 then - return collected[n] - else - return collected[1].mi or 0 - end -end -local function match(collected) - return collected and #collected>0 and collected[1].mi or 0 -end -local function index(collected) - return collected and #collected>0 and collected[1].ni or 0 -end -local function attributes(collected,arguments) - if collected and #collected>0 then - local at=collected[1].at - if arguments then - return at[arguments] - elseif next(at) then - return at - end - end -end -local function chainattribute(collected,arguments) - if collected and #collected>0 then - local e=collected[1] - while e do - local at=e.at - if at then - local a=at[arguments] - if a then - return a - end - else - break - end - e=e.__p__ - end - end - return "" -end -local function raw(collected) - if collected and #collected>0 then - local e=collected[1] or collected - return e and xmltostring(e) or "" - else - return "" - end -end -local xmltexthandler=xmlnewhandlers { - name="string", - initialize=function() - result={} - return result - end, - finalize=function() - return concat(result) - end, - handle=function(...) - result[#result+1]=concat {... } - end, - escape=false, -} -local function xmltotext(root) - local dt=root.dt - if not dt then - return "" - end - local nt=#dt - if nt==0 then - return "" - elseif nt==1 and type(dt[1])=="string" then - return dt[1] - else - return xmlserialize(root,xmltexthandler) or "" - end -end -function xml.serializetotext(root) - return root and xmlserialize(root,xmltexthandler) or "" -end -local function text(collected) - if collected then - local e=collected[1] or collected - return e and xmltotext(e) or "" - else - return "" - end -end -local function texts(collected) - if not collected then - return {} - end - local nc=#collected - if nc==0 then - return {} - end - local t,n={},0 - for c=1,nc do - local e=collected[c] - if e and e.dt then - n=n+1 - t[n]=e.dt - end - end - return t -end -local function tag(collected,n) - if not collected then - return - end - local nc=#collected - if nc==0 then - return - end - local c - if n==0 or not n then - c=collected[1] - elseif n>1 then - c=collected[n] - else - c=collected[nc-n+1] - end - return c and c.tg -end -local function name(collected,n) - if not collected then - return - end - local nc=#collected - if nc==0 then - return - end - local c - if n==0 or not n then - c=collected[1] - elseif n>1 then - c=collected[n] - else - c=collected[nc-n+1] - end - if not c then - elseif c.ns=="" then - return c.tg - else - return c.ns..":"..c.tg - end -end -local function tags(collected,nonamespace) - if not collected then - return - end - local nc=#collected - if nc==0 then - return - end - local t,n={},0 - for c=1,nc do - local e=collected[c] - local ns,tg=e.ns,e.tg - n=n+1 - if nonamespace or ns=="" then - t[n]=tg - else - t[n]=ns..":"..tg - end - end - return t -end -local function empty(collected,spacesonly) - if not collected then - return true - end - local nc=#collected - if nc==0 then - return true - end - for c=1,nc do - local e=collected[c] - if e then - local edt=e.dt - if edt then - local n=#edt - if n==1 then - local edk=edt[1] - local typ=type(edk) - if typ=="table" then - return false - elseif edk~="" then - return false - elseif spacesonly and not find(edk,"%S") then - return false - end - elseif n>1 then - return false - end - end - end - end - return true -end -finalizers.first=first -finalizers.last=last -finalizers.all=all -finalizers.reverse=reverse -finalizers.elements=all -finalizers.default=all -finalizers.attribute=attribute -finalizers.att=att -finalizers.count=count -finalizers.position=position -finalizers.match=match -finalizers.index=index -finalizers.attributes=attributes -finalizers.chainattribute=chainattribute -finalizers.text=text -finalizers.texts=texts -finalizers.tag=tag -finalizers.name=name -finalizers.tags=tags -finalizers.empty=empty -function xml.first(id,pattern) - return first(xmlfilter(id,pattern)) -end -function xml.last(id,pattern) - return last(xmlfilter(id,pattern)) -end -function xml.count(id,pattern) - return count(xmlfilter(id,pattern)) -end -function xml.attribute(id,pattern,a,default) - return attribute(xmlfilter(id,pattern),a,default) -end -function xml.raw(id,pattern) - if pattern then - return raw(xmlfilter(id,pattern)) - else - return raw(id) - end -end -function xml.text(id,pattern) - if pattern then - local collected=xmlfilter(id,pattern) - return collected and #collected>0 and xmltotext(collected[1]) or "" - elseif id then - return xmltotext(id) or "" - else - return "" - end -end -function xml.pure(id,pattern) - if pattern then - local collected=xmlfilter(id,pattern) - if collected and #collected>0 then - parsedentity=unescapedentity - local s=collected and #collected>0 and xmltotext(collected[1]) or "" - parsedentity=reparsedentity - return s - else - return "" - end - else - parsedentity=unescapedentity - local s=xmltotext(id) or "" - parsedentity=reparsedentity - return s - end -end -xml.content=text -function xml.position(id,pattern,n) - return position(xmlfilter(id,pattern),n) -end -function xml.match(id,pattern) - return match(xmlfilter(id,pattern)) -end -function xml.empty(id,pattern,spacesonly) - return empty(xmlfilter(id,pattern),spacesonly) -end -xml.all=xml.filter -xml.index=xml.position -xml.found=xml.filter -local function totable(x) - local t={} - for e in xmlcollected(x[1] or x,"/*") do - t[e.tg]=xmltostring(e.dt) or "" - end - return next(t) and t or nil -end -xml.table=totable -finalizers.table=totable -local function textonly(e,t) - if e then - local edt=e.dt - if edt then - for i=1,#edt do - local e=edt[i] - if type(e)=="table" then - textonly(e,t) - else - t[#t+1]=e - end - end - end - end - return t -end -function xml.textonly(e) - return concat(textonly(e,{})) -end -function finalizers.lowerall(collected) - for c=1,#collected do - local e=collected[c] - if not e.special then - e.tg=lower(e.tg) - local eat=e.at - if eat then - local t={} - for k,v in next,eat do - t[lower(k)]=v - end - e.at=t - end - end - end -end -function finalizers.upperall(collected) - for c=1,#collected do - local e=collected[c] - if not e.special then - e.tg=upper(e.tg) - local eat=e.at - if eat then - local t={} - for k,v in next,eat do - t[upper(k)]=v - end - e.at=t - end - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["trac-xml"] = package.loaded["trac-xml"] or true - --- original size: 6407, stripped down to: 4640 - -if not modules then modules={} end modules ['trac-xml']={ - version=1.001, - comment="companion to trac-log.mkiv", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local formatters=string.formatters -local reporters=logs.reporters -local xmlserialize=xml.serialize -local xmlcollected=xml.collected -local xmltext=xml.text -local xmlfirst=xml.first -local function showhelp(specification,...) - local root=xml.convert(specification.helpinfo or "") - if not root then - return - end - local xs=xml.gethandlers("string") - xml.sethandlersfunction(xs,"short",function(e,handler) xmlserialize(e.dt,handler) end) - xml.sethandlersfunction(xs,"ref",function(e,handler) handler.handle("--"..e.at.name) end) - local wantedcategories=select("#",...)==0 and true or table.tohash {... } - local nofcategories=xml.count(root,"/application/flags/category") - local report=specification.report - for category in xmlcollected(root,"/application/flags/category") do - local categoryname=category.at.name or "" - if wantedcategories==true or wantedcategories[categoryname] then - if nofcategories>1 then - report("%s options:",categoryname) - report() - end - for subcategory in xmlcollected(category,"/subcategory") do - for flag in xmlcollected(subcategory,"/flag") do - local name=flag.at.name - local value=flag.at.value - local short=xmltext(xmlfirst(flag,"/short")) - if value then - report("--%-20s %s",formatters["%s=%s"](name,value),short) - else - report("--%-20s %s",name,short) - end - end - report() - end - end - end - for category in xmlcollected(root,"/application/examples/category") do - local title=xmltext(xmlfirst(category,"/title")) - if title and title~="" then - report() - report(title) - report() - end - for subcategory in xmlcollected(category,"/subcategory") do - for example in xmlcollected(subcategory,"/example") do - local command=xmltext(xmlfirst(example,"/command")) - local comment=xmltext(xmlfirst(example,"/comment")) - report(command) - end - report() - end - end - for comment in xmlcollected(root,"/application/comments/comment") do - local comment=xmltext(comment) - report() - report(comment) - report() - end -end -local reporthelp=reporters.help -local exporthelp=reporters.export -local function xmlfound(t) - local helpinfo=t.helpinfo - if type(helpinfo)=="table" then - return false - end - if type(helpinfo)~="string" then - helpinfo="Warning: no helpinfo found." - t.helpinfo=helpinfo - return false - end - if string.find(helpinfo,".xml$") then - local ownscript=environment.ownscript - local helpdata=false - if ownscript then - local helpfile=file.join(file.pathpart(ownscript),helpinfo) - helpdata=io.loaddata(helpfile) - if helpdata=="" then - helpdata=false - end - end - if not helpdata then - local helpfile=resolvers.findfile(helpinfo,"tex") - helpdata=helpfile and io.loaddata(helpfile) - end - if helpdata and helpdata~="" then - helpinfo=helpdata - else - helpinfo=formatters["Warning: help file %a is not found."](helpinfo) - end - end - t.helpinfo=helpinfo - return string.find(t.helpinfo,"^<%?xml") and true or false -end -function reporters.help(t,...) - if xmlfound(t) then - showhelp(t,...) - else - reporthelp(t,...) - end -end -function reporters.export(t,methods,filename) - if not xmlfound(t) then - return exporthelp(t) - end - if not methods or methods=="" then - methods=environment.arguments["exporthelp"] - end - if not filename or filename=="" then - filename=environment.files[1] - end - dofile(resolvers.findfile("trac-exp.lua","tex")) - local exporters=logs.exporters - if not exporters or not methods then - return exporthelp(t) - end - if methods=="all" then - methods=table.keys(exporters) - elseif type(methods)=="string" then - methods=utilities.parsers.settings_to_array(methods) - else - return exporthelp(t) - end - if type(filename)~="string" or filename=="" then - filename=false - elseif file.pathpart(filename)=="" then - t.report("export file %a will not be saved on the current path (safeguard)",filename) - return - end - for i=1,#methods do - local method=methods[i] - local exporter=exporters[method] - if exporter then - local result=exporter(t,method) - if result and result~="" then - if filename then - local fullname=file.replacesuffix(filename,method) - t.report("saving export in %a",fullname) - dir.mkdirs(file.pathpart(fullname)) - io.savedata(fullname,result) - else - reporters.lines(t,result) - end - else - t.report("no output from exporter %a",method) - end - else - t.report("unknown exporter %a",method) - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-ini"] = package.loaded["data-ini"] or true - --- original size: 10947, stripped down to: 7176 - -if not modules then modules={} end modules ['data-ini']={ - 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 next,type,getmetatable,rawset=next,type,getmetatable,rawset -local gsub,find,gmatch,char=string.gsub,string.find,string.gmatch,string.char -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 sortedpairs=table.sortedpairs -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_expansions=false trackers.register("resolvers.expansions",function(v) trace_expansions=v end) -local report_initialization=logs.reporter("resolvers","initialization") -resolvers=resolvers or {} -local resolvers=resolvers -texconfig.kpse_init=false -texconfig.shell_escape='t' -if not (environment and environment.default_texmfcnf) and kpse and kpse.default_texmfcnf then - local default_texmfcnf=kpse.default_texmfcnf() - default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOLOC","selfautoloc:") - default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTODIR","selfautodir:") - default_texmfcnf=gsub(default_texmfcnf,"$SELFAUTOPARENT","selfautoparent:") - default_texmfcnf=gsub(default_texmfcnf,"$HOME","home:") - environment.default_texmfcnf=default_texmfcnf -end -kpse={ original=kpse } -setmetatable(kpse,{ - __index=function(kp,name) - report_initialization("fatal error: kpse library is accessed (key: %s)",name) - os.exit() - end -} ) -do - local osfontdir=osgetenv("OSFONTDIR") - if osfontdir and osfontdir~="" then - elseif osname=="windows" then - ossetenv("OSFONTDIR","c:/windows/fonts//") - elseif osname=="macosx" then - ossetenv("OSFONTDIR","$HOME/Library/Fonts//;/Library/Fonts//;/System/Library/Fonts//") - end -end -if not environment.homedir then - local oldhome=osgetenv('HOME') - local homedir=osgetenv(ostype=="windows" and 'USERPROFILE' or 'HOME') or '' - if not homedir or homedir=="" then - homedir=char(127) - end - homedir=file.collapsepath(homedir) - ossetenv("HOME",homedir) - ossetenv("USERPROFILE",homedir) - environment.oldhome=oldhome - environment.homedir=homedir -end -do - local args=environment.originalarguments or arg - if not environment.ownmain then - environment.ownmain=status and string.match(string.lower(status.banner),"this is ([%a]+)") or "luatex" - end - local ownbin=environment.ownbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luatex" - local ownpath=environment.ownpath or os.selfdir - ownbin=file.collapsepath(ownbin) - ownpath=file.collapsepath(ownpath) - if not ownpath or ownpath=="" or ownpath=="unset" then - ownpath=args[-1] or arg[-1] - ownpath=ownpath and filedirname(gsub(ownpath,"\\","/")) - if not ownpath or ownpath=="" then - ownpath=args[-0] or arg[-0] - ownpath=ownpath and filedirname(gsub(ownpath,"\\","/")) - end - local binary=ownbin - if not ownpath or ownpath=="" then - ownpath=ownpath and filedirname(binary) - end - if not ownpath or ownpath=="" then - if os.binsuffix~="" then - binary=file.replacesuffix(binary,os.binsuffix) - end - local path=osgetenv("PATH") - if path then - for p in gmatch(path,"[^"..io.pathseparator.."]+") do - local b=filejoin(p,binary) - if lfs.isfile(b) then - local olddir=lfs.currentdir() - if lfs.chdir(p) then - local pp=lfs.currentdir() - if trace_locating and p~=pp then - report_initialization("following symlink %a to %a",p,pp) - end - ownpath=pp - lfs.chdir(olddir) - else - if trace_locating then - report_initialization("unable to check path %a",p) - end - ownpath=p - end - break - end - end - end - end - if not ownpath or ownpath=="" then - ownpath="." - report_initialization("forcing fallback to ownpath %a",ownpath) - elseif trace_locating then - report_initialization("using ownpath %a",ownpath) - end - end - environment.ownbin=ownbin - environment.ownpath=ownpath -end -resolvers.ownpath=environment.ownpath -function resolvers.getownpath() - return environment.ownpath -end -do - local ownpath=environment.ownpath or dir.current() - if ownpath then - ossetenv('SELFAUTOLOC',file.collapsepath(ownpath)) - ossetenv('SELFAUTODIR',file.collapsepath(ownpath.."/..")) - ossetenv('SELFAUTOPARENT',file.collapsepath(ownpath.."/../..")) - else - report_initialization("error: unable to locate ownpath") - os.exit() - end -end -local texos=environment.texos or osgetenv("TEXOS") -local texmfos=environment.texmfos or osgetenv('SELFAUTODIR') -if not texos or texos=="" then - texos=file.basename(texmfos) -end -ossetenv('TEXMFOS',texmfos) -ossetenv('TEXOS',texos) -ossetenv('SELFAUTOSYSTEM',os.platform) -environment.texos=texos -environment.texmfos=texmfos -local texroot=environment.texroot or osgetenv("TEXROOT") -if not texroot or texroot=="" then - texroot=osgetenv('SELFAUTOPARENT') - ossetenv('TEXROOT',texroot) -end -environment.texroot=file.collapsepath(texroot) -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 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 - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-exp"] = package.loaded["data-exp"] or true - --- original size: 18179, stripped down to: 10432 - -if not modules then modules={} end modules ['data-exp']={ - 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 format,find,gmatch,lower,char,sub=string.format,string.find,string.gmatch,string.lower,string.char,string.sub -local concat,sort=table.concat,table.sort -local sortedkeys=table.sortedkeys -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 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 - for sa in gmatch(a,"[^,]+") do - n=n+1;t[n]=sa..sb - end - end - return concat(t,",") -end -local comma=P(",") -local nocomma=(1-comma)^1 -local docomma=comma^1/"," -local before=Cs((nocomma*Carg(1)+docomma)^0) -local after=Cs((Carg(1)*nocomma+docomma)^0) -local both=Cs(((C(nocomma)*Carg(1))/function(a,b) return lpegmatch(before,b,1,a) end+docomma)^0) -local function f_first (a,b) return lpegmatch(after,b,1,a) end -local function f_second(a,b) return lpegmatch(before,a,1,b) end -local function f_both (a,b) return lpegmatch(both,b,1,a) end -local left=P("{") -local right=P("}") -local var=P((1-S("{}" ))^0) -local set=P((1-S("{},"))^0) -local other=P(1) -local l_first=Cs((Cc("{")*(C(set)*left*C(var)*right/f_first)*Cc("}")+other )^0 ) -local l_second=Cs((Cc("{")*(left*C(var)*right*C(set)/f_second)*Cc("}")+other )^0 ) -local l_both=Cs((Cc("{")*(left*C(var)*right*left*C(var)*right/f_both)*Cc("}")+other )^0 ) -local l_rest=Cs((left*var*(left/"")*var*(right/"")*var*right+other )^0 ) -local stripper_1=lpeg.stripper ("{}@") -local replacer_1=lpeg.replacer { { ",}",",@}" },{ "{,","{@," },} -local function splitpathexpr(str,newlist,validate) - if trace_expansions then - report_expansions("expanding variable %a",str) - end - local t,ok,done=newlist or {},false,false - local n=#t - str=lpegmatch(replacer_1,str) - repeat - local old=str - repeat - local old=str - str=lpegmatch(l_first,str) - until old==str - repeat - local old=str - str=lpegmatch(l_second,str) - until old==str - repeat - local old=str - str=lpegmatch(l_both,str) - until old==str - repeat - local old=str - str=lpegmatch(l_rest,str) - until old==str - until old==str - str=lpegmatch(stripper_1,str) - if validate then - for s in gmatch(str,"[^,]+") do - s=validate(s) - if s then - n=n+1 - t[n]=s - end - end - else - for s in gmatch(str,"[^,]+") do - n=n+1 - t[n]=s - end - end - if trace_expansions then - for k=1,#t do - report_expansions("% 4i: %s",k,t[k]) - end - end - return t -end -local function validate(s) - s=collapsepath(s) - return s~="" and not find(s,"^!*unset/*$") and s -end -resolvers.validatedpath=validate -function resolvers.expandedpathfromlist(pathlist) - local newlist={} - for k=1,#pathlist do - splitpathexpr(pathlist[k],newlist,validate) - end - return newlist -end -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 - usedhomedir="." - end - end - 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 dodouble=P('"')/""*(expandhome+(1-P('"')))^0*P('"')/"" -local dosingle=P("'")/""*(expandhome+(1-P("'")))^0*P("'")/"" -local dostring=(expandhome+1 )^0 -local stripper=Cs( - lpegpatterns.unspacer*(dosingle+dodouble+dostring)*lpegpatterns.unspacer -) -function resolvers.checkedvariable(str) - return type(str)=="string" and lpegmatch(stripper,str) or str -end -local cache={} -local splitter=lpeg.tsplitat(";") -local backslashswapper=lpeg.replacer("\\","/") -local function splitconfigurationpath(str) - if str then - local found=cache[str] - if not found then - if str=="" then - found={} - else - local split=lpegmatch(splitter,lpegmatch(backslashswapper,str)) - found={} - local noffound=0 - for i=1,#split do - local s=split[i] - if not find(s,"^{*unset}*") then - noffound=noffound+1 - found[noffound]=s - end - end - if trace_expansions then - report_expansions("splitting path specification %a",str) - for k=1,noffound do - report_expansions("% 4i: %s",k,found[k]) - end - end - cache[str]=found - end - end - return found - end -end -resolvers.splitconfigurationpath=splitconfigurationpath -function resolvers.splitpath(str) - if type(str)=='table' then - return str - else - return splitconfigurationpath(str) - end -end -function resolvers.joinpath(str) - if type(str)=='table' then - 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 fullcache={} -local nofsharedscans=0 -local addcasecraptoo=true -local function scan(files,remap,spec,path,n,m,r,onlyone,tolerant) - local full=path=="" and spec or (spec..path..'/') - local dirlist={} - local nofdirs=0 - local pattern=tolerant and lessweird or weird - local filelist={} - local noffiles=0 - for name,mode in directory(full) do - if not lpegmatch(pattern,name) then - if not mode then - mode=attributes(full..name,"mode") - end - if mode=="file" then - n=n+1 - noffiles=noffiles+1 - filelist[noffiles]=name - elseif mode=="directory" then - m=m+1 - nofdirs=nofdirs+1 - if path~="" then - dirlist[nofdirs]=path.."/"..name - else - dirlist[nofdirs]=name - end - end - end - end - if noffiles>0 then - sort(filelist) - for i=1,noffiles do - local name=filelist[i] - local lower=lower(name) - local paths=files[lower] - if paths then - if onlyone then - else - 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 - if addcasecraptoo then - local paths=files[name] - if not paths then - files[name]=path - elseif type(paths)=="string" then - files[name]={ paths,path } - else - paths[#paths+1]=path - end - end - end - if type(paths)=="string" then - files[lower]={ paths,path } - else - paths[#paths+1]=path - end - end - else - files[lower]=path - 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 - end - end - if nofdirs>0 then - sort(dirlist) - for i=1,nofdirs do - files,remap,n,m,r=scan(files,remap,spec,dirlist[i],n,m,r,onlyonce,tolerant) - end - end - scancache[sub(full,1,-2)]=files - return files,remap,n,m,r -end -local function scanfiles(path,branch,usecache,onlyonce,tolerant) - local realpath=resolveprefix(path) - if usecache then - local content=fullcache[realpath] - if content then - if trace_locating then - report_expansions("using cached scan of path %a, branch %a",path,branch or path) - end - 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 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 - 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 usecache then - scanned[#scanned+1]=realpath - fullcache[realpath]=content - end - nofscans=nofscans+1 - statistics.stoptiming(timer) - return content -end -resolvers.scanfiles=scanfiles -function resolvers.simplescanfiles(path,branch,usecache) - return scanfiles(path,branch,usecache,true,true) -end -function resolvers.scandata() - table.sort(scanned) - return { - n=nofscans, - shared=nofsharedscans, - time=statistics.elapsedtime(timer), - 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 f=sortedkeys(files) - local n=#f - local i=0 - local function iterator() - while i<n do - i=i+1 - local k=f[i] - 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 - -do -- create closure to overcome 200 locals limit - -package.loaded["data-env"] = package.loaded["data-env"] or true - --- original size: 9501, stripped down to: 6413 - -if not modules then modules={} end modules ['data-env']={ - 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 lower,gsub=string.lower,string.gsub -local next,rawget=next,rawget -local resolvers=resolvers -local allocate=utilities.storage.allocate -local setmetatableindex=table.setmetatableindex -local suffixonly=file.suffixonly -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={ - ofm={ - names={ "ofm","omega font metric","omega font metrics" }, - variable='OFMFONTS', - suffixes={ 'ofm','tfm' }, - }, - ovf={ - names={ "ovf","omega virtual font","omega virtual fonts" }, - variable='OVFFONTS', - suffixes={ 'ovf','vf' }, - }, - tfm={ - names={ "tfm","tex font metric","tex font metrics" }, - variable='TFMFONTS', - suffixes={ 'tfm' }, - }, - vf={ - names={ "vf","virtual font","virtual fonts" }, - variable='VFFONTS', - suffixes={ 'vf' }, - }, - otf={ - names={ "otf","opentype","opentype font","opentype fonts"}, - variable='OPENTYPEFONTS', - suffixes={ 'otf' }, - }, - ttf={ - names={ "ttf","truetype","truetype font","truetype fonts","truetype collection","truetype collections","truetype dictionary","truetype dictionaries" }, - variable='TTFONTS', - suffixes={ 'ttf','ttc','dfont' }, - }, - afm={ - names={ "afm","adobe font metric","adobe font metrics" }, - variable="AFMFONTS", - suffixes={ "afm" }, - }, - pfb={ - names={ "pfb","type1","type 1","type1 font","type 1 font","type1 fonts","type 1 fonts" }, - variable='T1FONTS', - suffixes={ 'pfb','pfa' }, - }, - fea={ - names={ "fea","font feature","font features","font feature file","font feature files" }, - variable='FONTFEATURES', - suffixes={ 'fea' }, - }, - cid={ - names={ "cid","cid map","cid maps","cid file","cid files" }, - variable='FONTCIDMAPS', - suffixes={ 'cid','cidmap' }, - }, - fmt={ - names={ "fmt","format","tex format" }, - variable='TEXFORMATS', - suffixes={ 'fmt' }, - }, - mem={ - names={ 'mem',"metapost format" }, - variable='MPMEMS', - suffixes={ 'mem' }, - }, - mp={ - names={ "mp" }, - variable='MPINPUTS', - suffixes=CONTEXTLMTXMODE>0 - and { 'mpxl','mpvi','mpiv','mpii','mp' } - or { 'mpvi','mpiv','mpii','mp' }, - usertype=true, - }, - tex={ - names={ "tex" }, - variable='TEXINPUTS', - suffixes={ "tex","mkiv","mkvi","mkxl","mklx","mkii","cld","lfg","xml" }, - usertype=true, - }, - icc={ - names={ "icc","icc profile","icc profiles" }, - variable='ICCPROFILES', - suffixes={ 'icc' }, - }, - texmfscripts={ - names={ "texmfscript","texmfscripts","script","scripts" }, - variable='TEXMFSCRIPTS', - suffixes={ 'lua','rb','pl','py' }, - }, - lua={ - names={ "lua" }, - variable='LUAINPUTS', - suffixes={ luasuffixes.lua,luasuffixes.luc,luasuffixes.tma,luasuffixes.tmc }, - usertype=true, - }, - lib={ - names={ "lib" }, - variable='CLUAINPUTS', - suffixes=os.libsuffix and { os.libsuffix } or { 'dll','so' }, - }, - 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' }, - variable='FONTCONFIG_PATH', - }, - pk={ - names={ "pk" }, - variable='PKFONTS', - suffixes={ 'pk' }, - }, - }, - obsolete={ - enc={ - names={ "enc","enc files","enc file","encoding files","encoding file" }, - variable='ENCFONTS', - suffixes={ 'enc' }, - }, - map={ - names={ "map","map files","map file" }, - variable='TEXFONTMAPS', - suffixes={ 'map' }, - }, - lig={ - names={ "lig files","lig file","ligature file","ligature files" }, - variable='LIGFONTS', - suffixes={ 'lig' }, - }, - opl={ - names={ "opl" }, - variable='OPLFONTS', - suffixes={ 'opl' }, - }, - ovp={ - names={ "ovp" }, - variable='OVPFONTS', - suffixes={ 'ovp' }, - }, - }, - kpse={ - base={ - names={ 'base',"metafont format" }, - variable='MFBASES', - suffixes={ 'base','bas' }, - }, - cmap={ - names={ 'cmap','cmap files','cmap file' }, - variable='CMAPFONTS', - suffixes={ 'cmap' }, - }, - cnf={ - names={ 'cnf' }, - suffixes={ 'cnf' }, - }, - web={ - names={ 'web' }, - suffixes={ 'web','ch' } - }, - cweb={ - names={ 'cweb' }, - suffixes={ 'w','web','ch' }, - }, - gf={ - names={ 'gf' }, - suffixes={ '<resolution>gf' }, - }, - mf={ - names={ 'mf' }, - variable='MFINPUTS', - suffixes={ 'mf' }, - }, - mft={ - names={ 'mft' }, - suffixes={ 'mft' }, - }, - pk={ - names={ 'pk' }, - suffixes={ '<resolution>pk' }, - }, - }, -} -resolvers.relations=relations -function resolvers.updaterelations() - for category,categories in next,relations do - for name,relation in next,categories do - local rn=relation.names - local rv=relation.variable - 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 - if rs then - suffixes[rni]=rs - for i=1,#rs do - local rsi=rs[i] - suffixmap[rsi]=rni - end - end - end - if ru then - usertypes[name]=true - end - end - end - end -end -resolvers.updaterelations() -local function simplified(t,k) - return k and rawget(t,lower(gsub(k," ",""))) or nil -end -setmetatableindex(formats,simplified) -setmetatableindex(suffixes,simplified) -setmetatableindex(suffixmap,simplified) -function resolvers.suffixofformat(str) - local s=suffixes[str] - return s and s[1] or "" -end -function resolvers.suffixofformat(str) - return suffixes[str] or {} -end -for name,format in next,formats do - dangerous[name]=true -end -dangerous.tex=nil -function resolvers.formatofvariable(str) - return formats[str] or '' -end -function resolvers.formatofsuffix(str) - return suffixmap[suffixonly(str)] or 'tex' -end -function resolvers.variableofformat(str) - return formats[str] or '' -end -function resolvers.variableofformatorsuffix(str) - local v=formats[str] - if v then - return v - end - v=suffixmap[suffixonly(str)] - if v then - return formats[v] - end - return '' -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-tmp"] = package.loaded["data-tmp"] or true - --- original size: 16456, stripped down to: 11636 - -if not modules then modules={} end modules ['data-tmp']={ - version=1.100, - 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 next,type=next,type -local pcall,loadfile,collectgarbage=pcall,loadfile,collectgarbage -local format,lower,gsub=string.format,string.lower,string.gsub -local concat,serialize,fastserialize,serializetofile=table.concat,table.serialize,table.fastserialize,table.tofile -local mkdirs,expanddirname,isdir,isfile=dir.mkdirs,dir.expandname,lfs.isdir,lfs.isfile -local is_writable,is_readable=file.is_writable,file.is_readable -local collapsepath,joinfile,addsuffix,dirname=file.collapsepath,file.join,file.addsuffix,file.dirname -local savedata=file.savedata -local formatters=string.formatters -local osexit,osdate,osuuid=os.exit,os.date,os.uuid -local removefile=os.remove -local md5hex=md5.hex -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end) -local report_caches=logs.reporter("resolvers","caches") -local report_resolvers=logs.reporter("resolvers","caching") -local resolvers=resolvers -local cleanpath=resolvers.cleanpath -local resolvepath=resolvers.resolve -local luautilities=utilities.lua -do - 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 compilelua=luautilities.compile - function luautilities.compile(luafile,lucfile,cleanup,strip) - if cleanup==nil then cleanup=directive_cleanup end - if strip==nil then strip=directive_strip end - return compilelua(luafile,lucfile,cleanup,strip) - end -end -caches=caches or {} -local caches=caches -local writable=nil -local readables={} -local usedreadables={} -local compilelua=luautilities.compile -local luasuffixes=luautilities.suffixes -caches.base=caches.base or (LUATEXENGINE and LUATEXENGINE.."-cache") or "luatex-cache" -caches.more=caches.more or "context" -caches.defaults={ "TMPDIR","TEMPDIR","TMP","TEMP","HOME","HOMEPATH" } -local direct_cache=false -local fast_cache=false -local cache_tree=false -directives.register("system.caches.direct",function(v) direct_cache=true end) -directives.register("system.caches.fast",function(v) fast_cache=true end) -local function configfiles() - return concat(resolvers.configurationfiles(),";") -end -local function hashed(tree) - tree=gsub(tree,"[\\/]+$","") - tree=lower(tree) - local hash=md5hex(tree) - if trace_cache or trace_locating then - report_caches("hashing tree %a, hash %a",tree,hash) - end - return hash -end -local function treehash() - local tree=configfiles() - if not tree or tree=="" then - return false - else - return hashed(tree) - end -end -caches.hashed=hashed -caches.treehash=treehash -caches.configfiles=configfiles -local function identify() - local texmfcaches=resolvers.cleanpathlist("TEXMFCACHE") - if texmfcaches then - for k=1,#texmfcaches do - local cachepath=texmfcaches[k] - if cachepath~="" then - cachepath=resolvepath(cachepath) - cachepath=cleanpath(cachepath) - cachepath=collapsepath(cachepath) - local valid=isdir(cachepath) - if valid then - if is_readable(cachepath) then - readables[#readables+1]=cachepath - if not writable and is_writable(cachepath) then - writable=cachepath - end - end - elseif not writable then - local cacheparent=dirname(cachepath) - if is_writable(cacheparent) then - mkdirs(cachepath) - if isdir(cachepath) and is_writable(cachepath) then - report_caches("path %a created",cachepath) - writable=cachepath - readables[#readables+1]=cachepath - end - end - end - end - end - end - local texmfcaches=caches.defaults - if texmfcaches then - for k=1,#texmfcaches do - local cachepath=texmfcaches[k] - cachepath=resolvers.expansion(cachepath) - if cachepath~="" then - cachepath=resolvepath(cachepath) - cachepath=cleanpath(cachepath) - local valid=isdir(cachepath) - if valid and is_readable(cachepath) then - if not writable and is_writable(cachepath) then - readables[#readables+1]=cachepath - writable=cachepath - break - end - end - end - end - end - if not writable then - report_caches("fatal error: there is no valid writable cache path defined") - osexit() - elseif #readables==0 then - report_caches("fatal error: there is no valid readable cache path defined") - osexit() - end - writable=expanddirname(cleanpath(writable)) - local base=caches.base - local more=caches.more - local tree=cache_tree or treehash() - if tree then - cache_tree=tree - writable=mkdirs(writable,base,more,tree) - for i=1,#readables do - readables[i]=joinfile(readables[i],base,more,tree) - end - else - writable=mkdirs(writable,base,more) - for i=1,#readables do - readables[i]=joinfile(readables[i],base,more) - end - end - if trace_cache then - for i=1,#readables do - report_caches("using readable path %a (order %s)",readables[i],i) - end - report_caches("using writable path %a",writable) - end - identify=function() - return writable,readables - end - return writable,readables -end -function caches.usedpaths(separator) - local writable,readables=identify() - if #readables>1 then - local result={} - local done={} - for i=1,#readables do - local readable=readables[i] - if readable==writable then - done[readable]=true - result[#result+1]=formatters["readable+writable: %a"](readable) - elseif usedreadables[i] then - done[readable]=true - result[#result+1]=formatters["readable: %a"](readable) - end - end - if not done[writable] then - result[#result+1]=formatters["writable: %a"](writable) - end - return concat(result,separator or " | ") - else - return writable or "?" - end -end -local r_cache={} -local w_cache={} -local function getreadablepaths(...) - local tags={... } - local hash=concat(tags,"/") - local done=r_cache[hash] - if not done then - local writable,readables=identify() - if #tags>0 then - done={} - for i=1,#readables do - done[i]=joinfile(readables[i],...) - end - else - done=readables - end - r_cache[hash]=done - end - return done -end -local function getwritablepath(...) - local tags={... } - local hash=concat(tags,"/") - local done=w_cache[hash] - if not done then - local writable,readables=identify() - if #tags>0 then - done=mkdirs(writable,...) - else - done=writable - end - w_cache[hash]=done - end - return done -end -local function setfirstwritablefile(filename,...) - local wr=getwritablepath(...) - local fullname=joinfile(wr,filename) - return fullname,wr -end -local function setluanames(path,name) - return - format("%s/%s.%s",path,name,luasuffixes.tma), - format("%s/%s.%s",path,name,luasuffixes.tmc) -end -local function getfirstreadablefile(filename,...) - local fullname,path=setfirstwritablefile(filename,...) - if is_readable(fullname) then - return fullname,path - end - local rd=getreadablepaths(...) - for i=1,#rd do - local path=rd[i] - local fullname=joinfile(path,filename) - if is_readable(fullname) then - usedreadables[i]=true - return fullname,path - end - end - return fullname,path -end -caches.getreadablepaths=getreadablepaths -caches.getwritablepath=getwritablepath -caches.setfirstwritablefile=setfirstwritablefile -caches.getfirstreadablefile=getfirstreadablefile -caches.setluanames=setluanames -local checkmemory=utilities and utilities.lua and utilities.lua.checkmemory -local threshold=100 -function caches.loaddata(readables,name,writable) - local used=checkmemory and checkmemory() - if type(readables)=="string" then - readables={ readables } - end - for i=1,#readables do - local path=readables[i] - local loader=false - local state=false - local tmaname,tmcname=setluanames(path,name) - if isfile(tmcname) then - state,loader=pcall(loadfile,tmcname) - end - if not loader and isfile(tmaname) then - local tmacrap,tmcname=setluanames(writable,name) - if isfile(tmcname) then - state,loader=pcall(loadfile,tmcname) - end - compilelua(tmaname,tmcname) - if isfile(tmcname) then - state,loader=pcall(loadfile,tmcname) - end - if not loader then - state,loader=pcall(loadfile,tmaname) - end - end - if loader then - loader=loader() - if checkmemory then - checkmemory(used,threshold) - else - collectgarbage("step") - end - return loader - end - end - return false -end -function caches.is_writable(filepath,filename) - local tmaname,tmcname=setluanames(filepath,filename) - return is_writable(tmaname) -end -local saveoptions={ compact=true,accurate=not JITSUPPORTED } -function caches.savedata(filepath,filename,data,fast) - local tmaname,tmcname=setluanames(filepath,filename) - data.cache_uuid=osuuid() - if fast or fast_cache then - savedata(tmaname,fastserialize(data,true)) - elseif direct_cache then - savedata(tmaname,serialize(data,true,saveoptions)) - else - serializetofile(tmaname,data,true,saveoptions) - end - compilelua(tmaname,tmcname) -end -local content_state={} -function caches.contentstate() - return content_state or {} -end -function caches.loadcontent(cachename,dataname,filename) - if not filename then - local name=hashed(cachename) - local full,path=getfirstreadablefile(addsuffix(name,luasuffixes.lua),"trees") - filename=joinfile(path,name) - end - local state,blob=pcall(loadfile,addsuffix(filename,luasuffixes.luc)) - if not blob then - state,blob=pcall(loadfile,addsuffix(filename,luasuffixes.lua)) - end - if blob then - local data=blob() - if data and data.content then - if data.type==dataname then - if data.version==resolvers.cacheversion then - content_state[#content_state+1]=data.uuid - if trace_locating then - report_resolvers("loading %a for %a from %a",dataname,cachename,filename) - end - return data.content - else - report_resolvers("skipping %a for %a from %a (version mismatch)",dataname,cachename,filename) - end - else - report_resolvers("skipping %a for %a from %a (datatype mismatch)",dataname,cachename,filename) - end - elseif trace_locating then - report_resolvers("skipping %a for %a from %a (no content)",dataname,cachename,filename) - end - elseif trace_locating then - report_resolvers("skipping %a for %a from %a (invalid file)",dataname,cachename,filename) - end -end -function caches.collapsecontent(content) - for k,v in next,content do - if type(v)=="table" and #v==1 then - content[k]=v[1] - end - end -end -function caches.savecontent(cachename,dataname,content,filename) - if not filename then - local name=hashed(cachename) - local full,path=setfirstwritablefile(addsuffix(name,luasuffixes.lua),"trees") - filename=joinfile(path,name) - end - local luaname=addsuffix(filename,luasuffixes.lua) - local lucname=addsuffix(filename,luasuffixes.luc) - if trace_locating then - report_resolvers("preparing %a for %a",dataname,cachename) - end - local data={ - type=dataname, - root=cachename, - version=resolvers.cacheversion, - date=osdate("%Y-%m-%d"), - time=osdate("%H:%M:%S"), - content=content, - uuid=osuuid(), - } - local ok=savedata(luaname,serialize(data,true)) - if ok then - if trace_locating then - report_resolvers("category %a, cachename %a saved in %a",dataname,cachename,luaname) - end - if compilelua(luaname,lucname) then - if trace_locating then - report_resolvers("%a compiled to %a",dataname,lucname) - end - return true - else - if trace_locating then - report_resolvers("compiling failed for %a, deleting file %a",dataname,lucname) - end - removefile(lucname) - end - elseif trace_locating then - report_resolvers("unable to save %a in %a (access error)",dataname,luaname) - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-met"] = package.loaded["data-met"] or true - --- original size: 5518, stripped down to: 3854 - -if not modules then modules={} end modules ['data-met']={ - version=1.100, - 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=type -local find=string.find -local addurlscheme,urlhashed=url.addscheme,url.hashed -local collapsepath,joinfile=file.collapsepath,file.join -local report_methods=logs.reporter("resolvers","methods") -local trace_locating=false -local trace_methods=false -trackers.register("resolvers.locating",function(v) trace_methods=v end) -trackers.register("resolvers.methods",function(v) trace_methods=v end) -local allocate=utilities.storage.allocate -local resolvers=resolvers -local registered={} -local function splitmethod(filename) - if not filename then - return { - scheme="unknown", - original=filename, - } - end - if type(filename)=="table" then - return filename - end - filename=collapsepath(filename,".") - if not find(filename,"://",1,true) then - return { - scheme="file", - path=filename, - original=filename, - filename=filename, - } - end - local specification=urlhashed(filename) - if not specification.scheme or specification.scheme=="" then - return { - scheme="file", - path=filename, - original=filename, - filename=filename, - } - else - return specification - end -end -resolvers.splitmethod=splitmethod -local function methodhandler(what,first,...) - local method=registered[what] - if method then - local how=method.how - local namespace=method.namespace - if how=="uri" or how=="url" then - local specification=splitmethod(first) - local scheme=specification.scheme - local resolver=namespace and namespace[scheme] - if resolver then - if trace_methods then - report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,scheme,first) - end - return resolver(specification,...) - else - resolver=namespace.default or namespace.file - if resolver then - if trace_methods then - report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"default",first) - end - return resolver(specification,...) - elseif trace_methods then - report_methods("resolving, method %a, how %a, handler %a, argument %a",what,how,"unset") - end - end - elseif how=="tag" then - local resolver=namespace and namespace[first] - if resolver then - if trace_methods then - report_methods("resolving, method %a, how %a, tag %a",what,how,first) - end - return resolver(...) - else - resolver=namespace.default or namespace.file - if resolver then - if trace_methods then - report_methods("resolving, method %a, how %a, tag %a",what,how,"default") - end - return resolver(...) - elseif trace_methods then - report_methods("resolving, method %a, how %a, tag %a",what,how,"unset") - end - end - end - else - report_methods("resolving, invalid method %a") - end -end -resolvers.methodhandler=methodhandler -function resolvers.registermethod(name,namespace,how) - registered[name]={ - how=how or "tag", - namespace=namespace - } - namespace["byscheme"]=function(scheme,filename,...) - if scheme=="file" then - return methodhandler(name,filename,...) - else - return methodhandler(name,addurlscheme(filename,scheme),...) - end - end -end -local concatinators=allocate { notfound=joinfile } -local locators=allocate { notfound=function() end } -local hashers=allocate { notfound=function() end } -local generators=allocate { notfound=function() end } -resolvers.concatinators=concatinators -resolvers.locators=locators -resolvers.hashers=hashers -resolvers.generators=generators -local registermethod=resolvers.registermethod -registermethod("concatinators",concatinators,"tag") -registermethod("locators",locators,"uri") -registermethod("hashers",hashers,"uri") -registermethod("generators",generators,"uri") - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-res"] = package.loaded["data-res"] or true - --- original size: 69576, stripped down to: 44470 - -if not modules then modules={} end modules ['data-res']={ - 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 gsub,find,lower,upper,match,gmatch=string.gsub,string.find,string.lower,string.upper,string.match,string.gmatch -local concat,insert,remove=table.concat,table.insert,table.remove -local next,type,rawget,loadfile=next,type,rawget,loadfile -local mergedtable=table.merged -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 -local lpegmatch,lpegpatterns=lpeg.match,lpeg.patterns -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 urlhasscheme=url.hasscheme -local getcurrentdir=lfs.currentdir -local isfile=lfs.isfile -local isdir=lfs.isdir -local setmetatableindex=table.setmetatableindex -local luasuffixes=utilities.lua.suffixes -local trace_locating=false trackers .register("resolvers.locating",function(v) trace_locating=v end) -local trace_details=false trackers .register("resolvers.details",function(v) trace_details=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 -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.100" -resolvers.configbanner="" -resolvers.homedir=environment.homedir -resolvers.luacnfname="texmfcnf.lua" -resolvers.luacnffallback="contextcnf.lua" -resolvers.luacnfstate="unknown" -local criticalvars={ - "SELFAUTOLOC", - "SELFAUTODIR", - "SELFAUTOPARENT", - "TEXMFCNF", - "TEXMF", - "TEXOS", -} -if environment.default_texmfcnf then - resolvers.luacnfspec="home:texmf/web2c;"..environment.default_texmfcnf -else - resolvers.luacnfspec=concat ({ - "home:texmf/web2c", - "selfautoparent:/texmf-local/web2c", - "selfautoparent:/texmf-context/web2c", - "selfautoparent:/texmf-dist/web2c", - "selfautoparent:/texmf/web2c", - },";") -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" } -local instance=nil -local variable -local expansion -local setenv -local getenv -local formatofsuffix=resolvers.formatofsuffix -local splitpath=resolvers.splitpath -local splitmethod=resolvers.splitmethod -setenv=function(key,value,raw) - if instance then - instance.environment[key]=value - ossetenv(key,raw and value or resolveprefix(value)) - end -end -getenv=function(key) - local value=rawget(instance.environment,key) - if value and value~="" then - return value - else - local e=osgetenv(key) - return e~=nil and e~="" and checkedvariable(e) or "" - end -end -resolvers.getenv=getenv -resolvers.setenv=setenv -local dollarstripper=lpeg.stripper("$") -local inhibitstripper=P("!")^0*Cs(P(1)^0) -local expandedvariable,resolvedvariable do - local function resolveinstancevariable(k) - return instance.expansions[k] - end - local p_variable=P("$")/"" - local p_key=C(R("az","AZ","09","__","--")^1) - local p_whatever=P(";")*((1-S("!{}/\\"))^1*P(";")/"")+P(";")*(P(";")/"")+P(1) - local variableexpander=Cs((p_variable*(p_key/resolveinstancevariable)+p_whatever)^1 ) - local p_cleaner=P("\\")/"/"+P(";")*S("!{}/\\")^0*P(";")^1/";" - local variablecleaner=Cs((p_cleaner+P(1))^0) - local p_variable=R("az","AZ","09","__","--")^1/resolveinstancevariable - local p_variable=(P("$")/"")*(p_variable+(P("{")/"")*p_variable*(P("}")/"")) - local variableresolver=Cs((p_variable+P(1))^0) - expandedvariable=function(var) - return lpegmatch(variableexpander,var) or var - end - function resolvers.reset() - if trace_locating then - report_resolving("creating instance") - end - local environment={} - local variables={} - local expansions={} - local order={} - instance={ - environment=environment, - variables=variables, - expansions=expansions, - order=order, - files={}, - setups={}, - found={}, - foundintrees={}, - hashes={}, - hashed={}, - pathlists=false, - specification={}, - lists={}, - data={}, - fakepaths={}, - remember=true, - diskcache=true, - renewcache=false, - renewtree=false, - loaderror=false, - savelists=true, - pattern=nil, - force_suffixes=true, - pathstack={}, - } - setmetatableindex(variables,function(t,k) - local v - for i=1,#order do - v=order[i][k] - if v~=nil then - t[k]=v - return v - end - end - if v==nil then - v="" - end - t[k]=v - return v - end) - local repath=resolvers.repath - setmetatableindex(environment,function(t,k) - local v=osgetenv(k) - if v==nil then - v=variables[k] - end - if v~=nil then - v=checkedvariable(v) or "" - end - v=repath(v) - t[k]=v - return v - end) - setmetatableindex(expansions,function(t,k) - local v=environment[k] - if type(v)=="string" then - v=lpegmatch(variableresolver,v) - v=lpegmatch(variablecleaner,v) - end - t[k]=v - return v - end) - end -end -function resolvers.initialized() - return instance~=nil -end -local function reset_hashes() - instance.lists={} - instance.pathlists=false - instance.found={} -end -local function reset_caches() - instance.lists={} - instance.pathlists=false -end -local makepathexpression do - local slash=P("/") - local pathexpressionpattern=Cs ( - Cc("^")*( - Cc("%")*S(".-")+slash^2*P(-1)/"/.*" -+slash^2/"/"+(1-slash)*P(-1)*Cc("/")+P(1) - )^1*Cc("$") - ) - local cache={} - makepathexpression=function(str) - if str=="." then - return "^%./$" - else - local c=cache[str] - if not c then - c=lpegmatch(pathexpressionpattern,str) - cache[str]=c - end - return c - end - end -end -local function reportcriticalvariables(cnfspec) - if trace_locating then - for i=1,#criticalvars do - local k=criticalvars[i] - local v=getenv(k) or "unknown" - report_resolving("variable %a set to %a",k,v) - end - report_resolving() - if cnfspec then - report_resolving("using configuration specification %a",type(cnfspec)=="table" and concat(cnfspec,",") or cnfspec) - end - report_resolving() - end - reportcriticalvariables=function() end -end -local function identify_configuration_files() - local specification=instance.specification - if #specification==0 then - local cnfspec=getenv("TEXMFCNF") - if cnfspec=="" then - cnfspec=resolvers.luacnfspec - resolvers.luacnfstate="default" - else - resolvers.luacnfstate="environment" - end - reportcriticalvariables(cnfspec) - local cnfpaths=expandedpathfromlist(splitpath(cnfspec)) - local function locatecnf(luacnfname,kind) - for i=1,#cnfpaths do - local filepath=cnfpaths[i] - local filename=collapsepath(filejoin(filepath,luacnfname)) - local realname=resolveprefix(filename) - if trace_locating then - local fullpath=gsub(resolveprefix(collapsepath(filepath)),"//","/") - local weirdpath=find(fullpath,"/texmf.+/texmf") or not find(fullpath,"/web2c",1,true) - report_resolving("looking for %s %a on %s path %a from specification %a", - kind,luacnfname,weirdpath and "weird" or "given",fullpath,filepath) - end - if isfile(realname) then - specification[#specification+1]=filename - if trace_locating then - report_resolving("found %s configuration file %a",kind,realname) - end - end - end - end - locatecnf(resolvers.luacnfname,"regular") - if #specification==0 then - locatecnf(resolvers.luacnffallback,"fallback") - end - if trace_locating then - report_resolving() - end - elseif trace_locating then - report_resolving("configuration files already identified") - end -end -local function load_configuration_files() - local specification=instance.specification - local setups=instance.setups - local order=instance.order - if #specification>0 then - local luacnfname=resolvers.luacnfname - for i=1,#specification do - local filename=specification[i] - local pathname=filedirname(filename) - local filename=filejoin(pathname,luacnfname) - local realname=resolveprefix(filename) - local blob=loadfile(realname) - if blob then - local data=blob() - local parent=data and data.parent - if parent then - local filename=filejoin(pathname,parent) - local realname=resolveprefix(filename) - local blob=loadfile(realname) - if blob then - local parentdata=blob() - if parentdata then - report_resolving("loading configuration file %a",filename) - data=mergedtable(parentdata,data) - end - end - end - data=data and data.content - if data then - if trace_locating then - report_resolving("loading configuration file %a",filename) - report_resolving() - end - local variables=data.variables or {} - local warning=false - for k,v in next,data do - local variant=type(v) - if variant=="table" then - initializesetter(filename,k,v) - 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,resolveprefix(filename)) - warning=true - end - variables[k]=v - end - end - setups[pathname]=variables - if resolvers.luacnfstate=="default" then - local cnfspec=variables["TEXMFCNF"] - if cnfspec then - if trace_locating then - report_resolving("reloading configuration due to TEXMF redefinition") - end - setenv("TEXMFCNF",cnfspec) - instance.specification={} - identify_configuration_files() - load_configuration_files() - resolvers.luacnfstate="configuration" - break - end - end - else - if trace_locating then - report_resolving("skipping configuration file %a (no content)",filename) - end - setups[pathname]={} - instance.loaderror=true - end - elseif trace_locating then - report_resolving("skipping configuration file %a (no valid format)",filename) - end - order[#order+1]=setups[pathname] - if instance.loaderror then - break - end - end - elseif trace_locating then - report_resolving("warning: no lua configuration files found") - end -end -local expandedpathlist -local unexpandedpathlist -function resolvers.configurationfiles() - return instance.specification or {} -end -local function load_file_databases() - instance.loaderror=false - instance.files={} - if not instance.renewcache then - local hashes=instance.hashes - for k=1,#hashes do - local hash=hashes[k] - resolvers.hashers.byscheme(hash.type,hash.name) - if instance.loaderror then break end - end - end -end -local function locate_file_databases() - local texmfpaths=expandedpathlist("TEXMF") - if #texmfpaths>0 then - for i=1,#texmfpaths do - local path=collapsepath(texmfpaths[i]) - path=gsub(path,"/+$","") - local stripped=lpegmatch(inhibitstripper,path) - if stripped~="" then - local runtime=stripped==path - path=cleanpath(path) - local spec=splitmethod(stripped) - if runtime and (spec.noscheme or spec.scheme=="file") then - stripped="tree:///"..stripped - elseif spec.scheme=="cache" or spec.scheme=="file" then - stripped=spec.path - end - if trace_locating then - if runtime then - report_resolving("locating list of %a (runtime) (%s)",path,stripped) - else - report_resolving("locating list of %a (cached)",path) - end - end - methodhandler('locators',stripped) - end - end - if trace_locating then - report_resolving() - end - elseif trace_locating then - report_resolving("no texmf paths are defined (using TEXMF)") - end -end -local function generate_file_databases() - local hashes=instance.hashes - for k=1,#hashes do - local hash=hashes[k] - methodhandler('generators',hash.name) - end - if trace_locating then - report_resolving() - end -end -local function save_file_databases() - local hashes=instance.hashes - local files=instance.files - for i=1,#hashes do - local hash=hashes[i] - local cachename=hash.name - if hash.cache then - local content=files[cachename] - caches.collapsecontent(content) - if trace_locating then - report_resolving("saving tree %a",cachename) - end - caches.savecontent(cachename,"files",content) - elseif trace_locating then - report_resolving("not saving runtime tree %a",cachename) - end - end -end -function resolvers.renew(hashname) - local files=instance.files - if hashname and hashname~="" then - local expanded=expansion(hashname) or "" - if expanded~="" then - if trace_locating then - report_resolving("identifying tree %a from %a",expanded,hashname) - end - hashname=expanded - else - if trace_locating then - report_resolving("identifying tree %a",hashname) - end - end - local realpath=resolveprefix(hashname) - if isdir(realpath) then - if trace_locating then - report_resolving("using path %a",realpath) - end - methodhandler('generators',hashname) - local content=files[hashname] - caches.collapsecontent(content) - if trace_locating then - report_resolving("saving tree %a",hashname) - end - caches.savecontent(hashname,"files",content) - else - report_resolving("invalid path %a",realpath) - end - end -end -local function load_databases() - locate_file_databases() - if instance.diskcache and not instance.renewcache then - load_file_databases() - if instance.loaderror then - generate_file_databases() - save_file_databases() - end - else - generate_file_databases() - if instance.renewcache then - save_file_databases() - end - end -end -function resolvers.appendhash(type,name,cache) - local hashed=instance.hashed - local hashes=instance.hashes - if hashed[name] then - else - if trace_locating then - report_resolving("hash %a appended",name) - end - insert(hashes,{ type=type,name=name,cache=cache } ) - hashed[name]=cache - end -end -function resolvers.prependhash(type,name,cache) - local hashed=instance.hashed - local hashes=instance.hashes - if hashed[name] then - else - if trace_locating then - report_resolving("hash %a prepended",name) - end - insert(hashes,1,{ type=type,name=name,cache=cache } ) - hashed[name]=cache - end -end -function resolvers.extendtexmfvariable(specification) - local environment=instance.environment - local variables=instance.variables - local texmftrees=splitpath(getenv("TEXMF")) - insert(texmftrees,1,specification) - texmftrees=concat(texmftrees,",") - if environment["TEXMF"] then - environment["TEXMF"]=texmftrees - elseif variables["TEXMF"] then - variables["TEXMF"]=texmftrees - else - end - reset_hashes() -end -function resolvers.splitexpansions() - local expansions=instance.expansions - for k,v in next,expansions do - local t,tn,h,p={},0,{},splitconfigurationpath(v) - for kk=1,#p do - local vv=p[kk] - if vv~="" and not h[vv] then - tn=tn+1 - t[tn]=vv - h[vv]=true - end - end - if tn>1 then - expansions[k]=t - else - expansions[k]=t[1] - end - end -end -function resolvers.datastate() - return caches.contentstate() -end -variable=function(name) - local variables=instance.variables - local name=name and lpegmatch(dollarstripper,name) - local result=name and variables[name] - return result~=nil and result or "" -end -expansion=function(name) - local expansions=instance.expansions - local name=name and lpegmatch(dollarstripper,name) - local result=name and expansions[name] - return result~=nil and result or "" -end -resolvers.variable=variable -resolvers.expansion=expansion -unexpandedpathlist=function(str) - local pth=variable(str) - local lst=splitpath(pth) - return expandedpathfromlist(lst) -end -function resolvers.unexpandedpath(str) - return joinpath(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.resetextrapaths() - local extra_paths=instance.extra_paths - if not extra_paths then - done={} - instance.extra_paths={} - elseif #ep>0 then - done={} - reset_caches() - end -end -function resolvers.getextrapaths() - return instance.extra_paths or {} -end -function resolvers.registerextrapath(paths,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 extra_paths=instance.extra_paths or {} - local oldn=#extra_paths - local newn=oldn - local nofpaths=#paths - local nofsubpaths=#subpaths - if nofpaths>0 then - if nofsubpaths>0 then - for i=1,nofpaths do - local p=paths[i] - for j=1,nofsubpaths do - local s=subpaths[j] - local ps=p.."/"..s - if not done[ps] then - newn=newn+1 - extra_paths[newn]=cleanpath(ps) - done[ps]=true - end - end - end - else - for i=1,nofpaths do - local p=paths[i] - if not done[p] then - newn=newn+1 - extra_paths[newn]=cleanpath(p) - done[p]=true - end - end - end - elseif nofsubpaths>0 then - for i=1,oldn do - for j=1,nofsubpaths do - local s=subpaths[j] - local ps=extra_paths[i].."/"..s - if not done[ps] then - newn=newn+1 - extra_paths[newn]=cleanpath(ps) - done[ps]=true - end - end - end - end - if newn>0 then - instance.extra_paths=extra_paths - end - if newn~=oldn then - reset_caches() - end -end -function resolvers.pushextrapath(path) - local paths=settings_to_array(path) - local extra_stack=instance.extra_stack - if extra_stack then - insert(extra_stack,1,paths) - else - instance.extra_stack={ paths } - end - reset_caches() -end -function resolvers.popextrapath() - local extra_stack=instance.extra_stack - if extra_stack then - reset_caches() - return remove(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 - 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 extra_stack=instance.extra_stack - local extra_paths=instance.extra_paths - if extra_stack and #extra_stack>0 then - for k=1,#extra_stack do - add(extra_stack[k]) - end - end - if extra_paths and #extra_paths>0 then - add(extra_paths) - end - end - add(list) - return new -end -expandedpathlist=function(str,extra_too) - if not str then - return {} - 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,splitpath(expansion(str)),extra_too) - lst=expandedpathfromlist(l) - lists[str]=lst - end - return lst - else - local lst=splitpath(expansion(str)) - return made_list(instance,expandedpathfromlist(lst),extra_too) - end -end -resolvers.expandedpathlist=expandedpathlist -resolvers.unexpandedpathlist=unexpandedpathlist -function resolvers.cleanpathlist(str) - local t=expandedpathlist(str) - if t then - for i=1,#t do - t[i]=collapsepath(cleanpath(t[i])) - end - end - return t -end -function resolvers.expandpath(str) - return joinpath(expandedpathlist(str)) -end -local function expandedpathlistfromvariable(str) - str=lpegmatch(dollarstripper,str) - local tmp=resolvers.variableofformatorsuffix(str) - return expandedpathlist(tmp~="" and tmp or str) -end -function resolvers.expandpathfromvariable(str) - return joinpath(expandedpathlistfromvariable(str)) -end -resolvers.expandedpathlistfromvariable=expandedpathlistfromvariable -function resolvers.cleanedpathlist(v) - local t=expandedpathlist(v) - for i=1,#t do - t[i]=resolveprefix(cleanpath(t[i])) - end - return t -end -function resolvers.expandbraces(str) - local pth=expandedpathfromlist(splitpath(str)) - return joinpath(pth) -end -function resolvers.registerfilehash(name,content,someerror) - local files=instance.files - if content then - files[name]=content - else - files[name]={} - if somerror==true then - instance.loaderror=someerror - end - end -end -function resolvers.getfilehashes() - return instance and instance.files or {} -end -function resolvers.gethashes() - return instance and instance.hashes or {} -end -function resolvers.renewcache() - if instance then - instance.renewcache=true - end -end -local function isreadable(name) - local readable=isfile(name) - if trace_details then - if readable then - report_resolving("file %a is readable",name) - else - report_resolving("file %a is not readable",name) - end - end - return readable -end -local function collect_files(names) - local filelist={} - local noffiles=0 - local function check(hash,root,pathname,path,basename,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_details 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 filename=names[k] - if trace_details then - report_resolving("checking name %a",filename) - end - local basename=filebasename(filename) - local pathname=filedirname(filename) - if pathname=="" or find(pathname,"^%.") then - pathname=false - else - pathname=gsub(pathname,"%*",".*") - pathname="/"..pathname.."$" - end - local hashes=instance.hashes - local files=instance.files - for h=1,#hashes do - local hash=hashes[h] - local hashname=hash.name - local content=hashname and files[hashname] - if content then - if trace_details then - report_resolving("deep checking %a, base %a, pattern %a",hashname,basename,pathname) - 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,basename,name) - else - for i=1,#path do - check(hash,realroot,pathname,path[i],basename,name) - end - end - end - elseif trace_locating then - report_resolving("no match in %a (%s)",hashname,basename) - end - end - end - return noffiles>0 and filelist or nil -end -local fit={} -function resolvers.registerintrees(filename,format,filetype,usedmethod,foundname) - local foundintrees=instance.foundintrees - if usedmethod=="direct" and filename==foundname and fit[foundname] then - else - local collapsed=collapsepath(foundname,true) - local t={ - filename=filename, - format=format~="" and format or nil, - filetype=filetype~="" and filetype or nil, - usedmethod=usedmethod, - foundname=foundname, - fullname=collapsed, - } - fit[foundname]=t - foundintrees[#foundintrees+1]=t - end -end -function resolvers.foundintrees() - return instance.foundintrees or {} -end -function resolvers.foundintree(fullname) - local f=fit[fullname] - return f and f.usedmethod=="database" -end -local function can_be_dir(name) - local fakepaths=instance.fakepaths - if not fakepaths[name] then - if isdir(name) then - fakepaths[name]=1 - else - fakepaths[name]=2 - end - end - return fakepaths[name]==1 -end -local preparetreepattern=Cs((P(".")/"%%."+P("-")/"%%-"+P(1))^0*Cc("$")) -local collect_instance_files -local function find_analyze(filename,askedformat,allresults) - local filetype='' - local filesuffix=suffixonly(filename) - local wantedfiles={} - wantedfiles[#wantedfiles+1]=filename - if askedformat=="" then - if filesuffix=="" or not suffixmap[filesuffix] then - local defaultsuffixes=resolvers.defaultsuffixes - for i=1,#defaultsuffixes do - local forcedname=filename..'.'..defaultsuffixes[i] - wantedfiles[#wantedfiles+1]=forcedname - filetype=formatofsuffix(forcedname) - if trace_locating then - report_resolving("forcing filetype %a",filetype) - end - end - else - filetype=formatofsuffix(filename) - if trace_locating then - report_resolving("using suffix based filetype %a",filetype) - end - end - else - if filesuffix=="" or not suffixmap[filesuffix] then - local format_suffixes=suffixes[askedformat] - if format_suffixes then - for i=1,#format_suffixes do - wantedfiles[#wantedfiles+1]=filename.."."..format_suffixes[i] - end - end - end - filetype=askedformat - if trace_locating then - report_resolving("using given filetype %a",filetype) - end - end - return filetype,wantedfiles -end -local function find_direct(filename,allresults) - if not dangerous[askedformat] and isreadable(filename) then - if trace_details then - report_resolving("file %a found directly",filename) - end - return "direct",{ filename } - end -end -local function find_wildcard(filename,allresults) - if find(filename,'*',1,true) then - if trace_locating then - report_resolving("checking wildcard %a",filename) - end - local result=resolvers.findwildcardfiles(filename) - if result then - return "wildcard",result - end - end -end -local function find_qualified(filename,allresults,askedformat,alsostripped) - if not is_qualified_path(filename) then - return - end - if trace_locating then - report_resolving("checking qualified name %a",filename) - end - if isreadable(filename) then - if trace_details then - report_resolving("qualified file %a found",filename) - end - return "qualified",{ filename } - end - if trace_details then - report_resolving("locating qualified file %a",filename) - end - local forcedname,suffix="",suffixonly(filename) - if suffix=="" then - local format_suffixes=askedformat=="" and resolvers.defaultsuffixes or suffixes[askedformat] - if format_suffixes then - for i=1,#format_suffixes do - local suffix=format_suffixes[i] - forcedname=filename.."."..suffix - if isreadable(forcedname) then - if trace_locating then - report_resolving("no suffix, forcing format filetype %a",suffix) - end - return "qualified",{ forcedname } - end - end - end - end - if alsostripped and suffix and suffix~="" then - local basename=filebasename(filename) - local pattern=lpegmatch(preparetreepattern,filename) - local savedformat=askedformat - local format=savedformat or "" - if format=="" then - askedformat=formatofsuffix(suffix) - end - if not format then - askedformat="othertextfiles" - end - if basename~=filename then - local resolved=collect_instance_files(basename,askedformat,allresults) - if #resolved==0 then - local lowered=lower(basename) - if filename~=lowered then - resolved=collect_instance_files(lowered,askedformat,allresults) - end - end - resolvers.format=savedformat - if #resolved>0 then - local result={} - for r=1,#resolved do - local rr=resolved[r] - if find(rr,pattern) then - result[#result+1]=rr - end - end - if #result>0 then - return "qualified",result - end - end - end - end -end -local function check_subpath(fname) - if isreadable(fname) then - if trace_details then - report_resolving("found %a by deep scanning",fname) - end - return fname - end -end -local function makepathlist(list,filetype) - local typespec=resolvers.variableofformat(filetype) - local pathlist=expandedpathlist(typespec,filetype and usertypes[filetype]) - local entry={} - if pathlist and #pathlist>0 then - 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=urlhasscheme(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({},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_details then - report_resolving("checking filename %a in tree",filename) - end - for k=1,#pathlist do - local entry=pathlist[k] - local path=entry.path - local pathname=entry.pathname - local done=false - if filelist then - local expression=entry.expression - if trace_details then - report_resolving("using pattern %a for path %a",expression,pathname) - end - for k=1,#filelist do - local fl=filelist[k] - local f=fl[2] - local d=dirlist[k] - if find(d,expression) or find(resolveprefix(d),expression) then - result[#result+1]=resolveprefix(fl[3]) - done=true - if allresults then - if trace_details then - report_resolving("match to %a in hash for file %a and path %a, continue scanning",expression,f,d) - end - else - if trace_details then - report_resolving("match to %a in hash for file %a and path %a, quit scanning",expression,f,d) - end - break - end - elseif trace_details then - report_resolving("no match to %a in hash for file %a and path %a",expression,f,d) - end - end - end - if done then - method="database" - else - method="filesystem" - local scheme=entry.scheme - if not scheme or scheme=="file" then - local pname=entry.schemename - if not find(pname,"*",1,true) then - if can_be_dir(pname) then - if not done and not entry.prescanned then - if trace_details then - report_resolving("quick root scan for %a",pname) - end - 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 - end - end - if not done and entry.recursive then - if trace_details 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 - if done and not allresults then - break - end - end - end - end - end - 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 - break - end - end - if #result>0 then - return method,result - end - end -end -local function find_onpath(filename,filetype,wantedfiles,allresults) - if trace_details then - report_resolving("checking filename %a, filetype %a, wanted files %a",filename,filetype,concat(wantedfiles," | ")) - end - local result={} - for k=1,#wantedfiles do - local fname=wantedfiles[k] - if fname and isreadable(fname) then - filename=fname - result[#result+1]=filejoin('.',fname) - if not allresults then - break - end - end - end - if #result>0 then - return "onpath",result - end -end -local function find_otherwise(filename,filetype,wantedfiles,allresults) - local filelist=collect_files(wantedfiles) - local fl=filelist and filelist[1] - if fl then - 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().."/") - if allresults then - local filetype,wantedfiles=find_analyze(filename,askedformat) - local results={ - { find_direct (filename,true) }, - { find_wildcard (filename,true) }, - { find_qualified(filename,true,askedformat) }, - { find_intree (filename,filetype,wantedfiles,true) }, - { find_onpath (filename,filetype,wantedfiles,true) }, - { find_otherwise(filename,filetype,wantedfiles,true) }, - } - local result={} - local status={} - local done={} - for k,r in next,results do - local method,list=r[1],r[2] - if method and list then - for i=1,#list do - local c=collapsepath(list[i]) - if not done[c] then - result[#result+1]=c - done[c]=true - end - status[#status+1]=formatters["%-10s: %s"](method,c) - end - end - end - if trace_details then - report_resolving("lookup status: %s",table.serialize(status,filename)) - end - return result,status - else - local method,result,stamp,filetype,wantedfiles - if instance.remember then - 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 - report_resolving("remembered file %a",filename) - end - return result - end - end - method,result=find_direct(filename) - if not result then - method,result=find_wildcard(filename) - if not result then - method,result=find_qualified(filename,false,askedformat) - if not result then - filetype,wantedfiles=find_analyze(filename,askedformat) - method,result=find_intree(filename,filetype,wantedfiles) - if not result then - method,result=find_onpath(filename,filetype,wantedfiles) - if resolve_otherwise and not result then - method,result=find_otherwise(filename,filetype,wantedfiles) - end - end - end - end - end - if result and #result>0 then - local foundname=collapsepath(result[1]) - resolvers.registerintrees(filename,askedformat,filetype,method,foundname) - result={ foundname } - else - result={} - end - if stamp then - if trace_locating then - report_resolving("remembering file %a using hash %a",filename,stamp) - end - instance.found[stamp]=result - end - return result - end -end -local function findfiles(filename,filetype,allresults) - if not filename or filename=="" then - return {} - end - if allresults==nil then - allresults=true - end - local result,status=collect_instance_files(filename,filetype or "",allresults) - if not result or #result==0 then - local lowered=lower(filename) - if filename~=lowered then - result,status=collect_instance_files(lowered,filetype or "",allresults) - end - end - return result or {},status -end -local function findfile(filename,filetype) - if not filename or filename=="" then - return "" - else - return findfiles(filename,filetype,false)[1] or "" - end -end -resolvers.findfiles=findfiles -resolvers.findfile=findfile -resolvers.find_file=findfile -resolvers.find_files=findfiles -function resolvers.findpath(filename,filetype) - return filedirname(findfiles(filename,filetype,false)[1] or "") -end -local function findgivenfiles(filename,allresults) - local hashes=instance.hashes - local files=instance.files - local base=filebasename(filename) - local result={} - 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 content=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 i=1,#path do - if okay(hash,path[i],name) then - return result - end - end - end - end - end - return result -end -function resolvers.findgivenfiles(filename) - return findgivenfiles(filename,true) -end -function resolvers.findgivenfile(filename) - return findgivenfiles(filename,false)[1] or "" -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) - local files=instance.files - local hashes=instance.hashes - 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) - if find(name,"*",1,true) then - 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=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 - for k=1,#hashes do - local hash=hashes[k] - 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 -end -function resolvers.findwildcardfiles(filename,result) - return findwildcardfiles(filename,true,result) -end -function resolvers.findwildcardfile(filename) - return findwildcardfiles(filename,false)[1] or "" -end -do - local starttiming=statistics.starttiming - local stoptiming=statistics.stoptiming - local elapsedtime=statistics.elapsedtime - function resolvers.starttiming() - starttiming(instance) - end - function resolvers.stoptiming() - stoptiming(instance) - end - function resolvers.loadtime() - return elapsedtime(instance) - end -end -function resolvers.automount() -end -function resolvers.load(option) - resolvers.starttiming() - identify_configuration_files() - load_configuration_files() - if option~="nofiles" then - load_databases() - resolvers.automount() - end - resolvers.stoptiming() - local files=instance.files - return files and next(files) and true -end -local function report(str) - if trace_locating then - report_resolving(str) - else - print(str) - end -end -function resolvers.dowithfilesandreport(command,files,...) - if files and #files>0 then - if trace_locating then - report('') - end - if type(files)=="string" then - files={ files } - end - for f=1,#files do - local file=files[f] - local result=command(file,...) - if type(result)=='string' then - report(result) - else - for i=1,#result do - report(result[i]) - end - end - end - end -end -function resolvers.showpath(str) - return joinpath(expandedpathlist(resolvers.formatofvariable(str))) -end -function resolvers.registerfile(files,name,path) - if files[name] then - if type(files[name])=='string' then - files[name]={ files[name],path } - else - files[name]=path - end - else - files[name]=path - end -end -function resolvers.dowithpath(name,func) - local pathlist=expandedpathlist(name) - for i=1,#pathlist do - func("^"..cleanpath(pathlist[i])) - end -end -function resolvers.dowithvariable(name,func) - func(expandedvariable(name)) -end -function resolvers.locateformat(name) - local engine=environment.ownmain or "luatex" - local barename=removesuffix(file.basename(name)) - local fullname=addsuffix(barename,"fmt") - local fmtname=caches.getfirstreadablefile(fullname,"formats",engine) or "" - if fmtname=="" then - fmtname=findfile(fullname) - fmtname=cleanpath(fmtname) - end - if fmtname~="" 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 fmtname,luiname - elseif isfile(lucname) then - return fmtname,lucname - elseif isfile(luaname) then - return fmtname,luaname - end - end - return nil,nil -end -function resolvers.booleanvariable(str,default) - local b=expansion(str) - if b=="" then - return default - else - b=toboolean(b) - return (b==nil and default) or b - end -end -function resolvers.dowithfilesintree(pattern,handle,before,after) - local hashes=instance.hashes - local files=instance.files - for i=1,#hashes do - local hash=hashes[i] - local blobtype=hash.type - local blobpath=hash.name - if blobtype and blobpath then - local total=0 - local checked=0 - local done=0 - if before then - before(blobtype,blobpath,pattern) - end - for path,name in filtered(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 - end - if after then - after(blobtype,blobpath,pattern,checked,done) - end - end - end -end -function resolvers.knownvariables(pattern) - if instance then - local environment=instance.environment - local variables=instance.variables - local expansions=instance.expansions - local order=instance.order - local pattern=upper(pattern or "") - local result={} - for i=1,#order do - for key in next,order[i] do - if result[key]==nil and key~="" and (pattern=="" or find(upper(key),pattern)) then - result[key]={ - environment=rawget(environment,key), - variable=key, - expansion=expansions[key], - resolved=resolveprefix(expansions[key]), - } - end - end - end - return result - else - return {} - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-pre"] = package.loaded["data-pre"] or true - --- original size: 5872, stripped down to: 3691 - -if not modules then modules={} end modules ['data-pre']={ - 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 ipairs=ipairs -local insert,remove=table.insert,table.remove -local resolvers=resolvers -local prefixes=resolvers.prefixes -local cleanpath=resolvers.cleanpath -local findgivenfile=resolvers.findgivenfile -local expansion=resolvers.expansion -local getenv=resolvers.getenv -local basename=file.basename -local dirname=file.dirname -local joinpath=file.join -local isfile=lfs.isfile -local isdir=lfs.isdir -prefixes.environment=function(str) - return cleanpath(expansion(str)) -end -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=relative(str) - if not isfile(fullname) then - fullname=locate(str) - end - return fullname -end -prefixes.filename=function(str) - local fullname=findgivenfile(str) or "" - return cleanpath(basename((fullname~="" and fullname) or str)) -end -prefixes.pathname=function(str) - local fullname=findgivenfile(str) or "" - return cleanpath(dirname((fullname~="" and fullname) or str)) -end -prefixes.selfautoloc=function(str) - local pth=getenv('SELFAUTOLOC') - return cleanpath(str and joinpath(pth,str) or pth) -end -prefixes.selfautoparent=function(str) - local pth=getenv('SELFAUTOPARENT') - return cleanpath(str and joinpath(pth,str) or pth) -end -prefixes.selfautodir=function(str) - local pth=getenv('SELFAUTODIR') - return cleanpath(str and joinpath(pth,str) or pth) -end -prefixes.home=function(str) - local pth=getenv('HOME') - return cleanpath(str and joinpath(pth,str) or pth) -end -do - local tmppth - prefixes.temp=function(str) - if not tmppth then - for _,s in ipairs { "TMP","TEMP","TMPDIR","TEMPDIR" } do - tmppth=getenv(s) - if tmppth~="" and isdir(tmppth) then - break - end - end - if not tmppth or tmppth=="" then - tmppth="." - end - end - return cleanpath(str and joinpath(tmppth,str) or tmppth) - end - prefixes.texruns=function(str) - local pth=getenv('TEXRUNS') - if pth=="" then - pth=tmppth - end - return cleanpath(str and joinpath(pth,str) or pth) - end -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 inputstack={} -local stackpath=resolvers.stackpath -local function toppath() - if not inputstack then - return "." - end - local pathname=dirname(inputstack[#inputstack] or "") - if pathname=="" then - return "." - else - return pathname - end -end -local function jobpath() - local path=stackpath() - if not path or path=="" then - return "." - else - return path - end -end -local function pushinputname(name) - insert(inputstack,name) -end -local function popinputname(name) - return remove(inputstack) -end -resolvers.toppath=toppath -resolvers.jobpath=jobpath -resolvers.pushinputname=pushinputname -resolvers.popinputname=popinputname -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") - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-inp"] = package.loaded["data-inp"] or true - --- original size: 1050, stripped down to: 946 - -if not modules then modules={} end modules ['data-inp']={ - 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 allocate=utilities.storage.allocate -local resolvers=resolvers -local methodhandler=resolvers.methodhandler -local registermethod=resolvers.registermethod -local finders=allocate { helpers={},notfound=function() end } -local openers=allocate { helpers={},notfound=function() end } -local loaders=allocate { helpers={},notfound=function() return false,nil,0 end } -local tracers=allocate { helpers={},notfound=function() end } -registermethod("finders",finders,"uri") -registermethod("openers",openers,"uri") -registermethod("loaders",loaders,"uri") -registermethod("tracers",tracers,"uri") -resolvers.finders=finders -resolvers.openers=openers -resolvers.loaders=loaders -resolvers.tracers=tracers - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-out"] = package.loaded["data-out"] or true - --- original size: 682, stripped down to: 579 - -if not modules then modules={} end modules ['data-out']={ - 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 allocate=utilities.storage.allocate -local resolvers=resolvers -local registermethod=resolvers.registermethod -local savers=allocate { helpers={} } -resolvers.savers=savers -local cleaners=allocate { helpers={} } -resolvers.cleaners=cleaners -registermethod("savers",savers,"uri") -registermethod("cleaners",cleaners,"uri") - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-fil"] = package.loaded["data-fil"] or true - --- original size: 4365, stripped down to: 3452 - -if not modules then modules={} end modules ['data-fil']={ - 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 ioopen=io.open -local isdir=lfs.isdir -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 findfile=resolvers.findfile -local scanfiles=resolvers.scanfiles -local registerfilehash=resolvers.registerfilehash -local appendhash=resolvers.appendhash -local loadcachecontent=caches.loadcontent -function resolvers.locators.file(specification) - local filename=specification.filename - local realname=resolveprefix(filename) - if realname and realname~='' and isdir(realname) then - if trace_locating then - report_files("file locator %a found as %a",filename,realname) - end - appendhash('file',filename,true) - elseif trace_locating then - report_files("file locator %a not found",filename) - end -end -function resolvers.hashers.file(specification) - local pathname=specification.filename - local content=loadcachecontent(pathname,'files') - registerfilehash(pathname,content,content==nil) -end -function resolvers.generators.file(specification) - local pathname=specification.filename - local content=scanfiles(pathname,false,true) - registerfilehash(pathname,content,true) -end -resolvers.concatinators.file=file.join -local finders=resolvers.finders -local notfound=finders.notfound -function finders.file(specification,filetype) - local filename=specification.filename - local foundname=findfile(filename,filetype) - if foundname and foundname~="" then - if trace_locating then - report_files("file finder: %a found",filename) - end - return foundname - else - if trace_locating then - report_files("file finder: %a not found",filename) - end - return notfound() - end -end -local openers=resolvers.openers -local notfound=openers.notfound -local overloaded=false -local function textopener(tag,filename,f) - return { - reader=function() return f:read () end, - close=function() return f:close() end, - } -end -function openers.helpers.textopener(...) - return textopener(...) -end -function openers.helpers.settextopener(opener) - if overloaded then - report_files("file opener: %s overloaded","already") - else - if trace_locating then - report_files("file opener: %s overloaded","once") - end - overloaded=true - textopener=opener - end -end -function openers.file(specification,filetype) - local filename=specification.filename - if filename and filename~="" then - local f=ioopen(filename,"r") - if f then - if trace_locating then - report_files("file opener: %a opened",filename) - end - return textopener("file",filename,f) - end - end - if trace_locating then - report_files("file opener: %a not found",filename) - end - return notfound() -end -local loaders=resolvers.loaders -local notfound=loaders.notfound -function loaders.file(specification,filetype) - local filename=specification.filename - if filename and filename~="" then - local f=ioopen(filename,"rb") - if f then - if trace_locating then - report_files("file loader: %a loaded",filename) - end - local s=f:read("*a") - f:close() - if s then - return true,s,#s - end - end - end - if trace_locating then - report_files("file loader: %a not found",filename) - end - return notfound() -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-con"] = package.loaded["data-con"] or true - --- original size: 5487, stripped down to: 3757 - -if not modules then modules={} end modules ['data-con']={ - version=1.100, - 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 setmetatable=setmetatable -local format,lower,gsub=string.format,string.lower,string.gsub -local trace_cache=false trackers.register("resolvers.cache",function(v) trace_cache=v end) -local trace_containers=false trackers.register("resolvers.containers",function(v) trace_containers=v end) -local trace_storage=false trackers.register("resolvers.storage",function(v) trace_storage=v end) -containers=containers or {} -local containers=containers -containers.usecache=true -local getwritablepath=caches.getwritablepath -local getreadablepaths=caches.getreadablepaths -local cacheiswritable=caches.is_writable -local loaddatafromcache=caches.loaddata -local savedataincache=caches.savedata -local report_containers=logs.reporter("resolvers","containers") -local allocated={} -local mt={ - __index=function(t,k) - if k=="writable" then - local writable=getwritablepath(t.category,t.subcategory) or { "." } - t.writable=writable - return writable - elseif k=="readables" then - local readables=getreadablepaths(t.category,t.subcategory) or { "." } - t.readables=readables - return readables - end - end, - __storage__=true -} -function containers.define(category,subcategory,version,enabled,reload) - if category and subcategory then - local c=allocated[category] - if not c then - c={} - allocated[category]=c - end - local s=c[subcategory] - if not s then - s={ - category=category, - subcategory=subcategory, - storage={}, - enabled=enabled, - reload=reload, - version=version or math.pi, - trace=false, - } - setmetatable(s,mt) - c[subcategory]=s - end - return s - end -end -function containers.is_usable(container,name) - return container.enabled and caches and cacheiswritable(container.writable,name) -end -function containers.is_valid(container,name) - if name and name~="" then - local storage=container.storage[name] - return storage and storage.cache_version==container.version - else - return false - end -end -function containers.read(container,name) - local storage=container.storage - local reload=container.reload - local stored=not reload and storage[name] - if not stored and container.enabled and caches and containers.usecache then - stored=loaddatafromcache(container.readables,name,container.writable) - if stored and stored.cache_version==container.version then - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","load",container.subcategory,name) - end - else - stored=nil - end - storage[name]=stored - elseif stored then - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","reuse",container.subcategory,name) - end - end - return stored -end -function containers.write(container,name,data,fast) - if data then - data.cache_version=container.version - if container.enabled and caches then - local unique=data.unique - local shared=data.shared - data.unique=nil - data.shared=nil - savedataincache(container.writable,name,data,fast) - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","save",container.subcategory,name) - end - data.unique=unique - data.shared=shared - end - if trace_cache or trace_containers then - report_containers("action %a, category %a, name %a","store",container.subcategory,name) - end - container.storage[name]=data - end - return data -end -function containers.content(container,name) - return container.storage[name] -end -function containers.cleanname(name) - return (gsub(lower(name),"[^%w\128-\255]+","-")) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-use"] = package.loaded["data-use"] or true - --- original size: 5806, stripped down to: 2925 - -if not modules then modules={} end modules ['data-use']={ - 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 format=string.format -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local report_mounts=logs.reporter("resolvers","mounts") -local resolvers=resolvers -local findfile=resolvers.findfile -statistics.register("used config file",function() return caches.configfiles() end) -statistics.register("used cache path",function() return caches.usedpaths() end) -function statistics.savefmtstatus(texname,formatbanner,sourcefile,banner) - local enginebanner=status.banner - if formatbanner and enginebanner and sourcefile then - local luvname=file.replacesuffix(texname,"luv") - local luvdata={ - enginebanner=enginebanner, - formatbanner=formatbanner, - sourcehash=md5.hex(io.loaddata(findfile(sourcefile)) or "unknown"), - sourcefile=sourcefile, - luaversion=LUAVERSION, - formatid=LUATEXFORMATID, - functionality=LUATEXFUNCTIONALITY, - } - io.savedata(luvname,table.serialize(luvdata,true)) - lua.registerinitexfinalizer(function() - if jit then - logs.report("format banner","%s lua: %s jit",banner,LUAVERSION) - else - logs.report("format banner","%s lua: %s",banner,LUAVERSION) - end - logs.newline() - end,"show banner") - end -end -function statistics.checkfmtstatus(texname) - local enginebanner=status.banner - if enginebanner and texname then - local luvname=file.replacesuffix(texname,"luv") - if lfs.isfile(luvname) then - local luv=dofile(luvname) - if luv and luv.sourcefile then - local sourcehash=md5.hex(io.loaddata(findfile(luv.sourcefile)) or "unknown") - local luvbanner=luv.enginebanner or "?" - if luvbanner~=enginebanner then - return format("engine mismatch (luv: %s <> bin: %s)",luvbanner,enginebanner) - end - local luvhash=luv.sourcehash or "?" - if luvhash~=sourcehash then - return format("source mismatch (luv: %s <> bin: %s)",luvhash,sourcehash) - end - local luvluaversion=luv.luaversion or 0 - local engluaversion=LUAVERSION or 0 - if luvluaversion~=engluaversion then - return format("lua mismatch (luv: %s <> bin: %s)",luvluaversion,engluaversion) - end - local luvfunctionality=luv.functionality or 0 - local engfunctionality=status.development_id or 0 - if luvfunctionality~=engfunctionality then - return format("functionality mismatch (luv: %s <> bin: %s)",luvfunctionality,engfunctionality) - end - local luvformatid=luv.formatid or 0 - local engformatid=status.format_id or 0 - if luvformatid~=engformatid then - return format("formatid mismatch (luv: %s <> bin: %s)",luvformatid,engformatid) - end - else - return "invalid status file" - end - else - return "missing status file" - end - end - return true -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-zip"] = package.loaded["data-zip"] or true - --- original size: 10805, stripped down to: 7951 - -if not modules then modules={} end modules ['data-zip']={ - 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 format,find,match=string.format,string.find,string.match -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local report_zip=logs.reporter("resolvers","zip") -local resolvers=resolvers -local findfile=resolvers.findfile -local registerfile=resolvers.registerfile -local splitmethod=resolvers.splitmethod -local prependhash=resolvers.prependhash -local starttiming=resolvers.starttiming -local extendtexmf=resolvers.extendtexmfvariable -local stoptiming=resolvers.stoptiming -local urlquery=url.query -zip=zip or {} -local zip=zip -local archives=zip.archives or {} -zip.archives=archives -local registeredfiles=zip.registeredfiles or {} -zip.registeredfiles=registeredfiles -local zipfiles=utilities.zipfiles -local openzip,closezip,validfile,wholefile,filehandle,traversezip -if zipfiles then - local ipairs=ipairs - openzip=zipfiles.open - closezip=zipfiles.close - validfile=zipfiles.found - wholefile=zipfiles.unzip - local listzip=zipfiles.list - traversezip=function(zfile) - return ipairs(listzip(zfile)) - end - local streams=utilities.streams - local openstream=streams.open - local readstring=streams.readstring - local streamsize=streams.size - local metatable={ - close=streams.close, - read=function(stream,n) - readstring(stream,n=="*a" and streamsize(stream) or n) - end - } - filehandle=function(zfile,queryname) - local data=wholefile(zfile,queryname) - if data then - local stream=openstream(data) - if stream then - return setmetatableindex(stream,metatable) - end - end - end -else - openzip=zip.open - closezip=zip.close - validfile=function(zfile,queryname) - local dfile=zfile:open(queryname) - if dfile then - dfile:close() - return true - end - return false - end - traversezip=function(zfile) - return z:files() - end - wholefile=function(zfile,queryname) - local dfile=zfile:open(queryname) - if dfile then - local s=dfile:read("*all") - dfile:close() - return s - end - end - filehandle=function(zfile,queryname) - local dfile=zfile:open(queryname) - if dfile then - return dfile - end - end -end -local function validzip(str) - if not find(str,"^zip://") then - return "zip:///"..str - else - return str - end -end -local function openarchive(name) - if not name or name=="" then - return nil - else - local arch=archives[name] - if not arch then - local full=findfile(name) or "" - arch=full~="" and openzip(full) or false - archives[name]=arch - end - return arch - end -end -local function closearchive(name) - if not name or (name=="" and archives[name]) then - closezip(archives[name]) - archives[name]=nil - end -end -zip.openarchive=openarchive -zip.closearchive=closearchive -function resolvers.locators.zip(specification) - local archive=specification.filename - local zipfile=archive and archive~="" and openarchive(archive) - if trace_locating then - if zipfile then - report_zip("locator: archive %a found",archive) - else - report_zip("locator: archive %a not found",archive) - end - end -end -function resolvers.concatinators.zip(zipfile,path,name) - if not path or path=="" then - return format('%s?name=%s',zipfile,name) - else - return format('%s?name=%s/%s',zipfile,path,name) - end -end -local finders=resolvers.finders -local notfound=finders.notfound -function finders.zip(specification) - local original=specification.original - local archive=specification.filename - if archive then - local query=urlquery(specification.query) - local queryname=query.name - if queryname then - local zfile=openarchive(archive) - if zfile then - if trace_locating then - report_zip("finder: archive %a found",archive) - end - if validfile(zfile,queryname) then - if trace_locating then - report_zip("finder: file %a found",queryname) - end - return specification.original - elseif trace_locating then - report_zip("finder: file %a not found",queryname) - end - elseif trace_locating then - report_zip("finder: unknown archive %a",archive) - end - end - end - if trace_locating then - report_zip("finder: %a not found",original) - end - return notfound() -end -local openers=resolvers.openers -local notfound=openers.notfound -local textopener=openers.helpers.textopener -function openers.zip(specification) - local original=specification.original - local archive=specification.filename - if archive then - local query=urlquery(specification.query) - local queryname=query.name - if queryname then - local zfile=openarchive(archive) - if zfile then - if trace_locating then - report_zip("opener; archive %a opened",archive) - end - local handle=filehandle(zfile,queryname) - if handle then - if trace_locating then - report_zip("opener: file %a found",queryname) - end - return textopener('zip',original,handle) - elseif trace_locating then - report_zip("opener: file %a not found",queryname) - end - elseif trace_locating then - report_zip("opener: unknown archive %a",archive) - end - end - end - if trace_locating then - report_zip("opener: %a not found",original) - end - return notfound() -end -local loaders=resolvers.loaders -local notfound=loaders.notfound -function loaders.zip(specification) - local original=specification.original - local archive=specification.filename - if archive then - local query=urlquery(specification.query) - local queryname=query.name - if queryname then - local zfile=openarchive(archive) - if zfile then - if trace_locating then - report_zip("loader: archive %a opened",archive) - end - local data=wholefile(zfile,queryname) - if data then - if trace_locating then - report_zip("loader; file %a loaded",original) - end - return true,data,#data - elseif trace_locating then - report_zip("loader: file %a not found",queryname) - end - elseif trace_locating then - report_zip("loader; unknown archive %a",archive) - end - end - end - if trace_locating then - report_zip("loader: %a not found",original) - end - return notfound() -end -local function registerzipfile(z,tree) - local names={} - local files={} - local remap={} - local n=0 - local filter=tree=="" and "^(.+)/(.-)$" or format("^%s/(.+)/(.-)$",tree) - if trace_locating then - report_zip("registering: using filter %a",filter) - end - starttiming() - for i in traversezip(z) do - local filename=i.filename - local path,name=match(filename,filter) - if not path then - n=n+1 - registerfile(names,filename,"") - local usedname=lower(filename) - files[usedname]="" - if usedname~=filename then - remap[usedname]=filename - end - 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 - stoptiming() - report_zip("registering: %s files registered",n) - return { - files=files, - remap=remap, - } -end -local function usezipfile(archive) - local specification=splitmethod(archive) - local archive=specification.filename - if archive and not registeredfiles[archive] then - local z=openarchive(archive) - if z then - local tree=urlquery(specification.query).tree or "" - if trace_locating then - report_zip("registering: archive %a",archive) - end - prependhash('zip',archive) - extendtexmf(archive) - registeredfiles[archive]=z - registerfilehash(archive,registerzipfile(z,tree)) - elseif trace_locating then - report_zip("registering: unknown archive %a",archive) - end - elseif trace_locating then - report_zip("registering: archive %a not found",archive) - end -end -resolvers.usezipfile=usezipfile -resolvers.registerzipfile=registerzipfile -function resolvers.hashers.zip(specification) - local archive=specification.filename - if trace_locating then - report_zip("loading file %a",archive) - end - usezipfile(specification.original) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-tre"] = package.loaded["data-tre"] or true - --- original size: 10802, stripped down to: 6619 - -if not modules then modules={} end modules ['data-tre']={ - 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=type -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 finders=resolvers.finders -local openers=resolvers.openers -local loaders=resolvers.loaders -local locators=resolvers.locators -local hashers=resolvers.hashers -local generators=resolvers.generators -do - local collectors={} - local found={} - local notfound=finders.notfound - function finders.tree(specification) - local spec=specification.filename - local okay=found[spec] - if okay==nil then - if spec~="" then - 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 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 - okay=notfound() - found[spec]=okay - end - return okay - end -end -do - local resolveprefix=resolvers.resolve - local appendhash=resolvers.appendhash - local function dolocate(specification) - local name=specification.filename - local realname=resolveprefix(name) - if realname and realname~='' and isdir(realname) then - if trace_locating then - report_trees("locator %a found",realname) - end - appendhash('tree',name,false) - elseif trace_locating then - report_trees("locator %a not found",name) - end - end - locators.tree=dolocate - locators.dirlist=dolocate - locators.dirfile=dolocate -end -do - local filegenerator=generators.file - generators.dirlist=filegenerator - generators.dirfile=filegenerator -end -do - local filegenerator=generators.file - local methodhandler=resolvers.methodhandler - local function dohash(specification) - local name=specification.filename - if trace_locating then - report_trees("analyzing %a",name) - end - methodhandler("hashers",name) - filegenerator(specification) - end - hashers.tree=dohash - hashers.dirlist=dohash - hashers.dirfile=dohash -end -local resolve do - local collectors={} - local splitter=lpeg.splitat("/**/") - local stripper=lpeg.replacer { [P("/")*P("*")^1*P(-1)]="" } - local loadcontent=caches.loadcontent - local savecontent=caches.savecontent - local notfound=finders.notfound - local scanfiles=resolvers.scanfiles - local lookup=resolvers.get_from_content - table.setmetatableindex(collectors,function(t,k) - local rootname=lpegmatch(stripper,k) - local dataname=joinname(rootname,"dirlist") - local content=loadcontent(dataname,"files",dataname) - if not content then - content=scanfiles(rootname,nil,nil,false,true) - 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 - resolve=function(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=dirname(filename) - local name=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 - finders.dirlist=resolve - function finders.dirfile(specification) - local queries=specification.queries - if queries then - queries.option="fileonly" - else - specification.queries={ option="fileonly" } - end - return resolve(specification) - end -end -do - local fileopener=openers.file - local fileloader=loaders.file - openers.dirlist=fileopener - loaders.dirlist=fileloader - openers.dirfile=fileopener - loaders.dirfile=fileloader -end -do - local hashfile="dirhash.lua" - local kind="HASH256" - local version=1.0 - local loadtable=table.load - local savetable=table.save - local loaddata=io.loaddata - function resolvers.dirstatus(patterns) - local t=type(patterns) - if t=="string" then - patterns={ patterns } - elseif t~="table" then - return false - end - local status=loadtable(hashfile) - if not status or status.version~=version or status.kind~=kind then - status={ - version=1.0, - kind=kind, - hashes={}, - } - end - local hashes=status.hashes - local changed={} - local action=sha2[kind] - local update={} - for i=1,#patterns do - local pattern=patterns[i] - local files=globdir(pattern) - for i=1,#files do - local name=files[i] - local hash=action(loaddata(name)) - if hashes[name]~=hash then - changed[#changed+1]=name - end - update[name]=hash - end - end - status.hashes=update - savetable(hashfile,status) - return #changed>0 and changed or false - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-sch"] = package.loaded["data-sch"] or true - --- original size: 6945, stripped down to: 5408 - -if not modules then modules={} end modules ['data-sch']={ - 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 load,tonumber=load,tonumber -local gsub,format=string.gsub,string.format -local sortedhash,concat=table.sortedhash,table.concat -local finders,openers,loaders=resolvers.finders,resolvers.openers,resolvers.loaders -local addsuffix,suffix,splitbase=file.addsuffix,file.suffix,file.splitbase -local md5hex=md5.hex -local trace_schemes=false trackers.register("resolvers.schemes",function(v) trace_schemes=v end) -local report_schemes=logs.reporter("resolvers","schemes") -local http=require("socket.http") -local ltn12=require("ltn12") -if mbox then mbox=nil end -local resolvers=resolvers -local schemes=resolvers.schemes or {} -resolvers.schemes=schemes -local cleaners={} -schemes.cleaners=cleaners -local threshold=24*60*60 -directives.register("schemes.threshold",function(v) threshold=tonumber(v) or threshold end) -function cleaners.none(specification) - return specification.original -end -function cleaners.strip(specification) - local path,name=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 addsuffix(md5hex(specification.original),suffix(specification.path)) -end -local cleaner=cleaners.strip -directives.register("schemes.cleanmethod",function(v) cleaner=cleaners[v] or cleaners.strip end) -function resolvers.schemes.cleanname(specification) - local hash=cleaner(specification) - if trace_schemes then - report_schemes("hashing %a to %a",specification.original,hash) - end - return hash -end -local cached={} -local loaded={} -local reused={} -local thresholds={} -local handlers={} -local runner=sandbox.registerrunner { - name="curl resolver", - method="execute", - program="curl", - template='--silent --insecure --create-dirs --output "%cachename%" "%original%"', - checkers={ - cachename="cache", - original="url", - } -} -local function fetch(specification) - local original=specification.original - local scheme=specification.scheme - local cleanname=schemes.cleanname(specification) - local cachename=caches.setfirstwritablefile(cleanname,"schemes") - if not cached[original] then - statistics.starttiming(schemes) - if not io.exists(cachename) or (os.difftime(os.time(),lfs.attributes(cachename).modification)>(thresholds[protocol] or threshold)) then - cached[original]=cachename - local handler=handlers[scheme] - if handler then - if trace_schemes then - report_schemes("fetching %a, protocol %a, method %a",original,scheme,"built-in") - end - logs.flush() - handler(specification,cachename) - else - if trace_schemes then - report_schemes("fetching %a, protocol %a, method %a",original,scheme,"curl") - end - logs.flush() - runner { - original=original, - cachename=cachename, - } - end - end - if io.exists(cachename) then - cached[original]=cachename - if trace_schemes then - report_schemes("using cached %a, protocol %a, cachename %a",original,scheme,cachename) - end - else - cached[original]="" - if trace_schemes then - report_schemes("using missing %a, protocol %a",original,scheme) - end - end - loaded[scheme]=loaded[scheme]+1 - statistics.stoptiming(schemes) - else - if trace_schemes then - report_schemes("reusing %a, protocol %a",original,scheme) - end - reused[scheme]=reused[scheme]+1 - end - return cached[original] -end -local function finder(specification,filetype) - return resolvers.methodhandler("finders",fetch(specification),filetype) -end -local opener=openers.file -local loader=loaders.file -local function install(scheme,handler,newthreshold) - handlers [scheme]=handler - loaded [scheme]=0 - reused [scheme]=0 - finders [scheme]=finder - openers [scheme]=opener - loaders [scheme]=loader - thresholds[scheme]=newthreshold or threshold -end -schemes.install=install -local function http_handler(specification,cachename) - local tempname=cachename..".tmp" - local handle=io.open(tempname,"wb") - local status,message=http.request { - url=specification.original, - sink=ltn12.sink.file(handle) - } - if not status then - os.remove(tempname) - else - os.remove(cachename) - os.rename(tempname,cachename) - end - return cachename -end -install('http',http_handler) -install('https') -install('ftp') -statistics.register("scheme handling time",function() - local l,r,nl,nr={},{},0,0 - for k,v in sortedhash(loaded) do - if v>0 then - nl=nl+1 - l[nl]=k..":"..v - end - end - for k,v in sortedhash(reused) do - if v>0 then - nr=nr+1 - r[nr]=k..":"..v - end - end - local n=nl+nr - if n>0 then - if nl==0 then l={ "none" } end - if nr==0 then r={ "none" } end - return format("%s seconds, %s processed, threshold %s seconds, loaded: %s, reused: %s", - statistics.elapsedtime(schemes),n,threshold,concat(l," "),concat(l," ")) - else - return nil - end -end) -local httprequest=http.request -local toquery=url.toquery -local function fetchstring(url,data) - local q=data and toquery(data) - if q then - url=url.."?"..q - end - local reply=httprequest(url) - return reply -end -schemes.fetchstring=fetchstring -function schemes.fetchtable(url,data) - local reply=fetchstring(url,data) - if reply then - local s=load("return "..reply) - if s then - return s() - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-lua"] = package.loaded["data-lua"] or true - --- original size: 4227, stripped down to: 3049 - -if not modules then modules={} end modules ['data-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 package,lpeg=package,lpeg -local loadfile=loadfile -local addsuffix=file.addsuffix -local P,S,Cs,lpegmatch=lpeg.P,lpeg.S,lpeg.Cs,lpeg.match -local luasuffixes={ 'tex','lua' } -local libsuffixes={ 'lib' } -local luaformats={ 'TEXINPUTS','LUAINPUTS' } -local libformats={ 'CLUAINPUTS' } -local helpers=package.helpers or {} -local methods=helpers.methods or {} -local resolvers=resolvers -local resolveprefix=resolvers.resolve -local expandedpaths=resolvers.expandedpathlistfromvariable -local findfile=resolvers.findfile -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.sequence={ - "already loaded", - "preload table", - "lua variable format", - "lib variable format", - "lua extra list", - "lib extra list", - "path specification", - "cpath specification", - "all in one fallback", - "not loaded", -} -local pattern=Cs(P("!")^0/""*(P("/")*P(-1)/"/"+P("/")^1/"/"+1)^0) -function helpers.cleanpath(path) - return resolveprefix(lpegmatch(pattern,path)) -end -local loadedaslib=helpers.loadedaslib -local registerpath=helpers.registerpath -local lualibfile=helpers.lualibfile -local luaformatpaths -local libformatpaths -local function getluaformatpaths() - if not luaformatpaths then - luaformatpaths={} - for i=1,#luaformats do - registerpath("lua format","lua",luaformatpaths,expandedpaths(luaformats[i])) - end - end - return luaformatpaths -end -local function getlibformatpaths() - if not libformatpaths then - libformatpaths={} - for i=1,#libformats do - registerpath("lib format","lib",libformatpaths,expandedpaths(libformats[i])) - end - end - return libformatpaths -end -local function loadedbyformat(name,rawname,suffixes,islib,what) - local trace=helpers.trace - local report=helpers.report - for i=1,#suffixes do - local format=suffixes[i] - local resolved=findfile(name,format) or "" - if trace then - report("%s format, identifying %a using format %a",what,name,format) - end - if resolved~="" then - if trace then - report("%s format, %a found on %a",what,name,resolved) - end - if islib then - return loadedaslib(resolved,rawname) - else - return loadfile(resolved) - end - end - end -end -helpers.loadedbyformat=loadedbyformat -methods["lua variable format"]=function(name) - if helpers.trace then - helpers.report("%s format, checking %s paths","lua",#getluaformatpaths()) - end - return loadedbyformat(addsuffix(lualibfile(name),"lua"),name,luasuffixes,false,"lua") -end -methods["lib variable format"]=function(name) - if helpers.trace then - helpers.report("%s format, checking %s paths","lib",#getlibformatpaths()) - end - return loadedbyformat(addsuffix(lualibfile(name),os.libsuffix),name,libsuffixes,true,"lib") -end -resolvers.loadlualib=require - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-aux"] = package.loaded["data-aux"] or true - --- original size: 2610, stripped down to: 2019 - -if not modules then modules={} end modules ['data-aux']={ - 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 find=string.find -local type,next=type,next -local addsuffix,removesuffix=file.addsuffix,file.removesuffix -local loaddata,savedata=io.loaddata,io.savedata -local trace_locating=false trackers.register("resolvers.locating",function(v) trace_locating=v end) -local resolvers=resolvers -local cleanpath=resolvers.cleanpath -local findfiles=resolvers.findfiles -local report_scripts=logs.reporter("resolvers","scripts") -function resolvers.updatescript(oldname,newname) - local scriptpath="context/lua" - local oldscript=cleanpath(oldname) - local newname=addsuffix(newname,"lua") - local newscripts=findfiles(newname) or {} - if trace_locating then - report_scripts("to be replaced old script %a",oldscript) - end - if #newscripts==0 then - if trace_locating then - report_scripts("unable to locate new script") - end - else - for i=1,#newscripts do - local newscript=cleanpath(newscripts[i]) - if trace_locating then - report_scripts("checking new script %a",newscript) - end - if oldscript==newscript then - if trace_locating then - report_scripts("old and new script are the same") - end - elseif not find(newscript,scriptpath,1,true) then - if trace_locating then - report_scripts("new script should come from %a",scriptpath) - end - elseif not (find(oldscript,removesuffix(newname).."$") or find(oldscript,newname.."$")) then - if trace_locating then - report_scripts("invalid new script name") - end - else - local newdata=loaddata(newscript) - if newdata then - if trace_locating then - report_scripts("old script content replaced by new content: %s",oldscript) - end - savedata(oldscript,newdata) - break - elseif trace_locating then - report_scripts("unable to load new script") - end - end - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-tmf"] = package.loaded["data-tmf"] or true - --- original size: 2601, stripped down to: 1549 - -if not modules then modules={} end modules ['data-tmf']={ - 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 resolvers=resolvers -local report_tds=logs.reporter("resolvers","tds") -function resolvers.load_tree(tree,resolve) - if type(tree)=="string" and tree~="" then - local getenv,setenv=resolvers.getenv,resolvers.setenv - local texos="texmf-"..os.platform - local oldroot=environment.texroot - local newroot=file.collapsepath(tree) - local newtree=file.join(newroot,texos) - local newpath=file.join(newtree,"bin") - if not lfs.isdir(newtree) then - report_tds("no %a under tree %a",texos,tree) - os.exit() - end - if not lfs.isdir(newpath) then - report_tds("no '%s/bin' under tree %a",texos,tree) - os.exit() - end - local texmfos=newtree - environment.texroot=newroot - environment.texos=texos - environment.texmfos=texmfos - if resolve then - resolvers.luacnfspec=resolvers.resolve(resolvers.luacnfspec) - end - setenv('SELFAUTOPARENT',newroot) - setenv('SELFAUTODIR',newtree) - setenv('SELFAUTOLOC',newpath) - setenv('TEXROOT',newroot) - setenv('TEXOS',texos) - setenv('TEXMFOS',texmfos) - setenv('TEXMFCNF',resolvers.luacnfspec,true) - setenv('PATH',newpath..io.pathseparator..getenv('PATH')) - report_tds("changing from root %a to %a",oldroot,newroot) - report_tds("prepending %a to PATH",newpath) - report_tds("setting TEXMFCNF to %a",resolvers.luacnfspec) - report_tds() - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["data-lst"] = package.loaded["data-lst"] or true - --- original size: 2038, stripped down to: 1696 - -if not modules then modules={} end modules ['data-lst']={ - 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=type -local sortedhash=table.sortedhash -local isdir=lfs.isdir -local resolvers=resolvers -local listers=resolvers.listers or {} -resolvers.listers=listers -local resolveprefix=resolvers.resolve -local configurationfiles=resolvers.configurationfiles -local expandedpathfromlist=resolvers.expandedpathfromlist -local splitpath=resolvers.splitpath -local knownvariables=resolvers.knownvariables -local report_lists=logs.reporter("resolvers","lists") -local report_resolved=logs.reporter("system","resolved") -local function tabstr(str) - if not str then - return "unset" - elseif type(str)=='table' then - return concat(str," | ") - else - return str - end -end -function listers.variables(pattern) - local result=resolvers.knownvariables(pattern) - for key,value in sortedhash(result) do - report_lists(key) - report_lists(" env: %s",tabstr(value.environment)) - report_lists(" var: %s",tabstr(value.variable)) - report_lists(" exp: %s",tabstr(value.expansion)) - report_lists(" res: %s",tabstr(value.resolved)) - end -end -function listers.configurations() - local configurations=configurationfiles() - for i=1,#configurations do - report_resolved("file : %s",resolveprefix(configurations[i])) - end - report_resolved("") - local list=expandedpathfromlist(splitpath(resolvers.luacnfspec)) - for i=1,#list do - local li=resolveprefix(list[i]) - if isdir(li) then - report_resolved("path - %s",li) - else - report_resolved("path + %s",li) - end - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["libs-ini"] = package.loaded["libs-ini"] or true - --- original size: 6524, stripped down to: 4064 - -if not modules then modules={} end modules ['libs-ini']={ - 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,unpack=type,unpack -local find=string.find -local nameonly=file.nameonly -local joinfile=file.join -local addsuffix=file.addsuffix -local qualifiedpath=file.is_qualified_path -local isfile=lfs.isfile -local findfile=resolvers.findfile -local expandpaths=resolvers.expandedpathlistfromvariable -local report=logs.reporter("resolvers","libraries") -local trace=false -local silent=false -trackers.register("resolvers.lib",function(v) trace=v end) -trackers.register("resolvers.lib.silent",function(v) silent=v end) -local function findlib(required) - local suffix=os.libsuffix or "so" - if not qualifiedpath(required) then - local list=directives.value("system.librarynames" ) - local only=nameonly(required) - if type(list)=="table" then - list=list[only] - if type(list)~="table" then - list={ only } - end - else - list={ only } - end - if trace then - report("using lookup list for library %a: % | t",only,list) - end - for i=1,#list do - local name=list[i] - local found=findfile(name,"lib") - if not found or found=="" then - found=findfile(addsuffix(name,suffix),"lib") - end - if found and found~="" then - if trace then - report("library %a resolved via %a path to %a",name,"tds lib",found) - end - return found - end - end - if expandpaths then - local list=expandpaths("PATH") - local base=addsuffix(only,suffix) - for i=1,#list do - local full=joinfile(list[i],base) - local found=isfile(full) and full - if found and found~="" then - if trace then - report("library %a resolved via %a path to %a",full,"system",found) - end - return found - end - end - end - elseif isfile(addsuffix(required,suffix)) then - if trace then - report("library with qualified name %a %sfound",required,"") - end - return required - else - if trace then - report("library with qualified name %a %sfound",required,"not ") - end - end - return false -end -local foundlibraries=table.setmetatableindex(function(t,k) - local v=findlib(k) - t[k]=v - return v -end) -function resolvers.findlib(required) - return foundlibraries[required] -end -local libraries={} -resolvers.libraries=libraries -local report=logs.reporter("optional") -if optional then optional.loaded={} end -function libraries.validoptional(name) - local thelib=optional and optional[name] - if not thelib then - elseif thelib.initialize then - return thelib - else - report("invalid optional library %a",libname) - end -end -function libraries.optionalloaded(name,libnames) - local thelib=optional and optional[name] - if not thelib then - report("no optional %a library found",name) - else - local thelib_initialize=thelib.initialize - if not thelib_initialize then - report("invalid optional library %a",name) - else - if type(libnames)=="string" then - libnames={ libnames } - end - if type(libnames)=="table" then - for i=1,#libnames do - local libname=libnames[i] - local filename=foundlibraries[libname] - if filename and filename~="" then - libnames[i]=filename - else - report("unable to locate library %a",libname) - return - end - end - local initialized=thelib_initialize(unpack(libnames)) - if not initialized then - report("unable to initialize library '% + t'",libnames) - elseif not silent then - report("using library '% + t'",libnames) - end - return initialized - end - end - end -end -if FFISUPPORTED and ffi and ffi.load then - local ffiload=ffi.load - function ffi.load(name) - local full=name and foundlibraries[name] - if full then - return ffiload(full) - else - return ffiload(name) - end - end -end -local dofile=dofile -local savedrequire=require -function require(name,version) - if find(name,"%.lua$") or find(name,"%.lmt$") then - local m=dofile(findfile(name)) - if m then - package.loaded[name]=m - return m - end - else - return savedrequire(name) - end -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["luat-sta"] = package.loaded["luat-sta"] or true - --- original size: 5703, stripped down to: 2321 - -if not modules then modules={} end modules ['luat-sta']={ - version=1.001, - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local gmatch,match=string.gmatch,string.match -local type=type -states=states or {} -local states=states -states.data=states.data or {} -local data=states.data -states.hash=states.hash or {} -local hash=states.hash -states.tag=states.tag or "" -states.filename=states.filename or "" -function states.save(filename,tag) - tag=tag or states.tag - filename=file.addsuffix(filename or states.filename,'lus') - io.savedata(filename, - "-- generator : luat-sta.lua\n".."-- state tag : "..tag.."\n\n"..table.serialize(data[tag or states.tag] or {},true) - ) -end -function states.load(filename,tag) - states.filename=filename - states.tag=tag or "whatever" - states.filename=file.addsuffix(states.filename,'lus') - data[states.tag],hash[states.tag]=(io.exists(filename) and dofile(filename)) or {},{} -end -local function set_by_tag(tag,key,value,default,persistent) - local d,h=data[tag],hash[tag] - if d then - if type(d)=="table" then - local dkey,hkey=key,key - local pre,post=match(key,"(.+)%.([^%.]+)$") - if pre and post then - for k in gmatch(pre,"[^%.]+") do - local dk=d[k] - if not dk then - dk={} - d[k]=dk - elseif type(dk)=="string" then - break - end - d=dk - end - dkey,hkey=post,key - end - if value==nil then - value=default - elseif value==false then - elseif persistent then - value=value or d[dkey] or default - else - value=value or default - end - d[dkey],h[hkey]=value,value - elseif type(d)=="string" then - data[tag],hash[tag]=value,value - end - end -end -local function get_by_tag(tag,key,default) - local h=hash[tag] - if h and h[key] then - return h[key] - else - local d=data[tag] - if d then - for k in gmatch(key,"[^%.]+") do - local dk=d[k] - if dk~=nil then - d=dk - else - return default - end - end - if d==false then - return false - else - return d or default - end - end - end -end -states.set_by_tag=set_by_tag -states.get_by_tag=get_by_tag -function states.set(key,value,default,persistent) - set_by_tag(states.tag,key,value,default,persistent) -end -function states.get(key,default) - return get_by_tag(states.tag,key,default) -end - - -end -- of closure - -do -- create closure to overcome 200 locals limit - -package.loaded["luat-fmt"] = package.loaded["luat-fmt"] or true - --- original size: 11691, stripped down to: 8350 - -if not modules then modules={} end modules ['luat-fmt']={ - version=1.001, - comment="companion to mtxrun", - author="Hans Hagen, PRAGMA-ADE, Hasselt NL", - copyright="PRAGMA ADE / ConTeXt Development Team", - license="see context related readme files" -} -local format=string.format -local concat=table.concat -local quoted=string.quoted -local luasuffixes=utilities.lua.suffixes -local report_format=logs.reporter("resolvers","formats") -local function primaryflags(arguments) - local flags={} - if arguments.silent then - flags[#flags+1]="--interaction=batchmode" - end - return concat(flags," ") -end -local function secondaryflags(arguments) - local trackers=arguments.trackers - local directives=arguments.directives - local flags={} - if trackers and trackers~="" then - flags[#flags+1]="--c:trackers="..quoted(trackers) - end - if directives and directives~="" then - flags[#flags+1]="--c:directives="..quoted(directives) - end - if arguments.silent then - flags[#flags+1]="--c:silent" - end - if arguments.errors then - flags[#flags+1]="--c:errors" - end - if arguments.ansi then - flags[#flags+1]="--c:ansi" - end - if arguments.ansilog then - flags[#flags+1]="--c:ansilog" - end - if arguments.strip then - flags[#flags+1]="--c:strip" - end - if arguments.lmtx then - flags[#flags+1]="--c:lmtx" - end - return concat(flags," ") -end -local template=[[--ini %primaryflags% --lua=%luafile% %texfile% %secondaryflags% %redirect%]] -local checkers={ - primaryflags="verbose", - secondaryflags="verbose", - luafile="readable", - texfile="readable", - redirect="string", - binarypath="string", -} -local runners={ - luametatex=sandbox.registerrunner { - name="make luametatex format", - program="luametatex", - template=template, - checkers=checkers, - reporter=report_format, - }, - luatex=sandbox.registerrunner { - name="make luatex format", - program="luatex", - template=template, - checkers=checkers, - reporter=report_format, - }, - luajittex=sandbox.registerrunner { - name="make luajittex format", - program="luajittex", - template=template, - checkers=checkers, - reporter=report_format, - }, -} -local stubfiles={ - luametatex="luat-cod.lmt", - luatex="luat-cod.lua", - luajittex="luat-cod.lua", -} -local suffixes={ - luametatex="mkxl", - luatex="mkiv", - luajittex="mkiv", -} -local function validbinarypath() - if not environment.arguments.nobinarypath then - local path=environment.ownpath or file.dirname(environment.ownname) - if path and path~="" then - path=dir.expandname(path) - if path~="" and lfs.isdir(path) then - return path - end - end - end -end -local function fatalerror(startupdir,...) - report_format(...) - lfs.chdir(startupdir) -end -function environment.make_format(formatname) - local arguments=environment.arguments - local engine=environment.ownmain or "luatex" - local silent=arguments.silent - local errors=arguments.errors - local runner=runners[engine] - local startupdir=dir.current() - if not runner then - return fatalerror(startupdir,"the format %a cannot be generated, no runner available for engine %a",name,engine) - end - local luasourcename=stubfiles[engine] - if not luasourcename then - return fatalerror(startupdir,"no lua stub file specified for %a",engine) - end - local texsourcename=file.addsuffix(formatname,suffixes[engine]) - local fulltexsourcename=resolvers.findfile(texsourcename,"tex") or "" - if fulltexsourcename=="" then - return fatalerror(startupdir,"no tex source file with name %a (mkiv or tex)",formatname) - end - local fulltexsourcename=dir.expandname(fulltexsourcename) - local texsourcepath=file.dirname(fulltexsourcename) - if lfs.isfile(fulltexsourcename) then - report_format("using tex source file %a",fulltexsourcename) - else - return fatalerror(startupdir,"no accessible tex source file with name %a",fulltexsourcename) - end - local fullluasourcename=dir.expandname(file.join(texsourcepath,luasourcename) or "") - if lfs.isfile(fullluasourcename) then - report_format("using lua stub file %a",fullluasourcename) - else - return fatalerror(startupdir,"no accessible lua stub file with name %a",fulltexsourcename) - end - local validformatpath=caches.getwritablepath("formats",engine) or "" - if validformatpath=="" then - return fatalerror(startupdir,"invalid format path, insufficient write access") - end - local binarypath=validbinarypath() - report_format("changing to format path %a",validformatpath) - if not lfs.chdir(validformatpath) then - return fatalerror(startupdir,"unable to change to format path %a",validformatpath) - end - local primaryflags=primaryflags(arguments) - local secondaryflags=secondaryflags(arguments) - local specification={ - binarypath=binarypath, - primaryflags=primaryflags, - secondaryflags=secondaryflags, - luafile=quoted(fullluasourcename), - texfile=quoted(fulltexsourcename), - } - if silent then - specification.redirect="> temp.log" - end - statistics.starttiming("format") - local result=runner(specification) - statistics.stoptiming("format") - if silent then - os.remove("temp.log") - end - report_format() - if binarypath and binarypath~="" then - report_format("binary path : %s",binarypath or "?") - end - report_format("format path : %s",validformatpath) - report_format("luatex engine : %s",engine) - report_format("lua startup file : %s",fullluasourcename) - if primaryflags~="" then - report_format("primary flags : %s",primaryflags) - end - if secondaryflags~="" then - report_format("secondary flags : %s",secondaryflags) - end - report_format("context file : %s",fulltexsourcename) - report_format("run time : %.3f seconds",statistics.elapsed("format")) - report_format("return value : %s",result==0 and "okay" or "error") - report_format() - lfs.chdir(startupdir) -end -local template=[[%primaryflags% --fmt=%fmtfile% --lua=%luafile% %texfile% %secondaryflags%]] -local checkers={ - primaryflags="verbose", - secondaryflags="verbose", - fmtfile="readable", - luafile="readable", - texfile="readable", -} -local runners={ - luatex=sandbox.registerrunner { - name="run luatex format", - program="luatex", - template=template, - checkers=checkers, - reporter=report_format, - }, - luametatex=sandbox.registerrunner { - name="run luametatex format", - program="luametatex", - template=template, - checkers=checkers, - reporter=report_format, - }, - luajittex=sandbox.registerrunner { - name="run luajittex format", - program="luajittex", - template=template, - checkers=checkers, - reporter=report_format, - }, -} -function environment.run_format(formatname,scriptname,filename,primaryflags,secondaryflags,verbose) - local engine=environment.ownmain or "luatex" - if not formatname or formatname=="" then - report_format("missing format name") - return - end - if not scriptname or scriptname=="" then - report_format("missing script name") - return - end - if not lfs.isfile(formatname) or not lfs.isfile(scriptname) then - formatname,scriptname=resolvers.locateformat(formatname) - end - if not formatname or formatname=="" then - report_format("invalid format name") - return - end - if not scriptname or scriptname=="" then - report_format("invalid script name") - return - end - local runner=runners[engine] - if not runner then - report_format("format %a cannot be run, no runner available for engine %a",file.nameonly(name),engine) - return - end - if not filename then - filename "" - end - local binarypath=validbinarypath() - local specification={ - binarypath=binarypath, - primaryflags=primaryflags or "", - secondaryflags=secondaryflags or "", - fmtfile=quoted(formatname), - luafile=quoted(scriptname), - texfile=filename~="" and quoted(filename) or "", - } - statistics.starttiming("make format") - local result=runner(specification) - statistics.stoptiming("make format") - if verbose then - report_format() - if binarypath and binarypath~="" then - report_format("binary path : %s",binarypath) - end - report_format("luatex engine : %s",engine) - report_format("lua startup file : %s",scriptname) - report_format("tex format file : %s",formatname) - if filename~="" then - report_format("tex input file : %s",filename) - end - if primaryflags~="" then - report_format("primary flags : %s",primaryflags) - end - if secondaryflags~="" then - report_format("secondary flags : %s",secondaryflags) - end - report_format("run time : %0.3f seconds",statistics.elapsed("make format")) - report_format("return value : %s",result==0 and "okay" or "error") - report_format() - end - return result -end - - -end -- of closure - --- used libraries : l-bit32.lua l-lua.lua l-macro.lua l-sandbox.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-sha.lua l-url.lua l-dir.lua l-boolean.lua l-unicode.lua l-math.lua util-str.lua util-tab.lua util-fil.lua util-sac.lua util-sto.lua util-prs.lua util-fmt.lua util-soc-imp-reset.lua util-soc-imp-socket.lua util-soc-imp-copas.lua util-soc-imp-ltn12.lua util-soc-imp-mime.lua util-soc-imp-url.lua util-soc-imp-headers.lua util-soc-imp-tp.lua util-soc-imp-http.lua util-soc-imp-ftp.lua util-soc-imp-smtp.lua trac-set.lua trac-log.lua trac-inf.lua trac-pro.lua util-lua.lua util-deb.lua util-tpl.lua util-sbx.lua util-mrg.lua util-env.lua luat-env.lua util-zip.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 libs-ini.lua luat-sta.lua luat-fmt.lua --- skipped libraries : - --- original bytes : 1034927 --- stripped bytes : 407861 - --- end library merge - --- We need this hack till luatex is fixed. --- --- for k,v in pairs(arg) do print(k,v) end - -if arg and (arg[0] == 'luatex' or arg[0] == 'luatex.exe') and arg[1] == "--luaonly" then - arg[-1]=arg[0] arg[0]=arg[2] for k=3,#arg do arg[k-2]=arg[k] end arg[#arg]=nil arg[#arg]=nil -end - --- End of hack. - -local format, gsub, gmatch, match, find = string.format, string.gsub, string.gmatch, string.match, string.find -local concat = table.concat - -local ownname = environment and environment.ownname or arg[0] or 'mtxrun.lua' -local ownpath = gsub(match(ownname,"^(.+)[\\/].-$") or ".","\\","/") -local owntree = environment and environment.ownpath or ownpath - -local ownlibs = { -- order can be made better - - 'l-bit32.lua', - 'l-lua.lua', - 'l-macro.lua', - 'l-sandbox.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-sha.lua', - 'l-url.lua', - 'l-dir.lua', - 'l-boolean.lua', - 'l-unicode.lua', - 'l-math.lua', - - 'util-str.lua', -- code might move to l-string - 'util-tab.lua', - 'util-fil.lua', - 'util-sac.lua', - 'util-sto.lua', - 'util-prs.lua', - 'util-fmt.lua', - - 'util-soc-imp-reset.lua', - 'util-soc-imp-socket.lua', - 'util-soc-imp-copas.lua', - 'util-soc-imp-ltn12.lua', - -- 'util-soc-imp-mbox.lua', - 'util-soc-imp-mime.lua', - 'util-soc-imp-url.lua', - 'util-soc-imp-headers.lua', - 'util-soc-imp-tp.lua', - 'util-soc-imp-http.lua', - 'util-soc-imp-ftp.lua', - 'util-soc-imp-smtp.lua', - - 'trac-set.lua', - 'trac-log.lua', - 'trac-inf.lua', -- was before trac-set - 'trac-pro.lua', -- not really needed - 'util-lua.lua', -- indeed here? - 'util-deb.lua', - - 'util-tpl.lua', - 'util-sbx.lua', - 'util-mrg.lua', - - 'util-env.lua', - 'luat-env.lua', -- can come before inf (as in mkiv) - - 'util-zip.lua', - - 'lxml-tab.lua', - 'lxml-lpt.lua', - -- 'lxml-ent.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-tex.lua', --- 'data-bin.lua', - 'data-zip.lua', - 'data-tre.lua', - 'data-sch.lua', - 'data-lua.lua', - 'data-aux.lua', -- updater - 'data-tmf.lua', - 'data-lst.lua', - - 'libs-ini.lua', - - 'luat-sta.lua', - 'luat-fmt.lua', - -} - --- c:/data/develop/tex-context/tex/texmf-win64/bin/../../texmf-context/tex/context/base/mkiv/data-tmf.lua --- c:/data/develop/context/sources/data-tmf.lua - -local ownlist = { - -- '.', - -- ownpath , - owntree .. "/../../../../context/sources", -- HH's development path - -- - owntree .. "/../../texmf-local/tex/context/base/mkiv", - owntree .. "/../../texmf-context/tex/context/base/mkiv", - owntree .. "/../../texmf/tex/context/base/mkiv", - owntree .. "/../../../texmf-local/tex/context/base/mkiv", - owntree .. "/../../../texmf-context/tex/context/base/mkiv", - owntree .. "/../../../texmf/tex/context/base/mkiv", - -- - owntree .. "/../../texmf-local/tex/context/base", - owntree .. "/../../texmf-context/tex/context/base", - owntree .. "/../../texmf/tex/context/base", - owntree .. "/../../../texmf-local/tex/context/base", - owntree .. "/../../../texmf-context/tex/context/base", - owntree .. "/../../../texmf/tex/context/base", -} - -if ownpath == "." then table.remove(ownlist,1) end - -own = { - name = ownname, - path = ownpath, - tree = owntree, - list = ownlist, - libs = ownlibs, -} - -local function locate_libs() - for l=1,#ownlibs do - local lib = ownlibs[l] - for p =1,#ownlist do - local pth = ownlist[p] - local filename = pth .. "/" .. lib - local found = lfs.isfile(filename) - if found then - package.path = package.path .. ";" .. pth .. "/?.lua" -- in case l-* does a require - return pth - end - end - end -end - -local function load_libs() - local found = locate_libs() - if found then - for l=1,#ownlibs do - local filename = found .. "/" .. ownlibs[l] - local codeblob = loadfile(filename) - if codeblob then - codeblob() - end - end - else - resolvers = nil - end -end - -if not resolvers then - load_libs() -end - -if not resolvers then - print("") - print("Mtxrun is unable to start up due to lack of libraries. You may") - print("try to run 'lua mtxrun.lua --selfmerge' in the path where this") - print("script is located (normally under ..../scripts/context/lua) which") - print("will make this script library independent.") - os.exit() -end - --- verbosity - ------ e_verbose = environment.arguments["verbose"] - -local e_verbose = false - --- some common flags (also passed through environment) - -local e_silent = environment.argument("silent") -local e_errors = environment.argument("errors") -local e_noconsole = environment.argument("noconsole") - -local e_trackers = environment.argument("trackers") -local e_directives = environment.argument("directives") -local e_experiments = environment.argument("experiments") - -local t = { } - -if type(e_directives) == "string" then - t[#t+1] = e_directives -end - -if type(e_silent) == "string" then - t[#t+1] = format("logs.blocked={%s}",e_silent) -elseif e_silent == true then - t[#t+1] = "logs.blocked" -end - -if type(e_errors) == "string" then - t[#t+1] = format("logs.errors={%s}",e_errors) -elseif e_errors == true then - t[#t+1] = "logs.errors" -end - -if e_noconsole then - t[#t+1] = format("logs.target=file") -end - -if #t > 0 then - e_directives = concat(t,",") -end - -if e_trackers then trackers .enable(e_trackers) end -if e_directives then directives .enable(e_directives) end -if e_experiments then experiments.enable(e_experiments) end - -if not environment.trackers then environment.trackers = e_trackers end -if not environment.directives then environment.directives = e_directives end -if not environment.experiments then environment.experiments = e_experiments end - --- - -resolvers.reset() - -local helpinfo = [[ -<?xml version="1.0" ?> -<application> - <metadata> - <entry name="name">mtxrun</entry> - <entry name="detail">ConTeXt TDS Runner Tool</entry> - <entry name="version">1.33</entry> - </metadata> - <flags> - <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) (=loop) (exit|quit aborts)</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> - <flag name="internal"><short>run script using built in libraries (same as <ref name="ctxlua"/>)</short></flag> - <flag name="locate"><short>locate given filename in database (default) or system (<ref name="first"/> <ref name="all"/> <ref name="detail"/>)</short></flag> - </subcategory> - <subcategory> - <flag name="tree" value="pathtotree"><short>use given texmf tree (default file: setuptex.tmf)</short></flag> - <flag name="path" value="runpath"><short>go to given path before execution</short></flag> - <flag name="ifchanged" value="filename"><short>only execute when given file has changed (md checksum)</short></flag> - <flag name="iftouched" value="old,new"><short>only execute when given file has changed (time stamp)</short></flag> - </subcategory> - <subcategory> - <flag name="makestubs"><short>create stubs for (context related) scripts</short></flag> - <flag name="removestubs"><short>remove stubs (context related) scripts</short></flag> - <flag name="stubpath" value="binpath"><short>paths where stubs wil be written</short></flag> - <flag name="windows"><short>create windows (mswin) stubs</short></flag> - <flag name="unix"><short>create unix (linux) stubs</short></flag> - <flag name="addbinarypath"><short>prepend the (found) binarypath to runners</short></flag> - </subcategory> - <subcategory> - <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> - <flag name="launch"><short>launch files like manuals, assumes os support (<ref name="all"/>,<ref name="list"/>)</short></flag> - </subcategory> - <subcategory> - <flag name="timedrun"><short>run a script and time its run</short></flag> - <flag name="autogenerate"><short>regenerate databases if needed (handy when used to run context in an editor)</short></flag> - </subcategory> - <subcategory> - <flag name="usekpse"><short>use kpse as fallback (when no mkiv and cache installed, often slower)</short></flag> - <flag name="forcekpse"><short>force using kpse (handy when no mkiv and cache installed but less functionality)</short></flag> - </subcategory> - <subcategory> - <flag name="prefixes"><short>show supported prefixes</short></flag> - </subcategory> - <subcategory> - <flag name="generate"><short>generate file database</short></flag> - </subcategory> - <subcategory> - <flag name="variables"><short>show configuration variables</short></flag> - <flag name="configurations"><short>show configuration order</short></flag> - </subcategory> - <subcategory> - <flag name="directives"><short>show (known) directives</short></flag> - <flag name="trackers"><short>show (known) trackers</short></flag> - <flag name="experiments"><short>show (known) experiments</short></flag> - </subcategory> - <subcategory> - <flag name="expand-braces"><short>expand complex variable</short></flag> - <flag name="resolve-path"><short>expand variable (completely resolve paths)</short></flag> - <flag name="expand-path"><short>expand variable (resolve paths)</short></flag> - <flag name="expand-var"><short>expand variable (resolve references)</short></flag> - <flag name="show-path"><short>show path expansion of ...</short></flag> - <flag name="var-value"><short>report value of variable</short></flag> - <flag name="find-file"><short>report file location</short></flag> - <flag name="find-path"><short>report path of file</short></flag> - </subcategory> - <subcategory> - <flag name="pattern" value="string"><short>filter variables</short></flag> - </subcategory> - </category> - </flags> -</application> -]] - -local application = logs.application { - name = "mtxrun", - banner = "ConTeXt TDS Runner Tool 1.32", - helpinfo = helpinfo, -} - -local report = application.report - -messages = messages or { } -- for the moment - -runners = runners or { } -- global (might become local) - -runners.applications = { - ["lua"] = "luatex --luaonly", - ["luc"] = "luatex --luaonly", - ["pl"] = "perl", - ["py"] = "python", - ["rb"] = "ruby", -} - -runners.suffixes = { - 'rb', 'lua', 'py', 'pl' -} - -runners.registered = { - texexec = { 'texexec.rb', false }, -- context mkii runner (only tool not to be luafied) - texutil = { 'texutil.rb', true }, -- old perl based index sorter for mkii (old versions need it) - texfont = { 'texfont.pl', true }, -- perl script that makes mkii font metric files - texfind = { 'texfind.pl', false }, -- perltk based tex searching tool, mostly used at pragma - texshow = { 'texshow.pl', false }, -- perltk based context help system, will be luafied - -- texwork = { 'texwork.pl', false }, -- perltk based editing environment, only used at pragma - makempy = { 'makempy.pl', true }, - mptopdf = { 'mptopdf.pl', true }, - pstopdf = { 'pstopdf.rb', true }, -- converts ps (and some more) images, does some cleaning (replaced) - -- examplex = { 'examplex.rb', false }, - concheck = { 'concheck.rb', false }, - runtools = { 'runtools.rb', true }, - textools = { 'textools.rb', true }, - tmftools = { 'tmftools.rb', true }, - ctxtools = { 'ctxtools.rb', true }, - rlxtools = { 'rlxtools.rb', true }, - pdftools = { 'pdftools.rb', true }, - mpstools = { 'mpstools.rb', true }, - -- exatools = { 'exatools.rb', true }, - xmltools = { 'xmltools.rb', true }, - -- luatools = { 'luatools.lua', true }, - mtxtools = { 'mtxtools.rb', true }, - pdftrimwhite = { 'pdftrimwhite.pl', false }, -} - -runners.launchers = { - windows = { }, - unix = { }, -} - --- like runners.libpath("framework"): looks on script's subpath - -function runners.libpath(...) - package.prepend_libpath(file.dirname(environment.ownscript),...) - package.prepend_libpath(file.dirname(environment.ownname) ,...) -end - -function runners.prepare() - local checkname = environment.argument("ifchanged") - if type(checkname) == "string" and checkname ~= "" then - local oldchecksum = file.loadchecksum(checkname) - local newchecksum = file.checksum(checkname) - if oldchecksum == newchecksum then - if e_verbose then - report("file '%s' is unchanged",checkname) - end - return "skip" - elseif e_verbose then - report("file '%s' is changed, processing started",checkname) - end - file.savechecksum(checkname) - end - local touchname = environment.argument("iftouched") - if type(touchname) == "string" and touchname ~= "" then - local oldname, newname = string.splitup(touchname, ",") - if oldname and newname and oldname ~= "" and newname ~= "" then - if not file.needs_updating(oldname,newname) then - if e_verbose then - report("file '%s' and '%s' have same age",oldname,newname) - end - return "skip" - elseif e_verbose then - report("file '%s' is older than '%s'",oldname,newname) - end - end - end - local runpath = environment.argument("path") - if type(runpath) == "string" and not lfs.chdir(runpath) then - report("unable to change to path '%s'",runpath) - return "error" - end - runners.prepare = function() end - return "run" -end - -function runners.execute_script(fullname,internal,nosplit) - local noquote = environment.argument("noquotes") - if fullname and fullname ~= "" then - local state = runners.prepare() - if state == 'error' then - return false - elseif state == 'skip' then - return true - elseif state == "run" then - local path, name, suffix = file.splitname(fullname) - local result = "" - if path ~= "" then - result = fullname - elseif name then - name = gsub(name,"^int[%a]*:",function() - internal = true - return "" - end ) - name = gsub(name,"^script:","") - if suffix == "" and runners.registered[name] and runners.registered[name][1] then - name = runners.registered[name][1] - suffix = file.suffix(name) - end - if suffix == "" then - -- loop over known suffixes - for _,s in pairs(runners.suffixes) do - result = resolvers.findfile(name .. "." .. s, 'texmfscripts') - if result ~= "" then - break - end - end - elseif runners.applications[suffix] then - result = resolvers.findfile(name, 'texmfscripts') - else - -- maybe look on path - result = resolvers.findfile(name, 'other text files') - end - end - if result and result ~= "" then - if not no_split then - local before, after = environment.splitarguments(fullname) -- already done - environment.arguments_before, environment.arguments_after = before, after - end - if internal then - arg = { } for _,v in pairs(environment.arguments_after) do arg[#arg+1] = v end - environment.ownscript = result - dofile(result) - else -local texmfcnf = resolvers.getenv("TEXMFCNF") -if not texmfcnf or texmfcnf == "" then - texmfcnf = resolvers.expandedpathfromlist(resolvers.splitpath(resolvers.resolve(resolvers.luacnfspec))) - resolvers.setenv("TEXMFCNF",table.concat(texmfcnf,";")) -- for running texexec etc (after tl change to texmf-dist) -end - local binary = runners.applications[file.suffix(result)] - result = string.quoted(string.unquoted(result)) - -- if string.match(result,' ') and not string.match(result,"^\".*\"$") then - -- result = '"' .. result .. '"' - -- end - if binary and binary ~= "" then - result = binary .. " " .. result - end - local command = result .. " " .. environment.reconstructcommandline(environment.arguments_after,noquote) - if e_verbose then - report() - report("executing: %s",command) - report() - report() - io.flush() - end - local code = os.execute(command) - if code == 0 then - return true - else - if binary then - binary = file.addsuffix(binary,os.binsuffix) - for p in gmatch(os.getenv("PATH"),"[^"..io.pathseparator.."]+") do - if lfs.isfile(file.join(p,binary)) then - return false - end - end - report() - report("This script needs '%s' which seems not to be installed.",binary) - report() - end - return false - end - end - end - end - end - return false -end - -function runners.execute_program(fullname) - local noquote = environment.argument("noquotes") - if fullname and fullname ~= "" then - local state = runners.prepare() - if state == 'error' then - return false - elseif state == 'skip' then - return true - elseif state == "run" then - local before, after = environment.splitarguments(fullname) - for k=1,#after do after[k] = resolvers.resolve(after[k]) end - environment.initializearguments(after) - fullname = gsub(fullname,"^bin:","") - local command = fullname .. " " .. (environment.reconstructcommandline(after or "",noquote) or "") - report() - report("executing: %s",command) - report() - report() - io.flush() - local code = os.execute(command) - return code == 0 - end - end - return false -end - --- the --usekpse flag will fallback (not default) on kpse (hm, we can better update mtx-stubs) - -local windows_stub = '@echo off\013\010setlocal\013\010set ownpath=%%~dp0%%\013\010texlua "%%ownpath%%mtxrun.lua" --usekpse --execute %s %%*\013\010endlocal\013\010' -local unix_stub = '#!/bin/sh\010mtxrun --usekpse --execute %s \"$@\"\010' - -function runners.handle_stubs(create) - local stubpath = environment.argument('stubpath') or '.' -- 'auto' no longer subpathssupported - local windows = environment.argument('windows') or environment.argument('mswin') or false - local unix = environment.argument('unix') or environment.argument('linux') or false - if not windows and not unix then - if os.platform == "unix" then - unix = true - else - windows = true - end - end - for _,v in pairs(runners.registered) do - local name, doit = v[1], v[2] - if doit then - local base = gsub(file.basename(name), "%.(.-)$", "") - if create then - if windows then - io.savedata(file.join(stubpath,base..".bat"),format(windows_stub,name)) - report("windows stub for '%s' created",base) - end - if unix then - io.savedata(file.join(stubpath,base),format(unix_stub,name)) - report("unix stub for '%s' created",base) - end - else - if windows and (os.remove(file.join(stubpath,base..'.bat')) or os.remove(file.join(stubpath,base..'.cmd'))) then - report("windows stub for '%s' removed", base) - end - if unix and (os.remove(file.join(stubpath,base)) or os.remove(file.join(stubpath,base..'.sh'))) then - report("unix stub for '%s' removed",base) - end - end - end - end -end - -function runners.resolve_string(filename) - if filename and filename ~= "" then - runners.report_location(resolvers.resolve(filename)) - end -end - --- differs from texmfstart where locate appends .com .exe .bat ... todo - -function runners.locate_file(filename) -- was given file but only searches in tree - if filename and filename ~= "" then - if environment.argument("first") then - runners.report_location(resolvers.findfile(filename)) - -- resolvers.dowithfilesandreport(resolvers.findfile,filename) - elseif environment.argument("all") then - local result, status = resolvers.findfiles(filename) - if status and environment.argument("detail") then - runners.report_location(status) - else - runners.report_location(result) - end - else - runners.report_location(resolvers.findgivenfile(filename)) - -- resolvers.dowithfilesandreport(resolvers.findgivenfile,filename) - end - end -end - -function runners.locate_platform() - runners.report_location(os.platform) -end - -function runners.report_location(result) - if type(result) == "table" then - for i=1,#result do - if i > 1 then - io.write("\n") - end - io.write(result[i]) - end - else - io.write(result) - end -end - -function runners.edit_script(filename) -- we assume that gvim is present on most systems (todo: also in cnf file) - local editor = os.getenv("MTXRUN_EDITOR") or os.getenv("TEXMFSTART_EDITOR") or os.getenv("EDITOR") or 'gvim' - local rest = resolvers.resolve(filename) - if rest ~= "" then - local command = editor .. " " .. rest - if e_verbose then - report() - report("starting editor: %s",command) - report() - report() - end - os.launch(command) - end -end - -function runners.save_script_session(filename, list) - if type(list) == "table" then - local t = { } - for i=1,#list do - local key = list[i] - t[key] = environment.arguments[key] - end - io.savedata(filename,table.serialize(t,true)) - end -end - -function runners.load_script_session(filename) - if lfs.isfile(filename) then - local t = io.loaddata(filename) - if t then - t = loadstring(t) - if t then t = t() end - for key, value in pairs(t) do - environment.arguments[key] = value - end - end - end -end - -function resolvers.launch(str) - -- maybe we also need to test on mtxrun.launcher.suffix environment - -- variable or on windows consult the assoc and ftype vars and such - local launchers = runners.launchers[os.platform] if launchers then - local suffix = file.suffix(str) if suffix then - local runner = launchers[suffix] if runner then - str = runner .. " " .. str - end - end - end - os.launch(str) -end - -function runners.launch_file(filename) - local allresults = environment.arguments["all"] - local pattern = environment.arguments["pattern"] - local listonly = environment.arguments["list"] - if not pattern or pattern == "" then - pattern = filename - end - if not pattern or pattern == "" then - report("provide name or --pattern=") - else - local t = resolvers.findfiles(pattern,nil,allresults) - if not t or #t == 0 then - t = resolvers.findfiles("*/" .. pattern,nil,allresults) - end - if not t or #t == 0 then - t = resolvers.findfiles("*/" .. pattern .. "*",nil,allresults) - end - if t and #t > 0 then - for i=1,#t do - local name = t[i] - if listonly then - report("% 3i: %-30s %s",i,file.basename(name),file.dirname(name)) - else - report("launching: %s",name) - resolvers.launch(name) - if not allresults then - break - end - end - end - if listonly then - io.write("\n") - io.write("\n[select number]\n\n>> ") - local answer = tonumber(io.read()) - if answer then - io.write("\n") - local name = t[answer] - if name then - report("launching: %s",name) - resolvers.launch(name) - else - report("invalid number") - end - end - end - else - report("no match for %s", pattern) - end - end -end - -local mtxprefixes = { - { "^mtx%-", "mtx-" }, - { "^mtx%-t%-", "mtx-t-" }, -} - -function runners.find_mtx_script(filename) - local function found(name) - local path = file.dirname(name) - if path and path ~= "" then - return false - else - local fullname = own and own.path and file.join(own.path,name) - return io.exists(fullname) and fullname - end - end - filename = file.addsuffix(filename,"lua") - local basename = file.removesuffix(file.basename(filename)) - local suffix = file.suffix(filename) - -- qualified path, raw name - local fullname = file.is_qualified_path(filename) and io.exists(filename) and filename - if fullname and fullname ~= "" then - return fullname - end - -- current path, raw name - fullname = "./" .. filename - fullname = io.exists(fullname) and fullname - if fullname and fullname ~= "" then - return fullname - end - -- mtx- prefix checking - for i=1,#mtxprefixes do - local mtxprefix = mtxprefixes[i] - mtxprefix = find(filename,mtxprefix[1]) and "" or mtxprefix[2] - -- context namespace, mtx-<filename> - fullname = mtxprefix .. filename - fullname = found(fullname) or resolvers.findfile(fullname) - if fullname and fullname ~= "" then - return fullname - end - -- context namespace, mtx-<filename>s - fullname = mtxprefix .. basename .. "s" .. "." .. suffix - fullname = found(fullname) or resolvers.findfile(fullname) - if fullname and fullname ~= "" then - return fullname - end - -- context namespace, mtx-<filename minus trailing s> - fullname = mtxprefix .. gsub(basename,"s$","") .. "." .. suffix - fullname = found(fullname) or resolvers.findfile(fullname) - if fullname and fullname ~= "" then - return fullname - end - end - -- context namespace, just <filename> - fullname = resolvers.findfile(filename) - return fullname -end - -function runners.register_arguments(...) - local arguments = environment.arguments_after - local passedon = { ... } - for i=#passedon,1,-1 do - local pi = passedon[i] - if pi then - table.insert(arguments,1,pi) - end - end -end - -function runners.execute_ctx_script(filename,...) - runners.register_arguments(...) - local arguments = environment.arguments_after - local fullname = runners.find_mtx_script(filename) or "" - if file.suffix(fullname) == "cld" then - -- handy in editors where we force --autopdf - report("running cld script: %s",filename) - table.insert(arguments,1,fullname) - table.insert(arguments,"--autopdf") - fullname = runners.find_mtx_script("context") or "" - end - -- retry after generate but only if --autogenerate - if fullname == "" and environment.argument("autogenerate") then -- might become the default - resolvers.renewcache() - trackers.enable("resolvers.locating") - resolvers.load() - -- - fullname = runners.find_mtx_script(filename) or "" - end - -- that should do it - if fullname ~= "" then - local state = runners.prepare() - if state == 'error' then - return false - elseif state == 'skip' then - return true - elseif state == "run" then - -- load and save ... kind of undocumented - arg = { } for _,v in pairs(arguments) do arg[#arg+1] = resolvers.resolve(v) end - environment.initializearguments(arg) - local loadname = environment.arguments['load'] - if loadname then - if type(loadname) ~= "string" then loadname = file.basename(fullname) end - loadname = file.replacesuffix(loadname,"cfg") - runners.load_script_session(loadname) - end - filename = environment.files[1] - if e_verbose then - report("using script: %s (if --path is used don't run on path where mtxrun lives)\n",fullname) - end - environment.ownscript = fullname - dofile(fullname) - local savename = environment.arguments['save'] - if savename then - if type(savename) ~= "string" then savename = file.basename(fullname) end - savename = file.replacesuffix(savename,"cfg") - runners.save_script_session(savename,save_list) - end - return true - end - else - if filename == "" or filename == "help" then - local context = resolvers.findfile("mtx-context.lua") - trackers.enable("resolvers.locating") - if context ~= "" then - local result = dir.glob((gsub(context,"mtx%-context","mtx-*"))) -- () needed - local valid = { } - table.sort(result) - for i=1,#result do - local scriptname = result[i] - local scriptbase = match(scriptname,".*mtx%-([^%-]-)%.lua") - if scriptbase then - local data = io.loaddata(scriptname) - local application = match(data,"local application.-=.-(%{.-%})") - if application then - application = loadstring("return " .. application) - if application then - application = application() - local banner = application.banner - if banner then - local description, version = match(banner,"^(.-) ([%d.]+)$") - if description then - valid[#valid+1] = { scriptbase, version, description } - else - valid[#valid+1] = { scriptbase, "", banner } - end - end - end - end - end - end - if #valid > 0 then - application.identify() - report("no script name given, known scripts:") - report() - for k=1,#valid do - local v = valid[k] - report("%-12s %4s %s",v[1],v[2],v[3]) - end - end - else - report("no script name given") - end - else - filename = file.addsuffix(filename,"lua") - if file.is_qualified_path(filename) then - report("unknown script '%s'",filename) - else - report("unknown script '%s' or 'mtx-%s'",filename,filename) - end - end - return false - end -end - -function runners.prefixes() - application.identify() - report() - report(concat(resolvers.allprefixes(true)," ")) -end - -function runners.timedrun(filename) -- just for me - if filename and filename ~= "" then - runners.timed(function() os.execute(filename) end) - end -end - -function runners.timed(action) - statistics.timed(action,true) -end - -function runners.associate(filename) - os.launch(filename) -end - -function runners.evaluate(code,filename) -- for Luigi - local environment = table.setmetatableindex(_G) - if code == "loop" then - while true do - io.write("lua > ") - local code = io.read() - if code == "quit" or code == "exit" then - break - elseif code ~= "" then - local temp = string.match(code,"^= (.*)$") - if temp then - code = "inspect("..temp..")" - end - local compiled, message = load(code,"console","t",environment) - if type(compiled) ~= "function" then - compiled = load("inspect("..code..")","console","t",environment) - end - 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 = load(code,"console","t",environment) - if type(compiled) ~= "function" then - compiled = load("inspect("..code..")","console","t",environment) - end - 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 - local command = string.gsub(environment.argument("command") or "unknown","^%s*\\*(.-)%s*$","%1") - url = utilities.templates.replace(url,{ command = command }) - os.launch(url) - else - report("no --url given") - 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 - -local filename = environment.files[1] or "" -local ok = true - -local before, after = environment.splitarguments(filename) -environment.arguments_before, environment.arguments_after = before, after -environment.initializearguments(before) - -e_verbose = environment.arguments["verbose"] -- delayed till here (we need the ones before script) - -if e_verbose then - trackers.enable("resolvers.locating") -end - --- maybe the unset has to go to this level - -local is_mkii_stub = runners.registered[file.removesuffix(file.basename(filename))] - -local e_argument = environment.argument - -if e_argument("timedlog") then - logs.settimedlog() -end - -if e_argument("usekpse") or e_argument("forcekpse") or is_mkii_stub then - - resolvers.load_tree(e_argument('tree'),true) -- force resolve of TEXMFCNF - - os.setenv("engine","") - os.setenv("progname","") - - local remapper = { - otf = "opentype fonts", - ttf = "truetype fonts", - ttc = "truetype fonts", - pfb = "type1 fonts", - other = "other text files", - } - - local progname = e_argument("progname") or 'context' - - local function kpse_initialized() - texconfig.kpse_init = true - local t = os.clock() - local k = kpse.original.new("luatex",progname) - local dummy = k:find_file("mtxrun.lua") -- so that we're initialized - report("kpse fallback with progname '%s' initialized in %s seconds",progname,os.clock()-t) - kpse_initialized = function() return k end - return k - end - - local findfile = resolvers.findfile - local showpath = resolvers.showpath - - if e_argument("forcekpse") then - - function resolvers.findfile(name,kind) - return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or "" - end - function resolvers.showpath(name) - return (kpse_initialized():show_path(name)) or "" - end - - elseif e_argument("usekpse") or is_mkii_stub then - - resolvers.load() - - function resolvers.findfile(name,kind) - local found = findfile(name,kind) or "" - if found ~= "" then - return found - else - return (kpse_initialized():find_file(resolvers.cleanpath(name),(kind ~= "" and (remapper[kind] or kind)) or "tex") or "") or "" - end - end - function resolvers.showpath(name) - local found = showpath(name) or "" - if found ~= "" then - return found - else - return (kpse_initialized():show_path(name)) or "" - end - end - - end - - function runners.loadbase() - end - -else - - function runners.loadbase(...) - if not resolvers.load(...) then - report("forcing cache reload") - resolvers.renewcache() - trackers.enable("resolvers.locating") - if not resolvers.load(...) then - report("the resolver databases are not present or outdated") - end - end - end - - resolvers.load_tree(e_argument('tree'),e_argument("resolve")) - -end - --- joke .. reminds me of messing with gigi terminals - -do - - local a_locale = e_argument("locale") - - if a_locale then - - -- I really hate this crap but am too tired of discussing it over and over - -- again so for the sake of usiage outside context we will provide ways to - -- use locales in an otherwise supposed to be locale agnostic system. And - -- forget about support in case of interferences. - - report() - report(what == "force" and "forcing locale:" or "original locale:") - report() - report(" collate : %s",status.lc_collate or "<unset>") - report(" ctype : %s",status.lc_ctype or "<unset>") - report(" monetary : %s",status.lc_monetary or "<unset>") - report(" numeric : %s",status.lc_numeric or "<unset>") - report(" time : %s",status.lc_time or "<unset>") - report() - - end - - if a_locale == "force" then - os.setlocale(status.lc_collate ,"collate") - os.setlocale(status.lc_ctype ,"ctype") - os.setlocale(status.lc_monetary,"monetary") - os.setlocale(status.lc_numeric ,"numeric") - os.setlocale(status.lc_time ,"time") - else - function os.setlocale() - end - end - -end - --- if e_argument("ansi") or e_argument("ansilog") then - --- logs.setformatters(e_argument("ansi") and "ansi" or "ansilog") - --- -- local script = e_argument("script") or e_argument("scripts") --- -- --- -- if type(script) == "string" then --- -- logs.writer("]0;"..script.."") -- for Alan to test --- -- end - --- end - -if e_argument("script") or e_argument("scripts") then - - -- run a script by loading it (using libs), pass args - - if e_argument("nofiledatabase") then - -- handy for mtx-update - else - runners.loadbase() - end - if is_mkii_stub then - ok = runners.execute_script(filename,false,true) - else - 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 - - runners.loadbase() - local found = locate_libs() - - if found then - local mtxrun = resolvers.findfile("mtxrun.lua") -- includes local name - if lfs.isfile(mtxrun) then - utilities.merger.selfmerge(mtxrun,own.libs,{ found }) - application.report("runner updated on resolved path: %s",mtxrun) - else - utilities.merger.selfmerge(own.name,own.libs,{ found }) - application.report("runner updated on relative path: %s",own.name) - end - end - -elseif e_argument("selfclean") then - - -- remove embedded libraries - - runners.loadbase() - - local mtxrun = resolvers.findfile("mtxrun.lua") -- includes local name - if lfs.isfile(mtxrun) then - utilities.merger.selfclean(mtxrun) - application.report("runner cleaned on resolved path: %s",mtxrun) - else - utilities.merger.selfclean(own.name) - application.report("runner cleaned on relative path: %s",own.name) - end - -elseif e_argument("selfupdate") then - - runners.loadbase() - trackers.enable("resolvers.locating") - resolvers.updatescript(own.name,"mtxrun") - -elseif e_argument("ctxlua") or e_argument("internal") then - - -- run a script by loading it (using libs) - - runners.loadbase() - ok = runners.execute_script(filename,true) - -elseif e_argument("execute") then - - -- execute script - - runners.loadbase() - ok = runners.execute_script(filename) - -elseif e_argument("direct") then - - -- equals bin: - - runners.loadbase() - ok = runners.execute_program(filename) - -elseif e_argument("edit") then - - -- edit file - - runners.loadbase() - runners.edit_script(filename) - -elseif e_argument("launch") then - - runners.loadbase() - runners.launch_file(filename) - -elseif e_argument("associate") then - - runners.associate(filename) - -elseif e_argument("gethelp") then - - runners.gethelp() - -elseif e_argument("makestubs") then - - -- make stubs (depricated) - - runners.handle_stubs(true) - -elseif e_argument("removestubs") then - - -- remove stub (depricated) - - runners.loadbase() - runners.handle_stubs(false) - -elseif e_argument("resolve") then - - -- resolve string - - runners.loadbase() - runners.resolve_string(filename) - -elseif e_argument("locate") then - - -- locate file (only database) - - runners.loadbase() - runners.locate_file(filename) - -elseif e_argument("platform") or e_argument("show-platform") then - - -- locate platform - - runners.loadbase() - runners.locate_platform() - -elseif e_argument("prefixes") then - - runners.loadbase() - runners.prefixes() - -elseif e_argument("timedrun") then - - -- locate platform - - runners.loadbase() - runners.timedrun(filename) - -elseif e_argument("variables") or e_argument("show-variables") or e_argument("expansions") or e_argument("show-expansions") then - - -- luatools: runners.execute_ctx_script("mtx-base","--expansions",filename) - - resolvers.load("nofiles") - resolvers.listers.variables(e_argument("pattern")) - -elseif e_argument("configurations") or e_argument("show-configurations") then - - -- luatools: runners.execute_ctx_script("mtx-base","--configurations",filename) - - resolvers.load("nofiles") - resolvers.listers.configurations() - -elseif e_argument("find-file") then - - -- luatools: runners.execute_ctx_script("mtx-base","--find-file",filename) - - resolvers.load() - local e_all = e_argument("all") - local e_pattern = e_argument("pattern") - local e_format = e_argument("format") - local finder = e_all and resolvers.findfiles or resolvers.findfile - if not e_pattern then - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(finder,environment.files,e_format) - elseif type(e_pattern) == "string" then - resolvers.dowithfilesandreport(finder,{ e_pattern },e_format) - end - -elseif e_argument("find-path") then - - -- luatools: runners.execute_ctx_script("mtx-base","--find-path",filename) - - resolvers.load() - local path = resolvers.findpath(filename) - if e_verbose then - report(path) - else - print(path) - end - -elseif e_argument("expand-braces") then - - -- luatools: runners.execute_ctx_script("mtx-base","--expand-braces",filename) - - resolvers.load("nofiles") - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(resolvers.expandbraces, environment.files) - -elseif e_argument("expand-path") then - - -- luatools: runners.execute_ctx_script("mtx-base","--expand-path",filename) - - resolvers.load("nofiles") - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(resolvers.expandpath, environment.files) - -elseif e_argument("resolve-path") then - - resolvers.load("nofiles") - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(resolvers.cleanedpathlist, environment.files) - -elseif e_argument("expand-var") or e_argument("expand-variable") then - - -- luatools: runners.execute_ctx_script("mtx-base","--expand-var",filename) - - resolvers.load("nofiles") - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(resolvers.expansion, environment.files) - -elseif e_argument("show-path") or e_argument("path-value") then - - -- luatools: runners.execute_ctx_script("mtx-base","--show-path",filename) - - resolvers.load("nofiles") - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(resolvers.showpath, environment.files) - -elseif e_argument("var-value") or e_argument("show-value") then - - -- luatools: runners.execute_ctx_script("mtx-base","--show-value",filename) - - resolvers.load("nofiles") - runners.register_arguments(filename) - environment.initializearguments(environment.arguments_after) - resolvers.dowithfilesandreport(resolvers.variable,environment.files) - -elseif e_argument("format-path") then - - -- luatools: runners.execute_ctx_script("mtx-base","--format-path",filename) - - resolvers.load() - report(caches.getwritablepath("format")) - --- elseif e_argument("pattern") then --- --- -- luatools --- --- runners.execute_ctx_script("mtx-base","--pattern='" .. e_argument("pattern") .. "'",filename) - -elseif e_argument("generate") then - - -- luatools - - if filename and filename ~= "" then - resolvers.load("nofiles") - trackers.enable("resolvers.locating") - resolvers.renew(filename) - else - resolvers.renewcache() - trackers.enable("resolvers.locating") - resolvers.load() - end - - e_verbose = true - -elseif e_argument("make") or e_argument("ini") or e_argument("compile") then - - -- luatools: runners.execute_ctx_script("mtx-base","--make",filename) - - resolvers.load() - trackers.enable("resolvers.locating") - environment.make_format(filename) - -elseif e_argument("run") then - - -- luatools - - runners.execute_ctx_script("mtx-base","--run",filename) - -elseif e_argument("fmt") then - - -- luatools - - runners.execute_ctx_script("mtx-base","--fmt",filename) - -elseif e_argument("help") and filename=='base' then - - -- luatools - - runners.execute_ctx_script("mtx-base","--help") - -elseif e_argument("version") then - - application.version() - - application.report("source path",environment.ownbin) - -elseif e_argument("directives") then - - directives.show() - -elseif e_argument("trackers") then - - trackers.show() - -elseif e_argument("experiments") then - - experiments.show() - -elseif e_argument("exporthelp") then - - runners.loadbase() - application.export(e_argument("exporthelp"),filename) - -elseif e_argument("systeminfo") then - - runners.systeminfo() - -elseif e_argument("locale") then - - -- already done - -elseif e_argument("help") or filename=='help' or filename == "" then - - application.help() - -elseif find(filename,"^bin:") then - - runners.loadbase() - ok = runners.execute_program(filename) - -elseif is_mkii_stub then - - -- execute mkii script - - runners.loadbase() - ok = runners.execute_script(filename,false,true) - -elseif false then - - runners.loadbase() - ok = runners.execute_ctx_script(filename) - if not ok then - ok = runners.execute_script(filename) - end - -elseif environment.files[1] == 'texmfcnf.lua' then -- so that we don't need to load mtx-base - - resolvers.load("nofiles") - resolvers.listers.configurations() - -else - runners.loadbase() - runners.execute_ctx_script("mtx-base",filename) - -end - -if e_verbose then - report() - report("elapsed lua time: %0.3f seconds",os.runtime()) -end - -if os.type ~= "windows" then - texio.write("\n") -- is this still valid? -end - -if ok == false then ok = 1 elseif ok == true or ok == nil then ok = 0 end - -if lua and lua.getexitcode then - ok = lua.getexitcode() -end - --- os.exit(ok,true) -- true forces a cleanup in 5.2+ - -os.exit(ok) -- true forces a cleanup in 5.2+ but reports a wrong number then +../../texmf-dist/scripts/context/lua/mtxrun.lua
\ No newline at end of file |