texlive[49982] Master/texmf-dist: lualibs (7feb19)
commits+karl at tug.org
commits+karl at tug.org
Sat Feb 9 00:01:17 CET 2019
Revision: 49982
http://tug.org/svn/texlive?view=revision&revision=49982
Author: karl
Date: 2019-02-09 00:01:17 +0100 (Sat, 09 Feb 2019)
Log Message:
-----------
lualibs (7feb19)
Modified Paths:
--------------
trunk/Master/texmf-dist/doc/luatex/lualibs/NEWS
trunk/Master/texmf-dist/doc/luatex/lualibs/README
trunk/Master/texmf-dist/doc/luatex/lualibs/lualibs.pdf
trunk/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx
trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua
trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua
trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua
trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua
trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-lua.lua
trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-trac-inf.lua
trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-jsn.lua
trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-lua.lua
trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-str.lua
trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-tab.lua
trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua
Modified: trunk/Master/texmf-dist/doc/luatex/lualibs/NEWS
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/lualibs/NEWS 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/doc/luatex/lualibs/NEWS 2019-02-08 23:01:17 UTC (rev 49982)
@@ -1,6 +1,9 @@
History of the lualibs package
-2018-12-19 v2.62/ (upload 2019-01-16)
- * sync with Context beta as of 2018-12-19
+2019/01/28 v2.63/
+ * sync with Context beta as of 2019/01/28
+
+2019/01/28 v2.62/
+ * sync with Context beta as of 2018/12/19
2018/10/18 v2.61/
* sync with Context beta as of 2018-10-18
Modified: trunk/Master/texmf-dist/doc/luatex/lualibs/README
===================================================================
--- trunk/Master/texmf-dist/doc/luatex/lualibs/README 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/doc/luatex/lualibs/README 2019-02-08 23:01:17 UTC (rev 49982)
@@ -11,8 +11,8 @@
This package has been developed by the LuaLaTeX development team on
<http://github.com/lualatex/lualibs>.
-The current verson 2.62 has been build by Ulrike Fischer on
-<https://github.com/u-fischer/lualibs> from context 2018-12-19.
+The current verson 2.63 has been build by Ulrike Fischer on
+<https://github.com/u-fischer/lualibs> from context 2019-01-28.
See the 'NEWS' file for version history.
Modified: trunk/Master/texmf-dist/doc/luatex/lualibs/lualibs.pdf
===================================================================
(Binary files differ)
Modified: trunk/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx
===================================================================
--- trunk/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/source/luatex/lualibs/lualibs.dtx 2019-02-08 23:01:17 UTC (rev 49982)
@@ -37,7 +37,7 @@
\input docstrip.tex
\Msg{************************************************************************}
\Msg{* Installation}
-\Msg{* Package: lualibs 2018-12-19 v2.62 Lua additional functions.}
+\Msg{* Package: lualibs 2019-01-28 v2.63 Lua additional functions.}
\Msg{************************************************************************}
\keepsilent
@@ -107,7 +107,7 @@
%<*driver>
\NeedsTeXFormat{LaTeX2e}
\ProvidesFile{lualibs.drv}
- [2018/12/07 v2.62 Lua Libraries.]
+ [2010/01/28 v2.63 Lua Libraries.]
\documentclass{ltxdoc}
\usepackage{fancyvrb,xspace}
\usepackage[x11names]{xcolor}
@@ -208,7 +208,7 @@
% \GetFileInfo{lualibs.drv}
%
% \title{The \identifier{lualibs} package}
-% \date{2018/12/07 v2.62}
+% \date{2019/01/28 v2.63}
% \author{Élie Roux · \email{elie.roux at telecom-bretagne.eu}\\
% Philipp Gesang · \email{phg at phi-gamma.net}\\
% Ulrike Fischer · \email{fischer at troubleshooting-tex.de}\\
@@ -429,8 +429,8 @@
lualibs.module_info = {
name = "lualibs",
- version = 2.62,
- date = "2018-12-19",
+ version = 2.63,
+ date = "2019-01-28",
description = "ConTeXt Lua standard libraries.",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
copyright = "PRAGMA ADE / ConTeXt Development Team",
@@ -584,8 +584,8 @@
local lualibs_basic_module = {
name = "lualibs-basic",
- version = 2.62,
- date = "2018-12-19",
+ version = 2.63,
+ date = "2019-01-28",
description = "ConTeXt Lua libraries -- basic collection.",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
copyright = "PRAGMA ADE / ConTeXt Development Team",
@@ -666,8 +666,8 @@
local lualibs_extended_module = {
name = "lualibs-extended",
- version = 2.62,
- date = "2018-12-19",
+ version = 2.63,
+ date = "2019-01-28",
description = "ConTeXt Lua libraries -- extended collection.",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
copyright = "PRAGMA ADE / ConTeXt Development Team",
Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic-merged.lua 2019-02-08 23:01:17 UTC (rev 49982)
@@ -1,15 +1,15 @@
-- merged file : lualibs-basic-merged.lua
-- parent file : lualibs-basic.lua
--- merge date : Tue Dec 25 16:21:45 2018
+-- merge date : Wed Jan 30 23:25:49 2019
do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['l-lua']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
+ version=1.001,
+ comment="companion 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+).*$")
@@ -17,111 +17,110 @@
LUAMINORVERSION=tonumber(LUAMINORVERSION) or 1
LUAVERSION=LUAMAJORVERSION+LUAMINORVERSION/10
if LUAVERSION<5.2 and jit then
- MINORVERSION=2
- LUAVERSION=5.2
+ MINORVERSION=2
+ LUAVERSION=5.2
end
-_LUAVERSION=LUAVERSION
if not lpeg then
- lpeg=require("lpeg")
+ 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
+ local loadnormal=load
+ function load(first,...)
+ if type(first)=="string" then
+ return loadstring(first,...)
+ else
+ return loadnormal(first,...)
end
+ end
else
- loadstring=load
+ 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
+ local function iterate(a,i)
+ i=i+1
+ local v=a[i]
+ if v~=nil then
+ return i,v
end
- function ipairs(a)
- return iterate,a,0
- end
+ end
+ function ipairs(a)
+ return iterate,a,0
+ end
end
if not pairs then
- function pairs(t)
- return next,t
- end
+ function pairs(t)
+ return next,t
+ end
end
if not table.unpack then
- table.unpack=_G.unpack
+ table.unpack=_G.unpack
elseif not unpack then
- _G.unpack=table.unpack
+ _G.unpack=table.unpack
end
if not package.loaders then
- package.loaders=package.searchers
+ package.loaders=package.searchers
end
local print,select,tostring=print,select,tostring
local inspectors={}
function setinspector(kind,inspector)
- inspectors[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
+ 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
+ local ok,result=xpcall(require,dummy,...)
+ if ok then
+ return result
+ end
end
if lua then
- lua.mask=load([[τεχ = 1]]) and "utf" or "ascii"
+ lua.mask=load([[τεχ = 1]]) and "utf" or "ascii"
end
local flush=io.flush
if flush then
- local execute=os.execute if execute then function os.execute(...) flush() return execute(...) end end
- local exec=os.exec if exec then function os.exec (...) flush() return exec (...) end end
- local spawn=os.spawn if spawn then function os.spawn (...) flush() return spawn (...) end end
- local popen=io.popen if popen then function io.popen (...) flush() return popen (...) end end
+ 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
+ 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
+ ffi=nil
elseif not ffi.number then
- ffi.number=tonumber
+ ffi.number=tonumber
end
if not bit32 then
- bit32=require("l-bit32")
+ bit32=require("l-bit32")
end
end -- closure
@@ -129,11 +128,11 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="companion 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 gsub,format,find=string.gsub,string.format,string.find
@@ -141,40 +140,40 @@
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 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
+ 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
+ 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={
- "already loaded",
- "preload table",
- "qualified path",
- "lua extra list",
- "lib extra list",
- "path specification",
- "cpath specification",
- "all in one fallback",
- "not loaded",
- }
+ 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={
+ "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
@@ -190,51 +189,51 @@
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)
+ local nofpaths=#paths
+ if nofpaths>0 then
+ for i=1,nofpaths do
+ helpers.report("using %s path %i: %s",what,i,paths[i])
end
- return nofpaths
+ 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
+ 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
+ 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
+ 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
+ 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
@@ -241,204 +240,204 @@
package.extraluapaths=getextraluapaths
package.extralibpaths=getextralibpaths
local hashes={
- lua={},
- lib={},
+ 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
+ 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
- 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
+ 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
+ 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
+ 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,...)
+ registerpath("extra lua","lua",extraluapaths,...)
end
function package.pushluapath(path)
- pushpath("extra lua","lua",extraluapaths,path)
+ pushpath("extra lua","lua",extraluapaths,path)
end
function package.popluapath()
- poppath("extra lua","lua",extraluapaths)
+ poppath("extra lua","lua",extraluapaths)
end
function package.extralibpath(...)
- registerpath("extra lib","lib",extralibpaths,...)
+ registerpath("extra lib","lib",extralibpaths,...)
end
function package.pushlibpath(path)
- pushpath("extra lib","lib",extralibpaths,path)
+ pushpath("extra lib","lib",extralibpaths,path)
end
function package.poplibpath()
- poppath("extra lib","lua",extralibpaths)
+ poppath("extra lib","lua",extralibpaths)
end
local function loadedaslib(resolved,rawname)
- local base=gsub(rawname,"%.","_")
- local init="luaopen_"..gsub(base,"%.","_")
- if helpers.trace then
- helpers.report("calling loadlib with '%s' with init '%s'",resolved,init)
- end
- return package.loadlib(resolved,init)
+ local base=gsub(rawname,"%.","_")
+ local init="luaopen_"..gsub(base,"%.","_")
+ if helpers.trace then
+ helpers.report("calling loadlib with '%s' with init '%s'",resolved,init)
+ end
+ return package.loadlib(resolved,init)
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
+ 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
+ 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["already loaded"]=function(name)
- return package.loaded[name]
+ return package.loaded[name]
end
methods["preload table"]=function(name)
- return builtin["preload table"](name)
+ return builtin["preload table"](name)
end
methods["qualified path"]=function(name)
- return loadedbyname(addsuffix(lualibfile(name),"lua"),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")
+ 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")
+ return loadedbypath(addsuffix(lualibfile(name),os.libsuffix),name,getextralibpaths(),true,"lib")
end
methods["path specification"]=function(name)
- getluapaths()
- return builtin["path specification"](name)
+ getluapaths()
+ return builtin["path specification"](name)
end
methods["cpath specification"]=function(name)
- getlibpaths()
- return builtin["cpath specification"](name)
+ getlibpaths()
+ return builtin["cpath specification"](name)
end
methods["all in one fallback"]=function(name)
- return builtin["all in one fallback"](name)
+ return builtin["all in one fallback"](name)
end
methods["not loaded"]=function(name)
- if helpers.trace then
- helpers.report("unable to locate '%s'",name or "?")
- end
- return nil
+ if helpers.trace then
+ helpers.report("unable to locate '%s'",name or "?")
+ 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]
- if helpers.trace then
- helpers.report("%s, level '%s', method '%s', name '%s'","locating",level,method,name)
- end
- local result,rest=methods[method](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
+ local sequence=helpers.sequence
+ level=level+1
+ for i=1,#sequence do
+ local method=sequence[i]
+ if helpers.trace then
+ helpers.report("%s, level '%s', method '%s', name '%s'","locating",level,method,name)
end
- level=level-1
- return nil
+ local result,rest=methods[method](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
+ 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
+ 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
+ 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
- package.loaded[name]=nil
+ end
+ package.loaded[name]=nil
end
table.insert(searchers,1,helpers.loaded)
if context then
- package.path=""
+ package.path=""
end
end -- closure
@@ -446,11 +445,11 @@
do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['l-lpeg']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
+ version=1.001,
+ comment="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
@@ -461,7 +460,7 @@
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)
+ setinspector("lpeg",function(v) if lpegtype(v) then lpegprint(v) return true end end)
end
lpeg.patterns=lpeg.patterns or {}
local patterns=lpeg.patterns
@@ -484,7 +483,7 @@
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 newline=P("\r")*(P("\n")+P(true))+P("\n")
local escaped=P("\\")*anything
local squote=P("'")
local dquote=P('"')
@@ -493,9 +492,9 @@
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_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")
@@ -527,7 +526,7 @@
patterns.validutf8=validutf8char
patterns.validutf8char=validutf8char
local eol=S("\n\r")
-local spacer=S(" \t\f\v")
+local spacer=S(" \t\f\v")
local whitespace=eol+spacer
local nonspacer=1-spacer
local nonwhitespace=1-whitespace
@@ -536,7 +535,7 @@
patterns.whitespace=whitespace
patterns.nonspacer=nonspacer
patterns.nonwhitespace=nonwhitespace
-local stripper=spacer^0*C((spacer^0*nonspacer^1)^0)
+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)
@@ -613,83 +612,83 @@
patterns.beginline=#(1-newline)
patterns.longtostring=Cs(whitespace^0/""*((patterns.quoted+nonwhitespace^1+whitespace^1/""*(endofstring+Cc(" ")))^0))
function anywhere(pattern)
- return (1-P(pattern))^0*P(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
+ 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
+ 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
+ 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
+ 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
- return splitter
+ 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
+ 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)
+ 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
+ c=tsplitat(separator)
+ cache[separator]=c
end
return lpegmatch(c,str)
+ else
+ return { str }
+ end
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
@@ -698,276 +697,276 @@
local linesplitter=tsplitat(newline)
patterns.linesplitter=linesplitter
function string.splitlines(str)
- return lpegmatch(linesplitter,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)
+ 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)
+ 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 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)
+ 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)
+ 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)
+ return (P(str)+P(true))*Cs(anything^0)
end
function lpeg.endstripper(str)
- return Cs((1-P(str)*endofstring)^0)
+ 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
+ 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
- pattern=Cs((P(one)/(two or "")+u)^0)
+ for i=1,no do
+ local o=one[i]
+ p=p+P(o[1])/o[2]
+ end
+ pattern=Cs((p+u)^0)
end
- if makefunction then
- return function(str)
- return lpegmatch(pattern,str)
- end
- else
- return pattern
+ 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
+ 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
- pattern=P(lst)
+ for i=1,#lst do
+ pattern=pattern+P(lst[i])
+ end
end
- if isutf then
- pattern=((utf8char or 1)-pattern)^0*pattern
- else
- pattern=(1-pattern)^0*pattern
+ 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
- if makefunction then
- return function(str)
- return lpegmatch(pattern,str)
- end
- else
- return pattern
- 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
+ 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
+ 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
+ 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
+ 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 }
+ 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
+ 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"
+ 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
+ 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
+ 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
+ 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)
+ 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
- for i=1,#keys,1 do
- local k=keys[i]
- local v=list[k]
- p=P(k)/list+p
- end
+ p=P(k)+p
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
+ p=P(k)
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
+ 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
- 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
+ else
+ if k==v then
+ p=P(k)
+ else
+ p=P(k)/v
end
+ end
end
- return p
+ 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)
@@ -974,172 +973,172 @@
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
+ 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
+ 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
- if rest then
- p=p+p_true
- end
- return p
+ 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
+ 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
- if rest then
- p=p+p_true
- end
- return p
+ 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
+ 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
- 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
+ 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
- return (insensitive and make2 or make1)(tree)
+ 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
+ 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
+ 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
- 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
+ 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 }))
+ 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
+ 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={}
@@ -1146,15 +1145,15 @@
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
+ 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
@@ -1173,47 +1172,47 @@
patterns.bytestohex=bytestohex
patterns.bytestodec=bytestodec
function string.toHEX(s)
- if not s or s=="" then
- return s
- else
- return lpegmatch(bytestoHEX,s)
- end
+ 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
+ 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
+ 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
+ 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
+ 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)
+ return lpegmatch(patterns[what] or containsws(what),str)
end
end -- closure
@@ -1221,11 +1220,11 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="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
@@ -1235,11 +1234,11 @@
do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['l-string']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
local string=string
local sub,gmatch,format,char,byte,rep,lower=string.sub,string.gmatch,string.format,string.char,string.byte,string.rep,string.lower
@@ -1247,25 +1246,25 @@
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
+ return lpegmatch(unquoted,str) or str
end
function string.quoted(str)
- return format("%q",str)
+ return format("%q",str)
end
function string.count(str,pattern)
- local n=0
- for _ in gmatch(str,pattern) do
- n=n+1
- end
- return n
+ local n=0
+ for _ in gmatch(str,pattern) do
+ n=n+1
+ end
+ return n
end
function string.limit(str,n,sentinel)
- if #str>n then
- sentinel=sentinel or "..."
- return sub(str,1,(n-#sentinel))..sentinel
- else
- return str
- end
+ 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
@@ -1273,81 +1272,81 @@
local nospacer=patterns.nospacer
local longtostring=patterns.longtostring
function string.strip(str)
- return str and lpegmatch(stripper,str) or ""
+ return str and lpegmatch(stripper,str) or ""
end
function string.fullstrip(str)
- return str and lpegmatch(fullstripper,str) or ""
+ return str and lpegmatch(fullstripper,str) or ""
end
function string.collapsespaces(str)
- return str and lpegmatch(collapser,str) or ""
+ return str and lpegmatch(collapser,str) or ""
end
function string.nospaces(str)
- return str and lpegmatch(nospacer,str) or ""
+ return str and lpegmatch(nospacer,str) or ""
end
function string.longtostring(str)
- return str and lpegmatch(longtostring,str) or ""
+ 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
+ if not str or str=="" then
+ return true
+ else
+ return lpegmatch(pattern,str) and true or false
+ end
end
local anything=patterns.anything
local allescapes=Cc("%")*S(".-+%?()[]*")
-local someescapes=Cc("%")*S(".-+%()[]")
-local matchescapes=Cc(".")*S("*?")
+local someescapes=Cc("%")*S(".-+%()[]")
+local matchescapes=Cc(".")*S("*?")
local pattern_a=Cs ((allescapes+anything )^0 )
local pattern_b=Cs ((someescapes+matchescapes+anything )^0 )
local pattern_c=Cs (Cc("^")*(someescapes+matchescapes+anything )^0*Cc("$") )
function string.escapedpattern(str,simple)
- return lpegmatch(simple and pattern_b or pattern_a,str)
+ return lpegmatch(simple and pattern_b or pattern_a,str)
end
function string.topattern(str,lowercase,strict)
- if str=="" or type(str)~="string" then
- return ".*"
- elseif strict then
- str=lpegmatch(pattern_c,str)
- else
- str=lpegmatch(pattern_b,str)
- end
- if lowercase then
- return lower(str)
- else
- return str
- end
+ if str=="" or type(str)~="string" then
+ return ".*"
+ elseif strict then
+ str=lpegmatch(pattern_c,str)
+ else
+ str=lpegmatch(pattern_b,str)
+ end
+ if lowercase then
+ return lower(str)
+ else
+ return str
+ end
end
function string.valid(str,default)
- return (type(str)=="string" and str~="" and str) or default or nil
+ 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)
+ return lpegmatch(bytes and pattern_b or pattern_c,str)
end
local replacer=lpeg.replacer("@","%%")
function string.tformat(fmt,...)
- return format(lpegmatch(replacer,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
+ 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 -- closure
@@ -1355,11 +1354,11 @@
do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['l-table']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
+ version=1.001,
+ comment="companion 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=type,next,tostring,tonumber,select
local table,string=table,string
@@ -1370,147 +1369,147 @@
local floor=math.floor
local stripper=patterns.stripper
function table.getn(t)
- return t and #t
+ return t and #t
end
function table.strip(tab)
- local lst,l={},0
- for i=1,#tab do
- local s=lpegmatch(stripper,tab[i]) or ""
- if s=="" then
- else
- l=l+1
- lst[l]=s
- end
+ local lst,l={},0
+ for i=1,#tab do
+ local s=lpegmatch(stripper,tab[i]) or ""
+ if s=="" then
+ else
+ l=l+1
+ lst[l]=s
end
- return lst
+ end
+ return lst
end
function table.keys(t)
- if t then
- local keys,k={},0
- for key in next,t do
- k=k+1
- keys[k]=key
- end
- return keys
- else
- return {}
+ if t then
+ local keys,k={},0
+ for key in next,t do
+ k=k+1
+ keys[k]=key
end
+ return keys
+ else
+ return {}
+ end
end
local function compare(a,b)
- local ta=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
+ 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
- return tostring(a)<tostring(b)
+ 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,category,s={},0,0
- for key in next,tab do
- s=s+1
- srt[s]=key
- if category==3 then
- elseif category==1 then
- if type(key)~="string" then
- category=3
- end
- elseif category==2 then
- if type(key)~="number" then
- category=3
- end
- else
- local tkey=type(key)
- if tkey=="string" then
- category=1
- elseif tkey=="number" then
- category=2
- else
- category=3
- end
- end
+ if tab then
+ local srt,category,s={},0,0
+ for key in next,tab do
+ s=s+1
+ srt[s]=key
+ if category==3 then
+ elseif category==1 then
+ if type(key)~="string" then
+ category=3
end
- if s<2 then
- elseif category==3 then
- sort(srt,compare)
+ elseif category==2 then
+ if type(key)~="number" then
+ category=3
+ end
+ else
+ local tkey=type(key)
+ if tkey=="string" then
+ category=1
+ elseif tkey=="number" then
+ category=2
else
- sort(srt)
+ category=3
end
- return srt
+ end
+ end
+ if s<2 then
+ elseif category==3 then
+ sort(srt,compare)
else
- return {}
+ sort(srt)
end
+ return srt
+ else
+ return {}
+ end
end
local function sortedhashonly(tab)
- if tab then
- local srt,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 {}
+ if tab then
+ local srt,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,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 {}
+ if tab then
+ local srt,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,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 {}
+ if tab then
+ local srt,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
+ local keys={}
+ for k,v in next,t do
+ for k in next,v do
+ keys[k]=true
end
- return sortedkeys(keys)
+ end
+ return sortedkeys(keys)
end
table.sortedkeys=sortedkeys
table.sortedhashonly=sortedhashonly
@@ -1518,927 +1517,927 @@
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)
+ 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
- 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
end
- return nothing
+ 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
+ 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
+ local nl=#list
+ local nt=nl+#t
+ for i=#t,1,-1 do
+ t[nt]=t[i]
+ nt=nt-1
+ end
+ for i=1,#list do
+ t[i]=list[i]
+ end
+ return t
end
function table.merge(t,...)
- t=t or {}
- for i=1,select("#",...) do
- for k,v in next,(select(i,...)) do
- t[k]=v
- end
+ t=t or {}
+ for i=1,select("#",...) do
+ for k,v in next,(select(i,...)) do
+ t[k]=v
end
- return t
+ 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
+ local t={}
+ for i=1,select("#",...) do
+ for k,v in next,(select(i,...)) do
+ t[k]=v
end
- return t
+ 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
+ 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
- return t
+ end
+ return t
end
function table.imerged(...)
- local tmp,ntmp={},0
- for i=1,select("#",...) do
- local nst=select(i,...)
- for j=1,#nst do
- ntmp=ntmp+1
- tmp[ntmp]=nst[j]
- end
+ local tmp,ntmp={},0
+ for i=1,select("#",...) do
+ local nst=select(i,...)
+ for j=1,#nst do
+ ntmp=ntmp+1
+ tmp[ntmp]=nst[j]
end
- return tmp
+ 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 {}
+ if old then
+ local new={}
+ for k,v in next,old do
+ if type(v)=="table" then
+ new[k]=fastcopy(v,metatabletoo)
+ else
+ new[k]=v
+ end
end
+ if metatabletoo then
+ local mt=getmetatable(old)
+ if mt then
+ setmetatable(new,mt)
+ end
+ end
+ return new
+ else
+ return {}
+ end
end
local function copy(t,tables)
- tables=tables or {}
- local tcopy={}
- if not tables[t] then
- tables[t]=tcopy
+ tables=tables or {}
+ local tcopy={}
+ if not tables[t] then
+ tables[t]=tcopy
+ end
+ for i,v in next,t do
+ if type(i)=="table" then
+ if tables[i] then
+ i=tables[i]
+ else
+ i=copy(i,tables)
+ end
end
- 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
+ if type(v)~="table" then
+ tcopy[i]=v
+ elseif tables[v] then
+ tcopy[i]=tables[v]
+ else
+ tcopy[i]=copy(v,tables)
end
- local mt=getmetatable(t)
- if mt then
- setmetatable(tcopy,mt)
- end
- return tcopy
+ 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
+ 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
+ local h={}
+ if t then
+ if value==nil then value=true end
+ for _,v in next,t do
+ h[v]=value
end
- return h
+ end
+ return h
end
function table.fromhash(t)
- local hsh,h={},0
- for k,v in next,t do
- if v then
- h=h+1
- hsh[h]=k
- end
+ local hsh,h={},0
+ for k,v in next,t do
+ if v then
+ h=h+1
+ hsh[h]=k
end
- return hsh
+ end
+ return hsh
end
local noquotes,hexify,handle,compact,inline,functions,metacheck
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',
+ 'and','break','do','else','elseif','end','false','for','function','if',
+ 'in','local','nil','not','or','repeat','return','then','true','until','while',
+ 'NaN','goto',
}
local function is_simple_table(t,hexify)
- 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
+ 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)
+ 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
- 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)
- 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)
- 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
+ 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)
+ 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
- return nil
+ 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))
+ 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
- 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
+ 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
- if root and next(root)~=nil then
- local first,last=nil,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
+ if root and next(root)~=nil then
+ local first,last=nil,0
+ if compact then
+ last=#root
+ for k=1,last do
+ if rawget(root,k)==nil then
+ last=k-1
+ break
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))
- 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)
- 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))
- 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))
- 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))
- else
- handle(format("%s %s=%s,",depth,k,v))
- end
- else
- if hexify then
- handle(format("%s [%q]=0x%X,",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))
- 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))
- 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)
- if st then
- if tk=="number" then
- if hexify then
- handle(format("%s [0x%X]={ %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"))
- 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))
- 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
+ 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))
+ 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)
+ if st then
+ handle(format("%s { %s },",depth,concat(st,", ")))
else
- if tk=="number" then
- if hexify then
- handle(format("%s [0x%X]=%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
+ 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
- end
- if level>0 then
- handle(format("%s},",depth))
- end
-end
-local function serialize(_handle,root,name,specification)
- local tname=type(name)
- if type(specification)=="table" then
- noquotes=specification.noquotes
- hexify=specification.hexify
- handle=_handle or specification.handle or print
- functions=specification.functions
- compact=specification.compact
- inline=specification.inline and compact
- metacheck=specification.metacheck
- if functions==nil then
- functions=true
+ elseif k=="__p__" then
+ if false then
+ handle(format("%s __p__=nil,",depth))
end
- if compact==nil then
- compact=true
+ elseif tv=="number" then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%X]=0x%X,",depth,k,v))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v))
+ end
+ elseif tk=="boolean" then
+ if hexify then
+ handle(format("%s [%s]=0x%X,",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))
+ else
+ handle(format("%s %s=%s,",depth,k,v))
+ end
+ else
+ if hexify then
+ handle(format("%s [%q]=0x%X,",depth,k,v))
+ else
+ handle(format("%s [%q]=%s,",depth,k,v))
+ end
end
- if inline==nil then
- inline=compact
+ elseif tv=="string" then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%X]=%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
- 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 {")
+ elseif tv=="table" then
+ if next(v)==nil then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%X]={},",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)
+ if st then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%X]={ %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
- handle(name.."={")
+ do_serialize(v,k,depth,level+1)
end
- elseif tname=="number" then
- if hexify then
- handle(format("[0x%X]={",name))
+ elseif tv=="boolean" then
+ if tk=="number" then
+ if hexify then
+ handle(format("%s [0x%X]=%s,",depth,k,v and "true" or "false"))
+ else
+ handle(format("%s [%s]=%s,",depth,k,v and "true" or "false"))
+ end
+ 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("["..name.."]={")
+ handle(format("%s [%q]=%s,",depth,k,v and "true" or "false"))
end
- elseif tname=="boolean" then
- if name then
- handle("return {")
+ 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))
+ 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)))
+ 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("{")
+ handle(format("%s [%q]=%q,",depth,k,tostring(v)))
end
+ end
+ end
+ end
+ if level>0 then
+ handle(format("%s},",depth))
+ end
+end
+local function serialize(_handle,root,name,specification)
+ local tname=type(name)
+ if type(specification)=="table" then
+ noquotes=specification.noquotes
+ hexify=specification.hexify
+ handle=_handle or specification.handle or print
+ 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("t={")
+ handle(name.."={")
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
+ elseif tname=="number" then
+ if hexify then
+ handle(format("[0x%X]={",name))
+ else
+ handle("["..name.."]={")
end
- handle("}")
+ 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,n={},0
- local function flush(s)
- n=n+1
- t[n]=s
- end
- serialize(flush,root,name,specification)
- return concat(t,"\n")
+ local t,n={},0
+ local function flush(s)
+ n=n+1
+ t[n]=s
+ end
+ serialize(flush,root,name,specification)
+ return concat(t,"\n")
end
table.tohandle=serialize
local maxtab=2*1024
function table.tofile(filename,root,name,specification)
- local f=io.open(filename,'w')
- if f then
- if maxtab>1 then
- local t,n={},0
- local function flush(s)
- n=n+1
- t[n]=s
- if n>maxtab then
- f:write(concat(t,"\n"),"\n")
- t,n={},0
- end
- end
- serialize(flush,root,name,specification)
- f:write(concat(t,"\n"),"\n")
- else
- local function flush(s)
- f:write(s,"\n")
- end
- serialize(flush,root,name,specification)
+ local f=io.open(filename,'w')
+ if f then
+ if maxtab>1 then
+ local t,n={},0
+ local function flush(s)
+ n=n+1
+ t[n]=s
+ if n>maxtab then
+ f:write(concat(t,"\n"),"\n")
+ t,n={},0
end
- f:close()
- io.flush()
+ 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
+ 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
- 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
- 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
+ return f
end
table.flattened=flattened
local function collapsed(t,f,h)
- if f==nil then
- 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
- 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
+ return f
end
local function collapsedhash(t,h)
- if h==nil then
- 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
- 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
+ return h
end
-table.collapsed=collapsed
+table.collapsed=collapsed
table.collapsedhash=collapsedhash
local function unnest(t,f)
- if not f then
- 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
- 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
+ return f
end
function table.unnest(t)
- return 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
- n=n or 1
- m=m or #a
- for i=n,m do
- local ai,bi=a[i],b[i]
- if ai==bi then
- elseif type(ai)=="table" and type(bi)=="table" then
- if not are_equal(ai,bi) then
- return false
- end
- else
- return false
- end
+ if a==b then
+ return true
+ elseif a and b and #a==#b then
+ n=n or 1
+ m=m or #a
+ for i=n,m do
+ local ai,bi=a[i],b[i]
+ if ai==bi then
+ elseif type(ai)=="table" and type(bi)=="table" then
+ if not are_equal(ai,bi) then
+ return false
end
- return true
- else
+ 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
+ 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
- return true
+ 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
+ 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
- return new
+ end
+ return new
end
table.sparse=sparse
function table.compact(t)
- return sparse(t,true,true)
+ 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
+ if t then
+ for i=1,#t do
+ if t[i]==v then
+ return i
+ end
end
- return false
+ end
+ return false
end
function table.count(t)
- local n=0
- for k,v in next,t do
- n=n+1
- end
- return n
+ 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
+ local n={}
+ if s then
+ for k,v in next,s do
+ n[k]=v
end
- for k,v in next,t do
- n[v]=k
- end
- return n
+ 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
+ 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
+ local n={}
+ for k,v in next,t do
+ n[v]=k
+ n[k]=v
+ end
+ return n
end
function table.reversed(t)
- if t then
- local tt,tn={},#t
- if tn>0 then
- local ttn=0
- for i=tn,1,-1 do
- ttn=ttn+1
- tt[ttn]=t[i]
- end
- end
- return tt
+ if t then
+ local tt,tn={},#t
+ if tn>0 then
+ local ttn=0
+ for i=tn,1,-1 do
+ ttn=ttn+1
+ tt[ttn]=t[i]
+ end
end
+ return tt
+ end
end
function table.reverse(t)
- if t then
- local n=#t
- 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
+ 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)=="string" then
- return t
+ if not t then
+ return ""
+ elseif type(t)=="string" 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
- 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
+ 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=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
+ 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
- return concat(s,sep or " | ")
+ end
+ return concat(s,sep or " | ")
end
table.sequenced=sequenced
function table.print(t,...)
- if type(t)~="table" then
- print(tostring(t))
- else
- serialize(print,t,...)
- end
+ 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)
+ 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) }
+ return { unpack(t,i,j) }
end
function table.is_empty(t)
- return not t or next(t)==nil
+ return not t or next(t)==nil
end
function table.has_one_entry(t)
- return t and next(t,next(t))==nil
+ 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
+ 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
+ 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
- return new
+ end
+ return new
end
function table.sorted(t,...)
- sort(t,...)
- return t
+ sort(t,...)
+ return t
end
function table.values(t,s)
- if t then
- local values,keys,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 {}
+ if t then
+ local values,keys,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
+ 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
- return nothing
+ 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
+ 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 -- closure
@@ -2446,66 +2445,66 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="companion 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
+ 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
+ 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
+ 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
+ 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
- return default
+ end
+ return default
end
end -- closure
@@ -2513,11 +2512,11 @@
do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['l-number']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
+ version=1.001,
+ comment="companion to luat-lib.mkiv",
+ 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,floor,match,rep=string.format,math.floor,string.match,string.rep
@@ -2527,107 +2526,107 @@
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
+ 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"
+ 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
+ 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
+ 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
+ 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
+ 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)
+ return floor(i/d)
end
end -- closure
@@ -2635,90 +2634,90 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="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
+ math.ceiling=math.ceil
end
if not math.round then
- local floor=math.floor
- function math.round(x) return floor(x+0.5) end
+ local floor=math.floor
+ function math.round(x) return floor(x+0.5) end
end
if not math.div then
- local floor=math.floor
- function math.div(n,m) return floor(n/m) end
+ 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
+ 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
+ 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
+ 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
+ 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
+ function math.pow(x,y)
+ return x^y
+ end
end
if not math.atan2 then
- math.atan2=math.atan
+ math.atan2=math.atan
end
if not math.ldexp then
- function math.ldexp(x,e)
- return x*2.0^e
- end
+ 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
+ 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
+ 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
+ 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.tointeger(m,n)
- return floor(m)<floor(n)
- end
+ local floor=math.floor
+ function math.tointeger(m,n)
+ return floor(m)<floor(n)
+ end
end
end -- closure
@@ -2726,11 +2725,11 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="companion 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
@@ -2738,334 +2737,334 @@
local concat=table.concat
local type=type
if string.find(os.getenv("PATH"),";",1,true) then
- io.fileseparator,io.pathseparator="\\",";"
+ io.fileseparator,io.pathseparator="\\",";"
else
- io.fileseparator,io.pathseparator="/",":"
+ 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
+ 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
+ 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()
+ 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
- f:close()
- flush()
+ if data then
+ g:write(data)
+ end
+ end
+ g:close()
end
+ f:close()
+ flush()
+ end
end
function io.savedata(filename,data,joiner)
- local f=open(filename,"wb")
- if f then
- 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
+ local f=open(filename,"wb")
+ if f then
+ if type(data)=="table" then
+ f:write(concat(data,joiner or ""))
+ elseif type(data)=="function" then
+ data(f)
else
- return false
+ 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
+ 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
- local line=readline(f)
- f:close()
- if line and #line>0 then
- return line
- end
+ 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
+ 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
- local line=f:read("*line") or ""
- f:close()
- if #line>0 then
- return line
- end
+ 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
+ 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
+ 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
+ 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
+ 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
- local n=0
- for _ in f:lines() do
- n=n+1
- end
- f:seek('set',0)
- return n
+ 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
+ [ 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
+ 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
+ [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
+ 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,"|")))
+ 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
- if default then
- write(format(" [%s]",default))
+ end
+ local pattern="^"..answer
+ for k=1,#options do
+ local v=options[k]
+ if find(v,pattern) then
+ return v
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
+ 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
+ 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
+ if m then
+ f:seek("set",n)
+ n=m
+ end
+ local str=gsub(f:read(n),"\000","")
+ return str
end
end -- closure
@@ -3073,11 +3072,11 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="companion 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=os.date,os.time
@@ -3086,304 +3085,304 @@
local random,ceil,randomseed=math.random,math.ceil,math.randomseed
local rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring=rawget,rawset,type,getmetatable,setmetatable,tonumber,tostring
do
- local selfdir=os.selfdir
- if selfdir=="" then
- selfdir=nil
+ 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
- if arg then
- for i=1,#arg do
- local a=arg[i]
- if find(a,"^%-%-[c:]*texmfbinpath=") then
- selfdir=gsub(a,"^.-=","")
- break
- end
- end
+ 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
- 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
+ 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
- os.selfdir=selfdir or "."
+ 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 } )
+ 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
local execute=os.execute
local iopopen=io.popen
local function resultof(command)
- local handle=iopopen(command,"r")
- if handle then
- local result=handle:read("*all") or ""
- handle:close()
- return result
- else
- return ""
- end
+ local handle=iopopen(command,"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")
+ return iopopen(command,"w")
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
+ 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"
+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' }
+ os.libsuffix,os.binsuffix,os.binsuffixes='dll','exe',{ 'exe','cmd','bat' }
else
- os.libsuffix,os.binsuffix,os.binsuffixes='so','',{ '' }
+ os.libsuffix,os.binsuffix,os.binsuffixes='so','',{ '' }
end
local launchers={
- windows="start %s",
- macosx="open %s",
- unix="xdg-open %s &> /dev/null &",
+ windows="start %s",
+ macosx="open %s",
+ unix="xdg-open %s &> /dev/null &",
}
function os.launch(str)
- execute(format(launchers[os.name] or launchers.unix,str))
+ execute(format(launchers[os.name] or launchers.unix,str))
end
if not os.times then
- function os.times()
- return {
- utime=os.gettimeofday(),
- stime=0,
- cutime=0,
- cstime=0,
- }
- end
+ function os.times()
+ return {
+ utime=os.gettimeofday(),
+ stime=0,
+ cutime=0,
+ cstime=0,
+ }
+ end
end
local gettimeofday=os.gettimeofday or os.clock
os.gettimeofday=gettimeofday
local startuptime=gettimeofday()
function os.runtime()
- return gettimeofday()-startuptime
+ return gettimeofday()-startuptime
end
local resolvers=os.resolvers or {}
os.resolvers=resolvers
setmetatable(os,{ __index=function(t,k)
- local r=resolvers[k]
- return r and r(t,k) or nil
+ local r=resolvers[k]
+ return r and r(t,k) or nil
end })
local name,platform=os.name or "linux",os.getenv("MTX_PLATFORM") or ""
if platform~="" then
- os.platform=platform
+ os.platform=platform
elseif os.type=="windows" then
- function resolvers.platform(t,k)
- local architecture=os.getenv("PROCESSOR_ARCHITECTURE") or ""
- local platform=""
- if find(architecture,"AMD64",1,true) then
- platform="win64"
- else
- platform="mswin"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform=platform
- return platform
+ function resolvers.platform(t,k)
+ local architecture=os.getenv("PROCESSOR_ARCHITECTURE") or ""
+ local platform=""
+ if find(architecture,"AMD64",1,true) then
+ platform="win64"
+ else
+ platform="mswin"
end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
elseif name=="linux" then
- function resolvers.platform(t,k)
- local architecture=os.getenv("HOSTTYPE") or resultof("uname -m") or ""
- local platform=os.getenv("MTX_PLATFORM") or ""
- local musl=find(os.selfdir or "","linuxmusl")
- if platform~="" then
- elseif find(architecture,"x86_64",1,true) then
- platform=musl and "linuxmusl" or "linux-64"
- elseif find(architecture,"ppc",1,true) then
- platform="linux-ppc"
- else
- platform=musl and "linuxmusl" or "linux"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform=platform
- return platform
+ function resolvers.platform(t,k)
+ local architecture=os.getenv("HOSTTYPE") or resultof("uname -m") or ""
+ local platform=os.getenv("MTX_PLATFORM") or ""
+ local musl=find(os.selfdir or "","linuxmusl")
+ if platform~="" then
+ elseif find(architecture,"x86_64",1,true) then
+ platform=musl and "linuxmusl" or "linux-64"
+ elseif find(architecture,"ppc",1,true) then
+ platform="linux-ppc"
+ else
+ platform=musl and "linuxmusl" or "linux"
end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
elseif name=="macosx" then
- function resolvers.platform(t,k)
- local architecture=resultof("echo $HOSTTYPE") or ""
- local platform=""
- if architecture=="" then
- platform="osx-intel"
- elseif find(architecture,"i386",1,true) then
- platform="osx-intel"
- elseif find(architecture,"x86_64",1,true) then
- platform="osx-64"
- else
- platform="osx-ppc"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform=platform
- return platform
+ function resolvers.platform(t,k)
+ local architecture=resultof("echo $HOSTTYPE") or ""
+ local platform=""
+ if architecture=="" then
+ platform="osx-intel"
+ elseif find(architecture,"i386",1,true) then
+ platform="osx-intel"
+ elseif find(architecture,"x86_64",1,true) then
+ platform="osx-64"
+ else
+ platform="osx-ppc"
end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
elseif name=="sunos" then
- function resolvers.platform(t,k)
- local architecture=resultof("uname -m") or ""
- local platform=""
- if find(architecture,"sparc",1,true) then
- platform="solaris-sparc"
- else
- platform="solaris-intel"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform=platform
- return platform
+ function resolvers.platform(t,k)
+ local architecture=resultof("uname -m") or ""
+ local platform=""
+ if find(architecture,"sparc",1,true) then
+ platform="solaris-sparc"
+ else
+ platform="solaris-intel"
end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
elseif name=="freebsd" then
- function resolvers.platform(t,k)
- local architecture=resultof("uname -m") or ""
- local platform=""
- if find(architecture,"amd64",1,true) then
- platform="freebsd-amd64"
- else
- platform="freebsd"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform=platform
- return platform
+ function resolvers.platform(t,k)
+ local architecture=resultof("uname -m") or ""
+ local platform=""
+ if find(architecture,"amd64",1,true) then
+ platform="freebsd-amd64"
+ else
+ platform="freebsd"
end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
elseif name=="kfreebsd" then
- function resolvers.platform(t,k)
- local architecture=os.getenv("HOSTTYPE") or resultof("uname -m") or ""
- local platform=""
- if find(architecture,"x86_64",1,true) then
- platform="kfreebsd-amd64"
- else
- platform="kfreebsd-i386"
- end
- os.setenv("MTX_PLATFORM",platform)
- os.platform=platform
- return platform
+ function resolvers.platform(t,k)
+ local architecture=os.getenv("HOSTTYPE") or resultof("uname -m") or ""
+ local platform=""
+ if find(architecture,"x86_64",1,true) then
+ platform="kfreebsd-amd64"
+ else
+ platform="kfreebsd-i386"
end
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
else
- function resolvers.platform(t,k)
- local platform="linux"
- os.setenv("MTX_PLATFORM",platform)
- os.platform=platform
- return platform
- end
+ function resolvers.platform(t,k)
+ local platform="linux"
+ os.setenv("MTX_PLATFORM",platform)
+ os.platform=platform
+ return platform
+ end
end
os.newline=name=="windows" and "\013\010" or "\010"
function resolvers.bits(t,k)
- local bits=find(os.platform,"64",1,true) and 64 or 32
- os.bits=bits
- return bits
+ local bits=find(os.platform,"64",1,true) and 64 or 32
+ os.bits=bits
+ return bits
end
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)
- )
+ 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
local d
function os.timezone(delta)
- d=d or tonumber(tonumber(date("%H")-date("!%H")))
- if delta then
- if d>0 then
- return format("+%02i:00",d)
- else
- return format("-%02i:00",-d)
- end
+ d=d or tonumber(tonumber(date("%H")-date("!%H")))
+ if delta then
+ if d>0 then
+ return format("+%02i:00",d)
else
- return 1
+ return format("-%02i:00",-d)
end
+ else
+ return 1
+ end
end
local timeformat=format("%%s%s",os.timezone(true))
local dateformat="!%Y-%m-%d %H:%M:%S"
@@ -3390,129 +3389,129 @@
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
+ 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
+ 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
+ local t=tonumber(t)
+ if t and t>0 then
+ return date(dateformat,t)
+ else
+ return default or "-"
+ end
end
local memory={}
local function which(filename)
- local fullname=memory[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
+ local fullname=memory[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
- if not fullname then
- fullname=false
- end
- memory[filename]=fullname
+ end
end
- return fullname
+ if not fullname then
+ fullname=false
+ end
+ memory[filename]=fullname
+ end
+ return fullname
end
os.which=which
os.where=which
function os.today()
- return date("!*t")
+ return date("!*t")
end
function os.now()
- return date("!%Y-%m-%d %H:%M:%S")
+ return date("!%Y-%m-%d %H:%M:%S")
end
if not os.sleep then
- local socket=socket
- function os.sleep(n)
- if not socket then
- socket=require("socket")
- end
- socket.sleep(n)
+ local socket=socket
+ function os.sleep(n)
+ if not socket then
+ socket=require("socket")
end
+ socket.sleep(n)
+ end
end
local function isleapyear(year)
- return (year%4==0) and (year%100~=0 or year%400==0)
+ 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)
- if not month then
- return isleapyear(year) and 365 or 364
- else
- return month==2 and isleapyear(year) and 29 or days[month]
- end
+ if not month then
+ return isleapyear(year) and 365 or 364
+ else
+ return month==2 and isleapyear(year) and 29 or days[month]
+ end
end
os.nofdays=nofdays
function os.weekday(day,month,year)
- return date("%w",time { year=year,month=month,day=day })+1
+ 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
+ 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
- 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
+ return year,month,day
end
local osexit=os.exit
local exitcode=nil
function os.setexitcode(code)
- exitcode=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()
+ if exitcode~=nil then
+ return osexit(exitcode)
+ end
+ if c~=nil then
+ return osexit(c)
+ end
+ return osexit()
end
end -- closure
@@ -3520,16 +3519,16 @@
do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['l-file']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
+ version=1.001,
+ comment="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")
+ lfs=optionalrequire("lfs")
end
local insert,concat=table.insert,table.concat
local match,find,gmatch=string.match,string.find,string.gmatch
@@ -3539,20 +3538,20 @@
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)
- return attributes(name,"mode")=="directory"
+ return attributes(name,"mode")=="directory"
end
function lfs.isfile(name)
- local a=attributes(name,"mode")
- return a=="file" or a=="link" or nil
+ local a=attributes(name,"mode")
+ return a=="file" or a=="link" or nil
end
function lfs.isfound(name)
- local a=attributes(name,"mode")
- return (a=="file" or a=="link") and name or nil
+ local a=attributes(name,"mode")
+ return (a=="file" or a=="link") and name or nil
end
if sandbox then
- sandbox.redefine(lfs.isfile,"lfs.isfile")
- sandbox.redefine(lfs.isdir,"lfs.isdir")
- sandbox.redefine(lfs.isfound,"lfs.isfound")
+ 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(".")
@@ -3566,27 +3565,27 @@
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 ""
+ 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
+ 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
+ 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 ""
+ 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
+ if name then
+ return lpegmatch(pattern,name)
+ else
+ return ""
+ end
end
file.pathpart=pathpart
file.basename=basename
@@ -3595,7 +3594,7 @@
file.suffix=suffixonly
file.suffixesonly=suffixesonly
file.suffixes=suffixesonly
-file.dirname=pathpart
+file.dirname=pathpart
file.extname=suffixonly
local drive=C(R("az","AZ"))*colon
local path=C((noslashes^0*slashes)^0)
@@ -3611,142 +3610,142 @@
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
+ 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
+ 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
+ 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)
+ 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
+ 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
- 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
+ elseif t=="string" then
+ if s==criterium then
+ return filename
end
- return (n or filename).."."..suffix
+ 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
+ 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)
+ return str and lpegmatch(reslasher,str)
end
function file.is_writable(name)
- if not name then
- elseif lfs.isdir(name) then
- name=name.."/m_t_x_t_e_s_t.tmp"
- local f=io.open(name,"wb")
- if f then
- f:close()
- os.remove(name)
- return true
- end
- elseif lfs.isfile(name) then
- local f=io.open(name,"ab")
- if f then
- f:close()
- return true
- end
- else
- local f=io.open(name,"ab")
- if f then
- f:close()
- os.remove(name)
- return true
- end
+ 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
- return false
+ 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
+ if name then
+ local a=attributes(name)
+ return a and lpegmatch(readable,a.permissions) or false
+ else
+ return false
+ end
end
file.isreadable=file.is_readable
file.iswritable=file.is_writable
function file.size(name)
- if name then
- local a=attributes(name)
- return a and a.size or 0
- else
- return 0
- end
+ 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)
+ 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)
+ return tab and concat(tab,separator or io.pathseparator)
end
local someslash=S("\\/")
local stripper=Cs(P(fwslash)^0/""*reslasher)
@@ -3756,30 +3755,30 @@
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)
+ if not two then
+ return one=="" and one or lpegmatch(reslasher,one)
+ end
+ if one=="" then
+ return lpegmatch(stripper,three and concat({ two,three,... },"/") or two)
+ end
+ if lpegmatch(isnetwork,one) then
+ local one=lpegmatch(reslasher,one)
+ local two=lpegmatch(deslasher,three and concat({ two,three,... },"/") or two)
+ if lpegmatch(hasroot,two) then
+ return one..two
+ else
+ return one.."/"..two
end
- if one=="" then
- return lpegmatch(stripper,three and concat({ two,three,... },"/") or two)
- end
- if lpegmatch(isnetwork,one) then
- local one=lpegmatch(reslasher,one)
- local two=lpegmatch(deslasher,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
+ 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 lpegmatch(deslasher,concat({ one,two,three,... },"/"))
+ return "/"..two
end
+ else
+ return lpegmatch(deslasher,concat({ one,two,three,... },"/"))
+ end
end
local drivespec=R("az","AZ")^1*colon
local anchors=fwslash+drivespec
@@ -3789,56 +3788,56 @@
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)
+ 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
- i=i-1
+ end
+ if n<1 then
+ insert(newelements,1,'..')
+ end
+ elseif element~="" then
+ insert(newelements,1,element)
end
- if #newelements==0 then
- return starter or "."
- elseif starter then
- return starter..concat(newelements,'/')
- elseif lpegmatch(absolute,str) then
- return "/"..concat(newelements,'/')
+ 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
- newelements=concat(newelements,'/')
- if anchor=="." and find(str,"^%./") then
- return "./"..newelements
- else
- return newelements
- end
+ return newelements
end
+ end
end
local validchars=R("az","09","AZ","--","..")
local pattern_a=lpeg.replacer(1-validchars)
@@ -3846,14 +3845,14 @@
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
+ 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
@@ -3860,12 +3859,12 @@
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
+ 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("://")
@@ -3874,44 +3873,44 @@
lpeg.patterns.qualified=qualified
lpeg.patterns.rootbased=rootbased
function file.is_qualified_path(filename)
- return filename and lpegmatch(qualified,filename)~=nil
+ return filename and lpegmatch(qualified,filename)~=nil
end
function file.is_rootbased_path(filename)
- return filename and lpegmatch(rootbased,filename)~=nil
+ 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
+ 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
+ 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
+ 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
- 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
+ if l<0 then
+ return false
end
- return true
+ end
+ return true
end
local symlinkattributes=lfs.symlinkattributes
function lfs.readlink(name)
- return symlinkattributes(name,"target") or nil
+ return symlinkattributes(name,"target") or nil
end
end -- closure
@@ -3919,48 +3918,48 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
if not gzip then
- return
+ return
end
local suffix,suffixes=file.suffix,file.suffixes
function gzip.load(filename)
- local f=io.open(filename,"rb")
- if not f then
- elseif suffix(filename)=="gz" then
- f:close()
- local g=gzip.open(filename,"rb")
- if g then
- local str=g:read("*all")
- g:close()
- return str
- end
- else
- local str=f:read("*all")
- f:close()
- return str
+ local f=io.open(filename,"rb")
+ if not f then
+ elseif suffix(filename)=="gz" then
+ f:close()
+ local g=gzip.open(filename,"rb")
+ if g then
+ local str=g:read("*all")
+ g:close()
+ return str
end
+ else
+ local str=f:read("*all")
+ f:close()
+ return str
+ end
end
function gzip.save(filename,data)
- if suffix(filename)~="gz" then
- filename=filename..".gz"
- end
- local f=io.open(filename,"wb")
- if f then
- local s=zlib.compress(data or "",9,nil,15+16)
- f:write(s)
- f:close()
- return #s
- end
+ if suffix(filename)~="gz" then
+ filename=filename..".gz"
+ end
+ local f=io.open(filename,"wb")
+ if f then
+ local s=zlib.compress(data or "",9,nil,15+16)
+ f:write(s)
+ f:close()
+ return #s
+ end
end
function gzip.suffix(filename)
- local suffix,extra=suffixes(filename)
- local gzipped=extra=="gz"
- return suffix,gzipped
+ local suffix,extra=suffixes(filename)
+ local gzipped=extra=="gz"
+ return suffix,gzipped
end
end -- closure
@@ -3968,84 +3967,84 @@
do -- begin closure to overcome local limits and interference
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"
+ 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")
+ 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,
- }
+ 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
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
+ 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
function file.needsupdating(oldname,newname,threshold)
- local oldtime=lfs.attributes(oldname,"modification")
- if oldtime then
- local newtime=lfs.attributes(newname,"modification")
- 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
+ local oldtime=lfs.attributes(oldname,"modification")
+ if oldtime then
+ local newtime=lfs.attributes(newname,"modification")
+ if not newtime then
+ return true
+ elseif newtime>=oldtime then
+ return false
+ elseif oldtime-newtime<(threshold or 1) then
+ return false
else
- return false
+ return true
end
+ else
+ return false
+ end
end
file.needs_updating=file.needsupdating
function file.syncmtimes(oldname,newname)
- local oldtime=lfs.attributes(oldname,"modification")
- if oldtime and lfs.isfile(newname) then
- lfs.touch(newname,oldtime,oldtime)
- end
+ local oldtime=lfs.attributes(oldname,"modification")
+ if oldtime and lfs.isfile(newname) then
+ lfs.touch(newname,oldtime,oldtime)
+ end
end
function file.checksum(name)
- if md5 then
- local data=io.loaddata(name)
- if data then
- return md5.HEX(data)
- end
+ if md5 then
+ local data=io.loaddata(name)
+ if data then
+ return md5.HEX(data)
end
- return nil
+ end
+ return nil
end
function file.loadchecksum(name)
- if md5 then
- local data=io.loaddata(name..".md5")
- return data and (gsub(data,"%s",""))
- end
- return nil
+ if md5 then
+ local data=io.loaddata(name..".md5")
+ return data and (gsub(data,"%s",""))
+ end
+ return nil
end
function file.savechecksum(name,checksum)
- if not checksum then checksum=file.checksum(name) end
- if checksum then
- io.savedata(name..".md5",checksum)
- return checksum
- end
- return nil
+ if not checksum then checksum=file.checksum(name) end
+ if checksum then
+ io.savedata(name..".md5",checksum)
+ return checksum
+ end
+ return nil
end
end -- closure
@@ -4053,11 +4052,11 @@
do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['l-dir']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
+ version=1.001,
+ comment="companion 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
@@ -4069,7 +4068,7 @@
local lfs=lfs
local attributes=lfs.attributes
local walkdir=lfs.dir
-local isdir=lfs.isdir
+local isdir=lfs.isdir
local isfile=lfs.isfile
local currentdir=lfs.currentdir
local chdir=lfs.chdir
@@ -4076,471 +4075,471 @@
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
+ 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
- isfile=function(name)
- return attributes(name,"mode")=="file"
- end
- lfs.isdir=isdir
- lfs.isfile=isfile
+ 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
+ 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(),"\\","/"))
+ 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 in walkdir(usedpath) do
- if name~="." and name~=".." then
- local full=path..name
- local mode=attributes(full,'mode')
- if mode=='file' then
- if not patt or find(full,patt) then
- action(full)
- end
- elseif recurse and mode=="directory" then
- if 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
+ if isdir(path) then
local usedpath
if path=="/" then
- usedpath="/."
+ usedpath="/."
elseif not find(path,"/$") then
- usedpath=path.."/."
- path=path.."/"
+ usedpath=path.."/."
+ path=path.."/"
else
- usedpath=path
+ usedpath=path
end
local dirs
local nofdirs=0
- local noffiles=#result
- for name,a in walkdir(usedpath) do
- if name~="." and name~=".." then
- local full=path..name
- local mode=attributes(full,'mode')
- if mode=='file' then
- if not patt or find(full,patt) then
- 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
+ for name in walkdir(usedpath) do
+ if name~="." and name~=".." then
+ local full=path..name
+ local mode=attributes(full,'mode')
+ if mode=='file' then
+ if not patt or find(full,patt) then
+ action(full)
+ end
+ elseif recurse and mode=="directory" then
+ if 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
+ for i=1,nofdirs do
+ glob_pattern_function(dirs[i],patt,recurse,action)
+ end
end
- return result
+ end
end
-local function globpattern(path,patt,recurse,method)
- local kind=type(method)
- if patt and sub(patt,1,-3)==path then
- patt=false
+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,a in walkdir(usedpath) do
+ if name~="." and name~=".." then
+ local full=path..name
+ local mode=attributes(full,'mode')
+ if mode=='file' then
+ if not patt or find(full,patt) then
+ 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
- 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
+ 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)
+ 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
- if ok and type(scanner)=="function" then
- if not find(path,"/$") then
- path=path..'/'
+ 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
- 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
end
- return result
+ end
+ return result
end
dir.collectpattern=collectpattern
local separator,pattern
if onwindows then
- local slash=S("/\\")/"/"
- pattern={
- [1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3),
- [2]=Cs(((1-S("*?/\\"))^0*slash)^0),
- [3]=Cs(P(1)^0)
- }
+ local slash=S("/\\")/"/"
+ pattern={
+ [1]=(Cs(P(".")+slash^1)+Cs(R("az","AZ")*P(":")*slash^0)+Cc("./"))*V(2)*V(3),
+ [2]=Cs(((1-S("*?/\\"))^0*slash)^0),
+ [3]=Cs(P(1)^0)
+ }
else
- pattern={
- [1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3),
- [2]=C(((1-S("*?/"))^0*P("/"))^0),
- [3]=C(P(1)^0)
- }
+ pattern={
+ [1]=(C(P(".")+P("/")^1)+Cc("./"))*V(2)*V(3),
+ [2]=C(((1-S("*?/"))^0*P("/"))^0),
+ [3]=C(P(1)^0)
+ }
end
local filter=Cs ((
- P("**")/".*"+P("*")/"[^/]*"+P("?")/"[^/]"+P(".")/"%%."+P("+")/"%%+"+P("-")/"%%-"+P(1)
+ 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
+ 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
- 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
+ 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 in walkdir(path) do
- if find(name,"^%.") then
- else
- local mode=attributes(name,'mode')
- if mode=="directory" then
- if recurse then
- globfiles(path.."/"..name,recurse,func,files)
- end
- elseif mode=="file" then
- if not func or func(name) then
- noffiles=noffiles+1
- files[noffiles]=path.."/"..name
- end
- end
+ if type(func)=="string" then
+ local s=func
+ func=function(name) return find(name,s) end
+ end
+ files=files or {}
+ local noffiles=#files
+ for name in walkdir(path) do
+ if find(name,"^%.") then
+ else
+ local mode=attributes(name,'mode')
+ if mode=="directory" then
+ if recurse then
+ globfiles(path.."/"..name,recurse,func,files)
end
+ elseif mode=="file" then
+ if not func or func(name) then
+ noffiles=noffiles+1
+ files[noffiles]=path.."/"..name
+ end
+ end
end
- return files
+ 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 in walkdir(path) do
- if find(name,"^%.") then
- else
- local mode=attributes(name,'mode')
- 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
+ if type(func)=="string" then
+ local s=func
+ func=function(name) return find(name,s) end
+ end
+ files=files or {}
+ local noffiles=#files
+ for name in walkdir(path) do
+ if find(name,"^%.") then
+ else
+ local mode=attributes(name,'mode')
+ if mode=="directory" then
+ if 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
- return files
+ end
+ return files
end
dir.globdirs=globdirs
function dir.ls(pattern)
- return concat(glob(pattern),"\n")
+ 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
+ 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=""
- for i=1,n do
- local s=select(i,...)
- if s=="" then
- elseif str=="" then
- str=s
- else
- str=str.."/"..s
- end
- end
+ str=str.."/"..s
end
- local pth=""
- local drive=false
- local first,middle,last=match(str,"^(//)(//*)(.*)$")
+ 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
- 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
+ middle,last=match(str,"^(/*)(.-)$")
+ if not middle then
+ last=str
+ 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
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
+ 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
- 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
+ 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="."
- for s in gmatch(str,"[^/]+") do
- pth=pth.."/"..s
- if make_indeed and not isdir(pth) then
- mkdir(pth)
- end
- end
+ pth=pth.."/"..s
end
- return pth,(isdir(pth)==true)
+ 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
+ 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
- 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
+ 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~="" then
- chdir(newdir)
- return newdir
- else
- return curdir
- end
+ local curdir=currentdir()
+ insert(stack,curdir)
+ if newdir and newdir~="" then
+ chdir(newdir)
+ return newdir
+ else
+ return curdir
+ end
end
function dir.pop()
- local d=remove(stack)
- if d then
- chdir(d)
- end
- return d
+ 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
+ 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
@@ -4549,18 +4548,18 @@
do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['l-unicode']={
- version=1.001,
- comment="companion to luat-lib.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
+ version=1.001,
+ comment="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 {}
if not string.utfcharacters then
- local gmatch=string.gmatch
- function string.characters(str)
- return gmatch(str,".[\128-\191]*")
- end
+ local gmatch=string.gmatch
+ function string.characters(str)
+ return gmatch(str,".[\128-\191]*")
+ end
end
utf.characters=string.utfcharacters
local type=type
@@ -4583,304 +4582,304 @@
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
+ 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
- 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
+ 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
+ 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"
+ 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.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)
+ 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 )
+ 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
+ return lpegmatch(pattern,s) or s
end
local validatedutf=Cs (
- (
- patterns.utf8one+patterns.utf8two+patterns.utf8three+patterns.utf8four+P(1)/"�"
- )^0
+ (
+ 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
+ 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
+ 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
+ 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
- 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_one(s,p)
+ n=n+1
+ if n==first then
+ b=p
end
- local function slide_two(s,p)
- n=n+1
- if n==first then
- b=p
+ 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
- return true
+ start=start+1
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)
+ end
+ if stop<0 then
+ stop=l+stop
+ if stop==0 then
+ stop=1
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)
+ 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)
+ 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
- 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
+ if not pattern then
+ pattern=Cs((tabletopattern(mapping)/action+p_utf8character)^0)
+ end
+ return lpegmatch(pattern,str)
end
- elseif variant=="function" then
- if option=="pattern" then
- return Cs((p_utf8character/mapping+p_utf8character)^0)
+ 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
- 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
+ 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
- return function(str)
- return str or ""
+ 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
-end
-function utf.replacer(t)
- local r=replacer(t,false,false,true)
+ else
return function(str)
- return lpegmatch(r,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
+ 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)
@@ -4888,25 +4887,25 @@
local utfcharsplitter_raw=Ct(C(p_utf8character)^0)
patterns.utflinesplitter=utflinesplitter
function utf.splitlines(str)
- return lpegmatch(utflinesplitter,str or "")
+ 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
+ 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)
+ 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)
+ 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
@@ -4920,36 +4919,36 @@
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
+ 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
+ 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))
+ 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))
+ 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)
@@ -4960,88 +4959,88 @@
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
+ 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)
+ 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
- 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
+ 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
+ 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)
+ 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
- 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
+ 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
+ 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)
+ 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
- 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
+ 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
+ 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)
+ 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
- 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
+ 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
@@ -5052,225 +5051,225 @@
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
+ 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
+ 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
+ return endian and utf32_to_utf8_be_t(t) or utf32_to_utf8_le_t(t) or t
end
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
+ 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
+ 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
+ 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
+ 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
+ if littleendian then
+ return utf8_to_utf16_le(str,nobom)
+ else
+ return utf8_to_utf16_be(str,nobom)
+ 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
+ (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 " ")
+ return lpegmatch(pattern,str,1,separator or " ")
end
function utf.ustring(s)
- return format("U+%05X",type(s)=="number" and s or utfbyte(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))
+ 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
+ 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
+ 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()
+ 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
- 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
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
+ 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
+ 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
+ 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
- return s
+ 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
+ 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
- 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
+ first,last=lpegmatch(range,str)
+ if not last then
+ return P(str)
+ 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
+ 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 -- closure
@@ -5278,11 +5277,11 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="companion 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
@@ -5295,14 +5294,14 @@
local unescapes={}
local escapes={}
setmetatable(unescapes,{ __index=function(t,k)
- local v=char(tonumber(k,16))
- t[k]=v
- return v
+ 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
+ local v=format("%%%02X",byte(k))
+ t[k]=v
+ return v
end })
local colon=P(":")
local qmark=P("?")
@@ -5321,21 +5320,21 @@
local noslash=P("/")/""
local plustospace=P("+")/" "
local decoder=Cs((
- plustospace+escapedchar+P("\r\n")/"\n"+P(1)
- )^0 )
+ 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 )
+ 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.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 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
@@ -5353,19 +5352,19 @@
lpegpatterns.urlunescaper=unescaper
lpegpatterns.urlgetcleaner=getcleaner
function url.unescapeget(str)
- return lpegmatch(getcleaner,str)
+ return lpegmatch(getcleaner,str)
end
local function split(str)
- return (type(str)=="string" and lpegmatch(parser,str)) or 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
+ 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("://")
@@ -5375,161 +5374,161 @@
local backslashswapper=replacer("\\","/")
local equal=P("=")
local amp=P("&")
-local key=Cs(((plustospace+escapedchar+1)-equal )^0)
+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),
+ 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
+ if not str or str=="" then
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,
+ 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
+ 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]="://"
+ 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
- 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
+ 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
+ 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)
+ 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
+ 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
+ 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
+ if not path or path=="" then
+ return ""
+ else
+ return lpegmatch(pattern,path)
+ end
end
end -- closure
@@ -5537,11 +5536,11 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="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={}
@@ -5550,54 +5549,54 @@
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
+ 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
+ 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," ")
+ 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
+ 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 -- closure
Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-basic.lua 2019-02-08 23:01:17 UTC (rev 49982)
@@ -29,8 +29,8 @@
local lualibs_basic_module = {
name = "lualibs-basic",
- version = 2.62,
- date = "2018-12-19",
+ version = 2.63,
+ date = "2019-01-28",
description = "ConTeXt Lua libraries -- basic collection.",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
copyright = "PRAGMA ADE / ConTeXt Development Team",
Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended-merged.lua 2019-02-08 23:01:17 UTC (rev 49982)
@@ -1,15 +1,15 @@
-- merged file : lualibs-extended-merged.lua
-- parent file : lualibs-extended.lua
--- merge date : Tue Dec 25 16:21:26 2018
+-- merge date : Wed Jan 30 23:25:40 2019
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="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 {}
@@ -22,20 +22,12 @@
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 utfchar,utfbyte,utflen=utf.char,utf.byte,utf.len
-local loadstripped=nil
-local oldfashioned=LUAVERSION<5.2
-if oldfashioned then
- loadstripped=function(str,shortcuts)
- return load(str)
- end
-else
- 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
+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
@@ -53,32 +45,32 @@
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)
- end
- return lpegmatch(stripzeros,format("%.5fpt",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)
+ end
+ return lpegmatch(stripzeros,format("%.5fpt",n))
end
local function basepoints(n)
- if n==0 then
- return "0pt"
- end
- n=tonumber(n)
- if not n or n==0 then
- return "0pt"
- end
- n=n*bpf
- if n%1==0 then
- return format("%ibp",n)
- end
- return lpegmatch(stripzeros,format("%.5fbp",n))
+ if n==0 then
+ return "0pt"
+ end
+ n=tonumber(n)
+ if not n or n==0 then
+ return "0pt"
+ end
+ n=n*bpf
+ if n%1==0 then
+ return format("%ibp",n)
+ end
+ return lpegmatch(stripzeros,format("%.5fbp",n))
end
number.points=points
number.basepoints=basepoints
@@ -90,65 +82,65 @@
local redundant=rubish^3/"\n"
local pattern=Cs(leading*(trailing+redundant+stripped+anything)^0)
function strings.collapsecrlf(str)
- return lpegmatch(pattern,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
+ 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 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
+ 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((
+ 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
+ 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
+ extra,start=0,position
end+anything
- )^1)
+ )^1)
function strings.tabtospace(str,tab)
- return lpegmatch(pattern,str,1,tab or 7)
+ 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
+ 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/""
@@ -166,130 +158,130 @@
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_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,
+ ["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
+ return str and lpegmatch(striplinepatterns[how],str) or str
end
function strings.collapse(str)
- return str and lpegmatch(p_prune_intospace,str) or 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
+ 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)..'"')
+ 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).."'")
+ 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]",
+ "[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
+ 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
+ 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)
+ (((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
+ 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 ".")
+ 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
- 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
+ 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
- )
+ 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
+ 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("+")/""
@@ -300,41 +292,41 @@
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"
+ 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
- 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)
+ 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
+ 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
+ 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
+ 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
@@ -341,367 +333,341 @@
%s
return function(%s) return %s end
]]
-local preamble,environment="",{}
-if oldfashioned then
- preamble=[[
-local lpeg=lpeg
-local type=type
-local tostring=tostring
-local tonumber=tonumber
-local format=string.format
-local concat=table.concat
-local signed=number.signed
-local points=number.points
-local basepoints= number.basepoints
-local utfchar=utf.char
-local utfbyte=utf.byte
-local lpegmatch=lpeg.match
-local nspaces=string.nspaces
-local utfpadding=string.utfpadding
-local tracedchar=string.tracedchar
-local autosingle=string.autosingle
-local autodouble=string.autodouble
-local sequenced=table.sequenced
-local formattednumber=number.formatted
-local sparseexponent=number.sparseexponent
-local formattedfloat=number.formattedfloat
-local stripzero=lpeg.patterns.stripzero
-local stripzeros=lpeg.patterns.stripzeros
- ]]
-else
- 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,
- basepoints=number.basepoints,
- 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=lpeg.patterns.stripzero,
- stripzeros=lpeg.patterns.stripzeros,
- }
-end
+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,
+ basepoints=number.basepoints,
+ 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=lpeg.patterns.stripzero,
+ stripzeros=lpeg.patterns.stripzeros,
+}
local arguments={ "a1" }
setmetatable(arguments,{ __index=function(t,k)
- local v=t[k-1]..",a"..k
- t[k]=v
- return v
- end
+ 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
+ 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
+ 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
+ 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
+ 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=function()
- n=n+1
- return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n)
+ n=n+1
+ return format("(a%s ~= nil and format('%%q',tostring(a%s)) or '')",n,n)
end
local format_Q=function()
- n=n+1
- return format("format('%%q',tostring(a%s))",n)
+ n=n+1
+ return format("format('%%q',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
+ 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)
+ 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)
+ 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
+ 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,%i,%i)",n,b or 0,a or 0)
+ n=n+1
+ return format("formattedfloat(a%s,%i,%i)",n,b or 0,a or 0)
end
local format_g=function(f)
- n=n+1
- return format("format('%%%sg',a%s)",f,n)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ 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)
+ n=n+1
+ return format("utfchar(a%s)",n)
end
local format_C=function()
- n=n+1
- return format("tracedchar(a%s)",n)
+ 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)
+ 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
+ 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
+ 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
+ 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
+ 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)
+ n=n+1
+ return format("points(a%s)",n)
end
local format_b=function()
- n=n+1
- return format("basepoints(a%s)",n)
+ n=n+1
+ return format("basepoints(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
+ 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
+ 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)
+ 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)
+ 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)
+ 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=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)
+ 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
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
+ 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
+ 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
+ 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)
+ 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
+ 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
+ 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 "''"
+ n=n+(tonumber(f) or 1)
+ return "''"
end
local format_rest=function(s)
- return format("%q",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,"%.%.%.")
+ local extension=extensions[name] or "tostring(%s)"
+ local f=tonumber(f) or 1
+ local w=find(extension,"%.%.%.")
+ if w then
if f==0 then
- if w then
- extension=gsub(extension,"%.%.%.","")
- end
- return extension
+ extension=gsub(extension,"%.%.%.","")
+ 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)
+ extension=gsub(extension,"%.%.%.","%%s")
+ n=n+1
+ local a="a"..n
+ return format(extension,a,a)
elseif f<0 then
- local a="a"..(n+f+1)
- return format(extension,a,a)
+ local a="a"..(n+f+1)
+ return format(extension,a,a)
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))
+ extension=gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+ local t={}
+ for i=1,f do
+ n=n+1
+ t[i]="a"..n
+ end
+ return format(extension,unpack(t))
end
+ else
+ extension=gsub(extension,"%%s",function()
+ n=n+1
+ return "a"..n
+ end)
+ return extension
+ end
end
local builder=Cs { "start",
- start=(
- (
- P("%")/""*(
- V("!")
+ 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")
@@ -717,119 +683,117 @@
+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,
- ["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,
+ )+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,
+ ["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,
+ ["%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)()
+ 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
- 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
+ f=function() return str end
end
- t[str]=f
- return f
+ end
+ t[str]=f
+ return f
end
local function use(t,fmt,...)
- return t[fmt](...)
+ return t[fmt](...)
end
strings.formatters={}
-if oldfashioned then
- function strings.formatters.new(noconcat)
- local t={ _type_="formatter",_connector_=noconcat and "," or "..",_extensions_={},_preamble_=preamble,_environment_={} }
- setmetatable(t,{ __index=make,__call=use })
- return t
- end
-else
- 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
+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
+ if type(t)=="table" and t._type_=="formatter" then
+ t._extensions_[name]=template or "%s"
+ if type(preamble)=="string" then
+ t._preamble_=preamble.."\n"..t._preamble_
+ elseif type(preamble)=="table" then
+ for k,v in next,preamble do
+ t._environment_[k]=v
+ end
end
+ end
end
strings.formatters.add=add
patterns.xmlescape=Cs((P("<")/"<"+P(">")/">"+P("&")/"&"+P('"')/"""+anything)^0)
@@ -836,45 +800,39 @@
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('"'))
-if oldfashioned then
- add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape")
- add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape")
- add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape")
-else
- add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=lpeg.patterns.xmlescape })
- add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape })
- add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape })
-end
+add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape=lpeg.patterns.xmlescape })
+add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape=lpeg.patterns.texescape })
+add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape=lpeg.patterns.luaescape })
local dquote=patterns.dquote
local equote=patterns.escaped+dquote/'\\"'+1
local cquote=Cc('"')
-local pattern=Cs(dquote*(equote-P(-2))^0*dquote)
+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
+ 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)
+ 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
+ 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)
+ return f_16_16(n/65536.0)
end
end -- closure
@@ -882,11 +840,11 @@
do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['util-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"
+ version=1.001,
+ comment="companion 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=string.byte
local char=string.char
@@ -895,280 +853,280 @@
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
+ 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()
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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))
+ return byte(f:read(1))
end
function files.readbytes(f,n)
- return byte(f:read(n),1,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) }
+ local s=f:read(n or 1)
+ return { byte(s,1,#s) }
end
function files.readchar(f)
- return f:read(1)
+ return f:read(1)
end
function files.readstring(f,n)
- return f:read(n or 1)
+ 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
+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.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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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
+ 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 a,b=byte(f:read(2),1,2)
- if a>=0x80 then
- return (a-0x100)+b/0x100
- else
- return (a )+b/0x100
- end
+ local a,b=byte(f:read(2),1,2)
+ if a>=0x80 then
+ return (a-0x100)+b/0x100
+ else
+ return (a )+b/0x100
+ end
end
function files.readfixed4(f)
- local a,b,c,d=byte(f:read(4),1,4)
+ local a,b,c,d=byte(f:read(4),1,4)
+ if a>=0x80 then
+ return (0x100*a+b-0x10000)+(0x100*c+d)/0x10000
+ else
+ return (0x100*a+b )+(0x100*c+d)/0x10000
+ end
+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
- return (0x100*a+b-0x10000)+(0x100*c+d)/0x10000
+ local n=-(0x100*a+b)
+ return-(extract(n,14,2)+(band(n,0x3FFF)/16384.0))
else
- return (0x100*a+b )+(0x100*c+d)/0x10000
+ local n=0x100*a+b
+ return (extract(n,14,2)+(band(n,0x3FFF)/16384.0))
end
+ end
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))
+ f:read(2*(n or 1))
end
function files.skiplong(f,n)
- f:read(4*(n or 1))
+ 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
-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
-end
-function files.writecardinal4(f,n)
+ local rshift=bit32.rshift
+ function files.writecardinal2(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)
+ f:write(b,a)
+ 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
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.writestring(f,s)
- f:write(char(byte(s,1,#s)))
+ f:write(char(byte(s,1,#s)))
end
function files.writebyte(f,b)
- f:write(char(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.readinteger1=fio.readinteger1
- files.readinteger2=fio.readinteger2
- files.readinteger3=fio.readinteger3
- files.readinteger4=fio.readinteger4
- 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
+ files.readcardinal1=fio.readcardinal1
+ files.readcardinal2=fio.readcardinal2
+ files.readcardinal3=fio.readcardinal3
+ files.readcardinal4=fio.readcardinal4
+ files.readinteger1=fio.readinteger1
+ files.readinteger2=fio.readinteger2
+ files.readinteger3=fio.readinteger3
+ files.readinteger4=fio.readinteger4
+ 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.readcardinaltable then
- files.readcardinaltable=fio.readcardinaltable
- files.readintegertable=fio.readintegertable
+ 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
+ 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 -- closure
@@ -1176,11 +1134,11 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="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 {}
@@ -1195,219 +1153,219 @@
local utftoeight=utf.toeight
local splitter=lpeg.tsplitat(".")
function utilities.tables.definetable(target,nofirst,nolast)
- local composed,t=nil,{}
- 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
+ local composed,t=nil,{}
+ local snippets=lpegmatch(splitter,target)
+ for i=1,#snippets-(nolast and 1 or 0) do
+ local name=snippets[i]
if composed then
- if nolast then
- composed=composed.."."..snippets[#snippets]
- end
- return concat(t,"\n"),composed
+ composed=composed.."."..name
+ t[#t+1]=formatters["if not %s then %s = { } end"](composed,composed)
else
- return "",target
+ 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
+ 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
- return t
+ 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
+ local t=root or _G
+ for name in gmatch(target,"([^%.]+)") do
+ t=t[name]
+ if not t then
+ return
end
- return t
+ 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
+ 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
- t[names[#names]]=v
+ 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
+ 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
+ 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
+ for i=1,#t do
+ if t[i]==extra then
+ remove(t,i)
end
- for i=1,#t do
- if t[i]==value then
- insert(t,i,extra)
- return
- end
+ end
+ for i=1,#t do
+ if t[i]==value then
+ insert(t,i,extra)
+ return
end
- insert(t,1,extra)
+ 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
+ for i=1,#t do
+ if t[i]==extra then
+ remove(t,i)
end
- for i=1,#t do
- if t[i]==value then
- insert(t,i+1,extra)
- return
- end
+ end
+ for i=1,#t do
+ if t[i]==value then
+ insert(t,i+1,extra)
+ return
end
- insert(t,#t+1,extra)
+ 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])
+ 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
- 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
+ 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
+ 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")
+ 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={}
+ 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"]("inheritance",key,core))
- os.exit()
+ print(formatters["\ninvalid %s %a' in %a"]("overload",key,core))
+ os.exit()
else
- capsule[key]=value
+ rawset(t,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
+ } )
+ end
end
local f_hashed_string=formatters["[%q]=%q,"]
local f_hashed_number=formatters["[%q]=%s,"]
@@ -1421,157 +1379,157 @@
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
- for i=0,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
+ 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
+ for i=0,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
- 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
+ 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
- m=m+1
- if outer then
- r[m]="}"
- else
- r[m]="},"
+ 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
- return r
+ end
end
- return concat(fastserialize(t,true))
+ m=m+1
+ if outer then
+ r[m]="}"
+ else
+ r[m]="},"
+ end
+ return r
+ end
+ return concat(fastserialize(t,true))
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
+ 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
+ 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,...))
+ 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)
+ 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
- return f_return_table(r)
+ 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"
+ 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]="}"
- return concat(r)
+ 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
+ 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
+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
- setmetatable(t,selfmapper)
- return t
+ end
+ setmetatable(t,selfmapper)
+ return t
end
local f_start_key_idx=formatters["%w{"]
local f_start_key_num=formatters["%w[%s]={"]
@@ -1609,188 +1567,224 @@
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)
+ 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
- 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)
+ if root and next(root)~=nil then
+ local first=nil
+ local last=0
+ 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
+ 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 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
+ 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
- depth=depth+1
- end
- if root and next(root)~=nil then
- local first=nil
- local last=0
- last=#root
- for k=1,last do
- if rawget(root,k)==nil then
- last=k-1
- break
- 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
- if last>0 then
- first=1
+ 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
- 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
+ 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
- if level>0 then
- n=n+1 t[n]=f_stop(depth-1)
- end
+ 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
+ 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("t") }
+ t={ f_table_name(name) }
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
+ 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
- n=n+1
- t[n]=f_table_finish()
- return concat(t,"\n")
+ 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)
+ 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
end -- closure
@@ -1797,11 +1791,11 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="companion 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 {}
@@ -1808,154 +1802,154 @@
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
+ 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
+ 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__
+ 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
+ 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)
+ 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
+ t[k]=k
+ return k
end }
function storage.sparse(t)
- t=t or {}
- setmetatable(t,keyisvalue)
- return 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 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,
+ ["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
+ 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,
+ ["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
+ 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
+ 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
+ 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
+ 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]
+ 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
+ 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 -- closure
@@ -1963,11 +1957,11 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="companion 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
@@ -2009,8 +2003,8 @@
local nobracket=1-(lbracket+rbracket)
local escape,left,right=P("\\"),P('{'),P('}')
lpegpatterns.balanced=P {
- [1]=((escape*(left+right))+(1-(left+right))+V(2))^0,
- [2]=left*V(1)*right
+ [1]=((escape*(left+right))+(1-(left+right))+V(2))^0,
+ [2]=left*V(1)*right
}
local nestedbraces=P { lbrace*(nobrace+V(1))^0*rbrace }
local nestedparents=P { lparent*(noparent+V(1))^0*rparent }
@@ -2018,9 +2012,9 @@
local spaces=space^0
local argument=Cs((lbrace/"")*((nobrace+nestedbraces)^0)*(rbrace/""))
local content=(1-endofstring)^0
-lpegpatterns.nestedbraces=nestedbraces
+lpegpatterns.nestedbraces=nestedbraces
lpegpatterns.nestedparents=nestedparents
-lpegpatterns.nested=nestedbraces
+lpegpatterns.nested=nestedbraces
lpegpatterns.argument=argument
lpegpatterns.content=content
local value=lbrace*C((nobrace+nestedbraces)^0)*rbrace+C((nestedbraces+(1-comma))^0)
@@ -2032,7 +2026,7 @@
local pattern_b=spaces*comma^0*spaces*(key*((spaces*equal*spaces*value)+C("")))
local hash={}
local function set(key,value)
- hash[key]=value
+ hash[key]=value
end
local pattern_a_s=(pattern_a/set)^1
local pattern_b_s=(pattern_b/set)^1
@@ -2043,78 +2037,78 @@
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
+ 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
+ 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
- hash=existing or {}
- lpegmatch(pattern_a_s,str)
- return hash
+ 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
+ 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
+ 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
- hash=existing or {}
- lpegmatch(pattern_b_s,str)
- return hash
+ 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
+ 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)
@@ -2121,222 +2115,222 @@
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)
+ 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 }
+ 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
+ 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)
+ return lpegmatch(pattern,str)
end
local cache_a={}
local cache_b={}
function parsers.groupedsplitat(symbol,withaction)
- if not symbol then
- symbol=","
+ 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
- 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
+ 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
+ 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
+ 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
+ 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)
+ return lpegmatch(pattern,str,nil,t)
end
function parsers.hash_to_string(h,separator,yes,no,strict,omit)
- if h then
- local t,tn,s={},0,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
+ if h then
+ local t,tn,s={},0,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
- return concat(t,separator or ",")
- else
- return ""
+ 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
+ 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 utilities.parsers.settings_to_set(str)
- return str and lpegmatch(pattern,str) or {}
+ 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
+ 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,tn={},0
- for k,v in sortedhash(h) do
- if v then
- tn=tn+1
- t[tn]=k
- end
+ local t,tn={},0
+ for k,v in sortedhash(h) do
+ if v then
+ tn=tn+1
+ t[tn]=k
end
- return concat(t,separator or ",")
+ 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 utilities.parsers.options_to_hash(str,target)
- return str and lpegmatch(splitter,str,1,target or {}) or {}
+ return str and lpegmatch(splitter,str,1,target or {}) or {}
end
local splitter=lpeg.tsplitat(" ")
function utilities.parsers.options_to_array(str)
- return str and lpegmatch(splitter,str) or {}
+ 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
+ if not n then
+ return str
+ else
+ local s=lpegmatch(pattern_a,str)
+ if n==1 then
+ return unpack(s)
else
- local s=lpegmatch(pattern_a,str)
- if n==1 then
- return unpack(s)
- else
- local t,tn={},0
- for i=1,n do
- for j=1,#s do
- tn=tn+1
- t[tn]=s[j]
- end
- end
- return unpack(t)
+ local t,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
+ 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)
+ 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
+ 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
- parsers.settings_to_hash(settings,sc)
+ end
+ parsers.settings_to_hash(settings,sc)
end
function parsers.listitem(str)
- return gmatch(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"),
+ 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
+ return lpegmatch(pattern,str) or str
end
local optionalwhitespace=whitespace^0
lpegpatterns.words=Ct((Cs((1-punctuation-whitespace)^1)+anything)^1)
@@ -2350,75 +2344,75 @@
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
+ 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 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 quoteword=quotechar*C((1-quotechar)^0)*quotechar
- if quotedata then
- quotedata=quotedata+quoteword
- else
- quotedata=quoteword
- end
- end
- whatever=quotedata+whatever
+ specification=specification and setmetatableindex(specification,defaultspecification) or defaultspecification
+ local separator=specification.separator
+ local quotechar=specification.quote
+ 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 quoteword=quotechar*C((1-quotechar)^0)*quotechar
+ if quotedata then
+ quotedata=quotedata+quoteword
+ else
+ quotedata=quoteword
+ end
end
- local parser=Ct((Ct(whatever*(separator*whatever)^0)*S("\n\r")^1)^0 )
- return function(data)
- return lpegmatch(parser,data)
- 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 separator=specification.separator
- local quotechar=P(specification.quote)
- local dquotechar=quotechar*quotechar
+ specification=specification and setmetatableindex(specification,defaultspecification) or defaultspecification
+ local separator=specification.separator
+ local quotechar=P(specification.quote)
+ local dquotechar=quotechar*quotechar
/specification.quote
- local separator=S(separator~="" and separator or ",")
- local escaped=quotechar*Cs((dquotechar+(1-quotechar))^0)*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
+ local separator=S(separator~="" and separator or ",")
+ local escaped=quotechar*Cs((dquotechar+(1-quotechar))^0)*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)
+ 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.cardinal/tonumber
local spacers=lpegpatterns.spacer^0
@@ -2426,89 +2420,89 @@
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)
- if type(n)=="function" then
- lpegmatch(stepper,str,1,false,n or print)
- else
- lpegmatch(stepper,str,1,n,action or print)
- end
+ if type(n)=="function" then
+ lpegmatch(stepper,str,1,false,n or print)
+ else
+ 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)
+ 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)
+ return lpegmatch(pattern,str)
end
local cache={}
local spaces=lpegpatterns.space^0
local dummy=function() end
setmetatableindex(cache,function(t,k)
- local separator=P(k)
- local value=(1-separator)^0
- local pattern=spaces*C(value)*separator^0*Cp()
- t[k]=pattern
- return pattern
+ local separator=P(k)
+ local value=(1-separator)^0
+ local pattern=spaces*C(value)*separator^0*Cp()
+ t[k]=pattern
+ return pattern
end)
local commalistiterator=cache[","]
function utilities.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
+ 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 {}
+ 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 {}
+ return t[name] or {}
end
local function process(result,more)
- for k,v in next,more do
- result[k]=v
- end
- return result
+ 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 utilities.parsers.mergehashes(hash,list)
- return lpegmatch(merge,list,1,hash)
+ return lpegmatch(merge,list,1,hash)
end
function utilities.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
+ 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("->")
@@ -2516,11 +2510,11 @@
local token=lbrace*C((1-rbrace)^1)*rbrace+C(anything^1)
local pattern=spacing*(method*spacing*apply+Carg(1))*spacing*token
function utilities.parsers.splitmethod(str,default)
- if str then
- return lpegmatch(pattern,str,1,default or false)
- else
- return default or false,""
- end
+ if str then
+ return lpegmatch(pattern,str,1,default or false)
+ else
+ return default or false,""
+ end
end
end -- closure
@@ -2528,11 +2522,11 @@
do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['util-dim']={
- version=1.001,
- comment="support for dimensions",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
+ version=1.001,
+ comment="support for dimensions",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
local format,match,gsub,type,setmetatable=string.format,string.match,string.gsub,type,setmetatable
local P,S,R,Cc,C,lpegmatch=lpeg.P,lpeg.S,lpeg.R,lpeg.Cc,lpeg.C,lpeg.match
@@ -2546,34 +2540,34 @@
number.tonumberf=function(n) return lpegmatch(p_stripzeros,format("%.20f",n)) end
number.tonumberg=function(n) return format("%.20g",n) end
local dimenfactors=allocate {
- ["pt"]=1/65536,
- ["in"]=(100/7227)/65536,
- ["cm"]=(254/7227)/65536,
- ["mm"]=(2540/7227)/65536,
- ["sp"]=1,
- ["bp"]=(7200/7227)/65536,
- ["pc"]=(1/12)/65536,
- ["dd"]=(1157/1238)/65536,
- ["cc"]=(1157/14856)/65536,
- ["nd"]=(20320/21681)/65536,
- ["nc"]=(5080/65043)/65536
+ ["pt"]=1/65536,
+ ["in"]=(100/7227)/65536,
+ ["cm"]=(254/7227)/65536,
+ ["mm"]=(2540/7227)/65536,
+ ["sp"]=1,
+ ["bp"]=(7200/7227)/65536,
+ ["pc"]=(1/12)/65536,
+ ["dd"]=(1157/1238)/65536,
+ ["cc"]=(1157/14856)/65536,
+ ["nd"]=(20320/21681)/65536,
+ ["nc"]=(5080/65043)/65536
}
local f_none=formatters["%s%s"]
local f_true=formatters["%0.5F%s"]
local function numbertodimen(n,unit,fmt)
- if type(n)=='string' then
- return n
+ if type(n)=='string' then
+ return n
+ else
+ unit=unit or 'pt'
+ n=n*dimenfactors[unit]
+ if not fmt then
+ fmt=f_none(n,unit)
+ elseif fmt==true then
+ fmt=f_true(n,unit)
else
- unit=unit or 'pt'
- n=n*dimenfactors[unit]
- if not fmt then
- fmt=f_none(n,unit)
- elseif fmt==true then
- fmt=f_true(n,unit)
- else
- return formatters[fmt](n,unit)
- end
+ return formatters[fmt](n,unit)
end
+ end
end
number.maxdimen=1073741823
number.todimen=numbertodimen
@@ -2583,13 +2577,13 @@
function number.tocentimeters (n,fmt) return numbertodimen(n,"cm",fmt) end
function number.tomillimeters (n,fmt) return numbertodimen(n,"mm",fmt) end
function number.toscaledpoints(n,fmt) return numbertodimen(n,"sp",fmt) end
-function number.toscaledpoints(n) return n.."sp" end
-function number.tobasepoints (n,fmt) return numbertodimen(n,"bp",fmt) end
+function number.toscaledpoints(n) return n.."sp" end
+function number.tobasepoints (n,fmt) return numbertodimen(n,"bp",fmt) end
function number.topicas (n,fmt) return numbertodimen(n "pc",fmt) end
function number.todidots (n,fmt) return numbertodimen(n,"dd",fmt) end
-function number.tociceros (n,fmt) return numbertodimen(n,"cc",fmt) end
-function number.tonewdidots (n,fmt) return numbertodimen(n,"nd",fmt) end
-function number.tonewciceros (n,fmt) return numbertodimen(n,"nc",fmt) end
+function number.tociceros (n,fmt) return numbertodimen(n,"cc",fmt) end
+function number.tonewdidots (n,fmt) return numbertodimen(n,"nd",fmt) end
+function number.tonewciceros (n,fmt) return numbertodimen(n,"nc",fmt) end
local amount=(S("+-")^0*R("09")^0*P(".")^0*R("09")^0)+Cc("0")
local unit=R("az")^1+P("%")
local dimenpair=amount/tonumber*(unit^1/dimenfactors+Cc(1))
@@ -2596,10 +2590,10 @@
lpeg.patterns.dimenpair=dimenpair
local splitter=amount/tonumber*C(unit^1)
function number.splitdimen(str)
- return lpegmatch(splitter,str)
+ return lpegmatch(splitter,str)
end
setmetatableindex(dimenfactors,function(t,s)
- return false
+ return false
end)
local stringtodimen
local amount=S("+-")^0*R("09")^0*S(".,")^0*R("09")^0
@@ -2608,106 +2602,106 @@
lpeg.patterns.validdimen=validdimen
local dimensions={}
function dimensions.__add(a,b)
- local ta,tb=type(a),type(b)
- if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end
- if tb=="string" then b=stringtodimen(b) elseif tb=="table" then b=b[1] end
- return setmetatable({ a+b },dimensions)
+ local ta,tb=type(a),type(b)
+ if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end
+ if tb=="string" then b=stringtodimen(b) elseif tb=="table" then b=b[1] end
+ return setmetatable({ a+b },dimensions)
end
function dimensions.__sub(a,b)
- local ta,tb=type(a),type(b)
- if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end
- if tb=="string" then b=stringtodimen(b) elseif tb=="table" then b=b[1] end
- return setmetatable({ a-b },dimensions)
+ local ta,tb=type(a),type(b)
+ if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end
+ if tb=="string" then b=stringtodimen(b) elseif tb=="table" then b=b[1] end
+ return setmetatable({ a-b },dimensions)
end
function dimensions.__mul(a,b)
- local ta,tb=type(a),type(b)
- if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end
- if tb=="string" then b=stringtodimen(b) elseif tb=="table" then b=b[1] end
- return setmetatable({ a*b },dimensions)
+ local ta,tb=type(a),type(b)
+ if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end
+ if tb=="string" then b=stringtodimen(b) elseif tb=="table" then b=b[1] end
+ return setmetatable({ a*b },dimensions)
end
function dimensions.__div(a,b)
- local ta,tb=type(a),type(b)
- if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end
- if tb=="string" then b=stringtodimen(b) elseif tb=="table" then b=b[1] end
- return setmetatable({ a/b },dimensions)
+ local ta,tb=type(a),type(b)
+ if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end
+ if tb=="string" then b=stringtodimen(b) elseif tb=="table" then b=b[1] end
+ return setmetatable({ a/b },dimensions)
end
function dimensions.__unm(a)
- local ta=type(a)
- if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end
- return setmetatable({-a },dimensions)
+ local ta=type(a)
+ if ta=="string" then a=stringtodimen(a) elseif ta=="table" then a=a[1] end
+ return setmetatable({-a },dimensions)
end
function dimensions.__lt(a,b)
- return a[1]<b[1]
+ return a[1]<b[1]
end
function dimensions.__eq(a,b)
- return a[1]==b[1]
+ return a[1]==b[1]
end
function dimensions.__tostring(a)
- return a[1]/65536 .."pt"
+ return a[1]/65536 .."pt"
end
function dimensions.__index(tab,key)
- local d=dimenfactors[key]
- if not d then
- error("illegal property of dimen: "..key)
- d=1
- end
- return 1/d
+ local d=dimenfactors[key]
+ if not d then
+ error("illegal property of dimen: "..key)
+ d=1
+ end
+ return 1/d
end
- dimenfactors["ex"]=4*1/65536
- dimenfactors["em"]=10*1/65536
+ dimenfactors["ex"]=4*1/65536
+ dimenfactors["em"]=10*1/65536
local known={} setmetatable(known,{ __mode="v" })
function dimen(a)
- if a then
- local ta=type(a)
- if ta=="string" then
- local k=known[a]
- if k then
- a=k
- else
- local value,unit=lpegmatch(dimenpair,a)
- if value and unit then
- k=value/unit
- else
- k=0
- end
- known[a]=k
- a=k
- end
- elseif ta=="table" then
- a=a[1]
+ if a then
+ local ta=type(a)
+ if ta=="string" then
+ local k=known[a]
+ if k then
+ a=k
+ else
+ local value,unit=lpegmatch(dimenpair,a)
+ if value and unit then
+ k=value/unit
+ else
+ k=0
end
- return setmetatable({ a },dimensions)
- else
- return setmetatable({ 0 },dimensions)
+ known[a]=k
+ a=k
+ end
+ elseif ta=="table" then
+ a=a[1]
end
+ return setmetatable({ a },dimensions)
+ else
+ return setmetatable({ 0 },dimensions)
+ end
end
function string.todimen(str)
- if type(str)=="number" then
- return str
- else
- local k=known[str]
- if not k then
- local value,unit=lpegmatch(dimenpair,str)
- if value and unit then
- k=value/unit
- else
- k=0
- end
- known[str]=k
- end
- return k
+ if type(str)=="number" then
+ return str
+ else
+ local k=known[str]
+ if not k then
+ local value,unit=lpegmatch(dimenpair,str)
+ if value and unit then
+ k=value/unit
+ else
+ k=0
+ end
+ known[str]=k
end
+ return k
+ end
end
stringtodimen=string.todimen
function number.toscaled(d)
- return format("%0.5f",d/0x10000)
+ return format("%0.5f",d/0x10000)
end
function number.percent(n,d)
- d=d or texget("hsize")
- if type(d)=="string" then
- d=stringtodimen(d)
- end
- return (n/100)*d
+ d=d or texget("hsize")
+ if type(d)=="string" then
+ d=stringtodimen(d)
+ end
+ return (n/100)*d
end
number["%"]=number.percent
@@ -2716,15 +2710,15 @@
do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['util-jsn']={
- version=1.001,
- comment="companion to m-json.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
+ version=1.001,
+ comment="companion to m-json.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
local P,V,R,S,C,Cc,Cs,Ct,Cf,Cg=lpeg.P,lpeg.V,lpeg.R,lpeg.S,lpeg.C,lpeg.Cc,lpeg.Cs,lpeg.Ct,lpeg.Cf,lpeg.Cg
local lpegmatch=lpeg.match
-local format=string.format
+local format,gsub=string.format,string.gsub
local utfchar=utf.char
local concat=table.concat
local tonumber,tostring,rawset,type,next=tonumber,tostring,rawset,type,next
@@ -2740,13 +2734,15 @@
local whitespace=lpeg.patterns.whitespace
local optionalws=whitespace^0
local escapes={
- ["b"]="\010",
- ["f"]="\014",
- ["n"]="\n",
- ["r"]="\r",
- ["t"]="\t",
+ ["b"]="\010",
+ ["f"]="\014",
+ ["n"]="\n",
+ ["r"]="\r",
+ ["t"]="\t",
}
-local escape_un=C(P("\\u")/"0x"*S("09","AF","af"))/function(s) return utfchar(tonumber(s)) end
+local escape_un=P("\\u")/""*(C(R("09","AF","af")^-4)/function(s)
+ return utfchar(tonumber(s,16))
+end)
local escape_bs=P([[\]])/""*(P(1)/escapes)
local jstring=dquote*Cs((escape_un+escape_bs+(1-dquote))^0)*dquote
local jtrue=P("true")*Cc(true)
@@ -2755,75 +2751,90 @@
local jnumber=(1-whitespace-rparent-rbrace-comma)^1/tonumber
local key=jstring
local jsonconverter={ "value",
- hash=lbrace*Cf(Ct("")*(V("pair")*(comma*V("pair"))^0+optionalws),rawset)*rbrace,
- pair=Cg(optionalws*key*optionalws*colon*V("value")),
- array=Ct(lparent*(V("value")*(comma*V("value"))^0+optionalws)*rparent),
- value=optionalws*(jstring+V("hash")+V("array")+jtrue+jfalse+jnull+jnumber)*optionalws,
+ hash=lbrace*Cf(Ct("")*(V("pair")*(comma*V("pair"))^0+optionalws),rawset)*rbrace,
+ pair=Cg(optionalws*key*optionalws*colon*V("value")),
+ array=Ct(lparent*(V("value")*(comma*V("value"))^0+optionalws)*rparent),
+ value=optionalws*(jstring+V("hash")+V("array")+jtrue+jfalse+jnull+jnumber)*optionalws,
}
function json.tolua(str)
- return lpegmatch(jsonconverter,str)
+ return lpegmatch(jsonconverter,str)
end
-local function tojson(value,t)
- local kind=type(value)
- if kind=="table" then
- local done=false
- local size=#value
- if size==0 then
- for k,v in next,value do
- if done then
- t[#t+1]=","
- else
- t[#t+1]="{"
- done=true
- end
- t[#t+1]=format("%q:",k)
- tojson(v,t)
- end
- if done then
- t[#t+1]="}"
- else
- t[#t+1]="{}"
- end
- elseif size==1 then
- t[#t+1]="["
- tojson(value[1],t)
- t[#t+1]="]"
+local escaper
+local function tojson(value,t,n)
+ local kind=type(value)
+ if kind=="table" then
+ local done=false
+ local size=#value
+ if size==0 then
+ for k,v in next,value do
+ if done then
+ n=n+1;t[n]=","
else
- for i=1,size do
- if done then
- t[#t+1]=","
- else
- t[#t+1]="["
- done=true
- end
- tojson(value[i],t)
- end
- t[#t+1]="]"
+ n=n+1;t[n]="{"
+ done=true
end
- elseif kind=="string" then
- t[#t+1]=format("%q",value)
- elseif kind=="number" then
- t[#t+1]=value
- elseif kind=="boolean" then
- t[#t+1]=tostring(value)
+ n=n+1;t[n]=format("%q:",k)
+ t,n=tojson(v,t,n)
+ end
+ if done then
+ n=n+1;t[n]="}"
+ else
+ n=n+1;t[n]="{}"
+ end
+ elseif size==1 then
+ n=n+1;t[n]="["
+ t,n=tojson(value[1],t,n)
+ n=n+1;t[n]="]"
+ else
+ for i=1,size do
+ if done then
+ n=n+1;t[n]=","
+ else
+ n=n+1;t[n]="["
+ done=true
+ end
+ t,n=tojson(value[i],t,n)
+ end
+ n=n+1;t[n]="]"
end
- return t
+ elseif kind=="string" then
+ n=n+1;t[n]='"'
+ n=n+1;t[n]=lpegmatch(escaper,value) or value
+ n=n+1;t[n]='"'
+ elseif kind=="number" then
+ n=n+1;t[n]=value
+ elseif kind=="boolean" then
+ n=n+1;t[n]=tostring(value)
+ end
+ return t,n
end
function json.tostring(value)
- local kind=type(value)
- if kind=="table" then
- return concat(tojson(value,{}),"")
- elseif kind=="string" or kind=="number" then
- return value
- else
- return tostring(value)
+ local kind=type(value)
+ if kind=="table" then
+ if not escaper then
+ local escapes={
+ ["\\"]="\\u005C",
+ ["\""]="\\u0022",
+ }
+ for i=0,0x20 do
+ escapes[utfchar(i)]=format("\\u%04X",i)
+ end
+ escaper=Cs((
+ (R('\0\x20')+S('\"\\'))/escapes+P(1)
+ )^1 )
end
+ return concat((tojson(value,{},0)))
+ elseif kind=="string" or kind=="number" then
+ return lpegmatch(escaper,value) or value
+ else
+ return tostring(value)
+ end
end
function json.load(filename)
- local data=io.loaddata(filename)
- if data then
- return lpegmatch(jsonconverter,data)
- end
+ local data=io.loaddata(filename)
+ if data then
+ return lpegmatch(jsonconverter,data)
+ end
end
return json
@@ -2832,11 +2843,11 @@
do -- begin closure to overcome local limits and interference
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"
+ 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
@@ -2851,86 +2862,86 @@
statistics.threshold=0.01
local statusinfo,n,registered,timers={},0,{},{}
setmetatableindex(timers,function(t,k)
- local v={ timing=0,loadtime=0 }
- t[k]=v
- return v
+ local v={ timing=0,loadtime=0 }
+ t[k]=v
+ return v
end)
local function hastiming(instance)
- return instance and timers[instance]
+ return instance and timers[instance]
end
local function resettiming(instance)
- timers[instance or "notimer"]={ timing=0,loadtime=0 }
+ timers[instance or "notimer"]={ timing=0,loadtime=0 }
end
local ticks=clock
local seconds=function(n) return n or 0 end
local function starttiming(instance,reset)
- local timer=timers[instance or "notimer"]
- local it=timer.timing
- if reset then
- it=0
- timer.loadtime=0
+ 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
- if it==0 then
- timer.starttime=ticks()
- if not timer.loadtime then
- timer.loadtime=0
- end
- end
- timer.timing=it+1
+ 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
- return loadtime
- end
+ 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
+ return loadtime
end
- return 0
+ end
+ return 0
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) or 0
- end
+ if type(instance)=="number" then
+ return instance
+ else
+ local timer=timers[instance or "notimer"]
+ return timer and seconds(timer.loadtime) or 0
+ end
end
local function currenttime(instance)
- if type(instance)=="number" then
- return 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 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)
- end
- end
- return 0
+ local starttime=timer.starttime
+ if starttime and starttime>0 then
+ return seconds(timer.loadtime+ticks()-starttime)
+ end
end
+ return 0
+ end
end
local function elapsedtime(instance)
- return format("%0.3f",elapsed(instance))
+ return format("%0.3f",elapsed(instance))
end
local function elapsedindeed(instance)
- return elapsed(instance)>statistics.threshold
+ 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
+ if elapsedindeed(instance) then
+ return format("%0.3f seconds %s",elapsed(instance),rest or "")
+ end
end
statistics.hastiming=hastiming
statistics.resettiming=resettiming
@@ -2942,91 +2953,100 @@
statistics.elapsedindeed=elapsedindeed
statistics.elapsedseconds=elapsedseconds
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
+ 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 with functionality level %s, banner: %s",
- LUATEXENGINE,LUATEXVERSION,LUATEXFUNCTIONALITY,lower(status.banner))
- end)
- register("control sequences",function()
- return format("%s of %s + %s",status.cs_count,status.hash_size,status.hash_extra)
- end)
- register("callbacks",statistics.callbacks)
- if TEXENGINE=="luajittex" and JITSUPPORTED then
- local jitstatus=jit.status
- if jitstatus then
- local jitstatus={ jitstatus() }
- if jitstatus[1] then
- register("luajit options",concat(jitstatus," ",2))
- end
- end
+ 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 with functionality level %s, banner: %s",
+ LUATEXENGINE,LUATEXVERSION,LUATEXFUNCTIONALITY,lower(status.banner))
+ end)
+ register("control sequences",function()
+ return format("%s of %s + %s",status.cs_count,status.hash_size,status.hash_extra)
+ end)
+ register("callbacks",statistics.callbacks)
+ if TEXENGINE=="luajittex" and JITSUPPORTED then
+ local jitstatus=jit.status
+ if jitstatus then
+ local jitstatus={ jitstatus() }
+ if jitstatus[1] then
+ register("luajit options",concat(jitstatus," ",2))
end
- register("lua properties",function()
- local hashchar=tonumber(status.luatex_hashchars)
- local hashtype=status.luatex_hashtype
- local mask=lua.mask or "ascii"
- return format("engine: %s %s, used memory: %s, hash type: %s, hash chars: min(%i,40), symbol mask: %s (%s)",
- jit and "luajit" or "lua",
- LUAVERSION,
- statistics.memused(),
- hashtype or "default",
- hashchar and 2^hashchar or "unknown",
- 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
+ register("lua properties",function()
+ local hashchar=tonumber(status.luatex_hashchars)
+ local hashtype=status.luatex_hashtype
+ local mask=lua.mask or "ascii"
+ return format("engine: %s %s, used memory: %s, hash type: %s, hash chars: min(%i,40), symbol mask: %s (%s)",
+ jit and "luajit" or "lua",
+ LUAVERSION,
+ statistics.memused(),
+ hashtype or "default",
+ hashchar and 2^hashchar or "unknown",
+ 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)",round(collectgarbage("count")/1000),round(status.luastate_bytes/1000000))
+ local round=math.round or math.floor
+ return format("%s MB (ctx: %s MB)",round(collectgarbage("count")/1000),round(status.luastate_bytes/1000000))
end
starttiming(statistics)
function statistics.formatruntime(runtime)
- return format("%s seconds",runtime)
+ return format("%s seconds",runtime)
end
function statistics.runtime()
- stoptiming(statistics)
- return statistics.formatruntime(elapsedtime(statistics))
+ 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)
- starttiming("run")
- action()
- stoptiming("run")
- report("total runtime: %s seconds",elapsedtime("run"))
+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
+ 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
end -- closure
@@ -3034,12 +3054,12 @@
do -- begin closure to overcome local limits and interference
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"
+ 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
@@ -3050,7 +3070,7 @@
local report_mem=logs.reporter("system","lua memory")
local tracestripping=false
local tracememory=false
-luautilities.stripcode=true
+luautilities.stripcode=true
luautilities.alwaysstripcode=false
luautilities.nofstrippedchunks=0
luautilities.nofstrippedbytes=0
@@ -3057,143 +3077,144 @@
local strippedchunks={}
luautilities.strippedchunks=strippedchunks
luautilities.suffixes={
- tma="tma",
- tmc=jit and "tmb" or "tmc",
- lua="lua",
- luc=jit and "lub" or "luc",
- lui="lui",
- luv="luv",
- luj="luj",
- tua="tua",
- tuc="tuc",
+ tma="tma",
+ tmc=jit and "tmb" or "tmc",
+ lua="lua",
+ luc=jit and "lub" or "luc",
+ lui="lui",
+ luv="luv",
+ luj="luj",
+ tua="tua",
+ tuc="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
+ 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
+ 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",2,luafile)
+ report_lua("fatal error %a in file %a",1,luafile)
end
- return false,0
+ 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
+ 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
- local code,message
- if macros then
- code,message=macros.loaded(fullname,true,false)
+ if forcestrip or luautilities.alwaysstripcode then
+ register(name)
+ return load(dump(code,true)),0
else
- code,message=loadfile(fullname)
+ return code,0
end
- if code then
- code()
- else
- report_lua("loading of file %a failed:\n\t%s",fullname,message or "no message")
- 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
+ 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
+ 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
+ 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
+ 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
- return done
+ end
+ return done
end
function luautilities.loadstripped(...)
- local l=load(...)
- if l then
- return load(dump(l,true))
- end
+ 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
+ __gc=function(t)
+ for i=1,#t do
+ pcall(t[i])
end
+ end
} )
function luautilities.registerfinalizer(f)
- finalizers[#finalizers+1]=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
+ 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
- return current
+ end
+ return current
end
end -- closure
@@ -3201,11 +3222,11 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="companion 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
@@ -3224,38 +3245,38 @@
local initialize=false
if 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[[
+ 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
+ local target=ffi.new("__int64[1]")
+ ticks=function()
+ if kernel.QueryPerformanceCounter(target)==1 then
+ return tonumber(target[0])
+ else
+ return 0
end
- initialize=false
+ 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 [[
+ 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;
@@ -3262,228 +3283,228 @@
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
+ 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
+ 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[name]=v
+ 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
+ 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
- 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
+ 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
+ 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
- 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
+ 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 b[2]<a[2]
+ return a[5]<b[5]
end
+ else
+ return a[4]<b[4]
+ end
else
- return b[1]<a[1]
+ return b[3]<a[3]
end
- end)
- if length>50 then
- length=50
+ else
+ return b[2]<a[2]
+ end
+ else
+ return b[1]<a[1]
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)
+ 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("")
- printer(format("functions : %i",functions))
- printer(format("calls : %i",calls))
- printer(format("overhead : %f",seconds(overhead/1000)))
+ 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
+ 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
+ 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
+ getdebug()
+ if sethook and getinfo and nesting==0 then
+ running=true
+ if initialize then
+ initialize()
end
- if nesting>0 then
- nesting=nesting+1
+ 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
+ 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
+ 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
@@ -3492,15 +3513,15 @@
do -- begin closure to overcome local limits and interference
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"
+ version=1.001,
+ comment="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 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
@@ -3507,29 +3528,29 @@
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 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 ""
+ 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
- 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
+ return v
end
+ end
end
local sqlescape=lpeg.replacer {
- { "'","''" },
- { "\\","\\\\" },
- { "\r\n","\\n" },
- { "\r","\\n" },
+ { "'","''" },
+ { "\\","\\\\" },
+ { "\r\n","\\n" },
+ { "\r","\\n" },
}
local sqlquoted=Cs(Cc("'")*sqlescape*Cc("'"))
lpegpatterns.sqlescape=sqlescape
@@ -3536,44 +3557,44 @@
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,
+ 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,
+ 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
+ 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
+ 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 ""
+ local v=t[l]
+ return v and v~="" and lpegmatch(replacer,r,1,t,how or "lua",recurse or false) or ""
end
-local single=P("%")
+local single=P("%")
local double=P("%%")
local lquoted=P("%[")
local rquoted=P("]%")
@@ -3590,41 +3611,41 @@
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 key=nosingle*((C((1-nosingle )^1)*args)/replacekey )*nosingle
+local quoted=nolquotedq*((C((1-norquotedq )^1)*args)/replacekeyquoted )*norquotedq
+local unquoted=nolquoted*((C((1-norquoted )^1)*args)/replacekeyunquoted)*norquoted
local optional=noloptional*((C((1-nomoptional)^1)*nomoptional*C((1-noroptional)^1)*args)/replaceoptional)*noroptional
local any=P(1)
replacer=Cs((unquoted+quoted+escape+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
+ 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
+ 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
+ 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
+ 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 -- closure
@@ -3632,235 +3653,235 @@
do -- begin closure to overcome local limits and interference
if not modules then modules={} end modules ['util-sta']={
- version=1.001,
- comment="companion to util-ini.mkiv",
- author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
- copyright="PRAGMA ADE / ConTeXt Development Team",
- license="see context related readme files"
+ version=1.001,
+ comment="companion to util-ini.mkiv",
+ author="Hans Hagen, PRAGMA-ADE, Hasselt NL",
+ copyright="PRAGMA ADE / ConTeXt Development Team",
+ license="see context related readme files"
}
local insert,remove,fastcopy,concat=table.insert,table.remove,table.fastcopy,table.concat
local format=string.format
local select,tostring=select,tostring
-local trace_stacker=false trackers.register("stacker.resolve",function(v) trace_stacker=v end)
+local trace_stacker=false trackers.register("stacker.resolve",function(v) trace_stacker=v end)
local stacker=stacker or {}
utilities.stacker=stacker
local function start(s,t,first,last)
- if s.mode=="switch" then
- local n=tostring(t[last])
- if trace_stacker then
- s.report("start: %s",n)
- end
- return n
- else
- local r={}
- for i=first,last do
- r[#r+1]=tostring(t[i])
- end
- local n=concat(r," ")
- if trace_stacker then
- s.report("start: %s",n)
- end
- return n
+ if s.mode=="switch" then
+ local n=tostring(t[last])
+ if trace_stacker then
+ s.report("start: %s",n)
end
+ return n
+ else
+ local r={}
+ for i=first,last do
+ r[#r+1]=tostring(t[i])
+ end
+ local n=concat(r," ")
+ if trace_stacker then
+ s.report("start: %s",n)
+ end
+ return n
+ end
end
local function stop(s,t,first,last)
- if s.mode=="switch" then
- local n=tostring(false)
- if trace_stacker then
- s.report("stop: %s",n)
- end
- return n
- else
- local r={}
- for i=last,first,-1 do
- r[#r+1]=tostring(false)
- end
- local n=concat(r," ")
- if trace_stacker then
- s.report("stop: %s",n)
- end
- return n
+ if s.mode=="switch" then
+ local n=tostring(false)
+ if trace_stacker then
+ s.report("stop: %s",n)
end
+ return n
+ else
+ local r={}
+ for i=last,first,-1 do
+ r[#r+1]=tostring(false)
+ end
+ local n=concat(r," ")
+ if trace_stacker then
+ s.report("stop: %s",n)
+ end
+ return n
+ end
end
local function change(s,t1,first1,last1,t2,first2,last2)
- if s.mode=="switch" then
- local n=tostring(t2[last2])
- if trace_stacker then
- s.report("change: %s",n)
- end
- return n
- else
- local r={}
- for i=last1,first1,-1 do
- r[#r+1]=tostring(false)
- end
- local n=concat(r," ")
- for i=first2,last2 do
- r[#r+1]=tostring(t2[i])
- end
- if trace_stacker then
- s.report("change: %s",n)
- end
- return n
+ if s.mode=="switch" then
+ local n=tostring(t2[last2])
+ if trace_stacker then
+ s.report("change: %s",n)
end
+ return n
+ else
+ local r={}
+ for i=last1,first1,-1 do
+ r[#r+1]=tostring(false)
+ end
+ local n=concat(r," ")
+ for i=first2,last2 do
+ r[#r+1]=tostring(t2[i])
+ end
+ if trace_stacker then
+ s.report("change: %s",n)
+ end
+ return n
+ end
end
function stacker.new(name)
- local report=logs.reporter("stacker",name or nil)
- local s
- local stack={}
- local list={}
- local ids={}
- local hash={}
- local hashing=true
- local function push(...)
- for i=1,select("#",...) do
- insert(stack,(select(i,...)))
- end
- if hashing then
- local c=concat(stack,"|")
- local n=hash[c]
- if not n then
- n=#list+1
- hash[c]=n
- list[n]=fastcopy(stack)
- end
- insert(ids,n)
- return n
- else
- local n=#list+1
- list[n]=fastcopy(stack)
- insert(ids,n)
- return n
- end
+ local report=logs.reporter("stacker",name or nil)
+ local s
+ local stack={}
+ local list={}
+ local ids={}
+ local hash={}
+ local hashing=true
+ local function push(...)
+ for i=1,select("#",...) do
+ insert(stack,(select(i,...)))
end
- local function pop()
- remove(stack)
- remove(ids)
- return ids[#ids] or s.unset or -1
+ if hashing then
+ local c=concat(stack,"|")
+ local n=hash[c]
+ if not n then
+ n=#list+1
+ hash[c]=n
+ list[n]=fastcopy(stack)
+ end
+ insert(ids,n)
+ return n
+ else
+ local n=#list+1
+ list[n]=fastcopy(stack)
+ insert(ids,n)
+ return n
end
- local function clean()
- if #stack==0 then
- if trace_stacker then
- s.report("%s list entries, %s stack entries",#list,#stack)
- end
- end
+ end
+ local function pop()
+ remove(stack)
+ remove(ids)
+ return ids[#ids] or s.unset or -1
+ end
+ local function clean()
+ if #stack==0 then
+ if trace_stacker then
+ s.report("%s list entries, %s stack entries",#list,#stack)
+ end
end
- local tops={}
- local top=nil
- local switch=nil
- local function resolve_reset(mode)
- if #tops>0 then
- report("resetting %s left-over states of %a",#tops,name)
- end
- tops={}
- top=nil
- switch=nil
+ end
+ local tops={}
+ local top=nil
+ local switch=nil
+ local function resolve_reset(mode)
+ if #tops>0 then
+ report("resetting %s left-over states of %a",#tops,name)
end
- local function resolve_begin(mode)
- if mode then
- switch=mode=="switch"
- else
- switch=s.mode=="switch"
- end
- top={ switch=switch }
- insert(tops,top)
+ tops={}
+ top=nil
+ switch=nil
+ end
+ local function resolve_begin(mode)
+ if mode then
+ switch=mode=="switch"
+ else
+ switch=s.mode=="switch"
end
- local function resolve_step(ti)
- local result=nil
- local noftop=top and #top or 0
- if ti>0 then
- local current=list[ti]
- if current then
- local noflist=#current
- local nofsame=0
- if noflist>noftop then
- for i=1,noflist do
- if current[i]==top[i] then
- nofsame=i
- else
- break
- end
- end
- else
- for i=1,noflist do
- if current[i]==top[i] then
- nofsame=i
- else
- break
- end
- end
- end
- local plus=nofsame+1
- if plus<=noftop then
- if plus<=noflist then
- if switch then
- result=s.change(s,top,plus,noftop,current,nofsame,noflist)
- else
- result=s.change(s,top,plus,noftop,current,plus,noflist)
- end
- else
- if switch then
- result=s.change(s,top,plus,noftop,current,nofsame,noflist)
- else
- result=s.stop(s,top,plus,noftop)
- end
- end
- elseif plus<=noflist then
- if switch then
- result=s.start(s,current,nofsame,noflist)
- else
- result=s.start(s,current,plus,noflist)
- end
- end
- top=current
+ top={ switch=switch }
+ insert(tops,top)
+ end
+ local function resolve_step(ti)
+ local result=nil
+ local noftop=top and #top or 0
+ if ti>0 then
+ local current=list[ti]
+ if current then
+ local noflist=#current
+ local nofsame=0
+ if noflist>noftop then
+ for i=1,noflist do
+ if current[i]==top[i] then
+ nofsame=i
else
- if 1<=noftop then
- result=s.stop(s,top,1,noftop)
- end
- top={}
+ break
end
- return result
+ end
else
- if 1<=noftop then
- result=s.stop(s,top,1,noftop)
+ for i=1,noflist do
+ if current[i]==top[i] then
+ nofsame=i
+ else
+ break
end
- top={}
- return result
+ end
end
- end
- local function resolve_end()
- if #tops>0 then
- local result=s.stop(s,top,1,#top)
- remove(tops)
- top=tops[#tops]
- switch=top and top.switch
- return result
+ local plus=nofsame+1
+ if plus<=noftop then
+ if plus<=noflist then
+ if switch then
+ result=s.change(s,top,plus,noftop,current,nofsame,noflist)
+ else
+ result=s.change(s,top,plus,noftop,current,plus,noflist)
+ end
+ else
+ if switch then
+ result=s.change(s,top,plus,noftop,current,nofsame,noflist)
+ else
+ result=s.stop(s,top,plus,noftop)
+ end
+ end
+ elseif plus<=noflist then
+ if switch then
+ result=s.start(s,current,nofsame,noflist)
+ else
+ result=s.start(s,current,plus,noflist)
+ end
end
- end
- local function resolve(t)
- resolve_begin()
- for i=1,#t do
- resolve_step(t[i])
+ top=current
+ else
+ if 1<=noftop then
+ result=s.stop(s,top,1,noftop)
end
- resolve_end()
+ top={}
+ end
+ return result
+ else
+ if 1<=noftop then
+ result=s.stop(s,top,1,noftop)
+ end
+ top={}
+ return result
end
- s={
- name=name or "unknown",
- unset=-1,
- report=report,
- start=start,
- stop=stop,
- change=change,
- push=push,
- pop=pop,
- clean=clean,
- resolve=resolve,
- resolve_begin=resolve_begin,
- resolve_step=resolve_step,
- resolve_end=resolve_end,
- resolve_reset=resolve_reset,
- }
- return s
+ end
+ local function resolve_end()
+ if #tops>0 then
+ local result=s.stop(s,top,1,#top)
+ remove(tops)
+ top=tops[#tops]
+ switch=top and top.switch
+ return result
+ end
+ end
+ local function resolve(t)
+ resolve_begin()
+ for i=1,#t do
+ resolve_step(t[i])
+ end
+ resolve_end()
+ end
+ s={
+ name=name or "unknown",
+ unset=-1,
+ report=report,
+ start=start,
+ stop=stop,
+ change=change,
+ push=push,
+ pop=pop,
+ clean=clean,
+ resolve=resolve,
+ resolve_begin=resolve_begin,
+ resolve_step=resolve_step,
+ resolve_end=resolve_end,
+ resolve_reset=resolve_reset,
+ }
+ return s
end
end -- closure
Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-extended.lua 2019-02-08 23:01:17 UTC (rev 49982)
@@ -30,8 +30,8 @@
local lualibs_extended_module = {
name = "lualibs-extended",
- version = 2.62,
- date = "2018-12-19",
+ version = 2.63,
+ date = "2019-01-28",
description = "ConTeXt Lua libraries -- extended collection.",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
copyright = "PRAGMA ADE / ConTeXt Development Team",
Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-lua.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-lua.lua 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-lua.lua 2019-02-08 23:01:17 UTC (rev 49982)
@@ -35,8 +35,6 @@
LUAVERSION = 5.2
end
-_LUAVERSION = LUAVERSION -- for old times sake, will go away
-
-- lpeg
if not lpeg then
Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-trac-inf.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-trac-inf.lua 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-trac-inf.lua 2019-02-08 23:01:17 UTC (rev 49982)
@@ -253,16 +253,25 @@
function statistics.runtime()
stoptiming(statistics)
-- stoptiming(statistics) -- somehow we can start the timer twice, but where
- return statistics.formatruntime(elapsedtime(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)
+function statistics.timed(action,all)
starttiming("run")
action()
stoptiming("run")
- report("total runtime: %s seconds",elapsedtime("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
-- goodie
Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-jsn.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-jsn.lua 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-jsn.lua 2019-02-08 23:01:17 UTC (rev 49982)
@@ -14,10 +14,12 @@
--
-- Reminder for me: check usage in framework and extend when needed. Also document
-- it in the cld lib documentation.
+--
+-- Upgraded for handling the somewhat more fax server templates.
local P, V, R, S, C, Cc, Cs, Ct, Cf, Cg = lpeg.P, lpeg.V, lpeg.R, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Cs, lpeg.Ct, lpeg.Cf, lpeg.Cg
local lpegmatch = lpeg.match
-local format = string.format
+local format, gsub = string.format, string.gsub
local utfchar = utf.char
local concat = table.concat
@@ -26,9 +28,6 @@
local json = utilities.json or { }
utilities.json = json
--- moduledata = moduledata or { }
--- moduledata.json = json
-
-- \\ \/ \b \f \n \r \t \uHHHH
local lbrace = P("{")
@@ -43,16 +42,19 @@
local optionalws = whitespace^0
local escapes = {
- -- ["\\"] = "\\", -- lua will escape these
- -- ["/"] = "/", -- no need to escape this one
- ["b"] = "\010",
- ["f"] = "\014",
- ["n"] = "\n",
- ["r"] = "\r",
- ["t"] = "\t",
+ ["b"] = "\010",
+ ["f"] = "\014",
+ ["n"] = "\n",
+ ["r"] = "\r",
+ ["t"] = "\t",
}
-local escape_un = C(P("\\u") / "0x" * S("09","AF","af")) / function(s) return utfchar(tonumber(s)) end
+-- todo: also handle larger utf16
+
+local escape_un = P("\\u")/"" * (C(R("09","AF","af")^-4) / function(s)
+ return utfchar(tonumber(s,16))
+end)
+
local escape_bs = P([[\]]) / "" * (P(1) / escapes) -- if not found then P(1) is returned i.e. the to be escaped char
local jstring = dquote * Cs((escape_un + escape_bs + (1-dquote))^0) * dquote
@@ -85,7 +87,9 @@
return lpegmatch(jsonconverter,str)
end
-local function tojson(value,t) -- we could optimize #t
+local escaper
+
+local function tojson(value,t,n) -- we could optimize #t
local kind = type(value)
if kind == "table" then
local done = false
@@ -93,44 +97,46 @@
if size == 0 then
for k, v in next, value do
if done then
- t[#t+1] = ","
+ n = n + 1 ; t[n] = ","
else
- t[#t+1] = "{"
+ n = n + 1 ; t[n] = "{"
done = true
end
- t[#t+1] = format("%q:",k)
- tojson(v,t)
+ n = n + 1 ; t[n] = format("%q:",k)
+ t, n = tojson(v,t,n)
end
if done then
- t[#t+1] = "}"
+ n = n + 1 ; t[n] = "}"
else
- t[#t+1] = "{}"
+ n = n + 1 ; t[n] = "{}"
end
elseif size == 1 then
-- we can optimize for non tables
- t[#t+1] = "["
- tojson(value[1],t)
- t[#t+1] = "]"
+ n = n + 1 ; t[n] = "["
+ t, n = tojson(value[1],t,n)
+ n = n + 1 ; t[n] = "]"
else
for i=1,size do
if done then
- t[#t+1] = ","
+ n = n + 1 ; t[n] = ","
else
- t[#t+1] = "["
+ n = n + 1 ; t[n] = "["
done = true
end
- tojson(value[i],t)
+ t, n = tojson(value[i],t,n)
end
- t[#t+1] = "]"
+ n = n + 1 ; t[n] = "]"
end
elseif kind == "string" then
- t[#t+1] = format("%q",value)
+ n = n + 1 ; t[n] = '"'
+ n = n + 1 ; t[n] = lpegmatch(escaper,value) or value
+ n = n + 1 ; t[n] = '"'
elseif kind == "number" then
- t[#t+1] = value
+ n = n + 1 ; t[n] = value
elseif kind == "boolean" then
- t[#t+1] = tostring(value)
+ n = n + 1 ; t[n] = tostring(value)
end
- return t
+ return t, n
end
function json.tostring(value)
@@ -137,16 +143,29 @@
-- todo optimize for non table
local kind = type(value)
if kind == "table" then
- return concat(tojson(value,{}),"")
+ if not escaper then
+ local escapes = {
+ ["\\"] = "\\u005C",
+ ["\""] = "\\u0022",
+ }
+ for i=0,0x20 do
+ escapes[utfchar(i)] = format("\\u%04X",i)
+ end
+ escaper = Cs( (
+ (R('\0\x20') + S('\"\\')) / escapes
+ + P(1)
+ )^1 )
+
+ end
+ return concat((tojson(value,{},0)))
elseif kind == "string" or kind == "number" then
- return value
+ return lpegmatch(escaper,value) or value
else
return tostring(value)
end
end
--- local tmp = [[ { "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]]
-
+-- local tmp = [[ { "t" : "foobar", "a" : true, "b" : [ 123 , 456E-10, { "a" : true, "b" : [ 123 , 456 ] } ] } ]]
-- tmp = json.tolua(tmp)
-- inspect(tmp)
-- tmp = json.tostring(tmp)
@@ -155,7 +174,6 @@
-- inspect(tmp)
-- tmp = json.tostring(tmp)
-- inspect(tmp)
-
-- inspect(json.tostring(true))
function json.load(filename)
@@ -165,4 +183,11 @@
end
end
+-- local s = [[\foo"bar"]]
+-- local j = json.tostring { s = s }
+-- local l = json.tolua(j)
+-- inspect(j)
+-- inspect(l)
+-- print(s==l.s)
+
return json
Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-lua.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-lua.lua 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-lua.lua 2019-02-08 23:01:17 UTC (rev 49982)
@@ -88,6 +88,7 @@
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
Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-str.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-str.lua 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-str.lua 2019-02-08 23:01:17 UTC (rev 49982)
@@ -22,25 +22,12 @@
----- loadstripped = utilities.lua.loadstripped
----- setmetatableindex = table.setmetatableindex
-local loadstripped = nil
-local oldfashioned = LUAVERSION < 5.2
-
-if oldfashioned then
-
- loadstripped = function(str,shortcuts)
- return load(str)
+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
-
-else
-
- 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
-
end
-- todo: make a special namespace for the formatter
@@ -598,67 +585,35 @@
return function(%s) return %s end
]]
-local preamble, environment = "", { }
+local preamble = ""
-if oldfashioned then
+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,
+ basepoints = number.basepoints,
+ 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 = lpeg.patterns.stripzero,
+ stripzeros = lpeg.patterns.stripzeros,
+}
- preamble = [[
-local lpeg=lpeg
-local type=type
-local tostring=tostring
-local tonumber=tonumber
-local format=string.format
-local concat=table.concat
-local signed=number.signed
-local points=number.points
-local basepoints= number.basepoints
-local utfchar=utf.char
-local utfbyte=utf.byte
-local lpegmatch=lpeg.match
-local nspaces=string.nspaces
-local utfpadding=string.utfpadding
-local tracedchar=string.tracedchar
-local autosingle=string.autosingle
-local autodouble=string.autodouble
-local sequenced=table.sequenced
-local formattednumber=number.formatted
-local sparseexponent=number.sparseexponent
-local formattedfloat=number.formattedfloat
-local stripzero=lpeg.patterns.stripzero
-local stripzeros=lpeg.patterns.stripzeros
- ]]
-
-else
-
- 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,
- basepoints = number.basepoints,
- 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 = lpeg.patterns.stripzero,
- stripzeros = lpeg.patterns.stripzeros,
- }
-
-end
-
-- -- --
local arguments = { "a1" } -- faster than previously used (select(n,...))
@@ -1036,44 +991,86 @@
-- strip = true
-- end
+-- add(formatters,"texexp", [[texexp(...)]], "local texexp = metapost.texexp")
--
+-- add(formatters,"foo:bar",[[foo(...)]], { foo = function(...) print(...) return "!" end })
+-- print(string.formatters["foo %3!foo:bar! bar"](1,2,3))
+
local format_rest = function(s)
return format("%q",s) -- catches " and \n and such
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) -- maybe more times?
+-- elseif f < 0 then
+-- local a = "a" .. (n + f + 1)
+-- return format(extension,a,a)
+-- else
+-- if w then
+-- extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+-- end
+-- -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we
+-- -- cache we don't save much and there are hardly any extensions anyway
+-- local t = { }
+-- for i=1,f do
+-- n = n + 1
+-- -- t[#t+1] = "a" .. n
+-- t[i] = "a" .. n
+-- end
+-- return format(extension,unpack(t))
+-- end
+-- 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
+ if w then
+ -- we have a wildcard
+ if f == 0 then
extension = gsub(extension,"%.%.%.","")
- end
- return extension
- elseif f == 1 then
- if w then
+ return extension
+ elseif f == 1 then
extension = gsub(extension,"%.%.%.","%%s")
+ n = n + 1
+ local a = "a" .. n
+ return format(extension,a,a) -- maybe more times?
+ elseif f < 0 then
+ local a = "a" .. (n + f + 1)
+ return format(extension,a,a)
+ else
+ extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
+ -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we
+ -- cache we don't save much and there are hardly any extensions anyway
+ local t = { }
+ for i=1,f do
+ n = n + 1
+ -- t[#t+1] = "a" .. n
+ t[i] = "a" .. n
+ end
+ return format(extension,unpack(t))
end
- n = n + 1
- local a = "a" .. n
- return format(extension,a,a) -- maybe more times?
- elseif f < 0 then
- local a = "a" .. (n + f + 1)
- return format(extension,a,a)
else
- if w then
- extension = gsub(extension,"%.%.%.",rep("%%s,",f-1).."%%s")
- end
- -- we could fill an array and then n = n + 1 unpack(t,n,n+f) but as we
- -- cache we don't save much and there are hardly any extensions anyway
- local t = { }
- for i=1,f do
+ extension = gsub(extension,"%%s",function()
n = n + 1
- -- t[#t+1] = "a" .. n
- t[i] = "a" .. n
- end
- return format(extension,unpack(t))
+ return "a" .. n
+ end)
+ return extension
end
end
@@ -1273,36 +1270,22 @@
-- _connector_ is an experiment
-if oldfashioned then
-
- function strings.formatters.new(noconcat)
- local t = { _type_ = "formatter", _connector_ = noconcat and "," or "..", _extensions_ = { }, _preamble_ = preamble, _environment_ = { } }
- setmetatable(t, { __index = make, __call = use })
- return t
+function strings.formatters.new(noconcat)
+ local e = { } -- better make a copy as we can overload
+ for k, v in next, environment do
+ e[k] = v
end
-
-else
-
- function strings.formatters.new(noconcat)
- local e = { } -- better make a copy as we can overload
- 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 t = {
+ _type_ = "formatter",
+ _connector_ = noconcat and "," or "..",
+ _extensions_ = { },
+ _preamble_ = "",
+ _environment_ = e,
+ }
+ setmetatable(t, { __index = make, __call = use })
+ return t
end
--- function strings.formatters.new()
--- local t = { _extensions_ = { }, _preamble_ = "", _type_ = "formatter", _n_ = 0 }
--- local m = { _t_ = t }
--- setmetatable(t, { __index = m, __call = use })
--- setmetatable(m, { __index = make })
--- return t
--- end
-
local formatters = strings.formatters.new() -- the default instance
string.formatters = formatters -- in the main string namespace
@@ -1333,20 +1316,10 @@
-- escaping by lpeg is faster for strings without quotes, slower on a string with quotes, but
-- faster again when other q-escapables are found (the ones we don't need to escape)
-if oldfashioned then
+add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape = lpeg.patterns.xmlescape })
+add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape = lpeg.patterns.texescape })
+add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape = lpeg.patterns.luaescape })
- add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],"local xmlescape = lpeg.patterns.xmlescape")
- add(formatters,"tex",[[lpegmatch(texescape,%s)]],"local texescape = lpeg.patterns.texescape")
- add(formatters,"lua",[[lpegmatch(luaescape,%s)]],"local luaescape = lpeg.patterns.luaescape")
-
-else
-
- add(formatters,"xml",[[lpegmatch(xmlescape,%s)]],{ xmlescape = lpeg.patterns.xmlescape })
- add(formatters,"tex",[[lpegmatch(texescape,%s)]],{ texescape = lpeg.patterns.texescape })
- add(formatters,"lua",[[lpegmatch(luaescape,%s)]],{ luaescape = lpeg.patterns.luaescape })
-
-end
-
-- -- yes or no:
--
-- local function make(t,str)
Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-tab.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-tab.lua 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs-util-tab.lua 2019-02-08 23:01:17 UTC (rev 49982)
@@ -820,3 +820,53 @@
end)
end
+-- ordered hashes (for now here but in the table namespace):
+
+-- local t = table.orderedhash()
+--
+-- t["1"] = { "a", "b" }
+-- t["2"] = { }
+-- t["2a"] = { "a", "c", "d" }
+--
+-- for k, v in table.ordered(t) do
+-- ...
+-- 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
Modified: trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua
===================================================================
--- trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua 2019-02-08 23:00:59 UTC (rev 49981)
+++ trunk/Master/texmf-dist/tex/luatex/lualibs/lualibs.lua 2019-02-08 23:01:17 UTC (rev 49982)
@@ -25,8 +25,8 @@
lualibs.module_info = {
name = "lualibs",
- version = 2.62,
- date = "2018-12-19",
+ version = 2.63,
+ date = "2019-01-28",
description = "ConTeXt Lua standard libraries.",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL & Elie Roux & Philipp Gesang",
copyright = "PRAGMA ADE / ConTeXt Development Team",
More information about the tex-live-commits
mailing list