summaryrefslogtreecommitdiff
path: root/Master
diff options
context:
space:
mode:
Diffstat (limited to 'Master')
l---------[-rw-r--r--]Master/bin/aarch64-linux/mtxrun.lua27611
l---------[-rw-r--r--]Master/bin/amd64-freebsd/mtxrun.lua27611
l---------[-rw-r--r--]Master/bin/armhf-linux/mtxrun.lua27611
l---------[-rw-r--r--]Master/bin/i386-freebsd/mtxrun.lua27611
l---------[-rw-r--r--]Master/bin/i386-linux/mtxrun.lua27611
l---------[-rw-r--r--]Master/bin/i386-solaris/mtxrun.lua27611
l---------[-rw-r--r--]Master/bin/universal-darwin/mtxrun.lua27611
-rwxr-xr-xMaster/bin/windows/mtxrun.lua75
l---------[-rw-r--r--]Master/bin/x86_64-darwinlegacy/mtxrun.lua27611
l---------[-rw-r--r--]Master/bin/x86_64-linux/mtxrun.lua27611
l---------[-rw-r--r--]Master/bin/x86_64-linuxmusl/mtxrun.lua27611
l---------[-rw-r--r--]Master/bin/x86_64-solaris/mtxrun.lua27611
-rw-r--r--Master/texmf-dist/doc/context/documents/general/manuals/musings.pdfbin1469208 -> 2144254 bytes
-rw-r--r--Master/texmf-dist/doc/context/sources/general/manuals/lowlevel/lowlevel-buffers.tex506
-rw-r--r--Master/texmf-dist/doc/context/sources/general/manuals/luametatex/luametatex.tex7
-rw-r--r--Master/texmf-dist/doc/context/sources/general/manuals/musings/musings-toocomplex.tex2
-rw-r--r--Master/texmf-dist/doc/context/sources/general/manuals/musings/musings.tex1
-rw-r--r--Master/texmf-dist/metapost/context/base/common/mp-remapped-boxes.mp1
-rw-r--r--Master/texmf-dist/metapost/context/base/common/mp-remapped-hatching.mp10
-rwxr-xr-xMaster/texmf-dist/scripts/context/lua/mtxrun.lua75
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/char-def.lua6
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/context.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/data-ini.lua39
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/grph-con.lua12
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-dir.lua23
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/l-file.lua22
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua93
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua26
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/mult-def.lua8
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/page-flt.lua8
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/status-files.pdfbin24604 -> 24650 bytes
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/status-lua.pdfbin265851 -> 266630 bytes
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv2
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua5
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/typo-prc.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-client.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-ffi.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua2
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-sqlite.lua1
-rw-r--r--Master/texmf-dist/tex/context/base/mkiv/util-sql.lua29
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/anch-pos.lmt4
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/char-tex.lmt2
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/cont-new.mkxl2
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/context.mkxl16
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/core-con.mkxl25
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/core-uti.lmt60
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/file-syn.lmt79
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/file-syn.mklx8
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/lang-lab.lmt37
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/lang-lab.mkxl10
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/libs-imp-sqlite.lmt3
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/lpdf-lmt.lmt20
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/lpdf-mis.lmt17
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/math-acc.mklx117
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/math-act.lmt20
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/math-ali.mkxl60
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/math-def.mkxl5
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/math-ini.mkxl160
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/math-spa.lmt137
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/mlib-ctx.lmt2
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/mlib-fio.lmt17
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/mult-dim.mklx2
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/node-ali.lmt15
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/node-aux.lmt16
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/page-flt.mkxl30
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/page-lin.lmt2
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/page-one.mkxl91
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/page-sel.lmt2
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/page-txt.mklx21
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/spac-ver.lmt2
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-def.mkxl2
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-flt.lmt53
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-flt.mklx71
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-itm.lmt64
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-itm.mklx34
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-lst.lmt138
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-lst.mklx6
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-mat.lmt30
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-mat.mkxl45
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-ref.lmt169
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-ref.mklx2
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-reg.lmt153
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-reg.mkxl122
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-sec.mkxl15
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-syn.lmt420
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/strc-syn.mkxl65
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/tabl-ntb.lmt143
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/tabl-ntb.mkxl95
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/tabl-tbl.mkxl16
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/tabl-xtb.lmt4
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/task-ini.lmt6
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/toks-scn.lmt10
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/type-set.mkxl42
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-fkr.lmt122
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-fkr.mkxl6
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-inj.lmt119
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-inj.mkxl2
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-man.lmt119
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-prc.lmt129
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-prc.mklx7
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-rep.lmt135
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-rep.mkxl6
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-scr.mkxl38
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-spa.lmt4
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-wrp.lmt95
-rw-r--r--Master/texmf-dist/tex/context/base/mkxl/typo-wrp.mkxl13
-rw-r--r--Master/texmf-dist/tex/context/fonts/mkiv/kpfonts-math.lfg12
-rw-r--r--Master/texmf-dist/tex/context/modules/mkxl/m-tikz.mkxl7
-rw-r--r--Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-merged.lua22
-rw-r--r--Master/texmf-dist/web2c/texmfcnf.lua233
112 files changed, 4071 insertions, 304371 deletions
diff --git a/Master/bin/aarch64-linux/mtxrun.lua b/Master/bin/aarch64-linux/mtxrun.lua
index a00dc59288c..8825f964657 100644..120000
--- a/Master/bin/aarch64-linux/mtxrun.lua
+++ b/Master/bin/aarch64-linux/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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+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["%-15s | %s"],
- report_nop=formatters["%-15s |"],
- subreport_yes=formatters["%-15s | %s | %s"],
- subreport_nop=formatters["%-15s | %s |"],
- status_yes=formatters["%-15s : %s\n"],
- status_nop=formatters["%-15s :\n"],
- },
- },
- }
- logs.flush=ignore
- writer=function(s)
- write_nl(s)
- 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]="&amp;",
- [42]="&quot;",
- [47]="&apos;",
- [74]="&lt;",
- [76]="&gt;",
- }
- local predefined_simplified={
- [38]="&",amp="&",
- [42]='"',quot='"',
- [47]="'",apos="'",
- [74]="<",lt="<",
- [76]=">",gt=">",
- }
- local nofprivates=0xF0000
- local privates_u={
- [ [[&]] ]="&amp;",
- [ [["]] ]="&quot;",
- [ [[']] ]="&apos;",
- [ [[<]] ]="&lt;",
- [ [[>]] ]="&gt;",
- }
- 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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"
-local escaped=Cs(normal*(special*normal)^0)
-local normal=(1-S"&")^0
-local special=P("&lt;")/"<"+P("&gt;")/">"+P("&amp;")/"&"
-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
diff --git a/Master/bin/amd64-freebsd/mtxrun.lua b/Master/bin/amd64-freebsd/mtxrun.lua
index a00dc59288c..8825f964657 100644..120000
--- a/Master/bin/amd64-freebsd/mtxrun.lua
+++ b/Master/bin/amd64-freebsd/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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+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["%-15s | %s"],
- report_nop=formatters["%-15s |"],
- subreport_yes=formatters["%-15s | %s | %s"],
- subreport_nop=formatters["%-15s | %s |"],
- status_yes=formatters["%-15s : %s\n"],
- status_nop=formatters["%-15s :\n"],
- },
- },
- }
- logs.flush=ignore
- writer=function(s)
- write_nl(s)
- 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]="&amp;",
- [42]="&quot;",
- [47]="&apos;",
- [74]="&lt;",
- [76]="&gt;",
- }
- local predefined_simplified={
- [38]="&",amp="&",
- [42]='"',quot='"',
- [47]="'",apos="'",
- [74]="<",lt="<",
- [76]=">",gt=">",
- }
- local nofprivates=0xF0000
- local privates_u={
- [ [[&]] ]="&amp;",
- [ [["]] ]="&quot;",
- [ [[']] ]="&apos;",
- [ [[<]] ]="&lt;",
- [ [[>]] ]="&gt;",
- }
- 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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"
-local escaped=Cs(normal*(special*normal)^0)
-local normal=(1-S"&")^0
-local special=P("&lt;")/"<"+P("&gt;")/">"+P("&amp;")/"&"
-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
diff --git a/Master/bin/armhf-linux/mtxrun.lua b/Master/bin/armhf-linux/mtxrun.lua
index a00dc59288c..8825f964657 100644..120000
--- a/Master/bin/armhf-linux/mtxrun.lua
+++ b/Master/bin/armhf-linux/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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+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["%-15s | %s"],
- report_nop=formatters["%-15s |"],
- subreport_yes=formatters["%-15s | %s | %s"],
- subreport_nop=formatters["%-15s | %s |"],
- status_yes=formatters["%-15s : %s\n"],
- status_nop=formatters["%-15s :\n"],
- },
- },
- }
- logs.flush=ignore
- writer=function(s)
- write_nl(s)
- 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]="&amp;",
- [42]="&quot;",
- [47]="&apos;",
- [74]="&lt;",
- [76]="&gt;",
- }
- local predefined_simplified={
- [38]="&",amp="&",
- [42]='"',quot='"',
- [47]="'",apos="'",
- [74]="<",lt="<",
- [76]=">",gt=">",
- }
- local nofprivates=0xF0000
- local privates_u={
- [ [[&]] ]="&amp;",
- [ [["]] ]="&quot;",
- [ [[']] ]="&apos;",
- [ [[<]] ]="&lt;",
- [ [[>]] ]="&gt;",
- }
- 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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"
-local escaped=Cs(normal*(special*normal)^0)
-local normal=(1-S"&")^0
-local special=P("&lt;")/"<"+P("&gt;")/">"+P("&amp;")/"&"
-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
diff --git a/Master/bin/i386-freebsd/mtxrun.lua b/Master/bin/i386-freebsd/mtxrun.lua
index a00dc59288c..8825f964657 100644..120000
--- a/Master/bin/i386-freebsd/mtxrun.lua
+++ b/Master/bin/i386-freebsd/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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+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["%-15s | %s"],
- report_nop=formatters["%-15s |"],
- subreport_yes=formatters["%-15s | %s | %s"],
- subreport_nop=formatters["%-15s | %s |"],
- status_yes=formatters["%-15s : %s\n"],
- status_nop=formatters["%-15s :\n"],
- },
- },
- }
- logs.flush=ignore
- writer=function(s)
- write_nl(s)
- 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]="&amp;",
- [42]="&quot;",
- [47]="&apos;",
- [74]="&lt;",
- [76]="&gt;",
- }
- local predefined_simplified={
- [38]="&",amp="&",
- [42]='"',quot='"',
- [47]="'",apos="'",
- [74]="<",lt="<",
- [76]=">",gt=">",
- }
- local nofprivates=0xF0000
- local privates_u={
- [ [[&]] ]="&amp;",
- [ [["]] ]="&quot;",
- [ [[']] ]="&apos;",
- [ [[<]] ]="&lt;",
- [ [[>]] ]="&gt;",
- }
- 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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"
-local escaped=Cs(normal*(special*normal)^0)
-local normal=(1-S"&")^0
-local special=P("&lt;")/"<"+P("&gt;")/">"+P("&amp;")/"&"
-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
diff --git a/Master/bin/i386-linux/mtxrun.lua b/Master/bin/i386-linux/mtxrun.lua
index a00dc59288c..8825f964657 100644..120000
--- a/Master/bin/i386-linux/mtxrun.lua
+++ b/Master/bin/i386-linux/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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+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["%-15s | %s"],
- report_nop=formatters["%-15s |"],
- subreport_yes=formatters["%-15s | %s | %s"],
- subreport_nop=formatters["%-15s | %s |"],
- status_yes=formatters["%-15s : %s\n"],
- status_nop=formatters["%-15s :\n"],
- },
- },
- }
- logs.flush=ignore
- writer=function(s)
- write_nl(s)
- 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]="&amp;",
- [42]="&quot;",
- [47]="&apos;",
- [74]="&lt;",
- [76]="&gt;",
- }
- local predefined_simplified={
- [38]="&",amp="&",
- [42]='"',quot='"',
- [47]="'",apos="'",
- [74]="<",lt="<",
- [76]=">",gt=">",
- }
- local nofprivates=0xF0000
- local privates_u={
- [ [[&]] ]="&amp;",
- [ [["]] ]="&quot;",
- [ [[']] ]="&apos;",
- [ [[<]] ]="&lt;",
- [ [[>]] ]="&gt;",
- }
- 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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"
-local escaped=Cs(normal*(special*normal)^0)
-local normal=(1-S"&")^0
-local special=P("&lt;")/"<"+P("&gt;")/">"+P("&amp;")/"&"
-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
diff --git a/Master/bin/i386-solaris/mtxrun.lua b/Master/bin/i386-solaris/mtxrun.lua
index a00dc59288c..8825f964657 100644..120000
--- a/Master/bin/i386-solaris/mtxrun.lua
+++ b/Master/bin/i386-solaris/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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+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["%-15s | %s"],
- report_nop=formatters["%-15s |"],
- subreport_yes=formatters["%-15s | %s | %s"],
- subreport_nop=formatters["%-15s | %s |"],
- status_yes=formatters["%-15s : %s\n"],
- status_nop=formatters["%-15s :\n"],
- },
- },
- }
- logs.flush=ignore
- writer=function(s)
- write_nl(s)
- 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]="&amp;",
- [42]="&quot;",
- [47]="&apos;",
- [74]="&lt;",
- [76]="&gt;",
- }
- local predefined_simplified={
- [38]="&",amp="&",
- [42]='"',quot='"',
- [47]="'",apos="'",
- [74]="<",lt="<",
- [76]=">",gt=">",
- }
- local nofprivates=0xF0000
- local privates_u={
- [ [[&]] ]="&amp;",
- [ [["]] ]="&quot;",
- [ [[']] ]="&apos;",
- [ [[<]] ]="&lt;",
- [ [[>]] ]="&gt;",
- }
- 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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"
-local escaped=Cs(normal*(special*normal)^0)
-local normal=(1-S"&")^0
-local special=P("&lt;")/"<"+P("&gt;")/">"+P("&amp;")/"&"
-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
diff --git a/Master/bin/universal-darwin/mtxrun.lua b/Master/bin/universal-darwin/mtxrun.lua
index a00dc59288c..8825f964657 100644..120000
--- a/Master/bin/universal-darwin/mtxrun.lua
+++ b/Master/bin/universal-darwin/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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+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["%-15s | %s"],
- report_nop=formatters["%-15s |"],
- subreport_yes=formatters["%-15s | %s | %s"],
- subreport_nop=formatters["%-15s | %s |"],
- status_yes=formatters["%-15s : %s\n"],
- status_nop=formatters["%-15s :\n"],
- },
- },
- }
- logs.flush=ignore
- writer=function(s)
- write_nl(s)
- 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]="&amp;",
- [42]="&quot;",
- [47]="&apos;",
- [74]="&lt;",
- [76]="&gt;",
- }
- local predefined_simplified={
- [38]="&",amp="&",
- [42]='"',quot='"',
- [47]="'",apos="'",
- [74]="<",lt="<",
- [76]=">",gt=">",
- }
- local nofprivates=0xF0000
- local privates_u={
- [ [[&]] ]="&amp;",
- [ [["]] ]="&quot;",
- [ [[']] ]="&apos;",
- [ [[<]] ]="&lt;",
- [ [[>]] ]="&gt;",
- }
- 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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"
-local escaped=Cs(normal*(special*normal)^0)
-local normal=(1-S"&")^0
-local special=P("&lt;")/"<"+P("&gt;")/">"+P("&amp;")/"&"
-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
diff --git a/Master/bin/windows/mtxrun.lua b/Master/bin/windows/mtxrun.lua
index a00dc59288c..306f84a1ca6 100755
--- a/Master/bin/windows/mtxrun.lua
+++ b/Master/bin/windows/mtxrun.lua
@@ -4298,7 +4298,7 @@ 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
+-- original size: 22637, stripped down to: 10595
if not modules then modules={} end modules ['l-file']={
version=1.001,
@@ -4704,9 +4704,23 @@ function file.withinbase(path)
end
return true
end
-local symlinkattributes=lfs.symlinkattributes
-function lfs.readlink(name)
- return symlinkattributes(name,"target") or nil
+do
+ local symlinktarget=lfs.symlinktarget
+ local symlinkattributes=lfs.symlinkattributes
+ if symlinktarget then
+ function lfs.readlink(name)
+ local target=symlinktarget(name)
+ return name~=target and name or nil
+ end
+ elseif symlinkattributes then
+ function lfs.readlink(name)
+ return symlinkattributes(name,"target") or nil
+ end
+ else
+ function lfs.readlink(name)
+ return nil
+ end
+ end
end
@@ -5122,7 +5136,7 @@ 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
+-- original size: 18893, stripped down to: 11170
if not modules then modules={} end modules ['l-dir']={
version=1.001,
@@ -5586,6 +5600,23 @@ do
return str
end
end
+ function dir.expandlink(dir,report)
+ local curdir=currentdir()
+ local trace=type(report)=="function"
+ if chdir(dir) then
+ local newdir=currentdir()
+ if newdir~=dir and trace then
+ report("following symlink %a to %a",dir,newdir)
+ end
+ chdir(curdir)
+ return newdir
+ else
+ if trace then
+ report("unable to check path %a",dir)
+ end
+ return dir
+ end
+ end
end
file.expandname=dir.expandname
local stack={}
@@ -20734,7 +20765,7 @@ 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
+-- original size: 10636, stripped down to: 7049
if not modules then modules={} end modules ['data-ini']={
version=1.001,
@@ -20745,9 +20776,11 @@ if not modules then modules={} end modules ['data-ini']={
}
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 filedirname,filebasename,filejoin,replacesuffix=file.dirname,file.basename,file.join,file.replacesuffix
local ostype,osname,osuname,ossetenv,osgetenv=os.type,os.name,os.uname,os.setenv,os.getenv
local sortedpairs=table.sortedpairs
+local isfile,currentdir=lfs.isfile,lfs.currentdir
+local expandlink=dir.expandlink
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)
@@ -20797,10 +20830,11 @@ do
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 ownbin=environment.ownbin or os.selfbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luametatex"
local ownpath=environment.ownpath or os.selfdir
- ownbin=file.collapsepath(ownbin)
+ ownbin=file.collapsepath(ownbin)
ownpath=file.collapsepath(ownpath)
+ ownpath=expandlink(ownpath,trace_locating and report_initialization)
if not ownpath or ownpath=="" or ownpath=="unset" then
ownpath=args[-1] or arg[-1]
ownpath=ownpath and filedirname(gsub(ownpath,"\\","/"))
@@ -20814,27 +20848,14 @@ do
end
if not ownpath or ownpath=="" then
if os.binsuffix~="" then
- binary=file.replacesuffix(binary,os.binsuffix)
+ binary=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
+ if isfile(b) then
+ ownpath=expandlink(p,trace_locating and report_initialization)
break
end
end
@@ -26072,8 +26093,8 @@ 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
+-- original bytes : 1035743
+-- stripped bytes : 408144
-- end library merge
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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+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["%-15s | %s"],
- report_nop=formatters["%-15s |"],
- subreport_yes=formatters["%-15s | %s | %s"],
- subreport_nop=formatters["%-15s | %s |"],
- status_yes=formatters["%-15s : %s\n"],
- status_nop=formatters["%-15s :\n"],
- },
- },
- }
- logs.flush=ignore
- writer=function(s)
- write_nl(s)
- 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]="&amp;",
- [42]="&quot;",
- [47]="&apos;",
- [74]="&lt;",
- [76]="&gt;",
- }
- local predefined_simplified={
- [38]="&",amp="&",
- [42]='"',quot='"',
- [47]="'",apos="'",
- [74]="<",lt="<",
- [76]=">",gt=">",
- }
- local nofprivates=0xF0000
- local privates_u={
- [ [[&]] ]="&amp;",
- [ [["]] ]="&quot;",
- [ [[']] ]="&apos;",
- [ [[<]] ]="&lt;",
- [ [[>]] ]="&gt;",
- }
- 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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"
-local escaped=Cs(normal*(special*normal)^0)
-local normal=(1-S"&")^0
-local special=P("&lt;")/"<"+P("&gt;")/">"+P("&amp;")/"&"
-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
diff --git a/Master/bin/x86_64-linux/mtxrun.lua b/Master/bin/x86_64-linux/mtxrun.lua
index a00dc59288c..8825f964657 100644..120000
--- a/Master/bin/x86_64-linux/mtxrun.lua
+++ b/Master/bin/x86_64-linux/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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+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["%-15s | %s"],
- report_nop=formatters["%-15s |"],
- subreport_yes=formatters["%-15s | %s | %s"],
- subreport_nop=formatters["%-15s | %s |"],
- status_yes=formatters["%-15s : %s\n"],
- status_nop=formatters["%-15s :\n"],
- },
- },
- }
- logs.flush=ignore
- writer=function(s)
- write_nl(s)
- 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]="&amp;",
- [42]="&quot;",
- [47]="&apos;",
- [74]="&lt;",
- [76]="&gt;",
- }
- local predefined_simplified={
- [38]="&",amp="&",
- [42]='"',quot='"',
- [47]="'",apos="'",
- [74]="<",lt="<",
- [76]=">",gt=">",
- }
- local nofprivates=0xF0000
- local privates_u={
- [ [[&]] ]="&amp;",
- [ [["]] ]="&quot;",
- [ [[']] ]="&apos;",
- [ [[<]] ]="&lt;",
- [ [[>]] ]="&gt;",
- }
- 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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"
-local escaped=Cs(normal*(special*normal)^0)
-local normal=(1-S"&")^0
-local special=P("&lt;")/"<"+P("&gt;")/">"+P("&amp;")/"&"
-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
diff --git a/Master/bin/x86_64-linuxmusl/mtxrun.lua b/Master/bin/x86_64-linuxmusl/mtxrun.lua
index a00dc59288c..8825f964657 100644..120000
--- a/Master/bin/x86_64-linuxmusl/mtxrun.lua
+++ b/Master/bin/x86_64-linuxmusl/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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+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["%-15s | %s"],
- report_nop=formatters["%-15s |"],
- subreport_yes=formatters["%-15s | %s | %s"],
- subreport_nop=formatters["%-15s | %s |"],
- status_yes=formatters["%-15s : %s\n"],
- status_nop=formatters["%-15s :\n"],
- },
- },
- }
- logs.flush=ignore
- writer=function(s)
- write_nl(s)
- 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]="&amp;",
- [42]="&quot;",
- [47]="&apos;",
- [74]="&lt;",
- [76]="&gt;",
- }
- local predefined_simplified={
- [38]="&",amp="&",
- [42]='"',quot='"',
- [47]="'",apos="'",
- [74]="<",lt="<",
- [76]=">",gt=">",
- }
- local nofprivates=0xF0000
- local privates_u={
- [ [[&]] ]="&amp;",
- [ [["]] ]="&quot;",
- [ [[']] ]="&apos;",
- [ [[<]] ]="&lt;",
- [ [[>]] ]="&gt;",
- }
- 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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"
-local escaped=Cs(normal*(special*normal)^0)
-local normal=(1-S"&")^0
-local special=P("&lt;")/"<"+P("&gt;")/">"+P("&amp;")/"&"
-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
diff --git a/Master/bin/x86_64-solaris/mtxrun.lua b/Master/bin/x86_64-solaris/mtxrun.lua
index a00dc59288c..8825f964657 100644..120000
--- a/Master/bin/x86_64-solaris/mtxrun.lua
+++ b/Master/bin/x86_64-solaris/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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"+P('"')/"&quot;"+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["%-15s | %s"],
- report_nop=formatters["%-15s |"],
- subreport_yes=formatters["%-15s | %s | %s"],
- subreport_nop=formatters["%-15s | %s |"],
- status_yes=formatters["%-15s : %s\n"],
- status_nop=formatters["%-15s :\n"],
- },
- },
- }
- logs.flush=ignore
- writer=function(s)
- write_nl(s)
- 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]="&amp;",
- [42]="&quot;",
- [47]="&apos;",
- [74]="&lt;",
- [76]="&gt;",
- }
- local predefined_simplified={
- [38]="&",amp="&",
- [42]='"',quot='"',
- [47]="'",apos="'",
- [74]="<",lt="<",
- [76]=">",gt=">",
- }
- local nofprivates=0xF0000
- local privates_u={
- [ [[&]] ]="&amp;",
- [ [["]] ]="&quot;",
- [ [[']] ]="&apos;",
- [ [[<]] ]="&lt;",
- [ [[>]] ]="&gt;",
- }
- 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("<")/"&lt;"+P(">")/"&gt;"+P("&")/"&amp;"
-local escaped=Cs(normal*(special*normal)^0)
-local normal=(1-S"&")^0
-local special=P("&lt;")/"<"+P("&gt;")/">"+P("&amp;")/"&"
-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
diff --git a/Master/texmf-dist/doc/context/documents/general/manuals/musings.pdf b/Master/texmf-dist/doc/context/documents/general/manuals/musings.pdf
index 69197240f0b..a02e1b6a1da 100644
--- a/Master/texmf-dist/doc/context/documents/general/manuals/musings.pdf
+++ b/Master/texmf-dist/doc/context/documents/general/manuals/musings.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/context/sources/general/manuals/lowlevel/lowlevel-buffers.tex b/Master/texmf-dist/doc/context/sources/general/manuals/lowlevel/lowlevel-buffers.tex
new file mode 100644
index 00000000000..5c600cd6feb
--- /dev/null
+++ b/Master/texmf-dist/doc/context/sources/general/manuals/lowlevel/lowlevel-buffers.tex
@@ -0,0 +1,506 @@
+% language=us runpath=texruns:manuals/lowlevel
+
+\environment lowlevel-style
+
+\startdocument
+ [title=buffers,
+ color=middlegreen]
+
+\startsectionlevel[title=Preamble]
+
+Buffers are not that low level but it makes sense to discuss them in this
+perspective because it relates to tokenization, internal representation and
+manipulating.
+
+{\em In due time we can describe some more commands and details here. This
+is a start. Feel free to tell me what needs to be explained.}
+
+\stopsectionlevel
+
+\startsectionlevel[title=Encoding]
+
+Normally processing a document starts with reading from file. In the past we were
+talking single bytes that were then maps onto a specific input encoding that
+itself matches the encoding of a font. When you enter an \quote {a} its (normally
+\ASCII) number 97 becomes the index into a font. That same number is also used in
+the hyphenator which is why font encoding and hyphenation are strongly related.
+If in an eight bit \TEX\ engine you need a precomposed \quote {ä} you have to use
+an encoding that has that character in some slot with again matching fonts and
+patterns. The actually used font can have the {\em shapes} in different slots and
+remapping is then done in the backend code using encoding and mapping files. When
+\OPENTYPE\ fonts are used the relationship between characters (input) and glyphs
+(rendering) also depends on the application of font features.
+
+In eight bit environments all this brings a bit of a resource management
+nightmare along with complex installation of new fonts. It also puts strain on
+the macro package, especially when you want to mix different input encodings onto
+different font encodings and thereby pattern encodings in the same document. You
+can compare this with code pages in operating system, but imagine them
+potentially being mixed in one document, which can happen when you mix multiple
+languages where the accumulated number of different characters exceeds 256. You
+end up switching between encodings. One way to deal with it is making special
+characters active and let their meaning differ per situation. That is for
+instance how in \MKII\ we handled \UTF8\ and thereby got around distributing
+multiple pattern files per language as we only needed to encoding them in \UTF\
+and then remap them to the required encoding when loading patterns. A mental
+exercise is wondering how to support \CJK\ scripts in an eight bit \MKII,
+something that actually can be done with some effort.
+
+The good news is that when we moved from \MKII\ to \MKIV\ we went exclusively
+\UTF8\ because that is what the \LUATEX\ engine expects. Upto four bytes are read
+in and translated into one \UNICODE\ character. The internal representation is a
+32 bit integer (four bytes) instead of a single byte. That also means that in the
+transition we got rid of quite some encoding related low level font and pattern
+handling. We still support input encodings (called regimes in \CONTEXT) but I'm
+pretty sure that nowadays no one uses input other than \UTF8. While \CONTEXT\ is
+normally quite upward compatible this is one area where there were fundamental
+changes.
+
+There is still some interpretation going on when reading from file: for instance,
+we need to normalize the \UNICODE\ input, and we feed the engine separate lines
+on demand. Apart from that, some characters like the backslash, dollar sign and
+curly braces have special meaning so for accessing them as characters we have to
+use commands that inject those characters. That didn't change when we went from
+\MKII\ to \MKIV. In practice it's never really a problem unless you find yourself
+in one of the following situations:
+
+\startitemize
+\startitem
+ {\em Example code has to be typeset as|-|is, so braces etc.\ are just that.}
+ This means that we have to change the way characters are interpreted.
+ Typesetting code is needed when you want to document \TEX\ and macros which
+ is why mechanisms for that have to be present right from the start.
+\stopitem
+\startitem
+ {\em Content is collected and used later.} A separation of content and usage
+ later on often helps making a source look cleaner. Examples are \quotation
+ {wrapping a table in a buffer} and \quotation {including that buffer when a
+ table is placed} using the placement macros.
+\stopitem
+\startitem
+ {\em Embedded \METAPOST\ and \LUA\ code.} These languages come with different
+ interpretation of some characters and especially \METAPOST\ code is often
+ stored first and used (processed) later.
+\stopitem
+\startitem
+ {\em The content comes from a different source.} Examples are \XML\ files
+ where angle brackets are special but for instance braces aren't. The data is
+ interpreted as a stream or as a structured tree.
+\stopitem
+\startitem
+ {\em The content is generated.} It can for instance come from \LUA, where
+ bytes (representing \UTF) is just text and no special characters are to be
+ intercepted. Or it can come from a database (using a library).
+\stopitem
+\stopitemize
+
+For these reasons \CONTEXT\ always had ways to store data in ways that makes this
+possible. The details on how that is done might have changed over versions, been
+optimized, extended with additional interfaces and features but given where we
+come from most has been there from the start.
+
+\stopsectionlevel
+
+\startsectionlevel[title=Performance]
+
+When \TEX\ came around, the bottlenecks in running \TEX\ were the processor,
+memory and disks and depending on the way one used it the speed of the console or
+terminal; so, basically the whole system. One could sit there and wait for the
+page counters (\typ {[1] [2] ..} to show up. It was possible to run \TEX\ on a
+personal computer but it was somewhat resource hungry: one needed a decent disk
+(a 10 MB hard disk was huge and with todays phone camera snapshots that sounds
+crazy). One could use memory extenders to get around the 640K limitation (keep in
+mind that the programs and operating systems also took space). This all meant
+that one could not afford to store too many tokens in memory but even using files
+for all kind of (multi|-|pass) trickery was demanding.
+
+When processors became faster and memory plenty the disk became the bottleneck,
+but that changed when \SSD's showed up. Combined with already present file
+caching that had some impact. We are now in a situation that \CPU\ cores don't
+get that much faster (at least not twice as fast per iteration) and with \TEX\
+being a single core byte cruncher we're more or less in a situation where
+performance has to come from efficient programming. That means that, given enough
+memory, in some cases storing in tokens wins over storing in files, but it is no
+rule. In practice there is not much difference so one can even more than
+yesterday choose for the most convenient method. Just assume that the \CONTEXT\
+code, combined with \LUAMETATEX\ will give you what you need with a reasonable
+performance. When in doubt, test with simple test files and it that works out
+well compared to the real code, try to figure out where \quote {mistakes} are
+made. Inefficient \LUA\ and \TEX\ code has way more impact than storing a few
+more tokens or using some files.
+
+\stopsectionlevel
+
+\startsectionlevel[title=Files]
+
+Nearly always files are read once per run. The content (mixed with commands) is
+scanned and macros are expanded and|/|or text is typeset as we go. Internally the
+\LUAMETATEX\ engine is in \quotation {scanning from file}, \quotation {scanning
+from token lists}, or \quotation {scanning from \LUA\ output} mode. The first
+mode is (in principle) the slowest because \UTF\ sequences are converted to
+tokens (numbers) but there is no way around it. The second method is fast because
+we already have these numbers, but we need to take into account where the linked
+list of tokens comes from. If it is converted runtime from for instance file
+input or macro expansion we need to add the involved overhead. But scanning a
+stored macro body is pretty efficient especially when the macro is part of the
+loaded macro package (format file). The third method is comparable with reading
+from file but here we need to add the overhead involved with storing the \LUA\
+output into data structures suitable for \TEX's input mechanism, which can
+involve memory allocation outside the reserved pool of tokens. On modern systems
+that is not really a problem. It is good to keep in mind that when \TEX\ was
+written much attention was paid to optimization and in \LUAMETATEX\ we even went
+a bit further, also because we know what kind of input, processing and output
+we're dealing with.
+
+When reading from file or \LUA\ output we interpret bytes turned \UTF\ numbers
+and that is when catcode regimes kick in: characters are interpreted according to
+the catcode properties: escape character (backslash), curly braces (grouping and
+arguments), dollars (math), etc.\ While with reading from token lists these
+catcodes are already taken care of and we're basically interpreting meanings
+instead of characters. By changing the catcode regime we can for instance typeset
+content verbatim from files and \LUA\ strings but when reading from token lists
+we're sort of frozen. There are tricks to reinterpret the token list but that
+comes with overhead and limitations.
+
+\stopsectionlevel
+
+\startsectionlevel[title=Macros]
+
+A macro can be seen as a named token with a meaning attached. In \LUAMETATEX\
+macros can take up to 15 arguments (six more than regular \TEX) that can be
+separated by so called delimiters. A token has a command property (operator) and
+a value (operand). Because a \UNICODE\ character doesn't need all four bytes of
+an integer and because in the engine numbers, dimensions and pointers are limited
+in size we can store all of these efficiently with the command code. Here the
+body of \type {\foo} is a list of three tokens:
+
+\starttyping
+\def\foo{abc} \foo \foo \foo
+\stoptyping
+
+When the engine fetches a token from a list it will interpret the command and
+when it fetches from file it will create tokens on the fly and then interpret
+those. When a file or list is exhausted the engine pops the stack and continues
+at the previous level. Because macros are already tokenized they are more
+efficient than file input. For more about macros you can consult the low level
+document about them.
+
+The more you use a macro, the more it pays off compared to a file. However don't
+overestimate this, because in the end the typesetting and expanding all kind of
+other involved macros might reduce the file overhead to noise.
+
+\stopsectionlevel
+
+\startsectionlevel[title=Token lists]
+
+A token list is like a macro but is part of the variable (register) system. It
+is just a list (so no arguments) and you can append and prepend to that list.
+
+\starttyping
+\toks123={abc} \the\toks123
+\scratchtoks{abc} \the\scratchtoks
+\stoptyping
+
+Here \type {\scratchtoks} is defined with \type {\newtoks} which creates an
+efficient reference to a list so that, contrary to the first line, no register
+number has to be scanned. There are low level manuals about tokens and registers
+that you can read if you want to know more about this. As with macros the list in
+this example is three tokens long. Contrary to macros there is no macro overhead
+as there is no need to check for arguments. \footnote {In \LUAMETATEX\ a macro
+without arguments is also quite efficient.}
+
+Because they use more or less the same storage method macros and token list
+registers perform the same. The power of registers comes from some additional
+manipulators in \LUATEX\ (and \LUAMETATEX) and the fact that one can control
+expansion with \type {\the}, although that later advantage is compensated with
+extensions to the macro language (like \type {\protected} macro definitions).
+
+\stopsectionlevel
+
+\startsectionlevel[title=Buffers]
+
+Buffers are something specific for \CONTEXT\ and they have always been part of
+this system. A buffer is defined as follows:
+
+\startbuffer
+\startbuffer[one]
+line 1
+line 2
+\stopbuffer
+\stopbuffer
+
+\typebuffer
+
+Among the operations on buffers the next two are used most often:
+
+\starttyping
+\typebuffer[one]
+\getbuffer[one]
+\stoptyping
+
+Scanning a buffer at the \TEX\ end takes a little effort because when we start
+reading the catcodes are ignored and for instance backslashes and curly braces
+are retained. Hardly any interpretation takes place. The same is true for
+spacing, so multiple spaces are not collapsed and newlines stay. The tokenized
+content of a buffer is converted back to a string and that content is then read
+in as a pseudo file when we need it. So, basically buffers are files! In \MKII\
+they actually were files (in the \type {\jobname} name space and suffix \type
+{tmp}), but in \MKIV\ they are stored in and managed by \LUA. That also means
+that you can set them very efficiently at the \LUA\ end:
+
+\starttyping
+\startluacode
+buffers.assign("one",[[
+line 1
+line 2
+]])
+\stopluacode
+\stoptyping
+
+Always keep in mind that buffers eventually are read as files: character by
+character, and at that time the content gets (as with other files) tokenized. A
+buffer name is optional. You can nest buffers, with and without names.
+
+Because \CONTEXT\ is very much about re-use of content and selective processing
+we have an (already old) subsystem for defining named blocks of text (using \type
+{\begin...} and \type {\end...} tagging. These blocks are stored just like
+buffers but selective flushing is part of the concept. Think of coding an
+educational document with explanations, questions, answers and then typesetting
+only the explanations, or the explanation along width some questions. Other
+components can be typeset later so one can make for instance a special book(let)
+with answers that either of not repeats the questions. Here we need features like
+synchronization of numbers so that's why we cannot really use buffers. An
+alternative is to use \XML\ and filter from that.
+
+The \typ {\definebuffer} command defines a new buffer environment. When you set
+buffers in \LUA\ you don't need to define a buffer because likely you don't need
+the \type {\start} and \type {\stop} commands. Instead of \typ {\getbuffer} you
+can also use \typ {\getdefinedbuffer} with defined buffers. In that case the
+\type {before} and \type {after} keys of that specific instance are used.
+
+The \typ {\getinlinebuffer} command, which like the getters takes a list of
+buffer names, ignores leading and trailing spaces. When multiple buffers are
+flushed this way, spacing between buffers is retained.
+
+The most important aspect of buffers is that the content is {\em not} interpreted
+and tokenized: the bytes stay as they are.
+
+\startbuffer
+\definebuffer[MyBuffer]
+
+\startMyBuffer
+\bold{this is
+a buffer}
+\stopMyBuffer
+
+\typeMyBuffer \getMyBuffer
+\stopbuffer
+
+\typebuffer
+
+These commands result in:
+
+\getbuffer
+
+There are not that many parameters that can be set: \type {before}, \type {after}
+and \type {strip} (when set to \type {no} leading and trailing spacing will be
+kept. The \type {\stop...} command, in our example \typ {\stopMyBuffer}, can be
+defined independent to so something after the buffer has be read and stored but
+by default nothing is done.
+
+You can test if a buffer exists with \typ {\doifelsebuffer} (expandable) and \typ
+{\doifelsebufferempty} (unexpandable). A buffer is kept in memory unless it gets
+wiped clean with \typ {resetbuffer}.
+
+\starttyping
+\savebuffer [MyBuffer][temp] % gets name: jobname-temp.tmp
+\savebufferinfile[MyBuffer][temp.log] % gets name: temp.log
+\stoptyping
+
+You can also stepwise fill such a buffer:
+
+\starttyping
+\definesavebuffer[slide]
+
+\startslide
+ \starttext
+\stopslide
+\startslide
+ slide 1
+\stopslide
+text 1 \par
+\startslide
+ slide 2
+\stopslide
+text 2 \par
+\startslide
+ \stoptext
+\stopslide
+\stoptyping
+
+After this you will have a file \type {\jobname-slide.tex} that has the two lines
+wrapped as text. You can set up a \quote {save buffer} to use a different
+filename (with the \type {file} key), a different prefix using \type {prefix} and
+you can set up a \type {directory}. A different name is set with the \type {list}
+key.
+
+You can assign content to a buffer with a somewhat clumsy interface where we use
+the delimiter \type {\endbuffer}. The only restriction is that this delimiter
+cannot be part of the content:
+
+\starttyping
+\setbuffer[name]here comes some text\endbuffer
+\stoptyping
+
+For more details and obscure commands that are used in other commands
+you can peek into the source.
+
+% These are somewhat obscure:
+%
+% \getbufferdata{...}
+% \grabbufferdatadirect % name start stop
+% \grabbufferdata % was: \dostartbuffer
+% \thebuffernumber
+% \thedefinedbuffer
+
+Using buffers in the \CLD\ interface is tricky because of the catcode magick that is
+involved but there are setters and getters:
+
+\starttabulate[|T|T|]
+\BC function \BC arguments \NC \NR
+\ML
+\NC buffers.assign \NC name, content [,catcodes] \NC \NR
+%NC buffers.raw \NC \NC \NR
+\NC buffers.erase \NC name \NC \NR
+\NC buffers.prepend \NC name, content \NC \NR
+\NC buffers.append \NC name, content \NC \NR
+\NC buffers.exists \NC name \NC \NR
+\NC buffers.empty \NC name \NC \NR
+\NC buffers.getcontent \NC name \NC \NR
+\NC buffers.getlines \NC name \NC \NR
+%NC buffers.collectcontent \NC \NC \NR
+%NC buffers.loadcontent \NC \NC \NR
+%NC buffers.get \NC \NC \NR
+%NC buffers.getmkiv \NC \NC \NR
+%NC buffers.gettexbuffer \NC \NC \NR
+%NC buffers.run \NC \NC \NR
+\stoptabulate
+
+There are a few more helpers that are used in other (low level) commands. Their
+functionality might adapt to their usage there. The \typ {context.startbuffer}
+and \typ {context.stopbuffer} are somewhat differently defined than regular
+\CLD\ commands.
+
+\stopsectionlevel
+
+\startsectionlevel[title=Setups]
+
+A setup is basically a macro but is stored and accessed in a namespace separated
+from ordinary macros. One important characteristic is that inside setups newlines
+are ignored.
+
+\startbuffer
+\startsetups MySetupA
+ This is line 1
+ and this is line 2
+\stopsetups
+
+\setup{MySetupA}
+\stopbuffer
+
+\typebuffer {\bf \getbuffer}
+
+A simple way out is to add a comment character preceded by a space. Instead you
+can also use \type {\space}:
+
+\startbuffer
+\startsetups [MySetupB]
+ This is line 1 %
+ and this is line 2\space
+ while here we have line 3
+\stopsetups
+
+\setup[MySetupB]
+\stopbuffer
+
+\typebuffer {\bf \getbuffer}
+
+You can use square brackets instead of space delimited names in definitions and
+also in calling up a (list of) setup(s). The \type {\directsetup} command takes a
+single setup name and is therefore more efficient.
+
+Setups are basically simple macros although there is some magic involved that
+comes from their usage in for instance \XML\ where we pass an argument. That
+means we can do the following:
+
+\startbuffer
+\startsetups MySetupC
+ before#1after
+\stopsetups
+
+\setupwithargument{MySetupC}{ {\em and} }
+\stopbuffer
+
+\typebuffer {\bf \getbuffer}
+
+Because a setup is a macro, the body is a linked list of tokens where each token
+takes 8 bytes of memory, so \type {MySetupC} has 12 tokens that take 96 bytes of
+memory (plus some overhead related to macro management).
+
+\stopsectionlevel
+
+\startsectionlevel[title=\XML]
+
+Discussing \XML\ is outside the scope of this document but it is worth mentioning
+that once an \XML\ tree is read is, the content is stored in strings and can be
+filtered into \TEX, where it is interpreted as if coming from files (in this case
+\LUA\ strings). If needed the content can be interpreted as \TEX\ input.
+
+\stopsectionlevel
+
+\startsectionlevel[title=\LUA]
+
+As mentioned already, output from \LUA\ is stored and when a \LUA\ call finishes
+it ends up on the so called input stack. Every time the engine needs a token it
+will fetch from the input stack and the top of the stack can represent a file,
+token list or \LUA\ output. Interpreting bytes from files or \LUA\ strings
+results in tokens. As a side note: \LUA\ output can also be already tokenized,
+because we can actually write tokens and nodes from \LUA, but that's more an
+implementation detail that makes the \LUA\ input stack entries a bit more
+complex. It is normally not something users will do when they use \LUA\ in their
+documents.
+
+\stopsectionlevel
+
+\startsectionlevel[title=Protection]
+
+When you define macros there is the danger of overloading some defined by the
+system. Best use CamelCase so that you stay away from clashes. You can enable
+some checking:
+
+\starttyping
+\enabledirectives[overloadmode=warning]
+\stoptyping
+
+or when you want to quit on a clash:
+
+\starttyping
+\enabledirectives[overloadmode=error]
+\stoptyping
+
+When these trackers are enabled you can get around the check with:
+
+\starttyping
+\pushoverloadmode
+ ...
+\popoverloadmode
+\stoptyping
+
+But delay that till you're sure that redefining is okay.
+
+\stopsectionlevel
+
+% efficiency
+
+\stopdocument
+
diff --git a/Master/texmf-dist/doc/context/sources/general/manuals/luametatex/luametatex.tex b/Master/texmf-dist/doc/context/sources/general/manuals/luametatex/luametatex.tex
index bb20761bc7a..f845fed1711 100644
--- a/Master/texmf-dist/doc/context/sources/general/manuals/luametatex/luametatex.tex
+++ b/Master/texmf-dist/doc/context/sources/general/manuals/luametatex/luametatex.tex
@@ -105,6 +105,13 @@
% means that 43 pages per seconds is now the new normal but that might of course
% become less again as we evolve.
+% End Feburari 2023 I observed 8.2 seconds for 360 pages and making a format needed
+% 1.9 seconds instead if the usual 2.1 but that can be a side effect of the terminal
+% because the amount of output which is sensitive for refresh delays set. The new
+% target is nwo 50 pages per second for this manual but on this laptop that is
+% unlikely to happen any time soon. With tabulateusesize and tabulatesparseskips
+% experimends enabled we needed 8.1 second and 44.3 pps.
+
% \enableexperiments [tabulateusesize]
% \enableexperiments [tabulatesparseskips]
diff --git a/Master/texmf-dist/doc/context/sources/general/manuals/musings/musings-toocomplex.tex b/Master/texmf-dist/doc/context/sources/general/manuals/musings/musings-toocomplex.tex
index 103dd19069b..f12f15c1eee 100644
--- a/Master/texmf-dist/doc/context/sources/general/manuals/musings/musings-toocomplex.tex
+++ b/Master/texmf-dist/doc/context/sources/general/manuals/musings/musings-toocomplex.tex
@@ -387,3 +387,5 @@ is not needed any more by then.
\stopsection
\stopchapter
+
+\stopcomponent
diff --git a/Master/texmf-dist/doc/context/sources/general/manuals/musings/musings.tex b/Master/texmf-dist/doc/context/sources/general/manuals/musings/musings.tex
index 13bf4f4ef93..bccab890a38 100644
--- a/Master/texmf-dist/doc/context/sources/general/manuals/musings/musings.tex
+++ b/Master/texmf-dist/doc/context/sources/general/manuals/musings/musings.tex
@@ -28,6 +28,7 @@
% \component musings-whytex-again
\component musings-dontusetex
\component musings-speed
+ \component musings-texlive
\stopbodymatter
\stopproduct
diff --git a/Master/texmf-dist/metapost/context/base/common/mp-remapped-boxes.mp b/Master/texmf-dist/metapost/context/base/common/mp-remapped-boxes.mp
new file mode 100644
index 00000000000..f9cb4a5bb1c
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/common/mp-remapped-boxes.mp
@@ -0,0 +1 @@
+scantokens("input mp-xbox.mp" & (if metapostversion > 2 : "xl" else : "iv" fi)) ;
diff --git a/Master/texmf-dist/metapost/context/base/common/mp-remapped-hatching.mp b/Master/texmf-dist/metapost/context/base/common/mp-remapped-hatching.mp
new file mode 100644
index 00000000000..ae63b676ea0
--- /dev/null
+++ b/Master/texmf-dist/metapost/context/base/common/mp-remapped-hatching.mp
@@ -0,0 +1,10 @@
+% This is placeholder for Bogluslaw Jackowski's hatching.mp file which can be found in
+% the public domain and dates from 2000. It provides:
+%
+% draw hatched (fullcircle scaled 10cm) (45, 4, 1) withcolor "red" ;
+%
+% interim hatch_match := 1;
+%
+% This macro is not in mp-tool so this is a placeholder. The hatching macro doesn't fit
+% into metafun because it assume withcolor to behave in a certain way. Also, we use more
+% efficient path constructor.
diff --git a/Master/texmf-dist/scripts/context/lua/mtxrun.lua b/Master/texmf-dist/scripts/context/lua/mtxrun.lua
index a00dc59288c..306f84a1ca6 100755
--- a/Master/texmf-dist/scripts/context/lua/mtxrun.lua
+++ b/Master/texmf-dist/scripts/context/lua/mtxrun.lua
@@ -4298,7 +4298,7 @@ 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
+-- original size: 22637, stripped down to: 10595
if not modules then modules={} end modules ['l-file']={
version=1.001,
@@ -4704,9 +4704,23 @@ function file.withinbase(path)
end
return true
end
-local symlinkattributes=lfs.symlinkattributes
-function lfs.readlink(name)
- return symlinkattributes(name,"target") or nil
+do
+ local symlinktarget=lfs.symlinktarget
+ local symlinkattributes=lfs.symlinkattributes
+ if symlinktarget then
+ function lfs.readlink(name)
+ local target=symlinktarget(name)
+ return name~=target and name or nil
+ end
+ elseif symlinkattributes then
+ function lfs.readlink(name)
+ return symlinkattributes(name,"target") or nil
+ end
+ else
+ function lfs.readlink(name)
+ return nil
+ end
+ end
end
@@ -5122,7 +5136,7 @@ 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
+-- original size: 18893, stripped down to: 11170
if not modules then modules={} end modules ['l-dir']={
version=1.001,
@@ -5586,6 +5600,23 @@ do
return str
end
end
+ function dir.expandlink(dir,report)
+ local curdir=currentdir()
+ local trace=type(report)=="function"
+ if chdir(dir) then
+ local newdir=currentdir()
+ if newdir~=dir and trace then
+ report("following symlink %a to %a",dir,newdir)
+ end
+ chdir(curdir)
+ return newdir
+ else
+ if trace then
+ report("unable to check path %a",dir)
+ end
+ return dir
+ end
+ end
end
file.expandname=dir.expandname
local stack={}
@@ -20734,7 +20765,7 @@ 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
+-- original size: 10636, stripped down to: 7049
if not modules then modules={} end modules ['data-ini']={
version=1.001,
@@ -20745,9 +20776,11 @@ if not modules then modules={} end modules ['data-ini']={
}
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 filedirname,filebasename,filejoin,replacesuffix=file.dirname,file.basename,file.join,file.replacesuffix
local ostype,osname,osuname,ossetenv,osgetenv=os.type,os.name,os.uname,os.setenv,os.getenv
local sortedpairs=table.sortedpairs
+local isfile,currentdir=lfs.isfile,lfs.currentdir
+local expandlink=dir.expandlink
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)
@@ -20797,10 +20830,11 @@ do
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 ownbin=environment.ownbin or os.selfbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luametatex"
local ownpath=environment.ownpath or os.selfdir
- ownbin=file.collapsepath(ownbin)
+ ownbin=file.collapsepath(ownbin)
ownpath=file.collapsepath(ownpath)
+ ownpath=expandlink(ownpath,trace_locating and report_initialization)
if not ownpath or ownpath=="" or ownpath=="unset" then
ownpath=args[-1] or arg[-1]
ownpath=ownpath and filedirname(gsub(ownpath,"\\","/"))
@@ -20814,27 +20848,14 @@ do
end
if not ownpath or ownpath=="" then
if os.binsuffix~="" then
- binary=file.replacesuffix(binary,os.binsuffix)
+ binary=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
+ if isfile(b) then
+ ownpath=expandlink(p,trace_locating and report_initialization)
break
end
end
@@ -26072,8 +26093,8 @@ 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
+-- original bytes : 1035743
+-- stripped bytes : 408144
-- end library merge
diff --git a/Master/texmf-dist/tex/context/base/mkiv/char-def.lua b/Master/texmf-dist/tex/context/base/mkiv/char-def.lua
index 1aea51318fa..5e9d7d05a8b 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/char-def.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/char-def.lua
@@ -64034,6 +64034,8 @@ characters.data={
combining=0xE6,
description="COMBINING LEFT ARROW ABOVE",
direction="nsm",
+ mathclass="topaccent",
+ mathstretch="h",
linebreak="cm",
unicodeslot=0x20D6,
},
@@ -64248,6 +64250,8 @@ characters.data={
description="COMBINING LEFT ARROW BELOW",
direction="nsm",
linebreak="cm",
+ mathclass="bottomaccent",
+ mathstretch="h",
unicodeslot=0x20EE,
},
[0x20EF]={
@@ -64256,6 +64260,8 @@ characters.data={
description="COMBINING RIGHT ARROW BELOW",
direction="nsm",
linebreak="cm",
+ mathclass="bottomaccent",
+ mathstretch="h",
unicodeslot=0x20EF,
},
[0x20F0]={
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua
index 0bdc60379d4..9b5e705ca78 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/cldf-ini.lua
@@ -99,7 +99,7 @@ local tonut = node.direct.todirect
local tonode = node.direct.tonode
local newtoken = token.new
-local createtoken = token.create
+----- createtoken = token.create
local istoken = token.istoken or token.is_token
local setluatoken = token.setlua or token.set_lua
diff --git a/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv b/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv
index 2ff5bba1fbd..22e4d4baeac 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv
+++ b/Master/texmf-dist/tex/context/base/mkiv/cont-new.mkiv
@@ -13,7 +13,7 @@
% \normalend % uncomment this to get the real base runtime
-\newcontextversion{2023.02.23 21:26}
+\newcontextversion{2023.03.10 12:15}
%D This file is loaded at runtime, thereby providing an excellent place for hacks,
%D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/Master/texmf-dist/tex/context/base/mkiv/context.mkiv b/Master/texmf-dist/tex/context/base/mkiv/context.mkiv
index 7a7e2e8d5c3..1c9effa6a4c 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/context.mkiv
+++ b/Master/texmf-dist/tex/context/base/mkiv/context.mkiv
@@ -49,7 +49,7 @@
%D {YYYY.MM.DD HH:MM} format.
\edef\contextformat {\jobname}
-\edef\contextversion{2023.02.23 21:26}
+\edef\contextversion{2023.03.10 12:15}
%D Kind of special:
diff --git a/Master/texmf-dist/tex/context/base/mkiv/data-ini.lua b/Master/texmf-dist/tex/context/base/mkiv/data-ini.lua
index 6cf5669b3e7..57a800d8321 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/data-ini.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/data-ini.lua
@@ -8,9 +8,11 @@ if not modules then modules = { } end modules ['data-ini'] = {
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 filedirname, filebasename, filejoin, replacesuffix = file.dirname, file.basename, file.join, file.replacesuffix
local ostype, osname, osuname, ossetenv, osgetenv = os.type, os.name, os.uname, os.setenv, os.getenv
local sortedpairs = table.sortedpairs
+local isfile, currentdir = lfs.isfile, lfs.currentdir
+local expandlink = dir.expandlink
local P, S, R, C, Cs, Cc, lpegmatch = lpeg.P, lpeg.S, lpeg.R, lpeg.C, lpeg.Cs, lpeg.Cc, lpeg.match
@@ -103,12 +105,20 @@ do
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 ownbin = environment.ownbin or os.selfbin or args[-2] or arg[-2] or args[-1] or arg[-1] or arg[0] or "luametatex"
local ownpath = environment.ownpath or os.selfdir
- ownbin = file.collapsepath(ownbin)
+ ownbin = file.collapsepath(ownbin) -- This one an actually also contain the path!
ownpath = file.collapsepath(ownpath)
+ -- We need to follow the symlink on osx - texlive. This only works luametatex and
+ -- lmtx so we might as wel forget about luatex/mkiv there. The regular context
+ -- installation doesn't have this link issue. I tried several variants but in the
+ -- end the chdir variants was most reliable. Everything else is ugly. (Experimtal
+ -- code is in data-osx.lua).
+
+ ownpath = expandlink(ownpath,trace_locating and report_initialization)
+
if not ownpath or ownpath == "" or ownpath == "unset" then
ownpath = args[-1] or arg[-1]
ownpath = ownpath and filedirname(gsub(ownpath,"\\","/"))
@@ -122,31 +132,14 @@ do
end
if not ownpath or ownpath == "" then
if os.binsuffix ~= "" then
- binary = file.replacesuffix(binary,os.binsuffix)
+ binary = 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
- -- we assume that after changing to the path the currentdir function
- -- resolves to the real location and use this side effect here; this
- -- trick is needed because on the mac installations use symlinks in the
- -- path instead of real locations
- local olddir = lfs.currentdir()
- if lfs.chdir(p) then
- local pp = lfs.currentdir()
- if 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
+ if isfile(b) then
+ ownpath = expandlink(p,trace_locating and report_initialization)
break
end
end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/grph-con.lua b/Master/texmf-dist/tex/context/base/mkiv/grph-con.lua
index fdae2223bda..fcc8c931d27 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/grph-con.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/grph-con.lua
@@ -312,7 +312,7 @@ do -- png | jpg | profiles
-- [[convert %?colorspace: -colorspace "%colorspace%" ?%]]
local rgbprofile = "srgb_v4_icc_preference.icc" -- srgb.icc
- local cmykprofile = "isocoated_v2_300_eci.icc" -- isocoated_v2_eci.icc
+ local cmykprofile = "isocoated_v2_eci.icc" -- isocoated_v2_300_eci.icc
directives.register("graphics.conversion.rgbprofile", function(v) rgbprofile = type(v) == "string" and v or rgbprofile end)
directives.register("graphics.conversion.cmykprofile",function(v) cmykprofile = type(v) == "string" and v or cmykprofile end)
@@ -320,9 +320,14 @@ do -- png | jpg | profiles
local jpgconverters = converters.jpg
local pngconverters = converters.png
+ local findfile = resolvers.findfile
+
local function profiles()
if not isfile(rgbprofile) then
- local found = resolvers.findfile(rgbprofile)
+ local found = findfile(rgbprofile)
+ if not found or found == "" then
+ found = findfile("colo-imp-"..rgbprofile)
+ end
if found and found ~= "" then
rgbprofile = found
else
@@ -331,6 +336,9 @@ do -- png | jpg | profiles
end
if not isfile(cmykprofile) then
local found = resolvers.findfile(cmykprofile)
+ if not found or found == "" then
+ found = findfile("colo-imp-"..cmykprofile)
+ end
if found and found ~= "" then
cmykprofile = found
else
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-dir.lua b/Master/texmf-dist/tex/context/base/mkiv/l-dir.lua
index ac8e2f4e8e1..3e24e4e2a12 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/l-dir.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-dir.lua
@@ -197,7 +197,7 @@ local function collectpattern(path,patt,recurse,result)
if not find(path,"/$") then
path = path .. '/'
end
- for name in scanner, first do -- cna be optimized
+ for name in scanner, first do -- can be optimized
if name == "." then
-- skip
elseif name == ".." then
@@ -596,6 +596,27 @@ do
end
+ -- This go there anc check works okay in tricky situation as we encounter
+ -- on osx, where tex installations use rather complex chains of links.
+
+ function dir.expandlink(dir,report)
+ local curdir = currentdir()
+ local trace = type(report) == "function"
+ if chdir(dir) then
+ local newdir = currentdir()
+ if newdir ~= dir and trace then
+ report("following symlink %a to %a",dir,newdir)
+ end
+ chdir(curdir)
+ return newdir
+ else
+ if trace then
+ report("unable to check path %a",dir)
+ end
+ return dir
+ end
+ end
+
end
file.expandname = dir.expandname -- for convenience
diff --git a/Master/texmf-dist/tex/context/base/mkiv/l-file.lua b/Master/texmf-dist/tex/context/base/mkiv/l-file.lua
index 9f8fd654833..70f8188dc15 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/l-file.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/l-file.lua
@@ -741,8 +741,24 @@ end
-- not used in context but was in luatex once:
-local symlinkattributes = lfs.symlinkattributes
+do
+
+ local symlinktarget = lfs.symlinktarget -- luametatex (always returns string)
+ local symlinkattributes = lfs.symlinkattributes -- luatex (can return nil)
+
+ if symlinktarget then
+ function lfs.readlink(name)
+ local target = symlinktarget(name)
+ return name ~= target and name or nil
+ end
+ elseif symlinkattributes then
+ function lfs.readlink(name)
+ return symlinkattributes(name,"target") or nil
+ end
+ else
+ function lfs.readlink(name)
+ return nil
+ end
+ end
-function lfs.readlink(name)
- return symlinkattributes(name,"target") or nil
end
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua b/Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua
index 1b278926ec3..cb8053fb69c 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/lang-txt.lua
@@ -25,7 +25,7 @@ if not modules then modules = { } end modules ['lang-txt'] = {
-- bg Bulgarian Vladislav Hinkin, Aleš Ďurčanský (2019)
-- ca Catalan ...; additions Javier Gambin Monzo + Samuel Conca Coles (2022)
-- cn Chinese Wang Lei, ...
--- cs Czech Tom Hudec, Petr Sojka, Richard Gabriel
+-- cs Czech Tom Hudec, Petr Sojka, Richard Gabriel; additions Tomáš Hála (2022)
-- da Danish Arne Jorgensen
-- de German Tobias Burnus, ...
-- en English Hans Hagen, ...
@@ -52,7 +52,7 @@ if not modules then modules = { } end modules ['lang-txt'] = {
-- pt Portuguese Pedro F. M. Mendonça
-- ro Romanian Dan Seracu, ...
-- ru Russian Olga Briginets, Alexander Bokovoy, Victor Figurnov, ...
--- sk Slovak Tomáš Hála (2012)
+-- sk Slovak Tomáš Hála (2012, 2022)
-- sl Slovenian Mojca Miklavec
-- sr Serbian Ivan Pešić (2020)
-- sr-latn Serbian Ivan Pešić (2020)
@@ -84,6 +84,7 @@ data.labels={
["be"]="У",
["bg"]="в",
["ca"]="En",
+ ["cs"]={ "In", "V" },
["de"]="In",
["en"]="In",
["eo"]="En",
@@ -92,6 +93,7 @@ data.labels={
["fr"]="Dans",
["hy"]="Մեջ",
["mk"]="во",
+ ["sk"]={ "In", "V" },
["sr"]="У",
["sr-latn"]="U",
},
@@ -101,6 +103,7 @@ data.labels={
["be"]="Нумар",
["bg"]="номер",
["ca"]="Nombre",
+ ["cs"]="Číslo",
["de"]="Nummer",
["en"]="Number",
["eo"]="Nombro",
@@ -110,6 +113,7 @@ data.labels={
["hy"]="Համար",
["mk"]="Број",
["nl"]="Nummer",
+ ["sk"]="Číslo",
["sr"]="Број",
["sr-latn"]="Broj",
},
@@ -119,6 +123,7 @@ data.labels={
["be"]="Гук",
["bg"]="обем",
["ca"]="Volum",
+ ["cs"]="Svazek",
["de"]="Band",
["en"]="Volume",
["eo"]="Volumo",
@@ -129,6 +134,7 @@ data.labels={
["hy"]="Ծավալ",
["mk"]="Том",
["nl"]="Deel",
+ ["sk"]="Zväzok",
["sr"]="Том",
["sr-latn"]="Tom",
},
@@ -138,6 +144,7 @@ data.labels={
["be"]="i",
["bg"]="a",
["ca"]="i",
+ ["cs"]="a",
["de"]="und",
["en"]="and",
["eo"]="kaj",
@@ -149,6 +156,7 @@ data.labels={
["it"]="e",
["mk"]="и",
["nl"]="en",
+ ["sk"]="a",
["sr"]="и",
["sr-latn"]="i",
},
@@ -158,6 +166,7 @@ data.labels={
["be"]="Выданне",
["bg"]="издание",
["ca"]="Edició",
+ ["cs"]="Vydání",
["de"]="Auflage",
["en"]="edition",
["eo"]="eldono",
@@ -170,6 +179,7 @@ data.labels={
["it"]="edizione",
["mk"]="издание",
["nl"]="editie",
+ ["sk"]="Vydanie",
["sr"]="издање",
["sr-latn"]="izdanje",
},
@@ -179,6 +189,7 @@ data.labels={
["be"]="Рэдактар",
["bg"]="редактор",
["ca"]="Editor",
+ ["cs"]={ "Editor", "Editorka" },
["de"]="Herausgeber",
["en"]="editor",
["eo"]="eldonisto",
@@ -189,6 +200,7 @@ data.labels={
["hy"]="խմբագիր",
["it"]="a cura di",
["mk"]="уредник",
+ ["sk"]={ "Editor", "Editorka" },
["sr"]="уредник",
["sr-latn"]="urednik",
},
@@ -198,6 +210,7 @@ data.labels={
["be"]="Рэдактары",
["bg"]="редактори",
["ca"]="Editors",
+ ["cs"]="Editoři",
["de"]="Herausgeber",
["en"]="editors",
["eo"]="eldonistoj",
@@ -207,15 +220,29 @@ data.labels={
["hy"]="խմբագիրներ",
["it"]="a cura di",
["mk"]="уредници",
+ ["sk"]="Editori",
["sr"]="уредници",
["sr-latn"]="urednici",
},
},
+ ["editors:f"]={
+ ["labels"]={
+ ["cs"]="Editorky",
+ ["sk"]="Editorky",
+ },
+ },
+ ["editors:m"]={
+ ["labels"]={
+ ["cs"]="Editoři",
+ ["sk"]="Editori",
+ },
+ },
["in"]={
["labels"]={
["be"]="у",
["bg"]="в",
["ca"]="en",
+ ["cs"]="v",
["de"]="in",
["en"]="in",
["eo"]="en",
@@ -224,6 +251,7 @@ data.labels={
["fr"]="dans",
["hy"]="մեջ",
["mk"]="во",
+ ["sk"]="v",
["sr"]="у",
["sr-latn"]="u",
},
@@ -233,6 +261,7 @@ data.labels={
["be"]="Дыпломная работа",
["bg"]="дипломна работа",
["ca"]="Tesi de maestria",
+ ["cs"]="Diplomová práce",
["de"]="Masterarbeit",
["en"]="Master's thesis",
["eo"]="Magistreca disertaĵo",
@@ -245,6 +274,7 @@ data.labels={
["it"]="Tesi di laurea",
["mk"]="Магистерска дисертација",
["nl"]="Masterproef",
+ ["sk"]="Diplomová práca",
["sr"]="Мастер дисертација",
["sr-latn"]="Master disertacija",
},
@@ -254,6 +284,7 @@ data.labels={
["be"]="нумар",
["bg"]="номер",
["ca"]="nombre",
+ ["cs"]="číslo",
["de"]="Nummer",
["en"]="number",
["eo"]="numero",
@@ -264,6 +295,7 @@ data.labels={
["hy"]="համար",
["mk"]="број",
["nl"]="nummer",
+ ["sk"]="číslo",
["sr"]="број",
["sr-latn"]="broj",
},
@@ -273,6 +305,7 @@ data.labels={
["be"]="з",
["bg"]="на",
["ca"]="de",
+ ["cs"]="z",
["de"]="von",
["en"]="of",
["eo"]="de",
@@ -281,6 +314,7 @@ data.labels={
["hy"]="-ից",
["mk"]="од",
["nl"]="van",
+ ["sk"]="z",
["sr"]="од",
["sr-latn"]="od",
},
@@ -288,6 +322,7 @@ data.labels={
["others"]={
["labels"]={
["ca"]="et al.",
+ ["cs"]={ "a~kol.", "et al."},
["de"]="et al.",
["en"]="et al.",
["eo"]="aliaj",
@@ -296,6 +331,7 @@ data.labels={
["fr"]="et al.",
["hy"]="եւ այլն",
["mk"]="и др.",
+ ["sk"]={ "a~kol.", "et al."},
["sr"]="и др.",
["sr-latn"]="i dr.",
},
@@ -304,6 +340,7 @@ data.labels={
["labels"]={
["be"]="стар.",
["ca"]="p.",
+ ["cs"]="s.",
["de"]="S.",
["en"]="p.",
["eo"]="p.",
@@ -313,6 +350,7 @@ data.labels={
["fr"]="p.",
["hy"]="էջ",
["mk"]="стр.",
+ ["sk"]="s.",
["sr"]="стр.",
["sr-latn"]="str.",
},
@@ -322,6 +360,7 @@ data.labels={
["be"]="старонка",
["bg"]="страни",
["ca"]="pagines",
+ ["cs"]="strany",
["de"]="Seiten",
["en"]="pages",
["eo"]="paĝoj",
@@ -333,6 +372,7 @@ data.labels={
["hy"]="էջեր",
["mk"]="страници",
["nl"]="paginas",
+ ["sk"]="strany",
["sr"]="страницa",
["sr-latn"]="stranica",
},
@@ -342,6 +382,7 @@ data.labels={
["be"]="патэнт",
["bg"]="патент",
["ca"]="Patent",
+ ["cs"]="Patent",
["de"]="Patent",
["en"]="Patent",
["eo"]="Patento",
@@ -353,6 +394,7 @@ data.labels={
["it"]="Brevetto",
["mk"]="Патент",
["nl"]="Octrooi",
+ ["sk"]="Patent",
["sr"]="Патент",
["sr-latn"]="Patent",
},
@@ -362,6 +404,7 @@ data.labels={
["be"]="Доктарская дысертацыя",
["bg"]="дисертачна работа",
["ca"]="Tesi doctoral",
+ ["cs"]="Disertační práce",
["de"]="Dissertation",
["en"]="PhD thesis",
["eo"]="Doktoriĝa disertaĵo",
@@ -373,6 +416,7 @@ data.labels={
["it"]="Tesi di dottorato",
["mk"]="Докторска дисертација",
["nl"]="Proefschrift",
+ ["sk"]="Dizertačná práca",
["sr"]="Докторска дисертација",
["sr-latn"]="Doktorska disertacija",
},
@@ -380,6 +424,7 @@ data.labels={
["pp"]={
["labels"]={
["ca"]="pp",
+ ["cs"]="s.",
["de"]="S.",
["en"]="pp.",
["eo"]="pp.",
@@ -388,6 +433,7 @@ data.labels={
["fa"]="صص",
["hy"]="էջ",
["mk"]="стр.",
+ ["sk"]="s.",
["sr"]="стр.",
["sr-latn"]="str.",
},
@@ -397,6 +443,7 @@ data.labels={
["be"]="Тэхнічны даклад",
["bg"]="технически доклад",
["ca"]="Report tecnic",
+ ["cs"]="Technická zpráva",
["de"]="Technischer Bericht",
["en"]="Technical report",
["eo"]="Teknika raporto",
@@ -409,6 +456,7 @@ data.labels={
["it"]="Relazione tecnica",
["mk"]="Технички извештај",
["nl"]="Technisch rapport",
+ ["sk"]="Technická zpráva",
["sr"]="Технички извештај",
["sr-latn"]="Tehnički izveštaj",
},
@@ -418,6 +466,7 @@ data.labels={
["be"]="гучнасць",
["bg"]="обем",
["ca"]="volum",
+ ["cs"]="svazek",
["de"]="Band",
["en"]="volume",
["eo"]="volumo",
@@ -428,6 +477,7 @@ data.labels={
["hy"]="ծավալ",
["mk"]="том",
["nl"]="deel",
+ ["sk"]="zväzok",
["sr"]="том",
["sr-latn"]="tom",
},
@@ -437,6 +487,7 @@ data.labels={
["be"]="з",
["bg"]="със",
["ca"]="en",
+ ["cs"]="s",
["de"]="mit",
["en"]="with",
["eo"]="kun",
@@ -448,6 +499,7 @@ data.labels={
["it"]="con",
["mk"]="со",
["nl"]="met",
+ ["sk"]="s",
["sr"]="са",
["sr-latn"]="sa",
},
@@ -500,7 +552,7 @@ data.labels={
["sr-latn"]="arccosh",
},
},
- ["arcctg"]={
+ ["arccot"]={
["labels"]={
["ca"]="arc cot",
["cs"]="arccotg",
@@ -666,7 +718,7 @@ data.labels={
["sr-latn"]="cosec",
},
},
- ["ctg"]={
+--[[ ["ctg"]={
["labels"]={
["ca"]="cot",
["cs"]="cotg",
@@ -682,6 +734,7 @@ data.labels={
["sr-latn"]="ctg",
},
},
+--]]
["deg"]={
["labels"]={
["ca"]="gr",
@@ -712,9 +765,11 @@ data.labels={
["diff"]={
["labels"]={
["ca"]="d",
+ ["cs"]="d",
["en"]="d",
["eo"]="dif",
- ["hy"]="diff",
+ ["hy"]="d",
+ ["sk"]="d",
},
},
["dim"]={
@@ -903,7 +958,7 @@ data.labels={
},
["ln"]={
["labels"]={
- ["ca"]="En",
+ ["ca"]="ln",
["cs"]="ln",
["en"]="ln",
["eo"]="ln",
@@ -947,14 +1002,16 @@ data.labels={
["median"]={
["labels"]={
["ca"]="mitjana",
- ["cs"]="\\tilde",
+ -- ["cs"]="\\tilde", -- won't work
+ ["cs"]="Me",
["en"]="median",
["eo"]="mediano",
["es"]="Mediana",
["fi"]="mediaani",
["fr"]="médiane",
["hy"]="միջին",
- ["sk"]="\\tilde",
+ -- ["sk"]="\\tilde", -- won't work
+ ["sk"]="Med",
["sr"]="median",
["sr-latn"]="median",
},
@@ -1501,6 +1558,7 @@ data.labels={
["labels"]={
["bg"]="ден",
["ca"]="dia",
+ ["cs"]="den", -- {"den", "dne" }
["de"]="Tag",
["en"]="day",
["eo"]="tago",
@@ -1512,6 +1570,7 @@ data.labels={
["kr"]="일",
["mk"]="ден",
["nl"]="dag",
+ ["sk"]="deň", -- {"deň", "dňa" }
["sr"]="дан",
["sr-latn"]="dan",
},
@@ -1756,25 +1815,30 @@ data.labels={
},
["following:plural"]={
["labels"]={
+ ["cs"]="násl.",
["de"]="ff.",
["en"]="ff.",
["eo"]="sekvv",
["fr"]=hairspace .. "sqq",
["hy"]="ff.",
+ ["sk"]="násl.",
},
},
["following:singular"]={
["labels"]={
+ ["cs"]="násl.",
["de"]="f.",
["en"]="f.",
["eo"]="sekv",
["fr"]=hairspace .. "sq",
["hy"]="f.",
+ ["sk"]="násl.",
},
},
["followingpage"]={
["labels"]={
["ca"]="en la seguent pagina",
+ ["cs"]="na následující straně",
["de"]="auf einer Folgeseite",
["en"]="on a following page",
["eo"]="je sekvanta paĝo",
@@ -1786,6 +1850,7 @@ data.labels={
["hy"]="Հաջորդ էջում",
["mk"]="на следната страница",
["nl"]="op een volgende bladzijde",
+ ["sk"]="na nasledujúcej strane",
["sr"]="на следећој страници",
["sr-latn"]="na sledećoj stranici",
},
@@ -2979,6 +3044,7 @@ data.labels={
["precedingpage"]={
["labels"]={
["ca"]="en una pagina anterior",
+ ["cs"]="na předchozí straně",
["de"]="oben", -- "auf der vorigen Seite" ok, but not "auf einer vorigen Seite"
["en"]="on a preceding page",
["eo"]="sur antaŭa paĝo",
@@ -2990,6 +3056,7 @@ data.labels={
["hy"]="նախորդ էջ",
["mk"]="на претходната страница",
["nl"]="op een voorgaande bladzijde",
+ ["sk"]="na predchádzajúcej strane",
["sr"]="на претходној страници",
["sr-latn"]="na prethodnoj stranici",
},
@@ -3678,6 +3745,7 @@ data.labels={
["labels"]={
["bg"]="година",
["ca"]="any",
+ ["cs"]="rok",
["de"]="Jahr",
["en"]="year",
["eo"]="jaro",
@@ -3690,6 +3758,7 @@ data.labels={
["kr"]="년",
["mk"]="година",
["nl"]="jaar",
+ ["sk"]="rok",
["sr"]="година",
["sr-latn"]="godina",
},
@@ -3704,7 +3773,7 @@ data.labels={
["bg"]="Съкращения",
["ca"]="Abreviacions",
["cn"]="缩略语",
- ["cs"]="Zkratky",
+ ["cs"]="Seznam zkratek", --"Zkratky"
["da"]="Forkortelser",
["de"]="Abkürzungen",
["en"]="Abbreviations",
@@ -3731,7 +3800,7 @@ data.labels={
["pt"]="Abreviaturas",
["ro"]="Abrevieri",
["ru"]="Список сокращений",
- ["sk"]="Skratky",
+ ["sk"]="Zoznam skratiek", -- "Skratky"
["sl"]="Kratice",
["sr"]="Скраћенице",
["sr-latn"]="Skraćenice",
@@ -3914,7 +3983,7 @@ data.labels={
["pt"]="Índice",
["ro"]="Index",
["ru"]="Алфавитный указатель",
- ["sk"]="Zoznam",
+ ["sk"]="Register",
["sl"]="Stvarno kazalo",
["sr"]="Индекс појмова",
["sr-latn"]="Indeks pojmova",
@@ -4161,6 +4230,8 @@ functions.acosh = functions.arccosh
functions.atanh = functions.arctanh
functions.tg = functions.tan
+functions.ctg = functions.cot
functions.arctg = functions.arctan
+functions.arcctg = functions.arccot
functions.arctgh = functions.arctanh
diff --git a/Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua b/Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua
index 6702ed506b9..ce7cbd5c310 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/lpdf-nod.lua
@@ -69,18 +69,22 @@ end
-- We only define this for testing as we don't need it:
-local lateliteralnode = register(new_node(whatsit_code, lateliteralwhatsit_code))
-
-function nodepool.lateliteral(mode,str)
- local t = copy_node(lateliteralnode)
- if str then
- setfield(t,"mode",literals[mode] and mode or pageliteral_code)
- setdata(t,str)
- else
- setfield(t,"mode",pageliteral_code)
- setdata(t,mode)
+if lateliteralwhatsit_code then
+
+ local lateliteralnode = register(new_node(whatsit_code, lateliteralwhatsit_code))
+
+ function nodepool.lateliteral(mode,str)
+ local t = copy_node(lateliteralnode)
+ if str then
+ setfield(t,"mode",literals[mode] and mode or pageliteral_code)
+ setdata(t,str)
+ else
+ setfield(t,"mode",pageliteral_code)
+ setdata(t,mode)
+ end
+ return t
end
- return t
+
end
local savenode = register(new_node(whatsit_code, savewhatsit_code))
diff --git a/Master/texmf-dist/tex/context/base/mkiv/mult-def.lua b/Master/texmf-dist/tex/context/base/mkiv/mult-def.lua
index 4ac85137108..b0aba96d694 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/mult-def.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/mult-def.lua
@@ -8660,6 +8660,10 @@ return {
["fr"]="entrees",
["nl"]="ingangen",
},
+ ["extradata"]={
+ ["en"]="extradata",
+ ["nl"]="extragegevens",
+ },
["processors"]={
["en"]="processors",
},
@@ -12319,6 +12323,10 @@ return {
["pe"]="روش‌متن",
["ro"]="textmethod",
},
+ ["lasttextseparator"]={
+ ["en"]="lasttextseparator",
+ ["nl"]="laatstetekstscheider",
+ },
["textseparator"]={
["cs"]="oddelovactextu",
["de"]="textseparator",
diff --git a/Master/texmf-dist/tex/context/base/mkiv/page-flt.lua b/Master/texmf-dist/tex/context/base/mkiv/page-flt.lua
index 7c222084035..8df38b406aa 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/page-flt.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/page-flt.lua
@@ -51,6 +51,8 @@ local function initialize()
return {
text = { },
page = { },
+ top = { },
+ bottom = { },
leftpage = { },
rightpage = { },
somewhere = { },
@@ -317,11 +319,13 @@ function floats.checkedpagefloat(packed)
end
function floats.nofstacked(which)
- return #stacks[which or default] or 0
+ local s = stacks[which or default]
+ return s and #s or 0
end
function floats.hasstacked(which)
- return (#stacks[which or default] or 0) > 0
+ local s = stacks[which or default]
+ return (s and #s or 0) > 0
end
-- todo: check for digits !
diff --git a/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf b/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf
index 5e4560e8410..c073662c578 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf
+++ b/Master/texmf-dist/tex/context/base/mkiv/status-files.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf b/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf
index c403fd6c524..5bced88ec0d 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf
+++ b/Master/texmf-dist/tex/context/base/mkiv/status-lua.pdf
Binary files differ
diff --git a/Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv b/Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv
index 52b3b3ad972..520a9e3111c 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv
+++ b/Master/texmf-dist/tex/context/base/mkiv/strc-def.mkiv
@@ -27,6 +27,8 @@
% \part{second} \chapter{gamma} \section{a} \section{b} \subsection{x} \subsection{y} \chapter{delta}
% \stoptext
+\defineseparatorset [\v!none] [] []
+
\defineseparatorset [\s!default] [] [.]
\defineconversionset [\s!default] [] [numbers]
\defineresetset [\s!default] [] [1] % each level
diff --git a/Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua b/Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua
index 98d2f66c08d..c5137794181 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/toks-scn.lua
@@ -347,6 +347,11 @@ local presets = {
["2 arguments"] = { "argument", "argument" },
["3 arguments"] = { "argument", "argument", "argument" },
["4 arguments"] = { "argument", "argument", "argument", "argument" },
+
+ ["1 integer"] = { "integer" },
+ ["2 integers"] = { "integer", "integer" },
+ ["3 integers"] = { "integer", "integer", "integer" },
+ ["4 integers"] = { "integer", "integer", "integer", "integer" },
}
tokens.presets = presets
diff --git a/Master/texmf-dist/tex/context/base/mkiv/typo-prc.lua b/Master/texmf-dist/tex/context/base/mkiv/typo-prc.lua
index 2704149db99..72b159e9cac 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/typo-prc.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/typo-prc.lua
@@ -15,7 +15,7 @@ local implement = interfaces.implement
local formatters = string.formatters
-typesetters.processors = typesetters.processors or { }
+typesetters.processors = typesetters.processors or { }
local processors = typesetters.processors
local trace_processors = false
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-client.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-client.lua
index a2763feac4c..2f72ef13824 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-client.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-client.lua
@@ -23,7 +23,6 @@ local preparetemplate = helpers.preparetemplate
local splitdata = helpers.splitdata
local replacetemplate = utilities.templates.replace
local serialize = sql.serialize
-local deserialize = sql.deserialize
local getserver = sql.getserver
local osclock = os.gettimeofday
@@ -264,6 +263,7 @@ end
local wraptemplate = [[
local converters = utilities.sql.converters
local deserialize = utilities.sql.deserialize
+local fromjson = utilities.sql.fromjson
local tostring = tostring
local tonumber = tonumber
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-ffi.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-ffi.lua
index cbfd7bcf5f6..9cf306df775 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-ffi.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-ffi.lua
@@ -169,7 +169,6 @@ local validspecification = helpers.validspecification
local querysplitter = helpers.querysplitter
local dataprepared = helpers.preparetemplate
local serialize = sql.serialize
-local deserialize = sql.deserialize
local mysql_open_session = mysql.mysql_init
@@ -564,6 +563,7 @@ local ffi_tostring = ffi.string
local converters = utilities.sql.converters
local deserialize = utilities.sql.deserialize
+local fromjson = utilities.sql.fromjson
local tostring = tostring
local tonumber = tonumber
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua
index dbbeb32cc46..e43afc2f375 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-library.lua
@@ -79,7 +79,6 @@ local validspecification = helpers.validspecification
local querysplitter = helpers.querysplitter
local dataprepared = helpers.preparetemplate
local serialize = sql.serialize
-local deserialize = sql.deserialize
local formatters = string.formatters
local initialize = mysql.mysql
@@ -251,6 +250,7 @@ end
local wraptemplate = [[
local converters = utilities.sql.converters
local deserialize = utilities.sql.deserialize
+local fromjson = utilities.sql.fromjson
local tostring = tostring
local tonumber = tonumber
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-sqlite.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-sqlite.lua
index 781c92c896d..a82244bade3 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-sqlite.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql-imp-sqlite.lua
@@ -234,6 +234,7 @@ end
local wraptemplate = [[
local converters = utilities.sql.converters
local deserialize = utilities.sql.deserialize
+local fromjson = utilities.sql.fromjson
local tostring = tostring
local tonumber = tonumber
diff --git a/Master/texmf-dist/tex/context/base/mkiv/util-sql.lua b/Master/texmf-dist/tex/context/base/mkiv/util-sql.lua
index 55c4961f7da..f729acfb945 100644
--- a/Master/texmf-dist/tex/context/base/mkiv/util-sql.lua
+++ b/Master/texmf-dist/tex/context/base/mkiv/util-sql.lua
@@ -87,12 +87,22 @@ sql.helpers = helpers
local serialize = table.fastserialize
local deserialize = table.deserialize
+local json = require("util-jsn")
+local tojson = json.tostring
+local fromjson = json.tolua
+
sql.serialize = serialize
sql.deserialize = deserialize
helpers.serialize = serialize -- bonus
helpers.deserialize = deserialize -- bonus
+sql.tojson = tojson
+sql.fromjson = fromjson
+
+helpers.tojson = tojson -- bonus
+helpers.fromjson = fromjson -- bonus
+
local defaults = { __index =
{
resultfile = "result.dat",
@@ -174,6 +184,8 @@ local function makeconverter(entries,celltemplate,wraptemplate)
assignments[#assignments+1] = format("[%q] = tab_%s[%s],",name,#converters,value)
elseif kind == "deserialize" then
assignments[#assignments+1] = format("[%q] = deserialize(%s),",name,value)
+ elseif kind == "fromjson" then
+ assignments[#assignments+1] = format("[%q] = fromjson(%s),",name,value)
elseif kind == "key" then
-- hashed instead of indexed
key = value
@@ -392,13 +404,25 @@ function sql.usedatabase(presets,datatable)
name = name or "data"
for i=1,#records do
local record = records[i]
- local data = record[name]
+ local data = record[name]
if data then
record[name] = deserialize(data)
end
end
end
end
+ local function unpackjson(records,name)
+ if records then
+ name = name or "json"
+ for i=1,#records do
+ local record = records[i]
+ local data = record[name]
+ if data then
+ record[name] = fromjson(data)
+ end
+ end
+ end
+ end
return {
usedmethod = usedmethod,
presets = preset,
@@ -408,7 +432,10 @@ function sql.usedatabase(presets,datatable)
execute = execute,
serialize = serialize,
deserialize = deserialize,
+ tojson = tojson,
+ fromjson = fromjson,
unpackdata = unpackdata,
+ unpackjson = unpackjson,
}
else
report_state("missing name in usedatabase specification")
diff --git a/Master/texmf-dist/tex/context/base/mkxl/anch-pos.lmt b/Master/texmf-dist/tex/context/base/mkxl/anch-pos.lmt
index 79a0da09744..07a6ecf33f9 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/anch-pos.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/anch-pos.lmt
@@ -2280,13 +2280,13 @@ implement {
implement {
name = "markregionbox",
- arguments = { "integer", "integer" },
+ arguments = "2 integers",
actions = markregionbox
}
implement {
name = "setregionbox",
- arguments = { "integer", "integer" },
+ arguments = "2 integers",
actions = setregionbox
}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/char-tex.lmt b/Master/texmf-dist/tex/context/base/mkxl/char-tex.lmt
index 02d9a6cb62c..0e0297381bf 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/char-tex.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/char-tex.lmt
@@ -583,7 +583,7 @@ implement {
implement {
name = "uchar",
- arguments = { "integer", "integer" },
+ arguments = "2 integers",
actions = function(h,l)
context(utfchar(h*256+l))
end
diff --git a/Master/texmf-dist/tex/context/base/mkxl/cont-new.mkxl b/Master/texmf-dist/tex/context/base/mkxl/cont-new.mkxl
index 129e3d54531..ef7c4071708 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/cont-new.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/cont-new.mkxl
@@ -13,7 +13,7 @@
% \normalend % uncomment this to get the real base runtime
-\newcontextversion{2023.02.23 21:26}
+\newcontextversion{2023.03.10 12:15}
%D This file is loaded at runtime, thereby providing an excellent place for hacks,
%D patches, extensions and new features. There can be local overloads in cont-loc
diff --git a/Master/texmf-dist/tex/context/base/mkxl/context.mkxl b/Master/texmf-dist/tex/context/base/mkxl/context.mkxl
index 809fbc307d3..8f9513510e9 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/context.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/context.mkxl
@@ -29,7 +29,7 @@
%D {YYYY.MM.DD HH:MM} format.
\immutable\edef\contextformat {\jobname}
-\immutable\edef\contextversion{2023.02.23 21:26}
+\immutable\edef\contextversion{2023.03.10 12:15}
%overloadmode 1 % check frozen / warning
%overloadmode 2 % check frozen / error
@@ -702,7 +702,6 @@
% c:/data/develop/context/sources/file-ini.lua
% c:/data/develop/context/sources/file-lib.lua
% c:/data/develop/context/sources/file-res.lua
-% c:/data/develop/context/sources/file-syn.lua
% c:/data/develop/context/sources/font-afk.lua
% c:/data/develop/context/sources/font-agl.lua
@@ -782,7 +781,7 @@
% c:/data/develop/context/sources/meta-pdf.lua
% c:/data/develop/context/sources/meta-tex.lua
-% c:/data/develop/context/sources/mult-aux.lua
+% c:/data/develop/context/sources/mult-aux.lua % move some to s-system-*
% c:/data/develop/context/sources/mult-fmt.lua
% c:/data/develop/context/sources/page-cst.lua
@@ -822,17 +821,13 @@
% c:/data/develop/context/sources/strc-blk.lua
% c:/data/develop/context/sources/strc-con.lua
% c:/data/develop/context/sources/strc-doc.lua
-% c:/data/develop/context/sources/strc-flt.lua
% c:/data/develop/context/sources/strc-ini.lua
-% c:/data/develop/context/sources/strc-itm.lua
% c:/data/develop/context/sources/strc-lev.lua
-% c:/data/develop/context/sources/strc-mat.lua
% c:/data/develop/context/sources/strc-num.lua
% c:/data/develop/context/sources/strc-pag.lua
-% c:/data/develop/context/sources/strc-syn.lua
% c:/data/develop/context/sources/strc-usr.lua
-% c:/data/develop/context/sources/syst-cmp.lua
+% c:/data/develop/context/sources/syst-cmp.lua -- nothing
% c:/data/develop/context/sources/syst-con.lua
% c:/data/develop/context/sources/trac-ctx.lua
@@ -842,10 +837,5 @@
% c:/data/develop/context/sources/typo-cln.lua -- wrong name for what it does
% c:/data/develop/context/sources/typo-dha.lua
-% c:/data/develop/context/sources/typo-fkr.lua
-% c:/data/develop/context/sources/typo-inj.lua
-% c:/data/develop/context/sources/typo-man.lua
-% c:/data/develop/context/sources/typo-prc.lua
-% c:/data/develop/context/sources/typo-rep.lua
% c:/data/develop/context/sources/unic-ini.lua
diff --git a/Master/texmf-dist/tex/context/base/mkxl/core-con.mkxl b/Master/texmf-dist/tex/context/base/mkxl/core-con.mkxl
index f9aa1a69d18..bf607c34d07 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/core-con.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/core-con.mkxl
@@ -86,14 +86,14 @@
\permanent\def\Alphabeticnumerals#1{\clf_Alphabetic\numexpr#1\relax{}}
\permanent\def\thainumerals #1{\clf_alphabetic\numexpr#1\relax{thai}}
-\permanent\def\devanagarinumerals#1{\clf_decimals\numexpr#1\relax{devanagari}}
-\permanent\def\malayalamnumerals #1{\clf_decimals\numexpr#1\relax{malayalam}}
-\permanent\def\tamilnumerals #1{\clf_decimals\numexpr#1\relax{tamil}}
-\permanent\def\kannadanumerals #1{\clf_decimals\numexpr#1\relax{kannada}}
-\permanent\def\telugunumerals #1{\clf_decimals\numexpr#1\relax{telugu}}
-\permanent\def\bengalinumerals #1{\clf_decimals\numexpr#1\relax{bengali}}
-\permanent\def\gujaratinumerals #1{\clf_decimals\numexpr#1\relax{gujarati}}
-\permanent\def\gurmurkhinumerals #1{\clf_decimals\numexpr#1\relax{gurmurkhi}}
+\permanent\def\devanagarinumerals#1{\clf_decimals \numexpr#1\relax{devanagari}}
+\permanent\def\malayalamnumerals #1{\clf_decimals \numexpr#1\relax{malayalam}}
+\permanent\def\tamilnumerals #1{\clf_decimals \numexpr#1\relax{tamil}}
+\permanent\def\kannadanumerals #1{\clf_decimals \numexpr#1\relax{kannada}}
+\permanent\def\telugunumerals #1{\clf_decimals \numexpr#1\relax{telugu}}
+\permanent\def\bengalinumerals #1{\clf_decimals \numexpr#1\relax{bengali}}
+\permanent\def\gujaratinumerals #1{\clf_decimals \numexpr#1\relax{gujarati}}
+\permanent\def\gurmurkhinumerals #1{\clf_decimals \numexpr#1\relax{gurmurkhi}}
\permanent\def\tibetannumerals #1{\clf_alphabetic\numexpr#1\relax{tibetan}}
\permanent\def\greeknumerals #1{\clf_alphabetic\numexpr#1\relax{greek}}
\permanent\def\Greeknumerals #1{\clf_Alphabetic\numexpr#1\relax{greek}}
@@ -102,6 +102,9 @@
\permanent\def\arabicdecimals #1{\clf_decimals \numexpr#1\relax{arabic}}
\permanent\def\persiandecimals #1{\clf_decimals \numexpr#1\relax{persian}}
+\permanent\def\mathgreeknumerals #1{\im{\clf_alphabetic\numexpr#1\relax{greek}}}
+\permanent\def\mathGreeknumerals #1{\im{\clf_Alphabetic\numexpr#1\relax{greek}}}
+
\aliased \let\arabicexnumerals \persiannumerals
\permanent\def\koreannumerals #1{\clf_alphabetic\numexpr#1\relax{korean}}
@@ -711,6 +714,9 @@
\defineconversion [\v!greek] [\greeknumerals]
\defineconversion [\v!Greek] [\Greeknumerals]
+\defineconversion [\s!math:\v!greek] [\mathgreeknumerals]
+\defineconversion [\s!math:\v!Greek] [\mathGreeknumerals]
+
\defineconversion [g] [\greeknumerals]
\defineconversion [G] [\Greeknumerals]
@@ -745,6 +751,9 @@
\defineconversion [arabicdecimals] [\arabicdecimals]
\defineconversion [persiandecimals] [\persiandecimals]
+\defineconversion [mathgreeknumerals] [\mathgreeknumerals]
+\defineconversion [mathGreeknumerals] [\mathGreeknumerals]
+
\defineconversion [koreannumerals] [\koreannumerals]
\defineconversion [koreanparennumerals] [\koreanparenthesisnumerals] % for old times sake (for a while)
\defineconversion [koreanparenthesisnumerals]
diff --git a/Master/texmf-dist/tex/context/base/mkxl/core-uti.lmt b/Master/texmf-dist/tex/context/base/mkxl/core-uti.lmt
index 48737d7f62f..966428b36b1 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/core-uti.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/core-uti.lmt
@@ -20,7 +20,7 @@ saves much runtime but at the cost of more memory usage.</p>
local math = math
local next, type, tostring, tonumber, setmetatable, load = next, type, tostring, tonumber, setmetatable, load
local format, match = string.format, string.match
-local concat = table.concat
+local concat, sortedkeys = table.concat, table.sortedkeys
local definetable = utilities.tables.definetable
local accesstable = utilities.tables.accesstable
@@ -282,7 +282,7 @@ directives.register("job.pack",function(v) job.pack = v end)
local savedfiles = { }
local loadedfiles = { } -- for now only timers
-local otherfiles = { } -- for now only timers
+local othercache = { }
function job.save(filename) -- we could return a table but it can get pretty large
statistics.starttiming(savedfiles)
@@ -381,18 +381,12 @@ function job.load(filename)
statistics.stoptiming(loadedfiles)
end
-local othercache = { }
-
-function job.loadother(filename,cache)
- local unpacked = false
+function job.loadother(filename)
statistics.starttiming(loadedfiles)
filename = file.addsuffix(filename,"tuc")
- if cache then
- unpacked = othercache[filename]
- end
+ local unpacked = othercache[filename]
if not unpacked then
-- so we can register the same name twice(in loading order)
- otherfiles[#otherfiles+1] = file.nameonly(filename)
local utilitydata = load(filename)
if utilitydata then
local jobpacker = utilitydata.job.packed
@@ -408,34 +402,12 @@ function job.loadother(filename,cache)
end
end
unpacked.job.packed = nil -- nicer in inspecting
- if cache then
- othercache[filename] = unpacked
- end
- --
- local lists = utilitydata.structures.lists.collected or { }
- local sections = utilitydata.structures.sections.collected or { }
- local pages = utilitydata.structures.pages .collected or { }
- for i=1,#lists do
- local entry = lists[i]
- local references = entry.references
- if references then
- local section = references.section
- local realpage = references.realpage
- -- maybe entry.* instead:
- references.sectiondata = section and sections[section]
- references.pagedata = realpage and pages[realpage]
- -- get rid of these, maybe even crash as these are bogus
- -- references.internal = nil
- -- references.realpage = nil
- -- references.section = nil
- references.x = nil
- references.y = nil
- end
- end
- --
- -- also do the references here
+ othercache[filename] = unpacked
+ --
+ structures.lists .integrate(utilitydata)
+ structures.registers .integrate(utilitydata)
+ structures.references.integrate(utilitydata)
--
- structures.references.registerfromlist(lists,derived,pages,sections)
end
end
statistics.stoptiming(loadedfiles)
@@ -447,17 +419,19 @@ statistics.register("startup time", function()
end)
statistics.register("jobdata time",function()
+ local elapsedsave = statistics.elapsedtime(savedfiles)
+ local elapsedload = statistics.elapsedtime(loadedfiles)
if enabled then
- if #otherfiles > 0 then
- return format("%s seconds saving, %s seconds loading, other files: %s",statistics.elapsedtime(savedfiles),statistics.elapsedtime(loadedfiles),concat(otherfiles," "))
+ if next(othercache) then
+ return format("%s seconds saving, %s seconds loading, other files: %s",elapsedsave,elapsedload,concat(sortedkeys(othercache), ", "))
else
- return format("%s seconds saving, %s seconds loading",statistics.elapsedtime(savedfiles),statistics.elapsedtime(loadedfiles))
+ return format("%s seconds saving, %s seconds loading",elapsedsave,elapsedload)
end
else
- if #otherfiles > 0 then
- return format("nothing saved, %s seconds loading, other files: %s",statistics.elapsedtime(loadedfiles),concat(otherfiles," "))
+ if next(othercache) then
+ return format("nothing saved, %s seconds loading, other files: %s",elapsedload,concat(sortedkeys(othercache), ", "))
else
- return format("nothing saved, %s seconds loading",statistics.elapsedtime(loadedfiles))
+ return format("nothing saved, %s seconds loading",elapsedload)
end
end
end)
diff --git a/Master/texmf-dist/tex/context/base/mkxl/file-syn.lmt b/Master/texmf-dist/tex/context/base/mkxl/file-syn.lmt
new file mode 100644
index 00000000000..1c3010b43bc
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/file-syn.lmt
@@ -0,0 +1,79 @@
+if not modules then modules = { } end modules ['file-syn'] = {
+ version = 1.001,
+ comment = "companion to file-syn.mkvi",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+
+environment.filesynonyms = environment.filesynonyms or { }
+local filesynonyms = environment.filesynonyms
+
+local settings_to_array = utilities.parsers.settings_to_array
+local findfile = resolvers.findfile
+
+local implement = interfaces.implement
+
+storage.register("environment/filesynonyms", filesynonyms, "environment.filesynonyms")
+
+local function truefilename(name)
+ local realname = filesynonyms[name] or name
+ if realname ~= name then
+ return truefilename(realname)
+ else
+ return realname
+ end
+end
+
+environment.truefilename = truefilename
+
+function environment.definefilesynonym(name,realname)
+ if name and realname then
+ local names = settings_to_array(name)
+ for i=1,#names do
+ local name = names[i]
+ local synonym = filesynonyms[name]
+ if synonym then
+ interfaces.showmessage("files",1,{ name or "?", realname or "?", synonym or "?" })
+ end
+ filesynonyms[name] = realname
+ end
+ end
+end
+
+function environment.definefilefallback(name,alternatives)
+ if name and alternatives then
+ local names = settings_to_array(alternatives)
+ for i=1,#names do
+ local realname = findfile(names[i])
+ if realname ~= "" then
+ filesynonyms[name] = realname
+ break
+ end
+ end
+ end
+end
+
+implement {
+ name = "truefilename",
+ public = true,
+ actions = { truefilename, context },
+ arguments = "argument"
+}
+
+implement {
+ name = "definefilesynonym",
+ public = true,
+ protected = true,
+ actions = environment.definefilesynonym,
+ arguments = "2 optionals"
+}
+
+implement {
+ name = "definefilefallback",
+ public = true,
+ protected = true,
+ actions = environment,definefilefallback,
+ arguments = "2 optionals"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/file-syn.mklx b/Master/texmf-dist/tex/context/base/mkxl/file-syn.mklx
index 25f36f742fc..3bbf15c4c17 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/file-syn.mklx
+++ b/Master/texmf-dist/tex/context/base/mkxl/file-syn.mklx
@@ -15,7 +15,7 @@
\unprotect
-\registerctxluafile{file-syn}{}
+\registerctxluafile{file-syn}{autosuffix}
%D \macros
%D {definefilesynonym,definefilefallback}
@@ -42,8 +42,8 @@
%D \usemodules[pictex,chemie,unit]
%D \stoptyping
-\permanent\tolerant\def\definefilesynonym [#name]#spacer[#realname]{\clf_definefilesynonym {#name}{#realname}}
-\permanent\tolerant\def\definefilefallback[#name]#spacer[#alternatives]{\clf_definefilefallback{#name}{#alternatives}}
+% \permanent\tolerant\def\definefilesynonym [#name]#spacer[#realname]{\clf_definefilesynonym {#name}{#realname}}
+% \permanent\tolerant\def\definefilefallback[#name]#spacer[#alternatives]{\clf_definefilefallback{#name}{#alternatives}}
%D \macros
%D {truefilename}
@@ -56,6 +56,6 @@
%D
%D The implementation shows that nesting is supported.
-\permanent\def\truefilename#1{\clf_truefilename{#1}}
+% \permanent\def\truefilename#1{\clf_truefilename{#1}}
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/base/mkxl/lang-lab.lmt b/Master/texmf-dist/tex/context/base/mkxl/lang-lab.lmt
index b82721b7656..f1f9b358087 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/lang-lab.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/lang-lab.lmt
@@ -91,29 +91,28 @@ function labels.define(class,name,prefixed)
report_labels("defining label set %a",name)
for tag, data in next, list do
tag = variables[tag] or tag
- if data.hidden then
- -- skip
- elseif prefixed then
- local first, second = lpegmatch(splitter,tag)
- if second then
- if rawget(variables,first) then
- if rawget(variables,second) then
- definelanguagelabels(data,class,f_key_key(first,second),tag)
+ if not data.hidden then
+ local key = tag
+ if prefixed then
+ local first, second = lpegmatch(splitter,tag)
+ if second then
+ if rawget(variables,first) then
+ if rawget(variables,second) then
+ key = f_key_key(first,second)
+ else
+ key = f_key_raw(first,second)
+ end
+ elseif rawget(variables,second) then
+ key = f_raw_key(first,second)
else
- definelanguagelabels(data,class,f_key_raw(first,second),tag)
+ key = f_raw_raw(first,second)
end
- elseif rawget(variables,second) then
- definelanguagelabels(data,class,f_raw_key(first,second),tag)
- else
- definelanguagelabels(data,class,f_raw_raw(first,second),tag)
+ elseif rawget(variables,rawtag) then
+ key = f_key(tag)
end
- elseif rawget(variables,rawtag) then
- definelanguagelabels(data,class,f_key(tag),tag)
- else
- definelanguagelabels(data,class,tag,tag)
end
- else
- definelanguagelabels(data,class,tag,tag)
+ -- report_labels("defining class %a, key %a, tag %a",class,key,tag)
+ definelanguagelabels(data,class,key,tag)
end
end
else
diff --git a/Master/texmf-dist/tex/context/base/mkxl/lang-lab.mkxl b/Master/texmf-dist/tex/context/base/mkxl/lang-lab.mkxl
index a1d758f0979..6152d287412 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/lang-lab.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/lang-lab.mkxl
@@ -50,10 +50,10 @@
%D These commands accept all kind of inputs:
%D
%D \starttyping
-%D \setuplabeltext [language] [labellabel=text]
-%D \setuplabeltext [language] [labellabel=text,labellabel=text,...]
-%D \setuplabeltext [labellabel=text]
-%D \setuplabeltext [labellabel=text,labellabel=text,...]
+%D \setuplabeltext [language] [label1=text]
+%D \setuplabeltext [language] [label1=text,label2=text,...]
+%D \setuplabeltext [label1=text]
+%D \setuplabeltext [label1=text,label2=text,...]
%D \stoptyping
%D
%D The last two cases concern the current language.
@@ -141,7 +141,7 @@
\else
\enforced\let\thetextprefix\dummytextprefix
\fi}%
- \permanent \instance\protected\def#6##1{#3{##1}\expandafter\firstoftwoarguments \thetextprefix}% \flushleftlabelclass
+ \permanent\instance\protected\def#6##1{#3{##1}\expandafter\firstoftwoarguments \thetextprefix}% \flushleftlabelclass
\permanent\instance\protected\def#7##1{#3{##1}\expandafter\secondoftwoarguments \thetextprefix}% \flushrightlabelclass
\permanent\instance\protected\def#8##1{#3{##1}\expandafter\lang_labels_flush_both\thetextprefix}% \flushbothlabelclass #2
\permanent\instance\protected\def#9##1{#3{##1}\expandafter\firstoftwoarguments \thetextprefix}% \flushleftlabelclass
diff --git a/Master/texmf-dist/tex/context/base/mkxl/libs-imp-sqlite.lmt b/Master/texmf-dist/tex/context/base/mkxl/libs-imp-sqlite.lmt
index 5d38986f347..0d1f77d176b 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/libs-imp-sqlite.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/libs-imp-sqlite.lmt
@@ -100,7 +100,7 @@ local function execute(specification)
end
end
else
- db = open_db(filename)
+ db = sqlite_open(filename)
preamble = f_preamble(filename,base,base)
end
if not db then
@@ -156,6 +156,7 @@ end
local wraptemplate = [[
local converters = utilities.sql.converters
local deserialize = utilities.sql.deserialize
+local fromjson = utilities.sql.fromjson
local tostring = tostring
local tonumber = tonumber
diff --git a/Master/texmf-dist/tex/context/base/mkxl/lpdf-lmt.lmt b/Master/texmf-dist/tex/context/base/mkxl/lpdf-lmt.lmt
index 1d47c162071..f443632b82b 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/lpdf-lmt.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/lpdf-lmt.lmt
@@ -2130,6 +2130,20 @@ local finalize do
local f_group = formatters["Gp%d"]
local f_image = formatters["Im%d"]
+ local function checkedbox(mediabox,otherbox,what)
+ if otherbox and #mediabox == 4 and #otherbox == 4 then
+ local done = false
+ if otherbox[1] < mediabox[1] then done = true ; otherbox[1] = mediabox[1] end
+ if otherbox[2] < mediabox[2] then done = true ; otherbox[2] = mediabox[2] end
+ if otherbox[3] > mediabox[3] then done = true ; otherbox[3] = mediabox[3] end
+ if otherbox[4] > mediabox[4] then done = true ; otherbox[4] = mediabox[4] end
+ if done then
+ report("limiting %a to 'MediaBox'",what)
+ end
+ end
+ return otherbox
+ end
+
finalize = function(driver,details)
if not details then
@@ -2226,9 +2240,9 @@ else
-- Indirect objects don't work in all viewers.
- if TrimBox then pageattributes.TrimBox = pdfsharedobject(TrimBox ) end
- if CropBox then pageattributes.CropBox = pdfsharedobject(CropBox ) end
- if BleedBox then pageattributes.BleedBox = pdfsharedobject(BleedBox) end
+ if TrimBox then pageattributes.TrimBox = pdfsharedobject(checkedbox(bbox,TrimBox,"TrimBox")) end
+ if CropBox then pageattributes.CropBox = pdfsharedobject(checkedbox(bbox,CropBox,"CropBox")) end
+ if BleedBox then pageattributes.BleedBox = pdfsharedobject(checkedbox(bbox,BleedBox,"BleedBox")) end
end
diff --git a/Master/texmf-dist/tex/context/base/mkxl/lpdf-mis.lmt b/Master/texmf-dist/tex/context/base/mkxl/lpdf-mis.lmt
index a3a78c49ff8..577dbed5a96 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/lpdf-mis.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/lpdf-mis.lmt
@@ -415,14 +415,7 @@ local function documentspecification()
addtocatalog("Lang", pdfstring(tokens.getters.macro("currentmainlanguage")))
end
--- temp hack: the mediabox is not under our control and has a precision of 5 digits
-
-local factor = number.dimenfactors.bp
-local f_value = formatters["%.6N"]
-
-local function boxvalue(n) -- we could share them
- return pdfverbose(f_value(factor * n))
-end
+local bpfactor = number.dimenfactors.bp
local function pagespecification()
local canvas = getcanvas()
@@ -439,10 +432,10 @@ local function pagespecification()
local function extrabox(WhatBox,offset,always)
if offset ~= 0 or always then
addtopageattributes(WhatBox, pdfarray {
- boxvalue(llx + offset),
- boxvalue(lly + offset),
- boxvalue(urx - offset),
- boxvalue(ury - offset),
+ (llx + offset) * bpfactor,
+ (lly + offset) * bpfactor,
+ (urx - offset) * bpfactor,
+ (ury - offset) * bpfactor,
})
end
end
diff --git a/Master/texmf-dist/tex/context/base/mkxl/math-acc.mklx b/Master/texmf-dist/tex/context/base/mkxl/math-acc.mklx
index 6e25c413fe3..49f97ae9c1c 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/math-acc.mklx
+++ b/Master/texmf-dist/tex/context/base/mkxl/math-acc.mklx
@@ -57,23 +57,35 @@
[\v!bottom]
[\v!both]
+\setupmathaccents
+ [\v!top]
+ [i=\v!auto]
+
+\setupmathaccents
+ [\v!both]
+ [i=\v!auto]
+
+\setupmathaccents
+ [\v!bottom]
+ [i=]
+
\permanent\tolerant\protected\def\definemathtopaccent[#1]#*[#2]#*[#3]% class name top
{\ifparameter#3\or
- \frozen\protected\instance\edefcsname#2\endcsname{\math_accent_make_double {#1}\plusone{\number#3}\zerocount}%
+ \frozen\protected\instance\edefcsname#2\endcsname{\math_accent_make_double {#1}\plusone{\number#3}\zerocount}%
\else
\frozen\protected\instance\edefcsname#1\endcsname{\math_accent_make_double\noexpand\currentmathaccent\plusone{\number#2}\zerocount}%
\fi}
\permanent\tolerant\protected\def\definemathbottomaccent[#1]#*[#2]#*[#3]% class name bottom
{\ifparameter#3\or
- \frozen\protected\instance\edefcsname#2\endcsname{\math_accent_make_double {#1}\plustwo\zerocount{\number#3}}%
+ \frozen\protected\instance\edefcsname#2\endcsname{\math_accent_make_double {#1}\plustwo\zerocount{\number#3}}%
\else
\frozen\protected\instance\edefcsname#1\endcsname{\math_accent_make_double\noexpand\currentmathaccent\plustwo\zerocount{\number#2}}%
\fi}
\permanent\tolerant\protected\def\definemathdoubleaccent[#1]#*[#2]#*[#3]#*[#4]% class name top bottom
{\ifparameter#4\or
- \frozen\protected\instance\edefcsname#2\endcsname{\math_accent_make_double {#1}\plusthree{\number#3}{\number#4}}%
+ \frozen\protected\instance\edefcsname#2\endcsname{\math_accent_make_double {#1}\plusthree{\number#3}{\number#4}}%
\else
\frozen\protected\instance\edefcsname#1\endcsname{\math_accent_make_double\noexpand\currentmathaccent\plusthree{\number#2}{\number#3}}%
\fi}
@@ -97,16 +109,16 @@
\fam\zerocount#bottom
\or
both \m_fixed
- \fam\zerocount#top
\fam\zerocount#bottom
+ \fam\zerocount#top
\fi
- {\ifconditional\c_math_accent_auto_dotless\mathdotless\fi#content}%
+ {\ifcstok{\mathaccentparameter{i}}\v!auto\mathdotless\fi#content}%
\stopusemathstyleparameter
\endmathgroup}
%D Relative new:
-\newconditional\c_math_accent_auto_dotless \settrue\c_math_accent_auto_dotless % cf opentype math
+% \newconditional\c_math_accent_auto_dotless \settrue\c_math_accent_auto_dotless % cf opentype math
% \aliased\let\normalgrave\grave
% \aliased\let\normalddot \ddot
@@ -125,39 +137,100 @@
% These retain the given unicode values ... but can stretch when configured
% to do so: \setupmathaccent[\v!top][\c!stretch=\v!yes]
-\definemathtopaccent[\v!top][grave]["0060] % these are old school
-\definemathtopaccent[\v!top][ddot] ["00A8]
-\definemathtopaccent[\v!top][bar] ["00AF]
-\definemathtopaccent[\v!top][acute]["00B4]
-\definemathtopaccent[\v!top][hat] ["02C6]
-\definemathtopaccent[\v!top][check]["02C7]
-\definemathtopaccent[\v!top][breve]["02D8]
-\definemathtopaccent[\v!top][dot] ["02D9]
-\definemathtopaccent[\v!top][ring] ["02DA]
-\definemathtopaccent[\v!top][tilde]["02DC]
-\definemathtopaccent[\v!top][dddot]["20DB]
+% Extended/modified below
+%
+% \definemathtopaccent[\v!top][grave]["0060] % these are old school
+% \definemathtopaccent[\v!top][ddot] ["00A8]
+% \definemathtopaccent[\v!top][bar] ["00AF]
+% \definemathtopaccent[\v!top][acute]["00B4]
+% \definemathtopaccent[\v!top][hat] ["02C6]
+% \definemathtopaccent[\v!top][check]["02C7]
+% \definemathtopaccent[\v!top][breve]["02D8]
+% \definemathtopaccent[\v!top][dot] ["02D9]
+% \definemathtopaccent[\v!top][ring] ["02DA]
+% \definemathtopaccent[\v!top][tilde]["02DC]
+% \definemathtopaccent[\v!top][dddot]["20DB]
+
+\definemathtopaccent[\v!top][grave] ["0300]
+\definemathtopaccent[\v!top][acute] ["0301]
+\definemathtopaccent[\v!top][hat] ["0302]
+\definemathtopaccent[\v!top][tilde] ["0303]
+\definemathtopaccent[\v!top][bar] ["0304]
+%definemathtopaccent[\v!top][overbar] ["0305]% We expect overbar to stretch, so later
+\definemathtopaccent[\v!top][breve] ["0306]
+\definemathtopaccent[\v!top][dot] ["0307]
+\definemathtopaccent[\v!top][ddot] ["0308]
+\definemathtopaccent[\v!top][overhook]["0309]
+\definemathtopaccent[\v!top][ring] ["030A]
+\definemathtopaccent[\v!top][check] ["030C]
+
+% Here starts the weird unicode ones
+
+%definemathtopaccent[\v!top][candra] ["0310]
+%definemathtopaccent[\v!top][overturnedcomma] ["0312]
+%definemathtopaccent[\v!top][overcommatopright] ["0315]
+%definemathtopaccent[\v!top][leftangleabove] ["031A]
+\definemathtopaccent[\v!top][leftharpoonaccent] ["20D0]
+\definemathtopaccent[\v!top][rightharpoonaccent] ["20D1]
+%definemathtopaccent[\v!top][verticaloverlayaccent]["20D2]
+%definemathtopaccent[\v!top][vec] ["20D7]% We expect vec to stretch, so later
+\definemathtopaccent[\v!top][dddot] ["20DB]
+\definemathtopaccent[\v!top][ddddot] ["20DC]
+%definemathtopaccent[\v!top][annuityaccent] ["20E7]
+%definemathtopaccent[\v!top][overbracketaccent] ["20E9]
+%definemathtopaccent[\v!top][asterixaccent] ["20F0]
+
+% Weird ones (why no single and double underdots in unicode?)
+
+%definemathbottomaccent[\v!bottom][underdot] ["0323]%Conflicting
+%definemathbottomaccent[\v!bottom][underddot] ["0324]
+%definemathbottomaccent[\v!bottom][underdddot]["20E8]
\definemathaccent
[\v!top:\v!stretch]
[\v!top]
[\c!stretch=\v!yes]
+\definemathaccent
+ [\v!bottom:\v!stretch]
+ [\v!bottom]
+ [\c!stretch=\v!yes]
+
+\definemathaccent
+ [\v!both:\v!stretch]
+ [\v!both]
+ [\c!stretch=\v!yes]
+
%D We have a problem. We can use stackers but then we need to adapt the dimensions
%D which is font dependent. So, for now we keep them as accents.
\definemathtopaccent[\v!top:\v!stretch][widegrave]["0300] % these are generic modern
-\definemathtopaccent[\v!top:\v!stretch][wideddot] ["0308]
-\definemathtopaccent[\v!top:\v!stretch][widebar] ["0304]
\definemathtopaccent[\v!top:\v!stretch][wideacute]["0301]
\definemathtopaccent[\v!top:\v!stretch][widehat] ["0302]
-\definemathtopaccent[\v!top:\v!stretch][widecheck]["030C]
+\definemathtopaccent[\v!top:\v!stretch][widetilde]["0303]
+\definemathtopaccent[\v!top:\v!stretch][widebar] ["0305]%or 305
\definemathtopaccent[\v!top:\v!stretch][widebreve]["0306]
\definemathtopaccent[\v!top:\v!stretch][widedot] ["0307]
+\definemathtopaccent[\v!top:\v!stretch][wideddot] ["0308]
\definemathtopaccent[\v!top:\v!stretch][widering] ["030A]
-\definemathtopaccent[\v!top:\v!stretch][widetilde]["0303]
+\definemathtopaccent[\v!top:\v!stretch][widecheck]["030C]
\definemathtopaccent[\v!top:\v!stretch][widedddot]["20DB]
-\definemathtopaccent[\v!top:\v!stretch][vec] ["20D7] % clumsy notation for vectors
+\definemathtopaccent[\v!top:\v!stretch][vec]["20D7] % clumsy notation for vectors
+
+\definemathtopaccent[\v!top:\v!stretch][wideoverleftharpoon] ["20D0]
+\definemathtopaccent[\v!top:\v!stretch][wideoverrightharpoon] ["20D1]
+\definemathtopaccent[\v!top:\v!stretch][wideoverleftarrow] ["20D6]
+\definemathtopaccent[\v!top:\v!stretch][wideoverrightarrow] ["20D7]
+\definemathtopaccent[\v!top:\v!stretch][wideoverleftrightarrow]["20E1]
+
+\definemathbottomaccent[\v!bottom:\v!stretch][wideundertilde]["0330]
+\definemathbottomaccent[\v!bottom:\v!stretch][wideunderbar]["0332]
+\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftrightarrow]["034D]
+\definemathbottomaccent[\v!bottom:\v!stretch][wideunderrightharpoon]["20EC]
+\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftharpoon]["20ED]
+\definemathbottomaccent[\v!bottom:\v!stretch][wideunderleftarrow]["20EE]
+\definemathbottomaccent[\v!bottom:\v!stretch][wideunderrightarrow]["20EF]
\aliased\let\mathring\ring % for a while
diff --git a/Master/texmf-dist/tex/context/base/mkxl/math-act.lmt b/Master/texmf-dist/tex/context/base/mkxl/math-act.lmt
index 370415c8185..a6614aaa508 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/math-act.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/math-act.lmt
@@ -2624,6 +2624,20 @@ end
do
+ function mathtweaks.inspect(target,original,parameters)
+ local characters = target.characters
+ local slot = parameters.slot or parameters.unicode
+ if slot then
+ -- todo: show unicode
+ report_math(formatters["%C data:"](slot))
+ inspect(characters[slot])
+ end
+ end
+
+end
+
+do
+
local single <const> = 0x003D
local double <const> = 0x2A75
local triple <const> = 0x2A76
@@ -3886,13 +3900,13 @@ mathematics.horizontalcode = horizontalcode
interfaces.implement { -- can be public with two times "integerargument"
name = "extensiblecode",
- arguments = { "integer", "integer" },
+ arguments = "2 integers",
actions = { extensiblecode, context }
}
interfaces.implement { -- can be public with two times "integerargument"
name = "horizontalcode",
- arguments = { "integer", "integer" },
+ arguments = "2 integers",
actions = function(family,unicode)
local kind, loffset, roffset = horizontalcode(family,unicode)
texsetdimen(d_scratchleftoffset, loffset)
@@ -3939,7 +3953,7 @@ end
interfaces.implement {
name = "mathvariantcode",
public = true,
- arguments = { "integer", "integer" },
+ arguments = "2 integers",
actions = { mathematics.variantcode, context },
}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/math-ali.mkxl b/Master/texmf-dist/tex/context/base/mkxl/math-ali.mkxl
index baaa4666a85..b37887332d2 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/math-ali.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/math-ali.mkxl
@@ -330,6 +330,7 @@
\tabskip\centeringskip % fails in some cases
\aligntab
\span
+\hss % for MS to test this
\boundary\c_math_align_r_marker
\math_alignment_lbox{\aligncontent}%
\tabskip\zeropoint}%
@@ -1593,6 +1594,9 @@
\newdimension\d_math_matrix_margin_t
\newdimension\d_math_matrix_margin_b
+\newdimension\d_math_matrix_max_left
+\newdimension\d_math_matrix_max_right
+
\newboundary \c_math_matrix_ornament_l
\newboundary \c_math_matrix_ornament_r
\newboundary \c_math_matrix_ornament_t
@@ -1610,7 +1614,7 @@
{\NC
\enablematrixornaments
\global\settrue\c_math_matrix_text
- \global\settrue#1
+ \global\settrue#1%
\boundary#2%
\ignorespaces}
@@ -1642,6 +1646,8 @@
\d_math_matrix_margin_r\mathmatrixparameter\c!rightmargin\relax
\d_math_matrix_margin_t\strutdp
\d_math_matrix_margin_b\strutht
+ \global\d_math_matrix_max_left \zeropoint
+ \global\d_math_matrix_max_right\zeropoint
%\tabskip.5\d_math_eqalign_distance
\tabskip\zeropoint
\math_matrix_pickup
@@ -1672,6 +1678,9 @@
\mathmatrixright % experimental hook
\egroup}
+\permanent\protected\def\mathmatrixmaxleftwidth {\d_math_matrix_max_left }
+\permanent\protected\def\mathmatrixmaxrightwidth{\d_math_matrix_max_right}
+
\let\math_matrix_strut \strut
\let\math_matrix_set_style\relax
@@ -1752,7 +1761,7 @@
\normalstopimath
\egroup
\ifconditional\c_math_matrix_text
- \ifcstok{\mathmatrixparameter\c!left\mathmatrixparameter\c!right}\emptytoks\else
+ \ifcstok{\mathmatrixparameter\c!left\mathmatrixparameter\c!right\mathmatrixparameter\c!fences}\emptytoks\else
\scratchdistance\dimexpr(\wd\scratchbox-\scratchwidth)/\plustwo\relax
\advanceby\d_math_matrix_margin_l\scratchdistance
\advanceby\d_math_matrix_margin_r\scratchdistance
@@ -1765,7 +1774,15 @@
\ifconditional\c_math_matrix_text_t
\ht\scratchbox\dimexpr\ht\scratchbox+\lineheight\relax
\fi
- \box\scratchbox}
+ \edef\p_leftedge {\mathmatrixparameter\c!leftedge }%
+ \edef\p_rightedge{\mathmatrixparameter\c!rightedge}%
+ \ifempty\p_leftedge\else
+ \hskip\dimexpr\d_math_matrix_max_left+\p_leftedge\relax
+ \fi
+ \box\scratchbox
+ \ifempty\p_rightedge\else
+ \hskip\dimexpr\d_math_matrix_max_right+\p_rightedge\relax
+ \fi}
\definemathmatrix[matrix]
\definemathmatrix[\v!mathmatrix]
@@ -1957,24 +1974,53 @@
% \definemathmatrix[matrix:bars] [\c!left={\left|\mskip\thinmuskip},\c!right={\mskip\thinmuskip\right|},\c!align=\v!middle]
\definemathmatrix
+ [matrix:none]
+ [\c!align=\v!middle,
+ \c!simplecommand=matrix]
+
+\definemathmatrix
[matrix:brackets]
[\c!fences=bracket,
- \c!align=\v!middle]
+ \c!align=\v!middle,
+ \c!simplecommand=bmatrix]
\definemathmatrix
[matrix:parentheses]
[\c!fences=parenthesis,
- \c!align=\v!middle]
+ \c!align=\v!middle,
+ \c!simplecommand=pmatrix]
\definemathmatrix
[matrix:bars]
[\c!fences=bar,
- \c!align=\v!middle]
+ \c!align=\v!middle,
+ \c!simplecommand=vmatrix]
+
+\definemathmatrix
+ [matrix:doublebars]
+ [\c!fences=doublebar,
+ \c!align=\v!middle,
+ \c!simplecommand=vvmatrix]
+
+\definemathmatrix
+ [matrix:triplebars]
+ [\c!fences=triplebar,
+ \c!align=\v!middle,
+ \c!simplecommand=vvvmatrix]
+
+\definemathmatrix
+ [matrix:groups]
+ [\c!fences=group,
+ \c!align=\v!middle,
+ \c!simplecommand=gmatrix]
\definemathmatrix
[matrix:braces]
[\c!fences=brace,
- \c!align=\v!middle]
+ \c!align=\v!middle,
+ \c!simplecommand=bracematrix]%Seldom used, bmatrix occupied by brackets
+
+% MPS: Is this one really used? Yes, in the test suite ...
\definemathmatrix
[thematrix]
diff --git a/Master/texmf-dist/tex/context/base/mkxl/math-def.mkxl b/Master/texmf-dist/tex/context/base/mkxl/math-def.mkxl
index be33bac8619..a423a6a7934 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/math-def.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/math-def.mkxl
@@ -74,6 +74,11 @@
\definemathfunction [tan]
\definemathfunction [diff]
+% When [\c!command=] the label kicks in:
+
+\definemathfunction [cs:median] [\c!command=\widetilde]
+\definemathfunction [sk:median] [\c!command=\widetilde]
+
\aliased\let\normalmatharg\arg % todo: maybe automatically
%D This needs checking:
diff --git a/Master/texmf-dist/tex/context/base/mkxl/math-ini.mkxl b/Master/texmf-dist/tex/context/base/mkxl/math-ini.mkxl
index c76d7313a35..7d0c8ef81fc 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/math-ini.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/math-ini.mkxl
@@ -1932,37 +1932,135 @@
% \startformula[functionstyle=sans] \sin(x) = 10 \stopformula
% \stopTEXpage
-\protected\def\math_function_handle#1#2#3%
+% \protected\def\math_function_handle#1#2#3%
+% {\begingroup
+% \resetdummyparameter\c!mathlimits
+% \getdummyparameters[#1]%
+% \edef\p_limits{\dummyparameter\c!mathlimits}%
+% \mathatom
+% mathfont
+% class \mathfunctioncode
+% \ifx\p_limits\v!no
+% nolimits
+% \orelse\ifx\p_limits\v!yes
+% limits
+% \orelse\ifx\p_limits\v!auto
+% nolimits
+% limits
+% \fi
+% \bgroup % textfont
+% \math_tags_mfunctionlab{#3}\c_apply_function
+% \usemathematicscolorparameter\c!functioncolor
+% \edef\p_functionstyle{\mathematicsparameter\c!functionstyle}%
+% \ifempty\p_functionstyle
+% \expandafter\math_upright
+% \orelse\ifcsname\??alternativestyle\p_functionstyle\endcsname
+% \expandafter\lastnamedcs
+% \else
+% \expandafter\p_functionstyle
+% \fi
+% #2{#3}%
+% \egroup
+% \endgroup}
+
+\installcorenamespace{mathfunction}
+
+\installcommandhandler \??mathfunction {mathfunction} \??mathfunction
+
+\appendtoks
+ \frozen\protected\edefcsname\currentmathfunction\endcsname{\math_function_handle\plusone{\currentmathfunction}{}}% \instance
+\to \everydefinemathfunction
+
+\aliased\let\setupmathfunctions\setupmathfunction
+
+\setupmathfunctions
+ [\c!color=\mathematicsparameter\c!functioncolor,
+ \c!style=\mathematicsparameter\c!functionstyle]
+
+\def\math_function_handle_normal#1#2#3%
{\begingroup
- \resetdummyparameter\c!mathlimits
- \getdummyparameters[#1]%
- \edef\p_limits{\dummyparameter\c!mathlimits}%
- \mathatom
- mathfont
- class \mathfunctioncode
- \ifx\p_limits\v!no
- nolimits
- \orelse\ifx\p_limits\v!yes
- limits
- \orelse\ifx\p_limits\v!auto
- nolimits
- limits
- \fi
- \bgroup % textfont
- \math_tags_mfunctionlab{#3}\c_apply_function
- \usemathematicscolorparameter\c!functioncolor
- \edef\p_functionstyle{\mathematicsparameter\c!functionstyle}%
- \ifempty\p_functionstyle
- \expandafter\math_upright
- \orelse\ifcsname\??alternativestyle\p_functionstyle\endcsname
- \expandafter\lastnamedcs
- \else
- \expandafter\p_functionstyle
- \fi
- #2{#3}%
- \egroup
+ \edef\currentmathfunction{#2}%
+ \setupcurrentmathfunction[#3]%
+ \edef\p_limits{\mathfunctionparameter\c!mathlimits}%
+ \mathatom
+ mathfont
+ class \mathfunctioncode
+ \ifx\p_limits\v!no
+ nolimits
+ \orelse\ifx\p_limits\v!yes
+ limits
+ \orelse\ifx\p_limits\v!auto
+ nolimits
+ limits
+ \fi
+ \bgroup % textfont
+%
+% for now we reserve command for languages and it completely bypasses
+% the atom!
+%
+% \edef\p_command{\mathfunctionparameter\c!command}%
+% \ifempty\p_command
+ \math_tags_mfunctionlab{#2}\c_apply_function
+ \usemathfunctioncolorparameter\c!color
+ \edef\p_functionstyle{\mathfunctionparameter\c!style}%
+ \ifempty\p_functionstyle
+ \expandafter\math_upright
+ \orelse\ifcsname\??alternativestyle\p_functionstyle\endcsname
+ \expandafter\lastnamedcs
+ \else
+ \expandafter\p_functionstyle
+ \fi
+ \ifcase#1\relax
+ \expandafter\firstofoneargument
+ \or
+ \expandafter\mathlabeltext
+ \fi{#2}%
+% \else
+% \p_command\relax
+% \fi
+ \egroup
\endgroup}
+\def\math_function_handle_language_indeed#1#2#3%
+ {\edef\currentmathfunction{#2}%
+ \setupcurrentmathfunction[#3]%
+ \edef\p_command{\mathfunctionparameter\c!command}%
+ \ifempty\p_command
+ \endgroup\math_function_handle_normal#1{#2}{#3}%
+ \else
+ \normalexpanded{\endgroup\p_command\expandafter}%
+ \fi}
+
+\def\math_function_handle_language#1#2%
+ {\begingroup
+ \let\math_function_handle\math_function_handle_language_indeed
+ \csname\currentmainlanguage:#2\endcsname}
+
+\tolerant\protected\def\math_function_handle#1#2#3%
+ {\ifcsname\currentmainlanguage:#2\endcsname
+ \expandafter\math_function_handle_language
+ \else
+ \expandafter\math_function_handle_normal
+ \fi#1{#2}{#3}}
+
+\permanent\tolerant\protected\def\mfunctionlabeltext[#1]%
+ {\math_function_handle\plusone{#1}{}}
+
+% \mfunction [settings][name] [settings]{name} [name] {name}
+
+\permanent\tolerant\protected\def\mfunction[#1]%
+ {\ifhastok={#1}%
+ \expandafter\mfunction_yes
+ \orelse\ifparameter#1\or
+ \expandafter\mfunction_nop
+ \else
+ \expandafter\mfunction_yop
+ \fi{#1}}
+
+\permanent\tolerant\protected\def\mfunction_yes#1#*[#2]#;#3{\math_function_handle\zerocount{#2#3}{#1}}
+\permanent\protected\def\mfunction_nop #1{\math_function_handle\zerocount{#1}{}}
+\permanent\protected\def\mfunction_yop #1#2{\math_function_handle\zerocount{#2}{}}
+
\appendtoks
\edef\p_functionstyle{\formulaparameter\c!functionstyle}%
\ifempty\p_functionstyle\else
@@ -1974,12 +2072,6 @@
\fi
\to \everybeforedisplayformula
-\permanent\tolerant\protected\def\mfunction [#1]{\math_function_handle{#1}\firstofoneargument}
-\permanent\tolerant\protected\def\mfunctionlabeltext[#1]{\math_function_handle{#1}\mathlabeltext}
-
-\permanent\tolerant\protected\def\definemathfunction[#1]#*[#2]%
- {\frozen\protected\defcsname#1\endcsname{\math_function_handle{#2}\mathlabeltext{#1}}} % \instance
-
\let\math_tags_mfunctiontxt\gobbletwoarguments
\let\math_tags_mfunctionlab\gobbletwoarguments
diff --git a/Master/texmf-dist/tex/context/base/mkxl/math-spa.lmt b/Master/texmf-dist/tex/context/base/mkxl/math-spa.lmt
index 126bb739b07..9875f8b2d93 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/math-spa.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/math-spa.lmt
@@ -28,6 +28,7 @@ local tonode = nodes.tonode
local getid = nuts.getid
local getsubtype = nuts.getsubtype
local getnext = nuts.getnext
+local getprev = nuts.getprev
local getwidth = nuts.getwidth
local getdata = nuts.getdata
local getdepth = nuts.getdepth
@@ -47,6 +48,7 @@ local nextboundary = nuts.traversers.boundary
local nextnode = nuts.traversers.node
local texsetdimen = tex.setdimen
+local texgetdimen = tex.getdimen
local texsetcount = tex.setcount
local texisdimen = tex.isdimen
local texiscount = tex.iscount
@@ -63,44 +65,125 @@ local d_strc_math_first_height = texisdimen("d_strc_math_first_height")
local d_strc_math_last_depth = texisdimen("d_strc_math_last_depth")
local d_strc_math_indent = texisdimen("d_strc_math_indent")
+local function moveon(s)
+ for n, id, subtype in nextnode, getnext(s) do
+ s = n
+ if id == kern_code then
+ -- move on (s_2 case)
+ elseif id == glue_code then
+ -- move on
+ elseif id == penalty_code then
+ -- move on (untested)
+ elseif id == hlist_code and subtype == ghost_code then
+ -- move on
+ else
+ break
+ end
+ end
+ return s
+end
+
+-- stages[1] = function(specification,stage)
+-- local box = getbox(specification.box)
+-- local head = getlist(box)
+-- local align = specification.alignstate
+-- local distance = specification.distance
+-- for s in nextboundary, head do
+-- local data = getdata(s)
+-- if data == boundary then
+-- -- todo: skip over ghost, maybe penalty, maybe glues all in one loop
+-- s = moveon(s)
+-- for n, id, subtype in nextnode, getnext(s) do
+-- s = n
+-- if id == kern_code then
+-- -- move on (s_2 case)
+-- elseif id == glue_code then
+-- -- move on
+-- elseif id == penalty_code then
+-- -- move on (untested)
+-- elseif id == hlist_code and subtype == ghost_code then
+-- -- move on
+-- else
+-- break
+-- end
+-- end
+-- distance = distance + getdimensions(head,s)
+-- break
+-- end
+-- end
+-- texsetdimen("global",d_strc_math_indent,distance)
+-- if align == 2 then
+-- for n in nextglue, head do
+-- setglue(n,getwidth(n),0,0,0,0)
+-- end
+-- end
+-- end
+
+-- -- todo: skip over ghost, maybe penalty, maybe glues all in one loop
+--
+-- local n = getnext(s)
+-- if n and getid(n) == kern_code then -- also needed
+-- n = getnext(n)
+-- end
+-- while n and getid(n) == hlist_code and getsubtype(n) == ghost_code do
+-- n = getnext(n)
+-- end
+-- while n and getid(n) == glue_code do
+-- if n and getid(n) == glue_code then
+-- n = getnext(n)
+-- end
+
+local getpenalty = nuts.getpenalty
+
stages[1] = function(specification,stage)
local box = getbox(specification.box)
local head = getlist(box)
local align = specification.alignstate
local distance = specification.distance
+ local found = { }
+ local max = 0
for s in nextboundary, head do
- if getdata(s) == boundary then
- -- todo: skip over ghost, maybe penalty, maybe glues all in one loop
--- local n = getnext(s)
--- if n and getid(n) == kern_code then -- also needed
--- n = getnext(n)
--- end
--- while n and getid(n) == hlist_code and getsubtype(n) == ghost_code do
--- n = getnext(n)
--- end
--- -- while n and getid(n) == glue_code do
--- if n and getid(n) == glue_code then
--- n = getnext(n)
--- end
- for n, id, subtype in nextnode, getnext(s) do
- s = n
- if id == kern_code then
- -- move on (s_2 case)
- elseif id == glue_code then
- -- move on
- elseif id == penalty_code then
- -- move on (untested)
- elseif id == hlist_code and subtype == ghost_code then
- -- move on
- else
+ local data = getdata(s)
+ if data == boundary then
+ s = moveon(s)
+ found[#found+1] = { s, 0, head }
+ end
+ end
+ if #found > 0 then
+ if found[1] then
+ max = distance + getdimensions(head,found[1][1])
+ found[1][2] = max
+ end
+ for i=2,#found do
+ local f = found[i]
+ local n = f[1]
+ local p = n
+ while p do
+ if getid(p) == penalty_code and getpenalty(p) == -10000 then
+ local d = distance + getdimensions(p,n)
+ f[2] = d
+ f[3] = p
+ if d > max then
+ max = d
+ end
break
end
+ p = getprev(p)
end
- distance = distance + getdimensions(head,s)
- break
+ end
+ -- we use a hangindent so we need to treat the first one
+ local f = found[1]
+ local delta = f[2] - max
+ if delta ~= 0 then
+ nuts.insertafter(head,moveon(head),nuts.pool.kern(-delta))
+ end
+ for i=2,#found do
+ local f = found[i]
+ local delta = f[2] - max
+ nuts.insertafter(head,moveon(f[3]),nuts.pool.kern(-f[2])) -- check head
end
end
- texsetdimen("global",d_strc_math_indent,distance)
+ texsetdimen("global",d_strc_math_indent,max)
if align == 2 then
for n in nextglue, head do
setglue(n,getwidth(n),0,0,0,0)
diff --git a/Master/texmf-dist/tex/context/base/mkxl/mlib-ctx.lmt b/Master/texmf-dist/tex/context/base/mkxl/mlib-ctx.lmt
index 8ed6b0b00c5..1ee21db38ac 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/mlib-ctx.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/mlib-ctx.lmt
@@ -231,7 +231,7 @@ implement {
implement {
name = "mpsetoutercolor",
actions = function(...) metapost.setoutercolor(...) end, -- not yet implemented
- arguments = { "integer", "integer", "integer", "integer" }
+ arguments = "4 integers",
}
-- this has to become a codeinjection
diff --git a/Master/texmf-dist/tex/context/base/mkxl/mlib-fio.lmt b/Master/texmf-dist/tex/context/base/mkxl/mlib-fio.lmt
index 07c9275beca..57984839f12 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/mlib-fio.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/mlib-fio.lmt
@@ -69,15 +69,24 @@ local splitlines = string.splitlines
local suffixlist = { "mpxl", "mpiv", "mp" } -- no "mf"
+local remapped = {
+ -- We don't yet have an interface for adding more here but when needed
+ -- there will be one.
+ ["hatching.mp"] = "mp-remapped-hatching.mp",
+ ["boxes.mp"] = "mp-remapped-boxes.mp",
+ ["hatching"] = "mp-remapped-hatching.mp",
+ ["boxes"] = "mp-remapped-boxes.mp",
+}
+
local function findmpfile(name,ftype)
+ local usedname = remapped[name] or name
local validtyp = validftype(ftype)
- -- local fullname = findfile(name,validtyp)
- local fullname = findtexfile(name,validtyp)
+ local fullname = findtexfile(usedname,validtyp)
if fullname and fullname ~= "" then
return fullname
- elseif suffix(name) == "" then
+ elseif suffix(usedname) == "" then
for i=1,#suffixlist do
- fullname = findfile(addsuffix(name,suffixlist[i]),validtyp)
+ fullname = findfile(addsuffix(usedname,suffixlist[i]),validtyp)
if fullname and fullname ~= "" then
return fullname
end
diff --git a/Master/texmf-dist/tex/context/base/mkxl/mult-dim.mklx b/Master/texmf-dist/tex/context/base/mkxl/mult-dim.mklx
index 0526b3775a1..e2ed1993caa 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/mult-dim.mklx
+++ b/Master/texmf-dist/tex/context/base/mkxl/mult-dim.mklx
@@ -88,7 +88,7 @@
%D \macros
%D {assignvalue}
%D
-%D A variant that does not assume dimenions ios the following:
+%D A variant that does not assume dimenions is the following:
%D
%D \starttyping
%D \assignvalue
diff --git a/Master/texmf-dist/tex/context/base/mkxl/node-ali.lmt b/Master/texmf-dist/tex/context/base/mkxl/node-ali.lmt
index 510e56b8ec4..ba2ccdde7d6 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/node-ali.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/node-ali.lmt
@@ -343,6 +343,7 @@ do
local nextnode = nuts.traversers.node
local texgetdimen = tex.getdimen
+ local texsetdimen = tex.setdimen
local texgetglue = tex.getglue
local texget = tex.get
@@ -405,12 +406,12 @@ do
if subtype == linepenalty_code then
if l == 1 then
if splitmethod == v_both or splitmethod == v_first then
-print("FIRST")
+-- print("FIRST")
setpenalty(n, 10000)
end
elseif l == noflines then
if splitmethod == v_both or splitmethod == v_last then
-print("LAST")
+-- print("LAST")
setpenalty(n, 10000)
end
end
@@ -772,6 +773,8 @@ end
local topornament = tex.boundaries.system("c_math_matrix_ornament_t")
local bottomornament = tex.boundaries.system("c_math_matrix_ornament_b")
+ local verticalline = tex.boundaries.system("c_math_matrix_vl_boundary")
+
local left = 0
local right = 0
local nofcells = 0
@@ -802,7 +805,11 @@ end
c = c + 1
for bound in nextboundary, list do
local ornament = getdata(bound)
- if ornament == leftornament then
+ if ornament == verticalline then
+ -- this hack is is beyond ugly as we omit and span
+ c = c + 1
+ break
+ elseif ornament == leftornament then
if c == 1 then
local w = getwidth(cell)
if w > left then
@@ -874,6 +881,8 @@ end
rights = false
tops = false
bottoms = false
+ texsetdimen("global","d_math_matrix_max_left", left)
+ texsetdimen("global","d_math_matrix_max_right",right)
end
end
diff --git a/Master/texmf-dist/tex/context/base/mkxl/node-aux.lmt b/Master/texmf-dist/tex/context/base/mkxl/node-aux.lmt
index a640addc1ed..9794d4ab807 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/node-aux.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/node-aux.lmt
@@ -98,6 +98,22 @@ function nodes.takebox(id)
end
end
+if not nuts.migratebox then -- todo: add to nodes.direct, or maybe getmigrate, setmigrate
+
+ local setpre = nuts.setpre
+ local setpost = nuts.setpost
+ local getpre = nuts.getpre
+ local getpost = nuts.getpost
+
+ function nuts.migratebox(source,target)
+ setpre(target,getpre(source))
+ setpost(target,getpost(source))
+ setpre(source)
+ setpost(source)
+ end
+
+end
+
local splitbox = tex.splitbox
nodes.splitbox = splitbox
diff --git a/Master/texmf-dist/tex/context/base/mkxl/page-flt.mkxl b/Master/texmf-dist/tex/context/base/mkxl/page-flt.mkxl
index 8808ef00b6c..ae2bd4cf8e9 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/page-flt.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/page-flt.mkxl
@@ -167,6 +167,36 @@
\blank[\rootfloatparameter\c!spaceafter]%
\fi}}
+%D Not the best name for a command:
+%D
+%D \starttyping
+%D \samplefile{tufte}
+%D \placefigure[somewhere:a]{}{\externalfigure[dummy-001]}
+%D \samplefile{tufte}
+%D \placefigure{}{\externalfigure[dummy-002]}
+%D \samplefile{tufte}
+%D \startplacefigure[location={somewhere:b,tight}]
+%D \externalfigure[dummy-003]
+%D \stopplacefigure
+%D \samplefile{tufte}
+%D \placefigure{}{\externalfigure[dummy-004]}
+%D \page
+%D \placesavedfloat[figure][b][location={none,left}] \samplefile{tufte}
+%D \placesavedfloat[figure][a]
+%D % \placenamedfloat[figure][*]
+%D % \placenamedfloat[figure][b]
+%D \stoptyping
+
+\newbox\b_strc_float_saved
+
+\permanent\tolerant\protected\def\placesavedfloat[#1]#*[#2]#*[#3]% experiment for Alan B
+ {\clf_flushlabeledfloat\s!somewhere{#2}\relax
+ %\def\currentfloat{#1}%
+ \setbox\b_strc_float_saved\vpack{\box\floatbox}%
+ \startplacefloat[#1][\c!location=\v!none,#3]%
+ \box\b_strc_float_saved
+ \stopplacefloat}
+
% \setupcaption [figure] [align=flushleft]
% \setupcaption [figure-1] [align=flushleft,leftmargin=10mm]
% \setupcaption [figure-2] [align=flushleft,leftmargin=10mm,rightmargin=-10mm,width=\textwidth]
diff --git a/Master/texmf-dist/tex/context/base/mkxl/page-lin.lmt b/Master/texmf-dist/tex/context/base/mkxl/page-lin.lmt
index f50031ab300..3c20feaee8c 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/page-lin.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/page-lin.lmt
@@ -414,5 +414,5 @@ end
implement {
name = "addlinenumbers",
actions = boxed.addlinenumbers,
- arguments = { "integer", "integer", "integer" }
+ arguments = "3 integers",
}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/page-one.mkxl b/Master/texmf-dist/tex/context/base/mkxl/page-one.mkxl
index 8571c29829a..aece474a793 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/page-one.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/page-one.mkxl
@@ -366,6 +366,10 @@
\protected\def\page_one_command_set_top_insertions
{\bgroup
+ % a bit strange place but okay
+ \page_one_command_set_always_insertions_top
+ \page_one_command_set_always_insertions_bottom
+ %
\ifconditional\c_page_floats_some_waiting
\noffloatinserts\zerocount
\let\totaltopinserted\!!zeropoint
@@ -756,22 +760,79 @@
\fi
\fi}}
+% \def\page_one_place_float_otherwise_else
+% {\doifelseinset\v!always\floatlocationmethod
+% {\page_otr_command_check_if_float_fits
+% \ifconditional\c_page_floats_room
+% \page_one_place_float_auto_top_bottom
+% \else
+% \showmessage\m!floatblocks9\empty
+% \page_floats_resave\s!text
+% \fi}
+% {\page_otr_command_check_if_float_fits
+% \ifconditional\c_page_floats_room
+% \page_one_place_float_auto_top_bottom
+% \else
+% \page_floats_save\s!text
+% \nonoindentation
+% \fi}}
+
+% Some new always top/bottom trickery.
+%
+% Musical timestamp: 2023/3/2, listening to / watching Camille Bigeault on YT
+% (ANATMAN, Room 8, and others), a bit late discovery, creative drumming! Gavin
+% Harrison level creativity.
+
\def\page_one_place_float_otherwise_else
- {\doifelseinset\v!always\floatlocationmethod
- {\page_otr_command_check_if_float_fits
- \ifconditional\c_page_floats_room
- \page_one_place_float_auto_top_bottom
- \else
- \showmessage\m!floatblocks9\empty
- \page_floats_resave\s!text
- \fi}
- {\page_otr_command_check_if_float_fits
- \ifconditional\c_page_floats_room
- \page_one_place_float_auto_top_bottom
- \else
- \page_floats_save\s!text
- \nonoindentation
- \fi}}
+ {\doifelseinset\v!always\floatlocationmethod
+ {\page_otr_command_check_if_float_fits
+ \ifconditional\c_page_floats_room
+ \page_one_place_float_auto_top_bottom
+ \else
+ \showmessage\m!floatblocks9\empty
+ \doifelseinset\v!top\floatlocationmethod
+ {\page_floats_save\s!top}
+ {\doifelseinset\v!bottom\floatlocationmethod
+ {\page_floats_save\s!bottom}
+ {\page_floats_resave\s!text}}%
+ \fi}
+ {\page_otr_command_check_if_float_fits
+ \ifconditional\c_page_floats_room
+ \page_one_place_float_auto_top_bottom
+ \else
+ \page_floats_save\s!text
+ \nonoindentation
+ \fi}}
+
+\protected\def\page_one_command_set_always_insertions_bottom_indeed
+ {\page_floats_flush\s!bottom\plusone
+ \floatingpenalty\zerocount
+ \page_inserts_inject\namedinsertionnumber\s!bottomfloat\bgroup
+ \forgetall
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box
+ \egroup}
+
+\protected\def\page_one_command_set_always_insertions_bottom % will become an otr command
+ {\ifzero\nofstackedfloatsincategory\s!bottom\else
+ \page_one_command_set_always_insertions_bottom_indeed
+ \expandafter\page_one_command_set_always_insertions_bottom
+ \fi}
+
+\protected\def\page_one_command_set_always_insertions_top_indeed
+ {\page_floats_flush\s!top\plusone
+ \floatingpenalty\zerocount
+ \page_inserts_inject\namedinsertionnumber\s!bottomfloat\bgroup
+ \forgetall
+ \blank[\rootfloatparameter\c!spacebefore]%
+ \page_otr_command_flush_float_box
+ \egroup}
+
+\protected\def\page_one_command_set_always_insertions_top % will become an otr command
+ {\ifzero\nofstackedfloatsincategory\s!top\else
+ \page_one_command_set_always_insertions_top_indeed
+ \expandafter\page_one_command_set_always_insertions_top
+ \fi}
\mutable\def\floatautofactor{.5}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/page-sel.lmt b/Master/texmf-dist/tex/context/base/mkxl/page-sel.lmt
index a6ea84f472a..2ca93c039d0 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/page-sel.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/page-sel.lmt
@@ -19,7 +19,7 @@ do
local filedata = sections[filename]
if not filedata then
filedata = {
- data = job.loadother(addsuffix(filename,"tuc")) or false,
+ data = job.loadother(filename,"tuc") or false,
list = { }
}
sections[filename] = filedata
diff --git a/Master/texmf-dist/tex/context/base/mkxl/page-txt.mklx b/Master/texmf-dist/tex/context/base/mkxl/page-txt.mklx
index 76aa15cabf5..67ca325b2a9 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/page-txt.mklx
+++ b/Master/texmf-dist/tex/context/base/mkxl/page-txt.mklx
@@ -728,18 +728,31 @@
%D A few more page breakers:
+% \installpagebreakmethod \v!empty
+% {\page_otr_flush_all_floats
+% \page_otr_command_next_page
+% \doifnot{\namedlayoutelementparameter\v!header\c!state}\v!stop{\setuplayoutelement[\v!header][\c!state=\v!empty]}%
+% \doifnot{\namedlayoutelementparameter\v!footer\c!state}\v!stop{\setuplayoutelement[\v!footer][\c!state=\v!empty]}%
+% \page_otr_insert_dummy_page}
+%
+% \installpagebreakmethod \v!header
+% {\doifnot{\namedlayoutelementparameter\v!header\c!state}\v!stop{\setuplayoutelement[\v!header][\c!state=\v!empty]}}
+%
+% \installpagebreakmethod \v!footer
+% {\doifnot{\namedlayoutelementparameter\v!footer\c!state}\v!stop{\setuplayoutelement[\v!footer][\c!state=\v!empty]}}
+
\installpagebreakmethod \v!empty
{\page_otr_flush_all_floats
\page_otr_command_next_page
- \doifnot{\namedlayoutelementparameter\v!header\c!state}\v!stop{\setuplayoutelement[\v!header][\c!state=\v!empty]}%
- \doifnot{\namedlayoutelementparameter\v!footer\c!state}\v!stop{\setuplayoutelement[\v!footer][\c!state=\v!empty]}%
+ \ifcstok{\namedlayoutelementparameter\v!header\c!state}\v!stop\else\setuplayoutelement[\v!header][\c!state=\v!empty]\fi
+ \ifcstok{\namedlayoutelementparameter\v!footer\c!state}\v!stop\else\setuplayoutelement[\v!footer][\c!state=\v!empty]\fi
\page_otr_insert_dummy_page}
\installpagebreakmethod \v!header
- {\doifnot{\namedlayoutelementparameter\v!header\c!state}\v!stop{\setuplayoutelement[\v!header][\c!state=\v!empty]}}
+ {\ifcstok{\namedlayoutelementparameter\v!header\c!state}\v!stop\else\setuplayoutelement[\v!header][\c!state=\v!empty]\fi}
\installpagebreakmethod \v!footer
- {\doifnot{\namedlayoutelementparameter\v!footer\c!state}\v!stop{\setuplayoutelement[\v!footer][\c!state=\v!empty]}}
+ {\ifcstok{\namedlayoutelementparameter\v!footer\c!state}\v!stop\else\setuplayoutelement[\v!footer][\c!state=\v!empty]\fi}
%D While the header and footer lines are moved away from the main text, the top and
%D bottom lines are centered.
diff --git a/Master/texmf-dist/tex/context/base/mkxl/spac-ver.lmt b/Master/texmf-dist/tex/context/base/mkxl/spac-ver.lmt
index 06032bcce9d..a2b02c34c3e 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/spac-ver.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/spac-ver.lmt
@@ -2830,7 +2830,7 @@ do
name = "vspacingsnap",
actions = vspacing.snapbox,
scope = "private",
- arguments = { "integer", "integer" }
+ arguments = "2 integers",
}
implement {
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-def.mkxl b/Master/texmf-dist/tex/context/base/mkxl/strc-def.mkxl
index 52b3b3ad972..520a9e3111c 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/strc-def.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-def.mkxl
@@ -27,6 +27,8 @@
% \part{second} \chapter{gamma} \section{a} \section{b} \subsection{x} \subsection{y} \chapter{delta}
% \stoptext
+\defineseparatorset [\v!none] [] []
+
\defineseparatorset [\s!default] [] [.]
\defineconversionset [\s!default] [] [numbers]
\defineresetset [\s!default] [] [1] % each level
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-flt.lmt b/Master/texmf-dist/tex/context/base/mkxl/strc-flt.lmt
new file mode 100644
index 00000000000..e47046f8c80
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-flt.lmt
@@ -0,0 +1,53 @@
+if not modules then modules = { } end modules ['strc-flt'] = {
+ version = 1.001,
+ comment = "companion to strc-flt.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- nothing
+
+local sequencers = utilities.sequencers
+local appendaction = sequencers.appendaction
+local enableaction = sequencers.enableaction
+local disableaction = sequencers.disableaction
+
+local texgetdimen = tex.getdimen
+local texgetoutputactive = tex.getoutputactive
+
+local trace = trackers.register("structure.sidefloats.pageflush")
+local report = logs.reporter("structure","floats")
+
+local forcepageflush = builders.vspacing.forcepageflush
+
+local d_page_sides_vsize = tex.isdimen("d_page_sides_vsize")
+
+function builders.checksidefloat(mode,indented)
+ if not texgetoutputactive() then
+ local s = texgetdimen(d_page_sides_vsize)
+ if s > 0 then
+ if trace then
+ report("force flushing page state, height %p",s)
+ end
+ forcepageflush()
+ end
+ else
+ -- we don't have side floats outside the main vertical list
+ end
+ return indented
+end
+
+-- These two lines might move to task-ini.lmt where we currently only deal
+-- with node handlers:
+
+appendaction ("paragraph","system","builders.checksidefloat")
+disableaction("paragraph","builders.checksidefloat")
+
+interfaces.implement {
+ name = "enablesidefloatchecker",
+ onlyonce = true,
+ actions = function()
+ enableaction("paragraph","builders.checksidefloat")
+ end,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-flt.mklx b/Master/texmf-dist/tex/context/base/mkxl/strc-flt.mklx
index 55b825fe1e9..6af22631a80 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/strc-flt.mklx
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-flt.mklx
@@ -15,10 +15,12 @@
\writestatus{loading}{ConTeXt Structure Macros / Float Numbering}
-\registerctxluafile{strc-flt}{}
-
\unprotect
+\ifdefined\d_page_sides_vsize \else \newdimension\d_page_sides_vsize \fi
+
+\registerctxluafile{strc-flt}{autosuffix}
+
% todo: a keyword for this (and then a settings->hash for speed)
%
% \setuplayout[width=middle,backspace=3cm]
@@ -737,10 +739,10 @@
\strc_floats_set_current_tag{#tag}%
\strc_floats_reset_variables
% save
- \edef\m_location {\floatcaptionparameter\c!location}%
- \edef\m_topoffset {\floatcaptionparameter\c!topoffset}%
- \edef\m_bottomoffset{\floatcaptionparameter\c!bottomoffset}%
- \edef\m_freeregion {\floatcaptionparameter\c!freeregion}%
+ \edef\p_location {\floatcaptionparameter\c!location}%
+ \edef\p_topoffset {\floatcaptionparameter\c!topoffset}%
+ \edef\p_bottomoffset{\floatcaptionparameter\c!bottomoffset}%
+ \edef\P_freeregion {\floatcaptionparameter\c!freeregion}%
% preset
\resetfloatcaptionparameter \c!location
\setexpandedfloatcaptionparameter\c!topoffset {\floatparameter\c!topoffset}%
@@ -773,10 +775,10 @@
\setexpandedfloatparameter\c!bottomoffset{\floatcaptionparameter\c!bottomoffset}%
\setexpandedfloatparameter\c!freeregion {\floatcaptionparameter\c!freeregion}%
% restore
- \letfloatcaptionparameter\c!location \m_location
- \letfloatcaptionparameter\c!topoffset \m_topoffset
- \letfloatcaptionparameter\c!bottomoffset\m_bottomoffset
- \letfloatcaptionparameter\c!freeregion \m_freeregion
+ \letfloatcaptionparameter\c!location \p_location
+ \letfloatcaptionparameter\c!topoffset \p_topoffset
+ \letfloatcaptionparameter\c!bottomoffset\p_bottomoffset
+ \letfloatcaptionparameter\c!freeregion \P_freeregion
%
\strc_floats_analyze_location
\doifelseinset\v!split\floatlocation\strc_floats_place_next_box_split\strc_floats_place_next_box_normal
@@ -2127,15 +2129,38 @@
\hpack{\strc_floats_locate_text_float{\box\b_strc_floats_caption}}%
\fi}
+\def\strc_floats_build_box_top_stack_normal_tight
+ {\hpack{\box\b_strc_floats_caption}%
+ \strc_floats_between_stack
+ \hpack{\box\b_strc_floats_content}}
+
+\def\strc_floats_build_box_bottom_stack_normal_tight
+ {\hpack{\box\b_strc_floats_content}%
+ \strc_floats_between_stack
+ \hpack{\box\b_strc_floats_caption}}
+
\def\strc_floats_build_box_top_stack_normal
{\doifelseinset\v!overlay{\floatcaptionparameter\c!location}
\strc_floats_build_box_top_stack_normal_overlay
- \strc_floats_build_box_top_stack_normal_content}
+ {\doifelseinset\v!tight{\floatlocation}
+ \strc_floats_build_box_top_stack_normal_tight
+ \strc_floats_build_box_top_stack_normal_content}}
\def\strc_floats_build_box_bottom_stack_normal
- {\doifinset\v!overlay{\floatcaptionparameter\c!location}
+ {\doifelseinset\v!overlay{\floatcaptionparameter\c!location}
\strc_floats_build_box_bottom_stack_normal_overlay
- \strc_floats_build_box_bottom_stack_normal_content}
+ {\doifelseinset\v!tight{\floatlocation}
+ \strc_floats_build_box_bottom_stack_normal_tight
+ \strc_floats_build_box_bottom_stack_normal_content}}
+
+% \def\strc_floats_build_box_bottom_stack_normal
+% {\ifhasxtoks{,\v!overlay,}{,\floatcaptionparameter\c!location,}%
+% \strc_floats_build_box_bottom_stack_normal_overlay
+% \orelse\ifhasxtoks{,\v!tight,}{,\floatlocation,}%
+% \strc_floats_build_box_bottom_stack_normal_tight
+% \else
+% \strc_floats_build_box_bottom_stack_normal_content
+% \fi}
\def\strc_floats_build_box_top_stack_grid
{\dp\b_strc_floats_caption\strutdepth
@@ -2264,16 +2289,30 @@
\def\strc_floats_build_box_after
{\doifelseframed\floatframedparameter\strc_floats_build_box_after_indeed\relax}
+% \def\strc_floats_build_box_after_indeed
+% {\global\setbox\floatbox\hpack
+% {\edef\m_width{\floatframedparameter\c!width}%
+% \ifx\m_width\v!fit
+% \let\m_width\floatwidth
+% \orelse\ifx\m_width\v!broad
+% \let\m_width\v!fit
+% \fi
+% \letfloatframedparameter\c!strut\v!no
+% \letfloatframedparameter\c!width\m_width
+% \inheritedfloatframedframed
+% {\box\floatbox}}}
+
\def\strc_floats_build_box_after_indeed
{\global\setbox\floatbox\hpack
{\edef\m_width{\floatframedparameter\c!width}%
\ifx\m_width\v!fit
- \let\m_width\floatwidth
+ \letfloatframedparameter\c!width\floatwidth
\orelse\ifx\m_width\v!broad
- \let\m_width\v!fit
+ \letfloatframedparameter\c!width\v!fit
+ \else
+ \letfloatframedparameter\c!width\m_width % expanded, not really needed
\fi
\letfloatframedparameter\c!strut\v!no
- \letfloatframedparameter\c!width\m_width
\inheritedfloatframedframed
{\box\floatbox}}}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-itm.lmt b/Master/texmf-dist/tex/context/base/mkxl/strc-itm.lmt
new file mode 100644
index 00000000000..f9153c98e8b
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-itm.lmt
@@ -0,0 +1,64 @@
+if not modules then modules = { } end modules ['strc-itm'] = {
+ version = 1.001,
+ comment = "companion to strc-itm.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local structures = structures
+local itemgroups = structures.itemgroups
+local jobpasses = job.passes
+
+local implement = interfaces.implement
+
+local setvariable = jobpasses.save
+local getvariable = jobpasses.getfield
+
+local texsetcount = tex.setcount
+local texsetdimen = tex.setdimen
+
+local f_stamp = string.formatters["itemgroup:%s:%s"]
+local counts = table.setmetatableindex("number")
+
+local c_strc_itemgroups_max_items = tex.iscount("c_strc_itemgroups_max_items")
+local d_strc_itemgroups_max_width = tex.isdimen("d_strc_itemgroups_max_width")
+
+-- We keep the counter at the Lua end so we can group the items within
+-- an itemgroup which in turn makes for less passes when one itemgroup
+-- entry is added or removed.
+
+local trialtypesetting = context.trialtypesetting
+
+local function analyzeitemgroup(name,level)
+ local n = counts[name]
+ if level == 1 then
+ n = n + 1
+ counts[name] = n
+ end
+ local stamp = f_stamp(name,n)
+ texsetcount(c_strc_itemgroups_max_items,getvariable(stamp,level,1,0))
+ texsetdimen(d_strc_itemgroups_max_width,getvariable(stamp,level,2,0))
+end
+
+local function registeritemgroup(name,level,nofitems,maxwidth)
+ local n = counts[name]
+ if not trialtypesetting() then
+ -- no trialtypsetting
+ setvariable(f_stamp(name,n), { nofitems, maxwidth }, level)
+ elseif level == 1 then
+ counts[name] = n - 1
+ end
+end
+
+implement {
+ name = "analyzeitemgroup",
+ actions = analyzeitemgroup,
+ arguments = { "string", "integer" }
+}
+
+implement {
+ name = "registeritemgroup",
+ actions = registeritemgroup,
+ arguments = { "string", "integer", "integer", "dimen" }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-itm.mklx b/Master/texmf-dist/tex/context/base/mkxl/strc-itm.mklx
index a3a4c004076..737580a274d 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/strc-itm.mklx
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-itm.mklx
@@ -13,7 +13,12 @@
\writestatus{loading}{ConTeXt Structure Macros / Itemgroups}
-\registerctxluafile{strc-itm}{}
+\unprotect
+
+\newdimension\d_strc_itemgroups_max_width
+\newinteger \c_strc_itemgroups_max_items
+
+\registerctxluafile{strc-itm}{autosuffix}
%D As we analyze/register widths and such we could as well push and pop the numbers
%D at the \LUA\ end (which saves a few calls).
@@ -170,8 +175,6 @@
% \item {test} is this okay?
% \stopitemize
-\unprotect
-
\newconditional\c_strc_itemgroups_sub
\newconditional\c_strc_itemgroups_head
\newconditional\c_strc_itemgroups_intro
@@ -216,8 +219,10 @@
\newdimension \d_strc_itemgroups_list_width
\newdimension \d_strc_itemgroups_asked_width
-\newdimension \d_strc_itemgroups_max_width \def\d_strc_itemgroups_max_width_reference{\d_strc_itemgroups_max_width}
-\newinteger \c_strc_itemgroups_max_items
+%newdimension \d_strc_itemgroups_max_width % defined already, used at the Lua end
+%newinteger \c_strc_itemgroups_max_items % idem
+
+\def\d_strc_itemgroups_max_width_reference{\d_strc_itemgroups_max_width} % no alias!
\newinteger \c_strc_itemgroups_n_of_items
\newinteger \c_strc_itemgroups_nesting
@@ -1221,7 +1226,16 @@
% WS: make the distance between items customizable, think about better default values -> see itemize-1.tex
\strc_itemgroups_set_text_item_distance% HH: moved out and made configurable (sort of)
\removeunwantedspaces
- \hskip\m_strc_itemgroups_text_distance\relax
+ \ifnum\numexpr\c_strc_itemgroups_n_of_items+\plusone\relax=\c_strc_itemgroups_max_items
+ \itemgroupparameter\c!lasttextseparator
+ \else
+ \itemgroupparameter\c!textseparator
+ \fi
+ \ifempty\m_strc_itemgroups_text_distance
+ % safeguard
+ \else
+ \hskip\m_strc_itemgroups_text_distance\relax
+ \fi
\fi
\else
\strc_itemgroups_between_command
@@ -1502,7 +1516,9 @@
\dostoptagged
\fi
\box\b_strc_itemgroups
- \hskip\interwordspace}%
+ \ifzerodim\wd\b_strc_itemgroups\else
+ \hskip\interwordspace % not configureable (yet), could be \c!textdistance
+ \fi}%
\nobreak}
\def\strc_itemgroups_handle_groups_inline_item
@@ -1659,7 +1675,7 @@
\protected\def\strc_itemgroups_set_text_item_distance
{\edef\m_strc_itemgroups_text_distance{\itemgroupparameter\c!textdistance}%
\ifempty\m_strc_itemgroups_text_distance
- %
+ % \let\m_strc_itemgroups_text_distance\zeropoint % safeguard elsewhere
\orelse\ifcsname\??itemgroupdistance\m_strc_itemgroups_text_distance\endcsname
\lastnamedcs
\else
@@ -1978,6 +1994,8 @@
\c!criterium=\v!all, % permits 0 and negative numbers
%\c!option=,
\c!textdistance=\v!space, % none big medium small <dimension>
+ \c!lasttextseparator=\itemgroupparameter\c!textseparator,
+ %\c!lasttextseparator=,
\c!command=\strc_itemgroups_default_command,
\c!indenting=\v!next,
%\c!alignsymbol=v!no,
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-lst.lmt b/Master/texmf-dist/tex/context/base/mkxl/strc-lst.lmt
index 359fbd6b64c..b60b7520875 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/strc-lst.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-lst.lmt
@@ -95,6 +95,7 @@ local v_intro = variables.intro
local v_here = variables.here
local v_component = variables.component
local v_product = variables.product
+local v_file = variables.file
local v_local = variables["local"]
local v_default = variables.default
@@ -443,6 +444,42 @@ local listsorters = {
local filters = setmetatableindex(function(t,k) return t[v_default] end)
+
+local used = { }
+
+function lists.use(tag,filename,class)
+ used[tag] = {
+ names = names, -- optional
+ filename = filename,
+ data = job.loadother(filename),
+ }
+end
+
+implement {
+ name = "uselist",
+ arguments = "3 strings",
+ actions = lists.use,
+}
+
+filters.external = function(specification)
+ local collected = specification.collected or { }
+ local result = { }
+ local nofresult = 0
+ local all = specification.all
+ local names = specification.names
+ setmetatableindex(result,{ external = specification.reference }) -- brr, we also have the name in
+ for i=1,#collected do
+ local v = collected[i]
+ local m = v.metadata
+ if m and names[m.name] or all then
+ nofresult = nofresult + 1
+ result[nofresult] = v
+ end
+ end
+ return result
+end
+
+
local function filtercollected(specification)
--
local names = specification.names or { }
@@ -453,10 +490,10 @@ local function filtercollected(specification)
local forced = specification.forced or { }
local nested = specification.nested or false
local sortorder = specification.sortorder or specification.order
- --
local numbers = documents.data.numbers
local depth = documents.data.depth
local block = false -- all
+ --
local wantedblock, wantedcriterium = lpegmatch(splitter,criterium) -- block:criterium
if wantedblock == "" or wantedblock == v_all or wantedblock == v_text then
criterium = wantedcriterium ~= "" and wantedcriterium or criterium
@@ -473,7 +510,7 @@ local function filtercollected(specification)
names = settings_to_set(names)
end
local all = not next(names) or names[v_all] or false
- --
+ -- --
specification.names = names
specification.criterium = criterium
specification.number = 0 -- obsolete
@@ -853,47 +890,26 @@ filters[v_component] = function(specification)
return result
end
--- filters[v_product] = function(specification)
--- local reference = specification.reference
--- if reference and reference ~= "" then
--- -- local utilitydata = job.loadother(reference,true)
--- local fullname = file.replacesuffix(reference,"tuc")
--- if lfs.isfile(fullname) then
--- local utilitydata = job.loadother(fullname)
--- if utilitydata then
--- local collected = utilitydata.structures.lists.collected or { }
--- setmetatableindex(collected,{ external = reference })
--- return collected
--- end
--- end
--- end
--- return { }
--- end
-
filters[v_product] = function(specification)
local reference = specification.reference
if reference and reference ~= "" then
- local utilitydata = job.loadother(reference,true)
--- local fullname = file.replacesuffix(reference,"tuc")
--- if lfs.isfile(fullname) then
--- local utilitydata = job.loadother(fullname)
- if utilitydata then
- local collected = utilitydata.structures.lists.collected or { }
- local result = { }
- local nofresult = 0
- local all = specification.all
- local names = specification.names
+ local utilitydata = job.loadother(reference)
+ if utilitydata then
+ local collected = utilitydata.structures.lists.collected or { }
+ local result = { }
+ local nofresult = 0
+ local all = specification.all
+ local names = specification.names
setmetatableindex(result,{ external = reference }) -- brr
- for i=1,#collected do
- local v = collected[i]
- local m = v.metadata
- if m and names[m.name] or all then
- nofresult = nofresult + 1
- result[nofresult] = v
- end
+ for i=1,#collected do
+ local v = collected[i]
+ local m = v.metadata
+ if m and names[m.name] or all then
+ nofresult = nofresult + 1
+ result[nofresult] = v
end
- return result
--- end
+ end
+ return result
end
end
return { }
@@ -977,6 +993,14 @@ function lists.getresult(r)
end
function lists.process(specification)
+ local names = specification.names
+ local external = used[names or ""]
+ if external then
+ specification.reference = names
+ specification.names = external.names
+ specification.collected = external.data.structures.lists.collected
+ specification.criterium = "external"
+ end
local result = filtercollected(specification)
local total = #result
lists.result = result
@@ -1542,3 +1566,41 @@ function lists.reordered(entry)
end
return numberdata
end
+
+-- external data
+
+function lists.integrate(utilitydata)
+ local filename = utilitydata.comment.file
+ if filename then
+ local structures = utilitydata.structures
+ if structures then
+ local lists = structures.lists.collected or { }
+ if lists then
+ local sections = structures.sections.collected or { }
+ local pages = structures.pages.collected or { }
+ for i=1,#lists do
+ local entry = lists[i]
+ local references = entry.references
+ if references then
+ local section = references.section
+ local realpage = references.realpage
+ -- maybe entry.* instead:
+ references.sectiondata = section and sections[section]
+ references.pagedata = realpage and pages[realpage]
+ -- get rid of these, maybe even crash as these are bogus
+ -- references.internal = nil
+ -- references.realpage = nil
+ -- references.section = nil
+ if references.x then
+ references.x = nil
+ end
+ if references.y then
+ references.y = nil
+ end
+ references.external = filename
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-lst.mklx b/Master/texmf-dist/tex/context/base/mkxl/strc-lst.mklx
index 66a801241ee..6b8f2504f03 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/strc-lst.mklx
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-lst.mklx
@@ -78,6 +78,12 @@
%\c!expansion=,
\c!limittext=\languageparameter\c!limittext] % not used currently
+%D Kind of new:
+
+\permanent\protected\tolerant\def\uselist[#1]#*[#2]#*[#3]% tag file
+ {\doifelsefiledefined{#1}{}{\usefile[#1][#2]}%
+ \clf_uselist{#1}{#2}{#3}}
+
%D Helpers:
\permanent\protected\def\usenestedliststyleandcolor#style#color% will change
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-mat.lmt b/Master/texmf-dist/tex/context/base/mkxl/strc-mat.lmt
new file mode 100644
index 00000000000..3b2458eac7d
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-mat.lmt
@@ -0,0 +1,30 @@
+if not modules then modules = { } end modules ['strc-mat'] = {
+ version = 1.001,
+ comment = "companion to strc-mat.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local structures = structures
+
+local lists = structures.lists
+local sections = structures.sections
+local helpers = structures.helpers
+----- formulas = structures.formulas --reserved
+
+function helpers.formulanumber(data,spec)
+ if data then
+ local formulanumber = data.formulanumber
+ if formulanumber then
+ sections.number(data,spec,"formulanumber","formulanumber","number")
+ end
+ end
+end
+
+function lists.formulanumber(name,n,spec)
+ local result = lists.result
+ if result then
+ helpers.formulanumber(result[n])
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-mat.mkxl b/Master/texmf-dist/tex/context/base/mkxl/strc-mat.mkxl
index bcbe4a6f87f..2e6c21ad27f 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/strc-mat.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-mat.mkxl
@@ -13,7 +13,7 @@
\writestatus{loading}{ConTeXt Structure Macros / Math Numbering}
-\registerctxluafile{strc-mat}{}
+\registerctxluafile{strc-mat}{autosuffix}
% -- we have potential for captions
% -- this module will use the commandhandler
@@ -141,6 +141,12 @@
\permanent\protected\defcsname\e!start\v!formula\endcsname{\strc_formulas_start_formula{}}
\permanent\protected\defcsname\e!stop \v!formula\endcsname{\strc_formulas_stop_formula}
+\permanent\protected\def\startnamedformula[#1]%
+ {\strc_formulas_start_formula{#1}}
+
+\permanent\protected\def\stopnamedformula
+ {\strc_formulas_stop_formula}
+
\let\strc_formulas_start_formula\relax % defined later
\let\strc_formulas_stop_formula \relax % defined later
@@ -975,13 +981,12 @@
\setupformula
% [\c!split=\v!no,
- [\c!split=\v!text, % multi line no page breaks
+ [\c!split=\v!yes,
\c!numberlocation=,
\c!textdistance=\zeropoint,
- %\c!interlinespace=1.5\lineheight,
+ \c!interlinespace=1.125\lineheight, % back again, to be tuned
\c!textmargin=2\emwidth,
- \c!numbermethod=\v!down,
- \c!interlinespace=]
+ \c!numbermethod=\v!down]
% for the moment (when testing) we use a penalty 1
@@ -1206,12 +1211,15 @@
\fi{#2}%
\fi}
+\def\strc_math_break_here_indeed
+ {\strut\break}
+
\protected\def\strc_math_page_here
{\ifmmode
\ifconditional\c_strc_math_trace_hang
\strc_math_trace_okay{darkyellow}{B P}%
\fi
- \break
+ \strc_math_break_here_indeed
\vadjust pre {\vfill\penalty-100000}%
\strc_math_pickup_again
\fi}
@@ -1221,7 +1229,7 @@
\ifconditional\c_strc_math_trace_hang
\strc_math_trace_okay{darkyellow}{B S}%
\fi
- \break
+ \strc_math_break_here_indeed
\vadjust pre {\penalty\plustenthousand}%
\strc_math_pickup_again
\fi}
@@ -1231,7 +1239,7 @@
\ifconditional\c_strc_math_trace_hang
\strc_math_trace_okay{darkgreen}{B}%
\fi
- \break
+ \strc_math_break_here_indeed
\strc_math_pickup_again
\fi}
@@ -1392,7 +1400,10 @@
\doadaptleftskip\p_margin
\doadaptrightskip\p_margin
\fi
- %
+ % this was lost
+ \edef\p_interlinespace{\formulaparameter\c!interlinespace}%
+ \ifempty\p_interlinespace\else\baselineskip\p_interlinespace\fi
+ % and is now back
\global\setfalse\c_strc_math_aligned_here
\hsize\d_strc_formulas_display_width
\displaywidth\hsize
@@ -1557,7 +1568,8 @@
\iftrialtypesetting\else
\global\advanceby\c_strc_formulas_n\plusone
\fi
- \def\currentformula{#1}%
+ \edef\currentformula{#1}%
+ \usesetupsparameter\formulaparameter % new
\dostarttaggedchained\t!formula\currentformula\??formula
\strc_math_set_options{#2}%
\strc_math_set_split
@@ -1998,6 +2010,19 @@
%D New:
%D
%D \setupformula[snap=yes,snapstep=medium]
+%D
+%D \startbuffer
+%D We test \dorecurse{20}{$x^{#1}$ and $\frac{1}{#1}^x$ and $\sqrt[#1]{x}$ and }that's it.
+%D \stopbuffer
+%D
+%D \startcombination[nx=2,ny=3,location=top]
+%D {\ruledvbox{\hsize.45\textwidth \setupformula[snap=no] \showboxes \enabletrackers [math.snapping=darkred] \getbuffer}} {}
+%D {\ruledvbox{\hsize.45\textwidth \setupformula[snap=no] \disabletrackers[math.snapping] \getbuffer}} {}
+%D {\ruledvbox{\hsize.45\textwidth \setupformula[snap=yes,snapstep=small] \showboxes \darkgreen \enabletrackers [math.snapping=darkred] \getbuffer}} {}
+%D {\ruledvbox{\hsize.45\textwidth \setupformula[snap=yes,snapstep=small] \darkgreen \disabletrackers[math.snapping] \getbuffer}} {}
+%D {\ruledvbox{\hsize.45\textwidth \setupformula[snap=yes,snapstep=big] \showboxes \darkblue \enabletrackers [math.snapping=darkred] \getbuffer}} {}
+%D {\ruledvbox{\hsize.45\textwidth \setupformula[snap=yes,snapstep=big] \darkblue \disabletrackers[math.snapping] \getbuffer}} {}
+%D \stopcombination
\definesystemattribute[mathsnap][public]
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-ref.lmt b/Master/texmf-dist/tex/context/base/mkxl/strc-ref.lmt
index b97a1619b3f..26b1894753c 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/strc-ref.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-ref.lmt
@@ -18,7 +18,7 @@ local format, gmatch, match, strip = string.format, string.gmatch, string.match,
local floor = math.floor
local rawget, tonumber, type, next = rawget, tonumber, type, next
local lpegmatch = lpeg.match
-local insert, remove, copytable = table.insert, table.remove, table.copy
+local insert, remove, copytable, sortedhash = table.insert, table.remove, table.copy, table.sortedhash
local formatters = string.formatters
local P, Cs, lpegmatch = lpeg.P, lpeg.Cs, lpeg.match
@@ -130,6 +130,9 @@ local c_locationcount = texiscount("locationcount")
local c_locationorder = texiscount("locationorder")
local c_lastdestinationattribute = texiscount("lastdestinationattribute")
+local p_splitter = lpeg.splitat(":")
+local p_lower = lpeg.patterns.utf8lower
+
local context = context
local ctx_pushcatcodes = context.pushcatcodes
@@ -494,7 +497,7 @@ implement {
-- no metatable here .. better be sparse
-local function register_from_list(collected,derived,pages,sections)
+local function register_from_list(collected,derived,external)
local derived_g = derived[""] -- global
local derived_p = nil
local derived_c = nil
@@ -556,11 +559,24 @@ local function register_from_list(collected,derived,pages,sections)
end
end
-references.registerfromlist = function(collected,pages,sections)
- register_from_list(collected,derived,pages,sections)
+function references.integrate(utilitydata)
+ local filename = utilitydata.comment.file
+ if filename then
+ -- lists are already internalized
+ local structures = utilitydata.structures
+ if structures then
+ local lists = structures.lists.collected
+ if lists then
+ register_from_list(lists,derived,filename)
+ end
+ end
+ end
end
-references.registerinitializer(function() register_from_list(lists.collected,derived) end)
+references.registerinitializer(function()
+ -- the main document
+ register_from_list(lists.collected,derived)
+end)
-- tracing
@@ -953,7 +969,8 @@ local function resolve(prefix,reference,args,set) -- we start with prefix,refere
local var = splitreference(ri)
if var then
var.reference = ri
- local vo, vi = var.outer, var.inner
+ local vo = var.outer
+ local vi = var.inner
-- we catch this here .. it's a way to pass references with commas
if vi == "name" then
local arguments = var.arguments
@@ -1154,11 +1171,14 @@ local function loadproductreferences(productname,componentname,utilitydata)
report_importing("registering %s reference, kind %a, name %a, prefix %a, reference %a",
"product","regular",productname,prefix,reference)
end
- if not reference.sectiondata then
- reference.sectiondata = sections[reference.section or false]
- end
- if not reference.pagedata then
- reference.pagedata = pages[reference.realpage or false]
+ local references = data.references
+ if references then
+ if not references.sectiondata then
+ references.sectiondata = sections[references.section or false]
+ end
+ if not references.pagedata then
+ references.pagedata = pages[references.realpage or false]
+ end
end
end
end
@@ -1296,26 +1316,37 @@ end)
function references.loadpresets(product,component) -- we can consider a special components hash
if product and component and product~= "" and component ~= "" and not productdata.product then -- maybe: productdata.filename ~= filename
- productdata.product = product
+ productdata.product = product
productdata.component = component
-- todo: use other locator
- local fullname = file.replacesuffix(product,"tuc")
- if lfs.isfile(fullname) then
- local utilitydata = job.loadother(fullname)
- if utilitydata then
- if trace_importing then
- report_importing("loading references for component %a of product %a from %a",component,product,fullname)
- end
- loadproductvariables (product,component,utilitydata)
- loadproductreferences(product,component,utilitydata)
- loadproductcomponents(product,component,utilitydata)
+ local utilitydata = job.loadother(product)
+ if utilitydata then
+ if trace_importing then
+ report_importing("loading references for component %a of product %a",component,product)
end
+ loadproductvariables (product,component,utilitydata)
+ loadproductcomponents(product,component,utilitydata)
+ loadproductreferences(product,component,utilitydata)
+-- loadproductcomponents(product,component,utilitydata)
end
end
end
references.productdata = productdata
+implement {
+ name = "usereferences",
+ public = true,
+ protected = true,
+ arguments = "optional",
+ actions = function(product)
+ local utilitydata = job.loadother(product)
+ if utilitydata then
+ loadexternalreferences(product,utilitydata)
+ end
+ end
+}
+
local useproduct = commands.useproduct
if useproduct then
@@ -1392,6 +1423,10 @@ local function report_identify_outer(set,var,i,type)
end
end
+local function report_identify_auto(set,var,i,type)
+ report_identifying("type %a, reference %a, using auto outer %a",type,reference,var.outer)
+end
+
local function identify_special(set,var,i)
local special = var.special
local s = specials[special]
@@ -1547,6 +1582,61 @@ local function unprefixed_inner(set,var,prefix,collected,derived,tobesaved)
return var
end
+local function identify_auto(set,var,i)
+ local inner = var.inner
+ local prefix = set.prefix or ""
+ if prefix == "" then
+ prefix, inner = lpegmatch(p_splitter,inner)
+ if not inner then
+ inner = var.inner
+ prefix = false
+ end
+ end
+ local function okay(o,where)
+ var.outer = o
+ if trace_identifying then
+ report_identify_auto(set,var,i,where)
+ end
+ return true
+ end
+ for o, odata in sortedhash(externals) do
+ if o == outer or not odata then
+ -- skip this one
+ elseif prefix and prefix ~= "" then
+ local pdata = odata[prefix]
+ if pdata then
+ local r = pdata[inner]
+ if r then
+ return okay(o,"2h")
+ end
+ end
+ -- escape from prefix
+-- local pdata = odata[""]
+-- if pdata then
+-- local r = pdata[inner]
+-- if r then
+-- return okay(o,"2h")
+-- end
+-- end
+ else
+ for p, pdata in sortedhash(odata) do
+ local r = pdata[inner]
+ if r then
+ return okay(o,"2j")
+ end
+ end
+ local pdata = odata[""]
+ if pdata then
+ r = pdata[inner]
+ if r then
+ return okay(o,"2k")
+ end
+ end
+ end
+ end
+ return false
+end
+
local function identify_outer(set,var,i)
local outer = var.outer
local inner = var.inner
@@ -1587,18 +1677,6 @@ local function identify_outer(set,var,i)
end
end
end
- local external = productdata.componentreferences[outer]
- if external then
- local v = identify_inner(set,var,"",external)
- if v then
- v.kind = "outer with inner"
- set.external = true
- if trace_identifying then
- report_identify_outer(set,v,i,"2c")
- end
- return v
- end
- end
local external = productdata.productreferences[outer]
if external then
local vi = external[inner]
@@ -1612,6 +1690,18 @@ local function identify_outer(set,var,i)
return var
end
end
+ local external = productdata.componentreferences[outer]
+ if external then
+ local v = identify_inner(set,var,"",external)
+ if v then
+ v.kind = "outer with inner"
+ set.external = true
+ if trace_identifying then
+ report_identify_outer(set,v,i,"2c")
+ end
+ return v
+ end
+ end
-- the rest
local special = var.special
local arguments = var.arguments
@@ -1675,6 +1765,7 @@ end
local function identify_inner_or_outer(set,var,i)
-- here we fall back on product data
local inner = var.inner
+
if inner and inner ~= "" then
-- first we look up in collected and derived using the current prefix
@@ -1689,6 +1780,10 @@ local function identify_inner_or_outer(set,var,i)
return v
end
+ if var.inner == var.reference and identify_auto(set,var,i) and var.outer and var.outer ~= "" then
+ return identify_outer(set,var,i)
+ end
+
-- nest we look at each component (but we can omit the already consulted one
local jobstructure = job.structure
@@ -1861,6 +1956,9 @@ local function identify(prefix,reference)
elseif spe then
var = identify_special(set,var,i)
elseif var.outer then
+ if var.outer == "auto" then
+ identify_auto(set,var,i)
+ end
var = identify_outer(set,var,i)
elseif var.arguments then
var = identify_arguments(set,var,i)
@@ -2837,9 +2935,6 @@ end
-- experimental:
-local p_splitter = lpeg.splitat(":")
-local p_lower = lpeg.patterns.utf8lower
-
-- We can cache lowercased titles which saves a lot of time, but then
-- we can better have a global cache with weak keys.
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-ref.mklx b/Master/texmf-dist/tex/context/base/mkxl/strc-ref.mklx
index e7073b36ded..a1b6ac22d45 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/strc-ref.mklx
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-ref.mklx
@@ -557,7 +557,7 @@
%D \NC \NC $\star$ \NC \NC\NR
%D \stoptabulate
-\permanent\protected\def\usereferences[#filename]{} % obsolete
+% \permanent\protected\def\usereferences[#filename]{} % defined at the lua end
%D As mentioned we will also use the cross reference mechanism for navigational
%D purposes. The main reason for this is that we want to treat both categories
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-reg.lmt b/Master/texmf-dist/tex/context/base/mkxl/strc-reg.lmt
index a3a7dae6c88..b66b229212c 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/strc-reg.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-reg.lmt
@@ -1037,38 +1037,72 @@ function registers.finalize(data,options) -- maps character to index (order)
data.result = split
end
--- local function analyzeregister(class,options)
--- local data = collected[class]
--- if data and data.entries then
--- options = options or { }
--- sorters.setlanguage(options.language,options.method,options.numberorder)
--- registers.filter(data,options) -- filter entries into results (criteria)
--- registers.prepare(data,options) -- adds split table parallel to list table
--- registers.sort(data,options) -- sorts results
--- registers.unique(data,options) -- get rid of duplicates
--- registers.finalize(data,options) -- split result in ranges
--- data.metadata.sorted = true
--- return data.metadata.nofsorted or 0
--- else
--- return 0
--- end
--- end
+local used = { }
+
+function registers.use(tag,filename,class,prefix)
+ used[tag] = {
+ class = class,
+ filename = filename,
+ data = job.loadother(filename),
+ prefix = prefix or class,
+ }
+end
+
+implement {
+ name = "useregister",
+ arguments = "4 strings",
+ actions = registers.use,
+}
+
+implement {
+ name = "registerprefix",
+ arguments = "string",
+ actions = function(tag)
+ local u = used[tag]
+ if u then
+ context(u.prefix)
+ end
+ end
+}
+
+function registers.tweak(data,options)
+ -- Just in case it's needed.
+end
local function analyzeregister(class,options)
local data = rawget(collected,class)
if not data then
- local list = utilities.parsers.settings_to_array(class)
- local entries = { }
- local metadata = false
+ local list = utilities.parsers.settings_to_array(class)
+ local entries = { }
+ local nofentries = 0
+ local metadata = false
for i=1,#list do
local l = list[i]
+ local u = used[l]
local d = collected[l]
- local e = d.entries
- for i=1,#e do
- entries[#entries+1] = e[i]
+ if u then
+ local collected = u.data.structures.registers.collected
+ local class = u.class
+ if collected and class then
+ d = collected[class]
+ end
end
- if not metadata then
- metadata = d.metadata
+ if d then
+ local e = d.entries
+ local u = u and { u.prefix } or nil
+ for i=1,#e do
+ local ei = e[i]
+ nofentries = nofentries + 1
+ entries[nofentries] = ei
+ if u then
+ local eil = ei.list
+ eil[#eil+1] = u
+ ei.external = l -- this is the (current) abstract tag, used for prefix
+ end
+ end
+ if not metadata then
+ metadata = d.metadata
+ end
end
end
data = {
@@ -1080,11 +1114,12 @@ local function analyzeregister(class,options)
if data and data.entries then
options = options or { }
sorters.setlanguage(options.language,options.method,options.numberorder)
- registers.filter(data,options) -- filter entries into results (criteria)
- registers.prepare(data,options) -- adds split table parallel to list table
- registers.sort(data,options) -- sorts results
- registers.unique(data,options) -- get rid of duplicates
- registers.finalize(data,options) -- split result in ranges
+ registers.filter(data,options) -- filter entries into results (criteria)
+ registers.prepare(data,options) -- adds split table parallel to list table
+ registers.sort(data,options) -- sorts results
+ registers.unique(data,options) -- get rid of duplicates
+ registers.tweak(data,options) -- plugin
+ registers.finalize(data,options)-- split result in ranges
data.metadata.sorted = true
return data.metadata.nofsorted or 0
else
@@ -1131,12 +1166,12 @@ local function pagerange(f_entry,t_entry,is_last,prefixspec,pagespec)
ctx_registerpagerange(
f_entry.metadata.name or "",
f_entry.processors and f_entry.processors[2] or "",
- fer.internal or 0,
+ f_entry.external or fer.internal or 0,
fer.realpage or 0,
function()
h_prefixpage(f_entry,prefixspec,pagespec)
end,
- ter.internal or 0,
+ t_entry.external or ter.internal or 0,
ter.lastrealpage or ter.realpage or 0,
function()
if is_last then
@@ -1153,7 +1188,7 @@ local function pagenumber(entry,prefixspec,pagespec)
ctx_registeronepage(
entry.metadata.name or "",
entry.processors and entry.processors[2] or "",
- er.internal or 0,
+ entry.external or er.internal or 0,
er.realpage or 0,
function() h_prefixpage(entry,prefixspec,pagespec) end
)
@@ -1162,9 +1197,10 @@ end
local function packed(f_entry,t_entry)
local fer = f_entry.references
local ter = t_entry.references
+-- todo: make sure we don't end up here with external
ctx_registerpacked(
- fer.internal or 0,
- ter.internal or 0
+ f_entry.external or fer.internal or 0,
+ t_entry.external or ter.internal or 0
)
end
@@ -1286,6 +1322,10 @@ function registers.flush(data,options,prefixspec,pagespec)
-- report_registers("invalid see entry in register %a, reference %a",entry.metadata.name,list[1][1])
end
end
+ if entry.external then
+ local list = entry.list
+ list[#list] = nil
+ end
end
-- ok, this is tricky: we use e[i] delayed so we need it to be local
-- but we don't want to allocate too many entries so there we go
@@ -1497,7 +1537,7 @@ function registers.flush(data,options,prefixspec,pagespec)
local seeword = entry.seeword
local seetext = seeword.text or ""
local processor = seeword.processor or (entry.processors and entry.processors[1]) or ""
- local seeindex = entry.references.seeindex or ""
+ local seeindex = entry.external or entry.references.seeindex or ""
ctx_registerseeword(
metadata.name or "",
i,
@@ -1696,3 +1736,46 @@ interfaces.implement {
arguments = { "string", "string", "integer" },
actions = { registers.findinternal, context },
}
+
+-- external data
+
+function registers.integrate(utilitydata)
+ local filename = utilitydata.comment.file
+ if filename then
+ local structures = utilitydata.structures
+ if structures then
+ local registers = structures.registers.collected or { }
+ if registers then
+ local sections = structures.sections.collected or { }
+ local pages = structures.pages .collected or { }
+ for class, register in next, registers do
+ local entries = register.entries
+ if entries then
+ for i=1,#entries do
+ local entry = entries[i]
+ local references = entry.references
+ if references then
+ local section = references.section
+ local realpage = references.realpage
+ -- maybe entry.* instead:
+ references.sectiondata = section and sections[section]
+ references.pagedata = realpage and pages[realpage]
+ -- get rid of these, maybe even crash as these are bogus
+ -- references.internal = nil -- or 0
+ -- references.realpage = nil -- or 0
+ -- references.section = nil -- or 0
+ if references.x then
+ references.x = nil
+ end
+ if references.y then
+ references.y = nil
+ end
+ references.external = filename -- not really needed
+ end
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-reg.mkxl b/Master/texmf-dist/tex/context/base/mkxl/strc-reg.mkxl
index 485b68b746c..afe3d27a09c 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/strc-reg.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-reg.mkxl
@@ -757,6 +757,41 @@
% todo \index{todo}
% \stoptext
+%D Kind of new:
+
+% % index-1.tex:
+%
+% \setupinteraction[state=start]
+% \starttext
+% test \index{entry WB.1} \page empty \page
+% test \index{another WB.1} \page empty \page
+% test \index{onemore WB.1} \page empty \page
+% test \index{whatever WB.1} \page empty \page
+% test \index{common} \page empty \page
+% \placeregister[index]
+% \stoptext
+%
+% % index-2.tex:
+%
+% \setupinteraction[state=start]
+% \defineregister[xedni]
+% \useregister[workbook][index-1][index][WB ]
+% \starttext
+% test \index{onemore TB.1} \page
+% test \index{another TB.1} \page
+% test \index{entry TB.1} \page
+% test \index{common} \page
+% test \xedni{onemore TB.2} \page
+% test \xedni{another TB.2} \page
+% test \xedni{entry TB.2} \page
+% test \xedni{common} \page
+% \placeregister[index,xedni,workbook]
+% \stoptext
+
+\permanent\protected\tolerant\def\useregister[#1]#*[#2]#*[#3]#*[#4]% tag file class prefix
+ {\doifelsefiledefined{#1}{}{\usefile[#1][#2]}%
+ \clf_useregister{#1}{#2}{#3}{#4}}
+
%D Character rendering (sections):
\installcorenamespace{registerindicator}
@@ -1070,17 +1105,45 @@
\let\currentregisterrealpage\!!zerocount % todo: more general accessor
-\permanent\protected\def\withregisterpagecommand#1#2#3#4%
+% keep as reference
+%
+% \permanent\protected\def\withregisterpagecommand#1#2#3#4%
+% {\ifcase#3\relax
+% {\tt [entry\space not\space flushed]}%
+% \else
+% \def\currentregisterpageindex{#2}%
+% \def\currentregisterrealpage{#3}%
+% \iflocation
+% \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]%
+% \else
+% \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}%
+% \fi
+% \fi}
+%
+% todo: adapt \strc_references_goto_internal to take an extra argument, the ref
+
+\permanent\protected\def\withregisterpagecommand#1#2#3#4% #1:processor #2:internal #3:realpage #4:page
{\ifcase#3\relax
{\tt [entry\space not\space flushed]}%
\else
\def\currentregisterpageindex{#2}%
\def\currentregisterrealpage{#3}%
- \iflocation
- \strc_references_goto_internal{\applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}}[internal(#2)]%
+ \ifchknum\currentregisterpageindex\or
+ \lettonothing\currentregisterpageprefix
\else
- \applyprocessor{#1}{\registerparameter\c!pagecommand{#4}}%
+ \def\currentregisterpageprefix{\clf_registerprefix{\currentregisterpageindex}}%
\fi
+ \iflocation
+ \ifempty\currentregisterpageprefix
+ \strc_references_get_simple_reference{internal(\currentregisterpageindex)}%
+ \else
+ \strc_references_get_simple_reference{\currentregisterpageindex::page(\currentregisterrealpage)}%
+ \fi
+ \global\lastsavedreferenceattribute\currentreferenceattribute
+ \c_attr_reference\currentreferenceattribute
+ \setlocationattributes
+ \fi
+ \applyprocessor{#1}{\currentregisterpageprefix\registerparameter\c!pagecommand{#4}}%
\fi}
\lettonothing\m_current_register
@@ -1151,7 +1214,9 @@
\iflocation
\def\currentregisterseeindex{#4}%
\ifconditional\c_strc_registers_text_interaction
- \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#2}{#5}}[internal(#3)]%
+ \ifchknum\currentregisterpageindex\or
+ \strc_references_goto_internal{\setlocationcolor\doapplyregisterentrycommand{#2}{#5}}[internal(#3)]%
+ \fi
\else
\doapplyregisterentrycommand{#2}{#5}%
\fi
@@ -1179,6 +1244,30 @@
\applyprocessor{#1}{#2}%
\fi}
+% \permanent\protected\def\defaultregisterseeword#1#2#3#4#5#6#7% class i n #3:processor #4:internal #5:seeindex #6:word
+% {\pushcurrentregister{#1}%
+% \ifnum#2=\plusone
+% \registerpageseparator
+% \fi
+% \global\setconstant\c_strc_registers_page_state\plustwo
+% \def\currentregisterpageindex{#5}%
+% \dostarttagged\t!registersee\empty
+% \settrue\c_strc_registers_page_done
+% \iflocation
+% \def\currentregisterseeindex{#6}%
+% \else
+% \lettonothing\currentregisterseeindex
+% \fi
+% \ifnum#2=\plusone
+% \labeltexts\v!see{\doapplyregisterseecommand{#4}{#7}}%
+% \orelse\ifnum#2=#3\relax
+% \labeltexts\v!and{\doapplyregisterseecommand{#4}{#7}}%
+% \else
+% ,\space\doapplyregisterseecommand{#4}{#7}%
+% \fi
+% \dostoptagged
+% \popcurrentregister}
+
\permanent\protected\def\defaultregisterseeword#1#2#3#4#5#6#7% class i n #3:processor #4:internal #5:seeindex #6:word
{\pushcurrentregister{#1}%
\ifnum#2=\plusone
@@ -1186,19 +1275,30 @@
\fi
\global\setconstant\c_strc_registers_page_state\plustwo
\def\currentregisterpageindex{#5}%
+ \def\currentregisterseeindex{#6}%
\dostarttagged\t!registersee\empty
\settrue\c_strc_registers_page_done
- \iflocation
- \def\currentregisterseeindex{#6}%
+ \ifchknum\currentregisterseeindex\or
+ \lettonothing\currentregisterpageprefix
\else
- \lettonothing\currentregisterseeindex
+ \def\currentregisterpageprefix{\clf_registerprefix{\currentregisterseeindex}}%
+ \fi
+ \iflocation
+ \ifempty\currentregisterpageprefix
+ \strc_references_get_simple_reference{internal(\currentregisterseeindex)}%
+ \else
+ \strc_references_get_simple_reference{\currentregisterpageindex::page(\currentregisterrealpage)}%
+ \fi
+ \global\lastsavedreferenceattribute\currentreferenceattribute
+ \c_attr_reference\currentreferenceattribute
+ \setlocationattributes
\fi
\ifnum#2=\plusone
- \labeltexts\v!see{\doapplyregisterseecommand{#4}{#7}}%
+ \labeltexts\v!see{\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}}%
\orelse\ifnum#2=#3\relax
- \labeltexts\v!and{\doapplyregisterseecommand{#4}{#7}}%
+ \labeltexts\v!and{\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}}%
\else
- ,\space\doapplyregisterseecommand{#4}{#7}%
+ ,\space\doapplyregisterseecommand{#4}{\currentregisterpageprefix#7}%
\fi
\dostoptagged
\popcurrentregister}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-sec.mkxl b/Master/texmf-dist/tex/context/base/mkxl/strc-sec.mkxl
index 002945208f2..227d24704dc 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/strc-sec.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-sec.mkxl
@@ -125,6 +125,8 @@
% \section{bla 2} \subsection{bla 2 1} \subsection{bla 2 2}
% }
+\mutable\lettonothing\currentstructureextradata
+
\protected\def\strc_sectioning_register#1#2#3% #1=interfaced-settings, #2=optional user data (not yet supported)
{\begingroup
\setupstructure[\c!name={#1},#2]%
@@ -143,6 +145,7 @@
\xdef\currentstructuresaveinlist {\structureparameter\c!saveinlist}%
\xdef\currentstructureincrementnumber{\structureparameter\c!incrementnumber}%
\xdef\currentstructureplaceholder {\structureparameter\c!placeholder}%
+ \xdef\currentstructureextradata {\structureparameter\c!extradata}%
\ifx\currentstructureexpansion\s!xml
\xmlstartraw
\xdef\currentstructuretitle {\structureparameter\c!title}%
@@ -774,10 +777,6 @@
\newtoks\everyheadsynchronization
-% \appendtoks
-% \currentstructuresynchronize
-% \to \everyheadsynchronization
-
\aliased\let\currentstructuresynchronize\donothing
\appendtoks
@@ -785,9 +784,15 @@
\enforced\glet\currentstructuresynchronize\donothing
\to \everyheadsynchronization
+
\permanent\protected\def\theheadsynchronization % public
{% no, interferes: \signalcharacter
- \the\everyheadsynchronization}
+ \the\everyheadsynchronization
+ % new, this might move to a better place, e.g. first in the box
+ \currentstructureextradata
+ \lettonothing\currentstructureextradata
+ % done (can be used for e.g. index entries)
+ }
% BEWARE: \marking[section]{my text} does not work as we use list indices instead
% so we need a 'keep track of raw set option' (or maybe a funny internal prefix)
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-syn.lmt b/Master/texmf-dist/tex/context/base/mkxl/strc-syn.lmt
new file mode 100644
index 00000000000..940b982a72e
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-syn.lmt
@@ -0,0 +1,420 @@
+if not modules then modules = { } end modules ['strc-syn'] = {
+ version = 1.001,
+ comment = "companion to str-syn.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 sortedkeys = table.sortedkeys
+
+local context = context
+local implement = interfaces.implement
+
+local allocate = utilities.storage.allocate
+
+local sorters = sorters
+
+local structures = structures
+local synonyms = structures.synonyms
+local tags = structures.tags
+
+local collected = allocate()
+local tobesaved = allocate()
+
+local firstofsplit = sorters.firstofsplit
+local strip = sorters.strip
+local splitter = sorters.splitters.utf
+
+synonyms.collected = collected
+synonyms.tobesaved = tobesaved
+
+local progressions = { } -- false=not_yet_shown true=shown
+
+local variables = interfaces.variables
+local v_all = variables.all
+local v_current = variables.current
+
+local function initializer()
+ collected = synonyms.collected
+ tobesaved = synonyms.tobesaved
+end
+
+local function finalizer()
+ for entry, data in next, tobesaved do
+ data.hash = nil
+ -- being sparse can be an option but often we actually do want the
+ -- whole list so we don't do this ... only as possible option
+ --
+-- maybe pages = sortedkeys(pages) is more efficient
+ --
+ -- local entries = data.entries
+ -- local t = { }
+ -- local n = 0
+ -- for i=1,#entries do
+ -- local e = entries[i]
+ -- if e.definition.shown then
+ -- n = n + 1
+ -- t[n] = e
+ -- end
+ -- end
+ -- data.entries = t
+ end
+end
+
+job.register('structures.synonyms.collected', tobesaved, initializer, finalizer)
+
+-- todo: allocate becomes metatable
+
+table.setmetatableindex(tobesaved,function(t,k)
+ local v = {
+ metadata = {
+ language = 'en',
+ sorted = false,
+ class = v
+ },
+ entries = {
+ },
+ hash = {
+ }
+ }
+ t[k] = v
+ return v
+end)
+
+function synonyms.define(class,kind)
+ local data = tobesaved[class]
+ data.metadata.kind = kind
+end
+
+function synonyms.register(class,kind,spec)
+ local data = tobesaved[class]
+ local hash = data.hash
+ local definition = spec.definition
+ local tag = definition.tag or ""
+ data.metadata.kind = kind -- runtime, not saved in format (yet)
+ if not hash[tag] then
+ local entries = data.entries
+ entries[#entries+1] = spec
+ hash[tag] = spec
+ end
+end
+
+function synonyms.registerused(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ if okay then
+ local definition = okay.definition
+ definition.used = true
+ definition.list = true
+ end
+end
+
+function synonyms.registershown(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ if okay then
+ local definition = okay.definition
+ definition.shown = true
+ definition.list = true
+ end
+end
+
+function synonyms.isused(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ return okay and okay.definition.used or false
+end
+
+function synonyms.isshown(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ return okay and okay.definition.shown or false
+end
+
+local function resetused(class)
+ for tag, data in next, tobesaved[class].hash do
+ data.definition.used = nil
+ end
+end
+
+local function resetshown(class)
+ for tag, data in next, tobesaved[class].hash do
+ data.definition.shown = nil
+ end
+end
+
+local function resetlist(class)
+ for tag, data in next, tobesaved[class].hash do
+ data.definition.list = nil
+ end
+end
+
+local function resetall(class)
+ for tag, data in next, tobesaved[class].hash do
+ local definition = data.definition
+ definition.used = nil
+ definition.shown = nil
+ definition.list = nil
+ end
+end
+
+synonyms.resetused = resetused
+synonyms.resetshown = resetshown
+synonyms.resetlist = resetlist
+synonyms.resetall = resetall
+
+function synonyms.reset(class,what)
+ if what == "progress" then
+ progressions = { }
+ elseif what == "used" then
+ resetused(class)
+ elseif what == "shown" then
+ resetshown(class)
+ elseif what == "list" then
+ resetlist(class)
+ else
+ resetall(class)
+ end
+end
+
+function synonyms.synonym(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ if okay then
+ local definition = okay.definition
+ definition.used = true
+ definition.list = true
+ context(definition.synonym)
+ end
+ if progressions[tag] == nil then
+ progressions[tag] = false -- not yet shown
+ end
+end
+
+function synonyms.meaning(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ if okay then
+ local definition = okay.definition
+ definition.shown = true
+ definition.list = true
+ context(definition.meaning)
+ end
+end
+
+function synonyms.pages(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ if okay then
+ local definition = okay.definition
+ local pages = definition.pages
+ if pages and next(pages) then
+ context("%,t",sortedkeys(pages))
+ end
+ end
+end
+
+local ctx_latelua = context.latelua
+
+local function enhance(data)
+ local page = tex.getcount("realpageno")
+ data.pages[page] = true
+end
+
+function synonyms.enhance(class,tag)
+ local data = tobesaved[class]
+ local okay = data.hash[tag]
+ if okay then
+ local definition = okay.definition
+ local pages = definition.pages
+ if not pages then
+ pages = { }
+ definition.pages = pages
+ end
+ ctx_latelua { action = enhance, pages = pages }
+ end
+end
+
+synonyms.compare = sorters.comparers.basic -- (a,b)
+
+function synonyms.filter(data,options)
+ local result = { }
+ local entries = data.entries
+ local criterium = options and options.criterium
+ if criterium == v_all then
+ for i=1,#entries do
+ result[i] = entries[i]
+ end
+ else
+ for i=1,#entries do
+ local entry = entries[i]
+ local definition = entry.definition
+ if definition.list then
+ local tag = definition.tag
+ local done = progressions[tag]
+ if done == false then
+ result[#result+1] = entry
+ progressions[tag] = true
+ end
+ end
+ end
+ if criterium == v_current then
+ progressions = { }
+ end
+ end
+ data.result = result
+end
+
+function synonyms.prepare(data)
+ local result = data.result
+ if result then
+ for i=1, #result do
+ local entry = result[i]
+ local definition = entry.definition
+ if definition then
+ local srt = definition.sortkey or ""
+ local tag = definition.tag or ""
+ local key = (srt ~= "" and srt) or (tag ~= "" and tag) or definition.synonym
+ if key then
+ entry.split = splitter(strip(key))
+ end
+ end
+ end
+ end
+end
+
+function synonyms.sort(data,options)
+ sorters.sort(data.result,synonyms.compare)
+ data.metadata.sorted = true
+end
+
+function synonyms.finalize(data,options) -- mostly the same as registers so we will generalize it: sorters.split
+ local result = data.result
+ local split = { }
+ local nofsplit = 0
+ local lasttag = nil
+ local lasttag = nil
+ local nofdone = 0
+ for k=1,#result do
+ local entry = result[k]
+ local first, tag = firstofsplit(entry)
+ if tag ~= lasttag then
+ -- if trace_registers then
+ -- report_registers("splitting at %a",tag)
+ -- end
+ done = { }
+ nofdone = 0
+ nofsplit = nofsplit + 1
+ lasttag = tag
+ split[nofsplit] = { tag = tag, data = done }
+ end
+ nofdone = nofdone + 1
+ done[nofdone] = entry
+ end
+ data.result = split
+end
+
+-- for now, maybe at some point we will do a multipass or so
+-- maybe pass the settings differently
+
+local ctx_synonymentry = context.synonymentry
+
+function synonyms.flush(data,options)
+ local result = data.result
+ for i=1,#result do
+ local sublist = result[i]
+ local data = sublist.data
+ for d=1,#data do
+ local entry = data[d].definition
+ ctx_synonymentry(d,entry.tag,entry.synonym,entry.meaning or "")
+ end
+ end
+ data.result = nil
+ data.metadata.sorted = false
+end
+
+function synonyms.analyzed(class,options)
+ local data = collected[class]
+ if data and data.entries then
+ options = options or { }
+ sorters.setlanguage(options.language,options.method)
+ synonyms.filter(data,options) -- filters entries to result
+ synonyms.prepare(data,options) -- adds split table parallel to list table
+ synonyms.sort(data,options) -- sorts entries in result
+ synonyms.finalize(data,options) -- do things with data.entries
+ data.metadata.sorted = true
+ end
+ return data and data.metadata.sorted and data.result and next(data.result)
+end
+
+function synonyms.process(class,options)
+ if synonyms.analyzed(class,options) then
+ synonyms.flush(collected[class],options)
+ end
+end
+
+-- todo: local higher up
+
+implement { name = "registerusedsynonym", actions = synonyms.registerused, arguments = "2 strings" }
+implement { name = "registershownsynonym", actions = synonyms.registershown, arguments = "2 strings" }
+implement { name = "synonymmeaning", actions = synonyms.meaning, arguments = "2 arguments" }
+implement { name = "synonymname", actions = synonyms.synonym, arguments = "2 arguments" }
+implement { name = "synonympages", actions = synonyms.pages, arguments = "2 arguments" }
+implement { name = "enhancesynonym", actions = synonyms.enhance, arguments = "2 arguments" }
+-- { name = "resetusedsynonyms", actions = resetused, arguments = "string" }
+-- { name = "resetshownsynonyms", actions = resetshown, arguments = "string" }
+-- { name = "resetlistsynonyms", actions = resetlist, arguments = "string" }
+implement { name = "resetsynonyms", actions = synonyms.reset, arguments = "2 strings" }
+
+implement {
+ name = "doifelsesynonymused",
+ actions = { synonyms.isused, commands.doifelse },
+ arguments = "2 arguments",
+}
+
+implement {
+ name = "doifelsesynonymshown",
+ actions = { synonyms.isshown, commands.doifelse },
+ arguments = "2 arguments",
+}
+
+implement {
+ name = "registersynonym",
+ actions = synonyms.register,
+ arguments = {
+ "string",
+ "string",
+ {
+ { "metadata", {
+ { "catcodes", "integer" },
+ { "coding" },
+ { "xmlroot" }
+ }
+ },
+ {
+ "definition", {
+ { "tag" },
+ { "synonym" },
+ { "meaning" },
+ { "sortkey" },
+ { "used", "boolean" }
+ }
+ }
+ }
+ }
+}
+
+implement {
+ name = "processsynonyms",
+ actions = synonyms.process,
+ arguments = {
+ "string",
+ {
+ { "criterium" },
+ { "language" },
+ { "method" }
+ }
+ }
+}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/strc-syn.mkxl b/Master/texmf-dist/tex/context/base/mkxl/strc-syn.mkxl
index af6d0c6e204..9b4c37ceb53 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/strc-syn.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/strc-syn.mkxl
@@ -13,7 +13,7 @@
\writestatus{loading}{ConTeXt Structure Macros / Synonyms and Sorting}
-\registerctxluafile{strc-syn}{}
+\registerctxluafile{strc-syn}{autosuffix}
%D Although we could nowadays build this on top of regular lists we keep this
%D more efficient variant around. Eventually we can add some options to lists
@@ -354,24 +354,37 @@
}%
\relax
\ifx\currentsynonymoption\v!yes
- \instance\setuxvalue\currentsynonymtag{\strc_synonyms_insert{\currentsynonym}{\currentsynonymtag}}%
+ %\instance\setuxvalue\currentsynonymtag{\strc_synonyms_insert{\currentsynonym}{\currentsynonymtag}}%
+ \protected\instance\xdefcsname\currentsynonymtag\endcsname
+ {\strc_synonyms_insert{\currentsynonym}{\currentsynonymtag}}%
\fi
\fi
\endgroup}
\permanent\tolerant\protected\def\registersynonym [#1]#*[#2]{\clf_registerusedsynonym{#1}{#2}}
-\permanent \protected\def\currentsynonymname {\clf_synonymname{\currentsimplelist}{\currentsynonymtag}}
-\permanent \protected\def\currentsynonymmeaning {\clf_synonymmeaning{\currentsimplelist}{\currentsynonymtag}}
-\permanent \protected\def\doifelsecurrentsynonymused {\clf_doifelsesynonymused{\currentsimplelist}{\currentsynonymtag}}
-\permanent \protected\def\doifelsecurrentsynonymshown{\clf_doifelsesynonymshown{\currentsimplelist}{\currentsynonymtag}}
+\permanent \protected\def\currentsynonymname {\clf_synonymname\currentsimplelist\currentsynonymtag}
+\permanent \protected\def\currentsynonymmeaning {\clf_synonymmeaning\currentsimplelist\currentsynonymtag}
+\permanent \protected\def\currentsynonympages {\clf_synonympages\currentsimplelist\currentsynonymtag}
+\permanent \protected\def\doifelsecurrentsynonymused {\clf_doifelsesynonymused\currentsimplelist\currentsynonymtag}
+\permanent \protected\def\doifelsecurrentsynonymshown{\clf_doifelsesynonymshown\currentsimplelist\currentsynonymtag}
\permanent \protected\def\resetusedsynonyms [#1]{\clf_resetsynonyms{#1}{used}}
\permanent \protected\def\resetshownsynonyms [#1]{\clf_resetsynonyms{#1}{shown}}
\permanent \protected\def\resetlistsynonyms [#1]{\clf_resetsynonyms{#1}{list}}
\permanent \protected\def\resetsynonyms [#1]{\clf_resetsynonyms{#1}{all}}
\permanent \protected\def\resetsynonymsprogress [#1]{\clf_resetsynonyms{#1}{progress}}
+\permanent\protected\def\registercurrentsynonympage % \registercurrentsortingpage
+ {\ifcstok{\simplelistparameter\v!page}\v!yes
+ \clf_enhancesynonym\currentsimplelist\currentsortingtag
+ \fi}
+
\aliased\let\rawsynonymname \clf_synonymname
\aliased\let\rawsynonymmeaning\clf_synonymmeaning
+\aliased\let\rawsynonympages \clf_synonympages
+
+\permanent\protected\def\synonymname [#1]#*[#2]{\clf_synonymname {#1}{#2}}
+\permanent\protected\def\synonymmeaning[#1]#*[#2]{\clf_synonymmeaning{#1}{#2}}
+\permanent\protected\def\synonympages [#1]#*[#2]{\clf_synonympages {#1}{#2}}
\installcorenamespace{simplelistalternative} % specific ways of rendering a list
\installcorenamespace{simplelistrenderings} % a namespace for setups (rather local)
@@ -424,6 +437,7 @@
\dostarttaggedchained\t!synonym\currentsynonym\??simplelist
\dotagsynonym
\usesimpleliststyleandcolor\c!synonymstyle\c!synonymcolor
+ \registercurrentsynonympage
\simplelistparameter\c!synonymcommand{\currentsynonymname}%
\dostoptagged
\endgroup
@@ -523,9 +537,7 @@
\aliased\let\setupsorting\setupsimplelist
-% if #3=\relax or \v!none, then no command but still protected
-
-% these might become private
+% some of these might become private
\mutable\lettonothing\currentsortingoption
\mutable\lettonothing\currentsortingcoding
@@ -536,10 +548,14 @@
\permanent\tolerant\protected\def\definesorting[#1]#*[#2]#*[#3]%
{\ifnum\lastarguments=\plusthree
- \doifnot{#3}\v!none
- {\ifx#3\relax \else
- \protected\instance\def#3##1{\strc_sorting_insert{#1}{##1}}%
- \fi}%
+ %\ifparameter#3\or
+ \ifcstok{#3}\v!none
+ % skip
+ \orelse\ifrelax#3\relax
+ % skip
+ \else
+ \protected\instance\def#3##1{\strc_sorting_insert{#1}{##1}}%
+ \fi
\frozen\instance\protected\defcsname#1\endcsname{\definesort[\v!no][#1]}%
\else
\frozen\instance\protected\defcsname#1\endcsname{\definesort[\v!yes][#1]}%
@@ -600,14 +616,25 @@
}%
\relax
\ifx\currentsortingoption\v!yes
- \instance\setuxvalue\currentsortingtag{\strc_sorting_insert{\currentsorting}{\currentsortingtag}}%
+ %\instance\setuxvalue\currentsortingtag{\strc_sorting_insert{\currentsorting}{\currentsortingtag}}%
+ \protected\instance\xdefcsname\currentsortingtag\endcsname
+ {\strc_sorting_insert{\currentsorting}{\currentsortingtag}}%
\fi
\fi
\endgroup}
-\permanent\protected\def\currentsortingname {\clf_synonymname {\currentsimplelist}{\currentsortingtag}}
-\permanent\protected\def\doifelsecurrentsortingused {\clf_doifelsesynonymused {\currentsimplelist}{\currentsortingtag}}
-\permanent\protected\def\resetusedsortings [#1]{\clf_resetusedsynonyms {#1}}
+\permanent\protected\def\currentsortingname {\clf_synonymname\currentsimplelist\currentsortingtag}
+\permanent\protected\def\currentsortingpages {\clf_synonympages\currentsimplelist\currentsortingtag}
+\permanent\protected\def\doifelsecurrentsortingused {\clf_doifelsesynonymused\currentsimplelist\currentsortingtag}
+\permanent\protected\def\resetusedsortings [#1]{\clf_resetusedsynonyms{#1}}
+
+\permanent\protected\def\sortingname [#1]#*[#2]{\clf_synonymname {#1}{#2}}
+\permanent\protected\def\sortingpages[#1]#*[#2]{\clf_synonympages{#1}{#2}}
+
+\aliased\let\rawsortingname \clf_synonymname
+\aliased\let\rawsortingpages\clf_synonymmeaning
+
+\aliased\let\registercurrentsortingpage\registercurrentsynonympage
\setupsimplelist
[\v!sorting]
@@ -641,6 +668,7 @@
\dostarttaggedchained\t!sorting\currentsorting\??simplelist
\dotagsorting
\usesimpleliststyleandcolor\c!style\c!color
+ \registercurrentsortingpage
\currentsortingname
\dostoptagged
\endgroup
@@ -649,6 +677,9 @@
\permanent\tolerant\protected\def\registersort[#1]#*[#2]%
{\clf_registerusedsynonym{#1}{#2}}
+\permanent\tolerant\protected\def\registersortpage[#1]#*[#2]%
+ {\clf_enhancesynonym{#1}{#2}}
+
% before after
%
% maybe just 'commandset' and then combine
diff --git a/Master/texmf-dist/tex/context/base/mkxl/tabl-ntb.lmt b/Master/texmf-dist/tex/context/base/mkxl/tabl-ntb.lmt
new file mode 100644
index 00000000000..a307d046a8a
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/tabl-ntb.lmt
@@ -0,0 +1,143 @@
+if not modules then modules = { } end modules ['tabl-ntb'] = {
+ version = 1.001,
+ comment = "companion to tabl-ntb.mkxl",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local context = context
+
+local a_tablesection = attributes.system("tablesection")
+
+local hlist_code = nodes.nodecodes.hlist
+
+local nuts = nodes.nuts
+local tonode = nuts.tonode
+local getbox = nuts.getbox
+local getlist = nuts.getlist
+local getid = nuts.getid
+local getnext = nuts.getnext
+local setnext = nuts.setnext
+local getattr = nuts.getattr
+local copylist = nuts.copylist
+local flushlist = nuts.flushlist
+
+local integer_value = tokens.values.integer
+
+local implement = interfaces.implement
+
+local list = { }
+local sections = { }
+
+local function check(b)
+ local c = getbox(b)
+ local l = c and getlist(c)
+ local d = false
+ local n = 0
+ while l do
+ if getid(l) == hlist_code then
+ local line = getattr(l,a_tablesection)
+ if line and line ~= d then
+ local s = sections[line]
+ if s then
+ local count = s[2]
+ local last = l
+ local next = getnext(l)
+ while next and count > 0 do
+ last = next
+ next = getnext(next)
+ count = count - 1
+ end
+ setnext(last)
+ list[line] = { l, copylist(l) }
+ if next then
+ setnext(last,next)
+ end
+ d = line
+ end
+ end
+ n = n + 1
+ end
+ l = getnext(l)
+ end
+end
+
+local function reset(b)
+ for k, v in next, list do
+ flushlist(v[2])
+ end
+ list = { }
+ sections = { }
+end
+
+local function locate(b)
+ local c = getbox(b)
+ local l = c and getlist(c)
+ while l do
+ if getid(l) == hlist_code then
+ local line = getattr(l,a_tablesection)
+ if line then
+ local v = list[line]
+ if v and v[1] ~= l then
+ return line
+ end
+ end
+ return 0
+ end
+ l = getnext(l)
+ end
+ return 0
+end
+
+local function fetch(n)
+ local b = list[n]
+ if b then
+ b = copylist(b[2])
+ return tonode(b)
+ end
+end
+
+implement {
+ name = "tabl_ntb_set_sec",
+ public = true,
+ arguments = { "integer", "integer", "integer" },
+ actions = function(n,m,count)
+ sections[n] = { m, count }
+ end,
+}
+
+implement {
+ name = "tabl_ntb_get_sec",
+ public = true,
+ arguments = "integer",
+ usage = "value",
+ actions = function(n)
+ local s = sections[n]
+ return integer_value, s and s[1] or 0
+ end,
+}
+
+implement {
+ name = "ntb_split_section_check",
+ arguments = "integer",
+ actions = check,
+}
+
+implement {
+ name = "ntb_split_section_reset",
+ arguments = "integer",
+ actions = reset,
+}
+
+implement {
+ name = "ntb_split_section_locate",
+ arguments = "integer",
+ actions = { locate, context },
+}
+
+implement {
+ name = "ntb_split_section_fetch",
+ arguments = "integer",
+ actions = { fetch, context },
+}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/tabl-ntb.mkxl b/Master/texmf-dist/tex/context/base/mkxl/tabl-ntb.mkxl
index 6eb926b09e4..414a04f3a1b 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/tabl-ntb.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/tabl-ntb.mkxl
@@ -24,6 +24,8 @@
\writestatus{loading}{ConTeXt Table Macros / Natural Tables}
+\registerctxluafile{tabl-ntb}{autosuffix}
+
% sometimes this helps (with nc going wild): \setupTABLE[maxwidth=100cm]
%
% bug: width 3cm is not honored and column becomes too wide as given width is added
@@ -2295,6 +2297,99 @@
\permanent\protected\def\bTRs[#1]#2\eTRs
{\normalexpanded{\bTR[\begincsname\??naturaltablesetup#1\endcsname]}#2\eTR}
+%D This is new (for Ramkumar, Kb)
+%D
+%D \starttyping
+%D \bTABLE[split=repeat]
+%D \bTABLEhead
+%D \bTR \bTH \darkblue header \eTH \bTH \darkblue done \eTH \eTR
+%D \eTABLEhead
+%D \dorecurse{12}{
+%D \bTABLEbody
+%D \bTABLEsection
+%D \bTR \bTD \darkred line #1.1 \eTD \bTD \darkred done \eTD \eTR
+%D \bTR \bTD \darkred line #1.2 \eTD \bTD \darkred done \eTD \eTR
+%D \eTABLEsection
+%D \bTABLEsection[repeat=2]
+%D \bTR[samepage=after] \bTH \darkorange header #1.1 \eTH \bTH \darkorange done \eTH \eTR
+%D \bTR[samepage=after] \bTH \darkorange header #1.2 \eTH \bTH \darkorange done \eTH \eTR
+%D \bTR \bTD \darkgreen hline #1.3 \eTD \bTD \darkgreen done \eTD \eTR
+%D \bTR \bTD \darkgreen hline #1.4 \eTD \bTD \darkgreen done \eTD \eTR
+%D \bTR \bTD \darkgreen hline #1.5 \eTD \bTD \darkgreen done \eTD \eTR
+%D \eTABLEsection
+%D \eTABLEbody
+%D }
+%D \eTABLE
+%D \stoptyping
+
+\definesystemattribute[tablesection][public]
+
+\newinteger\c_tabl_ntb_section
+\newinteger\c_tabl_ntb_section_repeat
+
+\def\tabl_ntb_section_mark_indeed
+ {\ifcase\c_tabl_ntb_section_repeat
+ \tabl_ntb_set_sec\c_tabl_ntb_maximum_row\zerocount\zerocount
+ \else
+ \tabl_ntb_set_sec\c_tabl_ntb_maximum_row\c_tabl_ntb_section\c_tabl_ntb_section_repeat
+ \fi}
+
+\def\tabl_ntb_section_checkup_indeed
+ {\scratchcounter\tabl_ntb_get_sec\c_tabl_ntb_row\relax
+ \ifcase\scratchcounter
+ \c_attr_tablesection\attributeunsetvalue
+ \else
+ \c_attr_tablesection\scratchcounter
+ \fi}
+
+\def\tabl_ntb_section_split_indeed
+ {\scratchcounter\clf_ntb_split_section_locate\b_split_content\relax
+ \ifcase\scratchcounter\else
+ \clf_ntb_split_section_fetch\scratchcounter
+ \fi}
+
+\def\tabl_ntb_section_wrapup_indeed
+ {\clf_ntb_split_section_reset\b_split_content
+ \tabl_ntb_section_setup}
+
+\def\tabl_ntb_section_install_indeed
+ {\clf_ntb_split_section_check\b_split_content
+ \t_split_section{\tabl_ntb_section_split}}
+
+\def\tabl_ntb_section_disable
+ {\glet\tabl_ntb_section_mark \relax
+ \glet\tabl_ntb_section_checkup\relax
+ \glet\tabl_ntb_section_split \relax
+ \glet\tabl_ntb_section_install\relax
+ \glet\tabl_ntb_section_wrapup \relax}
+
+\def\tabl_ntb_section_enable
+ {\let\tabl_ntb_section_enable \relax
+ \glet\tabl_ntb_section_mark \tabl_ntb_section_mark_indeed
+ \glet\tabl_ntb_section_checkup\tabl_ntb_section_checkup_indeed
+ \glet\tabl_ntb_section_split \tabl_ntb_section_split_indeed
+ \glet\tabl_ntb_section_install\tabl_ntb_section_install_indeed
+ \glet\tabl_ntb_section_wrapup \tabl_ntb_section_wrapup_indeed}
+
+\def\tabl_ntb_section_setup
+ {\global\c_tabl_ntb_section_repeat\zerocount
+ \c_tabl_ntb_section\zerocount
+ \tabl_ntb_section_disable}
+
+\tolerant\permanent\protected\def\bTABLEsection[#1]%
+ {\ifempty{#1}%
+ \global\c_tabl_ntb_section_repeat\zerocount
+ \else
+ \letdummyparameter\c!repeat\zerocount
+ \getdummyparameters[#1]%
+ \global\c_tabl_ntb_section_repeat\dummyparameter\c!repeat\relax
+ \fi
+ \global\advanceby\c_tabl_ntb_section\plusone
+ \tabl_ntb_section_enable}
+
+\permanent\protected\def\eTABLEsection
+ {\global\c_tabl_ntb_section_repeat\zerocount}
+
\protect \endinput
% todo: mode: first|next (of niets)
diff --git a/Master/texmf-dist/tex/context/base/mkxl/tabl-tbl.mkxl b/Master/texmf-dist/tex/context/base/mkxl/tabl-tbl.mkxl
index b3b4b4c886c..6c4c3fd47a1 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/tabl-tbl.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/tabl-tbl.mkxl
@@ -1997,23 +1997,23 @@
\edef\currenttabulatemove{#1}%
\setupcurrenttabulatemove[#2]%
\fi
- \edef\m_orientation{\theorientation{\tabulatemoveparameter\c!orientation}}%
- \edef\m_xoffset {\tabulatemoveparameter\c!xoffset}%
- \edef\m_yoffset {\tabulatemoveparameter\c!yoffset}%
+ \edef\p_orientation{\theorientation{\tabulatemoveparameter\c!orientation}}%
+ \edef\p_xoffset {\tabulatemoveparameter\c!xoffset}%
+ \edef\p_yoffset {\tabulatemoveparameter\c!yoffset}%
\scratchyoffset
- \ifx\m_yoffset\v!depth
+ \ifx\p_yoffset\v!depth
-\strutdp
- \orelse\ifx\m_yoffset\v!height
+ \orelse\ifx\p_yoffset\v!height
-\strutht
\else
- \m_yoffset
+ \p_yoffset
\fi
\relax
- \scratchxoffset\m_xoffset\relax
+ \scratchxoffset\p_xoffset\relax
\xdef\tabl_tabulate_tm
{\ifzeropt\scratchxoffset\else\s!xmove \the\scratchxoffset\fi % or move
\ifzeropt\scratchyoffset\else\s!ymove \the\scratchyoffset\fi % or move
- \ifzero \m_orientation \else\s!orientation\m_orientation \fi
+ \ifzero \p_orientation \else\s!orientation\p_orientation \fi
}%
\endlocalcontrol
\noalign\tabl_tabulate_tm{}}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/tabl-xtb.lmt b/Master/texmf-dist/tex/context/base/mkxl/tabl-xtb.lmt
index b69bfd87346..c475d62330a 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/tabl-xtb.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/tabl-xtb.lmt
@@ -79,6 +79,7 @@ local copynodelist = nuts.copylist
local hpacknodelist = nuts.hpack
local flushnodelist = nuts.flushlist
local takebox = nuts.takebox
+local migratebox = nuts.migratebox
local nodepool = nuts.pool
@@ -562,7 +563,7 @@ end
local function showwidths(where,widths,autowidths)
local result = { }
for i=1,#widths do
- result[#result+1] = format("%12s%s",points(widths[i]),autowidths[i] and "*" or " ")
+ result[i] = format("%12s%s",points(widths[i]),autowidths[i] and "*" or " ")
end
return report_xtable("%s widths: %s",where,concat(result," "))
end
@@ -872,6 +873,7 @@ function xtables.construct()
-- setwhd(list,0,0,0)
-- faster:
local h = new_hlist(list)
+ migratebox(list,h)
list = h
--
if start then
diff --git a/Master/texmf-dist/tex/context/base/mkxl/task-ini.lmt b/Master/texmf-dist/tex/context/base/mkxl/task-ini.lmt
index 6d4ebfcc2d4..57376ae2be8 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/task-ini.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/task-ini.lmt
@@ -63,6 +63,7 @@ appendaction("processors", "lists", "typesetters.rubies.check",
appendaction("processors", "lists", "typesetters.characteralign.handler", nil, "nut", "disabled" )
appendaction("processors", "lists", "typesetters.spacings.handler", nil, "nut", "disabled" )
appendaction("processors", "lists", "typesetters.kerns.handler", nil, "nut", "disabled" )
+appendaction("processors", "lists", "typesetters.tighten.handler", nil, "nut", "disabled" )
appendaction("processors", "lists", "typesetters.digits.handler", nil, "nut", "disabled" )
appendaction("processors", "lists", "typesetters.italics.handler", nil, "nut", "disabled" )
appendaction("processors", "lists", "languages.visualizediscretionaries", nil, "nut", "disabled" )
@@ -226,3 +227,8 @@ directives.register("nodes.basepass", function(v)
disableaction("processors", "builders.kernel.kerning")
end
end)
+
+-- These are different and currently done in strc-flt.lmt but it might move here:
+--
+-- utilities.sequencers.appendaction ("paragraph","system","builders.checksidefloat")
+-- utilities.sequencers.disableaction("paragraph","builders.checksidefloat")
diff --git a/Master/texmf-dist/tex/context/base/mkxl/toks-scn.lmt b/Master/texmf-dist/tex/context/base/mkxl/toks-scn.lmt
index 5af351939f1..ab531a46288 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/toks-scn.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/toks-scn.lmt
@@ -358,6 +358,16 @@ local presets = {
["2 arguments"] = { "argument", "argument" },
["3 arguments"] = { "argument", "argument", "argument" },
["4 arguments"] = { "argument", "argument", "argument", "argument" },
+
+ ["1 integer"] = { "integer" },
+ ["2 integers"] = { "integer", "integer" },
+ ["3 integers"] = { "integer", "integer", "integer" },
+ ["4 integers"] = { "integer", "integer", "integer", "integer" },
+
+ ["1 optional"] = { "optional" },
+ ["2 optionals"] = { "optional", "optional" },
+ ["3 optionals"] = { "optional", "optional", "optional" },
+ ["4 optionals"] = { "optional", "optional", "optional", "optional" },
}
tokens.presets = presets
diff --git a/Master/texmf-dist/tex/context/base/mkxl/type-set.mkxl b/Master/texmf-dist/tex/context/base/mkxl/type-set.mkxl
index 5b83f287e48..62dd3c9ab4b 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/type-set.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/type-set.mkxl
@@ -105,26 +105,28 @@
\definefilesynonym [type-imp-eulernovum.mkiv] [type-imp-euler.mkiv]
\definefilesynonym [type-imp-eulernova.mkiv] [type-imp-euler.mkiv]
-\definefilesynonym [type-imp-euler-with-pagella.mkiv] [type-imp-euler.mkiv]
-\definefilesynonym [type-imp-pagella-with-euler.mkiv] [type-imp-euler.mkiv]
-
-\definefilesynonym [type-imp-mdbch.mkiv] [type-imp-mathdesign.mkiv]
-\definefilesynonym [type-imp-mdugm.mkiv] [type-imp-mathdesign.mkiv]
-\definefilesynonym [type-imp-mdput.mkiv] [type-imp-mathdesign.mkiv]
-\definefilesynonym [type-imp-mdici.mkiv] [type-imp-mathdesign.mkiv]
-\definefilesynonym [type-imp-mdpgd.mkiv] [type-imp-mathdesign.mkiv]
-\definefilesynonym [type-imp-mdpus.mkiv] [type-imp-mathdesign.mkiv]
-
-\definefilesynonym [type-imp-mathdesignch.mkiv] [type-imp-mathdesign.mkiv]
-\definefilesynonym [type-imp-mathdesigngm.mkiv] [type-imp-mathdesign.mkiv]
-\definefilesynonym [type-imp-mathdesignut.mkiv] [type-imp-mathdesign.mkiv]
-\definefilesynonym [type-imp-mathdesignci.mkiv] [type-imp-mathdesign.mkiv]
-\definefilesynonym [type-imp-mathdesigngd.mkiv] [type-imp-mathdesign.mkiv]
-\definefilesynonym [type-imp-mathdesignus.mkiv] [type-imp-mathdesign.mkiv]
-
-\definefilesynonym [type-imp-mathdesigncharter.mkiv] [type-imp-mathdesign.mkiv]
-\definefilesynonym [type-imp-mathdesigngaramond.mkiv] [type-imp-mathdesign.mkiv]
-\definefilesynonym [type-imp-mathdesignutopia.mkiv] [type-imp-mathdesign.mkiv]
+\definefilesynonym [type-imp-euler-with-pagella.mkiv] [type-imp-euler.mkxl]
+\definefilesynonym [type-imp-pagella-with-euler.mkiv] [type-imp-euler.mkxl]
+\definefilesynonym [type-imp-euleroverpagella.mkiv] [type-imp-euler.mkxl]
+\definefilesynonym [type-imp-pagellaovereuler.mkiv] [type-imp-euler.mkxl]
+
+%definefilesynonym [type-imp-mdbch.mkiv] [type-imp-mathdesign.mkiv]
+%definefilesynonym [type-imp-mdugm.mkiv] [type-imp-mathdesign.mkiv]
+%definefilesynonym [type-imp-mdput.mkiv] [type-imp-mathdesign.mkiv]
+%definefilesynonym [type-imp-mdici.mkiv] [type-imp-mathdesign.mkiv]
+%definefilesynonym [type-imp-mdpgd.mkiv] [type-imp-mathdesign.mkiv]
+%definefilesynonym [type-imp-mdpus.mkiv] [type-imp-mathdesign.mkiv]
+
+%definefilesynonym [type-imp-mathdesignch.mkiv] [type-imp-mathdesign.mkiv]
+%definefilesynonym [type-imp-mathdesigngm.mkiv] [type-imp-mathdesign.mkiv]
+%definefilesynonym [type-imp-mathdesignut.mkiv] [type-imp-mathdesign.mkiv]
+%definefilesynonym [type-imp-mathdesignci.mkiv] [type-imp-mathdesign.mkiv]
+%definefilesynonym [type-imp-mathdesigngd.mkiv] [type-imp-mathdesign.mkiv]
+%definefilesynonym [type-imp-mathdesignus.mkiv] [type-imp-mathdesign.mkiv]
+
+%definefilesynonym [type-imp-mathdesigncharter.mkiv] [type-imp-mathdesign.mkiv]
+%definefilesynonym [type-imp-mathdesigngaramond.mkiv] [type-imp-mathdesign.mkiv]
+%definefilesynonym [type-imp-mathdesignutopia.mkiv] [type-imp-mathdesign.mkiv]
\definefilesynonym [type-imp-cows.mkiv] [type-imp-koeielettersot.mkiv]
\definefilesynonym [type-imp-sheep.mkiv] [type-imp-koeielettersot.mkiv]
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-fkr.lmt b/Master/texmf-dist/tex/context/base/mkxl/typo-fkr.lmt
new file mode 100644
index 00000000000..3491c9effaf
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-fkr.lmt
@@ -0,0 +1,122 @@
+if not modules then modules = { } end modules ['typo-fkr'] = {
+ version = 1.001,
+ comment = "companion to typo-fkr.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local nuts = nodes.nuts
+local getid = nuts.getid
+local getnext = nuts.getnext
+local getattr = nuts.getattr
+local isglyph = nuts.isglyph
+
+local nodecodes = nodes.nodecodes
+local glyph_code = nodecodes.glyph
+
+local fontdata = fonts.hashes.identifiers
+local getkernpair = fonts.handlers.otf.getkern
+
+local insertbefore = nuts.insertbefore
+local new_kern = nuts.pool.fontkern
+
+local enableaction = nodes.tasks.enableaction
+
+local a_extrakern = attributes.private("extrafontkern")
+
+-- 0=none 1=min 2=max 3=mixed
+
+typesetters.fontkerns = { }
+
+function typesetters.fontkerns.handler(head)
+ local current = head
+ local lastfont = nil
+ local lastchar = nil
+ local lastdata = nil
+ while current do
+ local char, font = isglyph(current)
+ if char then
+ local a = getattr(current,a_extrakern)
+ if a then
+ if font ~= lastfont then
+ if a > 0 and lastchar then
+ if not lastdata then
+ lastdata = fontdata[lastfont]
+ end
+ local kern = nil
+ local data = fontdata[font]
+ local kern1 = getkernpair(lastdata,lastchar,char)
+ local kern2 = getkernpair(data,lastchar,char)
+ if a == 1 then
+ kern = kern1 > kern2 and kern2 or kern1 -- min
+ elseif a == 2 then
+ kern = kern1 > kern2 and kern1 or kern2 -- max
+ else -- 3
+ kern = (kern1 + kern2)/2 -- mixed
+ end
+ if kern ~= 0 then
+ head = insertbefore(head,current,new_kern(kern))
+ end
+ lastdata = data
+ else
+ lastdata = nil
+ end
+ elseif lastchar then
+ if not lastdata then
+ lastdata = fontdata[lastfont]
+ end
+ local kern = getkernpair(lastdata,lastchar,char)
+ if kern ~= 0 then
+ head = insertbefore(head,current,new_kern(kern))
+ end
+ end
+ lastchar = char
+ lastfont = font
+ elseif lastfont then
+ lastfont = nil
+ lastchar = nil
+ lastdata = nil
+ end
+ elseif lastfont then
+ lastfont = nil
+ lastchar = nil
+ lastdata = nil
+ end
+ current = getnext(current)
+ end
+ return head
+end
+
+do
+
+ local variables = interfaces.variables
+ local unsetvalue = attributes.unsetvalue
+ local enabled = false
+ local setattribute = tex.setattribute
+
+ local values = {
+ [variables.none ] = 0,
+ [variables.min ] = 1,
+ [variables.max ] = 2,
+ [variables.mixed] = 3,
+ [variables.reset] = unsetvalue,
+ }
+
+ local function setextrafontkerns(str)
+ if not enabled then
+ enableaction("processors","typesetters.fontkerns.handler")
+ enabled = true
+ end
+ setattribute(a_extrakern,str and values[str] or unsetvalue)
+ end
+
+ interfaces.implement {
+ name = "setextrafontkerns",
+ public = true,
+ protected = true,
+ arguments = "optional",
+ actions = setextrafontkerns,
+ }
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-fkr.mkxl b/Master/texmf-dist/tex/context/base/mkxl/typo-fkr.mkxl
index f56294dc057..726e02646db 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/typo-fkr.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-fkr.mkxl
@@ -13,7 +13,7 @@
\writestatus{loading}{ConTeXt Typesetting Macros / Additional Font Kerning}
-\registerctxluafile{typo-fkr}{}
+\registerctxluafile{typo-fkr}{autosuffix}
\definesystemattribute[extrafontkern][public]
@@ -25,8 +25,8 @@
% mixed : mean value across fonts
% reset : disable
-\permanent\protected\def\setextrafontkerns[#1]% % can be public implementor
- {\clf_setextrafontkerns{#1}}
+% \permanent\protected\def\setextrafontkerns[#1]% defined at the lua end
+% {\clf_setextrafontkerns{#1}}
\permanent\protected\def\resetextrafontkerns
{\c_attr_extrafontkern\attributeunsetvalue}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-inj.lmt b/Master/texmf-dist/tex/context/base/mkxl/typo-inj.lmt
new file mode 100644
index 00000000000..238524a94a3
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-inj.lmt
@@ -0,0 +1,119 @@
+if not modules then modules = { } end modules ['typo-inj'] = { -- was node-par
+ version = 1.001,
+ comment = "companion to typo-inj.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local tonumber = tonumber
+
+local context = context
+local implement = interfaces.implement
+
+local injectors = { }
+typesetters.injectors = injectors
+local list = { }
+injectors.list = list
+local showall = false
+
+local settings_to_array = utilities.parsers.settings_to_array
+
+local variables = interfaces.variables
+local v_next = variables.next
+local v_previous = variables.previous
+
+local ctx_domarkinjector = context.domarkinjector
+local ctx_doactivateinjector = context.doactivateinjector
+
+table.setmetatableindex(list,function(t,k)
+ local v = {
+ counter = 0,
+ actions = { },
+ show = false,
+ active = false,
+ }
+ t[k] = v
+ return v
+end)
+
+function injectors.reset(name)
+ list[name] = nil
+end
+
+local function activate(injector,name)
+ if not injector.active then
+ ctx_doactivateinjector(name)
+ injector.active = true
+ if showall then
+ -- in case we already enabled tracing
+ injector.show = true
+ end
+ end
+end
+
+function injectors.set(name,numbers,command)
+ local injector = list[name]
+ local actions = injector.actions
+ local places = settings_to_array(numbers)
+ for i=1,#places do
+ actions[tonumber(places[i])] = command
+ end
+ -- not: injector.show = true
+ activate(injector,name)
+end
+
+function injectors.show(name)
+ if not name or name == "" then
+ showall = true
+ local names = settings_to_array(name)
+ for name, injector in next, list do
+ injector.show = true
+ activate(injector,name)
+ end
+ else
+ local names = settings_to_array(name)
+ for i=1,#names do
+ local name = names[i]
+ local injector = list[name]
+ if injector then
+ injector.show = true
+ activate(injector,name)
+ end
+ end
+ end
+end
+
+function injectors.mark(name,show)
+ local injector = list[name]
+ local n = injector.counter + 1
+ injector.counter = n
+ if showall or injector.show then
+ ctx_domarkinjector(injector.actions[n] and 1 or 0,n)
+ end
+end
+
+function injectors.check(name,n) -- we could also accent n = number : +/- 2
+ local injector = list[name]
+ if not n or n == "" or n == v_next then
+ n = injector.counter + 1
+ elseif n == v_previous then
+ n = injector.counter
+ else
+ n = tonumber(n) or 0
+ end
+ local action = injector.actions[n]
+ if action then
+ context(action)
+ end
+end
+
+-- maybe string -> argument
+
+implement { name = "resetinjector", actions = injectors.reset, arguments = "string" }
+implement { name = "showinjector", actions = injectors.show, arguments = "string" }
+implement { name = "setinjector", actions = injectors.set, arguments = "3 strings" }
+implement { name = "markinjector", actions = injectors.mark, arguments = "string" }
+implement { name = "checkinjector", actions = injectors.check, arguments = "2 strings" }
+--------- { name = "checkpreviousinjector", actions = injectors.check, arguments = { "string", v_previous } }
+--------- { name = "checknextinjector", actions = injectors.check, arguments = { "string", v_next } }
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-inj.mkxl b/Master/texmf-dist/tex/context/base/mkxl/typo-inj.mkxl
index bf329482ed2..04c4f677cc4 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/typo-inj.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-inj.mkxl
@@ -24,7 +24,7 @@
\unprotect
-\registerctxluafile{typo-inj}{}
+\registerctxluafile{typo-inj}{autosuffix}
% todo: no need in trialmode
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-man.lmt b/Master/texmf-dist/tex/context/base/mkxl/typo-man.lmt
new file mode 100644
index 00000000000..051e888f1df
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-man.lmt
@@ -0,0 +1,119 @@
+if not modules then modules = { } end modules ['typo-man'] = {
+ version = 1.001,
+ comment = "companion to typo-prc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+if not characters then
+ -- for testing stand-alone
+ require("char-def")
+ require("char-ini")
+end
+
+local lpegmatch = lpeg.match
+local P, R, C, Ct, Cs, Carg = lpeg.P, lpeg.R, lpeg.C, lpeg.Ct, lpeg.Cs, lpeg.Carg
+local global = global or _G
+
+local methods = {
+ uppercase = characters.upper,
+ lowercase = characters.lower,
+ Word = converters.Word,
+ Words = converters.Words,
+}
+
+local function nothing(s) return s end -- we already have that one somewhere
+
+-- table.setmetatableindex(methods,function(t,k)
+-- t[k] = nothing
+-- return nothing
+-- end)
+
+local splitter = lpeg.tsplitat(".")
+
+table.setmetatableindex(methods,function(t,k)
+ local s = lpegmatch(splitter,k)
+ local v = global
+ for i=1,#s do
+ v = v[s[i]]
+ if not v then
+ break
+ end
+ end
+ if not v or v == global then
+ v = nothing
+ end
+ t[k] = v
+ return v
+end)
+
+local whitespace = lpeg.patterns.whitespace^0
+local separator = whitespace * P("->") * whitespace
+local pair = C((1-separator)^1) * separator * C(P(1)^0)
+local list = Ct((C((1-separator)^1) * separator)^1) * C(P(1)^0)
+
+local pattern = Carg(1) * pair / function(methods,operation,str)
+ return methods[operation](str) or str
+end
+
+local function apply(str,m)
+ return lpegmatch(pattern,str,1,m or methods) or str
+end
+
+local function splitspecification(field,m)
+ local m, f = lpegmatch(list,field,1,m or methods)
+ if m then
+ return m, f or field
+ else
+ return nil, field
+ end
+end
+
+local function applyspecification(actions,str)
+ if actions then
+ for i=1,#actions do
+ local action = methods[actions[i]]
+ if action then
+ str = action(str) or str
+ end
+ end
+ end
+ return str
+end
+
+if not typesetters then typesetters = { } end
+
+typesetters.manipulators = {
+ methods = methods,
+ apply = apply,
+ patterns = {
+ pair = pair,
+ list = list,
+ },
+ splitspecification = splitspecification,
+ applyspecification = applyspecification,
+}
+
+local pattern = Cs((1 - P(1) * P(-1))^0 * (P(".")/"" + P(1)))
+
+methods.stripperiod = function(str) return lpegmatch(pattern,str) end
+
+-- print(apply("hans"))
+-- print(apply("uppercase->hans"))
+-- print(apply("string.reverse -> hans"))
+-- print(apply("uppercase->hans",{ uppercase = string.reverse } ))
+
+-- print(applyspecification(splitspecification("hans")))
+-- print(applyspecification(splitspecification("lowercase->uppercase->hans")))
+-- print(applyspecification(splitspecification("uppercase->stripperiod->hans.")))
+
+if commands then
+
+ local context = context
+
+ function commands.manipulated(str)
+ context(apply(str))
+ end
+
+end
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-prc.lmt b/Master/texmf-dist/tex/context/base/mkxl/typo-prc.lmt
new file mode 100644
index 00000000000..72b159e9cac
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-prc.lmt
@@ -0,0 +1,129 @@
+if not modules then modules = { } end modules ['typo-prc'] = {
+ version = 1.001,
+ comment = "companion to typo-prc.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+local lpegmatch, patterns, P, C, Cs = lpeg.match, lpeg.patterns, lpeg.P, lpeg.C, lpeg.Cs
+
+-- processors: syntax: processor->data ... not ok yet
+
+local context = context
+local implement = interfaces.implement
+
+local formatters = string.formatters
+
+typesetters.processors = typesetters.processors or { }
+local processors = typesetters.processors
+
+local trace_processors = false
+local report_processors = logs.reporter("processors")
+local registered = { }
+
+local ctx_applyprocessor = context.applyprocessor
+local ctx_firstofoneargument = context.firstofoneargument
+
+trackers.register("typesetters.processors", function(v) trace_processors = v end)
+
+function processors.register(p)
+ registered[p] = true
+end
+
+function processors.reset(p)
+ registered[p] = nil
+end
+
+--~ local splitter = lpeg.splitat("->",true) -- also support =>
+
+local becomes = P('->')
+local processor = (1-becomes)^1
+local splitter = C(processor) * becomes * Cs(patterns.argument + patterns.content)
+
+function processors.split(str,nocheck)
+ local p, s = lpegmatch(splitter,str)
+ if p and (nocheck or registered[p]) then
+ return p, s
+ else
+ return false, str
+ end
+end
+
+function processors.apply(p,s)
+ local str = p
+ if s == nil then
+ p, s = lpegmatch(splitter,p)
+ end
+ if p and registered[p] then
+ if trace_processors then
+ report_processors("applying %s processor %a, argument: %s","known",p,s)
+ end
+ ctx_applyprocessor(p,s)
+ elseif s then
+ if trace_processors then
+ report_processors("applying %s processor %a, argument: %s","unknown",p,s)
+ end
+ context(s)
+ elseif str then
+ if trace_processors then
+ report_processors("applying %s processor, data: %s","ignored",str)
+ end
+ context(str)
+ end
+end
+
+function processors.startapply(p,s)
+ local str = p
+ if s == nil then
+ p, s = lpegmatch(splitter,p)
+ end
+ if p and registered[p] then
+ if trace_processors then
+ report_processors("start applying %s processor %a","known",p)
+ end
+ ctx_applyprocessor(p)
+ context("{")
+ return s
+ elseif p then
+ if trace_processors then
+ report_processors("start applying %s processor %a","unknown",p)
+ end
+ ctx_firstofoneargument()
+ context("{")
+ return s
+ else
+ if trace_processors then
+ report_processors("start applying %s processor","ignored")
+ end
+ ctx_firstofoneargument()
+ context("{")
+ return str
+ end
+end
+
+function processors.stopapply()
+ context("}")
+ if trace_processors then
+ report_processors("stop applying processor")
+ end
+end
+
+function processors.tostring(str)
+ local p, s = lpegmatch(splitter,str)
+ if registered[p] then
+ return formatters["\\applyprocessor{%s}{%s}"](p,s)
+ else
+ return str
+ end
+end
+
+function processors.stripped(str)
+ local p, s = lpegmatch(splitter,str)
+ return s or str
+end
+
+-- interface
+
+implement { name = "registerstructureprocessor", actions = processors.register, arguments = "string" }
+implement { name = "resetstructureprocessor", actions = processors.reset, arguments = "string" }
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-prc.mklx b/Master/texmf-dist/tex/context/base/mkxl/typo-prc.mklx
index 9531949b8f4..f2df329860f 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/typo-prc.mklx
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-prc.mklx
@@ -16,8 +16,8 @@
%D For the moment manipulators are loaded here too, as they're in the same category
%D as processors. This might change. (They are used in publications.)
-\registerctxluafile{typo-prc}{}
-\registerctxluafile{typo-man}{}
+\registerctxluafile{typo-prc}{autosuffix}
+\registerctxluafile{typo-man}{autosuffix}
\unprotect
@@ -72,8 +72,7 @@
\fi}
\def\typo_processor_apply
- {\edef\p_state{\processorparameter\c!state}%
- \ifx\p_state\v!stop
+ {\ifcstok{\processorparameter\c!state}\v!stop
\expandafter\firstofoneargument
\else
\expandafter\typo_processor_apply_indeed
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-rep.lmt b/Master/texmf-dist/tex/context/base/mkxl/typo-rep.lmt
new file mode 100644
index 00000000000..683b483efda
--- /dev/null
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-rep.lmt
@@ -0,0 +1,135 @@
+if not modules then modules = { } end modules ['typo-rep'] = {
+ version = 1.001,
+ comment = "companion to node-ini.mkiv",
+ author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright = "PRAGMA ADE / ConTeXt Development Team",
+ license = "see context related readme files"
+}
+
+-- This was rather boring to program (more of the same) but I could
+-- endure it by listening to a couple cd's by The Scene and The Lau
+-- on the squeezebox on my desk.
+
+local next, type, tonumber = next, type, tonumber
+
+local trace_stripping = false trackers.register("nodes.stripping", function(v) trace_stripping = v end)
+ trackers.register("fonts.stripping", function(v) trace_stripping = v end)
+
+local report_stripping = logs.reporter("fonts","stripping")
+
+local nodes = nodes
+local enableaction = nodes.tasks.enableaction
+
+local nuts = nodes.nuts
+
+local getnext = nuts.getnext
+local getchar = nuts.getchar
+local isglyph = nuts.isglyph
+
+local getattr = nuts.getattr
+
+local remove_node = nuts.remove
+local replace_node = nuts.replace
+local copy_node = nuts.copy
+
+local nodecodes = nodes.nodecodes
+
+local chardata = characters.data
+local collected = false
+
+local a_stripping = attributes.private("stripping")
+
+local texsetattribute = tex.setattribute
+local unsetvalue = attributes.unsetvalue
+
+local v_reset = interfaces.variables.reset
+
+-- todo: other namespace -> typesetters
+
+nodes.stripping = nodes.stripping or { } local stripping = nodes.stripping
+stripping.glyphs = stripping.glyphs or { } local glyphs = stripping.glyphs
+
+local function initialize()
+ for k, v in next, chardata do
+ if v.category == "cf" and not v.visible and not glyphs[k] then
+ glyphs[k] = true
+ end
+ end
+ initialize = nil
+end
+
+local function process(what,head,current,char)
+ if what == true then
+ if trace_stripping then
+ report_stripping("deleting %C from text",char)
+ end
+ head, current = remove_node(head,current,true)
+ elseif type(what) == "function" then
+ head, current = what(head,current)
+ current = getnext(current)
+ if trace_stripping then
+ report_stripping("processing %C in text",char)
+ end
+ elseif what then -- assume node
+ head, current = replace_node(head,current,copy_node(what))
+ current = getnext(current)
+ if trace_stripping then
+ report_stripping("replacing %C in text",char)
+ end
+ end
+ return head, current
+end
+
+function nodes.handlers.stripping(head) -- use loop
+ local current = head
+ while current do
+ local char, id = isglyph(current)
+ if char then
+ -- it's more efficient to keep track of what needs to be kept
+ local todo = getattr(current,a_stripping)
+ if todo == 1 then
+ local what = glyphs[char]
+ if what then
+ head, current = process(what,head,current,char)
+ else -- handling of spacing etc has to be done elsewhere
+ current = getnext(current)
+ end
+ else
+ current = getnext(current)
+ end
+ else
+ current = getnext(current)
+ end
+ end
+ return head
+end
+
+local enabled = false
+
+function stripping.set(n) -- number or 'reset'
+ if n == v_reset then
+ n = unsetvalue
+ else
+ n = tonumber(n)
+ if n then
+ if not enabled then
+ if initialize then initialize() end
+ enableaction("processors","nodes.handlers.stripping")
+ enabled = true
+ end
+ else
+ n = unsetvalue
+ end
+ end
+ texsetattribute(a_stripping,n)
+end
+
+-- interface
+
+interfaces.implement {
+ name = "setcharacterstripping",
+ public = true,
+ protected = true,
+ actions = stripping.set,
+ arguments = "optional"
+}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-rep.mkxl b/Master/texmf-dist/tex/context/base/mkxl/typo-rep.mkxl
index 6e0a9a22ce0..aa70c556499 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/typo-rep.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-rep.mkxl
@@ -24,12 +24,12 @@
\unprotect
-\registerctxluafile{typo-rep}{}
+\registerctxluafile{typo-rep}{autosuffix}
\definesystemattribute[stripping][public]
-\permanent\protected\def\setcharacterstripping[#1]%
- {\clf_setcharacterstripping{#1}}
+% \permanent\protected\def\setcharacterstripping[#1]% defined at the lua end
+% {\clf_setcharacterstripping{#1}}
\permanent\protected\def\resetcharacterstripping
{\c_attr_stripping\attributeunsetvalue}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-scr.mkxl b/Master/texmf-dist/tex/context/base/mkxl/typo-scr.mkxl
index bb67228cdc0..159b0be6b58 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/typo-scr.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-scr.mkxl
@@ -48,11 +48,36 @@
\appendtoks \frozen\protected\edefcsname\currentlow \endcsname{\typo_scripts_low [\currentlow ]}\to \everydefinelow
\appendtoks \frozen\protected\edefcsname\currenthigh\endcsname{\typo_scripts_high[\currenthigh]}\to \everydefinehigh
+\def\typo_scripts_distance#1%
+ {\edef\p_distance{#1\c!distance}%
+ \ifx\p_distance\v!tight
+ \tightfitboundary
+ \else
+ \kern\p_distance\relax
+ \fi}
+
+%D \startbuffer
+%D \setuplow [distance=\zeropoint]
+%D \setuphigh[distance=\zeropoint]
+%D
+%D {\showglyphs f\high{x}\quad p\high{x}\quad}
+%D
+%D \setuplow [\c!distance=\v!tight]
+%D \setuphigh[\c!distance=\v!tight]
+%D
+%D {\showglyphs f\high{x}\quad p\high{x}\quad}
+%D \stopbuffer
+%D
+%D \typebuffer {\getbuffer}
+
+% \type{f\kern\tightfitcompensation\high{x}}
+% \type{f\tightfitboundary \high{x}}
+
\protected\def\typo_scripts_low[#1]#2%
{\dontleavehmode
\begingroup
\edef\currentlow{#1}%
- \kern\lowparameter\c!distance\relax
+ \typo_scripts_distance\lowparameter
\setbox\scratchbox\runninghbox\bgroup
\lower\lowparameter\c!down\hbox\bgroup
\ifempty\fontsize
@@ -78,7 +103,7 @@
{\dontleavehmode
\begingroup
\edef\currenthigh{#1}%
- \kern\highparameter\c!distance\relax
+ \typo_scripts_distance\highparameter
\setbox\scratchbox\runninghbox\bgroup
\raise\highparameter\c!up\hbox\bgroup
\ifempty\fontsize
@@ -131,15 +156,15 @@
\c!down=.58\exheight] % values
\appendtoks
- \frozen\setuevalue\currentlowhigh{\typo_scripts_lowhigh[\currentlowhigh]}%
+ \frozen\edefcsname\currentlowhigh\endcsname{\typo_scripts_lowhigh[\currentlowhigh]}%
\to \everydefinelowhigh
\tolerant\protected\def\typo_scripts_lowhigh[#1]#*[#2]#:#3#4% todo: align .. [#1] is compatible hack
{\dontleavehmode
\runninghbox\bgroup
\edef\currentlowhigh{#1}%
+ \typo_scripts_distance\lowhighparameter
\dostarttagged\t!subsup\currentlowhigh
- \scratchdimen\lowhighparameter\c!distance\relax
\setbox\plusfour\hpack{\typo_scripts_lowhigh_low_high\lower\c!down\t!sub{#3}}%
\setbox\plussix \hpack{\typo_scripts_lowhigh_low_high\raise\c!up \t!sup{#4}}%
\edef\p_align{#2}%
@@ -163,8 +188,7 @@
\egroup}
\def\typo_scripts_lowhigh_low_high#1#2#3#4%
- {\kern\scratchdimen
- \setbox\scratchbox\hpack\bgroup
+ {\setbox\scratchbox\hpack\bgroup
#1\lowhighparameter#2\hbox\bgroup
\ifempty\fontsize
\ifmmode
@@ -221,7 +245,7 @@
\c!down=.8\struthtdp]
\appendtoks
- \frozen\setuevalue\currentlowmidhigh{\typo_scripts_lowmidhigh[\currentlowmidhigh]}%
+ \frozen\edefcsname\currentlowmidhigh\endcsname{\typo_scripts_lowmidhigh[\currentlowmidhigh]}%
\to \everydefinelowmidhigh
\protected\def\typo_scripts_lowmidhigh[#1]#2#3#4%
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-spa.lmt b/Master/texmf-dist/tex/context/base/mkxl/typo-spa.lmt
index 88ade876ed7..f06ac7913d8 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/typo-spa.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-spa.lmt
@@ -15,6 +15,7 @@ local report_spacing = logs.reporter("typesetting","spacing")
local nodes, fonts, node = nodes, fonts, node
local fonthashes = fonts.hashes
+local chardata = fonthashes.characters
local quaddata = fonthashes.quads
local texsetattribute = tex.setattribute
@@ -92,6 +93,9 @@ function spacings.handler(head)
local alternative = map.alternative
local quad = quaddata[font]
local prev = getprev(start)
+ if not chardata[font][char] then
+ report_spacing("missing character %C in font %i",char,font)
+ end
if left and left ~= 0 and prev then
local ok = false
local prevprev = getprev(prev)
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-wrp.lmt b/Master/texmf-dist/tex/context/base/mkxl/typo-wrp.lmt
index 5b31c401591..b77e2753221 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/typo-wrp.lmt
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-wrp.lmt
@@ -9,7 +9,9 @@ if not modules then modules = { } end modules ['typo-wrp'] = {
-- begin/end par wrapping stuff ... more to come
local boundary_code = nodes.nodecodes.boundary
+local glyph_code = nodes.nodecodes.glyph
local wordboundary_code = nodes.boundarycodes.word
+local userboundary_code = nodes.boundarycodes.user
local nuts = nodes.nuts
@@ -17,16 +19,25 @@ local findtail = nuts.tail
local getprev = nuts.getprev
local setnext = nuts.setnext
local getid = nuts.getid
+local getdata = nuts.getdata
+local isglyph = nuts.isglyph
local getsubtype = nuts.getsubtype
local getattr = nuts.getattr
local flushnodelist = nuts.flushlist
+local traverse_boundary = nuts.traversers.boundary
+local insertnodebefore = nuts.insertbefore
+local newkern = nuts.pool.kern
+
+local fontdata = fonts.hashes.identifiers
local enableaction = nodes.tasks.enableaction
+local implement = interfaces.implement
+
local wrappers = { }
typesetters.wrappers = wrappers
-local trace_wrappers = trackers.register("typesetters.wrappers",function(v) trace_wrappers = v end)
+local trace_wrappers trackers.register("typesetters.wrappers",function(v) trace_wrappers = v end)
local report = logs.reporter("paragraphs","wrappers")
-- In luametatex we don't have the parfilskip attached yet but we can have final glue
@@ -64,18 +75,86 @@ local function remove_dangling_crlf(head,tail)
return head, tail
end
-function wrappers.handler(head)
- if head then
- local tail = findtail(head)
- head, tail = remove_dangling_crlf(head,tail) -- will be action chain
+implement {
+ name = "enablecrlf",
+ onlyonce = true,
+ actions = function()
+ enableaction("processors","typesetters.wrappers.handler")
+ end
+}
+
+-- Here's a solution for a trivial challenge by MS who got it from the internet
+-- (SE). If needed we can make it a bit more granular.
+
+local tighten = { }
+typesetters.tighten = tighten
+
+local trace_tighten trackers.register("typesetters.tighten",function(v) trace_tighten = v end)
+local report = logs.reporter("typesetters","tighten")
+
+local a_tightfit_boundary = tex.boundaries.system("c_tightfit_boundary") -- private, not defined with \defineboundary
+
+local function bbcompensation(font,char)
+ local tfmdata = fontdata[font]
+ local character = tfmdata.characters[char]
+ if character then
+ local compensation = character.compensation
+ if not compensation then
+ local description = tfmdata.descriptions[char]
+ if description then
+ local boundingbox = description.boundingbox
+ return boundingbox and (boundingbox[3] - (description.width or 0)) * tfmdata.parameters.hfactor
+ end
+ character.compensation = compensation
+ end
+ end
+ return 0
+end
+
+function tighten.handler(head)
+ for n, subtype in traverse_boundary, head do
+ if subtype == userboundary_code and getdata(n) == a_tightfit_boundary then
+ local prev = getprev(n)
+ if prev then
+ local char, font = isglyph(prev)
+ if char then
+ local compensation = bbcompensation(font,char)
+ if compensation > 0 then
+ if trace_tighten then
+ report("compensating %p after %C",compensation,char)
+ end
+ insertnodebefore(head,n,newkern(compensation))
+ end
+ end
+ end
+ end
end
return head
end
-interfaces.implement {
- name = "enablecrlf",
+implement {
+ name = "enabletighten",
onlyonce = true,
actions = function()
- enableaction("processors","typesetters.wrappers.handler")
+ enableaction("processors","typesetters.tighten.handler")
end
}
+
+local dimension_value = tokens.values.dimension
+local texgetnest = tex.getnest
+
+implement {
+ name = "tightfitcompensation",
+ public = true,
+ protected = true,
+ usage = "value",
+ actions = function()
+ local list = texgetnest()
+ if list then
+ list = list.tail
+ end
+ return
+ dimension_value,
+ list and list.id == glyph_code and bbcompensation(list.font,list.char) or 0
+ end,
+}
diff --git a/Master/texmf-dist/tex/context/base/mkxl/typo-wrp.mkxl b/Master/texmf-dist/tex/context/base/mkxl/typo-wrp.mkxl
index 71559a8a3a5..2f536bc061a 100644
--- a/Master/texmf-dist/tex/context/base/mkxl/typo-wrp.mkxl
+++ b/Master/texmf-dist/tex/context/base/mkxl/typo-wrp.mkxl
@@ -59,4 +59,17 @@
\let\spac_crlf\space
\to \everysimplifycommands
+% experiment, triggered by MS:
+%
+% \type{f\kern\tightfitcompensation\high{x}}
+% \type{f\tightfitboundary \high{x}}
+
+% \tightfitcompensation : defined at the lua end
+
+\newboundary\c_tightfit_boundary
+
+\permanent\protected\def\tightfitboundary
+ {\clf_enabletighten
+ \boundary\c_tightfit_boundary}
+
\protect \endinput
diff --git a/Master/texmf-dist/tex/context/fonts/mkiv/kpfonts-math.lfg b/Master/texmf-dist/tex/context/fonts/mkiv/kpfonts-math.lfg
index 409b17cbc42..67ad3841f95 100644
--- a/Master/texmf-dist/tex/context/fonts/mkiv/kpfonts-math.lfg
+++ b/Master/texmf-dist/tex/context/fonts/mkiv/kpfonts-math.lfg
@@ -134,7 +134,17 @@ return {
tweak = "setoptions",
set = { "ignorekerndimensions" }
},
- },
+-- {
+-- tweak = "inspect",
+-- unicode = 0x2192
+-- },
+-- {
+-- tweak = "inspect",
+-- unicode = 0x20EF
+-- },
+-- {
+ }
+
},
alternates = {
-- italic = { feature = 'ss01', value = 1, comment = "Mathematical Alternative Lowercase Italic" },
diff --git a/Master/texmf-dist/tex/context/modules/mkxl/m-tikz.mkxl b/Master/texmf-dist/tex/context/modules/mkxl/m-tikz.mkxl
index 3d6c649d667..21544d14e59 100644
--- a/Master/texmf-dist/tex/context/modules/mkxl/m-tikz.mkxl
+++ b/Master/texmf-dist/tex/context/modules/mkxl/m-tikz.mkxl
@@ -67,6 +67,12 @@
\overloadmode\zerocount
+\newtoks\everytikzpicture
+
+% \appendtoks
+% \resetcharacterspacing
+% \to \everytikzpicture
+
\permanent\protected\def\starttikzsettings
{\pushoverloadmode
\pushmacro\meaning
@@ -81,6 +87,7 @@
\permanent\protected\def\starttikzpicture
{\dontleavehmode
\hcontainer\bgroup
+ \the\everytikzpicture
\autoparagraphmode\zerocount
\pushmacro\meaning
\let\meaning\meaningless
diff --git a/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-merged.lua b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-merged.lua
index e5c4b57eb7f..614793314d7 100644
--- a/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-merged.lua
+++ b/Master/texmf-dist/tex/generic/context/luatex/luatex-fonts-merged.lua
@@ -1,6 +1,6 @@
-- merged file : c:/data/develop/context/sources/luatex-fonts-merged.lua
-- parent file : c:/data/develop/context/sources/luatex-fonts.lua
--- merge date : 2023-02-23 21:26
+-- merge date : 2023-03-10 12:15
do -- begin closure to overcome local limits and interference
@@ -2952,9 +2952,23 @@ function file.withinbase(path)
end
return true
end
-local symlinkattributes=lfs.symlinkattributes
-function lfs.readlink(name)
- return symlinkattributes(name,"target") or nil
+do
+ local symlinktarget=lfs.symlinktarget
+ local symlinkattributes=lfs.symlinkattributes
+ if symlinktarget then
+ function lfs.readlink(name)
+ local target=symlinktarget(name)
+ return name~=target and name or nil
+ end
+ elseif symlinkattributes then
+ function lfs.readlink(name)
+ return symlinkattributes(name,"target") or nil
+ end
+ else
+ function lfs.readlink(name)
+ return nil
+ end
+ end
end
end -- closure
diff --git a/Master/texmf-dist/web2c/texmfcnf.lua b/Master/texmf-dist/web2c/texmfcnf.lua
index 9fd2d8e5988..dedadd1965a 100644
--- a/Master/texmf-dist/web2c/texmfcnf.lua
+++ b/Master/texmf-dist/web2c/texmfcnf.lua
@@ -1,79 +1,98 @@
--- public domain
+-- todo: come up with an auto-texlive identification (texmf-dist)
--- ConTeXt needs a properly expanded TEXMFLOCAL, so here is a
--- bit of lua code to make that happen
-
-local texmflocal = resolvers.prefixes.selfautoparent();
-texmflocal = string.gsub(texmflocal, "20%d%d$", "texmf-local");
+local hiddentexlivepath = ".texlive2023"
return {
type = "configuration",
- version = "1.1.0",
- date = "2012-05-24",
- time = "12:12:12",
- comment = "ConTeXt MkIV configuration file",
+ version = "1.1.3",
+ date = "2023-03-10", -- 2021-05-12 2011-06-02
+ time = "14:59:00",
+ comment = "ConTeXt MkIV and LMTX configuration file",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ target = "texlive",
content = {
- -- Originally there was support for engines and progname but I don't expect
- -- other engines to use this file, so first engines were removed. After that
- -- if made sense also to get rid of progname. At some point specific formats
- -- will be supported but then as a subtable with fallbacks, which sounds more
- -- natural. Also, at some point the paths will become tables. For the moment
- -- I don't care too much about it as extending is easy.
+ -- Originally there was support for engines and progname but I don't expect other engines to
+ -- use this file, so first engines were removed. After that if made sense also to get rid of
+ -- progname. In principle we could support multiple formats here (using subtables) but time
+ -- has demonstrated that we only have one format (the original ideas was to make a base layer
+ -- but I don't see it being used to it would be waste of time). So, after a decade it was
+ -- time to prune and update this file, also because LMTX has a few more features.
variables = {
- -- The following variable is predefined (but can be overloaded) and in
- -- most cases you can leve this one untouched. The built-in definition
- -- permits relocation of the tree.
+ -- The following variable is predefined (but can be overloaded) and in most cases you can
+ -- leave this one untouched. The built-in definition permits relocation of the tree.
--
- -- TEXMFCNF = "{selfautodir:,selfautoparent:}{,{/share,}/texmf{-local,}/web2c}"
+ -- if this_is_texlive then
+ -- resolvers.luacnfspec = 'selfautodir:;selfautoparent:;{selfautodir:,selfautoparent:}{/share,}/texmf{-local,}/web2c'
+ -- else
+ -- resolvers.luacnfspec = 'home:texmf/web2c;selfautoparent:texmf{-local,-context,}/web2c'
+ -- end
--
- -- more readable than "selfautoparent:{/texmf{-local,}{,/web2c},}}" is:
+ -- more readable is:
--
-- TEXMFCNF = {
- -- "selfautoparent:/texmf-local",
- -- "selfautoparent:/texmf-local/web2c",
- -- "selfautoparent:/texmf-dist",
- -- "selfautoparent:/texmf/web2c",
- -- "selfautoparent:",
+ -- "home:texmf/web2c,
+ -- "selfautoparent:texmf-local/web2c",
+ -- "selfautoparent:texmf-context/web2c",
+ -- "selfautoparent:texmf/web2c",
-- }
- -- only used for FONTCONFIG_PATH & TEXMFCACHE in TeX Live
+ -- We have only one cache path but there can be more. The first writable one will be taken
+ -- but there can be more readable paths.
- TEXMFSYSVAR = "selfautoparent:texmf-var",
- TEXMFVAR = "home:.texlive2023/texmf-var",
+ -- standalone:
+
+ -- TEXMFCACHE = "$SELFAUTOPARENT/texmf-cache",
- -- We have only one cache path but there can be more. The first writable one
- -- will be chosen but there can be more readable paths.
+ -- texlive
+ TEXMFVAR = "home:" .. hiddentexlivepath .. "/texmf-var",
+ TEXMFCONFIG = "home:" .. hiddentexlivepath .. "/texmf-config",
+ TEXMFSYSVAR = "selfautoparent:texmf-var",
TEXMFCACHE = "$TEXMFSYSVAR;$TEXMFVAR",
- TEXMFCONFIG = "home:.texlive2023/texmf-config",
- -- I don't like this texmf under home and texmf-home would make more
- -- sense. One never knows what installers put under texmf anywhere and
- -- sorting out problems will be a pain. But on the other hand ... home
- -- mess is normally under the users own responsibility.
+ -- I don't like this texmf under home and texmf-home would make more sense. One never knows
+ -- what installers put under texmf anywhere and sorting out problems will be a pain. But on
+ -- the other hand ... home mess is normally the users own responsibility.
--
- -- By using prefixes we don't get expanded paths in the cache __path__
- -- entry. This makes the tex root relocatable.
+ -- By using prefixes we don't get expanded paths in the cache __path__ entry. This makes the
+ -- tex root relocatable.
TEXMFOS = "selfautodir:",
- TEXMFDIST = "selfautoparent:texmf-dist",
- TEXMFLOCAL = texmflocal,
+ -- standalone:
+
+ -- TEXMFSYSTEM = "selfautoparent:texmf-$SELFAUTOSYSTEM",
+ -- TEXMFMAIN = "selfautoparent:texmf",
+ -- TEXMFCONTEXT = "selfautoparent:texmf-context",
+ -- TEXMFMODULES = "selfautoparent:texmf-modules",
+
+ -- texlive:
+
+ TEXMFDIST = "selfautoparent:texmf-dist",
TEXMFSYSCONFIG = "selfautoparent:texmf-config",
+
+ -- The texmf-local path is only used for (maybe) some additional configuration file.
+
+ TEXMFLOCAL = "selfautoparent:texmf-local",
TEXMFFONTS = "selfautoparent:texmf-fonts",
TEXMFPROJECT = "selfautoparent:texmf-project",
TEXMFHOME = "home:texmf",
-- TEXMFHOME = os.name == "macosx" and "home:Library/texmf" or "home:texmf",
- -- We need texmfos for a few rare files but as I have a few more bin trees
- -- a hack is needed. Maybe other users also have texmf-platform-new trees.
+ -- We need texmfos for a few rare files but as I have a few more bin trees a hack is needed.
+ -- Maybe other users also have texmf-platform-new trees, but so far I've never heard of it.
+
+ -- standalone:
+
+ -- TEXMF = "{$TEXMFHOME,!!$TEXMFPROJECT,!!$TEXMFFONTS,!!$TEXMFLOCAL,!!$TEXMFMODULES,!!$TEXMFCONTEXT,!!$TEXMFSYSTEM,!!$TEXMFMAIN}",
+
+ -- texlive:
TEXMF = "{$TEXMFCONFIG,$TEXMFHOME,!!$TEXMFSYSCONFIG,!!$TEXMFSYSVAR,!!$TEXMFPROJECT,!!$TEXMFFONTS,!!$TEXMFLOCAL,!!$TEXMFDIST}",
@@ -81,11 +100,11 @@ return {
ENCFONTS = ".;$TEXMF/fonts/data//;$TEXMF/fonts/enc/{dvips,pdftex}//",
VFFONTS = ".;$TEXMF/fonts/{data,vf}//",
TFMFONTS = ".;$TEXMF/fonts/{data,tfm}//",
+ PKFONTS = ".;$TEXMF/fonts/{data,pk}//",
T1FONTS = ".;$TEXMF/fonts/{data,type1}//;$OSFONTDIR",
AFMFONTS = ".;$TEXMF/fonts/{data,afm}//;$OSFONTDIR",
TTFONTS = ".;$TEXMF/fonts/{data,truetype}//;$OSFONTDIR",
OPENTYPEFONTS = ".;$TEXMF/fonts/{data,opentype}//;$OSFONTDIR",
- CMAPFONTS = ".;$TEXMF/fonts/cmap//",
FONTFEATURES = ".;$TEXMF/fonts/{data,fea}//;$OPENTYPEFONTS;$TTFONTS;$T1FONTS;$AFMFONTS",
FONTCIDMAPS = ".;$TEXMF/fonts/{data,cid}//",
OFMFONTS = ".;$TEXMF/fonts/{data,ofm,tfm}//",
@@ -101,12 +120,12 @@ return {
PYTHONINPUTS = ".;$TEXMF/scripts/context/python",
RUBYINPUTS = ".;$TEXMF/scripts/context/ruby",
LUAINPUTS = ".;$TEXINPUTS;$TEXMF/scripts/context/lua//",
- CLUAINPUTS = ".;$SELFAUTOLOC/lib/{context,luatex,}/lua//",
+ CLUAINPUTS = ".;$SELFAUTOLOC/lib/$engine//",
-- Not really used by MkIV so they might go away.
- BIBINPUTS = ".;$TEXMF/bibtex/bib//",
- BSTINPUTS = ".;$TEXMF/bibtex/bst//",
+ BIBINPUTS = ".;$TEXMF/bibtex/bib//;$TEXMF/tex/context//",
+ BSTINPUTS = ".;$TEXMF/bibtex/bst//;$TEXMF/tex/context//",
-- Experimental
@@ -115,28 +134,65 @@ return {
-- A few special ones that will change some day.
FONTCONFIG_FILE = "fonts.conf",
+
+ -- standalone
+
+ -- FONTCONFIG_PATH = "$TEXMFSYSTEM/fonts/conf",
+
+ --texlive
+
FONTCONFIG_PATH = "$TEXMFSYSVAR/fonts/conf",
},
- -- We have a few reserved subtables. These control runtime behaviour. The
- -- keys have names like 'foo.bar' which means that you have to use keys
- -- like ['foo.bar'] so for convenience we also support 'foo_bar'.
+ -- We have a few reserved subtables. These control runtime behaviour. Some are frozen at
+ -- at startup time, others can be changed any time.
directives = {
- -- There are a few variables that determine the engines
- -- limits. Most will fade away when we close in on version 1.
-
- ["luatex.expanddepth"] = "10000", -- 10000
- ["luatex.hashextra"] = "100000", -- 0
- ["luatex.nestsize"] = "1000", -- 50
- ["luatex.maxinopen"] = "500", -- 15
- ["luatex.maxprintline"] = " 10000", -- 79
- ["luatex.maxstrings"] = "500000", -- 15000 -- obsolete
- ["luatex.paramsize"] = "25000", -- 60
- ["luatex.savesize"] = "50000", -- 4000
- ["luatex.stacksize"] = "10000", -- 300
+ -- The default settings are actually set at startup so the values below overload
+ -- them. You can also specify a plus field which will bump a value and in LMTX a
+ -- step field that sets the incremental allocation of memory (because there we don't
+ -- allocate all at once).
+
+ -- texconfig.max_print_line = 100000
+ -- texconfig.function_size = 32768
+ -- texconfig.properties_size = 10000
+
+ -- These are for luametatex:
+
+ ["luametatex.errorlinesize"] = { size = 250 }, -- max = 255
+ ["luametatex.halferrorlinesize"] = { size = 250 }, -- max = 255
+ ["luametatex.expandsize"] = { size = 10000 }, -- max = 1000000
+ ["luametatex.stringsize"] = { size = 500000, step = 100000 }, -- max = 2097151 -- number of strings
+ ["luametatex.poolsize"] = { size = 10000000, step = 1000000 }, -- max = 100000000 -- chars in string
+ ["luametatex.hashsize"] = { size = 250000, step = 100000 }, -- max = 2097151
+ ["luametatex.nodesize"] = { size = 50000000, step = 500000 }, -- max = 50000000
+ ["luametatex.tokensize"] = { size = 10000000, step = 250000 }, -- max = 10000000
+ ["luametatex.buffersize"] = { size = 10000000, step = 1000000 }, -- max = 100000000
+ ["luametatex.inputsize"] = { size = 100000, step = 10000 }, -- max = 100000 -- aka stack
+ ["luametatex.filesize"] = { size = 2000, step = 200 }, -- max = 2000
+ ["luametatex.nestsize"] = { size = 10000, step = 1000 }, -- max = 10000
+ ["luametatex.parametersize"] = { size = 100000, step = 10000 }, -- max = 100000
+ ["luametatex.savesize"] = { size = 500000, step = 10000 }, -- max = 500000
+ ["luametatex.fontsize"] = { size = 100000, step = 250 }, -- max = 100000
+ ["luametatex.languagesize"] = { size = 250, step = 250 }, -- max = 10000
+ ["luametatex.marksize"] = { size = 250, step = 50 }, -- max = 10000
+ ["luametatex.insertsize"] = { size = 250, step = 25 }, -- max = 250
+
+ -- These are for luatex:
+
+ ["luatex.errorline"] = 250,
+ ["luatex.halferrorline"] = 125,
+ ["luatex.expanddepth"] = 10000,
+ ["luatex.hashextra"] = 100000,
+ ["luatex.nestsize"] = 1000,
+ ["luatex.maxinopen"] = 500,
+ ["luatex.maxprintline"] = 10000,
+ ["luatex.maxstrings"] = 500000,
+ ["luatex.paramsize"] = 25000,
+ ["luatex.savesize"] = 100000,
+ ["luatex.stacksize"] = 100000,
-- A few process related variables come next.
@@ -146,35 +202,68 @@ return {
["system.compile.cleanup"] = "no", -- remove tma files
["system.compile.strip"] = "yes", -- strip tmc files
- -- The io modes are similar to the traditional ones. Possible values
- -- are all, paranoid and restricted.
+ -- The io modes are similar to the traditional ones. Possible values are all, paranoid
+ -- and restricted.
["system.outputmode"] = "restricted",
["system.inputmode"] = "any",
- -- The following variable is under consideration. We do have protection
- -- mechanims but it's not enabled by default.
+ -- The following variable is under consideration. We do have protection mechanims but
+ -- it's not enabled by default.
["system.commandmode"] = "any", -- any none list
["system.commandlist"] = "mtxrun, convert, inkscape, gs, imagemagick, curl, bibtex, pstoedit",
- -- The mplib library support mechanisms have their own
- -- configuration. Normally these variables can be left as
- -- they are.
+ -- The mplib library support mechanisms have their own configuration. Normally these
+ -- variables can be left as they are.
["mplib.texerrors"] = "yes",
- -- Normally you can leave the font related directives untouched
- -- as they only make sense when testing.
+ -- Normally you can leave the font related directives untouched as they only make sense
+ -- when testing.
-- ["fonts.autoreload"] = "no",
- -- ["fonts.otf.loader.method"] = "table", -- table mixed sparse
-- ["fonts.otf.loader.cleanup"] = "0", -- 0 1 2 3
-- In an edit cycle it can be handy to launch an editor. The
-- preferred one can be set here.
- -- ["pdfview.method"] = "okular", -- default (often acrobat) xpdf okular
+ -- ["pdfview.method"] = "sumatra",
+
+ -- ["system.engine"] = "luajittex",
+ -- ["fonts.usesystemfonts"] = false,
+ -- ["modules.permitunprefixed"] = false,
+ -- ["resolvers.otherwise"] = false,
+
+ -- Sandboxing has been available for a while but is probably never used to maybe that mechanism
+ -- should be removed some day. Normally you will configure this in a local configuration file. By
+ -- default we are rather permissive. The next list comes from my machine:
+
+ -- ["system.rootlist"] = { "/data" }, -- { { "/data", "read" }, ... }
+
+ -- ["system.executionmode"] = "list", -- none | list | all
+ -- ["system.executionlist"] = {
+ -- "context",
+ -- "bibtex", "mlbibcontext",
+ -- "curl",
+ -- "gswin64c", "gswin32c", "gs",
+ -- "gm", "graphicmagick",
+ -- "pdftops",
+ -- "pstoedit",
+ -- "inkscape",
+ -- "woff2_decompress",
+ -- "hb-shape",
+ -- },
+ --
+ -- ["system.librarymode"] = "list", -- none | list | all
+ -- ["system.librarylist"] = {
+ -- "mysql",
+ -- "sqlite3",
+ -- "libharfbuzz", "libharfbuzz-0",
+ -- },
+ -- -- ["system.librarynames"] = {
+ -- -- ["libcurl"] = { "libcurl", "libcurl-4" },
+ -- -- },
},